@basou/cli 0.52.0 → 0.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -725,8 +725,8 @@ ${block}${markers.end}
725
725
  return `${section.before}${markers.start}
726
726
  ${block}${markers.end}${section.after}`;
727
727
  case "no_markers": {
728
- const sep2 = existing.endsWith("\n\n") ? "" : existing.endsWith("\n") ? "\n" : "\n\n";
729
- return `${existing}${sep2}${wrapped}`;
728
+ const sep4 = existing.endsWith("\n\n") ? "" : existing.endsWith("\n") ? "\n" : "\n\n";
729
+ return `${existing}${sep4}${wrapped}`;
730
730
  }
731
731
  default:
732
732
  throw new Error(
@@ -4876,6 +4876,9 @@ async function resolveRepositoryRootForInit(cwd) {
4876
4876
  }
4877
4877
 
4878
4878
  // src/commands/note.ts
4879
+ import { readFile as readFile4 } from "fs/promises";
4880
+ import { homedir as homedir9 } from "os";
4881
+ import { resolve as resolve8 } from "path";
4879
4882
  import {
4880
4883
  acquireLock as acquireLock4,
4881
4884
  appendEventToExistingSession as appendEventToExistingSession2,
@@ -4886,7 +4889,8 @@ import {
4886
4889
  findErrorCode as findErrorCode7,
4887
4890
  LOCAL_CLI_EVENT_SOURCE as LOCAL_CLI_EVENT_SOURCE3,
4888
4891
  readManifest as readManifest6,
4889
- resolveSessionId as resolveSessionId2
4892
+ resolveSessionId as resolveSessionId2,
4893
+ sanitizePath as sanitizePath2
4890
4894
  } from "@basou/core";
4891
4895
  import { InvalidArgumentError as InvalidArgumentError3 } from "commander";
4892
4896
  var NOTE_SUBCOMMAND_LOOKALIKES = /* @__PURE__ */ new Set([
@@ -4904,11 +4908,33 @@ var NOTE_SUBCOMMAND_LOOKALIKES = /* @__PURE__ */ new Set([
4904
4908
  ]);
4905
4909
  var LABEL_BODY_MAX = 80;
4906
4910
  var LABEL_TRUNCATE_HEAD2 = LABEL_BODY_MAX - 3;
4911
+ var NOTE_HELP = `
4912
+ Text that contains backticks, $(...), $VAR or ! is safest on stdin through a
4913
+ heredoc whose delimiter is QUOTED: the shell then passes the text through
4914
+ untouched. Inside double quotes the shell runs backticks and $(...) as commands
4915
+ and records their output in place of the text, without any error.
4916
+
4917
+ Example (heredoc on stdin):
4918
+ basou note <<'EOF'
4919
+ Next: rebase \`topic\` onto main, then rerun the $CI job.
4920
+ EOF
4921
+
4922
+ Keep the text on its own lines: words on the same line as <<'EOF' are ordinary
4923
+ shell words, not part of the quoted text. 'basou note -' does not read stdin;
4924
+ omit the argument instead.
4925
+
4926
+ Trailing newlines in text read from stdin or --file are dropped (a heredoc
4927
+ always ends with one); everything else is recorded exactly as read.
4928
+ `;
4929
+ var HEREDOC_EXAMPLE = [" basou note <<'EOF'", " <your note>", " EOF"].join("\n");
4930
+ var NO_INPUT_HINT2 = `No note text. Pass it on stdin through a quoted heredoc, with the text on its own lines:
4931
+ ${HEREDOC_EXAMPLE}
4932
+ or pass it as an argument, or with --file <path>.`;
4907
4933
  function registerNoteCommand(program2) {
4908
- program2.command("note").description("Record a free-text note (orientation surfaces the latest as the next step)").argument("<body>", "Note text", parseBody).option(
4934
+ program2.command("note").description("Record a free-text note (orientation surfaces the latest as the next step)").argument("[body]", "Note text (omit it to read the text from stdin or --file)", parseBody).option("--file <path>", "Read the note text from a file instead of the argument or stdin").option(
4909
4935
  "--session <session_id>",
4910
4936
  "Attach to an existing session; otherwise an ad-hoc session is created"
4911
- ).option("--json", "Output the result as JSON").option("-v, --verbose", "Show error causes").action(async (body, options) => {
4937
+ ).option("--json", "Output the result as JSON").option("-v, --verbose", "Show error causes").addHelpText("after", NOTE_HELP).action(async (body, options) => {
4912
4938
  await runNote(body, options);
4913
4939
  });
4914
4940
  }
@@ -4923,17 +4949,29 @@ async function runNote(body, options, ctx = {}) {
4923
4949
  process.exitCode = 1;
4924
4950
  }
4925
4951
  }
4926
- async function doRunNote(body, options, ctx) {
4952
+ async function doRunNote(bodyArgument, options, ctx) {
4953
+ const cwd = ctx.cwd ?? process.cwd();
4954
+ const { body, source } = await readNoteBody(bodyArgument, options, ctx, cwd);
4955
+ if (source === "stdin" && body.trim().length === 0) {
4956
+ throw new Error(NO_INPUT_HINT2);
4957
+ }
4927
4958
  if (body.trim().length === 0) {
4928
4959
  throw new Error("Note body must not be empty");
4929
4960
  }
4930
4961
  const reserved = body.trim().toLowerCase();
4931
4962
  if (NOTE_SUBCOMMAND_LOOKALIKES.has(reserved)) {
4932
4963
  throw new Error(
4933
- `'basou note' records a free-text note and has no '${body.trim()}' subcommand. To record a note, pass its full text (e.g. \`basou note "<your note>"\`).`
4964
+ `'basou note' records a free-text note and has no '${body.trim()}' subcommand. To record a note, pass its full text, e.g. on stdin through a quoted heredoc, with the text on its own lines:
4965
+ ${HEREDOC_EXAMPLE}`
4966
+ );
4967
+ }
4968
+ if (reserved === "-") {
4969
+ throw new Error(
4970
+ source === "argument" ? `'basou note -' does not read stdin; it would record '-' as the note. To pass the note on stdin, omit the argument:
4971
+ ${HEREDOC_EXAMPLE}` : `The note text is just '-', which would be recorded as the next step. Write the note itself, e.g.:
4972
+ ${HEREDOC_EXAMPLE}`
4934
4973
  );
4935
4974
  }
4936
- const cwd = ctx.cwd ?? process.cwd();
4937
4975
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "note");
4938
4976
  const paths = basouPaths11(repositoryRoot);
4939
4977
  await assertWorkspaceInitialized7(paths.root);
@@ -4972,7 +5010,7 @@ async function doRunNote(body, options, ctx) {
4972
5010
  workingDirectory: repositoryRoot,
4973
5011
  invocation: {
4974
5012
  command: "basou note",
4975
- args: [body]
5013
+ args: noteInvocationArgs({ body, source, file: options.file, cwd, repositoryRoot })
4976
5014
  },
4977
5015
  targetEventBuilders: [
4978
5016
  (sessionId, eventId) => buildNoteEvent({ eventId, sessionId, occurredAt, body })
@@ -5005,6 +5043,64 @@ function buildAdHocLabel2(body) {
5005
5043
  const truncated = oneLine3.length > LABEL_BODY_MAX ? `${oneLine3.slice(0, LABEL_TRUNCATE_HEAD2)}...` : oneLine3;
5006
5044
  return `Ad-hoc note: ${truncated}`;
5007
5045
  }
5046
+ async function readNoteBody(bodyArgument, options, ctx, cwd) {
5047
+ if (bodyArgument !== void 0 && options.file !== void 0) {
5048
+ throw new Error("Pass the note text either as an argument or with --file, not both.");
5049
+ }
5050
+ if (bodyArgument !== void 0) {
5051
+ return { body: bodyArgument, source: "argument" };
5052
+ }
5053
+ if (options.file !== void 0) {
5054
+ let raw;
5055
+ try {
5056
+ raw = await readFile4(resolve8(cwd, options.file), "utf8");
5057
+ } catch (error) {
5058
+ if (findErrorCode7(error, "ENOENT")) {
5059
+ throw new Error("--file names a file that does not exist", { cause: error });
5060
+ }
5061
+ if (findErrorCode7(error, "EISDIR")) {
5062
+ throw new Error("--file names a directory, not a file", { cause: error });
5063
+ }
5064
+ throw new Error("Could not read the file --file names", { cause: error });
5065
+ }
5066
+ return { body: dropTrailingNewlines(raw), source: "file" };
5067
+ }
5068
+ if (ctx.readInput !== void 0) {
5069
+ return { body: dropTrailingNewlines(await ctx.readInput()), source: "stdin" };
5070
+ }
5071
+ if (process.stdin.isTTY === true) {
5072
+ throw new Error(NO_INPUT_HINT2);
5073
+ }
5074
+ return { body: dropTrailingNewlines(await readStdinToEnd2()), source: "stdin" };
5075
+ }
5076
+ function dropTrailingNewlines(text) {
5077
+ let end = text.length;
5078
+ while (end > 0 && text[end - 1] === "\n") {
5079
+ end -= 1;
5080
+ if (end > 0 && text[end - 1] === "\r") end -= 1;
5081
+ }
5082
+ return text.slice(0, end);
5083
+ }
5084
+ async function readStdinToEnd2() {
5085
+ const chunks = [];
5086
+ for await (const chunk of process.stdin) {
5087
+ chunks.push(Buffer.from(chunk));
5088
+ }
5089
+ return Buffer.concat(chunks).toString("utf8");
5090
+ }
5091
+ function noteInvocationArgs(input) {
5092
+ if (input.source === "argument") return [input.body];
5093
+ if (input.source === "file" && input.file !== void 0) {
5094
+ return [
5095
+ "--file",
5096
+ sanitizePath2(resolve8(input.cwd, input.file), {
5097
+ workingDirectory: input.repositoryRoot,
5098
+ homedir: homedir9()
5099
+ })
5100
+ ];
5101
+ }
5102
+ return [];
5103
+ }
5008
5104
  function parseBody(raw) {
5009
5105
  if (raw.trim().length === 0) {
5010
5106
  throw new InvalidArgumentError3("Note body must not be empty");
@@ -5155,7 +5251,7 @@ import {
5155
5251
  writeFileSync,
5156
5252
  writeSync
5157
5253
  } from "fs";
5158
- import { basename as basename6, dirname as dirname4, isAbsolute as isAbsolute4, join as join12, relative as relative2, resolve as resolve8 } from "path";
5254
+ import { basename as basename6, dirname as dirname4, isAbsolute as isAbsolute4, join as join12, relative as relative2, resolve as resolve9 } from "path";
5159
5255
  import {
5160
5256
  appendBasouGitignore as appendBasouGitignore2,
5161
5257
  basouPaths as basouPaths12,
@@ -5530,7 +5626,7 @@ async function runProjectAdopt(options, ctx = {}) {
5530
5626
  }
5531
5627
  }
5532
5628
  function classifySourceRoot(repositoryRoot, declaredPath) {
5533
- const absolute = resolve8(repositoryRoot, declaredPath);
5629
+ const absolute = resolve9(repositoryRoot, declaredPath);
5534
5630
  let real;
5535
5631
  try {
5536
5632
  real = realpathSync(absolute);
@@ -5637,7 +5733,7 @@ async function gatherRepoWiring(repositoryRoot, entry) {
5637
5733
  };
5638
5734
  let real;
5639
5735
  try {
5640
- real = realpathSync(resolve8(repositoryRoot, entry.path));
5736
+ real = realpathSync(resolve9(repositoryRoot, entry.path));
5641
5737
  } catch {
5642
5738
  return { ...base, reachable: false, instructionFiles: [] };
5643
5739
  }
@@ -5756,7 +5852,7 @@ function gatherRepoGitignore(repositoryRoot, entry) {
5756
5852
  };
5757
5853
  let real;
5758
5854
  try {
5759
- real = realpathSync(resolve8(repositoryRoot, entry.path));
5855
+ real = realpathSync(resolve9(repositoryRoot, entry.path));
5760
5856
  } catch {
5761
5857
  return { ...base, reachable: false, currentLines: [] };
5762
5858
  }
@@ -5777,7 +5873,7 @@ function readGitignoreLines(file) {
5777
5873
  }
5778
5874
  }
5779
5875
  function applyGitignorePlan(repositoryRoot, plan) {
5780
- const file = join12(realpathSync(resolve8(repositoryRoot, plan.path)), ".gitignore");
5876
+ const file = join12(realpathSync(resolve9(repositoryRoot, plan.path)), ".gitignore");
5781
5877
  let existing = "";
5782
5878
  try {
5783
5879
  existing = readFileSync(file, "utf8");
@@ -5786,9 +5882,9 @@ function applyGitignorePlan(repositoryRoot, plan) {
5786
5882
  throw new Error("Failed to read .gitignore", { cause: error });
5787
5883
  }
5788
5884
  }
5789
- const sep2 = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
5885
+ const sep4 = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
5790
5886
  try {
5791
- writeFileSync(file, `${existing}${sep2}${plan.toAdd.join("\n")}
5887
+ writeFileSync(file, `${existing}${sep4}${plan.toAdd.join("\n")}
5792
5888
  `);
5793
5889
  } catch (error) {
5794
5890
  throw new Error("Failed to write .gitignore", { cause: error });
@@ -5912,7 +6008,7 @@ function gatherRepoSymlinks(repositoryRoot, anchorReal, entry) {
5912
6008
  const base = { path: entry.path, ...isSelf ? { self: true } : {} };
5913
6009
  let real;
5914
6010
  try {
5915
- real = realpathSync(resolve8(repositoryRoot, entry.path));
6011
+ real = realpathSync(resolve9(repositoryRoot, entry.path));
5916
6012
  } catch {
5917
6013
  return { ...base, isAnchor: false, reachable: false, canonicalPresent: false, files: [] };
5918
6014
  }
@@ -5984,7 +6080,7 @@ function gatherRepoSymlinks(repositoryRoot, anchorReal, entry) {
5984
6080
  function applySymlinkPlan(repositoryRoot, plan) {
5985
6081
  let real;
5986
6082
  try {
5987
- real = realpathSync(resolve8(repositoryRoot, plan.path));
6083
+ real = realpathSync(resolve9(repositoryRoot, plan.path));
5988
6084
  } catch (error) {
5989
6085
  const message = failureReason(error);
5990
6086
  return { created: [], failed: plan.toCreate.map((c) => ({ file: c.name, message })) };
@@ -6010,9 +6106,9 @@ function viewCanonicalCollision(repositoryRoot, roster, viewName) {
6010
6106
  for (const entry of roster) {
6011
6107
  let name;
6012
6108
  try {
6013
- name = basename6(realpathSync(resolve8(repositoryRoot, entry.path)));
6109
+ name = basename6(realpathSync(resolve9(repositoryRoot, entry.path)));
6014
6110
  } catch {
6015
- name = basename6(resolve8(repositoryRoot, entry.path));
6111
+ name = basename6(resolve9(repositoryRoot, entry.path));
6016
6112
  }
6017
6113
  if (name === viewName) return entry.path;
6018
6114
  }
@@ -6259,7 +6355,7 @@ async function runProjectWorkspace(options, ctx = {}) {
6259
6355
  }
6260
6356
  }
6261
6357
  function resolveViewDir(repositoryRoot, viewPath) {
6262
- const abs = resolve8(repositoryRoot, viewPath);
6358
+ const abs = resolve9(repositoryRoot, viewPath);
6263
6359
  try {
6264
6360
  return realpathSync(abs);
6265
6361
  } catch {
@@ -6273,7 +6369,7 @@ function resolveViewDir(repositoryRoot, viewPath) {
6273
6369
  function gatherViewRepo(repositoryRoot, viewDir, entry) {
6274
6370
  let repoReal;
6275
6371
  try {
6276
- repoReal = realpathSync(resolve8(repositoryRoot, entry.path));
6372
+ repoReal = realpathSync(resolve9(repositoryRoot, entry.path));
6277
6373
  } catch {
6278
6374
  return { path: entry.path, reachable: false };
6279
6375
  }
@@ -6325,7 +6421,7 @@ function classifyViewLink(viewDir, name, rosterRealpaths) {
6325
6421
  } catch {
6326
6422
  return null;
6327
6423
  }
6328
- const resolved = isAbsolute4(target) ? target : resolve8(viewDir, target);
6424
+ const resolved = isAbsolute4(target) ? target : resolve9(viewDir, target);
6329
6425
  try {
6330
6426
  if (rosterRealpaths.has(realpathSync(resolved))) return null;
6331
6427
  } catch {
@@ -6411,11 +6507,11 @@ async function doRunProjectWorkspace(options, ctx) {
6411
6507
  } else {
6412
6508
  const viewDir = resolveViewDir(repositoryRoot, viewPath);
6413
6509
  const facts = roster.map((entry) => gatherViewRepo(repositoryRoot, viewDir, entry));
6414
- const rosterNames = roster.map((entry) => basename6(resolve8(repositoryRoot, entry.path)));
6510
+ const rosterNames = roster.map((entry) => basename6(resolve9(repositoryRoot, entry.path)));
6415
6511
  const rosterRealpaths = /* @__PURE__ */ new Set();
6416
6512
  for (const entry of roster) {
6417
6513
  try {
6418
- rosterRealpaths.add(realpathSync(resolve8(repositoryRoot, entry.path)));
6514
+ rosterRealpaths.add(realpathSync(resolve9(repositoryRoot, entry.path)));
6419
6515
  } catch {
6420
6516
  }
6421
6517
  }
@@ -6595,7 +6691,7 @@ async function gatherRepoPreset(repositoryRoot, anchorReal, entry) {
6595
6691
  }
6596
6692
  let real;
6597
6693
  try {
6598
- real = realpathSync(resolve8(repositoryRoot, entry.path));
6694
+ real = realpathSync(resolve9(repositoryRoot, entry.path));
6599
6695
  } catch {
6600
6696
  return { ...declared, isAnchor: false, reachable: false, canonicalPresent: false };
6601
6697
  }
@@ -6651,7 +6747,7 @@ function viewPresetReposFor(repositoryRoot, roster) {
6651
6747
  anchorReal = void 0;
6652
6748
  }
6653
6749
  return roster.map((entry) => {
6654
- const abs = resolve8(repositoryRoot, entry.path);
6750
+ const abs = resolve9(repositoryRoot, entry.path);
6655
6751
  let real;
6656
6752
  try {
6657
6753
  real = realpathSync(abs);
@@ -6975,7 +7071,7 @@ function gatherArchiveTeardown(repositoryRoot, manifest, target) {
6975
7071
  };
6976
7072
  let real;
6977
7073
  try {
6978
- real = realpathSync(resolve8(repositoryRoot, target));
7074
+ real = realpathSync(resolve9(repositoryRoot, target));
6979
7075
  } catch {
6980
7076
  return empty;
6981
7077
  }
@@ -7024,7 +7120,7 @@ function viewLinkPointsAt(viewDir, name, repoReal) {
7024
7120
  if (!lstatSync(filePath).isSymbolicLink()) return false;
7025
7121
  const target = readlinkSync(filePath);
7026
7122
  if (isAbsolute4(target)) return false;
7027
- return realpathSync(resolve8(viewDir, target)) === repoReal;
7123
+ return realpathSync(resolve9(viewDir, target)) === repoReal;
7028
7124
  } catch {
7029
7125
  return false;
7030
7126
  }
@@ -7035,7 +7131,7 @@ function viewLinkPointsAtPath(viewDir, name, expectedRepoPath) {
7035
7131
  if (!lstatSync(filePath).isSymbolicLink()) return false;
7036
7132
  const target = readlinkSync(filePath);
7037
7133
  if (isAbsolute4(target)) return false;
7038
- return resolve8(viewDir, target) === expectedRepoPath;
7134
+ return resolve9(viewDir, target) === expectedRepoPath;
7039
7135
  } catch {
7040
7136
  return false;
7041
7137
  }
@@ -7044,19 +7140,19 @@ function gatherRepoTeardown(repositoryRoot, manifest, target) {
7044
7140
  const anchorReal = realpathSync(repositoryRoot);
7045
7141
  let repoReal;
7046
7142
  try {
7047
- repoReal = realpathSync(resolve8(repositoryRoot, target));
7143
+ repoReal = realpathSync(resolve9(repositoryRoot, target));
7048
7144
  } catch {
7049
7145
  repoReal = void 0;
7050
7146
  }
7051
7147
  const isAnchor = repoReal !== void 0 && repoReal === anchorReal;
7052
- const targetAbs = resolve8(repositoryRoot, target);
7148
+ const targetAbs = resolve9(repositoryRoot, target);
7053
7149
  const canonicalName = basename6(repoReal ?? targetAbs);
7054
7150
  const roster = manifest.repos ?? [];
7055
7151
  const declaredEntry = roster.find((r) => {
7056
7152
  try {
7057
- return realpathSync(resolve8(repositoryRoot, r.path)) === (repoReal ?? "\0");
7153
+ return realpathSync(resolve9(repositoryRoot, r.path)) === (repoReal ?? "\0");
7058
7154
  } catch {
7059
- return resolve8(repositoryRoot, r.path) === targetAbs;
7155
+ return resolve9(repositoryRoot, r.path) === targetAbs;
7060
7156
  }
7061
7157
  });
7062
7158
  const inRoster = declaredEntry !== void 0;
@@ -7065,7 +7161,7 @@ function gatherRepoTeardown(repositoryRoot, manifest, target) {
7065
7161
  const canonicalShared = roster.some((r) => {
7066
7162
  let rReal = null;
7067
7163
  try {
7068
- rReal = realpathSync(resolve8(repositoryRoot, r.path));
7164
+ rReal = realpathSync(resolve9(repositoryRoot, r.path));
7069
7165
  } catch {
7070
7166
  rReal = null;
7071
7167
  }
@@ -7073,8 +7169,8 @@ function gatherRepoTeardown(repositoryRoot, manifest, target) {
7073
7169
  if (repoReal !== void 0 && rReal === repoReal) return false;
7074
7170
  return basename6(rReal).toLowerCase() === cnFold;
7075
7171
  }
7076
- if (resolve8(repositoryRoot, r.path) === targetAbs) return false;
7077
- return basename6(resolve8(repositoryRoot, r.path)).toLowerCase() === cnFold;
7172
+ if (resolve9(repositoryRoot, r.path) === targetAbs) return false;
7173
+ return basename6(resolve9(repositoryRoot, r.path)).toLowerCase() === cnFold;
7078
7174
  });
7079
7175
  const collisionNote = "shared with another repo of the same basename, so it cannot be removed (check manually)";
7080
7176
  const items = [];
@@ -7255,7 +7351,7 @@ function applyRepoTeardown(repositoryRoot, manifest, plan) {
7255
7351
  const changed = (label) => failed.push({ label, message: "the state changed since the scan (re-run)" });
7256
7352
  let currentRepoReal = null;
7257
7353
  try {
7258
- currentRepoReal = realpathSync(resolve8(repositoryRoot, plan.target));
7354
+ currentRepoReal = realpathSync(resolve9(repositoryRoot, plan.target));
7259
7355
  } catch {
7260
7356
  currentRepoReal = null;
7261
7357
  }
@@ -7290,7 +7386,7 @@ function applyRepoTeardown(repositoryRoot, manifest, plan) {
7290
7386
  continue;
7291
7387
  }
7292
7388
  const viewDir = resolveViewDir(repositoryRoot, viewPath);
7293
- const owned = repoReal !== null ? viewLinkPointsAt(viewDir, item.label, repoReal) : viewLinkPointsAtPath(viewDir, item.label, resolve8(repositoryRoot, plan.target));
7389
+ const owned = repoReal !== null ? viewLinkPointsAt(viewDir, item.label, repoReal) : viewLinkPointsAtPath(viewDir, item.label, resolve9(repositoryRoot, plan.target));
7294
7390
  if (!owned) {
7295
7391
  changed(item.label);
7296
7392
  continue;
@@ -7452,7 +7548,7 @@ async function doRunProjectArchive(target, options, ctx) {
7452
7548
  const roster = manifest.repos ?? [];
7453
7549
  let targetIsAnchor = false;
7454
7550
  try {
7455
- targetIsAnchor = realpathSync(resolve8(repositoryRoot, target)) === realpathSync(repositoryRoot);
7551
+ targetIsAnchor = realpathSync(resolve9(repositoryRoot, target)) === realpathSync(repositoryRoot);
7456
7552
  } catch {
7457
7553
  targetIsAnchor = false;
7458
7554
  }
@@ -7609,7 +7705,7 @@ async function doRunProjectRename(oldPath, newPath, options, ctx) {
7609
7705
  const roster = manifest.repos ?? [];
7610
7706
  let oldIsAnchor = false;
7611
7707
  try {
7612
- oldIsAnchor = realpathSync(resolve8(repositoryRoot, oldPath)) === realpathSync(repositoryRoot);
7708
+ oldIsAnchor = realpathSync(resolve9(repositoryRoot, oldPath)) === realpathSync(repositoryRoot);
7613
7709
  } catch {
7614
7710
  oldIsAnchor = false;
7615
7711
  }
@@ -7755,7 +7851,7 @@ async function doRunProjectNew(repos, options, ctx) {
7755
7851
  const viewStem = productName ?? workspaceName;
7756
7852
  const viewOverridesProjectName = productName !== void 0 && typeof options.view === "string";
7757
7853
  const declared = repos.map((p) => {
7758
- const abs = resolve8(cwd, p);
7854
+ const abs = resolve9(cwd, p);
7759
7855
  let real;
7760
7856
  try {
7761
7857
  real = realpathSync(abs);
@@ -8020,7 +8116,7 @@ function pathPresent(p) {
8020
8116
  }
8021
8117
  function gatherRetrofit(repositoryRoot, anchorReal, roster, argAbs, argReal, viewCanonicalName) {
8022
8118
  const declaredEntry = roster.find((entry) => {
8023
- const entryAbs = resolve8(repositoryRoot, entry.path);
8119
+ const entryAbs = resolve9(repositoryRoot, entry.path);
8024
8120
  if (argReal !== void 0) {
8025
8121
  try {
8026
8122
  if (realpathSync(entryAbs) === argReal) return true;
@@ -8160,7 +8256,7 @@ async function doRunProjectRetrofit(repo, options, ctx) {
8160
8256
  }
8161
8257
  return result2;
8162
8258
  }
8163
- const argAbs = resolve8(repositoryRoot, repo);
8259
+ const argAbs = resolve9(repositoryRoot, repo);
8164
8260
  let argReal;
8165
8261
  try {
8166
8262
  argReal = realpathSync(argAbs);
@@ -8381,7 +8477,7 @@ function renderProjectRetrofit(result) {
8381
8477
  }
8382
8478
 
8383
8479
  // src/commands/protocol.ts
8384
- import { readFile as readFile4, stat as stat5 } from "fs/promises";
8480
+ import { readFile as readFile5, stat as stat5 } from "fs/promises";
8385
8481
  import {
8386
8482
  carryForwardProtocolStamp,
8387
8483
  PROTOCOL_END as PROTOCOL_END2,
@@ -8438,7 +8534,7 @@ async function readProtocolSources(entries) {
8438
8534
  for (const entry of entries) {
8439
8535
  let content;
8440
8536
  try {
8441
- content = await readFile4(entry.source, "utf8");
8537
+ content = await readFile5(entry.source, "utf8");
8442
8538
  } catch (error) {
8443
8539
  if (error instanceof Error && error.code === "ENOENT") {
8444
8540
  throw new Error(
@@ -8571,7 +8667,7 @@ import { InvalidArgumentError as InvalidArgumentError4 } from "commander";
8571
8667
 
8572
8668
  // src/commands/refresh-watch.ts
8573
8669
  import { readdir as readdir2, stat as stat6 } from "fs/promises";
8574
- import { homedir as homedir9 } from "os";
8670
+ import { homedir as homedir10 } from "os";
8575
8671
  import { join as join13 } from "path";
8576
8672
  import { findErrorCode as findErrorCode8 } from "@basou/core";
8577
8673
  var DEFAULT_WATCH_INTERVAL_SEC = 30;
@@ -8579,8 +8675,8 @@ var MIN_WATCH_INTERVAL_SEC = 5;
8579
8675
  var MAX_WATCH_INTERVAL_SEC = 86400;
8580
8676
  function watchedRoots(ctx) {
8581
8677
  return [
8582
- ctx.codexSessionsDir ?? join13(homedir9(), ".codex", "sessions"),
8583
- ctx.claudeProjectsDir ?? join13(homedir9(), ".claude", "projects")
8678
+ ctx.codexSessionsDir ?? join13(homedir10(), ".codex", "sessions"),
8679
+ ctx.claudeProjectsDir ?? join13(homedir10(), ".claude", "projects")
8584
8680
  ];
8585
8681
  }
8586
8682
  async function scanSourceLogs(roots) {
@@ -8701,19 +8797,19 @@ function parseInterval(value) {
8701
8797
  return seconds;
8702
8798
  }
8703
8799
  function abortableSleep(ms, signal) {
8704
- return new Promise((resolve14) => {
8800
+ return new Promise((resolve15) => {
8705
8801
  if (signal.aborted) {
8706
- resolve14();
8802
+ resolve15();
8707
8803
  return;
8708
8804
  }
8709
8805
  let timer;
8710
8806
  const onAbort = () => {
8711
8807
  clearTimeout(timer);
8712
- resolve14();
8808
+ resolve15();
8713
8809
  };
8714
8810
  timer = setTimeout(() => {
8715
8811
  signal.removeEventListener("abort", onAbort);
8716
- resolve14();
8812
+ resolve15();
8717
8813
  }, ms);
8718
8814
  signal.addEventListener("abort", onAbort, { once: true });
8719
8815
  });
@@ -8939,7 +9035,7 @@ async function assertWorkspaceInitialized8(basouRoot) {
8939
9035
  }
8940
9036
 
8941
9037
  // src/commands/report.ts
8942
- import { isAbsolute as isAbsolute5, resolve as resolve9 } from "path";
9038
+ import { isAbsolute as isAbsolute5, resolve as resolve10 } from "path";
8943
9039
  import {
8944
9040
  assertBasouRootSafe as assertBasouRootSafe10,
8945
9041
  basouPaths as basouPaths14,
@@ -8979,7 +9075,7 @@ async function doRunReportGenerate(options, ctx) {
8979
9075
  onTaskSkip: (taskId, reason) => printTaskSkip(taskId, reason)
8980
9076
  });
8981
9077
  if (options.out !== void 0) {
8982
- const outPath = isAbsolute5(options.out) ? options.out : resolve9(cwd, options.out);
9078
+ const outPath = isAbsolute5(options.out) ? options.out : resolve10(cwd, options.out);
8983
9079
  await writeMarkdownFile6(outPath, result.body);
8984
9080
  const { sessions, decisions, tasks } = result.data;
8985
9081
  console.error(
@@ -9017,9 +9113,9 @@ async function assertWorkspaceInitialized9(basouRoot) {
9017
9113
  }
9018
9114
 
9019
9115
  // src/commands/review.ts
9020
- import { readFile as readFile5 } from "fs/promises";
9021
- import { homedir as homedir10 } from "os";
9022
- import { resolve as resolve10 } from "path";
9116
+ import { readFile as readFile6 } from "fs/promises";
9117
+ import { homedir as homedir11 } from "os";
9118
+ import { resolve as resolve11 } from "path";
9023
9119
  import {
9024
9120
  assertBasouRootSafe as assertBasouRootSafe11,
9025
9121
  basouPaths as basouPaths15,
@@ -9031,7 +9127,7 @@ import {
9031
9127
  parseReviewRecordInput,
9032
9128
  readManifest as readManifest9,
9033
9129
  resolveRepoRoot,
9034
- sanitizePath as sanitizePath2
9130
+ sanitizePath as sanitizePath3
9035
9131
  } from "@basou/core";
9036
9132
  function registerReviewCommand(program2) {
9037
9133
  const review = program2.command("review").description("Record reviews that ran (the durable signal a review happened)");
@@ -9119,9 +9215,9 @@ async function doRunReviewRecord(options, ctx) {
9119
9215
  const manifest = await readManifest9(paths);
9120
9216
  const invocationArgs = options.file !== void 0 ? [
9121
9217
  "--file",
9122
- sanitizePath2(resolve10(cwd, options.file), {
9218
+ sanitizePath3(resolve11(cwd, options.file), {
9123
9219
  workingDirectory: repositoryRoot,
9124
- homedir: homedir10()
9220
+ homedir: homedir11()
9125
9221
  })
9126
9222
  ] : [];
9127
9223
  const adHoc = await createAdHocSessionWithEvent3({
@@ -9161,7 +9257,7 @@ ${detail}
9161
9257
  async function readReviewInput(options, ctx) {
9162
9258
  if (options.file !== void 0) {
9163
9259
  try {
9164
- return await readFile5(options.file, "utf8");
9260
+ return await readFile6(options.file, "utf8");
9165
9261
  } catch (error) {
9166
9262
  if (findErrorCode11(error, "ENOENT")) {
9167
9263
  throw new Error(`Input file not found: ${options.file}`);
@@ -9173,18 +9269,18 @@ async function readReviewInput(options, ctx) {
9173
9269
  return await ctx.readInput();
9174
9270
  }
9175
9271
  if (process.stdin.isTTY === true) {
9176
- throw new Error(NO_INPUT_HINT2);
9272
+ throw new Error(NO_INPUT_HINT3);
9177
9273
  }
9178
- return await readStdinToEnd2();
9274
+ return await readStdinToEnd3();
9179
9275
  }
9180
- async function readStdinToEnd2() {
9276
+ async function readStdinToEnd3() {
9181
9277
  const chunks = [];
9182
9278
  for await (const chunk of process.stdin) {
9183
9279
  chunks.push(Buffer.from(chunk));
9184
9280
  }
9185
9281
  return Buffer.concat(chunks).toString("utf8");
9186
9282
  }
9187
- var NO_INPUT_HINT2 = "No input: pipe a JSON object describing the review to stdin or pass --file <path>.";
9283
+ var NO_INPUT_HINT3 = "No input: pipe a JSON object describing the review to stdin or pass --file <path>.";
9188
9284
  function reviewToPayload(review) {
9189
9285
  const payload = {
9190
9286
  reviewer: review.reviewer,
@@ -9454,8 +9550,8 @@ function unattachedLines(u) {
9454
9550
  }
9455
9551
 
9456
9552
  // src/commands/run.ts
9457
- import { mkdir as mkdir2, readFile as readFile6 } from "fs/promises";
9458
- import { homedir as homedir11 } from "os";
9553
+ import { mkdir as mkdir2, readFile as readFile7 } from "fs/promises";
9554
+ import { homedir as homedir12 } from "os";
9459
9555
  import { join as join14 } from "path";
9460
9556
  import {
9461
9557
  acquireLock as acquireLock5,
@@ -9681,7 +9777,7 @@ async function runTrackedTool(args, options, ctx, adapter) {
9681
9777
  const rawRelated = computeRelatedFiles(preSnapshot, postSnapshot, diff);
9682
9778
  const relatedFiles = sanitizeRelatedFiles(rawRelated, {
9683
9779
  workingDirectory: repoRoot,
9684
- homedir: homedir11()
9780
+ homedir: homedir12()
9685
9781
  }).sanitized;
9686
9782
  const finalStatus = decideFinalStatus2(result, signalReceived);
9687
9783
  await appendEvent(sessionDir, {
@@ -9825,7 +9921,7 @@ function buildInitialSession2(input) {
9825
9921
  source: { ...input.source },
9826
9922
  started_at: input.startedAt,
9827
9923
  status: "initialized",
9828
- working_directory: sanitizeWorkingDirectory2(input.cwd, { homedir: homedir11() }),
9924
+ working_directory: sanitizeWorkingDirectory2(input.cwd, { homedir: homedir12() }),
9829
9925
  invocation: {
9830
9926
  command: input.command,
9831
9927
  args: [...input.args],
@@ -9901,7 +9997,7 @@ async function noteCodexHookStatusPreSpawn(_cwd, ctx) {
9901
9997
  const hooksPath = ctx.codexHooksPath ?? DEFAULT_CODEX_HOOKS_PATH;
9902
9998
  let location;
9903
9999
  try {
9904
- location = findBasouSessionStartHook2(JSON.parse(await readFile6(hooksPath, "utf8")));
10000
+ location = findBasouSessionStartHook2(JSON.parse(await readFile7(hooksPath, "utf8")));
9905
10001
  } catch (error) {
9906
10002
  if (!(error instanceof Error && error.code === "ENOENT")) return null;
9907
10003
  location = null;
@@ -9915,8 +10011,8 @@ async function noteCodexHookStatusPreSpawn(_cwd, ctx) {
9915
10011
  }
9916
10012
 
9917
10013
  // src/commands/session.ts
9918
- import { readFile as readFile7 } from "fs/promises";
9919
- import { basename as basename7, isAbsolute as isAbsolute6, join as join15, relative as relative3 } from "path";
10014
+ import { readFile as readFile8 } from "fs/promises";
10015
+ import { basename as basename7, isAbsolute as isAbsolute6, join as join15, relative as relative3, sep as sep2 } from "path";
9920
10016
  import {
9921
10017
  acquireLock as acquireLock6,
9922
10018
  appendEventToExistingSession as appendEventToExistingSession3,
@@ -10186,7 +10282,7 @@ function formatWorkingDir(workingDir, repositoryRoot, options) {
10186
10282
  if (workingDir === repositoryRoot) return "<repository_root>";
10187
10283
  const rel = relative3(repositoryRoot, workingDir);
10188
10284
  if (rel.length === 0 || rel === ".") return "<repository_root>";
10189
- if (rel.startsWith("..")) return rel;
10285
+ if (rel === ".." || rel.startsWith(`..${sep2}`)) return rel;
10190
10286
  return `./${rel}`;
10191
10287
  }
10192
10288
  function formatRelatedFiles(files) {
@@ -10386,7 +10482,7 @@ async function doRunSessionImport(options, ctx) {
10386
10482
  }
10387
10483
  async function readInputFile(path) {
10388
10484
  try {
10389
- return await readFile7(path, "utf8");
10485
+ return await readFile8(path, "utf8");
10390
10486
  } catch (error) {
10391
10487
  if (findErrorCode12(error, "ENOENT")) {
10392
10488
  throw new Error("Import source not found", { cause: error });
@@ -10503,7 +10599,7 @@ async function doRunSessionNote(sessionIdInput, options, ctx) {
10503
10599
  }
10504
10600
  async function readNoteFile(path) {
10505
10601
  try {
10506
- return await readFile7(path, "utf8");
10602
+ return await readFile8(path, "utf8");
10507
10603
  } catch (error) {
10508
10604
  if (findErrorCode12(error, "ENOENT")) {
10509
10605
  throw new Error("Note source not found", { cause: error });
@@ -10828,7 +10924,7 @@ function formatVersionGateMessage(error) {
10828
10924
  }
10829
10925
 
10830
10926
  // src/commands/task.ts
10831
- import { readFile as readFile8 } from "fs/promises";
10927
+ import { readFile as readFile9 } from "fs/promises";
10832
10928
  import { join as join16 } from "path";
10833
10929
  import {
10834
10930
  archiveTask,
@@ -11843,7 +11939,7 @@ function parsePositiveInt2(raw) {
11843
11939
  }
11844
11940
  async function readDescriptionFile(path) {
11845
11941
  try {
11846
- return await readFile8(path, "utf8");
11942
+ return await readFile9(path, "utf8");
11847
11943
  } catch (error) {
11848
11944
  if (findErrorCode15(error, "ENOENT")) {
11849
11945
  throw new Error("Description source not found", { cause: error });
@@ -12048,7 +12144,7 @@ async function assertWorkspaceInitialized14(basouRoot) {
12048
12144
  // src/commands/view.ts
12049
12145
  import { spawn } from "child_process";
12050
12146
  import { createHash as createHash2 } from "crypto";
12051
- import { basename as basename10, resolve as resolve13 } from "path";
12147
+ import { basename as basename10, resolve as resolve14 } from "path";
12052
12148
  import {
12053
12149
  assertBasouRootSafe as assertBasouRootSafe18,
12054
12150
  basouPaths as basouPaths24,
@@ -12061,7 +12157,7 @@ import { InvalidArgumentError as InvalidArgumentError8 } from "commander";
12061
12157
  // src/lib/portfolio-coverage.ts
12062
12158
  import { createReadStream as createReadStream2 } from "fs";
12063
12159
  import { readdir as readdir3, stat as stat7 } from "fs/promises";
12064
- import { homedir as homedir12 } from "os";
12160
+ import { homedir as homedir13 } from "os";
12065
12161
  import { basename as basename8, dirname as dirname5, join as join17 } from "path";
12066
12162
  import { createInterface as createInterface2 } from "readline";
12067
12163
  import { basouPaths as basouPaths23, readManifest as readManifest14, resolveRepositoryRoot as resolveRepositoryRoot13 } from "@basou/core";
@@ -12071,8 +12167,8 @@ function uncapturedTotal(result) {
12071
12167
  async function checkPortfolioCoverage(workspaces, ctx = {}) {
12072
12168
  const { roots, inertWorkspaces } = await collectDeclaredRoots(workspaces);
12073
12169
  const listedDirs = new Set([...roots].map((root) => encodeProjectDir(root)));
12074
- const claudeProjectsDir = ctx.claudeProjectsDir ?? join17(homedir12(), ".claude", "projects");
12075
- const codexSessionsDir = ctx.codexSessionsDir ?? join17(homedir12(), ".codex", "sessions");
12170
+ const claudeProjectsDir = ctx.claudeProjectsDir ?? join17(homedir13(), ".claude", "projects");
12171
+ const codexSessionsDir = ctx.codexSessionsDir ?? join17(homedir13(), ".codex", "sessions");
12076
12172
  const tally = new Tally(roots);
12077
12173
  const absentTrees = [];
12078
12174
  const claudeFiles = await listClaudeTranscripts(claudeProjectsDir);
@@ -12376,7 +12472,7 @@ function inertLines(result) {
12376
12472
  // src/lib/portfolio-safety.ts
12377
12473
  import { execFile as execFile2 } from "child_process";
12378
12474
  import { lstat as lstat2, realpath as realpath4 } from "fs/promises";
12379
- import { isAbsolute as isAbsolute7, join as join18, relative as relative4, resolve as resolve11 } from "path";
12475
+ import { isAbsolute as isAbsolute7, join as join18, relative as relative4, resolve as resolve12, sep as sep3 } from "path";
12380
12476
  import { promisify as promisify2 } from "util";
12381
12477
  import { readManifest as readManifest15 } from "@basou/core";
12382
12478
  var execFileAsync2 = promisify2(execFile2);
@@ -12387,12 +12483,12 @@ async function canonical(p) {
12387
12483
  try {
12388
12484
  return await realpath4(p);
12389
12485
  } catch {
12390
- return resolve11(p);
12486
+ return resolve12(p);
12391
12487
  }
12392
12488
  }
12393
12489
  function isInside(child, parent) {
12394
12490
  const rel = relative4(parent, child);
12395
- return rel === "" || !rel.startsWith("..") && !isAbsolute7(rel);
12491
+ return rel === "" || rel !== ".." && !rel.startsWith(`..${sep3}`) && !isAbsolute7(rel);
12396
12492
  }
12397
12493
  function isBasouPath(p) {
12398
12494
  return p === ".basou" || p.startsWith(".basou/") || p.includes("/.basou/") || p.endsWith("/.basou");
@@ -12455,13 +12551,13 @@ async function checkPortfolioSafety(workspaces) {
12455
12551
  }
12456
12552
  const monitored = /* @__PURE__ */ new Map();
12457
12553
  for (const root of sourceRoots) {
12458
- const display = resolve11(ws.repoRoot, root);
12554
+ const display = resolve12(ws.repoRoot, root);
12459
12555
  const real = await canonical(display);
12460
12556
  if (real !== wsReal) monitored.set(real, display);
12461
12557
  }
12462
12558
  const claimed = new Set(monitored.keys());
12463
12559
  if (isMaster && viewPath !== void 0) {
12464
- const viewReal = await canonical(resolve11(ws.repoRoot, viewPath));
12560
+ const viewReal = await canonical(resolve12(ws.repoRoot, viewPath));
12465
12561
  if (viewReal !== wsReal) claimed.add(viewReal);
12466
12562
  }
12467
12563
  records.push({ ws, real: wsReal, isMaster, claimed });
@@ -12554,7 +12650,7 @@ function formatSafetyReport(result) {
12554
12650
 
12555
12651
  // src/lib/view-server.ts
12556
12652
  import { createServer } from "http";
12557
- import { basename as basename9, join as join19, resolve as resolve12 } from "path";
12653
+ import { basename as basename9, join as join19, resolve as resolve13 } from "path";
12558
12654
  import {
12559
12655
  computeWorkStats as computeWorkStats2,
12560
12656
  enumerateApprovals as enumerateApprovals2,
@@ -13308,7 +13404,7 @@ function startViewServer(opts) {
13308
13404
  };
13309
13405
  let boundPort = port;
13310
13406
  const getPort = () => boundPort;
13311
- return new Promise((resolve14, reject) => {
13407
+ return new Promise((resolve15, reject) => {
13312
13408
  const server = createServer((req, res) => {
13313
13409
  handleRequest(req, res, deps, getPort, runExclusive).catch((error) => {
13314
13410
  sendError(res, error instanceof HttpError ? error.status : 500, pathlessMessage(error));
@@ -13319,7 +13415,7 @@ function startViewServer(opts) {
13319
13415
  const address = server.address();
13320
13416
  boundPort = isAddressInfo(address) ? address.port : port;
13321
13417
  server.off("error", reject);
13322
- resolve14({
13418
+ resolve15({
13323
13419
  url: `http://${host}:${boundPort}`,
13324
13420
  port: boundPort,
13325
13421
  close: () => closeServer(server)
@@ -13331,8 +13427,8 @@ function isAddressInfo(value) {
13331
13427
  return value !== null && typeof value === "object";
13332
13428
  }
13333
13429
  function closeServer(server) {
13334
- return new Promise((resolve14) => {
13335
- server.close(() => resolve14());
13430
+ return new Promise((resolve15) => {
13431
+ server.close(() => resolve15());
13336
13432
  server.closeAllConnections();
13337
13433
  });
13338
13434
  }
@@ -13604,7 +13700,7 @@ async function rosterRepos(repoRoot, manifest, resolveRemoteUrl) {
13604
13700
  const roster = manifest.repos ?? [];
13605
13701
  return Promise.all(
13606
13702
  roster.map(async (repo) => {
13607
- const abs = resolve12(repoRoot, repo.path);
13703
+ const abs = resolve13(repoRoot, repo.path);
13608
13704
  const remote = await resolveRemoteUrl(abs);
13609
13705
  const url = remote !== void 0 ? toBrowserUrl(remote) : null;
13610
13706
  return {
@@ -13880,12 +13976,12 @@ async function buildSingleDeps(ctx, cwd) {
13880
13976
  };
13881
13977
  }
13882
13978
  async function buildPortfolioDeps(workspaceFlags, ctx, cwd) {
13883
- const specs = workspaceFlags.length > 0 ? workspaceFlags.map((p) => ({ path: resolve13(cwd, p) })) : await loadPortfolioConfig(ctx.portfolioConfigPath);
13979
+ const specs = workspaceFlags.length > 0 ? workspaceFlags.map((p) => ({ path: resolve14(cwd, p) })) : await loadPortfolioConfig(ctx.portfolioConfigPath);
13884
13980
  const entries = [];
13885
13981
  const seenPath = /* @__PURE__ */ new Set();
13886
13982
  const seenKey = /* @__PURE__ */ new Set();
13887
13983
  for (const spec of specs) {
13888
- const repoRoot = resolve13(spec.path);
13984
+ const repoRoot = resolve14(spec.path);
13889
13985
  if (seenPath.has(repoRoot)) continue;
13890
13986
  seenPath.add(repoRoot);
13891
13987
  const entry = await buildWorkspaceEntry(repoRoot, ctx, spec.label);
@@ -13962,7 +14058,7 @@ function openInBrowser(url, override) {
13962
14058
  }
13963
14059
  }
13964
14060
  function waitForShutdown(signal) {
13965
- return new Promise((resolve14) => {
14061
+ return new Promise((resolve15) => {
13966
14062
  const cleanup = () => {
13967
14063
  process.off("SIGINT", onSignal);
13968
14064
  process.off("SIGTERM", onSignal);
@@ -13970,18 +14066,18 @@ function waitForShutdown(signal) {
13970
14066
  };
13971
14067
  const onSignal = () => {
13972
14068
  cleanup();
13973
- resolve14();
14069
+ resolve15();
13974
14070
  };
13975
14071
  const onAbort = () => {
13976
14072
  cleanup();
13977
- resolve14();
14073
+ resolve15();
13978
14074
  };
13979
14075
  process.on("SIGINT", onSignal);
13980
14076
  process.on("SIGTERM", onSignal);
13981
14077
  if (signal !== void 0) {
13982
14078
  if (signal.aborted) {
13983
14079
  cleanup();
13984
- resolve14();
14080
+ resolve15();
13985
14081
  return;
13986
14082
  }
13987
14083
  signal.addEventListener("abort", onAbort);
@@ -14015,7 +14111,7 @@ async function assertWorkspaceInitialized15(basouRoot) {
14015
14111
  function readBuildStamp() {
14016
14112
  if (false) return void 0;
14017
14113
  try {
14018
- return JSON.parse('{"version":"0.52.0","commit":"9e749db","committedAt":"2026-09-24T15:47:31+09:00"}');
14114
+ return JSON.parse('{"version":"0.54.0","commit":"ac2e5dd","committedAt":"2026-09-25T23:04:16+09:00"}');
14019
14115
  } catch {
14020
14116
  return void 0;
14021
14117
  }