@mmnto/cli 1.15.1 → 1.15.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/compile-prune.test.js +56 -1
- package/dist/commands/compile-prune.test.js.map +1 -1
- package/dist/commands/compile-refresh-manifest.test.d.ts +2 -0
- package/dist/commands/compile-refresh-manifest.test.d.ts.map +1 -0
- package/dist/commands/compile-refresh-manifest.test.js +163 -0
- package/dist/commands/compile-refresh-manifest.test.js.map +1 -0
- package/dist/commands/compile-templates.d.ts +1 -1
- package/dist/commands/compile-templates.d.ts.map +1 -1
- package/dist/commands/compile-templates.js +134 -0
- package/dist/commands/compile-templates.js.map +1 -1
- package/dist/commands/compile.d.ts +30 -0
- package/dist/commands/compile.d.ts.map +1 -1
- package/dist/commands/compile.js +227 -41
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/lesson-archive.test.d.ts +2 -0
- package/dist/commands/lesson-archive.test.d.ts.map +1 -0
- package/dist/commands/lesson-archive.test.js +192 -0
- package/dist/commands/lesson-archive.test.js.map +1 -0
- package/dist/commands/lesson.d.ts +23 -0
- package/dist/commands/lesson.d.ts.map +1 -1
- package/dist/commands/lesson.js +124 -0
- package/dist/commands/lesson.js.map +1 -1
- package/dist/commands/lint.d.ts +8 -0
- package/dist/commands/lint.d.ts.map +1 -1
- package/dist/commands/lint.js +14 -1
- package/dist/commands/lint.js.map +1 -1
- package/dist/commands/lint.test.js +71 -1
- package/dist/commands/lint.test.js.map +1 -1
- package/dist/commands/run-compiled-rules.d.ts +15 -1
- package/dist/commands/run-compiled-rules.d.ts.map +1 -1
- package/dist/commands/run-compiled-rules.js +49 -4
- package/dist/commands/run-compiled-rules.js.map +1 -1
- package/dist/commands/run-compiled-rules.test.js +6 -2
- package/dist/commands/run-compiled-rules.test.js.map +1 -1
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,192 @@
|
|
|
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 { generateOutputHash, readCompileManifest } from '@mmnto/totem';
|
|
6
|
+
import { cleanTmpDir } from '../test-utils.js';
|
|
7
|
+
import { lessonArchiveCommand } from './lesson.js';
|
|
8
|
+
// ─── Helpers ─────────────────────────────────────────
|
|
9
|
+
//
|
|
10
|
+
// Exercise `totem lesson archive <hash> [--reason <string>]` — the atomic
|
|
11
|
+
// archive verb from mmnto-ai/totem#1587 Task 3. The command mirrors
|
|
12
|
+
// `rulePromoteCommand` (rule.ts:300-394) in shape: preflight manifest read,
|
|
13
|
+
// atomic tmp+rename write of rules.json, refresh manifest output_hash.
|
|
14
|
+
// Idempotent on rerun: archivedReason refreshes, archivedAt is preserved
|
|
15
|
+
// across invocations.
|
|
16
|
+
function makeTmpDir() {
|
|
17
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), 'totem-lesson-archive-'));
|
|
18
|
+
}
|
|
19
|
+
function setupWorkspace(tmpDir, rules) {
|
|
20
|
+
fs.writeFileSync(path.join(tmpDir, 'totem.config.ts'), [
|
|
21
|
+
'export default {',
|
|
22
|
+
' targets: [{ glob: "**/*.ts", type: "code", strategy: "typescript-ast" }],',
|
|
23
|
+
' totemDir: ".totem",',
|
|
24
|
+
'};',
|
|
25
|
+
'',
|
|
26
|
+
].join('\n'), 'utf-8');
|
|
27
|
+
const totemDir = path.join(tmpDir, '.totem');
|
|
28
|
+
fs.mkdirSync(totemDir, { recursive: true });
|
|
29
|
+
const rulesPath = path.join(totemDir, 'compiled-rules.json');
|
|
30
|
+
const now = '2026-04-22T00:00:00Z';
|
|
31
|
+
fs.writeFileSync(rulesPath, JSON.stringify({
|
|
32
|
+
version: 1,
|
|
33
|
+
rules: rules.map((r) => ({
|
|
34
|
+
lessonHash: r.lessonHash,
|
|
35
|
+
lessonHeading: r.lessonHeading,
|
|
36
|
+
pattern: 'dummy-never-matches',
|
|
37
|
+
message: r.lessonHeading,
|
|
38
|
+
engine: 'regex',
|
|
39
|
+
severity: 'warning',
|
|
40
|
+
compiledAt: now,
|
|
41
|
+
...(r.status ? { status: r.status } : {}),
|
|
42
|
+
...(r.archivedReason ? { archivedReason: r.archivedReason } : {}),
|
|
43
|
+
...(r.archivedAt ? { archivedAt: r.archivedAt } : {}),
|
|
44
|
+
})),
|
|
45
|
+
nonCompilable: [],
|
|
46
|
+
}, null, 2) + '\n', 'utf-8');
|
|
47
|
+
const manifestPath = path.join(totemDir, 'compile-manifest.json');
|
|
48
|
+
fs.writeFileSync(manifestPath, JSON.stringify({
|
|
49
|
+
compiled_at: now,
|
|
50
|
+
model: 'test-model',
|
|
51
|
+
input_hash: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
52
|
+
output_hash: generateOutputHash(rulesPath),
|
|
53
|
+
rule_count: rules.length,
|
|
54
|
+
}, null, 2) + '\n', 'utf-8');
|
|
55
|
+
}
|
|
56
|
+
describe('lessonArchiveCommand (#1587)', () => {
|
|
57
|
+
let tmpDir;
|
|
58
|
+
let originalCwd;
|
|
59
|
+
beforeEach(() => {
|
|
60
|
+
tmpDir = makeTmpDir();
|
|
61
|
+
originalCwd = process.cwd();
|
|
62
|
+
process.chdir(tmpDir);
|
|
63
|
+
});
|
|
64
|
+
afterEach(() => {
|
|
65
|
+
process.chdir(originalCwd);
|
|
66
|
+
cleanTmpDir(tmpDir);
|
|
67
|
+
});
|
|
68
|
+
it('archives the target rule, refreshes manifest output_hash, and stamps archivedAt', async () => {
|
|
69
|
+
setupWorkspace(tmpDir, [{ lessonHash: 'abc123def456abcd', lessonHeading: 'Use err in catch' }]);
|
|
70
|
+
const totemDir = path.join(tmpDir, '.totem');
|
|
71
|
+
const rulesPath = path.join(totemDir, 'compiled-rules.json');
|
|
72
|
+
const manifestPath = path.join(totemDir, 'compile-manifest.json');
|
|
73
|
+
await lessonArchiveCommand('abc123def456abcd', { reason: 'Over-broad in test contexts' });
|
|
74
|
+
const rulesAfter = JSON.parse(fs.readFileSync(rulesPath, 'utf-8'));
|
|
75
|
+
const rule = rulesAfter.rules.find((r) => r.lessonHash === 'abc123def456abcd');
|
|
76
|
+
expect(rule.status).toBe('archived');
|
|
77
|
+
expect(rule.archivedReason).toBe('Over-broad in test contexts');
|
|
78
|
+
expect(typeof rule.archivedAt).toBe('string');
|
|
79
|
+
expect(rule.archivedAt).toMatch(/^\d{4}-\d{2}-\d{2}T/);
|
|
80
|
+
const manifestAfter = readCompileManifest(manifestPath);
|
|
81
|
+
expect(manifestAfter.output_hash).toBe(generateOutputHash(rulesPath));
|
|
82
|
+
});
|
|
83
|
+
it('is idempotent on rerun: archivedReason refreshes, archivedAt is preserved', async () => {
|
|
84
|
+
const originalArchivedAt = '2026-04-15T00:00:00.000Z';
|
|
85
|
+
setupWorkspace(tmpDir, [
|
|
86
|
+
{
|
|
87
|
+
lessonHash: 'abc123def456abcd',
|
|
88
|
+
lessonHeading: 'Use err in catch',
|
|
89
|
+
status: 'archived',
|
|
90
|
+
archivedReason: 'Original reason',
|
|
91
|
+
archivedAt: originalArchivedAt,
|
|
92
|
+
},
|
|
93
|
+
]);
|
|
94
|
+
const totemDir = path.join(tmpDir, '.totem');
|
|
95
|
+
const rulesPath = path.join(totemDir, 'compiled-rules.json');
|
|
96
|
+
await lessonArchiveCommand('abc123def456abcd', { reason: 'Updated reason' });
|
|
97
|
+
const rulesAfter = JSON.parse(fs.readFileSync(rulesPath, 'utf-8'));
|
|
98
|
+
const rule = rulesAfter.rules.find((r) => r.lessonHash === 'abc123def456abcd');
|
|
99
|
+
expect(rule.status).toBe('archived');
|
|
100
|
+
expect(rule.archivedReason).toBe('Updated reason');
|
|
101
|
+
expect(rule.archivedAt).toBe(originalArchivedAt);
|
|
102
|
+
});
|
|
103
|
+
it('accepts a hash prefix and resolves unambiguously', async () => {
|
|
104
|
+
setupWorkspace(tmpDir, [
|
|
105
|
+
{ lessonHash: 'abc123def456abcd', lessonHeading: 'Rule A' },
|
|
106
|
+
{ lessonHash: 'def789ghi012efgh', lessonHeading: 'Rule B' },
|
|
107
|
+
]);
|
|
108
|
+
const totemDir = path.join(tmpDir, '.totem');
|
|
109
|
+
const rulesPath = path.join(totemDir, 'compiled-rules.json');
|
|
110
|
+
await lessonArchiveCommand('abc12', { reason: 'prefix match' });
|
|
111
|
+
const rulesAfter = JSON.parse(fs.readFileSync(rulesPath, 'utf-8'));
|
|
112
|
+
const ruleA = rulesAfter.rules.find((r) => r.lessonHash === 'abc123def456abcd');
|
|
113
|
+
const ruleB = rulesAfter.rules.find((r) => r.lessonHash === 'def789ghi012efgh');
|
|
114
|
+
expect(ruleA.status).toBe('archived');
|
|
115
|
+
expect(ruleB.status).toBeUndefined();
|
|
116
|
+
});
|
|
117
|
+
it('fails fast on unknown hash without mutating any files', async () => {
|
|
118
|
+
setupWorkspace(tmpDir, [{ lessonHash: 'abc123def456abcd', lessonHeading: 'Use err in catch' }]);
|
|
119
|
+
const totemDir = path.join(tmpDir, '.totem');
|
|
120
|
+
const rulesPath = path.join(totemDir, 'compiled-rules.json');
|
|
121
|
+
const manifestPath = path.join(totemDir, 'compile-manifest.json');
|
|
122
|
+
const rulesBefore = fs.readFileSync(rulesPath, 'utf-8');
|
|
123
|
+
const manifestBefore = fs.readFileSync(manifestPath, 'utf-8');
|
|
124
|
+
await lessonArchiveCommand('ffff', { reason: 'not matching anything' });
|
|
125
|
+
expect(process.exitCode).toBe(1);
|
|
126
|
+
process.exitCode = 0;
|
|
127
|
+
expect(fs.readFileSync(rulesPath, 'utf-8')).toBe(rulesBefore);
|
|
128
|
+
expect(fs.readFileSync(manifestPath, 'utf-8')).toBe(manifestBefore);
|
|
129
|
+
});
|
|
130
|
+
it('fails fast on ambiguous prefix without mutating any files', async () => {
|
|
131
|
+
setupWorkspace(tmpDir, [
|
|
132
|
+
{ lessonHash: 'abc123def456abcd', lessonHeading: 'Rule A' },
|
|
133
|
+
{ lessonHash: 'abc999ghi012efgh', lessonHeading: 'Rule B' },
|
|
134
|
+
]);
|
|
135
|
+
const totemDir = path.join(tmpDir, '.totem');
|
|
136
|
+
const rulesPath = path.join(totemDir, 'compiled-rules.json');
|
|
137
|
+
const manifestPath = path.join(totemDir, 'compile-manifest.json');
|
|
138
|
+
const rulesBefore = fs.readFileSync(rulesPath, 'utf-8');
|
|
139
|
+
const manifestBefore = fs.readFileSync(manifestPath, 'utf-8');
|
|
140
|
+
await lessonArchiveCommand('abc', { reason: 'ambiguous' });
|
|
141
|
+
expect(process.exitCode).toBe(1);
|
|
142
|
+
process.exitCode = 0;
|
|
143
|
+
expect(fs.readFileSync(rulesPath, 'utf-8')).toBe(rulesBefore);
|
|
144
|
+
expect(fs.readFileSync(manifestPath, 'utf-8')).toBe(manifestBefore);
|
|
145
|
+
});
|
|
146
|
+
it('fails before mutating compiled-rules.json when compile-manifest.json is corrupt', async () => {
|
|
147
|
+
// Load-bearing atomicity contract (CR finding on PR #1629): the
|
|
148
|
+
// preflight manifest read must fail out BEFORE any write to
|
|
149
|
+
// compiled-rules.json. A corrupt manifest must not leave the rules
|
|
150
|
+
// file half-archived.
|
|
151
|
+
setupWorkspace(tmpDir, [{ lessonHash: 'abc123def456abcd', lessonHeading: 'Use err in catch' }]);
|
|
152
|
+
const totemDir = path.join(tmpDir, '.totem');
|
|
153
|
+
const rulesPath = path.join(totemDir, 'compiled-rules.json');
|
|
154
|
+
const manifestPath = path.join(totemDir, 'compile-manifest.json');
|
|
155
|
+
fs.writeFileSync(manifestPath, '{ this is: not valid json }', 'utf-8');
|
|
156
|
+
const rulesBefore = fs.readFileSync(rulesPath, 'utf-8'); // totem-ignore — test-fixture read, not static-analysis path
|
|
157
|
+
await expect(lessonArchiveCommand('abc123def456abcd', { reason: 'should not apply' })).rejects.toMatchObject({ code: 'PARSE_FAILED' });
|
|
158
|
+
// compiled-rules.json must be untouched.
|
|
159
|
+
expect(fs.readFileSync(rulesPath, 'utf-8')).toBe(rulesBefore); // totem-ignore — test-fixture read, not static-analysis path
|
|
160
|
+
});
|
|
161
|
+
it('fails before mutating compiled-rules.json when compiled-rules.json itself has duplicate hashes', async () => {
|
|
162
|
+
// Data-corruption surface (CR finding on PR mmnto-ai/totem#1629): duplicate full
|
|
163
|
+
// hashes are not prefix ambiguity; fail fast with a distinct signal.
|
|
164
|
+
setupWorkspace(tmpDir, [{ lessonHash: 'abc123def456abcd', lessonHeading: 'Rule A' }]);
|
|
165
|
+
const totemDir = path.join(tmpDir, '.totem');
|
|
166
|
+
const rulesPath = path.join(totemDir, 'compiled-rules.json');
|
|
167
|
+
const manifestPath = path.join(totemDir, 'compile-manifest.json');
|
|
168
|
+
// Rewrite the rules file with two entries carrying the SAME lessonHash.
|
|
169
|
+
const rulesJson = JSON.parse(fs.readFileSync(rulesPath, 'utf-8')); // totem-ignore — test-fixture read, not static-analysis path
|
|
170
|
+
rulesJson.rules.push({ ...rulesJson.rules[0], lessonHeading: 'Rule A duplicate' });
|
|
171
|
+
fs.writeFileSync(rulesPath, JSON.stringify(rulesJson, null, 2) + '\n', 'utf-8');
|
|
172
|
+
const rulesBefore = fs.readFileSync(rulesPath, 'utf-8'); // totem-ignore — test-fixture read, not static-analysis path
|
|
173
|
+
const manifestBefore = fs.readFileSync(manifestPath, 'utf-8'); // totem-ignore — test-fixture read, not static-analysis path
|
|
174
|
+
await lessonArchiveCommand('abc123def456abcd', { reason: 'duplicate' });
|
|
175
|
+
expect(process.exitCode).toBe(1);
|
|
176
|
+
process.exitCode = 0;
|
|
177
|
+
expect(fs.readFileSync(rulesPath, 'utf-8')).toBe(rulesBefore);
|
|
178
|
+
expect(fs.readFileSync(manifestPath, 'utf-8')).toBe(manifestBefore);
|
|
179
|
+
});
|
|
180
|
+
it('uses a default reason when --reason is omitted', async () => {
|
|
181
|
+
setupWorkspace(tmpDir, [{ lessonHash: 'abc123def456abcd', lessonHeading: 'Use err in catch' }]);
|
|
182
|
+
const totemDir = path.join(tmpDir, '.totem');
|
|
183
|
+
const rulesPath = path.join(totemDir, 'compiled-rules.json');
|
|
184
|
+
await lessonArchiveCommand('abc123def456abcd', {});
|
|
185
|
+
const rulesAfter = JSON.parse(fs.readFileSync(rulesPath, 'utf-8'));
|
|
186
|
+
const rule = rulesAfter.rules.find((r) => r.lessonHash === 'abc123def456abcd');
|
|
187
|
+
expect(rule.status).toBe('archived');
|
|
188
|
+
expect(typeof rule.archivedReason).toBe('string');
|
|
189
|
+
expect(rule.archivedReason.length).toBeGreaterThan(0);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
//# sourceMappingURL=lesson-archive.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lesson-archive.test.js","sourceRoot":"","sources":["../../src/commands/lesson-archive.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,26 @@
|
|
|
1
1
|
export declare function lessonListCommand(): Promise<void>;
|
|
2
2
|
export declare function lessonAddCommand(text: string): Promise<void>;
|
|
3
|
+
/**
|
|
4
|
+
* Archive a compiled rule by flipping its `status` to `'archived'`, setting
|
|
5
|
+
* the `archivedReason`, stamping `archivedAt` on first transition, and
|
|
6
|
+
* refreshing the compile manifest so `totem verify-manifest` passes on the
|
|
7
|
+
* next push (mmnto-ai/totem#1587).
|
|
8
|
+
*
|
|
9
|
+
* Atomic surface matches `rulePromoteCommand` (rule.ts:300-394): preflight
|
|
10
|
+
* the manifest read BEFORE mutating compiled-rules.json so a missing or
|
|
11
|
+
* corrupt manifest fails loud without leaving the rules file half-written.
|
|
12
|
+
* Tmp-file + rename on the rules write prevents torn writes if the process
|
|
13
|
+
* crashes mid-save.
|
|
14
|
+
*
|
|
15
|
+
* Idempotent on rerun. First archive transition owns `archivedAt`;
|
|
16
|
+
* subsequent invocations refresh `archivedReason` only. Matches the
|
|
17
|
+
* canonical archive-script pattern standardized in mmnto-ai/totem#1625.
|
|
18
|
+
*
|
|
19
|
+
* Supersedes the hand-rolled `scripts/archive-bad-postmerge-*.cjs` pattern
|
|
20
|
+
* for postmerge curation; the `/postmerge` skill calls this command
|
|
21
|
+
* directly after Task 4 of mmnto-ai/totem#1587 ships.
|
|
22
|
+
*/
|
|
23
|
+
export declare function lessonArchiveCommand(id: string, opts: {
|
|
24
|
+
reason?: string;
|
|
25
|
+
}): Promise<void>;
|
|
3
26
|
//# sourceMappingURL=lesson.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lesson.d.ts","sourceRoot":"","sources":["../../src/commands/lesson.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lesson.d.ts","sourceRoot":"","sources":["../../src/commands/lesson.ts"],"names":[],"mappings":"AAYA,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAuCvD;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0DlE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuI/F"}
|
package/dist/commands/lesson.js
CHANGED
|
@@ -87,4 +87,128 @@ export async function lessonAddCommand(text) {
|
|
|
87
87
|
log.warn(TAG, `Failed to trigger background sync: ${message}`);
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Archive a compiled rule by flipping its `status` to `'archived'`, setting
|
|
92
|
+
* the `archivedReason`, stamping `archivedAt` on first transition, and
|
|
93
|
+
* refreshing the compile manifest so `totem verify-manifest` passes on the
|
|
94
|
+
* next push (mmnto-ai/totem#1587).
|
|
95
|
+
*
|
|
96
|
+
* Atomic surface matches `rulePromoteCommand` (rule.ts:300-394): preflight
|
|
97
|
+
* the manifest read BEFORE mutating compiled-rules.json so a missing or
|
|
98
|
+
* corrupt manifest fails loud without leaving the rules file half-written.
|
|
99
|
+
* Tmp-file + rename on the rules write prevents torn writes if the process
|
|
100
|
+
* crashes mid-save.
|
|
101
|
+
*
|
|
102
|
+
* Idempotent on rerun. First archive transition owns `archivedAt`;
|
|
103
|
+
* subsequent invocations refresh `archivedReason` only. Matches the
|
|
104
|
+
* canonical archive-script pattern standardized in mmnto-ai/totem#1625.
|
|
105
|
+
*
|
|
106
|
+
* Supersedes the hand-rolled `scripts/archive-bad-postmerge-*.cjs` pattern
|
|
107
|
+
* for postmerge curation; the `/postmerge` skill calls this command
|
|
108
|
+
* directly after Task 4 of mmnto-ai/totem#1587 ships.
|
|
109
|
+
*/
|
|
110
|
+
export async function lessonArchiveCommand(id, opts) {
|
|
111
|
+
const fs = await import('node:fs');
|
|
112
|
+
const path = await import('node:path');
|
|
113
|
+
const { log, bold } = await import('../ui.js');
|
|
114
|
+
const { exportLessons, generateOutputHash, hashLesson, loadCompiledRulesFile, readAllLessons, readCompileManifest, writeCompileManifest, } = await import('@mmnto/totem');
|
|
115
|
+
const { loadConfig, resolveConfigPath } = await import('../utils.js');
|
|
116
|
+
const cwd = process.cwd();
|
|
117
|
+
const configPath = resolveConfigPath(cwd);
|
|
118
|
+
const config = await loadConfig(configPath);
|
|
119
|
+
const totemDir = path.join(cwd, config.totemDir);
|
|
120
|
+
const rulesPath = path.join(totemDir, 'compiled-rules.json');
|
|
121
|
+
const manifestPath = path.join(totemDir, 'compile-manifest.json');
|
|
122
|
+
if (!fs.existsSync(rulesPath)) {
|
|
123
|
+
log.error('Totem Error', `No compiled-rules.json at ${rulesPath}. Run 'totem lesson compile' first.`);
|
|
124
|
+
process.exitCode = 1;
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const rulesFile = loadCompiledRulesFile(rulesPath);
|
|
128
|
+
// Pre-index pass with duplicate-collision abort (CR finding on PR mmnto-ai/totem#1629).
|
|
129
|
+
// Duplicate full hashes in compiled-rules.json are data corruption, not
|
|
130
|
+
// prefix ambiguity; the "provide more characters to disambiguate" hint
|
|
131
|
+
// is impossible to satisfy when the full hash itself collides. Surface
|
|
132
|
+
// this as a distinct failure mode before prefix resolution runs.
|
|
133
|
+
const byHash = new Map();
|
|
134
|
+
const duplicates = new Set();
|
|
135
|
+
for (const r of rulesFile.rules) {
|
|
136
|
+
const key = r.lessonHash.toLowerCase();
|
|
137
|
+
if (byHash.has(key)) {
|
|
138
|
+
duplicates.add(key);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
byHash.set(key, r);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (duplicates.size > 0) {
|
|
145
|
+
log.error('Totem Error', `compiled-rules.json contains duplicate lessonHash entries: ${[...duplicates].join(', ')}`);
|
|
146
|
+
log.dim(TAG, 'This is data corruption. Run `totem verify-manifest` and investigate.');
|
|
147
|
+
process.exitCode = 1;
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const matches = rulesFile.rules.filter((r) => r.lessonHash.toLowerCase().startsWith(id.toLowerCase()));
|
|
151
|
+
if (matches.length === 0) {
|
|
152
|
+
log.error('Totem Error', `No rule found matching '${id}'`);
|
|
153
|
+
process.exitCode = 1;
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (matches.length > 1) {
|
|
157
|
+
log.warn(TAG, `Ambiguous prefix '${id}' matches ${matches.length} rules:`);
|
|
158
|
+
for (const m of matches) {
|
|
159
|
+
log.info(TAG, ` ${bold(m.lessonHash)} — ${m.lessonHeading}`);
|
|
160
|
+
}
|
|
161
|
+
log.dim(TAG, 'Provide more characters to disambiguate.');
|
|
162
|
+
process.exitCode = 1;
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const rule = matches[0];
|
|
166
|
+
// Preflight the manifest read BEFORE mutating rules.json (mmnto-ai/
|
|
167
|
+
// totem#1601 CR pattern on rulePromoteCommand). Missing / corrupt /
|
|
168
|
+
// unwritable manifest must fail out before any side effects on the
|
|
169
|
+
// rules file.
|
|
170
|
+
const compileManifest = readCompileManifest(manifestPath);
|
|
171
|
+
// Idempotent lifecycle transition: first archive owns archivedAt;
|
|
172
|
+
// reruns refresh archivedReason but leave archivedAt untouched. Matches
|
|
173
|
+
// the canonical archive-script shape standardized in mmnto-ai/totem#1625.
|
|
174
|
+
const wasAlreadyArchived = rule.status === 'archived';
|
|
175
|
+
rule.status = 'archived';
|
|
176
|
+
rule.archivedReason = opts.reason ?? 'Archived via `totem lesson archive`';
|
|
177
|
+
if (!rule.archivedAt) {
|
|
178
|
+
rule.archivedAt = new Date().toISOString();
|
|
179
|
+
}
|
|
180
|
+
// Atomic tmp+rename write matching the canonical on-disk format used
|
|
181
|
+
// by compile-lesson.ts, rule-mutator.ts, and rulePromoteCommand.
|
|
182
|
+
const tmpPath = `${rulesPath}.tmp`;
|
|
183
|
+
fs.writeFileSync(tmpPath, JSON.stringify(rulesFile, null, 2) + '\n', { encoding: 'utf-8' });
|
|
184
|
+
fs.renameSync(tmpPath, rulesPath);
|
|
185
|
+
// Refresh the manifest's output_hash so verify-manifest passes on the
|
|
186
|
+
// next push. Uses the compileManifest loaded above (preflighted) so the
|
|
187
|
+
// mutation order is: read-manifest -> mutate-rules -> write-rules ->
|
|
188
|
+
// update-manifest.
|
|
189
|
+
compileManifest.output_hash = generateOutputHash(rulesPath);
|
|
190
|
+
compileManifest.compiled_at = new Date().toISOString();
|
|
191
|
+
writeCompileManifest(manifestPath, compileManifest);
|
|
192
|
+
// Regenerate exports so the archived rule gets filtered out of
|
|
193
|
+
// copilot-instructions.md and junie rules.md (mirrors the compile.ts
|
|
194
|
+
// mmnto-ai/totem#1345 export-path filter). No-op if no exports are
|
|
195
|
+
// configured.
|
|
196
|
+
if (config.exports && Object.keys(config.exports).length > 0) {
|
|
197
|
+
const lessons = readAllLessons(totemDir);
|
|
198
|
+
const archivedHashes = new Set(rulesFile.rules
|
|
199
|
+
.filter((r) => r.status === 'archived')
|
|
200
|
+
.map((r) => r.lessonHash.toLowerCase()));
|
|
201
|
+
const lessonsForExport = archivedHashes.size === 0
|
|
202
|
+
? lessons
|
|
203
|
+
: lessons.filter((l) => !archivedHashes.has(hashLesson(l.heading, l.body).toLowerCase()));
|
|
204
|
+
for (const [name, filePath] of Object.entries(config.exports)) {
|
|
205
|
+
const absPath = path.join(cwd, filePath);
|
|
206
|
+
exportLessons(lessonsForExport, absPath);
|
|
207
|
+
log.dim(TAG, `Exported ${lessonsForExport.length} rules to ${filePath} (${name})`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const verb = wasAlreadyArchived ? 'Refreshed archive' : 'Archived';
|
|
211
|
+
log.success(TAG, `${verb} for rule ${bold(rule.lessonHash)} — ${rule.lessonHeading}`);
|
|
212
|
+
log.dim(TAG, 'Manifest refreshed. `totem verify-manifest` should pass.');
|
|
213
|
+
}
|
|
90
214
|
//# sourceMappingURL=lesson.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lesson.js","sourceRoot":"","sources":["../../src/commands/lesson.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lesson.js","sourceRoot":"","sources":["../../src/commands/lesson.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/lint.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TimeoutMode } from '@mmnto/totem';
|
|
1
2
|
import type { ShieldFormat } from './shield.js';
|
|
2
3
|
export interface LintOptions {
|
|
3
4
|
out?: string;
|
|
@@ -5,6 +6,13 @@ export interface LintOptions {
|
|
|
5
6
|
staged?: boolean;
|
|
6
7
|
/** PR number to post a comment on, or `true` to auto-infer from GitHub Actions env */
|
|
7
8
|
prComment?: number | true;
|
|
9
|
+
/**
|
|
10
|
+
* Bounded regex execution timeout mode (mmnto-ai/totem#1641). `strict`
|
|
11
|
+
* (default) surfaces pattern-evaluation timeouts as lint errors.
|
|
12
|
+
* `lenient` skips the timing-out rule-file pair with a warning and
|
|
13
|
+
* does not contribute to the exit code.
|
|
14
|
+
*/
|
|
15
|
+
timeoutMode?: TimeoutMode;
|
|
8
16
|
}
|
|
9
17
|
export declare function lintCommand(options: LintOptions): Promise<void>;
|
|
10
18
|
//# sourceMappingURL=lint.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/commands/lint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,sFAAsF;IACtF,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAID,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/commands/lint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,sFAAsF;IACtF,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAID,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAsHrE"}
|
package/dist/commands/lint.js
CHANGED
|
@@ -39,8 +39,9 @@ export async function lintCommand(options) {
|
|
|
39
39
|
return;
|
|
40
40
|
const allIgnore = [...config.ignorePatterns, ...(config.shieldIgnorePatterns ?? [])];
|
|
41
41
|
const exportPaths = config.exports ? Object.values(config.exports) : undefined;
|
|
42
|
+
const timeoutMode = options.timeoutMode ?? 'strict';
|
|
42
43
|
const startTime = Date.now();
|
|
43
|
-
const { violations, rules } = await runCompiledRules({
|
|
44
|
+
const { violations, rules, regexTimeouts } = await runCompiledRules({
|
|
44
45
|
diff: result.diff,
|
|
45
46
|
cwd,
|
|
46
47
|
totemDir: config.totemDir,
|
|
@@ -51,7 +52,19 @@ export async function lintCommand(options) {
|
|
|
51
52
|
tag: TAG,
|
|
52
53
|
configRoot,
|
|
53
54
|
isStaged: !!options.staged,
|
|
55
|
+
regexTimeoutMode: timeoutMode,
|
|
54
56
|
});
|
|
57
|
+
// mmnto-ai/totem#1641: strict mode surfaces any regex-evaluation timeout
|
|
58
|
+
// as a non-zero exit. Lenient mode logged warnings inside runCompiledRules
|
|
59
|
+
// and excludes timeouts from the exit code. The sub-shell CLI layer
|
|
60
|
+
// throws a TotemError so the existing exit-code wiring picks it up.
|
|
61
|
+
if (timeoutMode === 'strict' && regexTimeouts.length > 0) {
|
|
62
|
+
const { TotemError } = await import('@mmnto/totem');
|
|
63
|
+
const summary = regexTimeouts
|
|
64
|
+
.map((t) => `${t.ruleHash} on ${t.file} (${t.elapsedMs}ms)`)
|
|
65
|
+
.join('; ');
|
|
66
|
+
throw new TotemError('CHECK_FAILED', `Regex evaluation timed out on ${regexTimeouts.length} rule-file pair(s): ${summary}`, "Run with '--timeout-mode lenient' to skip timing-out rules, archive the offending rule via 'totem doctor --pr', or increase the timeout budget.");
|
|
67
|
+
}
|
|
55
68
|
// Post PR comment if requested (zero-API-keys invariant: only behind --pr-comment flag)
|
|
56
69
|
if (options.prComment == null)
|
|
57
70
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lint.js","sourceRoot":"","sources":["../../src/commands/lint.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lint.js","sourceRoot":"","sources":["../../src/commands/lint.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,7 +24,13 @@ vi.mock('../git.js', () => ({
|
|
|
24
24
|
}));
|
|
25
25
|
// ─── Mock run-compiled-rules to avoid needing real rules ─
|
|
26
26
|
vi.mock('./run-compiled-rules.js', () => ({
|
|
27
|
-
runCompiledRules: async () => ({
|
|
27
|
+
runCompiledRules: async () => ({
|
|
28
|
+
violations: [],
|
|
29
|
+
rules: [],
|
|
30
|
+
output: '',
|
|
31
|
+
findings: [],
|
|
32
|
+
regexTimeouts: [],
|
|
33
|
+
}),
|
|
28
34
|
}));
|
|
29
35
|
// ─── Helpers ────────────────────────────────────────────
|
|
30
36
|
function makeTmpDir() {
|
|
@@ -105,4 +111,68 @@ describe('lintCommand staleness check', () => {
|
|
|
105
111
|
await expect(lintCommand({})).resolves.toBeUndefined();
|
|
106
112
|
});
|
|
107
113
|
});
|
|
114
|
+
// ─── Regex timeout strict/lenient mode (mmnto-ai/totem#1641) ────
|
|
115
|
+
describe('lintCommand regex timeout handling', () => {
|
|
116
|
+
let tmpDir;
|
|
117
|
+
let originalCwd;
|
|
118
|
+
beforeEach(() => {
|
|
119
|
+
tmpDir = makeTmpDir();
|
|
120
|
+
originalCwd = process.cwd();
|
|
121
|
+
process.chdir(tmpDir);
|
|
122
|
+
fs.writeFileSync(path.join(tmpDir, 'totem.config.ts'), 'export default {};', 'utf-8');
|
|
123
|
+
const { lessonsDir, rulesPath, manifestPath } = scaffold(tmpDir);
|
|
124
|
+
writeValidManifest(manifestPath, lessonsDir, rulesPath);
|
|
125
|
+
});
|
|
126
|
+
afterEach(() => {
|
|
127
|
+
process.chdir(originalCwd);
|
|
128
|
+
cleanTmpDir(tmpDir);
|
|
129
|
+
vi.clearAllMocks();
|
|
130
|
+
vi.resetModules();
|
|
131
|
+
});
|
|
132
|
+
it('throws TotemError in strict mode when regex timeouts are present', async () => {
|
|
133
|
+
vi.doMock('./run-compiled-rules.js', () => ({
|
|
134
|
+
runCompiledRules: async () => ({
|
|
135
|
+
violations: [],
|
|
136
|
+
rules: [],
|
|
137
|
+
output: '',
|
|
138
|
+
findings: [],
|
|
139
|
+
regexTimeouts: [
|
|
140
|
+
{ ruleHash: 'hungRule', file: 'app.ts', elapsedMs: 120, mode: 'strict' },
|
|
141
|
+
],
|
|
142
|
+
}),
|
|
143
|
+
}));
|
|
144
|
+
const { lintCommand } = await import('./lint.js');
|
|
145
|
+
await expect(lintCommand({ timeoutMode: 'strict' })).rejects.toThrow(/Regex evaluation timed out/);
|
|
146
|
+
});
|
|
147
|
+
it('does not throw in lenient mode even when regex timeouts are present', async () => {
|
|
148
|
+
vi.doMock('./run-compiled-rules.js', () => ({
|
|
149
|
+
runCompiledRules: async () => ({
|
|
150
|
+
violations: [],
|
|
151
|
+
rules: [],
|
|
152
|
+
output: '',
|
|
153
|
+
findings: [],
|
|
154
|
+
regexTimeouts: [
|
|
155
|
+
{ ruleHash: 'hungRule', file: 'app.ts', elapsedMs: 120, mode: 'lenient' },
|
|
156
|
+
],
|
|
157
|
+
}),
|
|
158
|
+
}));
|
|
159
|
+
const { lintCommand } = await import('./lint.js');
|
|
160
|
+
await expect(lintCommand({ timeoutMode: 'lenient' })).resolves.toBeUndefined();
|
|
161
|
+
});
|
|
162
|
+
it('does not throw in strict mode when regex timeouts array is empty', async () => {
|
|
163
|
+
// Locks in that the strict-mode throw fires ONLY on non-empty timeouts,
|
|
164
|
+
// not on every strict-mode run.
|
|
165
|
+
vi.doMock('./run-compiled-rules.js', () => ({
|
|
166
|
+
runCompiledRules: async () => ({
|
|
167
|
+
violations: [],
|
|
168
|
+
rules: [],
|
|
169
|
+
output: '',
|
|
170
|
+
findings: [],
|
|
171
|
+
regexTimeouts: [],
|
|
172
|
+
}),
|
|
173
|
+
}));
|
|
174
|
+
const { lintCommand } = await import('./lint.js');
|
|
175
|
+
await expect(lintCommand({ timeoutMode: 'strict' })).resolves.toBeUndefined();
|
|
176
|
+
});
|
|
177
|
+
});
|
|
108
178
|
//# sourceMappingURL=lint.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lint.test.js","sourceRoot":"","sources":["../../src/commands/lint.test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAEzE,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAE3F,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,2DAA2D;AAE3D,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,IAAI,EAAE;IAChC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,YAAY,CAA+B,aAAa,CAAC,CAAC;IAClF,OAAO;QACL,GAAG,MAAM;QACT,iBAAiB,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC;QACrE,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YACvB,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,QAAQ;YAClB,cAAc,EAAE,EAAE;SACnB,CAAC;QACF,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;KAClB,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,2DAA2D;AAE3D,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC;IAC1B,gBAAgB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;CAC7C,CAAC,CAAC,CAAC;AAEJ,4DAA4D;AAE5D,EAAE,CAAC,IAAI,CAAC,yBAAyB,EAAE,GAAG,EAAE,CAAC,CAAC;IACxC,gBAAgB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"lint.test.js","sourceRoot":"","sources":["../../src/commands/lint.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CompiledRule, TotemFinding, Violation } from '@mmnto/totem';
|
|
1
|
+
import type { CompiledRule, RuleTimeoutOutcome, TimeoutMode, TotemFinding, Violation } from '@mmnto/totem';
|
|
2
2
|
import type { ShieldFormat } from './shield.js';
|
|
3
3
|
export interface RunCompiledRulesOptions {
|
|
4
4
|
diff: string;
|
|
@@ -13,6 +13,13 @@ export interface RunCompiledRulesOptions {
|
|
|
13
13
|
configRoot?: string;
|
|
14
14
|
/** True if we are linting staged changes only */
|
|
15
15
|
isStaged?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Bounded regex execution timeout mode (mmnto-ai/totem#1641). `strict`
|
|
18
|
+
* (default) surfaces regex timeouts as lint errors that contribute to
|
|
19
|
+
* the non-zero exit code. `lenient` skips the timing-out rule-file pair
|
|
20
|
+
* with a visible warning and excludes timeouts from the exit code.
|
|
21
|
+
*/
|
|
22
|
+
regexTimeoutMode?: TimeoutMode;
|
|
16
23
|
}
|
|
17
24
|
export interface RunCompiledRulesResult {
|
|
18
25
|
violations: Violation[];
|
|
@@ -20,6 +27,13 @@ export interface RunCompiledRulesResult {
|
|
|
20
27
|
findings: TotemFinding[];
|
|
21
28
|
rules: CompiledRule[];
|
|
22
29
|
output: string;
|
|
30
|
+
/**
|
|
31
|
+
* Any regex rule-file pairs that timed out during bounded evaluation
|
|
32
|
+
* (mmnto-ai/totem#1641). Empty on healthy runs. Strict mode expects the
|
|
33
|
+
* CLI caller to fail non-zero when non-empty; lenient mode emits
|
|
34
|
+
* warnings only.
|
|
35
|
+
*/
|
|
36
|
+
regexTimeouts: RuleTimeoutOutcome[];
|
|
23
37
|
}
|
|
24
38
|
/**
|
|
25
39
|
* Compiled-rules execution engine used by `totem lint`. Loads rules, extracts additions, enriches
|