@mmnto/totem 1.122.0 → 1.124.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 (45) hide show
  1. package/dist/artifacts/legs.d.ts +430 -0
  2. package/dist/artifacts/legs.d.ts.map +1 -0
  3. package/dist/artifacts/legs.js +577 -0
  4. package/dist/artifacts/legs.js.map +1 -0
  5. package/dist/artifacts/legs.test.d.ts +19 -0
  6. package/dist/artifacts/legs.test.d.ts.map +1 -0
  7. package/dist/artifacts/legs.test.js +628 -0
  8. package/dist/artifacts/legs.test.js.map +1 -0
  9. package/dist/config-schema.d.ts +35 -0
  10. package/dist/config-schema.d.ts.map +1 -1
  11. package/dist/config-schema.js +28 -0
  12. package/dist/config-schema.js.map +1 -1
  13. package/dist/config-schema.test.js +73 -0
  14. package/dist/config-schema.test.js.map +1 -1
  15. package/dist/errors.d.ts +3 -1
  16. package/dist/errors.d.ts.map +1 -1
  17. package/dist/errors.js.map +1 -1
  18. package/dist/index.d.ts +5 -0
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +3 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/routing/legs-owed.d.ts +65 -0
  23. package/dist/routing/legs-owed.d.ts.map +1 -0
  24. package/dist/routing/legs-owed.js +72 -0
  25. package/dist/routing/legs-owed.js.map +1 -0
  26. package/dist/routing/legs-owed.test.d.ts +10 -0
  27. package/dist/routing/legs-owed.test.d.ts.map +1 -0
  28. package/dist/routing/legs-owed.test.js +119 -0
  29. package/dist/routing/legs-owed.test.js.map +1 -0
  30. package/dist/semantic-dedup.d.ts.map +1 -1
  31. package/dist/semantic-dedup.js +2 -5
  32. package/dist/semantic-dedup.js.map +1 -1
  33. package/dist/semantic-dedup.test.js +32 -1
  34. package/dist/semantic-dedup.test.js.map +1 -1
  35. package/dist/store/lance-store.test.js +23 -0
  36. package/dist/store/lance-store.test.js.map +1 -1
  37. package/dist/store/search-lessons.d.ts +18 -0
  38. package/dist/store/search-lessons.d.ts.map +1 -0
  39. package/dist/store/search-lessons.js +18 -0
  40. package/dist/store/search-lessons.js.map +1 -0
  41. package/dist/store/search-lessons.test.d.ts +2 -0
  42. package/dist/store/search-lessons.test.d.ts.map +1 -0
  43. package/dist/store/search-lessons.test.js +48 -0
  44. package/dist/store/search-lessons.test.js.map +1 -0
  45. package/package.json +1 -1
@@ -0,0 +1,628 @@
1
+ /**
2
+ * Leg-deposit store tests (mmnto-ai/totem#2698).
3
+ *
4
+ * These lock the core-owned half of the design's "invariants to lock in via
5
+ * tests": the store is read JSON-AWARE through the schema (a file that merely
6
+ * quotes `diffSha`/`findings` in some other shape is not a deposit), ancestry
7
+ * ranking is exact > nearest ancestor > latest read, a corrupt file is
8
+ * disclosed by name and reason and never hides a valid sibling,
9
+ * `unknown-commit` and `not-ancestor` are DISTINCT stale reasons, the schema
10
+ * refuses control bytes and a non-subset `folded` at write and at read alike,
11
+ * and the writer is create-exclusive with a disclosed replacement.
12
+ *
13
+ * Every hostile string is built with `String.fromCharCode` on purpose: a
14
+ * literal `\u`/`\x` escape authored through an editing tool has landed as a
15
+ * RAW control byte in this repo before, which would make the test assert
16
+ * something other than what it reads as.
17
+ */
18
+ import * as fs from 'node:fs';
19
+ import * as os from 'node:os';
20
+ import * as path from 'node:path';
21
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
22
+ import { countLegFindings, findLegDepositForHead, LEG_DEPOSIT_KNOWN_MAJOR, LEG_DEPOSIT_SCHEMA_VERSION, LEG_FINDING_SEVERITIES, LegDepositExistsError, legDepositPath, LegDepositSchema, legsDir, loadLegDeposits, renderLegField, saveLegDeposit, } from './legs.js';
23
+ const LF = String.fromCharCode(0x0a);
24
+ const NUL = String.fromCharCode(0x00);
25
+ const NEL = String.fromCharCode(0x85);
26
+ const ESC = String.fromCharCode(0x1b);
27
+ /** Distinct, deterministic 40-hex shas — the store's addresses. */
28
+ function sha(seed) {
29
+ return seed.repeat(40).slice(0, 40);
30
+ }
31
+ const HEAD = sha('a');
32
+ const OLDER = sha('b');
33
+ const OLDEST = sha('c');
34
+ const ELSEWHERE = sha('d');
35
+ function finding(overrides = {}) {
36
+ return {
37
+ id: 'F1',
38
+ severity: 'BLOCKING',
39
+ file: 'packages/core/src/artifacts/legs.ts',
40
+ line: 12,
41
+ claim: 'the loader throws on a corrupt file',
42
+ counterexample: 'loadLegDeposits returns a corrupt row instead',
43
+ ...overrides,
44
+ };
45
+ }
46
+ function deposit(overrides = {}) {
47
+ return {
48
+ schemaVersion: LEG_DEPOSIT_SCHEMA_VERSION,
49
+ diffSha: HEAD,
50
+ readAt: '2026-09-03T05:00:00.000Z',
51
+ findings: [finding()],
52
+ folded: ['F1'],
53
+ verdict: 'one blocking finding, folded',
54
+ ...overrides,
55
+ };
56
+ }
57
+ /** A git seam that knows a fixed commit set, ancestry map, and per-sha diff. */
58
+ function fakeGit(options) {
59
+ const ancestors = options.ancestors ?? {};
60
+ const reach = options.reach ?? {};
61
+ return {
62
+ isCommit: (candidate) => options.commits.includes(candidate),
63
+ isAncestor: (base) => Object.hasOwn(ancestors, base),
64
+ distance: (base) => ancestors[base] ?? 0,
65
+ changedFiles: (_base, head) => reach[head] ?? [],
66
+ };
67
+ }
68
+ /**
69
+ * Armed by a test to publish a COMPETING deposit inside the window between the
70
+ * occupancy pre-check and the exclusive publish (mmnto-ai/totem#2745).
71
+ *
72
+ * The seam is the atomic writer rather than `fs.existsSync`: a `node:fs` export
73
+ * cannot be spied under ESM (the namespace is not configurable), and this hook
74
+ * fires at exactly the moment a second process would land — after this writer's
75
+ * temp exists, before it claims the final name.
76
+ */
77
+ let publishInsideWindow;
78
+ vi.mock('../fs-atomic.js', async (importOriginal) => {
79
+ const actual = await importOriginal();
80
+ return {
81
+ ...actual,
82
+ writeFileAtomicSync: (target, data, options) => {
83
+ actual.writeFileAtomicSync(target, data, options);
84
+ const hook = publishInsideWindow;
85
+ // Cleared BEFORE firing: the competing write goes through this same
86
+ // wrapper and must not re-enter.
87
+ publishInsideWindow = undefined;
88
+ hook?.();
89
+ },
90
+ };
91
+ });
92
+ let tmpDir = '';
93
+ beforeEach(() => {
94
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-legs-'));
95
+ });
96
+ afterEach(() => {
97
+ fs.rmSync(tmpDir, { recursive: true, force: true });
98
+ });
99
+ /** Write raw bytes into the store, bypassing the writer (the hand-edit path). */
100
+ function writeRaw(name, content) {
101
+ fs.mkdirSync(legsDir(tmpDir), { recursive: true });
102
+ fs.writeFileSync(path.join(legsDir(tmpDir), name), content, 'utf-8');
103
+ }
104
+ describe('LegDepositSchema — the parse boundary', () => {
105
+ it('accepts a well-formed deposit and tolerates a forward-minor unknown key', () => {
106
+ const forward = { ...deposit(), schemaVersion: '1.7.0', futureField: 'ignored by this reader' };
107
+ const parsed = LegDepositSchema.safeParse(forward);
108
+ expect(parsed.success).toBe(true);
109
+ // Tolerated means STRIPPED, not preserved (the run-artifact precedent).
110
+ if (parsed.success)
111
+ expect('futureField' in parsed.data).toBe(false);
112
+ });
113
+ it('refuses a newer major BY NAME, not as generic corruption', () => {
114
+ const parsed = LegDepositSchema.safeParse({ ...deposit(), schemaVersion: '2.0.0' });
115
+ expect(parsed.success).toBe(false);
116
+ if (!parsed.success) {
117
+ expect(parsed.error.issues.map((i) => i.message).join(' ')).toContain(`this reader understands major ${LEG_DEPOSIT_KNOWN_MAJOR}.x`);
118
+ }
119
+ });
120
+ it('requires a full 40-hex lowercase diffSha', () => {
121
+ for (const bad of [HEAD.slice(0, 8), HEAD.toUpperCase(), `${HEAD}0`, 'not-a-sha']) {
122
+ expect(LegDepositSchema.safeParse({ ...deposit(), diffSha: bad }).success, bad).toBe(false);
123
+ }
124
+ });
125
+ it('requires finding ids to be unique', () => {
126
+ const parsed = LegDepositSchema.safeParse(deposit({
127
+ findings: [finding({ id: 'F1' }), finding({ id: 'F1', claim: 'a second claim' })],
128
+ folded: [],
129
+ }));
130
+ expect(parsed.success).toBe(false);
131
+ if (!parsed.success) {
132
+ expect(parsed.error.issues.some((i) => i.message.includes('duplicate finding id'))).toBe(true);
133
+ }
134
+ });
135
+ it('requires folded to be a SUBSET of the finding ids', () => {
136
+ const parsed = LegDepositSchema.safeParse(deposit({ findings: [finding({ id: 'F1' })], folded: ['F1', 'F9'] }));
137
+ expect(parsed.success).toBe(false);
138
+ if (!parsed.success) {
139
+ expect(parsed.error.issues.some((i) => i.message.includes('"F9"'))).toBe(true);
140
+ expect(parsed.error.issues.some((i) => i.path.join('.') === 'folded.1')).toBe(true);
141
+ }
142
+ });
143
+ it('accepts empty findings and empty folded — a leg that found nothing still deposits', () => {
144
+ expect(LegDepositSchema.safeParse(deposit({ findings: [], folded: [], verdict: 'no findings' }))
145
+ .success).toBe(true);
146
+ });
147
+ it('refuses a multi-line verdict', () => {
148
+ const parsed = LegDepositSchema.safeParse(deposit({ verdict: `line one${LF}line two` }));
149
+ expect(parsed.success).toBe(false);
150
+ if (!parsed.success)
151
+ expect(parsed.error.issues[0]?.path.join('.')).toBe('verdict');
152
+ });
153
+ it('refuses control bytes in verdict, claim, counterexample and file', () => {
154
+ const cases = [
155
+ ['verdict', deposit({ verdict: `ok${NUL}` })],
156
+ ['findings.0.claim', deposit({ findings: [finding({ claim: `c${NEL}` })], folded: [] })],
157
+ [
158
+ 'findings.0.counterexample',
159
+ deposit({ findings: [finding({ counterexample: `${ESC}[2J` })], folded: [] }),
160
+ ],
161
+ ['findings.0.file', deposit({ findings: [finding({ file: `a.ts${LF}b.ts` })], folded: [] })],
162
+ ];
163
+ for (const [expectedPath, candidate] of cases) {
164
+ const parsed = LegDepositSchema.safeParse(candidate);
165
+ expect(parsed.success, expectedPath).toBe(false);
166
+ if (!parsed.success) {
167
+ expect(parsed.error.issues.map((i) => i.path.join('.'))).toContain(expectedPath);
168
+ }
169
+ }
170
+ });
171
+ it('allows an EMPTY counterexample but not an empty claim, file or verdict', () => {
172
+ expect(LegDepositSchema.safeParse(deposit({ findings: [finding({ counterexample: '' })], folded: [] })).success).toBe(true);
173
+ expect(LegDepositSchema.safeParse(deposit({ findings: [finding({ claim: '' })], folded: [] }))
174
+ .success).toBe(false);
175
+ expect(LegDepositSchema.safeParse(deposit({ findings: [finding({ file: '' })], folded: [] }))
176
+ .success).toBe(false);
177
+ expect(LegDepositSchema.safeParse(deposit({ verdict: '' })).success).toBe(false);
178
+ });
179
+ it('refuses a negative or fractional line, accepts 0', () => {
180
+ expect(LegDepositSchema.safeParse(deposit({ findings: [finding({ line: 0 })], folded: [] })).success).toBe(true);
181
+ expect(LegDepositSchema.safeParse(deposit({ findings: [finding({ line: -1 })], folded: [] }))
182
+ .success).toBe(false);
183
+ expect(LegDepositSchema.safeParse(deposit({ findings: [finding({ line: 1.5 })], folded: [] }))
184
+ .success).toBe(false);
185
+ });
186
+ it('pins the severity vocabulary as a set', () => {
187
+ expect([...LEG_FINDING_SEVERITIES]).toEqual(['BLOCKING', 'MATERIAL', 'MINOR']);
188
+ expect(LegDepositSchema.safeParse(deposit({ findings: [finding({ severity: 'CRITICAL' })], folded: [] })).success).toBe(false);
189
+ });
190
+ });
191
+ describe('saveLegDeposit — create-exclusive, atomic, validate-first', () => {
192
+ it('stores the deposit at <diffSha>.json with a diffSha equal to the name', () => {
193
+ const result = saveLegDeposit(tmpDir, deposit());
194
+ expect(result.path).toBe(legDepositPath(tmpDir, HEAD));
195
+ expect(path.basename(result.path)).toBe(`${HEAD}.json`);
196
+ expect(result.replaced).toBeUndefined();
197
+ const onDisk = JSON.parse(fs.readFileSync(result.path, 'utf-8'));
198
+ expect(onDisk.diffSha).toBe(path.basename(result.path, '.json'));
199
+ });
200
+ it('refuses an existing sha without replace, naming the incumbent readAt', () => {
201
+ saveLegDeposit(tmpDir, deposit({ readAt: '2026-09-01T00:00:00.000Z' }));
202
+ let caught;
203
+ try {
204
+ saveLegDeposit(tmpDir, deposit({ readAt: '2026-09-03T00:00:00.000Z' }));
205
+ }
206
+ catch (err) {
207
+ caught = err;
208
+ }
209
+ expect(caught).toBeInstanceOf(LegDepositExistsError);
210
+ const refusal = caught;
211
+ expect(refusal.code).toBe('LEG_DEPOSIT_EXISTS');
212
+ expect(refusal.existingReadAt).toBe('2026-09-01T00:00:00.000Z');
213
+ expect(refusal.message).toContain('2026-09-01T00:00:00.000Z');
214
+ // The refused write did NOT touch the incumbent.
215
+ const onDisk = JSON.parse(fs.readFileSync(legDepositPath(tmpDir, HEAD), 'utf-8'));
216
+ expect(onDisk.readAt).toBe('2026-09-01T00:00:00.000Z');
217
+ });
218
+ it('replaces with the OLD readAt reported', () => {
219
+ saveLegDeposit(tmpDir, deposit({ readAt: '2026-09-01T00:00:00.000Z' }));
220
+ const result = saveLegDeposit(tmpDir, deposit({ readAt: '2026-09-03T00:00:00.000Z' }), {
221
+ replace: true,
222
+ });
223
+ expect(result.replaced).toEqual({ readAt: '2026-09-01T00:00:00.000Z' });
224
+ const onDisk = JSON.parse(fs.readFileSync(result.path, 'utf-8'));
225
+ expect(onDisk.readAt).toBe('2026-09-03T00:00:00.000Z');
226
+ });
227
+ it('replaces a CORRUPT incumbent, disclosing that its instant was unreadable', () => {
228
+ writeRaw(`${HEAD}.json`, 'not json at all');
229
+ const result = saveLegDeposit(tmpDir, deposit(), { replace: true });
230
+ expect(result.replaced).toEqual({ readAt: undefined });
231
+ expect(loadLegDeposits(tmpDir).deposits).toHaveLength(1);
232
+ });
233
+ it('leaves NO file and NO temp behind on a validation failure', () => {
234
+ expect(() => saveLegDeposit(tmpDir, deposit({ verdict: `bad${LF}verdict` }))).toThrow();
235
+ expect(fs.existsSync(legsDir(tmpDir))).toBe(false);
236
+ // …and none beside an existing store either.
237
+ saveLegDeposit(tmpDir, deposit({ diffSha: OLDER }));
238
+ expect(() => saveLegDeposit(tmpDir, deposit({ diffSha: HEAD, folded: ['nope'] }))).toThrow();
239
+ expect(fs.readdirSync(legsDir(tmpDir))).toEqual([`${OLDER}.json`]);
240
+ });
241
+ it('leaves no temp file behind on a successful write either', () => {
242
+ saveLegDeposit(tmpDir, deposit());
243
+ expect(fs.readdirSync(legsDir(tmpDir)).filter((f) => f.endsWith('.tmp'))).toEqual([]);
244
+ });
245
+ });
246
+ describe('loadLegDeposits — tolerant, JSON-aware, never throws', () => {
247
+ it('returns empty results when the store directory does not exist', () => {
248
+ expect(loadLegDeposits(tmpDir)).toEqual({ deposits: [], corrupt: [] });
249
+ });
250
+ it('ignores non-.json entries entirely (not deposits, not corrupt rows)', () => {
251
+ saveLegDeposit(tmpDir, deposit());
252
+ writeRaw('notes.md', 'a leg wrote prose here');
253
+ writeRaw('.gitkeep', '');
254
+ const result = loadLegDeposits(tmpDir);
255
+ expect(result.deposits).toHaveLength(1);
256
+ expect(result.corrupt).toEqual([]);
257
+ });
258
+ it('is JSON-AWARE: a file that merely QUOTES diffSha/findings is corrupt, not a deposit', () => {
259
+ // A review artifact copied into the store: same words, different shape.
260
+ writeRaw(`${HEAD}.json`, JSON.stringify({
261
+ schemaVersion: '1.0.0',
262
+ note: `this record mentions diffSha ${HEAD} and findings but is a verdict artifact`,
263
+ findings: 3,
264
+ lanes: ['anthropic:claude-opus-5'],
265
+ }));
266
+ const result = loadLegDeposits(tmpDir);
267
+ expect(result.deposits).toEqual([]);
268
+ expect(result.corrupt).toHaveLength(1);
269
+ expect(result.corrupt[0]?.file).toBe(`${HEAD}.json`);
270
+ expect(result.corrupt[0]?.reason).toContain('schema-invalid');
271
+ });
272
+ it('discloses each corrupt file by name and reason WITHOUT hiding a valid sibling', () => {
273
+ saveLegDeposit(tmpDir, deposit({ diffSha: HEAD }));
274
+ writeRaw(`${OLDER}.json`, '{ this is not json');
275
+ writeRaw(`${OLDEST}.json`, JSON.stringify({ ...deposit({ diffSha: OLDEST }), verdict: '' }));
276
+ const result = loadLegDeposits(tmpDir);
277
+ expect(result.deposits.map((d) => d.diffSha)).toEqual([HEAD]);
278
+ expect(result.corrupt.map((c) => c.file).sort()).toEqual([`${OLDER}.json`, `${OLDEST}.json`].sort());
279
+ const unreadable = result.corrupt.find((c) => c.file === `${OLDER}.json`);
280
+ expect(unreadable?.reason).toContain('unreadable or not JSON');
281
+ const invalid = result.corrupt.find((c) => c.file === `${OLDEST}.json`);
282
+ expect(invalid?.reason).toContain('verdict');
283
+ });
284
+ it('every corrupt reason is ONE echo-safe line', () => {
285
+ writeRaw(`${HEAD}.json`, JSON.stringify(deposit({ verdict: `a${LF}b${NUL}c` })));
286
+ const [row] = loadLegDeposits(tmpDir).corrupt;
287
+ expect(row).toBeDefined();
288
+ const reason = row?.reason ?? '';
289
+ for (let i = 0; i < reason.length; i++) {
290
+ const code = reason.charCodeAt(i);
291
+ expect(code < 32 || (code >= 127 && code <= 159), `code ${code} at ${i}`).toBe(false);
292
+ }
293
+ });
294
+ it('refuses a newer-major deposit BY NAME rather than as corruption', () => {
295
+ writeRaw(`${HEAD}.json`, JSON.stringify({ ...deposit(), schemaVersion: '2.0.0' }));
296
+ const result = loadLegDeposits(tmpDir);
297
+ expect(result.deposits).toEqual([]);
298
+ expect(result.corrupt[0]?.reason).toContain('written by a newer totem');
299
+ expect(result.corrupt[0]?.reason).toContain('upgrade @mmnto/cli');
300
+ });
301
+ it('refuses a file whose NAME disagrees with its stored diffSha', () => {
302
+ writeRaw(`${OLDER}.json`, JSON.stringify(deposit({ diffSha: HEAD })));
303
+ const result = loadLegDeposits(tmpDir);
304
+ expect(result.deposits).toEqual([]);
305
+ expect(result.corrupt[0]?.reason).toContain('filename does not match its stored diffSha');
306
+ });
307
+ });
308
+ describe('findLegDepositForHead — ancestor-or-equal resolution', () => {
309
+ it('resolves nothing (but still discloses) when the store is empty', () => {
310
+ const resolution = findLegDepositForHead(tmpDir, HEAD, fakeGit({ commits: [] }));
311
+ expect(resolution.winner).toBeUndefined();
312
+ expect(resolution).toMatchObject({ superseded: [], stale: [], corrupt: [] });
313
+ });
314
+ it('EXACT outranks ancestor', () => {
315
+ saveLegDeposit(tmpDir, deposit({ diffSha: HEAD, readAt: '2026-09-01T00:00:00.000Z' }));
316
+ saveLegDeposit(tmpDir, deposit({ diffSha: OLDER, readAt: '2026-09-03T00:00:00.000Z' }));
317
+ const resolution = findLegDepositForHead(tmpDir, HEAD, fakeGit({ commits: [OLDER], ancestors: { [OLDER]: 1 } }));
318
+ expect(resolution.winner?.diffSha).toBe(HEAD);
319
+ expect(resolution.winner?.rank).toBe('exact');
320
+ expect(resolution.winner?.distance).toBe(0);
321
+ expect(resolution.superseded).toEqual([
322
+ { diffSha: OLDER, readAt: '2026-09-03T00:00:00.000Z', rank: 'ancestor', distance: 1 },
323
+ ]);
324
+ });
325
+ it('the NEAREST ancestor outranks a farther one', () => {
326
+ saveLegDeposit(tmpDir, deposit({ diffSha: OLDER, readAt: '2026-09-01T00:00:00.000Z' }));
327
+ saveLegDeposit(tmpDir, deposit({ diffSha: OLDEST, readAt: '2026-09-03T00:00:00.000Z' }));
328
+ const resolution = findLegDepositForHead(tmpDir, HEAD, fakeGit({ commits: [OLDER, OLDEST], ancestors: { [OLDER]: 2, [OLDEST]: 9 } }));
329
+ expect(resolution.winner?.diffSha).toBe(OLDER);
330
+ expect(resolution.winner?.rank).toBe('ancestor');
331
+ expect(resolution.winner?.distance).toBe(2);
332
+ expect(resolution.superseded.map((s) => s.diffSha)).toEqual([OLDEST]);
333
+ });
334
+ it('equal distance resolves to the LATEST readAt', () => {
335
+ saveLegDeposit(tmpDir, deposit({ diffSha: OLDER, readAt: '2026-09-01T00:00:00.000Z' }));
336
+ saveLegDeposit(tmpDir, deposit({ diffSha: OLDEST, readAt: '2026-09-02T00:00:00.000Z' }));
337
+ const resolution = findLegDepositForHead(tmpDir, HEAD, fakeGit({ commits: [OLDER, OLDEST], ancestors: { [OLDER]: 3, [OLDEST]: 3 } }));
338
+ expect(resolution.winner?.diffSha).toBe(OLDEST);
339
+ expect(resolution.superseded.map((s) => s.diffSha)).toEqual([OLDER]);
340
+ });
341
+ it('distinguishes unknown-commit from not-ancestor', () => {
342
+ saveLegDeposit(tmpDir, deposit({ diffSha: ELSEWHERE }));
343
+ saveLegDeposit(tmpDir, deposit({ diffSha: OLDER }));
344
+ const resolution = findLegDepositForHead(tmpDir, HEAD,
345
+ // OLDER is a commit here but on another branch; ELSEWHERE is unknown.
346
+ fakeGit({ commits: [OLDER], ancestors: {} }));
347
+ expect(resolution.winner).toBeUndefined();
348
+ expect(resolution.stale
349
+ .map((s) => ({ diffSha: s.diffSha, reason: s.reason }))
350
+ .sort((a, b) => a.diffSha.localeCompare(b.diffSha))).toEqual([
351
+ { diffSha: OLDER, reason: 'not-ancestor' },
352
+ { diffSha: ELSEWHERE, reason: 'unknown-commit' },
353
+ ].sort((a, b) => a.diffSha.localeCompare(b.diffSha)));
354
+ });
355
+ it('an EXACT match never consults the git seam', () => {
356
+ saveLegDeposit(tmpDir, deposit({ diffSha: HEAD }));
357
+ const explodes = {
358
+ isCommit: () => {
359
+ throw new Error('isCommit must not be called for an exact match');
360
+ },
361
+ isAncestor: () => {
362
+ throw new Error('isAncestor must not be called for an exact match');
363
+ },
364
+ distance: () => {
365
+ throw new Error('distance must not be called for an exact match');
366
+ },
367
+ changedFiles: () => {
368
+ throw new Error('changedFiles must not be called for an exact match');
369
+ },
370
+ };
371
+ expect(findLegDepositForHead(tmpDir, HEAD, explodes).winner?.rank).toBe('exact');
372
+ // Including under a coverage query: an exact match covers everything BY
373
+ // CONSTRUCTION, so measuring it would be a git call to confirm a tautology
374
+ // (mmnto-ai/totem#2698 fold 3).
375
+ const covered = findLegDepositForHead(tmpDir, HEAD, explodes, {
376
+ base: 'main',
377
+ owedFiles: ['docs/wiki/a.md', 'docs/wiki/b.md'],
378
+ });
379
+ expect(covered.winner?.coverage).toEqual({ covered: 2, owed: 2, missing: [] });
380
+ });
381
+ it('a corrupt file rides the resolution and never masks the valid winner', () => {
382
+ saveLegDeposit(tmpDir, deposit({ diffSha: HEAD }));
383
+ writeRaw(`${OLDER}.json`, 'garbage');
384
+ const resolution = findLegDepositForHead(tmpDir, HEAD, fakeGit({ commits: [] }));
385
+ expect(resolution.winner?.diffSha).toBe(HEAD);
386
+ expect(resolution.corrupt.map((c) => c.file)).toEqual([`${OLDER}.json`]);
387
+ });
388
+ });
389
+ describe('countLegFindings + renderLegField — the covariate v1.2 field', () => {
390
+ it('counts every severity, and folded findings stay counted in their bucket', () => {
391
+ const counts = countLegFindings(deposit({
392
+ findings: [
393
+ finding({ id: 'F1', severity: 'BLOCKING' }),
394
+ finding({ id: 'F2', severity: 'BLOCKING' }),
395
+ finding({ id: 'F3', severity: 'MATERIAL' }),
396
+ finding({ id: 'F4', severity: 'MINOR' }),
397
+ ],
398
+ folded: ['F1', 'F3'],
399
+ }));
400
+ expect(counts).toEqual({ blocking: 2, material: 1, minor: 1, folded: 2 });
401
+ });
402
+ it('renders EXACTLY `leg: <sha8> blocking=N material=N folded=N`', () => {
403
+ const rendered = renderLegField(deposit({
404
+ diffSha: HEAD,
405
+ findings: [
406
+ finding({ id: 'F1', severity: 'BLOCKING' }),
407
+ finding({ id: 'F2', severity: 'MATERIAL' }),
408
+ finding({ id: 'F3', severity: 'MINOR' }),
409
+ ],
410
+ folded: ['F2'],
411
+ }));
412
+ expect(rendered).toBe(`leg: ${HEAD.slice(0, 8)} blocking=1 material=1 folded=1`);
413
+ });
414
+ it('renders EXACTLY `leg: none` for no deposit', () => {
415
+ expect(renderLegField(undefined)).toBe('leg: none');
416
+ });
417
+ it('renders zeroes for a leg that found nothing', () => {
418
+ expect(renderLegField(deposit({ findings: [], folded: [] }))).toBe(`leg: ${HEAD.slice(0, 8)} blocking=0 material=0 folded=0`);
419
+ });
420
+ });
421
+ // ─── Coverage as a freshness predicate (mmnto-ai/totem#2698 fold 3) ─────────
422
+ //
423
+ // Ancestry alone is not freshness: a deposit against the branch's MERGE BASE
424
+ // satisfies ancestor-or-equal and reports a small distance, while the leg that
425
+ // wrote it saw none of the diff the push proposes. That exhibit is what the
426
+ // operator ruled on, so it is the first case here.
427
+ describe('findLegDepositForHead — coverage (mmnto-ai/totem#2698 fold 3)', () => {
428
+ const OWED = ['docs/wiki/enforcement-model.md', 'docs/wiki/cli-reference.md', 'adr/adr-1.md'];
429
+ const COVERAGE = { base: 'main', owedFiles: OWED };
430
+ it('an ancestor whose diff contains NO owed path is stale, not a winner', () => {
431
+ // The merge-base shape: a real commit, a real ancestor, one commit behind —
432
+ // and its own branch diff touched something else entirely.
433
+ saveLegDeposit(tmpDir, deposit({ diffSha: OLDER }));
434
+ const resolution = findLegDepositForHead(tmpDir, HEAD, fakeGit({
435
+ commits: [OLDER],
436
+ ancestors: { [OLDER]: 1 },
437
+ reach: { [OLDER]: ['src/other.ts'] },
438
+ }), COVERAGE);
439
+ expect(resolution.winner).toBeUndefined();
440
+ expect(resolution.stale).toEqual([
441
+ { diffSha: OLDER, readAt: expect.any(String), reason: 'no-coverage' },
442
+ ]);
443
+ });
444
+ it('the same deposit WINS without a coverage query — the predicate is opt-in', () => {
445
+ // Which is what makes a caller that cannot resolve a branch base (a staged
446
+ // scope) behave exactly as it did before, and say so.
447
+ saveLegDeposit(tmpDir, deposit({ diffSha: OLDER }));
448
+ const resolution = findLegDepositForHead(tmpDir, HEAD, fakeGit({
449
+ commits: [OLDER],
450
+ ancestors: { [OLDER]: 1 },
451
+ reach: { [OLDER]: ['src/other.ts'] },
452
+ }));
453
+ expect(resolution.winner?.diffSha).toBe(OLDER);
454
+ expect(resolution.winner?.coverage).toBeUndefined();
455
+ expect(resolution.stale).toEqual([]);
456
+ });
457
+ it('PARTIAL coverage resolves, and names exactly what the leg could not have read', () => {
458
+ saveLegDeposit(tmpDir, deposit({ diffSha: OLDER }));
459
+ const resolution = findLegDepositForHead(tmpDir, HEAD, fakeGit({
460
+ commits: [OLDER],
461
+ ancestors: { [OLDER]: 4 },
462
+ // It read one of the three owed paths, plus files nobody owes.
463
+ reach: { [OLDER]: ['docs/wiki/cli-reference.md', 'src/unrelated.ts'] },
464
+ }), COVERAGE);
465
+ expect(resolution.winner?.diffSha).toBe(OLDER);
466
+ expect(resolution.winner?.distance).toBe(4);
467
+ // K < N is DISCLOSURE, never a block — the fold re-arm doctrine owes the
468
+ // new read, and this number is what makes that question legible.
469
+ expect(resolution.winner?.coverage).toEqual({
470
+ covered: 1,
471
+ owed: 3,
472
+ missing: ['docs/wiki/enforcement-model.md', 'adr/adr-1.md'],
473
+ });
474
+ });
475
+ it('a duplicated owed path never inflates the denominator', () => {
476
+ // `owedFiles` comes from the BASIS, where one file matching three globs
477
+ // appears three times. `covers 1/3` for a single file would be unreadable.
478
+ saveLegDeposit(tmpDir, deposit({ diffSha: OLDER }));
479
+ const resolution = findLegDepositForHead(tmpDir, HEAD, fakeGit({ commits: [OLDER], ancestors: { [OLDER]: 1 }, reach: { [OLDER]: ['README.md'] } }), { base: 'main', owedFiles: ['README.md', 'README.md', 'README.md'] });
480
+ expect(resolution.winner?.coverage).toEqual({ covered: 1, owed: 1, missing: [] });
481
+ });
482
+ it('nothing owed spends NO reach probe (the intersection cannot change)', () => {
483
+ // mmnto-ai/totem#2698 fold 5, Q3: with an empty owed set the answer is
484
+ // `0/0` whatever the candidate reached, so the probe is a git call whose
485
+ // result is discarded. An adapter that would throw on one proves it is
486
+ // never made.
487
+ saveLegDeposit(tmpDir, deposit({ diffSha: OLDER }));
488
+ const resolution = findLegDepositForHead(tmpDir, HEAD, {
489
+ isCommit: () => true,
490
+ isAncestor: () => true,
491
+ distance: () => 2,
492
+ changedFiles: () => {
493
+ throw new Error('changedFiles must not be called when nothing is owed');
494
+ },
495
+ }, { base: 'main', owedFiles: [] });
496
+ expect(resolution.winner?.coverage).toEqual({ covered: 0, owed: 0, missing: [] });
497
+ expect(resolution.stale).toEqual([]);
498
+ });
499
+ it('nothing owed is 0/0 and NOT stale (vacuous coverage)', () => {
500
+ // Unreachable from the gate — it never consults the store when nothing is
501
+ // owed — so this pins the FUNCTION's own honest behavior rather than a
502
+ // live path: an empty owed set cannot be "covered by none of" anything.
503
+ saveLegDeposit(tmpDir, deposit({ diffSha: OLDER }));
504
+ const resolution = findLegDepositForHead(tmpDir, HEAD, fakeGit({ commits: [OLDER], ancestors: { [OLDER]: 1 }, reach: { [OLDER]: [] } }), { base: 'main', owedFiles: [] });
505
+ expect(resolution.stale).toEqual([]);
506
+ expect(resolution.winner?.coverage).toEqual({ covered: 0, owed: 0, missing: [] });
507
+ });
508
+ it('ranking is unchanged: the nearest ancestor still wins, and both carry coverage', () => {
509
+ // Along one lineage a nearer ancestor's diff is a superset of a farther
510
+ // one's, so nearest-first ALREADY orders by coverage — the ruling's reason
511
+ // for leaving the comparator alone.
512
+ saveLegDeposit(tmpDir, deposit({ diffSha: OLDEST, readAt: '2026-09-01T00:00:00.000Z' }));
513
+ saveLegDeposit(tmpDir, deposit({ diffSha: OLDER, readAt: '2026-09-02T00:00:00.000Z' }));
514
+ const resolution = findLegDepositForHead(tmpDir, HEAD, fakeGit({
515
+ commits: [OLDEST, OLDER],
516
+ ancestors: { [OLDEST]: 9, [OLDER]: 2 },
517
+ reach: { [OLDEST]: [OWED[1]], [OLDER]: [OWED[0], OWED[1]] },
518
+ }), COVERAGE);
519
+ expect(resolution.winner?.diffSha).toBe(OLDER);
520
+ expect(resolution.winner?.coverage?.covered).toBe(2);
521
+ expect(resolution.superseded).toEqual([
522
+ {
523
+ diffSha: OLDEST,
524
+ readAt: '2026-09-01T00:00:00.000Z',
525
+ rank: 'ancestor',
526
+ distance: 9,
527
+ coverage: { covered: 1, owed: 3, missing: [OWED[0], OWED[2]] },
528
+ },
529
+ ]);
530
+ });
531
+ it('a no-coverage candidate never hides a covering sibling', () => {
532
+ saveLegDeposit(tmpDir, deposit({ diffSha: OLDEST }));
533
+ saveLegDeposit(tmpDir, deposit({ diffSha: OLDER }));
534
+ const resolution = findLegDepositForHead(tmpDir, HEAD, fakeGit({
535
+ commits: [OLDEST, OLDER],
536
+ ancestors: { [OLDEST]: 9, [OLDER]: 2 },
537
+ reach: { [OLDEST]: ['src/other.ts'], [OLDER]: [OWED[0]] },
538
+ }), COVERAGE);
539
+ expect(resolution.winner?.diffSha).toBe(OLDER);
540
+ expect(resolution.stale).toEqual([
541
+ { diffSha: OLDEST, readAt: expect.any(String), reason: 'no-coverage' },
542
+ ]);
543
+ });
544
+ it('coverage is measured against the caller-supplied base, not a guess', () => {
545
+ // The base must be the SAME one the caller resolved for HEAD, or the
546
+ // measure is of a different diff than the one the push proposes.
547
+ saveLegDeposit(tmpDir, deposit({ diffSha: OLDEST }));
548
+ const seen = [];
549
+ const resolution = findLegDepositForHead(tmpDir, HEAD, {
550
+ isCommit: () => true,
551
+ isAncestor: () => true,
552
+ distance: () => 3,
553
+ changedFiles: (base, head) => {
554
+ seen.push(`${base}...${head}`);
555
+ return OWED;
556
+ },
557
+ }, { base: 'origin/release', owedFiles: OWED });
558
+ expect(seen).toEqual([`origin/release...${OLDEST}`]);
559
+ expect(resolution.winner?.coverage?.covered).toBe(3);
560
+ });
561
+ });
562
+ // ─── The publish is EXCLUSIVE, not merely checked ──────────────────────────
563
+ //
564
+ // Greptile P1 on PR mmnto-ai/totem#2745: `existsSync` then rename is
565
+ // check-then-act. Two no-replace writers for one sha both see "absent", both
566
+ // rename, and the later one wins SILENTLY — one leg's read overwritten by
567
+ // another's, in a store whose whole contract is that a second read at a head is
568
+ // a different observation. These drive the window directly.
569
+ describe('saveLegDeposit publishes exclusively (mmnto-ai/totem#2745, Greptile P1)', () => {
570
+ /** The incumbent's bytes, so a test can prove they were never touched. */
571
+ function incumbentBytes() {
572
+ return fs.readFileSync(legDepositPath(tmpDir, HEAD), 'utf-8');
573
+ }
574
+ afterEach(() => {
575
+ publishInsideWindow = undefined;
576
+ });
577
+ it('a deposit published INSIDE the check-to-publish window is refused, not overwritten', () => {
578
+ const winner = deposit({ diffSha: HEAD, readAt: '2026-09-01T00:00:00.000Z' });
579
+ const loser = deposit({ diffSha: HEAD, readAt: '2026-09-02T00:00:00.000Z' });
580
+ // The store is EMPTY, so the loser's pre-check honestly reports "absent".
581
+ // The competitor then publishes in the window the pre-check opened —
582
+ // after the loser's temp is written, before it claims the final name.
583
+ // That is the interleaving a second process produces, driven here.
584
+ publishInsideWindow = () => {
585
+ saveLegDeposit(tmpDir, winner);
586
+ };
587
+ expect(() => saveLegDeposit(tmpDir, loser)).toThrow(LegDepositExistsError);
588
+ // The incumbent is intact byte for byte: the loser overwrote nothing.
589
+ expect(incumbentBytes()).toBe(JSON.stringify(winner, null, 2));
590
+ expect(JSON.parse(incumbentBytes()).readAt).toBe('2026-09-01T00:00:00.000Z');
591
+ // And the loser left no temp behind — the store holds exactly one file.
592
+ expect(fs.readdirSync(legsDir(tmpDir))).toEqual([`${HEAD}.json`]);
593
+ });
594
+ it('the refusal from that window carries the WINNER instant, not the loser one', () => {
595
+ publishInsideWindow = () => {
596
+ saveLegDeposit(tmpDir, deposit({ diffSha: HEAD, readAt: '2026-09-01T00:00:00.000Z' }));
597
+ };
598
+ let caught;
599
+ try {
600
+ saveLegDeposit(tmpDir, deposit({ diffSha: HEAD, readAt: '2026-09-02T00:00:00.000Z' }));
601
+ }
602
+ catch (err) {
603
+ caught = err;
604
+ }
605
+ expect(caught).toBeInstanceOf(LegDepositExistsError);
606
+ // Read AFTER the loss, so it names the deposit that actually won — the one
607
+ // a seat has to decide whether to `--replace`.
608
+ expect(caught.existingReadAt).toBe('2026-09-01T00:00:00.000Z');
609
+ });
610
+ it('`replace` still overwrites, and leaves one file behind', () => {
611
+ // The exclusive publish must not turn `--replace` into a refusal: it is the
612
+ // one caller allowed to overwrite.
613
+ saveLegDeposit(tmpDir, deposit({ diffSha: HEAD, readAt: '2026-09-01T00:00:00.000Z' }));
614
+ const result = saveLegDeposit(tmpDir, deposit({ diffSha: HEAD, readAt: '2026-09-02T00:00:00.000Z' }), { replace: true });
615
+ expect(result.replaced).toEqual({ readAt: '2026-09-01T00:00:00.000Z' });
616
+ expect(JSON.parse(incumbentBytes()).readAt).toBe('2026-09-02T00:00:00.000Z');
617
+ expect(fs.readdirSync(legsDir(tmpDir))).toEqual([`${HEAD}.json`]);
618
+ });
619
+ it('`replace` with NOTHING to replace reports no replacement', () => {
620
+ const result = saveLegDeposit(tmpDir, deposit({ diffSha: HEAD }), { replace: true });
621
+ expect(result.replaced).toBeUndefined();
622
+ });
623
+ it('an ordinary create leaves no temp beside the deposit', () => {
624
+ saveLegDeposit(tmpDir, deposit({ diffSha: HEAD }));
625
+ expect(fs.readdirSync(legsDir(tmpDir))).toEqual([`${HEAD}.json`]);
626
+ });
627
+ });
628
+ //# sourceMappingURL=legs.test.js.map