@a9i5k4/dsh-auto-memory 2.5.3 → 3.0.1
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.
- package/README.md +189 -7
- package/README.zh-CN.md +189 -7
- package/docs/CONTRIBUTORS.html +471 -0
- package/docs/FRONTEND-CO-CREATION.md +191 -0
- package/docs/GM53-HOMEPAGE-PROMPT.md +323 -0
- package/docs/HANDOFF-CRITERIA.md +92 -0
- package/docs/HOMEPAGE-CONTENT-FOR-GM53.md +299 -0
- package/docs/INTEGRATION-ANALYSIS.md +350 -348
- package/docs/PROMO-PROMPT-3.0.md +100 -0
- package/docs/USER-GUIDE.en.md +58 -3
- package/docs/USER-GUIDE.zh-CN.md +59 -4
- package/docs/WHITEPAPER.md +207 -0
- package/docs/internal/ACCEPT-35-LIVE.md +143 -0
- package/docs/internal/ACCEPTANCE-20260914.md +90 -0
- package/docs/internal/ARCH-REVIEW-BRIEF.md +411 -0
- package/docs/internal/ARCH-REVIEW-REQUEST.md +201 -0
- package/docs/internal/ARCH-REVIEW-ROUND2.md +169 -0
- package/docs/internal/ARCH-REVIEW-ROUND3.md +206 -0
- package/docs/internal/ARCHITECTURE-FOR-ZCODE-20260920.md +397 -0
- package/docs/internal/ART-DIRECTION-DEEPSEEK-20260920.md +351 -0
- package/docs/internal/ART-DIRECTION-WIREFRAME.md +191 -181
- package/docs/internal/ART-DIRECTION-WIREFRAME.md.bak-superseded +181 -0
- package/docs/internal/AUDIT-WB-GRAPH-FULL-20260916.md +314 -0
- package/docs/internal/BATTLE-PLAN-20260917.md +871 -0
- package/docs/internal/CONCURRENCY-INVESTIGATION-20260917.md +192 -0
- package/docs/internal/CROSS-SESSION-SEARCH-PATH-DECISION.md +72 -0
- package/docs/internal/CROSS-SESSION-SEARCH-RESEARCH.md +131 -0
- package/docs/internal/DECISIONS-20260914-SESSION.md +269 -0
- package/docs/internal/DESIGN-P1-STATE-COMMIT-20260915.md +219 -0
- package/docs/internal/DIRECTION-CHECK-WB-GRAPH-20260916.md +132 -0
- package/docs/internal/FEATURE-INVENTORY.md +531 -0
- package/docs/internal/FEEDBACK-TO-DSHAPI-RELAY.md +13 -0
- package/docs/internal/G-SERIES-EXECUTION-20260917.md +248 -0
- package/docs/internal/G3-DESIGN-20260918.md +82 -0
- package/docs/internal/G3-DISK-FORMAT-GAP-20260919.md +92 -0
- package/docs/internal/GH-DISCUSSION-5732-COMMENT.md +74 -0
- package/docs/internal/GPT-ACCEPTANCE-PROMPT-20260916.md +352 -0
- package/docs/internal/GPT-REVIEW-PROMPT.md +216 -0
- package/docs/internal/GROUP-WEBHOOK-SETUP.md +33 -0
- package/docs/internal/HANDOFF-TO-ZCODE-20260920.md +309 -0
- package/docs/internal/HERMES-DATA-VERIFICATION-20260919.md +120 -0
- package/docs/internal/HERMES-LEGACY-STATUS-20260919.md +74 -0
- package/docs/internal/ISSUE-55-58-VERIFICATION-20260918.md +175 -0
- package/docs/internal/ISSUE10-FIX-EXECUTION-20260919.md +389 -0
- package/docs/internal/ISSUE10-PLAN-20260919.md +254 -0
- package/docs/internal/ISSUE10B-FORENSICS-20260919.md +468 -0
- package/docs/internal/ISSUE9-PURGE-AND-R1-PLAIN-20260919.md +150 -0
- package/docs/internal/ISSUE9-RESIDUAL-FORENSICS-20260919.md +114 -0
- package/docs/internal/KICKOFF-P0.md +254 -0
- package/docs/internal/LESSON-TO-CANDIDATE-STATUS-20260919.md +79 -0
- package/docs/internal/MASTER-PLAN-3.0.md +411 -0
- package/docs/internal/MEMORY-GOVERNANCE-20260917.md +309 -0
- package/docs/internal/MEMORY-MUTATION-AND-INDEX-DESIGN.md +85 -0
- package/docs/internal/MERGE-CONFLICT-SCAN-20260914.md +222 -0
- package/docs/internal/PENDING-FIXES-20260916.md +289 -0
- package/docs/internal/PRE-FRONTEND-CHECKLIST-20260919.md +705 -0
- package/docs/internal/PRE-FRONTEND-CHECKLIST-20260919.md.bak-s10 +649 -0
- package/docs/internal/PROCEDURAL-MEMORY-AND-APPROVAL-DESIGN-20260918.md +225 -0
- package/docs/internal/PROGRESS-20260917.md +93 -0
- package/docs/internal/PROMPT-GAP-AUDIT-20260920.md +128 -0
- package/docs/internal/R1-DEGRADE-AUDIT-20260918.md +163 -0
- package/docs/internal/R1-READABILITY-FORENSICS-20260919.md +127 -0
- package/docs/internal/R2-EVIDENCE-DEEP-AUDIT-20260918.md +140 -0
- package/docs/internal/R3-DEGRADE-LEDGER-DESIGN-20260918.md +138 -0
- package/docs/internal/R4-RECALL-QUOTA-PLAN-20260918.md +218 -0
- package/docs/internal/RAG-KARPATHY-PROGRAM.md +229 -0
- package/docs/internal/REPORT-P0-NIGHTLY.md +212 -0
- package/docs/internal/REPORT-P5-ACCEPTANCE.md +31 -0
- package/docs/internal/REPORT-WB-GRAPH-NIGHTLY.md +153 -0
- package/docs/internal/RESUME-20260918.md +171 -0
- package/docs/internal/RESUME-20260919.md +104 -0
- package/docs/internal/REVIEW-WB-GRAPH-SELF.md +81 -0
- package/docs/internal/RHINELAB-TO-DEEPSEEK-FEASIBILITY.md +198 -0
- package/docs/internal/ROADMAP-20260917-WEEK.md +439 -0
- package/docs/internal/ROADMAP.md +106 -0
- package/docs/internal/RUN-P0-NIGHTLY.md +227 -0
- package/docs/internal/S10-CONSTRUCTION-HANDOFF-20260917.md +185 -0
- package/docs/internal/S10-GAP-INVENTORY-20260917.md +239 -0
- package/docs/internal/S10-GAPS-PLAIN-20260917.md +125 -0
- package/docs/internal/SEMANTIC-ARCHITECTURE-SPEC.md +360 -0
- package/docs/internal/SESSION-FILE-REPAIR-PROTOCOL.md +90 -0
- package/docs/internal/T6-EXECUTION-20260920.md +130 -0
- package/docs/internal/TELEMETRY-EFFECT-REPORT-DESIGN-20260918.md +146 -0
- package/docs/internal/THESIS-GAP-ANALYSIS-20260918.md +89 -0
- package/docs/internal/THESIS-OUTLINE-20260918.md +147 -0
- package/docs/internal/THREE-LAYER-CONTRACT.md +219 -0
- package/docs/internal/TODO-BACKLOG.md +263 -142
- package/docs/internal/TODO-GRAPH.html +715 -0
- package/docs/internal/TODO-GRAPH.html.bak-20260914-v2 +493 -0
- package/docs/internal/TODO-GRAPH.html.bak-20260915-alsfix +710 -0
- package/docs/internal/TODO-GRAPH.html.bak-20260915-p1 +710 -0
- package/docs/internal/TODO-GRAPH.html.bak-20260915-p6a-rev +703 -0
- package/docs/internal/TODO-GRAPH.html.bak-20260915-wshint +710 -0
- package/docs/internal/TODO-GRAPH.html.bak-20260916-batch +715 -0
- package/docs/internal/UPSTREAM-ISSUE-PR-TRIAGE-20260919.md +297 -0
- package/docs/internal/UPSTREAM-ISSUES-3RD-AUDIT-20260920.md +104 -0
- package/docs/internal/WB-FORMAT-CONVENTION.md +112 -0
- package/docs/internal/WB-GRAPH-DECISIONS-20260914.md +71 -0
- package/docs/internal/reviews/CLAIM-VERIFICATION-20260914.md +56 -0
- package/docs/internal/reviews/PLAN-gpt6astra-round2-20260914.md +787 -0
- package/docs/internal/reviews/REVIEW-gpt6astra-20260914.md +112 -0
- package/docs/internal/reviews/ROUND3-REVIEW-INTEGRATION-20260914.md +230 -0
- package/docs/prompts/M8-3-enable-verify.md +49 -49
- package/docs/screenshots/promo/promo-0-banner-v3.png +0 -0
- package/lib/acceptance.js +71 -0
- package/lib/activation-host.js +153 -18
- package/lib/activation-inbox.js +25 -7
- package/lib/board-mode.js +30 -0
- package/lib/client.js +1758 -90
- package/lib/config-io.js +156 -0
- package/lib/context-bridge.js +5 -2
- package/lib/context-host.js +86 -15
- package/lib/degrade.js +385 -0
- package/lib/dsh-home.js +143 -0
- package/lib/engine-identity.js +149 -0
- package/lib/engine-switch.js +247 -0
- package/lib/episodic-store.js +63 -12
- package/lib/evidence-store.js +10 -3
- package/lib/fact-store.js +22 -3
- package/lib/fs-retry.js +46 -0
- package/lib/index-sync.js +13 -1
- package/lib/index.js +3446 -263
- package/lib/intent-clean-safe.js +258 -0
- package/lib/intent-clean.js +12 -16
- package/lib/l0-extract.js +478 -149
- package/lib/l0-index-sync.js +195 -0
- package/lib/l0-index.js +349 -239
- package/lib/ledger-criteria.js +142 -0
- package/lib/m4-corpus.js +8 -2
- package/lib/m7-index-sync-host.js +73 -5
- package/lib/m7-wire.js +3 -3
- package/lib/memory-anchor.js +56 -1
- package/lib/memory-envelope.js +257 -0
- package/lib/memory-hub.js +138 -13
- package/lib/memory-index.js +4 -2
- package/lib/memory-mutation.js +246 -0
- package/lib/memory-writer.js +204 -24
- package/lib/note-status-apply.js +118 -0
- package/lib/note-status.js +196 -0
- package/lib/procedure-observation.js +48 -0
- package/lib/procedure-store.js +118 -20
- package/lib/python-setup.js +1 -1
- package/lib/python-sidecar-client.js +29 -3
- package/lib/recall-fusion.js +83 -12
- package/lib/rerank-host.js +160 -0
- package/lib/rules-edit.js +159 -0
- package/lib/rules-layer.js +261 -0
- package/lib/semantic-decide.js +41 -8
- package/lib/semantic-js.js +66 -6
- package/lib/shadow-host.js +3 -5
- package/lib/shadow-retrieval.js +3 -3
- package/lib/skill-export-host.js +153 -0
- package/lib/skill-export.js +239 -0
- package/lib/state-commit.js +245 -0
- package/lib/storage-manage.js +6 -0
- package/lib/subagent-gc.js +4 -8
- package/lib/temporal-parse.js +191 -159
- package/lib/tier-layer-inject.js +650 -0
- package/lib/tier0-catalog.js +735 -0
- package/lib/water-window.js +263 -186
- package/lib/wb-contract.js +691 -0
- package/lib/wb-sidecar.js +890 -0
- package/lib/ws-overview-rank.js +2 -2
- package/package.json +1 -1
- package/python/m7_embedding_v1.py +5 -5
- package/python/worker_semantic_v1.py +17 -6
- package/python/worker_v1.py +38 -4
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# G 系列执行细则 · 记忆治理与白板维护
|
|
2
|
+
|
|
3
|
+
> 2026-09-17 定稿 · 上游纲领 `MEMORY-GOVERNANCE-20260917.md`
|
|
4
|
+
> **本文档 = 施工级细则**,纲领回答"为什么",本文档回答"怎么做、改哪一行、怎么验"。
|
|
5
|
+
> 用户已批准:**增删作废按本文档结论执行;落成文档后即可开工。**
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 0. 术语校准(用户已澄清)
|
|
10
|
+
|
|
11
|
+
| 用户说法 | 实际含义 | 证据 |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| **"第 8000 行注入"** | 指 `index.js` **8000 行附近的注入实现区**,不是 8000 字符 | `:8844` / `:8979` 两处 `ctx.systemPrompt.context()` |
|
|
14
|
+
| "自动写记忆文档的机制" | **铭文 · 每轮提醒** | `:556` 模板 + `:5244` `pushPart('otherDynamic','frame-inscription',...)` |
|
|
15
|
+
| "维护版本也是一个思路" | 即:**把白板维护挂到已有注入机制上**,不新建管线 | 见 §2 |
|
|
16
|
+
|
|
17
|
+
**关键区分(此前混淆过,务必记牢)**:
|
|
18
|
+
|
|
19
|
+
| 量 | 值 | 管什么 |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| `injectBudgetChars` | **8000 字符** | 每轮往上下文注入多少 |
|
|
22
|
+
| `noteCapacityChars` | 12000 字符 | 笔记**文件**能存多少 |
|
|
23
|
+
| 白板进接续 | `plan.slice(0,3000)` | 接续时白板节选 |
|
|
24
|
+
| 账本进接续 | 8000 | 接续时账本 |
|
|
25
|
+
| `SECTION_ORDER` | 10000 | 注入**顺序**(非预算) |
|
|
26
|
+
|
|
27
|
+
⇒ **调 `noteCapacityChars` 只让"本子更厚",不影响每轮注入量。** 这正是用户要的:多存不多占上下文。
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 1. G2 · 标本处置【立即执行,零风险】
|
|
32
|
+
|
|
33
|
+
### 1.1 目标
|
|
34
|
+
给 `~/.dsh/memory/workspaces/--D--dsh-auto-memory--/MEMORY.md` 的作废结论补**显式作废标记**,防止下一窗口据行 120 按"2 处"施工。
|
|
35
|
+
|
|
36
|
+
### 1.2 背景(两个活体标本)
|
|
37
|
+
|
|
38
|
+
**标本一 · 记忆层** — 同文件三条矛盾并存:
|
|
39
|
+
|
|
40
|
+
| 行 | 内容 | 状态 |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| **120** | 「逐处判读后结论 —— **真正该解耦的只有 2 处**」 | ❌ 作废 |
|
|
43
|
+
| **122** | GUIDANCE 白板零覆盖(实测) | ✅ 仍成立 |
|
|
44
|
+
| **124** | 「动手顺序已重排:①缺口2 → ②缺口4⑤…」 | ❌ 作废(编号体系已换) |
|
|
45
|
+
| **161-162** | 「那个结论划窄了范围…漏掉 handoffEnabled 一族」 | ✅ 修正声明 |
|
|
46
|
+
| **183** | 「13 处闸门逐条判归属后:**只需动 4 处**」 | ✅ 现行 |
|
|
47
|
+
|
|
48
|
+
**标本二 · 白板层** — 最新账本 `handoff-20260917-023635.md` 的「进度与下一步」写的是**旧编号计划**(缺口2→缺口1→缺口3→缺口4),与现行 `BATTLE-PLAN` 的 `L3.5→L4→L5→L6→L7→L3.6` **不一致**。
|
|
49
|
+
|
|
50
|
+
### 1.3 施工步骤
|
|
51
|
+
|
|
52
|
+
| 步 | 动作 | 说明 |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| G2a | 备份 | ✅ **已完成**:`MEMORY.md.bak-20260917-G2`(19610 字节) |
|
|
55
|
+
| G2b | 在行 120/124 **原地加作废标记** | 前缀 `> ⚠️ 已作废(2026-09-17)` + 指向 supersede 条目 |
|
|
56
|
+
| G2c | 追加一条**处置记录** | 说明三条的关系与现行结论 |
|
|
57
|
+
| G2d | 校验 | 字符数不超 12000;`git diff` 确认只增不删 |
|
|
58
|
+
|
|
59
|
+
**执行原则**:**不删原文**(保留追溯),只加标记。
|
|
60
|
+
|
|
61
|
+
### 1.4 验收断言
|
|
62
|
+
1. 行 120 出现 `已作废` 字样,且指向行 183 的"4 处"结论
|
|
63
|
+
2. 文件字符数仍 **< 12000**
|
|
64
|
+
3. 原文逐字保留(除新增标记行)
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 2. G4 · 白板维护挂进注入机制【用户核心诉求】
|
|
69
|
+
|
|
70
|
+
### 2.1 用户原话与意图
|
|
71
|
+
> "开工有一个核心点,就是白板的维护。现在应该是 8000 行吧,注入进去这样的话,模型能够记住。每次写入记忆的时候,也顺便维护一下白板。"
|
|
72
|
+
|
|
73
|
+
**意图拆解**:
|
|
74
|
+
1. 白板内容要**每轮可见**(靠注入,不是靠读文件)
|
|
75
|
+
2. **写记忆时顺带维护白板**(同一次工具调用,不额外增加轮次)
|
|
76
|
+
|
|
77
|
+
### 2.2 现状核查
|
|
78
|
+
|
|
79
|
+
| 项 | 现状 | 结论 |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| 白板是否每轮注入 | ✅ `GUIDANCE`(`:143`)+ Tier-0 目录层 | **已注入,但注入的是"目录"不是"全文"** |
|
|
82
|
+
| Tier-0 是否保护白板 | ✅ `floorLayers:['whiteboard','user']`(`tier0-catalog-pre.js:353`) | 有保底配额 |
|
|
83
|
+
| 接续时白板是否注入 | ✅ `plan.slice(0,3000)`(`:3686`) | 有 |
|
|
84
|
+
| **模型是否被要求"维护白板"** | ❌ **GUIDANCE 零覆盖**(实测:白板/PLAN/kind=plan/handoff 全 False) | **真因** |
|
|
85
|
+
| **写记忆时是否顺带维护白板** | ❌ 无联动 | **要新增的** |
|
|
86
|
+
|
|
87
|
+
### 2.3 施工步骤
|
|
88
|
+
|
|
89
|
+
| 步 | 文件:行 | 动作 |
|
|
90
|
+
|---|---|---|
|
|
91
|
+
| **G4a** | `lib/index.js:143`(`GUIDANCE`) | 扩写白板纪律(**三条硬约束**):①条件触发非每轮 ②只报告不自动删 ③白板关闭时跳过 |
|
|
92
|
+
| **G4b** | 铭文模板 `:556` | 评估是否加一句白板提醒(**谨慎**:铭文每轮注入,加内容=每轮成本) |
|
|
93
|
+
| **G4c** | `memory_log_pre` 的 `description`(`:9018` 附近) | 加一句"完成阶段性工作后,如白板已过时请一并调用 `memory_note_pre(kind=plan)` 更新" |
|
|
94
|
+
|
|
95
|
+
**⚠️ 边界(必须遵守)**:
|
|
96
|
+
- **零新增管线**——只改提示词/描述文本,不新增注入通道
|
|
97
|
+
- **不自动写盘**——只提示模型,是否维护由模型判断
|
|
98
|
+
- **白板关时无副作用**——`handoffEnabled=false` 时提示不得导致报错
|
|
99
|
+
|
|
100
|
+
### 2.4 与 M3 的关系
|
|
101
|
+
BATTLE-PLAN 的 **M3「GUIDANCE 白板纪律扩写」** 与本项**重叠**。
|
|
102
|
+
⇒ **合并**:G4 即 M3,在 M 层执行;G4c(写记忆时提示)是**新增部分**。
|
|
103
|
+
⇒ BATTLE-PLAN 的 M3 条目应标注"已被 G4 吸收"。
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## 3. 增删改作废 · 最终结论【用户已批准按此执行】
|
|
108
|
+
|
|
109
|
+
### 3.1 结论表
|
|
110
|
+
|
|
111
|
+
| 能力 | 现状 | 终局决定 |
|
|
112
|
+
|---|---|---|
|
|
113
|
+
| 增 | ✅ 有 | 不动 |
|
|
114
|
+
| 读 | ✅ 有 | 不动 |
|
|
115
|
+
| **改(覆盖结论)** | ⚠️ 仅白板 | **本次不扩到笔记层**(成本高,见 §3.3) |
|
|
116
|
+
| **删(硬删)** | ❌ 无 | **永远不做**——归档替代,原文必留 |
|
|
117
|
+
| **作废(软删)** | ❌ **空白** | ✅ **本次做**(方案 A,见 §3.2) |
|
|
118
|
+
| 归档 | ✅ 有 | 不动 |
|
|
119
|
+
| **语义重排** | ✅ **不需要** | **确认无需任何改动** |
|
|
120
|
+
|
|
121
|
+
### 3.2 方案 A(本次实施)· `supersedes` / `status` 约定
|
|
122
|
+
|
|
123
|
+
**格式**(写在笔记条目内,不影响 Markdown 渲染):
|
|
124
|
+
```markdown
|
|
125
|
+
### 2026-09-17 · 白板线解耦边界
|
|
126
|
+
<!-- id: mem_abc123 supersedes: mem_def456 status: current -->
|
|
127
|
+
结论:只需动 4 处...
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
- `supersedes:` — 本条作废了哪些 id(可多个,空格分隔)
|
|
131
|
+
- `status:` — `current`(默认)/ `superseded` / `deprecated`
|
|
132
|
+
|
|
133
|
+
**读取侧**:`pushL0` / `semSources` / `searchHandoffCorpus` 命中 `status != current` 的条目时,**输出前缀加 `[已作废 → 见 <新id>]`**,不静默丢弃(保留可追溯性)。
|
|
134
|
+
|
|
135
|
+
**写入侧**:`memory_note_pre` 的模板加这两个字段(**默认 current**,模型显式填 supersedes)。
|
|
136
|
+
|
|
137
|
+
**⚠️ 风险**:需模型自觉填写 `supersedes`。**缓解**:G5 的 lint 会检测漏填(同主题多条 current)。
|
|
138
|
+
|
|
139
|
+
### 3.3 方案 C 为何本次不做
|
|
140
|
+
笔记层引入 replace+archive 语义 = 改动写入路径 + 归档逻辑 + 迁移旧文件。**收益(自动去重)不如风险(可能误删结论)**。⇒ **留待 G6,等 G3 在真实数据上验证后再评估。**
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## 4. G1 结论更正【已完成,记录备查】
|
|
145
|
+
|
|
146
|
+
**我此前的误判**:据 `MEMORY.md` 19610 **字节** 对比上限 12000,判定"超限 63%、疑似 bug"。
|
|
147
|
+
|
|
148
|
+
**实测推翻**:
|
|
149
|
+
|
|
150
|
+
| 口径 | 值 |
|
|
151
|
+
|---|---|
|
|
152
|
+
| 文件字节 | 19610 字节 |
|
|
153
|
+
| **实际字符**(`String.length`) | **11956 字符** |
|
|
154
|
+
| 上限 | 12000 字符 |
|
|
155
|
+
| 判定 | ✅ **未超限,机制正常** |
|
|
156
|
+
|
|
157
|
+
**容量按字符计,不按字节。** 中文字符 UTF-8 占 3 字节 ⇒ 字节数 ≈ 字符数 × 1.6。
|
|
158
|
+
|
|
159
|
+
⚠️ **但余量仅 44 字符** ⇒ **下次写入必然触发整理**。而整理**不保证识别矛盾**(只做压缩),可能把作废结论折叠成"要点"而**丢失作废语义**。
|
|
160
|
+
⇒ **这就是 G2 必须赶在下一次写笔记之前做的原因。**
|
|
161
|
+
|
|
162
|
+
*(本条为自我更正记录,按"根因结论必须附证据、推断须标注为推断"纪律留痕。)*
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## 5. 容量建议值【用户自行在设置里调】
|
|
167
|
+
|
|
168
|
+
| 设置项 | 现值 | 建议 | 理由 |
|
|
169
|
+
|---|---|---|---|
|
|
170
|
+
| `noteCapacityChars` | 12000 | **24000** | 余量 44 字符太危险;今日单日日志峰值 ~30000 字符,结论层给 2 倍余量较稳 |
|
|
171
|
+
| `userCapacityChars` | 12000 | **不动** | 实测注入目录里用户级 46 条被裁 45 条 ⇒ **瓶颈在注入配额,不在文件容量**,加容量无效 |
|
|
172
|
+
|
|
173
|
+
**同时需知**:调大 `noteCapacityChars` **不影响每轮注入体积**(那是 `injectBudgetChars=8000` 的职责)。⇒ **多存不多占上下文。**
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## 6. 白板结构问题(标本二的深处)
|
|
178
|
+
|
|
179
|
+
### 6.1 实测现状
|
|
180
|
+
|
|
181
|
+
| 文件 | 体积 | 行数 |
|
|
182
|
+
|---|---|---|
|
|
183
|
+
| `PLAN.md` | **1506 字符** | 23 行 |
|
|
184
|
+
| `handoff-*.md`(最新) | 2922 字节 | ~30 行 |
|
|
185
|
+
|
|
186
|
+
**用户判断"量肯定是够了"——实测支持**:1506 字符 vs 接续预算 3000、注入预算 8000,**余量充足**。
|
|
187
|
+
|
|
188
|
+
### 6.2 四个结构问题
|
|
189
|
+
|
|
190
|
+
| # | 问题 | 证据 |
|
|
191
|
+
|---|---|---|
|
|
192
|
+
| 1 | **PLAN.md 是"项目说明书"不是"交接单"** — 写"是什么/从哪来",没写"现在卡在哪" | 全文 23 行,全是 3.0 收尾期内容 |
|
|
193
|
+
| 2 | **PLAN 与账本都写"下一步"** — 两处可能不同步 | 标本二即此 |
|
|
194
|
+
| 3 | 账本**文件名日期 ≠ 标题日期** — 按文件名排序 ≠ 时序 | `handoff-20260917-023635.md` 标题是 `2026-09-16 02:36` |
|
|
195
|
+
| 4 | 老账本**无作废标记** | 检索到会误导 |
|
|
196
|
+
|
|
197
|
+
### 6.3 分工调整(**待用户确认**)
|
|
198
|
+
|
|
199
|
+
| 账户 | 应写 | 不应写 |
|
|
200
|
+
|---|---|---|
|
|
201
|
+
| `PLAN.md` | **稳定事实**:是什么/架构/铁律/边界 | ❌ 不写"下一步" |
|
|
202
|
+
| `handoff-*.md` | **唯一权威的动态状态**:卡在哪/试过什么/下一步 | ❌ 不重复项目介绍 |
|
|
203
|
+
| `MEMORY.md` | **可复用结论** + `supersedes` 链 | ❌ 不写流水 |
|
|
204
|
+
|
|
205
|
+
**一句话**:**下一步只在一个地方写。**
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## 7. 执行顺序总表
|
|
210
|
+
|
|
211
|
+
```
|
|
212
|
+
【立即】G2 · 标本处置 ← 用户已批,压缩前先做
|
|
213
|
+
【立即】G1 结论已更正 ← 已完成(文档层)
|
|
214
|
+
────────── 以下并入主线 ──────────
|
|
215
|
+
L3.5 附件路径进转写 ← 已批准
|
|
216
|
+
L4 白板进检索
|
|
217
|
+
L5 锚点解耦(原义::1993/:2037)
|
|
218
|
+
L6 账本注释对齐(原义) ← 用户已批"按你的结论做"
|
|
219
|
+
L7 死导出
|
|
220
|
+
── 全量回归绿 ──
|
|
221
|
+
L3.6 旧对话可检索化 ← 最后开
|
|
222
|
+
────────── 与 M 层合并 ──────────
|
|
223
|
+
G4=M3 · GUIDANCE 白板纪律 + 写记忆时提示维护
|
|
224
|
+
G5 矛盾检测 lint(需 ③④ 判据)
|
|
225
|
+
G6 结论层 replace+archive(长期)
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## 8. 待用户拍板
|
|
231
|
+
|
|
232
|
+
1. **§6.3 白板分工调整**是否同意(PLAN 不写下一步,账本唯一权威)
|
|
233
|
+
2. **`supersedes` 自动还是手写**(自动需 AI 判同主题;手写可靠但靠自觉)
|
|
234
|
+
3. **`noteCapacityChars` 是否调 24000**(用户说自己调,此处仅给建议值)
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## 9. 收尾纪律(每个 G 项完成后)
|
|
239
|
+
|
|
240
|
+
1. 改动前备份(G2 已做)
|
|
241
|
+
2. `node --check` 语法校验(涉及代码时)
|
|
242
|
+
3. 可失败断言 + 变异演示(涉及代码时)
|
|
243
|
+
4. 留痕:`memory_log_pre` + 必要时 `memory_note_pre`
|
|
244
|
+
5. **白板回写**:PLAN.md / 账本同步更新(**这正是 G4 要固化的习惯**)
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
*本文档与 `MEMORY-GOVERNANCE-20260917.md` 配套:纲领答"为什么",本文档答"怎么做"。*
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# G3 · 结论层状态写入 · 实施设计(2026-09-18)
|
|
2
|
+
|
|
3
|
+
> **状态**:设计定稿,待实施。
|
|
4
|
+
> **权威依据**:`MEMORY-GOVERNANCE-20260917.md` §8(用户 2026-09-18 拍板)+ `BATTLE-PLAN-20260917.md` §M2 并入项。
|
|
5
|
+
> **纪律来源**:契约 §6 尾注(lint 只报告不自动改)+ S10.4(不建状态源)+ 语义引擎铁律。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. 一句话
|
|
10
|
+
|
|
11
|
+
**M2 说「这条可能过时」,G3 在下次写入时决定要不要标。**
|
|
12
|
+
M2(lint)已完工:只读、只报告、43/43 套件、全量回归 119/0。
|
|
13
|
+
G3 是**写入侧**:`memory_note_pre` 写新结论时,比对同主题旧条目,把被取代的那条标 `superseded`。
|
|
14
|
+
|
|
15
|
+
## 2. 触发范围(用户裁定,不可扩大)
|
|
16
|
+
|
|
17
|
+
| 路径 | 是否触发 G3 | 理由 |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| `memory_note_pre` · `kind='note'` | ✅ **唯一触发点** | 笔记 = 结论,append 是**错误**语义,才是矛盾滋生地 |
|
|
20
|
+
| `memory_note_pre` · `kind='plan'/'handoff'` | ❌ 不触发 | 白板/账本是**视图**,其状态归卡片,不归本机制 |
|
|
21
|
+
| `memory_log_pre` | ❌ **零改动** | 日志 = 流水,append 是**正确**语义 |
|
|
22
|
+
|
|
23
|
+
## 3. 三条硬约束(违反即回滚)
|
|
24
|
+
|
|
25
|
+
### 3.1 ★ 语义引擎铁律:必须 fail-soft 退回词法臂
|
|
26
|
+
```
|
|
27
|
+
语义引擎可用 ⇒ 语义臂检索同主题
|
|
28
|
+
语义引擎不可用 ⇒ 退回词法臂,**行为正常,不报错、不跳过写入**
|
|
29
|
+
```
|
|
30
|
+
**绝不允许**:一个引擎的存在成为另一个生效的前提;任一引擎不可用导致状态不写或写入失败。
|
|
31
|
+
|
|
32
|
+
### 3.2 ★ 保守阈值:宁可漏判,不可误判
|
|
33
|
+
- 误判代价**不对称**:漏判 = 矛盾继续存在(回到现状,可接受);**误判 = 有效结论被标作废,比不改更糟**。
|
|
34
|
+
- ⇒ **只在高置信度时自动标**;其余**只报告不标**(与 M2 lint 的分工呼应)。
|
|
35
|
+
|
|
36
|
+
### 3.3 ★ 不新建状态源(S10.4)
|
|
37
|
+
`status` 是**已有字段**(`l0-extract-pre.js:56` `L0_STATUSES`),G3 只是让它**第一次被写入**。
|
|
38
|
+
**禁止**:另建状态表 / 新配置文件 / 平行账本。
|
|
39
|
+
|
|
40
|
+
## 4. 撤销通道(U1,必需项)
|
|
41
|
+
|
|
42
|
+
**用户明确要求**(原话:「标错成 superseded 后,要有个撤销通道?」)。
|
|
43
|
+
|
|
44
|
+
**方案 U1**:`memory_note_pre` 增参数 `restore: [mem_id...]`
|
|
45
|
+
- 语义:把指定 id 的状态改回 `current`
|
|
46
|
+
- **必须留痕**:谁在何时把它改回(否则又变成「静默改写」—— 正是 §1 标本的成因)
|
|
47
|
+
- U2(面板可点)留给 S 层;U3(追加变更记录)与 §3.1「status 是字段不是新状态源」冲突,不采用
|
|
48
|
+
|
|
49
|
+
## 5. 实施边界(本轮做什么 / 不做什么)
|
|
50
|
+
|
|
51
|
+
| 项 | 本轮 |
|
|
52
|
+
|---|---|
|
|
53
|
+
| 判定函数(纯函数、可单测) | ✅ 做 |
|
|
54
|
+
| 词法臂(零依赖,保底) | ✅ 做 |
|
|
55
|
+
| 语义臂(复用现有 recall) | ✅ 做,**但必须可降级** |
|
|
56
|
+
| 实际写 `status` 到笔记文件 | ⚠️ **谨慎**:只改**本插件自己管理的** MEMORY.md 块,且经正常写入通道 |
|
|
57
|
+
| 变更留痕(写入位置) | ✅ 做(复用现有日志通道,不新建文件) |
|
|
58
|
+
| 面板展示 status | ❌ 不做(属 S 层) |
|
|
59
|
+
| `memory_log_pre` 任何改动 | ❌ **零改动**(套件断言) |
|
|
60
|
+
|
|
61
|
+
## 6. 验收口径(能失败)
|
|
62
|
+
|
|
63
|
+
- [ ] 写新结论、显式声明取代旧条目 ⇒ 旧条目 `status` 变 `superseded`
|
|
64
|
+
- [ ] **误标可撤销**:走 U1 改回 `current`,**且有留痕**
|
|
65
|
+
- [ ] **语义引擎不可用时**:退回词法臂,行为正常,**不报错、不跳过写入**
|
|
66
|
+
- [ ] `memory_log_pre` 路径**零改动**(断言:日志写入不触发任何 status 写入)
|
|
67
|
+
- [ ] 每条都在 `tests/smoke/` 有套件,且**故意改坏实现时会红**
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## 7. 待用户确认的两个判据(唯一阻塞点)
|
|
72
|
+
|
|
73
|
+
按契约 §8.5「阈值要保守」,以下两点**必须用户拍板**,我不自行决定:
|
|
74
|
+
|
|
75
|
+
1. **自动标的置信门槛**:
|
|
76
|
+
- (a) **只认显式声明**(新结论正文里写明「取代/替换/作废」+ 指向旧条目)⇒ 零误判可能,但覆盖窄
|
|
77
|
+
- (b) 显式声明 **+** 高相似度(词法/语义臂都命中同一旧条目)⇒ 覆盖率好,但有误判风险
|
|
78
|
+
- 建议 **(a) 起步**,(b) 后续按实测数据再开
|
|
79
|
+
|
|
80
|
+
2. **`superseded` 的可见后果**:
|
|
81
|
+
- 现状:非 `current` 条目在**检索侧被过滤**(`index.js:5834` 契约 I5)+ 注入侧另有一道
|
|
82
|
+
- ⇒ 标错 = 该结论**立刻搜不到**。确认这是期望行为,还是希望「降权」而非「剔除」?
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# G3 · 磁盘表示缺口与形态设计(2026-09-19)
|
|
2
|
+
|
|
3
|
+
> **本文档的地位**:`G3-DESIGN-20260918.md` / `MEMORY-GOVERNANCE-20260917.md` §8 的**实施前补丁**。
|
|
4
|
+
> 它不推翻任何已拍板项,只补一处**设计稿断言与实机不符**的地方,并提出形态方案。
|
|
5
|
+
> **触发**:R4-A 落地后按 PRE-FRONTEND-CHECKLIST 执行序推进 ⑥ G3 时的实施前核查。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. 一句话
|
|
10
|
+
|
|
11
|
+
设计稿 §8.1 断言「**地基已经存在,只差写入方**」。核查结论:
|
|
12
|
+
**该断言只对「内存索引列」成立;「`status` 在磁盘上怎么表示」这一层完全不存在,且没有现成载体。**
|
|
13
|
+
|
|
14
|
+
⇒ G3 不是「接一根线」,而是**必须先定一个磁盘形态**。这是本文档要解决的问题。
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 2. 证据链(可复现)
|
|
19
|
+
|
|
20
|
+
| # | 断言 | 证据 | 结论 |
|
|
21
|
+
|---|---|---|---|
|
|
22
|
+
| 1 | 锚点语法**不容纳属性** | `lib/memory-anchor-pre.js:28` `MARKER_RE = /^<!-- memory:(mem_[0-9a-f]{32}) -->$/` | 严格匹配,加 `status=…` 即不匹配 |
|
|
23
|
+
| 2 | 非法锚点行 ⇒ **冲突**(非静默忽略) | `memory-anchor-pre.js:214-217`:行首 `startsWith(MARKER_OPEN)` 但 `!MARKER_RE.test` ⇒ `conflicts.push({type:'malformed-anchor'})` | 不是"忽略",是**记冲突** |
|
|
24
|
+
| 3 | 冲突 ⇒ 该文件**写入被拒** | `storage-manage-pre.js:181-182`:`parsed.status !== 'clean'` ⇒ `{ok:false, reason:'conflict:'+types}` | 改锚点语法 = 破坏写入通道 |
|
|
25
|
+
| 4 | **零处**从磁盘读 `status` | `grep statusOf(` 全仓仅命中 `l0-extract-pre.js` 自身(定义 + 调用);无任何调用方传该参数 | 读取侧没有生产者 |
|
|
26
|
+
| 5 | 现存两处 `status: 'current'` 是**硬编码** | `tier0-catalog-pre.js:296`(注入目录条目)、`wb-contract-pre.js:186`(白板卡片) | 均为**运行期对象**,不落盘 |
|
|
27
|
+
| 6 | sidecar **不能**承载 | `memory-writer-pre.js:434` 注释:「sidecar 是**可重建的派生数据**」;`storage-manage-pre.js:26` 把 `stale-source` 列为**可自愈 rebuild** 分类 | 正文档 digest 一变 ⇒ sidecar 重建 ⇒ status 丢失 |
|
|
28
|
+
| 7 | 真机 MEMORY.md 无状态字段 | 实测 `~/.dsh/memory/workspaces/--D--dsh-auto-memory--/MEMORY.md`:25 个锚点、23549 字符;`status` 字样出现 6 次**全在正文散文里** | 现状确为「零写入」 |
|
|
29
|
+
|
|
30
|
+
### 2.1 与设计稿的差异(必须纠正的表述)
|
|
31
|
+
|
|
32
|
+
`MEMORY-GOVERNANCE-20260917.md` §8.1 的六行表格中:
|
|
33
|
+
|
|
34
|
+
- 第 1/2/3/4/5 行(`L0_STATUSES` / `L0_LAYERS` / 索引带列 / 状态进指纹 / 缺失即默认)—— **成立**,且是内存索引层的事实。
|
|
35
|
+
- 第 6 行「但没有任何地方在写这两个字段」—— **成立**,但**低估了缺口**:不只是「没有写入方」,
|
|
36
|
+
而是**「没有可写入的位置」**。
|
|
37
|
+
|
|
38
|
+
⇒ 修正表述:**缺口 = 「内存索引有列,磁盘无位」**,不是「有列,差个写入方」。
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 3. 三个候选形态(含排除理由)
|
|
43
|
+
|
|
44
|
+
### 方案 A:锚点行附加属性 —— ❌ **排除**
|
|
45
|
+
`<!-- memory:mem_xxx status=superseded -->`
|
|
46
|
+
- 撞证据 1/2/3:`MARKER_RE` 不匹配 ⇒ `malformed-anchor` 冲突 ⇒ 文件写入被永久拒绝。
|
|
47
|
+
- 即便同步改 `MARKER_RE`,`checkReservedSyntaxInContent`(`memory-anchor-pre.js:57`)用**同一个** `MARKER_OPEN` 判据,
|
|
48
|
+
且 `parseAnchors` 已被 40 个套件依赖 —— 属**契约级改动**,风险与收益不成比例。
|
|
49
|
+
- **结论:不动锚点语法。**(锚点是 issue #54 的核心防线:一旦漂移,整份文件永久拒写。)
|
|
50
|
+
|
|
51
|
+
### 方案 B:独立状态文件(如 `.dsh-memory/status.json`)—— ❌ **排除**
|
|
52
|
+
- 直接违反 S10.4「不新建状态源」,设计稿 §3.3 / §8.5-4 明确禁止。
|
|
53
|
+
|
|
54
|
+
### 方案 C:条目**正文内**保留行 —— ✅ **推荐**
|
|
55
|
+
```
|
|
56
|
+
<!-- memory:mem_xxx -->
|
|
57
|
+
## 2026-09-17
|
|
58
|
+
### 某结论
|
|
59
|
+
正文……
|
|
60
|
+
|
|
61
|
+
status: superseded(已被 mem_yyyy 取代)
|
|
62
|
+
```
|
|
63
|
+
- **合规**:状态仍归**记忆条目自身**,不新建状态源(S10.4 ✅)。
|
|
64
|
+
- **零语法风险**:不碰锚点,不触发任何 conflict。
|
|
65
|
+
- **用户可读**:MEMORY.md 是明文 Markdown,人打开就能看见。
|
|
66
|
+
- **对旧数据零影响**:无状态行的条目解析结果 = `current`(与「缺失即默认」口径一致)。
|
|
67
|
+
|
|
68
|
+
**★ 关键实现约束(否则会重蹈 M2.5a 的坑)**:状态行**不得放在条目正文开头**。
|
|
69
|
+
`extractL0Pre` 规则①取 `## 标题`、规则②取首个 `- ` 条目首句;若状态行在首行且不含 `##`,
|
|
70
|
+
会被规则②/③当作正文 ⇒ **L0 变成「⚠已作废…」,污染检索质量**(这正是 M2.5a 修的那类问题)。
|
|
71
|
+
⇒ **状态行只允许追加在条目正文末尾**,并在 L0 抽取时视为不可见。
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 4. 待用户拍板的两个形态项
|
|
76
|
+
|
|
77
|
+
设计稿 §7「待确认的两个判据」在 BATTLE-PLAN §7 已拍板(门槛 = **(a) 只认显式声明**)。
|
|
78
|
+
本文档新提出的是**另一组**形态问题 —— 它们决定「模型怎么写、用户看到什么」:
|
|
79
|
+
|
|
80
|
+
| # | 问题 | 候选 | agent 倾向 |
|
|
81
|
+
|---|---|---|---|
|
|
82
|
+
| **F1** | **状态行的具体语法** | (a) `status: superseded`(YAML 风格单行)<br>(b) 复用 R4-A 标记原文:`⚠已作废(已被 mem_xxx 取代)`<br>(c) 其他 | **(a)** —— 机器可解析且稳定;(b) 是**给人/AI 看的呈现**,把它当磁盘格式会让解析依赖文案,R4-A 改文案就会破坏读取 |
|
|
83
|
+
| **F2** | **「显式声明取代」的模型侧写法** | (a) `memory_note_pre` 增 `supersedes: [mem_id]` 参数(结构化)<br>(b) 从 content 正文里正则识别「取代/替换了 mem_xxx」<br>(c) 两者都支持 | **(a) 优先**,理由见下 |
|
|
84
|
+
|
|
85
|
+
**F2 倾向 (a) 的理由**(与「宁可漏判不可误判」同源):
|
|
86
|
+
- 结构化参数是**明确意图**,误判率≈0;正则识别自然语言**必然**有误判。
|
|
87
|
+
- 符合用户裁定的门槛「(a) 只认显式声明」—— 参数即最强的显式。
|
|
88
|
+
- (b) 可作**后续增量**(先跑一段看数据),不必首个版本就上。
|
|
89
|
+
|
|
90
|
+
> ⚠️ **纪律**:按「误判代价不对称」(漏判=维持现状;误判=有效结论被当废纸),
|
|
91
|
+
> **F1/F2 未定前不得上线任何自动写入**。判定函数与套件可以先写(纯函数、零副作用),
|
|
92
|
+
> 但**写盘接线必须等形态定稿**。
|
|
@@ -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 家族一致)。
|