@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.
- 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/doctor.d.ts +19 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +132 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/doctor.test.js +1 -0
- package/dist/commands/doctor.test.js.map +1 -1
- package/dist/commands/gate-install.d.ts.map +1 -1
- package/dist/commands/gate-install.js +12 -3
- package/dist/commands/gate-install.js.map +1 -1
- package/dist/commands/gate-install.test.js +13 -1
- package/dist/commands/gate-install.test.js.map +1 -1
- package/dist/commands/init-templates.d.ts +59 -7
- package/dist/commands/init-templates.d.ts.map +1 -1
- package/dist/commands/init-templates.js +223 -2
- package/dist/commands/init-templates.js.map +1 -1
- package/dist/commands/init.d.ts +38 -4
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +196 -13
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/init.test.js +13 -0
- package/dist/commands/init.test.js.map +1 -1
- package/dist/commands/install-hooks-exit-contract.test.d.ts +2 -0
- package/dist/commands/install-hooks-exit-contract.test.d.ts.map +1 -0
- package/dist/commands/install-hooks-exit-contract.test.js +339 -0
- package/dist/commands/install-hooks-exit-contract.test.js.map +1 -0
- package/dist/commands/install-hooks.d.ts +53 -1
- package/dist/commands/install-hooks.d.ts.map +1 -1
- package/dist/commands/install-hooks.js +239 -52
- 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/prepare-wrapper.test.d.ts +2 -0
- package/dist/commands/prepare-wrapper.test.d.ts.map +1 -0
- package/dist/commands/prepare-wrapper.test.js +284 -0
- package/dist/commands/prepare-wrapper.test.js.map +1 -0
- 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,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":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,uDAAuD;AAEvD;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAEvC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AA8B9C;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,WAAW,CAAC;AAkBhD,wDAAwD;AAExD,SAAS,WAAW,CAAC,OAA2B;IAC9C,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvF,CAAC;AAED,uDAAuD;AAEvD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAW,EAAE,aAAqB;IACtE,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,GAAG,CAAC;IACjF,MAAM,OAAO,GAAuB,EAAE,CAAC;IAEvC,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAEhC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9B,IAAI,CAAC,MAAM;YAAE,SAAS;QAEtB,wEAAwE;QACxE,MAAM,cAAc,GAAG,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,CAAC;QACxD,MAAM,SAAS,GAAG,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC,SAAS;YAAE,SAAS;QAEzB,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,SAAS;QAEpE,IAAI,IAAsB,CAAC;QAC3B,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,GAAG,CAAC;YACT,KAAK,GAAG;gBACN,IAAI,GAAG,OAAO,CAAC;gBACf,MAAM;YACR,KAAK,GAAG;gBACN,IAAI,GAAG,SAAS,CAAC;gBACjB,MAAM;YACR,KAAK,GAAG,CAAC;YACT,KAAK,GAAG,CAAC;YACT,KAAK,GAAG;gBACN,IAAI,GAAG,SAAS,CAAC;gBACjB,MAAM;YACR;gBACE,SAAS,CAAC,yDAAyD;QACvE,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;AAC3C,CAAC;AAWD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CACpC,KAAgC,EAChC,YAAoB;IAEpB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC3D,MAAM,OAAO,GAAuB,EAAE,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,OAAO,GAAG,YAAY;YAAE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;AAC3C,CAAC;AAED,wDAAwD;AAExD,MAAM,WAAW,GAAG,uCAAuC,CAAC;AAE5D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAkB,EAAE,IAA4B;IACrF,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;IACnC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAChB,OAAO,mEAAmE,WAAW,EAAE,CAAC;IAC1F,CAAC;IAED,MAAM,KAAK,GAAa;QACtB,+BAA+B,KAAK,wCAAwC;KAC7E,CAAC;IAEF,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC7C,IAAI,IAAI,KAAK,oBAAoB,EAAE,CAAC;gBAClC,MAAM,GAAG,cAAc,CAAC;YAC1B,CAAC;iBAAM,IAAI,IAAI,EAAE,CAAC;gBAChB,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;YACnD,CAAC;QACH,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,KAAK,KAAK,CAAC,IAAI,IAAI,MAAM,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,KAAK,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,GAAG,IAAI,CAAC,OAAO,QAAQ,CAAC,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACxB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -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;
|
|
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":"prepare-wrapper.test.d.ts","sourceRoot":"","sources":["../../src/commands/prepare-wrapper.test.ts"],"names":[],"mappings":""}
|