@mmnto/totem 1.23.0 → 1.25.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 (51) hide show
  1. package/dist/compile-lesson.d.ts +1 -1
  2. package/dist/compile-manifest.d.ts +14 -1
  3. package/dist/compile-manifest.d.ts.map +1 -1
  4. package/dist/compile-manifest.js +30 -1
  5. package/dist/compile-manifest.js.map +1 -1
  6. package/dist/compile-manifest.test.js +36 -1
  7. package/dist/compile-manifest.test.js.map +1 -1
  8. package/dist/compiler-schema.d.ts +44 -16
  9. package/dist/compiler-schema.d.ts.map +1 -1
  10. package/dist/compiler-schema.js +19 -3
  11. package/dist/compiler-schema.js.map +1 -1
  12. package/dist/compiler-schema.test.js +23 -1
  13. package/dist/compiler-schema.test.js.map +1 -1
  14. package/dist/compiler.d.ts +8 -1
  15. package/dist/compiler.d.ts.map +1 -1
  16. package/dist/compiler.js +11 -2
  17. package/dist/compiler.js.map +1 -1
  18. package/dist/compiler.test.js +35 -0
  19. package/dist/compiler.test.js.map +1 -1
  20. package/dist/config-schema.d.ts +2 -2
  21. package/dist/config-schema.js +2 -2
  22. package/dist/first-lint-promote.d.ts +90 -0
  23. package/dist/first-lint-promote.d.ts.map +1 -0
  24. package/dist/first-lint-promote.js +103 -0
  25. package/dist/first-lint-promote.js.map +1 -0
  26. package/dist/first-lint-promote.test.d.ts +2 -0
  27. package/dist/first-lint-promote.test.d.ts.map +1 -0
  28. package/dist/first-lint-promote.test.js +242 -0
  29. package/dist/first-lint-promote.test.js.map +1 -0
  30. package/dist/index.d.ts +5 -1
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +3 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/pack-discovery.d.ts +1 -1
  35. package/dist/pack-discovery.js +1 -1
  36. package/dist/pack-discovery.test.js +21 -21
  37. package/dist/pack-manifest-writer.d.ts +2 -2
  38. package/dist/pack-manifest-writer.js +3 -3
  39. package/dist/pack-manifest-writer.test.js +22 -22
  40. package/dist/pack-merge.d.ts +1 -1
  41. package/dist/pack-merge.js +1 -1
  42. package/dist/rule-engine.js +1 -1
  43. package/dist/verification-outcomes.d.ts +160 -0
  44. package/dist/verification-outcomes.d.ts.map +1 -0
  45. package/dist/verification-outcomes.js +149 -0
  46. package/dist/verification-outcomes.js.map +1 -0
  47. package/dist/verification-outcomes.test.d.ts +2 -0
  48. package/dist/verification-outcomes.test.d.ts.map +1 -0
  49. package/dist/verification-outcomes.test.js +228 -0
  50. package/dist/verification-outcomes.test.js.map +1 -0
  51. package/package.json +1 -1
@@ -0,0 +1,149 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { z } from 'zod';
4
+ import { canonicalStringify } from './compile-manifest.js';
5
+ /**
6
+ * Stage 4 outcome literals serialized into `.totem/verification-outcomes.json`
7
+ * (mmnto-ai/totem#1684, ADR-091 § Bootstrap CI-first). Mirrors the
8
+ * `Stage4Outcome` type from `stage4-verifier.ts` exactly so the storage
9
+ * vocabulary matches the runtime type and we avoid a translation layer that
10
+ * would drift on Stage 4 evolution.
11
+ *
12
+ * The `_OutcomeAlignment` type below enforces the mirror at compile time —
13
+ * if either side adds, drops, or renames a literal, the assertion below
14
+ * fails the build before drift can land in the corpus.
15
+ */
16
+ export const Stage4OutcomeStored = z.enum([
17
+ 'no-matches',
18
+ 'out-of-scope',
19
+ 'in-scope-bad-example',
20
+ 'candidate-debt',
21
+ ]);
22
+ const _stage4OutcomeAlignment = true;
23
+ void _stage4OutcomeAlignment;
24
+ /**
25
+ * One verification record per pack-installed rule (keyed by `lessonHash` in
26
+ * the file-level record). Persisted across lint runs so subsequent passes
27
+ * skip re-verification when the rule's content hash matches a recorded
28
+ * outcome.
29
+ */
30
+ export const VerificationOutcomeEntrySchema = z.object({
31
+ /**
32
+ * `lessonHash` of the rule the outcome was recorded against. Persisted
33
+ * inside the entry as well as serving as the file-level record key so a
34
+ * tampered key (key/value mismatch) can be detected on read.
35
+ */
36
+ ruleHash: z.string().trim().min(1),
37
+ /** ISO-8601 timestamp of when the verifier produced the outcome. */
38
+ verifiedAt: z.string().datetime(),
39
+ /** The terminal Stage 4 outcome that was recorded. */
40
+ outcome: Stage4OutcomeStored,
41
+ /** Repo-relative paths of baseline-scoped files where the rule fired. */
42
+ baselineMatches: z.array(z.string().trim().min(1)).default([]),
43
+ /** Repo-relative paths of in-scope files where the rule fired. */
44
+ inScopeMatches: z.array(z.string().trim().min(1)).default([]),
45
+ /**
46
+ * In-scope match lines that did not match the `badExample` shape — the
47
+ * Candidate Debt evidence carried forward to the `totem doctor` UX
48
+ * surface in mmnto-ai/totem#1685. Empty unless `outcome === 'candidate-debt'`.
49
+ */
50
+ candidateDebtLines: z.array(z.string().trim().min(1)).default([]),
51
+ });
52
+ /**
53
+ * The on-disk shape of `.totem/verification-outcomes.json`. Wraps the
54
+ * per-rule record in a versioned envelope so structural changes can break
55
+ * the file forward without silent migration: a loader that sees an unknown
56
+ * `version` treats the file as empty and re-verifies, instead of risking a
57
+ * partial parse against a newer schema.
58
+ */
59
+ export const VerificationOutcomesFileSchema = z.object({
60
+ version: z.literal(1).default(1),
61
+ outcomes: z.record(z.string(), VerificationOutcomeEntrySchema),
62
+ });
63
+ // ─── Persistence (mmnto-ai/totem#1684 T2) ───────────
64
+ /**
65
+ * Load the per-rule verification outcomes from a `verification-outcomes.json`
66
+ * file. Returns an empty store when the file is missing, contains malformed
67
+ * JSON, or fails schema validation — the corpus self-heals on the next
68
+ * write. The interceptor that wrote the corrupt file (or a future pass with
69
+ * a refreshed schema) will overwrite it on the next promotion run, so the
70
+ * cache state cannot wedge.
71
+ *
72
+ * Invariant: schema-version mismatch is treated as "no outcomes recorded"
73
+ * rather than attempted migration. A v2 file read by a v1 loader returns
74
+ * an empty store and warns; the next write produces a valid v1 file.
75
+ */
76
+ export function readVerificationOutcomes(filePath, onWarn) {
77
+ if (!fs.existsSync(filePath))
78
+ return {};
79
+ let raw;
80
+ try {
81
+ raw = fs.readFileSync(filePath, 'utf-8'); // totem-context: self-healing on transient read errors per Invariant #10 of #1684 — verification-outcomes.json is per-machine cache; corruption is recoverable on next write
82
+ }
83
+ catch (err) {
84
+ onWarn?.(
85
+ // totem-context: see preceding try — corrupt cache state self-heals; next write overwrites
86
+ `Could not read ${filePath}: ${err instanceof Error ? err.message : String(err)}`);
87
+ return {};
88
+ }
89
+ let parsed;
90
+ try {
91
+ parsed = JSON.parse(raw); // totem-context: self-healing on malformed JSON per Invariant #10 of #1684 — corrupt cache state self-heals; next write overwrites
92
+ }
93
+ catch (err) {
94
+ onWarn?.(
95
+ // totem-context: see preceding try — corrupt cache state self-heals; next write overwrites
96
+ `Malformed JSON in ${filePath}: ${err instanceof Error ? err.message : String(err)}. Treating as empty; next write will overwrite.`);
97
+ return {};
98
+ }
99
+ const result = VerificationOutcomesFileSchema.safeParse(parsed);
100
+ if (!result.success) {
101
+ const issues = result.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ');
102
+ onWarn?.(`Schema validation failed for ${filePath}: ${issues}. Treating as empty; next write will overwrite.`);
103
+ return {};
104
+ }
105
+ // totem-context: defense-in-depth — schema validates each entry's shape but
106
+ // not that the file-level record key matches the entry's stored ruleHash.
107
+ // A tampered or hand-edited file could memoize an outcome under the wrong
108
+ // hash. Drop those entries (with a warn) so memoization never satisfies a
109
+ // mismatched lookup.
110
+ const aligned = {};
111
+ for (const [key, entry] of Object.entries(result.data.outcomes)) {
112
+ if (entry.ruleHash !== key) {
113
+ onWarn?.(`Key/hash mismatch in ${filePath}: key=${key}, entry.ruleHash=${entry.ruleHash}. Ignoring entry.`);
114
+ continue;
115
+ }
116
+ aligned[key] = entry;
117
+ }
118
+ return aligned;
119
+ }
120
+ /**
121
+ * Persist the per-rule verification outcomes to disk via temp-file +
122
+ * atomic rename, so a concurrent CI lint pass that interrupts mid-write
123
+ * leaves the prior valid file intact rather than producing a truncated
124
+ * partial-write that the next loader would reject.
125
+ *
126
+ * Output is canonicalized (recursive object-key sort) before serialization
127
+ * so two lint passes that produce the same outcomes write byte-identical
128
+ * files — Invariant #11 in the design doc, which keeps consumer repos
129
+ * from seeing phantom diffs on every CI run.
130
+ */
131
+ export function writeVerificationOutcomes(filePath, outcomes) {
132
+ const dir = path.dirname(filePath);
133
+ fs.mkdirSync(dir, { recursive: true });
134
+ const file = { version: 1, outcomes };
135
+ const json = `${canonicalStringify(file, 2)}\n`;
136
+ // totem-context: per-write unique temp filename so two concurrent lint
137
+ // processes can't clobber each other's in-flight write and trigger a
138
+ // hard rename failure mid-pass (CR mmnto-ai/totem#1787 R1).
139
+ const tmpPath = `${filePath}.${process.pid}.${Date.now().toString(36)}.tmp`;
140
+ try {
141
+ fs.writeFileSync(tmpPath, json, 'utf-8');
142
+ fs.renameSync(tmpPath, filePath);
143
+ }
144
+ finally {
145
+ if (fs.existsSync(tmpPath))
146
+ fs.rmSync(tmpPath, { force: true });
147
+ }
148
+ }
149
+ //# sourceMappingURL=verification-outcomes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification-outcomes.js","sourceRoot":"","sources":["../src/verification-outcomes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=verification-outcomes.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification-outcomes.test.d.ts","sourceRoot":"","sources":["../src/verification-outcomes.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,228 @@
1
+ import * as fs from 'node:fs';
2
+ import * as os from 'node:os';
3
+ import * as path from 'node:path';
4
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
+ import { cleanTmpDir } from './test-utils.js';
6
+ import { readVerificationOutcomes, Stage4OutcomeStored, VerificationOutcomeEntrySchema, VerificationOutcomesFileSchema, writeVerificationOutcomes, } from './verification-outcomes.js';
7
+ // ─── Stage4OutcomeStored ───────────────────────────
8
+ describe('Stage4OutcomeStored', () => {
9
+ it('accepts each Stage4Outcome literal', () => {
10
+ for (const outcome of [
11
+ 'no-matches',
12
+ 'out-of-scope',
13
+ 'in-scope-bad-example',
14
+ 'candidate-debt',
15
+ ]) {
16
+ expect(Stage4OutcomeStored.parse(outcome)).toBe(outcome);
17
+ }
18
+ });
19
+ it('rejects an unknown literal', () => {
20
+ expect(() => Stage4OutcomeStored.parse('promoted')).toThrow();
21
+ });
22
+ });
23
+ // ─── VerificationOutcomeEntrySchema ────────────────
24
+ describe('VerificationOutcomeEntrySchema', () => {
25
+ const validEntry = {
26
+ ruleHash: 'abc123',
27
+ verifiedAt: '2026-05-01T12:34:56.000Z',
28
+ outcome: 'in-scope-bad-example',
29
+ baselineMatches: [],
30
+ inScopeMatches: ['src/foo.ts'],
31
+ candidateDebtLines: [],
32
+ };
33
+ it('accepts a fully-populated valid entry', () => {
34
+ const parsed = VerificationOutcomeEntrySchema.parse(validEntry);
35
+ expect(parsed.ruleHash).toBe('abc123');
36
+ expect(parsed.outcome).toBe('in-scope-bad-example');
37
+ expect(parsed.inScopeMatches).toEqual(['src/foo.ts']);
38
+ });
39
+ it('defaults match arrays to empty when omitted', () => {
40
+ const parsed = VerificationOutcomeEntrySchema.parse({
41
+ ruleHash: 'abc123',
42
+ verifiedAt: '2026-05-01T12:34:56.000Z',
43
+ outcome: 'no-matches',
44
+ });
45
+ expect(parsed.baselineMatches).toEqual([]);
46
+ expect(parsed.inScopeMatches).toEqual([]);
47
+ expect(parsed.candidateDebtLines).toEqual([]);
48
+ });
49
+ it('rejects invalid verification-outcomes schema payloads', () => {
50
+ expect(() => VerificationOutcomeEntrySchema.parse({ ...validEntry, ruleHash: '' })).toThrow();
51
+ expect(() => VerificationOutcomeEntrySchema.parse({ ...validEntry, ruleHash: 42 })).toThrow();
52
+ expect(() => VerificationOutcomeEntrySchema.parse({ ...validEntry, verifiedAt: 'not-a-date' })).toThrow();
53
+ expect(() => VerificationOutcomeEntrySchema.parse({ ...validEntry, outcome: 'promoted' })).toThrow();
54
+ expect(() => VerificationOutcomeEntrySchema.parse({ ...validEntry, ruleHash: ' ' })).toThrow();
55
+ expect(() => VerificationOutcomeEntrySchema.parse({ ...validEntry, inScopeMatches: [''] })).toThrow();
56
+ const { ruleHash: _omit, ...missingHash } = validEntry;
57
+ void _omit;
58
+ expect(() => VerificationOutcomeEntrySchema.parse(missingHash)).toThrow();
59
+ });
60
+ it('trims surrounding whitespace from ruleHash', () => {
61
+ const parsed = VerificationOutcomeEntrySchema.parse({ ...validEntry, ruleHash: ' abc123 ' });
62
+ expect(parsed.ruleHash).toBe('abc123');
63
+ });
64
+ });
65
+ // ─── VerificationOutcomesFileSchema ────────────────
66
+ describe('VerificationOutcomesFileSchema', () => {
67
+ const validEntry = {
68
+ ruleHash: 'abc123',
69
+ verifiedAt: '2026-05-01T12:34:56.000Z',
70
+ outcome: 'in-scope-bad-example',
71
+ baselineMatches: [],
72
+ inScopeMatches: [],
73
+ candidateDebtLines: [],
74
+ };
75
+ it('accepts an empty outcomes record with default version', () => {
76
+ const parsed = VerificationOutcomesFileSchema.parse({ outcomes: {} });
77
+ expect(parsed.version).toBe(1);
78
+ expect(parsed.outcomes).toEqual({});
79
+ });
80
+ it('accepts a populated outcomes record', () => {
81
+ const parsed = VerificationOutcomesFileSchema.parse({
82
+ version: 1,
83
+ outcomes: { abc123: validEntry },
84
+ });
85
+ expect(parsed.outcomes['abc123']?.outcome).toBe('in-scope-bad-example');
86
+ });
87
+ it('rejects a future schema version', () => {
88
+ expect(() => VerificationOutcomesFileSchema.parse({
89
+ version: 2,
90
+ outcomes: { abc123: validEntry },
91
+ })).toThrow();
92
+ });
93
+ it('rejects a malformed nested entry', () => {
94
+ expect(() => VerificationOutcomesFileSchema.parse({
95
+ version: 1,
96
+ outcomes: { abc123: { ...validEntry, outcome: 'promoted' } },
97
+ })).toThrow();
98
+ });
99
+ });
100
+ // ─── Persistence (mmnto-ai/totem#1684 T2) ───────────
101
+ describe('readVerificationOutcomes / writeVerificationOutcomes', () => {
102
+ let tmpDir;
103
+ beforeEach(() => {
104
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-vouts-'));
105
+ });
106
+ afterEach(() => {
107
+ cleanTmpDir(tmpDir);
108
+ });
109
+ function tmpFile(name = 'verification-outcomes.json') {
110
+ return path.join(tmpDir, name);
111
+ }
112
+ const sampleStore = {
113
+ abc123: {
114
+ ruleHash: 'abc123',
115
+ verifiedAt: '2026-05-01T12:34:56.000Z',
116
+ outcome: 'in-scope-bad-example',
117
+ baselineMatches: [],
118
+ inScopeMatches: ['src/foo.ts', 'src/bar.ts'],
119
+ candidateDebtLines: [],
120
+ },
121
+ def456: {
122
+ ruleHash: 'def456',
123
+ verifiedAt: '2026-05-01T12:35:00.000Z',
124
+ outcome: 'candidate-debt',
125
+ baselineMatches: [],
126
+ inScopeMatches: ['src/baz.ts'],
127
+ candidateDebtLines: ['src/baz.ts:10:something'],
128
+ },
129
+ };
130
+ it('returns an empty store when the file does not exist', () => {
131
+ const warnings = [];
132
+ const store = readVerificationOutcomes(tmpFile('absent.json'), (m) => warnings.push(m));
133
+ expect(store).toEqual({});
134
+ expect(warnings).toEqual([]);
135
+ });
136
+ it('writes verification outcomes atomically and creates missing directories', () => {
137
+ const filePath = path.join(tmpFile('nested'), 'deep', 'verification-outcomes.json');
138
+ expect(fs.existsSync(path.dirname(filePath))).toBe(false);
139
+ writeVerificationOutcomes(filePath, sampleStore);
140
+ expect(fs.existsSync(filePath)).toBe(true);
141
+ expect(fs.existsSync(`${filePath}.tmp`)).toBe(false);
142
+ const roundTripped = readVerificationOutcomes(filePath);
143
+ expect(roundTripped).toEqual(sampleStore);
144
+ });
145
+ it('round-trips the sample store byte-stably', () => {
146
+ const filePath = tmpFile();
147
+ writeVerificationOutcomes(filePath, sampleStore);
148
+ const firstBytes = fs.readFileSync(filePath, 'utf-8');
149
+ writeVerificationOutcomes(filePath, sampleStore);
150
+ const secondBytes = fs.readFileSync(filePath, 'utf-8');
151
+ expect(secondBytes).toBe(firstBytes);
152
+ });
153
+ it('canonicalizes object key order regardless of insertion order', () => {
154
+ const filePath = tmpFile();
155
+ writeVerificationOutcomes(filePath, sampleStore);
156
+ const firstBytes = fs.readFileSync(filePath, 'utf-8');
157
+ const reordered = {
158
+ def456: sampleStore['def456'],
159
+ abc123: sampleStore['abc123'],
160
+ };
161
+ writeVerificationOutcomes(filePath, reordered);
162
+ const secondBytes = fs.readFileSync(filePath, 'utf-8');
163
+ expect(secondBytes).toBe(firstBytes);
164
+ });
165
+ it('returns an empty store and warns on malformed JSON', () => {
166
+ const filePath = tmpFile();
167
+ fs.writeFileSync(filePath, '{ this is : not json,', 'utf-8');
168
+ const warnings = [];
169
+ const store = readVerificationOutcomes(filePath, (m) => warnings.push(m));
170
+ expect(store).toEqual({});
171
+ expect(warnings.length).toBe(1);
172
+ expect(warnings[0]).toMatch(/Malformed JSON/);
173
+ });
174
+ it('returns an empty store and warns on schema mismatch', () => {
175
+ const filePath = tmpFile();
176
+ fs.writeFileSync(filePath, JSON.stringify({ version: 2, outcomes: {} }), 'utf-8');
177
+ const warnings = [];
178
+ const store = readVerificationOutcomes(filePath, (m) => warnings.push(m));
179
+ expect(store).toEqual({});
180
+ expect(warnings.length).toBe(1);
181
+ expect(warnings[0]).toMatch(/Schema validation failed/);
182
+ });
183
+ it('overwrites a prior corrupt file on next write', () => {
184
+ const filePath = tmpFile();
185
+ fs.writeFileSync(filePath, 'garbage{', 'utf-8');
186
+ expect(readVerificationOutcomes(filePath, () => { })).toEqual({});
187
+ writeVerificationOutcomes(filePath, sampleStore);
188
+ expect(readVerificationOutcomes(filePath)).toEqual(sampleStore);
189
+ });
190
+ it('drops entries whose key does not match their stored ruleHash', () => {
191
+ // Defense in depth: schema validates each entry's shape but not that the
192
+ // file-level key matches the stored ruleHash. A tampered or hand-edited
193
+ // file could memoize an outcome under the wrong hash; the loader filters
194
+ // those out with a warn (CR mmnto-ai/totem#1787 R1).
195
+ const filePath = tmpFile();
196
+ const tampered = {
197
+ version: 1,
198
+ outcomes: {
199
+ // Key "abc123" but entry.ruleHash is "different-hash" — mismatch.
200
+ abc123: {
201
+ ruleHash: 'different-hash',
202
+ verifiedAt: '2026-05-02T00:00:00.000Z',
203
+ outcome: 'in-scope-bad-example',
204
+ baselineMatches: [],
205
+ inScopeMatches: [],
206
+ candidateDebtLines: [],
207
+ },
208
+ // Aligned entry — key matches ruleHash.
209
+ aligned: {
210
+ ruleHash: 'aligned',
211
+ verifiedAt: '2026-05-02T00:00:00.000Z',
212
+ outcome: 'no-matches',
213
+ baselineMatches: [],
214
+ inScopeMatches: [],
215
+ candidateDebtLines: [],
216
+ },
217
+ },
218
+ };
219
+ fs.writeFileSync(filePath, JSON.stringify(tampered), 'utf-8');
220
+ const warnings = [];
221
+ const store = readVerificationOutcomes(filePath, (m) => warnings.push(m));
222
+ expect(Object.keys(store)).toEqual(['aligned']);
223
+ expect(warnings.length).toBe(1);
224
+ expect(warnings[0]).toMatch(/Key\/hash mismatch/);
225
+ expect(warnings[0]).toMatch(/abc123/);
226
+ });
227
+ });
228
+ //# sourceMappingURL=verification-outcomes.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification-outcomes.test.js","sourceRoot":"","sources":["../src/verification-outcomes.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmnto/totem",
3
- "version": "1.23.0",
3
+ "version": "1.25.0",
4
4
  "description": "Persistent memory and context layer for AI agents",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",