pi-multi-viewers 0.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 (35) hide show
  1. package/AGENTS.md +192 -0
  2. package/README.md +153 -0
  3. package/docs/design.md +288 -0
  4. package/docs/examples/first-experiment/README.md +42 -0
  5. package/docs/examples/first-experiment/work-a/AGENTS.md +10 -0
  6. package/docs/examples/first-experiment/work-a/a/0001.md +65 -0
  7. package/docs/examples/first-experiment/work-a/a/0002.md +70 -0
  8. package/docs/examples/first-experiment/work-a/perspective.md +5 -0
  9. package/docs/examples/first-experiment/work-b/AGENTS.md +10 -0
  10. package/docs/examples/first-experiment/work-b/b/0001.md +100 -0
  11. package/docs/examples/first-experiment/work-b/perspective.md +6 -0
  12. package/docs/reviews/2026-09-10-e2e10-fork-source-modes-review.md +366 -0
  13. package/docs/reviews/2026-09-10-e2e11-forkmode-guards-review.md +229 -0
  14. package/docs/reviews/2026-09-10-e2e12-code-review.md +346 -0
  15. package/docs/reviews/2026-09-11-e2e13-code-review.md +284 -0
  16. package/docs/reviews/2026-09-11-e2e14-observability-review.md +216 -0
  17. package/docs/reviews/README.md +36 -0
  18. package/docs/test-methodology.md +258 -0
  19. package/extensions/multi-viewers-say/index.ts +156 -0
  20. package/fake_agent.py +120 -0
  21. package/human_sayer.py +144 -0
  22. package/human_viewer.py +215 -0
  23. package/meeting_core.py +255 -0
  24. package/meeting_engine.py +733 -0
  25. package/meeting_fs.py +1066 -0
  26. package/meeting_loop.py +606 -0
  27. package/package.json +41 -0
  28. package/prompts/multi-viewers.md +94 -0
  29. package/scripts/check-residue.sh +190 -0
  30. package/scripts/mv.sh +325 -0
  31. package/start_discussion.py +1485 -0
  32. package/templates/AGENTS.md.tpl +100 -0
  33. package/templates/agent.md.tpl +9 -0
  34. package/templates/gitignore.tpl +7 -0
  35. package/templates/spec-readme.md.tpl +87 -0
@@ -0,0 +1,366 @@
1
+ > **存档说明**:本文件是 2026-09-10 一次真实多视角自审(性能 / 可读性 / 铁律
2
+ > 三视角,meeting 协议)的 result.md 原文,主题为"fork 源模式描述与实现是否
3
+ > 一致"。修复见 commit 732fdff;其中"值只存在于产物里、无迁移负担"的假设
4
+ > 被证伪,相关制度见 docs/test-methodology.md 方法 12/13。
5
+ > 报告编号(D1/P0/P15 等)为当次讨论内部编号,不可跨文档核验。
6
+
7
+ # 多视角分析结论:审阅 fork 源模式描述与实现是否一致
8
+
9
+ > 主题:`docs/design.md` + `README.md` + `AGENTS.md` 对 fork 源机制的描述
10
+ > 与代码实现(`meeting_fs.py` / `meeting_loop.py` / `start_discussion.py` /
11
+ > `scripts/mv.sh`)是否一致。
12
+ > 参与者:可读性、性能、铁律(3 视角,各 12–13 条消息,含自由讨论 + RR 轮转)。
13
+ > 收敛:全员 pass(无保留异议);本报告为收敛结论的唯一权威版本。
14
+
15
+ ---
16
+
17
+ ## 0. 结论摘要
18
+
19
+ **核心机制描述与实现的一致性:大部分成立,发现 6 组确定不一致 + 3 组登记项。**
20
+
21
+ - 成立面(双方独立核验):三模式集合与默认值、budget 语义链(先折叠再裁、
22
+ 边界对齐、preface、est 对最终产物重算)、无 compaction 兜底、header 自描述
23
+ 字段口径、切换叙事 topic 单一来源、模型拼接无条件化——逐条对得上。
24
+ 折叠语义另有**产物侧独立证据**(可读性):thinking 块 0、省略标记 1071 处、
25
+ header 指纹三 agent 恒同(`est=80106 / dropped=2146`)。
26
+ - 不一致面:文档与代码中残留**已废除的模式名**(`curated`/`active`,含用户
27
+ 可见 CLI help);`docs/design.md` §一 的规模数字**混源且无测点**;
28
+ 非法 `forkMode` 无 fail-fast(已实测复现静默超窗形态,且磁盘上有持久化
29
+ 旧值实例);wrapper 对 `--fork-mode` **静默忽略**(文档教的操作无效);
30
+ 三处"完整上下文"与有损默认模式**承诺不符**;§三 拆分清单 8 函数 ≠ 实际 11。
31
+
32
+ **修复清单见 §3(P0/P1/P2 分批);登记项见 §4;未覆盖见 §5。**
33
+
34
+ ---
35
+
36
+ ## 1. 分析对象与方法
37
+
38
+ **对象(一次改动集)**:fork 源三模式(`budget`/`compaction`/`full`)的
39
+ 文档描述与实现,含:`meeting_fs.build_fork_source`/`_budget_entries`/
40
+ `_fold_entry`/`read_fork_stats`/`append_handoff_turns`;
41
+ `meeting_loop._prepare_fork_session`/`_build_wake_cmd`/`wake_llm`;
42
+ `start_discussion` 的 `--fork-mode`/`protocol.forkMode`;
43
+ `scripts/mv.sh`;`docs/design.md` / `README.md` / `AGENTS.md` / `prompts/` /
44
+ `templates/`。
45
+
46
+ **方法(三视角各自独立,后交叉)**:
47
+
48
+ | 视角 | 方法 |
49
+ |---|---|
50
+ | 性能 | 现场只读实测(计时 5 次取最小、tracemalloc 峰值;非法值实跑复现;MC SQLite 只读核查;以 wake prompt 为锚的请求轨迹) |
51
+ | 可读性 | 全文通读 + 本场三份真实 fork 产物核验(thinking/省略标记/指纹)+ 词表漂移 grep + 语义面扫描 |
52
+ | 铁律 | 逐条对照设计文档与代码(file:line),分支链推演 + 独立复核他方证据(git 溯源、持久化实例、engine 边界) |
53
+
54
+ **关键现场数据(三视角交叉互证的基准)**:
55
+
56
+ | 量 | 值 | 口径 |
57
+ |---|---|---|
58
+ | 三 agent fork 源 header | `est=80106 / dropped=2146`(三者恒同) | 产物侧指纹 |
59
+ | 唤醒 1 首请求(三 agent) | 132,665 / 132,767 / 132,882 | 消费侧(唤醒 1 首请求 @2026-09-10) |
60
+ | 校准比(est → 真实) | 1.656 / 1.657 / 1.659(±0.2%) | wake-1 首请求 ÷ est |
61
+ | 运行规模轨迹 | w1 132.8k → w7 209k(+56–76k);单请求峰值 222k | 唤醒首请求为锚 |
62
+ | 主 session | 15.7MB / 6816 条;末次请求 237,079 tokens | 现场快照 @2026-09-10 |
63
+
64
+ ---
65
+
66
+ ## 2. 一致确认项(描述↔实现核对通过)
67
+
68
+ 1. **模式集合与默认值**:CLI `choices=[compaction,budget,full]`、`default=budget`
69
+ → `gen_protocol` → `meeting_loop` 三处默认 + `proto.get("forkMode") or "budget"`
70
+ → `build_fork_source(mode=)`,全链一致(默认值唯一性另见 §3.3 铁律-3)。
71
+ 2. **budget 语义链**:compaction 边界起 → 折叠(丢 thinking、工具输出仅最近 8
72
+ 条保留全文、参数递归截断**保留结构**)→ 从尾部按**折叠后**规模累计 →
73
+ 边界对齐(孤儿 toolResult 向前扩展)→ preface(省略说明 + 压缩摘要)→
74
+ header 对最终产物重算 est。与 design.md §一/§二.1 逐条一致;"先折叠再裁"
75
+ 的顺序及反例(80k 预算曾只落到 17.5k)在代码注释与文档一致。
76
+ 3. **无 compaction 兜底**:`compaction` → 标记 `full`;`budget` → 仍折叠 + 统计。
77
+ 4. **header 自描述**:`forkSourceMode`(三模式均写)/`forkSourceTokensEst`/
78
+ `forkSourceDropped`(仅 budget)——与 §二.1 口径("Est 即提醒,不预测请求
79
+ 规模")一致。
80
+ 5. **切换叙事**:4 条 = 2 对;topic 取 `protocol.json.topic`(meeting_loop 已
81
+ 不解析 question.md)。
82
+ 6. **模型拼接无条件化**(无 `startswith` 形状特判),与决策记录一致。
83
+ 7. **折叠语义产物侧验证**(可读性独立方法):源区间 thinking=0、省略标记
84
+ 1071 处、三份 header 指纹恒同——与性能的代码侧/构建侧结论双源互证。
85
+
86
+ ---
87
+
88
+ ## 3. 确定不一致与修复清单(收敛结论)
89
+
90
+ ### 3.1 P0 优先(静默改变行为 / 高风险失真)
91
+
92
+ #### 铁律-3 与 R1 合并:**模式值必须端到端生效,任一入口不得静默丢弃或静默走偏**
93
+
94
+ **问题 A(D3,非法/旧 `forkMode` 无 fail-fast,已实测复现)**:
95
+
96
+ - 推演(铁律):`build_fork_source` 只对三个字面量判断、无 else 兜底 →
97
+ 非法值走"边界后全量、不折叠、无预算上限"的混合分支。
98
+ - 实测(性能,`mode="bogus"`):返回 `(2968, err=None)`、产物 6.13MB、
99
+ 0.20s、header `forkSourceMode="bogus"` 且无 est/dropped;对照 compaction
100
+ 同源同期 2969 条/6.14MB(差 1 条 = 不补 compaction 条目,与推演逐字吻合)。
101
+ - **现实输入**(铁律):`/tmp/mv-e2e9/disc4/work-*/protocol.json` 持久化着
102
+ rename 前的 `"forkMode": "curated"`——"值只存在于每次生成的 protocol.json,
103
+ 无迁移负担"的假设不成立:**值一旦写盘就会存活**。
104
+ - 后果链(性能 + 铁律):静默命中已知最贵形态(≈930k tokens,上午实测被
105
+ provider 400)→ 每轮"发超窗请求 + 失败判定"分钟级 churn;**且**
106
+ `meeting_engine.py:773-779` 统一异常边界把 fs 层报错吞成"每 2s 廉价重试"
107
+ → 600s 后以 `reason="stall"` 收尾(原因错配,误导未来读者)。
108
+ - 定性(铁律):不是"加固",是**既定 fail-fast 约定的第四层缺口**——三层
109
+ 守"源不存在",这层守"源存在但形状错"。
110
+
111
+ **问题 B(R1,wrapper 静默丢弃参数)**:`README.md:51-52` 教用户
112
+ `mv.sh --start <spec> --fork-mode X`,而 `scripts/mv.sh:295-298` 的 `--start)`
113
+ 只取 `$2` 后 `exit`,多余参数**静默丢弃**(python 收不到,一直用默认值)。
114
+
115
+ **修法(一次完成,四层同源)**:
116
+
117
+ | 层 | 动作 | 理由(分类,写入注释) |
118
+ |---|---|---|
119
+ | wrapper | `--start` 分支 **哑转发**余参给 python;**不解析值、不注入默认值**;usage 正文/头注释补 `[--fork-mode X]` | 转发者只转发(值识别不在此);默认值唯一家 = `DEFAULT_FORK_MODE` |
120
+ | CLI | `choices` 引用 `FORK_MODES` 常量(早失败) | 人输入早期反馈 |
121
+ | loop `__main__` | 新增门(照 `meeting_loop.py:517-522` forkSource 先例):非法 → `[fatal]` + `sys.exit(1)` | 配置错误不是运行期故障,不进 engine 重试路径 |
122
+ | fs | `build_fork_source` 入口(`open` 之前)值域校验 | 值集合定义权在实现处(库调用者守卫) |
123
+
124
+ **同批引入(配套)**:
125
+
126
+ - **值集合与默认值单一源**:`meeting_fs.FORK_MODES` / `DEFAULT_FORK_MODE`。
127
+ 默认值字面量共 **8 处**(生产 5:`start_discussion.py:915/386/737`、
128
+ `meeting_loop.py:528`、`meeting_fs.py:587`;内部签名 3:
129
+ `meeting_loop.py:265/354/432`)全部替换为常量引用。
130
+ - **替换边界(机械判据)**:`DEFAULT_FORK_MODE` **仅**用于默认值位置(8 处);
131
+ **全部模式名位置保持字面量**——比较 6 处(`meeting_fs.py:622` `!= "full"`、
132
+ 632/636/638 `== "compaction"`、641/666 `== "budget"`)+ 赋值 1 处
133
+ (`:640` `mode = "full"`)。机械验收:`grep 'mode [!=]= "'` 恒为 6;
134
+ 替换后默认值位置裸 `"budget"` 为 0。改默认值不得改分派(否则该模式分支
135
+ 静默走错)。注释落点:常量块一行解释"两种语义角色(缺省填谁 vs 处理哪个
136
+ 模式)"+ 641/666 各一行执行提醒;不铺满 6 处。
137
+ - **错误措辞对齐既有先例**(`meeting_core.py:130` 枚举合法值):
138
+ `f"未知 forkMode: {mode!r}(合法值: {FORK_MODES})"`——对历史值 `curated`
139
+ 的报错因此自解释。
140
+ - **词表**(design.md §一 表下两行):合法值 `budget/compaction/full`;
141
+ 历史产物/旧 `protocol.json` 可能含 `active`/`curated`(rename 前)→ 按
142
+ 非法值处理(D3 证据链与 D1 清扫的共同依据)。
143
+ - **死字段收掉**:`read_fork_stats` 的 `"entries": None` 删除(唯一调用方
144
+ 只用 mode/est/dropped);docstring 改为"mode/估算/丢弃数取自 header;
145
+ 条数由构建返回值提供"(R4 承诺修正)。
146
+ - **验收判据**:fs 门单测(非法 → 返回错误且**目标文件未创建**;错误文本
147
+ 含三个合法值);loop 门走 `tests/test_main_paths.py` 真实 subprocess 装置
148
+ (非法 protocol 值 → 退出码非零 + `[fatal]` 在输出 + **无 fork 源生成
149
+ 日志行**);CLI 早失败行为不变。wrapper 验收:`--fork-mode full` →
150
+ `protocol.json.forkMode == "full"`;不带 → `"budget"`(缺省≠非法,两条路径)。
151
+
152
+ ### 3.2 P1(文档承诺与实际不符 / 影响 spec 质量)
153
+
154
+ #### 铁律-5(原 R2):三处"完整上下文"与有损默认模式矛盾
155
+
156
+ - 位置:`prompts/multi-viewers.md:2`(**用户可见 description**)、`:37`
157
+ (给编排 LLM 的指令)、`templates/spec-readme.md.tpl:21`(**给写
158
+ background.md 的协作者**)。
159
+ - 与默认 budget 有损不符(实测丢弃 2146 条、省略 1071 处);同文件
160
+ `tpl:38-39` 自己写的是"按预算裁剪+折叠"——**同一文件自相矛盾**。
161
+ - 修:以 tpl:38-39 为**基准句**,三处照抄(description 用短式);`:21` 的
162
+ "为什么重要"警告语境**必须保留**(历史里有别的事会被当成任务),只换
163
+ 事实句。定性:**设计符合度**(机制承诺),不是文风。
164
+
165
+ #### 铁律-2(原 D2):`docs/design.md` §一 规模数字混源且无测点
166
+
167
+ - 证据(性能逐项对账):compaction 行 `2894 条/5.66MB`(改名前探针)与
168
+ `≈930k`(上午 e2e9 失败现场,当时 fork 2637 条/5.1MB)**不是同一份产物**;
169
+ budget 行 806 条已漂到 821(loop 日志);full 6741 → 现 6816;bullet
170
+ "主 pi ≈185k" 已漂到 **237,079**(同一 session 末次请求)。
171
+ - 违反文档自身纪律:§二.2"引用必须带唤醒序号"、数字四分类"实测须附口径
172
+ 与测点"——规则写在 §二,违例出现在同一提交的 §一,根因是**判据没挂在
173
+ 提交动作上**(§二 是声明,不是检查点)。
174
+ - 修:
175
+ 1. §一 **全节**加锚(表格 + 4 条 bullet):"产物侧,2026-09-10,主 session
176
+ ≈6.7k 条/15MB(数字随主会话增长漂移)";
177
+ 2. 消费侧数字(≈930k、≈132k)移入「为什么需要 budget」节并带唤醒序号
178
+ (§二.2 要求);budget 行注明"est 为预算钉住值(不漂),条数/MB 随源漂移";
179
+ 3. §二.3 引三点独立样本(1.656/1.657/1.659)支撑"不得固化为 2.0×";
180
+ 4. README 同族同批:`:32` "约 930k" 加锚;`:34` "≈132k 真实" 补"(唤醒 1
181
+ 首请求)";`README.md:26` 折叠清单补"**长参数截断**";数字定稿为
182
+ "约 80k est(示意值;权威口径见 docs/design.md §二)"(三约束:标示意、
183
+ 指向权威、不作验收口径)。
184
+ 5. 可执行形式固化(methodology):**数字(口径;测点)**模板,"同处"是
185
+ 关键——脚注/别节/口头都不算。
186
+
187
+ #### MC 作用域(性能发现 + 铁律裁决):声明范围过宽
188
+
189
+ - 证据(性能):fork 会话同样被 MC 裁剪(三份 fork 会话各有 `source_contents`
190
+ 67–70 条/会话,内容 = 旧 wake prompt + 旧自述;`session_meta` 有
191
+ `last_nudge_tokens`)。
192
+ - 裁决(铁律):`design.md` §四/§一 的"budget **不依赖任何扩展**"对
193
+ **构建期**成立(我们的代码,零扩展依赖),对**整条链路**失准——
194
+ 运行期上下文受环境扩展影响。修法是**限定作用域**,不是撤回。
195
+ - 定稿措辞(**3 处一次同改**:`meeting_fs.py:387` 注释块、`:593` docstring、
196
+ `docs/design.md:121`;其中 `:387` 行同时含 D1 旧名 → **与 D1 一次编辑**):
197
+
198
+ > fork 源**构建**不依赖任何扩展(纯 pi 语义 + 预算 + 折叠);**运行期**
199
+ > 上下文受环境扩展(如已安装 MC)的渲染期裁剪影响;未装扩展时的轨迹
200
+ > 取决于 pi 核心 compaction(本环境未观测)。
201
+
202
+ - **不断言方向**:性能 0006 §3 曾写"未装 MC 更早撞窗",作者本人在 0008 §2
203
+ 收回(未实测;此环境 pi compaction 从未观测——主 session 全部 compaction
204
+ 来自 MC,三个 fork 会话 0 条)。最终表述只保留"与扩展安装状态有关"。
205
+ - 配套:§二.4 增长口径标注 **post-environment-curation**;运行期数字统一
206
+ 以"唤醒首请求"为锚(峰值不用于增长模型);未观测部分进未覆盖节(§5)。
207
+ - 正面核验(铁律):MC 在 fork 会话丢的是旧 wake prompt/旧自述,**不影响
208
+ 协议正确性**——单一事实源在文件与 bare git,上下文只是叙事载体
209
+ (信息层/流程层分离的现场验证)。
210
+
211
+ #### 铁律-1(原 D1):改名残留(`curated`/`active`)
212
+
213
+ - 源码/文档残留 **8 处**:`meeting_fs.py:382/384/387/623/634/654`、
214
+ `meeting_loop.py:355`(docstring"活跃视图")、`start_discussion.py:921-922`
215
+ (**用户可见 CLI help**"首唤用活跃视图挂载主上下文")+ 测试 fixture
216
+ `tests/test_meeting_fs.py:457`(`curated.jsonl`)。
217
+ - 其中 `meeting_fs.py:654` 是**双重失效**:"单一心智模型(curated 不保证
218
+ 原始链完整,**docstring 已声明**)"——所指声明在现行 docstring 中不存在。
219
+ - 修:一次全仓清扫;`:387` 与 MC 措辞收窄同批;fixture 名/续行缩进一并修。
220
+ - **制度**(错误→制度化):改名/值域变更的完成判据 = **分区语义自检**
221
+ (一次 grep 可判):现行描述区(源码注释/docstring/CLI help/测试命名/
222
+ README/AGENTS/design.md 正文)旧名必须为空;`docs/examples/` 存档、
223
+ design.md 决策记录、git 历史**允许且应当**保留旧名(否则规则活不过第一次
224
+ 运行)。**不建常驻旧名清单**(清单只存在于改名提交时刻;历史值语义家 =
225
+ design.md 词汇行;methodology 只写"何时做/怎么做")。
226
+
227
+ ### 3.3 P2(顺手批,与 P0/P1 同批低成本执行)
228
+
229
+ - **铁律-4(原 D4 + 各微项)**:README 数字(§3.2 三约束版)+ 补"从
230
+ compaction 边界起";§二 补 `forkSourceDropped` 一行定义;`meeting_fs.py:587`
231
+ 续行缩进、fixture 名、局部 import(`meeting_fs.py:689/715-716` 与顶层重复);
232
+ **banner 降断言**——`start_discussion.py:1122` 的 "[start] 已启动 N 个
233
+ meeting loop 进程"改为"已拉起 N 个进程(存活未校验;loop 状态见
234
+ status/loop-*.log)",**与 loop 门同批**(新门使"坏了立即死"概率上升,
235
+ 不修则放大旧断言失真);`prompts/multi-viewers.md:57` 的 `--say` 主次
236
+ 修正(wrapper `--say` 放主位、`/multi-viewers-say` 标"(规划中)")。
237
+ - **铁律-6(原 R3)**:`docs/design.md` §三 拆分清单列 8 个函数,而 banner
238
+ (`meeting_fs.py:378-380`)实划 11 个(漏 `_registry_log`/`build_bootstrap`/
239
+ `preserve_result_md`;`append_handoff_turns` 实际在文件末)。修:banner
240
+ 分段(A 组 7 函数 + `append_handoff_turns` 上移归位 + banner C 三函数);
241
+ §三 清单按新章节点名;**§三 就地一行**制度指针("列举集合须同批对照",
242
+ 完整制度在 methodology)。与 F1 同根因(文档"列举集合"缺机械对照)。
243
+ - **F1 决策记录否因覆盖不足**(性能):`design.md:97` F1 行"收益仅 0.011s"
244
+ 只对 budget 产物成立(full 产物 134ms + 37MB 峰值),且漏同层替代
245
+ (`append_handoff_turns` 只保留尾行:不跨层传状态、不新增失效面)——被
246
+ 否决方案集合不完整。修:同层方案**独立成行**(否决表已有先例)或否因
247
+ 显式说明"已评估/未采纳(原因)";量级 0.4s vs ~130s/唤醒(0.3%),
248
+ 现在不写代码。
249
+
250
+ ### 3.4 规则与记录形态(收敛结论,非代码改动)
251
+
252
+ - **规则(可读性提出,铁律归位):断言强度与范围 ≤ 保证强度与范围**,
253
+ methodology 一条,三维一张表、五例:
254
+
255
+ | 维度 | 校核时机 | 例 | 去向 |
256
+ |---|---|---|---|
257
+ | 强度 | 写时 | R2"完整上下文"、R4"取自同一来源"、banner"已启动" | 铁律-5 / 铁律-4 / 登记·乙1 |
258
+ | 范围 | 写时 | "不依赖任何扩展"(构建 vs 整链) | MC 措辞(§3.2) |
259
+ | **引用完整性** | **被引用物状态变化时** | D1.6 假引用;**撤回传播**(引用已撤回断言) | 铁律-1;方法论一句 |
260
+
261
+ 边界:判据须可指认"位置 + 保证",不用于文风评审;本体范围 = 制品文本
262
+ (讨论消息不逐句约束——审议过程天然含试探与修正);讨论记录的失真由
263
+ **引用不豁免**规则拦截(撤回/修正后全部引用处同批更新)。两组自纠样本
264
+ (性能 0006→0008;铁律 0008→0009)作"撤回传播"在讨论面的完整教材。
265
+ - **守卫表合一**(可读性提议):three guards 的三份材料(三态链=效果、
266
+ 逐层注释=理由、校验成本=成本)并为**一张表**(列=守卫点/今日状态/本轮
267
+ 新增/理由/成本;表后一行"校验开销 <0.01%,不作设计约束";三态链作效果
268
+ 注)。归宿:result.md/design.md 决策记录(权威)+ 代码注释只留指针。
269
+ 范围注:三态链只描述 **protocol.json/历史值路径**(CLI 路径今日已
270
+ argparse 早失败,不入表——防"今日什么都不报错"误读)。
271
+ - **家的纪律**:制度/清单/词汇的**权威只一处**(design.md 决策记录 或
272
+ methodology),其他位置(代码注释、§三、AGENTS.md)只放**一行指针**;
273
+ 完整制度不复制(防"下次改动漏一处"的静默失配)。
274
+ - **`--wait` 对 `stopped` 接终态**(铁律提案,可读性加文案要求):现
275
+ `start_discussion.py:998-1006` 只对 `stalled`/`not-exists` 返回,`stopped`
276
+ 落入 10s 轮询无上界(与"loop 死后观察者不收敛"同族)。提案:接终态
277
+ (不新增状态,复用 `check_status` 既有定义),文案点名"未启动/启动后
278
+ 崩溃"两种成因与下一步。代价已声明:`--start` 之前调用 `--wait` 会立即
279
+ 退出(取舍:无上界等待 vs 提前告知)。
280
+
281
+ ---
282
+
283
+ ## 4. 登记项(不占结论位,但须记录)
284
+
285
+ **甲. 范围外(文档↔实现同源失真,非本轮 fork 主题)**
286
+
287
+ 1. `prompts/multi-viewers.md:57` 教用户敲 `/multi-viewers-say`——该扩展
288
+ 不存在(无 `extensions/`,package.json 只注册 `prompts`)→ 已归铁律-4
289
+ 直接修。
290
+ 2. `package.json files` 与 README 指针不同源(`docs/design.md`/
291
+ `AGENTS.md`/`docs/test-methodology.md` 不在 `files`)→ 安装态死链;
292
+ **发版 0.1.0 前置项**。
293
+
294
+ **乙. 可见面缺口(预存,非本轮修法引入)**
295
+
296
+ 1. `start_discussion.py:1104-1122` 启动 loop 后不校验存活即打印"已启动
297
+ N 个"(banner 降断言同批处理)。
298
+ 2. stall 判定在 loop 进程内评估(`meeting_engine.py:597-604`)——**全员
299
+ loop 死亡时无消费者执行 stall**,实际代价 = 墙钟等待无上界(直到人工
300
+ 检查)。
301
+ 3. `--wait` 对 `stopped` 不终止(§3.4 已附提案)。
302
+
303
+ **丙. 未覆盖(本轮不展开设计)**
304
+
305
+ 1. **合法值 + 超窗**:修掉非法值后该形态仍敞开(预算常量上调或窗口/预留
306
+ 变化时可合法越过)。判定式:`1.66×est + G ≤ 664k`(消息预算 = 1M − 384k);
307
+ `G` 实测 w1→w7 为 +56–76k(2026-09-10 现场,超 w7 未测)——**任何自检
308
+ 必须带校准因子**(直接对 est 会宽松 1.66–2.7 倍)。当前余量:est 可上调
309
+ ≈3 倍(80k→~230–260k)仍不触窗;约束在成本侧,非容量。触发:预算常量
310
+ 上调或模型窗口/预留变更时。
311
+ 2. **无 MC 环境的 pi 核心 compaction 轨迹未观测**(复测动作:无 MC 环境
312
+ 跑一轮;触发:环境变化或容量重估时)。
313
+ 3. **80k vs 53k 预算的产出质量对比未做**(质量无单点判据、N=3 欠功率;
314
+ 若重启须先登记判据与比较单位)。
315
+
316
+ ---
317
+
318
+ ## 5. 方法条目(本轮产出,供 methodology 收录)
319
+
320
+ 1. **分区语义自检**(改名/值域变更的完成判据):现行描述区旧名必须为空;
321
+ 存档/决策记录/git 历史允许保留;清单只在改名提交时刻存在,不建常驻名册。
322
+ 2. **断言强度/范围 ≤ 保证强度/范围**(制品文本;三维含引用完整性——
323
+ 引用不豁免、撤回须传播)。
324
+ 3. **数字(口径;测点)**:任何引用数字须在同处给出数据源与测点;消费侧
325
+ 数字带唤醒序号;配置派生值注推导式;外推标"外推";事后拟合关系明确
326
+ 标注(design.md §二 的"≤20%×(窗口−预留)"即事后归纳,非原始设计目标;
327
+ 初版"对齐 MC 88k"是刻度混淆——88k 真实 token ≠ 53k est)。
328
+ 4. **自反性与混源防范**(本主题特有):讨论 agent 会读取/引用/回灌讨论
329
+ 对象——按文本 marker 划边界必须用**精确等值 + 结构位置**(可读性实例:
330
+ "最后一次出现"定位把 agent 读自己产物的 toolResult 当边界,险些误报
331
+ "折叠失效");统计核验先声明数据源与测点、再声明区分手段(三例同源:
332
+ 假阳性、持久化旧值、混源表格)。
333
+ 5. **家的纪律**:制度/清单/词汇权威一处,其余位置一行指针。
334
+
335
+ ---
336
+
337
+ ## 6. 修复批次建议(供实施)
338
+
339
+ | 批次 | 内容 |
340
+ |---|---|
341
+ | **批 1(P0)** | 铁律-3+R1 全链(wrapper 哑转发 + CLI/loop/fs 三守卫 + 值集合/默认值单一源 + 替换边界 + 错误措辞 + 死字段 + 词汇表 + 三处验收测试);D1 清扫(含与 MC 措辞同行的 `:387` 一次编辑) |
342
+ | **批 2(P1 文档)** | 铁律-2(§一 全节加锚 + 消费侧移节 + §二.3 样本 + README 同族);铁律-5(规范句式三处);MC 措辞三处;铁律-6(banner 分段 + §三 清单 + 制度指针) |
343
+ | **批 3(P2 顺手)** | 铁律-4 全部(README 细节、§二 定义、缩进/fixture/import、banner 降断言同批、`--say` 主次);F1 决策记录补行;守卫表落 design.md |
344
+ | **批 4(制度)** | methodology 三至四条(分区自检 / 断言规则 / 数字模板 / 自反性防范) |
345
+
346
+ 全批完成后按项目规范:全量测试 + 真实 e2e 复检(本轮未跑测试——静态审阅
347
+ 主题,`README.md:73` 的"~280s"未核)。
348
+
349
+ ---
350
+
351
+ ## 7. 讨论过程记录(收敛轨迹)
352
+
353
+ - **自由讨论(meeting 阶段,各 9–10 条)**:性能先复核规模口径(数字全吻合)
354
+ 并发现 F1 覆盖不足与 README 第二数字源;铁律核验三模式描述(8 处改名残留、
355
+ 混源、非法值无门);可读性发现 R1(wrapper 静默丢弃)、R2("完整上下文")、
356
+ R3(清单 8≠11)、R4/R5,并以产物侧证据复核折叠语义。
357
+ - **交叉修正(关键节点)**:①性能实测复现非法值分支,与铁律推演逐字吻合
358
+ → D3 证据升级为"推演+实测+持久化实例";②性能发现 engine 异常边界,
359
+ 收回"启动即报错"的过度声明并给出 loop 门落点;③性能 0006→0008 自我
360
+ 修正"未装 MC 方向"断言——成为"断言规则"作用于讨论记录的首例;④铁律
361
+ 0008→0009 自我修正同一方向残留句;⑤可读性仲裁规则范围之争(本体=制品
362
+ 两维 + 引用完整性第三维),铁律作为边界提出者接受;⑥性能补 622 行分派
363
+ 点(铁律 0008 的 5 处 → 全集 6 处),铁律接受并补 640 赋值类。
364
+ - **RR 轮转**:全员 pass(可读性/0012、性能/0013、铁律/0013),无保留异议。
365
+ - **消息统计**:可读性 12 / 性能 13 / 铁律 13;本讨论现场自身即为"运行期
366
+ 受环境扩展影响"与"唤醒首请求增长轨迹"的实测样本(见 §1 数据)。
@@ -0,0 +1,229 @@
1
+ > **存档说明**:本文件是 2026-09-10 一次真实多视角自审(性能 / 可读性 / 铁律
2
+ > 三视角)的 result.md 原文,主题为"forkMode 四层守卫与默认值单一源的实现"。
3
+ > 该轮抓到 4 个真实代码缺陷(P1 重复 prepend / P2 replay 丢前缀 / 台账双重
4
+ > 计数 / P3 分派与值域非结构耦合),修复见 commit 9412e32。
5
+ > 报告中的"不变量 I1–I5""P1–P4"等编号已在代码 docstring 与测试名中落地。
6
+
7
+ # 多视角分析结果:审阅 forkMode 四层守卫与默认值单一源的实现(含文档口径与方法论条目)
8
+
9
+ - **分析目录**:`discuss-mv-main-20260910-163549`
10
+ - **参与者**:可读性 / 性能 / 铁律(3 视角,meeting 协议 39 条消息 + 全员 pass 收敛)
11
+ - **审阅对象**:e2e10 评审修复批次——四层值域守卫、默认值单一源、文档口径、方法论条目 11–14、`--wait` 终态与横幅降断言
12
+ - **方式**:只读审阅;三视角各自跑只读探针(复刻 pi bundle replay 算法、合成 session、真实主 session)与微基准;未修改代码
13
+
14
+ ---
15
+
16
+ ## 零、结论摘要
17
+
18
+ 1. **四层守卫与默认值单一源成立**——布点正确、运行时零热路径成本、全仓无默认值字面量残留;错误文本分层(用户门含迁移指引 / 库层纯)是**有意的正确分层**。
19
+ 2. **发现 2 项结构语义缺陷(P1/P2)、1 项结构守卫缺口(P3)、1 项台账缺陷、1 项即修项(P4)与 6 项制品文本问题**("声明≠保证"族);全部给出修法或记录触发条件,三方已裁决。
20
+ 3. **核心裁决**:P1 = 删除 `prepend`;P2 = 窗口内 compaction「规范化移除 + 桥接」(**撤回**先前的"锚点改写"方案);台账 = 对齐循环后重算 `dropped`(`orphans` 独立携带);新增不变量 **I5(记账闭合)**。
21
+ 4. 性能侧结论:本轮所有修复**零新增热路径成本**(纳秒—微秒级、无新增 pass)——不存在"性能 vs 正确性"的取舍。
22
+
23
+ ---
24
+
25
+ ## 一、确认成立(逐条独立核对,无需动作)
26
+
27
+ ### 1.1 四层守卫布点与职责(`forkMode`)
28
+
29
+ | 层 | 位置 | 核对结果 |
30
+ |---|---|---|
31
+ | wrapper(bash) | `scripts/mv.sh` `cmd_start` 第 3 步 `--skip-setup --start` 不接 `"$@"`(仅创建步转发) | 转发者只转发、不解析值 ✓ |
32
+ | CLI(argparse) | `start_discussion.py:915-916` `default`/`choices` 引用常量 | ✓ |
33
+ | 常驻入口 | `meeting_loop.py:517-524` 门在 `agent_loop` 之前、`exit(1)` + `[fatal]` | 配置错误不进 engine 重试路径 ✓ |
34
+ | 实现函数 | `meeting_fs.py:618-620` 校验在 `open` 之前 | 非法值不读文件、不落盘、不生成半成品 ✓ |
35
+
36
+ 运行时成本(性能实测):fs 门成员判断 ≈99ns;loop 复用同一次 `proto` 解析(无第二次 I/O);wrapper 无重复解析。**fs 门在 open 前是实质收益**:非法值代价 ≈0,放在 open 后会白付一次完整解析(142ms)+ 落盘 + 一次注定失败的模型请求(~132k tokens)。
37
+
38
+ ### 1.2 默认值单一源
39
+
40
+ 全仓 8 处默认值位置(`meeting_fs` 构建 1 + `meeting_loop` 形参/入口 4 + `start_discussion` 3)全部引用 `meeting_fs.DEFAULT_FORK_MODE`;无字面量残留(`grep '"budget"'` 仅命中常量定义与分派条件)。两种语义角色(**值集合** `FORK_MODES` vs **缺省填谁** `DEFAULT_FORK_MODE`)在代码与注释上分开 ✓。
41
+
42
+ ### 1.3 错误文本分层(有意的分层,非缺口)
43
+
44
+ - `meeting_loop.py:518-523`(用户门):含迁移指引(旧值提示)——用户入口层;
45
+ - `meeting_fs.py:618-620`(库函数):只报非法值 + 合法列表、不落盘——库层保持纯。
46
+
47
+ ### 1.4 其它确认
48
+
49
+ - **日志自描述**:`meeting_loop.py:236-238` 的"丢弃 N 条""est≈…(字符/3 估算)"均带口径;`read_fork_stats`(`meeting_fs.py:413-431`)单点解析 header、**只读首行 O(1)**(40µs vs 全文件 11.3ms ≈284×——此数字支持"P15 单一来源在性能上成立",建议以定性句 `O(1),与产物大小无关` 写入 docstring)。
50
+ - **`--wait` 两终态文本**(`start_discussion.py:1000-1014`):`stalled`(收尾中断)与 `stopped`(未运行)互斥、各有成因与下一步;`stopped` 终态净收益(消除无上界轮询),成本≈0(复用本来就要算的 `check_status`)。
51
+ - **启动横幅降断言**("已拉起 N 个进程(存活未校验)")正确。
52
+ - **文档口径表述**:`docs/design.md` §一 anchor 注、§二"20% 公式是事后归纳"标注、`README.md` 示意值指针——三处互不矛盾。
53
+ - **构建性能画像**:`build_fork_source` ≈181ms(解析 142ms 占 78%;折叠+裁剪+统计 ~39ms);每 agent 只建一次(首唤分支),后续唤醒走 `--session-id`。
54
+ - **`compaction` 产物 est ≈107 万**(≈窗口 1.6×)——独立印证"budget 是长会话唯一可行模式",可作设计文档 §一的实测补语。
55
+
56
+ ---
57
+
58
+ ## 二、需修复项
59
+
60
+ ### 2.0 结构语义缺陷(三方已裁决修法)
61
+
62
+ #### P1 `compaction` 模式产物含**重复 compaction 条目**(同一 id 两次)
63
+
64
+ - **证据**:真实主 session(6975 条 / 9 个 compaction)实测产物 body 3129 条,`c5d43076` 出现在位置 **[0, 805]**;两视角独立复现。
65
+ - **机制(经更正)**:正常路径 `kept_idx < comp_idx` **恒成立**(pi `session-manager.js` `appendCompaction(parentId=leafId)` 保证锚在 comp 之前)⇒ `entries[kept_idx:]` 必含原件 ⇒ `[comp] + body` **恒为重复**。prepend 副本**被 last-wins 遮蔽**(pi `buildEntryIndex` 顺序 `set`、后者覆盖前者 → 解析到原件),副本不可达、不参与 replay——"孤立节点"是**不成立的机制描述**(铁律/0001 与可读性/0003 均曾误用,后经核实更正)。
66
+ - **实害**:① 产物/声明不一致(违反"最后 compaction + firstKeptEntryId 起的条目");② 对**文件顺序**的隐含依赖(last-wins 遮蔽只在原件在后时成立);③ 对按 first-wins/线性扫描解释产物的消费者的脆弱性。
67
+ - **修法(定夺)**:**删除 prepend**——compaction 模式 = `entries[kept_idx:]`;锚失效保持 fail-fast(与"无静默"一致)。不写 fallback、不搬家("prepend 仅 fallback"在 compaction 模式无 fallback 可依——该表述曾误导两位评审者,meta 论据支持删除)。
68
+ - **docstring 措辞**:"从 `firstKeptEntryId` 起的条目(含最后一个 compaction 条目本身,位于其自然位置)"。
69
+ - **修复动机句**(表述纪律):引用仓内不变量("满足 I1(id 唯一)、消除 last-wins 顺序依赖")——**不写"修复 replay 破坏"**(replay 并未损坏)。
70
+
71
+ #### P2 `budget` 窗口含 compaction 条目时,pi replay **静默丢弃前缀**(含 preface)
72
+
73
+ - **证据(复刻 pi replay 探针)**:产物 `[preface, old7, k1, k2, C1, n0..n2]` → 可见 `[C1, n0..n2]`(前缀全丢)。两个形态:
74
+ - (a) 锚被裁掉(`firstKeptEntryId` 不在产物内)→ 前缀全丢;
75
+ - (b) 锚仍在产物内、但产物有锚前条目 → **锚前条目丢失**(场景5:`k0` 丢)。
76
+ - 精确化:**comp 是窗口首条时修复前就已正确**(`ci=0` 不扫描)。触发 ⇔ 窗口含 compaction 且其非窗口首条("刚压缩完就 fork")。
77
+ - **修法(定夺)**:**窗口内 compaction「规范化移除 + 桥接」**——
78
+ - 移除窗口内**全部** compaction 条目;指向被移除条目的 `parentId` 上溯到第一个非 compaction 祖先(连续 compaction 链亦正确);上溯出产物 → 链首 `parentId = None`(显式链首,与 preface 同型);
79
+ - 位置:在**边界对齐之后、preface 注入之前**;流水线整句进 docstring:**`fold → trim → 对齐 → normalize → preface → est`**;
80
+ - **退化守卫**:规范化致 body 为空(窗口仅含 compaction)→ **保留该条**(成为链首,replay 天然全集合可见);
81
+ - `est`:现有"对最终 body 统一求和"的单一测点自动正确(compaction 条目 `_entry_text` 为空、`_est_tokens` 返 1 → 移除后 est 降 `#removed`,无需恒等断言);
82
+ - **信息损失边界**:最后一条 comp 摘要已在 preface("此前压缩摘要"行);更早的是被滚动摘要覆盖的旧摘要——损失有界。
83
+ - **裁决记录**:先前 铁律/0004 提出的"**批量改写锚点**"方案**已撤回**(语义上伪造历史字段;且中间锚仍悬空)。性能/0007/0010 的"改写 0.07ms/0.27ms、est 恒等"测量**对应已撤回机制**——成稿勿并载(性能/0013 亦确认)。
84
+
85
+ #### 台账缺陷:边界对齐致 `dropped` **双重计数**(独立复现 + 第二破法场景)
86
+
87
+ - **证据**:`_budget_entries` 的 `dropped` 在边界对齐循环**之前**绑定(`meeting_fs.py` `dropped, kept = folded[:cut], folded[cut:]`),循环只改 `cut` 不回写 `dropped` → 回扩条目**同时留在 kept 与 dropped**。
88
+ - 场景 B(源 3 条:big / a1-toolCall / r1-toolResult,`keep_tokens=5`):kept=2 + dropped=2 = **4 ≠ 3**(a1 双重计数);
89
+ - 场景 C(源 2 条:big / 孤儿 r2):kept=2 + dropped=1 = **3 ≠ 2**(big 从 dropped 但在 kept);
90
+ - 真实源今日回扩 0 次 → **潜在态**(结构触发的低频路径,与 P2 同型)。
91
+ - **修法(最小)**:
92
+
93
+ ```python
94
+ orphans = [] # 新增:对齐中真正丢弃的孤儿(cut==0 分支)
95
+ while kept and (kept[0].get("message") or {}).get("role") == "toolResult":
96
+ if cut > 0:
97
+ cut -= 1
98
+ kept = folded[cut:]
99
+ else:
100
+ orphans.append(kept[0])
101
+ kept = kept[1:]
102
+ dropped = folded[:cut] + orphans # 循环后重算(消除 stale binding)
103
+ ```
104
+
105
+ 孤儿必须**独立列表**(重算 `folded[:cut]` 在 `cut==0` 时为空,会把循环 append 的孤儿清掉——orphan 来源是 `kept` 不是 `folded[:cut]`)。三场景验算:B→和 3 ✓;C→和 2 ✓;纯孤儿→kept 0 + dropped 1 = 1 ✓。
106
+ - **硬要求**:本修复与 P2 的 comp 移除计数**同批落地**(否则 I5 台账断言被旧 bug 污染,"先红后绿"验证对象失真——"事实基础同批"纪律的第三次应用)。
107
+
108
+ ### 2.1 族 A「声明≠保证」6 例(制品文本与事实不符)
109
+
110
+ | # | 位置 | 声明 | 实际保证 | 修法 |
111
+ |---|---|---|---|---|
112
+ | A-1 | `meeting_fs.py:394/414/613`、`meeting_loop.py:221/233` | 注释以 `(P0,e2e10 评审)`/`(P15)`/`(可读性 #2 拆分)` 作权威引用 | 编号不可核验(`docs/examples/` 无 e2e10 存档)——**违反 AGENTS.md 注释引用约定**("新增注释不再引入不可核验编号") | 改自描述("值域校验在入口(open 之前)——非法值就地报错、不生成半成品");决策记录表行标识改方案名 |
113
+ | A-2 | `docs/test-methodology.md` 方法 12 | "一次 grep 能判"两类分区 | 实现有**有意的第三类**:面向用户的迁移提示文本(`meeting_loop.py:520-522` 故意含旧名) | 方法 12 允许保留区增列该第三类(修文本,不修代码) |
114
+ | A-3 | `docs/design.md:26`(§一 budget 行) | "`est` 为**预算钉住值**(不随源漂移)" | 有上界、确定性成立;**"钉住"不成立**——边界回扩(toolResult → toolCall)与末条超预算保留会略上浮 | 改"以预算为**上界**(preface 计入、边界回扩可略上浮)";性能附精确式 `est ≤ max(预算, est(末条)) + Σ est(回扩条目) + preface`(工程余量 ~53 万 tokens,无需为它加保护) |
115
+ | A-4 | `build_fork_source` docstring | "最后 compaction + firstKeptEntryId 起的条目" | 产物含重复条目(P1) | 随 P1 同批改(见 2.0) |
116
+ | A-5 | 产物 header/est | 声明"保留"的集合 | replay 可见集合可能更小(P2) | 随 P2 同批改;**不变量 I4** 定义为集合身份 |
117
+ | A-6 | 性能/0001 §1.3/§1.4 触发条件 | "观察 `status-*.json`/日志即可估"(RSS/耗时/占比) | **观测手段不存在**:`status-*.json` 只写 `{"sessionID": ...}`;`log()` 只打时间戳+消息;全仓无构建耗时/RSS 记录点 | (a) 加一行构建日志(耗时+RSS)+ **触发条件分拆**:耗时=监控型、占比=复测型 |
118
+
119
+ ### 2.2 族 B 结构守卫缺口
120
+
121
+ #### P3 `FORK_MODES` 与分派**非结构耦合**——新值经值域校验后落入混合分支
122
+
123
+ - **证据(探针)**:`FORK_MODES += ("smart",)` 后 `build_fork_source(mode="smart")` 正常返回:header 记 `smart`、**无 est、无折叠、无 preface**("边界后全量"混合态);现有测试全绿。**正是方法 13 记录的 bug 类换门进入**。
124
+ - **代价不对称**:该混合态实测 ~930k tokens → 每唤醒一次必被 provider 400(一次注定失败的请求 + 数十秒延迟),历史上被 engine 异常边界吞成 ~2s 廉价重试。
125
+ - **修法**:分派显式化——末尾 `else` 抛错(值域守卫之后仍可达的只剩"新值未加分派");**逐值指纹测试**:budget→`forkSourceTokensEst` 存在;compaction→保留区结构;full→首条=源首条。
126
+
127
+ ### 2.3 即修项(原族 C 中的 P4 已拆出——"修比记便宜")
128
+
129
+ | # | 项 | 修法 | 成本 |
130
+ |---|---|---|---|
131
+ | P4 | `--wait` 的 `stopped` 无宽限/成因合并 | **消息文本按 `loop-*.log` 存在性分叉**("尚未启动" / "已启动、loop 不存活");**观测点必须用 `loop-*.log` 而非 `status-*.json`**(后者首唤完成后才写,会把"已启动、首唤中崩溃"误标为"尚未启动");不新增状态名;文案不含存活声称 | 一次 stat 1.6µs(vs `pgrep -f` 6.1ms/轮) |
132
+ | A-6 落法 | 构建观测点 | 一行日志:构建耗时(`perf_counter` 173ns)+ 峰值 RSS(`getrusage` 979ns);**不建指标体系、不进 status** | 1.2µs = 构建的百万分之六 |
133
+ | docstring | `read_fork_stats` 数字会过期 | 定性化:`只读首行(O(1),与产物大小无关)` | 纯文本 |
134
+ | F3 修订记录 | `design.md:108` F3 行"≈0.28s×3"无锚 | 按**修订记录**写:新值带锚 `181ms×3(本机、15.3MB 源)` + 旧值标注"口径不可考(或含调用侧开销)"(两者差 55%,不可静默替换) | 纯文本 |
135
+
136
+ ### 2.4 其余制品文本小项
137
+
138
+ | # | 位置 | 问题 | 修法 |
139
+ |---|---|---|---|
140
+ | 可读性-3 | `design.md` §三 决策表 | 行标识 `F1/F3/F2/F2'/P9'` 无出处;且 **F3 本仓同名两义**(`meeting_core.py:205` 的 review5 F3 vs 决策表 F3) | 行标识改**方案名**(消除实际歧义,成本最低) |
141
+ | 可读性-4 | `meeting_fs.py:649/654` 行内注释 | `# 分派用字面量(非默认值语义,勿换常量)` 是**纪律型注释**(说"别怎么改"不说"这行做什么");P1 那行真正需要的语义注释("仅 fallback 补 prepend")反而没有 | 随 P3 结构闭合消解;P1 处补一行语义注释 |
142
+ | 可读性-5 | `design.md:47` | 标题"三处互引"未枚举哪三处 | 枚举或删计数 |
143
+ | 可读性-6 | `meeting_loop.py:237` | `est // 1000` 在 `est < 1000` 时显示 `est≈0k` | `<1000` 时原值或 `<1k`(默认预算 80k 不受影响) |
144
+
145
+ ---
146
+
147
+ ## 三、不变量清单(I1–I5)——落点与验证方式(成稿核心)
148
+
149
+ ### 定义(进 `build_fork_source` docstring 不变量小节,**只写保证句**;"打破者/修复史"留在决策记录,不进代码)
150
+
151
+ | # | 不变量 | 检查 | 落点 |
152
+ |---|---|---|---|
153
+ | **I1** | 产物内 **id 唯一** | 集合计数 | 测试断言(静态) |
154
+ | **I2** | **链连续(强形式)**:链覆盖全部条目;除链首外每条 `parentId` 指向产物内条目;链首显式 | 逐条 id 查表 + 链走 | 测试断言(静态)——真实 budget 产物实测 **732/732 在链上、0 悬空、叶唯一** |
155
+ | **I3** | **replay 使用的锚点**(路径上最后一个 compaction)的 `firstKeptEntryId` 指向产物内条目 | 逐条查表 | **回归断言**(budget 平凡成立——规范化后无 comp;compaction 由构造保证——锚=`kept_idx` 条目)。非修复目标 |
156
+ | **I4** | **声明集合 == pi replay 可见集合**(**集合身份**比较,非 est 数值——1-token/条目、preface 计入、1.66× 校准比均不影响其语义) | 测试 oracle 复刻 `buildSessionPath + buildContextEntries` | **测试期 oracle,禁生产复刻**;注释**钉住复刻来源**(pi 版本/指纹 + 函数名);职责界定为"**我们产物结构的回归保护**",**不承担**检测 pi 变更(pi 漂移时 oracle 双侧静默——该防线归真实 e2e) |
157
+ | **I5** | **记账闭合**:**源保留区条目数 =(产物中非 preface 条目数)+ `forkSourceDropped`**(等价:源保留区条目数 + preface 数 = 产物条目数 + `forkSourceDropped`) | 数条 | 测试断言(静态);`header.forkSourceDropped = budget_dropped_n + removed_n` |
158
+
159
+ ### 落点与纪律
160
+
161
+ - I1–I3/I5:**测试断言,不做生产守卫**——判定依据是**复杂度匹配**(非成本):① 修复 P1/P2 后由构造保证,生产校验是"用检查代替构造纪律";② 真实成本在**失败路径设计与归因**(P3 的病灶正是错误被 engine 边界吞成廉价重试 + `reason=stall` 误归因——为永不触发的检查重开一层失败语义不划算);③ 避免"复制品义务"。实测成本 0.19ms/732 条(若生产化也无障碍,但归属是复杂度选择)。
162
+ - 测试名按 ID(`test_i1_...`/`test_i2_...`)——契约(docstring)↔ 断言(测试名)可 grep 对齐。
163
+ - **动机句引用仓内不变量 ID 可核验**(I1–I4 在本仓有定义);`P0/P15` 式外部编号不可引用——"注释不提编号"规则的可核验边界在此。
164
+ - **fixture 断言集**(P2/台账):① 产物无 compaction 条目(**除非窗口仅含 compaction——保留首条**);② I2 链连续(桥接后可走、无悬空、链首 `parentId=None`);③ I4 oracle 集合身份;④ I5 台账闭合;⑤ **反向断言(先红后绿)——fixture 的存在条件**,非可选步骤。退化路径(窗口仅含 comp)必须进 fixture。
165
+ - **est 恒等断言撤回**:compaction 条目 `_entry_text` 空 → `_est_tokens` 返 1,移除后 est 必降 `#removed`;"单一测点"已保证 est 反映最终 body。
166
+
167
+ ---
168
+
169
+ ## 四、记录项(不修,附触发条件)
170
+
171
+ | 项 | 实测/性质 | 触发条件 |
172
+ |---|---|---|
173
+ | 三处冗余 pass(`_entry_text` 双算、dropped 全量重算、`_shrink_value` 先拷贝再比较) | 合计 ~11ms = 构建的 **6%** | 源 ≥~100MB 或构建 >1s 且冗余占比 >20%(占比为**插桩型**判据→复测,非监控) |
174
+ | O(源) 内存(全量 `entries` + `folded` 驻留) | 15.3MB 源 → RSS 峰值 **55MB**(≈3.6×);3 loop 并发 ≈165MB | 单场构建 RSS >~500MB 或源 >~100MB |
175
+ | P4 宽限延迟 | 已拆出为即修项(文本分叉) | —(不适用) |
176
+ | 每 agent 三次构建(≈543ms) | 支持现状:三 loop 是独立进程,共享构建需跨进程协调/失效/原子写义务;为省 360ms 不划算(与 F3 否决同因) | N≫3 且会话至 100MB 量级 |
177
+
178
+ **口径纪律(方法 14 扩展)**:改数字先判"漂移 vs 复测";**无锚旧值按修订记录处理**(不静默替换)——F3 更新是此规则第一次实跑。
179
+
180
+ ---
181
+
182
+ ## 五、方法论与文档更新清单
183
+
184
+ ### 5.1 `docs/test-methodology.md`
185
+
186
+ 1. **方法 12**:允许保留区增列第三类「面向用户的迁移提示文本(错误信息中有意提及旧值)」——判据自身缺口,修文本。
187
+ 2. **方法 14 扩展句**:改数字→先判漂移/复测;无锚旧值按修订记录。
188
+ 3. **新条目(判据自足性)**:任何带触发条件的记录必须指名一个**现在就能用的**观测点——否则触发条件不是判据而是修辞("声明≠保证"第 6 例的规则化;与 2.1 A-6、可读性-2 同源)。
189
+ 4. **新条目(评审层表述纪律)**:**观察句**(实测)必须可复现;**机制句 + 承载严重性/修复动机**必须推演或引源码,否则显式标注"推断"——机制句会流向制品(docstring/决策记录/Motivation),传播链上受同等强度约束;机制句带**证据指针**(源码位置/探针命令)优于"推断"标记(标记会忘、指针仍在)。本轮已出现两例("孤立节点"与"parentId 指向区外")。
190
+ 5. **修复顺序纪律**(第三次应用):结构修复与其**事实基础/声明文本**同批——stale-binding 与 comp 移除计数同批、动机句基于修正后的事实。
191
+ 6. 可选:把 oracle 的"引用完整性"归属(被引用物=pi 算法变化 → oracle 需重审)挂在方法 11 引用完整性维度下(避免新判据)。
192
+
193
+ ### 5.2 `docs/design.md`
194
+
195
+ - §一:`est` 措辞改"以预算为上界";可加"compaction 产物 est ≈107 万"实测补语。
196
+ - §二:`forkSourceDropped` 定义改"被预算裁剪**与结构规范化移除**的条目数";写明**双口径**及其关系式 `header = budget_dropped_n + removed_n`(preface 文本只含预算省略——差异写在定义处就不是 bug);preface 计数须点名(I5 精确式)。
197
+ - §三:决策表行标识改方案名;F3 补实测数据(修订记录形态);"改动集"里暂缓的"锚点改写"应标为**已撤回**。
198
+ - `:47` 标题"三处互引"枚举或删计数。
199
+
200
+ ### 5.3 其它配置/常量
201
+
202
+ - `FORK_MODES`/`DEFAULT_FORK_MODE` 常量块:值域守卫注释按 A-1 改自描述。
203
+ - `meeting_fs.py:649/654` 分派字面量注释:改"此处匹配具体模式名(分派目标),不要替换为 `DEFAULT_FORK_MODE`"(或随 P3 结构闭合删除)。
204
+
205
+ ---
206
+
207
+ ## 六、视图分歧裁决记录(防成稿并载两版)
208
+
209
+ | 议题 | 裁决 |
210
+ |---|---|
211
+ | P1 "prepend 仅 fallback" vs 删除 | **删除 prepend**(compaction 无 fallback、prepend 恒为重复;表述曾误导两位评审者→分支应消失而非搬家) |
212
+ | P2 "锚点改写" vs "移除+桥接" | **移除+桥接**(语义诚实、形态统一、不变量简化);锚点改写**已撤回**,性能的改写测量(0.07/0.27ms、est 恒等)**不并载**为修复实现 |
213
+ | I3 范围 | **仅 replay 使用的锚点**(撤回"批量保证所有锚"——中间锚悬空是 compaction 模式的正常形态) |
214
+ | I4 落点 | **测试 oracle,禁生产复刻**(铁律从职责边界/过期后果、性能从维护耦合独立到达同一结论) |
215
+ | oracle 过期可见性 | **双侧静默**(撤回"测试过期会 CI 变红"——正确理由是修改/复核成本,不是可见性) |
216
+ | P4 观测点 | **`loop-*.log`**(status 文件待首唤完成才写;log 在 spawn 前创建) |
217
+ | P4 归类 | 从"族 C 记录项"**拆出为即修项**(修 1.6µs vs 记录=永久观测义务) |
218
+ | 计数器口径 | **双口径**(header=预算+规范化移除;preface 文本=只预算) |
219
+ | I2 强度 | 从"链连续"升为"**链覆盖全部条目**";链首显式 `None` |
220
+ | 退化守卫 | 规范化不产生空 body(保留 comp 首条);断言①带退化例外 |
221
+
222
+ ---
223
+
224
+ ## 七、未覆盖 / 说明
225
+
226
+ - **`_est_tokens` 空文本返 1**(无 message 条目贡献 1 token):量级 <0.01%,由 **I4 的集合身份定义**消解(est 只是集合近似指纹,非数值承诺)——如需可在 docstring 提一句"无文本条目按 1 token 计"。
227
+ - `keep_tokens` 仅 budget 分支消费、其余模式静默忽略:docstring 已写明,可接受。
228
+ - `start_discussion.py:737` 的 `getattr(args, "fork_mode", DEFAULT_FORK_MODE)` 在 argparse 路径不可达:与 `fork_source` 同款防御写法、同一常量,无语义风险。
229
+ - 性能视角的测量(181ms 解析主导、0.19/0.20ms 检查器、1.2µs 日志点、1.6µs stat、55MB RSS)均标注本机/源规模口径;入档时按方法 14 保留括注。