codebase-snapshot 0.9.12 → 0.9.14

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/cli.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { O as OutputFormat, D as DiscoveryMode, R as ResolvedSnapshotConfig } from './types-CTewen3J.cjs';
1
+ import { O as OutputFormat, D as DiscoveryMode, R as ResolvedSnapshotConfig } from './types-DIX6zWSt.cjs';
2
2
 
3
3
  /**
4
4
  * The machine-readable description of this tool.
package/dist/cli.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { O as OutputFormat, D as DiscoveryMode, R as ResolvedSnapshotConfig } from './types-CTewen3J.js';
1
+ import { O as OutputFormat, D as DiscoveryMode, R as ResolvedSnapshotConfig } from './types-DIX6zWSt.js';
2
2
 
3
3
  /**
4
4
  * The machine-readable description of this tool.
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
- import { buildAgentContract, runStdioServer, COMMAND_OPTION_SCOPE, commandsForOption, SKILL_NAME, renderSkill, renderContractText } from './chunk-5OR3WVPW.js';
2
- export { buildAgentContract } from './chunk-5OR3WVPW.js';
3
- import { shouldCheck, checkForUpdate, GENERATOR_VERSION, cacheFilePath, formatUpdateNotice, installKind, loadConfigFileDetailed, resolveConfig, validateSnapshot, describeManifestShapeProblem, explainPath, compareManifests, loadManifest, renderDiffText, generateSnapshot, formatNumber, isDiscoveryMode, ARTIFACT_NAMES, getPreset, unknownPresetMessage, GENERATOR_NAME, runInit, installPreCommitHook, PromptCancelled, planFirstRun, isEffectivelyEmpty, isInteractive, defaultIO, hasPriorSnapshot, DEFAULT_ANSWERS, findConfigFile, firstRunMessage, parseByteSize, gitignorePath, appendGitignoreEntries, escapeControls, MIN_MAX_PART_TOKENS, MIN_MAX_PART_BYTES, renderExplainText } from './chunk-3H45YMBG.js';
1
+ import { buildAgentContract, runStdioServer, COMMAND_OPTION_SCOPE, commandsForOption, SKILL_NAME, renderSkill, renderContractText } from './chunk-J4W74N4Y.js';
2
+ export { buildAgentContract } from './chunk-J4W74N4Y.js';
3
+ import { shouldCheck, checkForUpdate, GENERATOR_VERSION, cacheFilePath, formatUpdateNotice, installKind, loadConfigFileDetailed, resolveConfig, validateSnapshot, describeManifestShapeProblem, explainPath, compareManifests, loadManifest, renderDiffText, generateSnapshot, formatNumber, isDiscoveryMode, ARTIFACT_NAMES, getPreset, unknownPresetMessage, GENERATOR_NAME, runInit, installPreCommitHook, PromptCancelled, planFirstRun, isEffectivelyEmpty, isInteractive, defaultIO, hasPriorSnapshot, DEFAULT_ANSWERS, findConfigFile, firstRunMessage, parseByteSize, stripJsonComments, gitignorePath, appendGitignoreEntries, runWithStdoutCapture, escapeControls, MIN_MAX_PART_TOKENS, MIN_MAX_PART_BYTES, renderExplainText } from './chunk-DUZK5VL2.js';
4
4
  import { spawnSync } from 'child_process';
5
5
  import * as fs from 'fs';
6
6
  import * as path2 from 'path';
@@ -576,7 +576,9 @@ function nextStepHint(cwd, scriptsAddedNow) {
576
576
  let hasScript = scriptsAddedNow;
577
577
  if (!hasScript) {
578
578
  try {
579
- const parsed = JSON.parse(fs.readFileSync(path2.join(cwd, "package.json"), "utf8"));
579
+ const parsed = JSON.parse(
580
+ stripJsonComments(fs.readFileSync(path2.join(cwd, "package.json"), "utf8"))
581
+ );
580
582
  hasScript = typeof parsed.scripts?.snapshot === "string";
581
583
  } catch {
582
584
  hasScript = false;
@@ -678,18 +680,8 @@ function installDependencies(cwd) {
678
680
  return { manager: manager.name, command, ok: true, detail: seconds };
679
681
  }
680
682
  async function captureStdout(fn) {
681
- const original = process.stdout.write.bind(process.stdout);
682
- let text = "";
683
- process.stdout.write = ((chunk) => {
684
- text += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
685
- return true;
686
- });
687
- try {
688
- const code = await fn();
689
- return { code, text };
690
- } finally {
691
- process.stdout.write = original;
692
- }
683
+ const { value, text } = await runWithStdoutCapture(fn);
684
+ return { code: value, text };
693
685
  }
694
686
  async function runSetupCommand(invocation, options = {}) {
695
687
  try {
@@ -804,31 +796,33 @@ async function runSetupCommand(invocation, options = {}) {
804
796
  if (invocation.watch) generateArgs.push("--watch");
805
797
  if (invocation.format === "json") {
806
798
  const generated = await captureStdout(() => main(generateArgs));
807
- let manifest = null;
799
+ let parsed = null;
808
800
  try {
809
- manifest = JSON.parse(generated.text);
801
+ parsed = JSON.parse(generated.text);
810
802
  } catch {
811
- manifest = null;
803
+ parsed = null;
804
+ }
805
+ const setup = {
806
+ configPath: init.configPath,
807
+ configReused: init.reused,
808
+ preset: init.preset,
809
+ scripts: init.scripts,
810
+ dependency: init.dependency,
811
+ gitignoreEntries: init.gitignoreEntries,
812
+ install,
813
+ notes: init.notes,
814
+ hook
815
+ };
816
+ if (generated.code !== 0) {
817
+ const inner = parsed && typeof parsed.error === "object" && parsed.error !== null ? parsed.error : { message: "Snapshot generation failed during setup.", exitCode: generated.code };
818
+ process.stdout.write(
819
+ `${JSON.stringify({ error: inner, setup, manifest: null }, null, 2)}
820
+ `
821
+ );
822
+ return generated.code;
812
823
  }
813
824
  process.stdout.write(
814
- `${JSON.stringify(
815
- {
816
- setup: {
817
- configPath: init.configPath,
818
- configReused: init.reused,
819
- preset: init.preset,
820
- scripts: init.scripts,
821
- dependency: init.dependency,
822
- gitignoreEntries: init.gitignoreEntries,
823
- install,
824
- notes: init.notes,
825
- hook
826
- },
827
- manifest
828
- },
829
- null,
830
- 2
831
- )}
825
+ `${JSON.stringify({ setup, manifest: parsed }, null, 2)}
832
826
  `
833
827
  );
834
828
  return generated.code;
@@ -1021,6 +1015,10 @@ ${USAGE}
1021
1015
  largeFileBytes: invocation.largeFileBytes,
1022
1016
  maxMonolithBytes: invocation.maxMonolithBytes,
1023
1017
  skipArtifacts: invocation.skipArtifacts,
1018
+ // `--only-artifacts` is forwarded as itself, not only as the derived suppression list:
1019
+ // suppression cannot switch an artifact *on*, so a config that had turned one of the
1020
+ // requested artifacts off left the run with nothing to write.
1021
+ onlyArtifacts: invocation.onlyArtifacts,
1024
1022
  discovery: invocation.discovery,
1025
1023
  changedSince: invocation.changedSince,
1026
1024
  staged: invocation.staged,
@@ -1032,19 +1030,6 @@ ${USAGE}
1032
1030
  );
1033
1031
  if (invocation.command === "validate") {
1034
1032
  const result = validateSnapshot(resolved);
1035
- if (result.valid) {
1036
- const manifestPath = path2.resolve(resolved.cwd, resolved.outDir, "manifest.json");
1037
- let manifest;
1038
- try {
1039
- manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
1040
- } catch {
1041
- manifest = void 0;
1042
- }
1043
- const shapeError = manifest === void 0 ? null : describeManifestShapeProblem(manifest);
1044
- if (shapeError) {
1045
- return fail(invocation.format, `${manifestPath} is not a snapshot manifest: ${shapeError}`);
1046
- }
1047
- }
1048
1033
  emit(invocation.format, result, () => renderValidateText(result));
1049
1034
  return result.valid ? 0 : 1;
1050
1035
  }
@@ -1239,10 +1224,13 @@ function isGeneratedWatchPath(candidate, paths) {
1239
1224
  const outDir = comparablePath(path2.resolve(paths.cwd, paths.outDir));
1240
1225
  const tmpDir = comparablePath(path2.resolve(paths.cwd, paths.tmpDir));
1241
1226
  if (isSameOrInside(outDir, absolute) || isSameOrInside(tmpDir, absolute)) return true;
1242
- const parent = path2.dirname(absolute);
1243
- if (parent === path2.dirname(outDir) && path2.basename(absolute).startsWith(`${path2.basename(outDir)}.backup-`)) {
1244
- return true;
1245
- }
1227
+ const offsets = [path2.basename(outDir), path2.basename(tmpDir)].filter((name) => name.length > 0);
1228
+ const leftover = absolute.split(/[\\/]+/).some(
1229
+ (segment) => offsets.some(
1230
+ (name) => segment.startsWith(`${name}.backup-`) || segment.startsWith(`${name}.partial-`)
1231
+ )
1232
+ );
1233
+ if (leftover) return true;
1246
1234
  return absolute.split(/[\\/]+/).some((segment) => VCS_SEGMENTS.has(segment));
1247
1235
  }
1248
1236
  function decideWatchEvent(state, event, paths) {
@@ -1317,6 +1305,7 @@ async function runWatchLoop(invocation, resolved, options) {
1317
1305
  largeFileBytes: invocation.largeFileBytes,
1318
1306
  maxMonolithBytes: invocation.maxMonolithBytes,
1319
1307
  skipArtifacts: invocation.skipArtifacts,
1308
+ onlyArtifacts: invocation.onlyArtifacts,
1320
1309
  discovery: invocation.discovery,
1321
1310
  changedSince: invocation.changedSince,
1322
1311
  staged: invocation.staged,
@@ -1,3 +1,23 @@
1
+ /** The options `resolveConfig` was called with, as the CLI would have passed them. */
2
+ interface WorkspaceCliOptions {
3
+ cwd: string;
4
+ maxPartBytes?: number;
5
+ maxPartTokens?: number;
6
+ outDir?: string;
7
+ /**
8
+ * `true` or absent, never `false`.
9
+ *
10
+ * `resolveConfig` reads these as `cliOptions.x ?? config.x`, so a `false` here is an *explicit
11
+ * override* that beats `skeleton: true` in the project's configuration — the same trap the CLI
12
+ * documents. Absent means "whatever the configuration says".
13
+ */
14
+ skeleton?: true;
15
+ sarif?: true;
16
+ staged?: true;
17
+ withDependents?: true;
18
+ changedSince?: string;
19
+ }
20
+
1
21
  /** What the caller needs from a finished run; the whole manifest can be megabytes. */
2
22
  interface GenerateSummary {
3
23
  fingerprint: string;
@@ -48,10 +68,6 @@ declare function workerEntry(directory: string, isCjs: boolean): {
48
68
  * as a tool failure naming the reason — never silently retried on the calling thread, because a
49
69
  * quiet fallback would hide exactly the condition this exists to avoid.
50
70
  */
51
- declare function generateInWorker(cwd: string, cliOptions: {
52
- cwd: string;
53
- maxPartBytes?: number;
54
- outDir?: string;
55
- }): Promise<WorkerResults>;
71
+ declare function generateInWorker(cwd: string, cliOptions: WorkspaceCliOptions): Promise<WorkerResults>;
56
72
 
57
73
  export { type GenerateSummary as G, type WorkerResults as W, generateInWorker as g, workerEntry as w };
@@ -1,3 +1,23 @@
1
+ /** The options `resolveConfig` was called with, as the CLI would have passed them. */
2
+ interface WorkspaceCliOptions {
3
+ cwd: string;
4
+ maxPartBytes?: number;
5
+ maxPartTokens?: number;
6
+ outDir?: string;
7
+ /**
8
+ * `true` or absent, never `false`.
9
+ *
10
+ * `resolveConfig` reads these as `cliOptions.x ?? config.x`, so a `false` here is an *explicit
11
+ * override* that beats `skeleton: true` in the project's configuration — the same trap the CLI
12
+ * documents. Absent means "whatever the configuration says".
13
+ */
14
+ skeleton?: true;
15
+ sarif?: true;
16
+ staged?: true;
17
+ withDependents?: true;
18
+ changedSince?: string;
19
+ }
20
+
1
21
  /** What the caller needs from a finished run; the whole manifest can be megabytes. */
2
22
  interface GenerateSummary {
3
23
  fingerprint: string;
@@ -48,10 +68,6 @@ declare function workerEntry(directory: string, isCjs: boolean): {
48
68
  * as a tool failure naming the reason — never silently retried on the calling thread, because a
49
69
  * quiet fallback would hide exactly the condition this exists to avoid.
50
70
  */
51
- declare function generateInWorker(cwd: string, cliOptions: {
52
- cwd: string;
53
- maxPartBytes?: number;
54
- outDir?: string;
55
- }): Promise<WorkerResults>;
71
+ declare function generateInWorker(cwd: string, cliOptions: WorkspaceCliOptions): Promise<WorkerResults>;
56
72
 
57
73
  export { type GenerateSummary as G, type WorkerResults as W, generateInWorker as g, workerEntry as w };