@basou/cli 0.48.1 → 0.50.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
@@ -2467,26 +2467,36 @@ import { join as join10 } from "path";
2467
2467
  import { fileURLToPath } from "url";
2468
2468
  import { promisify } from "util";
2469
2469
  import {
2470
+ basouPaths as basouPaths10,
2470
2471
  buildSessionStartHookCommand,
2471
2472
  buildStopHookCommand,
2472
2473
  DEFAULT_STOP_HOOK_MIN_EDITS,
2473
2474
  evaluateStopHook,
2474
2475
  findBasouSessionStartHook,
2475
2476
  findBasouStopHookCommand,
2477
+ findClaudeSessionStartHooks,
2478
+ findUnrecognizedSessionStart,
2479
+ isClaudeSessionStartMalformed,
2476
2480
  isProtocolUpdateDue,
2477
2481
  ORIENTATION_END as ORIENTATION_END2,
2478
2482
  ORIENTATION_START as ORIENTATION_START2,
2483
+ observedRepoRoots,
2484
+ observeSessionChanges,
2479
2485
  PROTOCOL_END,
2480
2486
  PROTOCOL_START,
2481
2487
  parseMarkers as parseMarkers2,
2482
2488
  parseProtocolStamp,
2483
2489
  protocolSectionsFrom,
2484
2490
  protocolUpdateToken,
2491
+ readManifest as readManifest5,
2485
2492
  readMarkdownFile as readMarkdownFile6,
2493
+ recordSessionBaseline,
2494
+ removeClaudeSessionStartHook,
2486
2495
  removeSessionStartHook,
2487
2496
  removeStopHook,
2488
2497
  renderProtocolUpdate,
2489
2498
  transcriptStartedAt,
2499
+ upsertClaudeSessionStartHook,
2490
2500
  upsertSessionStartHook,
2491
2501
  upsertStopHook
2492
2502
  } from "@basou/core";
@@ -2911,7 +2921,9 @@ import {
2911
2921
  enumerateSessionDirs,
2912
2922
  findErrorCode as findErrorCode5,
2913
2923
  importSessionFromJson,
2924
+ observedFilesOf,
2914
2925
  readManifest as readManifest4,
2926
+ readSessionObservation,
2915
2927
  readSessionYaml as readSessionYaml2,
2916
2928
  reimportPreservingId,
2917
2929
  resolveRepositoryRoot as resolveRepositoryRoot5,
@@ -2996,10 +3008,13 @@ async function doRunImportClaudeCode(options, ctx) {
2996
3008
  const { records, sizeBytes } = await readJsonlRecords(file);
2997
3009
  const cwd = firstTranscriptCwd(records);
2998
3010
  if (cwd === void 0 || !projectSet.has(cwd)) return null;
3011
+ const observation = await readSessionObservation(paths.observations, externalId);
3012
+ const observedFiles = observation === null ? [] : observedFilesOf(observation);
2999
3013
  return claudeTranscriptToImportPayload(records, {
3000
3014
  workspaceId: manifest.workspace.id,
3001
3015
  externalId,
3002
- sourceSizeBytes: sizeBytes
3016
+ sourceSizeBytes: sizeBytes,
3017
+ ...observedFiles.length > 0 ? { observedFiles } : {}
3003
3018
  });
3004
3019
  }
3005
3020
  };
@@ -3832,11 +3847,14 @@ function registerHookCommand(program2) {
3832
3847
  });
3833
3848
  });
3834
3849
  hook.command("install [target]").description(
3835
- "Register a basou hook (reproducible, idempotent). Target `claude` (default): the Stop hook in ~/.claude/settings.json \u2014 advisory capture-only by default; --block opts into in-turn enforcement, --require-review into the review gate. Target `codex`: the SessionStart hook in ~/.codex/hooks.json, which hands each Codex session the position of the workspace it was opened in. Codex asks you to review and trust a new hook once before it runs."
3850
+ "Register a basou hook (reproducible, idempotent). Target `claude` (default): the Stop hook and the SessionStart hook in ~/.claude/settings.json. The Stop hook is advisory capture-only by default; --block opts into in-turn enforcement, --require-review into the review gate. The SessionStart hook hands each session the workspace's position and records the git baseline the Stop hook measures the session's file changes against; --no-session-start leaves it out. Target `codex`: the SessionStart hook in ~/.codex/hooks.json, which hands each Codex session the position of the workspace it was opened in. Codex asks you to review and trust a new hook once before it runs."
3836
3851
  ).option(
3837
3852
  "--block",
3838
3853
  "claude: register the blocking (opt-in enforcement) form instead of advisory"
3839
- ).option("--require-review", "claude: register with the opt-in review gate enabled").option("--min-edits <n>", "claude: pass a custom file-edit threshold to the registered hook").option("--settings <path>", "claude: override the settings.json path (intended for tests)").option("--hooks <path>", "codex: override the hooks.json path (intended for tests)").option(
3854
+ ).option("--require-review", "claude: register with the opt-in review gate enabled").option("--min-edits <n>", "claude: pass a custom file-edit threshold to the registered hook").option(
3855
+ "--no-session-start",
3856
+ "claude: register the Stop hook only, and leave any SessionStart hook as it is"
3857
+ ).option("--settings <path>", "claude: override the settings.json path (intended for tests)").option("--hooks <path>", "codex: override the hooks.json path (intended for tests)").option(
3840
3858
  "--codex-config <path>",
3841
3859
  "codex: override the Codex config.toml path (intended for tests)"
3842
3860
  ).option(
@@ -3845,11 +3863,23 @@ function registerHookCommand(program2) {
3845
3863
  ).option("--dry-run", "Print what would change without writing").option("-v, --verbose", "Show error causes").action(async (target, opts) => {
3846
3864
  await dispatchHookTarget(target, opts, {
3847
3865
  claude: () => runHookInstall(opts),
3848
- codex: () => runCodexHookInstall(opts)
3866
+ codex: async () => {
3867
+ if (opts.sessionStart === false) {
3868
+ renderCliError(
3869
+ new Error(
3870
+ "--no-session-start applies to target claude only; the Codex hook is itself a SessionStart hook."
3871
+ ),
3872
+ { verbose: isVerbose(opts) }
3873
+ );
3874
+ process.exitCode = 1;
3875
+ return;
3876
+ }
3877
+ await runCodexHookInstall(opts);
3878
+ }
3849
3879
  });
3850
3880
  });
3851
3881
  hook.command("uninstall [target]").description(
3852
- "Remove a basou hook, leaving other hooks intact. Target `claude` (default): the Stop hook in ~/.claude/settings.json. Target `codex`: the SessionStart hook in ~/.codex/hooks.json."
3882
+ "Remove a basou hook, leaving other hooks intact. Target `claude` (default): the Stop hook and the SessionStart hook in ~/.claude/settings.json. Target `codex`: the SessionStart hook in ~/.codex/hooks.json."
3853
3883
  ).option("--settings <path>", "claude: override the settings.json path (intended for tests)").option("--hooks <path>", "codex: override the hooks.json path (intended for tests)").option("--dry-run", "Print what would change without writing").option("-v, --verbose", "Show error causes").action(async (target, opts) => {
3854
3884
  await dispatchHookTarget(target, opts, {
3855
3885
  claude: () => runHookUninstall(opts),
@@ -3857,7 +3887,7 @@ function registerHookCommand(program2) {
3857
3887
  });
3858
3888
  });
3859
3889
  hook.command("status [target]").description(
3860
- "Report whether a basou hook is registered. Target `claude` (default): the Stop hook and its mode. Target `codex`: the SessionStart hook, and whether Codex has trusted it yet."
3890
+ "Report whether a basou hook is registered. Target `claude` (default): the Stop hook and its mode, and the SessionStart hook. Target `codex`: the SessionStart hook, and whether Codex has trusted it yet."
3861
3891
  ).option("--settings <path>", "claude: override the settings.json path (intended for tests)").option("--hooks <path>", "codex: override the hooks.json path (intended for tests)").option(
3862
3892
  "--codex-config <path>",
3863
3893
  "codex: override the Codex config.toml path (intended for tests)"
@@ -3905,9 +3935,11 @@ becomes the session's trusted context, so it withholds the position instead.
3905
3935
  Run 'basou refresh' to see which lines are responsible.
3906
3936
 
3907
3937
  Claude Code's SessionStart hook sends the same kind of payload (a JSON object
3908
- with 'cwd') and adds stdout to context the same way, so a Claude Code user may
3909
- register this command in ~/.claude/settings.json in place of 'basou orient' to
3910
- get both gates. basou does not install that one.
3938
+ with 'cwd') and adds stdout to context the same way. 'basou hook install'
3939
+ registers this command there too, in ~/.claude/settings.json, and replaces a
3940
+ hand-registered 'basou orient' SessionStart hook with it. In Claude Code it also
3941
+ records where each declared repository stood when the session started, which is
3942
+ what the Stop hook measures the session's file changes against.
3911
3943
 
3912
3944
  Codex trusts hooks by hash. A newly installed or changed hook is skipped until
3913
3945
  you review it: the interactive CLI asks at startup ("Hooks need review"), the
@@ -3972,6 +4004,8 @@ async function doRunHookStop(options, ctx) {
3972
4004
  }
3973
4005
  if (typeof payload !== "object" || payload === null) return;
3974
4006
  const fields = payload;
4007
+ const observe = ctx.observe ?? observeSessionFromPayload;
4008
+ await observe(fields, "changes", ctx.portfolioConfigPath).catch(() => void 0);
3975
4009
  if (fields.stop_hook_active === true) return;
3976
4010
  const transcriptPath = typeof fields.transcript_path === "string" ? fields.transcript_path : "";
3977
4011
  if (transcriptPath.length === 0) return;
@@ -4110,8 +4144,11 @@ async function doRunHookSessionStart(ctx) {
4110
4144
  return;
4111
4145
  }
4112
4146
  if (typeof payload !== "object" || payload === null) return;
4113
- const cwd = payload.cwd;
4147
+ const fields = payload;
4148
+ const cwd = fields.cwd;
4114
4149
  if (typeof cwd !== "string" || cwd.length === 0) return;
4150
+ const observe = ctx.observe ?? observeSessionFromPayload;
4151
+ await observe(fields, "baseline", ctx.portfolioConfigPath).catch(() => void 0);
4115
4152
  let body;
4116
4153
  try {
4117
4154
  body = (await render(cwd)).body;
@@ -4122,6 +4159,38 @@ async function doRunHookSessionStart(ctx) {
4122
4159
  write(`${body.replace(/\s+$/, "")}
4123
4160
  `);
4124
4161
  }
4162
+ async function observeSessionFromPayload(fields, pass, portfolioConfigPath) {
4163
+ const externalId = typeof fields.session_id === "string" ? fields.session_id : "";
4164
+ const cwd = typeof fields.cwd === "string" ? fields.cwd : "";
4165
+ if (externalId.length === 0 || cwd.length === 0) return;
4166
+ const configPath = portfolioConfigPath ?? DEFAULT_PORTFOLIO_CONFIG_PATH;
4167
+ let root;
4168
+ try {
4169
+ root = await resolveBasouRootForCommand(cwd, "hook observe", {
4170
+ portfolioConfigPath: configPath
4171
+ });
4172
+ } catch {
4173
+ return;
4174
+ }
4175
+ if (!await isRegisteredWorkspace(root, configPath)) return;
4176
+ const paths = basouPaths10(root);
4177
+ const nowIso = (/* @__PURE__ */ new Date()).toISOString();
4178
+ if (pass === "changes") {
4179
+ await observeSessionChanges({
4180
+ observationsDir: paths.observations,
4181
+ externalId,
4182
+ nowIso
4183
+ });
4184
+ return;
4185
+ }
4186
+ const manifest = await readManifest5(paths);
4187
+ await recordSessionBaseline({
4188
+ observationsDir: paths.observations,
4189
+ repoRoots: observedRepoRoots(root, manifest),
4190
+ externalId,
4191
+ nowIso
4192
+ });
4193
+ }
4125
4194
  function parseTranscript(transcript) {
4126
4195
  const records = [];
4127
4196
  for (const line of transcript.split(/\r?\n/)) {
@@ -4184,6 +4253,7 @@ function normalizeInstallOptions(raw) {
4184
4253
  const out = {};
4185
4254
  if (raw.block === true) out.block = true;
4186
4255
  if (raw.requireReview === true) out.requireReview = true;
4256
+ if (raw.sessionStart === false) out.noSessionStart = true;
4187
4257
  if (raw.settings !== void 0) out.settings = raw.settings;
4188
4258
  if (raw.hooks !== void 0) out.hooks = raw.hooks;
4189
4259
  if (raw.codexConfig !== void 0) out.codexConfig = raw.codexConfig;
@@ -4255,15 +4325,32 @@ async function doRunHookInstall(options, ctx = {}) {
4255
4325
  });
4256
4326
  await assertNotSymlink(settingsPath);
4257
4327
  const { raw, parsed } = await readSettings(settingsPath);
4258
- const { settings, action } = upsertStopHook(parsed, command);
4259
- const newBody = `${JSON.stringify(settings, null, 2)}
4260
- `;
4261
- if (raw !== null && newBody === raw) {
4262
- console.log(`The basou Stop hook is already registered (${mode}); no change.`);
4263
- return;
4328
+ const stop = upsertStopHook(parsed, command);
4329
+ let sessionStart;
4330
+ if (options.noSessionStart === true) {
4331
+ sessionStart = { kind: "skipped" };
4332
+ } else {
4333
+ try {
4334
+ const upsert = upsertClaudeSessionStartHook(
4335
+ stop.settings,
4336
+ buildSessionStartHookCommand({ cliEntry })
4337
+ );
4338
+ sessionStart = { kind: "done", action: upsert.action, settings: upsert.settings };
4339
+ } catch (error) {
4340
+ if (!isClaudeSessionStartMalformed(stop.settings)) throw error;
4341
+ sessionStart = { kind: "malformed" };
4342
+ }
4264
4343
  }
4265
- if (options.dryRun === true) {
4266
- console.log(`[dry-run] Would ${action} the basou Stop hook (${mode}).`);
4344
+ const settings = sessionStart.kind === "done" ? sessionStart.settings : stop.settings;
4345
+ const changed = stop.action !== "unchanged" || sessionStart.kind === "done" && sessionStart.action !== "unchanged";
4346
+ const dryRun = options.dryRun === true;
4347
+ const lines = [
4348
+ describeStopInstall(stop.action, mode, dryRun),
4349
+ describeSessionStartInstall(sessionStart, dryRun),
4350
+ ...describeSessionStartLeftovers(settings)
4351
+ ];
4352
+ if (!changed || dryRun) {
4353
+ for (const line of lines) console.log(line);
4267
4354
  return;
4268
4355
  }
4269
4356
  const recheck = await readSettings(settingsPath);
@@ -4273,8 +4360,55 @@ async function doRunHookInstall(options, ctx = {}) {
4273
4360
  );
4274
4361
  }
4275
4362
  await backupSettingsOnce(settingsPath, raw);
4276
- await writeFileDurable(settingsPath, newBody);
4277
- console.log(`${action === "installed" ? "Installed" : "Updated"} the basou Stop hook (${mode}).`);
4363
+ await writeFileDurable(settingsPath, `${JSON.stringify(settings, null, 2)}
4364
+ `);
4365
+ for (const line of lines) console.log(line);
4366
+ }
4367
+ function describeStopInstall(action, mode, dryRun) {
4368
+ if (action === "unchanged") {
4369
+ return `The basou Stop hook is already registered (${mode}); no change.`;
4370
+ }
4371
+ if (dryRun) {
4372
+ return `[dry-run] Would ${action === "installed" ? "install" : "update"} the basou Stop hook (${mode}).`;
4373
+ }
4374
+ return `${action === "installed" ? "Installed" : "Updated"} the basou Stop hook (${mode}).`;
4375
+ }
4376
+ function describeSessionStartInstall(outcome, dryRun) {
4377
+ if (outcome.kind === "skipped") {
4378
+ return "The SessionStart hook was left as it is (--no-session-start).";
4379
+ }
4380
+ if (outcome.kind === "malformed") {
4381
+ return "The basou SessionStart hook was NOT installed: 'hooks.SessionStart' in settings.json is not a list of hook groups. Fix it and re-run 'basou hook install'.";
4382
+ }
4383
+ const action = outcome.action;
4384
+ if (action === "unchanged") {
4385
+ return "The basou SessionStart hook is already registered; no change.";
4386
+ }
4387
+ const prefix = dryRun ? "[dry-run] Would " : "";
4388
+ if (action === "replaced") {
4389
+ return `${prefix}${dryRun ? "replace" : "Replaced"} the hand-registered 'basou orient' SessionStart hook with 'basou hook session-start': the same position, plus the baseline the Stop hook measures the session's file changes against. It differs in three ways: it speaks only for a workspace registered in ~/.basou/portfolio.yaml, it does not rewrite .basou/orientation.md at session start, and it stays silent when the position names another registered workspace.`;
4390
+ }
4391
+ if (action === "updated") {
4392
+ return `${prefix}${dryRun ? "update" : "Updated"} the basou SessionStart hook.`;
4393
+ }
4394
+ return `${prefix}${dryRun ? "install" : "Installed"} the basou SessionStart hook: each session gets the workspace's position, and the Stop hook can see the files the session changes through the shell.`;
4395
+ }
4396
+ function describeSessionStartLeftovers(settings) {
4397
+ const own = findClaudeSessionStartHooks(settings);
4398
+ if (own.length === 0) return [];
4399
+ const lines = [];
4400
+ for (const other of findUnrecognizedSessionStart(settings)) {
4401
+ lines.push(
4402
+ `note: this SessionStart hook runs basou '${other.runs === "orient" ? "orient" : "hook session-start"}' inside a longer command, so it was left as written, and a session may receive the position twice: ${other.command}`
4403
+ );
4404
+ }
4405
+ if (own.length > 1) {
4406
+ const matchers = own.map((o) => o.matcher ?? "(every source)").join(", ");
4407
+ lines.push(
4408
+ `note: ${own.length} basou SessionStart hooks remain, under different matchers (${matchers}). They were kept so that no session source stops firing; a source that more than one matches receives the position twice. Remove the one you do not want by hand.`
4409
+ );
4410
+ }
4411
+ return lines;
4278
4412
  }
4279
4413
  async function runHookUninstall(options) {
4280
4414
  try {
@@ -4292,15 +4426,22 @@ async function doRunHookUninstall(options) {
4292
4426
  console.log("No settings.json; nothing to remove.");
4293
4427
  return;
4294
4428
  }
4295
- const { settings, action } = removeStopHook(parsed);
4296
- if (action === "absent") {
4297
- console.log("No basou Stop hook found; nothing removed.");
4429
+ const stop = removeStopHook(parsed);
4430
+ const sessionStart = removeClaudeSessionStartHook(stop.settings);
4431
+ if (stop.action === "absent" && sessionStart.action === "absent") {
4432
+ console.log("No basou Stop hook or SessionStart hook found; nothing removed.");
4298
4433
  return;
4299
4434
  }
4300
- const newBody = `${JSON.stringify(settings, null, 2)}
4435
+ const newBody = `${JSON.stringify(sessionStart.settings, null, 2)}
4301
4436
  `;
4437
+ const removedNames = [
4438
+ ...stop.action === "removed" ? ["Stop hook"] : [],
4439
+ ...sessionStart.action === "removed" ? ["SessionStart hook"] : []
4440
+ ];
4302
4441
  if (options.dryRun === true) {
4303
- console.log("[dry-run] Would remove the basou Stop hook from settings.json.");
4442
+ for (const name of removedNames) {
4443
+ console.log(`[dry-run] Would remove the basou ${name} from settings.json.`);
4444
+ }
4304
4445
  return;
4305
4446
  }
4306
4447
  const recheck = await readSettings(settingsPath);
@@ -4311,7 +4452,9 @@ async function doRunHookUninstall(options) {
4311
4452
  }
4312
4453
  await backupSettingsOnce(settingsPath, raw);
4313
4454
  await writeFileDurable(settingsPath, newBody);
4314
- console.log("Removed the basou Stop hook from settings.json.");
4455
+ for (const name of removedNames) {
4456
+ console.log(`Removed the basou ${name} from settings.json.`);
4457
+ }
4315
4458
  }
4316
4459
  async function runHookStatus(options) {
4317
4460
  try {
@@ -4327,14 +4470,49 @@ async function doRunHookStatus(options) {
4327
4470
  const command = findBasouStopHookCommand(parsed);
4328
4471
  if (command === null) {
4329
4472
  console.log("basou Stop hook: not registered. Run 'basou hook install' to register it.");
4473
+ } else {
4474
+ const mode = describeHookMode({
4475
+ block: / --block\b/.test(command),
4476
+ review: / --require-review\b/.test(command)
4477
+ });
4478
+ console.log(`basou Stop hook: registered, ${mode}.`);
4479
+ await reportHookEntryBuild(command);
4480
+ }
4481
+ reportSessionStartStatus(parsed);
4482
+ }
4483
+ function reportSessionStartStatus(parsed) {
4484
+ if (isClaudeSessionStartMalformed(parsed)) {
4485
+ console.log(
4486
+ "basou SessionStart hook: cannot tell -- 'hooks.SessionStart' in settings.json is not a list of hook groups."
4487
+ );
4330
4488
  return;
4331
4489
  }
4332
- const mode = describeHookMode({
4333
- block: / --block\b/.test(command),
4334
- review: / --require-review\b/.test(command)
4335
- });
4336
- console.log(`basou Stop hook: registered, ${mode}.`);
4337
- await reportHookEntryBuild(command);
4490
+ const own = findClaudeSessionStartHooks(parsed);
4491
+ const others = findUnrecognizedSessionStart(parsed);
4492
+ for (const hook of own.filter((o) => o.kind === "session-start")) {
4493
+ console.log(`basou SessionStart hook: registered, fires ${describeFiring(hook.matcher)}.`);
4494
+ }
4495
+ for (const hook of own.filter((o) => o.kind === "orient")) {
4496
+ console.log(
4497
+ `basou SessionStart hook: 'basou orient' registered by hand, fires ${describeFiring(hook.matcher)}. It delivers the position but records no git baseline, so the files a session changes through the shell are not observed; 'basou hook install' replaces it with 'basou hook session-start'.`
4498
+ );
4499
+ }
4500
+ if (own.length === 0) {
4501
+ if (others.length === 0) {
4502
+ console.log(
4503
+ "basou SessionStart hook: not registered. Sessions get no position at start, and the files a session changes through the shell are not observed. Run 'basou hook install' to register it."
4504
+ );
4505
+ }
4506
+ for (const other of others) {
4507
+ console.log(
4508
+ other.runs === "orient" ? `basou SessionStart hook: not registered by basou. A SessionStart hook runs 'basou orient' inside a longer command, so sessions may get the position, but no git baseline is recorded: ${other.command}` : `basou SessionStart hook: not registered by basou. A SessionStart hook runs 'basou hook session-start' inside a longer command, which basou leaves as written: ${other.command}`
4509
+ );
4510
+ }
4511
+ }
4512
+ for (const line of describeSessionStartLeftovers(parsed)) console.log(line);
4513
+ }
4514
+ function describeFiring(matcher) {
4515
+ return matcher === void 0 || matcher === "" || matcher === "*" ? "on every session source" : `on ${matcher}`;
4338
4516
  }
4339
4517
  async function reportHookEntryBuild(command) {
4340
4518
  console.log(` this basou is: ${BASOU_VERSION_LINE}`);
@@ -4700,12 +4878,12 @@ import {
4700
4878
  acquireLock as acquireLock4,
4701
4879
  appendEventToExistingSession as appendEventToExistingSession2,
4702
4880
  assertBasouRootSafe as assertBasouRootSafe8,
4703
- basouPaths as basouPaths10,
4881
+ basouPaths as basouPaths11,
4704
4882
  createAdHocSessionWithEvent as createAdHocSessionWithEvent2,
4705
4883
  EVENT_SCHEMA_VERSION as EVENT_SCHEMA_VERSION4,
4706
4884
  findErrorCode as findErrorCode7,
4707
4885
  LOCAL_CLI_EVENT_SOURCE as LOCAL_CLI_EVENT_SOURCE3,
4708
- readManifest as readManifest5,
4886
+ readManifest as readManifest6,
4709
4887
  resolveSessionId as resolveSessionId2
4710
4888
  } from "@basou/core";
4711
4889
  import { InvalidArgumentError as InvalidArgumentError3 } from "commander";
@@ -4755,7 +4933,7 @@ async function doRunNote(body, options, ctx) {
4755
4933
  }
4756
4934
  const cwd = ctx.cwd ?? process.cwd();
4757
4935
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "note");
4758
- const paths = basouPaths10(repositoryRoot);
4936
+ const paths = basouPaths11(repositoryRoot);
4759
4937
  await assertWorkspaceInitialized7(paths.root);
4760
4938
  const now = ctx.nowProvider !== void 0 ? ctx.nowProvider() : /* @__PURE__ */ new Date();
4761
4939
  const occurredAt = now.toISOString();
@@ -4782,7 +4960,7 @@ async function doRunNote(body, options, ctx) {
4782
4960
  });
4783
4961
  return;
4784
4962
  }
4785
- const manifest = await readManifest5(paths);
4963
+ const manifest = await readManifest6(paths);
4786
4964
  const adHoc = await createAdHocSessionWithEvent2({
4787
4965
  paths,
4788
4966
  manifest,
@@ -4978,7 +5156,7 @@ import {
4978
5156
  import { basename as basename6, dirname as dirname4, isAbsolute as isAbsolute4, join as join12, relative as relative2, resolve as resolve8 } from "path";
4979
5157
  import {
4980
5158
  appendBasouGitignore as appendBasouGitignore2,
4981
- basouPaths as basouPaths11,
5159
+ basouPaths as basouPaths12,
4982
5160
  classifyRetrofit,
4983
5161
  createManifest as createManifest2,
4984
5162
  ensureBasouDirectory as ensureBasouDirectory2,
@@ -4993,7 +5171,7 @@ import {
4993
5171
  planRename,
4994
5172
  planRosterAdoption,
4995
5173
  planWorkspaceView,
4996
- readManifest as readManifest6,
5174
+ readManifest as readManifest7,
4997
5175
  readMarkdownFile as readMarkdownFile7,
4998
5176
  reconcileSourceRoots,
4999
5177
  removeMarkerSection as removeMarkerSection2,
@@ -5141,8 +5319,8 @@ function preservedUnknownLines(fields) {
5141
5319
  async function doRunProjectCheck(options, ctx) {
5142
5320
  const cwd = ctx.cwd ?? process.cwd();
5143
5321
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "project check");
5144
- const paths = basouPaths11(repositoryRoot);
5145
- const manifest = await readManifest6(paths);
5322
+ const paths = basouPaths12(repositoryRoot);
5323
+ const manifest = await readManifest7(paths);
5146
5324
  const roster = summarizeRosterDrift({
5147
5325
  ...manifest.repos !== void 0 ? { repos: manifest.repos } : {},
5148
5326
  sourceRoots: effectiveSourceRoots(manifest)
@@ -5276,8 +5454,8 @@ async function runProjectSync(options, ctx = {}) {
5276
5454
  async function doRunProjectSync(options, ctx) {
5277
5455
  const cwd = ctx.cwd ?? process.cwd();
5278
5456
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "project sync");
5279
- const paths = basouPaths11(repositoryRoot);
5280
- const manifest = await readManifest6(paths);
5457
+ const paths = basouPaths12(repositoryRoot);
5458
+ const manifest = await readManifest7(paths);
5281
5459
  const hasRoster = manifest.repos !== void 0 && manifest.repos.length > 0;
5282
5460
  const reconcile = reconcileSourceRoots({
5283
5461
  ...manifest.repos !== void 0 ? { repos: manifest.repos } : {},
@@ -5362,8 +5540,8 @@ function classifySourceRoot(repositoryRoot, declaredPath) {
5362
5540
  async function doRunProjectAdopt(options, ctx) {
5363
5541
  const cwd = ctx.cwd ?? process.cwd();
5364
5542
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "project adopt");
5365
- const paths = basouPaths11(repositoryRoot);
5366
- const manifest = await readManifest6(paths);
5543
+ const paths = basouPaths12(repositoryRoot);
5544
+ const manifest = await readManifest7(paths);
5367
5545
  const alreadyDeclared = manifest.repos !== void 0 && manifest.repos.length > 0;
5368
5546
  const candidates = effectiveSourceRoots(manifest).map(
5369
5547
  (r) => classifySourceRoot(repositoryRoot, r)
@@ -5484,8 +5662,8 @@ async function gatherRepoWiring(repositoryRoot, entry) {
5484
5662
  async function doRunProjectWiring(options, ctx) {
5485
5663
  const cwd = ctx.cwd ?? process.cwd();
5486
5664
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "project wiring");
5487
- const paths = basouPaths11(repositoryRoot);
5488
- const manifest = await readManifest6(paths);
5665
+ const paths = basouPaths12(repositoryRoot);
5666
+ const manifest = await readManifest7(paths);
5489
5667
  const roster = manifest.repos ?? [];
5490
5668
  const facts = [];
5491
5669
  for (const entry of roster) facts.push(await gatherRepoWiring(repositoryRoot, entry));
@@ -5617,8 +5795,8 @@ function applyGitignorePlan(repositoryRoot, plan) {
5617
5795
  async function doRunProjectGitignore(options, ctx) {
5618
5796
  const cwd = ctx.cwd ?? process.cwd();
5619
5797
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "project gitignore");
5620
- const paths = basouPaths11(repositoryRoot);
5621
- const manifest = await readManifest6(paths);
5798
+ const paths = basouPaths12(repositoryRoot);
5799
+ const manifest = await readManifest7(paths);
5622
5800
  const roster = manifest.repos ?? [];
5623
5801
  const facts = roster.map((entry) => gatherRepoGitignore(repositoryRoot, entry));
5624
5802
  const summary = planGitignore({ repos: facts, required: [...INSTRUCTION_FILES] });
@@ -5876,8 +6054,8 @@ function applyViewSymlinks(viewDir, files) {
5876
6054
  async function doRunProjectSymlinks(options, ctx) {
5877
6055
  const cwd = ctx.cwd ?? process.cwd();
5878
6056
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "project symlinks");
5879
- const paths = basouPaths11(repositoryRoot);
5880
- const manifest = await readManifest6(paths);
6057
+ const paths = basouPaths12(repositoryRoot);
6058
+ const manifest = await readManifest7(paths);
5881
6059
  const roster = manifest.repos ?? [];
5882
6060
  const anchorReal = realpathSync(repositoryRoot);
5883
6061
  const facts = roster.map((entry) => gatherRepoSymlinks(repositoryRoot, anchorReal, entry));
@@ -6206,8 +6384,8 @@ function pruneViewLinks(viewDir, toPrune, rosterRealpaths) {
6206
6384
  async function doRunProjectWorkspace(options, ctx) {
6207
6385
  const cwd = ctx.cwd ?? process.cwd();
6208
6386
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "project workspace");
6209
- const paths = basouPaths11(repositoryRoot);
6210
- const manifest = await readManifest6(paths);
6387
+ const paths = basouPaths12(repositoryRoot);
6388
+ const manifest = await readManifest7(paths);
6211
6389
  const viewPath = manifest.workspace.view;
6212
6390
  const roster = manifest.repos ?? [];
6213
6391
  let result;
@@ -6566,8 +6744,8 @@ function presetFailureReason(error) {
6566
6744
  async function doRunProjectPreset(options, ctx) {
6567
6745
  const cwd = ctx.cwd ?? process.cwd();
6568
6746
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "project preset");
6569
- const paths = basouPaths11(repositoryRoot);
6570
- const manifest = await readManifest6(paths);
6747
+ const paths = basouPaths12(repositoryRoot);
6748
+ const manifest = await readManifest7(paths);
6571
6749
  const roster = manifest.repos ?? [];
6572
6750
  const anchorReal = realpathSync(repositoryRoot);
6573
6751
  const facts = [];
@@ -7225,8 +7403,8 @@ function renderProjectTeardown(result) {
7225
7403
  async function doRunProjectTeardown(target, options, ctx = {}) {
7226
7404
  const cwd = ctx.cwd ?? process.cwd();
7227
7405
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "project teardown");
7228
- const paths = basouPaths11(repositoryRoot);
7229
- const manifest = await readManifest6(paths);
7406
+ const paths = basouPaths12(repositoryRoot);
7407
+ const manifest = await readManifest7(paths);
7230
7408
  const plan = gatherRepoTeardown(repositoryRoot, manifest, target);
7231
7409
  const willApply = options.apply === true && !plan.isAnchor && plan.removableCount > 0;
7232
7410
  const { removed, failed } = willApply ? applyRepoTeardown(repositoryRoot, manifest, plan) : { removed: [], failed: [] };
@@ -7267,8 +7445,8 @@ function buildArchivedManifest(manifest, plan, updatedAt) {
7267
7445
  async function doRunProjectArchive(target, options, ctx) {
7268
7446
  const cwd = ctx.cwd ?? process.cwd();
7269
7447
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "project archive");
7270
- const paths = basouPaths11(repositoryRoot);
7271
- const manifest = await readManifest6(paths);
7448
+ const paths = basouPaths12(repositoryRoot);
7449
+ const manifest = await readManifest7(paths);
7272
7450
  const roster = manifest.repos ?? [];
7273
7451
  let targetIsAnchor = false;
7274
7452
  try {
@@ -7424,8 +7602,8 @@ function buildRenamedManifest(manifest, plan, updatedAt) {
7424
7602
  async function doRunProjectRename(oldPath, newPath, options, ctx) {
7425
7603
  const cwd = ctx.cwd ?? process.cwd();
7426
7604
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "project rename");
7427
- const paths = basouPaths11(repositoryRoot);
7428
- const manifest = await readManifest6(paths);
7605
+ const paths = basouPaths12(repositoryRoot);
7606
+ const manifest = await readManifest7(paths);
7429
7607
  const roster = manifest.repos ?? [];
7430
7608
  let oldIsAnchor = false;
7431
7609
  try {
@@ -7600,7 +7778,7 @@ async function doRunProjectNew(repos, options, ctx) {
7600
7778
  const roster = rosterPaths.map((path) => ({ path }));
7601
7779
  const viewPath = options.view === false ? null : options.view ?? `../${viewStem}-workspace`;
7602
7780
  const sourceRoots = [...rosterPaths, ...viewPath !== null ? [viewPath] : []];
7603
- const paths = basouPaths11(repositoryRoot);
7781
+ const paths = basouPaths12(repositoryRoot);
7604
7782
  const existed = existsSync2(paths.files.manifest);
7605
7783
  const manifest = createManifest2({
7606
7784
  workspaceName,
@@ -7711,8 +7889,8 @@ async function runProjectDerive(options, ctx = {}) {
7711
7889
  async function doRunProjectDerive(options, ctx) {
7712
7890
  const cwd = ctx.cwd ?? process.cwd();
7713
7891
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "project derive");
7714
- const paths = basouPaths11(repositoryRoot);
7715
- const manifest = await readManifest6(paths);
7892
+ const paths = basouPaths12(repositoryRoot);
7893
+ const manifest = await readManifest7(paths);
7716
7894
  if (manifest.repos === void 0 || manifest.repos.length === 0) {
7717
7895
  console.log(
7718
7896
  "# Generate project wiring in one pass (declaration \u2192 wiring)\n\n\u2139\uFE0F No repo roster declared (manifest `repos`). Declare one first with `basou project new` (new project) or `basou project adopt` (bootstrap from existing source_roots)."
@@ -7752,8 +7930,8 @@ async function doRunProjectDerive(options, ctx) {
7752
7930
  async function doRunProjectSeedAnchor(options, ctx) {
7753
7931
  const cwd = ctx.cwd ?? process.cwd();
7754
7932
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "project derive");
7755
- const paths = basouPaths11(repositoryRoot);
7756
- const manifest = await readManifest6(paths);
7933
+ const paths = basouPaths12(repositoryRoot);
7934
+ const manifest = await readManifest7(paths);
7757
7935
  const roster = manifest.repos ?? [];
7758
7936
  console.log("# Anchor instruction-file seed (the planning master's own AGENTS.md)");
7759
7937
  console.log("");
@@ -7946,8 +8124,8 @@ async function applyViewRetrofit(anchorReal, outcome) {
7946
8124
  async function doRunProjectRetrofit(repo, options, ctx) {
7947
8125
  const cwd = ctx.cwd ?? process.cwd();
7948
8126
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "project retrofit");
7949
- const paths = basouPaths11(repositoryRoot);
7950
- const manifest = await readManifest6(paths);
8127
+ const paths = basouPaths12(repositoryRoot);
8128
+ const manifest = await readManifest7(paths);
7951
8129
  const roster = manifest.repos ?? [];
7952
8130
  const anchorReal = realpathSync(repositoryRoot);
7953
8131
  const viewPath = manifest.workspace.view;
@@ -8383,9 +8561,9 @@ async function doRunProtocolUnsync(options) {
8383
8561
  // src/commands/refresh.ts
8384
8562
  import {
8385
8563
  assertBasouRootSafe as assertBasouRootSafe9,
8386
- basouPaths as basouPaths12,
8564
+ basouPaths as basouPaths13,
8387
8565
  findErrorCode as findErrorCode9,
8388
- readManifest as readManifest7
8566
+ readManifest as readManifest8
8389
8567
  } from "@basou/core";
8390
8568
  import { InvalidArgumentError as InvalidArgumentError4 } from "commander";
8391
8569
 
@@ -8625,7 +8803,7 @@ async function doRunRefreshWatch(options, ctx) {
8625
8803
  if (options.force === true) throw new Error("--watch cannot be combined with --force.");
8626
8804
  const cwd = ctx.cwd ?? process.cwd();
8627
8805
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "refresh");
8628
- const paths = basouPaths12(repositoryRoot);
8806
+ const paths = basouPaths13(repositoryRoot);
8629
8807
  await assertWorkspaceInitialized8(paths.root);
8630
8808
  const intervalMs = (options.interval ?? DEFAULT_WATCH_INTERVAL_SEC) * 1e3;
8631
8809
  const controller = new AbortController();
@@ -8653,7 +8831,7 @@ async function doRunRefreshWatch(options, ctx) {
8653
8831
  async function computeRefresh(options, ctx) {
8654
8832
  const cwd = ctx.cwd ?? process.cwd();
8655
8833
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "refresh");
8656
- const paths = basouPaths12(repositoryRoot);
8834
+ const paths = basouPaths13(repositoryRoot);
8657
8835
  await assertWorkspaceInitialized8(paths.root);
8658
8836
  const nowIso = (ctx.nowProvider?.() ?? /* @__PURE__ */ new Date()).toISOString();
8659
8837
  const result = await refreshAll({
@@ -8692,7 +8870,7 @@ async function warnPosition(paths, result, ctx) {
8692
8870
  }
8693
8871
  async function retiredChannelNotice(paths) {
8694
8872
  try {
8695
- const manifest = await readManifest7(paths);
8873
+ const manifest = await readManifest8(paths);
8696
8874
  if (manifest.channels?.codex !== true) return null;
8697
8875
  return "codex channel: retired \u2014 the manifest's channels.codex is ignored; a Codex session now receives this workspace's position from the SessionStart hook (see `basou hook status codex`), and nothing is written to the user-global ~/.codex/AGENTS.md";
8698
8876
  } catch {
@@ -8762,7 +8940,7 @@ async function assertWorkspaceInitialized8(basouRoot) {
8762
8940
  import { isAbsolute as isAbsolute5, resolve as resolve9 } from "path";
8763
8941
  import {
8764
8942
  assertBasouRootSafe as assertBasouRootSafe10,
8765
- basouPaths as basouPaths13,
8943
+ basouPaths as basouPaths14,
8766
8944
  findErrorCode as findErrorCode10,
8767
8945
  renderReport,
8768
8946
  resolveRepositoryRoot as resolveRepositoryRoot8,
@@ -8787,7 +8965,7 @@ async function runReportGenerate(options, ctx = {}) {
8787
8965
  async function doRunReportGenerate(options, ctx) {
8788
8966
  const cwd = ctx.cwd ?? process.cwd();
8789
8967
  const repositoryRoot = await resolveRepositoryRootForReport(cwd);
8790
- const paths = basouPaths13(repositoryRoot);
8968
+ const paths = basouPaths14(repositoryRoot);
8791
8969
  await assertWorkspaceInitialized9(paths.root);
8792
8970
  const nowIso = (ctx.nowProvider?.() ?? /* @__PURE__ */ new Date()).toISOString();
8793
8971
  const result = await renderReport({
@@ -8842,14 +9020,14 @@ import { homedir as homedir10 } from "os";
8842
9020
  import { resolve as resolve10 } from "path";
8843
9021
  import {
8844
9022
  assertBasouRootSafe as assertBasouRootSafe11,
8845
- basouPaths as basouPaths14,
9023
+ basouPaths as basouPaths15,
8846
9024
  buildReviewRecordedEvent,
8847
9025
  buildReviewRecordLabel,
8848
9026
  createAdHocSessionWithEvent as createAdHocSessionWithEvent3,
8849
9027
  findErrorCode as findErrorCode11,
8850
9028
  findUnbindableRepos,
8851
9029
  parseReviewRecordInput,
8852
- readManifest as readManifest8,
9030
+ readManifest as readManifest9,
8853
9031
  resolveRepoRoot,
8854
9032
  sanitizePath as sanitizePath2
8855
9033
  } from "@basou/core";
@@ -8924,7 +9102,7 @@ async function runReviewRecord(options, ctx = {}) {
8924
9102
  async function doRunReviewRecord(options, ctx) {
8925
9103
  const cwd = ctx.cwd ?? process.cwd();
8926
9104
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "review record");
8927
- const paths = basouPaths14(repositoryRoot);
9105
+ const paths = basouPaths15(repositoryRoot);
8928
9106
  await assertWorkspaceInitialized10(paths.root);
8929
9107
  const raw = await readReviewInput(options, ctx);
8930
9108
  const review = parseReviewRecordInput(raw);
@@ -8936,7 +9114,7 @@ async function doRunReviewRecord(options, ctx) {
8936
9114
  }
8937
9115
  const now = ctx.nowProvider !== void 0 ? ctx.nowProvider() : /* @__PURE__ */ new Date();
8938
9116
  const occurredAt = now.toISOString();
8939
- const manifest = await readManifest8(paths);
9117
+ const manifest = await readManifest9(paths);
8940
9118
  const invocationArgs = options.file !== void 0 ? [
8941
9119
  "--file",
8942
9120
  sanitizePath2(resolve10(cwd, options.file), {
@@ -9071,7 +9249,7 @@ async function assertWorkspaceInitialized10(basouRoot) {
9071
9249
 
9072
9250
  // src/commands/review-gaps.ts
9073
9251
  import {
9074
- basouPaths as basouPaths15,
9252
+ basouPaths as basouPaths16,
9075
9253
  findReviewGaps
9076
9254
  } from "@basou/core";
9077
9255
  import { InvalidArgumentError as InvalidArgumentError5 } from "commander";
@@ -9112,7 +9290,7 @@ async function runReviewGaps(options, ctx = {}) {
9112
9290
  async function doRunReviewGaps(options, ctx) {
9113
9291
  const cwd = ctx.cwd ?? process.cwd();
9114
9292
  const repositoryRoot = await resolveBasouRootForCommand(cwd, "review-gaps");
9115
- const paths = basouPaths15(repositoryRoot);
9293
+ const paths = basouPaths16(repositoryRoot);
9116
9294
  const nowIso = (ctx.nowProvider?.() ?? /* @__PURE__ */ new Date()).toISOString();
9117
9295
  const summary = await findReviewGaps({
9118
9296
  paths,
@@ -9280,7 +9458,7 @@ import { join as join14 } from "path";
9280
9458
  import {
9281
9459
  acquireLock as acquireLock5,
9282
9460
  assertBasouRootSafe as assertBasouRootSafe12,
9283
- basouPaths as basouPaths16,
9461
+ basouPaths as basouPaths17,
9284
9462
  ChildProcessRunner as ChildProcessRunner2,
9285
9463
  claudeCodeAdapterMetadata,
9286
9464
  codexAdapterMetadata,
@@ -9292,7 +9470,7 @@ import {
9292
9470
  getSnapshot as getSnapshot2,
9293
9471
  overwriteYamlFile as overwriteYamlFile2,
9294
9472
  prefixedUlid as prefixedUlid4,
9295
- readManifest as readManifest9,
9473
+ readManifest as readManifest10,
9296
9474
  readYamlFile as readYamlFile6,
9297
9475
  resolveClaudeCodeCommand,
9298
9476
  resolveCodexCommand,
@@ -9352,9 +9530,9 @@ async function runTrackedTool(args, options, ctx, adapter) {
9352
9530
  const childArgs = adapter.transformArgs ? adapter.transformArgs(args) : args;
9353
9531
  const cwd = options.cwd ?? process.cwd();
9354
9532
  const repoRoot = await resolveRepositoryRootForRun(cwd);
9355
- const paths = basouPaths16(repoRoot);
9533
+ const paths = basouPaths17(repoRoot);
9356
9534
  await assertBasouRootSafe12(paths.root);
9357
- const manifest = await readManifest9(paths);
9535
+ const manifest = await readManifest10(paths);
9358
9536
  const sessionId = prefixedUlid4("ses");
9359
9537
  const sessionDir = join14(paths.sessions, sessionId);
9360
9538
  await mkdir2(sessionDir, { recursive: true });
@@ -9741,7 +9919,7 @@ import {
9741
9919
  acquireLock as acquireLock6,
9742
9920
  appendEventToExistingSession as appendEventToExistingSession3,
9743
9921
  assertBasouRootSafe as assertBasouRootSafe13,
9744
- basouPaths as basouPaths17,
9922
+ basouPaths as basouPaths18,
9745
9923
  EVENT_SCHEMA_VERSION as EVENT_SCHEMA_VERSION6,
9746
9924
  enumerateSessionDirs as enumerateSessionDirs2,
9747
9925
  findErrorCode as findErrorCode12,
@@ -9749,7 +9927,7 @@ import {
9749
9927
  LOCAL_CLI_EVENT_SOURCE as LOCAL_CLI_EVENT_SOURCE4,
9750
9928
  loadSessionEntries as loadSessionEntries2,
9751
9929
  readAllEvents,
9752
- readManifest as readManifest10,
9930
+ readManifest as readManifest11,
9753
9931
  readObservedDuration,
9754
9932
  readYamlFile as readYamlFile7,
9755
9933
  rechainSessionInPlace,
@@ -9810,7 +9988,7 @@ async function runSessionList(options, ctx = {}) {
9810
9988
  async function doRunSessionList(options, ctx) {
9811
9989
  const cwd = ctx.cwd ?? process.cwd();
9812
9990
  const repositoryRoot = await resolveRepositoryRootForSession(cwd, "list");
9813
- const paths = basouPaths17(repositoryRoot);
9991
+ const paths = basouPaths18(repositoryRoot);
9814
9992
  await assertWorkspaceInitialized11(paths.root);
9815
9993
  const now = /* @__PURE__ */ new Date();
9816
9994
  const records = (await loadSessionEntries2(paths, {
@@ -9862,7 +10040,7 @@ async function runSessionShow(idInput, options, ctx = {}) {
9862
10040
  async function doRunSessionShow(idInput, options, ctx) {
9863
10041
  const cwd = ctx.cwd ?? process.cwd();
9864
10042
  const repositoryRoot = await resolveRepositoryRootForSession(cwd, "show");
9865
- const paths = basouPaths17(repositoryRoot);
10043
+ const paths = basouPaths18(repositoryRoot);
9866
10044
  await assertWorkspaceInitialized11(paths.root);
9867
10045
  const sessionId = await resolveSessionId3(paths, idInput);
9868
10046
  const sessionDir = join15(paths.sessions, sessionId);
@@ -10174,9 +10352,9 @@ async function runSessionImport(options, ctx = {}) {
10174
10352
  async function doRunSessionImport(options, ctx) {
10175
10353
  const cwd = ctx.cwd ?? process.cwd();
10176
10354
  const repositoryRoot = await resolveRepositoryRootForSession(cwd, "import");
10177
- const paths = basouPaths17(repositoryRoot);
10355
+ const paths = basouPaths18(repositoryRoot);
10178
10356
  await assertWorkspaceInitialized11(paths.root);
10179
- const manifest = await readManifest10(paths);
10357
+ const manifest = await readManifest11(paths);
10180
10358
  const rawBody = await readInputFile(options.from);
10181
10359
  const json = parseJsonStrict(rawBody);
10182
10360
  const parsed = SessionImportPayloadSchema2.safeParse(json);
@@ -10290,7 +10468,7 @@ async function doRunSessionNote(sessionIdInput, options, ctx) {
10290
10468
  }
10291
10469
  const cwd = ctx.cwd ?? process.cwd();
10292
10470
  const repositoryRoot = await resolveRepositoryRootForSession(cwd, "note");
10293
- const paths = basouPaths17(repositoryRoot);
10471
+ const paths = basouPaths18(repositoryRoot);
10294
10472
  await assertWorkspaceInitialized11(paths.root);
10295
10473
  const sessionId = await resolveSessionId3(paths, sessionIdInput);
10296
10474
  const body = hasBody ? options.body : await readNoteFile(options.fromFile);
@@ -10372,7 +10550,7 @@ async function doRunSessionRechain(options, ctx) {
10372
10550
  }
10373
10551
  const cwd = ctx.cwd ?? process.cwd();
10374
10552
  const repositoryRoot = await resolveRepositoryRootForSession(cwd, "rechain");
10375
- const paths = basouPaths17(repositoryRoot);
10553
+ const paths = basouPaths18(repositoryRoot);
10376
10554
  await assertWorkspaceInitialized11(paths.root);
10377
10555
  const sessionIds = options.session !== void 0 ? [await resolveSessionId3(paths, options.session)] : await enumerateSessionDirs2(paths);
10378
10556
  const dryRun = options.dryRun === true;
@@ -10427,7 +10605,7 @@ function renderRechainRow(row, dryRun) {
10427
10605
  // src/commands/stats.ts
10428
10606
  import {
10429
10607
  assertBasouRootSafe as assertBasouRootSafe14,
10430
- basouPaths as basouPaths18,
10608
+ basouPaths as basouPaths19,
10431
10609
  computeWorkStats,
10432
10610
  findErrorCode as findErrorCode13,
10433
10611
  resolveRepositoryRoot as resolveRepositoryRoot10
@@ -10448,7 +10626,7 @@ async function runStats(options, ctx = {}) {
10448
10626
  async function doRunStats(options, ctx) {
10449
10627
  const cwd = ctx.cwd ?? process.cwd();
10450
10628
  const repositoryRoot = await resolveRepositoryRootForStats(cwd);
10451
- const paths = basouPaths18(repositoryRoot);
10629
+ const paths = basouPaths19(repositoryRoot);
10452
10630
  await assertWorkspaceInitialized12(paths.root);
10453
10631
  const now = ctx.nowProvider?.() ?? /* @__PURE__ */ new Date();
10454
10632
  const result = await computeWorkStats({
@@ -10561,10 +10739,10 @@ async function assertWorkspaceInitialized12(basouRoot) {
10561
10739
  // src/commands/status.ts
10562
10740
  import {
10563
10741
  assertBasouRootSafe as assertBasouRootSafe15,
10564
- basouPaths as basouPaths19,
10742
+ basouPaths as basouPaths20,
10565
10743
  buildStatusSnapshot,
10566
10744
  findErrorCode as findErrorCode14,
10567
- readManifest as readManifest11,
10745
+ readManifest as readManifest12,
10568
10746
  resolveRepositoryRoot as resolveRepositoryRoot11,
10569
10747
  writeStatus
10570
10748
  } from "@basou/core";
@@ -10584,7 +10762,7 @@ async function runStatus(options, ctx = {}) {
10584
10762
  async function doRunStatus(options, ctx) {
10585
10763
  const cwd = ctx.cwd ?? process.cwd();
10586
10764
  const repositoryRoot = await resolveRepositoryRootForStatus(cwd);
10587
- const paths = basouPaths19(repositoryRoot);
10765
+ const paths = basouPaths20(repositoryRoot);
10588
10766
  try {
10589
10767
  await assertBasouRootSafe15(paths.root);
10590
10768
  } catch (error) {
@@ -10595,7 +10773,7 @@ async function doRunStatus(options, ctx) {
10595
10773
  }
10596
10774
  let manifest;
10597
10775
  try {
10598
- manifest = await readManifest11(paths);
10776
+ manifest = await readManifest12(paths);
10599
10777
  } catch (error) {
10600
10778
  if (findErrorCode14(error, "ENOENT")) {
10601
10779
  throw new Error("Workspace not initialized. Run 'basou init' first.");
@@ -10652,7 +10830,7 @@ import { join as join16 } from "path";
10652
10830
  import {
10653
10831
  archiveTask,
10654
10832
  assertBasouRootSafe as assertBasouRootSafe16,
10655
- basouPaths as basouPaths20,
10833
+ basouPaths as basouPaths21,
10656
10834
  createTaskWithEvent,
10657
10835
  deleteTask,
10658
10836
  editTask,
@@ -10661,7 +10839,7 @@ import {
10661
10839
  loadSessionEntries as loadSessionEntries3,
10662
10840
  loadTaskEntries,
10663
10841
  prefixedUlid as prefixedUlid5,
10664
- readManifest as readManifest12,
10842
+ readManifest as readManifest13,
10665
10843
  readTaskFile,
10666
10844
  readTaskFileWithArchiveFallback,
10667
10845
  reconcileAllTasks,
@@ -10753,7 +10931,7 @@ async function doRunTaskNew(options, ctx) {
10753
10931
  }
10754
10932
  const cwd = ctx.cwd ?? process.cwd();
10755
10933
  const repositoryRoot = await resolveRepositoryRootForTask(cwd, "new");
10756
- const paths = basouPaths20(repositoryRoot);
10934
+ const paths = basouPaths21(repositoryRoot);
10757
10935
  await assertWorkspaceInitialized13(paths.root);
10758
10936
  const description = options.description !== void 0 ? options.description : options.fromFile !== void 0 ? await readDescriptionFile(options.fromFile) : "";
10759
10937
  const now = ctx.nowProvider !== void 0 ? ctx.nowProvider() : /* @__PURE__ */ new Date();
@@ -10788,7 +10966,7 @@ async function doRunTaskNew(options, ctx) {
10788
10966
  });
10789
10967
  return;
10790
10968
  }
10791
- const manifest = await readManifest12(paths);
10969
+ const manifest = await readManifest13(paths);
10792
10970
  const result = await createTaskWithEvent({
10793
10971
  mode: "ad-hoc",
10794
10972
  paths,
@@ -10862,7 +11040,7 @@ async function runTaskList(options, ctx = {}) {
10862
11040
  async function doRunTaskList(options, ctx) {
10863
11041
  const cwd = ctx.cwd ?? process.cwd();
10864
11042
  const repositoryRoot = await resolveRepositoryRootForTask(cwd, "list");
10865
- const paths = basouPaths20(repositoryRoot);
11043
+ const paths = basouPaths21(repositoryRoot);
10866
11044
  await assertWorkspaceInitialized13(paths.root);
10867
11045
  const entries = await loadTaskEntries(paths, {
10868
11046
  onSkip: (id, reason) => printTaskSkip(id, reason)
@@ -10966,7 +11144,7 @@ async function runTaskShow(idInput, options, ctx = {}) {
10966
11144
  async function doRunTaskShow(idInput, options, ctx) {
10967
11145
  const cwd = ctx.cwd ?? process.cwd();
10968
11146
  const repositoryRoot = await resolveRepositoryRootForTask(cwd, "show");
10969
- const paths = basouPaths20(repositoryRoot);
11147
+ const paths = basouPaths21(repositoryRoot);
10970
11148
  await assertWorkspaceInitialized13(paths.root);
10971
11149
  const taskId = await resolveTaskId2(paths, idInput, { includeArchived: true });
10972
11150
  const { doc, archived } = await readTaskFileWithArchiveFallback(paths, taskId);
@@ -11110,7 +11288,7 @@ async function doRunTaskStatus(taskIdInput, newStatusInput, options, ctx) {
11110
11288
  const newStatus = parseTaskStatusPositional(newStatusInput);
11111
11289
  const cwd = ctx.cwd ?? process.cwd();
11112
11290
  const repositoryRoot = await resolveRepositoryRootForTask(cwd, "status");
11113
- const paths = basouPaths20(repositoryRoot);
11291
+ const paths = basouPaths21(repositoryRoot);
11114
11292
  await assertWorkspaceInitialized13(paths.root);
11115
11293
  const taskId = await resolveTaskId2(paths, taskIdInput);
11116
11294
  const now = ctx.nowProvider !== void 0 ? ctx.nowProvider() : /* @__PURE__ */ new Date();
@@ -11136,7 +11314,7 @@ async function doRunTaskStatus(taskIdInput, newStatusInput, options, ctx) {
11136
11314
  });
11137
11315
  return;
11138
11316
  }
11139
- const manifest = await readManifest12(paths);
11317
+ const manifest = await readManifest13(paths);
11140
11318
  const result = await updateTaskStatusWithEvent({
11141
11319
  mode: "ad-hoc",
11142
11320
  paths,
@@ -11187,9 +11365,9 @@ async function runTaskReconcile(options, ctx = {}) {
11187
11365
  async function doRunTaskReconcile(options, ctx) {
11188
11366
  const cwd = ctx.cwd ?? process.cwd();
11189
11367
  const repositoryRoot = await resolveRepositoryRootForTask(cwd, "reconcile");
11190
- const paths = basouPaths20(repositoryRoot);
11368
+ const paths = basouPaths21(repositoryRoot);
11191
11369
  await assertWorkspaceInitialized13(paths.root);
11192
- const manifest = await readManifest12(paths);
11370
+ const manifest = await readManifest13(paths);
11193
11371
  const nowProvider = ctx.nowProvider ?? (() => /* @__PURE__ */ new Date());
11194
11372
  const write = options.write === true;
11195
11373
  const verbose = isVerbose(options);
@@ -11367,9 +11545,9 @@ async function doRunTaskRefreshLinkage(taskIdInput, options, ctx) {
11367
11545
  }
11368
11546
  const cwd = ctx.cwd ?? process.cwd();
11369
11547
  const repositoryRoot = await resolveRepositoryRootForTask(cwd, "refresh-linkage");
11370
- const paths = basouPaths20(repositoryRoot);
11548
+ const paths = basouPaths21(repositoryRoot);
11371
11549
  await assertWorkspaceInitialized13(paths.root);
11372
- const manifest = await readManifest12(paths);
11550
+ const manifest = await readManifest13(paths);
11373
11551
  const taskId = await resolveTaskId2(paths, taskIdInput);
11374
11552
  const nowProvider = ctx.nowProvider ?? (() => /* @__PURE__ */ new Date());
11375
11553
  const write = options.write === true;
@@ -11447,9 +11625,9 @@ async function doRunTaskEdit(taskIdInput, options, ctx) {
11447
11625
  }
11448
11626
  const cwd = ctx.cwd ?? process.cwd();
11449
11627
  const repositoryRoot = await resolveRepositoryRootForTask(cwd, "edit");
11450
- const paths = basouPaths20(repositoryRoot);
11628
+ const paths = basouPaths21(repositoryRoot);
11451
11629
  await assertWorkspaceInitialized13(paths.root);
11452
- const manifest = await readManifest12(paths);
11630
+ const manifest = await readManifest13(paths);
11453
11631
  const taskId = await resolveTaskId2(paths, taskIdInput);
11454
11632
  const now = ctx.nowProvider !== void 0 ? ctx.nowProvider() : /* @__PURE__ */ new Date();
11455
11633
  const occurredAt = now.toISOString();
@@ -11503,9 +11681,9 @@ async function doRunTaskDelete(taskIdInput, options, ctx) {
11503
11681
  }
11504
11682
  const cwd = ctx.cwd ?? process.cwd();
11505
11683
  const repositoryRoot = await resolveRepositoryRootForTask(cwd, "delete");
11506
- const paths = basouPaths20(repositoryRoot);
11684
+ const paths = basouPaths21(repositoryRoot);
11507
11685
  await assertWorkspaceInitialized13(paths.root);
11508
- const manifest = await readManifest12(paths);
11686
+ const manifest = await readManifest13(paths);
11509
11687
  const taskId = await resolveTaskId2(paths, taskIdInput);
11510
11688
  if (options.yes !== true) {
11511
11689
  await confirmDestructiveAction("delete", taskId);
@@ -11548,9 +11726,9 @@ async function doRunTaskArchive(taskIdInput, options, ctx) {
11548
11726
  }
11549
11727
  const cwd = ctx.cwd ?? process.cwd();
11550
11728
  const repositoryRoot = await resolveRepositoryRootForTask(cwd, "archive");
11551
- const paths = basouPaths20(repositoryRoot);
11729
+ const paths = basouPaths21(repositoryRoot);
11552
11730
  await assertWorkspaceInitialized13(paths.root);
11553
- const manifest = await readManifest12(paths);
11731
+ const manifest = await readManifest13(paths);
11554
11732
  const taskId = await resolveTaskId2(paths, taskIdInput);
11555
11733
  if (options.yes !== true) {
11556
11734
  await confirmDestructiveAction("archive", taskId);
@@ -11769,7 +11947,7 @@ function maxLen3(values, floor) {
11769
11947
  // src/commands/verify.ts
11770
11948
  import {
11771
11949
  assertBasouRootSafe as assertBasouRootSafe17,
11772
- basouPaths as basouPaths21,
11950
+ basouPaths as basouPaths22,
11773
11951
  enumerateSessionDirs as enumerateSessionDirs3,
11774
11952
  findErrorCode as findErrorCode16,
11775
11953
  resolveRepositoryRoot as resolveRepositoryRoot12,
@@ -11795,7 +11973,7 @@ async function doRunVerify(options, ctx) {
11795
11973
  }
11796
11974
  const cwd = ctx.cwd ?? process.cwd();
11797
11975
  const repositoryRoot = await resolveRepositoryRootForVerify(cwd);
11798
- const paths = basouPaths21(repositoryRoot);
11976
+ const paths = basouPaths22(repositoryRoot);
11799
11977
  await assertWorkspaceInitialized14(paths.root);
11800
11978
  const sessionIds = options.session !== void 0 ? [await resolveSessionId5(paths, options.session)] : await enumerateSessionDirs3(paths);
11801
11979
  const rows = [];
@@ -11870,9 +12048,9 @@ import { createHash as createHash2 } from "crypto";
11870
12048
  import { basename as basename10, resolve as resolve13 } from "path";
11871
12049
  import {
11872
12050
  assertBasouRootSafe as assertBasouRootSafe18,
11873
- basouPaths as basouPaths23,
12051
+ basouPaths as basouPaths24,
11874
12052
  findErrorCode as findErrorCode18,
11875
- readManifest as readManifest16,
12053
+ readManifest as readManifest17,
11876
12054
  resolveRepositoryRoot as resolveRepositoryRoot14
11877
12055
  } from "@basou/core";
11878
12056
  import { InvalidArgumentError as InvalidArgumentError8 } from "commander";
@@ -11883,7 +12061,7 @@ import { readdir as readdir3, stat as stat7 } from "fs/promises";
11883
12061
  import { homedir as homedir12 } from "os";
11884
12062
  import { basename as basename8, dirname as dirname5, join as join17 } from "path";
11885
12063
  import { createInterface as createInterface2 } from "readline";
11886
- import { basouPaths as basouPaths22, readManifest as readManifest13, resolveRepositoryRoot as resolveRepositoryRoot13 } from "@basou/core";
12064
+ import { basouPaths as basouPaths23, readManifest as readManifest14, resolveRepositoryRoot as resolveRepositoryRoot13 } from "@basou/core";
11887
12065
  function uncapturedTotal(result) {
11888
12066
  return result.groups.reduce((sum, g) => sum + g.logs, 0) + result.unplaceable;
11889
12067
  }
@@ -11926,7 +12104,7 @@ async function collectDeclaredRoots(workspaces) {
11926
12104
  }
11927
12105
  let resolved;
11928
12106
  try {
11929
- const manifest = await readManifest13(basouPaths22(importRoot));
12107
+ const manifest = await readManifest14(basouPaths23(importRoot));
11930
12108
  resolved = resolveSourceRoots({
11931
12109
  projectFlags: [],
11932
12110
  manifest,
@@ -12197,7 +12375,7 @@ import { execFile as execFile2 } from "child_process";
12197
12375
  import { lstat as lstat2, realpath as realpath4 } from "fs/promises";
12198
12376
  import { isAbsolute as isAbsolute7, join as join18, relative as relative4, resolve as resolve11 } from "path";
12199
12377
  import { promisify as promisify2 } from "util";
12200
- import { readManifest as readManifest14 } from "@basou/core";
12378
+ import { readManifest as readManifest15 } from "@basou/core";
12201
12379
  var execFileAsync2 = promisify2(execFile2);
12202
12380
  function errorCode(error) {
12203
12381
  return error instanceof Error ? error.code : void 0;
@@ -12253,7 +12431,7 @@ async function checkPortfolioSafety(workspaces) {
12253
12431
  let viewPath;
12254
12432
  let isMaster = false;
12255
12433
  try {
12256
- const manifest = await readManifest14(ws.paths);
12434
+ const manifest = await readManifest15(ws.paths);
12257
12435
  sourceRoots = manifest.import?.source_roots ?? [];
12258
12436
  viewPath = manifest.workspace.view;
12259
12437
  isMaster = true;
@@ -12383,7 +12561,7 @@ import {
12383
12561
  loadSessionEntries as loadSessionEntries4,
12384
12562
  loadTaskEntries as loadTaskEntries2,
12385
12563
  readAllEvents as readAllEvents2,
12386
- readManifest as readManifest15,
12564
+ readManifest as readManifest16,
12387
12565
  readMarkdownFile as readMarkdownFile9,
12388
12566
  readSessionYaml as readSessionYaml3,
12389
12567
  readTaskFile as readTaskFile2,
@@ -13368,7 +13546,7 @@ async function captureStaleness(ws, nowIso) {
13368
13546
  async function overview(ws, nowProvider, resolveRemoteUrl) {
13369
13547
  let manifest;
13370
13548
  try {
13371
- manifest = await readManifest15(ws.paths);
13549
+ manifest = await readManifest16(ws.paths);
13372
13550
  } catch (error) {
13373
13551
  if (findErrorCode17(error, "ENOENT")) {
13374
13552
  return { initialized: false, repoRoot: ws.repoRoot };
@@ -13669,7 +13847,7 @@ async function doRunView(options, ctx) {
13669
13847
  }
13670
13848
  async function buildSingleDeps(ctx, cwd) {
13671
13849
  const repositoryRoot = await resolveRepositoryRootForView(cwd);
13672
- const paths = basouPaths23(repositoryRoot);
13850
+ const paths = basouPaths24(repositoryRoot);
13673
13851
  await assertWorkspaceInitialized15(paths.root);
13674
13852
  const entry = await buildWorkspaceEntry(repositoryRoot, ctx);
13675
13853
  return {
@@ -13703,14 +13881,14 @@ async function buildPortfolioDeps(workspaceFlags, ctx, cwd) {
13703
13881
  };
13704
13882
  }
13705
13883
  async function buildWorkspaceEntry(repoRoot, ctx, labelOverride) {
13706
- const paths = basouPaths23(repoRoot);
13884
+ const paths = basouPaths24(repoRoot);
13707
13885
  const importCtx = {
13708
13886
  cwd: repoRoot,
13709
13887
  ...ctx.claudeProjectsDir !== void 0 ? { claudeProjectsDir: ctx.claudeProjectsDir } : {},
13710
13888
  ...ctx.codexSessionsDir !== void 0 ? { codexSessionsDir: ctx.codexSessionsDir } : {}
13711
13889
  };
13712
13890
  try {
13713
- const manifest = await readManifest16(paths);
13891
+ const manifest = await readManifest17(paths);
13714
13892
  return {
13715
13893
  key: manifest.workspace.id,
13716
13894
  label: labelOverride ?? manifest.workspace.name,
@@ -13815,7 +13993,7 @@ async function assertWorkspaceInitialized15(basouRoot) {
13815
13993
  function readBuildStamp() {
13816
13994
  if (false) return void 0;
13817
13995
  try {
13818
- return JSON.parse('{"version":"0.48.1","commit":"bb3398c","committedAt":"2026-09-21T21:38:14+09:00"}');
13996
+ return JSON.parse('{"version":"0.50.0","commit":"5b4c5dc","committedAt":"2026-09-23T19:12:06+09:00"}');
13819
13997
  } catch {
13820
13998
  return void 0;
13821
13999
  }