dsh-vibe-math 2.2.2 → 2.3.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 (36) hide show
  1. package/AUDIT-CHECKLIST.md +28 -0
  2. package/README.md +98 -1
  3. package/RELEASE-NOTES-2.3.0.md +207 -0
  4. package/audit-formal-sensitivity.mjs +247 -0
  5. package/audit-persona-sensitivity.mjs +249 -0
  6. package/audit-persona-surface.test.mjs +349 -0
  7. package/audit-v5-integrity.mjs +40 -1
  8. package/audit-v5-sensitivity.mjs +77 -6
  9. package/docs/formal-verification.md +321 -0
  10. package/docs/generate_framework_diagram_v5.mjs +22 -16
  11. package/formal-verify-v2.test.mjs +672 -0
  12. package/formal-verify-v3.test.mjs +824 -0
  13. package/formal-verify-v4.test.mjs +603 -0
  14. package/formal-verify-v5.test.mjs +526 -0
  15. package/package.json +15 -2
  16. package/prompt-corpus-persona/persona-corpus.json +32 -0
  17. package/prompt-corpus-persona/persona-corpus.md +674 -0
  18. package/prompt-corpus-v3/formal-verify-v3.json +280 -0
  19. package/prompt-corpus-v3/formal-verify-v3.md +2826 -0
  20. package/prompt-corpus-v5/prompt-corpus-v5.json +75 -9
  21. package/prompt-corpus-v5/prompt-corpus-v5.md +384 -65
  22. package/prompt-v5-integrity.test.mjs +111 -10
  23. package/vibe-math-v2/agent.cordis.yml +40 -2
  24. package/vibe-math-v2/vibe-math-v2.js +627 -19
  25. package/vibe-math-v2//345/256/236/347/216/260/346/226/271/346/241/210.md +145 -1
  26. package/vibe-math-v3/agent.cordis.yml +46 -2
  27. package/vibe-math-v3/vibe-math-v3.js +749 -21
  28. package/vibe-math-v3//345/256/236/347/216/260/346/226/271/346/241/210.md +87 -2
  29. package/vibe-math-v4/agent.cordis.yml +46 -4
  30. package/vibe-math-v4/vibe-math-v4.js +652 -15
  31. package/vibe-math-v4//345/256/236/347/216/260/346/226/271/346/241/210.md +226 -0
  32. package/vibe-math-v5/agent.cordis.yml +41 -5
  33. package/vibe-math-v5/vibe-math-v5.js +562 -9
  34. package/vibe-math-v5//345/256/236/347/216/260/346/226/271/346/241/210.md +108 -4
  35. package/vibe-math-v5//346/236/266/346/236/204/345/233/276.md +57 -0
  36. package//347/244/272/344/276/213/345/233/276//346/241/206/346/236/266/345/233/276-v5.svg +51 -46
@@ -0,0 +1,321 @@
1
+ # Lean 形式化验证(v2 / v3 / v4 / v5 共用设计)
2
+
3
+ > 本文件是四个架构**共同遵守的契约**。每个预设都在自己的单文件插件里独立实现同一套语义
4
+ > (四个预设之间零依赖、零共享模块,这是本项目的既有约定)。
5
+ > 参数、路径、工具名、提示词语义、门禁规则、索引格式都必须与本文件一致。
6
+
7
+ ---
8
+
9
+ ## 0. 为什么要有它
10
+
11
+ 多代理交叉验证的本质是**共识**,不是**证明**:m 个代理一致认为"这是对的",
12
+ 既不能排除共同误解,也不能排除共同漏掉的情形。Lean 形式化把"我认为"换成"机器已核对":
13
+ 一旦形式化代码通过,剩下的**唯一**不确定项就缩小为
14
+
15
+ > **Lean 代码里的定义、对象、条件、假设、结论,是否与命题原文完全一致?**
16
+
17
+ 这个问题人(和代理)是能有效审查的,而"这个证明对不对"交给内核。于是验证工作的性质发生变化:
18
+
19
+ | | 原验证工作 | 启用形式化后的验证工作 |
20
+ |---|---|---|
21
+ | 审查对象 | 命题本身(推导是否正确) | **忠实性**:Lean 代码 ↔ 命题原文是否一致 |
22
+ | 结论强度 | 共识(可能共同出错) | 严格(内核已检查),前提是忠实性成立 |
23
+ | 副产品 | 无 | 可复用的 Lean 定义/引理库 |
24
+
25
+ ---
26
+
27
+ ## 1. 参数(四个架构同名同语义)
28
+
29
+ | 参数 | 取值 | 默认 | 含义 |
30
+ |---|---|---|---|
31
+ | `formalVerify` | `'off'` \| `'encourage'` \| `'require'` | `'off'` | 三档开关,见 §2 |
32
+ | `leanCommand` | 字符串 | `'lean'` | 要执行的 Lean 可执行文件(例:`'lake'`) |
33
+ | `leanArgs` | 字符串数组 | `[]` | 插在文件名之前的附加参数(例:`['env','lean']` 配合 `leanCommand='lake'`) |
34
+ | `leanTimeoutMs` | 正整数 | `120000` | 单次 Lean 运行的超时上限 |
35
+
36
+ - 非法值一律**回退到默认**(`formalVerify` 非三档之一 → `'off'`;`leanTimeoutMs` 非正 → 默认)。
37
+ - 参数必须出现在该架构既有的参数体系里:`set_params` / `vibe_v4_set` / `vibe_v5_set`、
38
+ 参数 schema(`*_setup` / `*_template`)、`status`/`report` 的可读参数表。
39
+ - **模式是动态的**,可以在运行中切换:所有与模式相关的提示词文本都必须在**构造提示词的那一刻**
40
+ 由 `params.formalVerify` 现算,**不得**写进"入职时冻结"的人格/章程快照
41
+ (否则切换模式后成员读到的仍是旧指令)。
42
+
43
+ ---
44
+
45
+ ## 2. 三档语义
46
+
47
+ ### `off`(默认)—— 不额外进行任何要求
48
+
49
+ - 提示词里**不出现**任何 Lean 相关内容;验证流程、门禁、归档全部不变。
50
+ - 三个 Lean 工具**仍然注册**(注册是静态的,与既有 `ctx.effect` 纪律一致),
51
+ 但框架不会告诉代理它们存在;代理/人主动调用时它们照常工作。
52
+
53
+ ### `encourage` —— 鼓励但不强制
54
+
55
+ 注入到提示词里的要求:
56
+
57
+ 1. **验证时**:先判断该对象的**实现难度**;若能在可接受的工作量内形式化,优先写 Lean 代码并执行。
58
+ 一旦 Lean 通过,**你唯一需要确认的就是忠实性**(定义/对象/条件/假设/结论是否与命题原文一致),
59
+ 请把注意力放在这种逐条核对上,而不是重新做一遍推导。
60
+ 2. **平时工作时**:把常用或可能复用的对象/假设/新定义随手用 Lean 形式化定义,
61
+ 归档到全局可复用库,方便后续证明直接复用。
62
+ 3. 若判断不值得/无法形式化,可以不做——但**鼓励**在回执里写明难度判断(会记入索引)。
63
+
64
+ **不设门禁**:即使没有任何 Lean 产物,验证照常收口(与 `off` 相同的结论)。
65
+
66
+ ### `require` —— 强制上述要求
67
+
68
+ 与 `encourage` 相同的注入文本,但语气为"必须",并且**加门禁**:
69
+
70
+ > 一个对象要被判定为 **真**(严格证明)或 **假**(严格反驳),必须满足
71
+ > `formal.status ∈ {'passed', 'blocked'}`;
72
+ > 否则本次裁定**不生效**——框架把它记为 `undecided`(原因 `formal-required`),
73
+ > 写入「形式化待办」,并在群聊公告;对象留在原库,可形式化后再次提议。
74
+
75
+ - `passed`:有 Lean 产物且最近一次运行 `exitCode === 0`;
76
+ - `blocked`:代理给出了**显式的难度判断/阻塞原因**(`note` 非空)。
77
+ **这就是"根据实现难度决定是否通过 Lean"的落点**:决定权在代理,但决定必须显式、可审计,
78
+ 不允许静默跳过。
79
+ - 门禁是**兜底**而非唯一手段:`require` 模式下的验证提示词会先告知表决者
80
+ "定论前需要 `passed` 或 `blocked`,请先做形式化或记录阻塞原因",所以正常情况下不会触发门禁。
81
+
82
+ **为什么用 `undecided` 而不是"卡住不动"**:卡住会让研究所永久停在一个对象上;
83
+ 记为 `undecided` + 待办既保住了"未经形式化不得称为严格结论",又保证了系统可继续推进
84
+ (与既有"未达门槛留库附平均概率"的设计一致)。
85
+
86
+ ---
87
+
88
+ ## 3. 路径布局
89
+
90
+ ```
91
+ <VibeMath 根>/
92
+ ├─ Formal/ # 全局可复用 Lean 库(跨项目)
93
+ │ ├─ Lib/<name>.lean # 可复用定义/对象/假设(def / structure / notation)
94
+ │ ├─ Lib/Index.md # 名称 → 文件 → 类别 → 摘要
95
+ │ ├─ Proved/<name>.lean # 已成立的 Lean 命题/引理(机器已核对)
96
+ │ └─ Proved/Index.md # 名称 → 文件 → 陈述 → 依赖
97
+ └─ Projects/<项目>/ # (v5 为 Projects/<项目>/Institutes/<所>/)
98
+ ├─ Formal/
99
+ │ ├─ <对象id>.lean # 该对象的形式化工作文件
100
+ │ ├─ Index.md # 对象 → 状态 → 文件 → 归档证明 → 运行结果 → 难度判断
101
+ │ └─ TODO.md # require 模式下的「形式化待办」
102
+ └─ Verified/
103
+ ├─ <原有定论卡片>
104
+ └─ Lean/<对象id>.lean # ★ 归档证明:该定论对象对应的形式化代码
105
+ ```
106
+
107
+ - **归档证明放在 `Verified/Lean/<id>.lean`**:它和定论卡片同处 `Verified/`,
108
+ 一眼可见"这条结论的形式化证明在哪"。
109
+ - **可复用的东西放全局 `Formal/Lib` 与 `Formal/Proved`**:跨项目复用是这套设计的核心收益。
110
+ - 文件 id 一律过**该架构既有的 id 安全化函数**(去分隔符、去 `..`),防止路径穿越。
111
+ - `lean_run` 只接受位于 `<VibeMath 根>` 之内的路径;越界一律拒绝(`V5_INVALID_ARGUMENT` 或该架构对应错误)。
112
+
113
+ ---
114
+
115
+ ## 4. 对象的形式化状态(`formal`)
116
+
117
+ 每个可验证对象(命题/问题/子问题/方法卡)都带一个形式化记录:
118
+
119
+ ```jsonc
120
+ {
121
+ "status": "none" | "attempted" | "passed" | "blocked",
122
+ "file": "Formal/p-1.lean", // 工作文件(可为空)
123
+ "proof": "Verified/Lean/p-1.lean",// 归档证明(仅 passed)
124
+ "decision": "used" | "blocked", // 代理的显式难度判断
125
+ "note": "…", // blocked 时必填:难度判断 / 阻塞原因
126
+ "run": { "at": 0, "ok": true, "exitCode": 0, "ms": 0, "stdoutTail": "", "stderrTail": "" },
127
+ "updatedAt": 0
128
+ }
129
+ ```
130
+
131
+ 状态迁移:
132
+
133
+ | 事件 | 迁移 |
134
+ |---|---|
135
+ | `lean_run` 成功 | `none`/`attempted` → `attempted`(记录运行结果) |
136
+ | `lean_run` 失败 | `none` → `attempted`(记录失败输出,供代理修复) |
137
+ | `lean_archive{kinds:'proof', target, from|content}` + 该文件最近一次运行 `ok` | → `passed`,写 `Verified/Lean/<id>.lean` |
138
+ | `lean_archive{kinds:'blocked', target, note}` | → `blocked`(`note` 必填) |
139
+ | 回执里 `formal:{target, decision:'blocked', note}` | → `blocked` |
140
+ | 回执里 `formal:{target, decision:'used', file}` | → `attempted`(记录文件) |
141
+
142
+ ---
143
+
144
+ ## 5. 工具(每个架构三个,前缀各自不同)
145
+
146
+ 前缀:v2/v3 → `vibe_math_`;v4 → `vibe_v4_`;v5 → `vibe_v5_`。
147
+
148
+ ### 5.1 `<prefix>lean_run`
149
+
150
+ | 参数 | 类型 | 必填 | 说明 |
151
+ |---|---|---|---|
152
+ | `file` | string | ✅ | 相对 `<VibeMath 根>` 或项目根的 `.lean` 路径 |
153
+ | `target` | string | | 关联对象 id(给了就更新该对象的运行记录) |
154
+ | `timeout_ms` | integer | | 覆盖 `leanTimeoutMs` |
155
+
156
+ 返回:`{ok, exitCode, signal, ms, command, stdout, stderr, file}`;
157
+ 找不到工具链返回 `{ok:false, code:'LEAN_NOT_FOUND', error}`;超时返回 `{ok:false, code:'LEAN_TIMEOUT'}`。
158
+ **绝不抛异常到调度循环**——任何失败都要变成可读结果并记录。
159
+
160
+ ### 5.2 `<prefix>lean_archive`
161
+
162
+ 一个工具覆盖三种归档(`kind` 区分):
163
+
164
+ | `kind` | 必填 | 行为 |
165
+ |---|---|---|
166
+ | `'def'` / `'lemma'` | `name`, `content` 或 `from` | 写入全局 `Formal/Lib/<name>.lean`(def)或 `Formal/Proved/<name>.lean`(lemma),重建对应 `Index.md`;可选 `run:true` 先跑一次再归档 |
167
+ | `'proof'` | `target`, `content` 或 `from` | 写入 `Formal/<target>.lean`;若该文件最近一次运行 `ok`,同时写 `Verified/Lean/<target>.lean` 并把对象标为 `passed` |
168
+ | `'blocked'` | `target`, `note` | 记录显式难度判断/阻塞原因(`note` 空 → 拒绝),对象标为 `blocked` |
169
+
170
+ ### 5.3 `<prefix>lean_lib`
171
+
172
+ 无必填参数。**扫描并重建**三处索引(项目 `Formal/Index.md`、全局 `Lib/Index.md`、`Proved/Index.md`),
173
+ 返回可复用库清单(供代理写新定义前先查重、直接复用)。`refresh:false` 时只读不重建。
174
+
175
+ ---
176
+
177
+ ## 6. 提示词注入(在构造提示词时现算)
178
+
179
+ ### 6.1 验证提示词
180
+
181
+ `encourage`:
182
+
183
+ ```
184
+ 【Lean 形式化验证(鼓励模式)】
185
+ · 请先判断该对象的**实现难度**:若能在可接受的工作量内形式化,优先用 Lean 写形式化代码并执行。
186
+ · 工具:<prefix>lean_run(执行)· <prefix>lean_archive(归档)· <prefix>lean_lib(查已有可复用库)
187
+ · 工作目录:<项目根>/Formal/(可复用定义放 <VibeMath 根>/Formal/Lib/,已证引理放 Formal/Proved/)
188
+ · **一旦 Lean 通过,你唯一需要确认的就是忠实性**:Lean 代码里的定义/对象/条件/假设/结论
189
+ 是否与命题原文逐条一致。请把注意力放在这种核对上,而不是重新做一遍推导。
190
+ · 若判断不值得或无法形式化,可以不做,但请在回执的 formal 字段写明难度判断。
191
+ ```
192
+
193
+ `require`:同样内容,但"可以不做"改为"**必须**产出 Lean 形式化,或**必须**给出显式的阻塞原因",
194
+ 并附加:
195
+
196
+ ```
197
+ · 本模式下定论门禁:对象必须先达到 形式化已通过 或 已记录阻塞原因,否则本次裁定记为未定论
198
+ (原因 formal-required)并进入「形式化待办」。
199
+ ```
200
+
201
+ **门禁提示(两种模式都加,只要模式非 off)**:如果该对象**已经** `formal.status === 'passed'`,
202
+ 验证提示词改为强调:
203
+
204
+ ```
205
+ · 该对象已有**通过的 Lean 形式化证明**(<proof 路径>)。因此你不需要重新检查推导;
206
+ 你的任务是**忠实性审查**:逐条核对定义/对象/条件/假设/结论是否与命题原文一致,
207
+ 并据此给出 verdict。
208
+ ```
209
+
210
+ ### 6.2 平时工作提示词(solver / explorer / 常驻 / method-keeper 等)
211
+
212
+ ```
213
+ 【顺手形式化(<模式>)】把你工作中常用或可能复用的对象、假设、新定义,
214
+ 用 Lean 形式化定义并归档到全局可复用库(<prefix>lean_archive kind='def'),
215
+ 已成立的引理归到 Formal/Proved/(kind='lemma');写之前先 <prefix>lean_lib 查重,避免重复定义。
216
+ ```
217
+
218
+ ### 6.3 回执契约
219
+
220
+ 非 `off` 模式时,在每轮回执契约里加入:
221
+
222
+ ```
223
+ "formal": {"target":"p-x","decision":"used|blocked","file":"Formal/p-x.lean","note":"难度判断/阻塞原因"},
224
+ ```
225
+
226
+ ---
227
+
228
+ ## 7. Run 语义(实现要点)
229
+
230
+ - 用 `subprocess` 服务:`resolveExecutable(leanCommand)` → `spawn({argv:[exe,...leanArgs,file], cwd, stdio:{stdin:'ignore',stdout:{maxBytes},stderr:{maxBytes}}, graceMs})`
231
+ → `await handle.done` → `handle.collected.stdout?.readFrom(0).text`。
232
+ - **必须**给 `cwd`(项目根或 `<VibeMath 根>`),并对超时调用 `handle.terminate()`。
233
+ - 输出截断到 ~4KB 再入库(避免把巨大的编译器输出写进状态)。
234
+ - 宿主没有 `subprocess` 服务 → 返回 `{ok:false, code:'NO_SUBPROCESS'}`,并只记录 `attempted`。
235
+
236
+ ---
237
+
238
+ ## 8. 门禁(`require`)的实现位置
239
+
240
+ **必须在"写 Verified 卡片/判定定论"这唯一的收口点加门禁**,而不是散落在多处:
241
+
242
+ | 架构 | 收口点 |
243
+ |---|---|
244
+ | v2 | `writeVerifiedCardIfNeeded` 及其问题收口分支(`writeVerifiedProblemCardIfNeeded`);另有前置门禁 `formalVerdictDeferred`(在 `settleVerdict` / `processStatusUpdates` 中裁定前调用) |
245
+ | v3 | `writeVerifiedPropositionCardIfNeeded` / `writeVerifiedProblemCardIfNeeded`,以及最后一道闸门 `writeVerifiedCardIfChanged`;另有前置门禁 `formalBlocksConclusion`(在 `settleVerdict` / `processStatusUpdates` 中裁定前调用) |
246
+ | v4 | `finalizeVerify`(紧随其后的 `closeVerify` 之前) |
247
+ | v5 | `continueVerifyRound`(紧随其后的 `closeVerify` 之前;`finalizeUndecided` 不受影响) |
248
+
249
+ 门禁不通过时:把结果记为 `undecided`(原因 `formal-required: …`)、写 `Formal/TODO.md`、
250
+ 群聊公告、**不写** `Verified/` 卡片、不改变对象的既有权重/概率字段。
251
+
252
+ ---
253
+
254
+ ## 9. 索引格式(三份,框架维护)
255
+
256
+ ### 9.1 `<项目>/Formal/Index.md`
257
+
258
+ ```markdown
259
+ # Lean 形式化索引|<项目>
260
+ > 本文件由框架维护(工具调用时增量更新;`<prefix>lean_lib` 会重建)。权威状态在对象记录里。
261
+
262
+ | 对象 | 状态 | 形式化文件 | 归档证明 | 最近运行 | 难度判断 / 阻塞原因 |
263
+ |---|---|---|---|---|---|
264
+ | p-1 | passed | Formal/p-1.lean | Verified/Lean/p-1.lean | ok(exit 0,1.2s) | — |
265
+ | p-2 | blocked | — | — | — | 需要外层解析数论框架,本轮工作量不可接受 |
266
+ | p-3 | attempted | Formal/p-3.lean | — | fail(exit 1,0.8s) | — |
267
+
268
+ ## 形式化待办(require 模式)
269
+ - p-4 —— 尚未形式化(formal-required),定论被搁置
270
+ ```
271
+
272
+ ### 9.2 `<VibeMath 根>/Formal/Lib/Index.md`
273
+
274
+ ```markdown
275
+ # 可复用 Lean 定义库(跨项目)
276
+ | 名称 | 文件 | 类别 | 摘要 | 最近运行 |
277
+ |---|---|---|---|---|
278
+ | ZMod5 | Lib/ZMod5.lean | def | 模 5 剩余类与基本引理 | ok |
279
+ ```
280
+
281
+ ### 9.3 `<VibeMath 根>/Formal/Proved/Index.md`
282
+
283
+ ```markdown
284
+ # 已成立的 Lean 命题 / 引理(机器已核对,可跨项目复用)
285
+ | 名称 | 文件 | 陈述 | 依赖 | 最近运行 |
286
+ |---|---|---|---|---|
287
+ | pell_sq_odd | Proved/pell_sq_odd.lean | … | ZMod5 | ok |
288
+ ```
289
+
290
+ ---
291
+
292
+ ## 10. 测试要求(每个架构都要有)
293
+
294
+ 1. **`off` 是无操作**:提示词里不出现 Lean 字样;验证流程与门禁行为与改动前一致。
295
+ 2. **`encourage` 注入**:验证提示词含鼓励段落;平时工作提示词含"顺手形式化"段落;
296
+ 对象 `passed` 后,验证提示词切换为**忠实性审查**措辞。
297
+ 3. **`require` 门禁**:无形式化记录时"真"结论**不写入 Verified/**,而是 `undecided` +
298
+ `Formal/TODO.md` 记录;补上 `passed` 后重跑可正常写入,且卡片上记录形式化状态;
299
+ `blocked`(`note` 非空)也可放行;`note` 为空则拒绝。
300
+ 4. **工具**:`lean_run` 走注入的 mock subprocess 时能拿到 exitCode/输出并记录;
301
+ `lean_run` 拒绝越界路径;工具链缺失返回 `LEAN_NOT_FOUND` 且不崩;
302
+ `lean_archive` 三种 kind 分别落到正确路径并更新索引;`lean_lib` 能重建索引。
303
+ 5. **参数**:非法值回退;可在运行中切换(切换后新提示词立刻反映新模式)。
304
+ 6. **灵敏度探针**(新增,放进 `audit-formal-sensitivity.mjs`):每条不变式都要有能让对应套件**变红**的变异,
305
+ 且探针必须真的启动套件、真的被套件读取、变异真的改变行为(见 `AUDIT-CHECKLIST.md` §2)。
306
+ 7. **静态提示词面**(放进 `audit-persona-surface.test.mjs`,四个预设一起):三个 Lean 工具名与四个参数名
307
+ 必须出现在**该预设 persona 的 `prefix` 与 `text` 两个块**里,档位名(`'off'`/`'encourage'`/`'require'`)
308
+ 逐字出现,忠实性语义与 `Formal/Lib` / `Formal/Proved` / `Verified/Lean` 路径写清;
309
+ 反向:persona 里的每个 `vibe_*` 名字必须真的注册。`audit-persona-sensitivity.mjs` 用变异副本
310
+ 证明这套断言会变红。**教训**:本特性首版在 v2/v3/v4 上"工具已注册、persona 从未列出",
311
+ 而当时所有既有套件全绿——因为 e2e 套件直接 `apply(ctx)`,从不加载 YAML。
312
+
313
+ ---
314
+
315
+ ## 11. 不做什么(边界)
316
+
317
+ - **不内置 Lean**:本框架不安装工具链、不下载依赖。工具链不存在时优雅降级(记录 `LEAN_NOT_FOUND`)。
318
+ - **不判"忠实性"**:忠实性由代理/人审查并投票决定;框架只负责把审查焦点**换成**忠实性
319
+ (因为证明正确性已由内核保证)。框架不会假装自己能判断 Lean 代码是否对应命题。
320
+ - **不把 Lean 通过等同于"命题为真"**:`passed` 只表示"形式化代码通过内核检查",
321
+ 该代码是否忠实于命题仍需 m 票审查。这正是 §0 表格里"审查对象变化"的含义。
@@ -23,7 +23,7 @@ import { fileURLToPath } from 'node:url'
23
23
  const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..')
24
24
  const OUT = join(ROOT, '示例图', '框架图-v5.svg')
25
25
 
26
- const W = 1720, H = 1116
26
+ const W = 1720, H = 1204
27
27
  const FONT = "'Microsoft YaHei','PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Source Han Sans SC',sans-serif"
28
28
  const MONO = "'Cascadia Mono','Consolas','SFMono-Regular',monospace"
29
29
 
@@ -171,7 +171,7 @@ plain(RX, 536, '所内组织动作(分派 · 优先级 · 督办 · 会议 ·
171
171
  { size: 10.5, fill: C.mute, limit: RW, where: 'house note' })
172
172
 
173
173
  // ---- 框架 ----
174
- band(MAIN_L, 566, MAIN_R - MAIN_L, 286, '框架 vibe-v5 —— 只是媒介(middleware):中继 · 沉淀 · 计数 · 调度',
174
+ band(MAIN_L, 566, MAIN_R - MAIN_L, 382, '框架 vibe-v5 —— 只是媒介(middleware):中继 · 沉淀 · 计数 · 调度',
175
175
  '每轮发「状态块 + 本轮问句」(规章在 persona 里,不进对话);成员回一个 JSON:say / progress / record / verdict / task_* / hire / fire / reject_assign / input / vote_solved',
176
176
  { fill: C.frameBg, stroke: C.frame, titleFill: '#084d80' })
177
177
  const chips = [
@@ -186,15 +186,21 @@ const ccw = (IN_R - IN_L - 2 * 22) / 3
186
186
  chips.forEach((c, i) => {
187
187
  card(IN_L + (i % 3) * (ccw + 22), i < 3 ? 620 : 708, ccw, 78, c, { stroke: C.frame, fs: 12.5, sfs: 10.5 })
188
188
  })
189
- card(IN_L, 796, IN_R - IN_L, 38, [
189
+ card(IN_L, 796, IN_R - IN_L, 76, [
190
+ 'Lean 形式化验证(可调参数 formalVerify = off / encourage / require)',
191
+ 'encourage:验证时按实现难度决定是否形式化;require:真/假结论必须先有「Lean 通过」或显式阻塞记录',
192
+ '★ 一旦 Lean 通过,审查对象就变了:不再是「推导对不对」,而是「Lean 的定义/对象/条件/假设/结论是否忠实于命题原文」',
193
+ '归档:证明 → Verified/Lean/<对象>.lean|可复用定义 → VibeMath/Formal/Lib/|已证引理 → VibeMath/Formal/Proved/',
194
+ ], { stroke: C.gate, fs: 12.5, sfs: 10.5 })
195
+ card(IN_L, 880, IN_R - IN_L, 38, [
190
196
  '调度器优先级:进行中的会议或验证(二者互斥,永不同时)→ 队列中的验证 → 暂存会议 → 已认领/被分派的在办任务(按 activityTimeoutMs 节流)→ 加急邮件 → 群聊摘要 → 停滞自动开会 → 兜底心跳',
191
197
  ], { stroke: C.frame, fs: 11.5 })
192
198
 
193
199
  // ---- 数据面 ----
194
- band(FULL_L, 876, 790, 196, '状态权威源:会话日志的 host-only 投影单元(键 vibeMathV5)',
200
+ band(FULL_L, 964, 790, 196, '状态权威源:会话日志的 host-only 投影单元(键 vibeMathV5)',
195
201
  '副作用只是往会话日志追加事件 —— 不进模型上下文(零 token 成本),checkpoint / restore 交给 DSH',
196
202
  { fill: C.dataBg, stroke: C.data, titleFill: '#125a3c' })
197
- card(62, 932, 360, 124, [
203
+ card(62, 1020, 360, 124, [
198
204
  'applyV5Event(纯折叠,只此一份)',
199
205
  '11 类事件:institute / member / task /',
200
206
  'message / delivered / meeting / debate /',
@@ -202,7 +208,7 @@ card(62, 932, 360, 124, [
202
208
  '未知或损坏事件 → 跳过并记入 diagnostics:',
203
209
  '可用性优先,绝不因一条坏事件卡死全场',
204
210
  ], { stroke: C.data, fs: 12, sfs: 10.5 })
205
- card(434, 932, 374, 124, [
211
+ card(434, 1020, 374, 124, [
206
212
  'checkpoint / restore / resume',
207
213
  '投影随会话日志一起 checkpoint;restore',
208
214
  '时从快照 + 日志尾部重新折叠 → 跨进程与',
@@ -211,10 +217,10 @@ card(434, 932, 374, 124, [
211
217
  '加固 JSON:State/<institute>.v5state.json',
212
218
  ], { stroke: C.data, fs: 12, sfs: 10.5 })
213
219
 
214
- band(852, 876, FULL_R - 852, 196, '文件面:人可读产物(投影之外的一切都只是镜像)',
220
+ band(852, 964, FULL_R - 852, 196, '文件面:人可读产物(投影之外的一切都只是镜像)',
215
221
  '共识的权威在投影;文件是工作区与可读产物,手工改坏不会破坏研究所',
216
222
  { fill: C.dataBg, stroke: C.data, titleFill: '#125a3c' })
217
- card(874, 932, FULL_R - 874 - 22, 124, [
223
+ card(874, 1020, FULL_R - 874 - 22, 124, [
218
224
  'Members/<id>/Progress|Propos|Methods|Subproblems/',
219
225
  '只有本人可写,人人可读(跨读被鼓励)',
220
226
  'Shared/Chat/*.md · Shared/Meetings/<mt-id>.md · Shared/Debates/<obj>.md',
@@ -249,24 +255,24 @@ arrow(556, 400, 578, 400, { color: C.house, dashed: true, width: 1.8, marker: 'b
249
255
  arrow(556, 430, 578, 430, { color: C.house, dashed: true, width: 1.8, marker: 'bothHouse' })
250
256
 
251
257
  // ---- 连线:框架 ↔ 数据面 ----
252
- arrow(400, 852, 400, 876, { color: C.data, marker: 'bothData', width: 2 })
253
- plain(392, 868, 'append / fold / stateOf', { fill: C.data, anchor: 'end', size: 10.5, halo: true })
254
- arrow(1280, 852, 1280, 876, { color: C.data, marker: 'bothData', width: 2 })
255
- plain(1288, 868, '读写产物', { fill: C.data, anchor: 'start', size: 10.5, halo: true })
258
+ arrow(400, 940, 400, 964, { color: C.data, marker: 'bothData', width: 2 })
259
+ plain(392, 956, 'append / fold / stateOf', { fill: C.data, anchor: 'end', size: 10.5, halo: true })
260
+ arrow(1280, 940, 1280, 964, { color: C.data, marker: 'bothData', width: 2 })
261
+ plain(1288, 956, '读写产物', { fill: C.data, anchor: 'start', size: 10.5, halo: true })
256
262
 
257
263
  // ---- 图例 ----
258
- plain(52, 1098, '图例', { size: 12, fill: C.ink, weight: 700 })
264
+ plain(52, 1186, '图例', { size: 12, fill: C.ink, weight: 700 })
259
265
  const legend = [
260
266
  [C.human, '所办 / 人(外部接口,不研究不投票)'],
261
267
  [C.house, '所内成员与所内组织(虚线 = 不由框架执行)'],
262
268
  [C.frame, '框架(中继 / 沉淀 / 计数 / 调度)'],
263
269
  [C.data, '状态与产物'],
264
- [C.gate, '求真门槛(唯一定论规则)'],
270
+ [C.gate, '求真门槛 / Lean 形式化(可调)'],
265
271
  ]
266
272
  legend.forEach(([col, txt], i) => {
267
273
  const x = 108 + i * 330
268
- push(`<rect x="${x}" y="1087" width="14" height="14" rx="3" fill="#ffffff" stroke="${col}" stroke-width="2"/>`)
269
- plain(x + 21, 1099, txt, { size: 11, fill: C.ink2, limit: 305, where: 'legend' })
274
+ push(`<rect x="${x}" y="1175" width="14" height="14" rx="3" fill="#ffffff" stroke="${col}" stroke-width="2"/>`)
275
+ plain(x + 21, 1187, txt, { size: 11, fill: C.ink2, limit: 305, where: 'legend' })
270
276
  })
271
277
 
272
278
  push('</g>')