dsh-vibe-math 2.2.2 → 2.3.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.
Files changed (43) hide show
  1. package/AUDIT-CHECKLIST.md +61 -3
  2. package/README.md +119 -1
  3. package/RELEASE-NOTES-2.3.0.md +207 -0
  4. package/RELEASE-NOTES-2.3.1.md +134 -0
  5. package/audit-formal-sensitivity.mjs +333 -0
  6. package/audit-persona-sensitivity.mjs +249 -0
  7. package/audit-persona-surface.test.mjs +349 -0
  8. package/audit-v5-integrity.mjs +43 -2
  9. package/audit-v5-sensitivity.mjs +77 -6
  10. package/docs/formal-verification.md +401 -0
  11. package/docs/generate_framework_diagram_v5.mjs +22 -16
  12. package/docs/test-timing.md +79 -0
  13. package/formal-verify-v2.test.mjs +951 -0
  14. package/formal-verify-v3.test.mjs +1031 -0
  15. package/formal-verify-v4.test.mjs +882 -0
  16. package/formal-verify-v5.test.mjs +598 -0
  17. package/package.json +22 -2
  18. package/prompt-corpus-persona/persona-corpus.json +32 -0
  19. package/prompt-corpus-persona/persona-corpus.md +674 -0
  20. package/prompt-corpus-v2/formal-verify-v2.json +394 -0
  21. package/prompt-corpus-v2/formal-verify-v2.md +4250 -0
  22. package/prompt-corpus-v3/formal-verify-v3.json +382 -0
  23. package/prompt-corpus-v3/formal-verify-v3.md +3843 -0
  24. package/prompt-corpus-v4/formal-verify-v4.json +84 -0
  25. package/prompt-corpus-v4/formal-verify-v4.md +255 -0
  26. package/prompt-corpus-v5/prompt-corpus-v5.json +109 -5
  27. package/prompt-corpus-v5/prompt-corpus-v5.md +653 -109
  28. package/prompt-v5-integrity.test.mjs +1158 -984
  29. package/run-tests.mjs +99 -0
  30. package/vibe-math-v2/agent.cordis.yml +40 -2
  31. package/vibe-math-v2/vibe-math-v2.js +811 -21
  32. package/vibe-math-v2//345/256/236/347/216/260/346/226/271/346/241/210.md +218 -1
  33. package/vibe-math-v3/agent.cordis.yml +46 -2
  34. package/vibe-math-v3/vibe-math-v3.js +810 -21
  35. package/vibe-math-v3//345/256/236/347/216/260/346/226/271/346/241/210.md +104 -2
  36. package/vibe-math-v4/agent.cordis.yml +46 -4
  37. package/vibe-math-v4/vibe-math-v4.js +744 -15
  38. package/vibe-math-v4//345/256/236/347/216/260/346/226/271/346/241/210.md +255 -0
  39. package/vibe-math-v5/agent.cordis.yml +41 -5
  40. package/vibe-math-v5/vibe-math-v5.js +621 -9
  41. package/vibe-math-v5//345/256/236/347/216/260/346/226/271/346/241/210.md +131 -4
  42. package/vibe-math-v5//346/236/266/346/236/204/345/233/276.md +57 -0
  43. package//347/244/272/344/276/213/345/233/276//346/241/206/346/236/266/345/233/276-v5.svg +51 -46
@@ -76,9 +76,50 @@
76
76
  - [ ] 成员被解雇/失败后,还会不会收到后续消息?
77
77
  - [ ] 会话重建(resume)后的提示词,措辞是否与"新入职"区分开?
78
78
 
79
- ---
79
+ ### 1.6 静态提示词面:人设 ↔ 注册表
80
+
81
+ 1.1–1.5 检查的是**运行时逐条发出的**提示词;还有一层**静态**提示词面必须一起核对——
82
+ `agent.cordis.yml` 的 persona 行。它是主代理收到的**唯一**一份"有哪些工具、能调哪些参数"的清单,
83
+ 而所有 e2e 套件都直接 `apply(ctx)`,**从不加载 YAML**,因此对这一层完全盲。
84
+
85
+ - [ ] 注册的**每一个工具**是否在 persona(`prefix` 与 `text` **两个**块)里出现?
86
+ 没出现 = 代理**无法发现**该能力(连准确名字都猜不到)。
87
+ - [ ] persona 里出现的**每一个** `vibe_*` 名字是否都真的注册了?
88
+ 出现但未注册 = 代理会去调用一个必然失败的工具。
89
+ - [ ] 新参数是否同时进了 persona 与工具 description 的参数表?
90
+ (例:`formalVerify` / `leanCommand` / `leanArgs` / `leanTimeoutMs`)
91
+ 参数没写进 prompt = 用户无法开启这个能力。
92
+ - [ ] `prefix` 与 `text` 两个块是否**逐行一致**(只允许第 0 行不同)?
93
+ 旧宿主读 `text`、新宿主读 `prefix`,两者漂移 = 不同宿主看到不同的工具面。
94
+ - [ ] 工具**改名/删除**时 persona 是否同步?("persona 提到的名字 ⊆ 注册表"这条反向检查负责抓)
95
+ - [ ] 人设里写的路径/模式名(`Formal/Lib`、`off|encourage|require`)是否与实现中的字符串**逐字**一致?
96
+
97
+ `audit-persona-surface.test.mjs` 把上述各条变成断言("未文档化工具"用**显式快照**表示:
98
+ 新增工具必须主动改快照、或在 persona 里写清);`audit-persona-sensitivity.mjs` 用 11 条探针
99
+ 证明这套断言真的会变红。**v2.3.0 修的就是这一类缺陷**:三个 `*_lean_*` 工具无条件注册,
100
+ 而 v2/v3/v4 的 persona 从未列出它们(只有 v5 列了),v4 的 `vibe_v4_set` 参数表也漏了
101
+ `formalVerify`/`leanCommand`/`leanArgs`/`leanTimeoutMs`——当时**所有既有套件全绿**。
102
+
103
+ ### 1.7 语义映射:把"事实"映射成"字段值"时不能张冠李戴
104
+
105
+ §1.6 查的是"名字/路径/参数有没有写对";这一节查**语义有没有写反**。它比漏写更危险:提示词读起来
106
+ 通顺、完整,而套件往往只断言"包含某句话"就能全绿。
107
+
108
+ - [ ] 每一个"发现 X 就投 Y"的映射是否**语义正确**?**真实事故**:Lean 形式化与命题原文不一致时,
109
+ 提示词要求"投 0"——而 0 的含义是"**命题为假**"。于是"形式化写错了"被记成"命题被证伪",
110
+ 在布尔一致规则下直接被写进 `Verified/` 标注**假**:用来求真更严格的机制,反而**伪造出
111
+ 一个错误的否定结论**。现在改为独立一档 `defect`(撤回证明 + 进待办 + 不定论)。
112
+ - [ ] **反向情形**的指令是否也在?("只有独立于该证据也能确定时才可否决"这类边界必须写出来,
113
+ 否则代理只会照字面把"证据不合格"当成"结论为假"。)
114
+ - [ ] 提示词承诺的**框架行为**是否真的实现了?**真实事故**:v2 的提示词让代理"在回执的 `formal`
115
+ 字段写明难度判断",但回执契约里没有这个字段、框架也从不解析它——代理的判断**静默消失**,
116
+ 而套件只断言"那句话存在",177 条断言全绿却守着一个**死通道**。
117
+ - [ ] 提示词承诺的**强度档位**是否与实现一致?(`encourage` 档没有门禁,就**不能**声称
118
+ "框架会搁置本次裁定";只改文字不改机制 = 骗代理。)
119
+ - [ ] 每个档位(`off` / `encourage` / `require`)的注入文本是否**各自**被人读过?只读一个档位等于没读
120
+ ——首版 `require` 档的门禁措辞从未进入任何语料。
80
121
 
81
- ## 2. 第二优先:把上面每一条变成**会变红**的测试
122
+ ---
82
123
 
83
124
  ### 2.1 逐条断言,而不是抽查
84
125
 
@@ -105,6 +146,11 @@
105
146
  - 机器可读(JSON)+ 人可读(Markdown);
106
147
  - 覆盖全部交互类型(入职、重建、常规轮、心跳、表决初评/辩论、会议、提议、各类框头、框架提示、失败);
107
148
  - 把工作区路径归一化(如 `<WS>`),使语料**确定性、可 diff**;
149
+ - **归一化必须大小写与分隔符无关**:Windows 下 `os.tmpdir()` 可能给出与插件渲染路径**不同大小写**
150
+ 的同一目录,`split(WS)` 会漏掉全局根(如 `<VibeMath 根>/Formal/Lib`)的绝对路径——语料因此
151
+ **每次运行都变**(临时目录名一变就 diff 一大片)并**泄露本机路径**。真实事故,已修;
152
+ - **时间戳也要归一化**:提示词表头自带 `### YYYY-MM-DD hh:mm:ss|<成员>`,不归一化就**逐次都变**,
153
+ diff 完全失去意义(真实事故:v5 语料里 54 处时间戳)。判据很简单——**连续跑两次,哈希必须相同**;
108
154
  - **随包发布**,作为人工复核提示词正确性的入口——复核者不必去翻会话日志。
109
155
 
110
156
  ### 2.5 每个不变式都要有灵敏度探针
@@ -120,6 +166,14 @@
120
166
  这类变异不能做探针——它会让审计误报"盲点"。
121
167
  - [ ] 探针**不得引入语法错误**:语法错误导致的非零退出同样是"假红"。
122
168
  每条变异都应能被 `node --check` 通过。
169
+ - [ ] 变异必须替换锚点的**全部**出现:`String.prototype.replace` 只替换第一处。同一份契约常在
170
+ 两处发出(例如 v5 的回执契约同时出现在 `replySpec` 与表决提示词里),只改一处时套件
171
+ **合理地保持绿色**——那是**假盲点**,比漏测更误导(会让人去"修"一个本来就是对的不变式)。
172
+ 锚点声明了几次出现,就要替换几次;脚本应对此显式断言。
173
+ - [ ] 守 **persona 静态面**的套件也要有探针,且该套件必须支持"指向副本"的环境变量
174
+ (`audit-persona-surface.test.mjs` 的 `PERSONA_ROOT`):探针变异的是**副本**,
175
+ 套件不读这个变量就永远在跑原始文件、恒为绿(同 §2.5 第二条)。
176
+ 探针脚本还应在开跑前先确认"**未变异**的副本是绿的",否则它探测到的可能是覆盖机制本身。
123
177
  - [ ] 对**不可达**的守卫(设计上互斥、永远不会进入的分支),**不要**留一个永远为绿的探针;
124
178
  要么写行为可观测的等价探针,要么显式删除并在脚本里注明原因。
125
179
 
@@ -150,7 +204,11 @@
150
204
  - [ ] 需求可追溯:方案里列出的工具名、参数名、理念条目,代码里是否都存在。
151
205
  - [ ] 失败路径:看门狗、幂等、崩溃恢复、降级后端、配额、越权。
152
206
  - [ ] 全量回归:**所有**历史套件,且逐个检查退出码(不要用管道截断输出,
153
- 管道会吞掉退出码或造成 EPIPE)。
207
+ 管道会吞掉退出码或造成 EPIPE)。**用 `node run-tests.mjs` 并行跑**(并发 = min(4, 核数)),
208
+ 它会打印每项耗时、wall/sum、加速比与最慢几项——**先看时间再决定策略**,基线见
209
+ [`docs/test-timing.md`](docs/test-timing.md)。若某个套件远慢于基线,先查它是否在等一个
210
+ **永远不会发生的条件**(真实事故:v2 套件 186 s,主因是一次 `tick(1100)` 嵌在
211
+ "从不提前退出"的 16 次循环里)。
154
212
  - [ ] 发布产物自证:不是"publish 退出 0"就算完成——要从 registry 取回 tarball,
155
213
  核对 shasum、逐字节比对插件、确认修复标记存在、并在**已发布包内**跑一遍套件。
156
214
 
package/README.md CHANGED
@@ -230,6 +230,95 @@ flowchart TB
230
230
 
231
231
  ---
232
232
 
233
+ ## 🧮 Lean 形式化验证(四个架构共用,可调开关)
234
+
235
+ **它改变的不是"更严格一点",而是审查对象本身。** m 个代理一致认为"这是对的"仍然是**共识**——
236
+ 排除不了共同误解;Lean 通过是**机器核对**。于是剩下的唯一不确定项缩小为一个人能有效审查的问题:
237
+
238
+ > **Lean 代码里的定义 / 对象 / 条件 / 假设 / 结论,是否与命题原文完全一致?**
239
+
240
+ | | 原验证工作 | 形式化通过后的验证工作 |
241
+ |---|---|---|
242
+ | 审查对象 | 命题本身(推导是否正确) | **忠实性**:Lean 代码 ↔ 命题原文是否一致 |
243
+ | 结论强度 | 共识(可能共同出错) | 严格(内核已检查),前提是忠实性成立 |
244
+ | 副产品 | 无 | 可复用的 Lean 定义 / 引理库 |
245
+
246
+ ### 开关:`formalVerify`(四个架构同名,默认 `'off'`)
247
+
248
+ | 取值 | 含义 |
249
+ |---|---|
250
+ | **`'off'`(默认)** | **不额外进行任何要求。** 提示词里不出现任何 Lean 内容,验证流程与门禁完全不变(是**真正的无操作**) |
251
+ | `'encourage'` | **鼓励但不强制**:验证时先判断该对象的**实现难度**,能在可接受工作量内形式化就优先做;一旦 Lean 通过,审查重心转为**忠实性**。平时工作也鼓励把常用/可能复用的对象、假设、新定义随手形式化归档。**不设门禁** |
252
+ | `'require'` | **强制**:真/假结论必须满足「**Lean 已通过**」或「**显式记录了阻塞原因**」,否则本次裁定**不生效**——记为未定论(原因 `formal-required`)、写入「形式化待办」、群聊公告,对象留库待形式化后重新提议 |
253
+
254
+ > `require` 里的「显式记录阻塞原因」正是**"根据实现难度决定不做"**的落点:**决定权在代理,
255
+ > 但决定必须说出来、可审计**,不允许静默跳过。相关参数还有 `leanCommand`(默认 `lean`)、
256
+ > `leanArgs`(配合 `lake env lean`)、`leanTimeoutMs`(默认 120s)。
257
+
258
+ ### ⚠️ 忠实性缺陷 ≠ 命题为假(重要)
259
+
260
+ Lean 通过只保证"这段代码过了内核",**不保证它说的就是命题想说的**。所以当表决者逐条核对后
261
+ 发现 Lean 代码与命题原文不一致(写窄了 / 写宽了 / 换了对象 / 漏了条件)时:
262
+
263
+ - **不得投 0**。投 0 的含义是"**该命题为假**";一个写错的形式化会让框架把"形式化不合格"
264
+ 记成"命题被证伪",在 v5 的全 0 一致规则下甚至会把命题写进 `Verified/` 标注**假**——
265
+ 用来求真的机制反而**伪造出一个错误的否定结论**。
266
+ - 正确做法:给一个严格介于 0 与 1 之间的值(记为弃权)+ 用回执
267
+ `formal:{decision:'defect', note:'<具体偏差>'}` 记录偏差。框架随即**撤回这条证明的「已通过」状态**
268
+ (降级为 `attempted`、撤回 `Verified/Lean/<id>.lean`、写入「形式化待办」),`require` 档下
269
+ **本次裁定不定论**;修正形式化并重新跑通后再投票。
270
+ - 只有表决者**独立于这份 Lean 代码**也能确定命题为假(并能给出独立理由)时才投 0。
271
+
272
+ > 注入提示词的另外三条硬要求(契约 §6):工具名一律**全称**(`<prefix>lean_archive` 不是
273
+ > `lean_archive`——缩写不是注册名,代理照抄会调用一个不存在的工具);归档可复用定义/引理**前先跑通**,
274
+ > 跑不通不许进库;**工具链缺失**(`LEAN_NOT_FOUND`)时把代码写下来归档并在 `note` 写明
275
+ > "宿主无 Lean 工具链"——这算显式阻塞原因,门禁据此放行,不会因为装不了 Lean 而卡死。
276
+
277
+ ### 归档:形式化代码放哪里
278
+
279
+ ```
280
+ <VibeMath 根>/
281
+ ├─ Formal/ # ★ 跨项目可复用库(四个架构共用)
282
+ │ ├─ Lib/<name>.lean # 可复用定义 / 对象 / 假设(def / structure / notation)
283
+ │ ├─ Lib/Index.md # 名称 → 文件 → 类别 → 摘要(写新定义前先查这里)
284
+ │ ├─ Proved/<name>.lean # 已成立的 Lean 命题 / 引理(机器已核对)
285
+ │ └─ Proved/Index.md
286
+ └─ Projects/<项目>/ # (v5 为 Projects/<项目>/Institutes/<所>/)
287
+ ├─ Formal/
288
+ │ ├─ <对象id>.lean # 该对象的形式化工作文件
289
+ │ ├─ Index.md # 对象 → 状态 → 文件 → 归档证明 → 运行结果 → 难度判断
290
+ │ └─ TODO.md # require 模式下的「形式化待办」
291
+ └─ Verified/
292
+ ├─ <原有定论卡片>
293
+ └─ Lean/<对象id>.lean # ★ 归档证明:该定论对象对应的形式化代码
294
+ ```
295
+
296
+ ### 工具(每个架构三个,前缀跟随各自命名)
297
+
298
+ | 工具 | 作用 |
299
+ |---|---|
300
+ | `<prefix>_lean_run` | 在宿主 `subprocess` 服务上执行 Lean,返回 `{ok, exitCode, ms, stdout, stderr}`。**绝不抛异常**:缺工具链 → `LEAN_NOT_FOUND`,超时 → `LEAN_TIMEOUT`,路径越界 → 拒绝 |
301
+ | `<prefix>_lean_archive` | `kind='def'/'lemma'` → 归档到**跨项目** `Formal/Lib` 或 `Formal/Proved`;`kind='proof'` → 写 `Formal/<target>.lean`,运行通过则同时写 **`Verified/Lean/<target>.lean`** 并标记该对象为 Lean 通过;`kind='blocked'` → 记录显式难度判断/阻塞原因(**原因必填**) |
302
+ | `<prefix>_lean_lib` | 重建并返回三处索引与逐对象形式化状态——**写新定义前先查重、直接复用** |
303
+
304
+ 例如 v5 是 `vibe_v5_lean_run` / `vibe_v5_lean_archive` / `vibe_v5_lean_lib`,v2/v3 是 `vibe_math_lean_*`,v4 是 `vibe_v4_lean_*`。
305
+
306
+ **边界(有意为之)**:框架**不内置 Lean**(不装工具链、不下载依赖;工具链缺失时优雅降级并如实记录);
307
+ 框架**不判断忠实性**(那是代理/人审查并投票的对象,框架只负责把审查焦点**换成**忠实性);
308
+ **Lean 通过 ≠ 命题为真**——它只表示"这段形式化代码通过了内核检查"。
309
+
310
+ 完整契约(参数、路径、状态迁移、提示词语义、门禁位置、索引格式、测试要求)见
311
+ [`docs/formal-verification.md`](docs/formal-verification.md)。
312
+
313
+ > **四个预设的 persona(主代理收到的提示词)都完整列出了上面三个工具与四个参数**,
314
+ > 并且 `prefix` 与 `text` 两个块逐行一致(只允许第 0 行不同)。这一层由
315
+ > [`audit-persona-surface.test.mjs`](audit-persona-surface.test.mjs) 与
316
+ > [`audit-persona-sensitivity.mjs`](audit-persona-sensitivity.mjs) 守护——加入本特性时正是
317
+ > 在四个预设里发现了"工具已注册、persona 从未列出"的缺陷(同批还发现 persona 少列了两条
318
+ > 增删常驻研究员的工具、`/v4`/`/v5` 的子命令列表与实现不一致;详见随包发布说明)。
319
+
320
+ ---
321
+
233
322
  ## 🚀 安装
234
323
 
235
324
  两种安装方式,任选其一(也可并存):
@@ -422,6 +511,10 @@ v5 的完整架构(含成员生命周期、一轮时序、共识状态机、
422
511
  └─ <研究所>.v5state.json # 仅当宿主缺 sessionProjections 时的回退权威源
423
512
  ```
424
513
 
514
+ > 启用 Lean 形式化验证时另有两个目录:本所 `Formal/`(工作文件 + 索引 + 形式化待办)与 `Verified/Lean/`
515
+ > (**归档证明**),以及**跨项目**的 `<VibeMath根>/Formal/{Lib,Proved}/`(可复用定义与已证引理)——详见
516
+ > 上方「Lean 形式化验证」一节。
517
+
425
518
  **v5 铁律**:① 权威状态在**会话日志的 host-only 投影单元**(键 `vibeMathV5`)里,上表中除
426
519
  `State/<研究所>.v5state.json`(降级回退)之外的一切文件都只是**镜像/工作区**,手工改坏不会破坏研究所;
427
520
  ② 成员**只写自己的库**(`Members/<自己的代号>/`),但可以读任何人的库;
@@ -609,6 +702,10 @@ v5 的完整架构(含成员生命周期、一轮时序、共识状态机、
609
702
  | `tickIntervalMs` | 2000 | 调度器心跳间隔(毫秒) |
610
703
  | `activityLogCap` | 100 | 活动日志保留条数(report 最多显示 30 条) |
611
704
  | `maxExplorerRetries` | 3 | explorer 拆方向失败的重派生上限 |
705
+ | `formalVerify` | `'off'` | **Lean 形式化验证开关**:`'off'` 不额外要求(默认)|`'encourage'` 鼓励(验证时按实现难度自行决定是否形式化)|`'require'` 强制(真/假结论必须先有「Lean 通过」或显式阻塞记录,否则记为未定论并进入形式化待办)。非法值一律回退 `'off'` |
706
+ | `leanCommand` | `'lean'` | 要执行的 Lean 可执行文件(例:`'lake'`) |
707
+ | `leanArgs` | `[]` | 插在文件名之前的附加参数(例:`['env','lean']` 配合 `leanCommand='lake'`) |
708
+ | `leanTimeoutMs` | `120000` | 单次 Lean 运行的上限(毫秒) |
612
709
 
613
710
  ### v3(论文式 md + 规划代理 + 方法库)默认值
614
711
 
@@ -629,6 +726,10 @@ v5 的完整架构(含成员生命周期、一轮时序、共识状态机、
629
726
  | `indexAutoRebuild` | true | 每次写盘后自动重建 `State/index.json`(false = 手动 `vibe_math_index`) |
630
727
  | `projectLockTimeoutMs` | 60000 | 项目锁等待超时(同项目同一时刻只允许一个会话调度) |
631
728
  | `methodKeeperPersona` | 空 | 注入方法整理代理提示词开头的人格/要求 |
729
+ | `formalVerify` | `'off'` | **Lean 形式化验证开关**:`'off'` 不额外要求(默认)|`'encourage'` 鼓励(验证时按实现难度自行决定是否形式化)|`'require'` 强制(真/假结论必须先有「Lean 通过」或显式阻塞记录,否则记为未定论并进入形式化待办)。非法值一律回退 `'off'` |
730
+ | `leanCommand` | `'lean'` | 要执行的 Lean 可执行文件(例:`'lake'`) |
731
+ | `leanArgs` | `[]` | 插在文件名之前的附加参数(例:`['env','lean']` 配合 `leanCommand='lake'`) |
732
+ | `leanTimeoutMs` | `120000` | 单次 Lean 运行的上限(毫秒) |
632
733
 
633
734
  ### v4(常驻自组织 · 实验)默认值
634
735
 
@@ -647,6 +748,10 @@ v5 的完整架构(含成员生命周期、一轮时序、共识状态机、
647
748
  | `provider` / `model` | 空 | **常驻 LLM 路由**(空 = 常驻继承主代理的 provider/model;此前声明未用,v1.4.1 真正接入) |
648
749
  | `residentPersona` | 空 | 注入每个常驻提示词开头的人格/要求 |
649
750
  | `toolAllow` / `toolDeny` | `[]` | **常驻工具权限**(经 `startContinuable` 的 `toolFilter` 做作用域 `tools.restrict()`;空 = 继承全部工具;⚠️ 空 `allow:[]` 会拒绝一切工具) |
751
+ | `formalVerify` | `'off'` | **Lean 形式化验证开关**:`'off'` 不额外要求(默认)|`'encourage'` 鼓励(验证时按实现难度自行决定是否形式化)|`'require'` 强制(真/假结论必须先有「Lean 通过」或显式阻塞记录,否则记为未定论并进入形式化待办)。非法值一律回退 `'off'` |
752
+ | `leanCommand` | `'lean'` | 要执行的 Lean 可执行文件(例:`'lake'`) |
753
+ | `leanArgs` | `[]` | 插在文件名之前的附加参数(例:`['env','lean']` 配合 `leanCommand='lake'`) |
754
+ | `leanTimeoutMs` | `120000` | 单次 Lean 运行的上限(毫秒) |
650
755
 
651
756
  ### v5(研究所体系 · 实验)默认值
652
757
 
@@ -674,8 +779,12 @@ v5 的完整架构(含成员生命周期、一轮时序、共识状态机、
674
779
  | `toolAllow` / `toolDeny` | `[]` | 常驻员工工具权限(⚠️ 空 `allow:[]` 会拒绝一切工具) |
675
780
  | `tempToolAllow` / `tempToolDeny` | `[]` | 临时工的工具权限(比常驻更窄) |
676
781
  | `staffPersona` | 空 | 追加到每个成员章程前的人格/要求 |
782
+ | `formalVerify` | `'off'` | **Lean 形式化验证开关**:`'off'` 不额外要求(默认)|`'encourage'` 鼓励(验证时按实现难度自行决定是否形式化)|`'require'` 强制(真/假结论必须先有「Lean 通过」或显式阻塞记录,否则记为未定论并进入形式化待办)。非法值一律回退 `'off'` |
783
+ | `leanCommand` | `'lean'` | 要执行的 Lean 可执行文件(例:`'lake'`) |
784
+ | `leanArgs` | `[]` | 插在文件名之前的附加参数(例:`['env','lean']` 配合 `leanCommand='lake'`) |
785
+ | `leanTimeoutMs` | `120000` | 单次 Lean 运行的上限(毫秒) |
677
786
 
678
- 常用控制:`vibe_v5_configure`(先配置)→ `vibe_v5_start`(开工)→ `vibe_v5_report` / `vibe_v5_status`;`vibe_v5_message` / `vibe_v5_meeting` / `vibe_v5_members` / `vibe_v5_hire` / `vibe_v5_fire` / `vibe_v5_pause` / `vibe_v5_resume` / `vibe_v5_stop`;斜杠命令 `/v5`。
787
+ 常用控制:`vibe_v5_configure`(先配置)→ `vibe_v5_start`(开工)→ `vibe_v5_report` / `vibe_v5_status`;`vibe_v5_message` / `vibe_v5_meeting` / `vibe_v5_members` / `vibe_v5_hire` / `vibe_v5_fire`(临时工)/ `vibe_v5_add_researcher` / `vibe_v5_remove_researcher`(增删常驻,仅所办)/ `vibe_v5_pause` / `vibe_v5_resume` / `vibe_v5_stop`;斜杠命令 `/v5`。
679
788
 
680
789
  ---
681
790
 
@@ -694,6 +803,11 @@ v5 的完整架构(含成员生命周期、一轮时序、共识状态机、
694
803
  - **v4(常驻自组织)**:[`vibe-math-v4/实现方案.md`](vibe-math-v4/实现方案.md)
695
804
  - **v5(研究所体系)**:[`vibe-math-v5/实现方案.md`](vibe-math-v5/实现方案.md)(文字规格)· [`vibe-math-v5/架构图.md`](vibe-math-v5/架构图.md)(全套架构图)
696
805
  - **v5 提示词与交互语料**:[`prompt-corpus-v5/prompt-corpus-v5.md`](prompt-corpus-v5/prompt-corpus-v5.md)(框架真正发出的每一条提示词原文,可直接人工复核身份/编制/交互署名是否正确)
806
+ - **四套 Lean 提示词语料**:[`prompt-corpus-v2/formal-verify-v2.md`](prompt-corpus-v2/formal-verify-v2.md) · [`prompt-corpus-v3/formal-verify-v3.md`](prompt-corpus-v3/formal-verify-v3.md) · [`prompt-corpus-v4/formal-verify-v4.md`](prompt-corpus-v4/formal-verify-v4.md)(各自覆盖 off / encourage / **require** / 忠实性分支 / 工作轮 / 回执契约;工作区归一化为 `<WS>`、VibeMath 根为 `<VIBEMATH>`)
807
+ - **四个预设的 persona 原文**:[`prompt-corpus-persona/persona-corpus.md`](prompt-corpus-persona/persona-corpus.md)(主代理实际收到的提示词:有哪些工具、哪些参数、哪些斜杠子命令;由 `audit-persona-surface.test.mjs` 生成,随包发布)
808
+ - **Lean 形式化验证(四架构共用契约)**:[`docs/formal-verification.md`](docs/formal-verification.md)
809
+ - **测试耗时基线与并行跑法**:[`docs/test-timing.md`](docs/test-timing.md)(`node run-tests.mjs` 并行跑全部套件 ≈1.9 min;探针脚本 ≈2.6 min;每个 runner 都会打印耗时/加速比供下次选策略)
810
+ - **静态提示词面一致性(persona ↔ 工具注册表 ↔ 斜杠命令 hint/usage)**:[`audit-persona-surface.test.mjs`](audit-persona-surface.test.mjs)(197 条断言,并生成 [`prompt-corpus-persona/persona-corpus.md`](prompt-corpus-persona/persona-corpus.md) 供人工复核)+ [`audit-persona-sensitivity.mjs`](audit-persona-sensitivity.mjs)(11 条灵敏度探针)——守"注册的工具必须在 persona 里出现 / persona 里的名字必须真的注册 / `prefix` 与 `text` 两块逐行一致 / hint、usage、实际分支三处必须一致"
697
811
  - **全面检查必查清单**:[`AUDIT-CHECKLIST.md`](AUDIT-CHECKLIST.md)(本仓库的强制审计流程)
698
812
 
699
813
  ---
@@ -728,6 +842,10 @@ v5 的完整架构(含成员生命周期、一轮时序、共识状态机、
728
842
  - **成员章程是入职快照**:升级本包不会改写已在跑的研究所里成员的章程(它们仍用入职时冻结的版本)。
729
843
  需要新章程就在新会话里重开一个研究所;投影状态与文件树无需迁移。
730
844
  - **安装器行为同 v2**(版本化自动更新,`vibe-math-v5` 目录同样受管)。
845
+ - **Lean 形式化需要宿主上有 Lean 工具链**:框架不内置、不下载;没有工具链时三个 Lean 工具会如实返回
846
+ `LEAN_NOT_FOUND`,形式化代码仍可写下来归档,但无法执行验证。
847
+ - **`require` 模式的门禁是「搁置」而不是「卡死」**:缺形式化的真/假结论会被记为未定论 + 进入形式化待办,
848
+ 研究所继续推进(与「未达门槛留库附平均概率」同一取舍),不会被一个对象永久卡住。
731
849
 
732
850
  ---
733
851
 
@@ -0,0 +1,207 @@
1
+ # dsh-vibe-math 2.3.0 — 四个架构新增可调控的 Lean 形式化验证
2
+
3
+ > 上一版:2.2.2。本版为 **v2 / v3 / v4 / v5 四个架构**各新增同一个**可调控参数**与配套机制。
4
+
5
+ ---
6
+
7
+ ## 0. 这个参数解决什么问题
8
+
9
+ 多代理交叉验证的本质是**共识**:m 个代理一致认为"这是对的",既排除不了共同误解,
10
+ 也排除不了共同漏掉的情形。Lean 形式化把"我认为"换成"机器已核对",于是
11
+
12
+ > **一旦形式化代码通过,剩下的唯一不确定项就缩小为:Lean 代码里的定义 / 对象 / 条件 / 假设 / 结论,
13
+ > 是否与命题原文完全一致?**
14
+
15
+ 这个问题人(和代理)是能有效审查的,而"这个证明对不对"交给内核。所以这个参数改变的
16
+ **不是"更严格一点",而是审查对象本身**:
17
+
18
+ | | 原验证工作 | 形式化通过后的验证工作 |
19
+ |---|---|---|
20
+ | 审查对象 | 命题本身(推导是否正确) | **忠实性**:Lean 代码 ↔ 命题原文是否一致 |
21
+ | 结论强度 | 共识(可能共同出错) | 严格(内核已检查),前提是忠实性成立 |
22
+ | 副产品 | 无 | 可复用的 Lean 定义 / 引理库 |
23
+
24
+ ---
25
+
26
+ ## 1. 参数:`formalVerify`(四个架构同名同语义,默认 `'off'`)
27
+
28
+ | 取值 | 含义 |
29
+ |---|---|
30
+ | **`'off'`(默认)** | **不额外进行任何要求。** 提示词里不出现任何 Lean 内容,验证流程与门禁完全不变。**这是真正的无操作**,并且有专门的测试与灵敏度探针守着这一点(`formalOn` 被改成恒真时套件必须变红) |
31
+ | `'encourage'` | **鼓励但不强制**:验证时先判断该对象的**实现难度**,能在可接受工作量内形式化就优先做;一旦 Lean 通过,投票提示词明确告诉表决者"**你不需要重新检查推导**,你的任务是**忠实性审查**"。平时工作也鼓励把常用/可能复用的对象、假设、新定义随手形式化归档。**不设门禁** |
32
+ | `'require'` | **强制**:真/假结论必须满足「**Lean 已通过**」或「**显式记录了阻塞原因**」,否则本次裁定**不生效**——记为未定论(原因 `formal-required`)、写入「形式化待办」、公告全所,对象留库待形式化后重新提议。门禁落在**写 Verified 卡片的唯一收口点** |
33
+
34
+ 配套参数:`leanCommand`(默认 `'lean'`;配合 `leanArgs` 可做 `lake env lean`)、`leanArgs`(默认 `[]`)、
35
+ `leanTimeoutMs`(默认 `120000`)。
36
+
37
+ **非法值一律回退 `'off'`,绝不回退到更强的档位**——一个拼写错误若静默启用强制形式化,
38
+ 会让所有结论被门禁拦下。这条也有专门的断言与探针。
39
+
40
+ ### 关于「强制」的准确含义
41
+
42
+ `require` 强制的是**"必须做出并记录判断"**,不是"必须成功形式化":
43
+
44
+ - 形式化成功 → 走忠实性审查;
45
+ - 判断不值得/做不到 → 必须用 `kind='blocked'` 写下**原因**(`note` 必填),据此放行。
46
+
47
+ 也就是说:**"根据实现难度决定是否用 Lean"的决定权在代理,但决定必须显式、可审计,
48
+ 不允许静默跳过。** 这正是需求里那三个调控方向的落点。
49
+
50
+ ---
51
+
52
+ ## 2. 归档:形式化代码放在哪里
53
+
54
+ ```
55
+ <VibeMath 根>/
56
+ ├─ Formal/ # ★ 跨项目可复用库(四套共用同一份布局)
57
+ │ ├─ Lib/<name>.lean # 可复用定义 / 对象 / 假设
58
+ │ ├─ Lib/Index.md # 名称 → 文件 → 类别 → 摘要(写新定义前先查)
59
+ │ ├─ Proved/<name>.lean # 已成立的 Lean 命题 / 引理(机器已核对)
60
+ │ └─ Proved/Index.md
61
+ └─ Projects/<项目>/ # (v5 为 Projects/<项目>/Institutes/<所>/)
62
+ ├─ Formal/
63
+ │ ├─ <对象id>.lean # 该对象的形式化工作文件
64
+ │ ├─ Index.md # 对象 → 状态 → 文件 → 归档证明 → 运行结果 → 难度判断
65
+ │ └─ TODO.md # require 档下的「形式化待办」
66
+ └─ Verified/
67
+ ├─ <原有定论卡片> # 卡片上多一行 `- 形式化: <状态>`
68
+ └─ Lean/<对象id>.lean # ★ 归档证明:该定论对象对应的形式化代码
69
+ ```
70
+
71
+ **可复用的东西放全局**(跨项目复用是这套设计的核心收益),**证明与定论卡片放在一起**
72
+ (一眼可见"这条结论的证明在哪")。也因此 Lean 路径守卫的边界是 **VibeMath 根**而不是项目根:
73
+ 爬出项目但仍在 VibeMath 内是合法的,那正是全局库所在——而爬出 VibeMath 会被拒绝
74
+ (用**词法归一化**判断,不是字符串前缀,所以 `..` 穿越拦得住;这一点也有探针)。
75
+
76
+ ---
77
+
78
+ ## 3. 工具(每个架构三个,前缀跟随各自命名)
79
+
80
+ | 工具 | 作用 |
81
+ |---|---|
82
+ | `…_lean_run` | 在宿主 `subprocess` 服务上执行 Lean,返回 `{ok, exitCode, ms, command, stdout, stderr}`。**绝不抛异常到调度循环**:缺 `subprocess` → `NO_SUBPROCESS`,解析不到可执行文件 → `LEAN_NOT_FOUND`,非零退出 → `LEAN_FAILED`,超时 → `LEAN_TIMEOUT`(并 `terminate()`),路径越界 → 拒绝 |
83
+ | `…_lean_archive` | `kind='def'/'lemma'` → 归档到**跨项目** `Formal/Lib` 或 `Formal/Proved`;`kind='proof'` → 写 `Formal/<target>.lean`,运行通过则同时写 **`Verified/Lean/<target>.lean`** 并把对象标为 Lean 通过;`kind='blocked'` → 记录显式难度判断/阻塞原因(**原因空则拒绝**) |
84
+ | `…_lean_lib` | 重建并返回三处索引与逐对象形式化状态——**写新定义前先查重、直接复用** |
85
+
86
+ 前缀:v2/v3 → `vibe_math_lean_*`;v4 → `vibe_v4_lean_*`;v5 → `vibe_v5_lean_*`。
87
+ 三个工具**无条件注册**(注册是静态的,与既有 `ctx.effect` 纪律一致);`off` 档只是不主动告诉成员它们存在。
88
+
89
+ 另有回执通道 `"formal": {"target","decision":"used|blocked","file","note"}`:
90
+ 一个从不调用 Lean 工具的成员仍然可以(也必须在 `require` 档下)给出难度判断。
91
+
92
+ ---
93
+
94
+ ## 4. 各架构的实现落点(细节见各自 `实现方案.md`)
95
+
96
+ | | v2 | v3 | v4 | v5 |
97
+ |---|---|---|---|---|
98
+ | 状态存放 | `VibeMath_State/formal.json` | `State/formal.json` | `<项目>/State/formal.json` | **会话日志投影单元**(新事件 `vibe5/formal`) |
99
+ | 门禁收口点 | `writeVerifiedCardIfNeeded` + 问题收口(两处) | `writeVerifiedCardIfChanged`(唯一写卡点)+ 判定入口前置 | `finalizeVerify`(`closeVerify` 之前) | `continueVerifyRound`(`closeVerify` 之前) |
100
+ | 提示词注入 | `verifierReviewPrompt` / `verifierDebatePrompt` + solver 提示词 | 同上 + Method Keeper(沉淀可复用 Lean) | `verifyPrompt` + 常规/心跳/coreRules | `verifyPrompt` + 常规/心跳轮 + 状态块 `[形式化]` 行 |
101
+ | 可视化 | `status`/`report` | `status`/`report` + `Logs/报告.md` | `status`/`report` + `vibe_v4_formal_report` | `status().formal` + `report()` 的 Lean 小节 |
102
+ | 额外 | — | v3 的卡片刻意保持 **off 档字节不变**(新增锚点行只在非 off 且有记录时写) | 新增 `vibe_v4_prompts`(把"某成员会收到的确切提示词"作为可审计面) | `vibe_v5_overview` 增加形式化小节 |
103
+
104
+ **四套完全一致的语义**:默认 off 无操作、未知档位回退 off、通过后转忠实性审查、
105
+ `require` 门禁搁置而非卡死、阻塞原因必填、证明归档到 `Verified/Lean/`、
106
+ 可复用定义归档到跨项目 `Formal/Lib`、路径守卫词法归一。
107
+
108
+ 共用契约:[`docs/formal-verification.md`](docs/formal-verification.md)。
109
+
110
+ ---
111
+
112
+ ## 5. persona 静态提示词面:本次审计新发现的一整类缺陷(已修)
113
+
114
+ 给四套加工具时暴露了一类**此前没有审计维度**的缺陷——不是运行时发出的提示词(§1.1–1.5 守的
115
+ 那一层),而是 `agent.cordis.yml` 里 **persona 行本身**。persona 是主代理收到的**唯一**一份
116
+ "有哪些工具、能调哪些参数"的清单;而**所有 e2e 套件都直接 `apply(ctx)`,从不加载 YAML**,
117
+ 所以这一层对既有 4000+ 条断言完全盲。发现的真实缺陷:
118
+
119
+ | # | 缺陷 | 后果 |
120
+ |---|---|---|
121
+ | 1 | **v2 / v3 / v4 的 persona 从未列出**三个 `*_lean_*` 工具(只有 v5 列了,尽管它们**无条件注册**) | 主代理**不知道这个能力存在**,连准确名字都猜不到;用户在 v2/v3/v4 上无法指挥形式化 |
122
+ | 2 | v4 的 `vibe_v4_set {…}` 参数表漏了 `formalVerify`/`leanCommand`/`leanArgs`/`leanTimeoutMs` | 开关**不可发现**(工具 schema 里有、prompt 里没有) |
123
+ | 3 | v3 的 persona 从未列出 `vibe_math_setup` / `vibe_math_save_settings` / `vibe_math_template`(v2 列了) | 三个主控工具不可发现 |
124
+ | 4 | v4 的 persona 从未列出 `vibe_v4_prompts`("把成员会收到的确切提示词读出来"的审计工具) | 恰恰是审计提示词最需要的工具被藏起来了 |
125
+ | 5 | v5 的 persona 写了 `hire`/`fire`(临时工),却没写 `add_researcher`/`remove_researcher`(常驻),而它同时声称"所办握有增聘常驻的权力" | 权力存在但工具不可发现 |
126
+ | 6 | v5 的 `prefix` 与 `text` 两个块**漂移**:同一句在 `prefix` 里是 `... are`、在 `text` 里是 `... is` | 旧宿主读 `text`、新宿主读 `prefix`,同一版本对不同宿主呈现不同文字 |
127
+ | 7 | v4 的命令**失败提示** `usage` 长期列着 `message` 子命令,而处理器**没有** `message` 分支(`usage` 把自己再列一遍) | 用户按提示输入 `/v4 message …` 得到"未知子命令",而错误信息本身又说它存在。**这是复发**:同一个文件的 `/v4 set` 在更早一轮修过一次,但当时没留下"三处表面必须一致"的守卫 |
128
+ | 8 | v5 的 persona `/v5` 子命令列表漏了 `add` / `remove`(处理器实现了、`hint` 也列了);v4 的 `/v4` 列表漏了 `message` | 人读 prompt 与人读 hint 不一致 |
129
+
130
+ **新增 `audit-persona-surface.test.mjs`(197 条断言)**,把这一层变成硬约束:
131
+
132
+ - **双向**一致性:注册的每个工具必须在 persona 里出现(未文档化者必须进**显式快照**,
133
+ 新增工具会被迫做出"写进 prompt 还是明确不进"的决定);persona 里每个 `vibe_*` 名字必须真的注册
134
+ (反向检查抓改名/拼错/幽灵工具;`name*` 通配写法允许);
135
+ - `prefix` 与 `text` **逐行一致,只允许第 0 行不同**(防宿主间漂移);
136
+ - Lean 面在**两个块**里都齐全:三个工具名、四个参数名、三个档位名逐字出现、
137
+ 忠实性语义、`Formal/Lib` / `Formal/Proved` / `Verified/Lean` 路径;
138
+ - **斜杠命令四处一致**:`hint` ⊆ 实际分支、实际分支 ⊆ `hint`(`hint` 用 `...` 表示非穷举时除外)、
139
+ 失败 `usage` 串与分支集合**完全相等**、persona 的 `/vN` 列表与 `hint` 一致;
140
+ - 与共享契约 `docs/formal-verification.md` 交叉核对(契约里漏写参数/档位/路径同样变红)。
141
+
142
+ **新增 `audit-persona-sensitivity.mjs`(11 条探针)**证明上面这套断言真的会变红,
143
+ 并遵守既有四条防假绿纪律:开跑前先确认**未变异**的副本经由 `PERSONA_ROOT` 是绿的
144
+ (否则探针探测到的可能是覆盖机制本身);变异副本若损坏 persona 的 YAML 块结构判 SETUP-FAIL;
145
+ `.js` 变异副本先过 `node --check`;锚点出现次数不符判 SETUP-FAIL。
146
+
147
+ `AUDIT-CHECKLIST.md` 因此新增 **§1.6「静态提示词面:人设 ↔ 注册表」**,把这一类列为
148
+ 每次全面检查的必查项——本类的教训与 v2.1.0 的"身份错乱"同源:**审计维度漏了一整类,
149
+ 而不是某一行写错了**。
150
+
151
+ 同时新增**随包发布**的人工复核语料 [`prompt-corpus-persona/persona-corpus.md`](prompt-corpus-persona/persona-corpus.md)
152
+ (+ `.json`):四个预设的主代理实际收到的 persona 原文、注册工具数、斜杠命令 hint 一览,
153
+ 由 `audit-persona-surface.test.mjs` 每次运行时确定性重写——复核者不必去翻 YAML。
154
+
155
+ ---
156
+
157
+ ## 6. 测试与审计
158
+
159
+ | 套件 | 断言 |
160
+ |---|---|
161
+ | `formal-verify-v2.test.mjs` | **177** |
162
+ | `formal-verify-v3.test.mjs` | **189**(另导出 `prompt-corpus-v3/` 交互语料) |
163
+ | `formal-verify-v4.test.mjs` | **144** |
164
+ | `formal-verify-v5.test.mjs` | **88** |
165
+
166
+ 四套都用**注入的 `subprocess` 服务**做"假 Lean"(退出 0,除非文件里还有 `sorry` 或 `-- FAIL`),
167
+ 因此**不需要真的安装 Lean** 就能把整条路径(`resolveExecutable` → `spawn` → `collected.stdout` →
168
+ 退出码 → 归档 → 提示词切换 → 门禁)测到。四套都支持插件覆盖环境变量(`V2_PLUGIN` / `V3_PLUGIN` /
169
+ `V4_PLUGIN` / `V5_PLUGIN`)——这是灵敏度探针能生效的前提。
170
+
171
+ **新增 `audit-formal-sensitivity.mjs`**:33 个探针(v2 9 / v3 8 / v4 8 / v5 9 中的实际数目见运行输出),
172
+ 每个都故意打破一条不变式并要求**对应架构的套件变红**。脚本本身防住了四种"假绿":
173
+ 探针自身启动失败、套件不读覆盖变量、变异语义惰性、变异引入语法错误(每个变异副本都先过 `node --check`,
174
+ 语法错误直接判 SETUP-FAIL,绝不当作"探测成功")。
175
+
176
+ `prompt-v5-integrity.test.mjs` 另加了一组用例,把 Lean 相关提示词原文写进**随包发布的语料**
177
+ (`lean-work` / `lean-verify` / `lean-fidelity`),供人工复核"忠实性审查"那段的措辞;
178
+ v5 的架构图(`示例图/框架图-v5.svg`)也新增了 Lean 形式化区块。
179
+
180
+ `audit-v5-integrity.mjs` 的理念门禁从 31 条扩到 **48 条**,其中 17 条专守这个特性。
181
+
182
+ **新增 `audit-persona-surface.test.mjs`(197 条断言)** 与 **`audit-persona-sensitivity.mjs`(11 条探针)**:
183
+ 见 §5。它们守的是**静态提示词面**(persona ↔ 注册表 ↔ 斜杠命令 hint/usage),是本次审计新开的一个维度;
184
+ 套件同时生成随包发布的人工复核语料 `prompt-corpus-persona/`。
185
+
186
+ ---
187
+
188
+ ## 7. 边界(有意为之)
189
+
190
+ - **框架不内置 Lean**:不装工具链、不下载依赖。没有工具链时三个工具如实返回 `LEAN_NOT_FOUND`,
191
+ 形式化代码仍可写下来归档,但无法执行验证(不会崩、不会假装通过)。
192
+ - **框架不判断忠实性**:那是代理/人审查并投票的对象;框架只负责把审查焦点**换成**忠实性。
193
+ - **Lean 通过 ≠ 命题为真**:它只表示"这段形式化代码通过了内核检查"。这正是 §0 表格里
194
+ "审查对象变化"的含义。
195
+ - **`require` 是"搁置"而不是"卡死"**:缺形式化的裁定记为未定论 + 进入待办,研究所继续推进
196
+ (与既有的"未达门槛留库附平均概率"同一取舍),不会被一个对象永久卡住。
197
+
198
+ ---
199
+
200
+ ## 8. 升级
201
+
202
+ ```
203
+ npm i dsh-vibe-math@latest
204
+ ```
205
+
206
+ 无迁移:新参数默认 `off`,四套的既有行为与 `off` 完全一致(v3 的卡片刻意保持字节不变)。
207
+ 已经在跑的研究所/项目不受影响;把 `formalVerify` 调到 `encourage` 或 `require` 即启用。
@@ -0,0 +1,134 @@
1
+ # dsh-vibe-math 2.3.1 — 提示词与交互修复:忠实性缺陷不再被记成"命题为假"
2
+
3
+ > 上一版:2.3.0(四个架构新增 Lean 形式化验证)。本版是**审计驱动的修复版**:
4
+ > 2.3.0 的功能是对的,但**代理读到的文字**与**回执通道**里有几处会造成错误结论的缺陷。
5
+ > 发布前对"运行时注入的 Lean 提示词 + 回执通道 + 语料"做了一次专项审计,本版修掉全部发现。
6
+
7
+ ---
8
+
9
+ ## 0. 最严重的一条:形式化写错了 ≠ 命题为假
10
+
11
+ 2.3.0 的忠实性分支写的是:
12
+
13
+ ```
14
+ ▸ 因此请把 verdict 用在**忠实性**上:一致 → 1;发现任何偏离 → 0(或按不确定度给中间值并说明)。
15
+ ```
16
+
17
+ 当 Lean 代码写的不是命题想说的(把条件写窄了 / 写宽了 / 换了对象 / 漏了条件)时,这条指令让表决者
18
+ 投 **0**——而 0 的含义是"**该命题为假**"。于是:
19
+
20
+ - 框架把"形式化不合格"记成"命题被证伪";
21
+ - 在 v5 的**全 0 一致**规则(或 v4 的全组一致规则)下,一个写错的形式化会把命题
22
+ **写进 `Verified/` 并标注「假」**;
23
+ - 也就是说,**为了求真更严格而引入的机制,反而伪造出一个错误的否定结论**。
24
+
25
+ 本版把它改成独立的一档 `defect`(契约 §4.1):
26
+
27
+ | | 2.3.0 | 2.3.1 |
28
+ |---|---|---|
29
+ | 发现忠实性偏差 | 投 0(= 命题为假) | **不得投 0**:给严格介于 0 与 1 之间的值(记为弃权)+ 回执 `formal:{decision:'defect', note:'<具体偏差>'}` |
30
+ | 框架动作 | 按"假"参与定论 | **撤回「已通过」**:降级 `attempted`、清空 `proof`、撤回归档证明、写入「形式化待办」、公告 |
31
+ | `require` 档 | 门禁已放行(`passed`) | 门禁**重新拦住**:本次裁定**不定论**,修正形式化并重新跑通后再投票 |
32
+ | 什么时候才能投 0 | 发现偏差就投 | **只有独立于这份 Lean 代码也能确定命题为假**(并给出独立理由)时 |
33
+
34
+ > `encourage` 档没有门禁:框架仍然撤回证明并记入待办,但**不在提示词里承诺一个它无法强制的
35
+ > "不定论"**——那里靠表决者按指令给出的弃权使表决得不出布尔一致结论。(这条区分本身也是审计发现的:
36
+ > 首版草稿在两种档位下都声称"本次裁定不定论",而 `encourage` 档根本没有门禁。)
37
+
38
+ ---
39
+
40
+ ## 1. 本版修掉的缺陷(按严重度)
41
+
42
+ | # | 缺陷 | 影响 | 落点 |
43
+ |---|---|---|---|
44
+ | 1 | **v2 的 `formal` 回执通道是死代码**:提示词让代理"在回执的 formal 字段写明难度判断",但 v2 的两份验证回执契约里**没有**这个字段,框架也**从不解析**它 | 代理写下的难度判断**静默消失**;`require` 档下代理以为记录了阻塞,门禁却一直拦着 | 补齐 `formalJsonField` / `formalReplyNote` / `absorbFormalFromReply`,并接进初评 + 辩论两条路径 |
45
+ | 2 | **忠实性缺陷被判成"命题为假"**(四个架构) | 可能伪造出错误的否定结论(见 §0) | 新增 `defect` 档(四套) |
46
+ | 3 | **字段名写错**:v2/v3 的 Lean 段说"并据此给出 verdict",但这两套的回执字段是 `Result` | 代理回 `{"verdict":…}` 时**那一票被静默丢弃**(默认 0.5) | 忠实性分支改写为 `Result`(v3 还补上了缺失的"偏差怎么映射"指引) |
47
+ | 4 | **缩写工具名**:注入文本里出现 `lean_lib` / `lean_archive`(v2/v3/v5,**包括工具自己返回的 `hint`**) | 照抄的代理调用一个**不存在的工具** | 全部改为注册名全称 `<prefix>lean_*` |
48
+ | 5 | **没有"归档前先跑通"的要求** | 不编译的定义/引理会污染跨项目复用库 | 提示词明确:`run=true` 或先 `lean_run`,跑不通不许入库 |
49
+ | 6 | **工具链缺失没有出路** | 宿主没装 Lean 时,`require` 档代理可能反复空转 | 提示词明确:`LEAN_NOT_FOUND` 时把代码归档并在 `note` 写明"宿主无 Lean 工具链",算显式阻塞原因 |
50
+ | 7 | **语料不是确定性产物**:v5 的路径归一化在 Windows 下因**大小写**差异(`split(WS)` 匹配不上)漏掉了 VibeMath 根的绝对路径,且提示词表头自带 `### YYYY-MM-DD hh:mm:ss|<成员>` **时间戳** | 随包语料每跑一次都变(上一次提交里的语料改动就纯粹来自临时目录改名)、泄露本机路径、diff 失去意义 | `scrub` 改为大小写/分隔符无关,并把时间戳归一化为 `<TIME>`——现在**逐字节稳定**(已实测两次运行的 SHA256 相同) |
51
+ | 8 | **v2/v4 没有 Lean 提示词语料;`require` 档文本不在任何语料里** | 复核者只能翻源码;门禁那段话从没被人读过 | 四套各自新增 `prompt-corpus-vN/`,覆盖 off/encourage/**require**/忠实性/工作轮/回执契约 |
52
+ | 9 | **v2 套件的回执断言只查措辞**("提示词里有那句话") | 177 条断言全绿却守着一个**死通道** | 改为**行为断言**:把带 `formal` 的回执真的喂给框架,断言记录落库 |
53
+ | 10 | 套件里"占位垃圾"扫描用了裸 `\bundefined\b` | 把 v2 explorer 提示词里合法的英文 "no undefined symbols" 误报为垃圾 | 改为只匹配**数据位**的垃圾(`: undefined` / `"undefined"` / `undefined,` …) |
54
+
55
+ > 第 1、9 条是同一件事的两面:**提示词说了、框架没做、测试只查措辞**——这类缺陷在任何只断言
56
+ > "包含某些关键词"的套件里都是隐形的(`AUDIT-CHECKLIST.md` §2.2 早就点过名)。
57
+
58
+ ---
59
+
60
+ ## 2. 契约与文档同步
61
+
62
+ - `docs/formal-verification.md`:新增 **§4.1 `defect`**(含状态迁移与"唯一可以投 0 的情形")、
63
+ §6 顶部新增 **5 条提示词硬要求**、§6.1 忠实性分支改写、§6.3 回执契约加 `defect` 与"必须真的被解析",
64
+ §10 新增测试要求 8–11(行为断言 / 忠实性语义断言 / 每架构语料 + 归一化 / 提示词探针)。
65
+ - `README.md`:Lean 章节新增「⚠️ 忠实性缺陷 ≠ 命题为假」,并把三条硬要求写进正文。
66
+ - 各 `实现方案.md`:v2 / v3 / v4 / v5 都补了 `defect` 语义、工具名全称、归档前跑通、工具链缺失出路,
67
+ 以及各自的断言数与语料说明。
68
+ - `AUDIT-CHECKLIST.md` §1.6 静态提示词面 + §2.5 探针纪律:本版新增的 16 条**提示词探针**正是按它执行。
69
+
70
+ ---
71
+
72
+ ## 3. 测试与探针(本版实测)
73
+
74
+ | 套件 | 2.3.0 | 2.3.1 |
75
+ |---|---|---|
76
+ | `formal-verify-v2.test.mjs` | 177 | **261**(含 `defect` 双向 id 降级、回执通道行为断言、语料 89 条) |
77
+ | `formal-verify-v3.test.mjs` | 189 | **247** |
78
+ | `formal-verify-v4.test.mjs` | 144 | **226** |
79
+ | `formal-verify-v5.test.mjs` | 88 | **120** |
80
+ | `prompt-v5-integrity.test.mjs` | 563 | **588**(语料 70 条 / 27 类,新增 `lean-require`、`lean-after-defect`) |
81
+ | `audit-formal-sensitivity.mjs` | 33 探针 | **49 探针**(新增 16 条提示词探针:删掉"不要投 0"、把工具名换成缩写、删掉 `require` 门禁措辞、把回执契约里的 `defect` 去掉——四套各 4 条) |
82
+ | `audit-persona-sensitivity.mjs` | 11 探针 | 11 探针(不变,全红) |
83
+ | `audit-persona-surface.test.mjs` | 197 断言 | 197 断言(persona 未改,仍全绿) |
84
+
85
+ 四套现在都**自带**随包发布的人工复核语料:
86
+
87
+ ```
88
+ prompt-corpus-v2/formal-verify-v2.{json,md} # 89 条
89
+ prompt-corpus-v3/formal-verify-v3.{json,md}
90
+ prompt-corpus-v4/formal-verify-v4.{json,md}
91
+ prompt-corpus-v5/prompt-corpus-v5.md # 70 条 / 27 类
92
+ prompt-corpus-persona/persona-corpus.md # 四个预设的 persona 原文
93
+ ```
94
+
95
+ 语料里的工作区路径归一化为 `<WS>`、VibeMath 根归一化为 `<VIBEMATH>`,可 diff、不含本机路径。
96
+
97
+ ---
98
+
99
+ ## 3.5 测试执行提速:并行 runner + 耗时反馈(本版新增)
100
+
101
+ 这轮顺带做了一次"测试脚本自己有多慢"的审计,结论是**时间几乎全花在等待上,而不是在测东西**:
102
+
103
+ | | 优化前 | 优化后 | 手段 |
104
+ |---|---|---|---|
105
+ | 探针脚本 `audit-formal-sensitivity.mjs`(49 条) | **38 min**(串行) | **2.6 min**(wall 154.6 s,sum 612 s,**x3.96**) | ① 探针并行(并发 4,每个探针独立变异副本 + 独立语料目录,互不干扰);② 修掉 v2 套件的 186 s(见下) |
106
+ | 全量回归(23 个套件) | ≈ 5.5 min(串行) | **1.9 min**(wall 114.4 s,sum 219.4 s,**x1.92**) | 新增 **`run-tests.mjs`**:并行跑全部套件并打印每项耗时、wall/sum、加速比、最慢几项 |
107
+ | `formal-verify-v2.test.mjs` 单套件 | **186 s** | **≈32 s** | 两处根因:① 插件用 `setInterval(...,1000)` 轮询调度器,套件每次 `tick()` 都得等满 1 秒——套件现在**只把 `setInterval` 快进到 25 ms**(自己的 `sleep` 用 `setTimeout`,不受影响;插件内部"该不该 tick"仍按真实 200 ms 下限判断,**生产代码零改动**);② `verifyWithDebate` 的 16 次循环**从不提前退出**(判据 `autoDone` 之类的条件永远不会发生),每次调用白烧 ~21 s——现在按"连续 3 轮没有新 followup"提前退出。断言数不变(261) |
108
+ | `e2e-v4-fixes.test.mjs` | 105 s | 101 s | 12 个轮询循环加了"安静即停"(原判据 `autoDone‖running===false` 对活着的 run 永不成立)。**再往下压就要砍采样深度**:9 个慢用例(T13/T19/T22/T23/T25/T27/T2/T9/T20)是在观察"多轮之后某指令**没有**泄漏/重复",轮数就是它们的不变式本体 |
109
+
110
+ **耗时基线写进了 [`docs/test-timing.md`](docs/test-timing.md)**:单套件耗时表、并行安全性(语料目录必须
111
+ 逐实例隔离)、以及"按目的选最小代价组合"的策略表。两个 runner 每次都会打印耗时与加速比——
112
+ **下次跑之前先看这几行**,再决定并发数、要不要 `--only`、以及某个变慢的套件是不是又在等一个
113
+ 永远不会发生的条件。
114
+
115
+ ---
116
+
117
+ ## 4. 兼容性与迁移
118
+
119
+ 无破坏性变更,**不需要迁移**:
120
+
121
+ - 默认仍是 `formalVerify: 'off'`(真正的无操作),行为与 2.3.0 逐字节一致;
122
+ - `defect` 是**新增**的回执取值;已有代理若仍回 `"decision":"used"|"blocked"` 一切照旧;
123
+ - 提示词里的工具名由缩写改为全称,只会让**照抄的调用**从失败变为成功;
124
+ - 归档路径、门禁位置、三个工具、四个参数**都没有变**。
125
+
126
+ ---
127
+
128
+ ## 5. 升级
129
+
130
+ ```
131
+ npm i dsh-vibe-math@latest
132
+ ```
133
+
134
+ 升级后重启 DSH:未被手动改过的 preset 文件会自动更新;语言/提示词层面的变化在新会话生效。