dsh-vibe-math 2.4.1 → 2.5.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.
- package/README.en.md +14 -14
- package/README.md +15 -14
- package/cordis.patch.yml +33 -10
- package/docs/AUDIT-CHECKLIST.md +25 -6
- package/docs/COMPAT-AUDIT-ROUND3.md +16 -1
- package/docs/release-notes/RELEASE-NOTES-2.5.0.md +173 -0
- package/docs/test-timing.md +73 -40
- package/installer.js +225 -45
- package/package.json +3 -2
- package/preset-declaration.js +38 -7
- package/prompt-corpus-persona/persona-corpus.json +9 -9
- package/prompt-corpus-persona/persona-corpus.md +67 -21
- package/prompt-corpus-v2/formal-verify-v2.json +116 -92
- package/prompt-corpus-v2/formal-verify-v2.md +240 -93
- package/prompt-corpus-v3/formal-verify-v3.json +81 -81
- package/prompt-corpus-v3/formal-verify-v3.md +288 -1111
- package/prompt-corpus-v4/formal-verify-v4.json +38 -8
- package/prompt-corpus-v4/formal-verify-v4.md +157 -25
- package/prompt-corpus-v5/prompt-corpus-v5.json +17 -17
- package/prompt-corpus-v5/prompt-corpus-v5.md +32 -26
- package/tests/audit-installer-compat.test.mjs +70 -4
- package/tests/audit-installer-policy.test.mjs +229 -4
- package/tests/audit-persona-sensitivity.mjs +11 -4
- package/tests/audit-persona-surface.test.mjs +5 -1
- package/tests/audit-v5-sensitivity.mjs +47 -6
- package/tests/e2e-v5-round2.test.mjs +354 -0
- package/tests/formal-verify-v2.test.mjs +54 -2
- package/tests/formal-verify-v3.test.mjs +63 -2
- package/tests/formal-verify-v4.test.mjs +120 -4
- package/tests/run-tests.mjs +104 -23
- package/vibe-math-v2/agent.cordis.yml +6 -0
- package/vibe-math-v2/vibe-math-v2.js +503 -99
- package/vibe-math-v2//345/256/236/347/216/260/346/226/271/346/241/210.md +20 -4
- package/vibe-math-v3/agent.cordis.yml +26 -10
- package/vibe-math-v3/vibe-math-v3.js +555 -175
- package/vibe-math-v3//345/256/236/347/216/260/346/226/271/346/241/210.md +3 -3
- package/vibe-math-v4/agent.cordis.yml +26 -6
- package/vibe-math-v4/vibe-math-v4.js +404 -51
- package/vibe-math-v4//345/256/236/347/216/260/346/226/271/346/241/210.md +91 -9
- package/vibe-math-v5/agent.cordis.yml +8 -4
- package/vibe-math-v5/vibe-math-v5.js +513 -105
- package/vibe-math-v5//345/256/236/347/216/260/346/226/271/346/241/210.md +73 -40
|
@@ -529,72 +529,88 @@ flowchart TD
|
|
|
529
529
|
|
|
530
530
|
### 8.2 状态文件与版本
|
|
531
531
|
|
|
532
|
-
`State/<研究所>.v5state.json`(`<研究所>` = `vibe_v5_configure` 的 `institute`,默认 `institute`),`
|
|
532
|
+
`State/<研究所>.v5state.json`(`<研究所>` = `vibe_v5_configure` 的 `institute`,默认 `institute`),`v = 1`。
|
|
533
533
|
|
|
534
|
-
它**不是投影单元**:没有注册、没有 `wire`、没有 `stateSchema` 契约——就是一份普通(但加固写入)的 JSON
|
|
534
|
+
它**不是投影单元**:没有注册、没有 `wire`、没有 `stateSchema` 契约——就是一份普通(但加固写入)的 JSON。读到版本不匹配的快照即丢弃,**并且此后拒绝写入该路径**(见下)。
|
|
535
535
|
|
|
536
536
|
```ts
|
|
537
|
-
interface V5State {
|
|
538
|
-
|
|
539
|
-
institutes: Record<string /*
|
|
540
|
-
|
|
541
|
-
//
|
|
542
|
-
seq: { acad: number; researcher: number; temp: number
|
|
543
|
-
task: number; meeting: number; message: number; verify: number }
|
|
537
|
+
interface V5State { // 整份快照的顶层信封(代码:initState / emptyInstitute)
|
|
538
|
+
v: 1 // = PROJECTION_VERSION;版本不匹配的快照被丢弃
|
|
539
|
+
institutes: Record<string /* key */, Institute> // key = `${project}::${institute}`
|
|
540
|
+
order: string[] // key 的出现顺序
|
|
541
|
+
diagnostics?: { at: number; type: string; error: string }[] // 折叠跳过的事件 / 状态文件读取问题(最多 50 条)
|
|
544
542
|
}
|
|
545
543
|
|
|
546
544
|
interface Institute {
|
|
547
|
-
|
|
545
|
+
key: string // `${project}::${institute}`,与 institutes 的键一致
|
|
548
546
|
project: string // 项目名(VibeMath/Projects/<project>)
|
|
547
|
+
institute: string // 研究所名(= 状态文件名)
|
|
549
548
|
createdAt: number
|
|
550
549
|
phase: 'idle' | 'founding' | 'active' | 'paused' | 'stopped' | 'solved'
|
|
551
|
-
problem: { id: string; statement: string
|
|
552
|
-
params: Params // 见 §16
|
|
550
|
+
problem: { id: string; statement: string }
|
|
551
|
+
params: Params // 见 §16(只存被 vibe_v5_set/configure 显式设过的键)
|
|
553
552
|
|
|
554
|
-
members: Member[] //
|
|
553
|
+
members: Member[] // 只增不改身份字段(已解雇者保留,phase='dismissed')
|
|
555
554
|
tasks: Task[] // 含 tombstone(deleted)
|
|
556
|
-
messages: Message[] //
|
|
557
|
-
delivered: string[] // 已投递的 messageId
|
|
558
|
-
meetings: MeetingIndex[] //
|
|
559
|
-
debates: DebateIndex[]
|
|
560
|
-
verdicts: Record<string /* targetKey */, VerdictRecord>
|
|
561
|
-
|
|
555
|
+
messages: Message[] // 排队中的邮件(= 已入队 − delivered)
|
|
556
|
+
delivered: string[] // 已投递的 messageId 台账;**有界 LRU 窗口**(上限 500,只用于回答"是否已投递")
|
|
557
|
+
meetings: MeetingIndex[] // 只存索引,全文在磁盘;上限 200
|
|
558
|
+
debates: DebateIndex[] // 上限 200
|
|
559
|
+
verdicts: Record<string /* targetKey */, VerdictRecord> // 每对象一条(含 closed 的历史结论)
|
|
560
|
+
formal: Record<string /* targetKey */, FormalRecord> // 每个对象的形式化记录(见 §14.6)
|
|
561
|
+
todo: { id: string; at: number; why: string; verdict?: 0 | 1 }[] // 形式化待办
|
|
562
|
+
queue: { target: string; kind: string; proposer: string; reason: string; at: number }[] // 验证队列(FIFO)
|
|
563
|
+
counters: { academician: number; researcher: number; temp: number
|
|
564
|
+
task: number; meeting: number; message: number; verify: number }
|
|
565
|
+
runId: string
|
|
566
|
+
lastProgressAt: number
|
|
567
|
+
artifactCount: number
|
|
568
|
+
diagnostics: { at: number; type: string; error: string }[] // 每个研究所自己的诊断(上限 50)
|
|
562
569
|
}
|
|
563
570
|
|
|
564
571
|
interface Member {
|
|
565
572
|
id: string // 'acad' | 'r-3' | 't-7'
|
|
566
573
|
kind: 'academician' | 'researcher' | 'temp'
|
|
567
|
-
childId?: string // DSH continuable child session id
|
|
574
|
+
childId?: string // DSH continuable child session id('' = 无常驻会话)
|
|
568
575
|
phase: 'provisioning' | 'active' | 'failed' | 'dismissed'
|
|
569
576
|
direction: string // 研究方向 / 雇佣用途
|
|
570
577
|
hiredBy?: string // 临时工:雇主 id
|
|
571
|
-
|
|
578
|
+
term?: string // 临时工:雇佣期限(自由文本)
|
|
579
|
+
provider: string // 'spawn' | 'fork' | …
|
|
580
|
+
persona: string // **入职时冻结的章程**(= 该成员的 sealed 身份记录,见 §14.5.3)
|
|
572
581
|
error?: string
|
|
573
582
|
dismissedAt?: number
|
|
574
583
|
dismissReason?: string
|
|
575
584
|
createdAt: number
|
|
576
|
-
lastActiveAt: number
|
|
577
585
|
}
|
|
578
586
|
```
|
|
579
587
|
|
|
580
|
-
|
|
588
|
+
**读前必 load、按路径锁存、load 未成功拒绝写(2.4.1 审计 H1 的教训)**:
|
|
589
|
+
`makeFileBackend` 的加载锁存是**按路径**的(`loadedPath`),不是布尔量。`configure` 切换 project/institute 时,先读**目标路径**的状态文件:文件里已有该研究所(`members` 非空)就**接管**它,否则要求当前会话自己为空,绝不把空研究所写回去。若某个路径的读**没有成功**(读失败、解析失败、版本不匹配),后端**拒绝写入**该路径并抛 `V5_STATE_NOT_LOADED`,把原因记进 `diagnostics`(`vibe_v5_status.diagnostics` / `vibe_v5_report` 的「⚠ 状态诊断」节可见)。旧实现在这里出过一次真实的数据丢失事故:布尔锁存 + 不读就读的 `state()` + `configure` 结尾的整份快照写回 ⇒ 会话首个工具调用锁存默认研究所路径,之后 `configure {institute:'alpha'}` 从不读 alpha 的文件、直接用空研究所覆盖它。
|
|
590
|
+
|
|
591
|
+
### 8.3 事件与提交(沿用官方 version-2 风格)
|
|
592
|
+
|
|
593
|
+
提交一次 = `applyV5Event(state, { type, data })` 折一次 + 把折叠后的整份快照写进 `State/<研究所>.v5state.json`。
|
|
581
594
|
|
|
582
595
|
```
|
|
583
|
-
'vibe5/institute' { version:1,
|
|
584
|
-
'vibe5/member' { version:1,
|
|
585
|
-
'vibe5/task' { version:1,
|
|
586
|
-
'vibe5/message' { version:1,
|
|
587
|
-
'vibe5/delivered' { version:1,
|
|
588
|
-
'vibe5/meeting' { version:1,
|
|
589
|
-
'vibe5/
|
|
590
|
-
'vibe5/
|
|
591
|
-
|
|
592
|
-
|
|
596
|
+
'vibe5/institute' { version:1, key, patch } // 建所/参数变更/阶段变更
|
|
597
|
+
'vibe5/member' { version:1, key, member } // 编制变更(含 dismissed)
|
|
598
|
+
'vibe5/task' { version:1, key, task } // 任务快照(含 revision)
|
|
599
|
+
'vibe5/message' { version:1, key, message } // 入队
|
|
600
|
+
'vibe5/delivered' { version:1, key, ids: string[] } // 销账:这批 messageId 已投递
|
|
601
|
+
'vibe5/meeting' { version:1, key, index } // 会议索引
|
|
602
|
+
'vibe5/debate' { version:1, key, index } // 辩论录索引
|
|
603
|
+
'vibe5/verdict' { version:1, key, target, record } // 验证记录(record=null 删除)
|
|
604
|
+
'vibe5/formal' { version:1, key, target, record, todo } // 对象的形式化记录 + 形式化待办
|
|
605
|
+
'vibe5/queue' { version:1, key, queue } // 整条验证队列(数组整体替换)
|
|
606
|
+
'vibe5/counters' { version:1, key, counters } // 代号与编号(永不复用)
|
|
607
|
+
'vibe5/progress' { version:1, key, at, artifactCount } // 进展心跳 + 产物计数
|
|
593
608
|
```
|
|
594
609
|
|
|
595
|
-
共 **12
|
|
610
|
+
共 **12 类**事件。事件的 `key` 是 `${project}::${institute}`,它**只用于把事件折进正确的那个 `institutes[key]`**;权威状态是 JSON 文件本身的结构(顶层的 `institutes` / `order`,研究所内的 `counters`),**不是**事件负载里的字段。
|
|
611
|
+
(这一点曾经写错过,并直接掩盖了上面那条数据丢失缺陷:旧文档把 key 写成"持久化在快照里的 `instituteId`",而代码里的 key 是会话内存态、从路径重建的。)
|
|
596
612
|
|
|
597
|
-
>
|
|
613
|
+
> **这些事件只进内存折叠,不进任何日志**:事件名沿用 `vibe5/` 前缀是为了与投影时代的记录对齐,它们**不再是宿主会话日志里的事件类型**(那正是让会话不可恢复的做法,§8.1)。
|
|
598
614
|
|
|
599
615
|
**折叠纪律(吸取官方教训)**:官方在遇到非法事件时会 `state.failure = ...` **永久闩锁**,此后任何读取都抛错。v5 **不闩锁**:非法事件被**跳过并计入 `diagnostics`**,状态继续前进。理由——研究所的可用性优先于对日志的洁癖,且事件由我们自己的代码产生,非法即代码缺陷,应由测试而非运行时闩锁来发现。
|
|
600
616
|
|
|
@@ -609,10 +625,12 @@ VibeMath/Projects/<project>/Institutes/<institute>/
|
|
|
609
625
|
Shared/Chat/<day>.md # 群聊记录(追加)
|
|
610
626
|
Shared/Meetings/<mid>.md # 会议纪要全文
|
|
611
627
|
Shared/Debates/<target>.md # 辩论录全文
|
|
612
|
-
State
|
|
628
|
+
State/<institute>.v5state.json # **权威状态**(加固 JSON;不在任何宿主会话日志里)
|
|
629
|
+
State/README.md # 声明"权威状态是本目录的 <研究所>.v5state.json;其余仅镜像,勿手改"
|
|
613
630
|
```
|
|
614
631
|
|
|
615
|
-
|
|
632
|
+
除 `State/<研究所>.v5state.json` 之外的一切文件(含 `State/README.md` 本身)都是镜像:
|
|
633
|
+
**只写不读**,丢失或损坏都不影响正确性——这本身就是对 v4 F-9 一类数据丢失事故的结构性防护。
|
|
616
634
|
|
|
617
635
|
---
|
|
618
636
|
|
|
@@ -631,6 +649,8 @@ VibeMath/Projects/<project>/Institutes/<institute>/
|
|
|
631
649
|
- `v === 0` → **断言为假**
|
|
632
650
|
- `0 < v < 1` → **弃权/存疑**(记录,不计入 m)
|
|
633
651
|
- `B₁` = 投出恰好 1 的人集合;`B₀` = 投出恰好 0 的人集合。
|
|
652
|
+
- 计票只读 `E` 内的票:`fire()` 会把被解雇者从未关闭的表决记录里剔除,`judgeVerdict` 也忽略
|
|
653
|
+
不在 `E` 内的 id——已不在册的人既不能凑 `m`,也不能定论(2.4.1 审计 H2)。
|
|
634
654
|
|
|
635
655
|
### 9.2 裁定规则
|
|
636
656
|
|
|
@@ -646,6 +666,10 @@ VibeMath/Projects/<project>/Institutes/<institute>/
|
|
|
646
666
|
|
|
647
667
|
> **关键性质**:弃权**不阻塞**裁定(这是与 v4"全体一致"的实质差别),但**任何反对票都会阻塞**。
|
|
648
668
|
> 因此"少数人合谋"无法通过——只要有一个人明确投反向布尔值,该对象就定不了论。
|
|
669
|
+
> 又因为反向票阻塞,**`m` 票口径下"只要有人投布尔票,门槛就等于全部布尔票同向"**:
|
|
670
|
+
> 调低 `quorumCap` 只降低"至少几张布尔票",**不会让收敛更容易**(`m` 与 `P` 相等时两种口径完全一致)。
|
|
671
|
+
> 计票只认**当前**有表决权者:已解雇成员此前投下的票在 `fire()` 时从未关闭的表决记录中剔除,
|
|
672
|
+
> `judgeVerdict` 也只读 `E` 内的票——`Verified/` 永远不可能由"已不在册的人"凑出来。
|
|
649
673
|
|
|
650
674
|
### 9.3 流程(两段式,照搬 v4 已验证的辩论结构并收紧)
|
|
651
675
|
|
|
@@ -818,7 +842,14 @@ prompt = inbox + base
|
|
|
818
842
|
|
|
819
843
|
- 每位成员有一个 **pending 摘要桶**;群聊消息先入桶,不立即唤醒;
|
|
820
844
|
- 触发投递的时机:该成员**因其它原因**(任务/会议/验证/私信)被唤醒时,或在 `chatDigestMs`(默认 45 s)内积累到 `chatDigestMax`(默认 12 条)时;
|
|
821
|
-
-
|
|
845
|
+
- 投递格式是**一个**「新到的消息」块:框头 `[新到的消息(N 条)]`(只有 1 条时是 `[新到的消息]`),下面逐条是已经分好类的**单行**消息(`composeInbox` + `frameLine`):
|
|
846
|
+
```
|
|
847
|
+
[新到的消息(3 条)]
|
|
848
|
+
【研究所·群聊】r-2:…
|
|
849
|
+
【研究所·群聊】acad:…
|
|
850
|
+
【研究所·私信 from t-3】…
|
|
851
|
+
```
|
|
852
|
+
也就是说:**合批是真的**(一次唤醒只带一个块、不逐条唤醒),但**不是**把所有群聊折叠成一行摘要——每条消息保留自己的发送者与类别框头,成员才知道谁说了什么。
|
|
822
853
|
- 私信与会议/验证提示**不做合批**(时效性强),且**优先于摘要投递**(沿用 v4"共识链不被普通轮打断"的取舍:**只在无进行中的会议/验证时投递摘要**)。
|
|
823
854
|
|
|
824
855
|
### 11.3 会议
|
|
@@ -936,7 +967,8 @@ pass,而该 pass 又立刻唤醒同一个任务所有者 —— 一个未完
|
|
|
936
967
|
### 14.2 并发
|
|
937
968
|
|
|
938
969
|
- `maxParallel`(默认 3)限制同时唤醒的成员数;brainstorm 首轮"各自独立想"一次全开。
|
|
939
|
-
-
|
|
970
|
+
- 会议轮**受 `maxParallel` 限制**:`askMeetingRound` 每个 pass 最多向 `maxParallel` 名尚未发言者投递,其余由各自 `end` 事件串行驱动(比"一次唤醒全所"更安全;本条曾写成"不受限制",与代码不符)。
|
|
971
|
+
- 验证轮(初评与补票)**不受 `maxParallel` 限制**:共识需要全员投票,`askVoters` / `continueVerifyRound` 一轮内向所有尚未投票的在册表决者投递。
|
|
940
972
|
- 并行填充:一轮内尽量填满预算(每个 `wakeMember` 只投递即返回,等各自 `end` 异步回归)。
|
|
941
973
|
|
|
942
974
|
### 14.3 隔离(继承 v4,简化)
|
|
@@ -1067,7 +1099,7 @@ Progress/,不要从头再来",**不得**复用 `【入职首轮】` 与"你
|
|
|
1067
1099
|
| (跨架构)v4 的 `vibe_v4_set` 参数表漏了 `formalVerify`/`leanCommand`/`leanArgs`/`leanTimeoutMs` | 开关不可发现 |
|
|
1068
1100
|
| (跨架构)v4 的 `usage` 串长期列着不存在的 `message` 子命令 | 告诉用户一个会失败的子命令 |
|
|
1069
1101
|
|
|
1070
|
-
现在由 `audit-persona-surface.test.mjs`(仓库根,
|
|
1102
|
+
现在由 `audit-persona-surface.test.mjs`(仓库根,196 条断言)把这一层变成硬约束:
|
|
1071
1103
|
|
|
1072
1104
|
1. **双向工具一致性**:注册的每个工具必须在 persona 的 `prefix` 与 `text` 两块里出现
|
|
1073
1105
|
("未文档化"用**显式快照**表示——新增工具必须主动改快照,或在 persona 里写清;
|
|
@@ -1246,6 +1278,7 @@ runaway 的编译器会在框架已经报告超时之后继续存活;`done`
|
|
|
1246
1278
|
### 15.3 错误码(照搬 M7 风格)
|
|
1247
1279
|
|
|
1248
1280
|
`V5_INVALID_ARGUMENT`(参数缺失或非法,含"入库必须写明价值程度/动机用途计划/概率")、`V5_WRITE_FAILED`(库文件写入失败)、`V5_NOT_FOUND`(要执行的 Lean 文件不存在)、`V5_LEAD_REQUIRED`(职权不足)、`V5_NOT_ACADEMICIAN`(非院士调用院士专用工具)、`V5_NOT_MEMBER`、`V5_MEMBER_NOT_FOUND`、`V5_MEMBER_NAME_TAKEN`、`V5_MEMBER_LIMIT`、`V5_INVALID_MEMBER_NAME`、`V5_PROVISIONING_CONFLICT`、`V5_SELF_MESSAGE`、`V5_MAILBOX_FULL`、`V5_MESSAGE_TOO_LARGE`、`V5_INVALID_TIMEOUT`、`V5_WAIT_ABORTED`、`V5_TASK_LIMIT`、`V5_TASK_NOT_FOUND`、`V5_TASK_STALE_REVISION`、`V5_TASK_DELETED`、`V5_TASK_UNAUTHORIZED`、`V5_TASK_ALREADY_CLAIMED`、`V5_TASK_BLOCKED`、`V5_TASK_INVALID_TRANSITION`、`V5_TASK_HAS_DEPENDENTS`、`V5_TASK_DEPENDENCY_CYCLE`、`V5_NOT_VOTER`(临时工投票)、`V5_INVALID_VERDICT`、`V5_INSTITUTE_STATE`、`V5_INVALID_WRITE_SCOPE`、`V5_INTERNAL`(框架内部不变式被破坏——例如"要生成某成员的状态块却没有给出该成员";**宁可显式失败,也绝不猜身份**)。
|
|
1281
|
+
| `V5_NOT_OFFICE` | 调用者不是**可证明的会话根(所办)**:空身份或成员身份一律拒绝(`configure/start/resume/pause/stop/set` 与 `/v5` 的变更类子命令) |
|
|
1249
1282
|
|
|
1250
1283
|
Lean 工具另外会返回**非错误码**的失败原因(都属于"可读结果"而非异常):`NO_SUBPROCESS`(宿主没有 subprocess 服务)、`LEAN_NOT_FOUND`(解析不到 `leanCommand`)、`LEAN_SPAWN_FAILED`、`LEAN_RUN_FAILED`、`LEAN_FAILED`(编译器非零退出)、`LEAN_TIMEOUT`。
|
|
1251
1284
|
|