@mmnto/cli 1.101.1 → 1.102.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/doctor.d.ts +36 -6
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +27 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/doctor.test.js +46 -1
- package/dist/commands/doctor.test.js.map +1 -1
- package/dist/commands/ecl-gc.d.ts.map +1 -1
- package/dist/commands/ecl-gc.js +16 -4
- package/dist/commands/ecl-gc.js.map +1 -1
- package/dist/commands/eject.d.ts +37 -2
- package/dist/commands/eject.d.ts.map +1 -1
- package/dist/commands/eject.js +79 -9
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/eject.test.js +169 -7
- package/dist/commands/eject.test.js.map +1 -1
- package/dist/commands/gate-install.test.js +22 -1
- package/dist/commands/gate-install.test.js.map +1 -1
- package/dist/commands/init-detect.js +1 -1
- package/dist/commands/init-detect.js.map +1 -1
- package/dist/commands/init-detect.test.js +2 -1
- package/dist/commands/init-detect.test.js.map +1 -1
- package/dist/commands/init-templates.js +8 -8
- package/dist/commands/install-hooks.d.ts +16 -0
- package/dist/commands/install-hooks.d.ts.map +1 -1
- package/dist/commands/install-hooks.js +5 -1
- package/dist/commands/install-hooks.js.map +1 -1
- package/dist/commands/mail-cli-wiring.test.d.ts +15 -0
- package/dist/commands/mail-cli-wiring.test.d.ts.map +1 -0
- package/dist/commands/mail-cli-wiring.test.js +106 -0
- package/dist/commands/mail-cli-wiring.test.js.map +1 -0
- package/dist/commands/mail.d.ts +80 -0
- package/dist/commands/mail.d.ts.map +1 -1
- package/dist/commands/mail.js +241 -9
- package/dist/commands/mail.js.map +1 -1
- package/dist/commands/mail.test.js +359 -4
- package/dist/commands/mail.test.js.map +1 -1
- package/dist/commands/review-fan.d.ts.map +1 -1
- package/dist/commands/review-fan.js +32 -8
- package/dist/commands/review-fan.js.map +1 -1
- package/dist/commands/review-fan.test.js +153 -7
- package/dist/commands/review-fan.test.js.map +1 -1
- package/dist/commands/shield-generated.d.ts +145 -0
- package/dist/commands/shield-generated.d.ts.map +1 -0
- package/dist/commands/shield-generated.js +266 -0
- package/dist/commands/shield-generated.js.map +1 -0
- package/dist/commands/shield-generated.test.d.ts +2 -0
- package/dist/commands/shield-generated.test.d.ts.map +1 -0
- package/dist/commands/shield-generated.test.js +323 -0
- package/dist/commands/shield-generated.test.js.map +1 -0
- package/dist/commands/shield.d.ts +27 -5
- package/dist/commands/shield.d.ts.map +1 -1
- package/dist/commands/shield.js +116 -41
- package/dist/commands/shield.js.map +1 -1
- package/dist/commands/shield.test.js +92 -2
- package/dist/commands/shield.test.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +26 -2
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/status.test.js +55 -1
- package/dist/commands/status.test.js.map +1 -1
- package/dist/hook/schema.d.ts +2 -2
- package/dist/index.js +28 -7
- package/dist/index.js.map +1 -1
- package/dist/orchestrators/orchestrator.d.ts +86 -1
- package/dist/orchestrators/orchestrator.d.ts.map +1 -1
- package/dist/orchestrators/orchestrator.js +277 -9
- package/dist/orchestrators/orchestrator.js.map +1 -1
- package/dist/orchestrators/orchestrator.test.js +240 -4
- package/dist/orchestrators/orchestrator.test.js.map +1 -1
- package/dist/orchestrators/shell-orchestrator.d.ts +12 -1
- package/dist/orchestrators/shell-orchestrator.d.ts.map +1 -1
- package/dist/orchestrators/shell-orchestrator.js +256 -49
- package/dist/orchestrators/shell-orchestrator.js.map +1 -1
- package/dist/orchestrators/shell-orchestrator.test.js +252 -4
- package/dist/orchestrators/shell-orchestrator.test.js.map +1 -1
- package/dist/utils.d.ts +19 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +394 -108
- package/dist/utils.js.map +1 -1
- package/dist/utils.test.js +406 -14
- package/dist/utils.test.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as os from 'node:os';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
5
|
+
import { cleanTmpDir } from '../test-utils.js';
|
|
6
|
+
import { buildGeneratedArtifactSection, classifyGeneratedArtifacts, DEFAULT_GENERATED_ARTIFACT_GLOBS, formatGeneratedArtifactLine, gitattributesPatternToGlob, hashDiffSection, readGitattributesGeneratedPatterns, splitDiffIntoFileSections, } from './shield-generated.js';
|
|
7
|
+
// ─── Diff builders ──────────────────────────────────────
|
|
8
|
+
/** A minimal modified-file (regenerated) diff section. */
|
|
9
|
+
function modifiedSection(file, added = 1, removed = 1) {
|
|
10
|
+
const plus = Array.from({ length: added }, (_, i) => `+added-${i}`).join('\n');
|
|
11
|
+
const minus = Array.from({ length: removed }, (_, i) => `-removed-${i}`).join('\n');
|
|
12
|
+
return [
|
|
13
|
+
`diff --git a/${file} b/${file}`,
|
|
14
|
+
`index 1111111..2222222 100644`,
|
|
15
|
+
`--- a/${file}`,
|
|
16
|
+
`+++ b/${file}`,
|
|
17
|
+
`@@ -1,${removed} +1,${added} @@`,
|
|
18
|
+
minus,
|
|
19
|
+
plus,
|
|
20
|
+
'',
|
|
21
|
+
].join('\n');
|
|
22
|
+
}
|
|
23
|
+
function addedSection(file) {
|
|
24
|
+
return [
|
|
25
|
+
`diff --git a/${file} b/${file}`,
|
|
26
|
+
`new file mode 100644`,
|
|
27
|
+
`index 0000000..3333333`,
|
|
28
|
+
`--- /dev/null`,
|
|
29
|
+
`+++ b/${file}`,
|
|
30
|
+
`@@ -0,0 +1,2 @@`,
|
|
31
|
+
`+line one`,
|
|
32
|
+
`+line two`,
|
|
33
|
+
'',
|
|
34
|
+
].join('\n');
|
|
35
|
+
}
|
|
36
|
+
function deletedSection(file) {
|
|
37
|
+
return [
|
|
38
|
+
`diff --git a/${file} b/${file}`,
|
|
39
|
+
`deleted file mode 100644`,
|
|
40
|
+
`index 4444444..0000000`,
|
|
41
|
+
`--- a/${file}`,
|
|
42
|
+
`+++ /dev/null`,
|
|
43
|
+
`@@ -1,1 +0,0 @@`,
|
|
44
|
+
`-only line`,
|
|
45
|
+
'',
|
|
46
|
+
].join('\n');
|
|
47
|
+
}
|
|
48
|
+
function binarySection(file) {
|
|
49
|
+
return [
|
|
50
|
+
`diff --git a/${file} b/${file}`,
|
|
51
|
+
`index 5555555..6666666 100644`,
|
|
52
|
+
`Binary files a/${file} and b/${file} differ`,
|
|
53
|
+
'',
|
|
54
|
+
].join('\n');
|
|
55
|
+
}
|
|
56
|
+
// ─── splitDiffIntoFileSections ──────────────────────────
|
|
57
|
+
describe('splitDiffIntoFileSections', () => {
|
|
58
|
+
it('reconstructs the input exactly when sections are joined', () => {
|
|
59
|
+
const diff = modifiedSection('src/a.ts') + modifiedSection('src/b.ts');
|
|
60
|
+
const sections = splitDiffIntoFileSections(diff);
|
|
61
|
+
expect(sections.map((s) => s.section).join('')).toBe(diff);
|
|
62
|
+
});
|
|
63
|
+
it('extracts the destination path of each section', () => {
|
|
64
|
+
const diff = modifiedSection('src/a.ts') + addedSection('dist/out.js');
|
|
65
|
+
const sections = splitDiffIntoFileSections(diff);
|
|
66
|
+
expect(sections.map((s) => s.file)).toEqual(['src/a.ts', 'dist/out.js']);
|
|
67
|
+
});
|
|
68
|
+
it('handles quoted (spaced) paths', () => {
|
|
69
|
+
const diff = [
|
|
70
|
+
'diff --git "a/my file.ts" "b/my file.ts"',
|
|
71
|
+
'--- "a/my file.ts"',
|
|
72
|
+
'+++ "b/my file.ts"',
|
|
73
|
+
'@@ -1 +1 @@',
|
|
74
|
+
'-a',
|
|
75
|
+
'+b',
|
|
76
|
+
'',
|
|
77
|
+
].join('\n');
|
|
78
|
+
const sections = splitDiffIntoFileSections(diff);
|
|
79
|
+
expect(sections[0]?.file).toBe('my file.ts');
|
|
80
|
+
});
|
|
81
|
+
it('returns an empty array for an empty diff', () => {
|
|
82
|
+
expect(splitDiffIntoFileSections('')).toEqual([]);
|
|
83
|
+
});
|
|
84
|
+
it('parses a newline-less section (truncated diff tail) without truncating the filename', () => {
|
|
85
|
+
// GCA round on #2443: indexOf('\n') === -1 previously fed slice(0, -1),
|
|
86
|
+
// chopping the final character and breaking the $-anchored path match.
|
|
87
|
+
const sections = splitDiffIntoFileSections('diff --git a/dist/out.js b/dist/out.js');
|
|
88
|
+
expect(sections).toHaveLength(1);
|
|
89
|
+
expect(sections[0]?.file).toBe('dist/out.js');
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
// ─── hashDiffSection ────────────────────────────────────
|
|
93
|
+
describe('hashDiffSection', () => {
|
|
94
|
+
it('is deterministic and 12 hex chars', () => {
|
|
95
|
+
const section = modifiedSection('pnpm-lock.yaml');
|
|
96
|
+
const h1 = hashDiffSection(section);
|
|
97
|
+
const h2 = hashDiffSection(section);
|
|
98
|
+
expect(h1).toBe(h2);
|
|
99
|
+
expect(h1).toMatch(/^[0-9a-f]{12}$/);
|
|
100
|
+
});
|
|
101
|
+
it('differs when the section content differs', () => {
|
|
102
|
+
expect(hashDiffSection(modifiedSection('a', 1, 1))).not.toBe(hashDiffSection(modifiedSection('a', 2, 1)));
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
// ─── classifyGeneratedArtifacts ─────────────────────────
|
|
106
|
+
describe('classifyGeneratedArtifacts', () => {
|
|
107
|
+
it('leaves the diff and files byte-identical when nothing matches', () => {
|
|
108
|
+
const diff = modifiedSection('src/foo.ts') + modifiedSection('src/bar.ts');
|
|
109
|
+
const changedFiles = ['src/foo.ts', 'src/bar.ts'];
|
|
110
|
+
const result = classifyGeneratedArtifacts({ diff, changedFiles });
|
|
111
|
+
expect(result.keptDiff).toBe(diff);
|
|
112
|
+
expect(result.keptFiles).toEqual(changedFiles);
|
|
113
|
+
expect(result.artifactFiles).toEqual([]);
|
|
114
|
+
expect(result.summaries).toEqual([]);
|
|
115
|
+
});
|
|
116
|
+
it('classifies a lockfile, strips its bytes, and keeps a summary', () => {
|
|
117
|
+
const diff = modifiedSection('pnpm-lock.yaml', 42, 13) + modifiedSection('src/foo.ts');
|
|
118
|
+
const changedFiles = ['pnpm-lock.yaml', 'src/foo.ts'];
|
|
119
|
+
const result = classifyGeneratedArtifacts({ diff, changedFiles });
|
|
120
|
+
expect(result.artifactFiles).toEqual(['pnpm-lock.yaml']);
|
|
121
|
+
expect(result.keptFiles).toEqual(['src/foo.ts']);
|
|
122
|
+
// The lockfile bytes are gone from the kept diff; the code file remains.
|
|
123
|
+
expect(result.keptDiff).not.toContain('pnpm-lock.yaml');
|
|
124
|
+
expect(result.keptDiff).toContain('src/foo.ts');
|
|
125
|
+
const summary = result.summaries[0];
|
|
126
|
+
expect(summary?.file).toBe('pnpm-lock.yaml');
|
|
127
|
+
expect(summary?.shape).toBe('regenerated');
|
|
128
|
+
expect(summary?.addedLines).toBe(42);
|
|
129
|
+
expect(summary?.removedLines).toBe(13);
|
|
130
|
+
expect(summary?.binary).toBe(false);
|
|
131
|
+
expect(summary?.hash).toMatch(/^[0-9a-f]{12}$/);
|
|
132
|
+
});
|
|
133
|
+
it('classifies nested build output (**/dist/**) and *.wasm and compiled-rules.json', () => {
|
|
134
|
+
const files = [
|
|
135
|
+
'packages/cli/dist/index.js',
|
|
136
|
+
'src/pkg.wasm',
|
|
137
|
+
'.totem/compiled-rules.json',
|
|
138
|
+
'src/keep.ts',
|
|
139
|
+
];
|
|
140
|
+
const diff = files.map((f) => modifiedSection(f)).join('');
|
|
141
|
+
const result = classifyGeneratedArtifacts({ diff, changedFiles: files });
|
|
142
|
+
expect(result.artifactFiles.sort()).toEqual(['.totem/compiled-rules.json', 'packages/cli/dist/index.js', 'src/pkg.wasm'].sort());
|
|
143
|
+
expect(result.keptFiles).toEqual(['src/keep.ts']);
|
|
144
|
+
});
|
|
145
|
+
it('detects added / deleted / regenerated change shapes', () => {
|
|
146
|
+
const diff = addedSection('dist/new.js') + deletedSection('dist/old.js') + modifiedSection('dist/mod.js');
|
|
147
|
+
const changedFiles = ['dist/new.js', 'dist/old.js', 'dist/mod.js'];
|
|
148
|
+
const result = classifyGeneratedArtifacts({ diff, changedFiles });
|
|
149
|
+
const byFile = Object.fromEntries(result.summaries.map((s) => [s.file, s.shape]));
|
|
150
|
+
expect(byFile['dist/new.js']).toBe('added');
|
|
151
|
+
expect(byFile['dist/old.js']).toBe('deleted');
|
|
152
|
+
expect(byFile['dist/mod.js']).toBe('regenerated');
|
|
153
|
+
});
|
|
154
|
+
it('counts hunk content beginning with ++/-- (e.g. `+++i;`) and still skips the `+++ `/`--- ` headers', () => {
|
|
155
|
+
// GCA round on #2443: a bare `+++` prefix check swallowed real added lines
|
|
156
|
+
// like C's `++i;` (rendered `+++i;` in a hunk). Headers always carry a
|
|
157
|
+
// space (`+++ b/...`, `+++ /dev/null`) — that is the discriminator.
|
|
158
|
+
const section = [
|
|
159
|
+
'diff --git a/dist/gen.c b/dist/gen.c',
|
|
160
|
+
'index 1111111..2222222 100644',
|
|
161
|
+
'--- a/dist/gen.c',
|
|
162
|
+
'+++ b/dist/gen.c',
|
|
163
|
+
'@@ -1,2 +1,2 @@',
|
|
164
|
+
'---x;',
|
|
165
|
+
'+++i;',
|
|
166
|
+
'',
|
|
167
|
+
].join('\n');
|
|
168
|
+
const result = classifyGeneratedArtifacts({
|
|
169
|
+
diff: section,
|
|
170
|
+
changedFiles: ['dist/gen.c'],
|
|
171
|
+
generatedGlobs: [...DEFAULT_GENERATED_ARTIFACT_GLOBS],
|
|
172
|
+
excludeGlobs: [],
|
|
173
|
+
});
|
|
174
|
+
expect(result.summaries).toHaveLength(1);
|
|
175
|
+
expect(result.summaries[0]?.addedLines).toBe(1);
|
|
176
|
+
expect(result.summaries[0]?.removedLines).toBe(1);
|
|
177
|
+
});
|
|
178
|
+
it('marks a binary artifact and reports no line counts', () => {
|
|
179
|
+
const diff = binarySection('src/pkg.wasm');
|
|
180
|
+
const result = classifyGeneratedArtifacts({ diff, changedFiles: ['src/pkg.wasm'] });
|
|
181
|
+
const summary = result.summaries[0];
|
|
182
|
+
expect(summary?.binary).toBe(true);
|
|
183
|
+
expect(summary?.addedLines).toBe(0);
|
|
184
|
+
expect(summary?.removedLines).toBe(0);
|
|
185
|
+
});
|
|
186
|
+
it('honors an un-mark (exclude) glob — a matched default is NOT generated', () => {
|
|
187
|
+
const diff = modifiedSection('pnpm-lock.yaml');
|
|
188
|
+
const result = classifyGeneratedArtifacts({
|
|
189
|
+
diff,
|
|
190
|
+
changedFiles: ['pnpm-lock.yaml'],
|
|
191
|
+
excludeGlobs: ['**/pnpm-lock.yaml'],
|
|
192
|
+
});
|
|
193
|
+
expect(result.artifactFiles).toEqual([]);
|
|
194
|
+
expect(result.keptDiff).toBe(diff);
|
|
195
|
+
});
|
|
196
|
+
it('honors an added generated glob passed by the caller', () => {
|
|
197
|
+
const diff = modifiedSection('dashboards/report.html');
|
|
198
|
+
const result = classifyGeneratedArtifacts({
|
|
199
|
+
diff,
|
|
200
|
+
changedFiles: ['dashboards/report.html'],
|
|
201
|
+
generatedGlobs: [...DEFAULT_GENERATED_ARTIFACT_GLOBS, '**/dashboards/**'],
|
|
202
|
+
});
|
|
203
|
+
expect(result.artifactFiles).toEqual(['dashboards/report.html']);
|
|
204
|
+
});
|
|
205
|
+
it('produces an all-generated (empty kept diff) result', () => {
|
|
206
|
+
const diff = modifiedSection('pnpm-lock.yaml') + modifiedSection('yarn.lock');
|
|
207
|
+
const result = classifyGeneratedArtifacts({
|
|
208
|
+
diff,
|
|
209
|
+
changedFiles: ['pnpm-lock.yaml', 'yarn.lock'],
|
|
210
|
+
});
|
|
211
|
+
expect(result.keptDiff.trim()).toBe('');
|
|
212
|
+
expect(result.keptFiles).toEqual([]);
|
|
213
|
+
expect(result.summaries).toHaveLength(2);
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
// ─── gitattributesPatternToGlob ─────────────────────────
|
|
217
|
+
describe('gitattributesPatternToGlob', () => {
|
|
218
|
+
it('strips a leading root-anchor slash', () => {
|
|
219
|
+
expect(gitattributesPatternToGlob('/dist/bundle.js')).toBe('dist/bundle.js');
|
|
220
|
+
});
|
|
221
|
+
it('expands a trailing directory slash to a recursive glob', () => {
|
|
222
|
+
expect(gitattributesPatternToGlob('generated/')).toBe('generated/**');
|
|
223
|
+
});
|
|
224
|
+
it('passes a bare extension pattern through unchanged', () => {
|
|
225
|
+
expect(gitattributesPatternToGlob('*.lock')).toBe('*.lock');
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
// ─── readGitattributesGeneratedPatterns ─────────────────
|
|
229
|
+
describe('readGitattributesGeneratedPatterns', () => {
|
|
230
|
+
let dir;
|
|
231
|
+
afterEach(() => {
|
|
232
|
+
cleanTmpDir(dir);
|
|
233
|
+
dir = undefined;
|
|
234
|
+
});
|
|
235
|
+
it('returns empty pattern lists when .gitattributes is absent', () => {
|
|
236
|
+
dir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-gitattr-'));
|
|
237
|
+
expect(readGitattributesGeneratedPatterns(dir)).toEqual({ generated: [], notGenerated: [] });
|
|
238
|
+
});
|
|
239
|
+
it('parses generated (true) and un-mark (false) markers, skipping comments', () => {
|
|
240
|
+
dir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-gitattr-'));
|
|
241
|
+
fs.writeFileSync(path.join(dir, '.gitattributes'), [
|
|
242
|
+
'# a comment',
|
|
243
|
+
'dashboards/** linguist-generated',
|
|
244
|
+
'src/vendor.js linguist-generated=true',
|
|
245
|
+
'src/hand-written.min.js linguist-generated=false',
|
|
246
|
+
'legacy/build.js -linguist-generated',
|
|
247
|
+
'*.ts text',
|
|
248
|
+
'',
|
|
249
|
+
].join('\n'), 'utf-8');
|
|
250
|
+
const result = readGitattributesGeneratedPatterns(dir);
|
|
251
|
+
expect(result.generated).toContain('dashboards/**');
|
|
252
|
+
expect(result.generated).toContain('src/vendor.js');
|
|
253
|
+
expect(result.notGenerated).toContain('src/hand-written.min.js');
|
|
254
|
+
expect(result.notGenerated).toContain('legacy/build.js');
|
|
255
|
+
// A non-generated attribute line contributes nothing.
|
|
256
|
+
expect(result.generated).not.toContain('*.ts');
|
|
257
|
+
});
|
|
258
|
+
it('wires .gitattributes patterns end-to-end through classification', () => {
|
|
259
|
+
dir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-gitattr-'));
|
|
260
|
+
fs.writeFileSync(path.join(dir, '.gitattributes'),
|
|
261
|
+
// Un-mark a default match AND add a repo-specific generated dir.
|
|
262
|
+
['**/pnpm-lock.yaml linguist-generated=false', 'dashboards/ linguist-generated', ''].join('\n'), 'utf-8');
|
|
263
|
+
const gitattr = readGitattributesGeneratedPatterns(dir);
|
|
264
|
+
const diff = modifiedSection('pnpm-lock.yaml') + modifiedSection('dashboards/x.html');
|
|
265
|
+
const result = classifyGeneratedArtifacts({
|
|
266
|
+
diff,
|
|
267
|
+
changedFiles: ['pnpm-lock.yaml', 'dashboards/x.html'],
|
|
268
|
+
generatedGlobs: [...DEFAULT_GENERATED_ARTIFACT_GLOBS, ...gitattr.generated],
|
|
269
|
+
excludeGlobs: gitattr.notGenerated,
|
|
270
|
+
});
|
|
271
|
+
// pnpm-lock.yaml un-marked → kept; dashboards/ added → excluded.
|
|
272
|
+
expect(result.keptFiles).toContain('pnpm-lock.yaml');
|
|
273
|
+
expect(result.artifactFiles).toEqual(['dashboards/x.html']);
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
// ─── rendering ──────────────────────────────────────────
|
|
277
|
+
describe('formatGeneratedArtifactLine', () => {
|
|
278
|
+
it('renders shape, size delta, and hash', () => {
|
|
279
|
+
const line = formatGeneratedArtifactLine({
|
|
280
|
+
file: 'pnpm-lock.yaml',
|
|
281
|
+
shape: 'regenerated',
|
|
282
|
+
addedLines: 42,
|
|
283
|
+
removedLines: 13,
|
|
284
|
+
binary: false,
|
|
285
|
+
hash: 'abcdef012345',
|
|
286
|
+
});
|
|
287
|
+
expect(line).toBe('- pnpm-lock.yaml — regenerated, +42/-13 lines, hash abcdef012345');
|
|
288
|
+
});
|
|
289
|
+
it('renders "binary" instead of line counts for a binary artifact', () => {
|
|
290
|
+
const line = formatGeneratedArtifactLine({
|
|
291
|
+
file: 'src/pkg.wasm',
|
|
292
|
+
shape: 'regenerated',
|
|
293
|
+
addedLines: 0,
|
|
294
|
+
removedLines: 0,
|
|
295
|
+
binary: true,
|
|
296
|
+
hash: 'abcdef012345',
|
|
297
|
+
});
|
|
298
|
+
expect(line).toContain('binary');
|
|
299
|
+
expect(line).not.toContain('lines');
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
describe('buildGeneratedArtifactSection', () => {
|
|
303
|
+
it('returns an empty string when there are no artifacts', () => {
|
|
304
|
+
expect(buildGeneratedArtifactSection([])).toBe('');
|
|
305
|
+
});
|
|
306
|
+
it('labels the block as a summary, not diff content (#2329 guard)', () => {
|
|
307
|
+
const section = buildGeneratedArtifactSection([
|
|
308
|
+
{
|
|
309
|
+
file: 'pnpm-lock.yaml',
|
|
310
|
+
shape: 'regenerated',
|
|
311
|
+
addedLines: 1,
|
|
312
|
+
removedLines: 1,
|
|
313
|
+
binary: false,
|
|
314
|
+
hash: 'abcdef012345',
|
|
315
|
+
},
|
|
316
|
+
]);
|
|
317
|
+
expect(section).toContain('EXCLUDED GENERATED ARTIFACTS');
|
|
318
|
+
expect(section).toContain('NOT DIFF CONTENT');
|
|
319
|
+
expect(section).toContain('<generated_artifacts_summary>');
|
|
320
|
+
expect(section).toContain('- pnpm-lock.yaml — regenerated');
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
//# sourceMappingURL=shield-generated.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shield-generated.test.js","sourceRoot":"","sources":["../../src/commands/shield-generated.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,16 +9,38 @@ interface RetrievedContext {
|
|
|
9
9
|
lessons: SearchResult[];
|
|
10
10
|
}
|
|
11
11
|
export declare function buildFileContext(changedFiles: string[], cwd: string, maxLines: number, maxChars: number): Promise<string>;
|
|
12
|
-
export declare function assemblePrompt(diff: string, changedFiles: string[], context: RetrievedContext, systemPrompt: string, smartHints?: string[], fileContext?: string): string;
|
|
13
|
-
export declare function assembleStructuralPrompt(diff: string, changedFiles: string[], systemPrompt: string, smartHints?: string[], fileContext?: string): string;
|
|
12
|
+
export declare function assemblePrompt(diff: string, changedFiles: string[], context: RetrievedContext, systemPrompt: string, smartHints?: string[], fileContext?: string, generatedArtifactSummary?: string): string;
|
|
13
|
+
export declare function assembleStructuralPrompt(diff: string, changedFiles: string[], systemPrompt: string, smartHints?: string[], fileContext?: string, generatedArtifactSummary?: string): string;
|
|
14
14
|
export declare function parseVerdict(content: string): {
|
|
15
15
|
pass: boolean;
|
|
16
16
|
reason: string;
|
|
17
17
|
} | null;
|
|
18
|
+
export type StructuredVerdictExtractionLayer = 'xml' | 'fence' | 'bare-json';
|
|
19
|
+
export type StructuredVerdictExtractionFailureCause = 'empty-output' | 'no-candidate' | 'invalid-json' | 'schema-invalid';
|
|
20
|
+
export interface StructuredVerdictExtractionAttempt {
|
|
21
|
+
layer: StructuredVerdictExtractionLayer;
|
|
22
|
+
cause: Extract<StructuredVerdictExtractionFailureCause, 'invalid-json' | 'schema-invalid'>;
|
|
23
|
+
/** Bounded validation summaries; candidate/output text is never retained here. */
|
|
24
|
+
issues?: string[];
|
|
25
|
+
}
|
|
26
|
+
export type StructuredVerdictExtractionResult = {
|
|
27
|
+
ok: true;
|
|
28
|
+
verdict: ShieldStructuredVerdict;
|
|
29
|
+
layer: StructuredVerdictExtractionLayer;
|
|
30
|
+
} | {
|
|
31
|
+
ok: false;
|
|
32
|
+
cause: StructuredVerdictExtractionFailureCause;
|
|
33
|
+
attempts: StructuredVerdictExtractionAttempt[];
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Three-layer JSON extraction with bounded, candidate-free failure diagnostics.
|
|
37
|
+
* A schema-invalid candidate takes precedence over malformed candidates because
|
|
38
|
+
* it is the most semantically advanced failure reached by the cascade.
|
|
39
|
+
*/
|
|
40
|
+
export declare function extractStructuredVerdictDetailed(content: string): StructuredVerdictExtractionResult;
|
|
18
41
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* Returns null if all layers fail (caller falls back to V1 regex parseVerdict).
|
|
42
|
+
* Compatibility wrapper for callers that only need the parsed verdict.
|
|
43
|
+
* Returns null when all XML, fenced, and bare-JSON layers fail.
|
|
22
44
|
*/
|
|
23
45
|
export declare function extractStructuredVerdict(content: string): ShieldStructuredVerdict | null;
|
|
24
46
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shield.d.ts","sourceRoot":"","sources":["../../src/commands/shield.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA2B,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEvF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAkBzE,OAAO,EAWL,KAAK,aAAa,EAClB,KAAK,uBAAuB,EAO7B,MAAM,uBAAuB,CAAC;AAK/B,OAAO,EACL,cAAc,EACd,0BAA0B,EAC1B,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAI/B,UAAU,gBAAgB;IACxB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AA0BD,wBAAsB,gBAAgB,CACpC,YAAY,EAAE,MAAM,EAAE,EACtB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CA0CjB;AAID,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EAAE,EACtB,OAAO,EAAE,gBAAgB,EACzB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,EAAE,EACrB,WAAW,CAAC,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"shield.d.ts","sourceRoot":"","sources":["../../src/commands/shield.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/shield.js
CHANGED
|
@@ -64,7 +64,7 @@ export async function buildFileContext(changedFiles, cwd, maxLines, maxChars) {
|
|
|
64
64
|
return `\n=== FILE CONTEXT (unchanged code for reference) ===\n${entries.join('\n\n')}`;
|
|
65
65
|
}
|
|
66
66
|
// ─── Prompt assembly ────────────────────────────────────
|
|
67
|
-
export function assemblePrompt(diff, changedFiles, context, systemPrompt, smartHints, fileContext) {
|
|
67
|
+
export function assemblePrompt(diff, changedFiles, context, systemPrompt, smartHints, fileContext, generatedArtifactSummary) {
|
|
68
68
|
const sections = [systemPrompt];
|
|
69
69
|
// Diff section
|
|
70
70
|
sections.push('=== DIFF ===');
|
|
@@ -76,6 +76,11 @@ export function assemblePrompt(diff, changedFiles, context, systemPrompt, smartH
|
|
|
76
76
|
else {
|
|
77
77
|
sections.push(wrapXml('git_diff', diff));
|
|
78
78
|
}
|
|
79
|
+
// Excluded generated-artifact summary (mmnto-ai/totem#2398) — bytes excluded,
|
|
80
|
+
// signal preserved. Clearly labelled as a summary, not diff content (#2329).
|
|
81
|
+
if (generatedArtifactSummary) {
|
|
82
|
+
sections.push(generatedArtifactSummary);
|
|
83
|
+
}
|
|
79
84
|
// File context — full source for small changed files
|
|
80
85
|
if (fileContext) {
|
|
81
86
|
sections.push(fileContext);
|
|
@@ -108,7 +113,7 @@ export function assemblePrompt(diff, changedFiles, context, systemPrompt, smartH
|
|
|
108
113
|
return sections.join('\n');
|
|
109
114
|
}
|
|
110
115
|
// ─── Structural prompt assembly ──────────────────────────
|
|
111
|
-
export function assembleStructuralPrompt(diff, changedFiles, systemPrompt, smartHints, fileContext) {
|
|
116
|
+
export function assembleStructuralPrompt(diff, changedFiles, systemPrompt, smartHints, fileContext, generatedArtifactSummary) {
|
|
112
117
|
const sections = [systemPrompt];
|
|
113
118
|
sections.push('=== DIFF ===');
|
|
114
119
|
if (changedFiles.length > 0) {
|
|
@@ -121,6 +126,11 @@ export function assembleStructuralPrompt(diff, changedFiles, systemPrompt, smart
|
|
|
121
126
|
else {
|
|
122
127
|
sections.push(wrapXml('git_diff', diff));
|
|
123
128
|
}
|
|
129
|
+
// Excluded generated-artifact summary (mmnto-ai/totem#2398) — bytes excluded,
|
|
130
|
+
// signal preserved. Clearly labelled as a summary, not diff content (#2329).
|
|
131
|
+
if (generatedArtifactSummary) {
|
|
132
|
+
sections.push(generatedArtifactSummary);
|
|
133
|
+
}
|
|
124
134
|
// File context — full source for small changed files
|
|
125
135
|
if (fileContext) {
|
|
126
136
|
sections.push(fileContext);
|
|
@@ -142,54 +152,84 @@ export function parseVerdict(content) {
|
|
|
142
152
|
return null;
|
|
143
153
|
return { pass: match[1] === 'PASS', reason: match[2].trim() };
|
|
144
154
|
}
|
|
145
|
-
|
|
155
|
+
const MAX_EXTRACTION_ISSUES = 4;
|
|
156
|
+
const MAX_EXTRACTION_ISSUE_CHARS = 160;
|
|
157
|
+
function summarizeValidationIssues(issues) {
|
|
158
|
+
return issues.slice(0, MAX_EXTRACTION_ISSUES).map((issue) => {
|
|
159
|
+
const path = issue.path.length > 0 ? issue.path.join('.') : '<root>';
|
|
160
|
+
return `${path}: ${issue.code}`.slice(0, MAX_EXTRACTION_ISSUE_CHARS);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
function tryStructuredVerdictCandidate(layer, candidate) {
|
|
164
|
+
let parsed;
|
|
165
|
+
try {
|
|
166
|
+
parsed = JSON.parse(candidate);
|
|
167
|
+
// totem-context: malformed candidates are expected during the extraction cascade and are converted into the typed invalid-json result below.
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
return { ok: false, attempt: { layer, cause: 'invalid-json' } };
|
|
171
|
+
}
|
|
172
|
+
const result = ShieldStructuredVerdictSchema.safeParse(parsed);
|
|
173
|
+
if (result.success)
|
|
174
|
+
return { ok: true, verdict: result.data, layer };
|
|
175
|
+
return {
|
|
176
|
+
ok: false,
|
|
177
|
+
attempt: {
|
|
178
|
+
layer,
|
|
179
|
+
cause: 'schema-invalid',
|
|
180
|
+
issues: summarizeValidationIssues(result.error.issues),
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
}
|
|
146
184
|
/**
|
|
147
|
-
* Three-layer JSON extraction
|
|
148
|
-
*
|
|
149
|
-
*
|
|
185
|
+
* Three-layer JSON extraction with bounded, candidate-free failure diagnostics.
|
|
186
|
+
* A schema-invalid candidate takes precedence over malformed candidates because
|
|
187
|
+
* it is the most semantically advanced failure reached by the cascade.
|
|
150
188
|
*/
|
|
151
|
-
export function
|
|
152
|
-
|
|
189
|
+
export function extractStructuredVerdictDetailed(content) {
|
|
190
|
+
if (content.trim().length === 0)
|
|
191
|
+
return { ok: false, cause: 'empty-output', attempts: [] };
|
|
192
|
+
const attempts = [];
|
|
193
|
+
const tryCandidate = (layer, candidate) => {
|
|
194
|
+
const result = tryStructuredVerdictCandidate(layer, candidate);
|
|
195
|
+
if (result.ok)
|
|
196
|
+
return result.verdict;
|
|
197
|
+
attempts.push(result.attempt);
|
|
198
|
+
return null;
|
|
199
|
+
};
|
|
153
200
|
const xmlMatch = content.match(/<shield_verdict>([\s\S]*?)<\/shield_verdict>/);
|
|
154
201
|
if (xmlMatch) {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
if (result.success)
|
|
159
|
-
return result.data;
|
|
160
|
-
}
|
|
161
|
-
catch {
|
|
162
|
-
// Move to next layer
|
|
163
|
-
}
|
|
202
|
+
const verdict = tryCandidate('xml', xmlMatch[1]);
|
|
203
|
+
if (verdict)
|
|
204
|
+
return { ok: true, verdict, layer: 'xml' };
|
|
164
205
|
}
|
|
165
|
-
// Layer 2 — Markdown code fences (fallback)
|
|
166
206
|
const fenceMatch = content.match(/(?:```|~~~)(?:json)?\s*\n([\s\S]*?)\n\s*(?:```|~~~)/);
|
|
167
207
|
if (fenceMatch) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
if (result.success)
|
|
172
|
-
return result.data;
|
|
173
|
-
}
|
|
174
|
-
catch {
|
|
175
|
-
// Move to next layer
|
|
176
|
-
}
|
|
208
|
+
const verdict = tryCandidate('fence', fenceMatch[1]);
|
|
209
|
+
if (verdict)
|
|
210
|
+
return { ok: true, verdict, layer: 'fence' };
|
|
177
211
|
}
|
|
178
|
-
// Layer 3 — Bare JSON (last resort, guarded by "findings" keyword)
|
|
179
212
|
const firstBrace = content.indexOf('{');
|
|
180
213
|
const lastBrace = content.lastIndexOf('}');
|
|
181
214
|
if (firstBrace !== -1 && lastBrace > firstBrace && content.includes('"findings"')) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
|
|
215
|
+
const verdict = tryCandidate('bare-json', content.slice(firstBrace, lastBrace + 1));
|
|
216
|
+
if (verdict)
|
|
217
|
+
return { ok: true, verdict, layer: 'bare-json' };
|
|
218
|
+
}
|
|
219
|
+
if (attempts.length === 0)
|
|
220
|
+
return { ok: false, cause: 'no-candidate', attempts };
|
|
221
|
+
const cause = attempts.some((attempt) => attempt.cause === 'schema-invalid')
|
|
222
|
+
? 'schema-invalid'
|
|
223
|
+
: 'invalid-json';
|
|
224
|
+
return { ok: false, cause, attempts };
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Compatibility wrapper for callers that only need the parsed verdict.
|
|
228
|
+
* Returns null when all XML, fenced, and bare-JSON layers fail.
|
|
229
|
+
*/
|
|
230
|
+
export function extractStructuredVerdict(content) {
|
|
231
|
+
const result = extractStructuredVerdictDetailed(content);
|
|
232
|
+
return result.ok ? result.verdict : null;
|
|
193
233
|
}
|
|
194
234
|
/**
|
|
195
235
|
* Deterministic pass/fail based on findings.
|
|
@@ -898,6 +938,7 @@ export async function shieldCommand(options) {
|
|
|
898
938
|
const { filterDiffByPatterns, getDiffForReview } = await import('../git.js');
|
|
899
939
|
const { classifyChangedFiles } = await import('./shield-classify.js');
|
|
900
940
|
const { extractShieldContextAnnotations, extractShieldHints } = await import('./shield-hints.js');
|
|
941
|
+
const { DEFAULT_GENERATED_ARTIFACT_GLOBS, buildGeneratedArtifactSection, classifyGeneratedArtifacts, formatGeneratedArtifactLine, readGitattributesGeneratedPatterns, } = await import('./shield-generated.js');
|
|
901
942
|
// mmnto-ai/totem#1714: --estimate is the deterministic-rule pre-flight
|
|
902
943
|
// path. Reject incompatible flag combinations BEFORE any other
|
|
903
944
|
// validation (e.g. the --override length check below) so the user-
|
|
@@ -1047,6 +1088,40 @@ export async function shieldCommand(options) {
|
|
|
1047
1088
|
selectorForm: diffResult.selectorForm,
|
|
1048
1089
|
};
|
|
1049
1090
|
}
|
|
1091
|
+
// Stage 0.5: Exclude generated-artifact BYTES from the synthesis input
|
|
1092
|
+
// (mmnto-ai/totem#2398). Generated artifacts (lockfiles, compiled-rules.json,
|
|
1093
|
+
// dist/**, *.wasm, regenerated dashboards) burn review-context tokens on bytes
|
|
1094
|
+
// no reviewer should read. Classify them by default (seeded globs + honor
|
|
1095
|
+
// `.gitattributes` `linguist-generated`), strip their diff sections, and inject
|
|
1096
|
+
// a per-file SUMMARY instead of a silent drop — path, change shape, size delta,
|
|
1097
|
+
// semantic hash — so the "this regenerated" signal survives without the bytes.
|
|
1098
|
+
let generatedArtifactSummary;
|
|
1099
|
+
{
|
|
1100
|
+
const gitattr = readGitattributesGeneratedPatterns(cwd);
|
|
1101
|
+
const generated = classifyGeneratedArtifacts({
|
|
1102
|
+
diff,
|
|
1103
|
+
changedFiles,
|
|
1104
|
+
generatedGlobs: [...DEFAULT_GENERATED_ARTIFACT_GLOBS, ...gitattr.generated],
|
|
1105
|
+
excludeGlobs: gitattr.notGenerated,
|
|
1106
|
+
});
|
|
1107
|
+
if (generated.summaries.length > 0) {
|
|
1108
|
+
log.info(DISPLAY_TAG, `Excluded ${generated.summaries.length} generated-artifact file(s) from the review payload (summarized, not dropped):`);
|
|
1109
|
+
for (const summary of generated.summaries) {
|
|
1110
|
+
log.dim(DISPLAY_TAG, formatGeneratedArtifactLine(summary));
|
|
1111
|
+
}
|
|
1112
|
+
diff = generated.keptDiff;
|
|
1113
|
+
changedFiles = generated.keptFiles;
|
|
1114
|
+
generatedArtifactSummary = buildGeneratedArtifactSection(generated.summaries);
|
|
1115
|
+
// All changed files were generated artifacts — nothing left to review.
|
|
1116
|
+
// Deterministic PASS: the summary was already surfaced above (never a
|
|
1117
|
+
// silent skip). The artifacts' correctness is a gate concern, not the LLM's.
|
|
1118
|
+
if (!diff.trim()) {
|
|
1119
|
+
log.info(DISPLAY_TAG, 'Deterministic fast-path: all changed files are generated artifacts');
|
|
1120
|
+
await writeReviewedContentHash(cwd, config.totemDir, configRoot, config.review.sourceExtensions);
|
|
1121
|
+
return;
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1050
1125
|
// Stage 1: Classify files — fast-path for non-code-only diffs
|
|
1051
1126
|
const classification = classifyChangedFiles(changedFiles);
|
|
1052
1127
|
if (classification.allNonCode) {
|
|
@@ -1109,7 +1184,7 @@ export async function shieldCommand(options) {
|
|
|
1109
1184
|
if (options.mode === 'structural') {
|
|
1110
1185
|
log.info(DISPLAY_TAG, 'Running structural review (context-blind, no Totem knowledge)...');
|
|
1111
1186
|
const systemPrompt = getSystemPrompt('shield-structural', STRUCTURAL_SYSTEM_PROMPT_V2, cwd, config.totemDir);
|
|
1112
|
-
const prompt = assembleStructuralPrompt(filteredDiff, filteredFiles, systemPrompt, smartHints, fileContext);
|
|
1187
|
+
const prompt = assembleStructuralPrompt(filteredDiff, filteredFiles, systemPrompt, smartHints, fileContext, generatedArtifactSummary);
|
|
1113
1188
|
log.dim(DISPLAY_TAG, `Prompt: ${(prompt.length / 1024).toFixed(0)}KB`);
|
|
1114
1189
|
const content = await runOrchestrator({
|
|
1115
1190
|
prompt,
|
|
@@ -1152,7 +1227,7 @@ export async function shieldCommand(options) {
|
|
|
1152
1227
|
if (codeBlindGuard.banner)
|
|
1153
1228
|
log.warn(DISPLAY_TAG, codeBlindGuard.banner);
|
|
1154
1229
|
// Assemble prompt — use filtered diff/files for LLM review
|
|
1155
|
-
const prompt = assemblePrompt(filteredDiff, filteredFiles, context, codeBlindGuard.systemPrompt, smartHints, fileContext);
|
|
1230
|
+
const prompt = assemblePrompt(filteredDiff, filteredFiles, context, codeBlindGuard.systemPrompt, smartHints, fileContext, generatedArtifactSummary);
|
|
1156
1231
|
log.dim(DISPLAY_TAG, `Prompt: ${(prompt.length / 1024).toFixed(0)}KB`);
|
|
1157
1232
|
// Grounded run artifact (mmnto-ai/totem#2100): always-on for the standard
|
|
1158
1233
|
// review verdict path — every run is a future eval fixture. Per-item
|