@mmnto/cli 1.99.0 → 1.100.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.
- package/dist/commands/config-drift.test.js +5 -2
- package/dist/commands/config-drift.test.js.map +1 -1
- package/dist/commands/doctor-parity.d.ts.map +1 -1
- package/dist/commands/doctor-parity.js +57 -2
- package/dist/commands/doctor-parity.js.map +1 -1
- package/dist/commands/doctor-parity.test.js +60 -0
- package/dist/commands/doctor-parity.test.js.map +1 -1
- package/dist/commands/init-templates.d.ts +2 -2
- package/dist/commands/init-templates.d.ts.map +1 -1
- package/dist/commands/init-templates.js +1 -1
- package/dist/commands/install-hooks.d.ts +14 -1
- package/dist/commands/install-hooks.d.ts.map +1 -1
- package/dist/commands/install-hooks.js +109 -30
- package/dist/commands/install-hooks.js.map +1 -1
- package/dist/commands/install-hooks.test.js +105 -39
- package/dist/commands/install-hooks.test.js.map +1 -1
- package/dist/commands/lint-staleness.d.ts +122 -0
- package/dist/commands/lint-staleness.d.ts.map +1 -0
- package/dist/commands/lint-staleness.js +163 -0
- package/dist/commands/lint-staleness.js.map +1 -0
- package/dist/commands/lint-staleness.test.d.ts +2 -0
- package/dist/commands/lint-staleness.test.d.ts.map +1 -0
- package/dist/commands/lint-staleness.test.js +173 -0
- package/dist/commands/lint-staleness.test.js.map +1 -0
- package/dist/commands/lint.d.ts.map +1 -1
- package/dist/commands/lint.js +142 -3
- package/dist/commands/lint.js.map +1 -1
- package/dist/commands/tools-hook-parity.test.d.ts +2 -0
- package/dist/commands/tools-hook-parity.test.d.ts.map +1 -0
- package/dist/commands/tools-hook-parity.test.js +37 -0
- package/dist/commands/tools-hook-parity.test.js.map +1 -0
- package/dist/commands/wrap.d.ts.map +1 -1
- package/dist/commands/wrap.js +3 -2
- package/dist/commands/wrap.js.map +1 -1
- package/dist/commands/wrap.test.js +11 -1
- package/dist/commands/wrap.test.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { classifyLessonsByMtime, formatStalenessWarning, parseLessonNameStatus, PROVENANCE_LESSON_FILE_CAP, STALE_LESSON_NAME_CAP, UNTRACKED_PROVENANCE, } from './lint-staleness.js';
|
|
3
|
+
// The whole point of these helpers is to be PURE — no real git repo, no temp
|
|
4
|
+
// dir (the cohort's no-real-git-with-cwd=temp-on-Windows rule). The "git seam"
|
|
5
|
+
// is `git diff --name-status` OUTPUT, fed here as synthetic strings.
|
|
6
|
+
const LESSONS_PREFIX = '.totem/lessons';
|
|
7
|
+
const basename = (p) => p.split('/').pop() ?? p;
|
|
8
|
+
describe('parseLessonNameStatus', () => {
|
|
9
|
+
it('classifies added / changed / removed lessons', () => {
|
|
10
|
+
const raw = [
|
|
11
|
+
'A\t.totem/lessons/lesson-added.md',
|
|
12
|
+
'M\t.totem/lessons/lesson-changed.md',
|
|
13
|
+
'D\t.totem/lessons/lesson-removed.md',
|
|
14
|
+
].join('\n');
|
|
15
|
+
const delta = parseLessonNameStatus(raw, LESSONS_PREFIX);
|
|
16
|
+
expect(delta.entries).toEqual([
|
|
17
|
+
{ path: '.totem/lessons/lesson-added.md', kind: 'added' },
|
|
18
|
+
{ path: '.totem/lessons/lesson-changed.md', kind: 'changed' },
|
|
19
|
+
{ path: '.totem/lessons/lesson-removed.md', kind: 'removed' },
|
|
20
|
+
]);
|
|
21
|
+
});
|
|
22
|
+
it('treats a rename destination as changed and a copy destination as added', () => {
|
|
23
|
+
const raw = [
|
|
24
|
+
'R096\t.totem/lessons/old-name.md\t.totem/lessons/new-name.md',
|
|
25
|
+
'C100\t.totem/lessons/src.md\t.totem/lessons/copy.md',
|
|
26
|
+
].join('\n');
|
|
27
|
+
const delta = parseLessonNameStatus(raw, LESSONS_PREFIX);
|
|
28
|
+
// Sorted by path: copy.md < new-name.md.
|
|
29
|
+
expect(delta.entries).toEqual([
|
|
30
|
+
{ path: '.totem/lessons/copy.md', kind: 'added' },
|
|
31
|
+
{ path: '.totem/lessons/new-name.md', kind: 'changed' },
|
|
32
|
+
]);
|
|
33
|
+
});
|
|
34
|
+
it('maps a type-change (T) to changed', () => {
|
|
35
|
+
const delta = parseLessonNameStatus('T\t.totem/lessons/lesson-t.md', LESSONS_PREFIX);
|
|
36
|
+
expect(delta.entries).toEqual([{ path: '.totem/lessons/lesson-t.md', kind: 'changed' }]);
|
|
37
|
+
});
|
|
38
|
+
it('filters out non-.md files and paths outside the lessons prefix', () => {
|
|
39
|
+
const raw = [
|
|
40
|
+
'M\t.totem/lessons/lesson-keep.md',
|
|
41
|
+
'M\t.totem/lessons/notes.txt', // not .md
|
|
42
|
+
'M\t.totem/compiled-rules.json', // outside prefix
|
|
43
|
+
'M\tsrc/other/lesson-elsewhere.md', // outside prefix
|
|
44
|
+
].join('\n');
|
|
45
|
+
const delta = parseLessonNameStatus(raw, LESSONS_PREFIX);
|
|
46
|
+
expect(delta.entries).toEqual([{ path: '.totem/lessons/lesson-keep.md', kind: 'changed' }]);
|
|
47
|
+
});
|
|
48
|
+
it('ignores unknown status letters (e.g. unmerged) rather than guessing', () => {
|
|
49
|
+
const raw = ['U\t.totem/lessons/lesson-unmerged.md', 'A\t.totem/lessons/lesson-real.md'].join('\n');
|
|
50
|
+
const delta = parseLessonNameStatus(raw, LESSONS_PREFIX);
|
|
51
|
+
expect(delta.entries).toEqual([{ path: '.totem/lessons/lesson-real.md', kind: 'added' }]);
|
|
52
|
+
});
|
|
53
|
+
it('is empty for empty/whitespace input and tolerates a trailing prefix slash', () => {
|
|
54
|
+
expect(parseLessonNameStatus('', LESSONS_PREFIX).entries).toEqual([]);
|
|
55
|
+
expect(parseLessonNameStatus('\n \n', LESSONS_PREFIX).entries).toEqual([]);
|
|
56
|
+
const delta = parseLessonNameStatus('A\t.totem/lessons/x.md', `${LESSONS_PREFIX}/`);
|
|
57
|
+
expect(delta.entries).toEqual([{ path: '.totem/lessons/x.md', kind: 'added' }]);
|
|
58
|
+
});
|
|
59
|
+
it('sorts entries by path for deterministic output', () => {
|
|
60
|
+
const raw = [
|
|
61
|
+
'A\t.totem/lessons/zeta.md',
|
|
62
|
+
'A\t.totem/lessons/alpha.md',
|
|
63
|
+
'A\t.totem/lessons/mid.md',
|
|
64
|
+
].join('\n');
|
|
65
|
+
const delta = parseLessonNameStatus(raw, LESSONS_PREFIX);
|
|
66
|
+
expect(delta.entries.map((e) => e.path)).toEqual([
|
|
67
|
+
'.totem/lessons/alpha.md',
|
|
68
|
+
'.totem/lessons/mid.md',
|
|
69
|
+
'.totem/lessons/zeta.md',
|
|
70
|
+
]);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
describe('classifyLessonsByMtime', () => {
|
|
74
|
+
const COMPILED_AT = 1_000;
|
|
75
|
+
it('names files whose mtime is strictly after the compile instant as changed', () => {
|
|
76
|
+
const delta = classifyLessonsByMtime([
|
|
77
|
+
{ path: 'newer.md', mtimeMs: 2_000 },
|
|
78
|
+
{ path: 'older.md', mtimeMs: 500 },
|
|
79
|
+
{ path: 'equal.md', mtimeMs: 1_000 }, // not strictly after — excluded
|
|
80
|
+
], COMPILED_AT);
|
|
81
|
+
expect(delta.entries).toEqual([{ path: 'newer.md', kind: 'changed' }]);
|
|
82
|
+
});
|
|
83
|
+
it('returns an empty delta when compiledAt is not finite (unparseable date)', () => {
|
|
84
|
+
const delta = classifyLessonsByMtime([{ path: 'a.md', mtimeMs: 9_999 }], Number.NaN);
|
|
85
|
+
expect(delta.entries).toEqual([]);
|
|
86
|
+
});
|
|
87
|
+
it('sorts the fallback entries by path', () => {
|
|
88
|
+
const delta = classifyLessonsByMtime([
|
|
89
|
+
{ path: 'b.md', mtimeMs: 5_000 },
|
|
90
|
+
{ path: 'a.md', mtimeMs: 5_000 },
|
|
91
|
+
], COMPILED_AT);
|
|
92
|
+
expect(delta.entries.map((e) => e.path)).toEqual(['a.md', 'b.md']);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
describe('formatStalenessWarning', () => {
|
|
96
|
+
const opts = (provenance) => ({
|
|
97
|
+
nameCap: STALE_LESSON_NAME_CAP,
|
|
98
|
+
displayNameFor: basename,
|
|
99
|
+
provenance,
|
|
100
|
+
});
|
|
101
|
+
it('falls back to the generic line (stable prefix + remediation) when nothing is named', () => {
|
|
102
|
+
const msg = formatStalenessWarning({ entries: [] }, opts(null));
|
|
103
|
+
expect(msg).toBe("Compile manifest is stale — lessons changed since last compile. Run 'totem lesson compile' to update.");
|
|
104
|
+
// The stable prefix stays intact for any consumer matching on it.
|
|
105
|
+
expect(msg.startsWith('Compile manifest is stale')).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
it('names lessons with their change kind and last-commit provenance', () => {
|
|
108
|
+
const delta = {
|
|
109
|
+
entries: [
|
|
110
|
+
{ path: '.totem/lessons/a.md', kind: 'added' },
|
|
111
|
+
{ path: '.totem/lessons/b.md', kind: 'changed' },
|
|
112
|
+
],
|
|
113
|
+
};
|
|
114
|
+
const provenance = new Map([
|
|
115
|
+
['.totem/lessons/a.md', { shortSha: 'abc1234', author: 'Ada Lovelace' }],
|
|
116
|
+
['.totem/lessons/b.md', { shortSha: 'def5678', author: 'Alan Turing' }],
|
|
117
|
+
]);
|
|
118
|
+
const msg = formatStalenessWarning(delta, opts(provenance));
|
|
119
|
+
expect(msg).toBe([
|
|
120
|
+
'Compile manifest is stale — 2 lesson(s) changed since last compile.',
|
|
121
|
+
' • a.md (added) — abc1234 by Ada Lovelace',
|
|
122
|
+
' • b.md (changed) — def5678 by Alan Turing',
|
|
123
|
+
"Run 'totem lesson compile' to update.",
|
|
124
|
+
].join('\n'));
|
|
125
|
+
});
|
|
126
|
+
it('marks a lesson with no commit history as (untracked) — the #2113 class', () => {
|
|
127
|
+
const delta = { entries: [{ path: '.totem/lessons/scratch.md', kind: 'added' }] };
|
|
128
|
+
const provenance = new Map([
|
|
129
|
+
['.totem/lessons/scratch.md', UNTRACKED_PROVENANCE],
|
|
130
|
+
]);
|
|
131
|
+
const msg = formatStalenessWarning(delta, opts(provenance));
|
|
132
|
+
expect(msg).toContain(' • scratch.md (added) (untracked)');
|
|
133
|
+
});
|
|
134
|
+
it('renders name-only (no provenance suffix) when provenance is null', () => {
|
|
135
|
+
const delta = { entries: [{ path: '.totem/lessons/a.md', kind: 'changed' }] };
|
|
136
|
+
const msg = formatStalenessWarning(delta, opts(null));
|
|
137
|
+
const namedLine = msg.split('\n').find((l) => l.startsWith(' • '));
|
|
138
|
+
// The named line carries the kind but NO ` — <sha> by <author>` provenance
|
|
139
|
+
// suffix (the header line legitimately keeps its em dash).
|
|
140
|
+
expect(namedLine).toBe(' • a.md (changed)');
|
|
141
|
+
expect(msg).not.toContain('(untracked)');
|
|
142
|
+
});
|
|
143
|
+
it('caps the named list and appends "…and K more"', () => {
|
|
144
|
+
const entries = Array.from({ length: STALE_LESSON_NAME_CAP + 3 }, (_, i) => ({
|
|
145
|
+
path: `.totem/lessons/lesson-${String(i).padStart(2, '0')}.md`,
|
|
146
|
+
kind: 'changed',
|
|
147
|
+
}));
|
|
148
|
+
const msg = formatStalenessWarning({ entries }, opts(null));
|
|
149
|
+
const lines = msg.split('\n');
|
|
150
|
+
// 1 header + nameCap named + 1 "…and K more" + 1 remediation.
|
|
151
|
+
expect(lines).toHaveLength(STALE_LESSON_NAME_CAP + 3);
|
|
152
|
+
expect(lines[0]).toBe(`Compile manifest is stale — ${STALE_LESSON_NAME_CAP + 3} lesson(s) changed since last compile.`);
|
|
153
|
+
const namedLines = lines.filter((l) => l.startsWith(' • '));
|
|
154
|
+
expect(namedLines).toHaveLength(STALE_LESSON_NAME_CAP);
|
|
155
|
+
expect(msg).toContain(` …and 3 more.`);
|
|
156
|
+
expect(lines[lines.length - 1]).toBe("Run 'totem lesson compile' to update.");
|
|
157
|
+
});
|
|
158
|
+
it('does not append the "more" tail when the count is exactly at the cap', () => {
|
|
159
|
+
const entries = Array.from({ length: STALE_LESSON_NAME_CAP }, (_, i) => ({
|
|
160
|
+
path: `.totem/lessons/lesson-${i}.md`,
|
|
161
|
+
kind: 'added',
|
|
162
|
+
}));
|
|
163
|
+
const msg = formatStalenessWarning({ entries }, opts(null));
|
|
164
|
+
expect(msg).not.toContain('more.');
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
describe('constants', () => {
|
|
168
|
+
it('exposes a positive name cap and a provenance file cap', () => {
|
|
169
|
+
expect(STALE_LESSON_NAME_CAP).toBeGreaterThan(0);
|
|
170
|
+
expect(PROVENANCE_LESSON_FILE_CAP).toBeGreaterThan(STALE_LESSON_NAME_CAP);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
//# sourceMappingURL=lint-staleness.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lint-staleness.test.js","sourceRoot":"","sources":["../../src/commands/lint-staleness.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/commands/lint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,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;AAGhD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA2EhD,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sFAAsF;IACtF,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,WAAW,CAAC;CAC5B;AAID,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA+OrE"}
|
package/dist/commands/lint.js
CHANGED
|
@@ -1,3 +1,72 @@
|
|
|
1
|
+
// ─── Staleness naming helpers (mmnto-ai/totem#2399) ─
|
|
2
|
+
/**
|
|
3
|
+
* Timeout for each git spawn in the non-blocking staleness delta. Bounded so a
|
|
4
|
+
* hung git can never stall the lint hot path — the whole check is advisory and
|
|
5
|
+
* degrades to name-only / the generic line on any git failure.
|
|
6
|
+
*/
|
|
7
|
+
const STALENESS_GIT_TIMEOUT_MS = 5_000;
|
|
8
|
+
/**
|
|
9
|
+
* Recursively count `.md` files under `lessonsDir` (readdir only, never reads
|
|
10
|
+
* file content) so the caller can gate provenance on corpus size. Returns 0
|
|
11
|
+
* when the directory is unreadable — a safe floor that does not force the skip.
|
|
12
|
+
*/
|
|
13
|
+
function countLessonMdFiles(fs, path, lessonsDir) {
|
|
14
|
+
let entries;
|
|
15
|
+
try {
|
|
16
|
+
entries = fs.readdirSync(lessonsDir, { withFileTypes: true });
|
|
17
|
+
// totem-context: best-effort — an unreadable lessons dir yields 0 (does not force provenance-skip); this advisory-only count must never crash lint (mmnto-ai/totem#2399)
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
|
22
|
+
let count = 0;
|
|
23
|
+
for (const entry of entries) {
|
|
24
|
+
if (entry.isDirectory()) {
|
|
25
|
+
count += countLessonMdFiles(fs, path, path.join(lessonsDir, entry.name));
|
|
26
|
+
}
|
|
27
|
+
else if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
28
|
+
count += 1;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return count;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Walk `.md` files under `lessonsDir` and return each one's mtime (ms), keyed by
|
|
35
|
+
* a lessons-dir-relative forward-slash path. Feeds the mtime fallback classifier
|
|
36
|
+
* when git has no anchor. Best-effort: an unreadable subtree contributes nothing
|
|
37
|
+
* rather than throwing.
|
|
38
|
+
*/
|
|
39
|
+
function walkLessonMtimes(fs, path, lessonsDir) {
|
|
40
|
+
const out = [];
|
|
41
|
+
const walk = (dir) => {
|
|
42
|
+
let entries;
|
|
43
|
+
try {
|
|
44
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
45
|
+
// totem-context: best-effort — an unreadable subtree is skipped so this advisory-only mtime walk never crashes lint (mmnto-ai/totem#2399)
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
for (const entry of entries) {
|
|
51
|
+
const full = path.join(dir, entry.name);
|
|
52
|
+
if (entry.isDirectory()) {
|
|
53
|
+
walk(full);
|
|
54
|
+
}
|
|
55
|
+
else if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
56
|
+
try {
|
|
57
|
+
const rel = path.relative(lessonsDir, full).replace(/\\/g, '/');
|
|
58
|
+
out.push({ path: rel, mtimeMs: fs.statSync(full).mtimeMs });
|
|
59
|
+
// totem-context: best-effort — an unstattable file is omitted so this advisory-only mtime walk never crashes lint (mmnto-ai/totem#2399)
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
walk(lessonsDir);
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
1
70
|
// ─── Command ────────────────────────────────────────
|
|
2
71
|
export async function lintCommand(options) {
|
|
3
72
|
const { TotemConfigError } = await import('@mmnto/totem');
|
|
@@ -22,18 +91,88 @@ export async function lintCommand(options) {
|
|
|
22
91
|
// harnesses running multiple commands in sequence do not throw.
|
|
23
92
|
const { bootstrapEngine } = await import('../utils/bootstrap-engine.js');
|
|
24
93
|
await bootstrapEngine(config, configRoot);
|
|
25
|
-
// Non-blocking staleness check — warn if compile manifest is stale
|
|
94
|
+
// Non-blocking staleness check — warn if compile manifest is stale, and NAME
|
|
95
|
+
// the delta (which lessons changed/added/removed since last compile, with
|
|
96
|
+
// last-commit provenance) so the advisory is actionable (mmnto-ai/totem#2399).
|
|
26
97
|
try {
|
|
27
98
|
const fs = await import('node:fs');
|
|
28
99
|
const manifestPath = path.join(cwd, config.totemDir, 'compile-manifest.json');
|
|
29
100
|
if (fs.existsSync(manifestPath)) {
|
|
30
|
-
const { readCompileManifest, generateInputHash } = await import('@mmnto/totem');
|
|
101
|
+
const { readCompileManifest, generateInputHash, safeExec, findRepoRootSync } = await import('@mmnto/totem');
|
|
31
102
|
const { log: uiLog } = await import('../ui.js');
|
|
103
|
+
const { STALE_LESSON_NAME_CAP, PROVENANCE_LESSON_FILE_CAP, UNTRACKED_PROVENANCE, parseLessonNameStatus, classifyLessonsByMtime, formatStalenessWarning, } = await import('./lint-staleness.js');
|
|
32
104
|
const manifest = readCompileManifest(manifestPath);
|
|
33
105
|
const lessonsDir = path.join(cwd, config.totemDir, 'lessons');
|
|
34
106
|
const currentInputHash = generateInputHash(lessonsDir, cwd);
|
|
35
107
|
if (currentInputHash !== manifest.input_hash) {
|
|
36
|
-
|
|
108
|
+
// Bounded best-effort: any git failure inside these helpers degrades to
|
|
109
|
+
// the mtime fallback (or the generic line) rather than killing the warn.
|
|
110
|
+
// The whole block stays inside the outer never-crash try/catch below.
|
|
111
|
+
const toPosix = (p) => p.replace(/\\/g, '/');
|
|
112
|
+
const repoRoot = findRepoRootSync(cwd);
|
|
113
|
+
// Primary: classify from a `--name-status` diff against the commit that
|
|
114
|
+
// last wrote the manifest — the lesson drift since that anchor is exactly
|
|
115
|
+
// what makes the aggregate input hash disagree.
|
|
116
|
+
let delta = null;
|
|
117
|
+
let deltaFromGit = false;
|
|
118
|
+
if (repoRoot) {
|
|
119
|
+
const lessonsPrefix = toPosix(path.relative(repoRoot, lessonsDir));
|
|
120
|
+
try {
|
|
121
|
+
const anchor = safeExec('git', ['log', '-1', '--format=%H', '--', toPosix(path.relative(repoRoot, manifestPath))], { cwd: repoRoot, timeout: STALENESS_GIT_TIMEOUT_MS });
|
|
122
|
+
if (anchor.length > 0 && lessonsPrefix.length > 0) {
|
|
123
|
+
const nameStatus = safeExec('git', ['diff', '--name-status', anchor, '--', lessonsPrefix], { cwd: repoRoot, timeout: STALENESS_GIT_TIMEOUT_MS });
|
|
124
|
+
delta = parseLessonNameStatus(nameStatus, lessonsPrefix);
|
|
125
|
+
deltaFromGit = true;
|
|
126
|
+
}
|
|
127
|
+
// totem-context: best-effort — git unavailable/errored degrades to the mtime fallback below; this advisory-only naming must never crash lint (mmnto-ai/totem#2399)
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
delta = null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Fallback: name lessons whose mtime is after the manifest's compile
|
|
134
|
+
// instant (no git anchor available). Every hit is reported as 'changed'.
|
|
135
|
+
if (!deltaFromGit) {
|
|
136
|
+
const compiledAtMs = Date.parse(manifest.compiled_at);
|
|
137
|
+
delta = classifyLessonsByMtime(walkLessonMtimes(fs, path, lessonsDir), compiledAtMs);
|
|
138
|
+
}
|
|
139
|
+
const namedDelta = delta ?? { entries: [] };
|
|
140
|
+
// Provenance only for the git-derived delta (its paths are repo-relative,
|
|
141
|
+
// so a per-file `log -1` lookup resolves against repoRoot). Skipped
|
|
142
|
+
// entirely on a very large lesson corpus (PROVENANCE_LESSON_FILE_CAP) so
|
|
143
|
+
// the naming logic never paces the lint hot path.
|
|
144
|
+
let provenance = null;
|
|
145
|
+
if (deltaFromGit && repoRoot && namedDelta.entries.length > 0) {
|
|
146
|
+
if (countLessonMdFiles(fs, path, lessonsDir) <= PROVENANCE_LESSON_FILE_CAP) {
|
|
147
|
+
provenance = new Map();
|
|
148
|
+
for (const entry of namedDelta.entries.slice(0, STALE_LESSON_NAME_CAP)) {
|
|
149
|
+
try {
|
|
150
|
+
const out = safeExec('git', ['log', '-1', '--format=%h|%an', '--', entry.path], {
|
|
151
|
+
cwd: repoRoot,
|
|
152
|
+
timeout: STALENESS_GIT_TIMEOUT_MS,
|
|
153
|
+
});
|
|
154
|
+
if (out.length === 0) {
|
|
155
|
+
// No commit history — staged-but-uncommitted / untracked (mmnto-ai/totem#2113).
|
|
156
|
+
provenance.set(entry.path, UNTRACKED_PROVENANCE);
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const sep = out.indexOf('|');
|
|
160
|
+
const shortSha = sep === -1 ? out : out.slice(0, sep);
|
|
161
|
+
const author = sep === -1 ? '' : out.slice(sep + 1);
|
|
162
|
+
provenance.set(entry.path, { shortSha, author });
|
|
163
|
+
// totem-context: best-effort — a per-file provenance lookup that errors leaves the entry unset (renders name-only); this advisory must never crash lint (mmnto-ai/totem#2399)
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
provenance.delete(entry.path);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
uiLog.warn(TAG, formatStalenessWarning(namedDelta, {
|
|
172
|
+
nameCap: STALE_LESSON_NAME_CAP,
|
|
173
|
+
displayNameFor: (p) => path.basename(p),
|
|
174
|
+
provenance,
|
|
175
|
+
}));
|
|
37
176
|
}
|
|
38
177
|
}
|
|
39
178
|
}
|
|
@@ -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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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools-hook-parity.test.d.ts","sourceRoot":"","sources":["../../src/commands/tools-hook-parity.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
5
|
+
import { buildHookContent, buildPreCommitHook, buildPrePushHook, getFallbackCommand, } from './install-hooks.js';
|
|
6
|
+
// Bind the repo-local `tools/{pre-commit,pre-push,post-merge}` hook scripts — which
|
|
7
|
+
// `package.json`'s `prepare` (`node tools/install-hooks.js`) copies into `.git/hooks`
|
|
8
|
+
// on every install — to the CLI template builders that `totem hook install --force`
|
|
9
|
+
// uses. If a template changes without regenerating tools/, the copied scripts silently
|
|
10
|
+
// re-drift from the CLI-canonical hooks and stomp them on the next `pnpm install`
|
|
11
|
+
// (mmnto-ai/totem#2404). A failure here means tools/ must be regenerated in lockstep
|
|
12
|
+
// (byte-for-byte) with the builders before merging the template change.
|
|
13
|
+
const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../..');
|
|
14
|
+
const TOOLS_DIR = path.join(REPO_ROOT, 'tools');
|
|
15
|
+
// This repo pins no `hooks.tier` in totem.config.ts, so the installer's effective tier
|
|
16
|
+
// is the default 'standard'. The fallback command derives from the repo's lockfile
|
|
17
|
+
// exactly as the installer and doctor do (getFallbackCommand).
|
|
18
|
+
const TIER = 'standard';
|
|
19
|
+
const FALLBACK_CMD = getFallbackCommand(REPO_ROOT);
|
|
20
|
+
function readTool(hook) {
|
|
21
|
+
return fs.readFileSync(path.join(TOOLS_DIR, hook), 'utf-8');
|
|
22
|
+
}
|
|
23
|
+
describe('tools/ hook scripts match the CLI template builders (mmnto-ai/totem#2404)', () => {
|
|
24
|
+
it('resolves the pnpm-based fallback command for this repo', () => {
|
|
25
|
+
expect(FALLBACK_CMD).toBe('pnpm dlx @mmnto/cli');
|
|
26
|
+
});
|
|
27
|
+
it('tools/pre-commit is byte-identical to buildPreCommitHook output', () => {
|
|
28
|
+
expect(readTool('pre-commit')).toBe(buildPreCommitHook(TIER));
|
|
29
|
+
});
|
|
30
|
+
it('tools/pre-push is byte-identical to buildPrePushHook output', () => {
|
|
31
|
+
expect(readTool('pre-push')).toBe(buildPrePushHook(FALLBACK_CMD, TIER));
|
|
32
|
+
});
|
|
33
|
+
it('tools/post-merge is byte-identical to buildHookContent output', () => {
|
|
34
|
+
expect(readTool('post-merge')).toBe(buildHookContent(FALLBACK_CMD));
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=tools-hook-parity.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools-hook-parity.test.js","sourceRoot":"","sources":["../../src/commands/tools-hook-parity.test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAE5B,oFAAoF;AACpF,sFAAsF;AACtF,oFAAoF;AACpF,uFAAuF;AACvF,kFAAkF;AAClF,qFAAqF;AACrF,wEAAwE;AAExE,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;AAC5F,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAEhD,uFAAuF;AACvF,mFAAmF;AACnF,+DAA+D;AAC/D,MAAM,IAAI,GAAG,UAAmB,CAAC;AACjC,MAAM,YAAY,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;AAEnD,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;AAC9D,CAAC;AAED,QAAQ,CAAC,2EAA2E,EAAE,GAAG,EAAE;IACzF,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../../src/commands/wrap.ts"],"names":[],"mappings":"AAEA,QAAA,MAAM,GAAG,SAAS,CAAC;AAInB,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../../src/commands/wrap.ts"],"names":[],"mappings":"AAEA,QAAA,MAAM,GAAG,SAAS,CAAC;AAInB,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA0B5F;AAID,OAAO,EAAE,GAAG,EAAE,CAAC"}
|
package/dist/commands/wrap.js
CHANGED
|
@@ -41,11 +41,12 @@ export async function wrapCommand(_prNumbers, _options) {
|
|
|
41
41
|
' pnpm exec totem lesson extract <pr-numbers> --yes',
|
|
42
42
|
' pnpm exec totem sync',
|
|
43
43
|
' pnpm exec totem lesson compile --export',
|
|
44
|
-
'
|
|
44
|
+
' (review new rules; archive bad ones: pnpm exec totem lesson archive <hash> --reason "...")',
|
|
45
45
|
' pnpm run format',
|
|
46
|
-
' git add .totem/lessons/ .github/copilot-instructions.md .junie/skills/totem-rules/rules.md',
|
|
46
|
+
' git add .totem/lessons/ .totem/compiled-rules.json .totem/compile-manifest.json .github/copilot-instructions.md .junie/skills/totem-rules/rules.md',
|
|
47
47
|
" git commit -m 'chore: totem postmerge lessons for <prs>'",
|
|
48
48
|
'',
|
|
49
|
+
'Full sequence: .claude/skills/postmerge/SKILL.md',
|
|
49
50
|
'Tracking: mmnto-ai/totem#1361',
|
|
50
51
|
].join('\n'));
|
|
51
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap.js","sourceRoot":"","sources":["../../src/commands/wrap.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAE3D,MAAM,GAAG,GAAG,MAAM,CAAC;AAUnB,2DAA2D;AAE3D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAAoB,EAAE,QAAqB;IAC3E,oEAAoE;IACpE,sEAAsE;IACtE,sEAAsE;IACtE,iEAAiE;IACjE,kCAAkC;IAClC,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;IAEpD,MAAM,IAAI,UAAU,CAClB,gBAAgB,EAChB,0FAA0F,EAC1F;QACE,oCAAoC;QACpC,EAAE;QACF,qDAAqD;QACrD,wBAAwB;QACxB,2CAA2C;QAC3C,
|
|
1
|
+
{"version":3,"file":"wrap.js","sourceRoot":"","sources":["../../src/commands/wrap.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAE3D,MAAM,GAAG,GAAG,MAAM,CAAC;AAUnB,2DAA2D;AAE3D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAAoB,EAAE,QAAqB;IAC3E,oEAAoE;IACpE,sEAAsE;IACtE,sEAAsE;IACtE,iEAAiE;IACjE,kCAAkC;IAClC,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;IAEpD,MAAM,IAAI,UAAU,CAClB,gBAAgB,EAChB,0FAA0F,EAC1F;QACE,oCAAoC;QACpC,EAAE;QACF,qDAAqD;QACrD,wBAAwB;QACxB,2CAA2C;QAC3C,8FAA8F;QAC9F,mBAAmB;QACnB,sJAAsJ;QACtJ,4DAA4D;QAC5D,EAAE;QACF,kDAAkD;QAClD,+BAA+B;KAChC,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;AACJ,CAAC;AAED,6EAA6E;AAC7E,8DAA8D;AAC9D,OAAO,EAAE,GAAG,EAAE,CAAC"}
|
|
@@ -54,7 +54,17 @@ describe('wrapCommand (retired)', () => {
|
|
|
54
54
|
expect(hint).toContain('totem lesson extract');
|
|
55
55
|
expect(hint).toContain('totem sync');
|
|
56
56
|
expect(hint).toContain('totem lesson compile --export');
|
|
57
|
-
|
|
57
|
+
// Curation goes through the atomic archive, not a rules-file revert:
|
|
58
|
+
// `git checkout HEAD -- .totem/compiled-rules.json` desyncs the
|
|
59
|
+
// compile-manifest input/output hashes (postmerge SKILL forbids it).
|
|
60
|
+
expect(hint).toContain('totem lesson archive');
|
|
61
|
+
expect(hint).not.toContain('git checkout HEAD -- .totem/compiled-rules.json');
|
|
62
|
+
// The rules + manifest artifacts must be staged so the revert is
|
|
63
|
+
// unnecessary in the first place.
|
|
64
|
+
expect(hint).toContain('.totem/compiled-rules.json');
|
|
65
|
+
expect(hint).toContain('.totem/compile-manifest.json');
|
|
66
|
+
// Points at the canonical long-form sequence.
|
|
67
|
+
expect(hint).toContain('.claude/skills/postmerge/SKILL.md');
|
|
58
68
|
}
|
|
59
69
|
});
|
|
60
70
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap.test.js","sourceRoot":"","sources":["../../src/commands/wrap.test.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"wrap.test.js","sourceRoot":"","sources":["../../src/commands/wrap.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mmnto/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.100.0",
|
|
4
4
|
"description": "Totem: local-first toolkit that keeps AI-agent work queryable, enforceable, and derivable as plain files in your codebase",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"smol-toml": "^1.6.1",
|
|
29
29
|
"yaml": "^2.4.0",
|
|
30
30
|
"zod": "^3.24.0",
|
|
31
|
-
"@mmnto/totem": "1.
|
|
31
|
+
"@mmnto/totem": "1.100.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@anthropic-ai/sdk": "^0.98.0",
|