import assert from "node:assert/strict"; import { mkdtempSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import test from "node:test"; import { MemoryStore } from "../src/store.js"; import { workdayAt } from "../src/workday.js"; function withStore(run) { const directory = mkdtempSync(join(tmpdir(), "deskpaw-topics-")); const store = new MemoryStore(join(directory, "memory.sqlite"), join(directory, "bundles")); try { run(store); } finally { store.close(); rmSync(directory, { recursive: true, force: true }); } } test("workday has a fixed 03:30 Asia/Shanghai boundary", () => { assert.equal(workdayAt(Date.parse("2026-09-22T19:29:59Z")), "2026-09-22"); assert.equal(workdayAt(Date.parse("2026-09-22T19:30:00Z")), "2026-09-23"); }); test("lower maintenance groups chat into a stable cross-day topic", () => withStore((store) => { const first = Date.parse("2026-09-22T19:29:00Z"); const second = Date.parse("2026-09-22T19:31:00Z"); store.rememberInteractions({ interactions: [ { interaction_id: "one", source: "feishu", user: "我们聊聊记忆架构", manager: "可以讨论短期记忆。", created_at: first }, { interaction_id: "two", source: "terminal", user: "继续聊记忆架构", manager: "继续讨论话题单元。", created_at: second }, ] }); const firstPlan = store.maintenancePlan({ now: second }); assert.equal(firstPlan.workday, "2026-09-22"); assert.deepEqual(firstPlan.interactions.map((item) => item.interaction_id), ["one"]); assert.deepEqual(store.commitMaintenance({ workday: firstPlan.workday, topics: [ { title: "记忆架构", category: "chat", summary: "讨论短期记忆。", result: "待续", issues: "话题边界", interaction_ids: ["one"] }, ] }), { assigned: 1, facts: 0, skills: 0 }); const firstTopic = store.recall({ query: "记忆架构" }).related_topics[0]; const secondPlan = store.maintenancePlan({ now: second }); assert.equal(secondPlan.workday, "2026-09-23"); assert.deepEqual(secondPlan.interactions.map((item) => item.interaction_id), ["two"]); store.commitMaintenance({ workday: secondPlan.workday, topics: [ { topic_id: firstTopic.topic_id, title: "记忆架构", category: "chat", summary: "讨论话题单元。", result: "确定 03:30 边界", issues: "待实施", interaction_ids: ["two"] }, ] }); const detail = store.topicDetail({ topic_id: firstTopic.topic_id }); assert.equal(detail.segments.length, 2); assert.deepEqual(detail.interactions.map((item) => item.interaction_id), ["one", "two"]); assert.equal(store.recall({ query: "记忆架构" }).recent_workdays.length, 2); })); test("later batches see the previous segment for the same workday", () => withStore((store) => { const at = Date.parse("2026-09-23T04:00:00Z"); store.rememberInteractions({ interactions: [ { interaction_id: "first", source: "terminal", user: "讨论记忆压缩", manager: "记录短期", created_at: at }, { interaction_id: "later", source: "terminal", user: "继续讨论记忆压缩", manager: "讨论长期", created_at: at + 60_000 }, ] }); const workday = workdayAt(at); store.commitMaintenance({ workday, topics: [ { title: "记忆压缩", category: "chat", summary: "短期设计", segment_summary: "确定短期记忆的设计", result: "已定义短期", issues: "长期待议", interaction_ids: ["first"] }, ] }); const plan = store.maintenancePlan({ now: at + 60_000 }); assert.deepEqual(plan.interactions.map((row) => row.interaction_id), ["later"]); const topic = plan.topics.find((row) => row.title === "记忆压缩"); assert.equal(topic.workday_summary, "确定短期记忆的设计"); assert.equal(topic.workday_result, "已定义短期"); assert.equal(topic.workday_issues, "长期待议"); })); test("facts require verbatim user evidence and skills remain drafts", () => withStore((store) => { store.rememberInteractions({ interactions: [ { interaction_id: "pref", source: "feishu", user: "我喜欢简洁的回复", manager: "知道了", created_at: Date.now() }, ] }); const workday = store.maintenancePlan().workday; const result = store.commitMaintenance({ workday, topics: [], facts: [ { category: "profile", profile_kind: "preference", statement: "用户偏好简洁回复", scope: "global", evidence_interaction_id: "pref", user_quote: "我喜欢简洁的回复" }, { category: "environment", statement: "用户电脑永久需要 VPN", scope: "global", evidence_interaction_id: "pref", user_quote: "用户电脑永久需要 VPN" }, ], skills: [ { title: "回复", body: "简短回答", evidence_interaction_id: "pref", user_quote: "我喜欢简洁的回复" }, ] }); assert.deepEqual(result, { assigned: 0, facts: 1, skills: 1 }); const recalled = store.recall({ query: "回复偏好" }); assert.equal(recalled.core_facts[0].statement, "用户偏好简洁回复"); const skill = store.db.prepare("SELECT skill_id,status FROM memory_skills").get(); assert.equal(skill.status, "draft"); assert.throws(() => store.setSkillStatus({ skill_id: skill.skill_id, status: "active" }), /confirmation/); assert.equal(store.setSkillStatus({ skill_id: skill.skill_id, status: "active", confirmed_by_user: true }).status, "active"); assert.equal(store.recall({ query: "简短回答" }).relevant_skills[0].skill_id, skill.skill_id); })); test("nightly review has a fixed prior workday and does not rewrite raw interactions", () => withStore((store) => { const eventAt = Date.parse("2026-09-22T12:00:00Z"); const reviewAt = Date.parse("2026-09-22T19:31:00Z"); store.rememberInteractions({ interactions: [ { interaction_id: "night", source: "terminal", user: "讨论一下话题", manager: "先记录", created_at: eventAt }, ] }); store.commitMaintenance({ workday: "2026-09-22", topics: [ { title: "话题讨论", category: "chat", summary: "初稿", result: "未完成", issues: "待续", interaction_ids: ["night"] }, ] }); const plan = store.maintenancePlan({ now: reviewAt }); assert.equal(plan.review_workday, "2026-09-22"); assert.equal(plan.review_topics.length, 1); const topicId = plan.review_topics[0].topic_id; store.commitMaintenance({ workday: plan.workday, review_workday: plan.review_workday, nightly: true, topic_reviews: [{ topic_id: topicId, summary: "讨论话题边界", result: "形成初步定义", issues: "待验证" }] }); assert.equal(store.maintenanceStatus(reviewAt).nightly_due, false); assert.equal(store.topicDetail({ topic_id: topicId }).segments[0].summary, "讨论话题边界"); assert.equal(store.topicDetail({ topic_id: topicId }).interactions[0].user_text, "讨论一下话题"); })); test("relevance prioritizes linked topics and requires two workdays for device facts", () => withStore((store) => { const first = Date.parse("2026-09-21T04:00:00Z"); const second = Date.parse("2026-09-22T04:00:00Z"); store.rememberInteractions({ interactions: [ { interaction_id: "linked", source: "feishu", user: "讨论键鼠", manager: "记录了", task_id: "task-1", created_at: first }, { interaction_id: "scope", source: "terminal", user: "这台 Windows 电脑运行 Codex 要开 VPN", manager: "收到", created_at: first }, { interaction_id: "scope-again", source: "terminal", user: "这台 Windows 电脑运行 Codex 要开 VPN", manager: "已复核", created_at: second }, ] }); store.commitMaintenance({ workday: workdayAt(first), topics: [ { title: "键鼠", category: "execution", summary: "讨论纯 HID 控制", interaction_ids: ["linked"] }, { title: "网络", category: "chat", summary: "讨论 Codex 网络", interaction_ids: ["scope"] }, ], facts: [ { category: "environment", statement: "运行 Codex 要开 VPN", scope: "windows-pc", evidence_interaction_id: "scope", user_quote: "这台 Windows 电脑运行 Codex 要开 VPN" }, ] }); const linked = store.recall({ query: "刚才说的事", previous_interaction_id: "linked", task_id: "task-1" }); assert.equal(linked.related_topics[0].title, "键鼠"); assert.equal(store.recall({ query: "Codex", scope: "windows-pc" }).related_facts.length, 0); store.commitMaintenance({ workday: workdayAt(second), facts: [ { category: "environment", statement: "运行 Codex 要开 VPN", scope: "windows-pc", evidence_interaction_id: "scope-again", user_quote: "这台 Windows 电脑运行 Codex 要开 VPN" }, ] }); assert.equal(store.recall({ query: "Codex" }).related_facts.length, 0); assert.equal(store.recall({ query: "Codex", scope: "windows-pc" }).related_facts.length, 1); })); test("episodic profile claims stay out of core while a current project is related-only", () => withStore((store) => { store.rememberInteractions({ interactions: [ { interaction_id: "desk", source: "feishu", user: "我今天就在电脑前,可以自己核对效果", manager: "收到", created_at: Date.now() }, { interaction_id: "project", source: "feishu", user: "我在推进纯 HDMI 加 HID 控制电脑的优化", manager: "了解", created_at: Date.now() }, { interaction_id: "schedule", source: "feishu", user: "每天 8:30 分享推文到三个群", manager: "收到", created_at: Date.now() }, ] }); store.commitMaintenance({ workday: store.maintenancePlan().workday, facts: [ { category: "profile", profile_kind: "identity", statement: "用户当时在电脑前可自行核对", scope: "global", evidence_interaction_id: "desk", user_quote: "我今天就在电脑前" }, { category: "profile", statement: "用户在推进 HDMI HID 优化", scope: "global", evidence_interaction_id: "project", user_quote: "我在推进纯 HDMI 加 HID" }, { category: "profile", profile_kind: "work_style", statement: "用户每天 8:30 分享推文到三个群", scope: "global", evidence_interaction_id: "schedule", user_quote: "每天 8:30 分享推文到三个群" }, { category: "project", statement: "用户在推进纯 HDMI 与 HID 控制电脑项目", scope: "global", evidence_interaction_id: "project", user_quote: "我在推进纯 HDMI 加 HID" }, ] }); const recall = store.recall({ query: "HDMI HID 项目" }); assert.equal(recall.core_facts.length, 0); assert.equal(recall.related_facts.length, 1); assert.equal(recall.related_facts[0].category, "project"); })); test("nightly review expires stale candidates and inactive facts cannot be revived by maintenance", () => withStore((store) => { const old = Date.now() - 5 * 86_400_000; store.rememberInteractions({ interactions: [ { interaction_id: "old-device", source: "feishu", user: "鼠标临时没有反应", manager: "已记录", created_at: old }, { interaction_id: "pref", source: "feishu", user: "我喜欢简洁回答", manager: "收到", created_at: old }, ] }); const day = workdayAt(old); store.commitMaintenance({ workday: day, facts: [ { category: "environment", statement: "鼠标没有反应", scope: "device-a", evidence_interaction_id: "old-device", user_quote: "鼠标临时没有反应" }, { category: "profile", profile_kind: "preference", statement: "用户喜欢简洁回答", scope: "global", evidence_interaction_id: "pref", user_quote: "我喜欢简洁回答" }, ] }); const profileId = store.db.prepare("SELECT fact_id FROM memory_facts WHERE category='profile'").get().fact_id; store.commitMaintenance({ workday: workdayAt(Date.now()), nightly: true, fact_reviews: [{ fact_id: profileId, status: "inactive" }] }); assert.deepEqual(store.db.prepare("SELECT status FROM memory_facts ORDER BY category").all().map((row) => row.status), ["inactive", "inactive"]); store.commitMaintenance({ workday: day, facts: [ { category: "profile", profile_kind: "preference", statement: "用户喜欢简洁回答", scope: "global", evidence_interaction_id: "pref", user_quote: "我喜欢简洁回答" }, ] }); assert.equal(store.db.prepare("SELECT status FROM memory_facts WHERE fact_id=?").get(profileId).status, "inactive"); assert.equal(store.maintenancePlan().facts.length, 0); })); test("one observed environment failure stays a candidate until a second workday corroborates it", () => withStore((store) => { const first = Date.parse("2026-09-21T04:00:00Z"); const second = Date.parse("2026-09-22T04:00:00Z"); store.completeTask({ task_id: "check-1", objective: "检查网络", status: "completed", result: "Codex 直连超时" }); store.completeTask({ task_id: "check-2", objective: "再次检查网络", status: "completed", result: "Codex 直连超时" }); store.rememberInteractions({ interactions: [ { interaction_id: "obs-1", source: "terminal", user: "检查网络", manager: "任务完成", task_id: "check-1", created_at: first }, { interaction_id: "obs-2", source: "terminal", user: "再次检查网络", manager: "任务完成", task_id: "check-2", created_at: second }, ] }); const fact = (id) => ({ category: "environment", statement: "该设备 Codex 直连可能超时", scope: "pc-a", evidence_interaction_id: id, evidence_quote: "Codex 直连超时" }); store.commitMaintenance({ workday: workdayAt(first), facts: [fact("obs-1")] }); assert.equal(store.db.prepare("SELECT status FROM memory_facts").get().status, "candidate"); assert.equal(store.recall({ query: "Codex", scope: "pc-a" }).related_facts.length, 0); store.commitMaintenance({ workday: workdayAt(second), facts: [fact("obs-2")] }); assert.equal(store.db.prepare("SELECT status FROM memory_facts").get().status, "active"); assert.equal(store.recall({ query: "Codex", scope: "pc-a" }).related_facts.length, 1); })); test("topic detail pagination does not skip interactions with identical timestamps", () => withStore((store) => { const at = Date.parse("2026-09-23T04:00:00Z"); store.rememberInteractions({ interactions: [ { interaction_id: "a", source: "terminal", user: "第一条", manager: "收到", created_at: at }, { interaction_id: "b", source: "terminal", user: "第二条", manager: "收到", created_at: at }, ] }); store.commitMaintenance({ workday: workdayAt(at), topics: [ { title: "连续对话", summary: "两条对话", interaction_ids: ["a", "b"] }, ] }); const id = store.recall({ query: "连续对话" }).related_topics[0].topic_id; const first = store.topicDetail({ topic_id: id, limit: 1 }); const second = store.topicDetail({ topic_id: id, limit: 1, after: first.next_after }); assert.deepEqual([first.interactions[0].interaction_id, second.interactions[0].interaction_id], ["a", "b"]); }));