@mmnto/cli 1.99.0 → 1.101.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/commands/config-drift.test.js +5 -2
  2. package/dist/commands/config-drift.test.js.map +1 -1
  3. package/dist/commands/doctor-parity.d.ts.map +1 -1
  4. package/dist/commands/doctor-parity.js +57 -2
  5. package/dist/commands/doctor-parity.js.map +1 -1
  6. package/dist/commands/doctor-parity.test.js +60 -0
  7. package/dist/commands/doctor-parity.test.js.map +1 -1
  8. package/dist/commands/doctor.d.ts +19 -0
  9. package/dist/commands/doctor.d.ts.map +1 -1
  10. package/dist/commands/doctor.js +132 -0
  11. package/dist/commands/doctor.js.map +1 -1
  12. package/dist/commands/doctor.test.js +1 -0
  13. package/dist/commands/doctor.test.js.map +1 -1
  14. package/dist/commands/gate-install.d.ts.map +1 -1
  15. package/dist/commands/gate-install.js +12 -3
  16. package/dist/commands/gate-install.js.map +1 -1
  17. package/dist/commands/gate-install.test.js +13 -1
  18. package/dist/commands/gate-install.test.js.map +1 -1
  19. package/dist/commands/init-templates.d.ts +59 -7
  20. package/dist/commands/init-templates.d.ts.map +1 -1
  21. package/dist/commands/init-templates.js +223 -2
  22. package/dist/commands/init-templates.js.map +1 -1
  23. package/dist/commands/init.d.ts +38 -4
  24. package/dist/commands/init.d.ts.map +1 -1
  25. package/dist/commands/init.js +196 -13
  26. package/dist/commands/init.js.map +1 -1
  27. package/dist/commands/init.test.js +13 -0
  28. package/dist/commands/init.test.js.map +1 -1
  29. package/dist/commands/install-hooks-exit-contract.test.d.ts +2 -0
  30. package/dist/commands/install-hooks-exit-contract.test.d.ts.map +1 -0
  31. package/dist/commands/install-hooks-exit-contract.test.js +339 -0
  32. package/dist/commands/install-hooks-exit-contract.test.js.map +1 -0
  33. package/dist/commands/install-hooks.d.ts +53 -1
  34. package/dist/commands/install-hooks.d.ts.map +1 -1
  35. package/dist/commands/install-hooks.js +239 -52
  36. package/dist/commands/install-hooks.js.map +1 -1
  37. package/dist/commands/install-hooks.test.js +105 -39
  38. package/dist/commands/install-hooks.test.js.map +1 -1
  39. package/dist/commands/lint-staleness.d.ts +122 -0
  40. package/dist/commands/lint-staleness.d.ts.map +1 -0
  41. package/dist/commands/lint-staleness.js +163 -0
  42. package/dist/commands/lint-staleness.js.map +1 -0
  43. package/dist/commands/lint-staleness.test.d.ts +2 -0
  44. package/dist/commands/lint-staleness.test.d.ts.map +1 -0
  45. package/dist/commands/lint-staleness.test.js +173 -0
  46. package/dist/commands/lint-staleness.test.js.map +1 -0
  47. package/dist/commands/lint.d.ts.map +1 -1
  48. package/dist/commands/lint.js +142 -3
  49. package/dist/commands/lint.js.map +1 -1
  50. package/dist/commands/prepare-wrapper.test.d.ts +2 -0
  51. package/dist/commands/prepare-wrapper.test.d.ts.map +1 -0
  52. package/dist/commands/prepare-wrapper.test.js +284 -0
  53. package/dist/commands/prepare-wrapper.test.js.map +1 -0
  54. package/dist/commands/tools-hook-parity.test.d.ts +2 -0
  55. package/dist/commands/tools-hook-parity.test.d.ts.map +1 -0
  56. package/dist/commands/tools-hook-parity.test.js +37 -0
  57. package/dist/commands/tools-hook-parity.test.js.map +1 -0
  58. package/dist/commands/wrap.d.ts.map +1 -1
  59. package/dist/commands/wrap.js +3 -2
  60. package/dist/commands/wrap.js.map +1 -1
  61. package/dist/commands/wrap.test.js +11 -1
  62. package/dist/commands/wrap.test.js.map +1 -1
  63. package/package.json +2 -2
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Compile-manifest staleness delta naming (mmnto-ai/totem#2399).
3
+ *
4
+ * The staleness check in `lint.ts` compares one AGGREGATE `input_hash` against
5
+ * the manifest and, on mismatch, warned with a fixed string that named nothing.
6
+ * This module turns that boolean "stale" verdict into a NAMED delta: which
7
+ * lesson files changed / were added / were removed since the last compile, so
8
+ * the consumer can tell whether the drift is theirs, rode in on a merge, or is
9
+ * the mmnto-ai/totem#2113 untracked-at-compile class.
10
+ *
11
+ * Every export here is PURE (no `node:fs`, no `child_process`): the classify
12
+ * and format logic is unit-tested without a real git repo or temp dir (the
13
+ * cohort's standing "no real `git` with cwd=temp on Windows" rule — it leaves
14
+ * undeletable temp dirs). `lint.ts` owns the impure gathering (the `git`
15
+ * name-status diff + `git log` provenance via the shared `safeExec` helper, and
16
+ * the `fs` mtime walk) and feeds the results to these helpers.
17
+ */
18
+ // ─── Constants ──────────────────────────────────────
19
+ /**
20
+ * Max lesson names printed in the warning before collapsing the tail to
21
+ * "…and K more". Keeps the advisory to a glanceable block and caps the number
22
+ * of per-file `git log` provenance spawns at exactly this many.
23
+ */
24
+ export const STALE_LESSON_NAME_CAP = 5;
25
+ /**
26
+ * Above this many lesson files, skip per-file provenance (name-only mode).
27
+ * Provenance is already bounded to at most {@link STALE_LESSON_NAME_CAP} `git
28
+ * log` calls, but the whole staleness check is a non-blocking advisory on the
29
+ * lint hot path: on a very large lesson corpus we decline to spawn git per
30
+ * named file at all rather than let the naming logic pace the run.
31
+ */
32
+ export const PROVENANCE_LESSON_FILE_CAP = 500;
33
+ /**
34
+ * Sentinel provenance for a lesson with no commit history — staged-but-never-
35
+ * committed / untracked. This is the mmnto-ai/totem#2113 class and is worth
36
+ * distinguishing from a real commit in the warning.
37
+ */
38
+ export const UNTRACKED_PROVENANCE = 'untracked';
39
+ // ─── Sort ────────────────────────────────────────────
40
+ function sortEntries(entries) {
41
+ return [...entries].sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
42
+ }
43
+ // ─── Git name-status classifier (primary) ───────────
44
+ /**
45
+ * Parse `git diff --name-status <anchor>` output into a classified lesson delta,
46
+ * keeping only `.md` files under `lessonsPrefix` (a repo-relative, forward-slash
47
+ * directory prefix such as `.totem/lessons`).
48
+ *
49
+ * Status letters map: `A`/`C` → added, `D` → removed, `M`/`T` → changed. A
50
+ * rename (`R`) reports its DESTINATION path as `changed` (a lesson whose path
51
+ * moved shifts the input hash because `generateInputHash` folds the relative
52
+ * path into the digest). Rename/copy lines carry `OLD<TAB>NEW`, so the current
53
+ * path is the third tab field; A/M/D carry `STATUS<TAB>PATH`. Unknown status
54
+ * letters (`U` unmerged, etc.) are ignored — best-effort naming, never a throw.
55
+ */
56
+ export function parseLessonNameStatus(raw, lessonsPrefix) {
57
+ const prefix = lessonsPrefix.endsWith('/') ? lessonsPrefix : `${lessonsPrefix}/`;
58
+ const entries = [];
59
+ for (const rawLine of raw.split('\n')) {
60
+ const line = rawLine.trim();
61
+ if (line.length === 0)
62
+ continue;
63
+ const fields = line.split('\t');
64
+ const status = fields[0]?.[0];
65
+ if (!status)
66
+ continue;
67
+ // Rename/copy carry `OLD<TAB>NEW`; the destination is the current path.
68
+ const isRenameOrCopy = status === 'R' || status === 'C';
69
+ const rawTarget = isRenameOrCopy ? fields[2] : fields[1];
70
+ if (!rawTarget)
71
+ continue;
72
+ const target = rawTarget.replace(/\\/g, '/');
73
+ if (!target.startsWith(prefix) || !target.endsWith('.md'))
74
+ continue;
75
+ let kind;
76
+ switch (status) {
77
+ case 'A':
78
+ case 'C':
79
+ kind = 'added';
80
+ break;
81
+ case 'D':
82
+ kind = 'removed';
83
+ break;
84
+ case 'M':
85
+ case 'T':
86
+ case 'R':
87
+ kind = 'changed';
88
+ break;
89
+ default:
90
+ continue; // Unknown status (unmerged, etc.) — ignore, don't guess.
91
+ }
92
+ entries.push({ path: target, kind });
93
+ }
94
+ return { entries: sortEntries(entries) };
95
+ }
96
+ /**
97
+ * Fallback classifier for when git is unavailable (no repo, or the manifest was
98
+ * never committed so there is no anchor): a lesson file whose mtime is strictly
99
+ * after the manifest's compile instant is reported as `changed`.
100
+ *
101
+ * mtime alone cannot recover added-vs-removed-vs-edited (a removed file has no
102
+ * mtime to observe; a freshly-written file is indistinguishable from an edit),
103
+ * so every hit is `changed` — the honest floor when there is no git baseline.
104
+ * A non-finite `compiledAtMs` (unparseable `compiled_at`) yields an empty delta
105
+ * rather than naming every file.
106
+ */
107
+ export function classifyLessonsByMtime(files, compiledAtMs) {
108
+ if (!Number.isFinite(compiledAtMs))
109
+ return { entries: [] };
110
+ const entries = [];
111
+ for (const file of files) {
112
+ if (file.mtimeMs > compiledAtMs)
113
+ entries.push({ path: file.path, kind: 'changed' });
114
+ }
115
+ return { entries: sortEntries(entries) };
116
+ }
117
+ // ─── Warning formatter ───────────────────────────────
118
+ const REMEDIATION = "Run 'totem lesson compile' to update.";
119
+ /**
120
+ * Build the single warn-block body for a stale manifest. One block, ready to
121
+ * hand to `uiLog.warn(TAG, …)`.
122
+ *
123
+ * - `total === 0` (nothing could be named — git unavailable and no mtime hit,
124
+ * or an anchor miss): fall back to the generic advisory. The stable
125
+ * `Compile manifest is stale` prefix is preserved so any consumer matching on
126
+ * it keeps working, and we never assert "0 lesson(s) changed".
127
+ * - otherwise: a counted first line, up to `nameCap` named lessons with their
128
+ * change kind and (when derivable) `— <sha> by <author>` provenance or
129
+ * `(untracked)`, then "…and K more" when over the cap, then the remediation.
130
+ *
131
+ * The remediation intentionally points public consumers at `totem lesson
132
+ * compile`; the cohort-side compile freeze is overlay-governed, not this
133
+ * string's concern.
134
+ */
135
+ export function formatStalenessWarning(delta, opts) {
136
+ const total = delta.entries.length;
137
+ if (total === 0) {
138
+ return `Compile manifest is stale — lessons changed since last compile. ${REMEDIATION}`;
139
+ }
140
+ const lines = [
141
+ `Compile manifest is stale — ${total} lesson(s) changed since last compile.`,
142
+ ];
143
+ for (const entry of delta.entries.slice(0, opts.nameCap)) {
144
+ const name = opts.displayNameFor(entry.path);
145
+ let suffix = '';
146
+ if (opts.provenance) {
147
+ const prov = opts.provenance.get(entry.path);
148
+ if (prov === UNTRACKED_PROVENANCE) {
149
+ suffix = ' (untracked)';
150
+ }
151
+ else if (prov) {
152
+ suffix = ` — ${prov.shortSha} by ${prov.author}`;
153
+ }
154
+ }
155
+ lines.push(` • ${name} (${entry.kind})${suffix}`);
156
+ }
157
+ if (total > opts.nameCap) {
158
+ lines.push(` …and ${total - opts.nameCap} more.`);
159
+ }
160
+ lines.push(REMEDIATION);
161
+ return lines.join('\n');
162
+ }
163
+ //# sourceMappingURL=lint-staleness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint-staleness.js","sourceRoot":"","sources":["../../src/commands/lint-staleness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=lint-staleness.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint-staleness.test.d.ts","sourceRoot":"","sources":["../../src/commands/lint-staleness.test.ts"],"names":[],"mappings":""}
@@ -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;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;;;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,CAqJrE"}
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"}
@@ -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
- uiLog.warn(TAG, "Compile manifest is stale lessons changed since last compile. Run 'totem lesson compile' to update.");
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":"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"}
1
+ {"version":3,"file":"lint.js","sourceRoot":"","sources":["../../src/commands/lint.ts"],"names":[],"mappings":"AAKA,uDAAuD;AAEvD;;;;GAIG;AACH,MAAM,wBAAwB,GAAG,KAAK,CAAC;AAKvC;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,EAAY,EAAE,IAAgB,EAAE,UAAkB;IAC5E,IAAI,OAAmC,CAAC;IACxC,IAAI,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,yKAAyK;IAC3K,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,KAAK,IAAI,kBAAkB,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3E,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACxD,KAAK,IAAI,CAAC,CAAC;QACb,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,SAAS,gBAAgB,CAAC,EAAY,EAAE,IAAgB,EAAE,UAAkB;IAC1E,MAAM,GAAG,GAAqB,EAAE,CAAC;IACjC,MAAM,IAAI,GAAG,CAAC,GAAW,EAAQ,EAAE;QACjC,IAAI,OAAmC,CAAC;QACxC,IAAI,CAAC;YACH,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YACvD,0IAA0I;QAC5I,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACxC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,IAAI,CAAC,IAAI,CAAC,CAAC;YACb,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxD,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;oBAChE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;oBAC5D,wIAAwI;gBAC1I,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS;gBACX,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,UAAU,CAAC,CAAC;IACjB,OAAO,GAAG,CAAC;AACb,CAAC;AAsCD,uDAAuD;AAEvD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAoB;IACpD,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;IAC1D,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;IAC/E,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;IACvD,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;IAErE,MAAM,GAAG,GAAG,MAAM,CAAC;IACnB,MAAM,MAAM,GAAiB,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC;IACtD,MAAM,aAAa,GAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAChE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,gBAAgB,CACxB,qBAAqB,MAAM,oCAAoC,EAC/D,8CAA8C,EAC9C,gBAAgB,CACjB,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;IACvC,MAAM,UAAU,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,CAAC;IACb,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC;IAE5C,2EAA2E;IAC3E,wEAAwE;IACxE,wEAAwE;IACxE,gEAAgE;IAChE,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,8BAA8B,CAAC,CAAC;IACzE,MAAM,eAAe,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAE1C,6EAA6E;IAC7E,0EAA0E;IAC1E,+EAA+E;IAC/E,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;QACnC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,EAAE,uBAAuB,CAAC,CAAC;QAC9E,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAChC,MAAM,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,QAAQ,EAAE,gBAAgB,EAAE,GAC1E,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;YAC/B,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;YAChD,MAAM,EACJ,qBAAqB,EACrB,0BAA0B,EAC1B,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,GACvB,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;YAExC,MAAM,QAAQ,GAAG,mBAAmB,CAAC,YAAY,CAAC,CAAC;YACnD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;YAC9D,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;YAC5D,IAAI,gBAAgB,KAAK,QAAQ,CAAC,UAAU,EAAE,CAAC;gBAC7C,wEAAwE;gBACxE,yEAAyE;gBACzE,sEAAsE;gBACtE,MAAM,OAAO,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBAC7D,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;gBAEvC,wEAAwE;gBACxE,0EAA0E;gBAC1E,gDAAgD;gBAChD,IAAI,KAAK,GAAuB,IAAI,CAAC;gBACrC,IAAI,YAAY,GAAG,KAAK,CAAC;gBACzB,IAAI,QAAQ,EAAE,CAAC;oBACb,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;oBACnE,IAAI,CAAC;wBACH,MAAM,MAAM,GAAG,QAAQ,CACrB,KAAK,EACL,CAAC,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EAClF,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,wBAAwB,EAAE,CACrD,CAAC;wBACF,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;4BAClD,MAAM,UAAU,GAAG,QAAQ,CACzB,KAAK,EACL,CAAC,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,CAAC,EACtD,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,wBAAwB,EAAE,CACrD,CAAC;4BACF,KAAK,GAAG,qBAAqB,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;4BACzD,YAAY,GAAG,IAAI,CAAC;wBACtB,CAAC;wBACD,mKAAmK;oBACrK,CAAC;oBAAC,MAAM,CAAC;wBACP,KAAK,GAAG,IAAI,CAAC;oBACf,CAAC;gBACH,CAAC;gBAED,qEAAqE;gBACrE,yEAAyE;gBACzE,IAAI,CAAC,YAAY,EAAE,CAAC;oBAClB,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;oBACtD,KAAK,GAAG,sBAAsB,CAAC,gBAAgB,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;gBACvF,CAAC;gBAED,MAAM,UAAU,GAAG,KAAK,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;gBAE5C,0EAA0E;gBAC1E,oEAAoE;gBACpE,yEAAyE;gBACzE,kDAAkD;gBAClD,IAAI,UAAU,GAAwC,IAAI,CAAC;gBAC3D,IAAI,YAAY,IAAI,QAAQ,IAAI,UAAU,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC9D,IAAI,kBAAkB,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,0BAA0B,EAAE,CAAC;wBAC3E,UAAU,GAAG,IAAI,GAAG,EAA2B,CAAC;wBAChD,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,qBAAqB,CAAC,EAAE,CAAC;4BACvE,IAAI,CAAC;gCACH,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE;oCAC9E,GAAG,EAAE,QAAQ;oCACb,OAAO,EAAE,wBAAwB;iCAClC,CAAC,CAAC;gCACH,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oCACrB,gFAAgF;oCAChF,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;oCACjD,SAAS;gCACX,CAAC;gCACD,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gCAC7B,MAAM,QAAQ,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;gCACtD,MAAM,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;gCACpD,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;gCACjD,8KAA8K;4BAChL,CAAC;4BAAC,MAAM,CAAC;gCACP,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;4BAChC,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;gBAED,KAAK,CAAC,IAAI,CACR,GAAG,EACH,sBAAsB,CAAC,UAAU,EAAE;oBACjC,OAAO,EAAE,qBAAqB;oBAC9B,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;oBACvC,UAAU;iBACX,CAAC,CACH,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,mEAAmE;IACrE,CAAC;IAED,yEAAyE;IACzE,0EAA0E;IAC1E,2EAA2E;IAC3E,+DAA+D;IAC/D,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,gCAAgC,CAAC,CAAC;IAC/E,MAAM,mBAAmB,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IAEjE,uEAAuE;IACvE,yEAAyE;IACzE,6BAA6B;IAC7B,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,EAAE,GAAG,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC/F,IAAI,CAAC,MAAM;QAAE,OAAO;IAEpB,MAAM,SAAS,GAAG,CAAC,GAAG,MAAM,CAAC,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC,CAAC;IACrF,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE/E,MAAM,WAAW,GAAgB,OAAO,CAAC,WAAW,IAAI,QAAQ,CAAC;IACjE,2EAA2E;IAC3E,mEAAmE;IACnE,2EAA2E;IAC3E,MAAM,YAAY,GAChB,OAAO,CAAC,YAAY;QACpB,+IAA+I;QAC/I,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAElF,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,MAAM,gBAAgB,CAAC;QAClE,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,GAAG;QACH,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,MAAM;QACN,OAAO,EAAE,OAAO,CAAC,GAAG;QACpB,WAAW;QACX,cAAc,EAAE,SAAS;QACzB,GAAG,EAAE,GAAG;QACR,UAAU;QACV,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM;QAC1B,gBAAgB,EAAE,WAAW;QAC7B,YAAY;KACb,CAAC,CAAC;IAEH,yEAAyE;IACzE,2EAA2E;IAC3E,oEAAoE;IACpE,oEAAoE;IACpE,IAAI,WAAW,KAAK,QAAQ,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzD,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,aAAa;aAC1B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,QAAQ,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,SAAS,KAAK,CAAC;aAC3D,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,IAAI,UAAU,CAClB,cAAc,EACd,iCAAiC,aAAa,CAAC,MAAM,uBAAuB,OAAO,EAAE,EACrF,iJAAiJ,CAClJ,CAAC;IACJ,CAAC;IAED,2EAA2E;IAC3E,yEAAyE;IACzE,yEAAyE;IACzE,0EAA0E;IAC1E,mEAAmE;IAEnE,wFAAwF;IACxF,IAAI,OAAO,CAAC,SAAS,IAAI,IAAI;QAAE,OAAO;IAEtC,sFAAsF;IACtF,MAAM,QAAQ,GACZ,OAAO,CAAC,SAAS,KAAK,IAAI;QACxB,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,SAAS;QAC1F,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IAExB,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;QACzC,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;QACpD,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAE3D,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC;QAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QAE1C,IAAI,CAAC;YACH,MAAM,aAAa,CAAC;gBAClB,UAAU;gBACV,KAAK;gBACL,QAAQ;gBACR,SAAS;gBACT,UAAU;gBACV,GAAG;aACJ,CAAC,CAAC;YACH,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,0BAA0B,QAAQ,EAAE,CAAC,CAAC;QACzD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,IAAI,CACN,GAAG,EACH,gCAAgC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACnF,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=prepare-wrapper.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepare-wrapper.test.d.ts","sourceRoot":"","sources":["../../src/commands/prepare-wrapper.test.ts"],"names":[],"mappings":""}