@mmnto/cli 1.15.0 → 1.15.2
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/adr.d.ts +15 -0
- package/dist/commands/adr.d.ts.map +1 -0
- package/dist/commands/adr.js +24 -0
- package/dist/commands/adr.js.map +1 -0
- package/dist/commands/adr.test.d.ts +2 -0
- package/dist/commands/adr.test.d.ts.map +1 -0
- package/dist/commands/adr.test.js +70 -0
- package/dist/commands/adr.test.js.map +1 -0
- 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.d.ts +30 -0
- package/dist/commands/compile.d.ts.map +1 -1
- package/dist/commands/compile.js +120 -23
- 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/proposal.d.ts +15 -0
- package/dist/commands/proposal.d.ts.map +1 -0
- package/dist/commands/proposal.js +24 -0
- package/dist/commands/proposal.js.map +1 -0
- package/dist/commands/proposal.test.d.ts +2 -0
- package/dist/commands/proposal.test.d.ts.map +1 -0
- package/dist/commands/proposal.test.js +66 -0
- package/dist/commands/proposal.test.js.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/governance.d.ts +175 -0
- package/dist/utils/governance.d.ts.map +1 -0
- package/dist/utils/governance.js +327 -0
- package/dist/utils/governance.js.map +1 -0
- package/dist/utils/governance.test.d.ts +2 -0
- package/dist/utils/governance.test.d.ts.map +1 -0
- package/dist/utils/governance.test.js +525 -0
- package/dist/utils/governance.test.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `totem adr new <title>` — scaffolding entry point (mmnto/totem#1288).
|
|
3
|
+
*
|
|
4
|
+
* Resolves the strategy repo layout (submodule or standalone), writes the
|
|
5
|
+
* next NNN-prefixed ADR under `adr/`, refreshes the dashboard via
|
|
6
|
+
* `pnpm run docs:inject`, and stages the two mutated paths. All
|
|
7
|
+
* orchestration logic lives in `../utils/governance.ts`; this file is the
|
|
8
|
+
* thin CLI adapter that prints the user-facing summary.
|
|
9
|
+
*/
|
|
10
|
+
export interface AdrNewOptions {
|
|
11
|
+
/** Override the cwd (test seam). Defaults to `process.cwd()`. */
|
|
12
|
+
cwd?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function adrNewCommand(title: string, options?: AdrNewOptions): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=adr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adr.d.ts","sourceRoot":"","sources":["../../src/commands/adr.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,WAAW,aAAa;IAC5B,iEAAiE;IACjE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAe7F"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `totem adr new <title>` — scaffolding entry point (mmnto/totem#1288).
|
|
3
|
+
*
|
|
4
|
+
* Resolves the strategy repo layout (submodule or standalone), writes the
|
|
5
|
+
* next NNN-prefixed ADR under `adr/`, refreshes the dashboard via
|
|
6
|
+
* `pnpm run docs:inject`, and stages the two mutated paths. All
|
|
7
|
+
* orchestration logic lives in `../utils/governance.ts`; this file is the
|
|
8
|
+
* thin CLI adapter that prints the user-facing summary.
|
|
9
|
+
*/
|
|
10
|
+
const TAG = 'ADR';
|
|
11
|
+
export async function adrNewCommand(title, options = {}) {
|
|
12
|
+
const path = await import('node:path');
|
|
13
|
+
const { log, bold } = await import('../ui.js');
|
|
14
|
+
const { scaffoldGovernanceArtifact } = await import('../utils/governance.js');
|
|
15
|
+
const cwd = options.cwd ?? process.cwd();
|
|
16
|
+
const result = scaffoldGovernanceArtifact({ type: 'adr', title, cwd });
|
|
17
|
+
const relPath = path.relative(cwd, result.filePath);
|
|
18
|
+
const dashboardSummary = result.dashboardRefreshed
|
|
19
|
+
? 'dashboard refreshed'
|
|
20
|
+
: 'dashboard refresh skipped (manual required)';
|
|
21
|
+
const stagedSummary = result.staged ? 'staged' : 'not staged (manual git add required)';
|
|
22
|
+
log.success(TAG, `Scaffolded ${bold(relPath)}; ${dashboardSummary}; ${stagedSummary}.`);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=adr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adr.js","sourceRoot":"","sources":["../../src/commands/adr.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,GAAG,GAAG,KAAK,CAAC;AAOlB,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAa,EAAE,UAAyB,EAAE;IAC5E,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;IACvC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;IAC/C,MAAM,EAAE,0BAA0B,EAAE,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;IAE9E,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,MAAM,GAAG,0BAA0B,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IAEvE,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACpD,MAAM,gBAAgB,GAAG,MAAM,CAAC,kBAAkB;QAChD,CAAC,CAAC,qBAAqB;QACvB,CAAC,CAAC,6CAA6C,CAAC;IAClD,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,sCAAsC,CAAC;IAExF,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,cAAc,IAAI,CAAC,OAAO,CAAC,KAAK,gBAAgB,KAAK,aAAa,GAAG,CAAC,CAAC;AAC1F,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adr.test.d.ts","sourceRoot":"","sources":["../../src/commands/adr.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,70 @@
|
|
|
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, vi } from 'vitest';
|
|
5
|
+
import { cleanTmpDir } from '../test-utils.js';
|
|
6
|
+
function makeTmpDir() {
|
|
7
|
+
// `.native` expands Windows 8.3 short names; plain `realpathSync` does not.
|
|
8
|
+
// Required for parity with `git rev-parse --show-toplevel` on Windows CI.
|
|
9
|
+
return fs.realpathSync.native(fs.mkdtempSync(path.join(os.tmpdir(), 'totem-adr-')));
|
|
10
|
+
}
|
|
11
|
+
function initGit(dir) {
|
|
12
|
+
fs.mkdirSync(path.join(dir, '.git'), { recursive: true });
|
|
13
|
+
fs.writeFileSync(path.join(dir, '.git', 'HEAD'), 'ref: refs/heads/main\n', 'utf-8');
|
|
14
|
+
fs.writeFileSync(path.join(dir, '.git', 'config'), '[core]\n\trepositoryformatversion = 0\n', 'utf-8');
|
|
15
|
+
fs.mkdirSync(path.join(dir, '.git', 'objects'), { recursive: true });
|
|
16
|
+
fs.mkdirSync(path.join(dir, '.git', 'refs', 'heads'), { recursive: true });
|
|
17
|
+
}
|
|
18
|
+
/** Stub `safeExec` so the hooks run without spawning real subprocesses. */
|
|
19
|
+
vi.mock('@mmnto/totem', async () => {
|
|
20
|
+
const actual = await vi.importActual('@mmnto/totem');
|
|
21
|
+
return {
|
|
22
|
+
...actual,
|
|
23
|
+
safeExec: vi.fn((_cmd, _args) => ''),
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
describe('adrNewCommand', () => {
|
|
27
|
+
let tmpDir;
|
|
28
|
+
let originalCwd;
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
tmpDir = makeTmpDir();
|
|
31
|
+
originalCwd = process.cwd();
|
|
32
|
+
});
|
|
33
|
+
afterEach(() => {
|
|
34
|
+
process.chdir(originalCwd);
|
|
35
|
+
cleanTmpDir(tmpDir);
|
|
36
|
+
vi.restoreAllMocks();
|
|
37
|
+
});
|
|
38
|
+
it('creates 001-database-sharding.md with ADR-091 heading format', async () => {
|
|
39
|
+
initGit(tmpDir);
|
|
40
|
+
fs.mkdirSync(path.join(tmpDir, 'proposals', 'active'), { recursive: true });
|
|
41
|
+
fs.mkdirSync(path.join(tmpDir, 'adr'), { recursive: true });
|
|
42
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
43
|
+
const { adrNewCommand } = await import('./adr.js');
|
|
44
|
+
await adrNewCommand('Database Sharding', { cwd: tmpDir });
|
|
45
|
+
const filePath = path.join(tmpDir, 'adr', '001-database-sharding.md');
|
|
46
|
+
expect(fs.existsSync(filePath)).toBe(true);
|
|
47
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
48
|
+
// ADR-091: `# ADR NNN: Title` with SPACE separator, not a hyphen.
|
|
49
|
+
expect(content).toContain('# ADR 001: Database Sharding');
|
|
50
|
+
expect(content).not.toContain('# ADR-001');
|
|
51
|
+
expect(content).toContain('**Status:** Draft');
|
|
52
|
+
const output = consoleSpy.mock.calls.map((c) => String(c[0])).join('\n');
|
|
53
|
+
expect(output).toContain('Scaffolded');
|
|
54
|
+
expect(output).toContain('001-database-sharding.md');
|
|
55
|
+
});
|
|
56
|
+
it('respects gap numbering in adr/ directory', async () => {
|
|
57
|
+
initGit(tmpDir);
|
|
58
|
+
fs.mkdirSync(path.join(tmpDir, 'adr'), { recursive: true });
|
|
59
|
+
fs.writeFileSync(path.join(tmpDir, 'adr', '001-alpha.md'), '# a\n', 'utf-8');
|
|
60
|
+
fs.writeFileSync(path.join(tmpDir, 'adr', '004-beta.md'), '# b\n', 'utf-8');
|
|
61
|
+
const { adrNewCommand } = await import('./adr.js');
|
|
62
|
+
await adrNewCommand('Charlie', { cwd: tmpDir });
|
|
63
|
+
// Gap logic: max=4, next=005.
|
|
64
|
+
const filePath = path.join(tmpDir, 'adr', '005-charlie.md');
|
|
65
|
+
expect(fs.existsSync(filePath)).toBe(true);
|
|
66
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
67
|
+
expect(content).toContain('# ADR 005: Charlie');
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
//# sourceMappingURL=adr.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adr.test.js","sourceRoot":"","sources":["../../src/commands/adr.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { pruneStaleNonCompilable, pruneStaleRules } from './compile.js';
|
|
2
|
+
import { pruneStaleNonCompilable, pruneStaleRules, removeRuleByHash, upsertRule, } from './compile.js';
|
|
3
3
|
// ─── 4-tuple helpers (mmnto-ai/totem#1481) ───────────
|
|
4
4
|
function entry(title, reasonCode = 'out-of-scope', reason) {
|
|
5
5
|
return reason === undefined ? { title, reasonCode } : { title, reasonCode, reason };
|
|
@@ -130,4 +130,59 @@ describe('pruneStaleRules', () => {
|
|
|
130
130
|
expect(rules[1].lessonHash).toBe('stale');
|
|
131
131
|
});
|
|
132
132
|
});
|
|
133
|
+
// ─── upsertRule (mmnto-ai/totem#1587) ────────────────
|
|
134
|
+
describe('upsertRule', () => {
|
|
135
|
+
it('appends when no entry with the same lessonHash exists', () => {
|
|
136
|
+
const rules = [makeRule('abc'), makeRule('def')];
|
|
137
|
+
const fresh = makeRule('ghi', 'New rule');
|
|
138
|
+
upsertRule(rules, fresh);
|
|
139
|
+
expect(rules).toHaveLength(3);
|
|
140
|
+
expect(rules[2]).toBe(fresh);
|
|
141
|
+
});
|
|
142
|
+
it('replaces in-place when an entry with the same lessonHash exists', () => {
|
|
143
|
+
// Order preservation is load-bearing: re-compiling a mid-array rule
|
|
144
|
+
// under --force must NOT move it to the end. Appending instead of
|
|
145
|
+
// replacing causes diff churn in compiled-rules.json on every force
|
|
146
|
+
// run (CR finding on PR mmnto-ai/totem#1629).
|
|
147
|
+
const ruleA = makeRule('abc', 'Old A');
|
|
148
|
+
const ruleB = makeRule('def', 'B');
|
|
149
|
+
const ruleC = makeRule('ghi', 'C');
|
|
150
|
+
const rules = [ruleA, ruleB, ruleC];
|
|
151
|
+
const replacement = makeRule('abc', 'New A');
|
|
152
|
+
upsertRule(rules, replacement);
|
|
153
|
+
expect(rules).toHaveLength(3);
|
|
154
|
+
expect(rules[0]).toBe(replacement);
|
|
155
|
+
expect(rules[0].lessonHeading).toBe('New A');
|
|
156
|
+
expect(rules[1]).toBe(ruleB);
|
|
157
|
+
expect(rules[2]).toBe(ruleC);
|
|
158
|
+
});
|
|
159
|
+
it('is idempotent when called twice with the same rule object', () => {
|
|
160
|
+
const rules = [makeRule('abc', 'Original')];
|
|
161
|
+
const replacement = makeRule('abc', 'Updated');
|
|
162
|
+
upsertRule(rules, replacement);
|
|
163
|
+
upsertRule(rules, replacement);
|
|
164
|
+
expect(rules).toHaveLength(1);
|
|
165
|
+
expect(rules[0]).toBe(replacement);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
// ─── removeRuleByHash (mmnto-ai/totem#1587 + mmnto-ai/totem#1629 cloud parity) ──
|
|
169
|
+
describe('removeRuleByHash', () => {
|
|
170
|
+
it('removes the matching rule in place and preserves order of the rest', () => {
|
|
171
|
+
const ruleA = makeRule('abc', 'A');
|
|
172
|
+
const ruleB = makeRule('def', 'B');
|
|
173
|
+
const ruleC = makeRule('ghi', 'C');
|
|
174
|
+
const rules = [ruleA, ruleB, ruleC];
|
|
175
|
+
removeRuleByHash(rules, 'def');
|
|
176
|
+
expect(rules).toHaveLength(2);
|
|
177
|
+
expect(rules[0]).toBe(ruleA);
|
|
178
|
+
expect(rules[1]).toBe(ruleC);
|
|
179
|
+
});
|
|
180
|
+
it('is a no-op when the hash does not match any rule', () => {
|
|
181
|
+
const rules = [makeRule('abc'), makeRule('def')];
|
|
182
|
+
removeRuleByHash(rules, 'missing');
|
|
183
|
+
expect(rules).toHaveLength(2);
|
|
184
|
+
expect(rules[0].lessonHash).toBe('abc');
|
|
185
|
+
expect(rules[1].lessonHash).toBe('def');
|
|
186
|
+
});
|
|
187
|
+
});
|
|
133
188
|
//# sourceMappingURL=compile-prune.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile-prune.test.js","sourceRoot":"","sources":["../../src/commands/compile-prune.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAK9C,OAAO,
|
|
1
|
+
{"version":3,"file":"compile-prune.test.js","sourceRoot":"","sources":["../../src/commands/compile-prune.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile-refresh-manifest.test.d.ts","sourceRoot":"","sources":["../../src/commands/compile-refresh-manifest.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,163 @@
|
|
|
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, hashLesson, readCompileManifest } from '@mmnto/totem';
|
|
6
|
+
import { cleanTmpDir } from '../test-utils.js';
|
|
7
|
+
import { compileCommand } from './compile.js';
|
|
8
|
+
// ─── Helpers ─────────────────────────────────────────
|
|
9
|
+
//
|
|
10
|
+
// These tests exercise the `--refresh-manifest` primitive (mmnto-ai/totem#1587).
|
|
11
|
+
// The flag must recompute output_hash from the current compiled-rules.json
|
|
12
|
+
// state without invoking the LLM or touching any lessons. It is the non-LLM
|
|
13
|
+
// complement to #1348's input-hash drift refresh, covering the postmerge
|
|
14
|
+
// inline-archive workflow where a rule's `status: 'archived'` field is set
|
|
15
|
+
// directly by a curation script.
|
|
16
|
+
function makeTmpDir() {
|
|
17
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), 'totem-refresh-manifest-'));
|
|
18
|
+
}
|
|
19
|
+
function lessonMarkdown(heading, body) {
|
|
20
|
+
return `## Lesson — ${heading}\n\n**Tags:** test\n\n${body}\n`;
|
|
21
|
+
}
|
|
22
|
+
function setupWorkspace(tmpDir, options) {
|
|
23
|
+
fs.writeFileSync(path.join(tmpDir, 'totem.config.ts'), [
|
|
24
|
+
'export default {',
|
|
25
|
+
' targets: [{ glob: "**/*.ts", type: "code", strategy: "typescript-ast" }],',
|
|
26
|
+
' totemDir: ".totem",',
|
|
27
|
+
' orchestrator: {',
|
|
28
|
+
' provider: "shell",',
|
|
29
|
+
' command: "echo should-never-run",',
|
|
30
|
+
' defaultModel: "test-model",',
|
|
31
|
+
' },',
|
|
32
|
+
'};',
|
|
33
|
+
'',
|
|
34
|
+
].join('\n'), 'utf-8');
|
|
35
|
+
const totemDir = path.join(tmpDir, '.totem');
|
|
36
|
+
const lessonsDir = path.join(totemDir, 'lessons');
|
|
37
|
+
fs.mkdirSync(lessonsDir, { recursive: true });
|
|
38
|
+
for (const [name, body] of Object.entries(options.lessons)) {
|
|
39
|
+
fs.writeFileSync(path.join(lessonsDir, name), body, 'utf-8');
|
|
40
|
+
}
|
|
41
|
+
const rulesPath = path.join(totemDir, 'compiled-rules.json');
|
|
42
|
+
const now = '2026-04-22T00:00:00Z';
|
|
43
|
+
fs.writeFileSync(rulesPath, JSON.stringify({
|
|
44
|
+
version: 1,
|
|
45
|
+
rules: options.rules.map((r) => ({
|
|
46
|
+
lessonHash: r.lessonHash,
|
|
47
|
+
lessonHeading: r.lessonHeading,
|
|
48
|
+
pattern: 'dummy-never-matches',
|
|
49
|
+
message: r.lessonHeading,
|
|
50
|
+
engine: 'regex',
|
|
51
|
+
compiledAt: now,
|
|
52
|
+
...(r.status ? { status: r.status } : {}),
|
|
53
|
+
})),
|
|
54
|
+
nonCompilable: [],
|
|
55
|
+
}, null, 2) + '\n', 'utf-8');
|
|
56
|
+
// Write manifest with an output_hash that matches the rules file as written.
|
|
57
|
+
// Tests that want drift will mutate the rules file AFTER setupWorkspace.
|
|
58
|
+
const manifestPath = path.join(totemDir, 'compile-manifest.json');
|
|
59
|
+
fs.writeFileSync(manifestPath, JSON.stringify({
|
|
60
|
+
compiled_at: now,
|
|
61
|
+
model: 'test-model',
|
|
62
|
+
input_hash: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
63
|
+
output_hash: generateOutputHash(rulesPath),
|
|
64
|
+
rule_count: options.rules.length,
|
|
65
|
+
}, null, 2) + '\n', 'utf-8');
|
|
66
|
+
}
|
|
67
|
+
describe('compileCommand --refresh-manifest (#1587)', () => {
|
|
68
|
+
let tmpDir;
|
|
69
|
+
let originalCwd;
|
|
70
|
+
beforeEach(() => {
|
|
71
|
+
tmpDir = makeTmpDir();
|
|
72
|
+
originalCwd = process.cwd();
|
|
73
|
+
process.chdir(tmpDir);
|
|
74
|
+
});
|
|
75
|
+
afterEach(() => {
|
|
76
|
+
process.chdir(originalCwd);
|
|
77
|
+
cleanTmpDir(tmpDir);
|
|
78
|
+
});
|
|
79
|
+
it('updates manifest output_hash without invoking compilation when --refresh-manifest is passed', async () => {
|
|
80
|
+
// Scenario: a postmerge archive script mutates compiled-rules.json in
|
|
81
|
+
// place (flipping status to 'archived'). The output_hash in the manifest
|
|
82
|
+
// is now stale. `--refresh-manifest` must recompute it without running
|
|
83
|
+
// the LLM or touching lessons.
|
|
84
|
+
const heading = 'Use err in catch';
|
|
85
|
+
const body = 'Do not use the identifier "error" in catch blocks.';
|
|
86
|
+
const lessonHash = hashLesson(heading, body);
|
|
87
|
+
setupWorkspace(tmpDir, {
|
|
88
|
+
lessons: { 'use-err.md': lessonMarkdown(heading, body) },
|
|
89
|
+
rules: [{ lessonHash, lessonHeading: heading }],
|
|
90
|
+
});
|
|
91
|
+
const totemDir = path.join(tmpDir, '.totem');
|
|
92
|
+
const rulesPath = path.join(totemDir, 'compiled-rules.json');
|
|
93
|
+
const manifestPath = path.join(totemDir, 'compile-manifest.json');
|
|
94
|
+
const manifestBefore = readCompileManifest(manifestPath);
|
|
95
|
+
const hashBefore = manifestBefore.output_hash;
|
|
96
|
+
// Simulate the postmerge archive-in-place: mutate compiled-rules.json
|
|
97
|
+
// directly (flip status to 'archived' on the only rule).
|
|
98
|
+
const rulesJson = JSON.parse(fs.readFileSync(rulesPath, 'utf-8'));
|
|
99
|
+
rulesJson.rules[0].status = 'archived';
|
|
100
|
+
rulesJson.rules[0].archivedReason = 'test archive';
|
|
101
|
+
rulesJson.rules[0].archivedAt = '2026-04-23T00:00:00Z';
|
|
102
|
+
fs.writeFileSync(rulesPath, JSON.stringify(rulesJson, null, 2) + '\n', 'utf-8');
|
|
103
|
+
const rulesFileHashAfterMutation = generateOutputHash(rulesPath);
|
|
104
|
+
expect(rulesFileHashAfterMutation).not.toBe(hashBefore);
|
|
105
|
+
await compileCommand({ refreshManifest: true });
|
|
106
|
+
const manifestAfter = readCompileManifest(manifestPath);
|
|
107
|
+
expect(manifestAfter.output_hash).toBe(rulesFileHashAfterMutation);
|
|
108
|
+
});
|
|
109
|
+
it('is a no-op when the manifest is already fresh', async () => {
|
|
110
|
+
// Baseline: rules and manifest agree. `--refresh-manifest` must not
|
|
111
|
+
// write the manifest back (no compiled_at bump, no byte change).
|
|
112
|
+
const heading = 'Use err in catch';
|
|
113
|
+
const body = 'Do not use the identifier "error" in catch blocks.';
|
|
114
|
+
const lessonHash = hashLesson(heading, body);
|
|
115
|
+
setupWorkspace(tmpDir, {
|
|
116
|
+
lessons: { 'use-err.md': lessonMarkdown(heading, body) },
|
|
117
|
+
rules: [{ lessonHash, lessonHeading: heading }],
|
|
118
|
+
});
|
|
119
|
+
const totemDir = path.join(tmpDir, '.totem');
|
|
120
|
+
const manifestPath = path.join(totemDir, 'compile-manifest.json');
|
|
121
|
+
const manifestBytesBefore = fs.readFileSync(manifestPath, 'utf-8');
|
|
122
|
+
await compileCommand({ refreshManifest: true });
|
|
123
|
+
const manifestBytesAfter = fs.readFileSync(manifestPath, 'utf-8');
|
|
124
|
+
expect(manifestBytesAfter).toBe(manifestBytesBefore);
|
|
125
|
+
});
|
|
126
|
+
it('throws TotemConfigError when combined with --force', async () => {
|
|
127
|
+
// Strict exclusivity: --refresh-manifest is a no-LLM primitive and
|
|
128
|
+
// cannot combine with --force (an LLM-invoking regenerate). The combo
|
|
129
|
+
// is incoherent; fail loud rather than pick a silent resolution.
|
|
130
|
+
const heading = 'Use err in catch';
|
|
131
|
+
const body = 'Do not use the identifier "error" in catch blocks.';
|
|
132
|
+
const lessonHash = hashLesson(heading, body);
|
|
133
|
+
setupWorkspace(tmpDir, {
|
|
134
|
+
lessons: { 'use-err.md': lessonMarkdown(heading, body) },
|
|
135
|
+
rules: [{ lessonHash, lessonHeading: heading }],
|
|
136
|
+
});
|
|
137
|
+
await expect(compileCommand({ refreshManifest: true, force: true })).rejects.toMatchObject({
|
|
138
|
+
code: 'CONFIG_INVALID',
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
it('leaves the rules file untouched on a successful refresh', async () => {
|
|
142
|
+
// The primitive must be read-only w.r.t. compiled-rules.json. Only the
|
|
143
|
+
// manifest is written. Byte-for-byte equality is the strictest check.
|
|
144
|
+
const heading = 'Use err in catch';
|
|
145
|
+
const body = 'Do not use the identifier "error" in catch blocks.';
|
|
146
|
+
const lessonHash = hashLesson(heading, body);
|
|
147
|
+
setupWorkspace(tmpDir, {
|
|
148
|
+
lessons: { 'use-err.md': lessonMarkdown(heading, body) },
|
|
149
|
+
rules: [{ lessonHash, lessonHeading: heading, status: 'archived' }],
|
|
150
|
+
});
|
|
151
|
+
const totemDir = path.join(tmpDir, '.totem');
|
|
152
|
+
const rulesPath = path.join(totemDir, 'compiled-rules.json');
|
|
153
|
+
// Mutate the rules file so there is drift to refresh against.
|
|
154
|
+
const rulesJson = JSON.parse(fs.readFileSync(rulesPath, 'utf-8'));
|
|
155
|
+
rulesJson.rules[0].archivedReason = 'test archive drift';
|
|
156
|
+
fs.writeFileSync(rulesPath, JSON.stringify(rulesJson, null, 2) + '\n', 'utf-8');
|
|
157
|
+
const rulesBytesBefore = fs.readFileSync(rulesPath, 'utf-8');
|
|
158
|
+
await compileCommand({ refreshManifest: true });
|
|
159
|
+
const rulesBytesAfter = fs.readFileSync(rulesPath, 'utf-8');
|
|
160
|
+
expect(rulesBytesAfter).toBe(rulesBytesBefore);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
//# sourceMappingURL=compile-refresh-manifest.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile-refresh-manifest.test.js","sourceRoot":"","sources":["../../src/commands/compile-refresh-manifest.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -52,6 +52,16 @@ export interface CompileOptions {
|
|
|
52
52
|
/** Telemetry directive to inject into the Pipeline 2 prompt for this lesson. */
|
|
53
53
|
telemetryPrefix?: string;
|
|
54
54
|
}>;
|
|
55
|
+
/**
|
|
56
|
+
* Recompute `compile-manifest.json`'s `output_hash` from the current
|
|
57
|
+
* `compiled-rules.json` state without invoking the LLM or touching any
|
|
58
|
+
* lessons (mmnto-ai/totem#1587). Exists to support the postmerge
|
|
59
|
+
* inline-archive workflow where a curation script mutates
|
|
60
|
+
* `status: 'archived'` on a rule directly; `--refresh-manifest` is the
|
|
61
|
+
* blessed way to re-sync the manifest afterwards. Cannot combine with
|
|
62
|
+
* `--force`.
|
|
63
|
+
*/
|
|
64
|
+
refreshManifest?: boolean;
|
|
55
65
|
}
|
|
56
66
|
/**
|
|
57
67
|
* Build the directive injected into the Sonnet system prompt for `--upgrade`.
|
|
@@ -112,6 +122,26 @@ export declare function pruneStaleRules(rules: readonly CompiledRule[], currentH
|
|
|
112
122
|
fresh: CompiledRule[];
|
|
113
123
|
pruned: number;
|
|
114
124
|
};
|
|
125
|
+
/**
|
|
126
|
+
* Replace-by-lessonHash if an entry with the same hash is already in the
|
|
127
|
+
* array; otherwise append. Preserves array order for existing entries so
|
|
128
|
+
* the compile loop's output stays stable across runs.
|
|
129
|
+
*
|
|
130
|
+
* Used by the --force durability path (mmnto-ai/totem#1587) and the
|
|
131
|
+
* non-force add-new-rule path: all success-side pushes go through this
|
|
132
|
+
* helper so transient compile failures leave old rules intact and
|
|
133
|
+
* repeated successes do not double-insert.
|
|
134
|
+
*/
|
|
135
|
+
export declare function upsertRule(rules: CompiledRule[], rule: CompiledRule): void;
|
|
136
|
+
/**
|
|
137
|
+
* Remove the first rule matching `lessonHash` from `rules`, in place.
|
|
138
|
+
* No-op when no match. Used on the `--force` / upgrade skipped paths in
|
|
139
|
+
* both local and cloud workers: when a lesson transitions to
|
|
140
|
+
* non-compilable, any pre-existing rule for the same hash must be evicted
|
|
141
|
+
* from the active set, otherwise --force leaves the old rule alive while
|
|
142
|
+
* also marking the hash non-compilable (mmnto-ai/totem#1629 CR finding).
|
|
143
|
+
*/
|
|
144
|
+
export declare function removeRuleByHash(rules: CompiledRule[], lessonHash: string): void;
|
|
115
145
|
/**
|
|
116
146
|
* Format a lesson's trace array into a single multi-line block for the
|
|
117
147
|
* `--verbose` renderer. Returns a string (no trailing newline — caller
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/commands/compile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EAEZ,eAAe,EACf,WAAW,EACX,kBAAkB,EAClB,uBAAuB,EACxB,MAAM,cAAc,CAAC;AAYtB;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEvE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,gFAAgF;QAChF,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/commands/compile.ts"],"names":[],"mappings":"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"}
|