codebase-snapshot 0.9.9 → 0.9.12
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/CHANGELOG.md +494 -0
- package/README.md +3 -3
- package/dist/bin.js +5227 -3461
- package/dist/{chunk-KUVFTJHK.js → chunk-3H45YMBG.js} +1848 -507
- package/dist/{chunk-HQBEQ67K.js → chunk-5OR3WVPW.js} +366 -84
- package/dist/cli.cjs +5245 -3499
- package/dist/cli.d.cts +282 -3
- package/dist/cli.d.ts +282 -3
- package/dist/cli.js +160 -38
- package/dist/generate-worker-D5Xgh27c.d.cts +57 -0
- package/dist/generate-worker-D5Xgh27c.d.ts +57 -0
- package/dist/index.cjs +1799 -504
- package/dist/index.d.cts +293 -4
- package/dist/index.d.ts +293 -4
- package/dist/index.js +1 -3
- package/dist/mcp.cjs +5670 -4877
- package/dist/mcp.d.cts +70 -2
- package/dist/mcp.d.ts +70 -2
- package/dist/mcp.js +2 -4
- package/dist/{types-Ca4PmkiQ.d.cts → types-CTewen3J.d.cts} +115 -2
- package/dist/{types-Ca4PmkiQ.d.ts → types-CTewen3J.d.ts} +115 -2
- package/docs/agent.md +1 -1
- package/docs/cli.md +21 -3
- package/docs/configuration.md +5 -0
- package/docs/how-to-feed-a-repo-to-claude.md +61 -0
- package/docs/mcp.md +23 -10
- package/docs/output.md +36 -4
- package/docs/stale-context-is-your-bug.md +13 -0
- package/docs/vs-repomix.md +1 -1
- package/package.json +5 -3
package/dist/mcp.d.cts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { G as GenerateSummary, W as WorkerResults, g as generateInWorker } from './generate-worker-D5Xgh27c.cjs';
|
|
1
2
|
import { Readable, Writable } from 'node:stream';
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -187,7 +188,7 @@ interface ToolContext {
|
|
|
187
188
|
* Client-facing hints.
|
|
188
189
|
*
|
|
189
190
|
* `readOnlyHint` is the one that changes behaviour rather than appearance: clients use it to
|
|
190
|
-
* auto-approve a call.
|
|
191
|
+
* auto-approve a call. Seven of the eight tools never touch the filesystem, so they are marked
|
|
191
192
|
* read-only and only `snapshot_generate` prompts.
|
|
192
193
|
*/
|
|
193
194
|
interface ToolAnnotations {
|
|
@@ -297,6 +298,73 @@ declare function createMcpServer(options: McpServerOptions): McpServer;
|
|
|
297
298
|
/** Every tool this server exposes, in the order a first-time caller should read them. */
|
|
298
299
|
declare function buildTools(): McpTool[];
|
|
299
300
|
|
|
301
|
+
/**
|
|
302
|
+
* Reads one file's section back out of a rendered part.
|
|
303
|
+
*
|
|
304
|
+
* `snapshot_read` must not open the working tree. The snapshot is the contract: sensitive files
|
|
305
|
+
* are excluded from it, secret-shaped strings inside ordinary files are redacted on the way in,
|
|
306
|
+
* and a large file is emitted as a bounded preview. Reading the source directly would hand the
|
|
307
|
+
* model the `.env` the snapshot deliberately skipped and the credential it masked — so the read
|
|
308
|
+
* goes through the artifact instead.
|
|
309
|
+
*
|
|
310
|
+
* The format it parses is written by `renderFileSection`, and the parser is deliberately tied to
|
|
311
|
+
* that shape rather than to a regex over the whole document: a file's *content* may legitimately
|
|
312
|
+
* contain a line that looks like `### FILE: something`, and only fence tracking tells the two
|
|
313
|
+
* apart. Content fences are four or more backticks (`fenceForContent` never emits three), which
|
|
314
|
+
* is what makes "the next line equal to this exact fence" an unambiguous terminator.
|
|
315
|
+
*/
|
|
316
|
+
interface PartSection {
|
|
317
|
+
/** The path as rendered in the `### FILE:` heading. */
|
|
318
|
+
path: string;
|
|
319
|
+
/** The `<a id="…">` anchor from the line above the heading, when present. */
|
|
320
|
+
anchor: string | null;
|
|
321
|
+
/** The file body, without its fence. Redacted and possibly a bounded preview. */
|
|
322
|
+
body: string;
|
|
323
|
+
/** `full`, `preview` or `signatures`. */
|
|
324
|
+
inclusion: string | null;
|
|
325
|
+
includedLines: number | null;
|
|
326
|
+
}
|
|
327
|
+
/** Splits a part into one section per emitted file. */
|
|
328
|
+
declare function parsePartSections(partText: string): PartSection[];
|
|
329
|
+
/**
|
|
330
|
+
* Finds the section for one file.
|
|
331
|
+
*
|
|
332
|
+
* The **anchor** is the identifier, not the heading. `anchorForPath` hashes the real
|
|
333
|
+
* `relativePath`, so it is exact and injective; the heading is the display form, and for a path
|
|
334
|
+
* with a control character (escaped as `\uXXXX`) or one longer than 300 characters (capped from
|
|
335
|
+
* the middle) it is not the path at all. The old fallback for those cases was the content
|
|
336
|
+
* SHA-256, which the part no longer carries — and which could never disambiguate two files with
|
|
337
|
+
* the same content, the exact case that needs it.
|
|
338
|
+
*
|
|
339
|
+
* The heading comparison is kept as a second chance, for a snapshot written before the anchor
|
|
340
|
+
* was read, or a part whose anchor line was edited by hand.
|
|
341
|
+
*/
|
|
342
|
+
declare function findSection(sections: readonly PartSection[], relativePath: string): PartSection | null;
|
|
343
|
+
interface Window {
|
|
344
|
+
text: string;
|
|
345
|
+
fromLine: number;
|
|
346
|
+
returnedLines: number;
|
|
347
|
+
totalLines: number;
|
|
348
|
+
truncated: boolean;
|
|
349
|
+
nextFromLine: number | null;
|
|
350
|
+
/**
|
|
351
|
+
* True when `fromLine` is beyond the last line of the body.
|
|
352
|
+
*
|
|
353
|
+
* The start used to be clamped to the last line, so asking for line 9,000 of a 40-line file
|
|
354
|
+
* returned line 40 with a header that read `Lines 40–40 of 40` — a wrong answer dressed as a
|
|
355
|
+
* right one. The caller is told the request was out of range instead.
|
|
356
|
+
*/
|
|
357
|
+
pastEnd: boolean;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Cuts a line window out of a body.
|
|
361
|
+
*
|
|
362
|
+
* Windows are the whole point of this module: a part holds hundreds of kilobytes, and the only
|
|
363
|
+
* safe default for a tool that returns content is "as little as answers the question". `next` is
|
|
364
|
+
* an explicit pointer rather than an instruction to keep reading, so an agent decides.
|
|
365
|
+
*/
|
|
366
|
+
declare function windowText(body: string, fromLine: number, lineCount: number): Window;
|
|
367
|
+
|
|
300
368
|
declare function buildPrompts(): McpPrompt[];
|
|
301
369
|
|
|
302
370
|
declare function buildResourceProvider(): ResourceProvider;
|
|
@@ -409,4 +477,4 @@ declare function validateArguments(schema: InputSchema, value: unknown): string[
|
|
|
409
477
|
*/
|
|
410
478
|
declare function coerceNumericStrings(schema: InputSchema, value: JsonObject): JsonObject;
|
|
411
479
|
|
|
412
|
-
export { ERROR_CODES, type JsonRpcResponse, type JsonSchema, LEGACY_PROTOCOL_VERSIONS, type LineReaderOptions, MAX_LINE_BYTES, METHOD, MODERN_PROTOCOL_VERSIONS, type McpPrompt, type McpResourceContents, type McpResourceDescriptor, type McpResourceTemplate, type McpServer, type McpServerInfo, type McpServerOptions, type McpTool, type MessageWriter, type ProtocolEra, type ResourceProvider, SERVER_INSTRUCTIONS, SUPPORTED_PROTOCOL_VERSIONS, type ServerOptions, type SessionState, type ToolAnnotations, type ToolContext, type ToolOutcome, buildPrompts, buildResourceProvider, buildTools, classifyRequest, coerceNumericStrings, createLineReader, createMcpServer, createServer, createSession, createWriter, inspectModernMeta, negotiateLegacyVersion, runStdioServer, validateArguments };
|
|
480
|
+
export { ERROR_CODES, type JsonRpcResponse, type JsonSchema, LEGACY_PROTOCOL_VERSIONS, type LineReaderOptions, MAX_LINE_BYTES, METHOD, MODERN_PROTOCOL_VERSIONS, type McpPrompt, type McpResourceContents, type McpResourceDescriptor, type McpResourceTemplate, type McpServer, type McpServerInfo, type McpServerOptions, type McpTool, type MessageWriter, type PartSection, type ProtocolEra, type ResourceProvider, SERVER_INSTRUCTIONS, SUPPORTED_PROTOCOL_VERSIONS, type ServerOptions, type SessionState, type ToolAnnotations, type ToolContext, type ToolOutcome, type Window, buildPrompts, buildResourceProvider, buildTools, classifyRequest, coerceNumericStrings, createLineReader, createMcpServer, createServer, createSession, createWriter, findSection, inspectModernMeta, negotiateLegacyVersion, parsePartSections, runStdioServer, validateArguments, windowText };
|
package/dist/mcp.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { G as GenerateSummary, W as WorkerResults, g as generateInWorker } from './generate-worker-D5Xgh27c.js';
|
|
1
2
|
import { Readable, Writable } from 'node:stream';
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -187,7 +188,7 @@ interface ToolContext {
|
|
|
187
188
|
* Client-facing hints.
|
|
188
189
|
*
|
|
189
190
|
* `readOnlyHint` is the one that changes behaviour rather than appearance: clients use it to
|
|
190
|
-
* auto-approve a call.
|
|
191
|
+
* auto-approve a call. Seven of the eight tools never touch the filesystem, so they are marked
|
|
191
192
|
* read-only and only `snapshot_generate` prompts.
|
|
192
193
|
*/
|
|
193
194
|
interface ToolAnnotations {
|
|
@@ -297,6 +298,73 @@ declare function createMcpServer(options: McpServerOptions): McpServer;
|
|
|
297
298
|
/** Every tool this server exposes, in the order a first-time caller should read them. */
|
|
298
299
|
declare function buildTools(): McpTool[];
|
|
299
300
|
|
|
301
|
+
/**
|
|
302
|
+
* Reads one file's section back out of a rendered part.
|
|
303
|
+
*
|
|
304
|
+
* `snapshot_read` must not open the working tree. The snapshot is the contract: sensitive files
|
|
305
|
+
* are excluded from it, secret-shaped strings inside ordinary files are redacted on the way in,
|
|
306
|
+
* and a large file is emitted as a bounded preview. Reading the source directly would hand the
|
|
307
|
+
* model the `.env` the snapshot deliberately skipped and the credential it masked — so the read
|
|
308
|
+
* goes through the artifact instead.
|
|
309
|
+
*
|
|
310
|
+
* The format it parses is written by `renderFileSection`, and the parser is deliberately tied to
|
|
311
|
+
* that shape rather than to a regex over the whole document: a file's *content* may legitimately
|
|
312
|
+
* contain a line that looks like `### FILE: something`, and only fence tracking tells the two
|
|
313
|
+
* apart. Content fences are four or more backticks (`fenceForContent` never emits three), which
|
|
314
|
+
* is what makes "the next line equal to this exact fence" an unambiguous terminator.
|
|
315
|
+
*/
|
|
316
|
+
interface PartSection {
|
|
317
|
+
/** The path as rendered in the `### FILE:` heading. */
|
|
318
|
+
path: string;
|
|
319
|
+
/** The `<a id="…">` anchor from the line above the heading, when present. */
|
|
320
|
+
anchor: string | null;
|
|
321
|
+
/** The file body, without its fence. Redacted and possibly a bounded preview. */
|
|
322
|
+
body: string;
|
|
323
|
+
/** `full`, `preview` or `signatures`. */
|
|
324
|
+
inclusion: string | null;
|
|
325
|
+
includedLines: number | null;
|
|
326
|
+
}
|
|
327
|
+
/** Splits a part into one section per emitted file. */
|
|
328
|
+
declare function parsePartSections(partText: string): PartSection[];
|
|
329
|
+
/**
|
|
330
|
+
* Finds the section for one file.
|
|
331
|
+
*
|
|
332
|
+
* The **anchor** is the identifier, not the heading. `anchorForPath` hashes the real
|
|
333
|
+
* `relativePath`, so it is exact and injective; the heading is the display form, and for a path
|
|
334
|
+
* with a control character (escaped as `\uXXXX`) or one longer than 300 characters (capped from
|
|
335
|
+
* the middle) it is not the path at all. The old fallback for those cases was the content
|
|
336
|
+
* SHA-256, which the part no longer carries — and which could never disambiguate two files with
|
|
337
|
+
* the same content, the exact case that needs it.
|
|
338
|
+
*
|
|
339
|
+
* The heading comparison is kept as a second chance, for a snapshot written before the anchor
|
|
340
|
+
* was read, or a part whose anchor line was edited by hand.
|
|
341
|
+
*/
|
|
342
|
+
declare function findSection(sections: readonly PartSection[], relativePath: string): PartSection | null;
|
|
343
|
+
interface Window {
|
|
344
|
+
text: string;
|
|
345
|
+
fromLine: number;
|
|
346
|
+
returnedLines: number;
|
|
347
|
+
totalLines: number;
|
|
348
|
+
truncated: boolean;
|
|
349
|
+
nextFromLine: number | null;
|
|
350
|
+
/**
|
|
351
|
+
* True when `fromLine` is beyond the last line of the body.
|
|
352
|
+
*
|
|
353
|
+
* The start used to be clamped to the last line, so asking for line 9,000 of a 40-line file
|
|
354
|
+
* returned line 40 with a header that read `Lines 40–40 of 40` — a wrong answer dressed as a
|
|
355
|
+
* right one. The caller is told the request was out of range instead.
|
|
356
|
+
*/
|
|
357
|
+
pastEnd: boolean;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Cuts a line window out of a body.
|
|
361
|
+
*
|
|
362
|
+
* Windows are the whole point of this module: a part holds hundreds of kilobytes, and the only
|
|
363
|
+
* safe default for a tool that returns content is "as little as answers the question". `next` is
|
|
364
|
+
* an explicit pointer rather than an instruction to keep reading, so an agent decides.
|
|
365
|
+
*/
|
|
366
|
+
declare function windowText(body: string, fromLine: number, lineCount: number): Window;
|
|
367
|
+
|
|
300
368
|
declare function buildPrompts(): McpPrompt[];
|
|
301
369
|
|
|
302
370
|
declare function buildResourceProvider(): ResourceProvider;
|
|
@@ -409,4 +477,4 @@ declare function validateArguments(schema: InputSchema, value: unknown): string[
|
|
|
409
477
|
*/
|
|
410
478
|
declare function coerceNumericStrings(schema: InputSchema, value: JsonObject): JsonObject;
|
|
411
479
|
|
|
412
|
-
export { ERROR_CODES, type JsonRpcResponse, type JsonSchema, LEGACY_PROTOCOL_VERSIONS, type LineReaderOptions, MAX_LINE_BYTES, METHOD, MODERN_PROTOCOL_VERSIONS, type McpPrompt, type McpResourceContents, type McpResourceDescriptor, type McpResourceTemplate, type McpServer, type McpServerInfo, type McpServerOptions, type McpTool, type MessageWriter, type ProtocolEra, type ResourceProvider, SERVER_INSTRUCTIONS, SUPPORTED_PROTOCOL_VERSIONS, type ServerOptions, type SessionState, type ToolAnnotations, type ToolContext, type ToolOutcome, buildPrompts, buildResourceProvider, buildTools, classifyRequest, coerceNumericStrings, createLineReader, createMcpServer, createServer, createSession, createWriter, inspectModernMeta, negotiateLegacyVersion, runStdioServer, validateArguments };
|
|
480
|
+
export { ERROR_CODES, type JsonRpcResponse, type JsonSchema, LEGACY_PROTOCOL_VERSIONS, type LineReaderOptions, MAX_LINE_BYTES, METHOD, MODERN_PROTOCOL_VERSIONS, type McpPrompt, type McpResourceContents, type McpResourceDescriptor, type McpResourceTemplate, type McpServer, type McpServerInfo, type McpServerOptions, type McpTool, type MessageWriter, type PartSection, type ProtocolEra, type ResourceProvider, SERVER_INSTRUCTIONS, SUPPORTED_PROTOCOL_VERSIONS, type ServerOptions, type SessionState, type ToolAnnotations, type ToolContext, type ToolOutcome, type Window, buildPrompts, buildResourceProvider, buildTools, classifyRequest, coerceNumericStrings, createLineReader, createMcpServer, createServer, createSession, createWriter, findSection, inspectModernMeta, negotiateLegacyVersion, parsePartSections, runStdioServer, validateArguments, windowText };
|
package/dist/mcp.js
CHANGED
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
export { ERROR_CODES, LEGACY_PROTOCOL_VERSIONS, MAX_LINE_BYTES, METHOD, MODERN_PROTOCOL_VERSIONS, SERVER_INSTRUCTIONS, SUPPORTED_PROTOCOL_VERSIONS, buildPrompts, buildResourceProvider, buildTools, classifyRequest, coerceNumericStrings, createLineReader, createMcpServer, createServer, createSession, createWriter, inspectModernMeta, negotiateLegacyVersion, runStdioServer, validateArguments } from './chunk-
|
|
2
|
-
|
|
3
|
-
//# sourceMappingURL=mcp.js.map
|
|
4
|
-
//# sourceMappingURL=mcp.js.map
|
|
1
|
+
export { ERROR_CODES, LEGACY_PROTOCOL_VERSIONS, MAX_LINE_BYTES, METHOD, MODERN_PROTOCOL_VERSIONS, SERVER_INSTRUCTIONS, SUPPORTED_PROTOCOL_VERSIONS, buildPrompts, buildResourceProvider, buildTools, classifyRequest, coerceNumericStrings, createLineReader, createMcpServer, createServer, createSession, createWriter, findSection, inspectModernMeta, negotiateLegacyVersion, parsePartSections, runStdioServer, validateArguments, windowText } from './chunk-5OR3WVPW.js';
|
|
2
|
+
export { generateInWorker } from './chunk-3H45YMBG.js';
|
|
@@ -21,7 +21,7 @@ type TextEncoding = "utf-8" | "utf-8-lossy" | "utf-16le" | "utf-16be";
|
|
|
21
21
|
* `full` – the complete file body was emitted.
|
|
22
22
|
* `preview` – the body was truncated (by lines and/or bytes) before emission.
|
|
23
23
|
*/
|
|
24
|
-
type InclusionMode = "full" | "preview";
|
|
24
|
+
type InclusionMode = "full" | "preview" | "signatures";
|
|
25
25
|
interface SourceSummary {
|
|
26
26
|
directives: string[];
|
|
27
27
|
imports: string[];
|
|
@@ -88,7 +88,15 @@ type SkipReason = "binary" | "read-error" | "not-file"
|
|
|
88
88
|
* expected — which used to be recorded as the generic `not-file`, implying the path was a
|
|
89
89
|
* socket or a FIFO rather than a repository whose contents are simply somebody else's.
|
|
90
90
|
*/
|
|
91
|
-
| "nested-repository"
|
|
91
|
+
| "nested-repository"
|
|
92
|
+
/**
|
|
93
|
+
* Not in the set that `--changed-since` or `--staged` asked for.
|
|
94
|
+
*
|
|
95
|
+
* Deliberately distinct from `excluded`, which means the user's own glob rejected the path.
|
|
96
|
+
* Here the file is perfectly includable and simply did not change; reporting it as
|
|
97
|
+
* `excluded` would send a reader looking for an exclude pattern they never wrote.
|
|
98
|
+
*/
|
|
99
|
+
| "unchanged";
|
|
92
100
|
interface SkipRecord {
|
|
93
101
|
/** Path as it may be shown in an artifact: secret spans are masked. */
|
|
94
102
|
path: string;
|
|
@@ -144,6 +152,23 @@ interface PartMetadata {
|
|
|
144
152
|
filename: string;
|
|
145
153
|
/** Exact UTF-8 byte length of the emitted part file. */
|
|
146
154
|
byteSize: number;
|
|
155
|
+
/**
|
|
156
|
+
* Estimated tokens in this part.
|
|
157
|
+
*
|
|
158
|
+
* `byteSize` answers "will this fit the byte budget"; this answers the question a caller
|
|
159
|
+
* actually has, which is "will this fit my context window". An estimate, and labelled as
|
|
160
|
+
* one: `estimateTokens` documents exactly what it counts.
|
|
161
|
+
*/
|
|
162
|
+
estimatedTokens: number;
|
|
163
|
+
/**
|
|
164
|
+
* The byte budget this part was partitioned against.
|
|
165
|
+
*
|
|
166
|
+
* With per-layer budgets a snapshot has several budgets at once, so "within budget"
|
|
167
|
+
* cannot be answered without knowing which one applied. Verification compared every
|
|
168
|
+
* part against the *largest* budget in the run, which passed a part that was over its
|
|
169
|
+
* own.
|
|
170
|
+
*/
|
|
171
|
+
budgetBytes: number;
|
|
147
172
|
sha256: string;
|
|
148
173
|
lines: number;
|
|
149
174
|
fileCount: number;
|
|
@@ -198,6 +223,14 @@ interface ManifestTotals {
|
|
|
198
223
|
skippedFiles: number;
|
|
199
224
|
totalSourceBytes: number;
|
|
200
225
|
totalContentBytes: number;
|
|
226
|
+
/**
|
|
227
|
+
* Estimated tokens in the emitted parts.
|
|
228
|
+
*
|
|
229
|
+
* Optional because a manifest written before this was recorded has no such key. The number
|
|
230
|
+
* is an estimate — see `estimateTokens` for the method — and it exists because the snapshot
|
|
231
|
+
* is pasted into a context window, which is measured in tokens rather than bytes.
|
|
232
|
+
*/
|
|
233
|
+
estimatedTokens?: number;
|
|
201
234
|
partCount: number;
|
|
202
235
|
warningCount: number;
|
|
203
236
|
/**
|
|
@@ -256,13 +289,34 @@ interface ManifestConfigSnapshot {
|
|
|
256
289
|
/** Digest of the effective settings; see `configDigest`. */
|
|
257
290
|
digest?: string;
|
|
258
291
|
maxPartBytes: number;
|
|
292
|
+
/**
|
|
293
|
+
* The token ceiling the run was given, or `undefined` when only bytes were named.
|
|
294
|
+
*
|
|
295
|
+
* Recorded so the manifest states the budget the user chose rather than only the byte
|
|
296
|
+
* value it was converted to.
|
|
297
|
+
*/
|
|
298
|
+
maxPartTokens?: number;
|
|
259
299
|
largeFileBytes: number;
|
|
260
300
|
previewHeadLines: number;
|
|
261
301
|
previewTailLines: number;
|
|
262
302
|
includeMonolith: boolean;
|
|
303
|
+
/**
|
|
304
|
+
* The ceiling above which the monolith is not written; `null` for no ceiling.
|
|
305
|
+
*
|
|
306
|
+
* Optional because a manifest written before this was recorded has no such key.
|
|
307
|
+
*/
|
|
308
|
+
maxMonolithBytes?: number | null;
|
|
263
309
|
includeSensitiveFiles: boolean;
|
|
264
310
|
/** How files were discovered; `undefined` on manifests written before this was recorded. */
|
|
265
311
|
discovery?: DiscoveryMode;
|
|
312
|
+
/** The changed-files scope the snapshot was taken over, when one was used. */
|
|
313
|
+
changedSince?: string;
|
|
314
|
+
staged?: boolean;
|
|
315
|
+
withDependents?: boolean;
|
|
316
|
+
/** True when bodies were replaced by signatures. */
|
|
317
|
+
skeleton?: boolean;
|
|
318
|
+
/** True when `reports/audit.sarif` was written. */
|
|
319
|
+
sarif?: boolean;
|
|
266
320
|
artifacts: ResolvedArtifacts;
|
|
267
321
|
include: string[];
|
|
268
322
|
preset: string;
|
|
@@ -315,6 +369,14 @@ interface Manifest {
|
|
|
315
369
|
artifacts: {
|
|
316
370
|
fullJson: ManifestArtifact | null;
|
|
317
371
|
fullMarkdown: ManifestArtifact | null;
|
|
372
|
+
/**
|
|
373
|
+
* `reports/audit.sarif`, when `--sarif` asked for it.
|
|
374
|
+
*
|
|
375
|
+
* Optional because most runs do not write one, and a manifest written before this
|
|
376
|
+
* existed has no such key at all — the two are indistinguishable to a reader, which is
|
|
377
|
+
* why the presence of the file is also recorded in `config`.
|
|
378
|
+
*/
|
|
379
|
+
sarif?: ManifestArtifact;
|
|
318
380
|
};
|
|
319
381
|
layers: Record<string, number>;
|
|
320
382
|
kinds: Record<string, number>;
|
|
@@ -382,6 +444,15 @@ interface SnapshotConfig {
|
|
|
382
444
|
tmpDir?: string;
|
|
383
445
|
/** Raw bytes, or a human-readable size (`"120k"`, `"1.5mb"`). */
|
|
384
446
|
maxPartBytes?: ByteSize;
|
|
447
|
+
/**
|
|
448
|
+
* A per-part ceiling in *tokens* rather than bytes.
|
|
449
|
+
*
|
|
450
|
+
* The snapshot is pasted into a context window, and a context window is measured in tokens;
|
|
451
|
+
* bytes are what the partitioner writes. Naming a token budget sets `maxPartBytes` to the
|
|
452
|
+
* byte count that corresponds to it, so the byte bound — the thing the partitioner actually
|
|
453
|
+
* enforces — never stops being true. The smaller of the two ceilings wins.
|
|
454
|
+
*/
|
|
455
|
+
maxPartTokens?: ByteSize;
|
|
385
456
|
largeFileBytes?: ByteSize;
|
|
386
457
|
previewHeadLines?: number;
|
|
387
458
|
previewTailLines?: number;
|
|
@@ -393,6 +464,31 @@ interface SnapshotConfig {
|
|
|
393
464
|
include?: string[];
|
|
394
465
|
/** Force a preset by name instead of auto-detecting one. */
|
|
395
466
|
preset?: string;
|
|
467
|
+
/**
|
|
468
|
+
* Only include files changed since this git ref.
|
|
469
|
+
*
|
|
470
|
+
* The pull-request case: the diff is small and the repository is not. Unchanged files are
|
|
471
|
+
* recorded in `skipped[]` with reason `unchanged`, so the manifest accounts for them.
|
|
472
|
+
*/
|
|
473
|
+
changedSince?: string;
|
|
474
|
+
/** Only include files staged for the next commit. */
|
|
475
|
+
staged?: boolean;
|
|
476
|
+
/**
|
|
477
|
+
* Emit signatures instead of bodies for TypeScript and TSX files.
|
|
478
|
+
*
|
|
479
|
+
* Matches `inclusionMode: "signatures"` on the entries it applies to, so a reader can tell a
|
|
480
|
+
* compressed file from a whole one without diffing it against the source.
|
|
481
|
+
*/
|
|
482
|
+
skeleton?: boolean;
|
|
483
|
+
/** Also write `reports/audit.sarif` so a CI security gate can read the findings. */
|
|
484
|
+
sarif?: boolean;
|
|
485
|
+
/**
|
|
486
|
+
* With `changedSince` or `staged`, also include the files that import a changed one.
|
|
487
|
+
*
|
|
488
|
+
* A one-hop closure: the file you changed and the files that reference it are the context
|
|
489
|
+
* needed to change it safely.
|
|
490
|
+
*/
|
|
491
|
+
withDependents?: boolean;
|
|
396
492
|
/** Switch individual snapshot artifacts off. Everything is on by default. */
|
|
397
493
|
artifacts?: ArtifactSelection;
|
|
398
494
|
/**
|
|
@@ -418,6 +514,8 @@ interface ResolvedSnapshotConfig {
|
|
|
418
514
|
outDir: string;
|
|
419
515
|
tmpDir: string;
|
|
420
516
|
maxPartBytes: number;
|
|
517
|
+
/** The token ceiling the user asked for, before it was turned into `maxPartBytes`. */
|
|
518
|
+
maxPartTokens?: number;
|
|
421
519
|
largeFileBytes: number;
|
|
422
520
|
previewHeadLines: number;
|
|
423
521
|
previewTailLines: number;
|
|
@@ -430,6 +528,21 @@ interface ResolvedSnapshotConfig {
|
|
|
430
528
|
* reader treats `undefined` as `auto`, so the effective mode is never guessed twice.
|
|
431
529
|
*/
|
|
432
530
|
discovery?: DiscoveryMode;
|
|
531
|
+
/** Only files changed since this git ref; `undefined` scans everything. */
|
|
532
|
+
changedSince?: string;
|
|
533
|
+
/** Only files staged for the next commit. */
|
|
534
|
+
staged?: boolean;
|
|
535
|
+
/** Emit signatures instead of bodies for TypeScript and TSX files. */
|
|
536
|
+
skeleton?: boolean;
|
|
537
|
+
/**
|
|
538
|
+
* Also write `reports/audit.sarif`, the findings in SARIF 2.1.0.
|
|
539
|
+
*
|
|
540
|
+
* For a CI security gate: GitHub Code Scanning reads SARIF, and a markdown report it cannot
|
|
541
|
+
* ingest is a finding nobody's build can act on.
|
|
542
|
+
*/
|
|
543
|
+
sarif?: boolean;
|
|
544
|
+
/** Also include the files that import a changed one. */
|
|
545
|
+
withDependents?: boolean;
|
|
433
546
|
/** Empty means "no allow-list"; every discovered file is a candidate. */
|
|
434
547
|
include: string[];
|
|
435
548
|
/** The preset that was resolved (detected or forced). */
|
|
@@ -21,7 +21,7 @@ type TextEncoding = "utf-8" | "utf-8-lossy" | "utf-16le" | "utf-16be";
|
|
|
21
21
|
* `full` – the complete file body was emitted.
|
|
22
22
|
* `preview` – the body was truncated (by lines and/or bytes) before emission.
|
|
23
23
|
*/
|
|
24
|
-
type InclusionMode = "full" | "preview";
|
|
24
|
+
type InclusionMode = "full" | "preview" | "signatures";
|
|
25
25
|
interface SourceSummary {
|
|
26
26
|
directives: string[];
|
|
27
27
|
imports: string[];
|
|
@@ -88,7 +88,15 @@ type SkipReason = "binary" | "read-error" | "not-file"
|
|
|
88
88
|
* expected — which used to be recorded as the generic `not-file`, implying the path was a
|
|
89
89
|
* socket or a FIFO rather than a repository whose contents are simply somebody else's.
|
|
90
90
|
*/
|
|
91
|
-
| "nested-repository"
|
|
91
|
+
| "nested-repository"
|
|
92
|
+
/**
|
|
93
|
+
* Not in the set that `--changed-since` or `--staged` asked for.
|
|
94
|
+
*
|
|
95
|
+
* Deliberately distinct from `excluded`, which means the user's own glob rejected the path.
|
|
96
|
+
* Here the file is perfectly includable and simply did not change; reporting it as
|
|
97
|
+
* `excluded` would send a reader looking for an exclude pattern they never wrote.
|
|
98
|
+
*/
|
|
99
|
+
| "unchanged";
|
|
92
100
|
interface SkipRecord {
|
|
93
101
|
/** Path as it may be shown in an artifact: secret spans are masked. */
|
|
94
102
|
path: string;
|
|
@@ -144,6 +152,23 @@ interface PartMetadata {
|
|
|
144
152
|
filename: string;
|
|
145
153
|
/** Exact UTF-8 byte length of the emitted part file. */
|
|
146
154
|
byteSize: number;
|
|
155
|
+
/**
|
|
156
|
+
* Estimated tokens in this part.
|
|
157
|
+
*
|
|
158
|
+
* `byteSize` answers "will this fit the byte budget"; this answers the question a caller
|
|
159
|
+
* actually has, which is "will this fit my context window". An estimate, and labelled as
|
|
160
|
+
* one: `estimateTokens` documents exactly what it counts.
|
|
161
|
+
*/
|
|
162
|
+
estimatedTokens: number;
|
|
163
|
+
/**
|
|
164
|
+
* The byte budget this part was partitioned against.
|
|
165
|
+
*
|
|
166
|
+
* With per-layer budgets a snapshot has several budgets at once, so "within budget"
|
|
167
|
+
* cannot be answered without knowing which one applied. Verification compared every
|
|
168
|
+
* part against the *largest* budget in the run, which passed a part that was over its
|
|
169
|
+
* own.
|
|
170
|
+
*/
|
|
171
|
+
budgetBytes: number;
|
|
147
172
|
sha256: string;
|
|
148
173
|
lines: number;
|
|
149
174
|
fileCount: number;
|
|
@@ -198,6 +223,14 @@ interface ManifestTotals {
|
|
|
198
223
|
skippedFiles: number;
|
|
199
224
|
totalSourceBytes: number;
|
|
200
225
|
totalContentBytes: number;
|
|
226
|
+
/**
|
|
227
|
+
* Estimated tokens in the emitted parts.
|
|
228
|
+
*
|
|
229
|
+
* Optional because a manifest written before this was recorded has no such key. The number
|
|
230
|
+
* is an estimate — see `estimateTokens` for the method — and it exists because the snapshot
|
|
231
|
+
* is pasted into a context window, which is measured in tokens rather than bytes.
|
|
232
|
+
*/
|
|
233
|
+
estimatedTokens?: number;
|
|
201
234
|
partCount: number;
|
|
202
235
|
warningCount: number;
|
|
203
236
|
/**
|
|
@@ -256,13 +289,34 @@ interface ManifestConfigSnapshot {
|
|
|
256
289
|
/** Digest of the effective settings; see `configDigest`. */
|
|
257
290
|
digest?: string;
|
|
258
291
|
maxPartBytes: number;
|
|
292
|
+
/**
|
|
293
|
+
* The token ceiling the run was given, or `undefined` when only bytes were named.
|
|
294
|
+
*
|
|
295
|
+
* Recorded so the manifest states the budget the user chose rather than only the byte
|
|
296
|
+
* value it was converted to.
|
|
297
|
+
*/
|
|
298
|
+
maxPartTokens?: number;
|
|
259
299
|
largeFileBytes: number;
|
|
260
300
|
previewHeadLines: number;
|
|
261
301
|
previewTailLines: number;
|
|
262
302
|
includeMonolith: boolean;
|
|
303
|
+
/**
|
|
304
|
+
* The ceiling above which the monolith is not written; `null` for no ceiling.
|
|
305
|
+
*
|
|
306
|
+
* Optional because a manifest written before this was recorded has no such key.
|
|
307
|
+
*/
|
|
308
|
+
maxMonolithBytes?: number | null;
|
|
263
309
|
includeSensitiveFiles: boolean;
|
|
264
310
|
/** How files were discovered; `undefined` on manifests written before this was recorded. */
|
|
265
311
|
discovery?: DiscoveryMode;
|
|
312
|
+
/** The changed-files scope the snapshot was taken over, when one was used. */
|
|
313
|
+
changedSince?: string;
|
|
314
|
+
staged?: boolean;
|
|
315
|
+
withDependents?: boolean;
|
|
316
|
+
/** True when bodies were replaced by signatures. */
|
|
317
|
+
skeleton?: boolean;
|
|
318
|
+
/** True when `reports/audit.sarif` was written. */
|
|
319
|
+
sarif?: boolean;
|
|
266
320
|
artifacts: ResolvedArtifacts;
|
|
267
321
|
include: string[];
|
|
268
322
|
preset: string;
|
|
@@ -315,6 +369,14 @@ interface Manifest {
|
|
|
315
369
|
artifacts: {
|
|
316
370
|
fullJson: ManifestArtifact | null;
|
|
317
371
|
fullMarkdown: ManifestArtifact | null;
|
|
372
|
+
/**
|
|
373
|
+
* `reports/audit.sarif`, when `--sarif` asked for it.
|
|
374
|
+
*
|
|
375
|
+
* Optional because most runs do not write one, and a manifest written before this
|
|
376
|
+
* existed has no such key at all — the two are indistinguishable to a reader, which is
|
|
377
|
+
* why the presence of the file is also recorded in `config`.
|
|
378
|
+
*/
|
|
379
|
+
sarif?: ManifestArtifact;
|
|
318
380
|
};
|
|
319
381
|
layers: Record<string, number>;
|
|
320
382
|
kinds: Record<string, number>;
|
|
@@ -382,6 +444,15 @@ interface SnapshotConfig {
|
|
|
382
444
|
tmpDir?: string;
|
|
383
445
|
/** Raw bytes, or a human-readable size (`"120k"`, `"1.5mb"`). */
|
|
384
446
|
maxPartBytes?: ByteSize;
|
|
447
|
+
/**
|
|
448
|
+
* A per-part ceiling in *tokens* rather than bytes.
|
|
449
|
+
*
|
|
450
|
+
* The snapshot is pasted into a context window, and a context window is measured in tokens;
|
|
451
|
+
* bytes are what the partitioner writes. Naming a token budget sets `maxPartBytes` to the
|
|
452
|
+
* byte count that corresponds to it, so the byte bound — the thing the partitioner actually
|
|
453
|
+
* enforces — never stops being true. The smaller of the two ceilings wins.
|
|
454
|
+
*/
|
|
455
|
+
maxPartTokens?: ByteSize;
|
|
385
456
|
largeFileBytes?: ByteSize;
|
|
386
457
|
previewHeadLines?: number;
|
|
387
458
|
previewTailLines?: number;
|
|
@@ -393,6 +464,31 @@ interface SnapshotConfig {
|
|
|
393
464
|
include?: string[];
|
|
394
465
|
/** Force a preset by name instead of auto-detecting one. */
|
|
395
466
|
preset?: string;
|
|
467
|
+
/**
|
|
468
|
+
* Only include files changed since this git ref.
|
|
469
|
+
*
|
|
470
|
+
* The pull-request case: the diff is small and the repository is not. Unchanged files are
|
|
471
|
+
* recorded in `skipped[]` with reason `unchanged`, so the manifest accounts for them.
|
|
472
|
+
*/
|
|
473
|
+
changedSince?: string;
|
|
474
|
+
/** Only include files staged for the next commit. */
|
|
475
|
+
staged?: boolean;
|
|
476
|
+
/**
|
|
477
|
+
* Emit signatures instead of bodies for TypeScript and TSX files.
|
|
478
|
+
*
|
|
479
|
+
* Matches `inclusionMode: "signatures"` on the entries it applies to, so a reader can tell a
|
|
480
|
+
* compressed file from a whole one without diffing it against the source.
|
|
481
|
+
*/
|
|
482
|
+
skeleton?: boolean;
|
|
483
|
+
/** Also write `reports/audit.sarif` so a CI security gate can read the findings. */
|
|
484
|
+
sarif?: boolean;
|
|
485
|
+
/**
|
|
486
|
+
* With `changedSince` or `staged`, also include the files that import a changed one.
|
|
487
|
+
*
|
|
488
|
+
* A one-hop closure: the file you changed and the files that reference it are the context
|
|
489
|
+
* needed to change it safely.
|
|
490
|
+
*/
|
|
491
|
+
withDependents?: boolean;
|
|
396
492
|
/** Switch individual snapshot artifacts off. Everything is on by default. */
|
|
397
493
|
artifacts?: ArtifactSelection;
|
|
398
494
|
/**
|
|
@@ -418,6 +514,8 @@ interface ResolvedSnapshotConfig {
|
|
|
418
514
|
outDir: string;
|
|
419
515
|
tmpDir: string;
|
|
420
516
|
maxPartBytes: number;
|
|
517
|
+
/** The token ceiling the user asked for, before it was turned into `maxPartBytes`. */
|
|
518
|
+
maxPartTokens?: number;
|
|
421
519
|
largeFileBytes: number;
|
|
422
520
|
previewHeadLines: number;
|
|
423
521
|
previewTailLines: number;
|
|
@@ -430,6 +528,21 @@ interface ResolvedSnapshotConfig {
|
|
|
430
528
|
* reader treats `undefined` as `auto`, so the effective mode is never guessed twice.
|
|
431
529
|
*/
|
|
432
530
|
discovery?: DiscoveryMode;
|
|
531
|
+
/** Only files changed since this git ref; `undefined` scans everything. */
|
|
532
|
+
changedSince?: string;
|
|
533
|
+
/** Only files staged for the next commit. */
|
|
534
|
+
staged?: boolean;
|
|
535
|
+
/** Emit signatures instead of bodies for TypeScript and TSX files. */
|
|
536
|
+
skeleton?: boolean;
|
|
537
|
+
/**
|
|
538
|
+
* Also write `reports/audit.sarif`, the findings in SARIF 2.1.0.
|
|
539
|
+
*
|
|
540
|
+
* For a CI security gate: GitHub Code Scanning reads SARIF, and a markdown report it cannot
|
|
541
|
+
* ingest is a finding nobody's build can act on.
|
|
542
|
+
*/
|
|
543
|
+
sarif?: boolean;
|
|
544
|
+
/** Also include the files that import a changed one. */
|
|
545
|
+
withDependents?: boolean;
|
|
433
546
|
/** Empty means "no allow-list"; every discovered file is a candidate. */
|
|
434
547
|
include: string[];
|
|
435
548
|
/** The preset that was resolved (detected or forced). */
|
package/docs/agent.md
CHANGED
|
@@ -115,7 +115,7 @@ devDependency and the `.gitignore` entries for the snapshot directory, and nothi
|
|
|
115
115
|
|
|
116
116
|
## When the client speaks MCP
|
|
117
117
|
|
|
118
|
-
`codebase-snapshot mcp` serves the repository to a Model Context Protocol client over stdio:
|
|
118
|
+
`codebase-snapshot mcp` serves the repository to a Model Context Protocol client over stdio: eight
|
|
119
119
|
tools, `snapshot://` resources and two prompts. Prefer it over shelling out when the agent already
|
|
120
120
|
has an MCP connection, for two reasons that are properties of the design rather than of the wiring:
|
|
121
121
|
|
package/docs/cli.md
CHANGED
|
@@ -174,7 +174,7 @@ The whole first run in one command, with defaults and no prompts. This is the sa
|
|
|
174
174
|
🚀 Setup for: /path/to/repo
|
|
175
175
|
✅ Created snapshot.config.ts (preset: nextjs)
|
|
176
176
|
Added npm scripts: snapshot, snapshot:validate
|
|
177
|
-
Added devDependency: codebase-snapshot ^0.9.
|
|
177
|
+
Added devDependency: codebase-snapshot ^0.9.12
|
|
178
178
|
Added to .gitignore: snapshot/, snapshot.tmp/
|
|
179
179
|
⏳ Installing dependencies…
|
|
180
180
|
✅ Installed dependencies (npm install, 2.1s)
|
|
@@ -211,7 +211,7 @@ It also has three side effects on files you own, and it says so when it does the
|
|
|
211
211
|
```
|
|
212
212
|
✅ Created snapshot.config.ts (preset: node-lib)
|
|
213
213
|
Added npm scripts: snapshot, snapshot:validate
|
|
214
|
-
Added devDependency: codebase-snapshot ^0.9.
|
|
214
|
+
Added devDependency: codebase-snapshot ^0.9.12
|
|
215
215
|
Added to .gitignore: snapshot/, snapshot.tmp/
|
|
216
216
|
```
|
|
217
217
|
|
|
@@ -378,7 +378,7 @@ codebase-snapshot mcp # serve the current directory over stdio
|
|
|
378
378
|
codebase-snapshot mcp --cwd <path> # serve another repository
|
|
379
379
|
```
|
|
380
380
|
|
|
381
|
-
Serves the repository to a Model Context Protocol client over stdio:
|
|
381
|
+
Serves the repository to a Model Context Protocol client over stdio: eight tools, `snapshot://`
|
|
382
382
|
resources and two prompts. Stdout carries JSON-RPC messages and nothing else; every note goes to
|
|
383
383
|
stderr. It speaks both protocol eras — the legacy `initialize` handshake and the stateless
|
|
384
384
|
`2026-07-28` revision — and answers whichever the client starts with.
|
|
@@ -401,6 +401,7 @@ narrowest cases of the same rule.
|
|
|
401
401
|
| `--cwd <path>` | path | current directory | generate, validate, report, explain, init, skill | Repository to operate on. Must exist and be a directory. `diff` and `describe` take no `--cwd`. |
|
|
402
402
|
| `--out-dir <path>` | path | `snapshot` | generate, validate, report, explain, init | Where the snapshot is written or read. May be absolute. |
|
|
403
403
|
| `--max-part-bytes <n>` | size | `307200` (300 KB) | generate, validate, report, explain, init | Hard ceiling per markdown part. Accepts `120k`, `1.5mb`. Minimum 4096. |
|
|
404
|
+
| `--max-part-tokens <n>` | size | unset | generate, validate, setup | A per-part ceiling in **tokens**, for a context window rather than a disk. Narrows `--max-part-bytes` to the equivalent byte count (`tokens × 4`); the smaller of the two ceilings always wins, and both are recorded in the manifest. Accepts `32k`. Minimum 1024 — below that it is a usage error, not a value quietly raised to the floor. |
|
|
404
405
|
| `--large-file-bytes <n>` | size | `204800` (200 KB) | generate, validate, report, explain | Above this, a file becomes a head/tail preview. |
|
|
405
406
|
| `--max-monolith-bytes <n>` | size | unset | generate, validate, report, explain | Skip the single-file monolith when it would exceed this. |
|
|
406
407
|
| `--include-monolith` | flag | off | generate, validate, report, explain | Also write `full-codebase.json` and `full-codebase.md`. |
|
|
@@ -408,6 +409,12 @@ narrowest cases of the same rule.
|
|
|
408
409
|
| `--skip-artifacts <names>` | list | unset | generate, validate, report, explain, init | Comma-separated artifacts to omit. |
|
|
409
410
|
| `--only-artifacts <names>` | list | unset | generate, validate, report, explain, init | Write only these. Cannot be combined with `--skip-artifacts`. |
|
|
410
411
|
| `--format <text\|json>` | enum | `text` | generate, validate, report, explain, init, setup, diff, describe, skill | `json` writes a pure JSON payload to stdout. Every command honours it, and `describe` reports the same nine-command list. |
|
|
412
|
+
| `--sarif` | flag | off | generate, validate, setup | Also write `reports/audit.sarif`: the redaction findings as SARIF 2.1.0, for upload to GitHub Code Scanning. The artefact carries the path, the line and the rule — never the value. Works with `--skip-artifacts audit`, because a CI gate does not read markdown. Rule ids are fixed per rule name, so adding a custom rule never re-points an existing alert. |
|
|
413
|
+
| `--skeleton` | flag | off | generate, validate, setup | Emit TypeScript and TSX signatures instead of bodies: each function or method body becomes `{ /* ... */ }` in place, so formatting and comments around it are untouched. The summary still describes the whole file, and affected entries carry `inclusionMode: "signatures"`. `--include-monolith` still writes the whole body, so the monolith's `inclusionMode: "full"` stays true. |
|
|
414
|
+
| `--changed-since <ref>` | git ref | unset | generate, validate, explain | Include only files changed since this ref, plus untracked ones. Every other file is recorded in `manifest.skipped[]` with reason `unchanged` and is never opened. `validate` re-resolves the scope: a skipped file that has changed since is reported as drift, and one that has not is left alone — and with `--with-dependents`, so is a file that now imports one that changed. `explain` answers with the same rule. A ref beginning with `-` is refused. |
|
|
415
|
+
| `--staged` | flag | off | generate, validate, explain | Include only files staged for the next commit. |
|
|
416
|
+
| `--with-dependents` | flag | off | generate, validate, explain | With either of the two above, also include the files that import a changed one — a one-hop closure, not a transitive walk. Needs a scope; alone it is a usage error. |
|
|
417
|
+
| `--install-hook` | flag | off | init, setup | Write `.git/hooks/pre-commit` so a commit is refused while the snapshot is out of date. The hook checks the `outDir` the config names, so it works for a project that does not use `snapshot/`. An existing hook is never replaced; the note says what to add to it instead. |
|
|
411
418
|
| `--dry-run` | flag | off | generate, init, setup | Compute everything, print it, write nothing. |
|
|
412
419
|
| `--watch` | flag | off | generate | Regenerate on every change until interrupted. |
|
|
413
420
|
| `--autopilot` | flag | off | generate | Set the project up without asking — config, `.gitignore`, npm scripts, devDependency, install — then generate. Never overwrites an existing config; refuses an empty directory (exit `1`); contradicts `--no-config` (exit `2`). |
|
|
@@ -430,6 +437,17 @@ with and the comparison is like for like. `validate --skip-artifacts parts` on a
|
|
|
430
437
|
built without parts therefore agrees, while the same flag on a full snapshot reports a
|
|
431
438
|
config mismatch.
|
|
432
439
|
|
|
440
|
+
The same rule applies to the compression and scope options. `--skeleton`, `--sarif` and
|
|
441
|
+
`--max-part-tokens` are recorded in `manifest.config.digest`, so `validate` accepts them too —
|
|
442
|
+
without that, a snapshot generated with `--skeleton` could not be validated at all, and passing
|
|
443
|
+
the flag to `validate` was rejected as a flag that "does not apply to validate". `--changed-since`,
|
|
444
|
+
`--staged` and `--with-dependents` are accepted by `validate` and `explain` because they decide
|
|
445
|
+
which recorded `unchanged` skips are re-checked and what `explain` answers about one file.
|
|
446
|
+
|
|
447
|
+
`report` does not take any of them: it reads the manifest and prints what is there, so a
|
|
448
|
+
generation setting would change nothing. A flag that parses and does nothing is the silent
|
|
449
|
+
fallback this table exists to prevent.
|
|
450
|
+
|
|
433
451
|
Every option also accepts the `--option=value` form. That form is required for negative
|
|
434
452
|
numbers, which otherwise look like flags.
|
|
435
453
|
|