dsh-vibe-math 2.5.0 → 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.
@@ -148,27 +148,80 @@ const probes = [
148
148
  name: 'v4-usage-advertises-phantom-subcommand',
149
149
  preset: 'vibe-math-v4', file: 'vibe-math-v4.js', nth: 'first', expect: 1,
150
150
  guarantee: 'the unknown-subcommand usage string must not advertise a subcommand that no branch implements',
151
- // The anchor must be the CURRENT literal: Round A changed both the usage string and the
151
+ // The anchor must be the CURRENT literal. Round A changed both the usage string and the
152
152
  // hint to advertise `start [problem]` / `set <k=v>...` (vibe-math-v4.js:2492). While the
153
153
  // anchor kept the pre-fix literal it matched 0 times, so this probe reported SETUP-FAIL
154
154
  // every run and the F-section agreement between usage and branches had NO sensitivity
155
155
  // proof at all (the hint probe at :155 was updated, this one was not).
156
- from: "usage:'configure|start [problem]|resume|pause|abort|status|report|message <to|all> <content>|meeting|members|add|remove|set <k=v>...'",
157
- to: "usage:'configure|start [problem]|resume|pause|abort|status|report|message <to|all> <content>|meeting|members|add|remove|scan|set <k=v>...'",
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>...'",
158
160
  },
159
161
  {
160
162
  name: 'v4-hint-advertises-unimplemented-subcommand',
161
163
  preset: 'vibe-math-v4', file: 'vibe-math-v4.js', nth: 'first', expect: 1,
162
164
  guarantee: 'the typing hint must not advertise a subcommand the handler does not implement',
163
- from: "message <to|all> <content>|meeting|members|add|remove|set]'",
164
- to: "message <to|all> <content>|meeting|add|remove|set]'",
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]'",
165
170
  },
166
171
  {
167
172
  name: 'v5-persona-slash-list-drops-add-remove',
168
173
  preset: 'vibe-math-v5', file: 'agent.cordis.yml', nth: 'all', expect: 2,
169
174
  guarantee: "the persona's /v5 list must match the command hint (a human reading the persona must see every subcommand)",
170
- from: 'meeting|hire|fire|add|remove|set)',
171
- to: 'meeting|hire|fire|set)',
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',
172
225
  },
173
226
  ]
174
227
 
@@ -170,9 +170,11 @@ const PRESETS = [
170
170
  dir: 'vibe-math-v5',
171
171
  js: 'vibe-math-v5.js',
172
172
  prefix: 'vibe_v5_',
173
- tools: 35,
173
+ tools: 37,
174
174
  // member- and academician-facing tools; the office (main agent) holds only the
175
- // 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.
176
178
  undocumented: [
177
179
  'vibe_v5_wait', 'vibe_v5_record_progress', 'vibe_v5_record_proposition',
178
180
  'vibe_v5_record_method', 'vibe_v5_record_subproblem', 'vibe_v5_read_library',
@@ -258,12 +260,19 @@ for (const P of PRESETS) {
258
260
  if (!hintOpen) eq(implemented.filter((c) => !hinted.includes(c)).sort(), [], `${P.dir}: implemented slash subcommand(s) are missing from the hint`)
259
261
  eq(used.sort(), implemented, `${P.dir}: the usage string and the implemented slash subcommands disagree`)
260
262
  const personaEnum = /slash command mirrors[^(]*\(([\s\S]*?)\)/.exec(blocks.prefix.join('\n') + '\n' + blocks.text.join('\n'))
261
- if (personaEnum && personaEnum[1].includes('|')) {
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 {
262
271
  const personaCmds = cmdsFrom(personaEnum[1].replace(/^\s*\/[a-z0-9]+\s+/, ''))
263
- if (personaCmds.length) {
264
- eq(personaCmds.filter((c) => !hinted.includes(c)).sort(), [], `${P.dir}: the persona enumerates slash subcommand(s) the hint does not know`)
265
- if (!/\.\.\./.test(personaEnum[1]) && !hintOpen) eq(personaCmds.slice().sort(), hinted.slice().sort(), `${P.dir}: the persona's /vN list and the command hint disagree`)
266
- }
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`)
267
276
  }
268
277
 
269
278
  // ---- E. the Lean feature's prompt surface ----------------------------