@mmnto/cli 1.124.0 → 2.1.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.
Files changed (58) hide show
  1. package/dist/commands/describe.d.ts +13 -1
  2. package/dist/commands/describe.d.ts.map +1 -1
  3. package/dist/commands/describe.js +29 -1
  4. package/dist/commands/describe.js.map +1 -1
  5. package/dist/commands/describe.test.js +86 -3
  6. package/dist/commands/describe.test.js.map +1 -1
  7. package/dist/commands/doctor.d.ts +16 -10
  8. package/dist/commands/doctor.d.ts.map +1 -1
  9. package/dist/commands/doctor.js +162 -54
  10. package/dist/commands/doctor.js.map +1 -1
  11. package/dist/commands/doctor.test.js +444 -28
  12. package/dist/commands/doctor.test.js.map +1 -1
  13. package/dist/commands/hook-totemdir-render.test.js +55 -1
  14. package/dist/commands/hook-totemdir-render.test.js.map +1 -1
  15. package/dist/commands/init-templates.d.ts +2 -2
  16. package/dist/commands/init-templates.d.ts.map +1 -1
  17. package/dist/commands/init-templates.js +2 -2
  18. package/dist/commands/init.d.ts.map +1 -1
  19. package/dist/commands/init.js +39 -0
  20. package/dist/commands/init.js.map +1 -1
  21. package/dist/commands/init.test.js +32 -0
  22. package/dist/commands/init.test.js.map +1 -1
  23. package/dist/commands/install-hooks-exit-contract.test.js +32 -1
  24. package/dist/commands/install-hooks-exit-contract.test.js.map +1 -1
  25. package/dist/commands/install-hooks.d.ts +143 -10
  26. package/dist/commands/install-hooks.d.ts.map +1 -1
  27. package/dist/commands/install-hooks.js +596 -92
  28. package/dist/commands/install-hooks.js.map +1 -1
  29. package/dist/commands/install-hooks.test.js +1535 -19
  30. package/dist/commands/install-hooks.test.js.map +1 -1
  31. package/dist/commands/legs.d.ts +35 -7
  32. package/dist/commands/legs.d.ts.map +1 -1
  33. package/dist/commands/legs.js +26 -7
  34. package/dist/commands/legs.js.map +1 -1
  35. package/dist/commands/legs.test.js +87 -0
  36. package/dist/commands/legs.test.js.map +1 -1
  37. package/dist/commands/release-train-shape.test.d.ts +2 -0
  38. package/dist/commands/release-train-shape.test.d.ts.map +1 -0
  39. package/dist/commands/release-train-shape.test.js +226 -0
  40. package/dist/commands/release-train-shape.test.js.map +1 -0
  41. package/dist/commands/spec-templates.d.ts +17 -4
  42. package/dist/commands/spec-templates.d.ts.map +1 -1
  43. package/dist/commands/spec-templates.js +23 -3
  44. package/dist/commands/spec-templates.js.map +1 -1
  45. package/dist/commands/spec.d.ts +57 -8
  46. package/dist/commands/spec.d.ts.map +1 -1
  47. package/dist/commands/spec.js +124 -28
  48. package/dist/commands/spec.js.map +1 -1
  49. package/dist/commands/spec.test.js +277 -44
  50. package/dist/commands/spec.test.js.map +1 -1
  51. package/dist/commands/tools-hook-parity.test.js +200 -0
  52. package/dist/commands/tools-hook-parity.test.js.map +1 -1
  53. package/dist/utils.d.ts +5 -3
  54. package/dist/utils.d.ts.map +1 -1
  55. package/dist/utils.js.map +1 -1
  56. package/dist/utils.test.js +8 -3
  57. package/dist/utils.test.js.map +1 -1
  58. package/package.json +2 -2
@@ -0,0 +1,226 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import * as fs from 'node:fs';
3
+ import * as os from 'node:os';
4
+ import * as path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
7
+ // Executed regression cases for tools/release-train-shape.sh — the legs-gate CI
8
+ // arm's one exemption (mmnto-ai/totem#2779). The workflow pins the script's
9
+ // invocation (tools-hook-parity.test.ts); this file runs the script against a
10
+ // throwaway git repository and reads what it writes to $GITHUB_OUTPUT, so the
11
+ // rule "exempt only when the diff is exactly the release train's work" is
12
+ // proven by execution, case by case, including the bypass Greptile named on
13
+ // mmnto-ai/totem#2780: deleting a pending changeset without consuming them all.
14
+ const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../..');
15
+ const SCRIPT = path.join(REPO_ROOT, 'tools', 'release-train-shape.sh');
16
+ // A changeset body long enough that git's rename detection would pair its
17
+ // deletion with an ADDED file of the same text (the first-release case below
18
+ // reuses it verbatim): the script disables rename detection, so the pair must
19
+ // still read as D + A and stay exempt (the leg's F3 on mmnto-ai/totem#2780).
20
+ const CHANGESET_A = [
21
+ '---',
22
+ '"@example/y": minor',
23
+ '---',
24
+ '',
25
+ 'Add the first feature of package y, with enough prose that a rename',
26
+ 'heuristic would call the deleted changeset and the new CHANGELOG the same file.',
27
+ '',
28
+ ].join(String.fromCharCode(10));
29
+ // A POSIX bash that is not WSL (a WSL bash cannot run against a Windows temp
30
+ // path; the ubuntu and macos legs of the matrix run these cases regardless).
31
+ function bashUsable() {
32
+ const probe = spawnSync('bash', ['-c', 'uname -r'], { encoding: 'utf-8', timeout: 5000 });
33
+ if (probe.status !== 0)
34
+ return false;
35
+ return !/microsoft/i.test(probe.stdout);
36
+ }
37
+ const BASH_OK = bashUsable();
38
+ function git(cwd, ...args) {
39
+ const r = spawnSync('git', args, { cwd, encoding: 'utf-8' });
40
+ if (r.status !== 0)
41
+ throw new Error(`git ${args.join(' ')} failed: ${r.stderr}`);
42
+ return r.stdout;
43
+ }
44
+ function write(cwd, rel, content) {
45
+ const abs = path.join(cwd, rel);
46
+ fs.mkdirSync(path.dirname(abs), { recursive: true });
47
+ fs.writeFileSync(abs, content, 'utf-8');
48
+ }
49
+ /**
50
+ * Run the script with HEAD at `cwd`'s checkout against `base`; read
51
+ * $GITHUB_OUTPUT. The output file lives OUTSIDE the fixture repository, or the
52
+ * next scenario's `git add -A` would commit it and read it as a changed path.
53
+ */
54
+ function shape(cwd, base) {
55
+ const outFile = path.join(fs.mkdtempSync(path.join(os.tmpdir(), 'totem-gh-output-')), 'out');
56
+ fs.writeFileSync(outFile, '', 'utf-8');
57
+ const r = spawnSync('bash', [SCRIPT, base], {
58
+ cwd,
59
+ encoding: 'utf-8',
60
+ env: { ...process.env, GITHUB_OUTPUT: outFile },
61
+ });
62
+ return { status: r.status, exempt: fs.readFileSync(outFile, 'utf-8').trim(), log: r.stdout };
63
+ }
64
+ describe.skipIf(!BASH_OK)('tools/release-train-shape.sh (mmnto-ai/totem#2779)', () => {
65
+ let repo = '';
66
+ beforeAll(() => {
67
+ repo = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-release-train-'));
68
+ git(repo, 'init', '-q', '-b', 'main');
69
+ git(repo, 'config', 'user.email', 'test@example.invalid');
70
+ git(repo, 'config', 'user.name', 'test');
71
+ git(repo, 'config', 'commit.gpgsign', 'false');
72
+ git(repo, 'config', 'core.autocrlf', 'false');
73
+ // The base: two pending changesets, the README and config beside them, one
74
+ // workspace package with a CHANGELOG, one without (its first release ADDS
75
+ // one), the private root package.json, an owed doctrine file, and a path
76
+ // carrying whitespace.
77
+ write(repo, '.changeset/README.md', 'readme');
78
+ write(repo, '.changeset/config.json', '{}');
79
+ write(repo, '.changeset/a.md', CHANGESET_A);
80
+ write(repo, '.changeset/b.md', 'b');
81
+ write(repo, 'packages/x/package.json', '{"version":"1.0.0"}');
82
+ write(repo, 'packages/x/CHANGELOG.md', '# x');
83
+ write(repo, 'packages/y/package.json', '{"version":"0.0.0"}');
84
+ write(repo, 'package.json', '{"private":true}');
85
+ write(repo, 'doctrine/d.md', 'd');
86
+ write(repo, 'packages/x/CHANGELOG.md more', 'space');
87
+ git(repo, 'add', '-A');
88
+ git(repo, 'commit', '-q', '-m', 'base');
89
+ git(repo, 'branch', 'base');
90
+ // A second base with nothing pending.
91
+ git(repo, 'checkout', '-q', '-b', 'base-empty');
92
+ fs.rmSync(path.join(repo, '.changeset/a.md'));
93
+ fs.rmSync(path.join(repo, '.changeset/b.md'));
94
+ git(repo, 'add', '-A');
95
+ git(repo, 'commit', '-q', '-m', 'base-empty');
96
+ git(repo, 'checkout', '-q', 'base');
97
+ });
98
+ afterAll(() => {
99
+ if (repo.length > 0)
100
+ fs.rmSync(repo, { recursive: true, force: true });
101
+ });
102
+ let caseNo = 0;
103
+ /** Branch from `from`, apply `mutate`, commit, and run the script against `from`. */
104
+ function scenario(from, mutate) {
105
+ caseNo += 1;
106
+ git(repo, 'checkout', '-q', '-b', `case-${caseNo}`, from);
107
+ mutate();
108
+ git(repo, 'add', '-A');
109
+ git(repo, 'commit', '-q', '--allow-empty', '-m', `case ${caseNo}`);
110
+ return shape(repo, from);
111
+ }
112
+ const consumeAll = () => {
113
+ fs.rmSync(path.join(repo, '.changeset/a.md'));
114
+ fs.rmSync(path.join(repo, '.changeset/b.md'));
115
+ };
116
+ const renderX = () => {
117
+ write(repo, 'packages/x/CHANGELOG.md', '# x\n\n## 1.1.0');
118
+ write(repo, 'packages/x/package.json', '{"version":"1.1.0"}');
119
+ };
120
+ it('the release train: every pending changeset consumed, CHANGELOG and package.json rendered — exempt', () => {
121
+ const r = scenario('base', () => {
122
+ consumeAll();
123
+ renderX();
124
+ });
125
+ expect(r.status).toBe(0);
126
+ expect(r.exempt).toBe('exempt=true');
127
+ expect(r.log).toContain('::notice title=totem legs gate SKIPPED::');
128
+ });
129
+ it("a new package's first release ADDS its CHANGELOG (mmnto-ai/totem#2514), even one rename detection would pair with the deleted changeset — exempt", () => {
130
+ const r = scenario('base', () => {
131
+ consumeAll();
132
+ write(repo, 'packages/y/CHANGELOG.md', CHANGESET_A);
133
+ write(repo, 'packages/y/package.json', '{"version":"0.1.0"}');
134
+ });
135
+ expect(r.status).toBe(0);
136
+ expect(r.exempt).toBe('exempt=true');
137
+ expect(r.log).not.toContain('paths outside the shape');
138
+ });
139
+ it('nothing pending at the merge base, yet CHANGELOG and package.json rewritten — not exempt (the train writes nothing when it has nothing to consume)', () => {
140
+ const r = scenario('base-empty', () => {
141
+ write(repo, 'packages/x/CHANGELOG.md', '# TOTALLY FABRICATED');
142
+ write(repo, 'packages/x/package.json', '{"version":"9.9.9"}');
143
+ });
144
+ expect(r.status).toBe(0);
145
+ expect(r.exempt).toBe('exempt=false');
146
+ expect(r.log).toContain('nothing pending at the merge base');
147
+ });
148
+ it('the script parses (bash -n) — the only shell gate this repo runs on it', () => {
149
+ const r = spawnSync('bash', ['-n', SCRIPT], { encoding: 'utf-8' });
150
+ expect(r.status).toBe(0);
151
+ });
152
+ it('deleting a SUBSET of the pending changesets (the bypass Greptile named) — not exempt', () => {
153
+ const r = scenario('base', () => {
154
+ fs.rmSync(path.join(repo, '.changeset/a.md'));
155
+ renderX();
156
+ });
157
+ expect(r.status).toBe(0);
158
+ expect(r.exempt).toBe('exempt=false');
159
+ expect(r.log).toContain('not exactly the pending set');
160
+ });
161
+ it('deletions only, nothing rendered — not exempt', () => {
162
+ const r = scenario('base', consumeAll);
163
+ expect(r.status).toBe(0);
164
+ expect(r.exempt).toBe('exempt=false');
165
+ expect(r.log).toContain('no CHANGELOG rendered');
166
+ });
167
+ it('deleting .changeset/README.md beside the train — not exempt', () => {
168
+ const r = scenario('base', () => {
169
+ consumeAll();
170
+ renderX();
171
+ fs.rmSync(path.join(repo, '.changeset/README.md'));
172
+ });
173
+ expect(r.status).toBe(0);
174
+ expect(r.exempt).toBe('exempt=false');
175
+ // README is never pending, so its deletion is a mismatch of rule 2.
176
+ expect(r.log).toContain('not exactly the pending set');
177
+ });
178
+ it('the train plus an added owed doctrine file — not exempt', () => {
179
+ const r = scenario('base', () => {
180
+ consumeAll();
181
+ renderX();
182
+ write(repo, 'doctrine/new-rule.md', 'new');
183
+ });
184
+ expect(r.exempt).toBe('exempt=false');
185
+ expect(r.log).toContain('doctrine/new-rule.md');
186
+ });
187
+ it('the train plus the private root package.json — not exempt', () => {
188
+ const r = scenario('base', () => {
189
+ consumeAll();
190
+ renderX();
191
+ write(repo, 'package.json', '{"private":true,"x":1}');
192
+ });
193
+ expect(r.status).toBe(0);
194
+ expect(r.exempt).toBe('exempt=false');
195
+ expect(r.log).toContain('paths outside the shape');
196
+ expect(r.log).toMatch(/^M\s+package\.json$/m);
197
+ });
198
+ it('the train plus a path carrying whitespace — not exempt', () => {
199
+ const r = scenario('base', () => {
200
+ consumeAll();
201
+ renderX();
202
+ write(repo, 'packages/x/CHANGELOG.md more', 'changed');
203
+ });
204
+ expect(r.status).toBe(0);
205
+ expect(r.exempt).toBe('exempt=false');
206
+ expect(r.log).toContain('paths outside the shape');
207
+ expect(r.log).toContain('packages/x/CHANGELOG.md more');
208
+ });
209
+ it('an empty diff while changesets are pending — not exempt', () => {
210
+ const r = scenario('base', () => undefined);
211
+ expect(r.status).toBe(0);
212
+ expect(r.exempt).toBe('exempt=false');
213
+ expect(r.log).toContain('not exactly the pending set');
214
+ });
215
+ it('an empty diff with nothing pending — exempt (nothing to judge)', () => {
216
+ const r = scenario('base-empty', () => undefined);
217
+ expect(r.status).toBe(0);
218
+ expect(r.exempt).toBe('exempt=true');
219
+ });
220
+ it('a base ref that does not resolve — the derivation fails, nothing is written (fail-closed)', () => {
221
+ const r = shape(repo, 'no-such-ref');
222
+ expect(r.status).not.toBe(0);
223
+ expect(r.exempt).toBe('');
224
+ });
225
+ });
226
+ //# sourceMappingURL=release-train-shape.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release-train-shape.test.js","sourceRoot":"","sources":["../../src/commands/release-train-shape.test.ts"],"names":[],"mappings":"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"}
@@ -7,15 +7,28 @@ export { SYSTEM_PROMPT as SPEC_SYSTEM_PROMPT };
7
7
  * single-quoted `node -e '…'` body via `JSON.stringify` (the `runsDir`
8
8
  * precedent) and checks the draft carries each heading with a non-blank body.
9
9
  *
10
+ * Since mmnto-ai/totem#2737 the promise is the FULL skeleton: all nine `### `
11
+ * lines of {@link SYSTEM_PROMPT}, in prompt order. It named two of them before,
12
+ * which made the gate weaker than the command's own ask — the seven drafts
13
+ * recorded in `.totem/fixtures/spec-runs-2026-09-02/` all passed it while three
14
+ * carried an empty or an unmatched promised section.
15
+ *
10
16
  * Two invariants keep the two halves honest, both unit-tested:
11
17
  * 1. every entry is a VERBATIM line of {@link SYSTEM_PROMPT} — the gate can
12
18
  * only require what the command actually asks for;
13
- * 2. every entry is RENDERABLE into the reader (no quote, backslash, dollar,
14
- * backtick, newline or control character the mmnto-ai/totem#2692 C4
15
- * predicate), so a new heading can never break the hook silently.
19
+ * 2. every entry is RENDERABLE into the reader as a HEADING — no quote,
20
+ * backslash, dollar, backtick, or line-breaking character from the set the
21
+ * reader's `safe()` collapses: C0, the DEL/C1 band, and U+2028/U+2029
22
+ * (`hasUnrenderableHeadingChar`).
23
+ * Printable non-ASCII is permitted, unlike the path predicate that bans
24
+ * everything above 0x7e for git's C-quoting of `diff --name-only` output: a
25
+ * heading meets no path filter. That the em dash in the Verification heading
26
+ * really does survive `JSON.stringify` → the single-quoted `node -e` word →
27
+ * `sh` → node is not argued but EXECUTED, by the frozen falsifier in
28
+ * `install-hooks.test.ts` over the four schema-constrained R3 drafts.
16
29
  *
17
30
  * The skeleton is only applied to a draft written under the BUILT-IN prompt;
18
31
  * an override prompt is held to the looser DOCUMENT shape instead.
19
32
  */
20
- export declare const SPEC_REQUIRED_SECTIONS: readonly ["### Problem Statement", "### Implementation Tasks"];
33
+ export declare const SPEC_REQUIRED_SECTIONS: readonly ["### Problem Statement", "### Architectural Context", "### Files to Examine", "### Technical Approach & Contracts", "### Edge Cases & Traps", "### Implementation Tasks", "### Execution Flow (structural constraint)", "### Verification (MANDATORY — do not skip)", "### Test Plan"];
21
34
  //# sourceMappingURL=spec-templates.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"spec-templates.d.ts","sourceRoot":"","sources":["../../src/commands/spec-templates.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,aAAa,g7JAwEzB,CAAC;AAEF,OAAO,EAAE,aAAa,IAAI,kBAAkB,EAAE,CAAC;AAE/C;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,sBAAsB,gEAGzB,CAAC"}
1
+ {"version":3,"file":"spec-templates.d.ts","sourceRoot":"","sources":["../../src/commands/spec-templates.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,aAAa,g7JAwEzB,CAAC;AAEF,OAAO,EAAE,aAAa,IAAI,kBAAkB,EAAE,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,sBAAsB,kSAUzB,CAAC"}
@@ -81,18 +81,38 @@ export { SYSTEM_PROMPT as SPEC_SYSTEM_PROMPT };
81
81
  * single-quoted `node -e '…'` body via `JSON.stringify` (the `runsDir`
82
82
  * precedent) and checks the draft carries each heading with a non-blank body.
83
83
  *
84
+ * Since mmnto-ai/totem#2737 the promise is the FULL skeleton: all nine `### `
85
+ * lines of {@link SYSTEM_PROMPT}, in prompt order. It named two of them before,
86
+ * which made the gate weaker than the command's own ask — the seven drafts
87
+ * recorded in `.totem/fixtures/spec-runs-2026-09-02/` all passed it while three
88
+ * carried an empty or an unmatched promised section.
89
+ *
84
90
  * Two invariants keep the two halves honest, both unit-tested:
85
91
  * 1. every entry is a VERBATIM line of {@link SYSTEM_PROMPT} — the gate can
86
92
  * only require what the command actually asks for;
87
- * 2. every entry is RENDERABLE into the reader (no quote, backslash, dollar,
88
- * backtick, newline or control character the mmnto-ai/totem#2692 C4
89
- * predicate), so a new heading can never break the hook silently.
93
+ * 2. every entry is RENDERABLE into the reader as a HEADING — no quote,
94
+ * backslash, dollar, backtick, or line-breaking character from the set the
95
+ * reader's `safe()` collapses: C0, the DEL/C1 band, and U+2028/U+2029
96
+ * (`hasUnrenderableHeadingChar`).
97
+ * Printable non-ASCII is permitted, unlike the path predicate that bans
98
+ * everything above 0x7e for git's C-quoting of `diff --name-only` output: a
99
+ * heading meets no path filter. That the em dash in the Verification heading
100
+ * really does survive `JSON.stringify` → the single-quoted `node -e` word →
101
+ * `sh` → node is not argued but EXECUTED, by the frozen falsifier in
102
+ * `install-hooks.test.ts` over the four schema-constrained R3 drafts.
90
103
  *
91
104
  * The skeleton is only applied to a draft written under the BUILT-IN prompt;
92
105
  * an override prompt is held to the looser DOCUMENT shape instead.
93
106
  */
94
107
  export const SPEC_REQUIRED_SECTIONS = [
95
108
  '### Problem Statement',
109
+ '### Architectural Context',
110
+ '### Files to Examine',
111
+ '### Technical Approach & Contracts',
112
+ '### Edge Cases & Traps',
96
113
  '### Implementation Tasks',
114
+ '### Execution Flow (structural constraint)',
115
+ '### Verification (MANDATORY — do not skip)',
116
+ '### Test Plan',
97
117
  ];
98
118
  //# sourceMappingURL=spec-templates.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"spec-templates.js","sourceRoot":"","sources":["../../src/commands/spec-templates.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,0EAA0E;AAE1E,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwE5B,CAAC;AAEF,OAAO,EAAE,aAAa,IAAI,kBAAkB,EAAE,CAAC;AAE/C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,uBAAuB;IACvB,0BAA0B;CAClB,CAAC"}
1
+ {"version":3,"file":"spec-templates.js","sourceRoot":"","sources":["../../src/commands/spec-templates.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,0EAA0E;AAE1E,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwE5B,CAAC;AAEF,OAAO,EAAE,aAAa,IAAI,kBAAkB,EAAE,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,uBAAuB;IACvB,2BAA2B;IAC3B,sBAAsB;IACtB,oCAAoC;IACpC,wBAAwB;IACxB,0BAA0B;IAC1B,4CAA4C;IAC5C,4CAA4C;IAC5C,eAAe;CACP,CAAC"}
@@ -194,21 +194,64 @@ export interface GroundingFloorVerdict {
194
194
  withheld: WithheldCandidate[];
195
195
  /** Items with no relevance at all (FTS-only) — floor-EXEMPT, never withheld for a weak sibling's sake. */
196
196
  floorExempt: number;
197
+ /**
198
+ * Items whose vector-leg relevance failed the range predicate (non-finite, or
199
+ * outside [0, 1] — under `l2` a negative `_distance`: an SDK or data fault).
200
+ * Neither signal nor exemption: a fault cannot raise `bestRelevance`, cannot
201
+ * be withheld as a measurement, and cannot save a run the way a keyword-only
202
+ * hit does. A run whose every hit is faulted refuses — nothing usable grounds
203
+ * it (mmnto-ai/totem#2761 bot round, Greptile P1).
204
+ */
205
+ faulted: number;
197
206
  }
198
207
  /**
199
208
  * Judge the retrieval against the relevance floor (mmnto-ai/totem#2700), over
200
209
  * the spec, session and code partitions — that three-partition scoping is
201
210
  * mmnto-ai/totem#2735's decision, not mmnto-ai/totem#2700's, and the body
202
- * comment below says why. Mirrors the MCP tool's semantics
203
- * (`packages/mcp/src/tools/search-knowledge.ts`): the floor fires only when a
204
- * real relevance signal exists, and judges only the hits that carry one
205
- * keyword-only hits have no comparable relevance and are floor-EXEMPT, so a
206
- * mixed batch is never withheld because its vector-leg siblings scored weak.
211
+ * comment below says why. Shares the MCP tool's floor SHAPE
212
+ * (`packages/mcp/src/tools/search-knowledge.ts`) but not, since the bot round
213
+ * on mmnto-ai/totem#2761, its predicate: the MCP reader still selects relevances
214
+ * on a bare `typeof` and would read an out-of-range value as signal, while this
215
+ * gate classes it as FAULTED and refuses an all-faulted retrieval outright
216
+ * the one arm here that fires with NO real signal present. Otherwise the floor
217
+ * fires only when a real relevance signal exists, and it is a WHOLE-RUN gate on the BEST
218
+ * relevance, never a per-item filter — keyword-only hits have no comparable
219
+ * relevance and are floor-EXEMPT, so a single exempt hit from one of those
220
+ * three partitions saves the run.
221
+ *
222
+ * `floor` is OPTIONAL since mmnto-ai/totem#2727: `searchRelevanceFloor` carries
223
+ * no default, and with none configured the below-floor arm cannot fire at all
224
+ * (`withheld` stays empty). `bestRelevance` and `floorExempt` are still
225
+ * measured and returned — the measurement is not conditional on a floor.
207
226
  *
208
227
  * Zero items is this command's OWN rule, not an MCP mirror: nothing retrieved
209
- * means nothing grounds the run, so it refuses regardless of any floor.
228
+ * means nothing grounds the run, so it refuses regardless of any floor. Lessons
229
+ * do not ground a run — ruled final on mmnto-ai/totem#2727 — so they are
230
+ * delivered but never judged here.
231
+ *
232
+ * `isInRange` is core's `isRelevanceInRange` — the SAME predicate the grounding
233
+ * bundle builder omits on (mmnto-ai/totem#2738 fold 2, F2). It is a PARAMETER
234
+ * rather than a module-level import because a static value import from
235
+ * `@mmnto/totem` in `commands/**` pulls LanceDB into every CLI startup,
236
+ * including `--help` (mmnto-ai/totem#2339, an enforced rule); the one
237
+ * production caller supplies it from the dynamic `await import('@mmnto/totem')`
238
+ * the rule prescribes. Injecting a different predicate here would put the
239
+ * refusal gate and the run artifact back into disagreement about the same hit.
240
+ *
241
+ * Three classes of hit, judged by what the hit carries: a relevance IN range is
242
+ * SIGNAL; no relevance at all (a keyword-only hit) is EXEMPT and can save the
243
+ * run; a relevance that fails the predicate is FAULTED — omitted from the
244
+ * artifact by the same predicate, and here neither signal nor exemption, so a
245
+ * fault can never authorize synthesis (the mmnto-ai/totem#2761 bot round,
246
+ * Greptile P1, refuted the earlier "exempt" reading: an SDK fault is not
247
+ * evidence the way a keyword match is). A run whose hits are ALL faulted refuses.
248
+ *
249
+ * `isInRange` precedes `floor` deliberately: mmnto-ai/totem#2758 (open, also on
250
+ * this file) makes `floor` OPTIONAL, and a required parameter cannot follow an
251
+ * optional one. This PR merges AFTER #2758 and is rebased onto it, so the order
252
+ * is chosen to let that change land without another signature churn.
210
253
  */
211
- export declare function evaluateGroundingFloor(context: RetrievedContext, floor: number): GroundingFloorVerdict;
254
+ export declare function evaluateGroundingFloor(context: RetrievedContext, isInRange: (relevance: number) => boolean, floor?: number): GroundingFloorVerdict;
212
255
  /**
213
256
  * The refusal's text: the topic(s) refused, the measurement (`0 hits` or the
214
257
  * best relevance), the floor's VALUE and its PLACE, and every withheld
@@ -220,8 +263,14 @@ export declare function evaluateGroundingFloor(context: RetrievedContext, floor:
220
263
  * index grounds this run" beside `Found: … 10 lessons` — so when lessons were
221
264
  * delivered the message names them and says why they did not count
222
265
  * (mmnto-ai/totem#2735). With no lessons delivered the text is byte-unchanged.
266
+ *
267
+ * The floor line has TWO forms since mmnto-ai/totem#2727. With a value
268
+ * configured it names the value and its place; with none it says so plainly —
269
+ * a refusal that reached here without a floor did so on an arm that needs none
270
+ * (zero hits, or every hit faulted), and printing a number would claim a
271
+ * judgment no floor made.
223
272
  */
224
- export declare function formatGroundingRefusal(topics: string, verdict: GroundingFloorVerdict, floor: number, deliveredLessons: number): {
273
+ export declare function formatGroundingRefusal(topics: string, verdict: GroundingFloorVerdict, floor: number | undefined, deliveredLessons: number): {
225
274
  message: string;
226
275
  recoveryHint: string;
227
276
  };
@@ -1 +1 @@
1
- {"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../src/commands/spec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../src/commands/spec.ts"],"names":[],"mappings":"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"}