dsh-vibe-math 2.3.0 → 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.
- package/AUDIT-CHECKLIST.md +33 -3
- package/README.md +21 -0
- package/RELEASE-NOTES-2.3.1.md +134 -0
- package/audit-formal-sensitivity.mjs +125 -39
- package/audit-v5-integrity.mjs +5 -3
- package/docs/formal-verification.md +92 -12
- package/docs/test-timing.md +79 -0
- package/formal-verify-v2.test.mjs +286 -7
- package/formal-verify-v3.test.mjs +215 -8
- package/formal-verify-v4.test.mjs +282 -3
- package/formal-verify-v5.test.mjs +72 -0
- package/package.json +9 -2
- package/prompt-corpus-v2/formal-verify-v2.json +394 -0
- package/prompt-corpus-v2/formal-verify-v2.md +4250 -0
- package/prompt-corpus-v3/formal-verify-v3.json +159 -57
- package/prompt-corpus-v3/formal-verify-v3.md +1302 -285
- package/prompt-corpus-v4/formal-verify-v4.json +84 -0
- package/prompt-corpus-v4/formal-verify-v4.md +255 -0
- package/prompt-corpus-v5/prompt-corpus-v5.json +54 -16
- package/prompt-corpus-v5/prompt-corpus-v5.md +378 -153
- package/prompt-v5-integrity.test.mjs +1158 -1085
- package/run-tests.mjs +99 -0
- package/vibe-math-v2/vibe-math-v2.js +204 -22
- package/vibe-math-v2//345/256/236/347/216/260/346/226/271/346/241/210.md +77 -4
- package/vibe-math-v3/vibe-math-v3.js +82 -21
- package/vibe-math-v3//345/256/236/347/216/260/346/226/271/346/241/210.md +17 -0
- package/vibe-math-v4/vibe-math-v4.js +114 -22
- package/vibe-math-v4//345/256/236/347/216/260/346/226/271/346/241/210.md +29 -0
- package/vibe-math-v5/vibe-math-v5.js +81 -22
- package/vibe-math-v5//345/256/236/347/216/260/346/226/271/346/241/210.md +27 -4
|
@@ -121,8 +121,8 @@
|
|
|
121
121
|
"status": "none" | "attempted" | "passed" | "blocked",
|
|
122
122
|
"file": "Formal/p-1.lean", // 工作文件(可为空)
|
|
123
123
|
"proof": "Verified/Lean/p-1.lean",// 归档证明(仅 passed)
|
|
124
|
-
"decision": "used" | "blocked",
|
|
125
|
-
"note": "…", // blocked 时必填:难度判断 / 阻塞原因
|
|
124
|
+
"decision": "used" | "blocked" | "defect", // 代理的显式判断(defect 见 §4.1)
|
|
125
|
+
"note": "…", // blocked / defect 时必填:难度判断 / 阻塞原因 / 具体偏差
|
|
126
126
|
"run": { "at": 0, "ok": true, "exitCode": 0, "ms": 0, "stdoutTail": "", "stderrTail": "" },
|
|
127
127
|
"updatedAt": 0
|
|
128
128
|
}
|
|
@@ -136,9 +136,35 @@
|
|
|
136
136
|
| `lean_run` 失败 | `none` → `attempted`(记录失败输出,供代理修复) |
|
|
137
137
|
| `lean_archive{kinds:'proof', target, from|content}` + 该文件最近一次运行 `ok` | → `passed`,写 `Verified/Lean/<id>.lean` |
|
|
138
138
|
| `lean_archive{kinds:'blocked', target, note}` | → `blocked`(`note` 必填) |
|
|
139
|
-
| 回执里 `formal:{target, decision:'blocked', note}` | → `blocked` |
|
|
139
|
+
| 回执里 `formal:{target, decision:'blocked', note}` | → `blocked`(`note` 必填) |
|
|
140
|
+
| **回执里 `formal:{target, decision:'defect', note}`** | **撤回 `passed`:→ `attempted`,清空 `proof`、删除 `Verified/Lean/<id>.lean`、把 `note` 写入记录与 `Formal/TODO.md`、公告**(`note` 必填) |
|
|
140
141
|
| 回执里 `formal:{target, decision:'used', file}` | → `attempted`(记录文件) |
|
|
141
142
|
|
|
143
|
+
### 4.1 `defect`:忠实性缺陷**不是**"命题为假"
|
|
144
|
+
|
|
145
|
+
`passed` 只保证"这段 Lean 代码通过了内核检查",**不保证它说的就是命题想说的**。当表决者逐条核对后
|
|
146
|
+
发现 Lean 代码与命题原文不一致(写窄了 / 写宽了 / 换了对象 / 漏了条件…),那是**形式化不合格**,
|
|
147
|
+
不是命题被证伪。两种混淆的后果都很严重:
|
|
148
|
+
|
|
149
|
+
- 若让表决者"发现偏差 → 投 0",框架记下的是"**该命题为假**";在 v5 的全 0 一致规则下,
|
|
150
|
+
一个写错的形式化会直接把命题写进 `Verified/` 并标注**假**——用来求真更严格的机制,
|
|
151
|
+
反而**伪造出一个错误的否定结论**。
|
|
152
|
+
- 若只把偏差记成 `blocked`,门禁会**放行**(`blocked` 本就允许定论),等于带着一个坏形式化去定论。
|
|
153
|
+
|
|
154
|
+
因此 `defect` 是独立的一档,语义固定为:
|
|
155
|
+
|
|
156
|
+
1. **表决者**:不得投 `1` 或 `0`;给一个严格介于 0 与 1 之间的值(记为弃权)并在 `Reason` 里写清偏差;
|
|
157
|
+
同时用回执 `formal:{decision:'defect', note:'<具体偏差>'}` 记录(`note` 必填)。
|
|
158
|
+
2. **框架**:把该对象的形式化记录**降级为 `attempted`**(无论此前是 `passed` 还是 `blocked`——都让位于
|
|
159
|
+
"形式化不合格,需重做")、清空 `proof`、删除 `Verified/Lean/<id>.lean`
|
|
160
|
+
(工作文件 `Formal/<id>.lean` 保留,代码不丢)、`note` 记入记录与 `Formal/TODO.md`、公告。
|
|
161
|
+
3. **`require` 档**:降级后 `formalGateOk` 为假,本次裁定**不定论**,对象进入「形式化待办」——
|
|
162
|
+
修正形式化并重新跑通后再投票。这正是"形式化不合格 ⇒ 重做",而不是"命题为假"。
|
|
163
|
+
`encourage` 档没有门禁,框架**仍然**撤回证明并记入待办,但**不得在提示词里承诺一个它无法强制的
|
|
164
|
+
"不定论"**;那里靠表决者自己的弃权(§6.1 第 ① 条)使表决无法得出布尔一致结论。
|
|
165
|
+
4. **唯一可以投 0 的情形**:表决者**独立于这份 Lean 代码**也能确定命题为假(并能给出独立理由)。
|
|
166
|
+
此时 `Reason` 必须写清独立理由,不得以"Lean 与命题不一致"作为投 0 的依据。
|
|
167
|
+
|
|
142
168
|
---
|
|
143
169
|
|
|
144
170
|
## 5. 工具(每个架构三个,前缀各自不同)
|
|
@@ -176,6 +202,20 @@
|
|
|
176
202
|
|
|
177
203
|
## 6. 提示词注入(在构造提示词时现算)
|
|
178
204
|
|
|
205
|
+
> **硬要求(四套一致,逐字级别的约束)**
|
|
206
|
+
> 1. **工具名一律写全称**(`<prefix>lean_run` / `<prefix>lean_archive` / `<prefix>lean_lib`)。
|
|
207
|
+
> 注入文本里**不得**出现 `lean_run` / `lean_archive` / `lean_lib` 这类缩写——那不是注册名,
|
|
208
|
+
> 代理照抄会调用一个不存在的工具(工具自己返回的 `hint` 字段同样算注入文本)。
|
|
209
|
+
> 2. **回执字段名必须与该架构真实契约一致**:v2/v3 的评审值字段是 `Result`,v4/v5 是 `verdict`。
|
|
210
|
+
> 写错字段名 = 那一票被静默丢弃。
|
|
211
|
+
> 3. **归档可复用定义/引理前必须先跑通**:`<prefix>lean_archive` 支持 `run:true`,
|
|
212
|
+
> 或先 `<prefix>lean_run`。跑不通的代码不得进入 `Formal/Lib` / `Formal/Proved`——
|
|
213
|
+
> 否则"可复用库"会被不编译的定义污染。
|
|
214
|
+
> 4. **工具链缺失时的出路必须写出来**:`LEAN_NOT_FOUND` 时把代码写下来并归档,
|
|
215
|
+
> 在 `note` 里写明"宿主无 Lean 工具链";这算显式阻塞原因,`require` 档可以据此放行,
|
|
216
|
+
> 代理不会因为装不了 Lean 而卡死。
|
|
217
|
+
> 5. **忠实性缺陷不得用 0 表达**(§4.1 第 4 条):只有独立于 Lean 代码也能确定命题为假时才投 0。
|
|
218
|
+
|
|
179
219
|
### 6.1 验证提示词
|
|
180
220
|
|
|
181
221
|
`encourage`:
|
|
@@ -184,10 +224,13 @@
|
|
|
184
224
|
【Lean 形式化验证(鼓励模式)】
|
|
185
225
|
· 请先判断该对象的**实现难度**:若能在可接受的工作量内形式化,优先用 Lean 写形式化代码并执行。
|
|
186
226
|
· 工具:<prefix>lean_run(执行)· <prefix>lean_archive(归档)· <prefix>lean_lib(查已有可复用库)
|
|
187
|
-
· 工作目录:<项目根>/Formal/(可复用定义放 <VibeMath 根>/Formal/Lib/,已证引理放 Formal/Proved/)
|
|
227
|
+
· 工作目录:<项目根>/Formal/(可复用定义放 <VibeMath 根>/Formal/Lib/,已证引理放 <VibeMath 根>/Formal/Proved/)
|
|
188
228
|
· **一旦 Lean 通过,你唯一需要确认的就是忠实性**:Lean 代码里的定义/对象/条件/假设/结论
|
|
189
229
|
是否与命题原文逐条一致。请把注意力放在这种核对上,而不是重新做一遍推导。
|
|
190
230
|
· 若判断不值得或无法形式化,可以不做,但请在回执的 formal 字段写明难度判断。
|
|
231
|
+
· 归档可复用定义/引理前先跑通(<prefix>lean_archive run=true 或先 <prefix>lean_run);跑不通不要入库。
|
|
232
|
+
· 宿主没有 Lean 工具链(LEAN_NOT_FOUND)时:把代码写下来归档,并在会诊/回执的 note 里写明
|
|
233
|
+
"宿主无 Lean 工具链"——这算显式阻塞原因,定论门禁可以据此放行。
|
|
191
234
|
```
|
|
192
235
|
|
|
193
236
|
`require`:同样内容,但"可以不做"改为"**必须**产出 Lean 形式化,或**必须**给出显式的阻塞原因",
|
|
@@ -198,13 +241,21 @@
|
|
|
198
241
|
(原因 formal-required)并进入「形式化待办」。
|
|
199
242
|
```
|
|
200
243
|
|
|
201
|
-
|
|
202
|
-
|
|
244
|
+
**忠实性分支(两种模式都加,只要模式非 off)**:如果该对象**已经** `formal.status === 'passed'`,
|
|
245
|
+
验证提示词把审查对象换成忠实性,并**明确禁止**把偏差写成"假":
|
|
203
246
|
|
|
204
247
|
```
|
|
205
|
-
· 该对象已有**通过的 Lean 形式化证明**(<proof
|
|
206
|
-
|
|
207
|
-
|
|
248
|
+
· 该对象已有**通过的 Lean 形式化证明**(<proof 路径>,最近运行 exit 0)。
|
|
249
|
+
**你不需要重新检查推导**。你的任务是**忠实性审查**:逐条核对 Lean 代码里的
|
|
250
|
+
定义 / 对象 / 条件 / 假设 / 结论是否与命题原文**完全一致**。
|
|
251
|
+
▸ 一致 → 投 <真值 1>。
|
|
252
|
+
▸ **发现任何偏差,不要投 <0>**:偏差只说明**形式化不合格**,不代表命题为假。此时请:
|
|
253
|
+
① 投票给一个严格介于 0 与 1 之间的值(记为弃权),并在理由里写清偏差;
|
|
254
|
+
② 用回执 `formal:{decision:'defect', note:'<具体偏差>'}` 记录它。框架会撤回这条证明的
|
|
255
|
+
「已通过」状态(降级为 attempted、删除归档证明、写入形式化待办);`require` 档下
|
|
256
|
+
本次裁定**不定论**,`encourage` 档**不得**声称框架会强制搁置(那里靠你的弃权阻止定论)。
|
|
257
|
+
修正形式化并重新跑通后再投票。
|
|
258
|
+
▸ 只有当你**独立于这份 Lean 代码**也能确定命题为假时,才投 <0>,并在理由里写清独立理由。
|
|
208
259
|
```
|
|
209
260
|
|
|
210
261
|
### 6.2 平时工作提示词(solver / explorer / 常驻 / method-keeper 等)
|
|
@@ -212,17 +263,25 @@
|
|
|
212
263
|
```
|
|
213
264
|
【顺手形式化(<模式>)】把你工作中常用或可能复用的对象、假设、新定义,
|
|
214
265
|
用 Lean 形式化定义并归档到全局可复用库(<prefix>lean_archive kind='def'),
|
|
215
|
-
已成立的引理归到 Formal/Proved/(kind='lemma');写之前先 <prefix>lean_lib 查重,避免重复定义。
|
|
266
|
+
已成立的引理归到 <VibeMath 根>/Formal/Proved/(kind='lemma');写之前先 <prefix>lean_lib 查重,避免重复定义。
|
|
267
|
+
归档前先跑通(<prefix>lean_run 或 lean_archive run=true):跑不通的定义不要进可复用库。
|
|
216
268
|
```
|
|
217
269
|
|
|
218
270
|
### 6.3 回执契约
|
|
219
271
|
|
|
220
|
-
非 `off`
|
|
272
|
+
非 `off` 模式时,在每轮回执契约里加入(**必须真的被框架解析并落库**——只把字段写进提示词而不实现
|
|
273
|
+
解析,等于让代理的难度判断静默消失;每个架构都必须有"回执 → 记录"的行为断言,不能只断言措辞):
|
|
221
274
|
|
|
222
275
|
```
|
|
223
|
-
"formal": {"target":"p-x","decision":"used|blocked","file":"Formal/p-x.lean","note":"
|
|
276
|
+
"formal": {"target":"p-x","decision":"used|blocked|defect","file":"Formal/p-x.lean","note":"难度判断/阻塞原因/具体偏差"},
|
|
224
277
|
```
|
|
225
278
|
|
|
279
|
+
- `decision='blocked'` 与 `decision='defect'` 时 `note` 必填,否则整条记录被拒绝(返回该架构的
|
|
280
|
+
`*_INVALID_ARGUMENT`)。
|
|
281
|
+
- `decision='defect'` 的落库见 §4.1:**降级 + 删除归档证明 + 写入待办**。
|
|
282
|
+
- 这些字段必须出现在**该架构每一类会被表决者/研究者读到的回执契约**里(v2 的初评与辩论两条路径、
|
|
283
|
+
v3 的初评/辩论/工作轮、v4 的验证与常规/心跳轮、v5 的回执契约与心跳轮)。
|
|
284
|
+
|
|
226
285
|
---
|
|
227
286
|
|
|
228
287
|
## 7. Run 语义(实现要点)
|
|
@@ -309,6 +368,25 @@
|
|
|
309
368
|
反向:persona 里的每个 `vibe_*` 名字必须真的注册。`audit-persona-sensitivity.mjs` 用变异副本
|
|
310
369
|
证明这套断言会变红。**教训**:本特性首版在 v2/v3/v4 上"工具已注册、persona 从未列出",
|
|
311
370
|
而当时所有既有套件全绿——因为 e2e 套件直接 `apply(ctx)`,从不加载 YAML。
|
|
371
|
+
8. **回执通道必须是行为断言,不是措辞断言**(放进各架构的 `formal-verify-vN.test.mjs`):
|
|
372
|
+
构造一条带 `formal:{decision:'blocked'|'defect', note}` 的**代理回执**喂给框架,断言记录真的落库
|
|
373
|
+
(`blocked` → `blocked`;`defect` → `attempted` + `proof` 清空 + 归档文件被删 + 待办条目出现)。
|
|
374
|
+
**教训**:v2 首版只在提示词里写了"请在回执的 formal 字段写明难度判断",框架从不解析它;
|
|
375
|
+
而套件只断言"那句话存在",于是 177 条断言全绿却守着一个**死通道**——这正是
|
|
376
|
+
`AUDIT-CHECKLIST.md` §2.2 说的"只断言包含某些关键词"。
|
|
377
|
+
9. **忠实性语义必须有断言**(四套都要):断言注入文本**不含**"偏离 → 0"这类把形式化缺陷等同命题为假
|
|
378
|
+
的指令,且含"不要投 0 / 记为形式化不合格 / 走待办"的要求;并断言 `defect` 路径真的不得定论
|
|
379
|
+
(`require` 档下对象留在未定论 + `Formal/TODO.md`)。
|
|
380
|
+
10. **每个架构都要有人可读的 Lean 提示词语料**(`prompt-corpus-vN/`,随包发布):至少覆盖
|
|
381
|
+
`off` 不出文本、`encourage`、**`require`**、`passed` 忠实性分支、以及平时工作轮的"顺手形式化";
|
|
382
|
+
语料必须把工作区与 VibeMath 根**归一化为 `<WS>` / `<VIBEMATH>`**(大小写与分隔符无关——
|
|
383
|
+
Windows 下 `os.tmpdir()` 的大小写可能与插件渲染的不同),并把**时间戳归一化为 `<TIME>`**,
|
|
384
|
+
保证逐字节确定性、可 diff、不泄露本机路径。**教训**:首版只有 v3/v5 有语料,v2/v4 的 Lean
|
|
385
|
+
提示词只能翻源码;`require` 档文本不在任何语料里;v5 语料既有绝对临时路径又有时间戳,
|
|
386
|
+
每跑一次都变。
|
|
387
|
+
11. **提示词硬要求的探针**(放进 `audit-formal-sensitivity.mjs`):把注入文本里的工具名改成缩写
|
|
388
|
+
(`lean_archive`)、删掉 `require` 档的要求段落、把忠实性分支改回"偏离 → 0"——三者都必须让
|
|
389
|
+
对应套件**变红**。
|
|
312
390
|
|
|
313
391
|
---
|
|
314
392
|
|
|
@@ -317,5 +395,7 @@
|
|
|
317
395
|
- **不内置 Lean**:本框架不安装工具链、不下载依赖。工具链不存在时优雅降级(记录 `LEAN_NOT_FOUND`)。
|
|
318
396
|
- **不判"忠实性"**:忠实性由代理/人审查并投票决定;框架只负责把审查焦点**换成**忠实性
|
|
319
397
|
(因为证明正确性已由内核保证)。框架不会假装自己能判断 Lean 代码是否对应命题。
|
|
398
|
+
- **`defect` 也不是框架的判断**:框架不判断 Lean 代码是否忠实,只提供"表决者认定不忠实时"的
|
|
399
|
+
一档落库语义(§4.1)——**降级 + 待办 + 不定论**,而不是把它记成"命题为假"。
|
|
320
400
|
- **不把 Lean 通过等同于"命题为真"**:`passed` 只表示"形式化代码通过内核检查",
|
|
321
401
|
该代码是否忠实于命题仍需 m 票审查。这正是 §0 表格里"审查对象变化"的含义。
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# 测试与脚本耗时基线(决定每次跑什么、怎么跑)
|
|
2
|
+
|
|
3
|
+
> **为什么要写下来**:这套仓库的测试耗时极不均匀(一个套件 100 s,大多数不到 2 s;探针脚本要
|
|
4
|
+
> 把同一套件跑十几遍)。不看数据就会犯两种错:要么每次都全量顺序跑(浪费 30 分钟),要么为了
|
|
5
|
+
> 省时间去砍测例(降低覆盖)。**先看基线,再选策略**;每次跑完把实测时间跟本表对一下,偏差大
|
|
6
|
+
> 就更新本表。
|
|
7
|
+
|
|
8
|
+
## 1. 怎么跑(并行是默认)
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
node run-tests.mjs # 全部 *.test.mjs,并行(并发 = min(4, CPU 核数))
|
|
12
|
+
node run-tests.mjs --only formal # 只跑名字含 formal 的套件
|
|
13
|
+
node run-tests.mjs --concurrency=6 # 手动指定并发
|
|
14
|
+
node audit-formal-sensitivity.mjs # 49 条不变式探针,并行(--concurrency=N / --only=<preset> / --list)
|
|
15
|
+
node audit-persona-sensitivity.mjs # 11 条提示词面探针(串行,本身只要几秒)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
两个并行 runner 都会打印**每项耗时 + 汇总(wall / sum / speed-up / 最慢几项)**。跑完请读这几行。
|
|
19
|
+
|
|
20
|
+
## 2. 基线(本机:4 核 / 8 GB,Windows,2026-09 实测)
|
|
21
|
+
|
|
22
|
+
| 脚本 | 串行(sum) | 并行(wall) | 实测输出 |
|
|
23
|
+
|---|---|---|---|
|
|
24
|
+
| `run-tests.mjs`(23 个套件) | 219.4 s | **114.4 s**(并发 4,speed-up x1.92) | 关键路径 = `e2e-v4-fixes` 101.1 s |
|
|
25
|
+
| `audit-formal-sensitivity.mjs`(49 探针) | 612.0 s | **154.6 s**(并发 4,speed-up x3.96) | 关键路径 = 12 个 v2 探针(每个 ≈32 s) |
|
|
26
|
+
| `audit-persona-sensitivity.mjs`(11 探针) | ≈ 5 s | — | 本身很快,不需要并行 |
|
|
27
|
+
| `audit-v5-integrity.mjs` | ≈ 3 s | — | 静态审计 |
|
|
28
|
+
| `prompt-v5-integrity.test.mjs` | ≈ 7 s | — | 生成 v5 语料 |
|
|
29
|
+
|
|
30
|
+
> 优化前:全量回归 ≈ 5.5 min(串行,`formal-verify-v2` 单独 186 s);
|
|
31
|
+
> 探针脚本 ≈ **38 min**(49 条串行,其中 12 条 × `formal-verify-v2` 162 s)。
|
|
32
|
+
> 现在:**1.9 min / 2.6 min**。
|
|
33
|
+
|
|
34
|
+
单套件耗时(并行时的关键路径按此排序):
|
|
35
|
+
|
|
36
|
+
| 套件 | 耗时 | 备注 |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `e2e-v4-fixes.test.mjs` | **≈ 101 s** | 9 个用例是**轮次采样**型(如 T13 采样 400 轮、T19/T25 多轮);时间 ≈ 轮数 × 框架自身的 40 ms 计时粒度 |
|
|
39
|
+
| `formal-verify-v2.test.mjs` | **≈ 32 s** | 曾为 186 s:见 §3 |
|
|
40
|
+
| `e2e-regression.test.mjs` | ≈ 14 s | |
|
|
41
|
+
| `e2e-business.test.mjs` | ≈ 13 s | |
|
|
42
|
+
| `e2e-d9-d13.test.mjs` | ≈ 13 s | |
|
|
43
|
+
| `e2e-v3.test.mjs` | ≈ 11 s | |
|
|
44
|
+
| 其余 17 个 | ≤ 10 s | 其中 8 个 < 1 s |
|
|
45
|
+
|
|
46
|
+
## 3. 已经做过的优化(别再重复踩)
|
|
47
|
+
|
|
48
|
+
1. **v2 套件 186 s → 32 s**(5.8×,断言数不变 261):
|
|
49
|
+
- 插件用 `setInterval(..., 1000)` 轮询调度器,套件的每次 `tick()` 都得等满 1 秒;
|
|
50
|
+
套件现在**只把 `setInterval` 快进到 25 ms**(自己的 `sleep` 用 `setTimeout`,不受影响),
|
|
51
|
+
插件内部"该不该 tick"仍按真实 200 ms 下限判断,**生产代码零改动**;
|
|
52
|
+
- `verifyWithDebate` 的 16 次循环**从不提前退出**(判据是 `autoDone` 之类永远不会发生的条件),
|
|
53
|
+
于是每次调用都烧满 16×1.3 s ≈ 21 s。现在按"连续 3 轮没有新 followup"提前退出。
|
|
54
|
+
2. **v4-fixes 的 12 个轮询循环加了"安静即停"**(105 s → 98 s):原判据
|
|
55
|
+
`autoDone || running===false` 对活着的 run 永远不成立,循环只是空转;
|
|
56
|
+
现在连续 100 次无待答 followup 就停(`V4_IDLE_POLLS` 可调)。
|
|
57
|
+
**再往下压就要砍采样深度了**——那 9 个慢用例(T13/T19/T22/T23/T25/T27/T2/T9/T20)是在
|
|
58
|
+
观察"多轮之后某个指令**没有**泄漏/重复",轮数是它们的不变式本体,不要再动。
|
|
59
|
+
3. **两个 runner 并行**(本轮新增):探针 38 min → 2.6 min(sum 612 s,wall 154.6 s,x3.96);
|
|
60
|
+
全量回归 5.5 min → 1.9 min(sum 219.4 s,wall 114.4 s,x1.92)。
|
|
61
|
+
|
|
62
|
+
## 4. 并行安全(为什么可以并发)
|
|
63
|
+
|
|
64
|
+
- 每个套件/探针都自建 `mkdtempSync` 工作区,互不共享状态;
|
|
65
|
+
- **会写语料的套件必须给不同的语料目录**:`V2_CORPUS_DIR` / `V3_CORPUS_DIR` / `V4_CORPUS_DIR` /
|
|
66
|
+
`V5_CORPUS_DIR`。探针 runner 为**每个探针**分配独立目录,否则同一套件的并发实例会互相覆盖语料;
|
|
67
|
+
- `audit-persona-sensitivity.mjs` 用 `PERSONA_ROOT` 指向变异副本,且在覆盖模式下**不写**语料。
|
|
68
|
+
|
|
69
|
+
## 5. 策略建议(按目的选最小代价的组合)
|
|
70
|
+
|
|
71
|
+
| 目的 | 跑什么 | 预期 |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| 改了某个架构的插件 | `node run-tests.mjs --only <vN>` + `node audit-formal-sensitivity.mjs --only=vN` | 30 s – 2 min |
|
|
74
|
+
| 改了提示词/人设 | `node run-tests.mjs --only persona --only prompt` + `node audit-persona-sensitivity.mjs` | ≈ 15 s |
|
|
75
|
+
| 改了共享契约 / 发版前 | `node run-tests.mjs` + `node audit-formal-sensitivity.mjs` + `node audit-persona-sensitivity.mjs` + `node audit-v5-integrity.mjs` | ≈ 4.5 min |
|
|
76
|
+
| 只想知道"快不快" | `node run-tests.mjs --json` | 读 `wallSeconds` / `slowest` |
|
|
77
|
+
|
|
78
|
+
**每次跑完都要看那几行 timing**:如果某个套件突然比基线慢很多,先怀疑新增的固定等待,
|
|
79
|
+
再怀疑它是否在等一个永远不会发生的条件(这正是 v2 套件 186 s 的成因)。
|