dsh-vibe-math 2.4.1 → 2.6.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 +53 -14
- package/README.md +54 -14
- package/cordis.patch.yml +54 -17
- package/docs/AUDIT-CHECKLIST.md +26 -7
- package/docs/COMPAT-AUDIT-ROUND3.md +16 -1
- package/docs/final-paper.md +171 -0
- package/docs/release-notes/RELEASE-NOTES-2.5.0.md +173 -0
- package/docs/release-notes/RELEASE-NOTES-2.6.0.md +268 -0
- package/docs/test-timing.md +77 -40
- package/installer.js +225 -45
- package/package.json +6 -3
- package/preset-declaration.js +38 -7
- package/prompt-corpus-persona/persona-corpus.json +13 -13
- package/prompt-corpus-persona/persona-corpus.md +113 -39
- package/prompt-corpus-v2/formal-verify-v2.json +128 -92
- package/prompt-corpus-v2/formal-verify-v2.md +380 -142
- package/prompt-corpus-v3/formal-verify-v3.json +117 -81
- package/prompt-corpus-v3/formal-verify-v3.md +693 -1189
- 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 +68 -8
- package/tests/audit-persona-surface.test.mjs +21 -8
- package/tests/audit-v5-sensitivity.mjs +47 -6
- package/tests/e2e-v5-round2.test.mjs +825 -1
- package/tests/formal-verify-v2.test.mjs +57 -2
- package/tests/formal-verify-v3.test.mjs +67 -2
- package/tests/formal-verify-v4.test.mjs +120 -4
- package/tests/prompt-v5-integrity.test.mjs +9 -3
- package/tests/run-tests.mjs +104 -23
- package/tests/selfdrive-v5.mjs +55 -4
- package/vibe-math-v2/agent.cordis.yml +20 -4
- package/vibe-math-v2/vibe-math-v2.js +1318 -106
- 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 +36 -14
- package/vibe-math-v3/vibe-math-v3.js +1348 -179
- 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 +36 -8
- package/vibe-math-v4/vibe-math-v4.js +1195 -57
- 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 +16 -8
- package/vibe-math-v5/vibe-math-v5.js +1628 -112
- package/vibe-math-v5//345/256/236/347/216/260/346/226/271/346/241/210.md +143 -41
|
@@ -107,8 +107,10 @@ const probes = [
|
|
|
107
107
|
name: 'v3-tool-registered-but-not-documented',
|
|
108
108
|
preset: 'vibe-math-v3', file: 'vibe-math-v3.js', nth: 'first', expect: 2,
|
|
109
109
|
guarantee: 'a newly registered tool must be documented in the persona (or the snapshot updated on purpose)',
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
// NOTE: the description argument is now `TOOL_DESC.<name>` (v3 audit of the two
|
|
111
|
+
// registration paths) — the anchor follows the call shape, not the literal text.
|
|
112
|
+
from: " registerTool('vibe_math_lean_run', TOOL_DESC.vibe_math_lean_run,",
|
|
113
|
+
to: " registerTool('vibe_math_extra_tool', 'x', objParams({}), async function () { return {} })\n registerTool('vibe_math_lean_run', TOOL_DESC.vibe_math_lean_run,",
|
|
112
114
|
},
|
|
113
115
|
|
|
114
116
|
// ── v4 ─────────────────────────────────────────────────────────────────────
|
|
@@ -146,22 +148,80 @@ const probes = [
|
|
|
146
148
|
name: 'v4-usage-advertises-phantom-subcommand',
|
|
147
149
|
preset: 'vibe-math-v4', file: 'vibe-math-v4.js', nth: 'first', expect: 1,
|
|
148
150
|
guarantee: 'the unknown-subcommand usage string must not advertise a subcommand that no branch implements',
|
|
149
|
-
|
|
150
|
-
to
|
|
151
|
+
// The anchor must be the CURRENT literal. Round A changed both the usage string and the
|
|
152
|
+
// hint to advertise `start [problem]` / `set <k=v>...` (vibe-math-v4.js:2492). While the
|
|
153
|
+
// anchor kept the pre-fix literal it matched 0 times, so this probe reported SETUP-FAIL
|
|
154
|
+
// every run and the F-section agreement between usage and branches had NO sensitivity
|
|
155
|
+
// proof at all (the hint probe at :155 was updated, this one was not).
|
|
156
|
+
// Round H (final paper) inserted `paper [...]` into both the usage and the hint; the anchor
|
|
157
|
+
// follows the new literal again, so the probe keeps proving the usage<->branches agreement.
|
|
158
|
+
from: "usage:'configure|start [problem]|resume|pause|abort|status|report|message <to|all> <content>|meeting|paper [lang=zh|en] [format=md|tex|both] [editor=office|resident:<id>] [force]|members|add|remove|set <k=v>...'",
|
|
159
|
+
to: "usage:'configure|start [problem]|resume|pause|abort|status|report|message <to|all> <content>|meeting|paper [lang=zh|en] [format=md|tex|both] [editor=office|resident:<id>] [force]|members|add|remove|scan|set <k=v>...'",
|
|
151
160
|
},
|
|
152
161
|
{
|
|
153
162
|
name: 'v4-hint-advertises-unimplemented-subcommand',
|
|
154
163
|
preset: 'vibe-math-v4', file: 'vibe-math-v4.js', nth: 'first', expect: 1,
|
|
155
164
|
guarantee: 'the typing hint must not advertise a subcommand the handler does not implement',
|
|
156
|
-
|
|
157
|
-
|
|
165
|
+
// Same reason as above: the hint now carries the `paper [...]` entry between `meeting` and
|
|
166
|
+
// `members`, so the anchor names the current literal and drops an IMPLEMENTED subcommand
|
|
167
|
+
// (`members`) from the mutated hint — the suite's implemented-subset-of-hint check must fail.
|
|
168
|
+
from: "message <to|all> <content>|meeting|paper [lang=zh|en] [format=md|tex|both] [editor=office|resident:<id>] [force]|members|add|remove|set]'",
|
|
169
|
+
to: "message <to|all> <content>|meeting|paper [lang=zh|en] [format=md|tex|both] [editor=office|resident:<id>] [force]|add|remove|set]'",
|
|
158
170
|
},
|
|
159
171
|
{
|
|
160
172
|
name: 'v5-persona-slash-list-drops-add-remove',
|
|
161
173
|
preset: 'vibe-math-v5', file: 'agent.cordis.yml', nth: 'all', expect: 2,
|
|
162
174
|
guarantee: "the persona's /v5 list must match the command hint (a human reading the persona must see every subcommand)",
|
|
163
|
-
|
|
164
|
-
|
|
175
|
+
// Round H appended `|paper` to the persona's /v5 list (and to the command hint), so the
|
|
176
|
+
// anchor carries the new tail; the mutation still drops the two subcommands whose absence
|
|
177
|
+
// the Round-G persona actually had (`add|remove`), which the hint<->persona equality check
|
|
178
|
+
// must catch.
|
|
179
|
+
from: 'meeting|hire|fire|add|remove|set|paper)',
|
|
180
|
+
to: 'meeting|hire|fire|set|paper)',
|
|
181
|
+
},
|
|
182
|
+
// ── final-paper surface (Round H) ──────────────────────────────────────────
|
|
183
|
+
// These two pin the surface the final-paper feature ADDED, so a later edit cannot quietly
|
|
184
|
+
// drop it: the v4 hint must keep advertising the subcommand its handler implements, and the
|
|
185
|
+
// v5 persona must keep naming the tools the plugin actually registers.
|
|
186
|
+
{
|
|
187
|
+
name: 'v4-hint-stops-advertising-paper',
|
|
188
|
+
preset: 'vibe-math-v4', file: 'vibe-math-v4.js', nth: 'first', expect: 1,
|
|
189
|
+
guarantee: 'the /v4 hint must keep advertising the final-paper subcommand the handler implements',
|
|
190
|
+
from: "|meeting|paper [lang=zh|en] [format=md|tex|both] [editor=office|resident:<id>] [force]|members|add|remove|set]'",
|
|
191
|
+
to: "|meeting|members|add|remove|set]'",
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
name: 'v5-paper-tool-renamed-in-plugin',
|
|
195
|
+
preset: 'vibe-math-v5', file: 'vibe-math-v5.js', nth: 'first', expect: 1,
|
|
196
|
+
guarantee: 'renaming the final-paper tool must be caught (the persona still advertises vibe_v5_paper)',
|
|
197
|
+
from: " registerTool('vibe_v5_paper',",
|
|
198
|
+
to: " registerTool('vibe_v5_paperX',",
|
|
199
|
+
},
|
|
200
|
+
// ── the persona↔hint list itself (the gap that hid `paper` in v2/v3/v4) ────────────────────
|
|
201
|
+
// The surface suite used to SKIP this comparison whenever the persona list contained `...`
|
|
202
|
+
// (v3's trailing ellipsis) or an argument placeholder with `...` (v4's `set <k=v>...`), and v2
|
|
203
|
+
// never enumerated at all. Each probe below drops ONE implemented subcommand from the persona
|
|
204
|
+
// list and requires the suite to go RED, so a future omission cannot hide behind an ellipsis.
|
|
205
|
+
{
|
|
206
|
+
name: 'v2-persona-slash-list-drops-paper',
|
|
207
|
+
preset: 'vibe-math-v2', file: 'agent.cordis.yml', nth: 'all', expect: 2,
|
|
208
|
+
guarantee: 'the v2 persona must name EVERY implemented /vibe subcommand explicitly (it never enumerated before)',
|
|
209
|
+
from: '|decisions|agents|paper [lang=zh|en] [format=both|md|tex] [force]).',
|
|
210
|
+
to: '|decisions|agents).',
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
name: 'v3-persona-slash-list-drops-paper',
|
|
214
|
+
preset: 'vibe-math-v3', file: 'agent.cordis.yml', nth: 'all', expect: 2,
|
|
215
|
+
guarantee: "the v3 persona's /vibe list must name every implemented subcommand (the old trailing '...' skipped the check)",
|
|
216
|
+
from: '|decisions|agents|paper [lang=zh|en] [format=both|md|tex] [force]).',
|
|
217
|
+
to: '|decisions|agents).',
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
name: 'v4-persona-slash-list-drops-paper',
|
|
221
|
+
preset: 'vibe-math-v4', file: 'agent.cordis.yml', nth: 'all', expect: 2,
|
|
222
|
+
guarantee: "a dropped v4 persona entry must be caught even though the list contains `set <k=v>...` (the old ellipsis escape)",
|
|
223
|
+
from: '|meeting|paper [lang=zh|en] [format=md|tex|both] [editor=office|resident:<id>] [force]|members',
|
|
224
|
+
to: '|meeting|members',
|
|
165
225
|
},
|
|
166
226
|
]
|
|
167
227
|
|
|
@@ -143,7 +143,11 @@ const PRESETS = [
|
|
|
143
143
|
js: 'vibe-math-v3.js',
|
|
144
144
|
prefix: 'vibe_math_',
|
|
145
145
|
tools: 33,
|
|
146
|
-
undocumented:
|
|
146
|
+
// `vibe_math_sync_meta` is no longer undocumented: the promotion-contract line of the
|
|
147
|
+
// persona now names it as the place to report `lemmas[].价值/关键性` (v3 audit M1 —
|
|
148
|
+
// without a prompt-side source for that field the promotion main line is unreachable).
|
|
149
|
+
// The write-lock pair stays out: solver/method-keeper prompts carry it via kcWriteRules().
|
|
150
|
+
undocumented: ['vibe_math_claim_write', 'vibe_math_release_write'],
|
|
147
151
|
lean: { tools: ['vibe_math_lean_run', 'vibe_math_lean_archive', 'vibe_math_lean_lib'], extra: [] },
|
|
148
152
|
},
|
|
149
153
|
{
|
|
@@ -166,9 +170,11 @@ const PRESETS = [
|
|
|
166
170
|
dir: 'vibe-math-v5',
|
|
167
171
|
js: 'vibe-math-v5.js',
|
|
168
172
|
prefix: 'vibe_v5_',
|
|
169
|
-
tools:
|
|
173
|
+
tools: 37,
|
|
170
174
|
// member- and academician-facing tools; the office (main agent) holds only the
|
|
171
|
-
// institute-level controls plus the hiring authority.
|
|
175
|
+
// institute-level controls plus the hiring authority. The final-paper pair is an
|
|
176
|
+
// OFFICE control and IS named in the persona (vibe_v5_paper / vibe_v5_finalize_paper),
|
|
177
|
+
// so it must not appear in this snapshot.
|
|
172
178
|
undocumented: [
|
|
173
179
|
'vibe_v5_wait', 'vibe_v5_record_progress', 'vibe_v5_record_proposition',
|
|
174
180
|
'vibe_v5_record_method', 'vibe_v5_record_subproblem', 'vibe_v5_read_library',
|
|
@@ -254,12 +260,19 @@ for (const P of PRESETS) {
|
|
|
254
260
|
if (!hintOpen) eq(implemented.filter((c) => !hinted.includes(c)).sort(), [], `${P.dir}: implemented slash subcommand(s) are missing from the hint`)
|
|
255
261
|
eq(used.sort(), implemented, `${P.dir}: the usage string and the implemented slash subcommands disagree`)
|
|
256
262
|
const personaEnum = /slash command mirrors[^(]*\(([\s\S]*?)\)/.exec(blocks.prefix.join('\n') + '\n' + blocks.text.join('\n'))
|
|
257
|
-
|
|
263
|
+
// An ellipsis must NOT switch this check off (that is how a dropped `paper` entry survived here),
|
|
264
|
+
// and `...` inside an argument placeholder (`set <k=v>...`) is not an abbreviation at all. So the
|
|
265
|
+
// persona is compared against the BRANCHES (the ground truth), and every implemented subcommand
|
|
266
|
+
// must be named EXPLICITLY. Only a HINT that is itself abbreviated makes the reverse direction
|
|
267
|
+
// (persona ⊆ hint) unprovable, so only that direction is relaxed then.
|
|
268
|
+
if (!personaEnum) {
|
|
269
|
+
ok(false, `${P.dir}: the persona never enumerates its /vN subcommands (list them so a human can see every one)`)
|
|
270
|
+
} else {
|
|
258
271
|
const personaCmds = cmdsFrom(personaEnum[1].replace(/^\s*\/[a-z0-9]+\s+/, ''))
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
272
|
+
ok(personaCmds.length > 0, `${P.dir}: no slash subcommand could be parsed from the persona's /vN list`)
|
|
273
|
+
eq(personaCmds.filter((c) => !implemented.includes(c)).sort(), [], `${P.dir}: the persona enumerates slash subcommand(s) the handler does not implement`)
|
|
274
|
+
eq(implemented.filter((c) => !personaCmds.includes(c)).sort(), [], `${P.dir}: the persona's /vN list omits subcommand(s) the handler implements — list them explicitly, do not hide behind "..."`)
|
|
275
|
+
if (!hintOpen) eq(personaCmds.slice().sort(), implemented.slice().sort(), `${P.dir}: the persona's /vN list and the command hint disagree`)
|
|
263
276
|
}
|
|
264
277
|
|
|
265
278
|
// ---- E. the Lean feature's prompt surface ----------------------------
|
|
@@ -31,6 +31,31 @@ const original = readFileSync(SRC, 'utf8')
|
|
|
31
31
|
const REPO = fileURLToPath(new URL('..', import.meta.url))
|
|
32
32
|
const dir = mkdtempSync(join(tmpdir(), 'v5-sens-'))
|
|
33
33
|
|
|
34
|
+
// `armNextVerify`'s two exclusion gates (a live MEETING and a live VERIFICATION), each written
|
|
35
|
+
// at the function head AND as a re-check inside the `while` loop with no `await` in between.
|
|
36
|
+
// `armGuards(true, true)` is the pristine source text; the probes switch ONE gate off in BOTH
|
|
37
|
+
// copies, which is the minimal edit that actually breaks the guarantee. Keeping the block in
|
|
38
|
+
// one place means the two mutations cannot drift apart from the source they mutate.
|
|
39
|
+
const armGuards = (meetingOn, verifyOn) => [
|
|
40
|
+
...(meetingOn ? [' if (meeting) return'] : []),
|
|
41
|
+
' // Only one begin may be in flight. Without this, two callers (a scheduling pass',
|
|
42
|
+
' // and a fresh proposal) could both pass the `currentVerify()` check before either',
|
|
43
|
+
' // has published its verdict record and would start the SAME object twice.',
|
|
44
|
+
' if (beginLock) return',
|
|
45
|
+
...(verifyOn ? [' if (currentVerify()) return'] : []),
|
|
46
|
+
' beginLock = true',
|
|
47
|
+
' try {',
|
|
48
|
+
' while (true) {',
|
|
49
|
+
' // NEVER remove a proposal we are not about to run: the entry leaves the durable',
|
|
50
|
+
' // queue only in the same step that starts it. The old code shifted it out and then',
|
|
51
|
+
' // returned because a meeting was live, so the proposal existed in neither the queue',
|
|
52
|
+
' // nor `verdicts` until some later pass happened to re-arm it (audit M2). Re-check',
|
|
53
|
+
' // the exclusion guards here too: `await putQueue` can let a meeting open.',
|
|
54
|
+
' const q = inst().queue.slice()',
|
|
55
|
+
' if (!q.length) return',
|
|
56
|
+
' if (' + (meetingOn && verifyOn ? 'meeting || currentVerify()' : meetingOn ? 'meeting' : 'currentVerify()') + ') return',
|
|
57
|
+
].join('\n')
|
|
58
|
+
|
|
34
59
|
// Each probe: { name, ref, guarantee, from, to }
|
|
35
60
|
// `from` must occur exactly once, so a mutation can never quietly hit the wrong site.
|
|
36
61
|
const probes = [
|
|
@@ -141,9 +166,19 @@ const probes = [
|
|
|
141
166
|
name: 'begin-not-exclusive',
|
|
142
167
|
ref: 'prompt-v5-integrity.test.mjs',
|
|
143
168
|
guarantee: '⑱ a second proposal must QUEUE, never start a concurrent ballot',
|
|
144
|
-
from:
|
|
145
|
-
to:
|
|
146
|
-
},
|
|
169
|
+
from: armGuards(true, true),
|
|
170
|
+
to: armGuards(true, false),
|
|
171
|
+
},
|
|
172
|
+
// NOTE — the mutual-exclusion gates of `armNextVerify` are written TWICE: once at the
|
|
173
|
+
// function head and once as a re-check inside the `while (true)` loop, and there is NO
|
|
174
|
+
// `await` between them. The head copies are therefore redundant mirrors of the in-loop
|
|
175
|
+
// ones, and a probe that deletes only a head copy is SEMANTICALLY INERT — it can never go
|
|
176
|
+
// red, which would masquerade as a "blind spot" forever (this was the state of both of the
|
|
177
|
+
// ⑱/㉝ probes: the in-loop re-check kept the invariant alive and
|
|
178
|
+
// `prompt-v5-integrity.test.mjs` stayed green). The probes for ⑱ and ㉝ therefore remove
|
|
179
|
+
// BOTH copies of the ONE gate they test, which is the minimal edit that actually lets a
|
|
180
|
+
// second ballot start — and the suite's case 9b ("a second proposal QUEUES") and case 10b
|
|
181
|
+
// ("a verification proposed DURING a meeting must queue") do detect exactly that.
|
|
147
182
|
// NOTE — a probe for `continueMeetingRound`'s `if (finalizeLock) { armHeartbeat(); return }`
|
|
148
183
|
// re-arm was REMOVED, not because the re-arm is unnecessary but because the state it
|
|
149
184
|
// guards is UNREACHABLE, so no black-box probe can detect its removal:
|
|
@@ -269,8 +304,10 @@ const probes = [
|
|
|
269
304
|
name: 'verify-preempts-a-live-meeting',
|
|
270
305
|
ref: 'prompt-v5-integrity.test.mjs',
|
|
271
306
|
guarantee: '㉝ a verification proposed during a meeting must QUEUE, never start concurrently (the two are mutually exclusive)',
|
|
272
|
-
|
|
273
|
-
|
|
307
|
+
// Removes BOTH `meeting` gates (see the note above `meeting-never-finalized`): deleting
|
|
308
|
+
// only the head copy is inert because the in-loop re-check runs before any `await`.
|
|
309
|
+
from: armGuards(true, true),
|
|
310
|
+
to: armGuards(false, true),
|
|
274
311
|
},
|
|
275
312
|
|
|
276
313
|
// ── LEAN FORMAL VERIFICATION PROBES (docs/formal-verification.md) ─────────
|
|
@@ -362,7 +399,11 @@ for (const p of probes) {
|
|
|
362
399
|
continue
|
|
363
400
|
}
|
|
364
401
|
const r = spawnSync(process.execPath, [testPath], {
|
|
365
|
-
|
|
402
|
+
// V5_CORPUS_DIR: a MUTATED run must never rewrite the shipped `prompt-corpus-v5/`. The
|
|
403
|
+
// corpus is the mandatory human-review artifact (AUDIT-CHECKLIST §0.3/§2.4); letting a
|
|
404
|
+
// deliberately broken copy dump its prompts there would leave the working tree holding
|
|
405
|
+
// mutant text until someone re-ran the healthy suite.
|
|
406
|
+
env: Object.assign({}, process.env, { V5_PLUGIN: file, V5_CORPUS_DIR: join(dir, 'corpus') }),
|
|
366
407
|
encoding: 'utf8',
|
|
367
408
|
cwd: REPO,
|
|
368
409
|
})
|