dsh-vibe-math 2.2.1 → 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.
- package/AUDIT-CHECKLIST.md +48 -2
- package/README.md +368 -81
- package/RELEASE-NOTES-2.2.2.md +88 -0
- package/RELEASE-NOTES-2.3.0.md +207 -0
- package/audit-formal-sensitivity.mjs +247 -0
- package/audit-persona-sensitivity.mjs +249 -0
- package/audit-persona-surface.test.mjs +349 -0
- package/audit-v5-integrity.mjs +40 -1
- package/audit-v5-sensitivity.mjs +84 -6
- package/docs/formal-verification.md +321 -0
- package/docs/generate_framework_diagram_v5.mjs +290 -0
- package/docs//346/236/266/346/236/204/345/233/276.md +75 -0
- package/formal-verify-v2.test.mjs +672 -0
- package/formal-verify-v3.test.mjs +824 -0
- package/formal-verify-v4.test.mjs +603 -0
- package/formal-verify-v5.test.mjs +526 -0
- package/package.json +33 -15
- package/prompt-corpus-persona/persona-corpus.json +32 -0
- package/prompt-corpus-persona/persona-corpus.md +674 -0
- package/prompt-corpus-v3/formal-verify-v3.json +280 -0
- package/prompt-corpus-v3/formal-verify-v3.md +2826 -0
- package/prompt-corpus-v5/prompt-corpus-v5.json +131 -713
- package/prompt-corpus-v5/prompt-corpus-v5.md +1828 -5225
- package/prompt-v5-integrity.test.mjs +154 -11
- package/vibe-math-v2/agent.cordis.yml +40 -2
- package/vibe-math-v2/vibe-math-v2.js +627 -19
- package/vibe-math-v2//345/256/236/347/216/260/346/226/271/346/241/210.md +145 -1
- package/vibe-math-v3/agent.cordis.yml +46 -2
- package/vibe-math-v3/vibe-math-v3.js +749 -21
- package/vibe-math-v3//345/256/236/347/216/260/346/226/271/346/241/210.md +87 -2
- package/vibe-math-v4/agent.cordis.yml +46 -4
- package/vibe-math-v4/vibe-math-v4.js +652 -15
- package/vibe-math-v4//345/256/236/347/216/260/346/226/271/346/241/210.md +226 -0
- package/vibe-math-v5/agent.cordis.yml +41 -5
- package/vibe-math-v5/vibe-math-v5.js +572 -9
- package/vibe-math-v5//345/256/236/347/216/260/346/226/271/346/241/210.md +122 -4
- package/vibe-math-v5//346/236/266/346/236/204/345/233/276.md +426 -0
- package//347/244/272/344/276/213/345/233/276//346/241/206/346/236/266/345/233/276-v5.svg +173 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Vibe Math V5 架构图生成器(零依赖,纯 Node)
|
|
3
|
+
//
|
|
4
|
+
// node docs/generate_framework_diagram_v5.mjs
|
|
5
|
+
// → 写出 示例图/框架图-v5.svg
|
|
6
|
+
//
|
|
7
|
+
// v2/v3/v4 用 matplotlib 脚本生成 PNG;v5 用 Node 直接生成 **SVG**:
|
|
8
|
+
// · 本仓库的运行时就包含 Node,不需要额外装 Python / matplotlib;
|
|
9
|
+
// · SVG 是纯文本,diff 友好、可评审、任意缩放不糊。
|
|
10
|
+
// 需要 PNG 时用浏览器打开 SVG 另存,或用无头浏览器截图:
|
|
11
|
+
// chrome --headless=new --window-size=1720,1100 --screenshot=框架图-v5.png 框架图-v5.svg
|
|
12
|
+
//
|
|
13
|
+
// 版式约定(改布局时请遵守,否则会重叠):
|
|
14
|
+
// · 每个 band 的标题在 y+27、副标题在 y+47,**内容从 y+56 开始**;
|
|
15
|
+
// · 左侧 x=40..214 是一条「控制面通道」,只有所办↔框架的连线走这里,
|
|
16
|
+
// 研究所/框架两个 band 从 x=226 开始 —— 这样控制面的箭头不会穿过所内成员;
|
|
17
|
+
// · 生成时会估算文字宽度,超出容器的行会打印 WARN,便于立刻发现溢出。
|
|
18
|
+
// ============================================================
|
|
19
|
+
import { mkdirSync, writeFileSync } from 'node:fs'
|
|
20
|
+
import { dirname, join } from 'node:path'
|
|
21
|
+
import { fileURLToPath } from 'node:url'
|
|
22
|
+
|
|
23
|
+
const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..')
|
|
24
|
+
const OUT = join(ROOT, '示例图', '框架图-v5.svg')
|
|
25
|
+
|
|
26
|
+
const W = 1720, H = 1204
|
|
27
|
+
const FONT = "'Microsoft YaHei','PingFang SC','Hiragino Sans GB','Noto Sans CJK SC','Source Han Sans SC',sans-serif"
|
|
28
|
+
const MONO = "'Cascadia Mono','Consolas','SFMono-Regular',monospace"
|
|
29
|
+
|
|
30
|
+
const C = {
|
|
31
|
+
ink: '#10202e', ink2: '#2c4557', mute: '#5d7788',
|
|
32
|
+
frame: '#0b6fb8', frameBg: '#eaf3fd',
|
|
33
|
+
house: '#b26a00', houseBg: '#fdf5e2',
|
|
34
|
+
data: '#1f7a52', dataBg: '#eef7f1',
|
|
35
|
+
gate: '#b3202c', gateBg: '#fdeef0',
|
|
36
|
+
human: '#5b4bb8', humanBg: '#f1eefc',
|
|
37
|
+
line: '#7d93a3',
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// band geometry
|
|
41
|
+
const FULL_L = 40, FULL_R = W - 40 // 40 .. 1680
|
|
42
|
+
const MAIN_L = 226, MAIN_R = FULL_R // 研究所 / 框架(让出控制面通道)
|
|
43
|
+
const IN_L = MAIN_L + 22, IN_R = MAIN_R - 22 // 226+22=248 .. 1638
|
|
44
|
+
|
|
45
|
+
const warnings = []
|
|
46
|
+
const esc = (s) => String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
|
47
|
+
// 粗略字宽估算:CJK/全角 1.0em,ASCII 0.56em。用来抓文字溢出(比截图更快)。
|
|
48
|
+
const textWidth = (s, fs) => [...String(s)].reduce((n, ch) => n + (/[\u2e80-\u9fff\uff00-\uffef]/.test(ch) ? 1 : 0.56), 0) * fs
|
|
49
|
+
const fits = (s, fs, limit, where) => {
|
|
50
|
+
const w = textWidth(s, fs)
|
|
51
|
+
if (w > limit) warnings.push(`${where}: 文字宽 ${w.toFixed(0)} > 可用 ${limit.toFixed(0)} — ${String(s).slice(0, 42)}…`)
|
|
52
|
+
return w
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const out = []
|
|
56
|
+
const push = (s) => out.push(s)
|
|
57
|
+
|
|
58
|
+
// ---------- primitives ----------
|
|
59
|
+
function band(x, y, w, h, title, sub, { fill, stroke, titleFill = C.ink }) {
|
|
60
|
+
push(`<rect x="${x}" y="${y}" width="${w}" height="${h}" rx="14" fill="${fill}" stroke="${stroke}" stroke-width="2"/>`)
|
|
61
|
+
fits(title, 15, w - 36, 'band title')
|
|
62
|
+
push(`<text x="${x + 18}" y="${y + 27}" font-size="15" font-weight="700" fill="${titleFill}">${esc(title)}</text>`)
|
|
63
|
+
if (sub) {
|
|
64
|
+
fits(sub, 12, w - 36, 'band sub')
|
|
65
|
+
push(`<text x="${x + 18}" y="${y + 47}" font-size="12" fill="${C.mute}">${esc(sub)}</text>`)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function card(x, y, w, h, lines, { fill = '#ffffff', stroke = C.frame, fs = 13, sfs = 11, titleFill = C.ink } = {}) {
|
|
70
|
+
push(`<rect x="${x}" y="${y}" width="${w}" height="${h}" rx="10" fill="${fill}" stroke="${stroke}" stroke-width="1.6"/>`)
|
|
71
|
+
const cx = x + w / 2
|
|
72
|
+
const lead = fs + 4
|
|
73
|
+
const total = (lines.length - 1) * lead
|
|
74
|
+
if (total + fs > h) warnings.push(`card@${x},${y}: ${lines.length} 行需要高 ${(total + fs).toFixed(0)} > 容器 ${h}`)
|
|
75
|
+
let ty = y + h / 2 - total / 2 + fs * 0.36
|
|
76
|
+
lines.forEach((ln, i) => {
|
|
77
|
+
const size = i === 0 ? fs : sfs
|
|
78
|
+
fits(ln, size, w - 16, `card line@${x},${y}`)
|
|
79
|
+
push(`<text x="${cx}" y="${ty.toFixed(1)}" font-size="${size}" font-weight="${i === 0 ? 700 : 400}" `
|
|
80
|
+
+ `fill="${i === 0 ? titleFill : C.ink2}" text-anchor="middle">${esc(ln)}</text>`)
|
|
81
|
+
ty += lead
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function plain(x, y, text, { size = 12, fill = C.ink2, anchor = 'start', weight = 400, mono = false, limit = null, where = 'plain', halo = false } = {}) {
|
|
86
|
+
if (limit) fits(text, size, limit, where)
|
|
87
|
+
// halo: 白色描边垫在文字下,用于压在连线上的标签,避免线从字中间穿过
|
|
88
|
+
push(`<text x="${x}" y="${y}" font-size="${size}" font-weight="${weight}" fill="${fill}" text-anchor="${anchor}"`
|
|
89
|
+
+ (halo ? ' paint-order="stroke" stroke="#ffffff" stroke-width="4" stroke-linejoin="round"' : '')
|
|
90
|
+
+ (mono ? ` font-family="${MONO}"` : '') + `>${esc(text)}</text>`)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function arrow(x1, y1, x2, y2, { color = C.line, dashed = false, both = true, width = 1.6, marker = 'both' } = {}) {
|
|
94
|
+
push(`<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" stroke="${color}" stroke-width="${width}" `
|
|
95
|
+
+ (dashed ? 'stroke-dasharray="7 5" ' : '')
|
|
96
|
+
+ (both ? `marker-start="url(#${marker})" ` : '') + `marker-end="url(#${marker})"/>`)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function polyline(points, { color = C.human, width = 2, dashed = false, marker = 'bothHuman' } = {}) {
|
|
100
|
+
const d = points.map((p, i) => (i ? 'L' : 'M') + ' ' + p[0] + ' ' + p[1]).join(' ')
|
|
101
|
+
push(`<path d="${d}" fill="none" stroke="${color}" stroke-width="${width}" `
|
|
102
|
+
+ (dashed ? 'stroke-dasharray="7 5" ' : '') + `marker-start="url(#${marker})" marker-end="url(#${marker})"/>`)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ---------- document ----------
|
|
106
|
+
push('<?xml version="1.0" encoding="UTF-8"?>')
|
|
107
|
+
push(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${W} ${H}" width="${W}" height="${H}" role="img" aria-label="Vibe Math V5 研究所架构图">`)
|
|
108
|
+
push(`<defs>
|
|
109
|
+
<marker id="both" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M 0 0 L 10 5 L 0 10 z" fill="${C.line}"/></marker>
|
|
110
|
+
<marker id="bothHuman" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M 0 0 L 10 5 L 0 10 z" fill="${C.human}"/></marker>
|
|
111
|
+
<marker id="bothFrame" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M 0 0 L 10 5 L 0 10 z" fill="${C.frame}"/></marker>
|
|
112
|
+
<marker id="bothData" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M 0 0 L 10 5 L 0 10 z" fill="${C.data}"/></marker>
|
|
113
|
+
<marker id="bothHouse" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M 0 0 L 10 5 L 0 10 z" fill="${C.house}"/></marker>
|
|
114
|
+
</defs>`)
|
|
115
|
+
push(`<rect width="${W}" height="${H}" fill="#ffffff"/>`)
|
|
116
|
+
push(`<g font-family="${FONT}">`)
|
|
117
|
+
|
|
118
|
+
// ---- 标题 ----
|
|
119
|
+
plain(W / 2, 40, 'Vibe Math V5 —— 研究所体系', { size: 27, fill: C.ink, anchor: 'middle', weight: 700 })
|
|
120
|
+
plain(W / 2, 67, '框架只是媒介:中继消息 · 沉淀产物 · 计数表决 · 管理上下文。它绝不指派任务 —— 组织与分派是所内院士的职责',
|
|
121
|
+
{ size: 13, fill: C.mute, anchor: 'middle', limit: W - 80, where: 'subtitle' })
|
|
122
|
+
|
|
123
|
+
// ---- 求真门槛 ----
|
|
124
|
+
band(FULL_L, 84, FULL_R - FULL_L, 94, '求真门槛 —— 唯一让对象进入 Verified/ 的规则',
|
|
125
|
+
'm = min(quorumCap, 在册有表决权人数) · 票是 [0,1] 概率:恰好 1 = 断言为真,恰好 0 = 断言为假,严格介于两者 = 弃权/存疑(不计入 m,计入全组平均)',
|
|
126
|
+
{ fill: C.gateBg, stroke: C.gate, titleFill: C.gate })
|
|
127
|
+
card(62, 140, 506, 28, ['布尔票 ≥ m 且全部为 1 或全部为 0 → 定论,写入 Verified/'], { stroke: C.gate, fs: 12 })
|
|
128
|
+
card(588, 140, 506, 28, ['同时出现 1 与 0 → 阻塞:少数派无法靠别人弃权把结论推过去'], { stroke: C.gate, fs: 12 })
|
|
129
|
+
card(1114, 140, 524, 28, ['未达门槛 → 留在原库 + 全组平均概率 + 完整辩论录(不强行裁决)'], { stroke: C.gate, fs: 12 })
|
|
130
|
+
|
|
131
|
+
// ---- 所办 ----
|
|
132
|
+
band(FULL_L, 190, FULL_R - FULL_L, 100, '所办(会话根代理 / 人)—— 研究所的对外接口',
|
|
133
|
+
'不参与研究 · 不投票 · 只汇报与转达人的指令;代持平台要求的一次性创建权',
|
|
134
|
+
{ fill: C.humanBg, stroke: C.human, titleFill: C.human })
|
|
135
|
+
card(62, 246, 372, 38, ['自然语言接口 + 汇报者', '「求解 XX」「进度如何」「暂停」'], { stroke: C.human, fs: 12, sfs: 10.5 })
|
|
136
|
+
card(452, 246, 372, 38, ['vibe_v5_configure → start', 'message / meeting / hire / fire'], { stroke: C.human, fs: 12, sfs: 10.5 })
|
|
137
|
+
card(842, 246, 330, 38, ['pause / resume / stop', 'set 调参(立即生效)'], { stroke: C.human, fs: 12, sfs: 10.5 })
|
|
138
|
+
card(1190, 246, 448, 38, ['/v5 斜杠命令(与工具等价)', 'configure|start|resume|pause|status|report|members|message|meeting|hire|fire|set'],
|
|
139
|
+
{ stroke: C.human, fs: 12, sfs: 9 })
|
|
140
|
+
|
|
141
|
+
// ---- 研究所 ----
|
|
142
|
+
band(MAIN_L, 302, MAIN_R - MAIN_L, 240, '研究所(所内自治)—— 编制、组织与分派都在成员之间完成,框架永不指派',
|
|
143
|
+
'院士 acad:领头人 / 组织与协调中心 · 常驻研究员 r-n:有表决权 · 临时工 t-n:无表决权(由雇主雇入与解雇)',
|
|
144
|
+
{ fill: C.houseBg, stroke: C.house, titleFill: '#8a5200' })
|
|
145
|
+
card(IN_L, 362, 300, 142, [
|
|
146
|
+
'院士 acad',
|
|
147
|
+
'领头人 · 组织与协调中心',
|
|
148
|
+
'L1 建立全所视图(overview)',
|
|
149
|
+
'L2 拆解并分派任务(assign)',
|
|
150
|
+
'L3 设定优先级(prioritize)',
|
|
151
|
+
'L4 召集并主持会议(convene)',
|
|
152
|
+
'L5 督导进度(nudge)',
|
|
153
|
+
'L6 调配临时工 · L7 对外代表',
|
|
154
|
+
], { stroke: C.house, fs: 13.5, sfs: 10.5 })
|
|
155
|
+
plain(IN_L + 150, 520, '四条边界:一票与他人等重 / 分派的是工作不是结论 /', { size: 10, fill: C.gate, anchor: 'middle', limit: 300, where: 'acad note' })
|
|
156
|
+
plain(IN_L + 150, 536, '成员可据理反对 / 不能自我扩张编制', { size: 10, fill: C.gate, anchor: 'middle', limit: 300, where: 'acad note' })
|
|
157
|
+
|
|
158
|
+
const RX = IN_L + 328, RW = 1390 - 328 - 44
|
|
159
|
+
const rcw = (RW - 2 * 20) / 3
|
|
160
|
+
plain(RX, 372, '常驻研究员(有表决权 · 可自主雇佣/解雇自己的临时工)', { size: 11.5, fill: '#8a5200', weight: 700, limit: RW, where: 'researcher label' })
|
|
161
|
+
for (let i = 0; i < 3; i++) {
|
|
162
|
+
card(RX + i * (rcw + 20), 380, rcw, 52, [`常驻研究员 r-${i + 1}`, 'continuable 持久会话 · 自主方向 · 主动汇报'],
|
|
163
|
+
{ stroke: C.house, fs: 13, sfs: 10.5 })
|
|
164
|
+
}
|
|
165
|
+
plain(RX, 452, '临时工(无表决权 · 为特定任务临时雇入 · 雇主或院士可解雇)', { size: 11.5, fill: '#8a5200', weight: 700, limit: RW, where: 'temp label' })
|
|
166
|
+
for (let i = 0; i < 3; i++) {
|
|
167
|
+
card(RX + i * (rcw + 20), 460, rcw, 52, [`临时工 t-${i + 1}`, `由 r-${i + 1} 雇入 · 可读/可想/可发言/可写自己的库`],
|
|
168
|
+
{ stroke: '#c99a4a', fs: 13, sfs: 10.5 })
|
|
169
|
+
}
|
|
170
|
+
plain(RX, 536, '所内组织动作(分派 · 优先级 · 督办 · 会议 · 用人)由院士发起,不是框架行为 —— 框架只负责送达',
|
|
171
|
+
{ size: 10.5, fill: C.mute, limit: RW, where: 'house note' })
|
|
172
|
+
|
|
173
|
+
// ---- 框架 ----
|
|
174
|
+
band(MAIN_L, 566, MAIN_R - MAIN_L, 382, '框架 vibe-v5 —— 只是媒介(middleware):中继 · 沉淀 · 计数 · 调度',
|
|
175
|
+
'每轮发「状态块 + 本轮问句」(规章在 persona 里,不进对话);成员回一个 JSON:say / progress / record / verdict / task_* / hire / fire / reject_assign / input / vote_solved',
|
|
176
|
+
{ fill: C.frameBg, stroke: C.frame, titleFill: '#084d80' })
|
|
177
|
+
const chips = [
|
|
178
|
+
['消息中继(持久邮箱)', '群聊 / 私信 / 致全体表决者', '所办通知 / 分派 / 督办 / 框架提示', '逐收件人落盘 · 先落盘再投递 · 群聊合批'],
|
|
179
|
+
['会议 / 辩论', '议程 · 实时名册对账 · 随机发言序', '与验证互斥:任一方进行中,另一方排队', '看门狗:卡死即放弃并回到自组织'],
|
|
180
|
+
['任务板(CAS + DAG)', '开 / 认领 / 释放 / 完成 / 重开 / 分派', '版本号比较交换 · 依赖环检测', '写范围重叠告警 · 解雇自动收回'],
|
|
181
|
+
['m 票共识验证', '发起 → 独立初评 → 公开辩论重投', '布尔一致 + ≥ m 才定论', 'Verified/ 卡 + 辩论录 + 全组平均概率'],
|
|
182
|
+
['上下文与活性', '阈值压缩(人设不丢)· 免轮询活动等待', '优先级调度 · 心跳永远重武装', '并发闸 maxParallel · 停滞自动开会'],
|
|
183
|
+
['编制与雇佣', '院士/研究员可雇自己的临时工', '雇主或院士可真实解雇(释放子会话)', '代号永不复用 · 按人/全所双配额'],
|
|
184
|
+
]
|
|
185
|
+
const ccw = (IN_R - IN_L - 2 * 22) / 3
|
|
186
|
+
chips.forEach((c, i) => {
|
|
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
|
+
})
|
|
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, [
|
|
196
|
+
'调度器优先级:进行中的会议或验证(二者互斥,永不同时)→ 队列中的验证 → 暂存会议 → 已认领/被分派的在办任务(按 activityTimeoutMs 节流)→ 加急邮件 → 群聊摘要 → 停滞自动开会 → 兜底心跳',
|
|
197
|
+
], { stroke: C.frame, fs: 11.5 })
|
|
198
|
+
|
|
199
|
+
// ---- 数据面 ----
|
|
200
|
+
band(FULL_L, 964, 790, 196, '状态权威源:会话日志的 host-only 投影单元(键 vibeMathV5)',
|
|
201
|
+
'副作用只是往会话日志追加事件 —— 不进模型上下文(零 token 成本),checkpoint / restore 交给 DSH',
|
|
202
|
+
{ fill: C.dataBg, stroke: C.data, titleFill: '#125a3c' })
|
|
203
|
+
card(62, 1020, 360, 124, [
|
|
204
|
+
'applyV5Event(纯折叠,只此一份)',
|
|
205
|
+
'11 类事件:institute / member / task /',
|
|
206
|
+
'message / delivered / meeting / debate /',
|
|
207
|
+
'verdict / queue / counters / progress',
|
|
208
|
+
'未知或损坏事件 → 跳过并记入 diagnostics:',
|
|
209
|
+
'可用性优先,绝不因一条坏事件卡死全场',
|
|
210
|
+
], { stroke: C.data, fs: 12, sfs: 10.5 })
|
|
211
|
+
card(434, 1020, 374, 124, [
|
|
212
|
+
'checkpoint / restore / resume',
|
|
213
|
+
'投影随会话日志一起 checkpoint;restore',
|
|
214
|
+
'时从快照 + 日志尾部重新折叠 → 跨进程与',
|
|
215
|
+
'同进程恢复走同一条代码路径',
|
|
216
|
+
'回退:宿主无 sessionProjections 时改用',
|
|
217
|
+
'加固 JSON:State/<institute>.v5state.json',
|
|
218
|
+
], { stroke: C.data, fs: 12, sfs: 10.5 })
|
|
219
|
+
|
|
220
|
+
band(852, 964, FULL_R - 852, 196, '文件面:人可读产物(投影之外的一切都只是镜像)',
|
|
221
|
+
'共识的权威在投影;文件是工作区与可读产物,手工改坏不会破坏研究所',
|
|
222
|
+
{ fill: C.dataBg, stroke: C.data, titleFill: '#125a3c' })
|
|
223
|
+
card(874, 1020, FULL_R - 874 - 22, 124, [
|
|
224
|
+
'Members/<id>/Progress|Propos|Methods|Subproblems/',
|
|
225
|
+
'只有本人可写,人人可读(跨读被鼓励)',
|
|
226
|
+
'Shared/Chat/*.md · Shared/Meetings/<mt-id>.md · Shared/Debates/<obj>.md',
|
|
227
|
+
'Shared/TaskBoard.md · Institutes.md(编制镜像)· State/README.md(说明此处非权威)',
|
|
228
|
+
'Problems/<id>.md(原问题)· Problems/conclusion.md(结题)· Verified/<类型>/<id>.md(定论,只读)',
|
|
229
|
+
], { stroke: C.data, fs: 11.5, sfs: 10.5 })
|
|
230
|
+
|
|
231
|
+
// ---- 连线:控制面(左侧通道,不穿过所内成员) ----
|
|
232
|
+
const CHX = 127
|
|
233
|
+
polyline([[CHX, 290], [CHX, 700], [MAIN_L, 700]], { color: C.human, width: 2 })
|
|
234
|
+
plain(CHX, 336, '工具面', { fill: C.human, anchor: 'middle', size: 12, weight: 700, halo: true })
|
|
235
|
+
plain(CHX, 356, 'vibe_v5_*', { fill: C.human, anchor: 'middle', size: 11, halo: true })
|
|
236
|
+
plain(CHX, 374, '/v5 命令', { fill: C.human, anchor: 'middle', size: 11, halo: true })
|
|
237
|
+
plain(CHX, 398, '↓', { fill: C.human, anchor: 'middle', size: 13, weight: 700, halo: true })
|
|
238
|
+
plain(CHX, 470, '汇报', { fill: C.human, anchor: 'middle', size: 12, weight: 700, halo: true })
|
|
239
|
+
plain(CHX, 490, 'status', { fill: C.human, anchor: 'middle', size: 11, halo: true })
|
|
240
|
+
plain(CHX, 508, 'report', { fill: C.human, anchor: 'middle', size: 11, halo: true })
|
|
241
|
+
plain(CHX, 532, '↑', { fill: C.human, anchor: 'middle', size: 13, weight: 700, halo: true })
|
|
242
|
+
plain(CHX, 600, '所办不投票', { fill: C.mute, anchor: 'middle', size: 10, limit: 170, where: 'ch note' })
|
|
243
|
+
plain(CHX, 616, '不能让结论变真', { fill: C.mute, anchor: 'middle', size: 10, limit: 170, where: 'ch note' })
|
|
244
|
+
plain(CHX, 644, '也不替成员', { fill: C.mute, anchor: 'middle', size: 10, limit: 170, where: 'ch note' })
|
|
245
|
+
plain(CHX, 660, '思考或署名', { fill: C.mute, anchor: 'middle', size: 10, limit: 170, where: 'ch note' })
|
|
246
|
+
|
|
247
|
+
// ---- 连线:研究所 ↔ 框架(提示词 / 回执) ----
|
|
248
|
+
arrow(560, 542, 560, 566, { color: C.frame, marker: 'bothFrame', width: 2 })
|
|
249
|
+
arrow(1400, 542, 1400, 566, { color: C.frame, marker: 'bothFrame', width: 2 })
|
|
250
|
+
plain(980, 559, '↑ 每轮提示词(状态块 + 本轮问句) ↓ 单个 JSON 回执',
|
|
251
|
+
{ fill: C.frame, anchor: 'middle', size: 10.5, limit: 780, where: 'prompt label', halo: true })
|
|
252
|
+
|
|
253
|
+
// ---- 连线:所内组织(虚线 = 不由框架执行) ----
|
|
254
|
+
arrow(556, 400, 578, 400, { color: C.house, dashed: true, width: 1.8, marker: 'bothHouse' })
|
|
255
|
+
arrow(556, 430, 578, 430, { color: C.house, dashed: true, width: 1.8, marker: 'bothHouse' })
|
|
256
|
+
|
|
257
|
+
// ---- 连线:框架 ↔ 数据面 ----
|
|
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 })
|
|
262
|
+
|
|
263
|
+
// ---- 图例 ----
|
|
264
|
+
plain(52, 1186, '图例', { size: 12, fill: C.ink, weight: 700 })
|
|
265
|
+
const legend = [
|
|
266
|
+
[C.human, '所办 / 人(外部接口,不研究不投票)'],
|
|
267
|
+
[C.house, '所内成员与所内组织(虚线 = 不由框架执行)'],
|
|
268
|
+
[C.frame, '框架(中继 / 沉淀 / 计数 / 调度)'],
|
|
269
|
+
[C.data, '状态与产物'],
|
|
270
|
+
[C.gate, '求真门槛 / Lean 形式化(可调)'],
|
|
271
|
+
]
|
|
272
|
+
legend.forEach(([col, txt], i) => {
|
|
273
|
+
const x = 108 + i * 330
|
|
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' })
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
push('</g>')
|
|
279
|
+
push('</svg>')
|
|
280
|
+
|
|
281
|
+
mkdirSync(dirname(OUT), { recursive: true })
|
|
282
|
+
const svg = out.join('\n')
|
|
283
|
+
writeFileSync(OUT, svg, 'utf8')
|
|
284
|
+
console.log('saved ' + OUT + ' (' + svg.length + ' bytes)')
|
|
285
|
+
if (warnings.length) {
|
|
286
|
+
console.error('\n布局告警(文字可能溢出容器):')
|
|
287
|
+
for (const w of warnings) console.error(' WARN ' + w)
|
|
288
|
+
process.exit(1)
|
|
289
|
+
}
|
|
290
|
+
console.log('layout: no overflow warnings')
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Vibe Math 架构图
|
|
2
|
+
|
|
3
|
+
> 框架 = **一个主代理(助手)+ 一个代码调度器 + 五类子代理** + 一套按项目隔离的持久化数据布局。
|
|
4
|
+
> 下方的 Mermaid 代码块在 GitHub 上会**原生渲染**成流程图;本文件即图源,改完重新提交即可自动更新。
|
|
5
|
+
|
|
6
|
+
```mermaid
|
|
7
|
+
flowchart TB
|
|
8
|
+
subgraph L1["👤 交互层"]
|
|
9
|
+
U["😀 用户(自然语言)"]
|
|
10
|
+
M["🤖 主代理(助手 + 汇报者)<br/>翻译需求 · 汇报进度 · 问答配置<br/>不求解 · 不调度"]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
subgraph L2["⚙️ 调度层(插件代码)"]
|
|
14
|
+
SCHED["调度器 Scheduler<br/>唯一文件写者<br/>读 qs.csv · 派发子代理 · 推进状态机"]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
subgraph L3["🧠 子代理层(continuable 持久会话)"]
|
|
18
|
+
BRAIN["🧭 Brainstorm<br/>拆解多个求解方向"]
|
|
19
|
+
SOLV["✍️ Solver × N<br/>逐方向多轮迭代"]
|
|
20
|
+
DERI["🔀 Derive<br/>死路时派生新方向"]
|
|
21
|
+
VERI["🔬 Verifier × ≥3<br/>独立审查 → 辩论 → 裁决"]
|
|
22
|
+
DECI["⚖️ Decider<br/>判定是否解决"]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
subgraph L4["💾 数据层 · VibeMath/Projects/<项目>/"]
|
|
26
|
+
QS["📋 qs.csv"]
|
|
27
|
+
PEND["📥 Pending_Verification/"]
|
|
28
|
+
UNDR["📂 Under_Verification/"]
|
|
29
|
+
TVAL["✅ Temp_Validated/"]
|
|
30
|
+
KNOW["📚 Verified/ 可信知识库"]
|
|
31
|
+
STATE["🗄️ Progress_Logs/ · VibeMath_State/"]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
U -->|"求解 XX / 查进度 / 干预"| M
|
|
35
|
+
M -->|"vibe_math_* 工具"| SCHED
|
|
36
|
+
|
|
37
|
+
SCHED -->|"① 派发"| BRAIN
|
|
38
|
+
BRAIN -->|"多个大相径庭的方向"| SCHED
|
|
39
|
+
SCHED -->|"② 每方向一个"| SOLV
|
|
40
|
+
SOLV -->|"结构化结果 JSON"| SCHED
|
|
41
|
+
SOLV -.->|"迭代至卡死"| DERI
|
|
42
|
+
DERI -->|"派生 1~3 个新方向"| SCHED
|
|
43
|
+
SCHED -->|"③ 写盘"| PEND
|
|
44
|
+
SCHED -->|"④ 拆解为最小验证单元"| UNDR
|
|
45
|
+
SCHED -->|"⑤ 派发 ≥3 个"| VERI
|
|
46
|
+
VERI -->|"裁决 JSON"| SCHED
|
|
47
|
+
SCHED -->|"⑥ 通过"| TVAL
|
|
48
|
+
SCHED -->|"⑦ 晋升"| KNOW
|
|
49
|
+
SCHED -->|"⑧ 派发"| DECI
|
|
50
|
+
DECI -->|"⑨ 已解决 → 回写"| QS
|
|
51
|
+
SCHED <-->|"读取问题"| QS
|
|
52
|
+
SCHED <-->|"状态落盘 / 断点恢复"| STATE
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 主流程(编号对应上图)
|
|
56
|
+
|
|
57
|
+
- **①** 主代理把用户需求翻译成 `vibe_math_add_problem` + `vibe_math_start`,调度器从 `qs.csv` 选问题并派发 **Brainstorm** 子代理;
|
|
58
|
+
- **②** Brainstorm 返回多个「大相径庭」的求解方向,调度器为**每个方向**起一个专属 **Solver**(同一会话内多轮迭代,产出引理/子路线/存活概率/完整解法,以结构化 JSON 返回);
|
|
59
|
+
- **③** 调度器作为**唯一文件写者**,把 Solver 输出落盘到 `Pending_Verification/`;
|
|
60
|
+
- **④** 调度器把待验证输出**拆解为最小验证单元**(`Under_Verification/`);
|
|
61
|
+
- **⑤** 每个单元派 **≥3 个 Verifier** 独立审查 → 辩论 → 裁决(一票否决 / 加权投票);
|
|
62
|
+
- **⑥** 裁决通过 → `Temp_Validated/` → **⑦ 晋升**进 `Verified/` 可信知识库;
|
|
63
|
+
- **⑧** 派 **Decider** 判断新结论是否解决某未解决问题:**⑨** 是则回写 `qs.csv` 为 `solved` 并命名解法文件,否则留作后续方向复用的已知结论;
|
|
64
|
+
- **卡死兜底**:所有方向都走进死路时,派 **Derive** 基于历史痛点派生 1~3 个全新方向,回到 ②。
|
|
65
|
+
|
|
66
|
+
## 关键特性在图中对应
|
|
67
|
+
|
|
68
|
+
| 特性 | 图中的对应 |
|
|
69
|
+
|---|---|
|
|
70
|
+
| **断点续跑** | `调度器 ⇄ VibeMath_State/` 双向边:任务栈、代理注册表、决策队列、依赖图、验证器历史准确率全部落盘,重启后 `vibe_math_resume` 恢复 |
|
|
71
|
+
| **中途人工干预** | `manual` 模式下,调度器在 ① 派发 / ⑥ 裁决 / ⑦ 晋升 三个节点挂起决策,等主代理用 `vibe_math_list_decisions` / `vibe_math_decide` 处理,随时可切回 `auto` |
|
|
72
|
+
| **唯一写者铁律** | 所有指向数据层的实线都从「调度器」出发;子代理只返回 JSON,从不写文件,跨目录移动走临时原子交换 |
|
|
73
|
+
| **按项目隔离** | 整个数据层位于 `VibeMath/Projects/<项目>/` 下,互不干扰、可随时切换 |
|
|
74
|
+
| **子代理权限调控** | 调度器派发时注入 toolFilter(允许/禁止)与每轮外部工具调用上限 |
|
|
75
|
+
| **可配置** | 默认参数来自 `vibe_math_setting.json`(JSONC 含注释),`/vibe setup` 交互式配置 |
|