@a9i5k4/dsh-auto-memory 2.5.3 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/README.md +171 -1
  2. package/README.zh-CN.md +171 -1
  3. package/docs/CONTRIBUTORS.html +471 -0
  4. package/docs/HANDOFF-CRITERIA.md +92 -0
  5. package/docs/INTEGRATION-ANALYSIS.md +350 -348
  6. package/docs/USER-GUIDE.en.md +56 -1
  7. package/docs/USER-GUIDE.zh-CN.md +57 -2
  8. package/docs/internal/ACCEPT-35-LIVE.md +143 -0
  9. package/docs/internal/ACCEPTANCE-20260914.md +90 -0
  10. package/docs/internal/ARCH-REVIEW-BRIEF.md +411 -0
  11. package/docs/internal/ARCH-REVIEW-REQUEST.md +201 -0
  12. package/docs/internal/ARCH-REVIEW-ROUND2.md +169 -0
  13. package/docs/internal/ARCH-REVIEW-ROUND3.md +206 -0
  14. package/docs/internal/AUDIT-WB-GRAPH-FULL-20260916.md +314 -0
  15. package/docs/internal/CONCURRENCY-INVESTIGATION-20260917.md +192 -0
  16. package/docs/internal/CROSS-SESSION-SEARCH-PATH-DECISION.md +72 -0
  17. package/docs/internal/CROSS-SESSION-SEARCH-RESEARCH.md +131 -0
  18. package/docs/internal/DECISIONS-20260914-SESSION.md +269 -0
  19. package/docs/internal/DESIGN-P1-STATE-COMMIT-20260915.md +219 -0
  20. package/docs/internal/DIRECTION-CHECK-WB-GRAPH-20260916.md +132 -0
  21. package/docs/internal/FEEDBACK-TO-DSHAPI-RELAY.md +13 -0
  22. package/docs/internal/GH-DISCUSSION-5732-COMMENT.md +74 -0
  23. package/docs/internal/GPT-ACCEPTANCE-PROMPT-20260916.md +352 -0
  24. package/docs/internal/GPT-REVIEW-PROMPT.md +216 -0
  25. package/docs/internal/GROUP-WEBHOOK-SETUP.md +33 -0
  26. package/docs/internal/KICKOFF-P0.md +254 -0
  27. package/docs/internal/MASTER-PLAN-3.0.md +411 -0
  28. package/docs/internal/MEMORY-MUTATION-AND-INDEX-DESIGN.md +85 -0
  29. package/docs/internal/MERGE-CONFLICT-SCAN-20260914.md +222 -0
  30. package/docs/internal/PENDING-FIXES-20260916.md +289 -0
  31. package/docs/internal/RAG-KARPATHY-PROGRAM.md +229 -0
  32. package/docs/internal/REPORT-P0-NIGHTLY.md +212 -0
  33. package/docs/internal/REPORT-P5-ACCEPTANCE.md +31 -0
  34. package/docs/internal/REPORT-WB-GRAPH-NIGHTLY.md +153 -0
  35. package/docs/internal/REVIEW-WB-GRAPH-SELF.md +81 -0
  36. package/docs/internal/ROADMAP-20260917-WEEK.md +305 -0
  37. package/docs/internal/ROADMAP.md +106 -0
  38. package/docs/internal/RUN-P0-NIGHTLY.md +227 -0
  39. package/docs/internal/S10-CONSTRUCTION-HANDOFF-20260917.md +175 -0
  40. package/docs/internal/S10-GAPS-PLAIN-20260917.md +125 -0
  41. package/docs/internal/SEMANTIC-ARCHITECTURE-SPEC.md +360 -0
  42. package/docs/internal/SESSION-FILE-REPAIR-PROTOCOL.md +90 -0
  43. package/docs/internal/THREE-LAYER-CONTRACT.md +210 -0
  44. package/docs/internal/TODO-BACKLOG.md +263 -142
  45. package/docs/internal/TODO-GRAPH.html +715 -0
  46. package/docs/internal/TODO-GRAPH.html.bak-20260914-v2 +493 -0
  47. package/docs/internal/TODO-GRAPH.html.bak-20260915-alsfix +710 -0
  48. package/docs/internal/TODO-GRAPH.html.bak-20260915-p1 +710 -0
  49. package/docs/internal/TODO-GRAPH.html.bak-20260915-p6a-rev +703 -0
  50. package/docs/internal/TODO-GRAPH.html.bak-20260915-wshint +710 -0
  51. package/docs/internal/TODO-GRAPH.html.bak-20260916-batch +715 -0
  52. package/docs/internal/WB-FORMAT-CONVENTION.md +112 -0
  53. package/docs/internal/WB-GRAPH-DECISIONS-20260914.md +71 -0
  54. package/docs/internal/reviews/CLAIM-VERIFICATION-20260914.md +56 -0
  55. package/docs/internal/reviews/PLAN-gpt6astra-round2-20260914.md +787 -0
  56. package/docs/internal/reviews/REVIEW-gpt6astra-20260914.md +112 -0
  57. package/docs/internal/reviews/ROUND3-REVIEW-INTEGRATION-20260914.md +230 -0
  58. package/docs/prompts/M8-3-enable-verify.md +49 -49
  59. package/lib/acceptance.js +71 -0
  60. package/lib/activation-host.js +90 -9
  61. package/lib/activation-inbox.js +25 -7
  62. package/lib/board-mode.js +30 -0
  63. package/lib/client.js +878 -75
  64. package/lib/context-bridge.js +2 -2
  65. package/lib/context-host.js +70 -6
  66. package/lib/engine-identity.js +149 -0
  67. package/lib/engine-switch.js +247 -0
  68. package/lib/episodic-store.js +11 -10
  69. package/lib/evidence-store.js +2 -2
  70. package/lib/fact-store.js +1 -1
  71. package/lib/fs-retry.js +46 -0
  72. package/lib/index.js +1987 -153
  73. package/lib/intent-clean-safe.js +40 -0
  74. package/lib/intent-clean.js +12 -16
  75. package/lib/l0-extract.js +263 -149
  76. package/lib/l0-index-sync.js +195 -0
  77. package/lib/l0-index.js +349 -239
  78. package/lib/ledger-criteria.js +142 -0
  79. package/lib/m7-index-sync-host.js +65 -4
  80. package/lib/m7-wire.js +3 -3
  81. package/lib/memory-anchor.js +56 -1
  82. package/lib/memory-envelope.js +252 -0
  83. package/lib/memory-hub.js +14 -4
  84. package/lib/memory-mutation.js +246 -0
  85. package/lib/memory-writer.js +204 -24
  86. package/lib/procedure-observation.js +48 -0
  87. package/lib/procedure-store.js +34 -17
  88. package/lib/python-setup.js +1 -1
  89. package/lib/rerank-host.js +160 -0
  90. package/lib/rules-layer.js +261 -0
  91. package/lib/semantic-js.js +15 -0
  92. package/lib/shadow-retrieval.js +3 -3
  93. package/lib/state-commit.js +245 -0
  94. package/lib/subagent-gc.js +4 -8
  95. package/lib/tier-layer-inject.js +650 -0
  96. package/lib/tier0-catalog.js +693 -0
  97. package/lib/water-window.js +263 -186
  98. package/lib/wb-contract.js +495 -0
  99. package/lib/wb-sidecar.js +839 -0
  100. package/lib/ws-overview-rank.js +2 -2
  101. package/package.json +1 -1
  102. package/python/m7_embedding_v1.py +5 -5
  103. package/python/worker_semantic_v1.py +17 -6
  104. package/python/worker_v1.py +38 -4
@@ -0,0 +1,132 @@
1
+ # 方向核对清单 · WB-GRAPH 白板线(2026-09-16)
2
+
3
+ > **用途**:任务二材料。本文件是**给 GPT 及协作方核对"答题方向"**的清单——不是让 GPT 重新找 bug(那部分见 `GPT-REVIEW-PROMPT.md`),而是**确认修复方向是否正确、优先级是否合理、有没有更该做的事**。
4
+ > **前置**:任务一全量粗检已完成,结论见 `AUDIT-WB-GRAPH-FULL-20260916.md`。
5
+ > **当前状态**:**尚未动手修**。以下每一项都需要"确认/否决/改方向"三类裁决之一。
6
+
7
+ ---
8
+
9
+ ## 一、给 GPT 的三句话背景
10
+
11
+ 1. 这个插件(`dsh-auto-memory`)已在 npm 有真实用户(年下载约 10,900),**legacy 档必须字节级不变**是硬约束——任何修复都不能让老用户行为漂移。
12
+ 2. 白板线(WB-GRAPH)是"新功能 + 一键开关回退",开关默认 `legacy`。用户拍板过"一口气全做完,但线先别急着接"。
13
+ 3. 15 日下午→16 日凌晨这一批改动**不够严谨**:新代码全在闸门后、回归跑不到,于是 **PASS 95/0/0 完全掩盖了 4 条致命缺陷**。这次核对的核心问题是:**修复方向对不对**。
14
+
15
+ ---
16
+
17
+ ## 二、需要裁决的方向性问题(共 6 条)
18
+
19
+ ### Q1 ★ 注册闸门的修法:三选一
20
+
21
+ **问题**:`lib/index.js:7633` 是 `export function apply(ctx, config)`(**非 async**),而工具数组在 `apply()` 内**同步**构建(`:8506`),此刻 `engine.config` 仍是 `DEFAULT_CONFIG`(`boardMode:'legacy'`)⇒ 注册闸门**恒假**。
22
+
23
+ | 方案 | 做法 | 优点 | 风险 |
24
+ | --- | --- | --- | --- |
25
+ | A1-a | 工具无条件注册,闸门降到 **execute 内** | 改动最小 | legacy 档工具数变 16 ⇒ **违反"legacy 字节级不变"**,模型能看到不可用工具 |
26
+ | **A1-b(推荐)** | 新增**同步**读取器 `loadConfigSync()`(`readFileSync`+同合并逻辑),在 tools 构建前调用一次 | 保持 async 语义不动;启动期拿到真配置;闸门仍在注册层 ⇒ legacy 工具数仍 14 | 需保证 `loadConfigSync` 与 `loadConfig` **共用合并逻辑**,否则双源漂移 |
27
+ | A1-c | `apply` 改 `export async function apply` | 最"正统" | **需先确认 cordis 是否 await 插件 apply 的返回值**——未证实,风险最高 |
28
+
29
+ **请裁决**:A1-b 是否可行?有无第四条路(如 cordis 的 `inject`/配置注入机制本该提供启动期配置)?
30
+
31
+ > 附:本项目此前已把「工具注册须先 `await loadConfig()`」写进项目约定——**该约定本身表述有误**(apply 非 async),本次须一并更正为「启动期需要真配置时必须用同步读取器」。
32
+
33
+ ### Q2 ★ 修复顺序:先改代码还是先补测试?
34
+
35
+ **问题**:4 条致命里,**BUG-10(id 不一致)**和 **BUG-1(注册闸门)**都能被一条新测试稳定抓住。当前 20 个套件里没有一个测过 "graph 档端到端"。
36
+
37
+ **两种顺序**:
38
+ - **(a) 先补 graph 档端到端套件(红)→ 再修**(TDD 式,修复可信度高,但先要造出能过 `apply()` 的测试夹具)
39
+ - **(b) 先修 → 再补套件**(快,但容易重蹈"改完不知道有没有真修好")
40
+
41
+ **请裁决**:推荐 (a) 还是 (b)?若 (a),`apply()` 的测试夹具成本是否可控(现有 20 个套件已能调 `apply(`,说明夹具模式已存在)?
42
+
43
+ ### Q3 ★ 规划里 5 项"未做"(P2-3/P2-4/P2-5/P3-2/P3-3)是否本批一律补齐?
44
+
45
+ **背景**:这 5 项在 `WB-GRAPH-INTEGRATION-PLAN.md §5` 里**明确列了**,但 16 日凌晨没做。其中:
46
+ - **P3-3(三处工具数硬锁 14→16)被规划标为"必须项"**——不补则 graph 档测试必红。
47
+ - **P2-5(GUI 放行 `.json`)** 影响用户能否在面板里看到 `index.json`。
48
+ - **P2-3/P2-4** 是检索端与注入端的增强,**不做也不影响"能用"**,只是没兑现规划承诺。
49
+ - **P3-2** 只是一句 guide 文案。
50
+
51
+ **请裁决**:是"全补齐(严格按规划)",还是"先补齐 ①必须项(P3-3)+ ②让功能真正可用的(P2-5),其余(P2-3/P2-4/P3-2)另开批次"?
52
+
53
+ ### Q4 ★ 用户的核心诉求"实时可视化看板"(dsh-graph 接线)该不该在本批做?
54
+
55
+ **背景**:`vendor/dsh-graph/` 已搬入(MIT,含 NOTICE-VENDOR.md),但**cordis 接线未做**——因为要改**用户 profile 配置**(`~/.dsh/profiles/web/`),属高风险动作,需要先备份 + 用户明确同意。
56
+
57
+ **关键事实**:**即使前面 9 条全修完,只要 dsh-graph 不接线,用户依然"看不到看板"**——他最初的抱怨就没有真正解决。
58
+
59
+ **请裁决**:是
60
+ - (a) 本批就把 profile 接线做了(先备份,用户同意后执行),还是
61
+ - (b) 先把 memory_* 侧修干净、接线另立一步(用户可先验证 sidecar/遍历工具是否好用)?
62
+
63
+ ### Q5 ★ "白板锚点未写入 Markdown"算不算规划未兑现?
64
+
65
+ **背景**:`WB-FORMAT-CONVENTION §2` 承诺的收益是"**白板内容凭锚点自动进入检索语料**(L0 抽取按锚点切条),无需任何新机制"。实测:`wbEntryIdPre` 只把 `mem_<32hex>` 写进 **sidecar 的 id 字段**,**从未写入 `PLAN.md`/账本的 Markdown 正文**(`WB-FORMAT-CONVENTION §2` 要求标题行下方紧跟 `<!-- memory:mem_... -->`)。
66
+
67
+ ⇒ **该收益目前为零**:白板内容不会因锚点进检索。
68
+
69
+ **请裁决**:这是"实现 bug(应补写锚点到 Markdown)"还是"可以延期(先让 sidecar 跑通)"?若补写,会改动用户可见的 Markdown 内容,需确认是否可接受。
70
+
71
+ ### Q6 ★ 交付报告的高报要不要更正留痕?
72
+
73
+ **背景**:`REPORT-WB-GRAPH-NIGHTLY.md` 把 `events.jsonl`、遍历工具返回正文、dsh-graph 接线、工具数硬锁都标 ✅,实际均未完成。
74
+
75
+ **请裁决**:是
76
+ - (a) 直接改写该报告为"如实版"(丢失原始误报的痕迹),还是
77
+ - (b) **保留原报告不动 + 追加一份勘误节**("原始报告哪些项高报、实测如何")——**倾向 (b)**,因为能保留"为什么会误报"的教训?
78
+
79
+ ---
80
+
81
+ ## 三、我方的初步判断(供对方否决)
82
+
83
+ | 项 | 我的判断 | 置信度 |
84
+ | --- | --- | --- |
85
+ | Q1 修法 | **A1-b** | 中(未验证 cordis 是否提供启动期配置,故需 GPT 确认 A1-c 是否更正统) |
86
+ | Q2 顺序 | **(a) 先补 graph 端到端套件** | 高(否则无法证明修好了) |
87
+ | Q3 范围 | **补 P3-3 + P2-5 必修项;P2-3/P2-4/P3-2 看本批余量** | 中 |
88
+ | Q4 接线 | **(b) 另立一步**——但必须让用户明确知道"不接线 = 看不到看板" | 高(改 profile 风险高,且用户硬规矩要求先备份+同意) |
89
+ | Q5 锚点 | **算未兑现,建议补**(否则 §2 收益条款是空头承诺) | 中高 |
90
+ | Q6 报告 | **(b) 追加勘误节** | 高 |
91
+
92
+ ---
93
+
94
+ ## 四、我方**不做**的事(边界声明)
95
+
96
+ - 不改用户 profile(Q4 未裁决前)。
97
+ - 不 commit/push/publish(代码全留 pre 线)。
98
+ - 不重启 dsh web 宿主(用户自行重启)。
99
+ - 不为了"让测试变绿"而放宽断言——尤其不能把三处工具数硬锁从 `!== 14` 直接改成"随便多少"。
100
+
101
+ ---
102
+
103
+ ## 五、对方回复的期望格式
104
+
105
+ 请逐条回:
106
+
107
+ ```
108
+ Q1: 采纳 <A1-a|A1-b|A1-c|其他:____>,理由 <一句话>
109
+ Q2: <a|b>,理由 <一句话>
110
+ Q3: 本批范围 = <列出项号>,其余延后
111
+ Q4: <a|b>,理由 <一句话>
112
+ Q5: <补写锚点|延期>,理由 <一句话>
113
+ Q6: <a|b>
114
+ 补充意见: <如果有我漏掉的方向性问题>
115
+ ```
116
+
117
+ ---
118
+
119
+ ## 六、附:材料索引
120
+
121
+ | 文件 | 内容 |
122
+ | --- | --- |
123
+ | `docs/internal/AUDIT-WB-GRAPH-FULL-20260916.md` | 任务一全量粗检报告(4 致命 + 5 新缺陷 + 规划三态对账 + 修复方案 + 证据清单) |
124
+ | `docs/internal/REVIEW-WB-GRAPH-SELF.md` | 16 日凌晨自审(3 致命 + 6 高/中危,**其中 BUG-4 已被本次推翻**) |
125
+ | `docs/internal/GPT-REVIEW-PROMPT.md` | 找 bug 的任务书(与本文互补:那份找 bug,这份定方向) |
126
+ | `docs/internal/WB-GRAPH-INTEGRATION-PLAN.md` §5 | 改动清单原表(P0-P1/P2/P3 全部条目) |
127
+ | `docs/internal/WB-FORMAT-CONVENTION.md` | §2 锚点契约 / §3 索引派生 / §4 写入门 / §8 验收清单 |
128
+ | `docs/internal/WB-GRAPH-DECISIONS-20260914.md` §E | 16 日凌晨拍板留痕(A1-A8/B4/B7/P1 范围) |
129
+ | `docs/internal/REPORT-WB-GRAPH-NIGHTLY.md` | 交付报告(**含高报项,Q6 待裁决**) |
130
+ | `artifacts/_audit-p23-probe.mjs` | 可复跑:BUG-4 推翻 / tag 正则 / 返回契约 / boardMode 解析 |
131
+ | `artifacts/_audit-id-repro.mjs` | 可复跑:BUG-10 两条路径 id 对撞 |
132
+ | `artifacts/_audit-apply-await.mjs` | 可复跑:apply 函数体花括号配对 + await 深度分布 |
@@ -0,0 +1,13 @@
1
+ 站长你好,反馈一个 `openai-responses` 协议下的冲突问题。
2
+
3
+ **现象**:用 `api: openai-responses` 走 `https://api.dshapi.icu/v1` + `deepseek-v4.1-flash`,客户端(DSH)的会话会永久损坏——所有模型开始报 `400 Duplicate 'call_id'`,之后该会话再也不能用,只能手工清历史。
4
+
5
+ **原因**:responses 协议里工具调用的 id 字段和你返回的 `tool_calls[].id` 用的是一样的 `call_xx_xxxx` 命名规则,两边算出来的 id 会撞车。DSH 在 responses 这条路径上拿不到独立的 id,只能用自己生成的值兜底,同一轮里并发多个工具调用时就重复了,写进历史后每次请求都被上游拒绝。
6
+
7
+ **对比证据**:同一份客户端配置下,其他中转(sub-vankit、vankit-glm 等)都没有这个问题,只有走你们 responses 端点时会撞。
8
+
9
+ **想请你确认/解决**:
10
+ 1. 你们是否支持标准的 `chat/completions` 协议?我们这边实测 `https://api.dshapi.icu/v1/chat/completions` 是正常返回的,如果可以,我们改用标准协议就能绕过。
11
+ 2. 如果必须用 responses,能否让返回里的工具调用 id 与客户端请求中的 id 明确区分开(比如加独立前缀),避免撞车?
12
+
13
+ 麻烦看一下,谢谢!
@@ -0,0 +1,74 @@
1
+ # 补充确认:同轮内重复 tool_call_id(相邻双写形态)
2
+
3
+ ## EN
4
+
5
+ **Environment**: Windows 11 / Node 24 / dsh `0.1.5-rc.1`, strict OpenAI-compatible relay (Console Go, unique-id check).
6
+
7
+ **Symptom**: the session becomes permanently unusable — every model fails with:
8
+
9
+ ```
10
+ 400 invalid_request_error: Duplicate 'call_id': call_01_IBQv9P78wRhPI72L2XVh2573_call_01_IBQv9P78wRhPI72L2XVh257.
11
+ 400 Duplicate value for 'tool_call_id' of call_01_IBQv9P78wRhPI72L2XVh2573|call_01_IBQv9P78wRhPI72L2XVh2573 in message[3]
12
+ ```
13
+
14
+ The UI also fails to render: `[session-controller] event feed subscriber failed: conversation Context 20:trajectory-tool-call <id>|<id> received more than one start Match`.
15
+
16
+ **Evidence (3 sessions on disk, one night)**: the model emitted the same `tool_call_id` twice **within one step**; DSH persisted both verbatim:
17
+
18
+ ```
19
+ 981 tool/call call_01_UKmzZe2AlTekpCR0whQV6449|call_01...
20
+ 983 tool/call call_01_UKmzZe2AlTekpCR0whQV6449|call_01... <-- same id, 2 events apart
21
+ ```
22
+
23
+ Two of the three cases followed an aborted turn; **the third had no abort** — so this is not abort-specific.
24
+
25
+ **New finding — two shapes, only one is acute**: scanning 164 local session files, 30 contain duplicated ids:
26
+
27
+ | shape | gap | sessions | effect |
28
+ |---|---|---|---|
29
+ | adjacent double-write (same step) | 2 events | 3 | session permanently unusable |
30
+ | cross-turn reuse (different turn) | tens of thousands of events | 27 | tolerated today, one strict-provider switch from the same fate |
31
+
32
+ **New finding — a diagnostic signature that identifies the culprit provider**: DSH stores each tool call id as `<recorded>|<provider-mapped>`. Across all local sessions the two halves are **identical** (self-reflection: the provider echoes DSH's id back instead of returning its own) for exactly one provider:
33
+
34
+ ```
35
+ provider self-reflected normal-mapped no-separator
36
+ dshapi 11 0 0 <-- 100% self-reflected
37
+ sub-vankit 0 1431 ...
38
+ vankit-glm 0 821 ...
39
+ opencode-go2 0 1783 ...
40
+ ```
41
+
42
+ When the two halves are equal, concurrent tool calls in one step collide and produce the byte-identical `<id>|<id>` duplicates. So a fast triage question is: **"is your provider self-reflecting the ids?"** — check `data.callId` in any `tool/call` event; `X|X` = the provider is echoing ids instead of minting them.
43
+
44
+ **Repair (works, host restart required)**: drop the second `tool/call`+`tool/result` pair, keep all other events. Constraint: `session.v3.jsonl.zstd` is append-style multi-frame zstd with **one event per frame**, and the first frame must be *exactly* one header line — recompressing into a single frame bricks boot (`corrupt Zstandard session log: first frame is not exactly one header line`).
45
+
46
+ **Suggested fix**: enforce session-wide unique `toolCallId` at history append (rewrite the later occurrence + remap its `tool` message), and make the assembler isolate rather than fatal-throw on the duplicate `start Match` (same ask as the #5692 family).
47
+
48
+ ---
49
+
50
+ ## 中文
51
+
52
+ **环境**:Windows 11 / Node 24 / dsh `0.1.5-rc.1`,严格校验唯一 id 的 OpenAI 兼容中转(Console Go)。
53
+
54
+ **现象**:会话永久不可用——所有模型都报上面那两条 400;界面同时卡加载(`received more than one start Match`)。
55
+
56
+ **证据(一夜 3 个会话,磁盘日志)**:模型在**同一个 step 内**输出了两次相同的 `tool_call_id`,DSH 原样持久化两条(seq 981 → 983,相隔 2 条事件)。三次中两次在中断回合之后,**第三次没有任何中断**——并非中断专属。
57
+
58
+ **新发现一——两种形态,只有一种致命**:扫本地 164 个会话,30 个含重复 id——**相邻双写**(差 2 条,3 个会话,会话永久不可用)vs **跨 turn 复用**(相差数万条,27 个会话,当前被容忍但切换严格 provider 即同样失效)。
59
+
60
+ **新发现二——一个能直接指认元凶的鉴别特征**:DSH 把每次工具调用的 id 存成 `<记录的>|<provider 映射的>`。全部本地会话统计下来,只有一家 provider 的**两半完全相同**(自反映射:provider 不回吐自己的 id,而是把 DSH 给的 id 原样送回):
61
+
62
+ ```
63
+ provider 自反映射 正常映射 无分隔
64
+ dshapi 11 0 0 ← 100% 自反映射
65
+ sub-vankit 0 1431 ...
66
+ vankit-glm 0 821 ...
67
+ opencode-go2 0 1783 ...
68
+ ```
69
+
70
+ 两半相同时,同一 step 内的并发工具调用就会撞在一起,产生字节相同的 `<id>|<id>`。所以快速判断法:**看你 provider 是不是在自反映射**——打开任意 `tool/call` 事件的 `data.callId`,若是 `X|X` 形态,即 provider 没有自己生成 id 而是回吐了请求里的 id。
71
+
72
+ **修复方式(有效,需重启宿主)**:删除第二次出现的 `tool/call`+`tool/result` 对,其余保留。约束:会话日志是追加式多帧 zstd、**一帧一事件**,首帧必须恰好是 session 头一行——压成单帧会导致启动失败。
73
+
74
+ **建议修复**:历史 append 处强制会话内 `toolCallId` 唯一(改写后出现的那次 + 重映射其 `tool` 消息);assembler 在重复 `start Match` 时隔离该块而非致命抛出(与 #5692 家族一致)。
@@ -0,0 +1,352 @@
1
+ # GPT 验收任务书 · dsh-auto-memory「2026-09-15 下午 → 09-16 上午」全窗口改动
2
+
3
+ > **交付对象**:具备本地文件读取与命令执行能力的 AI 验收者(GPT)。
4
+ > **你的角色**:**独立第三方验收者**。不要相信施工方的任何自述——包括本文件。
5
+ > **产出**:一份**可执行的验收报告**,含逐项判定(通过/不通过/证据不足)+ 缺陷清单 + 放行建议。
6
+ > **铁律**:**只读审查,禁止修改任何文件**。本文件里凡是"作者声称"的部分,都是**待你证伪的假设**,不是事实。
7
+
8
+ ---
9
+
10
+ ## 0. 一句话背景
11
+
12
+ `dsh-auto-memory` 是 DeepSeek Harness(DSH)的记忆插件。本窗口(15 日下午到 16 日上午)施工方完成了一次**底层重建(代号 3.0,八阶段)**,并在 16 日白天追加了**白板可视化兼并改造**与**文档/贡献者页**工作。
13
+
14
+ 施工方**自认这段窗口"比较不严谨"**(用户原话),因此本轮验收的重点不是"功能能不能跑",而是:
15
+
16
+ 1. **声称与事实是否一致**(有没有把未做的写成已做);
17
+ 2. **绿灯是否可信**(测试全过 ≠ 缺陷不存在——本窗口已两次踩到"假绿");
18
+ 3. **与权威规划是否对得上**(有没有跑偏、有没有擅自扩大范围)。
19
+
20
+ ---
21
+
22
+ ## 1. 审查对象与时间窗(精确边界)
23
+
24
+ | 项 | 值 |
25
+ | --- | --- |
26
+ | 代码仓库(pre 开发线,**唯一审查对象**) | `D:\dsh-auto-memory` |
27
+ | 时间窗 | **2026-09-15 12:00 → 2026-09-16 12:00(本地时间)** |
28
+ | 窗口内 Git 提交数 | **0**(全部是未提交的工作区改动) |
29
+ | 工作区待审改动 | **204 项**(`git -C D:\dsh-auto-memory status --short`;**含本任务书自身**,去掉它是 203 项) |
30
+ | 宿主插件主体 | `D:\dsh-auto-memory\lib\index.js`(约 12,000 行,单文件) |
31
+ | 浏览器半边 | `D:\dsh-auto-memory\lib\client.js`(约 5,300 行) |
32
+ | 用户配置(**只读**) | `C:\Users\JH Z\.dsh\dsh-auto-memory-pre.json` |
33
+ | 全量回归入口 | `cd D:\dsh-auto-memory && node tools/run-smoke.mjs` |
34
+ | **施工方声称的当前基线** | `PASS 96 / FAIL 0 / TIMEOUT 0(143.3s)` |
35
+
36
+ **取窗口内文件清单的权威命令**(不要凭本文件的表格当结论):
37
+
38
+ ```powershell
39
+ cd D:\dsh-auto-memory
40
+ # 窗口内改动过的 lib 业务文件(排除备份)
41
+ Get-ChildItem lib -File | Where-Object {
42
+ $_.LastWriteTime -ge '2026-09-15 12:00' -and $_.LastWriteTime -le '2026-09-16 12:00' -and $_.Name -notlike '*.bak*'
43
+ } | Sort-Object Name | Select-Object LastWriteTime, Length, Name
44
+
45
+ # 窗口内新增的测试套件
46
+ Get-ChildItem tests\smoke -File | Where-Object {
47
+ $_.LastWriteTime -ge '2026-09-15 12:00' -and $_.LastWriteTime -le '2026-09-16 12:00' -and $_.Name -notlike '*.bak-*'
48
+ } | Sort-Object Name | Select-Object LastWriteTime, Length, Name
49
+
50
+ # 窗口内产出的内部文档
51
+ Get-ChildItem docs\internal -File | Where-Object {
52
+ $_.LastWriteTime -ge '2026-09-15 12:00' -and $_.LastWriteTime -le '2026-09-16 12:00'
53
+ } | Sort-Object LastWriteTime | Select-Object LastWriteTime, Length, Name
54
+ ```
55
+
56
+ ---
57
+
58
+ ## 2. 环境与硬约束(违反任一条即验收失败)
59
+
60
+ 1. **禁止修改、创建、删除仓库内任何文件**;禁止改配置文件。
61
+ 2. **禁止重启、停止任何 dsh / node 进程**。该进程承载验收者本体,杀它会中断验收。
62
+ 禁止 `Stop-Process` / `taskkill` / `Get-Process node | Stop-Process` 等**按进程名批量杀**的命令。
63
+ 3. 禁止 `git commit` / `git push` / `git checkout` / `npm publish`。**只读 Git 命令(log/diff/status/ls-files)允许**。
64
+ 4. 不要为"验证"而写入用户真实记忆目录 `C:\Users\JH Z\.dsh\memory\...`。
65
+ 需要文件系统实验时,**只用系统临时目录**(如 `$env:TEMP\gpt-verify-*`)。
66
+ 5. 允许:读文件、grep、跑测试命令、跑只读探针、把临时脚本写到系统临时目录后执行。
67
+ 6. **不要采信记忆文件、不要运行任何会改动状态的命令**。若某条结论必须靠"跑一下"才能验证,且该命令有副作用,**请标注为"未能验证"并说明原因**,不要擅自执行。
68
+
69
+ ---
70
+
71
+ ## 3. 权威依据(合规审查的唯一标尺,请先读它们)
72
+
73
+ 按优先级从高到低:
74
+
75
+ | # | 文件(绝对路径) | 作用 |
76
+ | --- | --- | --- |
77
+ | 1 | `D:\dsh-auto-memory\docs\internal\MASTER-PLAN-3.0.md` | **3.0 底层重建蓝本**——八阶段的目标、判据、验收口径 |
78
+ | 2 | `D:\dsh-auto-memory\docs\internal\TODO-GRAPH.html` | 3.0 看板(声称 47 卡全 ✅);**这是施工方自己的记账,可核对但不可作为证据** |
79
+ | 3 | `D:\dsh-auto-memory\docs\internal\WB-FORMAT-CONVENTION.md` | 白板格式契约(§2 锚点 id 契约 / §3 索引派生 / §4 写入门 / §6 lint / §8 验收清单) |
80
+ | 4 | `D:\dsh-auto-memory\docs\internal\WB-GRAPH-DECISIONS-20260914.md` | 用户拍板记录(§E 为最新裁定) |
81
+ | 5 | `D:\dsh-auto-memory\docs\internal\REVIEW-WB-GRAPH-SELF.md` | **施工方自审**(3 致命 + 6 高/中危)——请独立复核,**不要照抄** |
82
+ | 6 | `D:\dsh-auto-memory\docs\internal\AUDIT-WB-GRAPH-FULL-20260916.md` | 全量粗检审计报告(带行号证据) |
83
+ | 7 | `D:\dsh-auto-memory\docs\internal\DIRECTION-CHECK-WB-GRAPH-20260916.md` | 方向核对清单(6 个裁决点) |
84
+ | 8 | `D:\dsh-auto-memory\docs\internal\REPORT-WB-GRAPH-NIGHTLY.md` | 施工方交付报告(**注意:其中的"交付总览"含未完成项,可能与实际不符**) |
85
+ | 9 | `D:\dsh-auto-memory\docs\internal\REPORT-P5-ACCEPTANCE.md` | P5 验收清单(含 `releaseReady=false` 的如实标注) |
86
+ | 10 | `D:\dsh-auto-memory\docs\HANDOFF-CRITERIA.md` | 交接账本判据表(H1-H4 / P-H1 / P-S1 + 正反例)——**注意在 `docs\` 而非 `docs\internal\`** |
87
+
88
+ **若上述文件互相矛盾**:以文件 #1(MASTER-PLAN-3.0)与 #3(格式契约)为准;并把矛盾本身**作为一条发现记入报告**。
89
+
90
+ ---
91
+
92
+ ## 4. 施工方声称的交付(**全部是待证伪的假设**)
93
+
94
+ ### 4.1 3.0 八阶段(15 日下午 → 16 日凌晨)
95
+
96
+ 声称全部结项,顺序为 `P0 → P6A → P1 与 P6B → P2 → P3 → P4 → P5`:
97
+
98
+ | 阶段 | 声称交付 | 对应文件(绝对路径) |
99
+ | --- | --- | --- |
100
+ | P0 | 写入门 + 判据账本 + 注入表达 | `lib\memory-envelope-pre.js`、`lib\memory-writer-pre.js` |
101
+ | P6A | 注入节奏与措辞 | `lib\rules-layer-pre.js` |
102
+ | P1 | 状态提交 + miv 单源 + 并发原子写 | `lib\state-commit-pre.js`、`lib\ledger-criteria-pre.js` |
103
+ | P6B | kind 持久化 + 撤回 + 迁移 | `lib\rules-layer-pre.js` |
104
+ | P2 | 真增量(真实输入数/复用顺序/引擎身份门) | `lib\engine-identity-pre.js`、`lib\engine-switch-pre.js`、`lib\l0-index-sync-pre.js` |
105
+ | P3 | 共同检索融合决策(R1 双显示 + `opts.fusion:'legacy'` 回滚) | `lib\l0-index-pre.js`、`lib\m7-index-sync-host-pre.js` |
106
+ | P4 | 精排多级 + 有界异步窗口 | `lib\rerank-host-pre.js` |
107
+ | P5 | 验收清单(7 必需项 + U1 兼容门 + release-ready 门) | `lib\acceptance-pre.js`、`docs\internal\REPORT-P5-ACCEPTANCE.md` |
108
+
109
+ 窗口内新增 13 个 smoke 套件(**点名**,请核对是否真实存在且断言数对得上):
110
+
111
+ ```
112
+ tests\smoke\smoke-test-t0-3-budget-ledger-pre.mjs
113
+ tests\smoke\smoke-test-switch-decouple-pre.mjs
114
+ tests\smoke\smoke-test-capture-paths-pre.mjs
115
+ tests\smoke\smoke-test-state-commit-pre.mjs
116
+ tests\smoke\smoke-test-p1-concurrency-pre.mjs
117
+ tests\smoke\smoke-test-p6a-rules-layer-pre.mjs
118
+ tests\smoke\smoke-test-ws-hint-first-round-pre.mjs
119
+ tests\smoke\smoke-test-p6b-rules-kind-pre.mjs
120
+ tests\smoke\smoke-test-p2-delta-engine-pre.mjs
121
+ tests\smoke\smoke-test-p3-recall-decision-pre.mjs
122
+ tests\smoke\smoke-test-p4-rerank-window-pre.mjs
123
+ tests\smoke\smoke-test-p5-acceptance-pre.mjs
124
+ tests\smoke\smoke-test-p1-ledger-criteria-pre.mjs
125
+ ```
126
+
127
+ ### 4.2 白板可视化「兼并」(16 日凌晨 → 白天)
128
+
129
+ **用户裁定(原话口径)**:让 auto-memory **兼并** dsh-graph(**包括可视化**),不是往 profile 里再挂一个 dsh-graph 插件。
130
+
131
+ 施工方声称的落点(**请逐条核对代码**):
132
+
133
+ 1. `lib\wb-sidecar-pre.js` —— 纯函数投影层:`buildKanbanPre`(泳道卡片)、`buildKanbanMatrixPre`(矩阵:行=日期分组、列=5 泳道 + `misc` 兜底)、`ledgerDateOfPre`
134
+ 2. `lib\board-mode-pre.js` —— 总开关:`legacy`(默认)/ `graph`,**非法值 fail-closed 回 legacy**
135
+ 3. `lib\index.js` —— `kanbanBoardData` 同一路由**同时**返回 `lanes`(窄容器用)与 `matrix`(宽容器用)
136
+ 4. `lib\client.js` —— 双承载面:面板 `KanbanBoard`(侧边栏,列表视图)+ `KanbanView`(注册到 `conversation.view` 上栏,矩阵视图)
137
+
138
+ **声称的关键不变量**(可独立验证):
139
+ - 矩阵列合计 == 总卡数(**不得静默丢卡**);施工方称初版漏 `misc` 兜底列导致 59 张卡落不进任何列,已修
140
+ - `__undated__` 行必须存在(`PLAN.md` / 归档文件归此行)
141
+ - 行按日期倒序
142
+ - 同一输入**打乱顺序后**输出不变(注意:施工方自认"两次同输入结果相同"是**弱断言**,因为 V8 sort 稳定,撤掉 id 破平也照样通过)
143
+
144
+ ### 4.3 16 日白天的文档与贡献者页
145
+
146
+ | 交付 | 状态 | 证据 |
147
+ | --- | --- | --- |
148
+ | `D:\dsh-auto-memory\docs\CONTRIBUTORS.html` | 新建,**已推送** | 远程 `origin/main` = `794717d` |
149
+ | `D:\dsh-auto-memory\README.md` | 修改,**已推送** | 同上 |
150
+ | `D:\dsh-auto-memory\README.zh-CN.md` | 修改,**已推送** | 同上 |
151
+ | 贡献者数据 | 声称 18 位外部贡献者 / 17 PR / 32 Issue | 施工方称取自 GitHub API |
152
+
153
+ **注意一处施工方主动交代的错误**:初次统计时凭印象写成"14 PR / 37 issue"与"Minervaowl7 11 PR + 12 issue",后用脚本核对修正为 **17 PR / 32 issue**、**15 PR + 8 issue**。请复算验证最终数字是否正确。
154
+
155
+ ---
156
+
157
+ ## 4.4 【本批新增】2026-09-16 送审前缺陷清理批次(**请重点证伪**)
158
+
159
+ 背景:用户要求在送审**之前**先把已知 issue / 外部 PR / 群反馈一次性清掉,避免带着已知缺陷送审。
160
+ 施工清单与回执:`D:\dsh-auto-memory\docs\internal\PENDING-FIXES-20260916.md`(§「施工完成回执」)。
161
+ **关键前提**:外部 PR 打的是**发布线布局**(`lib/memory-writer.js` 等裸名),而 pre 线运行 `-pre.js` 具名模块,
162
+ ⇒ **不能 `git apply`**,施工方是按**根因在 pre 线重写**的。请重点核查"是否真的等价修好,而非贴着 PR 抄"。
163
+
164
+ | # | 项 | 施工方声称 | 建议验证 |
165
+ |---|---|---|---|
166
+ | N1 | **issue #54** 写入侧保留语法过滤 | 新增 `checkReservedSyntaxInContent()`(复用既有 `MARKER_OPEN`);`appendAnchoredRecord`/`replaceSingleRecord` 前置拦截;`conflict:` reason 带 `@行号` | 跑 `tests\smoke\smoke-test-issue54-pre.mjs`(声称 12/12);**独立构造**一条含 `<!-- memory:` 的正文,确认被拒且**后续良性写入仍成功**(本 issue 的核心危害是"整体中断"而非丢一条) |
167
+ | N2 | **issue #51** DATE_RE 锚定 | `ws-overview-rank.js` 改 `^(\d{4})-(\d{2})-(\d{2})$` | 跑 `smoke-test-issue51.mjs`(声称 29/29);核对与 `lib\index.js` 的 `DATE_RE` 是否**同源** |
168
+ | N3 | **issue #48** EPERM 退避 + 失败不降级 | 新增 `lib/fs-retry-pre.js`;`atomicReplace` 保留候选快照 + `recoveryPath`;`memory_log/note/user` 失败改为**抛出**(DSH 记 isError) | 跑 `smoke-test-issue48.mjs`(声称 37/37);**重点**:确认"写入失败不再被包装成成功字符串"——这是静默丢记忆的根因 |
169
+ | N4 | **issue #40** welcomeTourEnabled 失效 | 三处自动弹出分支全过 `allowTour`;配置未知不自动播放;✕ 直接关闭 | 跑 `smoke-test-startup-dispatch-pre.mjs`(声称 20/20);核对 `if (allowTour && ` 出现 **3** 次 |
170
+ | N5 | **issue #38** 容量整理净增长 | 根因 A:占位段 `(文件头)` 被凭空写出(引入 `synthetic` + `seqOf`);根因 B:`replace` 误按旧文件额度计费 | 跑 `smoke-test-issue38-pre.mjs`(声称 12/12)。**请独立复现**:施工方称修前在 pre 线实测 **67→77→87、8 轮单调 +80**;请检查 `lib\index.js` 的 `compactLegacyLayer` 是否还有无条件 `'## ' + s.title` 重序列化 |
171
+ | N6 | **issue #45** recall 256 截断 | 移除 `l0Corpus.length = 256` 与语义臂记录预算;新增"窗口受限"提示 | 跑 `smoke-test-issue45-recall-corpus.mjs`(声称 45/45)+ `smoke-test-p2-semantic-recall-pre.mjs`(声称 15/15) |
172
+ | N7 | **issue #30** 技能永久无法晋升 | **去重口径由 title 改指纹**(标题不是身份);观察行显式 `observationOnly`,晋升短接为 `observation-only` | 跑 `smoke-test-issue30-procedure-promotion-pre.mjs`(声称 36/36)。**注意**:施工方称 PR #36 自带用例**未覆盖它自己的根因**(同名碰撞链),故补了断言 —— 请复核该断言是否真的能抓住回归 |
173
+ | N8 | **issue #52** 子代理模型被旧 cfg 覆盖 | `set()` 改函数式更新 + 新增 `setMany()`;三个成对入口改原子更新 | 跑 `smoke-test-issue52-pre.mjs`(声称 9/9);核对 `set(` 是否**不再**引用闭包变量 `cfg` |
174
+ | N9 | **群反馈 #4** 注入可排除来源 | 新增 `injectExcludeSources` + `filterExcludedSourcesPre()`(id/整层/目录前缀/精确路径);注入闸门**之前**挡下 | 跑 `smoke-test-p0-4d-inject-exclude-pre.mjs`(声称 17/17)。**请核查施工方的一处自我更正**:该卡片写"注入上限待开工",但施工方称**上限部分早已存在**(冻结常量 `TIER_BUDGET_PRE_V1`),只有"排除来源"是真缺口 —— 请判定此说法是否成立 |
175
+ | N10 | **PR #37**(issue #35)**未移植** | 施工方称 pre 线已于 2026-09-14 按**用户裁定方案**修好(`sessionController.cancel()` 停旧回合),而 PR #37 的方案(idle 门、**不** cancel)与用户裁定**直接冲突**,故挂起待裁 | 请读 `lib\index.js` 中 `hostAutoContinue()` 的 2026-09-14 注释与 `decideAutoContinue()` 的 2026-09-14 注释,判定"挂起"是否是有据可依,而非回避 |
176
+
177
+ ### 4.5 施工期间**额外发现并修掉**的既有缺陷(不在原清单内 —— 请重点审这一条)
178
+
179
+ 施工方声称:**issue #54 的守卫暴露出一个既有的静默结构损坏**。
180
+
181
+ - **症状**:`maintain()` 的"无 AI 蒸馏"回退分支把 `archive/` 里日志**原文**内联进 `MEMORY.md`,
182
+ 而原文首行是**旧日志自己的 anchor marker** ⇒ 该 marker 变成 `MEMORY.md` 的结构锚点,产生**幻影记录**。
183
+ - **为何此前无人发现**:整行合法 marker 能被 `parseAnchors` 当锚点**吃下**,所以不报错 —— 静默损坏比报错更危险。
184
+ - **声称的修法**:新增 `stripAnchorLines()`(只剥整行合法 marker,正文一字不动),在 `appendText()` 的
185
+ **写入边界统一收口**(一处覆盖全部调用方),而非逐调用点打补丁。
186
+ - **建议验证**:跑 `tests\smoke\smoke-test-m3b3-pre.mjs`(E7 用例);并独立构造"把含 marker 的文档原文
187
+ 追加进另一个锚点文档",判定①是否被拒/被安全剥离 ②**是否产生幻影锚点**。
188
+ - **连带改动**(请一并复核是否合理,而非"为了过测试而改测试"):
189
+ - `smoke-test-m3b2-pre.mjs` D7:断言由"tmp 必须被清理"改为"完整候选必须保留"(与 N3 同一行为变更)
190
+ - `smoke-test-p4-l0-response-pre.mjs`:import 正则放宽为允许同源附加导入(因 `index.js` 新增 `stripAnchorLines` 导入)
191
+
192
+ ### 4.6 请特别检查的**方法论**问题(施工方自曝)
193
+
194
+ 外部 PR 自带测试可能**不覆盖它自己的根因**(#36 即如此:其用例只验 `observationOnly` 标记,
195
+ 未覆盖"同名观察行吞掉富候选"这条真实病灶链)。请抽查其余移植项是否也存在同类"测试在场但没测到点上"。
196
+
197
+ ---
198
+
199
+ ## 5. 施工方的"修复声明"(请逐条用命令证伪)
200
+
201
+ 自审报告 `docs\internal\REVIEW-WB-GRAPH-SELF.md` 列出 **3 个致命 bug**。施工方声称**全部已修**,请逐条验证:
202
+
203
+ | BUG | 症状 | 声称的修法 | 建议验证命令 |
204
+ | --- | --- | --- | --- |
205
+ | **BUG-1** | 工具注册时机早于配置加载 ⇒ graph 档永不生效(注册闸门结构性恒假) | 新增同步读取器 `loadConfigSync()`,在构建 tools **之前**调用 | `Select-String -Path D:\dsh-auto-memory\lib\index.js -Pattern "loadConfigSync"` —— 确认**调用点**位于 tools 构建之前(不是只定义了函数) |
206
+ | **BUG-2** | 用 `agent.cwd` 取工作区路径 ⇒ 跑到 DSH 安装目录 | 改走 `await this.resolvePaths(agent)` | 统计 `resolvePaths(agent)` 与 `agent.cwd` 的出现次数(**残留的 `agent.cwd` 若只在注释里,请注明**) |
207
+ | **BUG-3** | 设置页按钮只 `setCfg+setDirty` 未写盘即 reload ⇒ 用户点完等于没点 | 改走 `saveConfigPatch` | `Select-String -Path D:\dsh-auto-memory\lib\client.js -Pattern "saveConfigPatch"`,并核对该函数**真正落盘** |
208
+
209
+ **其余 6 项高/中危(施工方未声明已修,请独立判定现状)**:
210
+
211
+ | BUG | 内容 |
212
+ | --- | --- |
213
+ | BUG-4 | sidecar 用了不存在的 `this.wsDirKey`(真名 `wsKey(ws)`) |
214
+ | BUG-5 | 三处工具数硬锁未同步(`smoke-test.mjs` / `smoke-test-m3b3-pre.mjs` / `smoke-test-context-observer.mjs`)——**注意**:施工方称 legacy 档保持 **14**、graph 档为 **16**,两组断言分工不同 |
215
+ | BUG-6 | `events.jsonl` 未实现(方案 A2 与 P2-1 明确要求 appended-only `{ts,...}`) |
216
+ | BUG-7 | 遍历工具不返回正文(方案 §4.1 要求返回条目 Content) |
217
+ | BUG-8 | 无正文级检索兜底(方案 P3-1 要求 index.json 缺失时 fail-soft 回落 `searchHandoffCorpus`) |
218
+ | BUG-9 | 未接线 dsh-graph —— **此处注意**:用户后来裁定"兼并"而非"接线",请判断现行实现是否符合**兼并**语义(可视化长在 auto-memory 自己身上、不新增插件/存储/profile 改动) |
219
+
220
+ ---
221
+
222
+ ## 6. 施工方主动交代的"已踩过的坑"(请验证这些坑是否真的填上了)
223
+
224
+ 施工方称本窗口踩到以下陷阱并已处理,**每一条都是可验证的**:
225
+
226
+ 1. **结构性假绿**:graph 新能力全挂在 `boardMode==='graph'` 闸门后,而回归跑 legacy 档 ⇒ 新分支**一行都不执行**,测试全绿却漏掉 4 条致命缺陷。
227
+ → 请确认是否存在一条**真正切到 graph 档**的端到端套件,并检查它是否**真的**在跑 graph 分支(而不是被 fail-closed 回落到 legacy)。
228
+ → 相关文件:`D:\dsh-auto-memory\tests\smoke\smoke-test-graph-mode-pre.mjs`(声称 35 断言)
229
+
230
+ 2. **异步断言未被 await**:该套件的 `ta()` 曾是 `async`,汇总行在异步断言完成前就打印 ⇒ 失败被漏计("32 passed" 实为 35 条,甚至可能 exit 0)。
231
+ → 请检查该套件是否用 `pending[]` 收集 + 汇总前 `await Promise.all(pending)`
232
+
233
+ 3. **空 fixture 上的等式断言是假绿温床**:`totalCards=0` 时 `0 === 0` 恒真,第一版 G4 因此等于没测。
234
+ → 请检查 G5 类断言是否**喂了带真实卡的 fixture**
235
+
236
+ 4. **"函数写了但没人调用"**:`whiteboardTagMapPre()` 存在且逻辑正确,但**没有任何调用点**——这类缺陷无副作用,行为测试与 grep 定义处都会误判为"已实现"。
237
+ → 请对**新增的关键函数**抽查调用点是否存在
238
+
239
+ 5. **CSS 令牌凭印象拼写**:曾用 7 个**不存在**的 `--dsw-alias-*` 令牌(如 `--dsw-alias-text-primary`)⇒ 变量不解析 ⇒ 颜色静默失效(用户报"全都看不清")。
240
+ → 请 grep `D:\dsh-auto-memory\lib\client.js`,确认没有臆造令牌。**注意**:DSH 令牌由运行时注入,在 `dist/assets/*.css` 里 grep"定义"会全部落空,**判定真伪必须到官方 UI 包的 JS 源码里找"使用点"取并集**:
241
+ ```powershell
242
+ Get-ChildItem "$env:APPDATA\npm\node_modules\@deepseek-ai\dsh\node_modules\@deepseek-ai\dsh-client-ui-*" -Recurse -File -Include *.js |
243
+ Select-String -Pattern "--dsw-alias-[a-z0-9-]+" -AllMatches |
244
+ ForEach-Object { $_.Matches } | ForEach-Object { $_.Value } | Sort-Object -Unique
245
+ ```
246
+
247
+ 6. **浮层定位三次返工**:`fixed` → 容器内 `absolute` → `createPortal` 到 `document.body`。
248
+ → 请确认 `lib\client.js` 中抽屉最终用的是 `createPortal` + `position:fixed`(容器内 absolute 会随容器滚动而看不见)
249
+
250
+ 7. **变异演示基线必须是当前版本备份**:旧备份曾整体回滚改造。
251
+ → 请检查 `lib\*.bak-*` 的时间戳,判断是否有"用旧备份当变异基线"的痕迹
252
+
253
+ ---
254
+
255
+ ## 7. 你的验收任务(按档执行,逐项给判定)
256
+
257
+ ### A 档 · 事实核对(必做)
258
+
259
+ - **A1** 跑全量回归,**如实记录** `PASS / FAIL / TIMEOUT` 三个数字与实际耗时。若与施工方声称的 `104 / 0 / 0` 不符,**以你的实测为准**并写入报告。(注:本窗口早期基线为 `96 / 0 / 0`;本批新增 8 个套件后为 `104 / 0 / 0`,耗时 159.0s。)
260
+ - **A2** 单独跑 `tests\smoke\smoke-test-graph-mode-pre.mjs`,记录断言总数,**核对是否为 35**。
261
+ - **A3** 用第 1 节的命令列出窗口内改动文件,与第 4 节表格**逐项对账**:有没有"声称交付但文件不存在"、或"文件存在但不在窗口内"。
262
+ - **A4** 核对第 5 节的**三个致命 bug 修复声明**,各给出「已修 / 未修 / 证据不足」+ 证据(文件:行号)。
263
+ - **A5** 核对贡献者数字(18 / 17 / 32)与 `Minervaowl7` 的 15 PR + 8 Issue。(可用 `https://api.github.com/repos/Aik358/dsh-auto-memory/issues?state=all&per_page=100`;注意该端点**同时返回 PR 和 issue**,靠 `pull_request` 字段区分。)
264
+
265
+ ### B 档 · 合规审查(必做)
266
+
267
+ - **B1** 打开 `docs\internal\MASTER-PLAN-3.0.md`,逐一核对八阶段的**验收口径**是否达成。给出三态判定:**达成 / 部分达成 / 未达成**,每项附证据。
268
+ - **B2** 核对 `docs\internal\WB-FORMAT-CONVENTION.md` 的 §2(锚点 id 契约)/ §3(索引派生)/ §4(写入门)/ §8(验收清单)是否被实现遵守。
269
+ - **B3** 核对 `docs\internal\REVIEW-WB-GRAPH-SELF.md` 的 9 项缺陷**逐条现状**(不只 3 个致命的)。
270
+ - **B4** 判断有无**擅自扩大范围**的改动(规划没要求但改了)。
271
+
272
+ ### C 档 · 独立找缺陷(**这是本轮验收的核心价值**)
273
+
274
+ 施工方已两次踩到"绿灯撒谎"。请主动寻找**自审未覆盖**的缺陷,重点方向:
275
+
276
+ - **C1** 新能力是否真的**被调用**(而不是定义了没人用)——抽查 3-5 个新增关键函数,grep 调用点
277
+ - **C2** 新旧档切换是否**真的解耦**(用户硬性要求:单一开关不得顺带改变其他功能行为)
278
+ - **C3** legacy 档是否**字节级不变**(用户要求旧行为不能被污染)
279
+ - **C4** 断言是否**可证伪**——是否存在"恒真断言"(空 fixture 上的等式、自己断言自己)
280
+ - **C5** 是否存在**静默失败路径**(出错时不报错、不提示、直接返回空)
281
+ - **C6** 前后端 API 路径表是否一致(施工方称有 `smoke-test-api-paths-pre.mjs` 强制两侧同步)
282
+ - **C7** 有没有**测试自己改自己**(测试里写死了与被测代码同源的期望值)
283
+
284
+ ### D 档 · 变异测试(可选,但强烈建议)
285
+
286
+ 挑 2-3 条**关键断言**做变异演示:把被断言的代码**故意改坏**(**只在你自己的临时副本上改,禁止改仓库内文件**),确认测试**真的变红**。
287
+
288
+ 若某条断言在代码被改坏后**仍然通过**,说明它是**假绿**——这条发现的价值高于任何"全绿"报告。
289
+
290
+ ---
291
+
292
+ ## 8. 产出格式(严格按此结构)
293
+
294
+ ```markdown
295
+ # GPT 验收报告 · dsh-auto-memory 2026-09-15→16 窗口
296
+
297
+ ## 0. 结论先行
298
+ - 放行建议:☐ 通过 ☐ 有条件通过 ☐ 不通过
299
+ - 一句话理由:
300
+ - 最严重发现(1-3 条):
301
+
302
+ ## 1. 实测基线
303
+ | 项 | 施工方声称 | 我的实测 | 是否一致 |
304
+ |---|---|---|---|
305
+ | 全量回归 | PASS 96 / FAIL 0 / TIMEOUT 0 (143.3s) | | |
306
+ | graph 套件 | 35 断言 | | |
307
+ | 窗口内改动文件数 | 203(不含本任务书) | | |
308
+
309
+ ## 2. A 档 · 事实核对
310
+ (逐项:A1…A5,每条给 判定 + 证据文件:行号)
311
+
312
+ ## 3. B 档 · 合规审查
313
+ (B1…B4。B1 用表格:阶段 / 声称 / 判定 / 证据)
314
+
315
+ ## 4. C 档 · 独立发现
316
+ (每条:编号 / 症状 / 最小复现 / 影响面 / 建议修法 / 严重度)
317
+
318
+ ## 5. D 档 · 变异测试
319
+ (每条:被变异代码 / 变异内容 / 测试是否变红 / 结论)
320
+
321
+ ## 6. 与施工方自述的差异清单
322
+ | 施工方声称 | 实际情况 | 性质(误报/漏报/口径偏差) |
323
+ |---|---|---|
324
+
325
+ ## 7. 未验证项
326
+ (列出你**没能验证**的结论及原因——这比硬凑结论更有价值)
327
+
328
+ ## 8. 建议的下一步
329
+ (按优先级排序,每条可执行)
330
+ ```
331
+
332
+ ---
333
+
334
+ ## 9. 报告纪律(重要)
335
+
336
+ 1. **结论必须附证据**:文件路径 + 行号,或命令 + 原始输出。**没有证据的结论请标注为"推断"**。
337
+ 2. **不要照抄施工方自述**。本文件第 4、5 节的全部内容是**待证伪的假设**,不是事实。
338
+ 3. **区分三态**:确认 / 证伪 / 证据不足。**"证据不足"是合法且必要的结论**,不要为了给出结论而猜测。
339
+ 4. **绿不等于对**。若你发现某条断言在代码被改坏后仍然通过,**这比任何全绿报告都重要**,请优先报告。
340
+ 5. **不要修改任何文件**。若某条验证必须写文件,只用系统临时目录,并在报告中说明。
341
+ 6. **不要重启任何 dsh / node 进程**。
342
+ 7. 若你判断本任务书本身有误导、口径不当或遗漏关键审查面,**请在报告第 6 节直接指出**——这同样是有价值的验收结论。
343
+
344
+ ---
345
+
346
+ ## 附:施工方主动申报的已知边界(请验证这些"边界"是否被如实履行)
347
+
348
+ 1. **未接线的部分**:施工方称 `vendor\dsh-graph\` 只作**形态参照**,未搬运其代码、未新增 profile 依赖。请验证仓库中确实没有 `dsh-graph` 的运行时接线(比如 `~/.dsh/profiles/web/package.json` 未被改动)。
349
+ 2. **未发布**:施工方称所有功能代码**留在 pre 线未提交未推送**,仅 `README` / `README.zh-CN.md` / `docs/CONTRIBUTORS.html` 三个文档被推到 `origin/main`(提交 `794717d`)。
350
+ 请用只读命令验证:`git -C D:\dsh-auto-memory log --oneline origin/main -3` 与 `git -C D:\dsh-auto-memory status --short -- lib/`
351
+ 3. **P5 如实标注 `releaseReady=false`**:施工方称没有把未完成的说成已完成。请核对 `docs\internal\REPORT-P5-ACCEPTANCE.md` 与 `lib\acceptance-pre.js` 的实际门禁逻辑是否一致。
352
+ 4. **已知未做项**:BUG-6(`events.jsonl`)/ BUG-7(遍历工具不返回正文)/ BUG-8(无正文级检索兜底)。施工方**未声称这三项已修**——请确认真实状态,并判断它们是否影响 3.0 的验收结论。