codebase-snapshot 0.9.4 → 0.9.5

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.cjs CHANGED
@@ -4338,7 +4338,7 @@ function gitignorePath(cwd, filePath) {
4338
4338
 
4339
4339
  // src/version.ts
4340
4340
  var GENERATOR_NAME = "codebase-snapshot";
4341
- var GENERATOR_VERSION = "0.9.4";
4341
+ var GENERATOR_VERSION = "0.9.5";
4342
4342
  var LEGACY_GENERATOR_NAMES = ["@ankurhalder/codebase-snapshot"];
4343
4343
  function isOurGeneratorName(name) {
4344
4344
  if (typeof name !== "string") return false;
@@ -4472,6 +4472,12 @@ var PromptCancelled = class extends Error {
4472
4472
  this.name = "PromptCancelled";
4473
4473
  }
4474
4474
  };
4475
+ var PromptBack = class extends Error {
4476
+ constructor() {
4477
+ super("Prompt back");
4478
+ this.name = "PromptBack";
4479
+ }
4480
+ };
4475
4481
  function defaultIO() {
4476
4482
  return { input: process.stdin, output: process.stdout };
4477
4483
  }
@@ -4495,35 +4501,40 @@ function choiceLine(choice, active) {
4495
4501
  const hint = choice.hint ? ` ${choice.hint}` : "";
4496
4502
  return ` ${marker(active)} ${choice.label}${hint}`;
4497
4503
  }
4498
- function renderSelect(message, choices, index) {
4504
+ function listFooter(base, allowBack) {
4505
+ return allowBack ? `${base} \xB7 \u2190 back` : base;
4506
+ }
4507
+ function renderSelect(message, choices, index, allowBack = false) {
4499
4508
  const lines = [`\u25C6 ${message}`, ""];
4500
4509
  choices.forEach((choice, position) => lines.push(choiceLine(choice, position === index)));
4501
- lines.push("", " \u2191\u2193 move \xB7 enter select");
4510
+ lines.push("", ` ${listFooter("\u2191\u2193 move \xB7 enter select", allowBack)}`);
4502
4511
  return lines.join("\n");
4503
4512
  }
4504
- function renderMultiSelect(message, choices, index, selected) {
4513
+ function renderMultiSelect(message, choices, index, selected, allowBack = false) {
4505
4514
  const lines = [`\u25C6 ${message}`, ""];
4506
4515
  choices.forEach((choice, position) => {
4507
4516
  const box = selected.has(position) ? "\u25FC" : "\u25FB";
4508
4517
  const hint = choice.hint ? ` ${choice.hint}` : "";
4509
4518
  lines.push(` ${marker(position === index)} ${box} ${choice.label}${hint}`);
4510
4519
  });
4511
- lines.push("", " \u2191\u2193 move \xB7 space toggle \xB7 enter confirm");
4520
+ lines.push("", ` ${listFooter("\u2191\u2193 move \xB7 space toggle \xB7 enter confirm", allowBack)}`);
4512
4521
  return lines.join("\n");
4513
4522
  }
4514
- function renderConfirm(message, value) {
4523
+ function renderConfirm(message, value, allowBack = false) {
4524
+ const footer = allowBack ? "\u2190\u2192 or y/n \xB7 enter confirm \xB7 b back" : "\u2190\u2192 or y/n \xB7 enter confirm";
4515
4525
  return [
4516
4526
  `\u25C6 ${message}`,
4517
4527
  "",
4518
4528
  ` ${marker(value)} Yes`,
4519
4529
  ` ${marker(!value)} No`,
4520
4530
  "",
4521
- " \u2190\u2192 or y/n \xB7 enter confirm"
4531
+ ` ${footer}`
4522
4532
  ].join("\n");
4523
4533
  }
4524
- function renderText(message, value, error) {
4534
+ function renderText(message, value, error, allowBack = false) {
4525
4535
  const lines = [`\u25C6 ${message}`, "", ` ${value || "\u258F"}`];
4526
4536
  if (error) lines.push("", ` \u2716 ${error}`);
4537
+ if (allowBack) lines.push("", " enter confirm \xB7 \u2190 back");
4527
4538
  return lines.join("\n");
4528
4539
  }
4529
4540
  function keyReader(input) {
@@ -4572,14 +4583,18 @@ var Frame = class {
4572
4583
  function isCancel(key) {
4573
4584
  return key.ctrl === true && key.name === "c" || key.ctrl === true && key.name === "d";
4574
4585
  }
4586
+ function isListBack(key, allowBack) {
4587
+ return allowBack && (key.name === "left" || key.name === "b");
4588
+ }
4575
4589
  async function select(io, message, choices, options = {}) {
4576
4590
  if (choices.length === 0) throw new Error("select() requires at least one choice.");
4591
+ const allowBack = options.allowBack === true;
4577
4592
  const fallbackIndex = Math.max(
4578
4593
  0,
4579
4594
  choices.findIndex((choice) => choice.value === options.defaultValue)
4580
4595
  );
4581
4596
  if (!isInteractive(io)) {
4582
- io.output.write(`${renderSelect(message, choices, fallbackIndex)}
4597
+ io.output.write(`${renderSelect(message, choices, fallbackIndex, allowBack)}
4583
4598
  `);
4584
4599
  return choices[fallbackIndex].value;
4585
4600
  }
@@ -4588,9 +4603,10 @@ async function select(io, message, choices, options = {}) {
4588
4603
  let index = fallbackIndex;
4589
4604
  try {
4590
4605
  for (; ; ) {
4591
- frame.draw(renderSelect(message, choices, index));
4606
+ frame.draw(renderSelect(message, choices, index, allowBack));
4592
4607
  const key = await reader.next();
4593
4608
  if (isCancel(key)) throw new PromptCancelled();
4609
+ if (isListBack(key, allowBack)) throw new PromptBack();
4594
4610
  if (key.name === "up") index = moveSelection(index, -1, choices.length);
4595
4611
  else if (key.name === "down") index = moveSelection(index, 1, choices.length);
4596
4612
  else if (key.name === "return" || key.name === "enter") {
@@ -4599,18 +4615,22 @@ async function select(io, message, choices, options = {}) {
4599
4615
  } else if (key.name === "j") index = moveSelection(index, 1, choices.length);
4600
4616
  else if (key.name === "k") index = moveSelection(index, -1, choices.length);
4601
4617
  }
4618
+ } catch (error) {
4619
+ frame.erase();
4620
+ throw error;
4602
4621
  } finally {
4603
4622
  reader.close();
4604
4623
  }
4605
4624
  }
4606
4625
  async function multiSelect(io, message, choices, options = {}) {
4626
+ const allowBack = options.allowBack === true;
4607
4627
  const selected = /* @__PURE__ */ new Set();
4608
4628
  choices.forEach((choice, position) => {
4609
4629
  if (options.defaults?.includes(choice.value)) selected.add(position);
4610
4630
  });
4611
4631
  const result = () => choices.filter((_, position) => selected.has(position)).map((choice) => choice.value);
4612
4632
  if (!isInteractive(io)) {
4613
- io.output.write(`${renderMultiSelect(message, choices, 0, selected)}
4633
+ io.output.write(`${renderMultiSelect(message, choices, 0, selected, allowBack)}
4614
4634
  `);
4615
4635
  return result();
4616
4636
  }
@@ -4619,9 +4639,10 @@ async function multiSelect(io, message, choices, options = {}) {
4619
4639
  let index = 0;
4620
4640
  try {
4621
4641
  for (; ; ) {
4622
- frame.draw(renderMultiSelect(message, choices, index, selected));
4642
+ frame.draw(renderMultiSelect(message, choices, index, selected, allowBack));
4623
4643
  const key = await reader.next();
4624
4644
  if (isCancel(key)) throw new PromptCancelled();
4645
+ if (isListBack(key, allowBack)) throw new PromptBack();
4625
4646
  if (key.name === "up") index = moveSelection(index, -1, choices.length);
4626
4647
  else if (key.name === "down") index = moveSelection(index, 1, choices.length);
4627
4648
  else if (key.name === "space") {
@@ -4636,14 +4657,18 @@ async function multiSelect(io, message, choices, options = {}) {
4636
4657
  return result();
4637
4658
  }
4638
4659
  }
4660
+ } catch (error) {
4661
+ frame.erase();
4662
+ throw error;
4639
4663
  } finally {
4640
4664
  reader.close();
4641
4665
  }
4642
4666
  }
4643
4667
  async function confirm(io, message, options = {}) {
4668
+ const allowBack = options.allowBack === true;
4644
4669
  let value = options.defaultValue ?? true;
4645
4670
  if (!isInteractive(io)) {
4646
- io.output.write(`${renderConfirm(message, value)}
4671
+ io.output.write(`${renderConfirm(message, value, allowBack)}
4647
4672
  `);
4648
4673
  return value;
4649
4674
  }
@@ -4651,9 +4676,10 @@ async function confirm(io, message, options = {}) {
4651
4676
  const reader = keyReader(io.input);
4652
4677
  try {
4653
4678
  for (; ; ) {
4654
- frame.draw(renderConfirm(message, value));
4679
+ frame.draw(renderConfirm(message, value, allowBack));
4655
4680
  const key = await reader.next();
4656
4681
  if (isCancel(key)) throw new PromptCancelled();
4682
+ if (allowBack && key.name === "b") throw new PromptBack();
4657
4683
  if (key.name === "up" || key.name === "left") value = true;
4658
4684
  else if (key.name === "down" || key.name === "right") value = false;
4659
4685
  else if (key.name === "y") value = true;
@@ -4663,14 +4689,18 @@ async function confirm(io, message, options = {}) {
4663
4689
  return value;
4664
4690
  }
4665
4691
  }
4692
+ } catch (error) {
4693
+ frame.erase();
4694
+ throw error;
4666
4695
  } finally {
4667
4696
  reader.close();
4668
4697
  }
4669
4698
  }
4670
4699
  async function text(io, message, options = {}) {
4700
+ const allowBack = options.allowBack === true;
4671
4701
  const fallback = options.defaultValue ?? "";
4672
4702
  if (!isInteractive(io)) {
4673
- io.output.write(`${renderText(message, fallback)}
4703
+ io.output.write(`${renderText(message, fallback, void 0, allowBack)}
4674
4704
  `);
4675
4705
  return fallback;
4676
4706
  }
@@ -4680,9 +4710,10 @@ async function text(io, message, options = {}) {
4680
4710
  let error;
4681
4711
  try {
4682
4712
  for (; ; ) {
4683
- frame.draw(renderText(message, value, error));
4713
+ frame.draw(renderText(message, value, error, allowBack));
4684
4714
  const key = await reader.next();
4685
4715
  if (isCancel(key)) throw new PromptCancelled();
4716
+ if (allowBack && key.name === "left") throw new PromptBack();
4686
4717
  error = void 0;
4687
4718
  if (key.name === "return" || key.name === "enter") {
4688
4719
  const problem = options.validate ? options.validate(value) : null;
@@ -4703,6 +4734,9 @@ async function text(io, message, options = {}) {
4703
4734
  }
4704
4735
  if (_isPrintable(key)) value += _keyText(key);
4705
4736
  }
4737
+ } catch (error_) {
4738
+ frame.erase();
4739
+ throw error_;
4706
4740
  } finally {
4707
4741
  reader.close();
4708
4742
  }
@@ -4959,98 +4993,108 @@ async function runInit(options) {
4959
4993
  { value: "walk", label: "Go through each setting", hint: "every question starts on its default" },
4960
4994
  { value: "choose", label: "Pick a different preset", hint: "everything else stays at the defaults" }
4961
4995
  ];
4962
- const pace = await select(io, "How should I set this up?", paceChoices, {
4963
- defaultValue: fallback ? "choose" : "recommended"
4964
- });
4965
- if (pace === "choose") {
4966
- answers.preset = await select(
4967
- io,
4968
- "What kind of project is this?",
4969
- listPresetNames().map(
4970
- (name) => resolvePresetChoice(fallback ? null : detected.presetName, name)
4971
- ),
4972
- { defaultValue: answers.preset }
4973
- );
4974
- const chosen = detectPreset(options.cwd, answers.preset);
4975
- answers.preset = chosen.presetName;
4976
- reason = null;
4977
- fallback = false;
4978
- }
4979
- if (pace === "walk") {
4980
- const scope = await select(
4981
- io,
4982
- "What should go into the snapshot?",
4983
- [
4984
- { value: "all", label: "Everything the scanner finds", hint: "recommended \xB7 respects .gitignore" },
4985
- { value: "folders", label: "Only specific folders\u2026" },
4986
- { value: "no-tests", label: "Everything, but skip tests" },
4987
- { value: "custom", label: "Let me write glob patterns" }
4988
- ],
4989
- { defaultValue: "all" }
4990
- );
4991
- if (scope === "folders") {
4992
- const dirs = topLevelDirs(options.cwd).slice(0, 40);
4993
- if (dirs.length === 0) {
4994
- notes.push("No top-level directories found; the snapshot will include everything.");
4995
- } else {
4996
- const chosen = await multiSelect(
4997
- io,
4998
- "Select folders",
4999
- dirs.map((name) => ({ value: name, label: `${name}/` })),
5000
- { defaults: dirs }
5001
- );
5002
- answers.include = chosen.map((name) => `${name}/**`);
4996
+ const baseInclude = [...answers.include];
4997
+ const baseExclude = [...answers.excludePatterns];
4998
+ let lastScope = "all";
4999
+ const artifactChoices = [
5000
+ { value: "readme", label: "README.md", hint: "orientation page" },
5001
+ { value: "manifest", label: "manifest.json", hint: "required by validate and report" },
5002
+ { value: "parts", label: "parts/", hint: "the code payload" },
5003
+ { value: "navigation", label: "reports/navigation.md", hint: "file \u2192 part index" },
5004
+ { value: "projectTree", label: "reports/project-tree.md", hint: "ASCII tree" },
5005
+ { value: "audit", label: "reports/audit.md", hint: "security and health findings" },
5006
+ { value: "monolith", label: "full-codebase.json + .md", hint: "roughly doubles output" }
5007
+ ];
5008
+ const scopeStep = async () => {
5009
+ for (; ; ) {
5010
+ const scope = await select(
5011
+ io,
5012
+ "What should go into the snapshot?",
5013
+ [
5014
+ { value: "all", label: "Everything the scanner finds", hint: "recommended \xB7 respects .gitignore" },
5015
+ { value: "folders", label: "Only specific folders\u2026" },
5016
+ { value: "no-tests", label: "Everything, but skip tests" },
5017
+ { value: "custom", label: "Let me write glob patterns" }
5018
+ ],
5019
+ { defaultValue: lastScope, allowBack: true }
5020
+ );
5021
+ lastScope = scope;
5022
+ answers.include = [...baseInclude];
5023
+ answers.excludePatterns = [...baseExclude];
5024
+ try {
5025
+ if (scope === "folders") {
5026
+ const dirs = topLevelDirs(options.cwd).slice(0, 40);
5027
+ if (dirs.length === 0) {
5028
+ notes.push("No top-level directories found; the snapshot will include everything.");
5029
+ } else {
5030
+ const chosen = await multiSelect(
5031
+ io,
5032
+ "Select folders",
5033
+ dirs.map((name) => ({ value: name, label: `${name}/` })),
5034
+ { defaults: dirs, allowBack: true }
5035
+ );
5036
+ answers.include = chosen.map((name) => `${name}/**`);
5037
+ }
5038
+ } else if (scope === "no-tests") {
5039
+ answers.excludePatterns = [...baseExclude, "**/*.test.*", "**/*.spec.*", "tests", "test"];
5040
+ } else if (scope === "custom") {
5041
+ const raw = await text(io, "Glob patterns to include (comma separated)", {
5042
+ defaultValue: baseInclude.join(", "),
5043
+ allowBack: true
5044
+ });
5045
+ answers.include = raw.split(",").map((value) => value.trim()).filter(Boolean);
5046
+ }
5047
+ return;
5048
+ } catch (error) {
5049
+ if (error instanceof PromptBack) continue;
5050
+ throw error;
5003
5051
  }
5004
- } else if (scope === "no-tests") {
5005
- answers.excludePatterns = [
5006
- ...answers.excludePatterns,
5007
- "**/*.test.*",
5008
- "**/*.spec.*",
5009
- "tests",
5010
- "test"
5011
- ];
5012
- } else if (scope === "custom") {
5013
- const raw = await text(io, "Glob patterns to include (comma separated)", {
5014
- defaultValue: ""
5015
- });
5016
- answers.include = raw.split(",").map((value) => value.trim()).filter(Boolean);
5017
5052
  }
5018
- const currentBudget = String(answers.maxPartBytes);
5019
- const sizeChoice = await select(io, "How large should each part be?", SIZE_CHOICES, {
5020
- defaultValue: SIZE_CHOICES.some((choice) => choice.value === currentBudget) ? currentBudget : "120k"
5021
- });
5022
- if (sizeChoice === "custom") {
5023
- const raw = await text(io, "Part size (e.g. 150k, 1.5mb, 900000)", {
5024
- defaultValue: String(answers.maxPartBytes),
5025
- validate: (value) => parseByteSize(value) === void 0 ? "Not a valid size." : null
5053
+ };
5054
+ const sizeStep = async () => {
5055
+ for (; ; ) {
5056
+ const currentBudget = String(answers.maxPartBytes);
5057
+ const sizeChoice = await select(io, "How large should each part be?", SIZE_CHOICES, {
5058
+ defaultValue: SIZE_CHOICES.some((choice) => choice.value === currentBudget) ? currentBudget : "custom",
5059
+ allowBack: true
5026
5060
  });
5027
- answers.maxPartBytes = parseByteSize(raw) ?? answers.maxPartBytes;
5028
- } else {
5029
- answers.maxPartBytes = sizeChoice;
5030
- }
5031
- const artifactChoices = [
5032
- { value: "readme", label: "README.md", hint: "orientation page" },
5033
- { value: "manifest", label: "manifest.json", hint: "required by validate and report" },
5034
- { value: "parts", label: "parts/", hint: "the code payload" },
5035
- { value: "navigation", label: "reports/navigation.md", hint: "file \u2192 part index" },
5036
- { value: "projectTree", label: "reports/project-tree.md", hint: "ASCII tree" },
5037
- { value: "audit", label: "reports/audit.md", hint: "security and health findings" },
5038
- { value: "monolith", label: "full-codebase.json + .md", hint: "roughly doubles output" }
5039
- ];
5040
- const presetEnabled = ARTIFACT_NAMES.filter((name) => answers.artifacts[name]);
5061
+ if (sizeChoice !== "custom") {
5062
+ answers.maxPartBytes = sizeChoice;
5063
+ return;
5064
+ }
5065
+ try {
5066
+ const raw = await text(io, "Part size (e.g. 150k, 1.5mb, 900000)", {
5067
+ defaultValue: currentBudget,
5068
+ validate: (value) => parseByteSize(value) === void 0 ? "Not a valid size." : null,
5069
+ allowBack: true
5070
+ });
5071
+ answers.maxPartBytes = parseByteSize(raw) ?? answers.maxPartBytes;
5072
+ return;
5073
+ } catch (error) {
5074
+ if (error instanceof PromptBack) continue;
5075
+ throw error;
5076
+ }
5077
+ }
5078
+ };
5079
+ const artifactsStep = async () => {
5080
+ const enabled = ARTIFACT_NAMES.filter((name) => answers.artifacts[name]);
5041
5081
  const selectedArtifacts = await multiSelect(
5042
5082
  io,
5043
5083
  "Which artifacts should be generated?",
5044
5084
  artifactChoices,
5045
- { defaults: presetEnabled }
5085
+ { defaults: enabled, allowBack: true }
5046
5086
  );
5047
5087
  for (const name of ARTIFACT_NAMES) answers.artifacts[name] = selectedArtifacts.includes(name);
5048
- const enabledCount = ARTIFACT_NAMES.filter((name) => answers.artifacts[name]).length;
5088
+ };
5089
+ const credentialsStep = async () => {
5049
5090
  answers.includeSensitiveFiles = await confirm(
5050
5091
  io,
5051
- "Include credential files (.env, *.pem, .npmrc, .ssh/)?",
5052
- { defaultValue: false }
5092
+ "Include credential files (.env, *.pem, *.npmrc, *.ssh/)?",
5093
+ { defaultValue: answers.includeSensitiveFiles, allowBack: true }
5053
5094
  );
5095
+ };
5096
+ const reviewStep = async () => {
5097
+ const enabledCount = ARTIFACT_NAMES.filter((name) => answers.artifacts[name]).length;
5054
5098
  io.output.write("\n Review\n\n");
5055
5099
  io.output.write(` project ${answers.preset}
5056
5100
  `);
@@ -5065,8 +5109,53 @@ async function runInit(options) {
5065
5109
  `);
5066
5110
  io.output.write(" Will write snapshot.config with your answers, plus every other setting\n");
5067
5111
  io.output.write(" at its default \u2014 so nothing is hidden behind the docs.\n\n");
5068
- const proceed = await confirm(io, "Write this and continue?", { defaultValue: true });
5069
- if (!proceed) throw new PromptCancelled();
5112
+ const proceed = await confirm(io, "Write this and continue?", {
5113
+ defaultValue: true,
5114
+ allowBack: true
5115
+ });
5116
+ if (!proceed) throw new PromptBack();
5117
+ };
5118
+ const walk = async () => {
5119
+ const steps = [scopeStep, sizeStep, artifactsStep, credentialsStep, reviewStep];
5120
+ let index = 0;
5121
+ while (index < steps.length) {
5122
+ try {
5123
+ await steps[index]();
5124
+ index += 1;
5125
+ } catch (error) {
5126
+ if (!(error instanceof PromptBack)) throw error;
5127
+ if (index === 0) return false;
5128
+ index -= 1;
5129
+ io.output.write("\n");
5130
+ }
5131
+ }
5132
+ return true;
5133
+ };
5134
+ for (; ; ) {
5135
+ const pace = await select(io, "How should I set this up?", paceChoices, {
5136
+ defaultValue: fallback ? "choose" : "recommended"
5137
+ });
5138
+ if (pace === "choose") {
5139
+ try {
5140
+ answers.preset = await select(
5141
+ io,
5142
+ "What kind of project is this?",
5143
+ listPresetNames().map(
5144
+ (name) => resolvePresetChoice(fallback ? null : detected.presetName, name)
5145
+ ),
5146
+ { defaultValue: answers.preset, allowBack: true }
5147
+ );
5148
+ } catch (error) {
5149
+ if (error instanceof PromptBack) continue;
5150
+ throw error;
5151
+ }
5152
+ const chosen = detectPreset(options.cwd, answers.preset);
5153
+ answers.preset = chosen.presetName;
5154
+ reason = null;
5155
+ fallback = false;
5156
+ }
5157
+ if (pace === "walk" && !await walk()) continue;
5158
+ break;
5070
5159
  }
5071
5160
  }
5072
5161
  const configText = renderConfig(answers);
@@ -11163,14 +11252,13 @@ function installDependencies(cwd) {
11163
11252
  const manager = detectPackageManager(cwd);
11164
11253
  const command = `${manager.command} ${manager.args.join(" ")}`;
11165
11254
  const started = performance.now();
11166
- const result = childProcess.spawnSync(manager.command, manager.args, {
11255
+ const spawnOptions = {
11167
11256
  cwd,
11168
11257
  encoding: "utf8",
11169
- // npm, pnpm and yarn ship as `.cmd` shims on Windows, which spawnSync cannot exec directly.
11170
- shell: process.platform === "win32",
11171
11258
  timeout: INSTALL_TIMEOUT_MS,
11172
11259
  env: cleanInstallEnv()
11173
- });
11260
+ };
11261
+ const result = process.platform === "win32" ? childProcess.spawnSync(command, { ...spawnOptions, shell: true }) : childProcess.spawnSync(manager.command, manager.args, spawnOptions);
11174
11262
  const seconds = `${((performance.now() - started) / 1e3).toFixed(1)}s`;
11175
11263
  if (result.error) {
11176
11264
  return { manager: manager.name, command, ok: false, detail: `${result.error.message} (${seconds})` };
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
- import { buildAgentContract, runStdioServer, COMMAND_OPTION_SCOPE, commandsForOption, SKILL_NAME, renderSkill, renderContractText } from './chunk-EWZYK3VX.js';
2
- import { loadConfigFileDetailed, resolveConfig, validateSnapshot, describeManifestShapeProblem, explainPath, compareManifests, loadManifest, renderDiffText, generateSnapshot, formatNumber, GENERATOR_VERSION, isDiscoveryMode, ARTIFACT_NAMES, getPreset, unknownPresetMessage, GENERATOR_NAME, runInit, PromptCancelled, planFirstRun, isEffectivelyEmpty, isInteractive, defaultIO, hasPriorSnapshot, DEFAULT_ANSWERS, findConfigFile, firstRunMessage, parseByteSize, gitignorePath, appendGitignoreEntries, escapeControls, MIN_MAX_PART_BYTES, renderExplainText } from './chunk-FCWD4LY7.js';
1
+ import { buildAgentContract, runStdioServer, COMMAND_OPTION_SCOPE, commandsForOption, SKILL_NAME, renderSkill, renderContractText } from './chunk-4AHHSNGG.js';
2
+ import { loadConfigFileDetailed, resolveConfig, validateSnapshot, describeManifestShapeProblem, explainPath, compareManifests, loadManifest, renderDiffText, generateSnapshot, formatNumber, GENERATOR_VERSION, isDiscoveryMode, ARTIFACT_NAMES, getPreset, unknownPresetMessage, GENERATOR_NAME, runInit, PromptCancelled, planFirstRun, isEffectivelyEmpty, isInteractive, defaultIO, hasPriorSnapshot, DEFAULT_ANSWERS, findConfigFile, firstRunMessage, parseByteSize, gitignorePath, appendGitignoreEntries, escapeControls, MIN_MAX_PART_BYTES, renderExplainText } from './chunk-B336MMNC.js';
3
3
  import { spawnSync } from 'child_process';
4
4
  import * as fs from 'fs';
5
5
  import * as path2 from 'path';
@@ -587,14 +587,13 @@ function installDependencies(cwd) {
587
587
  const manager = detectPackageManager(cwd);
588
588
  const command = `${manager.command} ${manager.args.join(" ")}`;
589
589
  const started = performance.now();
590
- const result = spawnSync(manager.command, manager.args, {
590
+ const spawnOptions = {
591
591
  cwd,
592
592
  encoding: "utf8",
593
- // npm, pnpm and yarn ship as `.cmd` shims on Windows, which spawnSync cannot exec directly.
594
- shell: process.platform === "win32",
595
593
  timeout: INSTALL_TIMEOUT_MS,
596
594
  env: cleanInstallEnv()
597
- });
595
+ };
596
+ const result = process.platform === "win32" ? spawnSync(command, { ...spawnOptions, shell: true }) : spawnSync(manager.command, manager.args, spawnOptions);
598
597
  const seconds = `${((performance.now() - started) / 1e3).toFixed(1)}s`;
599
598
  if (result.error) {
600
599
  return { manager: manager.name, command, ok: false, detail: `${result.error.message} (${seconds})` };