codebase-snapshot 0.9.4 → 0.9.6

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/bin.js CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  // src/cli.ts
4
4
  import { spawnSync } from "child_process";
5
- import * as fs16 from "fs";
6
- import * as path17 from "path";
5
+ import * as fs17 from "fs";
6
+ import * as path18 from "path";
7
7
  import { parseArgs } from "util";
8
8
 
9
9
  // src/diff.ts
@@ -4346,7 +4346,7 @@ function gitignorePath(cwd, filePath) {
4346
4346
 
4347
4347
  // src/version.ts
4348
4348
  var GENERATOR_NAME = "codebase-snapshot";
4349
- var GENERATOR_VERSION = "0.9.4";
4349
+ var GENERATOR_VERSION = "0.9.6";
4350
4350
  var LEGACY_GENERATOR_NAMES = ["@ankurhalder/codebase-snapshot"];
4351
4351
  function isOurGeneratorName(name) {
4352
4352
  if (typeof name !== "string") return false;
@@ -4487,6 +4487,12 @@ var PromptCancelled = class extends Error {
4487
4487
  this.name = "PromptCancelled";
4488
4488
  }
4489
4489
  };
4490
+ var PromptBack = class extends Error {
4491
+ constructor() {
4492
+ super("Prompt back");
4493
+ this.name = "PromptBack";
4494
+ }
4495
+ };
4490
4496
  function defaultIO() {
4491
4497
  return { input: process.stdin, output: process.stdout };
4492
4498
  }
@@ -4510,35 +4516,40 @@ function choiceLine(choice, active) {
4510
4516
  const hint = choice.hint ? ` ${choice.hint}` : "";
4511
4517
  return ` ${marker(active)} ${choice.label}${hint}`;
4512
4518
  }
4513
- function renderSelect(message, choices, index) {
4519
+ function listFooter(base, allowBack) {
4520
+ return allowBack ? `${base} \xB7 \u2190 back` : base;
4521
+ }
4522
+ function renderSelect(message, choices, index, allowBack = false) {
4514
4523
  const lines = [`\u25C6 ${message}`, ""];
4515
4524
  choices.forEach((choice, position) => lines.push(choiceLine(choice, position === index)));
4516
- lines.push("", " \u2191\u2193 move \xB7 enter select");
4525
+ lines.push("", ` ${listFooter("\u2191\u2193 move \xB7 enter select", allowBack)}`);
4517
4526
  return lines.join("\n");
4518
4527
  }
4519
- function renderMultiSelect(message, choices, index, selected) {
4528
+ function renderMultiSelect(message, choices, index, selected, allowBack = false) {
4520
4529
  const lines = [`\u25C6 ${message}`, ""];
4521
4530
  choices.forEach((choice, position) => {
4522
4531
  const box = selected.has(position) ? "\u25FC" : "\u25FB";
4523
4532
  const hint = choice.hint ? ` ${choice.hint}` : "";
4524
4533
  lines.push(` ${marker(position === index)} ${box} ${choice.label}${hint}`);
4525
4534
  });
4526
- lines.push("", " \u2191\u2193 move \xB7 space toggle \xB7 enter confirm");
4535
+ lines.push("", ` ${listFooter("\u2191\u2193 move \xB7 space toggle \xB7 enter confirm", allowBack)}`);
4527
4536
  return lines.join("\n");
4528
4537
  }
4529
- function renderConfirm(message, value) {
4538
+ function renderConfirm(message, value, allowBack = false) {
4539
+ const footer = allowBack ? "\u2190\u2192 or y/n \xB7 enter confirm \xB7 b back" : "\u2190\u2192 or y/n \xB7 enter confirm";
4530
4540
  return [
4531
4541
  `\u25C6 ${message}`,
4532
4542
  "",
4533
4543
  ` ${marker(value)} Yes`,
4534
4544
  ` ${marker(!value)} No`,
4535
4545
  "",
4536
- " \u2190\u2192 or y/n \xB7 enter confirm"
4546
+ ` ${footer}`
4537
4547
  ].join("\n");
4538
4548
  }
4539
- function renderText(message, value, error) {
4549
+ function renderText(message, value, error, allowBack = false) {
4540
4550
  const lines = [`\u25C6 ${message}`, "", ` ${value || "\u258F"}`];
4541
4551
  if (error) lines.push("", ` \u2716 ${error}`);
4552
+ if (allowBack) lines.push("", " enter confirm \xB7 \u2190 back");
4542
4553
  return lines.join("\n");
4543
4554
  }
4544
4555
  function keyReader(input) {
@@ -4587,14 +4598,18 @@ var Frame = class {
4587
4598
  function isCancel(key) {
4588
4599
  return key.ctrl === true && key.name === "c" || key.ctrl === true && key.name === "d";
4589
4600
  }
4601
+ function isListBack(key, allowBack) {
4602
+ return allowBack && (key.name === "left" || key.name === "b");
4603
+ }
4590
4604
  async function select(io, message, choices, options = {}) {
4591
4605
  if (choices.length === 0) throw new Error("select() requires at least one choice.");
4606
+ const allowBack = options.allowBack === true;
4592
4607
  const fallbackIndex = Math.max(
4593
4608
  0,
4594
4609
  choices.findIndex((choice) => choice.value === options.defaultValue)
4595
4610
  );
4596
4611
  if (!isInteractive(io)) {
4597
- io.output.write(`${renderSelect(message, choices, fallbackIndex)}
4612
+ io.output.write(`${renderSelect(message, choices, fallbackIndex, allowBack)}
4598
4613
  `);
4599
4614
  return choices[fallbackIndex].value;
4600
4615
  }
@@ -4603,9 +4618,10 @@ async function select(io, message, choices, options = {}) {
4603
4618
  let index = fallbackIndex;
4604
4619
  try {
4605
4620
  for (; ; ) {
4606
- frame.draw(renderSelect(message, choices, index));
4621
+ frame.draw(renderSelect(message, choices, index, allowBack));
4607
4622
  const key = await reader.next();
4608
4623
  if (isCancel(key)) throw new PromptCancelled();
4624
+ if (isListBack(key, allowBack)) throw new PromptBack();
4609
4625
  if (key.name === "up") index = moveSelection(index, -1, choices.length);
4610
4626
  else if (key.name === "down") index = moveSelection(index, 1, choices.length);
4611
4627
  else if (key.name === "return" || key.name === "enter") {
@@ -4614,18 +4630,22 @@ async function select(io, message, choices, options = {}) {
4614
4630
  } else if (key.name === "j") index = moveSelection(index, 1, choices.length);
4615
4631
  else if (key.name === "k") index = moveSelection(index, -1, choices.length);
4616
4632
  }
4633
+ } catch (error) {
4634
+ frame.erase();
4635
+ throw error;
4617
4636
  } finally {
4618
4637
  reader.close();
4619
4638
  }
4620
4639
  }
4621
4640
  async function multiSelect(io, message, choices, options = {}) {
4641
+ const allowBack = options.allowBack === true;
4622
4642
  const selected = /* @__PURE__ */ new Set();
4623
4643
  choices.forEach((choice, position) => {
4624
4644
  if (options.defaults?.includes(choice.value)) selected.add(position);
4625
4645
  });
4626
4646
  const result = () => choices.filter((_, position) => selected.has(position)).map((choice) => choice.value);
4627
4647
  if (!isInteractive(io)) {
4628
- io.output.write(`${renderMultiSelect(message, choices, 0, selected)}
4648
+ io.output.write(`${renderMultiSelect(message, choices, 0, selected, allowBack)}
4629
4649
  `);
4630
4650
  return result();
4631
4651
  }
@@ -4634,9 +4654,10 @@ async function multiSelect(io, message, choices, options = {}) {
4634
4654
  let index = 0;
4635
4655
  try {
4636
4656
  for (; ; ) {
4637
- frame.draw(renderMultiSelect(message, choices, index, selected));
4657
+ frame.draw(renderMultiSelect(message, choices, index, selected, allowBack));
4638
4658
  const key = await reader.next();
4639
4659
  if (isCancel(key)) throw new PromptCancelled();
4660
+ if (isListBack(key, allowBack)) throw new PromptBack();
4640
4661
  if (key.name === "up") index = moveSelection(index, -1, choices.length);
4641
4662
  else if (key.name === "down") index = moveSelection(index, 1, choices.length);
4642
4663
  else if (key.name === "space") {
@@ -4651,14 +4672,18 @@ async function multiSelect(io, message, choices, options = {}) {
4651
4672
  return result();
4652
4673
  }
4653
4674
  }
4675
+ } catch (error) {
4676
+ frame.erase();
4677
+ throw error;
4654
4678
  } finally {
4655
4679
  reader.close();
4656
4680
  }
4657
4681
  }
4658
4682
  async function confirm(io, message, options = {}) {
4683
+ const allowBack = options.allowBack === true;
4659
4684
  let value = options.defaultValue ?? true;
4660
4685
  if (!isInteractive(io)) {
4661
- io.output.write(`${renderConfirm(message, value)}
4686
+ io.output.write(`${renderConfirm(message, value, allowBack)}
4662
4687
  `);
4663
4688
  return value;
4664
4689
  }
@@ -4666,9 +4691,10 @@ async function confirm(io, message, options = {}) {
4666
4691
  const reader = keyReader(io.input);
4667
4692
  try {
4668
4693
  for (; ; ) {
4669
- frame.draw(renderConfirm(message, value));
4694
+ frame.draw(renderConfirm(message, value, allowBack));
4670
4695
  const key = await reader.next();
4671
4696
  if (isCancel(key)) throw new PromptCancelled();
4697
+ if (allowBack && key.name === "b") throw new PromptBack();
4672
4698
  if (key.name === "up" || key.name === "left") value = true;
4673
4699
  else if (key.name === "down" || key.name === "right") value = false;
4674
4700
  else if (key.name === "y") value = true;
@@ -4678,14 +4704,18 @@ async function confirm(io, message, options = {}) {
4678
4704
  return value;
4679
4705
  }
4680
4706
  }
4707
+ } catch (error) {
4708
+ frame.erase();
4709
+ throw error;
4681
4710
  } finally {
4682
4711
  reader.close();
4683
4712
  }
4684
4713
  }
4685
4714
  async function text(io, message, options = {}) {
4715
+ const allowBack = options.allowBack === true;
4686
4716
  const fallback = options.defaultValue ?? "";
4687
4717
  if (!isInteractive(io)) {
4688
- io.output.write(`${renderText(message, fallback)}
4718
+ io.output.write(`${renderText(message, fallback, void 0, allowBack)}
4689
4719
  `);
4690
4720
  return fallback;
4691
4721
  }
@@ -4695,9 +4725,10 @@ async function text(io, message, options = {}) {
4695
4725
  let error;
4696
4726
  try {
4697
4727
  for (; ; ) {
4698
- frame.draw(renderText(message, value, error));
4728
+ frame.draw(renderText(message, value, error, allowBack));
4699
4729
  const key = await reader.next();
4700
4730
  if (isCancel(key)) throw new PromptCancelled();
4731
+ if (allowBack && key.name === "left") throw new PromptBack();
4701
4732
  error = void 0;
4702
4733
  if (key.name === "return" || key.name === "enter") {
4703
4734
  const problem = options.validate ? options.validate(value) : null;
@@ -4718,6 +4749,9 @@ async function text(io, message, options = {}) {
4718
4749
  }
4719
4750
  if (_isPrintable(key)) value += _keyText(key);
4720
4751
  }
4752
+ } catch (error_) {
4753
+ frame.erase();
4754
+ throw error_;
4721
4755
  } finally {
4722
4756
  reader.close();
4723
4757
  }
@@ -4974,98 +5008,108 @@ async function runInit(options) {
4974
5008
  { value: "walk", label: "Go through each setting", hint: "every question starts on its default" },
4975
5009
  { value: "choose", label: "Pick a different preset", hint: "everything else stays at the defaults" }
4976
5010
  ];
4977
- const pace = await select(io, "How should I set this up?", paceChoices, {
4978
- defaultValue: fallback ? "choose" : "recommended"
4979
- });
4980
- if (pace === "choose") {
4981
- answers.preset = await select(
4982
- io,
4983
- "What kind of project is this?",
4984
- listPresetNames().map(
4985
- (name) => resolvePresetChoice(fallback ? null : detected.presetName, name)
4986
- ),
4987
- { defaultValue: answers.preset }
4988
- );
4989
- const chosen = detectPreset(options.cwd, answers.preset);
4990
- answers.preset = chosen.presetName;
4991
- reason = null;
4992
- fallback = false;
4993
- }
4994
- if (pace === "walk") {
4995
- const scope = await select(
4996
- io,
4997
- "What should go into the snapshot?",
4998
- [
4999
- { value: "all", label: "Everything the scanner finds", hint: "recommended \xB7 respects .gitignore" },
5000
- { value: "folders", label: "Only specific folders\u2026" },
5001
- { value: "no-tests", label: "Everything, but skip tests" },
5002
- { value: "custom", label: "Let me write glob patterns" }
5003
- ],
5004
- { defaultValue: "all" }
5005
- );
5006
- if (scope === "folders") {
5007
- const dirs = topLevelDirs(options.cwd).slice(0, 40);
5008
- if (dirs.length === 0) {
5009
- notes.push("No top-level directories found; the snapshot will include everything.");
5010
- } else {
5011
- const chosen = await multiSelect(
5012
- io,
5013
- "Select folders",
5014
- dirs.map((name) => ({ value: name, label: `${name}/` })),
5015
- { defaults: dirs }
5016
- );
5017
- answers.include = chosen.map((name) => `${name}/**`);
5011
+ const baseInclude = [...answers.include];
5012
+ const baseExclude = [...answers.excludePatterns];
5013
+ let lastScope = "all";
5014
+ const artifactChoices = [
5015
+ { value: "readme", label: "README.md", hint: "orientation page" },
5016
+ { value: "manifest", label: "manifest.json", hint: "required by validate and report" },
5017
+ { value: "parts", label: "parts/", hint: "the code payload" },
5018
+ { value: "navigation", label: "reports/navigation.md", hint: "file \u2192 part index" },
5019
+ { value: "projectTree", label: "reports/project-tree.md", hint: "ASCII tree" },
5020
+ { value: "audit", label: "reports/audit.md", hint: "security and health findings" },
5021
+ { value: "monolith", label: "full-codebase.json + .md", hint: "roughly doubles output" }
5022
+ ];
5023
+ const scopeStep = async () => {
5024
+ for (; ; ) {
5025
+ const scope = await select(
5026
+ io,
5027
+ "What should go into the snapshot?",
5028
+ [
5029
+ { value: "all", label: "Everything the scanner finds", hint: "recommended \xB7 respects .gitignore" },
5030
+ { value: "folders", label: "Only specific folders\u2026" },
5031
+ { value: "no-tests", label: "Everything, but skip tests" },
5032
+ { value: "custom", label: "Let me write glob patterns" }
5033
+ ],
5034
+ { defaultValue: lastScope, allowBack: true }
5035
+ );
5036
+ lastScope = scope;
5037
+ answers.include = [...baseInclude];
5038
+ answers.excludePatterns = [...baseExclude];
5039
+ try {
5040
+ if (scope === "folders") {
5041
+ const dirs = topLevelDirs(options.cwd).slice(0, 40);
5042
+ if (dirs.length === 0) {
5043
+ notes.push("No top-level directories found; the snapshot will include everything.");
5044
+ } else {
5045
+ const chosen = await multiSelect(
5046
+ io,
5047
+ "Select folders",
5048
+ dirs.map((name) => ({ value: name, label: `${name}/` })),
5049
+ { defaults: dirs, allowBack: true }
5050
+ );
5051
+ answers.include = chosen.map((name) => `${name}/**`);
5052
+ }
5053
+ } else if (scope === "no-tests") {
5054
+ answers.excludePatterns = [...baseExclude, "**/*.test.*", "**/*.spec.*", "tests", "test"];
5055
+ } else if (scope === "custom") {
5056
+ const raw = await text(io, "Glob patterns to include (comma separated)", {
5057
+ defaultValue: baseInclude.join(", "),
5058
+ allowBack: true
5059
+ });
5060
+ answers.include = raw.split(",").map((value) => value.trim()).filter(Boolean);
5061
+ }
5062
+ return;
5063
+ } catch (error) {
5064
+ if (error instanceof PromptBack) continue;
5065
+ throw error;
5018
5066
  }
5019
- } else if (scope === "no-tests") {
5020
- answers.excludePatterns = [
5021
- ...answers.excludePatterns,
5022
- "**/*.test.*",
5023
- "**/*.spec.*",
5024
- "tests",
5025
- "test"
5026
- ];
5027
- } else if (scope === "custom") {
5028
- const raw = await text(io, "Glob patterns to include (comma separated)", {
5029
- defaultValue: ""
5030
- });
5031
- answers.include = raw.split(",").map((value) => value.trim()).filter(Boolean);
5032
5067
  }
5033
- const currentBudget = String(answers.maxPartBytes);
5034
- const sizeChoice = await select(io, "How large should each part be?", SIZE_CHOICES, {
5035
- defaultValue: SIZE_CHOICES.some((choice) => choice.value === currentBudget) ? currentBudget : "120k"
5036
- });
5037
- if (sizeChoice === "custom") {
5038
- const raw = await text(io, "Part size (e.g. 150k, 1.5mb, 900000)", {
5039
- defaultValue: String(answers.maxPartBytes),
5040
- validate: (value) => parseByteSize(value) === void 0 ? "Not a valid size." : null
5068
+ };
5069
+ const sizeStep = async () => {
5070
+ for (; ; ) {
5071
+ const currentBudget = String(answers.maxPartBytes);
5072
+ const sizeChoice = await select(io, "How large should each part be?", SIZE_CHOICES, {
5073
+ defaultValue: SIZE_CHOICES.some((choice) => choice.value === currentBudget) ? currentBudget : "custom",
5074
+ allowBack: true
5041
5075
  });
5042
- answers.maxPartBytes = parseByteSize(raw) ?? answers.maxPartBytes;
5043
- } else {
5044
- answers.maxPartBytes = sizeChoice;
5045
- }
5046
- const artifactChoices = [
5047
- { value: "readme", label: "README.md", hint: "orientation page" },
5048
- { value: "manifest", label: "manifest.json", hint: "required by validate and report" },
5049
- { value: "parts", label: "parts/", hint: "the code payload" },
5050
- { value: "navigation", label: "reports/navigation.md", hint: "file \u2192 part index" },
5051
- { value: "projectTree", label: "reports/project-tree.md", hint: "ASCII tree" },
5052
- { value: "audit", label: "reports/audit.md", hint: "security and health findings" },
5053
- { value: "monolith", label: "full-codebase.json + .md", hint: "roughly doubles output" }
5054
- ];
5055
- const presetEnabled = ARTIFACT_NAMES.filter((name) => answers.artifacts[name]);
5076
+ if (sizeChoice !== "custom") {
5077
+ answers.maxPartBytes = sizeChoice;
5078
+ return;
5079
+ }
5080
+ try {
5081
+ const raw = await text(io, "Part size (e.g. 150k, 1.5mb, 900000)", {
5082
+ defaultValue: currentBudget,
5083
+ validate: (value) => parseByteSize(value) === void 0 ? "Not a valid size." : null,
5084
+ allowBack: true
5085
+ });
5086
+ answers.maxPartBytes = parseByteSize(raw) ?? answers.maxPartBytes;
5087
+ return;
5088
+ } catch (error) {
5089
+ if (error instanceof PromptBack) continue;
5090
+ throw error;
5091
+ }
5092
+ }
5093
+ };
5094
+ const artifactsStep = async () => {
5095
+ const enabled = ARTIFACT_NAMES.filter((name) => answers.artifacts[name]);
5056
5096
  const selectedArtifacts = await multiSelect(
5057
5097
  io,
5058
5098
  "Which artifacts should be generated?",
5059
5099
  artifactChoices,
5060
- { defaults: presetEnabled }
5100
+ { defaults: enabled, allowBack: true }
5061
5101
  );
5062
5102
  for (const name of ARTIFACT_NAMES) answers.artifacts[name] = selectedArtifacts.includes(name);
5063
- const enabledCount = ARTIFACT_NAMES.filter((name) => answers.artifacts[name]).length;
5103
+ };
5104
+ const credentialsStep = async () => {
5064
5105
  answers.includeSensitiveFiles = await confirm(
5065
5106
  io,
5066
- "Include credential files (.env, *.pem, .npmrc, .ssh/)?",
5067
- { defaultValue: false }
5107
+ "Include credential files (.env, *.pem, *.npmrc, *.ssh/)?",
5108
+ { defaultValue: answers.includeSensitiveFiles, allowBack: true }
5068
5109
  );
5110
+ };
5111
+ const reviewStep = async () => {
5112
+ const enabledCount = ARTIFACT_NAMES.filter((name) => answers.artifacts[name]).length;
5069
5113
  io.output.write("\n Review\n\n");
5070
5114
  io.output.write(` project ${answers.preset}
5071
5115
  `);
@@ -5080,8 +5124,53 @@ async function runInit(options) {
5080
5124
  `);
5081
5125
  io.output.write(" Will write snapshot.config with your answers, plus every other setting\n");
5082
5126
  io.output.write(" at its default \u2014 so nothing is hidden behind the docs.\n\n");
5083
- const proceed = await confirm(io, "Write this and continue?", { defaultValue: true });
5084
- if (!proceed) throw new PromptCancelled();
5127
+ const proceed = await confirm(io, "Write this and continue?", {
5128
+ defaultValue: true,
5129
+ allowBack: true
5130
+ });
5131
+ if (!proceed) throw new PromptBack();
5132
+ };
5133
+ const walk = async () => {
5134
+ const steps = [scopeStep, sizeStep, artifactsStep, credentialsStep, reviewStep];
5135
+ let index = 0;
5136
+ while (index < steps.length) {
5137
+ try {
5138
+ await steps[index]();
5139
+ index += 1;
5140
+ } catch (error) {
5141
+ if (!(error instanceof PromptBack)) throw error;
5142
+ if (index === 0) return false;
5143
+ index -= 1;
5144
+ io.output.write("\n");
5145
+ }
5146
+ }
5147
+ return true;
5148
+ };
5149
+ for (; ; ) {
5150
+ const pace = await select(io, "How should I set this up?", paceChoices, {
5151
+ defaultValue: fallback ? "choose" : "recommended"
5152
+ });
5153
+ if (pace === "choose") {
5154
+ try {
5155
+ answers.preset = await select(
5156
+ io,
5157
+ "What kind of project is this?",
5158
+ listPresetNames().map(
5159
+ (name) => resolvePresetChoice(fallback ? null : detected.presetName, name)
5160
+ ),
5161
+ { defaultValue: answers.preset, allowBack: true }
5162
+ );
5163
+ } catch (error) {
5164
+ if (error instanceof PromptBack) continue;
5165
+ throw error;
5166
+ }
5167
+ const chosen = detectPreset(options.cwd, answers.preset);
5168
+ answers.preset = chosen.presetName;
5169
+ reason = null;
5170
+ fallback = false;
5171
+ }
5172
+ if (pace === "walk" && !await walk()) continue;
5173
+ break;
5085
5174
  }
5086
5175
  }
5087
5176
  const configText = renderConfig(answers);
@@ -5200,9 +5289,9 @@ function hasPriorSnapshot(cwd, outDir) {
5200
5289
  // src/index.ts
5201
5290
  import * as crypto3 from "crypto";
5202
5291
  import { AsyncLocalStorage } from "async_hooks";
5203
- import * as fs11 from "fs";
5204
- import * as os from "os";
5205
- import * as path12 from "path";
5292
+ import * as fs12 from "fs";
5293
+ import * as os2 from "os";
5294
+ import * as path13 from "path";
5206
5295
 
5207
5296
  // src/ast/profiles/shared.ts
5208
5297
  var MAX_SUMMARY_CHARS = 1e6;
@@ -5426,9 +5515,9 @@ var JAVA_METHOD = /^\s+(?:public|private|protected)\s+(?:static\s+)?(?:final\s+)
5426
5515
  var jvmProfile = {
5427
5516
  id: "jvm",
5428
5517
  extensions: [".java", ".kt", ".kts", ".scala"],
5429
- summarize(path18, content) {
5518
+ summarize(path19, content) {
5430
5519
  const summary = emptySummary();
5431
- const lower = path18.toLowerCase();
5520
+ const lower = path19.toLowerCase();
5432
5521
  const isJava = lower.endsWith(".java");
5433
5522
  const isKotlin = lower.endsWith(".kt") || lower.endsWith(".kts");
5434
5523
  eachLine(content, (line) => {
@@ -5884,16 +5973,16 @@ function summarizeTypeScriptSource(relativePath, content) {
5884
5973
  // src/ast/profiles/sfc.ts
5885
5974
  var SCRIPT_BLOCK = /<script[^>]*>([\s\S]*?)<\/script>/gi;
5886
5975
  var ASTRO_FRONTMATTER = /^\uFEFF?---[ \t]*\r?\n([\s\S]*?)\r?\n---[ \t]*(?=\r?\n|$)/;
5887
- function componentName(path18) {
5888
- const base = path18.split("/").pop() ?? path18;
5976
+ function componentName(path19) {
5977
+ const base = path19.split("/").pop() ?? path19;
5889
5978
  return base.replace(/\.[^.]+$/, "");
5890
5979
  }
5891
5980
  var sfcProfile = {
5892
5981
  id: "sfc",
5893
5982
  extensions: [".vue", ".svelte", ".astro"],
5894
- summarize(path18, content) {
5983
+ summarize(path19, content) {
5895
5984
  let script = "";
5896
- if (path18.toLowerCase().endsWith(".astro")) {
5985
+ if (path19.toLowerCase().endsWith(".astro")) {
5897
5986
  const frontmatter = ASTRO_FRONTMATTER.exec(content);
5898
5987
  if (frontmatter) script += `${frontmatter[1]}
5899
5988
  `;
@@ -5902,7 +5991,7 @@ var sfcProfile = {
5902
5991
  script += `${match[1]}
5903
5992
  `;
5904
5993
  }
5905
- const name = componentName(path18);
5994
+ const name = componentName(path19);
5906
5995
  if (!script.trim()) {
5907
5996
  const summary2 = emptySummary();
5908
5997
  if (name) {
@@ -5936,15 +6025,15 @@ for (const profile of LANGUAGE_PROFILES) {
5936
6025
  BY_EXTENSION.set(extension.toLowerCase(), profile);
5937
6026
  }
5938
6027
  }
5939
- function profileForPath(path18) {
5940
- const lower = path18.toLowerCase();
6028
+ function profileForPath(path19) {
6029
+ const lower = path19.toLowerCase();
5941
6030
  const dot = lower.lastIndexOf(".");
5942
6031
  if (dot === -1) return null;
5943
6032
  return BY_EXTENSION.get(lower.slice(dot)) ?? null;
5944
6033
  }
5945
- function summarizeWithProfile(path18, content) {
5946
- const profile = profileForPath(path18);
5947
- return profile ? profile.summarize(path18, content) : null;
6034
+ function summarizeWithProfile(path19, content) {
6035
+ const profile = profileForPath(path19);
6036
+ return profile ? profile.summarize(path19, content) : null;
5948
6037
  }
5949
6038
 
5950
6039
  // src/ast/structured.ts
@@ -6793,6 +6882,168 @@ function generateProjectTree(filePaths) {
6793
6882
  return ["# Project Tree", "", `${fence}text`, ...lines, fence, ""].join("\n");
6794
6883
  }
6795
6884
 
6885
+ // src/update-check.ts
6886
+ import * as fs11 from "fs";
6887
+ import * as https from "https";
6888
+ import * as os from "os";
6889
+ import * as path12 from "path";
6890
+ var PACKAGE_LATEST_URL = "https://registry.npmjs.org/codebase-snapshot/latest";
6891
+ var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
6892
+ var FAILURE_INTERVAL_MS = 60 * 60 * 1e3;
6893
+ var REQUEST_TIMEOUT_MS = 1200;
6894
+ function versionParts(value) {
6895
+ const core = value.trim().replace(/^v/i, "").split("-")[0];
6896
+ return core.split(".").map((part) => {
6897
+ const parsed = Number(part);
6898
+ return Number.isFinite(parsed) ? parsed : 0;
6899
+ });
6900
+ }
6901
+ function isNewer(candidate, current) {
6902
+ const left = versionParts(candidate);
6903
+ const right = versionParts(current);
6904
+ const length = Math.max(left.length, right.length);
6905
+ for (let index = 0; index < length; index += 1) {
6906
+ const a = left[index] ?? 0;
6907
+ const b = right[index] ?? 0;
6908
+ if (a !== b) return a > b;
6909
+ }
6910
+ return false;
6911
+ }
6912
+ function cacheDirectory(env = process.env, platform = process.platform) {
6913
+ if (platform === "win32") {
6914
+ const base2 = env.LOCALAPPDATA ?? path12.join(os.homedir(), "AppData", "Local");
6915
+ return path12.join(base2, "codebase-snapshot");
6916
+ }
6917
+ if (platform === "darwin") {
6918
+ return path12.join(os.homedir(), "Library", "Caches", "codebase-snapshot");
6919
+ }
6920
+ const base = env.XDG_CACHE_HOME ?? path12.join(os.homedir(), ".cache");
6921
+ return path12.join(base, "codebase-snapshot");
6922
+ }
6923
+ function cacheFilePath(env = process.env) {
6924
+ return path12.join(cacheDirectory(env), "update-check.json");
6925
+ }
6926
+ function shouldCheck(argv, env) {
6927
+ const disabled = ["1", "true", "yes"].includes(
6928
+ String(env.CODEBASE_SNAPSHOT_NO_UPDATE_CHECK ?? "").toLowerCase()
6929
+ );
6930
+ if (disabled) return false;
6931
+ if (env.CI !== void 0 && env.CI !== "" && env.CI !== "false" && env.CI !== "0") return false;
6932
+ const args = argv.map((argument) => argument.toLowerCase());
6933
+ if (args.includes("--no-update-check")) return false;
6934
+ for (const skip of ["mcp", "describe", "skill", "--version", "-v", "--help", "-h"]) {
6935
+ if (args.includes(skip)) return false;
6936
+ }
6937
+ if (args.some((argument) => argument.includes("json"))) return false;
6938
+ return true;
6939
+ }
6940
+ function readCache(file) {
6941
+ let raw;
6942
+ try {
6943
+ raw = fs11.readFileSync(file, "utf8");
6944
+ } catch {
6945
+ return null;
6946
+ }
6947
+ try {
6948
+ const parsed = JSON.parse(raw);
6949
+ if (typeof parsed !== "object" || parsed === null) return null;
6950
+ const candidate = parsed;
6951
+ if (typeof candidate.checkedAt !== "number") return null;
6952
+ const latest = typeof candidate.latest === "string" ? candidate.latest : null;
6953
+ return { checkedAt: candidate.checkedAt, latest };
6954
+ } catch {
6955
+ return null;
6956
+ }
6957
+ }
6958
+ function writeCache(file, entry) {
6959
+ try {
6960
+ fs11.mkdirSync(path12.dirname(file), { recursive: true });
6961
+ fs11.writeFileSync(file, `${JSON.stringify(entry)}
6962
+ `, "utf8");
6963
+ } catch {
6964
+ }
6965
+ }
6966
+ function fetchLatestVersion(url = PACKAGE_LATEST_URL, timeoutMs = REQUEST_TIMEOUT_MS) {
6967
+ return new Promise((resolve9) => {
6968
+ let settled = false;
6969
+ const finish = (value) => {
6970
+ if (settled) return;
6971
+ settled = true;
6972
+ resolve9(value);
6973
+ };
6974
+ const request = https.get(
6975
+ url,
6976
+ {
6977
+ headers: {
6978
+ accept: "application/json",
6979
+ "user-agent": "codebase-snapshot (update check)"
6980
+ }
6981
+ },
6982
+ (response) => {
6983
+ if (response.statusCode !== 200) {
6984
+ response.resume();
6985
+ finish(null);
6986
+ return;
6987
+ }
6988
+ let body = "";
6989
+ response.setEncoding("utf8");
6990
+ response.on("data", (chunk) => {
6991
+ body += chunk;
6992
+ if (body.length > 64 * 1024) {
6993
+ request.destroy();
6994
+ finish(null);
6995
+ }
6996
+ });
6997
+ response.on("end", () => {
6998
+ try {
6999
+ const parsed = JSON.parse(body);
7000
+ finish(typeof parsed.version === "string" ? parsed.version : null);
7001
+ } catch {
7002
+ finish(null);
7003
+ }
7004
+ });
7005
+ }
7006
+ );
7007
+ request.on("error", () => finish(null));
7008
+ request.setTimeout(timeoutMs, () => {
7009
+ request.destroy();
7010
+ finish(null);
7011
+ });
7012
+ });
7013
+ }
7014
+ async function checkForUpdate(options) {
7015
+ if (options.enabled === false) return null;
7016
+ const now = options.now ?? (() => Date.now());
7017
+ const fetchLatest = options.fetchLatest ?? fetchLatestVersion;
7018
+ let latest = null;
7019
+ try {
7020
+ const cached = readCache(options.cacheFile);
7021
+ let needsFetch = cached === null;
7022
+ if (cached) {
7023
+ const age = now() - cached.checkedAt;
7024
+ if (cached.latest === null) {
7025
+ needsFetch = age >= FAILURE_INTERVAL_MS;
7026
+ } else {
7027
+ latest = cached.latest;
7028
+ needsFetch = age >= CHECK_INTERVAL_MS;
7029
+ }
7030
+ }
7031
+ if (needsFetch) {
7032
+ const fetched = await fetchLatest(PACKAGE_LATEST_URL, REQUEST_TIMEOUT_MS);
7033
+ writeCache(options.cacheFile, { checkedAt: now(), latest: fetched });
7034
+ latest = fetched;
7035
+ }
7036
+ } catch {
7037
+ return null;
7038
+ }
7039
+ if (!latest) return null;
7040
+ return isNewer(latest, options.current) ? { current: options.current, latest } : null;
7041
+ }
7042
+ function formatUpdateNotice(notice) {
7043
+ return `\u2191 codebase-snapshot ${notice.latest} is available \u2014 you have ${notice.current}.
7044
+ npm install -g codebase-snapshot`;
7045
+ }
7046
+
6796
7047
  // src/index.ts
6797
7048
  var SCHEMA_VERSION = "3.0.0";
6798
7049
  var SUMMARY_MAX_SOURCE_BYTES = 2 * 1024 * 1024;
@@ -6874,13 +7125,13 @@ function buildImportResolver(files) {
6874
7125
  const relativePath = file.relativePath;
6875
7126
  remember(byPath, relativePath, relativePath);
6876
7127
  remember(byPathFolded, relativePath.toLowerCase(), relativePath);
6877
- const extension = path12.posix.extname(relativePath);
7128
+ const extension = path13.posix.extname(relativePath);
6878
7129
  if (!SOURCE_EXTENSIONS.has(extension)) continue;
6879
7130
  const stem = relativePath.slice(0, -extension.length);
6880
7131
  remember(byStem, stem, relativePath);
6881
7132
  remember(byStemFolded, stem.toLowerCase(), relativePath);
6882
- if (path12.posix.basename(stem) === "index") {
6883
- const directory = path12.posix.dirname(stem);
7133
+ if (path13.posix.basename(stem) === "index") {
7134
+ const directory = path13.posix.dirname(stem);
6884
7135
  remember(byStem, directory, relativePath);
6885
7136
  remember(byStemFolded, directory.toLowerCase(), relativePath);
6886
7137
  }
@@ -6889,8 +7140,8 @@ function buildImportResolver(files) {
6889
7140
  }
6890
7141
  function resolveSpecifier(fromFile, specifier, resolver) {
6891
7142
  if (!RELATIVE_SPECIFIER.test(specifier)) return null;
6892
- const joined = path12.posix.normalize(
6893
- path12.posix.join(path12.posix.dirname(fromFile), specifier)
7143
+ const joined = path13.posix.normalize(
7144
+ path13.posix.join(path13.posix.dirname(fromFile), specifier)
6894
7145
  );
6895
7146
  const exact = (key) => resolver.byPath.get(key) ?? resolver.byPathFolded.get(key.toLowerCase()) ?? null;
6896
7147
  const direct = exact(joined);
@@ -6983,11 +7234,11 @@ function verifyInMemory(files, parts, maxPartBytes) {
6983
7234
  return errors;
6984
7235
  }
6985
7236
  function resolveSafeOutputDirs(config) {
6986
- const cwd = path12.resolve(config.cwd);
6987
- const outDir = path12.resolve(cwd, config.outDir);
6988
- const tmpDir = path12.resolve(cwd, config.tmpDir);
6989
- const root = path12.parse(cwd).root;
6990
- const contains = (parent, child) => child === parent || child.startsWith(`${parent}${path12.sep}`);
7237
+ const cwd = path13.resolve(config.cwd);
7238
+ const outDir = path13.resolve(cwd, config.outDir);
7239
+ const tmpDir = path13.resolve(cwd, config.tmpDir);
7240
+ const root = path13.parse(cwd).root;
7241
+ const contains = (parent, child) => child === parent || child.startsWith(`${parent}${path13.sep}`);
6991
7242
  const reject = (reason) => {
6992
7243
  throw new Error(
6993
7244
  `Refusing to generate: ${reason}. outDir=${outDir} tmpDir=${tmpDir} cwd=${cwd}`
@@ -7043,14 +7294,14 @@ function listEntries(dir) {
7043
7294
  const walk = (absolute, prefix) => {
7044
7295
  let children;
7045
7296
  try {
7046
- children = fs11.readdirSync(absolute, { withFileTypes: true });
7297
+ children = fs12.readdirSync(absolute, { withFileTypes: true });
7047
7298
  } catch {
7048
7299
  return;
7049
7300
  }
7050
7301
  for (const child of children) {
7051
7302
  const relative11 = prefix === "" ? child.name : `${prefix}/${child.name}`;
7052
7303
  entries.push(relative11);
7053
- if (child.isDirectory()) walk(path12.join(absolute, child.name), relative11);
7304
+ if (child.isDirectory()) walk(path13.join(absolute, child.name), relative11);
7054
7305
  }
7055
7306
  };
7056
7307
  walk(dir, "");
@@ -7067,28 +7318,28 @@ function markerPayload(dir, state, id, createdAt) {
7067
7318
  pid: process.pid,
7068
7319
  entries: listEntries(dir)
7069
7320
  };
7070
- const manifestPath = path12.join(dir, "manifest.json");
7071
- if (fs11.existsSync(manifestPath)) {
7072
- marker2.manifestSha256 = sha256Hex2(fs11.readFileSync(manifestPath));
7321
+ const manifestPath = path13.join(dir, "manifest.json");
7322
+ if (fs12.existsSync(manifestPath)) {
7323
+ marker2.manifestSha256 = sha256Hex2(fs12.readFileSync(manifestPath));
7073
7324
  }
7074
7325
  return marker2;
7075
7326
  }
7076
7327
  function writeOwnershipMarker(dir, marker2) {
7077
- fs11.writeFileSync(
7078
- path12.join(dir, OWNERSHIP_MARKER),
7328
+ fs12.writeFileSync(
7329
+ path13.join(dir, OWNERSHIP_MARKER),
7079
7330
  `${JSON.stringify(marker2, null, 2)}
7080
7331
  `,
7081
7332
  "utf8"
7082
7333
  );
7083
7334
  }
7084
7335
  function readOwnershipMarker(dir) {
7085
- const markerPath = path12.join(dir, OWNERSHIP_MARKER);
7086
- if (!fs11.existsSync(markerPath)) {
7336
+ const markerPath = path13.join(dir, OWNERSHIP_MARKER);
7337
+ if (!fs12.existsSync(markerPath)) {
7087
7338
  return { marker: null, problem: "it holds no .codebase-snapshot marker" };
7088
7339
  }
7089
7340
  let raw;
7090
7341
  try {
7091
- raw = fs11.readFileSync(markerPath, "utf8");
7342
+ raw = fs12.readFileSync(markerPath, "utf8");
7092
7343
  } catch {
7093
7344
  return { marker: null, problem: "its .codebase-snapshot marker could not be read" };
7094
7345
  }
@@ -7156,11 +7407,11 @@ function assessSnapshotDirectory(dir) {
7156
7407
  marker: marker2
7157
7408
  };
7158
7409
  }
7159
- const manifestPath = path12.join(dir, "manifest.json");
7160
- if (fs11.existsSync(manifestPath)) {
7410
+ const manifestPath = path13.join(dir, "manifest.json");
7411
+ if (fs12.existsSync(manifestPath)) {
7161
7412
  let raw;
7162
7413
  try {
7163
- raw = fs11.readFileSync(manifestPath, "utf8");
7414
+ raw = fs12.readFileSync(manifestPath, "utf8");
7164
7415
  } catch {
7165
7416
  return {
7166
7417
  owned: false,
@@ -7242,13 +7493,13 @@ function containsNoFiles(dir) {
7242
7493
  const current = pending.pop();
7243
7494
  let entries;
7244
7495
  try {
7245
- entries = fs11.readdirSync(current, { withFileTypes: true });
7496
+ entries = fs12.readdirSync(current, { withFileTypes: true });
7246
7497
  } catch {
7247
7498
  return false;
7248
7499
  }
7249
7500
  for (const entry of entries) {
7250
7501
  if (entry.isDirectory()) {
7251
- pending.push(path12.join(current, entry.name));
7502
+ pending.push(path13.join(current, entry.name));
7252
7503
  } else if (!IGNORABLE_ENTRIES.has(entry.name)) {
7253
7504
  return false;
7254
7505
  }
@@ -7257,13 +7508,13 @@ function containsNoFiles(dir) {
7257
7508
  return true;
7258
7509
  }
7259
7510
  function assertReplaceable(target, label, secretRules) {
7260
- if (!fs11.existsSync(target)) return;
7261
- if (!fs11.statSync(target).isDirectory()) {
7511
+ if (!fs12.existsSync(target)) return;
7512
+ if (!fs12.statSync(target).isDirectory()) {
7262
7513
  throw new Error(
7263
7514
  `Refusing to write into ${label} ${target}: it exists but is not a directory.`
7264
7515
  );
7265
7516
  }
7266
- const entries = fs11.readdirSync(target);
7517
+ const entries = fs12.readdirSync(target);
7267
7518
  if (entries.length === 0) return;
7268
7519
  if (entries.every((name) => IGNORABLE_ENTRIES.has(name))) return;
7269
7520
  if (containsNoFiles(target)) return;
@@ -7283,18 +7534,18 @@ function assertReplaceable(target, label, secretRules) {
7283
7534
  );
7284
7535
  }
7285
7536
  function assertStagingRootUsable(tmpDir, secretRules) {
7286
- if (!fs11.existsSync(tmpDir)) return;
7287
- if (!fs11.statSync(tmpDir).isDirectory()) {
7537
+ if (!fs12.existsSync(tmpDir)) return;
7538
+ if (!fs12.statSync(tmpDir).isDirectory()) {
7288
7539
  throw new Error(`Refusing to write into tmpDir ${tmpDir}: it exists but is not a directory.`);
7289
7540
  }
7290
- const entries = fs11.readdirSync(tmpDir);
7541
+ const entries = fs12.readdirSync(tmpDir);
7291
7542
  if (entries.length === 0) return;
7292
7543
  const foreign = entries.filter((name) => {
7293
- const full = path12.join(tmpDir, name);
7544
+ const full = path13.join(tmpDir, name);
7294
7545
  if (!name.startsWith(RUN_DIR_PREFIX)) return true;
7295
7546
  let stats;
7296
7547
  try {
7297
- stats = fs11.statSync(full);
7548
+ stats = fs12.statSync(full);
7298
7549
  } catch {
7299
7550
  return true;
7300
7551
  }
@@ -7302,7 +7553,7 @@ function assertStagingRootUsable(tmpDir, secretRules) {
7302
7553
  const { marker: marker2 } = readOwnershipMarker(full);
7303
7554
  if (marker2) return false;
7304
7555
  try {
7305
- return fs11.readdirSync(full).length > 0;
7556
+ return fs12.readdirSync(full).length > 0;
7306
7557
  } catch {
7307
7558
  return true;
7308
7559
  }
@@ -7317,13 +7568,13 @@ function assertStagingRootUsable(tmpDir, secretRules) {
7317
7568
  function cleanStaleRunDirs(tmpDir) {
7318
7569
  let entries;
7319
7570
  try {
7320
- entries = fs11.readdirSync(tmpDir);
7571
+ entries = fs12.readdirSync(tmpDir);
7321
7572
  } catch {
7322
7573
  return;
7323
7574
  }
7324
7575
  for (const name of entries) {
7325
7576
  if (!name.startsWith(RUN_DIR_PREFIX)) continue;
7326
- const full = path12.join(tmpDir, name);
7577
+ const full = path13.join(tmpDir, name);
7327
7578
  const { marker: marker2 } = readOwnershipMarker(full);
7328
7579
  if (marker2) {
7329
7580
  const created = Date.parse(marker2.createdAt);
@@ -7331,33 +7582,33 @@ function cleanStaleRunDirs(tmpDir) {
7331
7582
  const abandoned = typeof marker2.pid === "number" && !isProcessAlive(marker2.pid);
7332
7583
  if (aged || abandoned) {
7333
7584
  try {
7334
- fs11.rmSync(full, { recursive: true, force: true });
7585
+ fs12.rmSync(full, { recursive: true, force: true });
7335
7586
  } catch {
7336
7587
  }
7337
7588
  }
7338
7589
  continue;
7339
7590
  }
7340
7591
  try {
7341
- if (fs11.readdirSync(full).length === 0) fs11.rmSync(full, { recursive: true, force: true });
7592
+ if (fs12.readdirSync(full).length === 0) fs12.rmSync(full, { recursive: true, force: true });
7342
7593
  } catch {
7343
7594
  }
7344
7595
  }
7345
7596
  }
7346
7597
  function removeIfEmpty(dir) {
7347
7598
  try {
7348
- if (fs11.readdirSync(dir).length === 0) fs11.rmSync(dir, { recursive: true, force: true });
7599
+ if (fs12.readdirSync(dir).length === 0) fs12.rmSync(dir, { recursive: true, force: true });
7349
7600
  } catch {
7350
7601
  }
7351
7602
  }
7352
7603
  function ensureParentDirectory(target, label) {
7353
- const parent = path12.dirname(target);
7354
- if (fs11.existsSync(parent) && !fs11.statSync(parent).isDirectory()) {
7604
+ const parent = path13.dirname(target);
7605
+ if (fs12.existsSync(parent) && !fs12.statSync(parent).isDirectory()) {
7355
7606
  throw new Error(
7356
7607
  `Refusing to create ${label} ${target}: ${parent} exists but is not a directory.`
7357
7608
  );
7358
7609
  }
7359
7610
  try {
7360
- fs11.mkdirSync(parent, { recursive: true });
7611
+ fs12.mkdirSync(parent, { recursive: true });
7361
7612
  } catch (err) {
7362
7613
  throw new Error(
7363
7614
  `Refusing to create ${label} ${target}: its parent ${parent} could not be created (${err.message}).`
@@ -7366,7 +7617,7 @@ function ensureParentDirectory(target, label) {
7366
7617
  }
7367
7618
  function acquireRunLock(stagingRoot) {
7368
7619
  const key = lockKeyFor(stagingRoot);
7369
- const lockPath = path12.join(os.tmpdir(), `codebase-snapshot-${key}.lock`);
7620
+ const lockPath = path13.join(os2.tmpdir(), `codebase-snapshot-${key}.lock`);
7370
7621
  const payload = `${JSON.stringify({
7371
7622
  pid: process.pid,
7372
7623
  stagingRoot,
@@ -7375,22 +7626,22 @@ function acquireRunLock(stagingRoot) {
7375
7626
  `;
7376
7627
  for (let attempt = 0; attempt < 2; attempt += 1) {
7377
7628
  try {
7378
- const handle = fs11.openSync(lockPath, "wx");
7629
+ const handle = fs12.openSync(lockPath, "wx");
7379
7630
  try {
7380
- fs11.writeSync(handle, payload);
7631
+ fs12.writeSync(handle, payload);
7381
7632
  } finally {
7382
- fs11.closeSync(handle);
7633
+ fs12.closeSync(handle);
7383
7634
  }
7384
7635
  return () => {
7385
7636
  try {
7386
- fs11.rmSync(lockPath, { force: true });
7637
+ fs12.rmSync(lockPath, { force: true });
7387
7638
  } catch {
7388
7639
  }
7389
7640
  };
7390
7641
  } catch (err) {
7391
7642
  if (err.code !== "EEXIST") throw err;
7392
7643
  if (attempt === 0 && lockOwnerIsGone(lockPath)) {
7393
- fs11.rmSync(lockPath, { force: true });
7644
+ fs12.rmSync(lockPath, { force: true });
7394
7645
  continue;
7395
7646
  }
7396
7647
  throw new Error(
@@ -7403,7 +7654,7 @@ function acquireRunLock(stagingRoot) {
7403
7654
  function lockKeyFor(stagingRoot) {
7404
7655
  let key = stagingRoot;
7405
7656
  try {
7406
- key = fs11.realpathSync(stagingRoot);
7657
+ key = fs12.realpathSync(stagingRoot);
7407
7658
  } catch {
7408
7659
  }
7409
7660
  if (process.platform === "win32" || process.platform === "darwin") key = key.toLowerCase();
@@ -7412,7 +7663,7 @@ function lockKeyFor(stagingRoot) {
7412
7663
  function lockOwnerIsGone(lockPath) {
7413
7664
  let raw;
7414
7665
  try {
7415
- raw = fs11.readFileSync(lockPath, "utf8");
7666
+ raw = fs12.readFileSync(lockPath, "utf8");
7416
7667
  } catch {
7417
7668
  return false;
7418
7669
  }
@@ -7432,12 +7683,12 @@ function lockOwnerIsGone(lockPath) {
7432
7683
  }
7433
7684
  function writeManifestAtomically(manifestPath, manifest) {
7434
7685
  const tempPath = `${manifestPath}.${process.pid}.tmp`;
7435
- fs11.writeFileSync(tempPath, JSON.stringify(manifest, null, 2), "utf8");
7686
+ fs12.writeFileSync(tempPath, JSON.stringify(manifest, null, 2), "utf8");
7436
7687
  try {
7437
- fs11.renameSync(tempPath, manifestPath);
7688
+ fs12.renameSync(tempPath, manifestPath);
7438
7689
  } catch (err) {
7439
7690
  try {
7440
- fs11.rmSync(tempPath, { force: true });
7691
+ fs12.rmSync(tempPath, { force: true });
7441
7692
  } catch {
7442
7693
  }
7443
7694
  throw err;
@@ -7460,31 +7711,31 @@ function swapIntoPlace(stagingDir, outDir) {
7460
7711
  }
7461
7712
  function swapOnce(stagingDir, outDir) {
7462
7713
  const backupDir = `${outDir}.backup-${process.pid}-${Date.now()}`;
7463
- const hadPrevious = fs11.existsSync(outDir);
7464
- if (hadPrevious) fs11.renameSync(outDir, backupDir);
7714
+ const hadPrevious = fs12.existsSync(outDir);
7715
+ if (hadPrevious) fs12.renameSync(outDir, backupDir);
7465
7716
  try {
7466
7717
  try {
7467
- fs11.renameSync(stagingDir, outDir);
7718
+ fs12.renameSync(stagingDir, outDir);
7468
7719
  } catch (err) {
7469
7720
  if (err.code !== "EXDEV") throw err;
7470
7721
  const partialDir = `${outDir}.partial-${process.pid}-${Date.now()}`;
7471
7722
  try {
7472
- fs11.cpSync(stagingDir, partialDir, { recursive: true });
7473
- fs11.renameSync(partialDir, outDir);
7474
- fs11.rmSync(stagingDir, { recursive: true, force: true });
7723
+ fs12.cpSync(stagingDir, partialDir, { recursive: true });
7724
+ fs12.renameSync(partialDir, outDir);
7725
+ fs12.rmSync(stagingDir, { recursive: true, force: true });
7475
7726
  } catch (copyErr) {
7476
7727
  try {
7477
- fs11.rmSync(partialDir, { recursive: true, force: true });
7728
+ fs12.rmSync(partialDir, { recursive: true, force: true });
7478
7729
  } catch {
7479
7730
  }
7480
7731
  throw copyErr;
7481
7732
  }
7482
7733
  }
7483
- if (hadPrevious) fs11.rmSync(backupDir, { recursive: true, force: true });
7734
+ if (hadPrevious) fs12.rmSync(backupDir, { recursive: true, force: true });
7484
7735
  } catch (err) {
7485
- if (hadPrevious && fs11.existsSync(backupDir)) {
7486
- if (fs11.existsSync(outDir)) fs11.rmSync(outDir, { recursive: true, force: true });
7487
- fs11.renameSync(backupDir, outDir);
7736
+ if (hadPrevious && fs12.existsSync(backupDir)) {
7737
+ if (fs12.existsSync(outDir)) fs12.rmSync(outDir, { recursive: true, force: true });
7738
+ fs12.renameSync(backupDir, outDir);
7488
7739
  }
7489
7740
  throw err;
7490
7741
  }
@@ -7579,7 +7830,7 @@ function generateSnapshot(configInput, options) {
7579
7830
  // first run cannot have marked them yet, so the name alone keeps a run from recording its own
7580
7831
  // output — but only at these exact paths, not at every directory that shares the name.
7581
7832
  toolOwnedPaths: [config.outDir, config.tmpDir].map(
7582
- (directory) => path12.relative(config.cwd, path12.resolve(config.cwd, directory)).replace(/\\/g, "/")
7833
+ (directory) => path13.relative(config.cwd, path13.resolve(config.cwd, directory)).replace(/\\/g, "/")
7583
7834
  ).filter((relative11) => relative11.length > 0 && !relative11.startsWith(".."))
7584
7835
  });
7585
7836
  const files = [];
@@ -7600,12 +7851,12 @@ function generateSnapshot(configInput, options) {
7600
7851
  let totalSizeBytes = 0;
7601
7852
  let largeFileCount = 0;
7602
7853
  for (const relativePath of collection.files) {
7603
- const absolutePath = path12.join(config.cwd, relativePath);
7854
+ const absolutePath = path13.join(config.cwd, relativePath);
7604
7855
  let stats;
7605
7856
  try {
7606
- stats = fs11.statSync(absolutePath);
7857
+ stats = fs12.statSync(absolutePath);
7607
7858
  if (!stats.isFile()) {
7608
- const nestedRepository = stats.isDirectory() && fs11.existsSync(path12.join(absolutePath, ".git"));
7859
+ const nestedRepository = stats.isDirectory() && fs12.existsSync(path13.join(absolutePath, ".git"));
7609
7860
  skipped.push(
7610
7861
  nestedRepository ? {
7611
7862
  path: relativePath,
@@ -7625,7 +7876,7 @@ function generateSnapshot(configInput, options) {
7625
7876
  }
7626
7877
  let buffer;
7627
7878
  try {
7628
- buffer = fs11.readFileSync(absolutePath);
7879
+ buffer = fs12.readFileSync(absolutePath);
7629
7880
  } catch {
7630
7881
  skipped.push({ path: relativePath, reason: "read-error" });
7631
7882
  continue;
@@ -7955,12 +8206,12 @@ function generateSnapshot(configInput, options) {
7955
8206
  let stagingDir = null;
7956
8207
  try {
7957
8208
  ensureParentDirectory(outDir, "outDir");
7958
- fs11.mkdirSync(tmpDir, { recursive: true });
8209
+ fs12.mkdirSync(tmpDir, { recursive: true });
7959
8210
  cleanStaleRunDirs(tmpDir);
7960
8211
  const snapshotId = crypto3.randomUUID();
7961
8212
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
7962
- stagingDir = path12.join(tmpDir, `${RUN_DIR_PREFIX}${process.pid}-${snapshotId.slice(0, 8)}`);
7963
- fs11.mkdirSync(stagingDir);
8213
+ stagingDir = path13.join(tmpDir, `${RUN_DIR_PREFIX}${process.pid}-${snapshotId.slice(0, 8)}`);
8214
+ fs12.mkdirSync(stagingDir);
7964
8215
  writeOwnershipMarker(stagingDir, {
7965
8216
  generator: GENERATOR_NAME,
7966
8217
  version: GENERATOR_VERSION,
@@ -7970,41 +8221,41 @@ function generateSnapshot(configInput, options) {
7970
8221
  id: snapshotId,
7971
8222
  pid: process.pid
7972
8223
  });
7973
- const partsDir = path12.join(stagingDir, "parts");
7974
- const reportsDir = path12.join(stagingDir, "reports");
7975
- if (artifacts.parts) fs11.mkdirSync(partsDir, { recursive: true });
8224
+ const partsDir = path13.join(stagingDir, "parts");
8225
+ const reportsDir = path13.join(stagingDir, "reports");
8226
+ if (artifacts.parts) fs12.mkdirSync(partsDir, { recursive: true });
7976
8227
  if (artifacts.navigation || artifacts.projectTree || artifacts.audit) {
7977
- fs11.mkdirSync(reportsDir, { recursive: true });
8228
+ fs12.mkdirSync(reportsDir, { recursive: true });
7978
8229
  }
7979
8230
  if (artifacts.parts) {
7980
8231
  for (const part of parts) {
7981
- fs11.writeFileSync(path12.join(partsDir, part.filename), part.markdown, "utf8");
8232
+ fs12.writeFileSync(path13.join(partsDir, part.filename), part.markdown, "utf8");
7982
8233
  }
7983
8234
  }
7984
8235
  if (projectTree !== null) {
7985
- fs11.writeFileSync(path12.join(reportsDir, "project-tree.md"), projectTree, "utf8");
8236
+ fs12.writeFileSync(path13.join(reportsDir, "project-tree.md"), projectTree, "utf8");
7986
8237
  }
7987
8238
  if (artifacts.navigation) {
7988
- fs11.writeFileSync(path12.join(reportsDir, "navigation.md"), generateNavigation(manifest), "utf8");
8239
+ fs12.writeFileSync(path13.join(reportsDir, "navigation.md"), generateNavigation(manifest), "utf8");
7989
8240
  }
7990
8241
  if (artifacts.audit) {
7991
- fs11.writeFileSync(
7992
- path12.join(reportsDir, "audit.md"),
8242
+ fs12.writeFileSync(
8243
+ path13.join(reportsDir, "audit.md"),
7993
8244
  generateAuditReport(manifest, secretFindings, config.secretRules),
7994
8245
  "utf8"
7995
8246
  );
7996
8247
  }
7997
8248
  if (artifacts.readme) {
7998
- fs11.writeFileSync(path12.join(stagingDir, "README.md"), generateReadme(manifest, artifacts), "utf8");
8249
+ fs12.writeFileSync(path13.join(stagingDir, "README.md"), generateReadme(manifest, artifacts), "utf8");
7999
8250
  }
8000
8251
  if (artifacts.manifest) {
8001
- fs11.writeFileSync(path12.join(stagingDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf8");
8252
+ fs12.writeFileSync(path13.join(stagingDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf8");
8002
8253
  }
8003
8254
  if (monolithJson !== null) {
8004
- fs11.writeFileSync(path12.join(stagingDir, "full-codebase.json"), monolithJson, "utf8");
8255
+ fs12.writeFileSync(path13.join(stagingDir, "full-codebase.json"), monolithJson, "utf8");
8005
8256
  }
8006
8257
  if (monolithMarkdown !== null) {
8007
- fs11.writeFileSync(path12.join(stagingDir, "full-codebase.md"), monolithMarkdown, "utf8");
8258
+ fs12.writeFileSync(path13.join(stagingDir, "full-codebase.md"), monolithMarkdown, "utf8");
8008
8259
  }
8009
8260
  writeOwnershipMarker(stagingDir, markerPayload(stagingDir, "complete", snapshotId, createdAt));
8010
8261
  swapIntoPlace(stagingDir, outDir);
@@ -8013,7 +8264,7 @@ function generateSnapshot(configInput, options) {
8013
8264
  const pendingHook = runAfterGenerate(config, manifest);
8014
8265
  const shipHookState = () => {
8015
8266
  if (artifacts.manifest && manifest.warnings.length !== warningsBeforeHook) {
8016
- writeManifestAtomically(path12.join(outDir, "manifest.json"), manifest);
8267
+ writeManifestAtomically(path13.join(outDir, "manifest.json"), manifest);
8017
8268
  }
8018
8269
  writeOwnershipMarker(outDir, markerPayload(outDir, "complete", snapshotId, createdAt));
8019
8270
  };
@@ -8036,7 +8287,7 @@ function generateSnapshot(configInput, options) {
8036
8287
  } catch (err) {
8037
8288
  if (stagingDir !== null) {
8038
8289
  try {
8039
- fs11.rmSync(stagingDir, { recursive: true, force: true });
8290
+ fs12.rmSync(stagingDir, { recursive: true, force: true });
8040
8291
  } catch {
8041
8292
  }
8042
8293
  }
@@ -8048,8 +8299,8 @@ function generateSnapshot(configInput, options) {
8048
8299
  }
8049
8300
 
8050
8301
  // src/mcp/tools.ts
8051
- import * as fs13 from "fs";
8052
- import * as path14 from "path";
8302
+ import * as fs14 from "fs";
8303
+ import * as path15 from "path";
8053
8304
 
8054
8305
  // src/mcp/part.ts
8055
8306
  var FILE_HEADING = "### FILE: ";
@@ -8135,15 +8386,15 @@ function windowText(body, fromLine, lineCount) {
8135
8386
  }
8136
8387
 
8137
8388
  // src/mcp/workspace.ts
8138
- import * as fs12 from "fs";
8139
- import * as path13 from "path";
8389
+ import * as fs13 from "fs";
8390
+ import * as path14 from "path";
8140
8391
  function foldForComparison(value) {
8141
8392
  return process.platform === "win32" || process.platform === "darwin" ? value.toLowerCase() : value;
8142
8393
  }
8143
8394
  function canonicalPath(value) {
8144
- const absolute = path13.resolve(value);
8395
+ const absolute = path14.resolve(value);
8145
8396
  try {
8146
- return fs12.realpathSync(absolute);
8397
+ return fs13.realpathSync(absolute);
8147
8398
  } catch {
8148
8399
  return absolute;
8149
8400
  }
@@ -8151,17 +8402,17 @@ function canonicalPath(value) {
8151
8402
  function isInside2(parent, child) {
8152
8403
  const foldedParent = foldForComparison(parent);
8153
8404
  const foldedChild = foldForComparison(child);
8154
- return foldedChild === foldedParent || foldedChild.startsWith(`${foldedParent}${path13.sep}`);
8405
+ return foldedChild === foldedParent || foldedChild.startsWith(`${foldedParent}${path14.sep}`);
8155
8406
  }
8156
8407
  function resolveRoot(requested, context) {
8157
8408
  if (requested !== void 0 && (typeof requested !== "string" || requested.trim().length === 0)) {
8158
8409
  return { ok: false, message: '"root" must be a non-empty string when provided.' };
8159
8410
  }
8160
8411
  const wanted = typeof requested === "string" ? requested.trim() : context.cwd;
8161
- const absolute = path13.resolve(context.cwd, wanted);
8412
+ const absolute = path14.resolve(context.cwd, wanted);
8162
8413
  let stats;
8163
8414
  try {
8164
- stats = fs12.statSync(absolute);
8415
+ stats = fs13.statSync(absolute);
8165
8416
  } catch {
8166
8417
  return { ok: false, message: `"${wanted}" does not exist, so it cannot be a repository root.` };
8167
8418
  }
@@ -8212,14 +8463,14 @@ async function openWorkspace(root, overrides = {}) {
8212
8463
  }
8213
8464
  var manifestCache = /* @__PURE__ */ new Map();
8214
8465
  function manifestPathFor(workspace) {
8215
- return path13.resolve(workspace.root, workspace.config.outDir, "manifest.json");
8466
+ return path14.resolve(workspace.root, workspace.config.outDir, "manifest.json");
8216
8467
  }
8217
8468
  function readManifest3(workspace) {
8218
8469
  const file = manifestPathFor(workspace);
8219
- const shown = path13.relative(workspace.root, file).split(path13.sep).join("/") || file;
8470
+ const shown = path14.relative(workspace.root, file).split(path14.sep).join("/") || file;
8220
8471
  let stats;
8221
8472
  try {
8222
- stats = fs12.statSync(file);
8473
+ stats = fs13.statSync(file);
8223
8474
  } catch {
8224
8475
  return {
8225
8476
  ok: false,
@@ -8233,7 +8484,7 @@ function readManifest3(workspace) {
8233
8484
  }
8234
8485
  let raw;
8235
8486
  try {
8236
- raw = fs12.readFileSync(file, "utf8");
8487
+ raw = fs13.readFileSync(file, "utf8");
8237
8488
  } catch (error) {
8238
8489
  return {
8239
8490
  ok: false,
@@ -8291,7 +8542,7 @@ function formatBytes(bytes) {
8291
8542
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
8292
8543
  }
8293
8544
  function relativeFor(workspace, absolute) {
8294
- return path14.relative(workspace.root, absolute).split(path14.sep).join("/");
8545
+ return path15.relative(workspace.root, absolute).split(path15.sep).join("/");
8295
8546
  }
8296
8547
  function capped(values, limit = 20) {
8297
8548
  return { count: values.length, sample: values.slice(0, limit) };
@@ -8310,12 +8561,12 @@ function summarizeDrift(drift) {
8310
8561
  function toRelativePath(root, value) {
8311
8562
  const cleaned = value.trim();
8312
8563
  if (cleaned.length === 0) return null;
8313
- if (!path14.isAbsolute(cleaned)) {
8564
+ if (!path15.isAbsolute(cleaned)) {
8314
8565
  return cleaned.replace(/\\/g, "/").replace(/^\.\//, "");
8315
8566
  }
8316
- const relative11 = path14.relative(root, cleaned);
8317
- if (relative11.startsWith("..") || path14.isAbsolute(relative11)) return null;
8318
- return relative11.split(path14.sep).join("/");
8567
+ const relative11 = path15.relative(root, cleaned);
8568
+ if (relative11.startsWith("..") || path15.isAbsolute(relative11)) return null;
8569
+ return relative11.split(path15.sep).join("/");
8319
8570
  }
8320
8571
  function symbolsOf(entry) {
8321
8572
  const summary = entry.summary;
@@ -8526,7 +8777,7 @@ var generateTool = {
8526
8777
  return failure(error instanceof Error ? error.message : String(error));
8527
8778
  }
8528
8779
  forgetManifest(manifestPathFor(workspace));
8529
- const written = relativeFor(workspace, path14.resolve(workspace.root, workspace.config.outDir));
8780
+ const written = relativeFor(workspace, path15.resolve(workspace.root, workspace.config.outDir));
8530
8781
  const lines = [
8531
8782
  `Wrote ${written}/`,
8532
8783
  `Files: ${manifest.counts.totalFiles} included, ${manifest.counts.skippedCount} skipped, ${plural(manifest.counts.partsCount, "part")}`,
@@ -8791,10 +9042,10 @@ var readTool = {
8791
9042
  `${relativePath} is not in the snapshot. Call snapshot_locate to find the path, or snapshot_explain to learn why it was excluded.`
8792
9043
  );
8793
9044
  }
8794
- const partPath = path14.resolve(workspace.root, workspace.config.outDir, "parts", entry.part);
9045
+ const partPath = path15.resolve(workspace.root, workspace.config.outDir, "parts", entry.part);
8795
9046
  let partText;
8796
9047
  try {
8797
- partText = fs13.readFileSync(partPath, "utf8");
9048
+ partText = fs14.readFileSync(partPath, "utf8");
8798
9049
  } catch {
8799
9050
  return failure(
8800
9051
  `${entry.part} could not be read, so the snapshot is damaged. Run snapshot_generate to rebuild it.`
@@ -9056,6 +9307,7 @@ var VALIDATE_OPTIONS = [
9056
9307
  "no-config",
9057
9308
  "discovery",
9058
9309
  "format",
9310
+ "no-update-check",
9059
9311
  "mode",
9060
9312
  "help",
9061
9313
  "version"
@@ -9079,6 +9331,7 @@ var COMMAND_OPTION_SCOPE = {
9079
9331
  "watch",
9080
9332
  "autopilot",
9081
9333
  "no-install",
9334
+ "no-update-check",
9082
9335
  "help",
9083
9336
  "version"
9084
9337
  ],
@@ -9094,6 +9347,7 @@ var COMMAND_OPTION_SCOPE = {
9094
9347
  "skip-artifacts",
9095
9348
  "only-artifacts",
9096
9349
  "no-config",
9350
+ "no-update-check",
9097
9351
  "format",
9098
9352
  "mode",
9099
9353
  "help",
@@ -9111,12 +9365,13 @@ var COMMAND_OPTION_SCOPE = {
9111
9365
  "only-artifacts",
9112
9366
  "no-config",
9113
9367
  "discovery",
9368
+ "no-update-check",
9114
9369
  "format",
9115
9370
  "mode",
9116
9371
  "help",
9117
9372
  "version"
9118
9373
  ],
9119
- diff: ["format", "mode", "no-config", "help", "version"],
9374
+ diff: ["format", "mode", "no-config", "no-update-check", "help", "version"],
9120
9375
  describe: ["format", "mode", "help", "version"],
9121
9376
  init: [
9122
9377
  "cwd",
@@ -9131,6 +9386,7 @@ var COMMAND_OPTION_SCOPE = {
9131
9386
  "yes",
9132
9387
  "force",
9133
9388
  "dry-run",
9389
+ "no-update-check",
9134
9390
  "format",
9135
9391
  "mode",
9136
9392
  "help",
@@ -9154,6 +9410,7 @@ var COMMAND_OPTION_SCOPE = {
9154
9410
  "force",
9155
9411
  "no-install",
9156
9412
  "dry-run",
9413
+ "no-update-check",
9157
9414
  "format",
9158
9415
  "mode",
9159
9416
  "help",
@@ -9586,6 +9843,13 @@ function buildAgentContract() {
9586
9843
  default: false,
9587
9844
  appliesTo: optionAppliesTo("no-install"),
9588
9845
  summary: "Skip installing the dependency before generating: `setup`, or `generate --autopilot` (CI, offline, or a lockfile you do not want a package manager to touch)."
9846
+ },
9847
+ {
9848
+ flag: "--no-update-check",
9849
+ type: "boolean",
9850
+ default: false,
9851
+ appliesTo: optionAppliesTo("no-update-check"),
9852
+ summary: "Skip the once-a-day check for a newer published version. The check is already skipped when stdout is not a terminal, in CI, in a JSON invocation, and in `mcp`, which makes no network requests."
9589
9853
  }
9590
9854
  ],
9591
9855
  presets: PRESETS.map((preset) => ({
@@ -9718,8 +9982,8 @@ function buildAgentContract() {
9718
9982
  }
9719
9983
 
9720
9984
  // src/agent/install-skill.ts
9721
- import * as fs14 from "fs";
9722
- import * as path15 from "path";
9985
+ import * as fs15 from "fs";
9986
+ import * as path16 from "path";
9723
9987
 
9724
9988
  // src/agent/skill.ts
9725
9989
  var PACKAGE_NAME2 = "codebase-snapshot";
@@ -9877,17 +10141,17 @@ var LEGACY_AGENTS_MARKER = "<!-- codebase-snapshot:skill:start -->";
9877
10141
  function targetPath(cwd, target) {
9878
10142
  switch (target) {
9879
10143
  case "claude":
9880
- return path15.join(cwd, ".claude", "skills", SKILL_NAME, "SKILL.md");
10144
+ return path16.join(cwd, ".claude", "skills", SKILL_NAME, "SKILL.md");
9881
10145
  case "cursor":
9882
- return path15.join(cwd, ".cursor", "rules", `${SKILL_NAME}.mdc`);
10146
+ return path16.join(cwd, ".cursor", "rules", `${SKILL_NAME}.mdc`);
9883
10147
  }
9884
10148
  }
9885
10149
  function assertWritableInsideRepository(cwd, filePath) {
9886
- const root = fs14.realpathSync(cwd);
9887
- const shown = path15.relative(root, filePath) || filePath;
10150
+ const root = fs15.realpathSync(cwd);
10151
+ const shown = path16.relative(root, filePath) || filePath;
9888
10152
  let stat = null;
9889
10153
  try {
9890
- stat = fs14.lstatSync(filePath);
10154
+ stat = fs15.lstatSync(filePath);
9891
10155
  } catch {
9892
10156
  stat = null;
9893
10157
  }
@@ -9903,32 +10167,32 @@ function assertWritableInsideRepository(cwd, filePath) {
9903
10167
  }
9904
10168
  let existing = filePath;
9905
10169
  const missing = [];
9906
- while (!fs14.existsSync(existing)) {
9907
- missing.unshift(path15.basename(existing));
9908
- const parent = path15.dirname(existing);
10170
+ while (!fs15.existsSync(existing)) {
10171
+ missing.unshift(path16.basename(existing));
10172
+ const parent = path16.dirname(existing);
9909
10173
  if (parent === existing) break;
9910
10174
  existing = parent;
9911
10175
  }
9912
- const realAncestor = fs14.realpathSync(existing);
9913
- const resolved = missing.length === 0 ? realAncestor : path15.join(realAncestor, ...missing);
9914
- if (resolved !== root && !resolved.startsWith(`${root}${path15.sep}`)) {
10176
+ const realAncestor = fs15.realpathSync(existing);
10177
+ const resolved = missing.length === 0 ? realAncestor : path16.join(realAncestor, ...missing);
10178
+ if (resolved !== root && !resolved.startsWith(`${root}${path16.sep}`)) {
9915
10179
  throw new Error(
9916
10180
  `${REFUSED}: ${shown} resolves outside the repository (${resolved}). Move it back inside ${root}, or remove the link, and run again.`
9917
10181
  );
9918
10182
  }
9919
10183
  }
9920
10184
  function writeIfChanged(target, filePath, content) {
9921
- const existing = fs14.existsSync(filePath) ? fs14.readFileSync(filePath, "utf8") : null;
10185
+ const existing = fs15.existsSync(filePath) ? fs15.readFileSync(filePath, "utf8") : null;
9922
10186
  if (existing === content) return { target, path: filePath, action: "unchanged" };
9923
- fs14.mkdirSync(path15.dirname(filePath), { recursive: true });
9924
- fs14.writeFileSync(filePath, content, "utf8");
10187
+ fs15.mkdirSync(path16.dirname(filePath), { recursive: true });
10188
+ fs15.writeFileSync(filePath, content, "utf8");
9925
10189
  return { target, path: filePath, action: existing === null ? "created" : "updated" };
9926
10190
  }
9927
10191
  function legacyAgentsNote(cwd) {
9928
- const filePath = path15.join(cwd, "AGENTS.md");
10192
+ const filePath = path16.join(cwd, "AGENTS.md");
9929
10193
  try {
9930
- if (!fs14.existsSync(filePath)) return null;
9931
- if (!fs14.readFileSync(filePath, "utf8").includes(LEGACY_AGENTS_MARKER)) return null;
10194
+ if (!fs15.existsSync(filePath)) return null;
10195
+ if (!fs15.readFileSync(filePath, "utf8").includes(LEGACY_AGENTS_MARKER)) return null;
9932
10196
  } catch {
9933
10197
  return null;
9934
10198
  }
@@ -9940,9 +10204,9 @@ function installSkill(cwd, target = "all") {
9940
10204
  const notes = [];
9941
10205
  const wanted = target === "all" ? ["claude", "cursor"] : [target];
9942
10206
  for (const item of wanted) assertWritableInsideRepository(cwd, targetPath(cwd, item));
9943
- const createsSomething = wanted.some((item) => !fs14.existsSync(targetPath(cwd, item)));
10207
+ const createsSomething = wanted.some((item) => !fs15.existsSync(targetPath(cwd, item)));
9944
10208
  if (createsSomething) {
9945
- assertWritableInsideRepository(cwd, path15.join(cwd, ".gitignore"));
10209
+ assertWritableInsideRepository(cwd, path16.join(cwd, ".gitignore"));
9946
10210
  }
9947
10211
  for (const item of wanted) {
9948
10212
  written.push(writeIfChanged(item, targetPath(cwd, item), skill));
@@ -10077,52 +10341,52 @@ function validateArguments(schema, value) {
10077
10341
  }
10078
10342
  return problems;
10079
10343
  }
10080
- function checkValue(path18, schema, value) {
10344
+ function checkValue(path19, schema, value) {
10081
10345
  if (schema.enum && !schema.enum.includes(value)) {
10082
- return [`"${path18}" must be one of: ${schema.enum.join(", ")}`];
10346
+ return [`"${path19}" must be one of: ${schema.enum.join(", ")}`];
10083
10347
  }
10084
10348
  switch (schema.type) {
10085
10349
  case "string": {
10086
- if (typeof value !== "string") return [`"${path18}" must be a string`];
10350
+ if (typeof value !== "string") return [`"${path19}" must be a string`];
10087
10351
  const problems = [];
10088
10352
  if (schema.minLength !== void 0 && value.length < schema.minLength) {
10089
- problems.push(`"${path18}" must be at least ${schema.minLength} character(s)`);
10353
+ problems.push(`"${path19}" must be at least ${schema.minLength} character(s)`);
10090
10354
  }
10091
10355
  if (schema.maxLength !== void 0 && value.length > schema.maxLength) {
10092
- problems.push(`"${path18}" must be at most ${schema.maxLength} character(s)`);
10356
+ problems.push(`"${path19}" must be at most ${schema.maxLength} character(s)`);
10093
10357
  }
10094
10358
  return problems;
10095
10359
  }
10096
10360
  case "number":
10097
10361
  case "integer": {
10098
10362
  if (typeof value !== "number" || Number.isNaN(value)) {
10099
- return [`"${path18}" must be a number`];
10363
+ return [`"${path19}" must be a number`];
10100
10364
  }
10101
10365
  if (schema.type === "integer" && !Number.isInteger(value)) {
10102
- return [`"${path18}" must be an integer`];
10366
+ return [`"${path19}" must be an integer`];
10103
10367
  }
10104
10368
  const problems = [];
10105
10369
  if (schema.minimum !== void 0 && value < schema.minimum) {
10106
- problems.push(`"${path18}" must be >= ${schema.minimum}`);
10370
+ problems.push(`"${path19}" must be >= ${schema.minimum}`);
10107
10371
  }
10108
10372
  if (schema.maximum !== void 0 && value > schema.maximum) {
10109
- problems.push(`"${path18}" must be <= ${schema.maximum}`);
10373
+ problems.push(`"${path19}" must be <= ${schema.maximum}`);
10110
10374
  }
10111
10375
  return problems;
10112
10376
  }
10113
10377
  case "boolean":
10114
- return typeof value === "boolean" ? [] : [`"${path18}" must be a boolean`];
10378
+ return typeof value === "boolean" ? [] : [`"${path19}" must be a boolean`];
10115
10379
  case "array": {
10116
- if (!Array.isArray(value)) return [`"${path18}" must be an array`];
10380
+ if (!Array.isArray(value)) return [`"${path19}" must be an array`];
10117
10381
  if (!schema.items) return [];
10118
10382
  const problems = [];
10119
10383
  value.forEach((item, index) => {
10120
- problems.push(...checkValue(`${path18}[${index}]`, schema.items, item));
10384
+ problems.push(...checkValue(`${path19}[${index}]`, schema.items, item));
10121
10385
  });
10122
10386
  return problems;
10123
10387
  }
10124
10388
  case "object":
10125
- return isJsonObject(value) ? [] : [`"${path18}" must be an object`];
10389
+ return isJsonObject(value) ? [] : [`"${path19}" must be an object`];
10126
10390
  default:
10127
10391
  return [];
10128
10392
  }
@@ -10136,6 +10400,18 @@ function applyDefaults(schema, value) {
10136
10400
  }
10137
10401
  return out;
10138
10402
  }
10403
+ function coerceNumericStrings(schema, value) {
10404
+ const out = { ...value };
10405
+ for (const [key, propertySchema] of Object.entries(schema.properties)) {
10406
+ const raw = out[key];
10407
+ if (typeof raw !== "string") continue;
10408
+ if (propertySchema.type !== "number" && propertySchema.type !== "integer") continue;
10409
+ if (raw.trim().length === 0) continue;
10410
+ const parsed = Number(raw);
10411
+ if (Number.isFinite(parsed)) out[key] = parsed;
10412
+ }
10413
+ return out;
10414
+ }
10139
10415
 
10140
10416
  // src/mcp/server.ts
10141
10417
  function capabilities() {
@@ -10224,7 +10500,8 @@ function createMcpServer(options) {
10224
10500
  if (!isJsonObject(rawArguments)) {
10225
10501
  return errorResponse(id, ERROR_CODES.invalidParams, '"arguments" must be a JSON object.');
10226
10502
  }
10227
- const problems = validateArguments(tool.inputSchema, rawArguments);
10503
+ const supplied = coerceNumericStrings(tool.inputSchema, rawArguments);
10504
+ const problems = validateArguments(tool.inputSchema, supplied);
10228
10505
  if (problems.length > 0) {
10229
10506
  return ok(
10230
10507
  id,
@@ -10236,7 +10513,7 @@ function createMcpServer(options) {
10236
10513
  modern
10237
10514
  );
10238
10515
  }
10239
- const args = applyDefaults(tool.inputSchema, rawArguments);
10516
+ const args = applyDefaults(tool.inputSchema, supplied);
10240
10517
  let outcome;
10241
10518
  try {
10242
10519
  outcome = await tool.handler(args, options.context);
@@ -10405,8 +10682,8 @@ function createMcpServer(options) {
10405
10682
  }
10406
10683
 
10407
10684
  // src/mcp/resources.ts
10408
- import * as fs15 from "fs";
10409
- import * as path16 from "path";
10685
+ import * as fs16 from "fs";
10686
+ import * as path17 from "path";
10410
10687
  var MAX_RESOURCE_BYTES = 512 * 1024;
10411
10688
  var PART_URI = /^snapshot:\/\/parts\/(\d+)$/;
10412
10689
  var REPORT_URIS = /* @__PURE__ */ new Map([
@@ -10440,7 +10717,7 @@ async function workspaceFor(context) {
10440
10717
  }
10441
10718
  function readFileIfPresent(file) {
10442
10719
  try {
10443
- return fs15.readFileSync(file, "utf8");
10720
+ return fs16.readFileSync(file, "utf8");
10444
10721
  } catch {
10445
10722
  return null;
10446
10723
  }
@@ -10519,7 +10796,7 @@ function buildResourceProvider() {
10519
10796
  const report = REPORT_URIS.get(uri);
10520
10797
  if (report) {
10521
10798
  const text2 = readFileIfPresent(
10522
- path16.resolve(workspace.root, workspace.config.outDir, "reports", report.file)
10799
+ path17.resolve(workspace.root, workspace.config.outDir, "reports", report.file)
10523
10800
  );
10524
10801
  if (text2 === null) return null;
10525
10802
  return { uri, mimeType: "text/markdown", text: capUtf8(text2, MAX_RESOURCE_BYTES).text };
@@ -10538,7 +10815,7 @@ function buildResourceProvider() {
10538
10815
  const part = read.manifest.parts.find((candidate) => candidate.index === index);
10539
10816
  if (!part) return null;
10540
10817
  const text2 = readFileIfPresent(
10541
- path16.resolve(workspace.root, workspace.config.outDir, "parts", part.filename)
10818
+ path17.resolve(workspace.root, workspace.config.outDir, "parts", part.filename)
10542
10819
  );
10543
10820
  if (text2 === null) return null;
10544
10821
  return { uri, mimeType: "text/markdown", text: capUtf8(text2, MAX_RESOURCE_BYTES).text };
@@ -10776,6 +11053,7 @@ var CLI_OPTIONS = {
10776
11053
  install: { type: "boolean" },
10777
11054
  "no-install": { type: "boolean" },
10778
11055
  target: { type: "string" },
11056
+ "no-update-check": { type: "boolean" },
10779
11057
  help: { type: "boolean", short: "h" },
10780
11058
  version: { type: "boolean", short: "v" }
10781
11059
  };
@@ -10850,6 +11128,8 @@ Options:
10850
11128
  --install Write the skill into the repository instead of printing
10851
11129
  --target <name> claude | cursor | all (default: all)
10852
11130
 
11131
+ --no-update-check Skip the daily check for a newer published version
11132
+
10853
11133
  -h, --help Display this help message
10854
11134
  -v, --version Display version
10855
11135
 
@@ -10914,10 +11194,10 @@ function parseCliArgs(argv) {
10914
11194
  }
10915
11195
  if (values.cwd !== void 0) {
10916
11196
  const target = String(values.cwd);
10917
- if (!fs16.existsSync(target)) {
11197
+ if (!fs17.existsSync(target)) {
10918
11198
  throw new UsageError(`--cwd directory does not exist: ${target}`);
10919
11199
  }
10920
- if (!fs16.statSync(target).isDirectory()) {
11200
+ if (!fs17.statSync(target).isDirectory()) {
10921
11201
  throw new UsageError(`--cwd is not a directory: ${target}`);
10922
11202
  }
10923
11203
  }
@@ -11063,7 +11343,7 @@ function parseCliArgs(argv) {
11063
11343
  install: values.install === true,
11064
11344
  noInstall: values["no-install"] === true,
11065
11345
  target: values.target === void 0 ? void 0 : String(values.target),
11066
- cwd: values.cwd === void 0 ? process.cwd() : path17.resolve(String(values.cwd)),
11346
+ cwd: values.cwd === void 0 ? process.cwd() : path18.resolve(String(values.cwd)),
11067
11347
  outDir: values["out-dir"] === void 0 ? void 0 : String(values["out-dir"]),
11068
11348
  includeMonolith: values["include-monolith"] === true || onlyNamesMonolith === true ? true : void 0,
11069
11349
  includeSensitiveFiles: values["include-sensitive-files"] === true ? true : void 0,
@@ -11120,24 +11400,24 @@ function splitList(value) {
11120
11400
  return value.split(",").map((entry) => entry.trim()).filter(Boolean);
11121
11401
  }
11122
11402
  function displayOutPath(cwd, outDir, ...segments) {
11123
- const absolute = path17.resolve(cwd, outDir, ...segments);
11124
- const relative11 = path17.relative(cwd, absolute);
11125
- if (relative11 && !relative11.startsWith("..") && !path17.isAbsolute(relative11)) return relative11;
11403
+ const absolute = path18.resolve(cwd, outDir, ...segments);
11404
+ const relative11 = path18.relative(cwd, absolute);
11405
+ if (relative11 && !relative11.startsWith("..") && !path18.isAbsolute(relative11)) return relative11;
11126
11406
  return absolute;
11127
11407
  }
11128
11408
  function nextStepHint(cwd, scriptsAddedNow) {
11129
11409
  let hasScript = scriptsAddedNow;
11130
11410
  if (!hasScript) {
11131
11411
  try {
11132
- const parsed = JSON.parse(fs16.readFileSync(path17.join(cwd, "package.json"), "utf8"));
11412
+ const parsed = JSON.parse(fs17.readFileSync(path18.join(cwd, "package.json"), "utf8"));
11133
11413
  hasScript = typeof parsed.scripts?.snapshot === "string";
11134
11414
  } catch {
11135
11415
  hasScript = false;
11136
11416
  }
11137
11417
  }
11138
11418
  if (!hasScript) return `npx ${GENERATOR_NAME} generate`;
11139
- const bin = path17.join(cwd, "node_modules", ".bin", "codebase-snapshot");
11140
- const installed = fs16.existsSync(bin) || fs16.existsSync(`${bin}.cmd`);
11419
+ const bin = path18.join(cwd, "node_modules", ".bin", "codebase-snapshot");
11420
+ const installed = fs17.existsSync(bin) || fs17.existsSync(`${bin}.cmd`);
11141
11421
  return installed ? "npm run snapshot" : "npm install && npm run snapshot";
11142
11422
  }
11143
11423
  function presetSummary(init) {
@@ -11167,7 +11447,7 @@ async function runInitCommand(invocation) {
11167
11447
  info(result.configText);
11168
11448
  return 0;
11169
11449
  }
11170
- info(`\u2705 Created ${path17.basename(result.configPath)} (${presetSummary(result)})`);
11450
+ info(`\u2705 Created ${path18.basename(result.configPath)} (${presetSummary(result)})`);
11171
11451
  if (result.scripts.length > 0) info(` Added npm scripts: ${result.scripts.join(", ")}`);
11172
11452
  if (result.dependency.added && result.dependency.range !== null) {
11173
11453
  info(` Added devDependency: ${result.dependency.name} ${result.dependency.range}`);
@@ -11187,7 +11467,7 @@ async function runInitCommand(invocation) {
11187
11467
  }
11188
11468
  }
11189
11469
  function detectPackageManager(cwd) {
11190
- const has = (name) => fs16.existsSync(path17.join(cwd, name));
11470
+ const has = (name) => fs17.existsSync(path18.join(cwd, name));
11191
11471
  if (has("bun.lockb") || has("bun.lock")) return { name: "bun", command: "bun", args: ["install"] };
11192
11472
  if (has("pnpm-lock.yaml")) return { name: "pnpm", command: "pnpm", args: ["install"] };
11193
11473
  if (has("yarn.lock")) return { name: "yarn", command: "yarn", args: ["install"] };
@@ -11206,14 +11486,13 @@ function installDependencies(cwd) {
11206
11486
  const manager = detectPackageManager(cwd);
11207
11487
  const command = `${manager.command} ${manager.args.join(" ")}`;
11208
11488
  const started = performance.now();
11209
- const result = spawnSync(manager.command, manager.args, {
11489
+ const spawnOptions = {
11210
11490
  cwd,
11211
11491
  encoding: "utf8",
11212
- // npm, pnpm and yarn ship as `.cmd` shims on Windows, which spawnSync cannot exec directly.
11213
- shell: process.platform === "win32",
11214
11492
  timeout: INSTALL_TIMEOUT_MS,
11215
11493
  env: cleanInstallEnv()
11216
- });
11494
+ };
11495
+ const result = process.platform === "win32" ? spawnSync(command, { ...spawnOptions, shell: true }) : spawnSync(manager.command, manager.args, spawnOptions);
11217
11496
  const seconds = `${((performance.now() - started) / 1e3).toFixed(1)}s`;
11218
11497
  if (result.error) {
11219
11498
  return { manager: manager.name, command, ok: false, detail: `${result.error.message} (${seconds})` };
@@ -11277,7 +11556,7 @@ async function runSetupCommand(invocation, options = {}) {
11277
11556
  }
11278
11557
  info("\n\u{1F9EA} Dry run \u2014 setup would:");
11279
11558
  info(
11280
- ` 1. ${init.reused ? `keep ${path17.basename(init.configPath)}` : `write ${path17.basename(init.configPath)} (preset: ${init.preset})`}`
11559
+ ` 1. ${init.reused ? `keep ${path18.basename(init.configPath)}` : `write ${path18.basename(init.configPath)} (preset: ${init.preset})`}`
11281
11560
  );
11282
11561
  info(" 2. add the npm scripts, the devDependency and the .gitignore entries");
11283
11562
  if (manager !== null) info(` 3. install with ${manager}`);
@@ -11289,9 +11568,9 @@ async function runSetupCommand(invocation, options = {}) {
11289
11568
  if (invocation.format !== "json") {
11290
11569
  if (!interactive) info(`\u{1F680} Setup for: ${invocation.cwd}`);
11291
11570
  if (init.reused) {
11292
- info(`\u267B Keeping ${path17.basename(init.configPath)} (${presetSummary(init)})`);
11571
+ info(`\u267B Keeping ${path18.basename(init.configPath)} (${presetSummary(init)})`);
11293
11572
  } else {
11294
- info(`\u2705 Created ${path17.basename(init.configPath)} (${presetSummary(init)})`);
11573
+ info(`\u2705 Created ${path18.basename(init.configPath)} (${presetSummary(init)})`);
11295
11574
  }
11296
11575
  if (init.scripts.length > 0) info(` Added npm scripts: ${init.scripts.join(", ")}`);
11297
11576
  if (init.dependency.added && init.dependency.range !== null) {
@@ -11399,7 +11678,7 @@ function runSkillCommand(invocation) {
11399
11678
  }
11400
11679
  info(`\u2705 Agent skill installed (${SKILL_NAME}):`);
11401
11680
  for (const item of result.written) {
11402
- const shown = path17.relative(invocation.cwd, item.path) || item.path;
11681
+ const shown = path18.relative(invocation.cwd, item.path) || item.path;
11403
11682
  info(` - ${item.action.padEnd(9)} ${shown}`);
11404
11683
  }
11405
11684
  if (result.gitignored.length > 0) {
@@ -11463,6 +11742,17 @@ function requestsJsonFormat(argv) {
11463
11742
  return format === "json";
11464
11743
  }
11465
11744
  async function main(argv = process.argv.slice(2)) {
11745
+ const pending = process.stdout.isTTY === true && shouldCheck(argv, process.env) ? checkForUpdate({ current: GENERATOR_VERSION, cacheFile: cacheFilePath() }) : null;
11746
+ const code = await runCommand(argv);
11747
+ if (pending) {
11748
+ const notice = await pending;
11749
+ if (notice) process.stderr.write(`
11750
+ ${formatUpdateNotice(notice)}
11751
+ `);
11752
+ }
11753
+ return code;
11754
+ }
11755
+ async function runCommand(argv) {
11466
11756
  let invocation;
11467
11757
  try {
11468
11758
  invocation = parseCliArgs(argv);
@@ -11495,7 +11785,7 @@ ${USAGE}
11495
11785
  return runSkillCommand(invocation);
11496
11786
  }
11497
11787
  if (invocation.command === "mcp") {
11498
- return await runStdioServer({ cwd: path17.resolve(invocation.cwd) });
11788
+ return await runStdioServer({ cwd: path18.resolve(invocation.cwd) });
11499
11789
  }
11500
11790
  if (invocation.command === "setup") {
11501
11791
  return runSetupCommand(invocation);
@@ -11512,7 +11802,7 @@ ${USAGE}
11512
11802
  warn("\u274C The config file could not be read. Fix it, or delete it to use the defaults.");
11513
11803
  return 1;
11514
11804
  }
11515
- if (loaded.file) info(`\u2699 Using config ${path17.relative(process.cwd(), loaded.file) || loaded.file}`);
11805
+ if (loaded.file) info(`\u2699 Using config ${path18.relative(process.cwd(), loaded.file) || loaded.file}`);
11516
11806
  const resolved = resolveConfig(
11517
11807
  loaded.config,
11518
11808
  {
@@ -11534,10 +11824,10 @@ ${USAGE}
11534
11824
  if (invocation.command === "validate") {
11535
11825
  const result = validateSnapshot(resolved);
11536
11826
  if (result.valid) {
11537
- const manifestPath = path17.resolve(resolved.cwd, resolved.outDir, "manifest.json");
11827
+ const manifestPath = path18.resolve(resolved.cwd, resolved.outDir, "manifest.json");
11538
11828
  let manifest;
11539
11829
  try {
11540
- manifest = JSON.parse(fs16.readFileSync(manifestPath, "utf8"));
11830
+ manifest = JSON.parse(fs17.readFileSync(manifestPath, "utf8"));
11541
11831
  } catch {
11542
11832
  manifest = void 0;
11543
11833
  }
@@ -11550,13 +11840,13 @@ ${USAGE}
11550
11840
  return result.valid ? 0 : 1;
11551
11841
  }
11552
11842
  if (invocation.command === "report") {
11553
- const manifestPath = path17.resolve(resolved.cwd, resolved.outDir, "manifest.json");
11554
- if (!fs16.existsSync(manifestPath)) {
11843
+ const manifestPath = path18.resolve(resolved.cwd, resolved.outDir, "manifest.json");
11844
+ if (!fs17.existsSync(manifestPath)) {
11555
11845
  return fail(invocation.format, `Manifest not found at ${manifestPath}. Run generate first.`);
11556
11846
  }
11557
11847
  let manifest;
11558
11848
  try {
11559
- manifest = JSON.parse(fs16.readFileSync(manifestPath, "utf8"));
11849
+ manifest = JSON.parse(fs17.readFileSync(manifestPath, "utf8"));
11560
11850
  } catch (err) {
11561
11851
  return fail(invocation.format, `Could not read ${manifestPath}: ${err.message}`);
11562
11852
  }
@@ -11720,20 +12010,20 @@ function finishWatchRun(state, now) {
11720
12010
  };
11721
12011
  }
11722
12012
  function comparablePath(value) {
11723
- const absolute = path17.resolve(value);
12013
+ const absolute = path18.resolve(value);
11724
12014
  return process.platform === "win32" ? absolute.toLowerCase() : absolute;
11725
12015
  }
11726
12016
  function isSameOrInside(parent, candidate) {
11727
- const relative11 = path17.relative(parent, candidate);
11728
- return relative11 === "" || relative11 !== ".." && !relative11.startsWith(`..${path17.sep}`) && !path17.isAbsolute(relative11);
12017
+ const relative11 = path18.relative(parent, candidate);
12018
+ return relative11 === "" || relative11 !== ".." && !relative11.startsWith(`..${path18.sep}`) && !path18.isAbsolute(relative11);
11729
12019
  }
11730
12020
  function isGeneratedWatchPath(candidate, paths) {
11731
- const absolute = comparablePath(path17.resolve(paths.cwd, candidate));
11732
- const outDir = comparablePath(path17.resolve(paths.cwd, paths.outDir));
11733
- const tmpDir = comparablePath(path17.resolve(paths.cwd, paths.tmpDir));
12021
+ const absolute = comparablePath(path18.resolve(paths.cwd, candidate));
12022
+ const outDir = comparablePath(path18.resolve(paths.cwd, paths.outDir));
12023
+ const tmpDir = comparablePath(path18.resolve(paths.cwd, paths.tmpDir));
11734
12024
  if (isSameOrInside(outDir, absolute) || isSameOrInside(tmpDir, absolute)) return true;
11735
- const parent = path17.dirname(absolute);
11736
- if (parent === path17.dirname(outDir) && path17.basename(absolute).startsWith(`${path17.basename(outDir)}.backup-`)) {
12025
+ const parent = path18.dirname(absolute);
12026
+ if (parent === path18.dirname(outDir) && path18.basename(absolute).startsWith(`${path18.basename(outDir)}.backup-`)) {
11737
12027
  return true;
11738
12028
  }
11739
12029
  return absolute.split(/[\\/]+/).some((segment) => VCS_SEGMENTS.has(segment));
@@ -11750,8 +12040,8 @@ function decideWatchEvent(state, event, paths) {
11750
12040
  return { state, action: "schedule" };
11751
12041
  }
11752
12042
  async function runWatchLoop(invocation, resolved) {
11753
- const outDir = path17.resolve(resolved.cwd, resolved.outDir);
11754
- const tmpDir = path17.resolve(resolved.cwd, resolved.tmpDir);
12043
+ const outDir = path18.resolve(resolved.cwd, resolved.outDir);
12044
+ const tmpDir = path18.resolve(resolved.cwd, resolved.tmpDir);
11755
12045
  const paths = { cwd: resolved.cwd, outDir, tmpDir };
11756
12046
  let state = initialWatchState();
11757
12047
  let timer = null;
@@ -11816,11 +12106,11 @@ async function runWatchLoop(invocation, resolved) {
11816
12106
  };
11817
12107
  info("\u{1F440} Watching for changes. Press Ctrl+C to stop.");
11818
12108
  void regenerate();
11819
- const watcher = fs16.watch(resolved.cwd, { recursive: true }, (_event, filename) => {
12109
+ const watcher = fs17.watch(resolved.cwd, { recursive: true }, (_event, filename) => {
11820
12110
  const decision = decideWatchEvent(
11821
12111
  state,
11822
12112
  {
11823
- path: filename ? path17.resolve(resolved.cwd, filename.toString()) : null,
12113
+ path: filename ? path18.resolve(resolved.cwd, filename.toString()) : null,
11824
12114
  now: performance.now()
11825
12115
  },
11826
12116
  paths
@@ -11848,7 +12138,7 @@ async function runWatchLoop(invocation, resolved) {
11848
12138
  return 0;
11849
12139
  }
11850
12140
  var entryFile = process.argv[1] ?? "";
11851
- var entryName = path17.basename(entryFile).toLowerCase();
12141
+ var entryName = path18.basename(entryFile).toLowerCase();
11852
12142
  var invokedDirectly = entryName === "cli.js" || entryName === "cli.cjs";
11853
12143
  if (invokedDirectly) {
11854
12144
  void main().then(