@a9i5k4/dsh-auto-memory 3.0.1 → 3.1.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 (124) hide show
  1. package/README.md +13 -8
  2. package/README.zh-CN.md +13 -8
  3. package/docs/HANDBOOK.md +88 -52
  4. package/docs/USER-GUIDE.en.md +9 -9
  5. package/docs/USER-GUIDE.zh-CN.md +9 -9
  6. package/docs/screenshots/promo/promo-0-banner-v4.png +0 -0
  7. package/docs/screenshots/promo/promo-1b-auto-recall.png +0 -0
  8. package/lib/activation-host.js +6 -1
  9. package/lib/client.js +819 -272
  10. package/lib/context-host.js +7 -1
  11. package/lib/episodic-store.js +90 -16
  12. package/lib/fact-store.js +463 -41
  13. package/lib/hub-io.js +217 -0
  14. package/lib/index.js +224 -45
  15. package/lib/intent-clean-safe.js +1 -1
  16. package/lib/memory-hub.js +37 -5
  17. package/lib/note-status.js +9 -1
  18. package/lib/procedure-store.js +252 -31
  19. package/lib/procedure-switch.js +38 -0
  20. package/lib/python-sidecar-client.js +285 -8
  21. package/package.json +6 -2
  22. package/docs/internal/ACCEPT-35-LIVE.md +0 -143
  23. package/docs/internal/ACCEPTANCE-20260914.md +0 -90
  24. package/docs/internal/ARCH-REVIEW-BRIEF.md +0 -411
  25. package/docs/internal/ARCH-REVIEW-REQUEST.md +0 -201
  26. package/docs/internal/ARCH-REVIEW-ROUND2.md +0 -169
  27. package/docs/internal/ARCH-REVIEW-ROUND3.md +0 -206
  28. package/docs/internal/ARCHITECTURE-FOR-ZCODE-20260920.md +0 -397
  29. package/docs/internal/ART-DIRECTION-DEEPSEEK-20260920.md +0 -351
  30. package/docs/internal/ART-DIRECTION-WIREFRAME.md +0 -191
  31. package/docs/internal/ART-DIRECTION-WIREFRAME.md.bak-superseded +0 -181
  32. package/docs/internal/AUDIT-WB-GRAPH-FULL-20260916.md +0 -314
  33. package/docs/internal/BATTLE-PLAN-20260917.md +0 -871
  34. package/docs/internal/CONCURRENCY-INVESTIGATION-20260917.md +0 -192
  35. package/docs/internal/CROSS-SESSION-SEARCH-PATH-DECISION.md +0 -72
  36. package/docs/internal/CROSS-SESSION-SEARCH-RESEARCH.md +0 -131
  37. package/docs/internal/CUA-VISION-FIX-NOTES.md +0 -78
  38. package/docs/internal/DECISIONS-20260914-SESSION.md +0 -269
  39. package/docs/internal/DESIGN-OVERHAUL-PRE-RESEARCH.md +0 -292
  40. package/docs/internal/DESIGN-P1-STATE-COMMIT-20260915.md +0 -219
  41. package/docs/internal/DIRECTION-CHECK-WB-GRAPH-20260916.md +0 -132
  42. package/docs/internal/FEATURE-INVENTORY.md +0 -531
  43. package/docs/internal/FEEDBACK-TO-DSHAPI-RELAY.md +0 -13
  44. package/docs/internal/G-SERIES-EXECUTION-20260917.md +0 -248
  45. package/docs/internal/G3-DESIGN-20260918.md +0 -82
  46. package/docs/internal/G3-DISK-FORMAT-GAP-20260919.md +0 -92
  47. package/docs/internal/GH-DISCUSSION-5732-COMMENT.md +0 -74
  48. package/docs/internal/GPT-ACCEPTANCE-PROMPT-20260916.md +0 -352
  49. package/docs/internal/GPT-REVIEW-PROMPT.md +0 -216
  50. package/docs/internal/GROUP-DIGEST-SETUP.md +0 -62
  51. package/docs/internal/GROUP-LISTENER-SETUP.md +0 -49
  52. package/docs/internal/GROUP-WEBHOOK-SETUP.md +0 -93
  53. package/docs/internal/HANDOFF-TO-ZCODE-20260920.md +0 -309
  54. package/docs/internal/HANDOFF-TO-ZCODE.md +0 -168
  55. package/docs/internal/HERMES-DATA-VERIFICATION-20260919.md +0 -120
  56. package/docs/internal/HERMES-LEGACY-STATUS-20260919.md +0 -74
  57. package/docs/internal/ISSUE-55-58-VERIFICATION-20260918.md +0 -175
  58. package/docs/internal/ISSUE10-FIX-EXECUTION-20260919.md +0 -389
  59. package/docs/internal/ISSUE10-PLAN-20260919.md +0 -254
  60. package/docs/internal/ISSUE10B-FORENSICS-20260919.md +0 -468
  61. package/docs/internal/ISSUE9-PURGE-AND-R1-PLAIN-20260919.md +0 -150
  62. package/docs/internal/ISSUE9-RESIDUAL-FORENSICS-20260919.md +0 -114
  63. package/docs/internal/KICKOFF-P0.md +0 -254
  64. package/docs/internal/LESSON-TO-CANDIDATE-STATUS-20260919.md +0 -79
  65. package/docs/internal/MASTER-PLAN-3.0.md +0 -411
  66. package/docs/internal/MEMORY-GOVERNANCE-20260917.md +0 -309
  67. package/docs/internal/MEMORY-MUTATION-AND-INDEX-DESIGN.md +0 -85
  68. package/docs/internal/MERGE-CONFLICT-SCAN-20260914.md +0 -222
  69. package/docs/internal/NEXT-VERSION-TODO.md +0 -95
  70. package/docs/internal/OFFICIAL-DISCUSSION-DRAFT.md +0 -80
  71. package/docs/internal/PENDING-FIXES-20260916.md +0 -289
  72. package/docs/internal/PRE-FRONTEND-CHECKLIST-20260919.md +0 -705
  73. package/docs/internal/PRE-FRONTEND-CHECKLIST-20260919.md.bak-s10 +0 -649
  74. package/docs/internal/PROCEDURAL-MEMORY-AND-APPROVAL-DESIGN-20260918.md +0 -225
  75. package/docs/internal/PROGRESS-20260917.md +0 -93
  76. package/docs/internal/PROMPT-GAP-AUDIT-20260920.md +0 -128
  77. package/docs/internal/R1-DEGRADE-AUDIT-20260918.md +0 -163
  78. package/docs/internal/R1-READABILITY-FORENSICS-20260919.md +0 -127
  79. package/docs/internal/R2-EVIDENCE-DEEP-AUDIT-20260918.md +0 -140
  80. package/docs/internal/R3-DEGRADE-LEDGER-DESIGN-20260918.md +0 -138
  81. package/docs/internal/R4-RECALL-QUOTA-PLAN-20260918.md +0 -218
  82. package/docs/internal/RAG-KARPATHY-PROGRAM.md +0 -229
  83. package/docs/internal/RELEASE-PROCESS.md +0 -99
  84. package/docs/internal/REPORT-P0-NIGHTLY.md +0 -212
  85. package/docs/internal/REPORT-P5-ACCEPTANCE.md +0 -31
  86. package/docs/internal/REPORT-WB-GRAPH-NIGHTLY.md +0 -153
  87. package/docs/internal/RESUME-20260918.md +0 -171
  88. package/docs/internal/RESUME-20260919.md +0 -104
  89. package/docs/internal/REVIEW-WB-GRAPH-SELF.md +0 -81
  90. package/docs/internal/RHINELAB-TO-DEEPSEEK-FEASIBILITY.md +0 -198
  91. package/docs/internal/ROADMAP-20260917-WEEK.md +0 -439
  92. package/docs/internal/ROADMAP.md +0 -106
  93. package/docs/internal/RUN-P0-NIGHTLY.md +0 -227
  94. package/docs/internal/S10-CONSTRUCTION-HANDOFF-20260917.md +0 -185
  95. package/docs/internal/S10-GAP-INVENTORY-20260917.md +0 -239
  96. package/docs/internal/S10-GAPS-PLAIN-20260917.md +0 -125
  97. package/docs/internal/SEMANTIC-ARCHITECTURE-SPEC.md +0 -360
  98. package/docs/internal/SESSION-FILE-REPAIR-PROTOCOL.md +0 -90
  99. package/docs/internal/SUBAGENT-REPORT-ROUTING-PRE-RESEARCH.md +0 -261
  100. package/docs/internal/T6-EXECUTION-20260920.md +0 -130
  101. package/docs/internal/TELEMETRY-EFFECT-REPORT-DESIGN-20260918.md +0 -146
  102. package/docs/internal/THESIS-GAP-ANALYSIS-20260918.md +0 -89
  103. package/docs/internal/THESIS-OUTLINE-20260918.md +0 -147
  104. package/docs/internal/THREE-LAYER-CONTRACT.md +0 -219
  105. package/docs/internal/TODO-BACKLOG.md +0 -263
  106. package/docs/internal/TODO-GRAPH.html +0 -715
  107. package/docs/internal/TODO-GRAPH.html.bak-20260914-v2 +0 -493
  108. package/docs/internal/TODO-GRAPH.html.bak-20260915-alsfix +0 -710
  109. package/docs/internal/TODO-GRAPH.html.bak-20260915-p1 +0 -710
  110. package/docs/internal/TODO-GRAPH.html.bak-20260915-p6a-rev +0 -703
  111. package/docs/internal/TODO-GRAPH.html.bak-20260915-wshint +0 -710
  112. package/docs/internal/TODO-GRAPH.html.bak-20260916-batch +0 -715
  113. package/docs/internal/UPSTREAM-ISSUE-PR-TRIAGE-20260919.md +0 -297
  114. package/docs/internal/UPSTREAM-ISSUES-3RD-AUDIT-20260920.md +0 -104
  115. package/docs/internal/WB-FORMAT-CONVENTION.md +0 -112
  116. package/docs/internal/WB-GRAPH-DECISIONS-20260914.md +0 -71
  117. package/docs/internal/WB-GRAPH-INTEGRATION-PLAN.md +0 -386
  118. package/docs/internal/WB-GRAPH-RESEARCH-BRIEF.md +0 -118
  119. package/docs/internal/WB-GRAPH-RESEARCH-EXTERNAL.md +0 -228
  120. package/docs/internal/WB-GRAPH-RESEARCH-LOCAL.md +0 -190
  121. package/docs/internal/reviews/CLAIM-VERIFICATION-20260914.md +0 -56
  122. package/docs/internal/reviews/PLAN-gpt6astra-round2-20260914.md +0 -787
  123. package/docs/internal/reviews/REVIEW-gpt6astra-20260914.md +0 -112
  124. package/docs/internal/reviews/ROUND3-REVIEW-INTEGRATION-20260914.md +0 -230
@@ -1,261 +0,0 @@
1
- # 子代理完成报告与窗口接续 · 技术预研
2
-
3
- > 状态:**只做预研,不出码**(用户 2026-09-10 指示「下一版再改」)。
4
- > 研究范围:DSH live 版本 0.1.5-rc.1 的官方包源码,逐条带 `文件:行号`。
5
- > 代码基准目录:`C:\Users\JH Z\AppData\Roaming\npm\node_modules\@deepseek-ai\dsh\node_modules\@deepseek-ai\`
6
- > 插件侧基准:`D:\dsh-auto-memory\lib\index.js`
7
-
8
- ---
9
-
10
- ## 0 结论摘要
11
-
12
- 1. **子代理完成后把报告投给"父",在 DSH 里是双重固定绑定,没有官方接口可以改投。**「re-parent / 改归属」在本版本不存在(`dsh-subagent` 的服务方法清单里没有任何写 `parentSession` 的方法)。
13
- 2. 想达成目标只有三条路:**①延后接续(避开问题)**、**②桥接转发(不改归属,改投递)**、**③双会话协同(交接材料声明 + 新会话自查)**。
14
- 3. 有一把**现成的官方钥匙**:DSH 的 Agent 句柄支持 `followup / steer / inject`,且 `ctx.get('agents').get(sessionId)` 按会话取句柄 —— 插件可以把任意消息投进**任意 live 会话并唤醒它**。转发路线就建立在这上面。
15
- 4. **另有一个比"投错窗口"更严重的隐患**:父会话不在 registry 时,结算通知**被静默丢弃**(`dsh-subagent:1249` 直接 `return`)。接续之后如果旧会话被销毁,在跑的子代理报告会**直接消失**——这条必须优先兜住。
16
- 5. 推荐顺序:**A 延后接续 → D 材料声明 → B 转发兜底 → C 可选**。
17
-
18
- ---
19
-
20
- ## 1 投递链:报告是怎么走到"父窗口"的
21
-
22
- 子代理分两类,**投递路径不同**。**本机默认走第二类**(`:1.2`)——`tool-subagent` 的 `backgroundMode` 在 standard/cordis preset 里是 `continuable`,所以用户看到的"报告"绝大多数是 **settlement notice**,不是 job 通知。
23
-
24
- ### 1.1 一次性后台子代理(走 job)
25
-
26
- - `dsh-tool-subagent/lib/index.js:537` 起一个 `kind: "background"` 的 job(带 `run_in_background` 的工具调用走这条;插件自己的 `auto-memory-fold/consolidate/greet` 也都是 one-shot)。
27
- - 完成通知由 **jobs 插件**发出:
28
- `dsh-tool-jobs/lib/index.js:206-227`
29
- ```js
30
- ctx.jobs.onJobDone((snapshot, owner) => {
31
- if (snapshot.reported || owner === void 0) return
32
- const message = createUserMessage({ content: [...], source: {...form: 'notice'} })
33
- if (delivery === 'wakeup' && owner.status === 'idle' && spent < wakeBudget) { owner.followup(message); return }
34
- owner.inject(message)
35
- })
36
- ```
37
- 官方模板:有界唤醒 `maxConsecutiveWakes: 3` + 超预算降级为 `inject`(不唤醒)。
38
- - **`owner` 是 spawn 时捕获的 Agent 句柄,不是 session id** —— 没有任何字符串层可以替换。
39
- - job 的所有权围栏同样按 owner 走:`dsh-jobs/lib/index.js:51-55`(「access is fenced by the owner's session id」)、`dsh-jobs-local/lib/index.js:179-180`(`job.owner.id === session`)。
40
-
41
- ### 1.2 可续子代理(走 activation;**本机默认**)
42
-
43
- - 结算投递:`dsh-subagent/lib/index.js:1244-1259`
44
- ```js
45
- notifySettlement(activation, terminal) {
46
- if (!activation.announced) return
47
- const parent = this.ctx.agents.get(activation.parentSession) // ← 结算时按 session id 现取
48
- if (parent === void 0) return // ← 父不在 ⇒ 静默丢弃
49
- const message = createSettlementMessage(activation.childId, terminal)
50
- if (this.closingTeardownFor(parent) !== undefined) { parent.inject(message); return }
51
- this.sendWaking(parent, message, parent.status === 'idle' ? 'queue' : 'steer')
52
- }
53
- ```
54
- - 投递原语:`dsh-subagent/lib/index.js:873-885` —— 父自身是 resident 激活时走它的 inbox 并唤醒,否则退化为 `parent.steer(message)` / `parent.followup(message)`。
55
- - 通知正文形态:`dsh-subagent/lib/index.js:641-681` —— 首行 `Background subagent <childId> finished...`,附「Its closing message:」+ 子代理最后一条消息;`source = { kind: 'subagent-settled', form: 'notice', senderSessionId: childId }`。
56
-
57
- ### 1.3 三处绑定 + 一处内存快照
58
-
59
- | 绑定 | 位置 | 性质 |
60
- |---|---|---|
61
- | `child.header.parentSession` | 子会话 header(持久化) | 只用于**查询过滤**(`dsh-subagent:2073`、`2180`)与**授权校验**(`:862`、`:968`) |
62
- | `activation.parentSession` | `dsh-subagent:1089` 建立激活时写入 | 内存快照;**通知投递读它**(`:1248`) |
63
- | `job.owner` | job 记录 | 一次性后台子代理的投递目标 |
64
-
65
- ### 1.4 我们真正能用的投递面(关键)
66
-
67
- `dsh-agent-loop/lib/index.js:773-797`:
68
- ```js
69
- get status() { return this.phase.kind === 'idle' || this.phase.kind === 'maintenance' ? 'idle' : 'running' }
70
- followup(input) { this.send(input, 'next-turn', true) } // 排队 + 唤醒
71
- steer(input) { this.send(input, 'next-step', true) } // 插到最近一步 + 唤醒
72
- inject(input) { this.send(input, 'next-step', false) } // 只排队,不唤醒
73
- ```
74
- 配合 `ctx.get('agents').get(sessionId)`(Agent 注册表按会话 id 取),**插件可以往任意 live 会话投递并选择是否唤醒**。这是转发方案的全部基础;插件目前已经在用同一注册表(`lib/index.js:6693` `engine._subagents = ctx.get('subagents')`,`_lastAgent` 也来自 `ctx.get('agents')`)。
75
-
76
- ### 1.5 实机取证(本机 2026-09-10 18:31)
77
-
78
- 从 DSH 的会话投影缓存直接读出(路径:`~/.dsh/storages/session_projcache/sessions/<sessionId>.json` → `record.rows.*`):
79
-
80
- **① 每个会话都有一行 `subagentCatalog`,内容就是它的直接子代理清单:**
81
- ```json
82
- {"inheritedEventCount":0,"head":{"values":[
83
- {"version":0,"childId":"…","childCreatedAt":1789035230558,"mode":"one-shot","label":"auto-memory-fold"},
84
- {"version":0,"childId":"…","childCreatedAt":1789035713789,"mode":"continuable","label":"文档体系审计"}
85
- ]}}
86
- ```
87
- 本机实测:旧会话 `40727a84` 的 catalog 有 13 条(含本预研刚 spawn 的两个研究子代理,`childCreatedAt=1789036077798/99`),新会话 `9cc01f76` 的 catalog 有 5 条(含 18:21:53 spawn 的三条设计审计)。
88
- → **归属是按父会话分行的,一行不会串到另一行** —— 这正是问题所在,也说明"哪个孩子属于谁"随时可查、成本极低。
89
-
90
- **② 接续之后两条会话同时 live**:18:31:38 与 18:31:28 两个时刻,`40727a84`(6.2MB)与 `9cc01f76`(1.4MB)的 `session.v3.jsonl.zstd` **都在持续写入**。
91
- → 旧会话并没有因为接续而退出,它仍然在跑回合、仍在收孩子的报告。这解释了用户看到的现象,也让"以旧父身份继续管孩子"(路线 C)在当前进程内成立。
92
-
93
- **③ 由此得到一条更省事的数据源**:判定"某会话是否还有孩子在跑",不必非走 `listChildren`,用 `agents.get(childId)?.status === 'running'` 就行(`status` 语义见 §1.4),孩子的 id 从 `subagentCatalog` 投影行拿。`agents` 服务插件已经在用。
94
- ⚠️ 但 `subagentCatalog` 本身**没有 activity 字段**(`SA/lib/types/projection-types.d.ts:8-17`:只有 `{id, createdAt, mode, label}`),而且 `listChildren` 的 `activity` 走的是 Session store 口径(在内存= running),**只有浏览器面 `remoteExportList` 才会重新采样 Agent driver**(`SA/lib/index.js:74-83`)。所以要拿到真实"在跑"状态,host 侧应当自己 `agents.get(id)?.status` 复核。
95
-
96
- ### 1.6 可用的官方投递面(实现时会用到的原语清单)
97
-
98
- | 原语 | 位置 | 语义 |
99
- |---|---|---|
100
- | `agent.followup(msg)` | `dsh-agent-loop:789` | 排到 next-turn **并唤醒**(空闲会话立刻开新回合) |
101
- | `agent.steer(msg)` | `:792` | 插到 next-step **并唤醒** |
102
- | `agent.inject(msg)` | `:795` | 插到 next-step **不唤醒**;空闲会话可能永远不醒,`cancel`/dispose 会丢弃 |
103
- | `agent.status` | `:773` | `idle` / `running` |
104
- | `ctx.get('agents').get(sessionId)` | Agent 注册表 | **只返回 live 的** Agent |
105
- | `sessionController.resolveAgent(sessionId)` | host-only | 冷会话也能**现场拉起**再投递 |
106
- | `sessionController.prompt({requestId, sessionId, mode:'queue'\|'steer', content})` | `SC/lib/index.js:773-774` | `queue`=新回合、`steer`=当前回合下一步;两者都不打断 |
107
- | `ctx.on('subagent/end', info)` | `SA/lib/types/index.d.ts:94` | 子代理结束事件:`{runId, provider, id, stopReason, lastAssistantMessage?}` |
108
- | `ctx.on('agent/turn-stopping')` | `AG/lib/types/runtime-types.d.ts:396` | 回合将关;listener 可 `agent.steer()` 让回合继续 |
109
- | `ctx.on('agent/status')` | `:247` | `{agent, status}` 状态跃迁(可做"子代理由 running→idle"的触发) |
110
-
111
- **两条硬边界**(必须记住):
112
- - 子代理子会话(`header.origin === 'subagent'`)不能走 `sessionController.prompt`,一律 `session/agent-busy` + `use subagent delivery for this child session`。
113
- - `sessionController` **没有** session 级 ACL:`dsh-authorization` 与越权无关;host 插件直调不需要 approval。换句话说,该做的闸门由插件自己把关(只对"已被接续过的旧会话"做转发)。
114
-
115
- ---
116
-
117
- ## 2 「能不能直接改投」— 逐条否证
118
-
119
- | 设想的办法 | 结论 | 证据 |
120
- |---|---|---|
121
- | 官方有没有 re-parent / transfer 接口 | **没有**。服务方法清单只有 `list / listChildren / listDescendants / remoteExportList / prompt / interrupt / drainContinuableChildren / start / startContinuable / sendMessage` | `dsh-subagent:2981 / 2999 / 3015 / 3040 / 3082 / 2959` |
122
- | 让新会话直接接管旧会话的子代理 | **被授权拒绝**:控制面按 `header.parentSession` 校验,跨父报 `subagent "X" belongs to another parent session` | `dsh-subagent:862`、`:968`、`:945` |
123
- | 改子会话 header 的 `parentSession` | **不建议**:官方持久化格式字段 + 内存快照(activation)与 job.owner 各自独立,改一处不足以重定向 job 那条路,还会让 `authorizeLineage` 与新父不一致 | `:1001`、`:945`、`:968` |
124
- | 反射式改 `activation.parentSession` / `job.owner` | 理论可行、**强烈不建议**:跨版本立即碎,且 `ancestry` 校验(`:863`、`:945`)按建立时的谱系判定,改完控制面全废 | 同上 |
125
-
126
- **唯一"正解"是把投递改写在自己的层上** —— 见第 3 节 B。
127
-
128
- ---
129
-
130
- ## 3 四条可行路线
131
-
132
- ### A. 延后接续(治本,先做)
133
-
134
- **原理**:问题的本质是「旧会话还有在跑的孩子,却被接续了」。把空闲判据从「回合边界」扩到「回合边界 **且** 无 running 直接子代理」。
135
-
136
- - **接续时记名**(最小改动、收益最大):在 `hostAutoContinue` / 一键接续组装材料前,用 `listChildren(oldSid)` 取一次"未完成子代理清单",把**子代理 id + 标签 + 起始时间**写进交接材料(路线 D)。即使它们后来报告到了旧窗口,新会话也知道"有谁在外面跑、用哪个 id 去问"。
137
- - 数据源:`ctx.get('subagents').listChildren(parentSessionId, signal)` → `resolveCandidateRows(...)` 按 `header.parentSession === parentSessionId && origin === 'subagent'` 过滤(`dsh-subagent:2073`);`remoteExportList` 额外给 `activity: running | inactive`(用 live Agent 注册表判定,`:74-83`)。
138
- - ⚠️ **只有用旧会话 id 查得到这些孩子**:`listChildren(newSid)` 查不到(`:2073` 按 `header.parentSession` 过滤)——这也是"新会话无法接管"的同一个根因。
139
- - 落点:插件 `lib/index.js:2143-2150` 的 `tickAutoContinue` → `awaitIdle` 分支,`busy` 判据追加「有 running 直接子代理」,沿用现有 `deferCount` 上限机制(最多 5 次 × 20s)。
140
- - 必须带三条保险:①**硬上限**(例如最多推迟 5 分钟或 5 次),超时照常接续,避免长任务里永不接续;②**用户手动接续不受限**(一键接续直接走);③service 不可用时 **fail-open**(`subagent/projections-unavailable` 等错误照常接续)。
141
- - 代价:约 10-15 行 + 一处 service 调用。风险:低。
142
-
143
- ### B. 桥接转发(真正把报告送进新窗口)
144
-
145
- **原理**:不改变归属,插件自己把「结算事实」再投一份到新会话。
146
-
147
- #### B-0 触发器:**官方有专门的事件,插件直接订阅即可**
148
-
149
- `dsh-subagent/lib/types/index.d.ts:85,94` 提供两个事件:**`subagent/start`** 与 **`subagent/end`**;
150
- `SubagentRunEndInfo = { runId, provider, id: SessionId, local, stopReason, lastAssistantMessage?: ContentBlock[] }`(`types.d.ts:93-110`),`stopReason ∈ {completed, aborted, error, 'max-tokens', refusal}`。
151
-
152
- 官方现成消费范例(实现 Claude Code 的 `SubagentStop` 钩子):
153
- ```js
154
- // dsh-hooks-claude-code/lib/index.js:309-329
155
- ctx.on("subagent/start", (info) => { const child = ctx.get("agents")?.get(info.id) ... })
156
- ctx.on("subagent/end", (info) => { const child = subagentChildren.get(info.runId) ?? ctx.get("agents")?.get(info.id) ... })
157
- ```
158
- ⇒ **转发只要在插件自己的 ctx 上 `ctx.on('subagent/end', info => ...)`**,payload 里已经带了子代理 id、结束原因与最后一条消息 —— 不需要枚举孩子、不需要轮询、不需要读日志。
159
-
160
- ⚠️ 但 **payload 里没有 parentId**,而且该事件是在 `notifySettlement` **之后**才 emit 的(`dsh-subagent:1239 → :1241`:看到事件时原通知已经入队)。所以"这条报告原本要发给谁"要在事件里自己解一次:
161
- ```js
162
- ctx.on('subagent/end', (info) => {
163
- const child = ctx.get('agents')?.get(info.id) // 官方范例就是这么取的
164
- const fromSid = child?.session?.header?.parentSession // 子会话自己的 durable 头
165
- ... // 再用闩锁表把 fromSid 映射到 toSid
166
- })
167
- ```
168
- (官方另有一个反解范例:`dsh-sdk-jsonrpc-server/lib/index.js:35-37 subagentParentOf`。)
169
-
170
- ⚠️ **不要用"打补丁 steer/followup"的方式拦截**:当父本身是常驻可续子代理时,通知走的是父自己的 activation inbox(`dsh-subagent:874-881`),根本不经过 `agent.steer/followup` —— 补丁会漏。正确做法是**旁听**(`subagent/end` 或 `agent/inbox/inserted`),把文本**复制**一份给新会话。
171
-
172
- **兜底触发器**(覆盖 `subagent/end` 看不到的路径,例如 job 通知未走 activation):插件今天已经在监听原始事件流 `ctx.on('session/event', ...)`(`lib/index.js:6826-6828`),并已在里面按 `event.type === 'user/message'` 分流、读 `source.kind` 与插件名(`:1182-1186`、`:6109-6110`)。两类通知最终都是父会话里的一条 `user/message`:
173
- - 可续子代理:`source = { kind: 'subagent-settled', form: 'notice', senderSessionId: <childId> }`(`dsh-subagent:674-679`)
174
- - job:`source = { kind: 'plugin', plugin: 'tool-jobs', form: 'notice' }`(`dsh-tool-jobs:213-218`)
175
-
176
- #### B-1 投递目标
177
-
178
- 后继会话 id 从已接续闩锁文件 `~/.dsh/memory/auto-continue-done.json`(`{sessions:[{from,to,at}]}`)取 —— 现成数据,`from` 命中事件所属会话即可。
179
-
180
- #### B-2 投递方式
181
-
182
- ```js
183
- const agents = ctx.get('agents')
184
- let target = agents?.get(toSid) // 只返回 live 的
185
- if (!target) target = await ctx.sessionController?.resolveAgent(toSid) // 冷会话现场拉起
186
- target.status === 'idle' ? target.followup(msg) : target.inject(msg)
187
- ```
188
- 与官方 `sendWaking` 同款策略(`dsh-subagent:1255`):空闲则排队并唤醒,忙则只排队不打断。
189
-
190
- ⚠️ 三个必须避开的坑(均来自官方明文):
191
- 1. **不要用 `sessionController.prompt` 投给子代理子会话**:`header.origin === 'subagent'` 一律被拒为 `session/agent-busy`,reason `use subagent delivery for this child session`(`dsh-api-session-controller/lib/index.js:124-138`)。
192
- 2. **`requestId` 是幂等键**:撞车时服务**静默返回 `accepted:true` 但不投递**(`SC/lib/index.js:741`)。转发每次都要现铸新 id,否则报告会丢。
193
- 3. **必须自带唤醒预算**:照抄 `maxConsecutiveWakes` 思路,否则每个子代理结算都开一个模型回合(烧钱且噪音大);超预算降级为 `inject`。
194
- 另:`prompt` 的兜底 catch 会把一切 admission 异常包成 `session/agent-busy` / `"prompt rejected"`,真因只在 `reason` —— 日志必须打 `reason`,否则失败不可见(这正是 2.4.0 修过的那条故障线)。
195
-
196
- #### B-3 消息形态建议
197
-
198
- ```
199
- 【上游子代理结算 · 来自已被接续的会话 <oldSid8>】
200
- Background subagent <childId> finished...(原文首行)
201
- 摘要:<...>
202
- 回读:job_output(<jobId>) / 该子会话 <childId> 末尾若干条
203
- ```
204
-
205
- #### B-4 遗留问题
206
-
207
- - 旧会话里的原通知**无法撤回**,会与新会话里的转发件并存(可接受;若嫌吵,可在旧会话侧做"已转发"标记,但这需要改官方渲染面,不做)。
208
- - 转发件是 user 角色消息,新会话可能当真用户输入 —— 故正文必须显式标注来源(见 B-3)。
209
- - 退避:同一 `senderSessionId` + 同一内容指纹去重,避免重复投递。
210
-
211
- ### C. 以旧父身份继续管那些子代理(可选)
212
-
213
- 插件是 host 侧、持有原始 service,可以直接:
214
- ```js
215
- subagents.prompt({ parentSessionId: oldSid, childSessionId, mode: 'continuable', delivery: 'queue', requestId, content })
216
- subagents.interrupt({ parentSessionId: oldSid, childSessionId, mode: 'continuable' })
217
- ```
218
- 前提:旧会话 agent 仍 live(否则 `subagent/parent-unavailable`,`dsh-subagent:3046`);子代理必须是 continuable(`subagent/not-resumable`)。**新会话自己不能管**(授权按 header.parentSession)。
219
-
220
- 用途:续问/收拢/中断"遗留孩子"。不是必须项。
221
-
222
- ### D. 交接材料声明 + 新会话可查(顺手做,零风险)
223
-
224
- - 接续时把「旧会话在跑的子代理清单」(id + 标题 + 起始时间 + 是否 continuable)写进交接材料(carry),让新会话一开始就知道"还有哪些活在外面跑"。
225
- - 插件再暴露一个**只读**查询面(HTTP 端点或给新会话用的工具),回答"旧会话的孩子现在什么状态、输出在哪"。
226
- - 代价:小。把「完全看不见」变成「看得见、可回读」。
227
-
228
- ---
229
-
230
- ## 4 需要实机验证的点(改之前先测)
231
-
232
- 1. 接续之后,旧会话的 agent 是否仍 live(`ctx.get('agents').get(oldSid)`)?—— 决定 A 能否等待、B/C 能否读到孩子输出。**已初步取证:是**(18:31 两份 v3 日志同时在写,见 §1.5)。
233
- 2. `listChildren(oldSid)` 在本机能否返回(取决于 projections / sessionQuery 是否挂载),错误码分别是什么。
234
- 3. 一次性后台子代理的 job `snapshot` 里有没有可判别"这是子代理 job"的字段(`kind` / `label`),用于 B 的过滤。
235
- 4. **`subagent/end` 在插件 ctx 上的可见范围**:能否收到别的作用域下的子代理结束(官方 `dsh-hooks-claude-code` 用它实现全局 SubagentStop,倾向可以);payload **不含 parentId**,需自己从子会话 header 反解。
236
- 5. **`announced` 门**:通知只在 `activation.announced === true` 时发出,而它只在父**真的投递过消息**给子代理才置位(`dsh-subagent:1246`、`:1809/1929`)—— 存在"结算了但从不产生通知"的子代理,这类只能靠 A/D 兜。
237
- 6. **本机 `backgroundMode` 已确认为 `continuable`**(`dsh-agent-presets/presets/standard/agent.cordis.yml:181-187`),故 live 路径是 settlement notice;job 那条路只对显式 `run_in_background` 的 one-shot 生效。
238
- 7. 新会话被 `followup` 唤醒时的打扰程度(用户正在输入时是否该退化为 `inject` 只排队)。
239
- 8. 父会话销毁后通知是否真的丢弃(`:1249`)—— 若会丢,B 必须"落盘优先",否则报告永久消失。
240
-
241
- ---
242
-
243
- ## 5 明确不做的事
244
-
245
- - ❌ 不改 DSH 内部对象(`activation.parentSession`、`job.owner`)。
246
- - ❌ 不重写子会话 header 的 `parentSession`(官方持久化格式 + 校验,跨版本必碎)。
247
- - ❌ 不改官方 UI 的 subagent 面板;所有改动留在插件自己的 layer。
248
- - ❌ 不在本轮出码 —— 本文只是预研。
249
-
250
- ---
251
-
252
- ## 6 与现有插件的接口对照(落点清单)
253
-
254
- | 需要的东西 | 现状 | 缺什么 |
255
- |---|---|---|
256
- | subagents service | `lib/index.js:117` 已 `inject: ['subagents']`,`:6693` 已缓存 `_subagents` | 直接用 `listChildren` / `remoteExportList`(尚未调用) |
257
- | agents 注册表 | `_lastAgent` / `inheritPermission*` 已在用 | 把它当"投递口"用(`followup/inject`)是新增语义 |
258
- | 接续映射表 | `~/.dsh/memory/auto-continue-done.json`(`from → to`) | 正好可作为 B 的判据来源 |
259
- | job 完成事件 | 未订阅 | 新增 `ctx.jobs.onJobDone` 监听器 |
260
- | 空闲判据 | `tickAutoContinue` 的 `awaitIdle`(`:2143-2150`) | 追加"无 running 子代理" |
261
- | 交接材料 | `buildContinueCarry` | 追加"在外子代理清单"一节 |
@@ -1,130 +0,0 @@
1
- # T6 执行记录 — 代码能力 ↔ 模型 prompt 全量对齐 + DeepSeek Flow 可行性研究
2
-
3
- > 日期:2026-09-20 · 触发:用户拍板「**全量补上,不然现在没有大模型的加持,这些代码都是死代码,什么都用不了**」
4
- > 基线:改前全量回归 **PASS 134 / FAIL 0 / TIMEOUT 0**;改后 **PASS 134 / FAIL 0 / TIMEOUT 0(139.5s)**
5
-
6
- ---
7
-
8
- ## 一、DeepSeek Flow 可行性研究结论(用户指定站点)
9
-
10
- **站点**:https://deepseekflow.kanghelyu.org/ · **仓库**:https://github.com/kanghelyu/dsh-deepseek-flow · **许可**:MIT(§License 确认)· **版本**:npm 0.4.2 / 站点标 v0.3.17
11
-
12
- ### 它是什么(实测抓取)
13
-
14
- | 维度 | 实测内容 |
15
- |---|---|
16
- | 定位 | **可视化工作流编辑器** —— 官网原文「DeepSeek Flow 是编辑器,而不是工作流运行器」 |
17
- | 事实来源 | 一份 `WORKFLOW.md` + 每步一个 `STEP.md`,Markdown 为唯一 source of truth |
18
- | 画布 | 节点/连线/分支/依赖,可缩放拖拽;画布与 Markdown **双向同步** |
19
- | 逻辑门 | **8 类**:IF/ELSE · AND · OR · NOT · NAND · NOR · XOR · XNOR(`data.gateType`) |
20
- | 谓词 | 仅 `truthy` / `falsy` / `nonEmpty` —— **严禁自然语言条件**,语义判断须上游 Agent 步骤输出 JSON 布尔 |
21
- | 拓扑事务 | 本地校验 → Session 审查 → 二次校验 → **原子保存**(新 revision,过期拒绝) |
22
- | 隔离 | **per-session**:每个 Harness session 各持自己的工作流 |
23
- | 模型工具 | `flow_create` / `flow_read` / `flow_put` / `flow_finalize_canvas` 等,附 `skills/deepseek-flow/SKILL.md` |
24
- | 技术栈 | ESM + `zod` + `@deepseek-ai/dsh-typert-protocol`;client 注入 4 个 DSH client 包;`platform: web` |
25
- | 主题 | 跟随 Harness 明暗 + 界面语言(中/EN 完整覆盖) |
26
- | 测试 | 官方称 **75** 条自动化测试 |
27
-
28
- ### 结论:**形态不同,不能直接替换看板;但三条架构可移植**
29
-
30
- | # | 可移植点 | 为什么对我们有价值 | 风险 |
31
- |---|---|---|---|
32
- | **F-1** | **Markdown 为唯一事实源 + 画布双向同步** | 我们的白板/账本本来就是 Markdown;看板是**只读投影**,模型改文件、面板跟着变,与它的范式一致 | 低 —— 我们已是这个架构 |
33
- | **F-2** | **待审草稿 → Session 审查 → 原子保存** | 正好解决用户痛点:模型改白板**不静默落盘**,先成草稿,再由 Session 审,带 revision 防并发覆盖 | 中 —— 需引入 revision 概念 |
34
- | **F-3** | **`SKILL.md` 随插件分发、注册后自动加载** | 与 T4 的 `memory_procedure_pre` + skill 导出层方向一致,可参考其 frontmatter 与工具命名规范 | 低 |
35
- | **F-4** | **8 类确定性逻辑门** | ⚠️ **不适用** —— 我们的看板是**状态展示**不是**流程编排**;硬套会引入无意义的布尔语义 | —— |
36
-
37
- ### 判定(一句话)
38
-
39
- **不能换掉看板,但可以吸收「草稿→审查→原子保存」这一条改造看板的写侧。** 用户说「自由发挥空间还挺多的」成立:看板目前是纯只读投影,写侧完全靠模型直接改文件;Flow 的拓扑事务模型正好是补这块的现成参照。**是否要做,待用户拍板**(属前端重构范畴,触及 §8 决策点)。
40
-
41
- ---
42
-
43
- ## 二、T6 主体:全量补齐模型侧缺口(已落地)
44
-
45
- ### 改了什么(7 处,全部在 pre 线)
46
-
47
- | # | 位置 | 内容 | 性质 |
48
- |---|---|---|---|
49
- | 1 | `lib/index.js` `applyNoteStatusPre` | 签名与 JSDoc 加 `retract` / `reason` | 新能力 |
50
- | 2 | `lib/index.js` `applyNoteStatusPre` 循环体 | **新增 `plan.retract` 处理循环**(调 `applyStatusToRecordPre(text, id, 'retracted', {reason})`) | 🔴 A1 通道打通 |
51
- | 3 | `lib/index.js` `memory_note_pre` 调用侧 | 透传 `retract` + `retractReason`;门扩为三门 | 接线 |
52
- | 4 | `lib/index.js` `memory_note_pre` 参数表 | 新增 `retract` / `retractReason` 两个参数,**含与 supersedes 的分工说明** | 模型可见 |
53
- | 5 | `lib/index.js` `memory_note_pre` 主描述 | 补「结论失效时的两个通道(不要混用)」+ 看板 tag 说明 | 模型可见 |
54
- | 6 | `lib/index.js` `renderMemoryStatic` | **新增「看板分列(5 条泳道 + tag 命名约定)」整条注入** | 🔴 A5/A6 打通 |
55
- | 7 | `lib/index.js` + `lib/client.js` 铭文 | 第④条改为「结论失效/被取代」(含 retract 分工);**新增第⑤条「看板落列」** | 收尾提醒 |
56
-
57
- ### 关键设计决策
58
-
59
- **`retracted` 与 `superseded` 严格分工**(写进工具描述,模型据此选):
60
-
61
- - `supersedes` = 被**更新的结论取代**(有后继,可追 `mem_id`)
62
- - `retract` = **当时就做错了、直接撤回**(无后继,"错误本身"就是教训)
63
- - `restore` = 撤销通道(标错了改回 `current`)
64
-
65
- 依据:用户 2026-09-18 裁定「**retracted 不是垃圾,是教训,不过滤只备注**」。此前 `note-status-pre.js` 三态齐备、`renderStatusLinePre` 也支持渲染 retracted、L0 侧还有 `L0_RETRACTED_MARK_PRE_V1='⚠已撤回'` 的呈现后缀,**但工具层只有 supersedes 一个通道且硬编码映射到 superseded** ⇒ 教训通路模型根本写不了。
66
-
67
- **为什么铭文上限从 800 放宽到 1200**:新增的 retract 分工与看板 tag 属**必需内容**(模型不知道则对应功能永不触发)。实测约 950 字符 ≈ 475 token = `injectBudgetChars`(8000) 的 12%;且本段走 `systemPrompt.context()`(**不击穿前缀缓存**),内容不变时 `project()` 去重不加发。1200 是**防继续膨胀的护栏**,不是精确预算。
68
-
69
- ---
70
-
71
- ## 三、验收(全部实跑,非纸面)
72
-
73
- | 项 | 结果 |
74
- |---|---|
75
- | `node --check`(index.js / client.js) | ✅ 通过 |
76
- | G4 套件 | ✅ **10 / 10**(新增 G4-6c / G4-6d 两条接线守卫) |
77
- | G3 套件 | ✅ **29 / 29**(门锁同步并加严) |
78
- | note-status 套件 | ✅ **74 / 74** |
79
- | **变异验证** | ✅ **4 / 4 全部真红**(`artifacts/_mutate-t6.mjs`) |
80
- | 字节一致还原 | ✅ SHA256 `DF32BABA…A8835` |
81
- | **全量回归** | ✅ **PASS 134 / FAIL 0 / TIMEOUT 0(139.5s)** |
82
-
83
- ### 变异验证明细(这是本轮最有价值的部分)
84
-
85
- | 靶点 | 结果 |
86
- |---|---|
87
- | 删掉 `plan.retract` 处理循环 | ✅ 真红 |
88
- | 删掉调用侧 `args.retract` 透传 | ✅ 真红 |
89
- | 删掉工具参数 `retract` 定义 | ✅ 真红 |
90
- | 删掉静态纪律整条看板 tag 语句 | ✅ 真红 |
91
-
92
- **★ 过程中抓到一个真实缺陷**:G4-6 首版**只断言铭文文本含 `retract` 字样**,第一次变异(删掉 `plan.retract` 循环)时套件**仍然全绿** —— 典型「**断言太弱、路径未覆盖**」。据此**新增 G4-6c**(断言 retract 通道三处齐备:参数/描述/处理循环/调用侧透传)与 **G4-6d**(断言看板 tag 真在 `renderMemoryStatic` 函数体内,而非文件别处的同名注释)。
93
-
94
- **★ 另一个教训**:变异4 首版**靶点选错**(只删段中一句,tag 名仍在续行 ⇒ 假绿)。判定为**靶点无效**而非守卫失效,改为正则整段删除后真红。⇒ **变异假绿要先怀疑靶点,再怀疑守卫。**
95
-
96
- ---
97
-
98
- ## 四、顺带修的两处硬锁(属合法扩展,锁同步加严)
99
-
100
- | 套件 | 原锁 | 处置 |
101
- |---|---|---|
102
- | `smoke-test-note-status-pre.mjs` #7-5 | `!IDX.includes('note-status-pre.js')` —— 用**弱子串**检测"是否已接线" | **误报**:我注释里写了文件名即触发。真实接线走 `note-status-apply-pre.js`。改注释措辞消除,**锁语义未动** |
103
- | `smoke-test-g3-note-status-wire-pre.mjs` #2-2 | `/if \(sup\.length \|\| res\.length\)/` 字面锁两门 | 门扩为三门是**合法扩展**;锁同步为三门,并**加严**:逐个断言 `sup`/`ret`/`res` 都在门里 |
104
-
105
- ---
106
-
107
- ## 五、B 类剩余缺口(**尚未补**,待拍板)
108
-
109
- 以下 11 条已在前轮 `PROMPT-GAP-AUDIT-20260920.md` 列出,本轮**只补了 B1/B2 相关的铭文部分**,其余仍在:
110
-
111
- | # | 缺什么 | 影响 |
112
- |---|---|---|
113
- | B1 | 白板/账本**两套四段措辞**(`:5726` vs `:570`/`:3658`)| 模型可能当同一件事 |
114
- | B3 | procedure 缺 `successCriteria` **结构上永不晋升**(T4 硬事实,未在描述里点明) | 模型可能写空判据 |
115
- | B4 | R1 四条可读性判据仅在文档 | 模型不知何为"可读" |
116
- | B5-B11 | 各工具参数/时机的描述不全(`date` 补写过去 / 容量整理行为 / `expand` 组合语义 / `days` 阈值 / `status`+`reflect` 时机 / `external` 只记指针 / 自动沉淀 vs 手动 consolidate 边界) | 模型用错或不用 |
117
-
118
- **A 类剩余**(模型零入口,需新增工具):
119
-
120
- - **A2** `fact-store-pre.js` 9 个能力(含 `isExpired` 过期、`resolveConflict` 冲突、`revokeBySource`)—— **零 `defineTool`**
121
- - **A3** episodic 写入 —— 仅宿主自动(`index.js:7411`)
122
- - **A4** fact 5 个枚举(epistemic_status / scope / source_kind / source_class / trend)无语义说明
123
-
124
- ---
125
-
126
- ## 六、需用户动作
127
-
128
- 1. **重启 DSH 宿主** —— 本轮改了 `lib/index.js` + `lib/client.js`,不重启不生效(**宿主只能用户手动重启,AI 不得执行**)
129
- 2. **拍板是否继续补 B 类剩余 + A2/A3/A4**
130
- 3. **拍板 DeepSeek Flow 的 F-2(草稿→审查→原子保存)是否纳入前端重构**
@@ -1,146 +0,0 @@
1
- # 用户端「效果统计与回传」设计(2026-09-18 立项稿)
2
-
3
- > 状态:**设计定稿,实现后置**(排在「Surface 前端重构之后、S 层之前」)
4
- > 用户原话:「我希望把这个统计功能扩展一下,也给用户们装上,让用户收集一下这个插件的效果,
5
- > 比如有效性。用户可以选择是否通过 GitHub 或者通过 QQ 群发给我」
6
-
7
- ---
8
-
9
- ## 0. 一句话
10
-
11
- **把已有的观测面(degrade 台账 + 配额探针 + tier0Meta)派生成一份「效果报告」,
12
- 用户在本地看一眼、自己决定要不要发回来。插件永远不主动联网。**
13
-
14
- ---
15
-
16
- ## 1. 三条硬红线(不可协商)
17
-
18
- | # | 红线 | 理由 |
19
- |---|---|---|
20
- | **R1** | **插件自身绝不发起网络请求** | 这是**记忆插件**,数据面本身就是隐私面。回传只能是"用户手动搬运",不能是"插件悄悄上报" |
21
- | **R2** | **报告只含聚合量,绝不含内容** | 禁止出现:记忆正文、文件路径、查询词、会话 ID、模型名、分钟级时间戳。只允许:计数 / 比例 / **分桶** / 布尔 / schema 版本 |
22
- | **R3** | **发送永远是显式动作** | 本地生成报告 = 随时可做(纯派生,无副作用);**发出去** = 用户点按钮/复制粘贴,且事先能看到全文 |
23
-
24
- > **为什么这么严**:本仓已发布 npm 3.0.0,有真实用户与年下载量。
25
- > 普通插件的遥测泄漏是"行为数据",记忆插件的遥测泄漏是**用户自己写下的东西**。量级不同。
26
-
27
- ---
28
-
29
- ## 2. 与既有观测面的关系(守 S10.4)
30
-
31
- **不新建状态源** —— 报告是**纯函数派生**,数据全部来自已经存在的东西:
32
-
33
- | 数据 | 来源 | 现状 |
34
- |---|---|---|
35
- | 降级频次/种类 | `degrade-pre/latest.json` 的 degrade 段 | ✅ R1–R3 已有 |
36
- | 配额判定四档、各层丢弃率 | 同文件的 `quota` 段 | ✅ R4 第 2 批已有 |
37
- | 注入侧 items/candidates/dropped/perLayer/tokens | `tier0Meta` | ✅ 已有 |
38
- | 配置开关 | 配置快照,**只取布尔/枚举,不取值** | ✅ 已有 |
39
- | 召回层分布、compaction 原因分布 | — | ⚠️ **需新增少量计数器** |
40
-
41
- ### 2.1 唯一的新增状态(有界计数器)
42
-
43
- 为回答「有效性」必须有的、目前**没有**的计数:
44
-
45
- ```
46
- recall: calls / withHits / emptyRate / layerMix{结论层,流水层,其他}
47
- injection: tokensPerTurn(均值) / droppedPerTurn(均值) / perLayerDropRate
48
- compaction: count / reasons{成功,no-removable,still-over-capacity} / recoveredChars
49
- scale: daysInstalled / sessions / entries / logLines ← 全部**分桶**
50
- ```
51
-
52
- 全部落进**同一个有界计数器对象**(复用 `lib/degrade-pre.js`,与 `quota` 并列),
53
- 仍不新建文件、不新建配置键。**`layerMix` 是重点**:它直接回答
54
- 「R4-B 的分层展示有没有让结论层真的浮出来」。
55
-
56
- ---
57
-
58
- ## 3. 报告形态
59
-
60
- ```jsonc
61
- {
62
- "reportSchemaVersion": "am_effect_report_v1", // 必需:作者要能解析异构报告
63
- "generatedAt": "2026-09-18", // ★ 只到天
64
- "plugin": { "version": "3.1.0", "dshVersion": "x.y.z" }, // 版本必需,否则无法归因
65
-
66
- "scale": { // ★ 全部分桶,绝不给精确值(防指纹)
67
- "daysInstalled": "30-90",
68
- "sessions": "50-200",
69
- "entries": "100-500",
70
- "logLines": "500-2000"
71
- },
72
-
73
- "features": { // 只有布尔/枚举,没有具体数值
74
- "boardMode": "graph",
75
- "handoffEnabled": true,
76
- "semanticEngine": "js",
77
- "pythonBackendEnabled": false
78
- },
79
-
80
- "effectiveness": {
81
- "recall": { "calls": 412, "withHits": 380, "emptyRate": 0.078,
82
- "layerMix": { "project": 0.31, "log": 0.52, "whiteboard": 0.09, "other": 0.08 } },
83
- "injection": { "tokensPerTurnAvg": 812, "droppedPerTurnAvg": 3.4,
84
- "perLayerDropRate": { "log": 0.61, "reflection": 0.12 } },
85
- "compaction": { "count": 7, "reasons": { "ok": 6, "no-removable": 1 }, "recoveredChars": 18240 }
86
- },
87
-
88
- "health": {
89
- "degradeCounts": { "semantic-arm": 2, "tier0-catalog": 0 },
90
- "quotaVerdict": "balanced",
91
- "degradedArms": ["c3(python)→c2(js)"]
92
- },
93
-
94
- "userReport": { // ★★ 主观部分 —— 这才是「有效性」的核心
95
- "rating": null, // 1–5,默认空,用户填
96
- "helpedMost": "", // 自由文本,默认空
97
- "broke": "" // 遇到的问题,默认空
98
- }
99
- }
100
- ```
101
-
102
- **关键设计**:`userReport` **默认全空**。有效性由**用户说**,不由插件猜 ——
103
- 插件只提供客观事实(计数、分布、健康度),主观评价留给填写。
104
- 这也顺带避免了"用行为指标冒充有效性"的构念效度问题。
105
-
106
- ---
107
-
108
- ## 4. 两条回传通道
109
-
110
- ### 4.1 GitHub
111
- - 面板按钮「生成报告」→ 展示全文 → 「复制并打开 Issue」
112
- - 打开预填 URL:
113
- `https://github.com/Aik358/dsh-auto-memory/issues/new?title=<enc>&body=<enc>`
114
- - **本机凭据只有 `pull: true` 权限**,所以这条路**只能由用户点** —— 与设计天然一致。
115
-
116
- ### 4.2 QQ 群
117
- - 同一份文本,前面附一段可删的说明模板,用户复制后自行粘贴。
118
-
119
- ### 4.3 附带:AI 侧工具
120
- 提供 `memory_telemetry_report`(无参)——用户对 AI 说「生成效果报告」即可产出,
121
- 比翻面板更顺手;输出与面板完全同源(同一派生函数),**不做第二套渲染**(沿用 M1 的纪律)。
122
-
123
- ---
124
-
125
- ## 5. 为什么建议「设计现在写、实现最后做」
126
-
127
- 1. **UI 要长在 `lib/client.js` 上,而你正要重构 Surface 前端** —— 今晚做按钮,重构后大概率返工。
128
- 2. **隐私面需要冷静设计** —— 凌晨赶工最容易漏字段;这条红线漏一次就无法挽回。
129
- 3. **依赖今晚的收尾** —— 要统计的「层分布」「compaction 原因分布」正是 R4/G3 正在改的地方,
130
- 等它们定稿,计数器不用改两遍。
131
- 4. **设计文档现在写成本≈0**,且能把今天的讨论结论固定下来不丢。
132
-
133
- → **落位:Surface 前端重构之后、S 层之前**(正好是用户说的「万事俱备」那一刻)。
134
-
135
- ---
136
-
137
- ## 6. ⚠️ 若这批数据将来用于毕业论文,须额外注意
138
-
139
- 用户论文方向与本系统强相关(`docs/internal/THESIS-OUTLINE-20260918.md`)。
140
- **真实用户效果数据对论文极有价值**(正好补上"无对外 baseline / 无真实用户数据"的缺口),
141
- 但因此**同意文本的措辞就变成研究伦理问题**,不是产品文案问题:
142
-
143
- - 报告页需明确写:数据用于什么、谁会看到、是否匿名、能否撤回
144
- - 分桶设计本身是良好的去标识化,但 `userReport` 的自由文本**可能含个人信息**
145
- → 该字段必须由用户**逐字确认**后再发,且提示"请勿填写隐私内容"
146
- - 若要做正式研究,需要走伦理审查(见论文缺口分析的"伦理许可"项)
@@ -1,89 +0,0 @@
1
- # 毕业论文方向缺口分析 · dsh-auto-memory / dsh-anchored-monitor
2
-
3
- > 日期:2026-09-18 | 视角:语言科学与数据分析(主修)+ 人工智能与数据分析(第二专业)
4
- > 结论摘要:代码与工程严谨度已经够用;缺口集中在**研究问题学术化、外部对照、消融、时间维度、测量工具信度**五处。
5
-
6
- ## 一、可当论文资产直接用的部分(已具备)
7
-
8
- | 资产 | 现状证据 | 论文中的角色 |
9
- | --- | --- | --- |
10
- | 可运行系统 | lib/ 120 文件,`lib/index.js` 10389 行;npm `@a9i5k4/dsh-auto-memory` v3.0.0 已发布 | Method / System 章节;部署真实性 |
11
- | 真实用户外部效度 | 年下载 10,900;GitHub `Aik358/dsh-auto-memory` | 区别于"玩具原型"的说服力 |
12
- | 统计纪律雏形 | M7:69 条人工金标 held-out、pairId 聚类 bootstrap B=2000、预注册式冻结计划、零重调参 | 统计章节的骨架 |
13
- | 参照系统语料 | `.research/` cognee / Memori / supermemory;`.research-mirix/MIRIX-main` | Related Work 与 baseline 来源 |
14
- | 锚定线理论雏形 | `E:\dsh_dynamic_adjust\project_feasibility_report.md`(620 行):三波段 spec 0-0.19 / mixed 0.2-0.49 / react 0.5-1.0、相变、路径承诺、措辞实验 | **最适合当论文主轴**:这是唯一有可证伪理论味的部分 |
15
- | 纵向日志基础设施 | 锚定监控 JSONL 事件流、每日工作日志、会话转写 | 时间维度实验的数据来源 |
16
-
17
- ## 二、缺口清单(按评审最可能扣分的顺序)
18
-
19
- ### 缺口 1 · 研究问题仍是工程目标,不是可证伪假设
20
- "记忆不断线""跨窗口续命"是产品目标。论文需要 RQ / H0 / H1 + 自变量·因变量·控制变量表 + 什么结果会推翻假设。
21
-
22
- ### 缺口 2 · 没有对外可比的 baseline
23
- 现有指标全部是自比(3.0 vs 2.5.3)。缺:与 ≥2 个公开系统(Mem0 / cognee / MIRIX / 无记忆裸模型)在同一任务集上的对照,并报告效应量而非仅 p 值。
24
-
25
- ### 缺口 3 · 没有消融实验
26
- 分层(Tier-0/1/2)、唤回、沉淀、白板、账本是一整套,无法归因到组件。优势是开关已全部在配置里,可直接跑 one-at-a-time 或 2^k 设计。
27
-
28
- ### 缺口 4 · 没有时间维度 / 纵向曲线
29
- 单轮或单会话测量测不到记忆系统的核心价值。缺:跨会话、跨天、上下文窗口填充过程中的纵向曲线(≥2 周、≥N 会话)。JSONL 已在写,但从未被当成数据集分析。
30
-
31
- ### 缺口 5 · 测量工具本身没有被验证(语言科学的主场)
32
- we / let's / let me 目前是正则词频计数——没有标注一致性、没有信度报告、没有反例验证、没有词表敏感性分析。
33
- 缺:人工标注子集 + Krippendorff α 或 Cohen κ + 词表扰动实验。
34
- **这一条是把"波段"从经验阈值升级为经构念效度检验的测量工具的关键**,也正是语言科学训练最能发挥的地方。
35
-
36
- ### 缺口 6 · 统计推断不完整
37
- 已有 bootstrap CI,但缺:多重比较校正(Holm/BH)、效应量(Cliff's δ / Cohen's d)、正式预注册登记、失败案例定性分析。
38
-
39
- ### 缺口 7 · 伦理与合规
40
- - 若含人类被试(问卷 / 可用性测试)→ 需要伦理审查(IRB/HREC)批件;
41
- - 若只用自用日志 → 必须写明数据来源、脱敏方式、LLM 使用声明;
42
- - 第三方仓库许可必须逐个核对(cognee / MIRIX / Memori / supermemory 的 license 决定能否作为 baseline 分发)。
43
-
44
- ### 缺口 8 · 学术写作要件
45
- Related Work 目前是散装仓库而非系统综述;缺论文骨架(Intro / Related Work / Method / Experiments / Results / Discussion / Limitations / Ethics Statement)与可复现 artifact 包(代码 + 数据 + 一键复现脚本)。
46
-
47
- ## 三、三个候选研究问题(按两个专业的契合度排序)
48
-
49
- ### RQ-A(推荐主轴)· 思维链语域指纹的构念效度与预测力
50
- - H1:人称/施事标记(we 型 vs let me 型)构成稳定语域,而非随机波动。
51
- - H2:语域可预测任务结果,且时间上先于结果(需时序检验,排除"高分导致 we"的反向解释)。
52
- - 方法:会话语料 → 人工标注 → 词频与句法特征 → 变点检测 / 分段 → 预测建模(交叉验证)。
53
- - 契合:语言科学(语域、语用、人称指称、指称链)+ 数据分析(变点检测、混合效应模型、交叉验证)。
54
-
55
- ### RQ-B · 记忆注入措辞的言语行为效应
56
- - 假设:指令类措辞(命令式)与断言/建议类措辞(参考式)对模型行为改变率存在显著差异。
57
- - 设计:自变量 = 措辞类型(3 水平:命令 / 建议 / 中性陈述);因变量 = 行为改变率、命中率、返工次数、token 成本;拉丁方平衡顺序;混合效应模型。
58
- - 已有基础:2026-09-08 记录的 A/B 分级实验设计(弱提示 vs 明确指令式)。
59
- - 契合:语用学(Searle 言语行为理论)+ 实验设计统计。
60
-
61
- ### RQ-C(最保守,创新性最低)· 分层记忆注入的成本-收益曲线
62
- - 假设:注入预算是边际收益递减的,存在最优点。
63
- - 方法:扫描注入预算参数,画 quality–token 曲线。
64
-
65
- ## 四、时间线(对齐已有课程节点)
66
-
67
- | 时间 | 动作 |
68
- | --- | --- |
69
- | 10 月上旬 | 定 RQ 与导师;写 1 页预注册(假设、判据、止损线) |
70
- | 10–11 月 | 数据采集启动:锚定监控与自用日志持续累积;适配 2 个公开 baseline |
71
- | 12–1 月 | 消融 + baseline 跑完;人工标注子集完成,出信度报告 |
72
- | 2 月 | 分析、作图、写作主体 |
73
- | 3 月 | 修订、artifact 打包、提交 |
74
-
75
- ## 五、验收口径("够了"的定义)
76
-
77
- 1. 有一个可证伪假设,且写明什么结果会推翻它;
78
- 2. ≥2 个外部 baseline 的同任务集对照;
79
- 3. 一张消融表(逐组件增益);
80
- 4. 一份标注信度报告(α 或 κ);
81
- 5. 有效应量与置信区间,不只 p 值;
82
- 6. 一键复现的 artifact(代码 + 数据 + 脚本)。
83
-
84
- ## 六、最小下一步(本周可执行)
85
-
86
- 1. 把 `project_feasibility_report.md` 1.5 节的措辞实验扩写成 RQ-B 的正式假设与变量表;
87
- 2. 从现有会话 JSONL 中抽 200 条 reasoning 块,人工标注 we / let me 与"是否计划式",算一次 κ;
88
- 3. 核 cognee / MIRIX / Memori / supermemory 的 license,确定哪个能当 baseline。
89
-