@basou/cli 0.8.0 → 0.10.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 +313 -102
- package/dist/index.js.map +1 -1
- package/dist/program.js +313 -102
- package/dist/program.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/error-render.ts","../src/program.ts","../src/commands/approval.ts","../src/commands/decision.ts","../src/commands/decisions.ts","../src/commands/exec.ts","../src/commands/handoff.ts","../src/commands/import.ts","../src/commands/init.ts","../src/commands/refresh.ts","../src/lib/provenance-actions.ts","../src/commands/refresh-watch.ts","../src/commands/run.ts","../src/commands/session.ts","../src/lib/format-duration.ts","../src/commands/stats.ts","../src/commands/status.ts","../src/commands/task.ts","../src/commands/view.ts","../src/lib/view-server.ts","../src/lib/view-ui.ts","../src/index.ts"],"sourcesContent":["import {\n FailedToFinalizeError,\n type ReplayWarning,\n type SessionSkipReason,\n type TaskSkipReason,\n} from \"@basou/core\";\n\n// ============================================================================\n// Short-id helpers\n// ============================================================================\n\nconst SES_PREFIX = \"ses_\";\nconst TASK_PREFIX = \"task_\";\nconst SHORT_ID_LEN = 6;\n\n/**\n * Strip the `ses_` prefix and slice the first {@link SHORT_ID_LEN} chars of\n * the ULID body for human-readable session identification in CLI output.\n * IDs without the prefix are sliced from offset 0.\n */\nexport function shortSessionId(id: string): string {\n if (id.startsWith(SES_PREFIX))\n return id.slice(SES_PREFIX.length, SES_PREFIX.length + SHORT_ID_LEN);\n return id.slice(0, SHORT_ID_LEN);\n}\n\n/**\n * Same as {@link shortSessionId} but for `task_<ULID>` ids.\n */\nexport function shortTaskId(id: string): string {\n if (id.startsWith(TASK_PREFIX))\n return id.slice(TASK_PREFIX.length, TASK_PREFIX.length + SHORT_ID_LEN);\n return id.slice(0, SHORT_ID_LEN);\n}\n\n// ============================================================================\n// Verbose mode detection\n// ============================================================================\n\n/**\n * Unified verbose-mode predicate: `options.verbose === true` OR the\n * `BASOU_DEBUG=1` environment variable. CLI surfaces use this everywhere\n * the verbose error / cause label rendering needs a yes/no answer.\n */\nexport function isVerbose(options: { verbose?: boolean } | undefined): boolean {\n return options?.verbose === true || process.env.BASOU_DEBUG === \"1\";\n}\n\n// ============================================================================\n// Cause-chain walk (pathless)\n// ============================================================================\n\nconst CAUSE_CHAIN_MAX_DEPTH = 4;\n\n/**\n * Walk the cause chain (up to {@link CAUSE_CHAIN_MAX_DEPTH} hops) and return\n * the first errno-style `code` found, falling back to the deepest\n * constructor name. The value goes into `Caused by: <label>` so verbose\n * output stays pathless even when capability layers wrap native errors.\n *\n * Returns `undefined` when `error.cause` is not itself an Error (= no chain\n * to walk).\n */\nexport function extractCauseLabel(error: Error): string | undefined {\n let current: unknown = error.cause;\n let constructorName: string | undefined;\n for (let depth = 0; depth < CAUSE_CHAIN_MAX_DEPTH; depth += 1) {\n if (!(current instanceof Error)) break;\n const code = (current as Error & { code?: unknown }).code;\n if (typeof code === \"string\" && code.length > 0) return code;\n constructorName = current.constructor.name;\n current = current.cause;\n }\n return constructorName;\n}\n\n// ============================================================================\n// Pluggable classifier interface\n// ============================================================================\n\n/**\n * Plug-in for command-specific error rendering. {@link renderCliError}\n * invokes every classifier whose {@link match} returns true and emits each\n * line returned by {@link additionalLines} after the main `error.message`\n * line. Classifiers MUST keep their lines pathless — no absolute paths, no\n * `cause.message` echo.\n */\nexport interface ErrorClassifier {\n match(error: Error): boolean;\n additionalLines(error: Error): readonly string[];\n}\n\n/**\n * Shared classifier for {@link FailedToFinalizeError}. Both `task.ts` and\n * `decision.ts` need exactly the same two warning lines — the session.yaml\n * status update failed AFTER the target event was already written, so the\n * operator must NOT retry the command.\n */\nexport const failedToFinalizeClassifier: ErrorClassifier = {\n match: (error) => error instanceof FailedToFinalizeError,\n additionalLines: (error) => {\n const e = error as FailedToFinalizeError;\n const sid = shortSessionId(e.sessionId);\n // `targetEventIds[0]` is the operator-facing anchor event (= the\n // `decision_recorded` / `task_created` / `task_reconciled` event the\n // command was meant to produce). Multi-target ad-hoc sessions (e.g.\n // `task new --status done` which adds `task_status_changed`) carry the\n // additional ids in `targetEventIds[1..]`; one anchor is enough for the\n // do-not-rerun warning.\n const anchor = e.targetEventIds[0];\n return [\n `Recorded ${anchor} in session ${sid}; do not rerun`,\n \"Warning: session.yaml status update failed; events.jsonl is consistent\",\n ];\n },\n};\n\n// ============================================================================\n// Generic CLI error renderer\n// ============================================================================\n\n/**\n * Render an unknown thrown value to stderr without leaking absolute paths.\n *\n * Always prints `error.message` first, then any classifier-emitted lines,\n * and finally — in verbose mode — a single `Caused by: <label>` line where\n * `<label>` is the first errno code found while walking `error.cause` (or\n * the deepest constructor name as a fallback). The error's `cause.message`\n * is intentionally never printed because Node's native fs errors embed\n * absolute paths there.\n *\n * Non-Error values are coerced via `String(error)` so the catch-all fallback\n * in `program.parseAsync().catch(...)` still produces something readable.\n */\nexport function renderCliError(\n error: unknown,\n options: { verbose: boolean; classifiers?: readonly ErrorClassifier[] },\n): void {\n if (!(error instanceof Error)) {\n console.error(String(error));\n return;\n }\n console.error(error.message);\n for (const classifier of options.classifiers ?? []) {\n if (classifier.match(error)) {\n for (const line of classifier.additionalLines(error)) console.error(line);\n }\n }\n if (options.verbose) {\n const label = extractCauseLabel(error);\n if (label !== undefined) console.error(`Caused by: ${label}`);\n }\n}\n\n// ============================================================================\n// Warning surface helpers\n// ============================================================================\n\n/**\n * Print a `ReplayWarning` on stderr in the canonical short form used by\n * every command that consumes the event-replay stream (= task / handoff /\n * decisions / etc.). The session id is shortened via {@link shortSessionId}\n * for readability.\n */\nexport function printReplayWarning(warning: ReplayWarning, sessionId: string): void {\n const short = shortSessionId(sessionId);\n switch (warning.kind) {\n case \"partial_trailing_line\":\n console.error(`Warning: ignored partial trailing line in ${short}/events.jsonl`);\n break;\n case \"malformed_json\":\n console.error(\n `Warning: skipped malformed JSON at line ${warning.line} in ${short}/events.jsonl`,\n );\n break;\n case \"schema_violation\":\n console.error(\n `Warning: skipped invalid event at line ${warning.line} in ${short}/events.jsonl`,\n );\n break;\n }\n}\n\n/**\n * Print a session-skip warning in the \"scan\" form used by handoff / decisions\n * generators: `events_jsonl_unreadable` is mapped to the standardised\n * suspect-check warning used elsewhere in the CLI, every other reason falls\n * through to a generic `Skipped <sid>: <reason>` form preserving the raw\n * enum value.\n */\nexport function printSessionSkip(sid: string, reason: SessionSkipReason): void {\n const short = shortSessionId(sid);\n if (reason === \"events_jsonl_unreadable\") {\n console.error(`Warning: skipped suspect check for ${short}: events.jsonl unreadable`);\n } else {\n console.error(`Skipped ${short}: ${reason}`);\n }\n}\n\n/**\n * Print a session-skip warning in the \"list\" form used by `session list`.\n * Each reason is mapped to a user-friendly English phrase rather than the\n * raw enum value. `events_jsonl_unreadable` shares the wording produced by\n * {@link printSessionSkip} so the CLI surface stays consistent across\n * subcommands.\n */\nexport function printSessionListSkip(sid: string, reason: SessionSkipReason): void {\n const short = shortSessionId(sid);\n switch (reason) {\n case \"session_yaml_missing\":\n console.error(`Skipped ${short}: session.yaml not found`);\n break;\n case \"session_yaml_invalid\":\n console.error(`Skipped ${short}: invalid session schema`);\n break;\n case \"events_jsonl_unreadable\":\n console.error(`Warning: skipped suspect check for ${short}: events.jsonl unreadable`);\n break;\n }\n}\n\n/**\n * Print a task-skip warning shared between `task list` (which sees a\n * narrowed {@link TaskSkipReason} enum) and handoff / decisions generators\n * (which may forward an arbitrary reason string). Accepts a plain `string`\n * so both shapes route through the same renderer.\n */\nexport function printTaskSkip(taskId: string, reason: TaskSkipReason | string): void {\n console.error(`Skipped ${shortTaskId(taskId)}: ${reason}`);\n}\n","import { createRequire } from \"node:module\";\nimport { Command } from \"commander\";\nimport { registerApprovalCommand } from \"./commands/approval.js\";\nimport { registerDecisionCommand } from \"./commands/decision.js\";\nimport { registerDecisionsCommand } from \"./commands/decisions.js\";\nimport { registerExecCommand } from \"./commands/exec.js\";\nimport { registerHandoffCommand } from \"./commands/handoff.js\";\nimport { registerImportCommand } from \"./commands/import.js\";\nimport { registerInitCommand } from \"./commands/init.js\";\nimport { registerRefreshCommand } from \"./commands/refresh.js\";\nimport { registerRunCommand } from \"./commands/run.js\";\nimport { registerSessionCommand } from \"./commands/session.js\";\nimport { registerStatsCommand } from \"./commands/stats.js\";\nimport { registerStatusCommand } from \"./commands/status.js\";\nimport { registerTaskCommand } from \"./commands/task.js\";\nimport { registerViewCommand } from \"./commands/view.js\";\n\n// Read the CLI release version directly from the sibling package.json so\n// `basou --version` cannot drift past a future package-bump (the v0.2/v0.3\n// releases both shipped with a stale \"0.1.0\" constant before the dynamic\n// read landed). The relative path is stable across the dev (src/program.ts\n// → src/../package.json) and built (dist/program.js → dist/../package.json)\n// layouts, since both files sit one directory below the package root.\nconst require = createRequire(import.meta.url);\nconst pkg = require(\"../package.json\") as { version: string };\nexport const BASOU_CLI_VERSION = pkg.version;\n\n/**\n * Build the fully-registered `basou` command tree WITHOUT parsing argv.\n *\n * This is the side-effect-free entry shared by the CLI binary (./index.ts)\n * and any introspection consumer — e.g. the docs generator that renders the\n * command reference from the published `@basou/cli`. Importing this module\n * must never parse `process.argv` or run a command action; `index.ts` owns\n * the single `parseAsync` call.\n */\nexport function buildProgram(): Command {\n const program = new Command();\n program\n .name(\"basou\")\n .description(\"Provenance layer for AI development\")\n .version(BASOU_CLI_VERSION)\n // Required so that `basou exec` (and any other passThroughOptions\n // subcommand) can forward unknown flags to the wrapped child.\n .enablePositionalOptions();\n\n registerInitCommand(program);\n registerStatusCommand(program);\n registerStatsCommand(program);\n registerExecCommand(program);\n registerRunCommand(program);\n registerSessionCommand(program);\n registerImportCommand(program);\n registerRefreshCommand(program);\n registerViewCommand(program);\n registerApprovalCommand(program);\n registerDecisionCommand(program);\n registerTaskCommand(program);\n registerHandoffCommand(program);\n registerDecisionsCommand(program);\n\n return program;\n}\n","import { unlink } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport {\n type Approval,\n type ApprovalLocation,\n ApprovalSchema,\n type ApprovalStatus,\n ApprovalStatusSchema,\n appendEvent,\n assertBasouRootSafe,\n type BasouPaths,\n basouPaths,\n type Event,\n enumerateApprovals,\n findErrorCode,\n isLazyExpired,\n linkYamlFile,\n loadApproval,\n prefixedUlid,\n readYamlFile,\n replayEvents,\n resolveRepositoryRoot,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport { isVerbose, printReplayWarning, renderCliError } from \"../lib/error-render.js\";\n\nconst APPR_PREFIX = \"appr_\";\nconst SHORT_ID_BASE_LEN = 6;\nconst SHORT_ID_MAX_LEN = 26; // ULID body length\nconst ACTION_KEY_DETAIL_MAX_LEN = 60;\nconst REASON_TEXT_MAX_LEN = 80;\n\nconst STATUS_VALUES = ApprovalStatusSchema.options;\n\nexport type ApprovalListOptions = {\n json?: boolean;\n status?: ApprovalStatus;\n verbose?: boolean;\n};\n\nexport type ApprovalShowOptions = {\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type ApprovalApproveOptions = {\n note?: string;\n verbose?: boolean;\n};\n\nexport type ApprovalRejectOptions = {\n reason: string;\n verbose?: boolean;\n};\n\nexport type ApprovalContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n};\n\ntype ApprovalListRecord = {\n approval: Approval;\n location: ApprovalLocation;\n lazyExpired: boolean;\n};\n\n/**\n * Wire `basou approval list / show / approve / reject` onto `program`.\n *\n * The `approval` group is registered up front so future subcommands\n * (`cancel`, `recover`) added in later steps slot under the same group\n * without changing the externally visible CLI surface.\n */\nexport function registerApprovalCommand(program: Command): void {\n const approval = program\n .command(\"approval\")\n .description(\"Manage Basou approval requests under .basou/approvals/\");\n\n approval\n .command(\"list\")\n .description(\"List approvals across pending and resolved (newest first)\")\n .option(\"--json\", \"Output the list as a JSON array\")\n .option(\n \"--status <state>\",\n `Filter by approval status (one of: ${STATUS_VALUES.join(\", \")})`,\n parseApprovalStatus,\n )\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: ApprovalListOptions) => {\n await runApprovalList(options);\n });\n\n approval\n .command(\"show <id>\")\n .description(\"Show an approval's metadata and related events\")\n .option(\"--json\", \"Output the approval and events as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (id: string, options: ApprovalShowOptions) => {\n await runApprovalShow(id, options);\n });\n\n approval\n .command(\"approve <id>\")\n .description(\"Approve a pending approval\")\n .option(\"--note <text>\", \"Optional note to attach to the approval_approved event\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (id: string, options: ApprovalApproveOptions) => {\n await runApprovalApprove(id, options);\n });\n\n approval\n .command(\"reject <id>\")\n .description(\"Reject a pending approval\")\n .requiredOption(\"--reason <text>\", \"Reason for rejection (required)\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (id: string, options: ApprovalRejectOptions) => {\n await runApprovalReject(id, options);\n });\n}\n\n// === list ===\n\n/**\n * Programmatic entry for `basou approval list` that owns process exit\n * state. Tests targeting only the success path or the thrown error should\n * prefer {@link doRunApprovalList}.\n */\nexport async function runApprovalList(\n options: ApprovalListOptions,\n ctx: ApprovalContext = {},\n): Promise<void> {\n try {\n await doRunApprovalList(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * Pure runner for `approval list`. Throws on any failure with a pathless\n * message; native errors are attached as `cause` for verbose surfacing.\n */\nexport async function doRunApprovalList(\n options: ApprovalListOptions,\n ctx: ApprovalContext,\n): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForApproval(cwd, \"list\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const ids = await enumerateApprovals(paths);\n // A single `now` shared across every record so that two reads on the\n // same boundary instant cannot disagree (e.g. one record flagged expired\n // and another not when both straddle the same `expires_at`).\n const now = new Date();\n const records: ApprovalListRecord[] = [];\n\n // Resolve dedupe set: id appearing in both directories → prefer resolved\n // and surface a stderr warning about the stale pending entry.\n const resolvedSet = new Set(ids.resolved);\n for (const id of ids.pending) {\n if (resolvedSet.has(id)) {\n console.error(`Warning: stale pending entry for ${shortId(id)}; resolved version preferred`);\n continue;\n }\n const rec = await readApprovalListRecord(paths, id, \"pending\", now);\n if (rec !== null) records.push(rec);\n }\n for (const id of ids.resolved) {\n const rec = await readApprovalListRecord(paths, id, \"resolved\", now);\n if (rec !== null) records.push(rec);\n }\n\n records.sort((a, b) => Date.parse(b.approval.created_at) - Date.parse(a.approval.created_at));\n\n const filtered =\n options.status !== undefined\n ? records.filter((r) => r.approval.status === options.status)\n : records;\n\n if (filtered.length === 0) {\n printNoApprovals(options);\n return;\n }\n\n if (options.json === true) {\n console.log(\n JSON.stringify(\n filtered.map((r) => ({ ...r.approval, lazy_expired: r.lazyExpired })),\n null,\n 2,\n ),\n );\n } else {\n printApprovalListText(filtered);\n }\n}\n\nasync function readApprovalListRecord(\n paths: BasouPaths,\n id: string,\n location: ApprovalLocation,\n now: Date,\n): Promise<ApprovalListRecord | null> {\n const filePath = join(paths.approvals[location], `${id}.yaml`);\n let raw: unknown;\n try {\n raw = await readYamlFile(filePath);\n } catch (error: unknown) {\n console.error(`Skipped ${shortId(id)}: ${describeReadError(error)}`);\n return null;\n }\n const parse = ApprovalSchema.safeParse(raw);\n if (!parse.success) {\n console.error(`Skipped ${shortId(id)}: invalid approval schema`);\n return null;\n }\n if (parse.data.id !== id) {\n // Surface a stderr warning rather than dropping silently so an operator\n // can spot the corrupted entry from `basou approval list`.\n console.error(`Skipped ${shortId(id)}: filename and YAML body id disagree`);\n return null;\n }\n const approval = parse.data;\n return { approval, location, lazyExpired: isLazyExpired(approval, now) };\n}\n\n// === show ===\n\nexport async function runApprovalShow(\n idInput: string,\n options: ApprovalShowOptions,\n ctx: ApprovalContext = {},\n): Promise<void> {\n try {\n await doRunApprovalShow(idInput, options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunApprovalShow(\n idInput: string,\n options: ApprovalShowOptions,\n ctx: ApprovalContext,\n): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForApproval(cwd, \"show\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const { id } = await resolveApprovalId(paths, idInput);\n const loaded = await loadApproval(paths, id);\n if (loaded === null) {\n throw new Error(`Approval not found: ${idInput}`);\n }\n\n // events.jsonl I/O failure throws \"Failed to read events.jsonl\" and is\n // converted to exit 1 by the wrapping try/catch — partial / malformed /\n // schema warnings stream through onWarning.\n const sessionDir = join(paths.sessions, loaded.approval.session_id);\n const relatedEvents: Event[] = [];\n for await (const ev of replayEvents(sessionDir, {\n onWarning: (w) => printReplayWarning(w, loaded.approval.session_id),\n })) {\n if (isApprovalEvent(ev) && ev.approval_id === id) {\n relatedEvents.push(ev);\n }\n }\n\n const now = new Date();\n const lazyExpired = isLazyExpired(loaded.approval, now);\n\n if (options.json === true) {\n console.log(\n JSON.stringify(\n {\n approval: { ...loaded.approval, lazy_expired: lazyExpired },\n events: relatedEvents,\n },\n null,\n 2,\n ),\n );\n return;\n }\n\n printApprovalShowText(loaded.approval, loaded.location, relatedEvents, lazyExpired);\n}\n\n// === approve / reject ===\n\nexport async function runApprovalApprove(\n idInput: string,\n options: ApprovalApproveOptions,\n ctx: ApprovalContext = {},\n): Promise<void> {\n try {\n await doRunApprovalResolve(idInput, options, ctx, \"approve\");\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\nexport async function runApprovalReject(\n idInput: string,\n options: ApprovalRejectOptions,\n ctx: ApprovalContext = {},\n): Promise<void> {\n try {\n await doRunApprovalResolve(idInput, options, ctx, \"reject\");\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\nasync function doRunApprovalResolve(\n idInput: string,\n options: ApprovalApproveOptions | ApprovalRejectOptions,\n ctx: ApprovalContext,\n decision: \"approve\" | \"reject\",\n): Promise<void> {\n if (decision === \"reject\") {\n const reason = (options as ApprovalRejectOptions).reason;\n if (reason.length === 0) {\n throw new Error(\"--reason must not be empty\");\n }\n }\n\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForApproval(cwd, decision);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n // Step D-2: resolve id (search both directories).\n const { id, location } = await resolveApprovalId(paths, idInput);\n\n // Step D-3: a resolved-side hit means there is nothing left to decide.\n if (location === \"resolved\") {\n throw new Error(`Approval already resolved: ${idInput}`);\n }\n\n // Step D-4: read + parse the pending YAML.\n const pendingPath = join(paths.approvals.pending, `${id}.yaml`);\n let pendingRaw: unknown;\n try {\n pendingRaw = await readYamlFile(pendingPath);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"YAML file not found\") {\n throw new Error(`Approval not found: ${idInput}`);\n }\n throw new Error(\"Failed to read approval\", { cause: error });\n }\n // Wrap zod's parse so a malformed pending YAML surfaces through the\n // pathless `Failed to read approval` contract instead of leaking a raw\n // ZodError through the rendered output.\n const approvalParse = ApprovalSchema.safeParse(pendingRaw);\n if (!approvalParse.success) {\n throw new Error(\"Failed to read approval\", { cause: approvalParse.error });\n }\n const approval = approvalParse.data;\n // Defensive id check (matches loadApproval): filename id and body id\n // must agree, otherwise we'd resolve one approval while emitting events\n // for another.\n if (approval.id !== id) {\n throw new Error(\"Failed to read approval\", {\n cause: new Error(`Approval id mismatch: filename id ${id} vs YAML body id ${approval.id}`),\n });\n }\n // A pending-side YAML whose status is no longer `pending` means the\n // file was corrupted (or hand-edited mid-resolution). Refuse to fire a\n // second resolution event for it.\n if (approval.status !== \"pending\") {\n throw new Error(`Approval status mismatch: pending YAML has status=${approval.status}`);\n }\n\n // Step D-5: events.jsonl fence — if a resolution event already exists\n // for this approval, refuse to fire a second one. This guards the\n // crash-mid-orchestration window where step 8 succeeded but step 10\n // failed (events.jsonl is the source-of-truth, not the YAML mirror).\n const sessionDir = join(paths.sessions, approval.session_id);\n for await (const ev of replayEvents(sessionDir, {\n onWarning: (w) => printReplayWarning(w, approval.session_id),\n })) {\n if (\n isApprovalEvent(ev) &&\n ev.approval_id === approval.id &&\n (ev.type === \"approval_approved\" ||\n ev.type === \"approval_rejected\" ||\n ev.type === \"approval_expired\")\n ) {\n throw new Error(`Approval already resolved (per events.jsonl): ${idInput}`);\n }\n }\n\n // Step D-6: lazy expire state-fence. No event is fired here; the\n // approval_expired event is reserved for a later step that owns\n // expiry-side orchestration.\n const now = new Date();\n if (isLazyExpired(approval, now)) {\n throw new Error(`Approval already expired: ${idInput}`);\n }\n\n // Step D-7: prepare event id + occurred_at (shared with step 9 below).\n const occurredAt = now.toISOString();\n const eventId = prefixedUlid(\"evt\");\n\n // Step D-8: append the resolution event to events.jsonl. After this\n // point the trail is committed; subsequent failures must not roll back\n // the event because that would break the source-of-truth invariant.\n if (decision === \"approve\") {\n const note = (options as ApprovalApproveOptions).note ?? null;\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n id: eventId,\n session_id: approval.session_id,\n occurred_at: occurredAt,\n source: \"local-cli\",\n type: \"approval_approved\",\n approval_id: approval.id,\n resolver: \"local-cli\",\n note,\n });\n } else {\n const reason = (options as ApprovalRejectOptions).reason;\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n id: eventId,\n session_id: approval.session_id,\n occurred_at: occurredAt,\n source: \"local-cli\",\n type: \"approval_rejected\",\n approval_id: approval.id,\n resolver: \"local-cli\",\n reason,\n });\n }\n\n // Step D-9: build the resolved-side YAML body in memory.\n const resolvedApproval: Approval =\n decision === \"approve\"\n ? {\n ...approval,\n status: \"approved\",\n resolver: \"local-cli\",\n resolved_at: occurredAt,\n note: (options as ApprovalApproveOptions).note ?? null,\n }\n : {\n ...approval,\n status: \"rejected\",\n resolver: \"local-cli\",\n resolved_at: occurredAt,\n rejection_reason: (options as ApprovalRejectOptions).reason,\n };\n\n // Step D-10: create-only write. linkYamlFile fails fast with EEXIST if a\n // concurrent resolver already populated the resolved-side YAML — the\n // events.jsonl fence above should have caught it first, so reaching\n // EEXIST here implies a near-simultaneous race we surface explicitly.\n const resolvedPath = join(paths.approvals.resolved, `${id}.yaml`);\n try {\n await linkYamlFile(resolvedPath, resolvedApproval);\n } catch (error: unknown) {\n const cause = error instanceof Error ? error.cause : undefined;\n if (cause instanceof Error && (cause as Error & { code?: unknown }).code === \"EEXIST\") {\n throw new Error(\"Approval already resolved at the same time\", { cause });\n }\n throw error;\n }\n\n // Step D-11: best-effort unlink of the pending YAML. The trail and the\n // resolved-side YAML are already consistent at this point; a leftover\n // pending entry is reconciled by the next `approval list`'s dedupe.\n try {\n await unlink(pendingPath);\n } catch {\n console.error(\n `Warning: failed to unlink pending entry for ${shortId(id)}; events.jsonl is consistent`,\n );\n }\n\n // Step D-12: success message.\n const verb = decision === \"approve\" ? \"Approved\" : \"Rejected\";\n console.log(`${verb} approval ${shortId(id)}`);\n}\n\n// === helpers ===\n\nasync function resolveApprovalId(\n paths: BasouPaths,\n input: string,\n): Promise<{ id: string; location: ApprovalLocation }> {\n const trimmed = input.trim();\n if (trimmed.length === 0) {\n throw new Error(\"Approval id is empty\");\n }\n const normalized = trimmed.startsWith(APPR_PREFIX) ? trimmed : `${APPR_PREFIX}${trimmed}`;\n // Reject prefix-only input so a bare prefix cannot match an arbitrary\n // approval via `startsWith`.\n if (normalized.length <= APPR_PREFIX.length) {\n throw new Error(`Approval not found: ${input}`);\n }\n\n const enumeration = await enumerateApprovals(paths);\n\n // Aggregate by full id so a duplicate (same id in both pending and\n // resolved) collapses to one entry with location=resolved (preferred).\n const byId = new Map<string, ApprovalLocation>();\n for (const id of enumeration.pending) {\n if (id.startsWith(normalized)) byId.set(id, \"pending\");\n }\n for (const id of enumeration.resolved) {\n if (!id.startsWith(normalized)) continue;\n if (byId.get(id) === \"pending\") {\n // Same full id present on both sides: resolved wins, surface a warning.\n console.error(`Warning: stale pending entry for ${shortId(id)}; resolved version preferred`);\n }\n byId.set(id, \"resolved\");\n }\n\n if (byId.size === 0) {\n throw new Error(`Approval not found: ${input}`);\n }\n if (byId.size > 1) {\n throw new Error(\n `Ambiguous approval id '${input}': matched ${byId.size} approvals. Disambiguate with a longer prefix.`,\n );\n }\n const first = byId.entries().next().value;\n if (first === undefined) {\n throw new Error(`Approval not found: ${input}`);\n }\n const [id, location] = first;\n return { id, location };\n}\n\nfunction isApprovalEvent(ev: Event): ev is Event & { approval_id: string } {\n return (\n ev.type === \"approval_requested\" ||\n ev.type === \"approval_approved\" ||\n ev.type === \"approval_rejected\" ||\n ev.type === \"approval_expired\"\n );\n}\n\nfunction printApprovalListText(records: ApprovalListRecord[]): void {\n // Grow the SHORT_ID column on collision. The dedupe in doRunApprovalList\n // already collapsed duplicates by full id, so feeding only the unique\n // ids here is correct.\n const allIds = records.map((r) => r.approval.id);\n const shortLen = computeUniquePrefixLen(allIds);\n const rows = records.map((r) => {\n const sid = sliceShort(r.approval.id, shortLen);\n const status = r.lazyExpired ? `${r.approval.status} (expired)` : r.approval.status;\n const risk = r.approval.risk_level;\n const action = r.approval.action.kind;\n const createdAt = r.approval.created_at;\n const reason = truncate(r.approval.reason, REASON_TEXT_MAX_LEN);\n return { sid, status, risk, action, createdAt, reason };\n });\n\n const widths = {\n sid: maxLen(\n rows.map((r) => r.sid),\n \"SHORT_ID\".length,\n ),\n status: maxLen(\n rows.map((r) => r.status),\n \"STATUS\".length,\n ),\n risk: maxLen(\n rows.map((r) => r.risk),\n \"RISK\".length,\n ),\n action: maxLen(\n rows.map((r) => r.action),\n \"ACTION\".length,\n ),\n createdAt: maxLen(\n rows.map((r) => r.createdAt),\n \"CREATED_AT\".length,\n ),\n };\n\n console.log(\n `${pad(\"SHORT_ID\", widths.sid)} ${pad(\"STATUS\", widths.status)} ${pad(\"RISK\", widths.risk)} ${pad(\"ACTION\", widths.action)} ${pad(\"CREATED_AT\", widths.createdAt)} REASON`,\n );\n for (const row of rows) {\n console.log(\n `${pad(row.sid, widths.sid)} ${pad(row.status, widths.status)} ${pad(row.risk, widths.risk)} ${pad(row.action, widths.action)} ${pad(row.createdAt, widths.createdAt)} ${row.reason}`,\n );\n }\n}\n\nfunction printApprovalShowText(\n approval: Approval,\n _location: ApprovalLocation,\n events: readonly Event[],\n lazyExpired: boolean,\n): void {\n console.log(`Approval: ${approval.id} (status: ${approval.status})`);\n console.log(`Session: ${approval.session_id}`);\n console.log(`Created at: ${approval.created_at}`);\n console.log(`Risk level: ${approval.risk_level}`);\n console.log(`Action: ${formatActionLine(approval.action)}`);\n console.log(`Reason: ${approval.reason}`);\n const expiresLabel = formatExpiresLabel(approval.expires_at, lazyExpired);\n console.log(`Expires at: ${expiresLabel}`);\n console.log(`Resolver: ${approval.resolver ?? \"(none)\"}`);\n console.log(`Resolved at: ${approval.resolved_at ?? \"(none)\"}`);\n console.log(`Note: ${approval.note ?? \"(none)\"}`);\n console.log(`Rejection reason: ${approval.rejection_reason ?? \"(none)\"}`);\n\n console.log(\"\");\n console.log(`Related events: ${events.length} total`);\n for (const ev of events) {\n console.log(` ${formatApprovalEventLine(ev)}`);\n }\n}\n\nfunction formatActionLine(action: { kind: string } & Record<string, unknown>): string {\n const extras: string[] = [];\n for (const [key, value] of Object.entries(action)) {\n if (key === \"kind\") continue;\n if (typeof value !== \"string\") continue;\n extras.push(`${key}=\"${truncate(value, ACTION_KEY_DETAIL_MAX_LEN)}\"`);\n if (extras.length >= 2) break;\n }\n return extras.length === 0 ? action.kind : `${action.kind} (${extras.join(\", \")})`;\n}\n\nfunction formatExpiresLabel(expiresAt: string | null, lazyExpired: boolean): string {\n if (expiresAt === null) return \"(none)\";\n return lazyExpired ? `${expiresAt} (expired)` : expiresAt;\n}\n\nfunction formatApprovalEventLine(ev: Event): string {\n const summary = approvalEventSummary(ev);\n return `${ev.occurred_at} [${ev.source}] ${ev.type} ${summary}`;\n}\n\nfunction approvalEventSummary(ev: Event): string {\n switch (ev.type) {\n case \"approval_requested\":\n return `${ev.action.kind} risk=${ev.risk_level}`;\n case \"approval_approved\":\n return ev.resolver !== undefined ? `by ${ev.resolver}` : \"(approved)\";\n case \"approval_rejected\":\n return ev.resolver !== undefined ? `by ${ev.resolver}: ${ev.reason}` : ev.reason;\n case \"approval_expired\":\n return `approval=${ev.approval_id}`;\n default:\n // Other event types are filtered out before reaching this helper.\n return \"\";\n }\n}\n\nfunction shortId(id: string): string {\n return sliceShort(id, SHORT_ID_BASE_LEN);\n}\n\n// Known Basou prefixed-id leading tokens. Strip whichever applies so that\n// a session id passed through the warning handler renders as the bare\n// ULID prefix (matching what session.ts already emits) instead of leaving\n// the `ses_` head in the truncated short id.\nconst KNOWN_ID_PREFIXES = [\"appr_\", \"ses_\", \"evt_\", \"ws_\", \"task_\", \"decision_\"] as const;\n\nfunction sliceShort(id: string, len: number): string {\n for (const prefix of KNOWN_ID_PREFIXES) {\n if (id.startsWith(prefix)) {\n return id.slice(prefix.length, prefix.length + len);\n }\n }\n return id.slice(0, len);\n}\n\nfunction computeUniquePrefixLen(ids: readonly string[]): number {\n if (ids.length <= 1) return SHORT_ID_BASE_LEN;\n for (let len = SHORT_ID_BASE_LEN; len <= SHORT_ID_MAX_LEN; len += 2) {\n const seen = new Set<string>();\n let collided = false;\n for (const id of ids) {\n const key = sliceShort(id, len);\n if (seen.has(key)) {\n collided = true;\n break;\n }\n seen.add(key);\n }\n if (!collided) return len;\n }\n return SHORT_ID_MAX_LEN;\n}\n\nfunction pad(value: string, width: number): string {\n return value.length >= width ? value : value + \" \".repeat(width - value.length);\n}\n\nfunction maxLen(values: readonly string[], floor: number): number {\n let max = floor;\n for (const v of values) if (v.length > max) max = v.length;\n return max;\n}\n\nfunction truncate(value: string, maxLength: number): string {\n if (value.length <= maxLength) return value;\n return `${value.slice(0, maxLength - 3)}...`;\n}\n\nasync function resolveRepositoryRootForApproval(\n cwd: string,\n subcmd: \"list\" | \"show\" | \"approve\" | \"reject\",\n): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\n `Not a git repository. Run 'git init' first, then re-run 'basou approval ${subcmd}'.`,\n { cause: error },\n );\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n\nfunction describeReadError(error: unknown): string {\n if (error instanceof Error) {\n if (error.message === \"YAML file not found\") return \"approval YAML not found\";\n if (error.message === \"Failed to parse YAML content\") return \"invalid YAML\";\n return error.message;\n }\n return String(error);\n}\n\nfunction parseApprovalStatus(raw: string): ApprovalStatus {\n const result = ApprovalStatusSchema.safeParse(raw);\n if (!result.success) {\n throw new Error(`Invalid approval status: ${raw}. Valid values: ${STATUS_VALUES.join(\", \")}`);\n }\n return result.data;\n}\n\nfunction printNoApprovals(options: ApprovalListOptions): void {\n if (options.json === true) {\n console.log(\"[]\");\n } else {\n console.log(\"No approvals found.\");\n }\n}\n","import {\n acquireLock,\n appendEventToExistingSession,\n assertBasouRootSafe,\n basouPaths,\n createAdHocSessionWithEvent,\n type Event,\n findErrorCode,\n type PrefixedId,\n prefixedUlid,\n readManifest,\n resolveRepositoryRoot,\n resolveSessionId,\n type SessionStatus,\n} from \"@basou/core\";\nimport { type Command, InvalidArgumentError } from \"commander\";\nimport {\n failedToFinalizeClassifier,\n isVerbose,\n renderCliError,\n shortSessionId,\n} from \"../lib/error-render.js\";\n\n// Raised from the original 40-char cap to 80 chars so a long decision\n// title (= the most common ad-hoc trigger) retains its core information\n// without being truncated. 80 chars still fits comfortably in\n// single-column session list / handoff renderings. Operator feedback\n// from real-world long-title outliers may revisit this value.\nconst LABEL_TITLE_MAX = 80;\nconst LABEL_TRUNCATE_HEAD = LABEL_TITLE_MAX - 3;\n\nexport type DecisionRecordOptions = {\n title: string;\n rationale?: string;\n rejectedReason?: string;\n alternative?: string[];\n linkedEvent?: string[];\n linkedFile?: string[];\n session?: string;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type DecisionContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n /** Defaults to `() => new Date()`. Injectable for tests. */\n nowProvider?: () => Date;\n};\n\n/**\n * Wire `basou decision record` onto `program`. The `decision` group only\n * contains the write-side `record` subcommand in v0.1; list/show inspectors\n * are deferred to a v0.3+ follow-up.\n */\nexport function registerDecisionCommand(program: Command): void {\n const decision = program\n .command(\"decision\")\n .description(\"Record human-authored decisions as events\");\n\n decision\n .command(\"record\")\n .description(\"Record a decision_recorded event\")\n .requiredOption(\"--title <text>\", \"Decision title\", parseTitle)\n .option(\"--rationale <text>\", \"Rationale for the decision\", parseRationale)\n .option(\n \"--rejected-reason <text>\",\n \"Reason rejected alternatives were not chosen\",\n parseRejectedReason,\n )\n .option(\n \"--alternative <text>\",\n \"Alternative considered (repeatable: --alternative yup --alternative joi)\",\n collectAlternative,\n [] as string[],\n )\n .option(\n \"--linked-event <event_id>\",\n \"Related event id (repeatable). Schema only checks the prefix; existence is verified at render time.\",\n collectLinkedEvent,\n [] as string[],\n )\n .option(\n \"--linked-file <path>\",\n \"Related file path (repeatable). Path is opaque; existence is verified at render time.\",\n collectLinkedFile,\n [] as string[],\n )\n .option(\n \"--session <session_id>\",\n \"Attach to an existing session; otherwise an ad-hoc session is created\",\n )\n .option(\"--json\", \"Output the result as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: DecisionRecordOptions) => {\n await runDecisionRecord(options);\n });\n}\n\n/**\n * Programmatic entry for `basou decision record`. Owns process exit state.\n * Tests targeting the success path or the thrown error should prefer\n * {@link doRunDecisionRecord}.\n */\nexport async function runDecisionRecord(\n options: DecisionRecordOptions,\n ctx: DecisionContext = {},\n): Promise<void> {\n try {\n await doRunDecisionRecord(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, {\n verbose: isVerbose(options),\n classifiers: [failedToFinalizeClassifier],\n });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunDecisionRecord(\n options: DecisionRecordOptions,\n ctx: DecisionContext,\n): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForDecision(cwd);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const now = ctx.nowProvider !== undefined ? ctx.nowProvider() : new Date();\n const occurredAt = now.toISOString();\n const decisionId = prefixedUlid(\"decision\");\n\n const rich = pickRichFields(options);\n\n if (options.session !== undefined) {\n const sessionId = await resolveSessionId(paths, options.session);\n const sesId = sessionId as PrefixedId<\"ses\">;\n // Per-session lock guards the session.yaml status read + events.jsonl\n // append window against a concurrent writer (`basou session note`,\n // another `decision record --session`, or an attach-flavoured task\n // command). `appendEventToExistingSession` itself holds no lock; the\n // caller owns the critical section.\n const sessionLock = await acquireLock(paths, \"session\", sesId);\n let result: Awaited<ReturnType<typeof appendEventToExistingSession>>;\n try {\n result = await appendEventToExistingSession({\n paths,\n sessionId: sesId,\n eventBuilder: (eventId) =>\n buildDecisionEvent({\n eventId,\n sessionId: sesId,\n decisionId,\n title: options.title,\n occurredAt,\n rich,\n }),\n });\n } finally {\n await sessionLock.release();\n }\n printDecisionResult(options, {\n mode: \"attached\",\n sessionId,\n decisionId,\n eventId: result.eventId,\n sessionStatus: result.sessionStatus,\n title: options.title,\n rich,\n });\n return;\n }\n\n const manifest = await readManifest(paths);\n const adHoc = await createAdHocSessionWithEvent({\n paths,\n manifest,\n label: buildAdHocLabel(options.title),\n occurredAt,\n sessionSource: \"human\",\n workingDirectory: repositoryRoot,\n invocation: {\n command: \"basou decision record\",\n args: [\"--title\", options.title],\n },\n targetEventBuilders: [\n (sessionId, eventId) =>\n buildDecisionEvent({\n eventId,\n sessionId,\n decisionId,\n title: options.title,\n occurredAt,\n rich,\n }),\n ],\n });\n printDecisionResult(options, {\n mode: \"ad-hoc\",\n sessionId: adHoc.sessionId,\n decisionId,\n eventId: adHoc.targetEventIds[0] as string,\n sessionStatus: \"completed\",\n title: options.title,\n rich,\n });\n}\n\ntype RichDecisionFields = {\n rationale?: string;\n rejected_reason?: string;\n alternatives?: string[];\n linked_events?: string[];\n linked_files?: string[];\n};\n\nfunction pickRichFields(options: DecisionRecordOptions): RichDecisionFields {\n const out: RichDecisionFields = {};\n if (options.rationale !== undefined) out.rationale = options.rationale;\n if (options.rejectedReason !== undefined) out.rejected_reason = options.rejectedReason;\n if (options.alternative !== undefined && options.alternative.length > 0) {\n out.alternatives = [...options.alternative];\n }\n if (options.linkedEvent !== undefined && options.linkedEvent.length > 0) {\n out.linked_events = [...options.linkedEvent];\n }\n if (options.linkedFile !== undefined && options.linkedFile.length > 0) {\n out.linked_files = [...options.linkedFile];\n }\n return out;\n}\n\nfunction buildDecisionEvent(input: {\n eventId: PrefixedId<\"evt\">;\n sessionId: PrefixedId<\"ses\">;\n decisionId: PrefixedId<\"decision\">;\n title: string;\n occurredAt: string;\n rich: RichDecisionFields;\n}): Event {\n return {\n schema_version: \"0.1.0\",\n id: input.eventId,\n session_id: input.sessionId,\n occurred_at: input.occurredAt,\n source: \"local-cli\",\n type: \"decision_recorded\",\n decision_id: input.decisionId,\n title: input.title,\n ...(input.rich.rationale !== undefined ? { rationale: input.rich.rationale } : {}),\n ...(input.rich.alternatives !== undefined ? { alternatives: input.rich.alternatives } : {}),\n ...(input.rich.rejected_reason !== undefined\n ? { rejected_reason: input.rich.rejected_reason }\n : {}),\n ...(input.rich.linked_events !== undefined\n ? { linked_events: input.rich.linked_events as Array<`evt_${string}`> }\n : {}),\n ...(input.rich.linked_files !== undefined ? { linked_files: input.rich.linked_files } : {}),\n };\n}\n\nfunction buildAdHocLabel(title: string): string {\n const truncated =\n title.length > LABEL_TITLE_MAX ? `${title.slice(0, LABEL_TRUNCATE_HEAD)}...` : title;\n return `Ad-hoc decision: ${truncated}`;\n}\n\nfunction parseTitle(raw: string): string {\n if (raw.length === 0) {\n throw new InvalidArgumentError(\"Title must not be empty\");\n }\n return raw;\n}\n\nfunction parseRationale(raw: string): string {\n if (raw.length === 0) {\n throw new InvalidArgumentError(\"Rationale must not be empty\");\n }\n return raw;\n}\n\nfunction parseRejectedReason(raw: string): string {\n if (raw.length === 0) {\n throw new InvalidArgumentError(\"Rejected reason must not be empty\");\n }\n return raw;\n}\n\nfunction collectAlternative(value: string, prev: string[]): string[] {\n if (value.length === 0) {\n throw new InvalidArgumentError(\"Alternative must not be empty\");\n }\n return prev.concat(value);\n}\n\nconst EVENT_ID_RE = /^evt_[A-Z0-9]+$/;\n\nfunction collectLinkedEvent(value: string, prev: string[]): string[] {\n if (!EVENT_ID_RE.test(value)) {\n throw new InvalidArgumentError(`Linked event id must match evt_<ULID>, got '${value}'`);\n }\n return prev.concat(value);\n}\n\nfunction collectLinkedFile(value: string, prev: string[]): string[] {\n if (value.length === 0) {\n throw new InvalidArgumentError(\"Linked file path must not be empty\");\n }\n if (value.length > 4096) {\n throw new InvalidArgumentError(\"Linked file path exceeds 4096 chars\");\n }\n return prev.concat(value);\n}\n\ntype DecisionPrintInput = {\n mode: \"ad-hoc\" | \"attached\";\n sessionId: string;\n decisionId: string;\n eventId: string;\n sessionStatus: SessionStatus;\n title: string;\n rich: RichDecisionFields;\n};\n\nfunction printDecisionResult(options: DecisionRecordOptions, result: DecisionPrintInput): void {\n const sid = shortSessionId(result.sessionId);\n if (options.json === true) {\n const payload: Record<string, unknown> = {\n decision_id: result.decisionId,\n event_id: result.eventId,\n session_id: result.sessionId,\n session_status: result.sessionStatus,\n mode: result.mode,\n title: result.title,\n };\n // Rich fields are now persisted into the decision_recorded event, so\n // they appear in the JSON summary as-is (the old `rationale_saved:\n // false` indicator is gone).\n if (result.rich.rationale !== undefined) payload.rationale = result.rich.rationale;\n if (result.rich.alternatives !== undefined) payload.alternatives = result.rich.alternatives;\n if (result.rich.rejected_reason !== undefined) {\n payload.rejected_reason = result.rich.rejected_reason;\n }\n if (result.rich.linked_events !== undefined) payload.linked_events = result.rich.linked_events;\n if (result.rich.linked_files !== undefined) payload.linked_files = result.rich.linked_files;\n console.log(JSON.stringify(payload));\n return;\n }\n const rationaleSuffix =\n result.rich.rationale !== undefined ? ` (rationale: ${result.rich.rationale})` : \"\";\n if (result.mode === \"ad-hoc\") {\n console.log(`Recorded ${result.decisionId} in ad-hoc session ${sid}${rationaleSuffix}`);\n } else {\n console.log(\n `Recorded ${result.decisionId} in session ${sid} (${result.sessionStatus})${rationaleSuffix}`,\n );\n }\n}\n\nasync function resolveRepositoryRootForDecision(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\n \"Not a git repository. Run 'git init' first, then re-run 'basou decision record'.\",\n { cause: error },\n );\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n","import {\n assertBasouRootSafe,\n basouPaths,\n findErrorCode,\n readMarkdownFile,\n renderDecisions,\n renderWithMarkers,\n resolveRepositoryRoot,\n writeMarkdownFile,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport {\n isVerbose,\n printReplayWarning,\n printSessionSkip,\n renderCliError,\n} from \"../lib/error-render.js\";\n\nexport type DecisionsGenerateOptions = { verbose?: boolean };\n\nexport type DecisionsContext = {\n cwd?: string;\n nowProvider?: () => Date;\n};\n\n/** Wire `basou decisions generate` onto `program`. Mirrors `handoff` exactly. */\nexport function registerDecisionsCommand(program: Command): void {\n const decisions = program\n .command(\"decisions\")\n .description(\"Generate or inspect .basou/decisions.md\");\n\n decisions\n .command(\"generate\")\n .description(\"Regenerate .basou/decisions.md from recorded decision events\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (opts: DecisionsGenerateOptions) => {\n await runDecisionsGenerate(opts);\n });\n}\n\nexport async function runDecisionsGenerate(\n options: DecisionsGenerateOptions,\n ctx: DecisionsContext = {},\n): Promise<void> {\n try {\n await doRunDecisionsGenerate(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunDecisionsGenerate(\n options: DecisionsGenerateOptions,\n ctx: DecisionsContext,\n): Promise<void> {\n void options;\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForDecisions(cwd);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const nowIso = (ctx.nowProvider?.() ?? new Date()).toISOString();\n const result = await renderDecisions({\n paths,\n nowIso,\n onWarning: (w, sid) => printReplayWarning(w, sid),\n onSessionSkip: (sid, reason) => printSessionSkip(sid, reason),\n });\n\n const existing = await readMarkdownFile(paths.files.decisions);\n const finalBody = renderWithMarkers(existing, result.body, \"decisions.md\");\n await writeMarkdownFile(paths.files.decisions, finalBody);\n\n console.log(`Generated .basou/decisions.md (decisions: ${result.decisionCount})`);\n}\n\nasync function resolveRepositoryRootForDecisions(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\n \"Not a git repository. Run 'git init' first, then re-run 'basou decisions generate'.\",\n { cause: error },\n );\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n","import type { ChildProcess } from \"node:child_process\";\nimport { mkdir } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport {\n assertBasouRootSafe,\n basouPaths,\n ChildProcessRunner,\n appendEvent as coreAppendEvent,\n getSnapshot,\n overwriteYamlFile,\n type PrefixedId,\n type ProcessRunner,\n parseDuration,\n prefixedUlid,\n type RunResult,\n readManifest,\n readYamlFile,\n resolveRepositoryRoot,\n type Session,\n SessionSchema,\n sanitizeWorkingDirectory,\n writeYamlFile,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport { isVerbose, renderCliError } from \"../lib/error-render.js\";\n\ntype AppendEventFn = typeof coreAppendEvent;\n\n/**\n * `basou exec` orchestration: spawn an arbitrary child as a single new\n * Basou session and record its lifecycle (session_started, optional\n * git_snapshot pre, status_changed, command_executed, optional git_snapshot\n * post, status_changed, session_ended) to `events.jsonl`.\n *\n * Output is forwarded to the parent's terminal (`capture: \"none\"`); raw\n * stdout/stderr is intentionally not stored in events.jsonl or `.basou/raw/`.\n */\nexport type ExecOptions = {\n timeout?: string;\n cwd?: string;\n // commander turns `--no-snapshot` into `snapshot: false`. The default\n // (no flag) leaves this `undefined` (treated as `true` downstream).\n snapshot?: boolean;\n verbose?: boolean;\n};\n\ntype ExecContext = {\n runner?: ProcessRunner;\n now?: () => Date;\n // events.jsonl writer override. Tests use this to verify that appendEvent\n // failures during git_snapshot propagate as exec failures (see\n // tryAppendGitSnapshot below) instead of being swallowed into a skip warning.\n appendEvent?: AppendEventFn;\n // Last-resort SIGKILL hook installation hook. Tests capture the handler\n // installed on `process.on(\"exit\", ...)` and trigger it manually to verify\n // that activeChild is killed when the parent exits abnormally.\n onExitHookInstalled?: (handler: () => void) => void;\n};\n\nexport function registerExecCommand(program: Command): void {\n program\n .command(\"exec <command> [args...]\")\n .description(\"Execute a command and record it as a Basou session\")\n // Pass through unknown options/flags after the command name to the\n // child so callers can write `basou exec npm test --watch` instead of\n // `basou exec -- npm test --watch`. basou's own options (--timeout,\n // --no-snapshot, --cwd, -v) must come before the command name.\n .passThroughOptions()\n .option(\"--timeout <duration>\", \"Kill the child after this duration (e.g. 30s, 5m, 1h)\")\n .option(\"--no-snapshot\", \"Skip git_snapshot before/after the command\")\n .option(\"--cwd <path>\", \"Run from a Basou root other than process.cwd()\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (command: string, args: string[], options: ExecOptions) => {\n try {\n const exitCode = await runExec(command, args, options);\n process.exit(exitCode);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exit(1);\n }\n });\n}\n\nexport async function runExec(\n command: string,\n args: string[],\n options: ExecOptions,\n ctx: ExecContext = {},\n): Promise<number> {\n const runner = ctx.runner ?? new ChildProcessRunner();\n const now = ctx.now ?? (() => new Date());\n const appendEvent: AppendEventFn = ctx.appendEvent ?? coreAppendEvent;\n const cwd = options.cwd ?? process.cwd();\n\n // 0. timeout option fail-fast: invalid timeout never creates a session.\n const timeout_ms = options.timeout !== undefined ? parseDuration(options.timeout) : undefined;\n\n // 1. Resolve repository root before touching anything; matches existing\n // init/status semantics so subdir invocations still find `.basou/`.\n const repoRoot = await resolveRepositoryRootForExec(cwd);\n const paths = basouPaths(repoRoot);\n\n // 2. Workspace safety check (caller responsibility).\n await assertBasouRootSafe(paths.root);\n\n // 3. Read manifest to bind session.workspace_id.\n const manifest = await readManifest(paths);\n\n // 4. Build a fresh session and persist its initial state.\n const sessionId = prefixedUlid(\"ses\");\n const sessionDir = join(paths.sessions, sessionId);\n await mkdir(sessionDir, { recursive: true });\n\n const startedAt = now().toISOString();\n const sessionYamlPath = join(sessionDir, \"session.yaml\");\n const session = buildInitialSession({\n id: sessionId,\n command,\n args,\n cwd,\n workspaceId: manifest.workspace.id,\n startedAt,\n });\n await writeYamlFile(sessionYamlPath, session);\n\n // 5. session_started.\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_started\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: startedAt,\n source: \"terminal-recording\",\n });\n\n // 6. Optional pre-execute git_snapshot.\n if (options.snapshot !== false) {\n await tryAppendGitSnapshot(sessionDir, sessionId, repoRoot, now, appendEvent);\n }\n\n // 7. status_changed: initialized -> running.\n const runningAt = now().toISOString();\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_status_changed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: runningAt,\n source: \"terminal-recording\",\n from: \"initialized\",\n to: \"running\",\n });\n await mutateSessionYaml(sessionYamlPath, (s) => {\n s.session.status = \"running\";\n });\n\n // 8. Transient signal hooks: SIGINT / SIGTERM / exit. The exit hook is\n // a synchronous last-resort SIGKILL if the parent exits abnormally.\n const controller = new AbortController();\n let signalReceived: NodeJS.Signals | null = null;\n let activeChild: ChildProcess | null = null;\n const signalHandler = (sig: NodeJS.Signals) => {\n if (signalReceived !== null) return;\n signalReceived = sig;\n controller.abort();\n };\n const exitHandler = () => {\n if (activeChild !== null) {\n try {\n activeChild.kill(\"SIGKILL\");\n } catch {\n // swallow: best-effort cleanup\n }\n }\n };\n // Bind explicit signal names so `process.emit(\"SIGINT\")` etc. produce the\n // right `received_signal` regardless of Node's listener-arg conventions.\n const onSigInt = () => signalHandler(\"SIGINT\");\n const onSigTerm = () => signalHandler(\"SIGTERM\");\n process.on(\"SIGINT\", onSigInt);\n process.on(\"SIGTERM\", onSigTerm);\n process.on(\"exit\", exitHandler);\n // Allow tests to capture the exit handler and trigger the activeChild\n // SIGKILL fallback synchronously without faking `process.emit(\"exit\")`.\n ctx.onExitHookInstalled?.(exitHandler);\n\n let result: RunResult;\n try {\n try {\n result = await runner.run(command, args, {\n cwd,\n capture: \"none\",\n ...(timeout_ms !== undefined ? { timeout_ms } : {}),\n signal: controller.signal,\n onSpawn: (child) => {\n activeChild = child;\n },\n });\n } catch (spawnError: unknown) {\n // Spawn-time error / pre-aborted / validation error: tear down the\n // session as failed before propagating so events.jsonl and session.yaml\n // are consistent even on error.\n await finalizeSessionAsFailed(sessionDir, sessionYamlPath, sessionId, appendEvent, {\n command,\n args,\n cwd,\n occurredAt: now().toISOString(),\n signalReceived,\n });\n throw spawnError;\n }\n } finally {\n process.off(\"SIGINT\", onSigInt);\n process.off(\"SIGTERM\", onSigTerm);\n process.off(\"exit\", exitHandler);\n activeChild = null;\n }\n\n const endedAt = now().toISOString();\n\n // 9. command_executed (with parent received_signal vs child terminating signal).\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"command_executed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: endedAt,\n source: \"terminal-recording\",\n command,\n args,\n cwd,\n exit_code: result.exit_code,\n ...(result.signal !== null ? { signal: result.signal } : {}),\n ...(signalReceived !== null ? { received_signal: signalReceived } : {}),\n duration_ms: result.duration_ms,\n });\n\n // 10. Optional post-execute git_snapshot (after command_executed so the\n // event sequence reads chronologically: pre-snapshot, run, post-snapshot).\n if (options.snapshot !== false) {\n await tryAppendGitSnapshot(sessionDir, sessionId, repoRoot, now, appendEvent);\n }\n\n const finalStatus = decideFinalStatus(result, signalReceived);\n\n // 11. status_changed: running -> final.\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_status_changed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: endedAt,\n source: \"terminal-recording\",\n from: \"running\",\n to: finalStatus,\n });\n\n // 12. session_ended.\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_ended\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: endedAt,\n source: \"terminal-recording\",\n ...(result.exit_code !== null ? { exit_code: result.exit_code } : {}),\n });\n\n // 13. Final session.yaml update (status / ended_at / invocation.exit_code).\n await mutateSessionYaml(sessionYamlPath, (s) => {\n s.session.status = finalStatus;\n s.session.ended_at = endedAt;\n s.session.invocation.exit_code = result.exit_code;\n });\n\n if (result.exit_code !== null) {\n return result.exit_code;\n }\n return signalToExitCode(signalReceived ?? result.signal);\n}\n\nfunction decideFinalStatus(\n result: { exit_code: number | null; signal: NodeJS.Signals | null },\n signalReceived: NodeJS.Signals | null,\n): \"completed\" | \"failed\" | \"interrupted\" {\n if (signalReceived === \"SIGINT\" || signalReceived === \"SIGTERM\") return \"interrupted\";\n if (result.signal === \"SIGINT\" || result.signal === \"SIGTERM\" || result.signal === \"SIGKILL\") {\n return \"interrupted\";\n }\n if (result.exit_code === 0) return \"completed\";\n return \"failed\";\n}\n\nconst SIGNUM_MAP: Record<string, number> = {\n SIGHUP: 1,\n SIGINT: 2,\n SIGQUIT: 3,\n SIGKILL: 9,\n SIGTERM: 15,\n};\n\nfunction signalToExitCode(sig: NodeJS.Signals | null): number {\n if (sig === null) return 1;\n const num = SIGNUM_MAP[sig] ?? 1;\n return 128 + num;\n}\n\nasync function tryAppendGitSnapshot(\n sessionDir: string,\n sessionId: string,\n repoRoot: string,\n now: () => Date,\n appendEvent: AppendEventFn,\n): Promise<void> {\n // Stage 1: snapshot acquisition. Capability-level failures (no git repo,\n // git binary missing, no commits) are recoverable and downgrade to a skip\n // warning. The session continues and events.jsonl simply lacks this\n // git_snapshot entry.\n let snapshot: Awaited<ReturnType<typeof getSnapshot>>;\n try {\n snapshot = await getSnapshot(repoRoot);\n } catch (error: unknown) {\n console.warn(normalizeGitSnapshotSkipMessage(error));\n return;\n }\n // Stage 2: events.jsonl append. Schema validation / disk failures here are\n // NOT a \"snapshot capability\" miss — they would corrupt the events.jsonl\n // integrity contract (the fixed 7-event sequence when snapshot is on). We\n // intentionally do NOT swallow these; let them propagate so the exec call\n // fails loudly instead of producing a session that looks successful but\n // has missing or partial events.\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"git_snapshot\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: now().toISOString(),\n source: \"git-capability\",\n ...snapshot,\n });\n}\n\nfunction normalizeGitSnapshotSkipMessage(error: unknown): string {\n if (!(error instanceof Error)) {\n return `git_snapshot skipped: ${String(error)}`;\n }\n const msg = error.message;\n if (msg === \"Not a git repository\") {\n return \"git_snapshot skipped: not in a git repository\";\n }\n if (msg === \"Git executable not found in PATH. Install git first.\") {\n return \"git_snapshot skipped: git executable not found\";\n }\n if (msg === \"No commits in repository\") {\n return \"git_snapshot skipped: no commits in repository\";\n }\n return `git_snapshot skipped: ${msg}`;\n}\n\nfunction buildInitialSession(input: {\n id: PrefixedId<\"ses\">;\n command: string;\n args: string[];\n cwd: string;\n workspaceId: PrefixedId<\"ws\">;\n startedAt: string;\n}): Session {\n const cmdline = [input.command, ...input.args].join(\" \");\n return {\n schema_version: \"0.1.0\",\n session: {\n id: input.id,\n label: `basou exec ${cmdline} (${input.startedAt})`,\n task_id: null,\n workspace_id: input.workspaceId,\n source: { kind: \"terminal\", version: \"0.1.0\" },\n started_at: input.startedAt,\n status: \"initialized\",\n working_directory: sanitizeWorkingDirectory(input.cwd, { homedir: homedir() }),\n invocation: {\n command: input.command,\n args: [...input.args],\n exit_code: null,\n },\n related_files: [],\n events_log: \"events.jsonl\",\n },\n };\n}\n\nasync function mutateSessionYaml(\n filePath: string,\n mutator: (session: Session) => void,\n): Promise<void> {\n const raw = await readYamlFile(filePath);\n const parsed = SessionSchema.parse(raw);\n mutator(parsed);\n // Re-validate after mutation to catch drift, then overwrite atomically.\n const validated = SessionSchema.parse(parsed);\n await overwriteYamlFile(filePath, validated);\n}\n\nasync function finalizeSessionAsFailed(\n sessionDir: string,\n sessionYamlPath: string,\n sessionId: string,\n appendEvent: AppendEventFn,\n ctx: {\n command: string;\n args: string[];\n cwd: string;\n occurredAt: string;\n signalReceived: NodeJS.Signals | null;\n },\n): Promise<void> {\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"command_executed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: ctx.occurredAt,\n source: \"terminal-recording\",\n command: ctx.command,\n args: ctx.args,\n cwd: ctx.cwd,\n exit_code: null,\n signal: null,\n ...(ctx.signalReceived !== null ? { received_signal: ctx.signalReceived } : {}),\n duration_ms: 0,\n });\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_status_changed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: ctx.occurredAt,\n source: \"terminal-recording\",\n from: \"running\",\n to: \"failed\",\n });\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_ended\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: ctx.occurredAt,\n source: \"terminal-recording\",\n });\n await mutateSessionYaml(sessionYamlPath, (s) => {\n s.session.status = \"failed\";\n s.session.ended_at = ctx.occurredAt;\n s.session.invocation.exit_code = null;\n });\n}\n\nasync function resolveRepositoryRootForExec(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\"Not a git repository. Run 'git init' first, then re-run 'basou exec'.\", {\n cause: error,\n });\n }\n throw error;\n }\n}\n","import {\n assertBasouRootSafe,\n basouPaths,\n findErrorCode,\n readMarkdownFile,\n renderHandoff,\n renderWithMarkers,\n resolveRepositoryRoot,\n writeMarkdownFile,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport {\n isVerbose,\n printReplayWarning,\n printSessionSkip,\n printTaskSkip,\n renderCliError,\n} from \"../lib/error-render.js\";\n\nexport type HandoffGenerateOptions = { verbose?: boolean };\n\nexport type HandoffContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n /** Defaults to `() => new Date()`. Injectable for tests. */\n nowProvider?: () => Date;\n};\n\n/**\n * Wire `basou handoff generate` onto `program`. The `handoff` group is\n * registered up front so future subcommands (e.g. `show`) can slot under\n * the same group without breaking the CLI surface.\n */\nexport function registerHandoffCommand(program: Command): void {\n const handoff = program.command(\"handoff\").description(\"Generate or inspect .basou/handoff.md\");\n\n handoff\n .command(\"generate\")\n .description(\"Regenerate .basou/handoff.md from current session state\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (opts: HandoffGenerateOptions) => {\n await runHandoffGenerate(opts);\n });\n}\n\n/**\n * Programmatic entry that owns `process.exitCode`. Tests that only care\n * about the happy path or a thrown error should prefer {@link doRunHandoffGenerate}.\n */\nexport async function runHandoffGenerate(\n options: HandoffGenerateOptions,\n ctx: HandoffContext = {},\n): Promise<void> {\n try {\n await doRunHandoffGenerate(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * Pure runner for `handoff generate`. Throws on any failure with a pathless\n * message; native errors are attached as `cause` for verbose surfacing.\n */\nexport async function doRunHandoffGenerate(\n options: HandoffGenerateOptions,\n ctx: HandoffContext,\n): Promise<void> {\n void options;\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForHandoff(cwd);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const nowIso = (ctx.nowProvider?.() ?? new Date()).toISOString();\n const result = await renderHandoff({\n paths,\n nowIso,\n onWarning: (w, sid) => printReplayWarning(w, sid),\n onSessionSkip: (sid, reason) => printSessionSkip(sid, reason),\n onTaskSkip: (taskId, reason) => printTaskSkip(taskId, reason),\n });\n\n const existing = await readMarkdownFile(paths.files.handoff);\n const finalBody = renderWithMarkers(existing, result.body, \"handoff.md\");\n await writeMarkdownFile(paths.files.handoff, finalBody);\n\n console.log(\n `Generated .basou/handoff.md (sessions: ${result.sessionCount}, tasks: ${result.taskCount}, decisions: ${result.decisionCount}, pending approvals: ${result.pendingApprovalsCount})`,\n );\n}\n\nasync function resolveRepositoryRootForHandoff(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\n \"Not a git repository. Run 'git init' first, then re-run 'basou handoff generate'.\",\n { cause: error },\n );\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n","import { createReadStream, type Dirent } from \"node:fs\";\nimport { readdir, readFile, rm, stat } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { basename, join, resolve } from \"node:path\";\nimport { createInterface } from \"node:readline\";\nimport {\n assertBasouRootSafe,\n type BasouPaths,\n basouPaths,\n CLAUDE_IMPORT_SOURCE,\n type ClaudeTranscriptRecord,\n CODEX_IMPORT_SOURCE,\n type CodexRolloutRecord,\n claudeTranscriptToImportPayload,\n codexRolloutToImportPayload,\n enumerateSessionDirs,\n findErrorCode,\n type ImportSessionResult,\n importSessionFromJson,\n type Manifest,\n readManifest,\n readSessionYaml,\n reimportPreservingId,\n resolveRepositoryRoot,\n type Session,\n type SessionImportPayload,\n SessionImportPayloadSchema,\n type SessionSourceKind,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport { isVerbose, renderCliError } from \"../lib/error-render.js\";\n\nconst SES_PREFIX = \"ses_\";\nconst SHORT_ID_LEN = 6;\n\n/** Options shared by every `basou import <adapter>` subcommand. */\nexport type ImportOptions = {\n /**\n * Source project roots whose native logs to import. Repeatable on the CLI;\n * empty means \"fall back to the manifest's `import.source_roots`, then the\n * repository root\". Each entry may be absolute or relative to the cwd.\n */\n project?: string[];\n session?: string;\n all?: boolean;\n force?: boolean;\n dryRun?: boolean;\n json?: boolean;\n verbose?: boolean;\n};\n\n/** Commander collector: accumulate a repeatable option into an array. */\nfunction collectPath(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\nexport type ImportClaudeCodeOptions = ImportOptions;\nexport type ImportCodexOptions = ImportOptions;\n\nexport type ImportContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n /**\n * Root that holds per-project Claude transcript directories. Defaults to\n * `~/.claude/projects`. Injectable for tests so no real home dir is touched.\n */\n claudeProjectsDir?: string;\n /**\n * Root that holds Codex rollout logs (`<year>/<month>/<day>/rollout-*.jsonl`).\n * Defaults to `~/.codex/sessions`. Injectable for tests.\n */\n codexSessionsDir?: string;\n};\n\n/**\n * A single source session ready to be derived and imported. The dedup key\n * (`externalId`) is known up front from discovery; `toPayload` reads and\n * transforms the source log lazily, so a session that is skipped (already\n * imported) is never read.\n */\ntype ImportCandidate = {\n externalId: string;\n /**\n * Absolute path of the source native log. The orchestrator stats this (a\n * cheap, parse-free probe) to decide whether an already-imported source\n * changed, before paying to read + derive it.\n */\n sourcePath: string;\n toPayload: () => Promise<SessionImportPayload | null>;\n};\n\n/**\n * Wire the `basou import` command group onto `program`. Each adapter\n * (`claude-code`, `codex`, ...) is a subcommand sharing the same flags, so\n * future adapters slot in without changing the visible surface.\n */\nexport function registerImportCommand(program: Command): void {\n const importCmd = program\n .command(\"import\")\n .description(\"Import provenance from an external AI tool's native logs\");\n\n importCmd\n .command(\"claude-code\")\n .description(\"Derive Basou sessions from Claude Code native transcripts (~/.claude/projects)\")\n .option(\n \"--project <path>\",\n \"Source project path whose transcripts to import (repeatable; defaults to the manifest source roots, then the repository root)\",\n collectPath,\n [],\n )\n .option(\"--session <id>\", \"Import a single transcript by its Claude session id\")\n .option(\"--all\", \"Import every transcript found for the project\")\n .option(\n \"--force\",\n \"Re-import sessions already imported: delete and replace them instead of skipping\",\n )\n .option(\"--dry-run\", \"Validate and preview only; do not write to disk\")\n .option(\"--json\", \"Output the result as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: ImportClaudeCodeOptions) => {\n await runImportClaudeCode(options);\n });\n\n importCmd\n .command(\"codex\")\n .description(\"Derive Basou sessions from OpenAI Codex native rollout logs (~/.codex/sessions)\")\n .option(\n \"--project <path>\",\n \"Source project path whose rollouts to import (repeatable; defaults to the manifest source roots, then the repository root)\",\n collectPath,\n [],\n )\n .option(\"--session <id>\", \"Import a single rollout by its Codex session id\")\n .option(\"--all\", \"Import every rollout found for the project\")\n .option(\n \"--force\",\n \"Re-import sessions already imported: delete and replace them instead of skipping\",\n )\n .option(\"--dry-run\", \"Validate and preview only; do not write to disk\")\n .option(\"--json\", \"Output the result as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: ImportCodexOptions) => {\n await runImportCodex(options);\n });\n}\n\n/**\n * Programmatic entry for `basou import claude-code`. Owns process exit state;\n * tests should prefer {@link doRunImportClaudeCode}.\n */\nexport async function runImportClaudeCode(\n options: ImportClaudeCodeOptions,\n ctx: ImportContext = {},\n): Promise<void> {\n try {\n await doRunImportClaudeCode(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * Programmatic entry for `basou import codex`. Owns process exit state;\n * tests should prefer {@link doRunImportCodex}.\n */\nexport async function runImportCodex(\n options: ImportCodexOptions,\n ctx: ImportContext = {},\n): Promise<void> {\n try {\n await doRunImportCodex(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * Resolve the absolute source roots to import from, applying precedence:\n * explicit `--project` flags first (resolved against the cwd), else the\n * manifest's `import.source_roots` (resolved against the repo root), else the\n * repository root alone. The result is de-duplicated, so a root listed twice\n * (or equal to the repo root) is scanned once.\n */\nfunction resolveSourceRoots(args: {\n projectFlags: string[];\n manifest: Manifest;\n repoRoot: string;\n cwd: string;\n}): string[] {\n const { projectFlags, manifest, repoRoot, cwd } = args;\n let resolved: string[];\n if (projectFlags.length > 0) {\n resolved = projectFlags.map((p) => resolve(cwd, p));\n } else {\n const roots = manifest.import?.source_roots;\n resolved =\n roots !== undefined && roots.length > 0 ? roots.map((r) => resolve(repoRoot, r)) : [repoRoot];\n }\n return [...new Set(resolved)];\n}\n\nexport async function doRunImportClaudeCode(\n options: ImportClaudeCodeOptions,\n ctx: ImportContext,\n): Promise<void> {\n assertSelector(options);\n const { repositoryRoot, paths, manifest } = await resolveImportTarget(ctx);\n\n const projectPaths = resolveSourceRoots({\n projectFlags: options.project ?? [],\n manifest,\n repoRoot: repositoryRoot,\n cwd: ctx.cwd ?? process.cwd(),\n });\n const projectsRoot = ctx.claudeProjectsDir ?? join(homedir(), \".claude\", \"projects\");\n\n const files = await selectTranscriptFiles(projectsRoot, projectPaths, options);\n const candidates: ImportCandidate[] = files.map((file) => {\n // The transcript filename is the Claude session id; it is both the dedup\n // key and the source external_id.\n const externalId = basename(file, \".jsonl\");\n return {\n externalId,\n sourcePath: file,\n toPayload: async () => {\n const { records, sizeBytes } = await readJsonlRecords(file);\n return claudeTranscriptToImportPayload(records, {\n workspaceId: manifest.workspace.id,\n externalId,\n sourceSizeBytes: sizeBytes,\n });\n },\n };\n });\n\n await importDerivedSessions(paths, manifest, options, CLAUDE_IMPORT_SOURCE, candidates);\n}\n\nexport async function doRunImportCodex(\n options: ImportCodexOptions,\n ctx: ImportContext,\n): Promise<void> {\n assertSelector(options);\n const { repositoryRoot, paths, manifest } = await resolveImportTarget(ctx);\n\n const projectPaths = resolveSourceRoots({\n projectFlags: options.project ?? [],\n manifest,\n repoRoot: repositoryRoot,\n cwd: ctx.cwd ?? process.cwd(),\n });\n const sessionsRoot = ctx.codexSessionsDir ?? join(homedir(), \".codex\", \"sessions\");\n\n const rollouts = await discoverCodexRollouts(sessionsRoot, projectPaths, options);\n const candidates: ImportCandidate[] = rollouts.map(({ file, externalId }) => ({\n externalId,\n sourcePath: file,\n toPayload: async () => {\n const { records, sizeBytes } = await readJsonlRecords(file);\n return codexRolloutToImportPayload(records as CodexRolloutRecord[], {\n workspaceId: manifest.workspace.id,\n externalId,\n sourceSizeBytes: sizeBytes,\n });\n },\n }));\n\n await importDerivedSessions(paths, manifest, options, CODEX_IMPORT_SOURCE, candidates);\n}\n\nfunction assertSelector(options: ImportOptions): void {\n if (options.session !== undefined && options.all === true) {\n throw new Error(\"Specify either --session <id> or --all, not both\");\n }\n if (options.session === undefined && options.all !== true) {\n throw new Error(\"Specify --session <id> or --all\");\n }\n}\n\nasync function resolveImportTarget(\n ctx: ImportContext,\n): Promise<{ repositoryRoot: string; paths: BasouPaths; manifest: Manifest }> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForImport(cwd);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n const manifest = await readManifest(paths);\n return { repositoryRoot, paths, manifest };\n}\n\n/**\n * The vendor-neutral import core: dedup, derive, validate, and write each\n * candidate, then report. Every `basou import <adapter>` funnels its\n * discovered candidates through here, so dedup / `--force` / `--dry-run`\n * semantics stay identical across adapters. Dedup is scoped to `sourceKind`\n * so one adapter never matches (or, under `--force`, deletes) another\n * adapter's session that happens to share an id string.\n */\nasync function importDerivedSessions(\n paths: BasouPaths,\n manifest: Manifest,\n options: ImportOptions,\n sourceKind: SessionSourceKind,\n candidates: ReadonlyArray<ImportCandidate>,\n): Promise<void> {\n const existingByExternalId = await loadExistingByExternalId(paths, sourceKind);\n // Session ids imported earlier in THIS run, so two source files that map to\n // one session id never double-import within a single invocation.\n const seenThisRun = new Set<string>();\n\n const results: ImportSessionResult[] = [];\n const counts: ImportCounts = {\n skippedNoAction: 0,\n skippedExisting: 0,\n replaced: 0,\n reimported: 0,\n skippedLegacy: 0,\n skippedDecreased: 0,\n skippedDuplicate: 0,\n };\n let sanitizedPaths = 0;\n\n // Parse + version-gate a derived payload before it touches disk. Returns null\n // when the source carried no provenance worth importing (the caller skips).\n const validate = (payload: SessionImportPayload | null): SessionImportPayload | null => {\n if (payload === null) return null;\n const parsed = SessionImportPayloadSchema.safeParse(payload);\n if (!parsed.success) {\n throw new Error(\"Invalid import payload\", { cause: parsed.error });\n }\n if (parsed.data.schema_version !== \"0.1.0\") {\n throw new Error(`Unsupported import schema_version: ${parsed.data.schema_version}`);\n }\n return parsed.data;\n };\n\n for (const { externalId, sourcePath, toPayload } of candidates) {\n if (seenThisRun.has(externalId)) {\n counts.skippedExisting++;\n continue;\n }\n const priors = existingByExternalId.get(externalId) ?? [];\n\n // Already imported in a prior run. Default is to skip (idempotent), but a\n // source whose native log GREW is re-imported in place, and --force\n // deletes + replaces regardless.\n if (priors.length > 0 && options.force !== true) {\n const prior = await classifyReimport(priors, sourcePath, externalId, counts);\n if (prior === null) continue; // skip recorded by classifyReimport\n const payload = validate(await toPayload());\n if (payload === null) {\n counts.skippedNoAction++;\n continue;\n }\n // Re-confirm growth against the size ACTUALLY read (the decision above used\n // a cheap pre-read stat): if the source was truncated / rotated between the\n // stat and the read, the smaller buffer must not be re-imported as a grow.\n const readSize = payload.session.source.source_size_bytes;\n if (\n prior.sourceSizeBytes !== undefined &&\n readSize !== undefined &&\n readSize <= prior.sourceSizeBytes\n ) {\n console.error(\n `Import: ${externalId} source changed during read (now ${readSize} <= ${prior.sourceSizeBytes} bytes); re-import skipped`,\n );\n counts.skippedDecreased++;\n continue;\n }\n const outcome = await reimportPreservingId(paths, manifest, prior.sessionId, payload, {\n dryRun: options.dryRun === true,\n });\n if (outcome.status === \"skipped\") {\n const detail =\n outcome.reason === \"prior_events_unreadable\"\n ? \"prior events.jsonl has unreadable lines\"\n : \"source changed in a non-append way (derived events would be dropped)\";\n console.error(`Import: ${externalId} ${detail}; re-import skipped`);\n counts.skippedNoAction++;\n continue;\n }\n counts.reimported++;\n seenThisRun.add(externalId);\n continue;\n }\n\n const payload = validate(await toPayload());\n if (payload === null) {\n counts.skippedNoAction++;\n continue;\n }\n\n // --force replace: delete the prior session(s) for this external id, but\n // only once the fresh payload is known good, so a failed re-derivation\n // never destroys the existing import. Skipped under --dry-run.\n if (priors.length > 0 && options.force === true) {\n if (options.dryRun !== true) {\n for (const { sessionId } of priors) {\n await rm(join(paths.sessions, sessionId), { recursive: true, force: true });\n }\n }\n counts.replaced++;\n }\n\n const result = await importSessionFromJson(paths, manifest, payload, {\n dryRun: options.dryRun === true,\n });\n results.push(result);\n seenThisRun.add(externalId);\n sanitizedPaths +=\n result.pathSanitizeReport.relatedFiles +\n (result.pathSanitizeReport.workingDirectoryRewritten ? 1 : 0);\n }\n\n if (sanitizedPaths > 0) {\n console.error(`Imported sessions: ${sanitizedPaths} path(s) sanitized`);\n }\n\n printImportResult(options, results, counts);\n}\n\n/** Mutable tally of every import disposition, surfaced by {@link printImportResult}. */\ntype ImportCounts = {\n skippedNoAction: number;\n /** Already imported and unchanged (or a duplicate-within-this-run). */\n skippedExisting: number;\n /** Deleted + replaced under --force. */\n replaced: number;\n /** Re-imported in place because the source grew. */\n reimported: number;\n /** Already imported but with no recorded size (pre-size-tracking import); not re-imported. */\n skippedLegacy: number;\n /** Source shrank since import (truncated / rotated); needs --force to replace. */\n skippedDecreased: number;\n /** More than one prior session for one external id (anomalous); needs --force. */\n skippedDuplicate: number;\n};\n\n/**\n * Decide whether an already-imported external id should be re-imported in place\n * because its source grew. Returns the single prior import to re-import into, or\n * `null` (recording the right skip count) when it must be left alone:\n * unchanged / shrank / legacy (no recorded size) / anomalously duplicated. The\n * size probe is a parse-free `stat`, so unchanged sources are dismissed cheaply.\n */\nasync function classifyReimport(\n priors: PriorImport[],\n sourcePath: string,\n externalId: string,\n counts: ImportCounts,\n): Promise<PriorImport | null> {\n if (priors.length > 1) {\n // Anomalous: a scoped re-import cannot pick which id to preserve, and\n // delete+recreate would orphan any linked_events. Leave it to --force.\n console.error(\n `Import: ${externalId} has ${priors.length} prior sessions; re-import skipped (use --force)`,\n );\n counts.skippedDuplicate++;\n return null;\n }\n const prior = priors[0];\n if (prior === undefined) {\n counts.skippedExisting++;\n return null;\n }\n const currentSize = await statSize(sourcePath);\n if (currentSize === undefined) {\n // Source vanished between discovery and now; nothing to re-import.\n counts.skippedExisting++;\n return null;\n }\n if (prior.sourceSizeBytes === undefined) {\n // Legacy import (no recorded size baseline): never auto-re-import; the size\n // populates on the next --force / fresh import.\n counts.skippedLegacy++;\n return null;\n }\n if (currentSize === prior.sourceSizeBytes) {\n counts.skippedExisting++; // unchanged\n return null;\n }\n if (currentSize < prior.sourceSizeBytes) {\n // Truncated / rotated: do NOT auto-replace derived provenance; --force only.\n console.error(\n `Import: ${externalId} source shrank (${currentSize} < ${prior.sourceSizeBytes} bytes); re-import skipped (use --force to replace)`,\n );\n counts.skippedDecreased++;\n return null;\n }\n return prior; // grew => re-import preserving id\n}\n\n/**\n * Encode an absolute project path into Claude Code's per-project directory\n * name. Claude Code replaces path separators with `-`, so\n * `/Users/x/projects/foo` becomes `-Users-x-projects-foo`. Best-effort for\n * the common case; paths with characters the vendor encodes differently may\n * need an explicit `--project`-derived directory in a later revision.\n */\nfunction encodeProjectDir(projectPath: string): string {\n return projectPath.replaceAll(\"/\", \"-\");\n}\n\n/**\n * Map of source external_id -> Basou session id(s) already present in the\n * workspace for the given `sourceKind`, so a re-import can skip (default) or,\n * under --force, delete and replace the existing session. Scoping to one\n * source kind keeps each adapter's id namespace separate: a Codex import must\n * never dedup against, or delete, a Claude-derived session that happens to\n * share an id string. Recognises both the structured `source.external_id`\n * (current imports) and the `claude-code import <id>` label form (sessions\n * imported before external_id existed), so existing dogfood imports are\n * matched either way. Unreadable sessions are skipped.\n */\n/**\n * A prior Basou session for an external id, with the source byte size recorded\n * at its last import (absent for legacy imports made before the field existed).\n * The size lets a re-import detect that an append-only source GREW.\n */\ntype PriorImport = { sessionId: string; sourceSizeBytes?: number };\n\nasync function loadExistingByExternalId(\n paths: BasouPaths,\n sourceKind: SessionSourceKind,\n): Promise<Map<string, PriorImport[]>> {\n const byExternalId = new Map<string, PriorImport[]>();\n const add = (externalId: string, prior: PriorImport): void => {\n const list = byExternalId.get(externalId);\n if (list === undefined) byExternalId.set(externalId, [prior]);\n else list.push(prior);\n };\n let sessionIds: string[];\n try {\n sessionIds = await enumerateSessionDirs(paths);\n } catch {\n return byExternalId;\n }\n for (const sessionId of sessionIds) {\n let session: Session;\n try {\n session = await readSessionYaml(paths, sessionId);\n } catch {\n continue;\n }\n if (session.session.source.kind !== sourceKind) continue;\n const sourceSizeBytes = session.session.source.source_size_bytes;\n // Build once; omit the size key entirely when absent (legacy import) so the\n // optional property stays absent rather than explicitly undefined.\n const prior: PriorImport =\n sourceSizeBytes !== undefined ? { sessionId, sourceSizeBytes } : { sessionId };\n const ext = session.session.source.external_id;\n if (typeof ext === \"string\" && ext.length > 0) {\n add(ext, prior);\n continue;\n }\n const label = session.session.label;\n const match = typeof label === \"string\" ? label.match(/^claude-code import (\\S+)$/) : null;\n if (match?.[1] !== undefined) add(match[1], prior);\n }\n return byExternalId;\n}\n\n/**\n * Select the Claude transcript files to import across one or more source roots.\n * Each root maps to a per-project transcript directory under `projectsRoot`.\n * With `--session`, every root is probed and only existing matches are returned\n * (an error is raised only if no root holds that transcript). With `--all`, the\n * `.jsonl` files of every root are unioned; a root whose directory is absent\n * contributes nothing. The missing-directory error is raised only when NO root\n * has a transcript directory, so refresh classifies \"nothing anywhere\" as a\n * skip rather than a failure.\n */\nasync function selectTranscriptFiles(\n projectsRoot: string,\n projectPaths: string[],\n options: ImportClaudeCodeOptions,\n): Promise<string[]> {\n if (options.session !== undefined) {\n const matches: string[] = [];\n for (const projectPath of projectPaths) {\n const file = join(projectsRoot, encodeProjectDir(projectPath), `${options.session}.jsonl`);\n if (await pathExists(file)) matches.push(file);\n }\n if (matches.length === 0) {\n throw new Error(\"Claude transcript not found for session id in project\");\n }\n return [...new Set(matches)];\n }\n const files: string[] = [];\n let anyDirFound = false;\n for (const projectPath of projectPaths) {\n const transcriptDir = join(projectsRoot, encodeProjectDir(projectPath));\n let entries: string[];\n try {\n entries = await readdir(transcriptDir);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) continue; // this root has no transcripts; try the next\n throw new Error(\"Failed to read Claude transcript directory\", { cause: error });\n }\n anyDirFound = true;\n for (const name of entries) {\n if (name.endsWith(\".jsonl\")) files.push(join(transcriptDir, name));\n }\n }\n if (!anyDirFound) {\n throw new Error(\"Claude transcript directory not found for project\");\n }\n return [...new Set(files)].sort();\n}\n\n/** Whether `file` exists (ENOENT => false; any other error propagates). */\nasync function pathExists(file: string): Promise<boolean> {\n try {\n await stat(file);\n return true;\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) return false;\n throw error;\n }\n}\n\n/** The file's byte size, or undefined if it vanished (ENOENT); other errors propagate. */\nasync function statSize(file: string): Promise<number | undefined> {\n try {\n return (await stat(file)).size;\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) return undefined;\n throw error;\n }\n}\n\n/**\n * Discover the Codex rollouts that belong to any of `projectPaths`. Codex\n * stores rollouts under date directories (not per-project like Claude), so the\n * whole tree is walked once and each rollout's `session_meta.cwd` is matched\n * against the set of requested roots. The exact-match is also the safety\n * boundary: only sessions started in a requested root are ever imported.\n * `--session` narrows to a single rollout by its Codex session id within those\n * roots; a session id that matches no rollout is an error, mirroring how the\n * Claude path fails on a missing `--session` transcript rather than reporting a\n * silent success.\n */\nasync function discoverCodexRollouts(\n sessionsRoot: string,\n projectPaths: string[],\n options: ImportCodexOptions,\n): Promise<Array<{ file: string; externalId: string }>> {\n const projectSet = new Set(projectPaths);\n const files = await findRolloutFiles(sessionsRoot);\n const matched: Array<{ file: string; externalId: string }> = [];\n for (const file of files) {\n const meta = await readRolloutMeta(file);\n if (meta === undefined) continue;\n if (!projectSet.has(meta.cwd)) continue;\n if (options.session !== undefined && meta.id !== options.session) continue;\n matched.push({ file, externalId: meta.id });\n }\n if (options.session !== undefined && matched.length === 0) {\n throw new Error(\"Codex rollout not found for session id in project\");\n }\n return matched;\n}\n\n/** Recursively collect every `rollout-*.jsonl` under the Codex sessions root. */\nasync function findRolloutFiles(sessionsRoot: string): Promise<string[]> {\n const found: string[] = [];\n const walk = async (dir: string, isRoot: boolean): Promise<void> => {\n let entries: Dirent[];\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n if (isRoot) {\n throw new Error(\"Codex sessions directory not found\", { cause: error });\n }\n return; // a subdir vanished mid-walk; ignore\n }\n throw new Error(\"Failed to read Codex sessions directory\", { cause: error });\n }\n for (const entry of entries) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n await walk(full, false);\n } else if (\n entry.isFile() &&\n entry.name.startsWith(\"rollout-\") &&\n entry.name.endsWith(\".jsonl\")\n ) {\n found.push(full);\n }\n }\n };\n await walk(sessionsRoot, true);\n return found.sort();\n}\n\n/**\n * Read just the `session_meta` (first record) of a rollout to learn its\n * project cwd and session id, without parsing the whole — usually large — log.\n * Returns `undefined` for any file whose first record is not a usable\n * `session_meta`, so the caller can skip it.\n */\nasync function readRolloutMeta(file: string): Promise<{ id: string; cwd: string } | undefined> {\n const firstLine = await readFirstLine(file);\n if (firstLine === undefined) return undefined;\n let parsed: unknown;\n try {\n parsed = JSON.parse(firstLine);\n } catch {\n return undefined;\n }\n if (!isObject(parsed) || parsed.type !== \"session_meta\") return undefined;\n const payload = isObject(parsed.payload) ? parsed.payload : undefined;\n if (payload === undefined) return undefined;\n const id = payload.id;\n const cwd = payload.cwd;\n if (typeof id !== \"string\" || id.length === 0) return undefined;\n if (typeof cwd !== \"string\" || cwd.length === 0) return undefined;\n return { id, cwd };\n}\n\n/** Read the first non-empty line of a file, streaming so large files are cheap. */\nasync function readFirstLine(file: string): Promise<string | undefined> {\n const stream = createReadStream(file, { encoding: \"utf8\" });\n const rl = createInterface({ input: stream, crlfDelay: Number.POSITIVE_INFINITY });\n try {\n for await (const line of rl) {\n const trimmed = line.trim();\n if (trimmed.length > 0) return trimmed;\n }\n return undefined;\n } catch {\n return undefined;\n } finally {\n rl.close();\n stream.destroy();\n }\n}\n\n/**\n * Read a JSONL native log into an array of records, plus the file's exact byte\n * size. A malformed line is skipped rather than failing the whole file, so\n * partial native logs still yield best-effort provenance. The byte size is read\n * from the SAME buffer that produced the records (an immutable snapshot), so the\n * size persisted as `source.source_size_bytes` always matches the imported\n * content even if the file is being appended to concurrently.\n */\nasync function readJsonlRecords(\n file: string,\n): Promise<{ records: ClaudeTranscriptRecord[]; sizeBytes: number }> {\n let buffer: Buffer;\n try {\n buffer = await readFile(file);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Source log not found\", { cause: error });\n }\n if (findErrorCode(error, \"EISDIR\")) {\n throw new Error(\"Source log path is not a file\", { cause: error });\n }\n throw new Error(\"Failed to read source log\", { cause: error });\n }\n\n const records: ClaudeTranscriptRecord[] = [];\n for (const line of buffer.toString(\"utf8\").split(\"\\n\")) {\n const trimmed = line.trim();\n if (trimmed.length === 0) continue;\n try {\n const parsed: unknown = JSON.parse(trimmed);\n if (isObject(parsed)) {\n records.push(parsed);\n }\n } catch {\n // A malformed line is skipped rather than failing the whole file.\n }\n }\n return { records, sizeBytes: buffer.length };\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction printImportResult(\n options: ImportOptions,\n results: ImportSessionResult[],\n counts: ImportCounts,\n): void {\n const isDry = options.dryRun === true;\n const eventTotal = results.reduce((sum, r) => sum + r.eventCount, 0);\n const {\n skippedNoAction,\n skippedExisting,\n replaced,\n reimported,\n skippedLegacy,\n skippedDecreased,\n skippedDuplicate,\n } = counts;\n\n if (options.json === true) {\n console.log(\n JSON.stringify({\n imported: results.map((r) => ({\n session_id: r.sessionId,\n event_count: r.eventCount,\n status: r.finalStatus,\n source: { kind: r.finalSourceKind, version: \"0.1.0\" },\n })),\n imported_count: results.length,\n replaced_count: replaced,\n reimported_count: reimported,\n skipped_no_action: skippedNoAction,\n skipped_already_imported: skippedExisting,\n skipped_legacy_untracked: skippedLegacy,\n skipped_decreased: skippedDecreased,\n skipped_duplicate: skippedDuplicate,\n event_total: eventTotal,\n dry_run: isDry,\n }),\n );\n return;\n }\n\n const skipParts: string[] = [];\n if (skippedNoAction > 0) skipParts.push(`${skippedNoAction} with no actions`);\n if (skippedExisting > 0) skipParts.push(`${skippedExisting} already imported`);\n if (skippedLegacy > 0) skipParts.push(`${skippedLegacy} legacy (untracked size)`);\n if (skippedDecreased > 0) skipParts.push(`${skippedDecreased} shrank`);\n if (skippedDuplicate > 0) skipParts.push(`${skippedDuplicate} duplicated`);\n const skipSuffix = skipParts.length > 0 ? `; skipped ${skipParts.join(\", \")}` : \"\";\n const eventsPart =\n replaced > 0 ? `${eventTotal} events, ${replaced} replaced` : `${eventTotal} events`;\n\n if (isDry) {\n const parts: string[] = [];\n if (results.length > 0) parts.push(`import ${results.length} session(s) (${eventsPart})`);\n if (reimported > 0) parts.push(`re-import ${reimported} changed session(s)`);\n const head = parts.length > 0 ? `Dry run: would ${parts.join(\", \")}` : \"Dry run: no changes\";\n console.log(`${head}${skipSuffix}`);\n return;\n }\n\n if (results.length === 0 && reimported === 0) {\n console.log(\n skipParts.length > 0\n ? `No new sessions imported (skipped ${skipParts.join(\", \")})`\n : \"No transcripts found to import\",\n );\n return;\n }\n\n const segments: string[] = [];\n if (results.length > 0) {\n const single =\n results.length === 1 && results[0] !== undefined ? ` (${shortId(results[0].sessionId)})` : \"\";\n segments.push(`Imported ${results.length} session(s)${single} (${eventsPart})`);\n }\n if (reimported > 0) {\n segments.push(\n `${results.length > 0 ? \"re-imported\" : \"Re-imported\"} ${reimported} changed session(s)`,\n );\n }\n console.log(`${segments.join(\", \")}${skipSuffix}`);\n}\n\nfunction shortId(id: string): string {\n if (id.startsWith(SES_PREFIX)) {\n return id.slice(SES_PREFIX.length, SES_PREFIX.length + SHORT_ID_LEN);\n }\n return id.slice(0, SHORT_ID_LEN);\n}\n\nasync function resolveRepositoryRootForImport(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\"Not a git repository. Run 'git init' first, then re-run 'basou import'.\", {\n cause: error,\n });\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n","import { basename, relative, resolve } from \"node:path\";\nimport {\n appendBasouGitignore,\n createManifest,\n ensureBasouDirectory,\n resolveRepositoryRoot,\n tryRemoteUrl,\n writeManifest,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport { extractCauseLabel, isVerbose, renderCliError } from \"../lib/error-render.js\";\n\nexport type InitOptions = {\n name?: string;\n projectName?: string;\n projectDescription?: string;\n repoUrl?: string;\n /**\n * Import source roots (repeatable). Each may be absolute or relative to the\n * invocation cwd; persisted as a path relative to the repository root under\n * `import.source_roots`, so one `.basou/` can aggregate sibling repos.\n */\n sourceRoot?: string[];\n force?: boolean;\n verbose?: boolean;\n};\n\n/** Commander collector: accumulate a repeatable option into an array. */\nfunction collectValue(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\nexport type InitContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n};\n\n/**\n * Register `basou init` on a commander program. The `--repo-url \"\"` (empty\n * string) form is the documented way to set `project.repository_url` to\n * `null` explicitly; omitting `--repo-url` falls back to\n * `git config --local remote.origin.url` and finally to omission.\n */\nexport function registerInitCommand(program: Command): void {\n program\n .command(\"init\")\n .description(\"Initialize a Basou workspace at the current Git repository root\")\n .option(\"--name <name>\", \"Workspace name (defaults to the repository directory name)\")\n .option(\"--project-name <name>\", \"Project display name\")\n .option(\"--project-description <description>\", \"Project description\")\n .option(\n \"--repo-url <url>\",\n \"Repository URL (defaults to git remote.origin.url; pass empty string for null)\",\n )\n .option(\n \"--source-root <path>\",\n \"Extra import source root, relative to the repo root (repeatable; aggregates sibling repos into this workspace)\",\n collectValue,\n [],\n )\n .option(\"-f, --force\", \"Overwrite an existing manifest\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: InitOptions) => {\n await runInit(options);\n });\n}\n\n/**\n * Programmatic entry that mutates process state (`exitCode`, stderr).\n * Exported for tests, but tests should prefer {@link doRunInit} so they are\n * not coupled to process global state.\n */\nexport async function runInit(options: InitOptions, ctx: InitContext = {}): Promise<void> {\n try {\n await doRunInit(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * Pure runner: resolves inputs, calls core APIs, prints the success line.\n * On any failure throws an Error whose `message` is pathless and whose\n * `cause` MAY contain a native fs error. Exported for tests so they can\n * assert on thrown errors without touching `process.exitCode`.\n */\nexport async function doRunInit(options: InitOptions, ctx: InitContext): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForInit(cwd);\n const workspaceName = options.name ?? basename(repositoryRoot);\n\n // --repo-url > git config --local remote.origin.url > omit\n // --repo-url \"\" => explicit null\n let repositoryUrl: string | null | undefined;\n if (options.repoUrl !== undefined) {\n repositoryUrl = options.repoUrl === \"\" ? null : options.repoUrl;\n } else {\n repositoryUrl = await tryRemoteUrl(repositoryRoot);\n }\n\n // Normalize each --source-root to a repo-root-relative path. A root that is\n // the repo root itself becomes \".\". Stored relative so the committed manifest\n // carries no absolute machine paths.\n const sourceRoots = (options.sourceRoot ?? []).map((p) => {\n const rel = relative(repositoryRoot, resolve(cwd, p));\n return rel === \"\" ? \".\" : rel;\n });\n\n const paths = await ensureBasouDirectory(repositoryRoot);\n const manifest = createManifest({\n workspaceName,\n ...(options.projectName !== undefined ? { projectName: options.projectName } : {}),\n ...(options.projectDescription !== undefined\n ? { projectDescription: options.projectDescription }\n : {}),\n ...(repositoryUrl !== undefined ? { repositoryUrl } : {}),\n ...(sourceRoots.length > 0 ? { sourceRoots } : {}),\n });\n\n await writeManifest(paths, manifest, { force: options.force === true });\n\n // .gitignore is best-effort: init succeeds even if this step fails.\n // The \"safe to run on an existing Git repo\" completion contract holds\n // even when manifest writes but .gitignore cannot (e.g. permission\n // denied) -- the core feature set still works.\n try {\n await appendBasouGitignore(repositoryRoot);\n } catch (error: unknown) {\n renderGitignoreWarning(error, isVerbose(options));\n }\n\n console.log(`Initialized Basou workspace: ${manifest.workspace.id}`);\n}\n\n/**\n * Render a non-fatal warning when `.gitignore` cannot be updated. Mirrors\n * the pathless contract enforced by {@link renderCliError} — never prints\n * `error.cause.message` because native fs errors embed the absolute path\n * in it.\n */\nfunction renderGitignoreWarning(error: unknown, verbose: boolean): void {\n const baseMessage = error instanceof Error ? error.message : String(error);\n // The fallback hint is intentionally `dist`-only-portable: it does not\n // reference any in-repo doc path, since the CLI is published\n // independently of `docs/`.\n console.error(\n `Warning: Could not update .gitignore (${baseMessage}). Add Basou's default .gitignore block manually.`,\n );\n if (verbose && error instanceof Error) {\n const label = extractCauseLabel(error);\n if (label !== undefined) console.error(`Caused by: ${label}`);\n }\n}\n\n/**\n * Wrap the core git capability so the CLI surfaces the command-specific\n * \"Run 'git init' first, then re-run 'basou init'.\" suffix while the\n * capability layer remains command-agnostic.\n */\nasync function resolveRepositoryRootForInit(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\"Not a git repository. Run 'git init' first, then re-run 'basou init'.\", {\n cause: error,\n });\n }\n throw error;\n }\n}\n","import { assertBasouRootSafe, basouPaths, findErrorCode, resolveRepositoryRoot } from \"@basou/core\";\nimport { type Command, InvalidArgumentError } from \"commander\";\nimport { isVerbose, renderCliError } from \"../lib/error-render.js\";\nimport { type ImportOutcome, type RefreshResult, refreshAll } from \"../lib/provenance-actions.js\";\nimport type { ImportContext } from \"./import.js\";\nimport {\n DEFAULT_WATCH_INTERVAL_SEC,\n MAX_WATCH_INTERVAL_SEC,\n MIN_WATCH_INTERVAL_SEC,\n runRefreshWatch,\n} from \"./refresh-watch.js\";\n\nexport type RefreshOptions = {\n project?: string[];\n force?: boolean;\n dryRun?: boolean;\n json?: boolean;\n /** Run as a long-lived watcher: re-import when the native logs change. */\n watch?: boolean;\n /** Poll interval in seconds for `--watch` (default {@link DEFAULT_WATCH_INTERVAL_SEC}). */\n interval?: number;\n verbose?: boolean;\n};\n\n/** Commander collector: accumulate a repeatable option into an array. */\nfunction collectPath(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\n/** Commander parser: `--interval` is an integer count of seconds within the supported range. */\nexport function parseInterval(value: string): number {\n const seconds = Number(value);\n if (\n !Number.isInteger(seconds) ||\n seconds < MIN_WATCH_INTERVAL_SEC ||\n seconds > MAX_WATCH_INTERVAL_SEC\n ) {\n throw new InvalidArgumentError(\n `--interval must be an integer between ${MIN_WATCH_INTERVAL_SEC} and ${MAX_WATCH_INTERVAL_SEC} (seconds).`,\n );\n }\n return seconds;\n}\n\n/** Resolve after `ms`, or early when `signal` aborts (e.g. on Ctrl-C). Leaves no listener behind. */\nfunction abortableSleep(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise<void>((resolve) => {\n if (signal.aborted) {\n resolve();\n return;\n }\n let timer: ReturnType<typeof setTimeout>;\n const onAbort = (): void => {\n clearTimeout(timer);\n resolve();\n };\n timer = setTimeout(() => {\n signal.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nexport type RefreshContext = ImportContext & {\n /** Defaults to `() => new Date()`. Injectable for tests. */\n nowProvider?: () => Date;\n};\n\n/**\n * Wire `basou refresh` onto `program`. One command that imports every adapter\n * for the project and regenerates handoff + decisions, so the dogfood loop is\n * a single invocation instead of four.\n */\nexport function registerRefreshCommand(program: Command): void {\n program\n .command(\"refresh\")\n .description(\n \"Import all adapters for the project and regenerate handoff + decisions in one step\",\n )\n .option(\n \"--project <path>\",\n \"Source project path to import (repeatable; defaults to the manifest source roots, then the repository root)\",\n collectPath,\n [],\n )\n .option(\"--force\", \"Re-import sessions already imported instead of skipping\")\n .option(\"--dry-run\", \"Preview imports and skip writing handoff / decisions\")\n .option(\"--json\", \"Output the result as JSON\")\n .option(\n \"--watch\",\n \"Keep running: re-import + regenerate when the native logs change (Ctrl-C to stop)\",\n )\n .option(\n \"--interval <seconds>\",\n `Poll interval for --watch, in seconds (default ${DEFAULT_WATCH_INTERVAL_SEC}, min ${MIN_WATCH_INTERVAL_SEC})`,\n parseInterval,\n )\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: RefreshOptions) => {\n await runRefresh(options);\n });\n}\n\n/**\n * Programmatic entry that owns `process.exitCode`. Tests should prefer\n * {@link doRunRefresh}, which returns the structured result.\n */\nexport async function runRefresh(options: RefreshOptions, ctx: RefreshContext = {}): Promise<void> {\n try {\n if (options.watch === true) {\n await doRunRefreshWatch(options, ctx);\n } else {\n await doRunRefresh(options, ctx);\n }\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * `basou refresh --watch`: resolve + validate, then run the polling watcher\n * until SIGINT / SIGTERM. Startup failures (bad combo, no workspace, failed\n * initial refresh) propagate and exit non-zero; a steady-state cycle failure is\n * logged inside the loop and the watcher keeps running.\n */\nexport async function doRunRefreshWatch(\n options: RefreshOptions,\n ctx: RefreshContext,\n): Promise<void> {\n if (options.dryRun === true) throw new Error(\"--watch cannot be combined with --dry-run.\");\n if (options.json === true) throw new Error(\"--watch cannot be combined with --json.\");\n if (options.force === true) throw new Error(\"--watch cannot be combined with --force.\");\n\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForRefresh(cwd);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const intervalMs = (options.interval ?? DEFAULT_WATCH_INTERVAL_SEC) * 1000;\n const controller = new AbortController();\n const onSignal = (): void => controller.abort();\n process.on(\"SIGINT\", onSignal);\n process.on(\"SIGTERM\", onSignal);\n try {\n await runRefreshWatch({\n ctx,\n paths,\n intervalMs,\n importOptions:\n options.project !== undefined && options.project.length > 0\n ? { project: options.project }\n : {},\n now: () => ctx.nowProvider?.() ?? new Date(),\n signal: controller.signal,\n sleep: abortableSleep,\n log: (line) => console.log(line),\n });\n } finally {\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n }\n}\n\n/**\n * Pure runner: resolves the workspace, runs the shared refresh pipeline, and\n * prints a summary (or JSON). Returns the {@link RefreshResult} so the same\n * pipeline can be exercised by tests and reused by the view server.\n */\nexport async function doRunRefresh(\n options: RefreshOptions,\n ctx: RefreshContext,\n): Promise<RefreshResult> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForRefresh(cwd);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const nowIso = (ctx.nowProvider?.() ?? new Date()).toISOString();\n const result = await refreshAll({\n options: {\n ...(options.project !== undefined && options.project.length > 0\n ? { project: options.project }\n : {}),\n ...(options.force === true ? { force: true } : {}),\n ...(options.dryRun === true ? { dryRun: true } : {}),\n },\n ctx,\n paths,\n nowIso,\n });\n\n if (options.json === true) {\n console.log(JSON.stringify(result));\n } else {\n printRefreshSummary(result);\n }\n return result;\n}\n\nfunction describeImport(outcome: ImportOutcome): string {\n if (outcome.status === \"skipped\") {\n return `${outcome.adapter}: skipped (${outcome.reason})`;\n }\n const verb = outcome.dryRun ? \"would import\" : \"imported\";\n const parts = [`${outcome.importedCount} session(s)`, `${outcome.eventTotal} events`];\n if (outcome.reimportedCount > 0) parts.push(`${outcome.reimportedCount} re-imported`);\n if (outcome.replacedCount > 0) parts.push(`${outcome.replacedCount} replaced`);\n if (outcome.skippedAlreadyImported > 0)\n parts.push(`${outcome.skippedAlreadyImported} already imported`);\n if (outcome.skippedLegacyUntracked > 0) parts.push(`${outcome.skippedLegacyUntracked} legacy`);\n return `${outcome.adapter}: ${verb} ${parts.join(\", \")}`;\n}\n\nfunction printRefreshSummary(result: RefreshResult): void {\n console.log(describeImport(result.claudeCode));\n console.log(describeImport(result.codex));\n if (result.handoff.status === \"generated\") {\n console.log(\n `handoff: regenerated (sessions: ${result.handoff.sessionCount}, decisions: ${result.handoff.decisionCount})`,\n );\n } else {\n console.log(`handoff: skipped (${result.handoff.reason})`);\n }\n if (result.decisions.status === \"generated\") {\n console.log(`decisions: regenerated (${result.decisions.decisionCount})`);\n } else {\n console.log(`decisions: skipped (${result.decisions.reason})`);\n }\n}\n\nasync function resolveRepositoryRootForRefresh(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\"Not a git repository. Run 'git init' first, then re-run 'basou refresh'.\", {\n cause: error,\n });\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n","import {\n type BasouPaths,\n readMarkdownFile,\n renderDecisions,\n renderHandoff,\n renderWithMarkers,\n writeMarkdownFile,\n} from \"@basou/core\";\nimport {\n doRunImportClaudeCode,\n doRunImportCodex,\n type ImportContext,\n type ImportOptions,\n} from \"../commands/import.js\";\n\n/**\n * Shared provenance actions reused by both `basou refresh` (one-shot CLI) and\n * the `basou view` server's action endpoints, so the two stay behaviourally\n * identical. These wrap the existing import commands and markdown renderers;\n * they own no process state and print nothing of their own.\n */\n\n/** Which native-log adapter an import outcome came from. */\nexport type ImportAdapter = \"claude-code\" | \"codex\";\n\n/** Result of running one adapter's import, or a note that it was skipped. */\nexport type ImportOutcome =\n | {\n adapter: ImportAdapter;\n status: \"ran\";\n importedCount: number;\n replacedCount: number;\n /** Sessions re-imported in place because their source grew. */\n reimportedCount: number;\n skippedNoAction: number;\n skippedAlreadyImported: number;\n /** Already imported but with no recorded source size (pre-size-tracking); not re-imported. */\n skippedLegacyUntracked: number;\n eventTotal: number;\n dryRun: boolean;\n }\n | { adapter: ImportAdapter; status: \"skipped\"; reason: string };\n\n/** Counts from regenerating handoff.md / decisions.md, or a skip note. */\nexport type GenerateOutcome<TExtra> =\n | ({ status: \"generated\" } & TExtra)\n | { status: \"skipped\"; reason: string };\n\nexport type HandoffCounts = {\n sessionCount: number;\n taskCount: number;\n decisionCount: number;\n pendingApprovalsCount: number;\n};\n\n/** Structured result of {@link refreshAll}. */\nexport type RefreshResult = {\n claudeCode: ImportOutcome;\n codex: ImportOutcome;\n handoff: GenerateOutcome<HandoffCounts>;\n decisions: GenerateOutcome<{ decisionCount: number }>;\n dryRun: boolean;\n};\n\nexport type RefreshActionOptions = {\n project?: string[];\n force?: boolean;\n dryRun?: boolean;\n};\n\n/**\n * Run `fn` (an import command invoked with `json: true`) while capturing its\n * console output, then return the single machine-readable JSON result line.\n * The import commands print their result as one JSON object on stdout; that\n * line is the result contract. `console` is always restored, even on throw.\n */\nasync function captureImportJson(fn: () => Promise<void>): Promise<Record<string, unknown>> {\n const stdout: string[] = [];\n const originalLog = console.log;\n const originalError = console.error;\n console.log = ((...args: unknown[]) => {\n stdout.push(args.map((a) => String(a)).join(\" \"));\n }) as typeof console.log;\n // The import path writes an informational \"N path(s) sanitized\" line to\n // stderr; swallow it so refresh / the view server stay quiet.\n console.error = (() => {}) as typeof console.error;\n try {\n await fn();\n } finally {\n console.log = originalLog;\n console.error = originalError;\n }\n for (let i = stdout.length - 1; i >= 0; i--) {\n const line = stdout[i];\n if (line === undefined) continue;\n try {\n const parsed: unknown = JSON.parse(line);\n if (parsed !== null && typeof parsed === \"object\" && \"imported_count\" in parsed) {\n return parsed as Record<string, unknown>;\n }\n } catch {\n // Not the JSON result line; keep scanning earlier lines.\n }\n }\n throw new Error(\"Import produced no parseable result\");\n}\n\nfunction readCount(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\n/**\n * A source-log directory that does not exist for the requested project is a\n * normal \"this adapter has nothing here\" condition for refresh, not a failure.\n */\nfunction isMissingSourceDir(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n return (\n error.message === \"Claude transcript directory not found for project\" ||\n error.message === \"Codex sessions directory not found\"\n );\n}\n\n/** Run one adapter import as a best-effort action, classifying a missing source dir as skipped. */\nasync function runImport(adapter: ImportAdapter, fn: () => Promise<void>): Promise<ImportOutcome> {\n try {\n const json = await captureImportJson(fn);\n return {\n adapter,\n status: \"ran\",\n importedCount: readCount(json.imported_count),\n replacedCount: readCount(json.replaced_count),\n reimportedCount: readCount(json.reimported_count),\n skippedNoAction: readCount(json.skipped_no_action),\n skippedAlreadyImported: readCount(json.skipped_already_imported),\n skippedLegacyUntracked: readCount(json.skipped_legacy_untracked),\n eventTotal: readCount(json.event_total),\n dryRun: json.dry_run === true,\n };\n } catch (error: unknown) {\n if (isMissingSourceDir(error)) {\n return { adapter, status: \"skipped\", reason: \"no source logs for this project\" };\n }\n throw error;\n }\n}\n\nfunction importOptions(options: RefreshActionOptions): ImportOptions {\n return {\n all: true,\n json: true,\n ...(options.project !== undefined ? { project: options.project } : {}),\n ...(options.force === true ? { force: true } : {}),\n ...(options.dryRun === true ? { dryRun: true } : {}),\n };\n}\n\n/** Import Claude Code transcripts for the project (best-effort). */\nexport function importClaudeCode(\n options: RefreshActionOptions,\n ctx: ImportContext,\n): Promise<ImportOutcome> {\n return runImport(\"claude-code\", () => doRunImportClaudeCode(importOptions(options), ctx));\n}\n\n/** Import Codex rollouts for the project (best-effort). */\nexport function importCodex(\n options: RefreshActionOptions,\n ctx: ImportContext,\n): Promise<ImportOutcome> {\n return runImport(\"codex\", () => doRunImportCodex(importOptions(options), ctx));\n}\n\ntype RenderCallbacks = Parameters<typeof renderHandoff>[0];\n\n/** Regenerate `.basou/handoff.md` and return the renderer's counts. */\nexport async function regenerateHandoff(\n paths: BasouPaths,\n nowIso: string,\n callbacks?: Omit<RenderCallbacks, \"paths\" | \"nowIso\">,\n): Promise<HandoffCounts> {\n const result = await renderHandoff({ paths, nowIso, ...callbacks });\n const existing = await readMarkdownFile(paths.files.handoff);\n await writeMarkdownFile(\n paths.files.handoff,\n renderWithMarkers(existing, result.body, \"handoff.md\"),\n );\n return {\n sessionCount: result.sessionCount,\n taskCount: result.taskCount,\n decisionCount: result.decisionCount,\n pendingApprovalsCount: result.pendingApprovalsCount,\n };\n}\n\n/** Regenerate `.basou/decisions.md` and return the decision count. */\nexport async function regenerateDecisions(\n paths: BasouPaths,\n nowIso: string,\n callbacks?: Omit<Parameters<typeof renderDecisions>[0], \"paths\" | \"nowIso\">,\n): Promise<{ decisionCount: number }> {\n const result = await renderDecisions({ paths, nowIso, ...callbacks });\n const existing = await readMarkdownFile(paths.files.decisions);\n await writeMarkdownFile(\n paths.files.decisions,\n renderWithMarkers(existing, result.body, \"decisions.md\"),\n );\n return { decisionCount: result.decisionCount };\n}\n\n/**\n * The shared refresh pipeline: import both adapters (best-effort) for the\n * project, then regenerate handoff + decisions. Under `dryRun`, imports run in\n * preview mode and the markdown files are left untouched. The caller resolves\n * `paths` / `nowIso` and supplies the import `ctx`.\n */\nexport async function refreshAll(args: {\n options: RefreshActionOptions;\n ctx: ImportContext;\n paths: BasouPaths;\n nowIso: string;\n}): Promise<RefreshResult> {\n const { options, ctx, paths, nowIso } = args;\n const dryRun = options.dryRun === true;\n\n const claudeCode = await importClaudeCode(options, ctx);\n const codex = await importCodex(options, ctx);\n\n if (dryRun) {\n const skipped = { status: \"skipped\" as const, reason: \"dry-run\" };\n return { claudeCode, codex, handoff: skipped, decisions: skipped, dryRun };\n }\n\n const handoffCounts = await regenerateHandoff(paths, nowIso);\n const decisionCounts = await regenerateDecisions(paths, nowIso);\n return {\n claudeCode,\n codex,\n handoff: { status: \"generated\", ...handoffCounts },\n decisions: { status: \"generated\", ...decisionCounts },\n dryRun,\n };\n}\n","import type { Dirent } from \"node:fs\";\nimport { readdir, stat } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { type BasouPaths, findErrorCode } from \"@basou/core\";\nimport {\n type ImportOutcome,\n importClaudeCode,\n importCodex,\n type RefreshActionOptions,\n regenerateDecisions,\n regenerateHandoff,\n} from \"../lib/provenance-actions.js\";\nimport type { ImportContext } from \"./import.js\";\n\n/** Default poll interval for `--watch`, in seconds. */\nexport const DEFAULT_WATCH_INTERVAL_SEC = 30;\n/** Smallest accepted `--interval`, in seconds. */\nexport const MIN_WATCH_INTERVAL_SEC = 5;\n/** Largest accepted `--interval`, in seconds (1 day; keeps the timer well within the 32-bit ms range). */\nexport const MAX_WATCH_INTERVAL_SEC = 86_400;\n\n/** A file's change signature: a refresh is triggered when this moves. */\ntype FileSig = { mtimeMs: number; size: number };\n/** Absolute `*.jsonl` path -> its {mtime, size} signature. */\nexport type SourceLogScan = Map<string, FileSig>;\n\n/**\n * The native-log stores the importers read (Codex rollouts + Claude\n * transcripts), resolved from the context or the `~` defaults. These are the\n * directories the watcher polls -- a new session is a new/grown `*.jsonl` here.\n */\nexport function watchedRoots(ctx: ImportContext): string[] {\n return [\n ctx.codexSessionsDir ?? join(homedir(), \".codex\", \"sessions\"),\n ctx.claudeProjectsDir ?? join(homedir(), \".claude\", \"projects\"),\n ];\n}\n\n/**\n * Recursively collect a `{mtime, size}` signature of every `*.jsonl` under the\n * given roots, keyed by absolute path. A missing root contributes nothing (it\n * may appear later); a file that vanishes mid-walk is skipped. No file content\n * is read, so this is cheap to run every poll.\n */\nexport async function scanSourceLogs(roots: string[]): Promise<SourceLogScan> {\n const out: SourceLogScan = new Map();\n const walk = async (dir: string): Promise<void> => {\n let entries: Dirent[];\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch (error: unknown) {\n // Absent (ENOENT) or not a directory (ENOTDIR): nothing to scan here.\n if (findErrorCode(error, \"ENOENT\") || findErrorCode(error, \"ENOTDIR\")) return;\n // Surface other errors pathlessly (the native message carries the path).\n throw new Error(\"Failed to read a source log directory\", { cause: error });\n }\n for (const entry of entries) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n await walk(full);\n } else if (entry.isFile() && entry.name.endsWith(\".jsonl\")) {\n try {\n const info = await stat(full);\n out.set(full, { mtimeMs: info.mtimeMs, size: info.size });\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) continue; // vanished mid-walk; skip\n throw new Error(\"Failed to stat a source log file\", { cause: error });\n }\n }\n }\n };\n for (const root of roots) await walk(root);\n return out;\n}\n\n/** Whether two scans describe the same set of files at the same size/mtime. */\nexport function scansEqual(a: SourceLogScan, b: SourceLogScan): boolean {\n if (a.size !== b.size) return false;\n for (const [path, sig] of a) {\n const other = b.get(path);\n if (other === undefined || other.mtimeMs !== sig.mtimeMs || other.size !== sig.size) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * How many sessions an import outcome changed on disk: new imports PLUS\n * in-place re-imports of grown sources PLUS --force replacements. Any\n * non-zero count must trigger a handoff / decisions regeneration, so a session\n * that was re-imported (not freshly imported) does not leave the derived\n * markdown stale.\n */\nfunction changedCount(outcome: ImportOutcome): number {\n return outcome.status === \"ran\"\n ? outcome.importedCount + outcome.reimportedCount + outcome.replacedCount\n : 0;\n}\n\nfunction describeOutcome(outcome: ImportOutcome): string {\n if (outcome.status !== \"ran\") return `${outcome.adapter} skipped`;\n const reimported = outcome.reimportedCount > 0 ? ` ~${outcome.reimportedCount}` : \"\";\n return `${outcome.adapter} +${outcome.importedCount}${reimported}`;\n}\n\nfunction hms(date: Date): string {\n return date.toISOString().slice(11, 19);\n}\n\n/** Dependencies for {@link runRefreshWatch}; timers / clock / signal are injectable for tests. */\nexport type WatchDeps = {\n ctx: ImportContext;\n paths: BasouPaths;\n intervalMs: number;\n /** Import options forwarded to each cycle (project source roots only; no force / dry-run in watch). */\n importOptions: RefreshActionOptions;\n now: () => Date;\n signal: AbortSignal;\n /** Resolves after `ms`, or early when `signal` aborts. */\n sleep: (ms: number, signal: AbortSignal) => Promise<void>;\n log: (line: string) => void;\n};\n\n/** Import both adapters for the workspace's source roots; returns the outcomes + total imported. */\nasync function runImports(\n deps: WatchDeps,\n): Promise<{ claude: ImportOutcome; codex: ImportOutcome; changed: number }> {\n const claude = await importClaudeCode(deps.importOptions, deps.ctx);\n const codex = await importCodex(deps.importOptions, deps.ctx);\n return { claude, codex, changed: changedCount(claude) + changedCount(codex) };\n}\n\n/** Regenerate handoff + decisions; returns the handoff session count. */\nasync function regenerate(deps: WatchDeps): Promise<number> {\n const nowIso = deps.now().toISOString();\n const handoff = await regenerateHandoff(deps.paths, nowIso);\n await regenerateDecisions(deps.paths, nowIso);\n return handoff.sessionCount;\n}\n\n/**\n * Poll the native-log stores and keep the workspace current. Does an initial\n * catch-up refresh, then on each interval re-imports ONLY when the logs are\n * quiescent (unchanged since the previous poll, so no session is mid-write) AND\n * have changed since the last import. Handoff / decisions regenerate only when\n * something was imported, so unrelated AI activity elsewhere never rewrites this\n * workspace's files. A failure inside a steady-state cycle is logged and the\n * loop continues; the initial refresh failing is fatal (it propagates). Returns\n * when `signal` aborts (after the in-flight cycle, never mid-write).\n */\nexport async function runRefreshWatch(deps: WatchDeps): Promise<void> {\n const { intervalMs, ctx, signal, sleep, log } = deps;\n const roots = watchedRoots(ctx);\n log(\n `watching ${roots.join(\", \")} every ${Math.round(intervalMs / 1000)}s ` +\n \"(imports on change; Ctrl-C to stop)\",\n );\n\n // Baseline BEFORE the initial import, so a session that appears during the\n // import window is not mistaken for \"already seen\" and missed forever.\n let lastScan = await scanSourceLogs(roots);\n let importedScan = lastScan;\n\n // Initial catch-up: failure here is fatal (propagates to the caller).\n const initial = await runImports(deps);\n const initialSessions = await regenerate(deps);\n log(\n `[${hms(deps.now())}] refreshed: ${describeOutcome(initial.codex)}, ` +\n `${describeOutcome(initial.claude)} (sessions: ${initialSessions})`,\n );\n if (signal.aborted) {\n log(\"watch stopped\");\n return;\n }\n\n // Set when an import succeeded but the matching regenerate has not yet (so a\n // regenerate failure cannot leave handoff / decisions stale forever).\n let pendingRegen = false;\n while (!signal.aborted) {\n await sleep(intervalMs, signal);\n if (signal.aborted) break;\n try {\n const current = await scanSourceLogs(roots);\n // Quiescent since the previous poll AND changed since the last import.\n if (scansEqual(current, lastScan) && !scansEqual(current, importedScan)) {\n const { claude, codex, changed } = await runImports(deps);\n if (changed > 0) pendingRegen = true;\n if (pendingRegen) {\n const sessions = await regenerate(deps);\n pendingRegen = false;\n log(\n `[${hms(deps.now())}] refreshed: ${describeOutcome(codex)}, ` +\n `${describeOutcome(claude)} (sessions: ${sessions})`,\n );\n }\n importedScan = current;\n }\n lastScan = current;\n } catch (error: unknown) {\n // A transient fs error must not kill a long-running watcher. Messages from\n // the scan / import / render layers are pathless by contract.\n const message = error instanceof Error ? error.message : String(error);\n log(`[${hms(deps.now())}] refresh cycle skipped: ${message}`);\n }\n }\n log(\"watch stopped\");\n}\n","import type { ChildProcess } from \"node:child_process\";\nimport { mkdir } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport {\n assertBasouRootSafe,\n basouPaths,\n ChildProcessRunner,\n claudeCodeAdapterMetadata,\n appendEvent as coreAppendEvent,\n type DiffResult,\n type GitSnapshot,\n getDiff,\n getSnapshot,\n overwriteYamlFile,\n type PrefixedId,\n type ProcessRunner,\n prefixedUlid,\n type RunResult,\n readManifest,\n readYamlFile,\n resolveClaudeCodeCommand,\n resolveRepositoryRoot,\n type Session,\n SessionSchema,\n sanitizeRelatedFiles,\n sanitizeWorkingDirectory,\n writeYamlFile,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport { isVerbose, renderCliError } from \"../lib/error-render.js\";\n\ntype AppendEventFn = typeof coreAppendEvent;\ntype ResolveCommandFn = typeof resolveClaudeCodeCommand;\ntype GetDiffFn = typeof getDiff;\n\n/**\n * `basou run claude-code` orchestration: spawn claude-code as a single new\n * Basou session and record its lifecycle (session_started, optional\n * git_snapshot pre, status_changed, command_executed, optional git_snapshot\n * post, file_changed × N, status_changed, session_ended) to events.jsonl.\n *\n * The child inherits the parent's stdio (`capture: \"none\"`) so that\n * claude-code's interactive TTY remains usable; raw stdout/stderr is\n * intentionally NOT captured into events.jsonl or `.basou/raw/` in v0.1.\n */\nexport type RunOptions = {\n // commander turns `--no-snapshot` into `snapshot: false`. The default\n // (no flag) leaves this `undefined` (treated as `true` downstream).\n snapshot?: boolean;\n cwd?: string;\n verbose?: boolean;\n};\n\nexport type RunContext = {\n runner?: ProcessRunner;\n now?: () => Date;\n appendEvent?: AppendEventFn;\n onExitHookInstalled?: (handler: () => void) => void;\n // Override the claude-code PATH lookup. Tests use this to skip real\n // `which` invocations and force success / failure deterministically.\n resolveCommand?: ResolveCommandFn;\n // Override the git diff capability. Tests use this to force capability\n // failure deterministically without rewriting the git fixture state.\n getDiff?: GetDiffFn;\n};\n\n/**\n * Wire the `basou run` command group into `program`. The optional `ctx` is\n * passed through to `runClaudeCode` so tests can intercept the action callback\n * (fake runner, fake clock, deterministic resolveCommand / getDiff). Production\n * callers omit it.\n *\n * Basou options (`--no-snapshot`, `--cwd`, `-v`) are defined on both the\n * `run` group and the inner `claude-code` subcommand. commander's\n * `passThroughOptions()` only forwards UNKNOWN options to args, so a\n * group-only definition would make `basou run claude-code --no-snapshot`\n * crash with \"unknown option\". Duplicating the definitions lets the option\n * be recognized regardless of position; only `--`-separated args go to the\n * child. v0.2+ adapter additions (codex / gemini) should consider\n * extracting a common-option helper rather than re-duplicating.\n */\nexport function registerRunCommand(program: Command, ctx: RunContext = {}): void {\n const runCommand = program\n .command(\"run\")\n .description(\"Run an AI coding tool through Basou as a tracked session\")\n // Required so the inner `claude-code` subcommand can pass through\n // arguments after `--` to the child without commander interpreting them\n // as run-group options.\n .enablePositionalOptions()\n .option(\"--no-snapshot\", \"Skip git_snapshot before/after the session\")\n .option(\"--cwd <path>\", \"Run from a Basou root other than process.cwd()\")\n .option(\"-v, --verbose\", \"Show error causes\");\n\n runCommand\n .command(\"claude-code [args...]\")\n .description(\"Run Claude Code CLI as a Basou-tracked session\")\n // Same options redeclared on the subsubcommand so they are recognized\n // when placed AFTER `claude-code` as well; see the function comment.\n .option(\"--no-snapshot\", \"Skip git_snapshot before/after the session\")\n .option(\"--cwd <path>\", \"Run from a Basou root other than process.cwd()\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .passThroughOptions()\n .action(async (args: string[], options: RunOptions, command: Command) => {\n const parentOptions = (command.parent?.opts() ?? {}) as RunOptions;\n // Both layers default `snapshot` to `true` when --no-snapshot is\n // omitted, so a naive spread would let the subsubcommand's default\n // overwrite a `--no-snapshot` set on the parent. Take a logical AND\n // instead: snapshot stays on only when neither layer disables it.\n const snapshotOn = parentOptions.snapshot !== false && options.snapshot !== false;\n const merged: RunOptions = {\n ...parentOptions,\n ...options,\n snapshot: snapshotOn,\n };\n try {\n const exitCode = await runClaudeCode(args, merged, ctx);\n process.exit(exitCode);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(merged) });\n process.exit(1);\n }\n });\n}\n\nexport async function runClaudeCode(\n args: string[],\n options: RunOptions,\n ctx: RunContext = {},\n): Promise<number> {\n const runner = ctx.runner ?? new ChildProcessRunner();\n const now = ctx.now ?? (() => new Date());\n const appendEvent: AppendEventFn = ctx.appendEvent ?? coreAppendEvent;\n const resolveCommand: ResolveCommandFn = ctx.resolveCommand ?? resolveClaudeCodeCommand;\n const getDiffFn: GetDiffFn = ctx.getDiff ?? getDiff;\n\n // 1. Resolve the claude-code executable BEFORE any side-effect: a missing\n // CLI is a user installation issue, not something worth recording as a\n // Basou session. Failure here leaves no sessions/<id>/ entry behind.\n const { command } = await resolveCommand();\n\n const cwd = options.cwd ?? process.cwd();\n\n // 2. Resolve repository root (entry-fail when not in a git repo).\n const repoRoot = await resolveRepositoryRootForRun(cwd);\n const paths = basouPaths(repoRoot);\n\n // 3. Workspace safety check.\n await assertBasouRootSafe(paths.root);\n\n // 4. Read manifest to bind session.workspace_id.\n const manifest = await readManifest(paths);\n\n // 5. Build a fresh session and persist its initial state.\n const sessionId = prefixedUlid(\"ses\");\n const sessionDir = join(paths.sessions, sessionId);\n await mkdir(sessionDir, { recursive: true });\n\n const startedAt = now().toISOString();\n const sessionYamlPath = join(sessionDir, \"session.yaml\");\n const session = buildInitialSession({\n id: sessionId,\n command,\n args,\n cwd: repoRoot,\n workspaceId: manifest.workspace.id,\n startedAt,\n });\n await writeYamlFile(sessionYamlPath, session);\n\n // 6. session_started.\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_started\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: startedAt,\n source: claudeCodeAdapterMetadata.kind,\n });\n\n // 7. Optional pre-execute git_snapshot.\n let preSnapshot: GitSnapshot | null = null;\n if (options.snapshot !== false) {\n preSnapshot = await tryAppendGitSnapshot(sessionDir, sessionId, repoRoot, now, appendEvent);\n }\n\n // 8. status_changed: initialized -> running.\n const runningAt = now().toISOString();\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_status_changed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: runningAt,\n source: claudeCodeAdapterMetadata.kind,\n from: \"initialized\",\n to: \"running\",\n });\n await mutateSessionYaml(sessionYamlPath, (s) => {\n s.session.status = \"running\";\n });\n\n // 9. Transient signal hooks (SIGINT / SIGTERM / exit). The exit hook is a\n // last-resort SIGKILL if the parent dies abnormally.\n const controller = new AbortController();\n let signalReceived: NodeJS.Signals | null = null;\n let activeChild: ChildProcess | null = null;\n const signalHandler = (sig: NodeJS.Signals) => {\n if (signalReceived !== null) return;\n signalReceived = sig;\n controller.abort();\n };\n const exitHandler = () => {\n if (activeChild !== null) {\n try {\n activeChild.kill(\"SIGKILL\");\n } catch {\n // best-effort cleanup\n }\n }\n };\n const onSigInt = () => signalHandler(\"SIGINT\");\n const onSigTerm = () => signalHandler(\"SIGTERM\");\n process.on(\"SIGINT\", onSigInt);\n process.on(\"SIGTERM\", onSigTerm);\n process.on(\"exit\", exitHandler);\n ctx.onExitHookInstalled?.(exitHandler);\n\n // 10-11. runner.run() execute (capture: \"none\" inherits the parent stdio so\n // claude-code keeps a real TTY). Spawn-time errors finalize the\n // session as failed and propagate the error.\n let result: RunResult;\n try {\n try {\n result = await runner.run(command, args, {\n cwd: repoRoot,\n capture: \"none\",\n signal: controller.signal,\n onSpawn: (child) => {\n activeChild = child;\n },\n });\n } catch (spawnError: unknown) {\n await finalizeSessionAsFailed(sessionDir, sessionYamlPath, sessionId, appendEvent, {\n command,\n args,\n cwd: repoRoot,\n occurredAt: now().toISOString(),\n signalReceived,\n });\n throw spawnError;\n }\n } finally {\n process.off(\"SIGINT\", onSigInt);\n process.off(\"SIGTERM\", onSigTerm);\n process.off(\"exit\", exitHandler);\n activeChild = null;\n }\n\n const endedAt = now().toISOString();\n\n // 12. command_executed (parent received_signal vs child terminating signal).\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"command_executed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: endedAt,\n source: \"terminal-recording\",\n command,\n args,\n cwd: repoRoot,\n exit_code: result.exit_code,\n ...(result.signal !== null ? { signal: result.signal } : {}),\n ...(signalReceived !== null ? { received_signal: signalReceived } : {}),\n duration_ms: result.duration_ms,\n });\n\n // 13. Optional post-execute git_snapshot.\n let postSnapshot: GitSnapshot | null = null;\n if (options.snapshot !== false) {\n postSnapshot = await tryAppendGitSnapshot(sessionDir, sessionId, repoRoot, now, appendEvent);\n }\n\n // 14-15. file_changed events derived from getDiff(preHead, postHead). Only\n // committed changes appear here; dirty (staged/unstaged/untracked)\n // edits are surfaced via session.yaml.related_files instead.\n let diff: DiffResult | null = null;\n if (preSnapshot !== null && postSnapshot !== null) {\n diff = await tryAppendFileChangedEvents(\n sessionDir,\n sessionId,\n repoRoot,\n preSnapshot.head,\n postSnapshot.head,\n now().toISOString(),\n appendEvent,\n getDiffFn,\n );\n }\n\n // 16. Compute related_files = pre+post snapshot ∪ diff (sorted, deduped).\n // Then sanitize so /Users/<u>/projects/foo/... is stored relative to\n // the session's working_directory; system paths outside both bases\n // stay verbatim. Git output is usually repo-relative already, but the\n // sanitizer is idempotent and cheap so we run it unconditionally\n // against the very subset of paths that ever reach session.yaml.\n const rawRelated = computeRelatedFiles(preSnapshot, postSnapshot, diff);\n const relatedFiles = sanitizeRelatedFiles(rawRelated, {\n workingDirectory: repoRoot,\n homedir: homedir(),\n }).sanitized;\n\n const finalStatus = decideFinalStatus(result, signalReceived);\n\n // 17-18. status_changed: running -> final.\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_status_changed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: endedAt,\n source: claudeCodeAdapterMetadata.kind,\n from: \"running\",\n to: finalStatus,\n });\n\n // 19. session_ended.\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_ended\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: endedAt,\n source: claudeCodeAdapterMetadata.kind,\n ...(result.exit_code !== null ? { exit_code: result.exit_code } : {}),\n });\n\n // 20. Final session.yaml update (status / ended_at / invocation.exit_code /\n // related_files).\n await mutateSessionYaml(sessionYamlPath, (s) => {\n s.session.status = finalStatus;\n s.session.ended_at = endedAt;\n s.session.invocation.exit_code = result.exit_code;\n s.session.related_files = relatedFiles;\n });\n\n if (result.exit_code !== null) return result.exit_code;\n return signalToExitCode(signalReceived ?? result.signal);\n}\n\nfunction decideFinalStatus(\n result: { exit_code: number | null; signal: NodeJS.Signals | null },\n signalReceived: NodeJS.Signals | null,\n): \"completed\" | \"failed\" | \"interrupted\" {\n if (signalReceived === \"SIGINT\" || signalReceived === \"SIGTERM\") return \"interrupted\";\n if (result.signal === \"SIGINT\" || result.signal === \"SIGTERM\" || result.signal === \"SIGKILL\") {\n return \"interrupted\";\n }\n if (result.exit_code === 0) return \"completed\";\n return \"failed\";\n}\n\nconst SIGNUM_MAP: Record<string, number> = {\n SIGHUP: 1,\n SIGINT: 2,\n SIGQUIT: 3,\n SIGKILL: 9,\n SIGTERM: 15,\n};\n\nfunction signalToExitCode(sig: NodeJS.Signals | null): number {\n if (sig === null) return 1;\n const num = SIGNUM_MAP[sig] ?? 1;\n return 128 + num;\n}\n\nasync function tryAppendGitSnapshot(\n sessionDir: string,\n sessionId: string,\n repoRoot: string,\n now: () => Date,\n appendEvent: AppendEventFn,\n): Promise<GitSnapshot | null> {\n // Stage 1: capability acquisition. Capability-level failures (no git\n // repository, git binary missing, no commits) downgrade to a skip warning;\n // events.jsonl simply lacks this git_snapshot entry.\n let snapshot: GitSnapshot;\n try {\n snapshot = await getSnapshot(repoRoot);\n } catch (error: unknown) {\n console.warn(normalizeGitSnapshotSkipMessage(error));\n return null;\n }\n // Stage 2: events.jsonl append. Failures here would corrupt the events.jsonl\n // integrity contract; let them propagate so the run fails loudly rather\n // than producing a session that looks successful but is actually missing\n // events.\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"git_snapshot\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: now().toISOString(),\n source: \"git-capability\",\n ...snapshot,\n });\n return snapshot;\n}\n\nasync function tryAppendFileChangedEvents(\n sessionDir: string,\n sessionId: string,\n repoRoot: string,\n baseRef: string,\n headRef: string,\n occurredAt: string,\n appendEvent: AppendEventFn,\n getDiffFn: GetDiffFn,\n): Promise<DiffResult | null> {\n // Stage 1: capability acquisition (same skip-vs-fail split as\n // tryAppendGitSnapshot).\n let diff: DiffResult;\n try {\n diff = await getDiffFn(repoRoot, baseRef, headRef);\n } catch (error: unknown) {\n console.warn(normalizeFileChangedSkipMessage(error));\n return null;\n }\n // Stage 2: per-path appendEvent. Schema validation / disk failures here\n // are NOT a capability miss; let them propagate.\n for (const change of diff.changed_files) {\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"file_changed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: occurredAt,\n source: \"git-capability\",\n path: change.path,\n change_type: change.status,\n ...(change.old_path !== undefined ? { old_path: change.old_path } : {}),\n });\n }\n return diff;\n}\n\nfunction computeRelatedFiles(\n preSnapshot: GitSnapshot | null,\n postSnapshot: GitSnapshot | null,\n diff: DiffResult | null,\n): string[] {\n const set = new Set<string>();\n for (const snap of [preSnapshot, postSnapshot]) {\n if (snap === null) continue;\n for (const p of snap.staged) set.add(p);\n for (const p of snap.unstaged) set.add(p);\n for (const p of snap.untracked) set.add(p);\n }\n if (diff !== null) {\n for (const change of diff.changed_files) set.add(change.path);\n }\n return [...set].sort();\n}\n\nfunction normalizeGitSnapshotSkipMessage(error: unknown): string {\n if (!(error instanceof Error)) {\n return `git_snapshot skipped: ${String(error)}`;\n }\n const msg = error.message;\n if (msg === \"Not a git repository\") return \"git_snapshot skipped: not in a git repository\";\n if (msg === \"Git executable not found in PATH. Install git first.\") {\n return \"git_snapshot skipped: git executable not found\";\n }\n if (msg === \"No commits in repository\") return \"git_snapshot skipped: no commits in repository\";\n return `git_snapshot skipped: ${msg}`;\n}\n\nfunction normalizeFileChangedSkipMessage(error: unknown): string {\n if (!(error instanceof Error)) {\n return `file_changed skipped: ${String(error)}`;\n }\n const msg = error.message;\n if (msg === \"Not a git repository\") return \"file_changed skipped: not in a git repository\";\n if (msg === \"Git executable not found in PATH. Install git first.\") {\n return \"file_changed skipped: git executable not found\";\n }\n if (msg === \"Invalid ref\") return \"file_changed skipped: invalid git ref\";\n if (msg === \"Failed to compute git diff\")\n return \"file_changed skipped: failed to compute git diff\";\n return `file_changed skipped: ${msg}`;\n}\n\nfunction buildInitialSession(input: {\n id: PrefixedId<\"ses\">;\n command: string;\n args: string[];\n cwd: string;\n workspaceId: PrefixedId<\"ws\">;\n startedAt: string;\n}): Session {\n const cmdline = [input.command, ...input.args].join(\" \");\n return {\n schema_version: \"0.1.0\",\n session: {\n id: input.id,\n label: `basou run ${cmdline} (${input.startedAt})`,\n task_id: null,\n workspace_id: input.workspaceId,\n source: { ...claudeCodeAdapterMetadata },\n started_at: input.startedAt,\n status: \"initialized\",\n working_directory: sanitizeWorkingDirectory(input.cwd, { homedir: homedir() }),\n invocation: {\n command: input.command,\n args: [...input.args],\n exit_code: null,\n },\n related_files: [],\n events_log: \"events.jsonl\",\n },\n };\n}\n\nasync function mutateSessionYaml(\n filePath: string,\n mutator: (session: Session) => void,\n): Promise<void> {\n const raw = await readYamlFile(filePath);\n const parsed = SessionSchema.parse(raw);\n mutator(parsed);\n const validated = SessionSchema.parse(parsed);\n await overwriteYamlFile(filePath, validated);\n}\n\nasync function finalizeSessionAsFailed(\n sessionDir: string,\n sessionYamlPath: string,\n sessionId: string,\n appendEvent: AppendEventFn,\n ctx: {\n command: string;\n args: string[];\n cwd: string;\n occurredAt: string;\n signalReceived: NodeJS.Signals | null;\n },\n): Promise<void> {\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"command_executed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: ctx.occurredAt,\n source: \"terminal-recording\",\n command: ctx.command,\n args: ctx.args,\n cwd: ctx.cwd,\n exit_code: null,\n signal: null,\n ...(ctx.signalReceived !== null ? { received_signal: ctx.signalReceived } : {}),\n duration_ms: 0,\n });\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_status_changed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: ctx.occurredAt,\n source: claudeCodeAdapterMetadata.kind,\n from: \"running\",\n to: \"failed\",\n });\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_ended\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: ctx.occurredAt,\n source: claudeCodeAdapterMetadata.kind,\n });\n await mutateSessionYaml(sessionYamlPath, (s) => {\n s.session.status = \"failed\";\n s.session.ended_at = ctx.occurredAt;\n s.session.invocation.exit_code = null;\n });\n}\n\nasync function resolveRepositoryRootForRun(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\"Not a git repository. Run 'git init' first, then re-run 'basou run'.\", {\n cause: error,\n });\n }\n throw error;\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { basename, isAbsolute, join, relative } from \"node:path\";\nimport {\n acquireLock,\n appendEventToExistingSession,\n assertBasouRootSafe,\n basouPaths,\n type Event,\n findErrorCode,\n type ImportSessionOptions,\n type ImportSessionResult,\n importSessionFromJson,\n loadSessionEntries,\n readAllEvents,\n readManifest,\n readYamlFile,\n resolveRepositoryRoot,\n resolveSessionId,\n resolveTaskId,\n type Session,\n SessionImportPayloadSchema,\n SessionSchema,\n type SessionStatus,\n SessionStatusSchema,\n sessionWorkStatsFromEvents,\n} from \"@basou/core\";\nimport { type Command, InvalidArgumentError } from \"commander\";\nimport {\n isVerbose,\n printReplayWarning,\n printSessionListSkip,\n renderCliError,\n} from \"../lib/error-render.js\";\nimport { formatDurationMs } from \"../lib/format-duration.js\";\n\nconst SES_PREFIX = \"ses_\";\nconst TASK_PREFIX = \"task_\";\nconst SHORT_ID_BASE_LEN = 6;\nconst SHORT_ID_MAX_LEN = 26; // ULID body length\n\nconst STATUS_VALUES = SessionStatusSchema.options;\n\nexport type SessionListOptions = {\n json?: boolean;\n status?: SessionStatus;\n verbose?: boolean;\n};\n\nexport type SessionShowOptions = {\n json?: boolean;\n events?: boolean;\n last?: number;\n fullPath?: boolean;\n verbose?: boolean;\n};\n\nexport type SessionContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n /** Defaults to `() => new Date()`. Injectable so the `session show` work\n * span is deterministic in tests and for a running session. */\n nowProvider?: () => Date;\n};\n\ntype SessionListRecord = {\n sessionId: string;\n session: Session;\n suspect: boolean;\n suspectReason: string | null;\n};\n\n/**\n * Wire `basou session list` and `basou session show <id>` onto `program`.\n *\n * The `session` group is registered up front so future subcommands\n * (`note`, `import`) added in later steps slot under the same group without\n * changing the externally visible CLI surface.\n */\nexport function registerSessionCommand(program: Command): void {\n const session = program\n .command(\"session\")\n .description(\"Inspect Basou sessions stored under .basou/sessions/\");\n\n session\n .command(\"list\")\n .description(\"List sessions in the current workspace (newest first)\")\n .option(\"--json\", \"Output the list as a JSON array\")\n .option(\n \"--status <state>\",\n `Filter by session status (one of: ${STATUS_VALUES.join(\", \")})`,\n parseSessionStatus,\n )\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: SessionListOptions) => {\n await runSessionList(options);\n });\n\n session\n .command(\"show <id>\")\n .description(\"Show a session's metadata and recent events\")\n .option(\"--json\", \"Output the session and events as JSON\")\n .option(\"--events\", \"List all events instead of just the trailing few\")\n .option(\"--last <n>\", \"Number of trailing events to display (default: 5)\", parsePositiveInt)\n .option(\n \"--full-path\",\n \"Show working_directory as an absolute path instead of repository-relative\",\n )\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (id: string, options: SessionShowOptions) => {\n await runSessionShow(id, options);\n });\n\n session\n .command(\"import\")\n .description(\"Import a session from a JSON file\")\n .requiredOption(\"--format <format>\", \"Input format (currently only 'json')\", parseImportFormat)\n .requiredOption(\"--from <path>\", \"Path to the input JSON file\")\n .option(\"--label <text>\", \"Override the session label\", parseLabelOverride)\n .option(\"--task <task_id>\", \"Override the session task_id\", parseTaskIdOverride)\n .option(\"--dry-run\", \"Validate input only; do not write to disk\")\n .option(\"--json\", \"Output the result as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: SessionImportOptions) => {\n await runSessionImport(options);\n });\n\n session\n .command(\"note <session_id>\")\n .description(\"Append a note_added event to an existing session\")\n .option(\"--body <text>\", \"Note body (inline)\", parseNoteBodyOption)\n .option(\"--from-file <path>\", \"Read note body from a file\")\n .option(\"--json\", \"Output the result as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (sessionIdInput: string, options: SessionNoteOptions) => {\n await runSessionNote(sessionIdInput, options);\n });\n}\n\n/**\n * Programmatic entry for `basou session list` that owns process exit state.\n * Tests targeting only the success path or the thrown error should prefer\n * {@link doRunSessionList}.\n */\nexport async function runSessionList(\n options: SessionListOptions,\n ctx: SessionContext = {},\n): Promise<void> {\n try {\n await doRunSessionList(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * Pure runner for `session list`. Throws on any failure with a pathless\n * message; native errors are attached as `cause` for verbose surfacing.\n */\nexport async function doRunSessionList(\n options: SessionListOptions,\n ctx: SessionContext,\n): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForSession(cwd, \"list\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n // Orchestration is delegated to core's `loadSessionEntries`. To preserve\n // the existing stderr surface (\"Skipped <sid>: <reason>\" and\n // \"Warning: skipped suspect check for <sid>: events.jsonl unreadable\"),\n // map onSkip / onWarning on the CLI side.\n const now = new Date();\n const records: SessionListRecord[] = (\n await loadSessionEntries(paths, {\n now,\n onWarning: (w, sid) => printReplayWarning(w, sid),\n onSkip: (sid, reason) => printSessionListSkip(sid, reason),\n })\n ).map((entry) => ({\n sessionId: entry.sessionId,\n session: entry.session,\n suspect: entry.suspect,\n suspectReason: entry.suspectReason,\n }));\n\n if (records.length === 0) {\n printNoSessions(options);\n return;\n }\n\n // started_at desc using Date.parse to normalize across timezone offsets;\n // a lexicographic compare would swap two timestamps that point at the same\n // instant when their offsets differ.\n records.sort(\n (a, b) => Date.parse(b.session.session.started_at) - Date.parse(a.session.session.started_at),\n );\n\n const filtered =\n options.status !== undefined\n ? records.filter((r) => r.session.session.status === options.status)\n : records;\n\n if (filtered.length === 0) {\n printNoSessions(options);\n return;\n }\n\n if (options.json === true) {\n console.log(\n JSON.stringify(\n filtered.map((r) => ({\n ...r.session.session,\n suspect: r.suspect,\n suspect_reason: r.suspectReason,\n })),\n null,\n 2,\n ),\n );\n } else {\n printSessionListText(filtered);\n }\n}\n\n/**\n * Programmatic entry for `basou session show <id>`. See {@link runSessionList}\n * for the split pattern rationale.\n */\nexport async function runSessionShow(\n idInput: string,\n options: SessionShowOptions,\n ctx: SessionContext = {},\n): Promise<void> {\n try {\n await doRunSessionShow(idInput, options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunSessionShow(\n idInput: string,\n options: SessionShowOptions,\n ctx: SessionContext,\n): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForSession(cwd, \"show\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const sessionId = await resolveSessionId(paths, idInput);\n\n const sessionDir = join(paths.sessions, sessionId);\n const sessionYamlPath = join(sessionDir, \"session.yaml\");\n let session: Session;\n try {\n const raw = await readYamlFile(sessionYamlPath);\n session = SessionSchema.parse(raw);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(`Session not found: ${idInput}`);\n }\n throw new Error(\"Failed to read session\", { cause: error });\n }\n\n const events = await readAllEvents(sessionDir, {\n onWarning: (w) => printReplayWarning(w, sessionId),\n });\n\n if (options.json === true) {\n console.log(JSON.stringify({ session: session.session, events }, null, 2));\n return;\n }\n\n const now = ctx.nowProvider?.() ?? new Date();\n printSessionShowText(session, events, options, repositoryRoot, now);\n}\n\nfunction suspectLabel(reason: string | null): string {\n if (reason === \"events_say_ended_but_yaml_running\") return \" ⚠ ended (yaml stale)\";\n if (reason === \"running_no_end_event\") return \" ⚠ no end event\";\n return \"\";\n}\n\nfunction printSessionListText(records: SessionListRecord[]): void {\n // Grow the SHORT_ID column to the first length where every prefix is\n // unique. Without this an ambiguous prefix would copy-paste from the list\n // and fail `resolveSessionId` with \"Ambiguous session id\".\n const shortLen = computeUniquePrefixLen(records.map((r) => r.sessionId));\n const rows = records.map((r) => {\n const sid = sliceShort(r.sessionId, shortLen);\n const status = `${r.session.session.status}${suspectLabel(r.suspectReason)}`;\n const source = r.session.session.source.kind;\n const startedAt = r.session.session.started_at;\n const fileCount = r.session.session.related_files.length;\n const filesSuffix = fileCount > 0 ? ` (${fileCount} files)` : \"\";\n const label = (r.session.session.label ?? \"\") + filesSuffix;\n return { sid, status, source, startedAt, label };\n });\n\n const widths = {\n sid: maxLen(\n rows.map((r) => r.sid),\n \"SHORT_ID\".length,\n ),\n status: maxLen(\n rows.map((r) => r.status),\n \"STATUS\".length,\n ),\n source: maxLen(\n rows.map((r) => r.source),\n \"SOURCE\".length,\n ),\n startedAt: maxLen(\n rows.map((r) => r.startedAt),\n \"STARTED_AT\".length,\n ),\n };\n\n console.log(\n `${pad(\"SHORT_ID\", widths.sid)} ${pad(\"STATUS\", widths.status)} ${pad(\"SOURCE\", widths.source)} ${pad(\"STARTED_AT\", widths.startedAt)} LABEL`,\n );\n for (const row of rows) {\n console.log(\n `${pad(row.sid, widths.sid)} ${pad(row.status, widths.status)} ${pad(row.source, widths.source)} ${pad(row.startedAt, widths.startedAt)} ${row.label}`,\n );\n }\n}\n\nfunction printSessionShowText(\n session: Session,\n events: Event[],\n options: SessionShowOptions,\n repositoryRoot: string,\n now: Date,\n): void {\n const s = session.session;\n console.log(`Session: ${s.id} (status: ${s.status})`);\n console.log(`Source: ${s.source.kind} (v${s.source.version})`);\n console.log(`Workspace: ${s.workspace_id}`);\n console.log(`Started at: ${s.started_at}`);\n if (s.ended_at !== undefined) {\n console.log(`Ended at: ${s.ended_at}`);\n }\n console.log(`Working dir: ${formatWorkingDir(s.working_directory, repositoryRoot, options)}`);\n const invocationArgs = s.invocation.args.length > 0 ? ` ${s.invocation.args.join(\" \")}` : \"\";\n console.log(`Invocation: ${s.invocation.command}${invocationArgs}`);\n if (s.invocation.exit_code !== null) {\n console.log(`Exit code: ${s.invocation.exit_code}`);\n }\n if (s.label !== undefined) {\n console.log(`Label: ${s.label}`);\n }\n console.log(`Related files: ${formatRelatedFiles(s.related_files)}`);\n\n console.log(\"\");\n console.log(`Events: ${events.length} total`);\n const counts = countByType(events);\n for (const [type, n] of counts) {\n console.log(` ${pad(`${type}:`, 24)} ${n}`);\n }\n\n console.log(\"\");\n console.log(`Work: ${formatSessionWork(session, events, now)}`);\n\n if (events.length === 0) return;\n\n const last = options.last ?? 5;\n const showAll = options.events === true && options.last === undefined;\n const slice = showAll ? events : events.slice(-last);\n const heading = showAll ? \"All events:\" : `Last ${slice.length} events:`;\n console.log(\"\");\n console.log(heading);\n for (const ev of slice) {\n console.log(` ${formatEventLine(ev)}`);\n }\n}\n\n/**\n * One-line work summary for `session show`: output volume + action counts +\n * time proxies, reusing the same per-session computation as `basou stats`.\n * `command n/a (import)` flags sources whose shell time is unrecorded.\n */\nfunction formatSessionWork(session: Session, events: Event[], now: Date): string {\n const w = sessionWorkStatsFromEvents(session.session.id, session.session, events, now);\n const parts: string[] = [];\n if (w.tokens.output > 0) parts.push(`${w.tokens.output.toLocaleString(\"en-US\")} output tokens`);\n parts.push(`${w.commandCount} cmd / ${w.fileChangedCount} files / ${w.decisionCount} dec`);\n const activeBasis = w.activeTimeBasis === \"engaged-turns\" ? \"turns\" : \"events\";\n parts.push(`active ${formatDurationMs(w.activeTimeMs)} (${activeBasis})`);\n if (w.availability.machineActive) {\n parts.push(`machine ${formatDurationMs(w.machineActiveTimeMs)}`);\n }\n parts.push(`span ${formatDurationMs(w.sessionSpanMs)}${w.open ? \" (open)\" : \"\"}`);\n parts.push(\n w.availability.commandTime\n ? `command ${formatDurationMs(w.commandTimeMs)}`\n : \"command n/a (import)\",\n );\n return parts.join(\", \");\n}\n\nfunction formatWorkingDir(\n workingDir: string,\n repositoryRoot: string,\n options: SessionShowOptions,\n): string {\n if (options.fullPath === true) return workingDir;\n\n // v0.3 sanitized sessions write `working_directory` as a relative form\n // (`~/projects/foo`, `src/sub`, `.`, etc.) rather than the absolute\n // path the older write paths used. path.relative against a relative\n // input would silently resolve it against process.cwd and produce\n // nonsense like `<cwd>/~/projects/foo`, so the relative form must be\n // surfaced verbatim. The one literal we collapse is `.`, which means\n // \"the session ran at the repo root\" — same semantic as an absolute\n // workingDir equal to repositoryRoot.\n if (!isAbsolute(workingDir)) {\n if (workingDir === \".\") return \"<repository_root>\";\n return workingDir;\n }\n\n if (workingDir === repositoryRoot) return \"<repository_root>\";\n const rel = relative(repositoryRoot, workingDir);\n if (rel.length === 0 || rel === \".\") return \"<repository_root>\";\n // Outside-repo working directories surface as a `../...` relative path\n // rather than the absolute path so the default-display contract holds\n // even for sessions recorded from a sibling checkout. `--full-path` is\n // the explicit opt-in for the absolute form.\n if (rel.startsWith(\"..\")) return rel;\n return `./${rel}`;\n}\n\nfunction formatRelatedFiles(files: readonly string[]): string {\n if (files.length === 0) return \"0 paths\";\n const head = files.slice(0, 3).join(\", \");\n const remaining = files.length - 3;\n if (remaining <= 0) return `${files.length} paths (${head})`;\n return `${files.length} paths (${head}, ... +${remaining} more)`;\n}\n\nfunction countByType(events: readonly Event[]): Array<[string, number]> {\n const map = new Map<string, number>();\n for (const ev of events) {\n map.set(ev.type, (map.get(ev.type) ?? 0) + 1);\n }\n return [...map.entries()];\n}\n\nfunction formatEventLine(ev: Event): string {\n return `${ev.occurred_at} [${ev.source}] ${ev.type} ${eventVariantSummary(ev)}`;\n}\n\nfunction eventVariantSummary(ev: Event): string {\n switch (ev.type) {\n case \"command_executed\": {\n const argsPart = ev.args.length > 0 ? ` ${ev.args.join(\" \")}` : \"\";\n const exitPart = ev.exit_code === null ? \"exit=signal\" : `exit=${ev.exit_code}`;\n return `${ev.command}${argsPart} (${exitPart}, ${ev.duration_ms}ms)`;\n }\n case \"git_snapshot\":\n return `branch=${ev.branch} dirty=${ev.dirty}`;\n case \"file_changed\":\n return `${ev.change_type} ${ev.path}`;\n case \"session_status_changed\":\n return `${ev.from} -> ${ev.to}`;\n case \"session_started\":\n return \"(start)\";\n case \"session_ended\":\n return ev.exit_code !== undefined ? `exit_code=${ev.exit_code}` : \"(end)\";\n case \"approval_requested\":\n return `${ev.action.kind} risk=${ev.risk_level}`;\n case \"approval_approved\":\n return ev.resolver !== undefined ? `by ${ev.resolver}` : \"(approved)\";\n case \"approval_rejected\":\n return ev.resolver !== undefined ? `by ${ev.resolver}: ${ev.reason}` : ev.reason;\n case \"approval_expired\":\n return `approval=${ev.approval_id}`;\n case \"decision_recorded\":\n return ev.title;\n case \"task_created\":\n return ev.title;\n case \"task_status_changed\":\n return `${ev.from} -> ${ev.to}`;\n case \"task_reconciled\": {\n const createdPart =\n ev.removed_created_in_session !== null ? \"1 created_in_session\" : \"0 created_in_session\";\n return `task ${shortTaskId(ev.task_id)}: cleared ${ev.removed_linked_sessions.length} linked + ${createdPart}`;\n }\n case \"task_linkage_refreshed\": {\n const added = ev.added_linked_sessions.length;\n const removed = ev.removed_linked_sessions.length;\n const final = ev.final_count !== undefined ? ` final=${ev.final_count}` : \"\";\n return `task ${shortTaskId(ev.task_id)}: +${added} / -${removed} linked${final}`;\n }\n case \"task_deleted\":\n return `task ${shortTaskId(ev.task_id)}: ${ev.title} (deleted)`;\n case \"task_archived\":\n return `task ${shortTaskId(ev.task_id)}: ${ev.title} (archived)`;\n case \"note_added\":\n return ev.body.length > 80 ? `${ev.body.slice(0, 77)}...` : ev.body;\n case \"adapter_output\":\n return `${ev.stream} \"${ev.summary}\" raw_ref=${ev.raw_ref}`;\n }\n}\n\nfunction shortId(id: string): string {\n return sliceShort(id, SHORT_ID_BASE_LEN);\n}\n\nfunction shortTaskId(id: string): string {\n if (id.startsWith(TASK_PREFIX)) {\n return id.slice(TASK_PREFIX.length, TASK_PREFIX.length + SHORT_ID_BASE_LEN);\n }\n return id.slice(0, SHORT_ID_BASE_LEN);\n}\n\nfunction sliceShort(id: string, len: number): string {\n if (id.startsWith(SES_PREFIX)) {\n return id.slice(SES_PREFIX.length, SES_PREFIX.length + len);\n }\n return id.slice(0, len);\n}\n\n/**\n * Find the smallest length where every short_id derived from `sessionIds`\n * is unique. Starts at {@link SHORT_ID_BASE_LEN} and grows by 2 chars at a\n * time (mirroring git's automatic abbreviation behaviour). Caps at the full\n * ULID body length so a pathological collision still terminates.\n */\nfunction computeUniquePrefixLen(sessionIds: readonly string[]): number {\n if (sessionIds.length <= 1) return SHORT_ID_BASE_LEN;\n for (let len = SHORT_ID_BASE_LEN; len <= SHORT_ID_MAX_LEN; len += 2) {\n const seen = new Set<string>();\n let collided = false;\n for (const sid of sessionIds) {\n const key = sliceShort(sid, len);\n if (seen.has(key)) {\n collided = true;\n break;\n }\n seen.add(key);\n }\n if (!collided) return len;\n }\n return SHORT_ID_MAX_LEN;\n}\n\nfunction pad(value: string, width: number): string {\n return value.length >= width ? value : value + \" \".repeat(width - value.length);\n}\n\nfunction maxLen(values: readonly string[], floor: number): number {\n let max = floor;\n for (const v of values) if (v.length > max) max = v.length;\n return max;\n}\n\nasync function resolveRepositoryRootForSession(\n cwd: string,\n subcmd: \"list\" | \"show\" | \"import\" | \"note\",\n): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\n `Not a git repository. Run 'git init' first, then re-run 'basou session ${subcmd}'.`,\n { cause: error },\n );\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n\nfunction parsePositiveInt(raw: string): number {\n const n = Number.parseInt(raw, 10);\n if (!Number.isInteger(n) || n < 1 || raw.trim() !== String(n)) {\n throw new Error(`Invalid number: ${raw}`);\n }\n return n;\n}\n\nfunction parseSessionStatus(raw: string): SessionStatus {\n const result = SessionStatusSchema.safeParse(raw);\n if (!result.success) {\n throw new Error(`Invalid session status: ${raw}. Valid values: ${STATUS_VALUES.join(\", \")}`);\n }\n return result.data;\n}\n\nfunction printNoSessions(options: SessionListOptions): void {\n if (options.json === true) {\n console.log(\"[]\");\n } else {\n console.log(\"No sessions found.\");\n }\n}\n\n// ----------------------------------------------------------------------------\n// session import\n// ----------------------------------------------------------------------------\n\nexport type SessionImportOptions = {\n format: \"json\";\n from: string;\n label?: string;\n task?: string;\n dryRun?: boolean;\n json?: boolean;\n verbose?: boolean;\n};\n\n/**\n * Programmatic entry for `basou session import`. Mirrors the wrapper /\n * pure-runner split used by list / show so tests can target either layer.\n */\nexport async function runSessionImport(\n options: SessionImportOptions,\n ctx: SessionContext = {},\n): Promise<void> {\n try {\n await doRunSessionImport(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunSessionImport(\n options: SessionImportOptions,\n ctx: SessionContext,\n): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForSession(cwd, \"import\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const manifest = await readManifest(paths);\n\n const rawBody = await readInputFile(options.from);\n const json = parseJsonStrict(rawBody);\n\n const parsed = SessionImportPayloadSchema.safeParse(json);\n if (!parsed.success) {\n throw new Error(\"Invalid import payload\", { cause: parsed.error });\n }\n\n if (parsed.data.schema_version !== \"0.1.0\") {\n throw new Error(`Unsupported import schema_version: ${parsed.data.schema_version}`);\n }\n\n const importOptions: ImportSessionOptions = { dryRun: options.dryRun === true };\n if (options.label !== undefined) importOptions.labelOverride = options.label;\n if (options.task !== undefined) {\n importOptions.taskIdOverride = await resolveTaskId(paths, options.task);\n }\n\n const result = await importSessionFromJson(paths, manifest, parsed.data, importOptions);\n\n // Path sanitize visibility: the importer rewrites absolute / homedir\n // prefixes inside related_files[] and working_directory so the operator-\n // private layout does not leak into local state. Surface a single-line\n // warning when anything was actually rewritten — silence on zero so the\n // happy path stays quiet. The warning fires for dry-run too so the\n // operator can preview the rewrite before committing.\n const sanitizeReport = result.pathSanitizeReport;\n if (sanitizeReport.relatedFiles > 0 || sanitizeReport.workingDirectoryRewritten) {\n const wdCount = sanitizeReport.workingDirectoryRewritten ? 1 : 0;\n console.error(\n `Imported session: ${sanitizeReport.relatedFiles + wdCount} path(s) sanitized (related_files: ${sanitizeReport.relatedFiles}, working_directory: ${wdCount})`,\n );\n }\n\n printSessionImportResult(options, result);\n}\n\nasync function readInputFile(path: string): Promise<string> {\n try {\n return await readFile(path, \"utf8\");\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Import source not found\", { cause: error });\n }\n if (findErrorCode(error, \"EISDIR\")) {\n throw new Error(\"Import source is not a file\", { cause: error });\n }\n throw new Error(\"Failed to read import source\", { cause: error });\n }\n}\n\nfunction parseJsonStrict(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch (error: unknown) {\n throw new Error(\"Failed to parse import JSON\", { cause: error });\n }\n}\n\nfunction parseImportFormat(raw: string): \"json\" {\n if (raw !== \"json\") {\n throw new InvalidArgumentError(`Unsupported format: ${raw}. Valid values: json`);\n }\n return \"json\";\n}\n\nfunction parseLabelOverride(raw: string): string {\n if (raw.length === 0) {\n throw new InvalidArgumentError(\"Label must not be empty\");\n }\n return raw;\n}\n\nfunction parseTaskIdOverride(raw: string): string {\n if (raw.length === 0) {\n throw new InvalidArgumentError(\"Task id is empty\");\n }\n return raw;\n}\n\nfunction printSessionImportResult(\n options: SessionImportOptions,\n result: ImportSessionResult,\n): void {\n const isDry = options.dryRun === true;\n const sid = shortId(result.sessionId);\n if (options.json === true) {\n console.log(\n JSON.stringify({\n session_id: result.sessionId,\n event_count: result.eventCount,\n dry_run: isDry,\n source: { kind: result.finalSourceKind, version: \"0.1.0\" },\n status: result.finalStatus,\n }),\n );\n return;\n }\n\n if (isDry) {\n console.log(\n `Dry run: would import ${result.eventCount} events into ${sid} (illustrative ID; not reserved, no files written)`,\n );\n return;\n }\n\n console.log(\n `Imported session ${sid} (${result.eventCount} events) from ${basename(options.from)}`,\n );\n}\n\n// ----------------------------------------------------------------------------\n// session note\n// ----------------------------------------------------------------------------\n\nconst NOTE_BODY_PREVIEW_LIMIT = 80;\nconst NOTE_BODY_PREVIEW_HEAD = 77;\n\nexport type SessionNoteOptions = {\n body?: string;\n fromFile?: string;\n json?: boolean;\n verbose?: boolean;\n};\n\n/**\n * Programmatic entry for `basou session note <session_id>`. Appends a single\n * `note_added` event to an existing attachable session. `session.yaml` is\n * deliberately NOT modified.\n */\nexport async function runSessionNote(\n sessionIdInput: string,\n options: SessionNoteOptions,\n ctx: SessionContext = {},\n): Promise<void> {\n try {\n await doRunSessionNote(sessionIdInput, options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunSessionNote(\n sessionIdInput: string,\n options: SessionNoteOptions,\n ctx: SessionContext,\n): Promise<void> {\n const hasBody = options.body !== undefined;\n const hasFromFile = options.fromFile !== undefined;\n if (!hasBody && !hasFromFile) {\n throw new Error(\"Provide --body or --from-file\");\n }\n if (hasBody && hasFromFile) {\n throw new Error(\"--body and --from-file are mutually exclusive\");\n }\n // The stdin pipe path is not supported in v0.1. Surface a dedicated\n // pathless error before any disk I/O so the failure mode is obvious.\n if (hasFromFile && options.fromFile === \"-\") {\n throw new Error(\"--from-file - (stdin) is not supported in v0.1\");\n }\n\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForSession(cwd, \"note\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const sessionId = await resolveSessionId(paths, sessionIdInput);\n\n const body = hasBody ? (options.body as string) : await readNoteFile(options.fromFile as string);\n if (body.length === 0) {\n throw new Error(\"Note body is empty\");\n }\n\n const occurredAt = new Date().toISOString();\n const sesId = sessionId as `ses_${string}`;\n\n // Per-session lock guards the events.jsonl append + status read window\n // against a concurrent writer (decision record / task attach / another\n // session note on the same id). The lock is the caller's responsibility:\n // appendEventToExistingSession holds no lock so we can compose larger\n // critical sections (e.g. attach-flavoured task commands) under the same\n // lock without re-entrant deadlock.\n const sessionLock = await acquireLock(paths, \"session\", sesId);\n let result: Awaited<ReturnType<typeof appendEventToExistingSession>>;\n try {\n result = await appendEventToExistingSession({\n paths,\n sessionId: sesId,\n eventBuilder: (eventId) =>\n ({\n schema_version: \"0.1.0\",\n id: eventId,\n session_id: sesId,\n occurred_at: occurredAt,\n source: \"local-cli\",\n type: \"note_added\",\n body,\n }) as Event,\n });\n } finally {\n await sessionLock.release();\n }\n\n printSessionNoteResult(options, sessionId, result.eventId, result.sessionStatus, body);\n}\n\nasync function readNoteFile(path: string): Promise<string> {\n try {\n return await readFile(path, \"utf8\");\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Note source not found\", { cause: error });\n }\n if (findErrorCode(error, \"EISDIR\")) {\n throw new Error(\"Note source is not a file\", { cause: error });\n }\n throw new Error(\"Failed to read note source\", { cause: error });\n }\n}\n\nfunction parseNoteBodyOption(raw: string): string {\n if (raw.length === 0) {\n throw new InvalidArgumentError(\"--body must not be empty\");\n }\n return raw;\n}\n\nfunction printSessionNoteResult(\n options: SessionNoteOptions,\n sessionId: string,\n eventId: string,\n sessionStatus: SessionStatus,\n body: string,\n): void {\n const sid = shortId(sessionId);\n if (options.json === true) {\n console.log(\n JSON.stringify({\n event_id: eventId,\n session_id: sessionId,\n session_status: sessionStatus,\n body_length: body.length,\n }),\n );\n return;\n }\n const preview =\n body.length > NOTE_BODY_PREVIEW_LIMIT ? `${body.slice(0, NOTE_BODY_PREVIEW_HEAD)}...` : body;\n console.log(`Added note to session ${sid} (${sessionStatus}): ${preview}`);\n}\n","/**\n * Coarse human duration from milliseconds: \"3h 05m\" / \"12m 30s\" / \"8s\".\n * Shared by the work-stats surfaces (`basou stats`, `basou session show`) so\n * they format identically.\n */\nexport function formatDurationMs(ms: number): string {\n const totalSeconds = Math.round(ms / 1000);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n if (hours > 0) return `${hours}h ${String(minutes).padStart(2, \"0\")}m`;\n if (minutes > 0) return `${minutes}m ${String(seconds).padStart(2, \"0\")}s`;\n return `${seconds}s`;\n}\n","import {\n assertBasouRootSafe,\n basouPaths,\n computeWorkStats,\n findErrorCode,\n resolveRepositoryRoot,\n type SourceWorkStats,\n type WorkStatsResult,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport {\n isVerbose,\n printReplayWarning,\n printSessionSkip,\n renderCliError,\n} from \"../lib/error-render.js\";\nimport { formatDurationMs } from \"../lib/format-duration.js\";\n\nexport type StatsOptions = {\n json?: boolean;\n bySource?: boolean;\n byDay?: boolean;\n verbose?: boolean;\n};\n\nexport type StatsContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n /** Defaults to `() => new Date()`. Injectable for tests. */\n nowProvider?: () => Date;\n};\n\n/**\n * Register `basou stats`: an honest \"how much did the AI work\" report. It\n * leads with output VOLUME (tokens + action counts), which is the most direct\n * signal, and reports TIME measures as labeled proxies.\n */\nexport function registerStatsCommand(program: Command): void {\n program\n .command(\"stats\")\n .description(\"Report how much the AI worked (output volume + time proxies) across sessions\")\n .option(\"--by-source\", \"Break the totals down by session source kind\")\n .option(\"--by-day\", \"Break billable time and volume down by calendar day\")\n .option(\"--json\", \"Output the full stats as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: StatsOptions) => {\n await runStats(options);\n });\n}\n\n/** Programmatic entry that owns `process.exitCode`. Tests prefer {@link doRunStats}. */\nexport async function runStats(options: StatsOptions, ctx: StatsContext = {}): Promise<void> {\n try {\n await doRunStats(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/** Pure runner: resolve the workspace, aggregate, and print (text or JSON). */\nexport async function doRunStats(options: StatsOptions, ctx: StatsContext): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForStats(cwd);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const now = ctx.nowProvider?.() ?? new Date();\n const result = await computeWorkStats({\n paths,\n now,\n onWarning: (w, sid) => printReplayWarning(w, sid),\n onSessionSkip: (sid, reason) => printSessionSkip(sid, reason),\n });\n\n if (options.json === true) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n printStatsText(result, options.bySource === true, options.byDay === true);\n}\n\nfunction printStatsText(result: WorkStatsResult, bySource: boolean, byDay: boolean): void {\n const t = result.totals;\n const statusPart =\n result.byStatus.length > 0\n ? ` (${result.byStatus.map((s) => `${s.status} ${s.count}`).join(\", \")})`\n : \"\";\n console.log(`Sessions: ${t.sessionCount}${statusPart}`);\n\n console.log(\"\");\n console.log(\"Volume (what the AI produced):\");\n const tokenSessions = result.sessions.filter((s) => s.availability.tokens).length;\n const tokenCaveat =\n t.tokensAvailable && tokenSessions < t.sessionCount\n ? ` (token data on ${tokenSessions} of ${t.sessionCount} sessions)`\n : t.tokensAvailable\n ? \"\"\n : \" (no token data captured; re-import to backfill)\";\n console.log(` Output tokens: ${formatInt(t.tokens.output)}${tokenCaveat}`);\n if (t.tokens.reasoning > 0) {\n console.log(` Reasoning tokens: ${formatInt(t.tokens.reasoning)} (Codex)`);\n }\n console.log(\n ` Actions: ${t.commandCount} commands, ${t.fileChangedCount} files, ${t.decisionCount} decisions`,\n );\n\n console.log(\"\");\n console.log(\"Time (proxies for human harness labor; active = billing primary):\");\n const turnSessions = result.sessions.filter((s) => s.activeTimeBasis === \"engaged-turns\").length;\n const basisCaveat =\n turnSessions === t.sessionCount\n ? \"engaged turns\"\n : turnSessions === 0\n ? \"event stream; re-import to capture conversation\"\n : `engaged turns on ${turnSessions} of ${t.sessionCount} sessions, event stream on the rest`;\n console.log(\n ` Billable active: ${formatDurationMs(t.billableActiveTimeMs)} (union; ${basisCaveat}; idle gaps > 5m excluded; tz ${result.timeZone})`,\n );\n if (t.activeTimeMs !== t.billableActiveTimeMs) {\n console.log(\n ` Summed: ${formatDurationMs(t.activeTimeMs)} (per-session sum; concurrent sessions double-counted)`,\n );\n }\n if (t.machineActiveAvailable) {\n const machineSessions = result.sessions.filter((s) => s.availability.machineActive).length;\n console.log(\n ` Model working: ${formatDurationMs(t.machineActiveTimeMs)} (model compute, subset of active; Codex turn duration on ${machineSessions} of ${t.sessionCount} sessions; summed, not wall-clock-deduped)`,\n );\n }\n const openPart = t.openSessionCount > 0 ? `; ${t.openSessionCount} open counted to now` : \"\";\n console.log(\n ` Span: ${formatDurationMs(t.sessionSpanMs)} (total elapsed${openPart})`,\n );\n const cmdCaveat = t.commandTimeReliable\n ? \"\"\n : \"; some sessions (e.g. claude-code-import) report 0 shell time\";\n console.log(\n ` Command: ${formatDurationMs(t.commandTimeMs)} (real shell execution${cmdCaveat})`,\n );\n\n if (bySource && result.bySource.length > 0) {\n console.log(\"\");\n console.log(\"By source:\");\n for (const s of result.bySource) {\n console.log(` ${s.sourceKind}: ${describeSource(s)}`);\n }\n }\n\n if (byDay && result.byDay.length > 0) {\n console.log(\"\");\n console.log(\"By day (billable time x volume):\");\n for (const d of result.byDay) {\n const machine =\n d.machineActiveTimeMs > 0 ? ` (model ${formatDurationMs(d.machineActiveTimeMs)})` : \"\";\n console.log(\n ` ${d.date}: ${formatDurationMs(d.billableActiveTimeMs)} active${machine}, ${formatInt(d.tokens.output)} out tok, ${d.commandCount} cmd / ${d.fileChangedCount} files / ${d.decisionCount} dec`,\n );\n }\n }\n}\n\nfunction describeSource(s: SourceWorkStats): string {\n const cmd = s.commandTimeReliable ? formatDurationMs(s.commandTimeMs) : \"n/a\";\n const tokens = s.tokensAvailable ? `${formatInt(s.tokens.output)} out tok` : \"no tokens\";\n const machine = s.machineActiveAvailable\n ? `, model ${formatDurationMs(s.machineActiveTimeMs)}`\n : \"\";\n return `${s.sessionCount} sessions, ${tokens}, active ${formatDurationMs(s.activeTimeMs)}${machine}, command ${cmd}`;\n}\n\n/** \"1,234,567\" — thousands-separated, fixed en-US so output is deterministic. */\nfunction formatInt(n: number): string {\n return n.toLocaleString(\"en-US\");\n}\n\nasync function resolveRepositoryRootForStats(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\"Not a git repository. Run 'git init' first, then re-run 'basou stats'.\", {\n cause: error,\n });\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n","import {\n assertBasouRootSafe,\n basouPaths,\n buildStatusSnapshot,\n findErrorCode,\n type Manifest,\n readManifest,\n resolveRepositoryRoot,\n type StatusSnapshot,\n writeStatus,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport { isVerbose, renderCliError } from \"../lib/error-render.js\";\n\nexport type StatusOptions = {\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type StatusContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n};\n\n/**\n * Register `basou status` on a commander program. The command outputs a\n * human-readable summary by default, or a JSON document when `--json` is\n * given. In both modes `.basou/status.json` is rewritten as a side effect.\n */\nexport function registerStatusCommand(program: Command): void {\n program\n .command(\"status\")\n .description(\"Show the current Basou workspace status\")\n .option(\"--json\", \"Output the snapshot as JSON to stdout\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: StatusOptions) => {\n await runStatus(options);\n });\n}\n\n/**\n * Programmatic entry that mutates process state (`exitCode`, stderr).\n * Exported for tests, but tests should prefer {@link doRunStatus} when they\n * only need to assert on success behaviour or thrown errors.\n */\nexport async function runStatus(options: StatusOptions, ctx: StatusContext = {}): Promise<void> {\n try {\n await doRunStatus(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * Pure runner: resolves inputs, performs the status snapshot, writes\n * `status.json`, and prints output. On any failure throws an Error whose\n * `message` is pathless; native fs / parse errors are attached as `cause`.\n * Exported for tests so they can assert on thrown errors without touching\n * `process.exitCode`.\n */\nexport async function doRunStatus(options: StatusOptions, ctx: StatusContext): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForStatus(cwd);\n const paths = basouPaths(repositoryRoot);\n\n // Pre-condition: refuse to operate on a swapped/non-directory .basou root\n // before we ever touch a file. Treat ENOENT (root absent) the same way as\n // a missing manifest below — both mean \"workspace not initialized\".\n try {\n await assertBasouRootSafe(paths.root);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n\n let manifest: Manifest;\n try {\n manifest = await readManifest(paths);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n // ZodError's `message` echoes invalid input values verbatim, which can\n // include path-like strings if a user-edited manifest contains them.\n // Wrap in a fixed pathless message and surface only the cause's\n // constructor name in verbose mode via the shared renderCliError helper.\n throw new Error(\"Failed to read workspace manifest\", { cause: error });\n }\n\n const snapshot = await buildStatusSnapshot({ manifest, paths });\n await writeStatus(paths, snapshot);\n\n if (options.json === true) {\n console.log(JSON.stringify(snapshot, null, 2));\n } else {\n renderTextStatus(snapshot);\n }\n}\n\nfunction renderTextStatus(s: StatusSnapshot): void {\n console.log(`Workspace: ${s.workspace.name} (${s.workspace.id})`);\n // The label changed from \"Basou version\" to \"Spec version\" in v0.3.1\n // because the field tracks the workspace data-format spec\n // (`basou_version` literal-locked to \"0.1.0\") and was repeatedly\n // mistaken for the release version returned by `basou --version`. The\n // wire payload field name (= `workspace.basou_version`) stays the same\n // so JSON consumers are unaffected; only the human-readable label\n // moves.\n console.log(`Spec version: ${s.workspace.basou_version}`);\n console.log(`Generated at: ${s.generated_at}`);\n const dp = s.directories_present;\n const total = Object.keys(dp).length;\n const present = Object.values(dp).filter((v) => v === true).length;\n console.log(`Subdirectories present: ${present}/${total}`);\n}\n\n/**\n * Wrap the core git capability so the CLI surfaces the command-specific\n * \"Run 'git init' first, then re-run 'basou status'.\" suffix while the\n * capability layer remains command-agnostic.\n */\nasync function resolveRepositoryRootForStatus(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\"Not a git repository. Run 'git init' first, then re-run 'basou status'.\", {\n cause: error,\n });\n }\n throw error;\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport {\n archiveTask,\n assertBasouRootSafe,\n basouPaths,\n createTaskWithEvent,\n deleteTask,\n type Event,\n editTask,\n enumerateArchivedTaskIds,\n findErrorCode,\n loadSessionEntries,\n loadTaskEntries,\n type PrefixedId,\n prefixedUlid,\n type ReconcileFailure,\n type ReconcileResult,\n type RefreshLinkageResult,\n readManifest,\n readTaskFile,\n readTaskFileWithArchiveFallback,\n reconcileAllTasks,\n reconcileTask,\n refreshTaskLinkedSessions,\n replayEvents,\n resolveRepositoryRoot,\n resolveSessionId,\n resolveTaskId,\n type SessionEntry,\n type SessionStatus,\n type TaskDocument,\n type TaskReconciledEvent,\n type TaskStatus,\n TaskStatusSchema,\n TaskWriteAfterEventError,\n updateTaskStatusWithEvent,\n} from \"@basou/core\";\nimport { type Command, InvalidArgumentError } from \"commander\";\nimport {\n type ErrorClassifier,\n failedToFinalizeClassifier,\n isVerbose,\n printReplayWarning,\n printTaskSkip,\n renderCliError,\n shortSessionId,\n shortTaskId,\n} from \"../lib/error-render.js\";\n\nconst STATUS_VALUES = TaskStatusSchema.options;\n\n// ============================================================================\n// Public registration\n// ============================================================================\n\nexport type TaskNewOptions = {\n title: string;\n label?: string;\n status?: TaskStatus;\n /**\n * ISO-8601 timestamp written into `task.md.updated_at` when status is a\n * terminal value (done / cancelled). Lets the operator backdate a\n * retroactively-recorded completed task so `task.md` reflects the\n * actual completion moment while `events.jsonl` keeps recording time.\n * Rejected (exit 1) when supplied with a non-terminal status.\n */\n completedAt?: string;\n session?: string;\n description?: string;\n fromFile?: string;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type TaskListOptions = {\n status?: TaskStatus;\n includeArchived?: boolean;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type TaskShowOptions = {\n json?: boolean;\n events?: boolean;\n last?: number;\n verbose?: boolean;\n};\n\nexport type TaskStatusOptions = {\n session?: string;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type TaskReconcileOptions = {\n task?: string;\n write?: boolean;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type TaskRefreshLinkageOptions = {\n write?: boolean;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type TaskEditOptions = {\n title?: string;\n status?: TaskStatus;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type TaskDeleteOptions = {\n yes?: boolean;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type TaskArchiveOptions = {\n yes?: boolean;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type TaskContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n /** Defaults to `() => new Date()`. Injectable for tests. */\n nowProvider?: () => Date;\n};\n\nexport function registerTaskCommand(program: Command): void {\n const task = program\n .command(\"task\")\n .description(\"Manage Basou tasks (purpose units that span sessions)\");\n\n task\n .command(\"new\")\n .description(\"Create a new task and fire a task_created event\")\n .requiredOption(\"--title <text>\", \"Task title\", parseTitle)\n .option(\"--label <text>\", \"Optional label for the task\", parseLabel)\n .option(\n \"--status <status>\",\n `Initial status (one of: ${STATUS_VALUES.join(\", \")}; default planned). For done/cancelled the orchestrator also emits a task_status_changed event so the audit trail records the implicit transition.`,\n parseInitialTaskStatus,\n )\n .option(\n \"--completed-at <iso>\",\n \"ISO-8601 timestamp to record as the task's updated_at when --status is done or cancelled (rejected otherwise)\",\n parseIsoTimestampOption,\n )\n .option(\"--session <session_id>\", \"Attach to existing session; otherwise ad-hoc\")\n .option(\"--description <text>\", \"Task description body (inline)\", parseDescriptionOption)\n .option(\"--from-file <path>\", \"Read description body from a file\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: TaskNewOptions) => {\n await runTaskNew(options);\n });\n\n task\n .command(\"list\")\n .description(\"List tasks in the current workspace (newest first)\")\n .option(\n \"--status <status>\",\n `Filter by task status (one of: ${STATUS_VALUES.join(\", \")})`,\n parseTaskStatusFilter,\n )\n .option(\"--include-archived\", \"Also list tasks under .basou/tasks/archive/ (hidden by default)\")\n .option(\"--json\", \"Output the list as a JSON array\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: TaskListOptions) => {\n await runTaskList(options);\n });\n\n task\n .command(\"show <task_id>\")\n .description(\"Show a task with its metadata, linked sessions, and events\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--events\", \"Show all related events instead of trailing few\")\n .option(\"--last <n>\", \"Number of trailing events to display (default: 5)\", parsePositiveInt)\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (id: string, options: TaskShowOptions) => {\n await runTaskShow(id, options);\n });\n\n task\n .command(\"status <task_id> <new_status>\")\n .description(\"Change task status and fire a task_status_changed event\")\n .option(\"--session <session_id>\", \"Attach to existing session; otherwise ad-hoc\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (taskIdInput: string, newStatusInput: string, options: TaskStatusOptions) => {\n await runTaskStatus(taskIdInput, newStatusInput, options);\n });\n\n task\n .command(\"reconcile\")\n .description(\n \"Dry-run audit of task session references; use --write to repair broken refs. Forward sync (events -> task.md linked_sessions) is out of scope.\",\n )\n .option(\"--task <task_id>\", \"Limit to a single task (otherwise scan all)\")\n .option(\"--write\", \"Apply repairs (default: dry-run)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"-v, --verbose\", \"Show error causes and broken session_id values\")\n .action(async (options: TaskReconcileOptions) => {\n await runTaskReconcile(options);\n });\n\n task\n .command(\"refresh-linkage <task_id>\")\n .description(\n \"Re-derive task.md linked_sessions[] from session.yaml.task_id matches across the workspace (forward sync events -> task.md). Dry-run default; use --write to apply.\",\n )\n .option(\"--write\", \"Apply the refresh (default: dry-run)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (taskIdInput: string, options: TaskRefreshLinkageOptions) => {\n await runTaskRefreshLinkage(taskIdInput, options);\n });\n\n task\n .command(\"edit <task_id>\")\n .description(\n \"Update --title and/or --status on an existing task. Status changes fire a task_status_changed event; title changes update task.md only (no event).\",\n )\n .option(\"--title <text>\", \"New title (must be non-empty)\", parseTitle)\n .option(\n \"--status <status>\",\n `New status (one of: ${STATUS_VALUES.join(\", \")}); routed through STATUS_TRANSITIONS so only valid edges are accepted`,\n parseInitialTaskStatus,\n )\n .option(\"--json\", \"Output as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (taskIdInput: string, options: TaskEditOptions) => {\n await runTaskEdit(taskIdInput, options);\n });\n\n task\n .command(\"delete <task_id>\")\n .description(\n \"Hard-delete a task.md file and fire a task_deleted event. Requires confirmation by default; use --yes to skip the prompt.\",\n )\n .option(\"--yes\", \"Skip the confirmation prompt (required when stdin is not a TTY)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (taskIdInput: string, options: TaskDeleteOptions) => {\n await runTaskDelete(taskIdInput, options);\n });\n\n task\n .command(\"archive <task_id>\")\n .description(\n \"Move task.md into .basou/tasks/archive/ and fire a task_archived event. Requires confirmation by default; use --yes to skip the prompt.\",\n )\n .option(\"--yes\", \"Skip the confirmation prompt (required when stdin is not a TTY)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (taskIdInput: string, options: TaskArchiveOptions) => {\n await runTaskArchive(taskIdInput, options);\n });\n}\n\n// ============================================================================\n// task new\n// ============================================================================\n\nexport async function runTaskNew(options: TaskNewOptions, ctx: TaskContext = {}): Promise<void> {\n try {\n await doRunTaskNew(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options), classifiers: TASK_CLASSIFIERS });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunTaskNew(options: TaskNewOptions, ctx: TaskContext): Promise<void> {\n if (options.description !== undefined && options.fromFile !== undefined) {\n throw new Error(\"--description and --from-file are mutually exclusive\");\n }\n if (options.fromFile === \"-\") {\n throw new Error(\"--from-file - (stdin) is not supported in v0.1\");\n }\n\n const initialStatus = options.status ?? \"planned\";\n // `--completed-at` only makes sense paired with a terminal status. Catching\n // the mismatch up front avoids ambiguity about whether the override would\n // still be honored on a planned/in_progress task (= it wouldn't).\n if (options.completedAt !== undefined && !isTerminalStatusForCli(initialStatus)) {\n throw new Error(\"--completed-at requires --status done or cancelled\");\n }\n\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForTask(cwd, \"new\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const description =\n options.description !== undefined\n ? options.description\n : options.fromFile !== undefined\n ? await readDescriptionFile(options.fromFile)\n : \"\";\n\n const now = ctx.nowProvider !== undefined ? ctx.nowProvider() : new Date();\n const occurredAt = now.toISOString();\n const taskId = prefixedUlid(\"task\");\n\n if (options.session !== undefined) {\n const sessionId = (await resolveSessionId(paths, options.session)) as PrefixedId<\"ses\">;\n const result = await createTaskWithEvent({\n mode: \"attach\",\n paths,\n occurredAt,\n sessionId,\n taskId,\n title: options.title,\n ...(options.label !== undefined ? { label: options.label } : {}),\n initialStatus,\n description,\n ...(options.completedAt !== undefined ? { completedAt: options.completedAt } : {}),\n });\n printTaskNewResult(options, {\n mode: \"attached\",\n taskId: result.taskId,\n eventId: result.eventId,\n sessionId: result.sessionId,\n sessionStatus: result.sessionStatus,\n title: options.title,\n ...(options.label !== undefined ? { label: options.label } : {}),\n status: initialStatus,\n occurredAt,\n ...(options.completedAt !== undefined ? { completedAt: options.completedAt } : {}),\n descriptionLength: description.length,\n });\n return;\n }\n\n const manifest = await readManifest(paths);\n const result = await createTaskWithEvent({\n mode: \"ad-hoc\",\n paths,\n manifest,\n occurredAt,\n taskId,\n title: options.title,\n ...(options.label !== undefined ? { label: options.label } : {}),\n initialStatus,\n description,\n workingDirectory: repositoryRoot,\n ...(options.completedAt !== undefined ? { completedAt: options.completedAt } : {}),\n });\n printTaskNewResult(options, {\n mode: \"ad-hoc\",\n taskId: result.taskId,\n eventId: result.eventId,\n sessionId: result.sessionId,\n sessionStatus: result.sessionStatus,\n title: options.title,\n ...(options.label !== undefined ? { label: options.label } : {}),\n status: initialStatus,\n occurredAt,\n ...(options.completedAt !== undefined ? { completedAt: options.completedAt } : {}),\n descriptionLength: description.length,\n });\n}\n\nfunction isTerminalStatusForCli(status: TaskStatus): boolean {\n return status === \"done\" || status === \"cancelled\";\n}\n\ntype TaskNewPrint = {\n mode: \"ad-hoc\" | \"attached\";\n taskId: string;\n eventId: string;\n sessionId: string;\n sessionStatus: SessionStatus;\n title: string;\n label?: string;\n status: TaskStatus;\n occurredAt: string;\n completedAt?: string;\n descriptionLength: number;\n};\n\nfunction printTaskNewResult(options: TaskNewOptions, result: TaskNewPrint): void {\n if (options.json === true) {\n console.log(\n JSON.stringify({\n task_id: result.taskId,\n event_id: result.eventId,\n session_id: result.sessionId,\n session_status: result.sessionStatus,\n mode: result.mode,\n title: result.title,\n label: result.label ?? null,\n status: result.status,\n recorded_at: result.occurredAt,\n completed_at: result.completedAt ?? null,\n description_length: result.descriptionLength,\n }),\n );\n return;\n }\n const shortSes = shortSessionId(result.sessionId);\n const created =\n result.mode === \"ad-hoc\"\n ? `Created ${result.taskId} in ad-hoc session ${shortSes}`\n : `Created ${result.taskId} in session ${shortSes} (${result.sessionStatus})`;\n console.log(created);\n console.log(` Title: ${result.title}`);\n // For terminal initial statuses surface both the recording time (= the\n // ad-hoc session timestamp = now) and the supplied completion time so the\n // operator can tell at a glance that the audit trail (events.jsonl)\n // reflects the former while task.md.updated_at reflects the latter.\n if (result.completedAt !== undefined) {\n console.log(\n ` Status: ${result.status} (recorded at ${result.occurredAt}, completed at ${result.completedAt})`,\n );\n } else {\n console.log(` Status: ${result.status}`);\n }\n console.log(` Label: ${result.label ?? \"(none)\"}`);\n}\n\n// ============================================================================\n// task list\n// ============================================================================\n\nexport async function runTaskList(options: TaskListOptions, ctx: TaskContext = {}): Promise<void> {\n try {\n await doRunTaskList(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options), classifiers: TASK_CLASSIFIERS });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunTaskList(options: TaskListOptions, ctx: TaskContext): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForTask(cwd, \"list\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const entries = await loadTaskEntries(paths, {\n onSkip: (id, reason) => printTaskSkip(id, reason),\n });\n // Archive entries are read from `<paths.tasks>/archive/` directly (no\n // dedicated loader yet — call sites are rare). Marshalling them through a\n // separate scan keeps the default `task list` path fast (no extra readdir\n // when the operator does not opt in).\n const archivedEntries: { doc: TaskDocument; archived: true }[] = [];\n if (options.includeArchived === true) {\n const archivedIds = await enumerateArchivedTaskIds(paths);\n for (const id of archivedIds) {\n try {\n const { doc } = await readTaskFileWithArchiveFallback(paths, id);\n archivedEntries.push({ doc, archived: true });\n } catch {\n // Skip unreadable archive entries — keep the list output usable\n // when one file is corrupt rather than aborting the run.\n }\n }\n }\n const combined = [...entries, ...archivedEntries.map((a) => a.doc)];\n const archivedIdSet = new Set(archivedEntries.map((a) => a.doc.task.task.id));\n // loadTaskEntries returns asc by created_at; reverse for newest-first display.\n const ordered = [...combined].sort(\n (a, b) => Date.parse(b.task.task.created_at) - Date.parse(a.task.task.created_at),\n );\n const filtered =\n options.status !== undefined\n ? ordered.filter((t) => t.task.task.status === options.status)\n : ordered;\n\n if (filtered.length === 0) {\n if (options.json === true) {\n console.log(\"[]\");\n } else {\n console.log(\"No tasks found.\");\n }\n return;\n }\n\n if (options.json === true) {\n console.log(\n JSON.stringify(\n filtered.map((t) => ({\n task_id: t.task.task.id,\n title: t.task.task.title,\n label: t.task.task.label ?? null,\n status: t.task.task.status,\n created_at: t.task.task.created_at,\n updated_at: t.task.task.updated_at,\n linked_session_count: t.task.task.linked_sessions.length,\n archived: archivedIdSet.has(t.task.task.id),\n })),\n null,\n 2,\n ),\n );\n return;\n }\n printTaskListText(filtered, archivedIdSet);\n}\n\nfunction printTaskListText(\n entries: ReadonlyArray<TaskDocument>,\n archivedIds: ReadonlySet<string>,\n): void {\n const rows = entries.map((t) => ({\n sid: shortTaskId(t.task.task.id),\n status: t.task.task.status,\n createdAt: t.task.task.created_at,\n label: t.task.task.label ?? \"(none)\",\n // Mark archived entries with a leading [archived] tag so the operator\n // can distinguish them from live tasks when --include-archived is on.\n title: archivedIds.has(t.task.task.id) ? `[archived] ${t.task.task.title}` : t.task.task.title,\n linkedCount: String(t.task.task.linked_sessions.length),\n }));\n const widths = {\n sid: maxLen(\n rows.map((r) => r.sid),\n \"SHORT_ID\".length,\n ),\n status: maxLen(\n rows.map((r) => r.status),\n \"STATUS\".length,\n ),\n createdAt: maxLen(\n rows.map((r) => r.createdAt),\n \"CREATED_AT\".length,\n ),\n linkedCount: maxLen(\n rows.map((r) => r.linkedCount),\n \"LINKS\".length,\n ),\n label: maxLen(\n rows.map((r) => r.label),\n \"LABEL\".length,\n ),\n };\n console.log(\n `${pad(\"SHORT_ID\", widths.sid)} ${pad(\"STATUS\", widths.status)} ${pad(\"CREATED_AT\", widths.createdAt)} ${pad(\"LINKS\", widths.linkedCount)} ${pad(\"LABEL\", widths.label)} TITLE`,\n );\n for (const r of rows) {\n console.log(\n `${pad(r.sid, widths.sid)} ${pad(r.status, widths.status)} ${pad(r.createdAt, widths.createdAt)} ${pad(r.linkedCount, widths.linkedCount)} ${pad(r.label, widths.label)} ${r.title}`,\n );\n }\n}\n\n// ============================================================================\n// task show\n// ============================================================================\n\nexport async function runTaskShow(\n idInput: string,\n options: TaskShowOptions,\n ctx: TaskContext = {},\n): Promise<void> {\n try {\n await doRunTaskShow(idInput, options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options), classifiers: TASK_CLASSIFIERS });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunTaskShow(\n idInput: string,\n options: TaskShowOptions,\n ctx: TaskContext,\n): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForTask(cwd, \"show\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const taskId = await resolveTaskId(paths, idInput, { includeArchived: true });\n const { doc, archived } = await readTaskFileWithArchiveFallback(paths, taskId);\n\n // Collect events related to this task by replaying every session's\n // events.jsonl and filtering by task_id. Could be optimised via an\n // index.json cache later; v0.1 accepts the linear scan.\n const sessions = await loadSessionEntries(paths, { now: new Date() });\n const events: Event[] = [];\n const linkedSessionIds = new Set<string>(doc.task.task.linked_sessions);\n // Replay warnings (malformed JSON / schema violations / partial trailing\n // lines) and unreadable events.jsonl files must reach the operator so\n // silent gaps in the events history don't go unnoticed.\n for (const s of sessions) {\n const sessionDir = join(paths.sessions, s.sessionId);\n try {\n for await (const ev of replayEvents(sessionDir, {\n onWarning: (w) => printReplayWarning(w, s.sessionId),\n })) {\n if (\n (ev.type === \"task_created\" ||\n ev.type === \"task_status_changed\" ||\n ev.type === \"task_reconciled\" ||\n ev.type === \"task_linkage_refreshed\" ||\n ev.type === \"task_deleted\" ||\n ev.type === \"task_archived\") &&\n ev.task_id === taskId\n ) {\n events.push(ev);\n linkedSessionIds.add(s.sessionId);\n }\n }\n } catch (error: unknown) {\n // I/O failure (events.jsonl unreadable). The renderer still works on\n // task.md metadata alone, but the operator must know events from this\n // session are missing from the aggregate.\n const short = shortSessionId(s.sessionId);\n const suffix = error instanceof Error ? `: ${error.message}` : \"\";\n console.error(`Warning: events unavailable for session ${short}${suffix}`);\n }\n }\n events.sort((a, b) => Date.parse(a.occurred_at) - Date.parse(b.occurred_at));\n\n if (options.json === true) {\n console.log(\n JSON.stringify(\n {\n task: doc.task.task,\n body: doc.body,\n linked_sessions: [...linkedSessionIds],\n archived,\n events,\n },\n null,\n 2,\n ),\n );\n return;\n }\n\n printTaskShowText(doc, [...linkedSessionIds], events, sessions, options, archived);\n}\n\nfunction printTaskShowText(\n doc: TaskDocument,\n linkedSessions: string[],\n events: ReadonlyArray<Event>,\n sessionEntries: ReadonlyArray<SessionEntry>,\n options: TaskShowOptions,\n archived: boolean,\n): void {\n const t = doc.task.task;\n const archivedTag = archived ? \" [archived]\" : \"\";\n console.log(`Task: ${t.id}${archivedTag}`);\n console.log(` Title: ${t.title}`);\n console.log(` Status: ${t.status}`);\n console.log(` Label: ${t.label ?? \"(none)\"}`);\n console.log(` Created at: ${t.created_at}`);\n console.log(` Updated at: ${t.updated_at}`);\n console.log(` Workspace: ${t.workspace_id}`);\n console.log(\"\");\n console.log(`Linked sessions (${linkedSessions.length}):`);\n const sessionStatusMap = new Map<string, string>(\n sessionEntries.map((s) => [s.sessionId, s.session.session.status]),\n );\n for (const sid of linkedSessions) {\n const status = sessionStatusMap.get(sid) ?? \"unknown\";\n console.log(` ${sid} (${status})`);\n }\n console.log(\"\");\n console.log(\"Description:\");\n if (doc.body.length === 0) {\n console.log(\"(no description)\");\n } else {\n console.log(doc.body);\n }\n console.log(\"\");\n console.log(`Events: ${events.length} total`);\n if (events.length === 0) return;\n const showAll = options.events === true && options.last === undefined;\n const last = options.last ?? 5;\n const slice = showAll ? events : events.slice(-last);\n const heading = showAll ? \"All events:\" : `Last ${slice.length} events:`;\n console.log(\"\");\n console.log(heading);\n const verbose = isVerbose(options);\n for (const ev of slice) {\n console.log(` ${formatTaskEvent(ev)}`);\n if (verbose && ev.type === \"task_reconciled\") {\n for (const line of formatTaskReconciledDetails(ev)) {\n console.log(line);\n }\n }\n }\n}\n\nfunction formatTaskEvent(ev: Event): string {\n if (ev.type === \"task_created\") {\n return `${ev.occurred_at} [${ev.source}] task_created ${ev.title}`;\n }\n if (ev.type === \"task_status_changed\") {\n return `${ev.occurred_at} [${ev.source}] task_status_changed ${ev.from} -> ${ev.to}`;\n }\n if (ev.type === \"task_reconciled\") {\n const removedCount =\n (ev.removed_created_in_session !== null ? 1 : 0) + ev.removed_linked_sessions.length;\n return `${ev.occurred_at} [${ev.source}] task_reconciled ${removedCount} broken ref${removedCount === 1 ? \"\" : \"s\"} (use -v for details)`;\n }\n if (ev.type === \"task_linkage_refreshed\") {\n const added = ev.added_linked_sessions.length;\n const removed = ev.removed_linked_sessions.length;\n const finalPart = ev.final_count !== undefined ? `, final=${ev.final_count}` : \"\";\n return `${ev.occurred_at} [${ev.source}] task_linkage_refreshed +${added} / -${removed}${finalPart}`;\n }\n if (ev.type === \"task_deleted\") {\n return `${ev.occurred_at} [${ev.source}] task_deleted ${ev.title}`;\n }\n if (ev.type === \"task_archived\") {\n return `${ev.occurred_at} [${ev.source}] task_archived ${ev.title}`;\n }\n return `${ev.occurred_at} [${ev.source}] ${ev.type}`;\n}\n\nfunction formatTaskReconciledDetails(ev: TaskReconciledEvent): string[] {\n const lines: string[] = [];\n if (ev.removed_created_in_session !== null) {\n lines.push(` removed_created_in_session: ${ev.removed_created_in_session}`);\n }\n if (ev.created_in_session_replacement !== null) {\n lines.push(` created_in_session_replacement: ${ev.created_in_session_replacement}`);\n }\n if (ev.removed_linked_sessions.length > 0) {\n lines.push(\" removed_linked_sessions:\");\n for (const sid of ev.removed_linked_sessions) {\n lines.push(` - ${sid}`);\n }\n }\n return lines;\n}\n\n// ============================================================================\n// task status\n// ============================================================================\n\nexport async function runTaskStatus(\n taskIdInput: string,\n newStatusInput: string,\n options: TaskStatusOptions,\n ctx: TaskContext = {},\n): Promise<void> {\n try {\n await doRunTaskStatus(taskIdInput, newStatusInput, options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options), classifiers: TASK_CLASSIFIERS });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunTaskStatus(\n taskIdInput: string,\n newStatusInput: string,\n options: TaskStatusOptions,\n ctx: TaskContext,\n): Promise<void> {\n if (taskIdInput.trim().length === 0) {\n throw new Error(\"Task id is empty\");\n }\n const newStatus = parseTaskStatusPositional(newStatusInput);\n\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForTask(cwd, \"status\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const taskId = (await resolveTaskId(paths, taskIdInput)) as PrefixedId<\"task\">;\n const now = ctx.nowProvider !== undefined ? ctx.nowProvider() : new Date();\n const occurredAt = now.toISOString();\n\n if (options.session !== undefined) {\n const sessionId = (await resolveSessionId(paths, options.session)) as PrefixedId<\"ses\">;\n const result = await updateTaskStatusWithEvent({\n mode: \"attach\",\n paths,\n occurredAt,\n sessionId,\n taskId,\n newStatus,\n });\n printTaskStatusResult(options, {\n mode: \"attached\",\n taskId: result.taskId,\n eventId: result.eventId,\n sessionId: result.sessionId,\n sessionStatus: result.sessionStatus,\n previousStatus: result.previousStatus,\n newStatus: result.newStatus,\n });\n return;\n }\n\n const manifest = await readManifest(paths);\n const result = await updateTaskStatusWithEvent({\n mode: \"ad-hoc\",\n paths,\n manifest,\n occurredAt,\n taskId,\n newStatus,\n workingDirectory: repositoryRoot,\n });\n printTaskStatusResult(options, {\n mode: \"ad-hoc\",\n taskId: result.taskId,\n eventId: result.eventId,\n sessionId: result.sessionId,\n sessionStatus: result.sessionStatus,\n previousStatus: result.previousStatus,\n newStatus: result.newStatus,\n });\n}\n\ntype TaskStatusPrint = {\n mode: \"ad-hoc\" | \"attached\";\n taskId: string;\n eventId: string;\n sessionId: string;\n sessionStatus: SessionStatus;\n previousStatus: TaskStatus;\n newStatus: TaskStatus;\n};\n\nfunction printTaskStatusResult(options: TaskStatusOptions, result: TaskStatusPrint): void {\n if (options.json === true) {\n console.log(\n JSON.stringify({\n task_id: result.taskId,\n event_id: result.eventId,\n session_id: result.sessionId,\n session_status: result.sessionStatus,\n mode: result.mode,\n previous_status: result.previousStatus,\n new_status: result.newStatus,\n }),\n );\n return;\n }\n const sid = shortSessionId(result.sessionId);\n console.log(\n `Updated ${result.taskId} status: ${result.previousStatus} -> ${result.newStatus} (in session ${sid})`,\n );\n}\n\n// ============================================================================\n// task reconcile\n// ============================================================================\n\nexport async function runTaskReconcile(\n options: TaskReconcileOptions,\n ctx: TaskContext = {},\n): Promise<void> {\n try {\n await doRunTaskReconcile(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options), classifiers: TASK_CLASSIFIERS });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunTaskReconcile(\n options: TaskReconcileOptions,\n ctx: TaskContext,\n): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForTask(cwd, \"reconcile\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n const manifest = await readManifest(paths);\n const nowProvider = ctx.nowProvider ?? ((): Date => new Date());\n const write = options.write === true;\n const verbose = isVerbose(options);\n const json = options.json === true;\n\n if (options.task !== undefined) {\n const taskId = (await resolveTaskId(paths, options.task)) as PrefixedId<\"task\">;\n const result = await reconcileTask(paths, manifest, {\n taskId,\n occurredAt: nowProvider().toISOString(),\n workingDirectory: repositoryRoot,\n write,\n scope: \"single\",\n });\n if (json) {\n printReconcileJson({ dryRun: !write, scanned: 1, results: [result], failed: [] });\n } else {\n await printReconcileSingleText(result, paths, { write, verbose });\n }\n return;\n }\n\n const all = await reconcileAllTasks(paths, manifest, {\n occurredAt: () => nowProvider().toISOString(),\n workingDirectory: repositoryRoot,\n write,\n });\n if (json) {\n printReconcileJson({\n dryRun: !write,\n scanned: all.scanned,\n results: all.results,\n failed: all.failed,\n });\n } else {\n printReconcileAllText(all.results, all.failed, all.scanned, { write, verbose });\n }\n if (all.failed.length > 0) {\n process.exitCode = 1;\n }\n}\n\nfunction printReconcileJson(input: {\n dryRun: boolean;\n scanned: number;\n results: ReadonlyArray<ReconcileResult>;\n failed: ReadonlyArray<ReconcileFailure>;\n}): void {\n console.log(\n JSON.stringify(\n {\n dry_run: input.dryRun,\n scanned: input.scanned,\n reconciled: input.results.map((r) => ({\n task_id: r.taskId,\n removed_created_in_session: r.brokenCreatedInSession,\n created_in_session_replacement:\n r.brokenCreatedInSession !== null && r.reconcileSession !== null\n ? r.reconcileSession.sessionId\n : null,\n removed_linked_sessions: r.brokenLinkedSessions,\n reconcile_session_id: r.reconcileSession?.sessionId ?? null,\n event_id: r.reconcileSession?.eventId ?? null,\n })),\n failed: input.failed.map((f) => ({\n task_id: f.taskId,\n error_class: f.errorClass,\n phase: f.phase,\n })),\n },\n null,\n 2,\n ),\n );\n}\n\nasync function printReconcileSingleText(\n result: ReconcileResult,\n paths: ReturnType<typeof basouPaths>,\n options: { write: boolean; verbose: boolean },\n): Promise<void> {\n if (result.clean) {\n // For the --task path with no broken refs we report counts of reachable\n // references so the operator gets a positive audit confirmation rather\n // than a bare \"ok\". Re-read task.md cheaply; the core API already did\n // the integrity work so this is just for the display string.\n let createdCount = 0;\n let linkedCount = 0;\n try {\n const doc = await readTaskFile(paths, result.taskId);\n createdCount = 1;\n linkedCount = doc.task.task.linked_sessions.length;\n } catch {\n // If the file became unreadable between reconcileTask and here just\n // fall back to a less detailed message rather than crashing the run.\n }\n console.log(\n `${result.taskId}: no broken refs (${createdCount} created_in_session + ${linkedCount} linked_sessions, all reachable).`,\n );\n return;\n }\n if (options.write) {\n const sessionPart =\n result.reconcileSession !== null\n ? ` (in session ${shortSessionId(result.reconcileSession.sessionId)})`\n : \"\";\n console.log(`Reconciled ${result.taskId}: ${describeReconcileSummary(result)}${sessionPart}.`);\n return;\n }\n const summary = describeBrokenSummary(result, \"task\", options.verbose);\n console.log(`(dry-run) Would reconcile ${result.taskId}: ${summary}`);\n console.log(\"Note: events -> task.md forward sync is handled by `basou task refresh-linkage`.\");\n console.log(\"Re-run with --write to apply.\");\n}\n\nfunction printReconcileAllText(\n results: ReadonlyArray<ReconcileResult>,\n failed: ReadonlyArray<ReconcileFailure>,\n scanned: number,\n options: { write: boolean; verbose: boolean },\n): void {\n if (results.length === 0 && failed.length === 0) {\n console.log(`Scanned ${scanned} tasks, no broken refs detected.`);\n return;\n }\n\n let totalBrokenRefs = 0;\n for (const r of results) {\n totalBrokenRefs += r.brokenLinkedSessions.length + (r.brokenCreatedInSession !== null ? 1 : 0);\n }\n\n if (options.write) {\n for (const r of results) {\n const sessionPart =\n r.reconcileSession !== null\n ? ` (in session ${shortSessionId(r.reconcileSession.sessionId)})`\n : \"\";\n console.log(`Reconciled ${r.taskId}: ${describeReconcileSummary(r)}${sessionPart}`);\n }\n for (const f of failed) {\n const phase = f.phase ?? \"unknown\";\n console.error(\n `Failed to reconcile ${f.taskId}: ${f.errorClass} (phase: ${phase}); see Caused by with -v`,\n );\n }\n const reconciledCount = results.length;\n const reconciledRefs = totalBrokenRefs;\n const reconciledPart = `reconciled ${reconciledCount} task${reconciledCount === 1 ? \"\" : \"s\"} (${reconciledRefs} broken ref${reconciledRefs === 1 ? \"\" : \"s\"})`;\n const failedPart =\n failed.length === 0 ? \"\" : `, ${failed.length} task${failed.length === 1 ? \"\" : \"s\"} failed`;\n console.log(`Scanned ${scanned} tasks, ${reconciledPart}${failedPart}.`);\n if (failed.length > 0) {\n console.error(\"(exit code 1)\");\n }\n return;\n }\n\n // dry-run with broken refs\n for (const r of results) {\n const summary = describeBrokenSummary(r, \"all\", options.verbose);\n console.log(`(dry-run) Would reconcile ${r.taskId}: ${summary}`);\n }\n console.log(\n `Scanned ${scanned} tasks, would reconcile ${results.length} task${results.length === 1 ? \"\" : \"s\"} (${totalBrokenRefs} broken ref${totalBrokenRefs === 1 ? \"\" : \"s\"}).`,\n );\n console.log(\"Note: events -> task.md forward sync is handled by `basou task refresh-linkage`.\");\n console.log(\"Re-run with --write to apply.\");\n}\n\nfunction describeReconcileSummary(r: ReconcileResult): string {\n const linkedCount = r.brokenLinkedSessions.length;\n const parts: string[] = [];\n if (r.brokenCreatedInSession !== null) {\n parts.push(\"replaced created_in_session\");\n }\n if (linkedCount > 0) {\n parts.push(`removed ${linkedCount} linked_sessions entr${linkedCount === 1 ? \"y\" : \"ies\"}`);\n }\n return parts.join(\" + \");\n}\n\nfunction describeBrokenSummary(\n r: ReconcileResult,\n scope: \"all\" | \"task\",\n verbose: boolean,\n): string {\n const showIds = scope === \"task\" || verbose;\n const parts: string[] = [];\n if (r.brokenCreatedInSession !== null) {\n parts.push(\n showIds\n ? `broken created_in_session ${formatSessionIdForDisplay(r.brokenCreatedInSession, verbose, scope)}`\n : \"broken created_in_session\",\n );\n }\n const linkedCount = r.brokenLinkedSessions.length;\n if (linkedCount > 0) {\n if (showIds) {\n const ids = r.brokenLinkedSessions\n .map((id) => formatSessionIdForDisplay(id, verbose, scope))\n .join(\", \");\n parts.push(`${linkedCount} linked_sessions entr${linkedCount === 1 ? \"y\" : \"ies\"} [${ids}]`);\n } else {\n parts.push(`${linkedCount} linked_sessions entr${linkedCount === 1 ? \"y\" : \"ies\"}`);\n }\n }\n return parts.join(\" + \");\n}\n\nfunction formatSessionIdForDisplay(id: string, verbose: boolean, scope: \"all\" | \"task\"): string {\n if (verbose && scope === \"task\") return id;\n return `ses_${shortSessionId(id)}`;\n}\n\n// ============================================================================\n// task refresh-linkage\n// ============================================================================\n\nexport async function runTaskRefreshLinkage(\n taskIdInput: string,\n options: TaskRefreshLinkageOptions,\n ctx: TaskContext = {},\n): Promise<void> {\n try {\n await doRunTaskRefreshLinkage(taskIdInput, options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options), classifiers: TASK_CLASSIFIERS });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunTaskRefreshLinkage(\n taskIdInput: string,\n options: TaskRefreshLinkageOptions,\n ctx: TaskContext,\n): Promise<void> {\n if (taskIdInput.trim().length === 0) {\n throw new Error(\"Task id is empty\");\n }\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForTask(cwd, \"refresh-linkage\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n const manifest = await readManifest(paths);\n const taskId = (await resolveTaskId(paths, taskIdInput)) as PrefixedId<\"task\">;\n const nowProvider = ctx.nowProvider ?? ((): Date => new Date());\n const write = options.write === true;\n\n const result = await refreshTaskLinkedSessions(paths, manifest, {\n taskId,\n occurredAt: nowProvider().toISOString(),\n workingDirectory: repositoryRoot,\n write,\n });\n\n if (options.json === true) {\n printRefreshLinkageJson(result, { dryRun: !write });\n return;\n }\n printRefreshLinkageText(result, { dryRun: !write });\n}\n\nfunction printRefreshLinkageJson(result: RefreshLinkageResult, input: { dryRun: boolean }): void {\n console.log(\n JSON.stringify(\n {\n task_id: result.taskId,\n clean: result.clean,\n dry_run: input.dryRun,\n added_linked_sessions: result.addedLinkedSessions,\n removed_linked_sessions: result.removedLinkedSessions,\n final_count: result.finalCount,\n refresh_session_id: result.refreshSession?.sessionId ?? null,\n event_id: result.refreshSession?.eventId ?? null,\n },\n null,\n 2,\n ),\n );\n}\n\nfunction printRefreshLinkageText(result: RefreshLinkageResult, input: { dryRun: boolean }): void {\n if (result.clean) {\n console.log(\n `${result.taskId}: linked_sessions already fresh (${result.finalCount} entr${result.finalCount === 1 ? \"y\" : \"ies\"}).`,\n );\n return;\n }\n const addedCount = result.addedLinkedSessions.length;\n const removedCount = result.removedLinkedSessions.length;\n const summaryParts: string[] = [];\n if (addedCount > 0) {\n summaryParts.push(`+${addedCount} added`);\n }\n if (removedCount > 0) {\n summaryParts.push(`-${removedCount} removed`);\n }\n const summary = summaryParts.join(\", \");\n if (input.dryRun) {\n console.log(`(dry-run) Would refresh ${result.taskId} linked_sessions: ${summary}.`);\n console.log(\"Re-run with --write to apply.\");\n return;\n }\n const sid =\n result.refreshSession !== null\n ? ` (in session ${shortSessionId(result.refreshSession.sessionId)})`\n : \"\";\n console.log(\n `Refreshed ${result.taskId} linked_sessions: ${summary}${sid}; final count ${result.finalCount}.`,\n );\n}\n\n// ============================================================================\n// task edit / delete / archive\n// ============================================================================\n\nexport async function runTaskEdit(\n taskIdInput: string,\n options: TaskEditOptions,\n ctx: TaskContext = {},\n): Promise<void> {\n try {\n await doRunTaskEdit(taskIdInput, options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options), classifiers: TASK_CLASSIFIERS });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunTaskEdit(\n taskIdInput: string,\n options: TaskEditOptions,\n ctx: TaskContext,\n): Promise<void> {\n if (taskIdInput.trim().length === 0) {\n throw new Error(\"Task id is empty\");\n }\n if (options.title === undefined && options.status === undefined) {\n throw new Error(\"Nothing to edit: provide --title or --status\");\n }\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForTask(cwd, \"edit\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n const manifest = await readManifest(paths);\n const taskId = (await resolveTaskId(paths, taskIdInput)) as PrefixedId<\"task\">;\n const now = ctx.nowProvider !== undefined ? ctx.nowProvider() : new Date();\n const occurredAt = now.toISOString();\n\n const result = await editTask({\n paths,\n taskId,\n occurredAt,\n manifest,\n workingDirectory: repositoryRoot,\n ...(options.title !== undefined ? { title: options.title } : {}),\n ...(options.status !== undefined ? { newStatus: options.status } : {}),\n });\n\n if (options.json === true) {\n console.log(\n JSON.stringify({\n task_id: result.taskId,\n title_updated: result.titleUpdated,\n status_updated: result.statusUpdated,\n previous_status: result.previousStatus,\n new_status: result.newStatus,\n status_change_session_id: result.statusChangeSession?.sessionId ?? null,\n status_change_event_id: result.statusChangeSession?.eventId ?? null,\n }),\n );\n return;\n }\n if (result.statusUpdated) {\n const sid =\n result.statusChangeSession !== null\n ? ` (in session ${shortSessionId(result.statusChangeSession.sessionId)})`\n : \"\";\n console.log(\n `Updated ${result.taskId} status: ${result.previousStatus} -> ${result.newStatus}${sid}`,\n );\n }\n if (result.titleUpdated) {\n console.log(`Updated ${result.taskId} title.`);\n }\n if (!result.statusUpdated && !result.titleUpdated) {\n // Both fields were supplied but matched the current values exactly —\n // tell the operator the task was already in the requested state.\n console.log(`No changes for ${result.taskId}.`);\n }\n}\n\nexport async function runTaskDelete(\n taskIdInput: string,\n options: TaskDeleteOptions,\n ctx: TaskContext = {},\n): Promise<void> {\n try {\n await doRunTaskDelete(taskIdInput, options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options), classifiers: TASK_CLASSIFIERS });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunTaskDelete(\n taskIdInput: string,\n options: TaskDeleteOptions,\n ctx: TaskContext,\n): Promise<void> {\n if (taskIdInput.trim().length === 0) {\n throw new Error(\"Task id is empty\");\n }\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForTask(cwd, \"delete\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n const manifest = await readManifest(paths);\n const taskId = (await resolveTaskId(paths, taskIdInput)) as PrefixedId<\"task\">;\n\n if (options.yes !== true) {\n await confirmDestructiveAction(\"delete\", taskId);\n }\n\n const now = ctx.nowProvider !== undefined ? ctx.nowProvider() : new Date();\n const occurredAt = now.toISOString();\n const result = await deleteTask({\n paths,\n manifest,\n taskId,\n occurredAt,\n workingDirectory: repositoryRoot,\n });\n\n if (options.json === true) {\n console.log(\n JSON.stringify({\n task_id: result.taskId,\n title: result.title,\n session_id: result.sessionId,\n event_id: result.eventId,\n }),\n );\n return;\n }\n console.log(\n `Deleted ${result.taskId} (\"${result.title}\") in ad-hoc session ${shortSessionId(result.sessionId)}.`,\n );\n}\n\nexport async function runTaskArchive(\n taskIdInput: string,\n options: TaskArchiveOptions,\n ctx: TaskContext = {},\n): Promise<void> {\n try {\n await doRunTaskArchive(taskIdInput, options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options), classifiers: TASK_CLASSIFIERS });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunTaskArchive(\n taskIdInput: string,\n options: TaskArchiveOptions,\n ctx: TaskContext,\n): Promise<void> {\n if (taskIdInput.trim().length === 0) {\n throw new Error(\"Task id is empty\");\n }\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForTask(cwd, \"archive\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n const manifest = await readManifest(paths);\n const taskId = (await resolveTaskId(paths, taskIdInput)) as PrefixedId<\"task\">;\n\n if (options.yes !== true) {\n await confirmDestructiveAction(\"archive\", taskId);\n }\n\n const now = ctx.nowProvider !== undefined ? ctx.nowProvider() : new Date();\n const occurredAt = now.toISOString();\n const result = await archiveTask({\n paths,\n manifest,\n taskId,\n occurredAt,\n workingDirectory: repositoryRoot,\n });\n\n if (options.json === true) {\n console.log(\n JSON.stringify({\n task_id: result.taskId,\n title: result.title,\n session_id: result.sessionId,\n event_id: result.eventId,\n }),\n );\n return;\n }\n console.log(\n `Archived ${result.taskId} (\"${result.title}\") in ad-hoc session ${shortSessionId(result.sessionId)}.`,\n );\n}\n\n/**\n * Read a single y/N answer from stdin when stdin is a TTY. Refuses to wait\n * for input when stdin is not a TTY (operator must pass --yes explicitly),\n * so piping `echo y | basou task delete` cannot accidentally trigger a\n * destructive action.\n */\nasync function confirmDestructiveAction(\n action: \"delete\" | \"archive\",\n taskId: string,\n): Promise<void> {\n if (process.stdin.isTTY !== true) {\n throw new Error(`Refusing to ${action} without TTY; rerun with --yes to skip confirmation.`);\n }\n const verb = action === \"delete\" ? \"Delete\" : \"Archive\";\n process.stdout.write(`${verb} task \\`${taskId}\\`? [y/N] `);\n const answer = await readSingleLineFromStdin();\n const normalized = answer.trim().toLowerCase();\n if (normalized !== \"y\" && normalized !== \"yes\") {\n throw new Error(`${verb} aborted by user.`);\n }\n}\n\nasync function readSingleLineFromStdin(): Promise<string> {\n const { createInterface } = await import(\"node:readline/promises\");\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n try {\n const line = await rl.question(\"\");\n return line;\n } finally {\n rl.close();\n }\n}\n\n// ============================================================================\n// option converters\n// ============================================================================\n\nfunction parseTitle(raw: string): string {\n if (raw.length === 0) {\n throw new InvalidArgumentError(\"Title must not be empty\");\n }\n return raw;\n}\n\nfunction parseLabel(raw: string): string {\n if (raw.length === 0) {\n throw new InvalidArgumentError(\"Label must not be empty\");\n }\n return raw;\n}\n\nfunction parseInitialTaskStatus(raw: string): TaskStatus {\n const result = TaskStatusSchema.safeParse(raw);\n if (!result.success) {\n throw new InvalidArgumentError(\n `Initial task status must be one of: ${STATUS_VALUES.join(\", \")}`,\n );\n }\n return result.data;\n}\n\nconst ISO_DATE_RE = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/;\n\nfunction parseIsoTimestampOption(raw: string): string {\n // Mirror the IsoTimestampSchema accepted form: date + time + explicit\n // zone designator. We rely on Date.parse for content validation and the\n // regex above for shape so misformed inputs are rejected before we hand\n // the string to the orchestrator's downstream parsers.\n if (!ISO_DATE_RE.test(raw) || Number.isNaN(Date.parse(raw))) {\n throw new InvalidArgumentError(\n \"Invalid --completed-at value; expected ISO-8601 timestamp like 2026-05-10T12:34:56+09:00\",\n );\n }\n return raw;\n}\n\nfunction parseTaskStatusFilter(raw: string): TaskStatus {\n const result = TaskStatusSchema.safeParse(raw);\n if (!result.success) {\n throw new InvalidArgumentError(\n `Invalid task status: ${raw}. Valid values: ${STATUS_VALUES.join(\", \")}`,\n );\n }\n return result.data;\n}\n\nfunction parseTaskStatusPositional(raw: string): TaskStatus {\n const result = TaskStatusSchema.safeParse(raw);\n if (!result.success) {\n throw new Error(`Invalid task status: ${raw}. Valid values: ${STATUS_VALUES.join(\", \")}`);\n }\n return result.data;\n}\n\nfunction parseDescriptionOption(raw: string): string {\n if (raw.length === 0) {\n throw new InvalidArgumentError(\"Description must not be empty\");\n }\n return raw;\n}\n\nfunction parsePositiveInt(raw: string): number {\n const n = Number.parseInt(raw, 10);\n if (!Number.isInteger(n) || n < 1 || raw.trim() !== String(n)) {\n throw new InvalidArgumentError(`Invalid number: ${raw}`);\n }\n return n;\n}\n\n// ============================================================================\n// IO helpers\n// ============================================================================\n\nasync function readDescriptionFile(path: string): Promise<string> {\n try {\n return await readFile(path, \"utf8\");\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Description source not found\", { cause: error });\n }\n if (findErrorCode(error, \"EISDIR\")) {\n throw new Error(\"Description source is not a file\", { cause: error });\n }\n throw new Error(\"Failed to read description source\", { cause: error });\n }\n}\n\nasync function resolveRepositoryRootForTask(\n cwd: string,\n subcmd:\n | \"new\"\n | \"list\"\n | \"show\"\n | \"status\"\n | \"reconcile\"\n | \"refresh-linkage\"\n | \"edit\"\n | \"delete\"\n | \"archive\",\n): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\n `Not a git repository. Run 'git init' first, then re-run 'basou task ${subcmd}'.`,\n { cause: error },\n );\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n\n/**\n * Task-specific classifier for {@link TaskWriteAfterEventError}. The\n * generic renderer ({@link renderCliError}) already prints the underlying\n * `error.message`; this classifier appends the two task-specific lines\n * that explain WHICH artefact is in unsafe state and the manual-repair\n * hint. Combined with {@link failedToFinalizeClassifier} from the shared\n * lib so both error classes are surfaced consistently across `task new`,\n * `task status`, `task reconcile`, etc.\n */\nconst taskWriteAfterEventClassifier: ErrorClassifier = {\n match: (error) => error instanceof TaskWriteAfterEventError,\n additionalLines: (error) => {\n const e = error as TaskWriteAfterEventError;\n const sid = shortSessionId(e.sessionId);\n const tid = shortTaskId(e.taskId);\n const unsafeArtefact = describeUnsafeArtefact(e.phase, tid, sid);\n const warning = describeWriteFailureWarning(e.phase);\n const hint =\n e.phase === \"reconcile-concurrent\"\n ? \"re-run `basou task reconcile`\"\n : e.phase === \"linkage-refresh-concurrent\"\n ? \"re-run `basou task refresh-linkage`\"\n : \"manual repair required; see `basou task show -v` for event payload\";\n return [\n `Recorded ${e.eventId} in session ${sid}; ${unsafeArtefact} is in unsafe state; do not rerun`,\n `Warning: ${warning}; events.jsonl is consistent; ${hint}`,\n ];\n },\n};\n\nconst TASK_CLASSIFIERS: readonly ErrorClassifier[] = [\n taskWriteAfterEventClassifier,\n failedToFinalizeClassifier,\n];\n\nfunction describeUnsafeArtefact(\n phase: TaskWriteAfterEventError[\"phase\"],\n tid: string,\n sid: string,\n): string {\n switch (phase) {\n case \"create\":\n return `task ${tid} file`;\n case \"overwrite\":\n return `task ${tid} file`;\n case \"link-session\":\n return \"session-task linkage\";\n case \"reconcile\":\n return `task ${tid} file (reconcile incomplete)`;\n case \"reconcile-finalize\":\n return `reconcile session ${sid} (finalize incomplete)`;\n case \"reconcile-concurrent\":\n return `task ${tid} file (concurrent modification detected)`;\n case \"linkage-refresh\":\n return `task ${tid} file (linkage refresh incomplete)`;\n case \"linkage-refresh-finalize\":\n return `linkage refresh session ${sid} (finalize incomplete)`;\n case \"linkage-refresh-concurrent\":\n return `task ${tid} file (concurrent modification detected)`;\n case \"delete\":\n return `task ${tid} file (delete incomplete; file still on disk)`;\n case \"archive\":\n return `task ${tid} file (archive incomplete; check tasks/ and tasks/archive/)`;\n }\n}\n\nfunction describeWriteFailureWarning(phase: TaskWriteAfterEventError[\"phase\"]): string {\n switch (phase) {\n case \"create\":\n return \"task.md creation failed\";\n case \"overwrite\":\n return \"task.md update failed\";\n case \"link-session\":\n return \"session.yaml task_id update failed\";\n case \"reconcile\":\n return \"task.md reconciliation failed\";\n case \"reconcile-finalize\":\n return \"reconcile session finalize failed (session.yaml status update)\";\n case \"reconcile-concurrent\":\n return \"task.md was modified concurrently; re-run reconcile to retry\";\n case \"linkage-refresh\":\n return \"task.md linkage refresh write failed\";\n case \"linkage-refresh-finalize\":\n return \"linkage refresh session finalize failed (session.yaml status update)\";\n case \"linkage-refresh-concurrent\":\n return \"task.md was modified concurrently; re-run refresh-linkage to retry\";\n case \"delete\":\n return \"task.md unlink failed after task_deleted event committed\";\n case \"archive\":\n return \"task.md move to archive/ failed after task_archived event committed\";\n }\n}\n\nfunction pad(value: string, width: number): string {\n return value.length >= width ? value : value + \" \".repeat(width - value.length);\n}\n\nfunction maxLen(values: readonly string[], floor: number): number {\n let max = floor;\n for (const v of values) if (v.length > max) max = v.length;\n return max;\n}\n","import { spawn } from \"node:child_process\";\nimport { assertBasouRootSafe, basouPaths, findErrorCode, resolveRepositoryRoot } from \"@basou/core\";\nimport { type Command, InvalidArgumentError } from \"commander\";\nimport { isVerbose, renderCliError } from \"../lib/error-render.js\";\nimport { startViewServer, type ViewServerDeps, type ViewServerHandle } from \"../lib/view-server.js\";\n\nconst DEFAULT_PORT = 4319;\n\nexport type ViewOptions = {\n port?: number;\n open?: boolean;\n verbose?: boolean;\n};\n\nexport type ViewContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n /** Defaults to `() => new Date()`. Injectable for tests. */\n nowProvider?: () => Date;\n /** Override the `~/.claude/projects` root used by imports. */\n claudeProjectsDir?: string;\n /** Override the `~/.codex/sessions` root used by imports. */\n codexSessionsDir?: string;\n /** Override how the browser is opened (tests pass a no-op). */\n openBrowser?: (url: string) => void;\n /** Resolves the keep-alive wait, so tests can stop the server without a signal. */\n signal?: AbortSignal;\n /** Called once the server is listening, with its handle (for tests). */\n onListening?: (handle: ViewServerHandle) => void;\n};\n\nfunction parsePort(value: string): number {\n const port = Number.parseInt(value, 10);\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new InvalidArgumentError(\"Port must be an integer between 1 and 65535.\");\n }\n return port;\n}\n\n/**\n * Wire `basou view` onto `program`. Starts a localhost-only web UI for\n * browsing provenance and running imports / regeneration by clicking.\n */\nexport function registerViewCommand(program: Command): void {\n program\n .command(\"view\")\n .description(\"Open a local web UI to browse provenance and run imports (localhost only)\")\n .option(\"--port <number>\", \"Port to listen on (default 4319)\", parsePort)\n .option(\"--no-open\", \"Do not open the browser automatically\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: ViewOptions) => {\n await runView(options);\n });\n}\n\n/** Programmatic entry that owns `process.exitCode`. Tests prefer {@link doRunView}. */\nexport async function runView(options: ViewOptions, ctx: ViewContext = {}): Promise<void> {\n try {\n await doRunView(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * Pure runner: resolve the workspace, start the server, open the browser, and\n * keep running until SIGINT / SIGTERM (or an injected abort signal). The\n * server is always closed on the way out.\n */\nexport async function doRunView(options: ViewOptions, ctx: ViewContext): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForView(cwd);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const deps: ViewServerDeps = {\n paths,\n repoRoot: repositoryRoot,\n importCtx: {\n cwd: repositoryRoot,\n ...(ctx.claudeProjectsDir !== undefined ? { claudeProjectsDir: ctx.claudeProjectsDir } : {}),\n ...(ctx.codexSessionsDir !== undefined ? { codexSessionsDir: ctx.codexSessionsDir } : {}),\n },\n nowProvider: ctx.nowProvider ?? (() => new Date()),\n };\n\n const port = options.port ?? DEFAULT_PORT;\n const handle = await startListening(port, deps);\n\n // Everything past listen runs under try/finally so a throw from the browser\n // launch or the onListening callback still closes the server.\n try {\n console.log(`basou view running at ${handle.url}`);\n console.log(\n \"Localhost only, no authentication. Do not expose this port beyond your machine. Press Ctrl+C to stop.\",\n );\n\n if (options.open !== false) {\n openInBrowser(handle.url, ctx.openBrowser);\n }\n ctx.onListening?.(handle);\n\n await waitForShutdown(ctx.signal);\n } finally {\n await handle.close();\n }\n}\n\nasync function startListening(port: number, deps: ViewServerDeps): Promise<ViewServerHandle> {\n try {\n return await startViewServer({ port, deps });\n } catch (error: unknown) {\n if (findErrorCode(error, \"EADDRINUSE\")) {\n throw new Error(`Port ${port} is already in use. Pass --port <n> to choose another.`, {\n cause: error,\n });\n }\n throw error;\n }\n}\n\nfunction openInBrowser(url: string, override?: (url: string) => void): void {\n if (override !== undefined) {\n override(url);\n return;\n }\n if (process.platform !== \"darwin\") return; // print-only elsewhere\n try {\n const child = spawn(\"open\", [url], { stdio: \"ignore\", detached: true });\n child.on(\"error\", () => {}); // browser launch is best-effort\n child.unref();\n } catch {\n // ignore: the URL is already printed\n }\n}\n\n/** Resolve once the process is asked to stop (signal) or the injected abort fires. */\nfunction waitForShutdown(signal: AbortSignal | undefined): Promise<void> {\n return new Promise((resolve) => {\n const cleanup = (): void => {\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n signal?.removeEventListener(\"abort\", onAbort);\n };\n const onSignal = (): void => {\n cleanup();\n resolve();\n };\n const onAbort = (): void => {\n cleanup();\n resolve();\n };\n process.on(\"SIGINT\", onSignal);\n process.on(\"SIGTERM\", onSignal);\n if (signal !== undefined) {\n if (signal.aborted) {\n cleanup();\n resolve();\n return;\n }\n signal.addEventListener(\"abort\", onAbort);\n }\n });\n}\n\nasync function resolveRepositoryRootForView(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\"Not a git repository. Run 'git init' first, then re-run 'basou view'.\", {\n cause: error,\n });\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n","import { createServer, type IncomingMessage, type Server, type ServerResponse } from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\nimport { join } from \"node:path\";\nimport {\n type BasouPaths,\n computeWorkStats,\n enumerateApprovals,\n findErrorCode,\n isLazyExpired,\n loadApproval,\n loadSessionEntries,\n loadTaskEntries,\n type Manifest,\n readAllEvents,\n readManifest,\n readMarkdownFile,\n readSessionYaml,\n readTaskFile,\n renderDecisions,\n renderHandoff,\n} from \"@basou/core\";\nimport type { ImportContext } from \"../commands/import.js\";\nimport {\n importClaudeCode,\n importCodex,\n type RefreshActionOptions,\n refreshAll,\n regenerateDecisions,\n regenerateHandoff,\n} from \"./provenance-actions.js\";\nimport { VIEW_HTML } from \"./view-ui.js\";\n\n/** Everything the request handlers need; resolved once when the server starts. */\nexport type ViewServerDeps = {\n paths: BasouPaths;\n repoRoot: string;\n importCtx: ImportContext;\n nowProvider: () => Date;\n};\n\n/** A running view server, with the means to stop it. */\nexport type ViewServerHandle = {\n url: string;\n port: number;\n close: () => Promise<void>;\n};\n\n/** A handler-level failure that maps to a specific HTTP status (vs a 500). */\nclass HttpError extends Error {\n constructor(\n readonly status: number,\n message: string,\n ) {\n super(message);\n }\n}\n\nconst MAX_BODY_BYTES = 64 * 1024;\n\n/**\n * Start a localhost-only provenance viewer. Binds 127.0.0.1, serves a single\n * inline HTML page at `/` and a small JSON API under `/api/*`. Resolves once\n * listening (rejects on a bind error such as EADDRINUSE).\n */\nexport function startViewServer(opts: {\n port: number;\n host?: string;\n deps: ViewServerDeps;\n}): Promise<ViewServerHandle> {\n const { port, host = \"127.0.0.1\", deps } = opts;\n // Mutating POSTs swap process-global console (import capture); serialize them\n // so concurrent requests from a reloaded tab never interleave.\n let actionQueue: Promise<unknown> = Promise.resolve();\n const runExclusive = <T>(fn: () => Promise<T>): Promise<T> => {\n const result = actionQueue.then(fn, fn);\n actionQueue = result.then(\n () => undefined,\n () => undefined,\n );\n return result;\n };\n\n let boundPort = port;\n const getPort = (): number => boundPort;\n\n return new Promise((resolve, reject) => {\n const server = createServer((req, res) => {\n handleRequest(req, res, deps, getPort, runExclusive).catch((error: unknown) => {\n sendError(res, error instanceof HttpError ? error.status : 500, pathlessMessage(error));\n });\n });\n server.on(\"error\", reject);\n server.listen(port, host, () => {\n const address = server.address();\n boundPort = isAddressInfo(address) ? address.port : port;\n server.off(\"error\", reject);\n resolve({\n url: `http://${host}:${boundPort}`,\n port: boundPort,\n close: () => closeServer(server),\n });\n });\n });\n}\n\nfunction isAddressInfo(value: string | AddressInfo | null): value is AddressInfo {\n return value !== null && typeof value === \"object\";\n}\n\nfunction closeServer(server: Server): Promise<void> {\n return new Promise((resolve) => {\n server.close(() => resolve());\n // Force-terminate any in-flight connection (e.g. a client holding a POST\n // body open) so close() resolves promptly instead of hanging shutdown.\n server.closeAllConnections();\n });\n}\n\nasync function handleRequest(\n req: IncomingMessage,\n res: ServerResponse,\n deps: ViewServerDeps,\n getPort: () => number,\n runExclusive: <T>(fn: () => Promise<T>) => Promise<T>,\n): Promise<void> {\n const method = req.method ?? \"GET\";\n const url = new URL(req.url ?? \"/\", \"http://localhost\");\n const pathname = url.pathname;\n\n if (!hostAllowed(req, getPort())) {\n sendError(res, 403, \"Forbidden: host not allowed\");\n return;\n }\n\n if (method === \"GET\") {\n await handleGet(res, pathname, deps);\n return;\n }\n if (method === \"POST\") {\n if (!originAllowed(req, getPort())) {\n sendError(res, 403, \"Forbidden: cross-origin request\");\n return;\n }\n const body = await readBody(req);\n await handlePost(res, pathname, body, deps, runExclusive);\n return;\n }\n sendError(res, 405, \"Method not allowed\");\n}\n\nasync function handleGet(\n res: ServerResponse,\n pathname: string,\n deps: ViewServerDeps,\n): Promise<void> {\n if (pathname === \"/\") {\n sendHtml(res, VIEW_HTML);\n return;\n }\n if (pathname === \"/api/overview\") {\n sendJson(res, 200, await overview(deps));\n return;\n }\n if (pathname === \"/api/sessions\") {\n sendJson(res, 200, await sessionsList(deps));\n return;\n }\n const sessionId = matchId(pathname, \"/api/sessions/\");\n if (sessionId !== null) {\n sendJson(res, 200, await sessionDetail(deps, sessionId));\n return;\n }\n if (pathname === \"/api/tasks\") {\n sendJson(res, 200, await tasksList(deps));\n return;\n }\n const taskId = matchId(pathname, \"/api/tasks/\");\n if (taskId !== null) {\n sendJson(res, 200, await taskDetail(deps, taskId));\n return;\n }\n if (pathname === \"/api/decisions\") {\n sendJson(res, 200, await decisionsView(deps));\n return;\n }\n if (pathname === \"/api/approvals\") {\n sendJson(res, 200, await approvalsView(deps));\n return;\n }\n if (pathname === \"/api/handoff\") {\n sendJson(res, 200, await handoffView(deps));\n return;\n }\n if (pathname === \"/api/stats\") {\n sendJson(res, 200, await computeWorkStats({ paths: deps.paths, now: deps.nowProvider() }));\n return;\n }\n sendError(res, 404, \"Not found\");\n}\n\nasync function handlePost(\n res: ServerResponse,\n pathname: string,\n body: Record<string, unknown>,\n deps: ViewServerDeps,\n runExclusive: <T>(fn: () => Promise<T>) => Promise<T>,\n): Promise<void> {\n const nowIso = deps.nowProvider().toISOString();\n const actionOptions = readActionOptions(body);\n\n if (pathname === \"/api/refresh\") {\n const result = await runExclusive(() =>\n refreshAll({ options: actionOptions, ctx: deps.importCtx, paths: deps.paths, nowIso }),\n );\n sendJson(res, 200, result);\n return;\n }\n if (pathname === \"/api/import/claude-code\") {\n sendJson(res, 200, await runExclusive(() => importClaudeCode(actionOptions, deps.importCtx)));\n return;\n }\n if (pathname === \"/api/import/codex\") {\n sendJson(res, 200, await runExclusive(() => importCodex(actionOptions, deps.importCtx)));\n return;\n }\n if (pathname === \"/api/handoff/generate\") {\n sendJson(res, 200, await runExclusive(() => regenerateHandoff(deps.paths, nowIso)));\n return;\n }\n if (pathname === \"/api/decisions/generate\") {\n sendJson(res, 200, await runExclusive(() => regenerateDecisions(deps.paths, nowIso)));\n return;\n }\n sendError(res, 404, \"Not found\");\n}\n\n// --- handlers -------------------------------------------------------------\n\nasync function overview(deps: ViewServerDeps): Promise<Record<string, unknown>> {\n let manifest: Manifest;\n try {\n manifest = await readManifest(deps.paths);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n return { initialized: false, repoRoot: deps.repoRoot };\n }\n throw error;\n }\n const nowIso = deps.nowProvider().toISOString();\n const handoff = await renderHandoff({ paths: deps.paths, nowIso });\n const approvals = await enumerateApprovals(deps.paths);\n return {\n initialized: true,\n repoRoot: deps.repoRoot,\n workspace: {\n id: manifest.workspace.id,\n name: manifest.workspace.name,\n basouVersion: manifest.basou_version,\n },\n counts: {\n sessions: handoff.sessionCount,\n suspectSessions: handoff.suspectCount,\n tasks: handoff.taskCount,\n pendingTasks: handoff.pendingTaskCount,\n decisions: handoff.decisionCount,\n approvalsPending: approvals.pending.length,\n approvalsResolved: approvals.resolved.length,\n },\n generatedAt: nowIso,\n };\n}\n\nasync function sessionsList(deps: ViewServerDeps): Promise<Record<string, unknown>> {\n const entries = await loadSessionEntries(deps.paths, { now: deps.nowProvider() });\n // loadSessionEntries returns oldest-first; show newest-first.\n const sessions = entries\n .map((entry) => ({\n sessionId: entry.sessionId,\n label: entry.session.session.label ?? null,\n status: entry.session.session.status,\n sourceKind: entry.session.session.source.kind,\n startedAt: entry.session.session.started_at,\n endedAt: entry.session.session.ended_at ?? null,\n suspect: entry.suspect,\n suspectReason: entry.suspectReason,\n taskId: entry.session.session.task_id ?? null,\n relatedFilesCount: entry.session.session.related_files.length,\n }))\n .reverse();\n return { sessions };\n}\n\nasync function sessionDetail(\n deps: ViewServerDeps,\n sessionId: string,\n): Promise<Record<string, unknown>> {\n let session: Awaited<ReturnType<typeof readSessionYaml>>;\n try {\n session = await readSessionYaml(deps.paths, sessionId);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"YAML file not found\") {\n throw new HttpError(404, \"Session not found\");\n }\n throw error;\n }\n // An unreadable events.jsonl must not 500 the detail view; surface the\n // session with an empty, flagged-degraded timeline (mirrors the list path).\n try {\n const events = await readAllEvents(join(deps.paths.sessions, sessionId));\n return { session, events };\n } catch {\n return { session, events: [], degraded: true };\n }\n}\n\nasync function tasksList(deps: ViewServerDeps): Promise<Record<string, unknown>> {\n const entries = await loadTaskEntries(deps.paths);\n return { tasks: entries.map((entry) => entry.task).reverse() };\n}\n\nasync function taskDetail(deps: ViewServerDeps, taskId: string): Promise<Record<string, unknown>> {\n try {\n const doc = await readTaskFile(deps.paths, taskId);\n return { task: doc.task, body: doc.body };\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Task file not found\") {\n throw new HttpError(404, \"Task not found\");\n }\n throw error;\n }\n}\n\nasync function decisionsView(deps: ViewServerDeps): Promise<Record<string, unknown>> {\n // Prefer the on-disk decisions.md so hand-edited content (outside the\n // generated markers) is shown, mirroring the handoff view; fall back to a\n // fresh render when the file does not exist yet.\n const fromDisk = await readMarkdownFile(deps.paths.files.decisions);\n if (fromDisk !== null) {\n return { body: fromDisk, fromDisk: true };\n }\n const nowIso = deps.nowProvider().toISOString();\n const result = await renderDecisions({ paths: deps.paths, nowIso });\n return { body: result.body, decisionCount: result.decisionCount, fromDisk: false };\n}\n\nasync function approvalsView(deps: ViewServerDeps): Promise<Record<string, unknown>> {\n const now = deps.nowProvider();\n const ids = await enumerateApprovals(deps.paths);\n const toViews = async (list: string[]): Promise<Array<Record<string, unknown>>> => {\n const views: Array<Record<string, unknown>> = [];\n for (const id of list) {\n const loaded = await loadApproval(deps.paths, id);\n if (loaded === null) continue;\n views.push({ id, expired: isLazyExpired(loaded.approval, now), approval: loaded.approval });\n }\n return views;\n };\n return { pending: await toViews(ids.pending), resolved: await toViews(ids.resolved) };\n}\n\nasync function handoffView(deps: ViewServerDeps): Promise<Record<string, unknown>> {\n const fromDisk = await readMarkdownFile(deps.paths.files.handoff);\n if (fromDisk !== null) {\n return { body: fromDisk, fromDisk: true };\n }\n const nowIso = deps.nowProvider().toISOString();\n const result = await renderHandoff({ paths: deps.paths, nowIso });\n return { body: result.body, fromDisk: false };\n}\n\n// --- request helpers ------------------------------------------------------\n\nfunction readActionOptions(body: Record<string, unknown>): RefreshActionOptions {\n const options: RefreshActionOptions = {};\n // Accept `project` as a single string (the UI sends one) or an array of\n // strings (multi-root callers); normalize to a non-empty string[].\n const project = normalizeProject(body.project);\n if (project.length > 0) options.project = project;\n if (body.force === true) options.force = true;\n if (body.dryRun === true) options.dryRun = true;\n return options;\n}\n\n/** Coerce a request body `project` field into a list of non-empty path strings. */\nfunction normalizeProject(value: unknown): string[] {\n const raw = Array.isArray(value) ? value : [value];\n return raw.filter((p): p is string => typeof p === \"string\" && p.length > 0);\n}\n\nfunction hostAllowed(req: IncomingMessage, port: number): boolean {\n const host = req.headers.host;\n return host === `127.0.0.1:${port}` || host === `localhost:${port}`;\n}\n\nfunction originAllowed(req: IncomingMessage, port: number): boolean {\n const origin = req.headers.origin;\n if (origin === undefined) return true; // non-browser client (curl, tests)\n return origin === `http://127.0.0.1:${port}` || origin === `http://localhost:${port}`;\n}\n\nasync function readBody(req: IncomingMessage): Promise<Record<string, unknown>> {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of req) {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));\n size += buf.length;\n if (size > MAX_BODY_BYTES) throw new HttpError(413, \"Request body too large\");\n chunks.push(buf);\n }\n const raw = Buffer.concat(chunks).toString(\"utf8\").trim();\n if (raw.length === 0) return {};\n try {\n const parsed: unknown = JSON.parse(raw);\n if (parsed !== null && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n } catch {\n // fall through to the shared 400 below\n }\n throw new HttpError(400, \"Invalid JSON body\");\n}\n\nfunction matchId(pathname: string, prefix: string): string | null {\n if (!pathname.startsWith(prefix)) return null;\n const encoded = pathname.slice(prefix.length);\n if (encoded.length === 0 || encoded.includes(\"/\")) return null;\n let id: string;\n try {\n id = decodeURIComponent(encoded);\n } catch {\n return null; // malformed percent-escape\n }\n // Reject anything that could escape the storage root once decoded: a path\n // separator (incl. the percent-encoded `%2f` that slips past the check\n // above) or a `.`/`..` segment. Ids are otherwise opaque to this layer.\n if (\n id.length === 0 ||\n id.includes(\"/\") ||\n id.includes(\"\\\\\") ||\n id.includes(\"\\0\") ||\n id === \".\" ||\n id === \"..\"\n ) {\n return null;\n }\n return id;\n}\n\nfunction sendJson(res: ServerResponse, status: number, data: unknown): void {\n const body = JSON.stringify(data);\n res.writeHead(status, {\n \"Content-Type\": \"application/json; charset=utf-8\",\n \"Cache-Control\": \"no-store\",\n });\n res.end(body);\n}\n\nfunction sendHtml(res: ServerResponse, html: string): void {\n res.writeHead(200, {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"no-store\",\n });\n res.end(html);\n}\n\nfunction sendError(res: ServerResponse, status: number, message: string): void {\n if (res.headersSent) {\n res.end();\n return;\n }\n sendJson(res, status, { error: message });\n}\n\n/**\n * A pathless, audience-safe message: the Error's own message is already\n * pathless by the codebase's convention; native fs errors are wrapped before\n * they reach here. Falls back to a generic string for non-Error throws.\n */\nfunction pathlessMessage(error: unknown): string {\n return error instanceof Error ? error.message : \"Internal error\";\n}\n","/**\n * The single-page UI for `basou view`, served verbatim at `GET /`. Kept as one\n * inline string so the CLI build needs no asset pipeline. All data is rendered\n * with createElement / textContent (never innerHTML), so session, task, and\n * command content cannot inject markup. The embedded script deliberately uses\n * no template literals (this file is itself a template literal).\n */\nexport const VIEW_HTML = `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<title>basou view</title>\n<style>\n :root { color-scheme: light dark; }\n * { box-sizing: border-box; }\n body { margin: 0; font: 14px/1.5 system-ui, -apple-system, Segoe UI, sans-serif; }\n header { padding: 10px 16px; border-bottom: 1px solid #8884; display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center; }\n header h1 { font-size: 15px; margin: 0 12px 0 0; font-weight: 700; }\n header .grow { flex: 1; }\n input[type=text] { padding: 4px 8px; border: 1px solid #8886; border-radius: 6px; min-width: 280px; font: inherit; }\n button { padding: 4px 10px; border: 1px solid #8886; border-radius: 6px; background: #8881; cursor: pointer; font: inherit; }\n button.primary { background: #2563eb; color: #fff; border-color: #2563eb; }\n button:disabled { opacity: .5; cursor: default; }\n label.chk { font-size: 13px; opacity: .85; }\n #status { padding: 6px 16px; font-size: 13px; min-height: 20px; border-bottom: 1px solid #8884; white-space: pre-wrap; }\n #status.err { color: #dc2626; }\n nav { display: flex; gap: 2px; padding: 6px 12px; border-bottom: 1px solid #8884; flex-wrap: wrap; }\n nav button { border: none; border-radius: 6px; background: transparent; }\n nav button.active { background: #2563eb22; font-weight: 600; }\n main { display: grid; grid-template-columns: minmax(220px, 320px) 1fr; min-height: 60vh; }\n main.single { grid-template-columns: 1fr; }\n #list { border-right: 1px solid #8884; overflow: auto; max-height: 80vh; }\n #list .row { padding: 8px 12px; border-bottom: 1px solid #8883; cursor: pointer; }\n #list .row:hover { background: #8881; }\n #list .row.active { background: #2563eb22; }\n #list .row .meta { font-size: 12px; opacity: .7; }\n #detail { padding: 12px 16px; overflow: auto; max-height: 80vh; }\n .badge { display: inline-block; padding: 0 6px; border-radius: 6px; background: #8882; font-size: 12px; }\n .badge.warn { background: #f59e0b33; }\n pre { background: #8881; padding: 12px; border-radius: 8px; overflow: auto; white-space: pre-wrap; word-break: break-word; }\n table.kv { border-collapse: collapse; }\n table.kv td { padding: 2px 10px 2px 0; vertical-align: top; }\n table.kv td.k { opacity: .7; }\n .cards { display: flex; flex-wrap: wrap; gap: 10px; }\n .card { border: 1px solid #8884; border-radius: 8px; padding: 10px 14px; min-width: 120px; }\n .card .n { font-size: 22px; font-weight: 700; }\n .card .l { font-size: 12px; opacity: .7; }\n .tl { border-left: 2px solid #8885; margin-left: 6px; padding-left: 12px; }\n .tl .ev { margin-bottom: 8px; }\n .tl .ev .t { font-size: 12px; opacity: .65; }\n .muted { opacity: .6; }\n</style>\n</head>\n<body>\n<header>\n <h1>basou view</h1>\n <input type=\"text\" id=\"project\" placeholder=\"source root (optional override)\" />\n <button class=\"primary\" id=\"btn-refresh\">Refresh all</button>\n <button id=\"btn-import-claude\">Import claude-code</button>\n <button id=\"btn-import-codex\">Import codex</button>\n <button id=\"btn-gen-handoff\">Regenerate handoff</button>\n <button id=\"btn-gen-decisions\">Regenerate decisions</button>\n <span class=\"grow\"></span>\n <label class=\"chk\"><input type=\"checkbox\" id=\"opt-force\" /> force</label>\n <label class=\"chk\"><input type=\"checkbox\" id=\"opt-dry\" /> dry-run</label>\n</header>\n<div id=\"status\"></div>\n<nav id=\"tabs\"></nav>\n<main id=\"main\">\n <div id=\"list\"></div>\n <div id=\"detail\"></div>\n</main>\n<script>\n(function () {\n var TABS = ['overview', 'stats', 'sessions', 'tasks', 'decisions', 'approvals', 'handoff'];\n var state = { tab: 'overview', repoRoot: '' };\n\n function $(id) { return document.getElementById(id); }\n function clear(node) { while (node.firstChild) node.removeChild(node.firstChild); }\n\n function el(tag, attrs, children) {\n var node = document.createElement(tag);\n if (attrs) {\n for (var k in attrs) {\n if (!Object.prototype.hasOwnProperty.call(attrs, k)) continue;\n if (k === 'class') node.className = attrs[k];\n else if (k === 'text') node.textContent = attrs[k];\n else if (k.slice(0, 2) === 'on') node.addEventListener(k.slice(2), attrs[k]);\n else node.setAttribute(k, attrs[k]);\n }\n }\n if (children) {\n for (var i = 0; i < children.length; i++) {\n var c = children[i];\n if (c === null || c === undefined) continue;\n node.appendChild(typeof c === 'string' ? document.createTextNode(c) : c);\n }\n }\n return node;\n }\n\n function setStatus(msg, isErr) {\n var s = $('status');\n s.textContent = msg || '';\n s.className = isErr ? 'err' : '';\n }\n\n function fetchJson(path, opts) {\n return fetch(path, opts).then(function (res) {\n return res.text().then(function (text) {\n var data = null;\n try { data = text ? JSON.parse(text) : null; } catch (e) { data = null; }\n if (!res.ok) {\n var m = data && data.error ? data.error : ('HTTP ' + res.status);\n throw new Error(m);\n }\n return data;\n });\n });\n }\n\n function single(on) { $('main').className = on ? 'single' : ''; if (on) clear($('list')); }\n\n // --- action bar ---------------------------------------------------------\n\n function actionBody() {\n var body = {};\n var project = $('project').value.trim();\n if (project) body.project = project;\n if ($('opt-force').checked) body.force = true;\n if ($('opt-dry').checked) body.dryRun = true;\n return body;\n }\n\n function setBusy(busy) {\n var ids = ['btn-refresh', 'btn-import-claude', 'btn-import-codex', 'btn-gen-handoff', 'btn-gen-decisions'];\n for (var i = 0; i < ids.length; i++) $(ids[i]).disabled = busy;\n }\n\n function post(path, label) {\n setBusy(true);\n setStatus(label + '...', false);\n fetchJson(path, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(actionBody())\n }).then(function (data) {\n setStatus(label + ' done: ' + summarize(data), false);\n loadTab(state.tab);\n }).catch(function (err) {\n setStatus(label + ' failed: ' + err.message, true);\n }).then(function () { setBusy(false); });\n }\n\n function summarize(data) {\n if (!data) return 'ok';\n if (data.claudeCode || data.codex) {\n return 'claude-code ' + imp(data.claudeCode) + ', codex ' + imp(data.codex)\n + (data.handoff && data.handoff.status === 'generated' ? '; handoff+decisions regenerated' : '');\n }\n if (data.status === 'ran') return imp(data);\n if (data.status === 'skipped') return 'skipped (' + data.reason + ')';\n if (typeof data.sessionCount === 'number') return 'sessions ' + data.sessionCount + ', decisions ' + data.decisionCount;\n if (typeof data.decisionCount === 'number') return 'decisions ' + data.decisionCount;\n return 'ok';\n }\n function imp(o) {\n if (!o) return '-';\n if (o.status === 'skipped') return 'skipped';\n return (o.dryRun ? 'would import ' : 'imported ') + o.importedCount + ' (' + o.eventTotal + ' events)';\n }\n\n // --- tabs ---------------------------------------------------------------\n\n function buildTabs() {\n var nav = $('tabs');\n clear(nav);\n TABS.forEach(function (name) {\n nav.appendChild(el('button', {\n class: name === state.tab ? 'active' : '',\n text: name,\n onclick: function () { loadTab(name); }\n }));\n });\n }\n\n function loadTab(name) {\n state.tab = name;\n buildTabs();\n clear($('detail'));\n clear($('list'));\n if (name === 'overview') return loadOverview();\n if (name === 'stats') return loadStats();\n if (name === 'sessions') return loadSessions();\n if (name === 'tasks') return loadTasks();\n if (name === 'decisions') return loadMarkdown('/api/decisions', 'decisions');\n if (name === 'approvals') return loadApprovals();\n if (name === 'handoff') return loadMarkdown('/api/handoff', 'handoff');\n }\n\n function fail(err) { setStatus(err.message, true); }\n\n function loadOverview() {\n single(true);\n fetchJson('/api/overview').then(function (d) {\n var detail = $('detail');\n if (!d || d.initialized === false) {\n detail.appendChild(el('p', { class: 'muted', text: 'Workspace not initialized.' }));\n return;\n }\n // Leave the project field empty by default so refresh / import use the\n // manifest's import.source_roots (then the repo root) -- pre-filling the\n // repo root here would send it as an explicit --project and silently\n // override multi-root source roots. The field is an optional override.\n state.repoRoot = d.repoRoot || '';\n detail.appendChild(el('p', {}, [\n el('strong', { text: d.workspace.name }), ' ',\n el('span', { class: 'muted', text: d.workspace.id })\n ]));\n var c = d.counts;\n var cards = el('div', { class: 'cards' }, [\n card(c.sessions, 'sessions'),\n card(c.suspectSessions, 'suspect'),\n card(c.tasks, 'tasks'),\n card(c.pendingTasks, 'pending tasks'),\n card(c.decisions, 'decisions'),\n card(c.approvalsPending, 'approvals pending')\n ]);\n detail.appendChild(cards);\n detail.appendChild(el('p', { class: 'muted', text: 'repo: ' + d.repoRoot }));\n }).catch(fail);\n }\n function card(n, label) {\n return el('div', { class: 'card' }, [\n el('div', { class: 'n', text: String(n) }),\n el('div', { class: 'l', text: label })\n ]);\n }\n\n function numfmt(n) { return (n || 0).toLocaleString('en-US'); }\n function fmtDur(ms) {\n var s = Math.round((ms || 0) / 1000);\n var h = Math.floor(s / 3600), m = Math.floor((s % 3600) / 60), sec = s % 60;\n if (h > 0) return h + 'h ' + (m < 10 ? '0' : '') + m + 'm';\n if (m > 0) return m + 'm ' + (sec < 10 ? '0' : '') + sec + 's';\n return sec + 's';\n }\n function kvrow(k, v) {\n return el('tr', {}, [el('td', { class: 'k', text: k }), el('td', { text: v })]);\n }\n\n function loadStats() {\n single(true);\n fetchJson('/api/stats').then(function (d) {\n var detail = $('detail');\n var t = d.totals;\n detail.appendChild(el('p', { text: 'Sessions: ' + t.sessionCount }));\n detail.appendChild(el('h3', { text: 'Volume (what the AI produced)' }));\n detail.appendChild(el('div', { class: 'cards' }, [\n card(numfmt(t.tokens.output), 'output tokens'),\n (t.tokens.reasoning > 0 ? card(numfmt(t.tokens.reasoning), 'reasoning tokens') : null),\n card(t.commandCount, 'commands'),\n card(t.fileChangedCount, 'files'),\n card(t.decisionCount, 'decisions')\n ]));\n var sessions = d.sessions || [];\n var tokenSessions = sessions.filter(function (s) { return s.availability && s.availability.tokens; }).length;\n if (!t.tokensAvailable) {\n detail.appendChild(el('p', { class: 'muted', text: 'No token data captured; re-import to backfill.' }));\n } else if (tokenSessions < t.sessionCount) {\n detail.appendChild(el('p', { class: 'muted', text: 'Token data on ' + tokenSessions + ' of ' + t.sessionCount + ' sessions; re-import to backfill the rest.' }));\n }\n var degraded = sessions.filter(function (s) { return s.eventsUnreadable; }).length;\n if (degraded > 0) {\n detail.appendChild(el('p', { class: 'muted', text: degraded + ' session(s) had unreadable event logs; their counts are incomplete.' }));\n }\n detail.appendChild(el('h3', { text: 'Time (human harness labor; active = billing primary)' }));\n var turnSessions = sessions.filter(function (s) { return s.activeTimeBasis === 'engaged-turns'; }).length;\n var basisNote = turnSessions === t.sessionCount ? 'engaged turns' : (turnSessions === 0 ? 'event stream; re-import to capture conversation' : 'engaged turns on ' + turnSessions + ' of ' + t.sessionCount + ' sessions');\n var timeRows = [kvrow('billable active', fmtDur(t.billableActiveTimeMs) + ' (union; ' + basisNote + '; idle gaps > 5m excluded; tz ' + d.timeZone + ')')];\n if (t.activeTimeMs !== t.billableActiveTimeMs) {\n timeRows.push(kvrow('summed', fmtDur(t.activeTimeMs) + ' (concurrent sessions double-counted)'));\n }\n if (t.machineActiveAvailable) {\n var machineSessions = sessions.filter(function (s) { return s.availability && s.availability.machineActive; }).length;\n timeRows.push(kvrow('model working', fmtDur(t.machineActiveTimeMs) + ' (model compute, subset of active; Codex turn duration on ' + machineSessions + ' of ' + t.sessionCount + ' sessions; not wall-clock-deduped)'));\n }\n timeRows.push(kvrow('span', fmtDur(t.sessionSpanMs) + (t.openSessionCount > 0 ? ' (' + t.openSessionCount + ' open)' : '')));\n timeRows.push(kvrow('command', fmtDur(t.commandTimeMs) + (t.commandTimeReliable ? '' : ' (some sessions report 0)')));\n detail.appendChild(el('table', { class: 'kv' }, [el('tbody', {}, timeRows)]));\n if (d.bySource && d.bySource.length) {\n detail.appendChild(el('h3', { text: 'By source' }));\n d.bySource.forEach(function (s) {\n var cmd = s.commandTimeReliable ? fmtDur(s.commandTimeMs) : 'n/a';\n var machine = s.machineActiveAvailable ? ', model ' + fmtDur(s.machineActiveTimeMs) : '';\n detail.appendChild(el('div', { class: 'row' }, [\n el('span', { text: s.sourceKind + ': ' + s.sessionCount + ' sessions, ' + numfmt(s.tokens.output) + ' out tok, active ' + fmtDur(s.activeTimeMs) + machine + ', command ' + cmd })\n ]));\n });\n }\n if (d.byDay && d.byDay.length) {\n detail.appendChild(el('h3', { text: 'By day (billable time x volume)' }));\n d.byDay.forEach(function (day) {\n var dayMachine = day.machineActiveTimeMs > 0 ? ' (model ' + fmtDur(day.machineActiveTimeMs) + ')' : '';\n detail.appendChild(el('div', { class: 'row' }, [\n el('span', { text: day.date + ': ' + fmtDur(day.billableActiveTimeMs) + ' active' + dayMachine + ', ' + numfmt(day.tokens.output) + ' out tok, ' + day.commandCount + ' cmd / ' + day.fileChangedCount + ' files / ' + day.decisionCount + ' dec' })\n ]));\n });\n }\n }).catch(fail);\n }\n\n function loadSessions() {\n single(false);\n fetchJson('/api/sessions').then(function (d) {\n var list = $('list');\n var rows = (d && d.sessions) || [];\n if (rows.length === 0) { list.appendChild(el('div', { class: 'row muted', text: 'no sessions' })); return; }\n rows.forEach(function (s) {\n var row = el('div', { class: 'row', onclick: function () { selectSession(row, s.sessionId); } }, [\n el('div', { text: s.label || s.sessionId }),\n el('div', { class: 'meta', text: s.sourceKind + ' ' + s.status + (s.suspect ? ' suspect' : '') })\n ]);\n list.appendChild(row);\n });\n }).catch(fail);\n }\n function selectSession(row, id) {\n var rows = $('list').querySelectorAll('.row');\n for (var i = 0; i < rows.length; i++) rows[i].classList.remove('active');\n row.classList.add('active');\n var detail = $('detail');\n clear(detail);\n fetchJson('/api/sessions/' + encodeURIComponent(id)).then(function (d) {\n var s = d.session.session;\n detail.appendChild(el('h3', { text: s.label || id }));\n detail.appendChild(kv([\n ['status', s.status], ['source', s.source.kind], ['started', s.started_at],\n ['ended', s.ended_at || '-'], ['workdir', s.working_directory]\n ]));\n if (d.degraded) detail.appendChild(el('p', { class: 'badge warn', text: 'events unreadable' }));\n var events = d.events || [];\n detail.appendChild(el('p', { class: 'muted', text: events.length + ' events' }));\n var tl = el('div', { class: 'tl' }, []);\n events.forEach(function (ev) {\n tl.appendChild(el('div', { class: 'ev' }, [\n el('div', { class: 't', text: ev.occurred_at + ' ' + ev.type }),\n el('div', { text: eventSummary(ev) })\n ]));\n });\n detail.appendChild(tl);\n }).catch(fail);\n }\n function eventSummary(ev) {\n if (ev.type === 'command_executed') {\n var cmd = (ev.args && ev.args.length) ? ev.args.join(' ') : ev.command;\n var ex = (ev.exit_code === null || ev.exit_code === undefined) ? '' : ' (exit ' + ev.exit_code + ')';\n return cmd + ex;\n }\n if (ev.type === 'file_changed') return ev.path + ' [' + ev.change_type + ']';\n if (ev.type === 'decision_recorded') return ev.title || '';\n return '';\n }\n\n function loadTasks() {\n single(false);\n fetchJson('/api/tasks').then(function (d) {\n var list = $('list');\n var rows = (d && d.tasks) || [];\n if (rows.length === 0) { list.appendChild(el('div', { class: 'row muted', text: 'no tasks' })); return; }\n rows.forEach(function (t) {\n var row = el('div', { class: 'row', onclick: function () { selectTask(row, t.id); } }, [\n el('div', { text: t.title || t.label || t.id }),\n el('div', { class: 'meta', text: String(t.status || '') })\n ]);\n list.appendChild(row);\n });\n }).catch(fail);\n }\n function selectTask(row, id) {\n var rows = $('list').querySelectorAll('.row');\n for (var i = 0; i < rows.length; i++) rows[i].classList.remove('active');\n row.classList.add('active');\n var detail = $('detail');\n clear(detail);\n fetchJson('/api/tasks/' + encodeURIComponent(id)).then(function (d) {\n detail.appendChild(el('h3', { text: (d.task && (d.task.title || d.task.label)) || id }));\n detail.appendChild(el('pre', { text: JSON.stringify(d.task, null, 2) }));\n if (d.body) detail.appendChild(el('pre', { text: d.body }));\n }).catch(fail);\n }\n\n function loadMarkdown(path, label) {\n single(true);\n fetchJson(path).then(function (d) {\n var detail = $('detail');\n var count = (typeof d.decisionCount === 'number') ? (' (' + d.decisionCount + ' decisions)') : '';\n detail.appendChild(el('p', { class: 'muted', text: label + count }));\n detail.appendChild(el('pre', { text: (d && d.body) || '(empty)' }));\n }).catch(fail);\n }\n\n function loadApprovals() {\n single(true);\n fetchJson('/api/approvals').then(function (d) {\n var detail = $('detail');\n var groups = [['pending', d.pending || []], ['resolved', d.resolved || []]];\n groups.forEach(function (g) {\n detail.appendChild(el('h3', { text: g[0] + ' (' + g[1].length + ')' }));\n if (g[1].length === 0) { detail.appendChild(el('p', { class: 'muted', text: 'none' })); return; }\n g[1].forEach(function (a) {\n detail.appendChild(el('div', { class: 'row' }, [\n el('span', { text: a.id + ' ' }),\n el('span', { class: a.expired ? 'badge warn' : 'badge', text: a.expired ? 'expired' : (a.approval && a.approval.status) || '' })\n ]));\n });\n });\n }).catch(fail);\n }\n\n function kv(pairs) {\n var tbody = el('tbody', {}, pairs.map(function (p) {\n return el('tr', {}, [el('td', { class: 'k', text: p[0] }), el('td', { text: String(p[1]) })]);\n }));\n return el('table', { class: 'kv' }, [tbody]);\n }\n\n // --- wire up ------------------------------------------------------------\n\n $('btn-refresh').addEventListener('click', function () { post('/api/refresh', 'Refresh all'); });\n $('btn-import-claude').addEventListener('click', function () { post('/api/import/claude-code', 'Import claude-code'); });\n $('btn-import-codex').addEventListener('click', function () { post('/api/import/codex', 'Import codex'); });\n $('btn-gen-handoff').addEventListener('click', function () { post('/api/handoff/generate', 'Regenerate handoff'); });\n $('btn-gen-decisions').addEventListener('click', function () { post('/api/decisions/generate', 'Regenerate decisions'); });\n\n buildTabs();\n loadTab('overview');\n})();\n</script>\n</body>\n</html>`;\n","import { isVerbose, renderCliError } from \"./lib/error-render.js\";\nimport { buildProgram } from \"./program.js\";\n\n// Thin binary entry: construction lives in the side-effect-free ./program.ts\n// (so the docs generator can import `buildProgram` and introspect the command\n// surface without triggering a parse); this file owns the single argv parse.\nconst program = buildProgram();\n\nprogram.parseAsync(process.argv).catch((err: unknown) => {\n // Top-level safety net: never print the Error object directly because\n // Node's util.inspect recursively expands `error.cause`, which can carry\n // absolute paths from native fs errors. Delegates to the shared pathless\n // renderer; verbose mode is gated on BASOU_DEBUG only since the failure\n // bypassed the subcommand handler that owns the `-v` flag.\n renderCliError(err, { verbose: isVerbose(undefined) });\n process.exit(1);\n});\n"],"mappings":"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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","names":["program","id","assertBasouRootSafe","basouPaths","findErrorCode","prefixedUlid","resolveRepositoryRoot","program","basouPaths","assertWorkspaceInitialized","prefixedUlid","resolveRepositoryRoot","assertBasouRootSafe","findErrorCode","assertBasouRootSafe","basouPaths","findErrorCode","resolveRepositoryRoot","program","basouPaths","assertWorkspaceInitialized","resolveRepositoryRoot","assertBasouRootSafe","findErrorCode","join","assertBasouRootSafe","basouPaths","prefixedUlid","readManifest","readYamlFile","resolveRepositoryRoot","program","appendEvent","basouPaths","assertBasouRootSafe","readManifest","prefixedUlid","join","readYamlFile","resolveRepositoryRoot","assertBasouRootSafe","basouPaths","findErrorCode","readMarkdownFile","renderWithMarkers","resolveRepositoryRoot","writeMarkdownFile","program","basouPaths","assertWorkspaceInitialized","readMarkdownFile","renderWithMarkers","writeMarkdownFile","resolveRepositoryRoot","assertBasouRootSafe","findErrorCode","homedir","join","assertBasouRootSafe","basouPaths","findErrorCode","readManifest","resolveRepositoryRoot","SES_PREFIX","SHORT_ID_LEN","program","join","homedir","basouPaths","assertWorkspaceInitialized","readManifest","payload","findErrorCode","shortId","resolveRepositoryRoot","assertBasouRootSafe","basename","resolve","resolveRepositoryRoot","program","basename","resolve","resolveRepositoryRoot","assertBasouRootSafe","basouPaths","findErrorCode","resolveRepositoryRoot","InvalidArgumentError","readMarkdownFile","renderDecisions","renderHandoff","renderWithMarkers","writeMarkdownFile","renderHandoff","readMarkdownFile","writeMarkdownFile","renderWithMarkers","renderDecisions","readdir","stat","homedir","join","findErrorCode","join","homedir","readdir","findErrorCode","stat","collectPath","InvalidArgumentError","resolve","program","basouPaths","assertWorkspaceInitialized","resolveRepositoryRoot","assertBasouRootSafe","findErrorCode","mkdir","homedir","join","assertBasouRootSafe","basouPaths","ChildProcessRunner","coreAppendEvent","getSnapshot","overwriteYamlFile","prefixedUlid","readManifest","readYamlFile","resolveRepositoryRoot","SessionSchema","sanitizeWorkingDirectory","writeYamlFile","program","ChildProcessRunner","appendEvent","coreAppendEvent","basouPaths","assertBasouRootSafe","readManifest","prefixedUlid","join","mkdir","buildInitialSession","writeYamlFile","tryAppendGitSnapshot","mutateSessionYaml","finalizeSessionAsFailed","homedir","decideFinalStatus","signalToExitCode","SIGNUM_MAP","getSnapshot","normalizeGitSnapshotSkipMessage","sanitizeWorkingDirectory","readYamlFile","SessionSchema","overwriteYamlFile","resolveRepositoryRoot","readFile","basename","join","relative","acquireLock","appendEventToExistingSession","assertBasouRootSafe","basouPaths","findErrorCode","importSessionFromJson","readManifest","readYamlFile","resolveRepositoryRoot","resolveSessionId","SessionImportPayloadSchema","SessionSchema","InvalidArgumentError","SES_PREFIX","TASK_PREFIX","SHORT_ID_BASE_LEN","SHORT_ID_MAX_LEN","STATUS_VALUES","program","basouPaths","assertWorkspaceInitialized","resolveSessionId","join","readYamlFile","SessionSchema","findErrorCode","computeUniquePrefixLen","sliceShort","maxLen","pad","relative","shortTaskId","shortId","resolveRepositoryRoot","assertBasouRootSafe","readManifest","SessionImportPayloadSchema","importOptions","importSessionFromJson","readFile","InvalidArgumentError","basename","acquireLock","appendEventToExistingSession","assertBasouRootSafe","basouPaths","findErrorCode","resolveRepositoryRoot","program","basouPaths","assertWorkspaceInitialized","resolveRepositoryRoot","assertBasouRootSafe","findErrorCode","assertBasouRootSafe","basouPaths","findErrorCode","readManifest","resolveRepositoryRoot","program","basouPaths","assertBasouRootSafe","findErrorCode","readManifest","resolveRepositoryRoot","readFile","join","assertBasouRootSafe","basouPaths","findErrorCode","loadSessionEntries","prefixedUlid","readManifest","replayEvents","resolveRepositoryRoot","resolveSessionId","resolveTaskId","InvalidArgumentError","STATUS_VALUES","program","parseTitle","parsePositiveInt","basouPaths","assertWorkspaceInitialized","prefixedUlid","resolveSessionId","result","readManifest","maxLen","pad","resolveTaskId","loadSessionEntries","join","replayEvents","createInterface","InvalidArgumentError","readFile","findErrorCode","resolveRepositoryRoot","assertBasouRootSafe","assertBasouRootSafe","basouPaths","findErrorCode","resolveRepositoryRoot","InvalidArgumentError","join","computeWorkStats","enumerateApprovals","findErrorCode","isLazyExpired","loadApproval","loadSessionEntries","loadTaskEntries","readAllEvents","readManifest","readMarkdownFile","readSessionYaml","readTaskFile","renderDecisions","renderHandoff","resolve","computeWorkStats","readManifest","findErrorCode","renderHandoff","enumerateApprovals","loadSessionEntries","readSessionYaml","readAllEvents","join","loadTaskEntries","readTaskFile","readMarkdownFile","renderDecisions","loadApproval","isLazyExpired","InvalidArgumentError","program","basouPaths","assertWorkspaceInitialized","findErrorCode","resolve","resolveRepositoryRoot","assertBasouRootSafe","require","program"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/error-render.ts","../src/program.ts","../src/commands/approval.ts","../src/commands/decision.ts","../src/commands/decisions.ts","../src/commands/exec.ts","../src/commands/handoff.ts","../src/commands/import.ts","../src/commands/init.ts","../src/commands/refresh.ts","../src/lib/provenance-actions.ts","../src/commands/refresh-watch.ts","../src/commands/run.ts","../src/commands/session.ts","../src/lib/format-duration.ts","../src/commands/stats.ts","../src/commands/status.ts","../src/commands/task.ts","../src/commands/verify.ts","../src/commands/view.ts","../src/lib/view-server.ts","../src/lib/view-ui.ts","../src/index.ts"],"sourcesContent":["import {\n FailedToFinalizeError,\n type ReplayWarning,\n type SessionSkipReason,\n type TaskSkipReason,\n} from \"@basou/core\";\n\n// ============================================================================\n// Short-id helpers\n// ============================================================================\n\nconst SES_PREFIX = \"ses_\";\nconst TASK_PREFIX = \"task_\";\nconst SHORT_ID_LEN = 6;\n\n/**\n * Strip the `ses_` prefix and slice the first {@link SHORT_ID_LEN} chars of\n * the ULID body for human-readable session identification in CLI output.\n * IDs without the prefix are sliced from offset 0.\n */\nexport function shortSessionId(id: string): string {\n if (id.startsWith(SES_PREFIX))\n return id.slice(SES_PREFIX.length, SES_PREFIX.length + SHORT_ID_LEN);\n return id.slice(0, SHORT_ID_LEN);\n}\n\n/**\n * Same as {@link shortSessionId} but for `task_<ULID>` ids.\n */\nexport function shortTaskId(id: string): string {\n if (id.startsWith(TASK_PREFIX))\n return id.slice(TASK_PREFIX.length, TASK_PREFIX.length + SHORT_ID_LEN);\n return id.slice(0, SHORT_ID_LEN);\n}\n\n// ============================================================================\n// Verbose mode detection\n// ============================================================================\n\n/**\n * Unified verbose-mode predicate: `options.verbose === true` OR the\n * `BASOU_DEBUG=1` environment variable. CLI surfaces use this everywhere\n * the verbose error / cause label rendering needs a yes/no answer.\n */\nexport function isVerbose(options: { verbose?: boolean } | undefined): boolean {\n return options?.verbose === true || process.env.BASOU_DEBUG === \"1\";\n}\n\n// ============================================================================\n// Cause-chain walk (pathless)\n// ============================================================================\n\nconst CAUSE_CHAIN_MAX_DEPTH = 4;\n\n/**\n * Walk the cause chain (up to {@link CAUSE_CHAIN_MAX_DEPTH} hops) and return\n * the first errno-style `code` found, falling back to the deepest\n * constructor name. The value goes into `Caused by: <label>` so verbose\n * output stays pathless even when capability layers wrap native errors.\n *\n * Returns `undefined` when `error.cause` is not itself an Error (= no chain\n * to walk).\n */\nexport function extractCauseLabel(error: Error): string | undefined {\n let current: unknown = error.cause;\n let constructorName: string | undefined;\n for (let depth = 0; depth < CAUSE_CHAIN_MAX_DEPTH; depth += 1) {\n if (!(current instanceof Error)) break;\n const code = (current as Error & { code?: unknown }).code;\n if (typeof code === \"string\" && code.length > 0) return code;\n constructorName = current.constructor.name;\n current = current.cause;\n }\n return constructorName;\n}\n\n// ============================================================================\n// Pluggable classifier interface\n// ============================================================================\n\n/**\n * Plug-in for command-specific error rendering. {@link renderCliError}\n * invokes every classifier whose {@link match} returns true and emits each\n * line returned by {@link additionalLines} after the main `error.message`\n * line. Classifiers MUST keep their lines pathless — no absolute paths, no\n * `cause.message` echo.\n */\nexport interface ErrorClassifier {\n match(error: Error): boolean;\n additionalLines(error: Error): readonly string[];\n}\n\n/**\n * Shared classifier for {@link FailedToFinalizeError}. Both `task.ts` and\n * `decision.ts` need exactly the same two warning lines — the session.yaml\n * status update failed AFTER the target event was already written, so the\n * operator must NOT retry the command.\n */\nexport const failedToFinalizeClassifier: ErrorClassifier = {\n match: (error) => error instanceof FailedToFinalizeError,\n additionalLines: (error) => {\n const e = error as FailedToFinalizeError;\n const sid = shortSessionId(e.sessionId);\n // `targetEventIds[0]` is the operator-facing anchor event (= the\n // `decision_recorded` / `task_created` / `task_reconciled` event the\n // command was meant to produce). Multi-target ad-hoc sessions (e.g.\n // `task new --status done` which adds `task_status_changed`) carry the\n // additional ids in `targetEventIds[1..]`; one anchor is enough for the\n // do-not-rerun warning.\n const anchor = e.targetEventIds[0];\n return [\n `Recorded ${anchor} in session ${sid}; do not rerun`,\n \"Warning: session.yaml status update failed; events.jsonl is consistent\",\n ];\n },\n};\n\n// ============================================================================\n// Generic CLI error renderer\n// ============================================================================\n\n/**\n * Render an unknown thrown value to stderr without leaking absolute paths.\n *\n * Always prints `error.message` first, then any classifier-emitted lines,\n * and finally — in verbose mode — a single `Caused by: <label>` line where\n * `<label>` is the first errno code found while walking `error.cause` (or\n * the deepest constructor name as a fallback). The error's `cause.message`\n * is intentionally never printed because Node's native fs errors embed\n * absolute paths there.\n *\n * Non-Error values are coerced via `String(error)` so the catch-all fallback\n * in `program.parseAsync().catch(...)` still produces something readable.\n */\nexport function renderCliError(\n error: unknown,\n options: { verbose: boolean; classifiers?: readonly ErrorClassifier[] },\n): void {\n if (!(error instanceof Error)) {\n console.error(String(error));\n return;\n }\n console.error(error.message);\n for (const classifier of options.classifiers ?? []) {\n if (classifier.match(error)) {\n for (const line of classifier.additionalLines(error)) console.error(line);\n }\n }\n if (options.verbose) {\n const label = extractCauseLabel(error);\n if (label !== undefined) console.error(`Caused by: ${label}`);\n }\n}\n\n// ============================================================================\n// Warning surface helpers\n// ============================================================================\n\n/**\n * Print a `ReplayWarning` on stderr in the canonical short form used by\n * every command that consumes the event-replay stream (= task / handoff /\n * decisions / etc.). The session id is shortened via {@link shortSessionId}\n * for readability.\n */\nexport function printReplayWarning(warning: ReplayWarning, sessionId: string): void {\n const short = shortSessionId(sessionId);\n switch (warning.kind) {\n case \"partial_trailing_line\":\n console.error(`Warning: ignored partial trailing line in ${short}/events.jsonl`);\n break;\n case \"malformed_json\":\n console.error(\n `Warning: skipped malformed JSON at line ${warning.line} in ${short}/events.jsonl`,\n );\n break;\n case \"schema_violation\":\n console.error(\n `Warning: skipped invalid event at line ${warning.line} in ${short}/events.jsonl`,\n );\n break;\n }\n}\n\n/**\n * Print a session-skip warning in the \"scan\" form used by handoff / decisions\n * generators: `events_jsonl_unreadable` is mapped to the standardised\n * suspect-check warning used elsewhere in the CLI, every other reason falls\n * through to a generic `Skipped <sid>: <reason>` form preserving the raw\n * enum value.\n */\nexport function printSessionSkip(sid: string, reason: SessionSkipReason): void {\n const short = shortSessionId(sid);\n if (reason === \"events_jsonl_unreadable\") {\n console.error(`Warning: skipped suspect check for ${short}: events.jsonl unreadable`);\n } else {\n console.error(`Skipped ${short}: ${reason}`);\n }\n}\n\n/**\n * Print a session-skip warning in the \"list\" form used by `session list`.\n * Each reason is mapped to a user-friendly English phrase rather than the\n * raw enum value. `events_jsonl_unreadable` shares the wording produced by\n * {@link printSessionSkip} so the CLI surface stays consistent across\n * subcommands.\n */\nexport function printSessionListSkip(sid: string, reason: SessionSkipReason): void {\n const short = shortSessionId(sid);\n switch (reason) {\n case \"session_yaml_missing\":\n console.error(`Skipped ${short}: session.yaml not found`);\n break;\n case \"session_yaml_invalid\":\n console.error(`Skipped ${short}: invalid session schema`);\n break;\n case \"events_jsonl_unreadable\":\n console.error(`Warning: skipped suspect check for ${short}: events.jsonl unreadable`);\n break;\n }\n}\n\n/**\n * Print a task-skip warning shared between `task list` (which sees a\n * narrowed {@link TaskSkipReason} enum) and handoff / decisions generators\n * (which may forward an arbitrary reason string). Accepts a plain `string`\n * so both shapes route through the same renderer.\n */\nexport function printTaskSkip(taskId: string, reason: TaskSkipReason | string): void {\n console.error(`Skipped ${shortTaskId(taskId)}: ${reason}`);\n}\n","import { createRequire } from \"node:module\";\nimport { Command } from \"commander\";\nimport { registerApprovalCommand } from \"./commands/approval.js\";\nimport { registerDecisionCommand } from \"./commands/decision.js\";\nimport { registerDecisionsCommand } from \"./commands/decisions.js\";\nimport { registerExecCommand } from \"./commands/exec.js\";\nimport { registerHandoffCommand } from \"./commands/handoff.js\";\nimport { registerImportCommand } from \"./commands/import.js\";\nimport { registerInitCommand } from \"./commands/init.js\";\nimport { registerRefreshCommand } from \"./commands/refresh.js\";\nimport { registerRunCommand } from \"./commands/run.js\";\nimport { registerSessionCommand } from \"./commands/session.js\";\nimport { registerStatsCommand } from \"./commands/stats.js\";\nimport { registerStatusCommand } from \"./commands/status.js\";\nimport { registerTaskCommand } from \"./commands/task.js\";\nimport { registerVerifyCommand } from \"./commands/verify.js\";\nimport { registerViewCommand } from \"./commands/view.js\";\n\n// Read the CLI release version directly from the sibling package.json so\n// `basou --version` cannot drift past a future package-bump (the v0.2/v0.3\n// releases both shipped with a stale \"0.1.0\" constant before the dynamic\n// read landed). The relative path is stable across the dev (src/program.ts\n// → src/../package.json) and built (dist/program.js → dist/../package.json)\n// layouts, since both files sit one directory below the package root.\nconst require = createRequire(import.meta.url);\nconst pkg = require(\"../package.json\") as { version: string };\nexport const BASOU_CLI_VERSION = pkg.version;\n\n/**\n * Build the fully-registered `basou` command tree WITHOUT parsing argv.\n *\n * This is the side-effect-free entry shared by the CLI binary (./index.ts)\n * and any introspection consumer — e.g. the docs generator that renders the\n * command reference from the published `@basou/cli`. Importing this module\n * must never parse `process.argv` or run a command action; `index.ts` owns\n * the single `parseAsync` call.\n */\nexport function buildProgram(): Command {\n const program = new Command();\n program\n .name(\"basou\")\n .description(\"Provenance layer for AI development\")\n .version(BASOU_CLI_VERSION)\n // Required so that `basou exec` (and any other passThroughOptions\n // subcommand) can forward unknown flags to the wrapped child.\n .enablePositionalOptions();\n\n registerInitCommand(program);\n registerStatusCommand(program);\n registerStatsCommand(program);\n registerExecCommand(program);\n registerRunCommand(program);\n registerSessionCommand(program);\n registerImportCommand(program);\n registerRefreshCommand(program);\n registerVerifyCommand(program);\n registerViewCommand(program);\n registerApprovalCommand(program);\n registerDecisionCommand(program);\n registerTaskCommand(program);\n registerHandoffCommand(program);\n registerDecisionsCommand(program);\n\n return program;\n}\n","import { unlink } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport {\n type Approval,\n type ApprovalLocation,\n ApprovalSchema,\n type ApprovalStatus,\n ApprovalStatusSchema,\n acquireLock,\n appendChainedEventLocked,\n assertBasouRootSafe,\n type BasouPaths,\n basouPaths,\n type Event,\n enumerateApprovals,\n findErrorCode,\n isLazyExpired,\n linkYamlFile,\n loadApproval,\n prefixedUlid,\n readSessionYaml,\n readYamlFile,\n replayEvents,\n resolveRepositoryRoot,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport { isVerbose, printReplayWarning, renderCliError } from \"../lib/error-render.js\";\n\nconst APPR_PREFIX = \"appr_\";\nconst SHORT_ID_BASE_LEN = 6;\nconst SHORT_ID_MAX_LEN = 26; // ULID body length\nconst ACTION_KEY_DETAIL_MAX_LEN = 60;\nconst REASON_TEXT_MAX_LEN = 80;\n\nconst STATUS_VALUES = ApprovalStatusSchema.options;\n\nexport type ApprovalListOptions = {\n json?: boolean;\n status?: ApprovalStatus;\n verbose?: boolean;\n};\n\nexport type ApprovalShowOptions = {\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type ApprovalApproveOptions = {\n note?: string;\n verbose?: boolean;\n};\n\nexport type ApprovalRejectOptions = {\n reason: string;\n verbose?: boolean;\n};\n\nexport type ApprovalContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n};\n\ntype ApprovalListRecord = {\n approval: Approval;\n location: ApprovalLocation;\n lazyExpired: boolean;\n};\n\n/**\n * Wire `basou approval list / show / approve / reject` onto `program`.\n *\n * The `approval` group is registered up front so future subcommands\n * (`cancel`, `recover`) added in later steps slot under the same group\n * without changing the externally visible CLI surface.\n */\nexport function registerApprovalCommand(program: Command): void {\n const approval = program\n .command(\"approval\")\n .description(\"Manage Basou approval requests under .basou/approvals/\");\n\n approval\n .command(\"list\")\n .description(\"List approvals across pending and resolved (newest first)\")\n .option(\"--json\", \"Output the list as a JSON array\")\n .option(\n \"--status <state>\",\n `Filter by approval status (one of: ${STATUS_VALUES.join(\", \")})`,\n parseApprovalStatus,\n )\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: ApprovalListOptions) => {\n await runApprovalList(options);\n });\n\n approval\n .command(\"show <id>\")\n .description(\"Show an approval's metadata and related events\")\n .option(\"--json\", \"Output the approval and events as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (id: string, options: ApprovalShowOptions) => {\n await runApprovalShow(id, options);\n });\n\n approval\n .command(\"approve <id>\")\n .description(\"Approve a pending approval\")\n .option(\"--note <text>\", \"Optional note to attach to the approval_approved event\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (id: string, options: ApprovalApproveOptions) => {\n await runApprovalApprove(id, options);\n });\n\n approval\n .command(\"reject <id>\")\n .description(\"Reject a pending approval\")\n .requiredOption(\"--reason <text>\", \"Reason for rejection (required)\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (id: string, options: ApprovalRejectOptions) => {\n await runApprovalReject(id, options);\n });\n}\n\n// === list ===\n\n/**\n * Programmatic entry for `basou approval list` that owns process exit\n * state. Tests targeting only the success path or the thrown error should\n * prefer {@link doRunApprovalList}.\n */\nexport async function runApprovalList(\n options: ApprovalListOptions,\n ctx: ApprovalContext = {},\n): Promise<void> {\n try {\n await doRunApprovalList(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * Pure runner for `approval list`. Throws on any failure with a pathless\n * message; native errors are attached as `cause` for verbose surfacing.\n */\nexport async function doRunApprovalList(\n options: ApprovalListOptions,\n ctx: ApprovalContext,\n): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForApproval(cwd, \"list\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const ids = await enumerateApprovals(paths);\n // A single `now` shared across every record so that two reads on the\n // same boundary instant cannot disagree (e.g. one record flagged expired\n // and another not when both straddle the same `expires_at`).\n const now = new Date();\n const records: ApprovalListRecord[] = [];\n\n // Resolve dedupe set: id appearing in both directories → prefer resolved\n // and surface a stderr warning about the stale pending entry.\n const resolvedSet = new Set(ids.resolved);\n for (const id of ids.pending) {\n if (resolvedSet.has(id)) {\n console.error(`Warning: stale pending entry for ${shortId(id)}; resolved version preferred`);\n continue;\n }\n const rec = await readApprovalListRecord(paths, id, \"pending\", now);\n if (rec !== null) records.push(rec);\n }\n for (const id of ids.resolved) {\n const rec = await readApprovalListRecord(paths, id, \"resolved\", now);\n if (rec !== null) records.push(rec);\n }\n\n records.sort((a, b) => Date.parse(b.approval.created_at) - Date.parse(a.approval.created_at));\n\n const filtered =\n options.status !== undefined\n ? records.filter((r) => r.approval.status === options.status)\n : records;\n\n if (filtered.length === 0) {\n printNoApprovals(options);\n return;\n }\n\n if (options.json === true) {\n console.log(\n JSON.stringify(\n filtered.map((r) => ({ ...r.approval, lazy_expired: r.lazyExpired })),\n null,\n 2,\n ),\n );\n } else {\n printApprovalListText(filtered);\n }\n}\n\nasync function readApprovalListRecord(\n paths: BasouPaths,\n id: string,\n location: ApprovalLocation,\n now: Date,\n): Promise<ApprovalListRecord | null> {\n const filePath = join(paths.approvals[location], `${id}.yaml`);\n let raw: unknown;\n try {\n raw = await readYamlFile(filePath);\n } catch (error: unknown) {\n console.error(`Skipped ${shortId(id)}: ${describeReadError(error)}`);\n return null;\n }\n const parse = ApprovalSchema.safeParse(raw);\n if (!parse.success) {\n console.error(`Skipped ${shortId(id)}: invalid approval schema`);\n return null;\n }\n if (parse.data.id !== id) {\n // Surface a stderr warning rather than dropping silently so an operator\n // can spot the corrupted entry from `basou approval list`.\n console.error(`Skipped ${shortId(id)}: filename and YAML body id disagree`);\n return null;\n }\n const approval = parse.data;\n return { approval, location, lazyExpired: isLazyExpired(approval, now) };\n}\n\n// === show ===\n\nexport async function runApprovalShow(\n idInput: string,\n options: ApprovalShowOptions,\n ctx: ApprovalContext = {},\n): Promise<void> {\n try {\n await doRunApprovalShow(idInput, options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunApprovalShow(\n idInput: string,\n options: ApprovalShowOptions,\n ctx: ApprovalContext,\n): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForApproval(cwd, \"show\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const { id } = await resolveApprovalId(paths, idInput);\n const loaded = await loadApproval(paths, id);\n if (loaded === null) {\n throw new Error(`Approval not found: ${idInput}`);\n }\n\n // events.jsonl I/O failure throws \"Failed to read events.jsonl\" and is\n // converted to exit 1 by the wrapping try/catch — partial / malformed /\n // schema warnings stream through onWarning.\n const sessionDir = join(paths.sessions, loaded.approval.session_id);\n const relatedEvents: Event[] = [];\n for await (const ev of replayEvents(sessionDir, {\n onWarning: (w) => printReplayWarning(w, loaded.approval.session_id),\n })) {\n if (isApprovalEvent(ev) && ev.approval_id === id) {\n relatedEvents.push(ev);\n }\n }\n\n const now = new Date();\n const lazyExpired = isLazyExpired(loaded.approval, now);\n\n if (options.json === true) {\n console.log(\n JSON.stringify(\n {\n approval: { ...loaded.approval, lazy_expired: lazyExpired },\n events: relatedEvents,\n },\n null,\n 2,\n ),\n );\n return;\n }\n\n printApprovalShowText(loaded.approval, loaded.location, relatedEvents, lazyExpired);\n}\n\n// === approve / reject ===\n\nexport async function runApprovalApprove(\n idInput: string,\n options: ApprovalApproveOptions,\n ctx: ApprovalContext = {},\n): Promise<void> {\n try {\n await doRunApprovalResolve(idInput, options, ctx, \"approve\");\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\nexport async function runApprovalReject(\n idInput: string,\n options: ApprovalRejectOptions,\n ctx: ApprovalContext = {},\n): Promise<void> {\n try {\n await doRunApprovalResolve(idInput, options, ctx, \"reject\");\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\nasync function doRunApprovalResolve(\n idInput: string,\n options: ApprovalApproveOptions | ApprovalRejectOptions,\n ctx: ApprovalContext,\n decision: \"approve\" | \"reject\",\n): Promise<void> {\n if (decision === \"reject\") {\n const reason = (options as ApprovalRejectOptions).reason;\n if (reason.length === 0) {\n throw new Error(\"--reason must not be empty\");\n }\n }\n\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForApproval(cwd, decision);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n // Step D-2: resolve id (search both directories).\n const { id, location } = await resolveApprovalId(paths, idInput);\n\n // Step D-3: a resolved-side hit means there is nothing left to decide.\n if (location === \"resolved\") {\n throw new Error(`Approval already resolved: ${idInput}`);\n }\n\n // Step D-4: read + parse the pending YAML.\n const pendingPath = join(paths.approvals.pending, `${id}.yaml`);\n let pendingRaw: unknown;\n try {\n pendingRaw = await readYamlFile(pendingPath);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"YAML file not found\") {\n throw new Error(`Approval not found: ${idInput}`);\n }\n throw new Error(\"Failed to read approval\", { cause: error });\n }\n // Wrap zod's parse so a malformed pending YAML surfaces through the\n // pathless `Failed to read approval` contract instead of leaking a raw\n // ZodError through the rendered output.\n const approvalParse = ApprovalSchema.safeParse(pendingRaw);\n if (!approvalParse.success) {\n throw new Error(\"Failed to read approval\", { cause: approvalParse.error });\n }\n const approval = approvalParse.data;\n // Defensive id check (matches loadApproval): filename id and body id\n // must agree, otherwise we'd resolve one approval while emitting events\n // for another.\n if (approval.id !== id) {\n throw new Error(\"Failed to read approval\", {\n cause: new Error(`Approval id mismatch: filename id ${id} vs YAML body id ${approval.id}`),\n });\n }\n // A pending-side YAML whose status is no longer `pending` means the\n // file was corrupted (or hand-edited mid-resolution). Refuse to fire a\n // second resolution event for it.\n if (approval.status !== \"pending\") {\n throw new Error(`Approval status mismatch: pending YAML has status=${approval.status}`);\n }\n\n // Step D-6/D-7 timestamps + event id, computed up front so they are shared\n // with the resolved-side YAML (Step D-9, built after the lock is released).\n const now = new Date();\n const occurredAt = now.toISOString();\n const eventId = prefixedUlid(\"evt\");\n\n // Hold the session lock across the replay fence and the resolution append so\n // two concurrent resolvers cannot both pass the fence before either appends\n // (closing a pre-existing double-resolution race) and so the resolution line\n // chains onto the session's on-disk tail. The caller owns the critical\n // section, so the lock-assumed append primitive is used here.\n const sessionLock = await acquireLock(paths, \"session\", approval.session_id);\n try {\n // Step D-5: events.jsonl fence — if a resolution event already exists\n // for this approval, refuse to fire a second one. This guards the\n // crash-mid-orchestration window where step 8 succeeded but step 10\n // failed (events.jsonl is the source-of-truth, not the YAML mirror).\n const sessionDir = join(paths.sessions, approval.session_id);\n for await (const ev of replayEvents(sessionDir, {\n onWarning: (w) => printReplayWarning(w, approval.session_id),\n })) {\n if (\n isApprovalEvent(ev) &&\n ev.approval_id === approval.id &&\n (ev.type === \"approval_approved\" ||\n ev.type === \"approval_rejected\" ||\n ev.type === \"approval_expired\")\n ) {\n throw new Error(`Approval already resolved (per events.jsonl): ${idInput}`);\n }\n }\n\n // Step D-6: lazy expire state-fence. No event is fired here; the\n // approval_expired event is reserved for a later step that owns\n // expiry-side orchestration.\n if (isLazyExpired(approval, now)) {\n throw new Error(`Approval already expired: ${idInput}`);\n }\n\n // Step D-6b: attachable-status fence. An approval is resolved while its\n // session is still live (initialized / running / waiting_approval). Refuse\n // any other status — matching every other attach path — so a resolution\n // line is never chained onto a finalized (anchored) or imported log, which\n // `verify` would otherwise read as tampered (the at-rest anchor would no\n // longer match the extended log). Only a positively read non-attachable\n // status blocks; a missing or unreadable session.yaml falls through to the\n // pre-existing behavior.\n let sessionStatus: string | null = null;\n try {\n sessionStatus = (await readSessionYaml(paths, approval.session_id)).session.status;\n } catch {\n sessionStatus = null;\n }\n const attachable =\n sessionStatus === \"initialized\" ||\n sessionStatus === \"running\" ||\n sessionStatus === \"waiting_approval\";\n if (sessionStatus !== null && !attachable) {\n throw new Error(\n `Cannot resolve an approval for a session that is not active (status=${sessionStatus}): ${idInput}`,\n );\n }\n\n // Step D-8: append the resolution event to events.jsonl, chained onto the\n // on-disk tail. After this point the trail is committed; subsequent\n // failures must not roll back the event (the source-of-truth invariant).\n if (decision === \"approve\") {\n const note = (options as ApprovalApproveOptions).note ?? null;\n await appendChainedEventLocked(paths, approval.session_id, {\n schema_version: \"0.1.0\",\n id: eventId,\n session_id: approval.session_id,\n occurred_at: occurredAt,\n source: \"local-cli\",\n type: \"approval_approved\",\n approval_id: approval.id,\n resolver: \"local-cli\",\n note,\n });\n } else {\n const reason = (options as ApprovalRejectOptions).reason;\n await appendChainedEventLocked(paths, approval.session_id, {\n schema_version: \"0.1.0\",\n id: eventId,\n session_id: approval.session_id,\n occurred_at: occurredAt,\n source: \"local-cli\",\n type: \"approval_rejected\",\n approval_id: approval.id,\n resolver: \"local-cli\",\n reason,\n });\n }\n } finally {\n await sessionLock.release();\n }\n\n // Step D-9: build the resolved-side YAML body in memory.\n const resolvedApproval: Approval =\n decision === \"approve\"\n ? {\n ...approval,\n status: \"approved\",\n resolver: \"local-cli\",\n resolved_at: occurredAt,\n note: (options as ApprovalApproveOptions).note ?? null,\n }\n : {\n ...approval,\n status: \"rejected\",\n resolver: \"local-cli\",\n resolved_at: occurredAt,\n rejection_reason: (options as ApprovalRejectOptions).reason,\n };\n\n // Step D-10: create-only write. linkYamlFile fails fast with EEXIST if a\n // concurrent resolver already populated the resolved-side YAML — the\n // events.jsonl fence above should have caught it first, so reaching\n // EEXIST here implies a near-simultaneous race we surface explicitly.\n const resolvedPath = join(paths.approvals.resolved, `${id}.yaml`);\n try {\n await linkYamlFile(resolvedPath, resolvedApproval);\n } catch (error: unknown) {\n const cause = error instanceof Error ? error.cause : undefined;\n if (cause instanceof Error && (cause as Error & { code?: unknown }).code === \"EEXIST\") {\n throw new Error(\"Approval already resolved at the same time\", { cause });\n }\n throw error;\n }\n\n // Step D-11: best-effort unlink of the pending YAML. The trail and the\n // resolved-side YAML are already consistent at this point; a leftover\n // pending entry is reconciled by the next `approval list`'s dedupe.\n try {\n await unlink(pendingPath);\n } catch {\n console.error(\n `Warning: failed to unlink pending entry for ${shortId(id)}; events.jsonl is consistent`,\n );\n }\n\n // Step D-12: success message.\n const verb = decision === \"approve\" ? \"Approved\" : \"Rejected\";\n console.log(`${verb} approval ${shortId(id)}`);\n}\n\n// === helpers ===\n\nasync function resolveApprovalId(\n paths: BasouPaths,\n input: string,\n): Promise<{ id: string; location: ApprovalLocation }> {\n const trimmed = input.trim();\n if (trimmed.length === 0) {\n throw new Error(\"Approval id is empty\");\n }\n const normalized = trimmed.startsWith(APPR_PREFIX) ? trimmed : `${APPR_PREFIX}${trimmed}`;\n // Reject prefix-only input so a bare prefix cannot match an arbitrary\n // approval via `startsWith`.\n if (normalized.length <= APPR_PREFIX.length) {\n throw new Error(`Approval not found: ${input}`);\n }\n\n const enumeration = await enumerateApprovals(paths);\n\n // Aggregate by full id so a duplicate (same id in both pending and\n // resolved) collapses to one entry with location=resolved (preferred).\n const byId = new Map<string, ApprovalLocation>();\n for (const id of enumeration.pending) {\n if (id.startsWith(normalized)) byId.set(id, \"pending\");\n }\n for (const id of enumeration.resolved) {\n if (!id.startsWith(normalized)) continue;\n if (byId.get(id) === \"pending\") {\n // Same full id present on both sides: resolved wins, surface a warning.\n console.error(`Warning: stale pending entry for ${shortId(id)}; resolved version preferred`);\n }\n byId.set(id, \"resolved\");\n }\n\n if (byId.size === 0) {\n throw new Error(`Approval not found: ${input}`);\n }\n if (byId.size > 1) {\n throw new Error(\n `Ambiguous approval id '${input}': matched ${byId.size} approvals. Disambiguate with a longer prefix.`,\n );\n }\n const first = byId.entries().next().value;\n if (first === undefined) {\n throw new Error(`Approval not found: ${input}`);\n }\n const [id, location] = first;\n return { id, location };\n}\n\nfunction isApprovalEvent(ev: Event): ev is Event & { approval_id: string } {\n return (\n ev.type === \"approval_requested\" ||\n ev.type === \"approval_approved\" ||\n ev.type === \"approval_rejected\" ||\n ev.type === \"approval_expired\"\n );\n}\n\nfunction printApprovalListText(records: ApprovalListRecord[]): void {\n // Grow the SHORT_ID column on collision. The dedupe in doRunApprovalList\n // already collapsed duplicates by full id, so feeding only the unique\n // ids here is correct.\n const allIds = records.map((r) => r.approval.id);\n const shortLen = computeUniquePrefixLen(allIds);\n const rows = records.map((r) => {\n const sid = sliceShort(r.approval.id, shortLen);\n const status = r.lazyExpired ? `${r.approval.status} (expired)` : r.approval.status;\n const risk = r.approval.risk_level;\n const action = r.approval.action.kind;\n const createdAt = r.approval.created_at;\n const reason = truncate(r.approval.reason, REASON_TEXT_MAX_LEN);\n return { sid, status, risk, action, createdAt, reason };\n });\n\n const widths = {\n sid: maxLen(\n rows.map((r) => r.sid),\n \"SHORT_ID\".length,\n ),\n status: maxLen(\n rows.map((r) => r.status),\n \"STATUS\".length,\n ),\n risk: maxLen(\n rows.map((r) => r.risk),\n \"RISK\".length,\n ),\n action: maxLen(\n rows.map((r) => r.action),\n \"ACTION\".length,\n ),\n createdAt: maxLen(\n rows.map((r) => r.createdAt),\n \"CREATED_AT\".length,\n ),\n };\n\n console.log(\n `${pad(\"SHORT_ID\", widths.sid)} ${pad(\"STATUS\", widths.status)} ${pad(\"RISK\", widths.risk)} ${pad(\"ACTION\", widths.action)} ${pad(\"CREATED_AT\", widths.createdAt)} REASON`,\n );\n for (const row of rows) {\n console.log(\n `${pad(row.sid, widths.sid)} ${pad(row.status, widths.status)} ${pad(row.risk, widths.risk)} ${pad(row.action, widths.action)} ${pad(row.createdAt, widths.createdAt)} ${row.reason}`,\n );\n }\n}\n\nfunction printApprovalShowText(\n approval: Approval,\n _location: ApprovalLocation,\n events: readonly Event[],\n lazyExpired: boolean,\n): void {\n console.log(`Approval: ${approval.id} (status: ${approval.status})`);\n console.log(`Session: ${approval.session_id}`);\n console.log(`Created at: ${approval.created_at}`);\n console.log(`Risk level: ${approval.risk_level}`);\n console.log(`Action: ${formatActionLine(approval.action)}`);\n console.log(`Reason: ${approval.reason}`);\n const expiresLabel = formatExpiresLabel(approval.expires_at, lazyExpired);\n console.log(`Expires at: ${expiresLabel}`);\n console.log(`Resolver: ${approval.resolver ?? \"(none)\"}`);\n console.log(`Resolved at: ${approval.resolved_at ?? \"(none)\"}`);\n console.log(`Note: ${approval.note ?? \"(none)\"}`);\n console.log(`Rejection reason: ${approval.rejection_reason ?? \"(none)\"}`);\n\n console.log(\"\");\n console.log(`Related events: ${events.length} total`);\n for (const ev of events) {\n console.log(` ${formatApprovalEventLine(ev)}`);\n }\n}\n\nfunction formatActionLine(action: { kind: string } & Record<string, unknown>): string {\n const extras: string[] = [];\n for (const [key, value] of Object.entries(action)) {\n if (key === \"kind\") continue;\n if (typeof value !== \"string\") continue;\n extras.push(`${key}=\"${truncate(value, ACTION_KEY_DETAIL_MAX_LEN)}\"`);\n if (extras.length >= 2) break;\n }\n return extras.length === 0 ? action.kind : `${action.kind} (${extras.join(\", \")})`;\n}\n\nfunction formatExpiresLabel(expiresAt: string | null, lazyExpired: boolean): string {\n if (expiresAt === null) return \"(none)\";\n return lazyExpired ? `${expiresAt} (expired)` : expiresAt;\n}\n\nfunction formatApprovalEventLine(ev: Event): string {\n const summary = approvalEventSummary(ev);\n return `${ev.occurred_at} [${ev.source}] ${ev.type} ${summary}`;\n}\n\nfunction approvalEventSummary(ev: Event): string {\n switch (ev.type) {\n case \"approval_requested\":\n return `${ev.action.kind} risk=${ev.risk_level}`;\n case \"approval_approved\":\n return ev.resolver !== undefined ? `by ${ev.resolver}` : \"(approved)\";\n case \"approval_rejected\":\n return ev.resolver !== undefined ? `by ${ev.resolver}: ${ev.reason}` : ev.reason;\n case \"approval_expired\":\n return `approval=${ev.approval_id}`;\n default:\n // Other event types are filtered out before reaching this helper.\n return \"\";\n }\n}\n\nfunction shortId(id: string): string {\n return sliceShort(id, SHORT_ID_BASE_LEN);\n}\n\n// Known Basou prefixed-id leading tokens. Strip whichever applies so that\n// a session id passed through the warning handler renders as the bare\n// ULID prefix (matching what session.ts already emits) instead of leaving\n// the `ses_` head in the truncated short id.\nconst KNOWN_ID_PREFIXES = [\"appr_\", \"ses_\", \"evt_\", \"ws_\", \"task_\", \"decision_\"] as const;\n\nfunction sliceShort(id: string, len: number): string {\n for (const prefix of KNOWN_ID_PREFIXES) {\n if (id.startsWith(prefix)) {\n return id.slice(prefix.length, prefix.length + len);\n }\n }\n return id.slice(0, len);\n}\n\nfunction computeUniquePrefixLen(ids: readonly string[]): number {\n if (ids.length <= 1) return SHORT_ID_BASE_LEN;\n for (let len = SHORT_ID_BASE_LEN; len <= SHORT_ID_MAX_LEN; len += 2) {\n const seen = new Set<string>();\n let collided = false;\n for (const id of ids) {\n const key = sliceShort(id, len);\n if (seen.has(key)) {\n collided = true;\n break;\n }\n seen.add(key);\n }\n if (!collided) return len;\n }\n return SHORT_ID_MAX_LEN;\n}\n\nfunction pad(value: string, width: number): string {\n return value.length >= width ? value : value + \" \".repeat(width - value.length);\n}\n\nfunction maxLen(values: readonly string[], floor: number): number {\n let max = floor;\n for (const v of values) if (v.length > max) max = v.length;\n return max;\n}\n\nfunction truncate(value: string, maxLength: number): string {\n if (value.length <= maxLength) return value;\n return `${value.slice(0, maxLength - 3)}...`;\n}\n\nasync function resolveRepositoryRootForApproval(\n cwd: string,\n subcmd: \"list\" | \"show\" | \"approve\" | \"reject\",\n): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\n `Not a git repository. Run 'git init' first, then re-run 'basou approval ${subcmd}'.`,\n { cause: error },\n );\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n\nfunction describeReadError(error: unknown): string {\n if (error instanceof Error) {\n if (error.message === \"YAML file not found\") return \"approval YAML not found\";\n if (error.message === \"Failed to parse YAML content\") return \"invalid YAML\";\n return error.message;\n }\n return String(error);\n}\n\nfunction parseApprovalStatus(raw: string): ApprovalStatus {\n const result = ApprovalStatusSchema.safeParse(raw);\n if (!result.success) {\n throw new Error(`Invalid approval status: ${raw}. Valid values: ${STATUS_VALUES.join(\", \")}`);\n }\n return result.data;\n}\n\nfunction printNoApprovals(options: ApprovalListOptions): void {\n if (options.json === true) {\n console.log(\"[]\");\n } else {\n console.log(\"No approvals found.\");\n }\n}\n","import {\n acquireLock,\n appendEventToExistingSession,\n assertBasouRootSafe,\n basouPaths,\n createAdHocSessionWithEvent,\n type Event,\n findErrorCode,\n type PrefixedId,\n prefixedUlid,\n readManifest,\n resolveRepositoryRoot,\n resolveSessionId,\n type SessionStatus,\n} from \"@basou/core\";\nimport { type Command, InvalidArgumentError } from \"commander\";\nimport {\n failedToFinalizeClassifier,\n isVerbose,\n renderCliError,\n shortSessionId,\n} from \"../lib/error-render.js\";\n\n// Raised from the original 40-char cap to 80 chars so a long decision\n// title (= the most common ad-hoc trigger) retains its core information\n// without being truncated. 80 chars still fits comfortably in\n// single-column session list / handoff renderings. Operator feedback\n// from real-world long-title outliers may revisit this value.\nconst LABEL_TITLE_MAX = 80;\nconst LABEL_TRUNCATE_HEAD = LABEL_TITLE_MAX - 3;\n\nexport type DecisionRecordOptions = {\n title: string;\n rationale?: string;\n rejectedReason?: string;\n alternative?: string[];\n linkedEvent?: string[];\n linkedFile?: string[];\n session?: string;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type DecisionContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n /** Defaults to `() => new Date()`. Injectable for tests. */\n nowProvider?: () => Date;\n};\n\n/**\n * Wire `basou decision record` onto `program`. The `decision` group only\n * contains the write-side `record` subcommand in v0.1; list/show inspectors\n * are deferred to a v0.3+ follow-up.\n */\nexport function registerDecisionCommand(program: Command): void {\n const decision = program\n .command(\"decision\")\n .description(\"Record human-authored decisions as events\");\n\n decision\n .command(\"record\")\n .description(\"Record a decision_recorded event\")\n .requiredOption(\"--title <text>\", \"Decision title\", parseTitle)\n .option(\"--rationale <text>\", \"Rationale for the decision\", parseRationale)\n .option(\n \"--rejected-reason <text>\",\n \"Reason rejected alternatives were not chosen\",\n parseRejectedReason,\n )\n .option(\n \"--alternative <text>\",\n \"Alternative considered (repeatable: --alternative yup --alternative joi)\",\n collectAlternative,\n [] as string[],\n )\n .option(\n \"--linked-event <event_id>\",\n \"Related event id (repeatable). Schema only checks the prefix; existence is verified at render time.\",\n collectLinkedEvent,\n [] as string[],\n )\n .option(\n \"--linked-file <path>\",\n \"Related file path (repeatable). Path is opaque; existence is verified at render time.\",\n collectLinkedFile,\n [] as string[],\n )\n .option(\n \"--session <session_id>\",\n \"Attach to an existing session; otherwise an ad-hoc session is created\",\n )\n .option(\"--json\", \"Output the result as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: DecisionRecordOptions) => {\n await runDecisionRecord(options);\n });\n}\n\n/**\n * Programmatic entry for `basou decision record`. Owns process exit state.\n * Tests targeting the success path or the thrown error should prefer\n * {@link doRunDecisionRecord}.\n */\nexport async function runDecisionRecord(\n options: DecisionRecordOptions,\n ctx: DecisionContext = {},\n): Promise<void> {\n try {\n await doRunDecisionRecord(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, {\n verbose: isVerbose(options),\n classifiers: [failedToFinalizeClassifier],\n });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunDecisionRecord(\n options: DecisionRecordOptions,\n ctx: DecisionContext,\n): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForDecision(cwd);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const now = ctx.nowProvider !== undefined ? ctx.nowProvider() : new Date();\n const occurredAt = now.toISOString();\n const decisionId = prefixedUlid(\"decision\");\n\n const rich = pickRichFields(options);\n\n if (options.session !== undefined) {\n const sessionId = await resolveSessionId(paths, options.session);\n const sesId = sessionId as PrefixedId<\"ses\">;\n // Per-session lock guards the session.yaml status read + events.jsonl\n // append window against a concurrent writer (`basou session note`,\n // another `decision record --session`, or an attach-flavoured task\n // command). `appendEventToExistingSession` itself holds no lock; the\n // caller owns the critical section.\n const sessionLock = await acquireLock(paths, \"session\", sesId);\n let result: Awaited<ReturnType<typeof appendEventToExistingSession>>;\n try {\n result = await appendEventToExistingSession({\n paths,\n sessionId: sesId,\n eventBuilder: (eventId) =>\n buildDecisionEvent({\n eventId,\n sessionId: sesId,\n decisionId,\n title: options.title,\n occurredAt,\n rich,\n }),\n });\n } finally {\n await sessionLock.release();\n }\n printDecisionResult(options, {\n mode: \"attached\",\n sessionId,\n decisionId,\n eventId: result.eventId,\n sessionStatus: result.sessionStatus,\n title: options.title,\n rich,\n });\n return;\n }\n\n const manifest = await readManifest(paths);\n const adHoc = await createAdHocSessionWithEvent({\n paths,\n manifest,\n label: buildAdHocLabel(options.title),\n occurredAt,\n sessionSource: \"human\",\n workingDirectory: repositoryRoot,\n invocation: {\n command: \"basou decision record\",\n args: [\"--title\", options.title],\n },\n targetEventBuilders: [\n (sessionId, eventId) =>\n buildDecisionEvent({\n eventId,\n sessionId,\n decisionId,\n title: options.title,\n occurredAt,\n rich,\n }),\n ],\n });\n printDecisionResult(options, {\n mode: \"ad-hoc\",\n sessionId: adHoc.sessionId,\n decisionId,\n eventId: adHoc.targetEventIds[0] as string,\n sessionStatus: \"completed\",\n title: options.title,\n rich,\n });\n}\n\ntype RichDecisionFields = {\n rationale?: string;\n rejected_reason?: string;\n alternatives?: string[];\n linked_events?: string[];\n linked_files?: string[];\n};\n\nfunction pickRichFields(options: DecisionRecordOptions): RichDecisionFields {\n const out: RichDecisionFields = {};\n if (options.rationale !== undefined) out.rationale = options.rationale;\n if (options.rejectedReason !== undefined) out.rejected_reason = options.rejectedReason;\n if (options.alternative !== undefined && options.alternative.length > 0) {\n out.alternatives = [...options.alternative];\n }\n if (options.linkedEvent !== undefined && options.linkedEvent.length > 0) {\n out.linked_events = [...options.linkedEvent];\n }\n if (options.linkedFile !== undefined && options.linkedFile.length > 0) {\n out.linked_files = [...options.linkedFile];\n }\n return out;\n}\n\nfunction buildDecisionEvent(input: {\n eventId: PrefixedId<\"evt\">;\n sessionId: PrefixedId<\"ses\">;\n decisionId: PrefixedId<\"decision\">;\n title: string;\n occurredAt: string;\n rich: RichDecisionFields;\n}): Event {\n return {\n schema_version: \"0.1.0\",\n id: input.eventId,\n session_id: input.sessionId,\n occurred_at: input.occurredAt,\n source: \"local-cli\",\n type: \"decision_recorded\",\n decision_id: input.decisionId,\n title: input.title,\n ...(input.rich.rationale !== undefined ? { rationale: input.rich.rationale } : {}),\n ...(input.rich.alternatives !== undefined ? { alternatives: input.rich.alternatives } : {}),\n ...(input.rich.rejected_reason !== undefined\n ? { rejected_reason: input.rich.rejected_reason }\n : {}),\n ...(input.rich.linked_events !== undefined\n ? { linked_events: input.rich.linked_events as Array<`evt_${string}`> }\n : {}),\n ...(input.rich.linked_files !== undefined ? { linked_files: input.rich.linked_files } : {}),\n };\n}\n\nfunction buildAdHocLabel(title: string): string {\n const truncated =\n title.length > LABEL_TITLE_MAX ? `${title.slice(0, LABEL_TRUNCATE_HEAD)}...` : title;\n return `Ad-hoc decision: ${truncated}`;\n}\n\nfunction parseTitle(raw: string): string {\n if (raw.length === 0) {\n throw new InvalidArgumentError(\"Title must not be empty\");\n }\n return raw;\n}\n\nfunction parseRationale(raw: string): string {\n if (raw.length === 0) {\n throw new InvalidArgumentError(\"Rationale must not be empty\");\n }\n return raw;\n}\n\nfunction parseRejectedReason(raw: string): string {\n if (raw.length === 0) {\n throw new InvalidArgumentError(\"Rejected reason must not be empty\");\n }\n return raw;\n}\n\nfunction collectAlternative(value: string, prev: string[]): string[] {\n if (value.length === 0) {\n throw new InvalidArgumentError(\"Alternative must not be empty\");\n }\n return prev.concat(value);\n}\n\nconst EVENT_ID_RE = /^evt_[A-Z0-9]+$/;\n\nfunction collectLinkedEvent(value: string, prev: string[]): string[] {\n if (!EVENT_ID_RE.test(value)) {\n throw new InvalidArgumentError(`Linked event id must match evt_<ULID>, got '${value}'`);\n }\n return prev.concat(value);\n}\n\nfunction collectLinkedFile(value: string, prev: string[]): string[] {\n if (value.length === 0) {\n throw new InvalidArgumentError(\"Linked file path must not be empty\");\n }\n if (value.length > 4096) {\n throw new InvalidArgumentError(\"Linked file path exceeds 4096 chars\");\n }\n return prev.concat(value);\n}\n\ntype DecisionPrintInput = {\n mode: \"ad-hoc\" | \"attached\";\n sessionId: string;\n decisionId: string;\n eventId: string;\n sessionStatus: SessionStatus;\n title: string;\n rich: RichDecisionFields;\n};\n\nfunction printDecisionResult(options: DecisionRecordOptions, result: DecisionPrintInput): void {\n const sid = shortSessionId(result.sessionId);\n if (options.json === true) {\n const payload: Record<string, unknown> = {\n decision_id: result.decisionId,\n event_id: result.eventId,\n session_id: result.sessionId,\n session_status: result.sessionStatus,\n mode: result.mode,\n title: result.title,\n };\n // Rich fields are now persisted into the decision_recorded event, so\n // they appear in the JSON summary as-is (the old `rationale_saved:\n // false` indicator is gone).\n if (result.rich.rationale !== undefined) payload.rationale = result.rich.rationale;\n if (result.rich.alternatives !== undefined) payload.alternatives = result.rich.alternatives;\n if (result.rich.rejected_reason !== undefined) {\n payload.rejected_reason = result.rich.rejected_reason;\n }\n if (result.rich.linked_events !== undefined) payload.linked_events = result.rich.linked_events;\n if (result.rich.linked_files !== undefined) payload.linked_files = result.rich.linked_files;\n console.log(JSON.stringify(payload));\n return;\n }\n const rationaleSuffix =\n result.rich.rationale !== undefined ? ` (rationale: ${result.rich.rationale})` : \"\";\n if (result.mode === \"ad-hoc\") {\n console.log(`Recorded ${result.decisionId} in ad-hoc session ${sid}${rationaleSuffix}`);\n } else {\n console.log(\n `Recorded ${result.decisionId} in session ${sid} (${result.sessionStatus})${rationaleSuffix}`,\n );\n }\n}\n\nasync function resolveRepositoryRootForDecision(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\n \"Not a git repository. Run 'git init' first, then re-run 'basou decision record'.\",\n { cause: error },\n );\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n","import {\n assertBasouRootSafe,\n basouPaths,\n findErrorCode,\n readMarkdownFile,\n renderDecisions,\n renderWithMarkers,\n resolveRepositoryRoot,\n writeMarkdownFile,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport {\n isVerbose,\n printReplayWarning,\n printSessionSkip,\n renderCliError,\n} from \"../lib/error-render.js\";\n\nexport type DecisionsGenerateOptions = { verbose?: boolean };\n\nexport type DecisionsContext = {\n cwd?: string;\n nowProvider?: () => Date;\n};\n\n/** Wire `basou decisions generate` onto `program`. Mirrors `handoff` exactly. */\nexport function registerDecisionsCommand(program: Command): void {\n const decisions = program\n .command(\"decisions\")\n .description(\"Generate or inspect .basou/decisions.md\");\n\n decisions\n .command(\"generate\")\n .description(\"Regenerate .basou/decisions.md from recorded decision events\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (opts: DecisionsGenerateOptions) => {\n await runDecisionsGenerate(opts);\n });\n}\n\nexport async function runDecisionsGenerate(\n options: DecisionsGenerateOptions,\n ctx: DecisionsContext = {},\n): Promise<void> {\n try {\n await doRunDecisionsGenerate(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunDecisionsGenerate(\n options: DecisionsGenerateOptions,\n ctx: DecisionsContext,\n): Promise<void> {\n void options;\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForDecisions(cwd);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const nowIso = (ctx.nowProvider?.() ?? new Date()).toISOString();\n const result = await renderDecisions({\n paths,\n nowIso,\n onWarning: (w, sid) => printReplayWarning(w, sid),\n onSessionSkip: (sid, reason) => printSessionSkip(sid, reason),\n });\n\n const existing = await readMarkdownFile(paths.files.decisions);\n const finalBody = renderWithMarkers(existing, result.body, \"decisions.md\");\n await writeMarkdownFile(paths.files.decisions, finalBody);\n\n console.log(`Generated .basou/decisions.md (decisions: ${result.decisionCount})`);\n}\n\nasync function resolveRepositoryRootForDecisions(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\n \"Not a git repository. Run 'git init' first, then re-run 'basou decisions generate'.\",\n { cause: error },\n );\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n","import type { ChildProcess } from \"node:child_process\";\nimport { mkdir } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport {\n acquireLock,\n assertBasouRootSafe,\n type BasouPaths,\n basouPaths,\n ChildProcessRunner,\n appendChainedEvent as coreAppendChainedEvent,\n finalizeSessionYaml,\n getSnapshot,\n overwriteYamlFile,\n type PrefixedId,\n type ProcessRunner,\n parseDuration,\n prefixedUlid,\n type RunResult,\n readManifest,\n readYamlFile,\n resolveRepositoryRoot,\n type Session,\n SessionSchema,\n sanitizeWorkingDirectory,\n writeYamlFile,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport { isVerbose, renderCliError } from \"../lib/error-render.js\";\n\n// Appends one event to the session's events.jsonl. The `sessionDir` argument\n// is retained for the test-injection seam (ctx.appendEvent); the production\n// binding ignores it and chains via paths + sessionId.\ntype AppendEventFn = (sessionDir: string, event: unknown) => Promise<void>;\n\n/**\n * `basou exec` orchestration: spawn an arbitrary child as a single new\n * Basou session and record its lifecycle (session_started, optional\n * git_snapshot pre, status_changed, command_executed, optional git_snapshot\n * post, status_changed, session_ended) to `events.jsonl`.\n *\n * Output is forwarded to the parent's terminal (`capture: \"none\"`); raw\n * stdout/stderr is intentionally not stored in events.jsonl or `.basou/raw/`.\n */\nexport type ExecOptions = {\n timeout?: string;\n cwd?: string;\n // commander turns `--no-snapshot` into `snapshot: false`. The default\n // (no flag) leaves this `undefined` (treated as `true` downstream).\n snapshot?: boolean;\n verbose?: boolean;\n};\n\ntype ExecContext = {\n runner?: ProcessRunner;\n now?: () => Date;\n // events.jsonl writer override. Tests use this to verify that appendEvent\n // failures during git_snapshot propagate as exec failures (see\n // tryAppendGitSnapshot below) instead of being swallowed into a skip warning.\n appendEvent?: AppendEventFn;\n // Last-resort SIGKILL hook installation hook. Tests capture the handler\n // installed on `process.on(\"exit\", ...)` and trigger it manually to verify\n // that activeChild is killed when the parent exits abnormally.\n onExitHookInstalled?: (handler: () => void) => void;\n};\n\nexport function registerExecCommand(program: Command): void {\n program\n .command(\"exec <command> [args...]\")\n .description(\"Execute a command and record it as a Basou session\")\n // Pass through unknown options/flags after the command name to the\n // child so callers can write `basou exec npm test --watch` instead of\n // `basou exec -- npm test --watch`. basou's own options (--timeout,\n // --no-snapshot, --cwd, -v) must come before the command name.\n .passThroughOptions()\n .option(\"--timeout <duration>\", \"Kill the child after this duration (e.g. 30s, 5m, 1h)\")\n .option(\"--no-snapshot\", \"Skip git_snapshot before/after the command\")\n .option(\"--cwd <path>\", \"Run from a Basou root other than process.cwd()\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (command: string, args: string[], options: ExecOptions) => {\n try {\n const exitCode = await runExec(command, args, options);\n process.exit(exitCode);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exit(1);\n }\n });\n}\n\nexport async function runExec(\n command: string,\n args: string[],\n options: ExecOptions,\n ctx: ExecContext = {},\n): Promise<number> {\n const runner = ctx.runner ?? new ChildProcessRunner();\n const now = ctx.now ?? (() => new Date());\n const cwd = options.cwd ?? process.cwd();\n\n // 0. timeout option fail-fast: invalid timeout never creates a session.\n const timeout_ms = options.timeout !== undefined ? parseDuration(options.timeout) : undefined;\n\n // 1. Resolve repository root before touching anything; matches existing\n // init/status semantics so subdir invocations still find `.basou/`.\n const repoRoot = await resolveRepositoryRootForExec(cwd);\n const paths = basouPaths(repoRoot);\n\n // 2. Workspace safety check (caller responsibility).\n await assertBasouRootSafe(paths.root);\n\n // 3. Read manifest to bind session.workspace_id.\n const manifest = await readManifest(paths);\n\n // 4. Build a fresh session and persist its initial state.\n const sessionId = prefixedUlid(\"ses\");\n const sessionDir = join(paths.sessions, sessionId);\n await mkdir(sessionDir, { recursive: true });\n\n // Every append chains onto the on-disk tail under a short-lived session lock\n // (the self-locking wrapper); the lock is NEVER held across the child. Tests\n // inject ctx.appendEvent to force append failures.\n const appendEvent: AppendEventFn =\n ctx.appendEvent ??\n (async (_sessionDir, event) => {\n await coreAppendChainedEvent(paths, sessionId, event);\n });\n\n const startedAt = now().toISOString();\n const sessionYamlPath = join(sessionDir, \"session.yaml\");\n const session = buildInitialSession({\n id: sessionId,\n command,\n args,\n cwd,\n workspaceId: manifest.workspace.id,\n startedAt,\n });\n await writeYamlFile(sessionYamlPath, session);\n\n // 5. session_started.\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_started\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: startedAt,\n source: \"terminal-recording\",\n });\n\n // 6. Optional pre-execute git_snapshot.\n if (options.snapshot !== false) {\n await tryAppendGitSnapshot(sessionDir, sessionId, repoRoot, now, appendEvent);\n }\n\n // 7. status_changed: initialized -> running.\n const runningAt = now().toISOString();\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_status_changed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: runningAt,\n source: \"terminal-recording\",\n from: \"initialized\",\n to: \"running\",\n });\n // Lock the status write so it cannot interleave-clobber a foreign locked\n // session.yaml writer (e.g. a task attach setting task_id on this session).\n const runningLock = await acquireLock(paths, \"session\", sessionId);\n try {\n await mutateSessionYaml(sessionYamlPath, (s) => {\n s.session.status = \"running\";\n });\n } finally {\n await runningLock.release();\n }\n\n // 8. Transient signal hooks: SIGINT / SIGTERM / exit. The exit hook is\n // a synchronous last-resort SIGKILL if the parent exits abnormally.\n const controller = new AbortController();\n let signalReceived: NodeJS.Signals | null = null;\n let activeChild: ChildProcess | null = null;\n const signalHandler = (sig: NodeJS.Signals) => {\n if (signalReceived !== null) return;\n signalReceived = sig;\n controller.abort();\n };\n const exitHandler = () => {\n if (activeChild !== null) {\n try {\n activeChild.kill(\"SIGKILL\");\n } catch {\n // swallow: best-effort cleanup\n }\n }\n };\n // Bind explicit signal names so `process.emit(\"SIGINT\")` etc. produce the\n // right `received_signal` regardless of Node's listener-arg conventions.\n const onSigInt = () => signalHandler(\"SIGINT\");\n const onSigTerm = () => signalHandler(\"SIGTERM\");\n process.on(\"SIGINT\", onSigInt);\n process.on(\"SIGTERM\", onSigTerm);\n process.on(\"exit\", exitHandler);\n // Allow tests to capture the exit handler and trigger the activeChild\n // SIGKILL fallback synchronously without faking `process.emit(\"exit\")`.\n ctx.onExitHookInstalled?.(exitHandler);\n\n let result: RunResult;\n try {\n try {\n result = await runner.run(command, args, {\n cwd,\n capture: \"none\",\n ...(timeout_ms !== undefined ? { timeout_ms } : {}),\n signal: controller.signal,\n onSpawn: (child) => {\n activeChild = child;\n },\n });\n } catch (spawnError: unknown) {\n // Spawn-time error / pre-aborted / validation error: tear down the\n // session as failed before propagating so events.jsonl and session.yaml\n // are consistent even on error.\n await finalizeSessionAsFailed(paths, sessionDir, sessionId, appendEvent, {\n command,\n args,\n cwd,\n occurredAt: now().toISOString(),\n signalReceived,\n });\n throw spawnError;\n }\n } finally {\n process.off(\"SIGINT\", onSigInt);\n process.off(\"SIGTERM\", onSigTerm);\n process.off(\"exit\", exitHandler);\n activeChild = null;\n }\n\n const endedAt = now().toISOString();\n\n // 9. command_executed (with parent received_signal vs child terminating signal).\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"command_executed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: endedAt,\n source: \"terminal-recording\",\n command,\n args,\n cwd,\n exit_code: result.exit_code,\n ...(result.signal !== null ? { signal: result.signal } : {}),\n ...(signalReceived !== null ? { received_signal: signalReceived } : {}),\n duration_ms: result.duration_ms,\n });\n\n // 10. Optional post-execute git_snapshot (after command_executed so the\n // event sequence reads chronologically: pre-snapshot, run, post-snapshot).\n if (options.snapshot !== false) {\n await tryAppendGitSnapshot(sessionDir, sessionId, repoRoot, now, appendEvent);\n }\n\n const finalStatus = decideFinalStatus(result, signalReceived);\n\n // 11. status_changed: running -> final.\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_status_changed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: endedAt,\n source: \"terminal-recording\",\n from: \"running\",\n to: finalStatus,\n });\n\n // 12. session_ended.\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_ended\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: endedAt,\n source: \"terminal-recording\",\n ...(result.exit_code !== null ? { exit_code: result.exit_code } : {}),\n });\n\n // 13. Final session.yaml update (status / ended_at / invocation.exit_code)\n // plus the integrity head anchor, written from the on-disk tail under the\n // session lock so a foreign line appended just before finalize is\n // anchored and a later attach (now terminal) is rejected.\n await finalizeSessionYaml(paths, sessionId, (s) => {\n s.session.status = finalStatus;\n s.session.ended_at = endedAt;\n s.session.invocation.exit_code = result.exit_code;\n });\n\n if (result.exit_code !== null) {\n return result.exit_code;\n }\n return signalToExitCode(signalReceived ?? result.signal);\n}\n\nfunction decideFinalStatus(\n result: { exit_code: number | null; signal: NodeJS.Signals | null },\n signalReceived: NodeJS.Signals | null,\n): \"completed\" | \"failed\" | \"interrupted\" {\n if (signalReceived === \"SIGINT\" || signalReceived === \"SIGTERM\") return \"interrupted\";\n if (result.signal === \"SIGINT\" || result.signal === \"SIGTERM\" || result.signal === \"SIGKILL\") {\n return \"interrupted\";\n }\n if (result.exit_code === 0) return \"completed\";\n return \"failed\";\n}\n\nconst SIGNUM_MAP: Record<string, number> = {\n SIGHUP: 1,\n SIGINT: 2,\n SIGQUIT: 3,\n SIGKILL: 9,\n SIGTERM: 15,\n};\n\nfunction signalToExitCode(sig: NodeJS.Signals | null): number {\n if (sig === null) return 1;\n const num = SIGNUM_MAP[sig] ?? 1;\n return 128 + num;\n}\n\nasync function tryAppendGitSnapshot(\n sessionDir: string,\n sessionId: string,\n repoRoot: string,\n now: () => Date,\n appendEvent: AppendEventFn,\n): Promise<void> {\n // Stage 1: snapshot acquisition. Capability-level failures (no git repo,\n // git binary missing, no commits) are recoverable and downgrade to a skip\n // warning. The session continues and events.jsonl simply lacks this\n // git_snapshot entry.\n let snapshot: Awaited<ReturnType<typeof getSnapshot>>;\n try {\n snapshot = await getSnapshot(repoRoot);\n } catch (error: unknown) {\n console.warn(normalizeGitSnapshotSkipMessage(error));\n return;\n }\n // Stage 2: events.jsonl append. Schema validation / disk failures here are\n // NOT a \"snapshot capability\" miss — they would corrupt the events.jsonl\n // integrity contract (the fixed 7-event sequence when snapshot is on). We\n // intentionally do NOT swallow these; let them propagate so the exec call\n // fails loudly instead of producing a session that looks successful but\n // has missing or partial events.\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"git_snapshot\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: now().toISOString(),\n source: \"git-capability\",\n ...snapshot,\n });\n}\n\nfunction normalizeGitSnapshotSkipMessage(error: unknown): string {\n if (!(error instanceof Error)) {\n return `git_snapshot skipped: ${String(error)}`;\n }\n const msg = error.message;\n if (msg === \"Not a git repository\") {\n return \"git_snapshot skipped: not in a git repository\";\n }\n if (msg === \"Git executable not found in PATH. Install git first.\") {\n return \"git_snapshot skipped: git executable not found\";\n }\n if (msg === \"No commits in repository\") {\n return \"git_snapshot skipped: no commits in repository\";\n }\n return `git_snapshot skipped: ${msg}`;\n}\n\nfunction buildInitialSession(input: {\n id: PrefixedId<\"ses\">;\n command: string;\n args: string[];\n cwd: string;\n workspaceId: PrefixedId<\"ws\">;\n startedAt: string;\n}): Session {\n const cmdline = [input.command, ...input.args].join(\" \");\n return {\n schema_version: \"0.1.0\",\n session: {\n id: input.id,\n label: `basou exec ${cmdline} (${input.startedAt})`,\n task_id: null,\n workspace_id: input.workspaceId,\n source: { kind: \"terminal\", version: \"0.1.0\" },\n started_at: input.startedAt,\n status: \"initialized\",\n working_directory: sanitizeWorkingDirectory(input.cwd, { homedir: homedir() }),\n invocation: {\n command: input.command,\n args: [...input.args],\n exit_code: null,\n },\n related_files: [],\n events_log: \"events.jsonl\",\n },\n };\n}\n\nasync function mutateSessionYaml(\n filePath: string,\n mutator: (session: Session) => void,\n): Promise<void> {\n const raw = await readYamlFile(filePath);\n const parsed = SessionSchema.parse(raw);\n mutator(parsed);\n // Re-validate after mutation to catch drift, then overwrite atomically.\n const validated = SessionSchema.parse(parsed);\n await overwriteYamlFile(filePath, validated);\n}\n\nasync function finalizeSessionAsFailed(\n paths: BasouPaths,\n sessionDir: string,\n sessionId: string,\n appendEvent: AppendEventFn,\n ctx: {\n command: string;\n args: string[];\n cwd: string;\n occurredAt: string;\n signalReceived: NodeJS.Signals | null;\n },\n): Promise<void> {\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"command_executed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: ctx.occurredAt,\n source: \"terminal-recording\",\n command: ctx.command,\n args: ctx.args,\n cwd: ctx.cwd,\n exit_code: null,\n signal: null,\n ...(ctx.signalReceived !== null ? { received_signal: ctx.signalReceived } : {}),\n duration_ms: 0,\n });\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_status_changed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: ctx.occurredAt,\n source: \"terminal-recording\",\n from: \"running\",\n to: \"failed\",\n });\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_ended\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: ctx.occurredAt,\n source: \"terminal-recording\",\n });\n await finalizeSessionYaml(paths, sessionId, (s) => {\n s.session.status = \"failed\";\n s.session.ended_at = ctx.occurredAt;\n s.session.invocation.exit_code = null;\n });\n}\n\nasync function resolveRepositoryRootForExec(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\"Not a git repository. Run 'git init' first, then re-run 'basou exec'.\", {\n cause: error,\n });\n }\n throw error;\n }\n}\n","import {\n assertBasouRootSafe,\n basouPaths,\n findErrorCode,\n readMarkdownFile,\n renderHandoff,\n renderWithMarkers,\n resolveRepositoryRoot,\n writeMarkdownFile,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport {\n isVerbose,\n printReplayWarning,\n printSessionSkip,\n printTaskSkip,\n renderCliError,\n} from \"../lib/error-render.js\";\n\nexport type HandoffGenerateOptions = { verbose?: boolean };\n\nexport type HandoffContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n /** Defaults to `() => new Date()`. Injectable for tests. */\n nowProvider?: () => Date;\n};\n\n/**\n * Wire `basou handoff generate` onto `program`. The `handoff` group is\n * registered up front so future subcommands (e.g. `show`) can slot under\n * the same group without breaking the CLI surface.\n */\nexport function registerHandoffCommand(program: Command): void {\n const handoff = program.command(\"handoff\").description(\"Generate or inspect .basou/handoff.md\");\n\n handoff\n .command(\"generate\")\n .description(\"Regenerate .basou/handoff.md from current session state\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (opts: HandoffGenerateOptions) => {\n await runHandoffGenerate(opts);\n });\n}\n\n/**\n * Programmatic entry that owns `process.exitCode`. Tests that only care\n * about the happy path or a thrown error should prefer {@link doRunHandoffGenerate}.\n */\nexport async function runHandoffGenerate(\n options: HandoffGenerateOptions,\n ctx: HandoffContext = {},\n): Promise<void> {\n try {\n await doRunHandoffGenerate(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * Pure runner for `handoff generate`. Throws on any failure with a pathless\n * message; native errors are attached as `cause` for verbose surfacing.\n */\nexport async function doRunHandoffGenerate(\n options: HandoffGenerateOptions,\n ctx: HandoffContext,\n): Promise<void> {\n void options;\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForHandoff(cwd);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const nowIso = (ctx.nowProvider?.() ?? new Date()).toISOString();\n const result = await renderHandoff({\n paths,\n nowIso,\n onWarning: (w, sid) => printReplayWarning(w, sid),\n onSessionSkip: (sid, reason) => printSessionSkip(sid, reason),\n onTaskSkip: (taskId, reason) => printTaskSkip(taskId, reason),\n });\n\n const existing = await readMarkdownFile(paths.files.handoff);\n const finalBody = renderWithMarkers(existing, result.body, \"handoff.md\");\n await writeMarkdownFile(paths.files.handoff, finalBody);\n\n console.log(\n `Generated .basou/handoff.md (sessions: ${result.sessionCount}, tasks: ${result.taskCount}, decisions: ${result.decisionCount}, pending approvals: ${result.pendingApprovalsCount})`,\n );\n}\n\nasync function resolveRepositoryRootForHandoff(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\n \"Not a git repository. Run 'git init' first, then re-run 'basou handoff generate'.\",\n { cause: error },\n );\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n","import { createReadStream, type Dirent } from \"node:fs\";\nimport { readdir, readFile, rm, stat } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { basename, join, resolve } from \"node:path\";\nimport { createInterface } from \"node:readline\";\nimport {\n assertBasouRootSafe,\n type BasouPaths,\n basouPaths,\n CLAUDE_IMPORT_SOURCE,\n type ClaudeTranscriptRecord,\n CODEX_IMPORT_SOURCE,\n type CodexRolloutRecord,\n claudeTranscriptToImportPayload,\n codexRolloutToImportPayload,\n enumerateSessionDirs,\n findErrorCode,\n type ImportSessionResult,\n importSessionFromJson,\n type Manifest,\n readManifest,\n readSessionYaml,\n reimportPreservingId,\n resolveRepositoryRoot,\n type Session,\n type SessionImportPayload,\n SessionImportPayloadSchema,\n type SessionSourceKind,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport { isVerbose, renderCliError } from \"../lib/error-render.js\";\n\nconst SES_PREFIX = \"ses_\";\nconst SHORT_ID_LEN = 6;\n\n/** Options shared by every `basou import <adapter>` subcommand. */\nexport type ImportOptions = {\n /**\n * Source project roots whose native logs to import. Repeatable on the CLI;\n * empty means \"fall back to the manifest's `import.source_roots`, then the\n * repository root\". Each entry may be absolute or relative to the cwd.\n */\n project?: string[];\n session?: string;\n all?: boolean;\n force?: boolean;\n dryRun?: boolean;\n json?: boolean;\n verbose?: boolean;\n};\n\n/** Commander collector: accumulate a repeatable option into an array. */\nfunction collectPath(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\nexport type ImportClaudeCodeOptions = ImportOptions;\nexport type ImportCodexOptions = ImportOptions;\n\nexport type ImportContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n /**\n * Root that holds per-project Claude transcript directories. Defaults to\n * `~/.claude/projects`. Injectable for tests so no real home dir is touched.\n */\n claudeProjectsDir?: string;\n /**\n * Root that holds Codex rollout logs (`<year>/<month>/<day>/rollout-*.jsonl`).\n * Defaults to `~/.codex/sessions`. Injectable for tests.\n */\n codexSessionsDir?: string;\n};\n\n/**\n * A single source session ready to be derived and imported. The dedup key\n * (`externalId`) is known up front from discovery; `toPayload` reads and\n * transforms the source log lazily, so a session that is skipped (already\n * imported) is never read.\n */\ntype ImportCandidate = {\n externalId: string;\n /**\n * Absolute path of the source native log. The orchestrator stats this (a\n * cheap, parse-free probe) to decide whether an already-imported source\n * changed, before paying to read + derive it.\n */\n sourcePath: string;\n toPayload: () => Promise<SessionImportPayload | null>;\n};\n\n/**\n * Wire the `basou import` command group onto `program`. Each adapter\n * (`claude-code`, `codex`, ...) is a subcommand sharing the same flags, so\n * future adapters slot in without changing the visible surface.\n */\nexport function registerImportCommand(program: Command): void {\n const importCmd = program\n .command(\"import\")\n .description(\"Import provenance from an external AI tool's native logs\");\n\n importCmd\n .command(\"claude-code\")\n .description(\"Derive Basou sessions from Claude Code native transcripts (~/.claude/projects)\")\n .option(\n \"--project <path>\",\n \"Source project path whose transcripts to import (repeatable; defaults to the manifest source roots, then the repository root)\",\n collectPath,\n [],\n )\n .option(\"--session <id>\", \"Import a single transcript by its Claude session id\")\n .option(\"--all\", \"Import every transcript found for the project\")\n .option(\n \"--force\",\n \"Re-import sessions already imported: delete and replace them instead of skipping\",\n )\n .option(\"--dry-run\", \"Validate and preview only; do not write to disk\")\n .option(\"--json\", \"Output the result as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: ImportClaudeCodeOptions) => {\n await runImportClaudeCode(options);\n });\n\n importCmd\n .command(\"codex\")\n .description(\"Derive Basou sessions from OpenAI Codex native rollout logs (~/.codex/sessions)\")\n .option(\n \"--project <path>\",\n \"Source project path whose rollouts to import (repeatable; defaults to the manifest source roots, then the repository root)\",\n collectPath,\n [],\n )\n .option(\"--session <id>\", \"Import a single rollout by its Codex session id\")\n .option(\"--all\", \"Import every rollout found for the project\")\n .option(\n \"--force\",\n \"Re-import sessions already imported: delete and replace them instead of skipping\",\n )\n .option(\"--dry-run\", \"Validate and preview only; do not write to disk\")\n .option(\"--json\", \"Output the result as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: ImportCodexOptions) => {\n await runImportCodex(options);\n });\n}\n\n/**\n * Programmatic entry for `basou import claude-code`. Owns process exit state;\n * tests should prefer {@link doRunImportClaudeCode}.\n */\nexport async function runImportClaudeCode(\n options: ImportClaudeCodeOptions,\n ctx: ImportContext = {},\n): Promise<void> {\n try {\n await doRunImportClaudeCode(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * Programmatic entry for `basou import codex`. Owns process exit state;\n * tests should prefer {@link doRunImportCodex}.\n */\nexport async function runImportCodex(\n options: ImportCodexOptions,\n ctx: ImportContext = {},\n): Promise<void> {\n try {\n await doRunImportCodex(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * Resolve the absolute source roots to import from, applying precedence:\n * explicit `--project` flags first (resolved against the cwd), else the\n * manifest's `import.source_roots` (resolved against the repo root), else the\n * repository root alone. The result is de-duplicated, so a root listed twice\n * (or equal to the repo root) is scanned once.\n */\nfunction resolveSourceRoots(args: {\n projectFlags: string[];\n manifest: Manifest;\n repoRoot: string;\n cwd: string;\n}): string[] {\n const { projectFlags, manifest, repoRoot, cwd } = args;\n let resolved: string[];\n if (projectFlags.length > 0) {\n resolved = projectFlags.map((p) => resolve(cwd, p));\n } else {\n const roots = manifest.import?.source_roots;\n resolved =\n roots !== undefined && roots.length > 0 ? roots.map((r) => resolve(repoRoot, r)) : [repoRoot];\n }\n return [...new Set(resolved)];\n}\n\nexport async function doRunImportClaudeCode(\n options: ImportClaudeCodeOptions,\n ctx: ImportContext,\n): Promise<void> {\n assertSelector(options);\n const { repositoryRoot, paths, manifest } = await resolveImportTarget(ctx);\n\n const projectPaths = resolveSourceRoots({\n projectFlags: options.project ?? [],\n manifest,\n repoRoot: repositoryRoot,\n cwd: ctx.cwd ?? process.cwd(),\n });\n const projectsRoot = ctx.claudeProjectsDir ?? join(homedir(), \".claude\", \"projects\");\n\n const files = await selectTranscriptFiles(projectsRoot, projectPaths, options);\n const candidates: ImportCandidate[] = files.map((file) => {\n // The transcript filename is the Claude session id; it is both the dedup\n // key and the source external_id.\n const externalId = basename(file, \".jsonl\");\n return {\n externalId,\n sourcePath: file,\n toPayload: async () => {\n const { records, sizeBytes } = await readJsonlRecords(file);\n return claudeTranscriptToImportPayload(records, {\n workspaceId: manifest.workspace.id,\n externalId,\n sourceSizeBytes: sizeBytes,\n });\n },\n };\n });\n\n await importDerivedSessions(paths, manifest, options, CLAUDE_IMPORT_SOURCE, candidates);\n}\n\nexport async function doRunImportCodex(\n options: ImportCodexOptions,\n ctx: ImportContext,\n): Promise<void> {\n assertSelector(options);\n const { repositoryRoot, paths, manifest } = await resolveImportTarget(ctx);\n\n const projectPaths = resolveSourceRoots({\n projectFlags: options.project ?? [],\n manifest,\n repoRoot: repositoryRoot,\n cwd: ctx.cwd ?? process.cwd(),\n });\n const sessionsRoot = ctx.codexSessionsDir ?? join(homedir(), \".codex\", \"sessions\");\n\n const rollouts = await discoverCodexRollouts(sessionsRoot, projectPaths, options);\n const candidates: ImportCandidate[] = rollouts.map(({ file, externalId }) => ({\n externalId,\n sourcePath: file,\n toPayload: async () => {\n const { records, sizeBytes } = await readJsonlRecords(file);\n return codexRolloutToImportPayload(records as CodexRolloutRecord[], {\n workspaceId: manifest.workspace.id,\n externalId,\n sourceSizeBytes: sizeBytes,\n });\n },\n }));\n\n await importDerivedSessions(paths, manifest, options, CODEX_IMPORT_SOURCE, candidates);\n}\n\nfunction assertSelector(options: ImportOptions): void {\n if (options.session !== undefined && options.all === true) {\n throw new Error(\"Specify either --session <id> or --all, not both\");\n }\n if (options.session === undefined && options.all !== true) {\n throw new Error(\"Specify --session <id> or --all\");\n }\n}\n\nasync function resolveImportTarget(\n ctx: ImportContext,\n): Promise<{ repositoryRoot: string; paths: BasouPaths; manifest: Manifest }> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForImport(cwd);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n const manifest = await readManifest(paths);\n return { repositoryRoot, paths, manifest };\n}\n\n/**\n * The vendor-neutral import core: dedup, derive, validate, and write each\n * candidate, then report. Every `basou import <adapter>` funnels its\n * discovered candidates through here, so dedup / `--force` / `--dry-run`\n * semantics stay identical across adapters. Dedup is scoped to `sourceKind`\n * so one adapter never matches (or, under `--force`, deletes) another\n * adapter's session that happens to share an id string.\n */\nasync function importDerivedSessions(\n paths: BasouPaths,\n manifest: Manifest,\n options: ImportOptions,\n sourceKind: SessionSourceKind,\n candidates: ReadonlyArray<ImportCandidate>,\n): Promise<void> {\n const existingByExternalId = await loadExistingByExternalId(paths, sourceKind);\n // Session ids imported earlier in THIS run, so two source files that map to\n // one session id never double-import within a single invocation.\n const seenThisRun = new Set<string>();\n\n const results: ImportSessionResult[] = [];\n const counts: ImportCounts = {\n skippedNoAction: 0,\n skippedExisting: 0,\n replaced: 0,\n reimported: 0,\n skippedLegacy: 0,\n skippedDecreased: 0,\n skippedDuplicate: 0,\n };\n let sanitizedPaths = 0;\n\n // Parse + version-gate a derived payload before it touches disk. Returns null\n // when the source carried no provenance worth importing (the caller skips).\n const validate = (payload: SessionImportPayload | null): SessionImportPayload | null => {\n if (payload === null) return null;\n const parsed = SessionImportPayloadSchema.safeParse(payload);\n if (!parsed.success) {\n throw new Error(\"Invalid import payload\", { cause: parsed.error });\n }\n if (parsed.data.schema_version !== \"0.1.0\") {\n throw new Error(`Unsupported import schema_version: ${parsed.data.schema_version}`);\n }\n return parsed.data;\n };\n\n for (const { externalId, sourcePath, toPayload } of candidates) {\n if (seenThisRun.has(externalId)) {\n counts.skippedExisting++;\n continue;\n }\n const priors = existingByExternalId.get(externalId) ?? [];\n\n // Already imported in a prior run. Default is to skip (idempotent), but a\n // source whose native log GREW is re-imported in place, and --force\n // deletes + replaces regardless.\n if (priors.length > 0 && options.force !== true) {\n const prior = await classifyReimport(priors, sourcePath, externalId, counts);\n if (prior === null) continue; // skip recorded by classifyReimport\n const payload = validate(await toPayload());\n if (payload === null) {\n counts.skippedNoAction++;\n continue;\n }\n // Re-confirm growth against the size ACTUALLY read (the decision above used\n // a cheap pre-read stat): if the source was truncated / rotated between the\n // stat and the read, the smaller buffer must not be re-imported as a grow.\n const readSize = payload.session.source.source_size_bytes;\n if (\n prior.sourceSizeBytes !== undefined &&\n readSize !== undefined &&\n readSize <= prior.sourceSizeBytes\n ) {\n console.error(\n `Import: ${externalId} source changed during read (now ${readSize} <= ${prior.sourceSizeBytes} bytes); re-import skipped`,\n );\n counts.skippedDecreased++;\n continue;\n }\n const outcome = await reimportPreservingId(paths, manifest, prior.sessionId, payload, {\n dryRun: options.dryRun === true,\n });\n if (outcome.status === \"skipped\") {\n const detail =\n outcome.reason === \"prior_events_unreadable\"\n ? \"prior events.jsonl has unreadable lines\"\n : outcome.reason === \"prior_chain_broken\"\n ? \"prior events.jsonl failed hash-chain verification (run 'basou verify')\"\n : \"source changed in a non-append way (derived events would be dropped)\";\n console.error(`Import: ${externalId} ${detail}; re-import skipped`);\n counts.skippedNoAction++;\n continue;\n }\n counts.reimported++;\n seenThisRun.add(externalId);\n continue;\n }\n\n const payload = validate(await toPayload());\n if (payload === null) {\n counts.skippedNoAction++;\n continue;\n }\n\n // --force replace: delete the prior session(s) for this external id, but\n // only once the fresh payload is known good, so a failed re-derivation\n // never destroys the existing import. Skipped under --dry-run.\n if (priors.length > 0 && options.force === true) {\n if (options.dryRun !== true) {\n for (const { sessionId } of priors) {\n await rm(join(paths.sessions, sessionId), { recursive: true, force: true });\n }\n }\n counts.replaced++;\n }\n\n const result = await importSessionFromJson(paths, manifest, payload, {\n dryRun: options.dryRun === true,\n });\n results.push(result);\n seenThisRun.add(externalId);\n sanitizedPaths +=\n result.pathSanitizeReport.relatedFiles +\n (result.pathSanitizeReport.workingDirectoryRewritten ? 1 : 0);\n }\n\n if (sanitizedPaths > 0) {\n console.error(`Imported sessions: ${sanitizedPaths} path(s) sanitized`);\n }\n\n printImportResult(options, results, counts);\n}\n\n/** Mutable tally of every import disposition, surfaced by {@link printImportResult}. */\ntype ImportCounts = {\n skippedNoAction: number;\n /** Already imported and unchanged (or a duplicate-within-this-run). */\n skippedExisting: number;\n /** Deleted + replaced under --force. */\n replaced: number;\n /** Re-imported in place because the source grew. */\n reimported: number;\n /** Already imported but with no recorded size (pre-size-tracking import); not re-imported. */\n skippedLegacy: number;\n /** Source shrank since import (truncated / rotated); needs --force to replace. */\n skippedDecreased: number;\n /** More than one prior session for one external id (anomalous); needs --force. */\n skippedDuplicate: number;\n};\n\n/**\n * Decide whether an already-imported external id should be re-imported in place\n * because its source grew. Returns the single prior import to re-import into, or\n * `null` (recording the right skip count) when it must be left alone:\n * unchanged / shrank / legacy (no recorded size) / anomalously duplicated. The\n * size probe is a parse-free `stat`, so unchanged sources are dismissed cheaply.\n */\nasync function classifyReimport(\n priors: PriorImport[],\n sourcePath: string,\n externalId: string,\n counts: ImportCounts,\n): Promise<PriorImport | null> {\n if (priors.length > 1) {\n // Anomalous: a scoped re-import cannot pick which id to preserve, and\n // delete+recreate would orphan any linked_events. Leave it to --force.\n console.error(\n `Import: ${externalId} has ${priors.length} prior sessions; re-import skipped (use --force)`,\n );\n counts.skippedDuplicate++;\n return null;\n }\n const prior = priors[0];\n if (prior === undefined) {\n counts.skippedExisting++;\n return null;\n }\n const currentSize = await statSize(sourcePath);\n if (currentSize === undefined) {\n // Source vanished between discovery and now; nothing to re-import.\n counts.skippedExisting++;\n return null;\n }\n if (prior.sourceSizeBytes === undefined) {\n // Legacy import (no recorded size baseline): never auto-re-import; the size\n // populates on the next --force / fresh import.\n counts.skippedLegacy++;\n return null;\n }\n if (currentSize === prior.sourceSizeBytes) {\n counts.skippedExisting++; // unchanged\n return null;\n }\n if (currentSize < prior.sourceSizeBytes) {\n // Truncated / rotated: do NOT auto-replace derived provenance; --force only.\n console.error(\n `Import: ${externalId} source shrank (${currentSize} < ${prior.sourceSizeBytes} bytes); re-import skipped (use --force to replace)`,\n );\n counts.skippedDecreased++;\n return null;\n }\n return prior; // grew => re-import preserving id\n}\n\n/**\n * Encode an absolute project path into Claude Code's per-project directory\n * name. Claude Code replaces path separators with `-`, so\n * `/Users/x/projects/foo` becomes `-Users-x-projects-foo`. Best-effort for\n * the common case; paths with characters the vendor encodes differently may\n * need an explicit `--project`-derived directory in a later revision.\n */\nfunction encodeProjectDir(projectPath: string): string {\n return projectPath.replaceAll(\"/\", \"-\");\n}\n\n/**\n * Map of source external_id -> Basou session id(s) already present in the\n * workspace for the given `sourceKind`, so a re-import can skip (default) or,\n * under --force, delete and replace the existing session. Scoping to one\n * source kind keeps each adapter's id namespace separate: a Codex import must\n * never dedup against, or delete, a Claude-derived session that happens to\n * share an id string. Recognises both the structured `source.external_id`\n * (current imports) and the `claude-code import <id>` label form (sessions\n * imported before external_id existed), so existing dogfood imports are\n * matched either way. Unreadable sessions are skipped.\n */\n/**\n * A prior Basou session for an external id, with the source byte size recorded\n * at its last import (absent for legacy imports made before the field existed).\n * The size lets a re-import detect that an append-only source GREW.\n */\ntype PriorImport = { sessionId: string; sourceSizeBytes?: number };\n\nasync function loadExistingByExternalId(\n paths: BasouPaths,\n sourceKind: SessionSourceKind,\n): Promise<Map<string, PriorImport[]>> {\n const byExternalId = new Map<string, PriorImport[]>();\n const add = (externalId: string, prior: PriorImport): void => {\n const list = byExternalId.get(externalId);\n if (list === undefined) byExternalId.set(externalId, [prior]);\n else list.push(prior);\n };\n let sessionIds: string[];\n try {\n sessionIds = await enumerateSessionDirs(paths);\n } catch {\n return byExternalId;\n }\n for (const sessionId of sessionIds) {\n let session: Session;\n try {\n session = await readSessionYaml(paths, sessionId);\n } catch {\n continue;\n }\n if (session.session.source.kind !== sourceKind) continue;\n const sourceSizeBytes = session.session.source.source_size_bytes;\n // Build once; omit the size key entirely when absent (legacy import) so the\n // optional property stays absent rather than explicitly undefined.\n const prior: PriorImport =\n sourceSizeBytes !== undefined ? { sessionId, sourceSizeBytes } : { sessionId };\n const ext = session.session.source.external_id;\n if (typeof ext === \"string\" && ext.length > 0) {\n add(ext, prior);\n continue;\n }\n const label = session.session.label;\n const match = typeof label === \"string\" ? label.match(/^claude-code import (\\S+)$/) : null;\n if (match?.[1] !== undefined) add(match[1], prior);\n }\n return byExternalId;\n}\n\n/**\n * Select the Claude transcript files to import across one or more source roots.\n * Each root maps to a per-project transcript directory under `projectsRoot`.\n * With `--session`, every root is probed and only existing matches are returned\n * (an error is raised only if no root holds that transcript). With `--all`, the\n * `.jsonl` files of every root are unioned; a root whose directory is absent\n * contributes nothing. The missing-directory error is raised only when NO root\n * has a transcript directory, so refresh classifies \"nothing anywhere\" as a\n * skip rather than a failure.\n */\nasync function selectTranscriptFiles(\n projectsRoot: string,\n projectPaths: string[],\n options: ImportClaudeCodeOptions,\n): Promise<string[]> {\n if (options.session !== undefined) {\n const matches: string[] = [];\n for (const projectPath of projectPaths) {\n const file = join(projectsRoot, encodeProjectDir(projectPath), `${options.session}.jsonl`);\n if (await pathExists(file)) matches.push(file);\n }\n if (matches.length === 0) {\n throw new Error(\"Claude transcript not found for session id in project\");\n }\n return [...new Set(matches)];\n }\n const files: string[] = [];\n let anyDirFound = false;\n for (const projectPath of projectPaths) {\n const transcriptDir = join(projectsRoot, encodeProjectDir(projectPath));\n let entries: string[];\n try {\n entries = await readdir(transcriptDir);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) continue; // this root has no transcripts; try the next\n throw new Error(\"Failed to read Claude transcript directory\", { cause: error });\n }\n anyDirFound = true;\n for (const name of entries) {\n if (name.endsWith(\".jsonl\")) files.push(join(transcriptDir, name));\n }\n }\n if (!anyDirFound) {\n throw new Error(\"Claude transcript directory not found for project\");\n }\n return [...new Set(files)].sort();\n}\n\n/** Whether `file` exists (ENOENT => false; any other error propagates). */\nasync function pathExists(file: string): Promise<boolean> {\n try {\n await stat(file);\n return true;\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) return false;\n throw error;\n }\n}\n\n/** The file's byte size, or undefined if it vanished (ENOENT); other errors propagate. */\nasync function statSize(file: string): Promise<number | undefined> {\n try {\n return (await stat(file)).size;\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) return undefined;\n throw error;\n }\n}\n\n/**\n * Discover the Codex rollouts that belong to any of `projectPaths`. Codex\n * stores rollouts under date directories (not per-project like Claude), so the\n * whole tree is walked once and each rollout's `session_meta.cwd` is matched\n * against the set of requested roots. The exact-match is also the safety\n * boundary: only sessions started in a requested root are ever imported.\n * `--session` narrows to a single rollout by its Codex session id within those\n * roots; a session id that matches no rollout is an error, mirroring how the\n * Claude path fails on a missing `--session` transcript rather than reporting a\n * silent success.\n */\nasync function discoverCodexRollouts(\n sessionsRoot: string,\n projectPaths: string[],\n options: ImportCodexOptions,\n): Promise<Array<{ file: string; externalId: string }>> {\n const projectSet = new Set(projectPaths);\n const files = await findRolloutFiles(sessionsRoot);\n const matched: Array<{ file: string; externalId: string }> = [];\n for (const file of files) {\n const meta = await readRolloutMeta(file);\n if (meta === undefined) continue;\n if (!projectSet.has(meta.cwd)) continue;\n if (options.session !== undefined && meta.id !== options.session) continue;\n matched.push({ file, externalId: meta.id });\n }\n if (options.session !== undefined && matched.length === 0) {\n throw new Error(\"Codex rollout not found for session id in project\");\n }\n return matched;\n}\n\n/** Recursively collect every `rollout-*.jsonl` under the Codex sessions root. */\nasync function findRolloutFiles(sessionsRoot: string): Promise<string[]> {\n const found: string[] = [];\n const walk = async (dir: string, isRoot: boolean): Promise<void> => {\n let entries: Dirent[];\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n if (isRoot) {\n throw new Error(\"Codex sessions directory not found\", { cause: error });\n }\n return; // a subdir vanished mid-walk; ignore\n }\n throw new Error(\"Failed to read Codex sessions directory\", { cause: error });\n }\n for (const entry of entries) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n await walk(full, false);\n } else if (\n entry.isFile() &&\n entry.name.startsWith(\"rollout-\") &&\n entry.name.endsWith(\".jsonl\")\n ) {\n found.push(full);\n }\n }\n };\n await walk(sessionsRoot, true);\n return found.sort();\n}\n\n/**\n * Read just the `session_meta` (first record) of a rollout to learn its\n * project cwd and session id, without parsing the whole — usually large — log.\n * Returns `undefined` for any file whose first record is not a usable\n * `session_meta`, so the caller can skip it.\n */\nasync function readRolloutMeta(file: string): Promise<{ id: string; cwd: string } | undefined> {\n const firstLine = await readFirstLine(file);\n if (firstLine === undefined) return undefined;\n let parsed: unknown;\n try {\n parsed = JSON.parse(firstLine);\n } catch {\n return undefined;\n }\n if (!isObject(parsed) || parsed.type !== \"session_meta\") return undefined;\n const payload = isObject(parsed.payload) ? parsed.payload : undefined;\n if (payload === undefined) return undefined;\n const id = payload.id;\n const cwd = payload.cwd;\n if (typeof id !== \"string\" || id.length === 0) return undefined;\n if (typeof cwd !== \"string\" || cwd.length === 0) return undefined;\n return { id, cwd };\n}\n\n/** Read the first non-empty line of a file, streaming so large files are cheap. */\nasync function readFirstLine(file: string): Promise<string | undefined> {\n const stream = createReadStream(file, { encoding: \"utf8\" });\n const rl = createInterface({ input: stream, crlfDelay: Number.POSITIVE_INFINITY });\n try {\n for await (const line of rl) {\n const trimmed = line.trim();\n if (trimmed.length > 0) return trimmed;\n }\n return undefined;\n } catch {\n return undefined;\n } finally {\n rl.close();\n stream.destroy();\n }\n}\n\n/**\n * Read a JSONL native log into an array of records, plus the file's exact byte\n * size. A malformed line is skipped rather than failing the whole file, so\n * partial native logs still yield best-effort provenance. The byte size is read\n * from the SAME buffer that produced the records (an immutable snapshot), so the\n * size persisted as `source.source_size_bytes` always matches the imported\n * content even if the file is being appended to concurrently.\n */\nasync function readJsonlRecords(\n file: string,\n): Promise<{ records: ClaudeTranscriptRecord[]; sizeBytes: number }> {\n let buffer: Buffer;\n try {\n buffer = await readFile(file);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Source log not found\", { cause: error });\n }\n if (findErrorCode(error, \"EISDIR\")) {\n throw new Error(\"Source log path is not a file\", { cause: error });\n }\n throw new Error(\"Failed to read source log\", { cause: error });\n }\n\n const records: ClaudeTranscriptRecord[] = [];\n for (const line of buffer.toString(\"utf8\").split(\"\\n\")) {\n const trimmed = line.trim();\n if (trimmed.length === 0) continue;\n try {\n const parsed: unknown = JSON.parse(trimmed);\n if (isObject(parsed)) {\n records.push(parsed);\n }\n } catch {\n // A malformed line is skipped rather than failing the whole file.\n }\n }\n return { records, sizeBytes: buffer.length };\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction printImportResult(\n options: ImportOptions,\n results: ImportSessionResult[],\n counts: ImportCounts,\n): void {\n const isDry = options.dryRun === true;\n const eventTotal = results.reduce((sum, r) => sum + r.eventCount, 0);\n const {\n skippedNoAction,\n skippedExisting,\n replaced,\n reimported,\n skippedLegacy,\n skippedDecreased,\n skippedDuplicate,\n } = counts;\n\n if (options.json === true) {\n console.log(\n JSON.stringify({\n imported: results.map((r) => ({\n session_id: r.sessionId,\n event_count: r.eventCount,\n status: r.finalStatus,\n source: { kind: r.finalSourceKind, version: \"0.1.0\" },\n })),\n imported_count: results.length,\n replaced_count: replaced,\n reimported_count: reimported,\n skipped_no_action: skippedNoAction,\n skipped_already_imported: skippedExisting,\n skipped_legacy_untracked: skippedLegacy,\n skipped_decreased: skippedDecreased,\n skipped_duplicate: skippedDuplicate,\n event_total: eventTotal,\n dry_run: isDry,\n }),\n );\n return;\n }\n\n const skipParts: string[] = [];\n if (skippedNoAction > 0) skipParts.push(`${skippedNoAction} with no actions`);\n if (skippedExisting > 0) skipParts.push(`${skippedExisting} already imported`);\n if (skippedLegacy > 0) skipParts.push(`${skippedLegacy} legacy (untracked size)`);\n if (skippedDecreased > 0) skipParts.push(`${skippedDecreased} shrank`);\n if (skippedDuplicate > 0) skipParts.push(`${skippedDuplicate} duplicated`);\n const skipSuffix = skipParts.length > 0 ? `; skipped ${skipParts.join(\", \")}` : \"\";\n const eventsPart =\n replaced > 0 ? `${eventTotal} events, ${replaced} replaced` : `${eventTotal} events`;\n\n if (isDry) {\n const parts: string[] = [];\n if (results.length > 0) parts.push(`import ${results.length} session(s) (${eventsPart})`);\n if (reimported > 0) parts.push(`re-import ${reimported} changed session(s)`);\n const head = parts.length > 0 ? `Dry run: would ${parts.join(\", \")}` : \"Dry run: no changes\";\n console.log(`${head}${skipSuffix}`);\n return;\n }\n\n if (results.length === 0 && reimported === 0) {\n console.log(\n skipParts.length > 0\n ? `No new sessions imported (skipped ${skipParts.join(\", \")})`\n : \"No transcripts found to import\",\n );\n return;\n }\n\n const segments: string[] = [];\n if (results.length > 0) {\n const single =\n results.length === 1 && results[0] !== undefined ? ` (${shortId(results[0].sessionId)})` : \"\";\n segments.push(`Imported ${results.length} session(s)${single} (${eventsPart})`);\n }\n if (reimported > 0) {\n segments.push(\n `${results.length > 0 ? \"re-imported\" : \"Re-imported\"} ${reimported} changed session(s)`,\n );\n }\n console.log(`${segments.join(\", \")}${skipSuffix}`);\n}\n\nfunction shortId(id: string): string {\n if (id.startsWith(SES_PREFIX)) {\n return id.slice(SES_PREFIX.length, SES_PREFIX.length + SHORT_ID_LEN);\n }\n return id.slice(0, SHORT_ID_LEN);\n}\n\nasync function resolveRepositoryRootForImport(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\"Not a git repository. Run 'git init' first, then re-run 'basou import'.\", {\n cause: error,\n });\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n","import { basename, relative, resolve } from \"node:path\";\nimport {\n appendBasouGitignore,\n createManifest,\n ensureBasouDirectory,\n resolveRepositoryRoot,\n tryRemoteUrl,\n writeManifest,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport { extractCauseLabel, isVerbose, renderCliError } from \"../lib/error-render.js\";\n\nexport type InitOptions = {\n name?: string;\n projectName?: string;\n projectDescription?: string;\n repoUrl?: string;\n /**\n * Import source roots (repeatable). Each may be absolute or relative to the\n * invocation cwd; persisted as a path relative to the repository root under\n * `import.source_roots`, so one `.basou/` can aggregate sibling repos.\n */\n sourceRoot?: string[];\n force?: boolean;\n verbose?: boolean;\n};\n\n/** Commander collector: accumulate a repeatable option into an array. */\nfunction collectValue(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\nexport type InitContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n};\n\n/**\n * Register `basou init` on a commander program. The `--repo-url \"\"` (empty\n * string) form is the documented way to set `project.repository_url` to\n * `null` explicitly; omitting `--repo-url` falls back to\n * `git config --local remote.origin.url` and finally to omission.\n */\nexport function registerInitCommand(program: Command): void {\n program\n .command(\"init\")\n .description(\"Initialize a Basou workspace at the current Git repository root\")\n .option(\"--name <name>\", \"Workspace name (defaults to the repository directory name)\")\n .option(\"--project-name <name>\", \"Project display name\")\n .option(\"--project-description <description>\", \"Project description\")\n .option(\n \"--repo-url <url>\",\n \"Repository URL (defaults to git remote.origin.url; pass empty string for null)\",\n )\n .option(\n \"--source-root <path>\",\n \"Extra import source root, relative to the repo root (repeatable; aggregates sibling repos into this workspace)\",\n collectValue,\n [],\n )\n .option(\"-f, --force\", \"Overwrite an existing manifest\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: InitOptions) => {\n await runInit(options);\n });\n}\n\n/**\n * Programmatic entry that mutates process state (`exitCode`, stderr).\n * Exported for tests, but tests should prefer {@link doRunInit} so they are\n * not coupled to process global state.\n */\nexport async function runInit(options: InitOptions, ctx: InitContext = {}): Promise<void> {\n try {\n await doRunInit(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * Pure runner: resolves inputs, calls core APIs, prints the success line.\n * On any failure throws an Error whose `message` is pathless and whose\n * `cause` MAY contain a native fs error. Exported for tests so they can\n * assert on thrown errors without touching `process.exitCode`.\n */\nexport async function doRunInit(options: InitOptions, ctx: InitContext): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForInit(cwd);\n const workspaceName = options.name ?? basename(repositoryRoot);\n\n // --repo-url > git config --local remote.origin.url > omit\n // --repo-url \"\" => explicit null\n let repositoryUrl: string | null | undefined;\n if (options.repoUrl !== undefined) {\n repositoryUrl = options.repoUrl === \"\" ? null : options.repoUrl;\n } else {\n repositoryUrl = await tryRemoteUrl(repositoryRoot);\n }\n\n // Normalize each --source-root to a repo-root-relative path. A root that is\n // the repo root itself becomes \".\". Stored relative so the committed manifest\n // carries no absolute machine paths.\n const sourceRoots = (options.sourceRoot ?? []).map((p) => {\n const rel = relative(repositoryRoot, resolve(cwd, p));\n return rel === \"\" ? \".\" : rel;\n });\n\n const paths = await ensureBasouDirectory(repositoryRoot);\n const manifest = createManifest({\n workspaceName,\n ...(options.projectName !== undefined ? { projectName: options.projectName } : {}),\n ...(options.projectDescription !== undefined\n ? { projectDescription: options.projectDescription }\n : {}),\n ...(repositoryUrl !== undefined ? { repositoryUrl } : {}),\n ...(sourceRoots.length > 0 ? { sourceRoots } : {}),\n });\n\n await writeManifest(paths, manifest, { force: options.force === true });\n\n // .gitignore is best-effort: init succeeds even if this step fails.\n // The \"safe to run on an existing Git repo\" completion contract holds\n // even when manifest writes but .gitignore cannot (e.g. permission\n // denied) -- the core feature set still works.\n try {\n await appendBasouGitignore(repositoryRoot);\n } catch (error: unknown) {\n renderGitignoreWarning(error, isVerbose(options));\n }\n\n console.log(`Initialized Basou workspace: ${manifest.workspace.id}`);\n}\n\n/**\n * Render a non-fatal warning when `.gitignore` cannot be updated. Mirrors\n * the pathless contract enforced by {@link renderCliError} — never prints\n * `error.cause.message` because native fs errors embed the absolute path\n * in it.\n */\nfunction renderGitignoreWarning(error: unknown, verbose: boolean): void {\n const baseMessage = error instanceof Error ? error.message : String(error);\n // The fallback hint is intentionally `dist`-only-portable: it does not\n // reference any in-repo doc path, since the CLI is published\n // independently of `docs/`.\n console.error(\n `Warning: Could not update .gitignore (${baseMessage}). Add Basou's default .gitignore block manually.`,\n );\n if (verbose && error instanceof Error) {\n const label = extractCauseLabel(error);\n if (label !== undefined) console.error(`Caused by: ${label}`);\n }\n}\n\n/**\n * Wrap the core git capability so the CLI surfaces the command-specific\n * \"Run 'git init' first, then re-run 'basou init'.\" suffix while the\n * capability layer remains command-agnostic.\n */\nasync function resolveRepositoryRootForInit(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\"Not a git repository. Run 'git init' first, then re-run 'basou init'.\", {\n cause: error,\n });\n }\n throw error;\n }\n}\n","import { assertBasouRootSafe, basouPaths, findErrorCode, resolveRepositoryRoot } from \"@basou/core\";\nimport { type Command, InvalidArgumentError } from \"commander\";\nimport { isVerbose, renderCliError } from \"../lib/error-render.js\";\nimport { type ImportOutcome, type RefreshResult, refreshAll } from \"../lib/provenance-actions.js\";\nimport type { ImportContext } from \"./import.js\";\nimport {\n DEFAULT_WATCH_INTERVAL_SEC,\n MAX_WATCH_INTERVAL_SEC,\n MIN_WATCH_INTERVAL_SEC,\n runRefreshWatch,\n} from \"./refresh-watch.js\";\n\nexport type RefreshOptions = {\n project?: string[];\n force?: boolean;\n dryRun?: boolean;\n json?: boolean;\n /** Run as a long-lived watcher: re-import when the native logs change. */\n watch?: boolean;\n /** Poll interval in seconds for `--watch` (default {@link DEFAULT_WATCH_INTERVAL_SEC}). */\n interval?: number;\n verbose?: boolean;\n};\n\n/** Commander collector: accumulate a repeatable option into an array. */\nfunction collectPath(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\n/** Commander parser: `--interval` is an integer count of seconds within the supported range. */\nexport function parseInterval(value: string): number {\n const seconds = Number(value);\n if (\n !Number.isInteger(seconds) ||\n seconds < MIN_WATCH_INTERVAL_SEC ||\n seconds > MAX_WATCH_INTERVAL_SEC\n ) {\n throw new InvalidArgumentError(\n `--interval must be an integer between ${MIN_WATCH_INTERVAL_SEC} and ${MAX_WATCH_INTERVAL_SEC} (seconds).`,\n );\n }\n return seconds;\n}\n\n/** Resolve after `ms`, or early when `signal` aborts (e.g. on Ctrl-C). Leaves no listener behind. */\nfunction abortableSleep(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise<void>((resolve) => {\n if (signal.aborted) {\n resolve();\n return;\n }\n let timer: ReturnType<typeof setTimeout>;\n const onAbort = (): void => {\n clearTimeout(timer);\n resolve();\n };\n timer = setTimeout(() => {\n signal.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nexport type RefreshContext = ImportContext & {\n /** Defaults to `() => new Date()`. Injectable for tests. */\n nowProvider?: () => Date;\n};\n\n/**\n * Wire `basou refresh` onto `program`. One command that imports every adapter\n * for the project and regenerates handoff + decisions, so the dogfood loop is\n * a single invocation instead of four.\n */\nexport function registerRefreshCommand(program: Command): void {\n program\n .command(\"refresh\")\n .description(\n \"Import all adapters for the project and regenerate handoff + decisions in one step\",\n )\n .option(\n \"--project <path>\",\n \"Source project path to import (repeatable; defaults to the manifest source roots, then the repository root)\",\n collectPath,\n [],\n )\n .option(\"--force\", \"Re-import sessions already imported instead of skipping\")\n .option(\"--dry-run\", \"Preview imports and skip writing handoff / decisions\")\n .option(\"--json\", \"Output the result as JSON\")\n .option(\n \"--watch\",\n \"Keep running: re-import + regenerate when the native logs change (Ctrl-C to stop)\",\n )\n .option(\n \"--interval <seconds>\",\n `Poll interval for --watch, in seconds (default ${DEFAULT_WATCH_INTERVAL_SEC}, min ${MIN_WATCH_INTERVAL_SEC})`,\n parseInterval,\n )\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: RefreshOptions) => {\n await runRefresh(options);\n });\n}\n\n/**\n * Programmatic entry that owns `process.exitCode`. Tests should prefer\n * {@link doRunRefresh}, which returns the structured result.\n */\nexport async function runRefresh(options: RefreshOptions, ctx: RefreshContext = {}): Promise<void> {\n try {\n if (options.watch === true) {\n await doRunRefreshWatch(options, ctx);\n } else {\n await doRunRefresh(options, ctx);\n }\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * `basou refresh --watch`: resolve + validate, then run the polling watcher\n * until SIGINT / SIGTERM. Startup failures (bad combo, no workspace, failed\n * initial refresh) propagate and exit non-zero; a steady-state cycle failure is\n * logged inside the loop and the watcher keeps running.\n */\nexport async function doRunRefreshWatch(\n options: RefreshOptions,\n ctx: RefreshContext,\n): Promise<void> {\n if (options.dryRun === true) throw new Error(\"--watch cannot be combined with --dry-run.\");\n if (options.json === true) throw new Error(\"--watch cannot be combined with --json.\");\n if (options.force === true) throw new Error(\"--watch cannot be combined with --force.\");\n\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForRefresh(cwd);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const intervalMs = (options.interval ?? DEFAULT_WATCH_INTERVAL_SEC) * 1000;\n const controller = new AbortController();\n const onSignal = (): void => controller.abort();\n process.on(\"SIGINT\", onSignal);\n process.on(\"SIGTERM\", onSignal);\n try {\n await runRefreshWatch({\n ctx,\n paths,\n intervalMs,\n importOptions:\n options.project !== undefined && options.project.length > 0\n ? { project: options.project }\n : {},\n now: () => ctx.nowProvider?.() ?? new Date(),\n signal: controller.signal,\n sleep: abortableSleep,\n log: (line) => console.log(line),\n });\n } finally {\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n }\n}\n\n/**\n * Pure runner: resolves the workspace, runs the shared refresh pipeline, and\n * prints a summary (or JSON). Returns the {@link RefreshResult} so the same\n * pipeline can be exercised by tests and reused by the view server.\n */\nexport async function doRunRefresh(\n options: RefreshOptions,\n ctx: RefreshContext,\n): Promise<RefreshResult> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForRefresh(cwd);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const nowIso = (ctx.nowProvider?.() ?? new Date()).toISOString();\n const result = await refreshAll({\n options: {\n ...(options.project !== undefined && options.project.length > 0\n ? { project: options.project }\n : {}),\n ...(options.force === true ? { force: true } : {}),\n ...(options.dryRun === true ? { dryRun: true } : {}),\n },\n ctx,\n paths,\n nowIso,\n });\n\n if (options.json === true) {\n console.log(JSON.stringify(result));\n } else {\n printRefreshSummary(result);\n }\n return result;\n}\n\nfunction describeImport(outcome: ImportOutcome): string {\n if (outcome.status === \"skipped\") {\n return `${outcome.adapter}: skipped (${outcome.reason})`;\n }\n const verb = outcome.dryRun ? \"would import\" : \"imported\";\n const parts = [`${outcome.importedCount} session(s)`, `${outcome.eventTotal} events`];\n if (outcome.reimportedCount > 0) parts.push(`${outcome.reimportedCount} re-imported`);\n if (outcome.replacedCount > 0) parts.push(`${outcome.replacedCount} replaced`);\n if (outcome.skippedAlreadyImported > 0)\n parts.push(`${outcome.skippedAlreadyImported} already imported`);\n if (outcome.skippedLegacyUntracked > 0) parts.push(`${outcome.skippedLegacyUntracked} legacy`);\n return `${outcome.adapter}: ${verb} ${parts.join(\", \")}`;\n}\n\nfunction printRefreshSummary(result: RefreshResult): void {\n console.log(describeImport(result.claudeCode));\n console.log(describeImport(result.codex));\n if (result.handoff.status === \"generated\") {\n console.log(\n `handoff: regenerated (sessions: ${result.handoff.sessionCount}, decisions: ${result.handoff.decisionCount})`,\n );\n } else {\n console.log(`handoff: skipped (${result.handoff.reason})`);\n }\n if (result.decisions.status === \"generated\") {\n console.log(`decisions: regenerated (${result.decisions.decisionCount})`);\n } else {\n console.log(`decisions: skipped (${result.decisions.reason})`);\n }\n}\n\nasync function resolveRepositoryRootForRefresh(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\"Not a git repository. Run 'git init' first, then re-run 'basou refresh'.\", {\n cause: error,\n });\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n","import {\n type BasouPaths,\n readMarkdownFile,\n renderDecisions,\n renderHandoff,\n renderWithMarkers,\n writeMarkdownFile,\n} from \"@basou/core\";\nimport {\n doRunImportClaudeCode,\n doRunImportCodex,\n type ImportContext,\n type ImportOptions,\n} from \"../commands/import.js\";\n\n/**\n * Shared provenance actions reused by both `basou refresh` (one-shot CLI) and\n * the `basou view` server's action endpoints, so the two stay behaviourally\n * identical. These wrap the existing import commands and markdown renderers;\n * they own no process state and print nothing of their own.\n */\n\n/** Which native-log adapter an import outcome came from. */\nexport type ImportAdapter = \"claude-code\" | \"codex\";\n\n/** Result of running one adapter's import, or a note that it was skipped. */\nexport type ImportOutcome =\n | {\n adapter: ImportAdapter;\n status: \"ran\";\n importedCount: number;\n replacedCount: number;\n /** Sessions re-imported in place because their source grew. */\n reimportedCount: number;\n skippedNoAction: number;\n skippedAlreadyImported: number;\n /** Already imported but with no recorded source size (pre-size-tracking); not re-imported. */\n skippedLegacyUntracked: number;\n eventTotal: number;\n dryRun: boolean;\n }\n | { adapter: ImportAdapter; status: \"skipped\"; reason: string };\n\n/** Counts from regenerating handoff.md / decisions.md, or a skip note. */\nexport type GenerateOutcome<TExtra> =\n | ({ status: \"generated\" } & TExtra)\n | { status: \"skipped\"; reason: string };\n\nexport type HandoffCounts = {\n sessionCount: number;\n taskCount: number;\n decisionCount: number;\n pendingApprovalsCount: number;\n};\n\n/** Structured result of {@link refreshAll}. */\nexport type RefreshResult = {\n claudeCode: ImportOutcome;\n codex: ImportOutcome;\n handoff: GenerateOutcome<HandoffCounts>;\n decisions: GenerateOutcome<{ decisionCount: number }>;\n dryRun: boolean;\n};\n\nexport type RefreshActionOptions = {\n project?: string[];\n force?: boolean;\n dryRun?: boolean;\n};\n\n/**\n * Run `fn` (an import command invoked with `json: true`) while capturing its\n * console output, then return the single machine-readable JSON result line.\n * The import commands print their result as one JSON object on stdout; that\n * line is the result contract. `console` is always restored, even on throw.\n */\nasync function captureImportJson(fn: () => Promise<void>): Promise<Record<string, unknown>> {\n const stdout: string[] = [];\n const originalLog = console.log;\n const originalError = console.error;\n console.log = ((...args: unknown[]) => {\n stdout.push(args.map((a) => String(a)).join(\" \"));\n }) as typeof console.log;\n // The import path writes an informational \"N path(s) sanitized\" line to\n // stderr; swallow it so refresh / the view server stay quiet.\n console.error = (() => {}) as typeof console.error;\n try {\n await fn();\n } finally {\n console.log = originalLog;\n console.error = originalError;\n }\n for (let i = stdout.length - 1; i >= 0; i--) {\n const line = stdout[i];\n if (line === undefined) continue;\n try {\n const parsed: unknown = JSON.parse(line);\n if (parsed !== null && typeof parsed === \"object\" && \"imported_count\" in parsed) {\n return parsed as Record<string, unknown>;\n }\n } catch {\n // Not the JSON result line; keep scanning earlier lines.\n }\n }\n throw new Error(\"Import produced no parseable result\");\n}\n\nfunction readCount(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\n/**\n * A source-log directory that does not exist for the requested project is a\n * normal \"this adapter has nothing here\" condition for refresh, not a failure.\n */\nfunction isMissingSourceDir(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n return (\n error.message === \"Claude transcript directory not found for project\" ||\n error.message === \"Codex sessions directory not found\"\n );\n}\n\n/** Run one adapter import as a best-effort action, classifying a missing source dir as skipped. */\nasync function runImport(adapter: ImportAdapter, fn: () => Promise<void>): Promise<ImportOutcome> {\n try {\n const json = await captureImportJson(fn);\n return {\n adapter,\n status: \"ran\",\n importedCount: readCount(json.imported_count),\n replacedCount: readCount(json.replaced_count),\n reimportedCount: readCount(json.reimported_count),\n skippedNoAction: readCount(json.skipped_no_action),\n skippedAlreadyImported: readCount(json.skipped_already_imported),\n skippedLegacyUntracked: readCount(json.skipped_legacy_untracked),\n eventTotal: readCount(json.event_total),\n dryRun: json.dry_run === true,\n };\n } catch (error: unknown) {\n if (isMissingSourceDir(error)) {\n return { adapter, status: \"skipped\", reason: \"no source logs for this project\" };\n }\n throw error;\n }\n}\n\nfunction importOptions(options: RefreshActionOptions): ImportOptions {\n return {\n all: true,\n json: true,\n ...(options.project !== undefined ? { project: options.project } : {}),\n ...(options.force === true ? { force: true } : {}),\n ...(options.dryRun === true ? { dryRun: true } : {}),\n };\n}\n\n/** Import Claude Code transcripts for the project (best-effort). */\nexport function importClaudeCode(\n options: RefreshActionOptions,\n ctx: ImportContext,\n): Promise<ImportOutcome> {\n return runImport(\"claude-code\", () => doRunImportClaudeCode(importOptions(options), ctx));\n}\n\n/** Import Codex rollouts for the project (best-effort). */\nexport function importCodex(\n options: RefreshActionOptions,\n ctx: ImportContext,\n): Promise<ImportOutcome> {\n return runImport(\"codex\", () => doRunImportCodex(importOptions(options), ctx));\n}\n\ntype RenderCallbacks = Parameters<typeof renderHandoff>[0];\n\n/** Regenerate `.basou/handoff.md` and return the renderer's counts. */\nexport async function regenerateHandoff(\n paths: BasouPaths,\n nowIso: string,\n callbacks?: Omit<RenderCallbacks, \"paths\" | \"nowIso\">,\n): Promise<HandoffCounts> {\n const result = await renderHandoff({ paths, nowIso, ...callbacks });\n const existing = await readMarkdownFile(paths.files.handoff);\n await writeMarkdownFile(\n paths.files.handoff,\n renderWithMarkers(existing, result.body, \"handoff.md\"),\n );\n return {\n sessionCount: result.sessionCount,\n taskCount: result.taskCount,\n decisionCount: result.decisionCount,\n pendingApprovalsCount: result.pendingApprovalsCount,\n };\n}\n\n/** Regenerate `.basou/decisions.md` and return the decision count. */\nexport async function regenerateDecisions(\n paths: BasouPaths,\n nowIso: string,\n callbacks?: Omit<Parameters<typeof renderDecisions>[0], \"paths\" | \"nowIso\">,\n): Promise<{ decisionCount: number }> {\n const result = await renderDecisions({ paths, nowIso, ...callbacks });\n const existing = await readMarkdownFile(paths.files.decisions);\n await writeMarkdownFile(\n paths.files.decisions,\n renderWithMarkers(existing, result.body, \"decisions.md\"),\n );\n return { decisionCount: result.decisionCount };\n}\n\n/**\n * The shared refresh pipeline: import both adapters (best-effort) for the\n * project, then regenerate handoff + decisions. Under `dryRun`, imports run in\n * preview mode and the markdown files are left untouched. The caller resolves\n * `paths` / `nowIso` and supplies the import `ctx`.\n */\nexport async function refreshAll(args: {\n options: RefreshActionOptions;\n ctx: ImportContext;\n paths: BasouPaths;\n nowIso: string;\n}): Promise<RefreshResult> {\n const { options, ctx, paths, nowIso } = args;\n const dryRun = options.dryRun === true;\n\n const claudeCode = await importClaudeCode(options, ctx);\n const codex = await importCodex(options, ctx);\n\n if (dryRun) {\n const skipped = { status: \"skipped\" as const, reason: \"dry-run\" };\n return { claudeCode, codex, handoff: skipped, decisions: skipped, dryRun };\n }\n\n const handoffCounts = await regenerateHandoff(paths, nowIso);\n const decisionCounts = await regenerateDecisions(paths, nowIso);\n return {\n claudeCode,\n codex,\n handoff: { status: \"generated\", ...handoffCounts },\n decisions: { status: \"generated\", ...decisionCounts },\n dryRun,\n };\n}\n","import type { Dirent } from \"node:fs\";\nimport { readdir, stat } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { type BasouPaths, findErrorCode } from \"@basou/core\";\nimport {\n type ImportOutcome,\n importClaudeCode,\n importCodex,\n type RefreshActionOptions,\n regenerateDecisions,\n regenerateHandoff,\n} from \"../lib/provenance-actions.js\";\nimport type { ImportContext } from \"./import.js\";\n\n/** Default poll interval for `--watch`, in seconds. */\nexport const DEFAULT_WATCH_INTERVAL_SEC = 30;\n/** Smallest accepted `--interval`, in seconds. */\nexport const MIN_WATCH_INTERVAL_SEC = 5;\n/** Largest accepted `--interval`, in seconds (1 day; keeps the timer well within the 32-bit ms range). */\nexport const MAX_WATCH_INTERVAL_SEC = 86_400;\n\n/** A file's change signature: a refresh is triggered when this moves. */\ntype FileSig = { mtimeMs: number; size: number };\n/** Absolute `*.jsonl` path -> its {mtime, size} signature. */\nexport type SourceLogScan = Map<string, FileSig>;\n\n/**\n * The native-log stores the importers read (Codex rollouts + Claude\n * transcripts), resolved from the context or the `~` defaults. These are the\n * directories the watcher polls -- a new session is a new/grown `*.jsonl` here.\n */\nexport function watchedRoots(ctx: ImportContext): string[] {\n return [\n ctx.codexSessionsDir ?? join(homedir(), \".codex\", \"sessions\"),\n ctx.claudeProjectsDir ?? join(homedir(), \".claude\", \"projects\"),\n ];\n}\n\n/**\n * Recursively collect a `{mtime, size}` signature of every `*.jsonl` under the\n * given roots, keyed by absolute path. A missing root contributes nothing (it\n * may appear later); a file that vanishes mid-walk is skipped. No file content\n * is read, so this is cheap to run every poll.\n */\nexport async function scanSourceLogs(roots: string[]): Promise<SourceLogScan> {\n const out: SourceLogScan = new Map();\n const walk = async (dir: string): Promise<void> => {\n let entries: Dirent[];\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch (error: unknown) {\n // Absent (ENOENT) or not a directory (ENOTDIR): nothing to scan here.\n if (findErrorCode(error, \"ENOENT\") || findErrorCode(error, \"ENOTDIR\")) return;\n // Surface other errors pathlessly (the native message carries the path).\n throw new Error(\"Failed to read a source log directory\", { cause: error });\n }\n for (const entry of entries) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n await walk(full);\n } else if (entry.isFile() && entry.name.endsWith(\".jsonl\")) {\n try {\n const info = await stat(full);\n out.set(full, { mtimeMs: info.mtimeMs, size: info.size });\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) continue; // vanished mid-walk; skip\n throw new Error(\"Failed to stat a source log file\", { cause: error });\n }\n }\n }\n };\n for (const root of roots) await walk(root);\n return out;\n}\n\n/** Whether two scans describe the same set of files at the same size/mtime. */\nexport function scansEqual(a: SourceLogScan, b: SourceLogScan): boolean {\n if (a.size !== b.size) return false;\n for (const [path, sig] of a) {\n const other = b.get(path);\n if (other === undefined || other.mtimeMs !== sig.mtimeMs || other.size !== sig.size) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * How many sessions an import outcome changed on disk: new imports PLUS\n * in-place re-imports of grown sources PLUS --force replacements. Any\n * non-zero count must trigger a handoff / decisions regeneration, so a session\n * that was re-imported (not freshly imported) does not leave the derived\n * markdown stale.\n */\nfunction changedCount(outcome: ImportOutcome): number {\n return outcome.status === \"ran\"\n ? outcome.importedCount + outcome.reimportedCount + outcome.replacedCount\n : 0;\n}\n\nfunction describeOutcome(outcome: ImportOutcome): string {\n if (outcome.status !== \"ran\") return `${outcome.adapter} skipped`;\n const reimported = outcome.reimportedCount > 0 ? ` ~${outcome.reimportedCount}` : \"\";\n return `${outcome.adapter} +${outcome.importedCount}${reimported}`;\n}\n\nfunction hms(date: Date): string {\n return date.toISOString().slice(11, 19);\n}\n\n/** Dependencies for {@link runRefreshWatch}; timers / clock / signal are injectable for tests. */\nexport type WatchDeps = {\n ctx: ImportContext;\n paths: BasouPaths;\n intervalMs: number;\n /** Import options forwarded to each cycle (project source roots only; no force / dry-run in watch). */\n importOptions: RefreshActionOptions;\n now: () => Date;\n signal: AbortSignal;\n /** Resolves after `ms`, or early when `signal` aborts. */\n sleep: (ms: number, signal: AbortSignal) => Promise<void>;\n log: (line: string) => void;\n};\n\n/** Import both adapters for the workspace's source roots; returns the outcomes + total imported. */\nasync function runImports(\n deps: WatchDeps,\n): Promise<{ claude: ImportOutcome; codex: ImportOutcome; changed: number }> {\n const claude = await importClaudeCode(deps.importOptions, deps.ctx);\n const codex = await importCodex(deps.importOptions, deps.ctx);\n return { claude, codex, changed: changedCount(claude) + changedCount(codex) };\n}\n\n/** Regenerate handoff + decisions; returns the handoff session count. */\nasync function regenerate(deps: WatchDeps): Promise<number> {\n const nowIso = deps.now().toISOString();\n const handoff = await regenerateHandoff(deps.paths, nowIso);\n await regenerateDecisions(deps.paths, nowIso);\n return handoff.sessionCount;\n}\n\n/**\n * Poll the native-log stores and keep the workspace current. Does an initial\n * catch-up refresh, then on each interval re-imports ONLY when the logs are\n * quiescent (unchanged since the previous poll, so no session is mid-write) AND\n * have changed since the last import. Handoff / decisions regenerate only when\n * something was imported, so unrelated AI activity elsewhere never rewrites this\n * workspace's files. A failure inside a steady-state cycle is logged and the\n * loop continues; the initial refresh failing is fatal (it propagates). Returns\n * when `signal` aborts (after the in-flight cycle, never mid-write).\n */\nexport async function runRefreshWatch(deps: WatchDeps): Promise<void> {\n const { intervalMs, ctx, signal, sleep, log } = deps;\n const roots = watchedRoots(ctx);\n log(\n `watching ${roots.join(\", \")} every ${Math.round(intervalMs / 1000)}s ` +\n \"(imports on change; Ctrl-C to stop)\",\n );\n\n // Baseline BEFORE the initial import, so a session that appears during the\n // import window is not mistaken for \"already seen\" and missed forever.\n let lastScan = await scanSourceLogs(roots);\n let importedScan = lastScan;\n\n // Initial catch-up: failure here is fatal (propagates to the caller).\n const initial = await runImports(deps);\n const initialSessions = await regenerate(deps);\n log(\n `[${hms(deps.now())}] refreshed: ${describeOutcome(initial.codex)}, ` +\n `${describeOutcome(initial.claude)} (sessions: ${initialSessions})`,\n );\n if (signal.aborted) {\n log(\"watch stopped\");\n return;\n }\n\n // Set when an import succeeded but the matching regenerate has not yet (so a\n // regenerate failure cannot leave handoff / decisions stale forever).\n let pendingRegen = false;\n while (!signal.aborted) {\n await sleep(intervalMs, signal);\n if (signal.aborted) break;\n try {\n const current = await scanSourceLogs(roots);\n // Quiescent since the previous poll AND changed since the last import.\n if (scansEqual(current, lastScan) && !scansEqual(current, importedScan)) {\n const { claude, codex, changed } = await runImports(deps);\n if (changed > 0) pendingRegen = true;\n if (pendingRegen) {\n const sessions = await regenerate(deps);\n pendingRegen = false;\n log(\n `[${hms(deps.now())}] refreshed: ${describeOutcome(codex)}, ` +\n `${describeOutcome(claude)} (sessions: ${sessions})`,\n );\n }\n importedScan = current;\n }\n lastScan = current;\n } catch (error: unknown) {\n // A transient fs error must not kill a long-running watcher. Messages from\n // the scan / import / render layers are pathless by contract.\n const message = error instanceof Error ? error.message : String(error);\n log(`[${hms(deps.now())}] refresh cycle skipped: ${message}`);\n }\n }\n log(\"watch stopped\");\n}\n","import type { ChildProcess } from \"node:child_process\";\nimport { mkdir } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport {\n acquireLock,\n assertBasouRootSafe,\n type BasouPaths,\n basouPaths,\n ChildProcessRunner,\n claudeCodeAdapterMetadata,\n appendChainedEvent as coreAppendChainedEvent,\n type DiffResult,\n finalizeSessionYaml,\n type GitSnapshot,\n getDiff,\n getSnapshot,\n overwriteYamlFile,\n type PrefixedId,\n type ProcessRunner,\n prefixedUlid,\n type RunResult,\n readManifest,\n readYamlFile,\n resolveClaudeCodeCommand,\n resolveRepositoryRoot,\n type Session,\n SessionSchema,\n sanitizeRelatedFiles,\n sanitizeWorkingDirectory,\n writeYamlFile,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport { isVerbose, renderCliError } from \"../lib/error-render.js\";\n\n// Appends one event to the session's events.jsonl. The `sessionDir` argument\n// is retained for the test-injection seam (ctx.appendEvent); the production\n// binding ignores it and chains via paths + sessionId.\ntype AppendEventFn = (sessionDir: string, event: unknown) => Promise<void>;\ntype ResolveCommandFn = typeof resolveClaudeCodeCommand;\ntype GetDiffFn = typeof getDiff;\n\n/**\n * `basou run claude-code` orchestration: spawn claude-code as a single new\n * Basou session and record its lifecycle (session_started, optional\n * git_snapshot pre, status_changed, command_executed, optional git_snapshot\n * post, file_changed × N, status_changed, session_ended) to events.jsonl.\n *\n * The child inherits the parent's stdio (`capture: \"none\"`) so that\n * claude-code's interactive TTY remains usable; raw stdout/stderr is\n * intentionally NOT captured into events.jsonl or `.basou/raw/` in v0.1.\n */\nexport type RunOptions = {\n // commander turns `--no-snapshot` into `snapshot: false`. The default\n // (no flag) leaves this `undefined` (treated as `true` downstream).\n snapshot?: boolean;\n cwd?: string;\n verbose?: boolean;\n};\n\nexport type RunContext = {\n runner?: ProcessRunner;\n now?: () => Date;\n appendEvent?: AppendEventFn;\n onExitHookInstalled?: (handler: () => void) => void;\n // Override the claude-code PATH lookup. Tests use this to skip real\n // `which` invocations and force success / failure deterministically.\n resolveCommand?: ResolveCommandFn;\n // Override the git diff capability. Tests use this to force capability\n // failure deterministically without rewriting the git fixture state.\n getDiff?: GetDiffFn;\n};\n\n/**\n * Wire the `basou run` command group into `program`. The optional `ctx` is\n * passed through to `runClaudeCode` so tests can intercept the action callback\n * (fake runner, fake clock, deterministic resolveCommand / getDiff). Production\n * callers omit it.\n *\n * Basou options (`--no-snapshot`, `--cwd`, `-v`) are defined on both the\n * `run` group and the inner `claude-code` subcommand. commander's\n * `passThroughOptions()` only forwards UNKNOWN options to args, so a\n * group-only definition would make `basou run claude-code --no-snapshot`\n * crash with \"unknown option\". Duplicating the definitions lets the option\n * be recognized regardless of position; only `--`-separated args go to the\n * child. v0.2+ adapter additions (codex / gemini) should consider\n * extracting a common-option helper rather than re-duplicating.\n */\nexport function registerRunCommand(program: Command, ctx: RunContext = {}): void {\n const runCommand = program\n .command(\"run\")\n .description(\"Run an AI coding tool through Basou as a tracked session\")\n // Required so the inner `claude-code` subcommand can pass through\n // arguments after `--` to the child without commander interpreting them\n // as run-group options.\n .enablePositionalOptions()\n .option(\"--no-snapshot\", \"Skip git_snapshot before/after the session\")\n .option(\"--cwd <path>\", \"Run from a Basou root other than process.cwd()\")\n .option(\"-v, --verbose\", \"Show error causes\");\n\n runCommand\n .command(\"claude-code [args...]\")\n .description(\"Run Claude Code CLI as a Basou-tracked session\")\n // Same options redeclared on the subsubcommand so they are recognized\n // when placed AFTER `claude-code` as well; see the function comment.\n .option(\"--no-snapshot\", \"Skip git_snapshot before/after the session\")\n .option(\"--cwd <path>\", \"Run from a Basou root other than process.cwd()\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .passThroughOptions()\n .action(async (args: string[], options: RunOptions, command: Command) => {\n const parentOptions = (command.parent?.opts() ?? {}) as RunOptions;\n // Both layers default `snapshot` to `true` when --no-snapshot is\n // omitted, so a naive spread would let the subsubcommand's default\n // overwrite a `--no-snapshot` set on the parent. Take a logical AND\n // instead: snapshot stays on only when neither layer disables it.\n const snapshotOn = parentOptions.snapshot !== false && options.snapshot !== false;\n const merged: RunOptions = {\n ...parentOptions,\n ...options,\n snapshot: snapshotOn,\n };\n try {\n const exitCode = await runClaudeCode(args, merged, ctx);\n process.exit(exitCode);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(merged) });\n process.exit(1);\n }\n });\n}\n\nexport async function runClaudeCode(\n args: string[],\n options: RunOptions,\n ctx: RunContext = {},\n): Promise<number> {\n const runner = ctx.runner ?? new ChildProcessRunner();\n const now = ctx.now ?? (() => new Date());\n const resolveCommand: ResolveCommandFn = ctx.resolveCommand ?? resolveClaudeCodeCommand;\n const getDiffFn: GetDiffFn = ctx.getDiff ?? getDiff;\n\n // 1. Resolve the claude-code executable BEFORE any side-effect: a missing\n // CLI is a user installation issue, not something worth recording as a\n // Basou session. Failure here leaves no sessions/<id>/ entry behind.\n const { command } = await resolveCommand();\n\n const cwd = options.cwd ?? process.cwd();\n\n // 2. Resolve repository root (entry-fail when not in a git repo).\n const repoRoot = await resolveRepositoryRootForRun(cwd);\n const paths = basouPaths(repoRoot);\n\n // 3. Workspace safety check.\n await assertBasouRootSafe(paths.root);\n\n // 4. Read manifest to bind session.workspace_id.\n const manifest = await readManifest(paths);\n\n // 5. Build a fresh session and persist its initial state.\n const sessionId = prefixedUlid(\"ses\");\n const sessionDir = join(paths.sessions, sessionId);\n await mkdir(sessionDir, { recursive: true });\n\n // Every append chains onto the on-disk tail under a short-lived session lock\n // (the self-locking wrapper); the lock is NEVER held across the child. Tests\n // inject ctx.appendEvent to force append failures.\n const appendEvent: AppendEventFn =\n ctx.appendEvent ??\n (async (_sessionDir, event) => {\n await coreAppendChainedEvent(paths, sessionId, event);\n });\n\n const startedAt = now().toISOString();\n const sessionYamlPath = join(sessionDir, \"session.yaml\");\n const session = buildInitialSession({\n id: sessionId,\n command,\n args,\n cwd: repoRoot,\n workspaceId: manifest.workspace.id,\n startedAt,\n });\n await writeYamlFile(sessionYamlPath, session);\n\n // 6. session_started.\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_started\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: startedAt,\n source: claudeCodeAdapterMetadata.kind,\n });\n\n // 7. Optional pre-execute git_snapshot.\n let preSnapshot: GitSnapshot | null = null;\n if (options.snapshot !== false) {\n preSnapshot = await tryAppendGitSnapshot(sessionDir, sessionId, repoRoot, now, appendEvent);\n }\n\n // 8. status_changed: initialized -> running.\n const runningAt = now().toISOString();\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_status_changed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: runningAt,\n source: claudeCodeAdapterMetadata.kind,\n from: \"initialized\",\n to: \"running\",\n });\n // Lock the status write so it cannot interleave-clobber a foreign locked\n // session.yaml writer (e.g. a task attach setting task_id on this session).\n const runningLock = await acquireLock(paths, \"session\", sessionId);\n try {\n await mutateSessionYaml(sessionYamlPath, (s) => {\n s.session.status = \"running\";\n });\n } finally {\n await runningLock.release();\n }\n\n // 9. Transient signal hooks (SIGINT / SIGTERM / exit). The exit hook is a\n // last-resort SIGKILL if the parent dies abnormally.\n const controller = new AbortController();\n let signalReceived: NodeJS.Signals | null = null;\n let activeChild: ChildProcess | null = null;\n const signalHandler = (sig: NodeJS.Signals) => {\n if (signalReceived !== null) return;\n signalReceived = sig;\n controller.abort();\n };\n const exitHandler = () => {\n if (activeChild !== null) {\n try {\n activeChild.kill(\"SIGKILL\");\n } catch {\n // best-effort cleanup\n }\n }\n };\n const onSigInt = () => signalHandler(\"SIGINT\");\n const onSigTerm = () => signalHandler(\"SIGTERM\");\n process.on(\"SIGINT\", onSigInt);\n process.on(\"SIGTERM\", onSigTerm);\n process.on(\"exit\", exitHandler);\n ctx.onExitHookInstalled?.(exitHandler);\n\n // 10-11. runner.run() execute (capture: \"none\" inherits the parent stdio so\n // claude-code keeps a real TTY). Spawn-time errors finalize the\n // session as failed and propagate the error.\n let result: RunResult;\n try {\n try {\n result = await runner.run(command, args, {\n cwd: repoRoot,\n capture: \"none\",\n signal: controller.signal,\n onSpawn: (child) => {\n activeChild = child;\n },\n });\n } catch (spawnError: unknown) {\n await finalizeSessionAsFailed(paths, sessionDir, sessionId, appendEvent, {\n command,\n args,\n cwd: repoRoot,\n occurredAt: now().toISOString(),\n signalReceived,\n });\n throw spawnError;\n }\n } finally {\n process.off(\"SIGINT\", onSigInt);\n process.off(\"SIGTERM\", onSigTerm);\n process.off(\"exit\", exitHandler);\n activeChild = null;\n }\n\n const endedAt = now().toISOString();\n\n // 12. command_executed (parent received_signal vs child terminating signal).\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"command_executed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: endedAt,\n source: \"terminal-recording\",\n command,\n args,\n cwd: repoRoot,\n exit_code: result.exit_code,\n ...(result.signal !== null ? { signal: result.signal } : {}),\n ...(signalReceived !== null ? { received_signal: signalReceived } : {}),\n duration_ms: result.duration_ms,\n });\n\n // 13. Optional post-execute git_snapshot.\n let postSnapshot: GitSnapshot | null = null;\n if (options.snapshot !== false) {\n postSnapshot = await tryAppendGitSnapshot(sessionDir, sessionId, repoRoot, now, appendEvent);\n }\n\n // 14-15. file_changed events derived from getDiff(preHead, postHead). Only\n // committed changes appear here; dirty (staged/unstaged/untracked)\n // edits are surfaced via session.yaml.related_files instead.\n let diff: DiffResult | null = null;\n if (preSnapshot !== null && postSnapshot !== null) {\n diff = await tryAppendFileChangedEvents(\n sessionDir,\n sessionId,\n repoRoot,\n preSnapshot.head,\n postSnapshot.head,\n now().toISOString(),\n appendEvent,\n getDiffFn,\n );\n }\n\n // 16. Compute related_files = pre+post snapshot ∪ diff (sorted, deduped).\n // Then sanitize so /Users/<u>/projects/foo/... is stored relative to\n // the session's working_directory; system paths outside both bases\n // stay verbatim. Git output is usually repo-relative already, but the\n // sanitizer is idempotent and cheap so we run it unconditionally\n // against the very subset of paths that ever reach session.yaml.\n const rawRelated = computeRelatedFiles(preSnapshot, postSnapshot, diff);\n const relatedFiles = sanitizeRelatedFiles(rawRelated, {\n workingDirectory: repoRoot,\n homedir: homedir(),\n }).sanitized;\n\n const finalStatus = decideFinalStatus(result, signalReceived);\n\n // 17-18. status_changed: running -> final.\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_status_changed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: endedAt,\n source: claudeCodeAdapterMetadata.kind,\n from: \"running\",\n to: finalStatus,\n });\n\n // 19. session_ended.\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_ended\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: endedAt,\n source: claudeCodeAdapterMetadata.kind,\n ...(result.exit_code !== null ? { exit_code: result.exit_code } : {}),\n });\n\n // 20. Final session.yaml update (status / ended_at / invocation.exit_code /\n // related_files) plus the integrity head anchor, written from the on-disk\n // tail under the session lock so a foreign line appended just before\n // finalize is anchored and a later attach (now terminal) is rejected.\n await finalizeSessionYaml(paths, sessionId, (s) => {\n s.session.status = finalStatus;\n s.session.ended_at = endedAt;\n s.session.invocation.exit_code = result.exit_code;\n s.session.related_files = relatedFiles;\n });\n\n if (result.exit_code !== null) return result.exit_code;\n return signalToExitCode(signalReceived ?? result.signal);\n}\n\nfunction decideFinalStatus(\n result: { exit_code: number | null; signal: NodeJS.Signals | null },\n signalReceived: NodeJS.Signals | null,\n): \"completed\" | \"failed\" | \"interrupted\" {\n if (signalReceived === \"SIGINT\" || signalReceived === \"SIGTERM\") return \"interrupted\";\n if (result.signal === \"SIGINT\" || result.signal === \"SIGTERM\" || result.signal === \"SIGKILL\") {\n return \"interrupted\";\n }\n if (result.exit_code === 0) return \"completed\";\n return \"failed\";\n}\n\nconst SIGNUM_MAP: Record<string, number> = {\n SIGHUP: 1,\n SIGINT: 2,\n SIGQUIT: 3,\n SIGKILL: 9,\n SIGTERM: 15,\n};\n\nfunction signalToExitCode(sig: NodeJS.Signals | null): number {\n if (sig === null) return 1;\n const num = SIGNUM_MAP[sig] ?? 1;\n return 128 + num;\n}\n\nasync function tryAppendGitSnapshot(\n sessionDir: string,\n sessionId: string,\n repoRoot: string,\n now: () => Date,\n appendEvent: AppendEventFn,\n): Promise<GitSnapshot | null> {\n // Stage 1: capability acquisition. Capability-level failures (no git\n // repository, git binary missing, no commits) downgrade to a skip warning;\n // events.jsonl simply lacks this git_snapshot entry.\n let snapshot: GitSnapshot;\n try {\n snapshot = await getSnapshot(repoRoot);\n } catch (error: unknown) {\n console.warn(normalizeGitSnapshotSkipMessage(error));\n return null;\n }\n // Stage 2: events.jsonl append. Failures here would corrupt the events.jsonl\n // integrity contract; let them propagate so the run fails loudly rather\n // than producing a session that looks successful but is actually missing\n // events.\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"git_snapshot\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: now().toISOString(),\n source: \"git-capability\",\n ...snapshot,\n });\n return snapshot;\n}\n\nasync function tryAppendFileChangedEvents(\n sessionDir: string,\n sessionId: string,\n repoRoot: string,\n baseRef: string,\n headRef: string,\n occurredAt: string,\n appendEvent: AppendEventFn,\n getDiffFn: GetDiffFn,\n): Promise<DiffResult | null> {\n // Stage 1: capability acquisition (same skip-vs-fail split as\n // tryAppendGitSnapshot).\n let diff: DiffResult;\n try {\n diff = await getDiffFn(repoRoot, baseRef, headRef);\n } catch (error: unknown) {\n console.warn(normalizeFileChangedSkipMessage(error));\n return null;\n }\n // Stage 2: per-path appendEvent. Schema validation / disk failures here\n // are NOT a capability miss; let them propagate.\n for (const change of diff.changed_files) {\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"file_changed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: occurredAt,\n source: \"git-capability\",\n path: change.path,\n change_type: change.status,\n ...(change.old_path !== undefined ? { old_path: change.old_path } : {}),\n });\n }\n return diff;\n}\n\nfunction computeRelatedFiles(\n preSnapshot: GitSnapshot | null,\n postSnapshot: GitSnapshot | null,\n diff: DiffResult | null,\n): string[] {\n const set = new Set<string>();\n for (const snap of [preSnapshot, postSnapshot]) {\n if (snap === null) continue;\n for (const p of snap.staged) set.add(p);\n for (const p of snap.unstaged) set.add(p);\n for (const p of snap.untracked) set.add(p);\n }\n if (diff !== null) {\n for (const change of diff.changed_files) set.add(change.path);\n }\n return [...set].sort();\n}\n\nfunction normalizeGitSnapshotSkipMessage(error: unknown): string {\n if (!(error instanceof Error)) {\n return `git_snapshot skipped: ${String(error)}`;\n }\n const msg = error.message;\n if (msg === \"Not a git repository\") return \"git_snapshot skipped: not in a git repository\";\n if (msg === \"Git executable not found in PATH. Install git first.\") {\n return \"git_snapshot skipped: git executable not found\";\n }\n if (msg === \"No commits in repository\") return \"git_snapshot skipped: no commits in repository\";\n return `git_snapshot skipped: ${msg}`;\n}\n\nfunction normalizeFileChangedSkipMessage(error: unknown): string {\n if (!(error instanceof Error)) {\n return `file_changed skipped: ${String(error)}`;\n }\n const msg = error.message;\n if (msg === \"Not a git repository\") return \"file_changed skipped: not in a git repository\";\n if (msg === \"Git executable not found in PATH. Install git first.\") {\n return \"file_changed skipped: git executable not found\";\n }\n if (msg === \"Invalid ref\") return \"file_changed skipped: invalid git ref\";\n if (msg === \"Failed to compute git diff\")\n return \"file_changed skipped: failed to compute git diff\";\n return `file_changed skipped: ${msg}`;\n}\n\nfunction buildInitialSession(input: {\n id: PrefixedId<\"ses\">;\n command: string;\n args: string[];\n cwd: string;\n workspaceId: PrefixedId<\"ws\">;\n startedAt: string;\n}): Session {\n const cmdline = [input.command, ...input.args].join(\" \");\n return {\n schema_version: \"0.1.0\",\n session: {\n id: input.id,\n label: `basou run ${cmdline} (${input.startedAt})`,\n task_id: null,\n workspace_id: input.workspaceId,\n source: { ...claudeCodeAdapterMetadata },\n started_at: input.startedAt,\n status: \"initialized\",\n working_directory: sanitizeWorkingDirectory(input.cwd, { homedir: homedir() }),\n invocation: {\n command: input.command,\n args: [...input.args],\n exit_code: null,\n },\n related_files: [],\n events_log: \"events.jsonl\",\n },\n };\n}\n\nasync function mutateSessionYaml(\n filePath: string,\n mutator: (session: Session) => void,\n): Promise<void> {\n const raw = await readYamlFile(filePath);\n const parsed = SessionSchema.parse(raw);\n mutator(parsed);\n const validated = SessionSchema.parse(parsed);\n await overwriteYamlFile(filePath, validated);\n}\n\nasync function finalizeSessionAsFailed(\n paths: BasouPaths,\n sessionDir: string,\n sessionId: string,\n appendEvent: AppendEventFn,\n ctx: {\n command: string;\n args: string[];\n cwd: string;\n occurredAt: string;\n signalReceived: NodeJS.Signals | null;\n },\n): Promise<void> {\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"command_executed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: ctx.occurredAt,\n source: \"terminal-recording\",\n command: ctx.command,\n args: ctx.args,\n cwd: ctx.cwd,\n exit_code: null,\n signal: null,\n ...(ctx.signalReceived !== null ? { received_signal: ctx.signalReceived } : {}),\n duration_ms: 0,\n });\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_status_changed\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: ctx.occurredAt,\n source: claudeCodeAdapterMetadata.kind,\n from: \"running\",\n to: \"failed\",\n });\n await appendEvent(sessionDir, {\n schema_version: \"0.1.0\",\n type: \"session_ended\",\n id: prefixedUlid(\"evt\"),\n session_id: sessionId,\n occurred_at: ctx.occurredAt,\n source: claudeCodeAdapterMetadata.kind,\n });\n await finalizeSessionYaml(paths, sessionId, (s) => {\n s.session.status = \"failed\";\n s.session.ended_at = ctx.occurredAt;\n s.session.invocation.exit_code = null;\n });\n}\n\nasync function resolveRepositoryRootForRun(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\"Not a git repository. Run 'git init' first, then re-run 'basou run'.\", {\n cause: error,\n });\n }\n throw error;\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { basename, isAbsolute, join, relative } from \"node:path\";\nimport {\n acquireLock,\n appendEventToExistingSession,\n assertBasouRootSafe,\n basouPaths,\n type Event,\n enumerateSessionDirs,\n findErrorCode,\n type ImportSessionOptions,\n type ImportSessionResult,\n importSessionFromJson,\n loadSessionEntries,\n type RechainResult,\n readAllEvents,\n readManifest,\n readYamlFile,\n rechainSessionInPlace,\n resolveRepositoryRoot,\n resolveSessionId,\n resolveTaskId,\n type Session,\n SessionImportPayloadSchema,\n SessionSchema,\n type SessionStatus,\n SessionStatusSchema,\n sessionWorkStatsFromEvents,\n} from \"@basou/core\";\nimport { type Command, InvalidArgumentError } from \"commander\";\nimport {\n isVerbose,\n printReplayWarning,\n printSessionListSkip,\n renderCliError,\n} from \"../lib/error-render.js\";\nimport { formatDurationMs } from \"../lib/format-duration.js\";\n\nconst SES_PREFIX = \"ses_\";\nconst TASK_PREFIX = \"task_\";\nconst SHORT_ID_BASE_LEN = 6;\nconst SHORT_ID_MAX_LEN = 26; // ULID body length\n\nconst STATUS_VALUES = SessionStatusSchema.options;\n\nexport type SessionListOptions = {\n json?: boolean;\n status?: SessionStatus;\n verbose?: boolean;\n};\n\nexport type SessionShowOptions = {\n json?: boolean;\n events?: boolean;\n last?: number;\n fullPath?: boolean;\n verbose?: boolean;\n};\n\nexport type SessionContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n /** Defaults to `() => new Date()`. Injectable so the `session show` work\n * span is deterministic in tests and for a running session. */\n nowProvider?: () => Date;\n};\n\nexport type SessionRechainOptions = {\n session?: string;\n all?: boolean;\n dryRun?: boolean;\n json?: boolean;\n verbose?: boolean;\n};\n\n/** One row of `basou session rechain` output. */\nexport type RechainRow = {\n session_id: string;\n status: \"rechained\" | \"skipped\" | \"error\";\n /** Skip reason, present when status is \"skipped\". */\n reason?: Extract<RechainResult, { status: \"skipped\" }>[\"reason\"];\n /** Chained event count, present when status is \"rechained\". */\n event_count?: number;\n /** Fixed error message, present when status is \"error\". */\n message?: string;\n};\n\ntype SessionListRecord = {\n sessionId: string;\n session: Session;\n suspect: boolean;\n suspectReason: string | null;\n};\n\n/**\n * Wire `basou session list` and `basou session show <id>` onto `program`.\n *\n * The `session` group is registered up front so future subcommands\n * (`note`, `import`) added in later steps slot under the same group without\n * changing the externally visible CLI surface.\n */\nexport function registerSessionCommand(program: Command): void {\n const session = program\n .command(\"session\")\n .description(\"Inspect Basou sessions stored under .basou/sessions/\");\n\n session\n .command(\"list\")\n .description(\"List sessions in the current workspace (newest first)\")\n .option(\"--json\", \"Output the list as a JSON array\")\n .option(\n \"--status <state>\",\n `Filter by session status (one of: ${STATUS_VALUES.join(\", \")})`,\n parseSessionStatus,\n )\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: SessionListOptions) => {\n await runSessionList(options);\n });\n\n session\n .command(\"show <id>\")\n .description(\"Show a session's metadata and recent events\")\n .option(\"--json\", \"Output the session and events as JSON\")\n .option(\"--events\", \"List all events instead of just the trailing few\")\n .option(\"--last <n>\", \"Number of trailing events to display (default: 5)\", parsePositiveInt)\n .option(\n \"--full-path\",\n \"Show working_directory as an absolute path instead of repository-relative\",\n )\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (id: string, options: SessionShowOptions) => {\n await runSessionShow(id, options);\n });\n\n session\n .command(\"import\")\n .description(\"Import a session from a JSON file\")\n .requiredOption(\"--format <format>\", \"Input format (currently only 'json')\", parseImportFormat)\n .requiredOption(\"--from <path>\", \"Path to the input JSON file\")\n .option(\"--label <text>\", \"Override the session label\", parseLabelOverride)\n .option(\"--task <task_id>\", \"Override the session task_id\", parseTaskIdOverride)\n .option(\"--dry-run\", \"Validate input only; do not write to disk\")\n .option(\"--json\", \"Output the result as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: SessionImportOptions) => {\n await runSessionImport(options);\n });\n\n session\n .command(\"note <session_id>\")\n .description(\"Append a note_added event to an existing session\")\n .option(\"--body <text>\", \"Note body (inline)\", parseNoteBodyOption)\n .option(\"--from-file <path>\", \"Read note body from a file\")\n .option(\"--json\", \"Output the result as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (sessionIdInput: string, options: SessionNoteOptions) => {\n await runSessionNote(sessionIdInput, options);\n });\n\n session\n .command(\"rechain\")\n .description(\n \"Add the tamper-evidence hash chain, in place, to imported sessions created before chaining existed\",\n )\n .option(\"--session <id>\", \"Rechain a single session (unique id prefix accepted)\")\n .option(\"--all\", \"Rechain every session in the workspace\")\n .option(\"--dry-run\", \"Compute the outcomes only; do not write\")\n .option(\"--json\", \"Output the outcomes as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: SessionRechainOptions) => {\n await runSessionRechain(options);\n });\n}\n\n/**\n * Programmatic entry for `basou session list` that owns process exit state.\n * Tests targeting only the success path or the thrown error should prefer\n * {@link doRunSessionList}.\n */\nexport async function runSessionList(\n options: SessionListOptions,\n ctx: SessionContext = {},\n): Promise<void> {\n try {\n await doRunSessionList(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * Pure runner for `session list`. Throws on any failure with a pathless\n * message; native errors are attached as `cause` for verbose surfacing.\n */\nexport async function doRunSessionList(\n options: SessionListOptions,\n ctx: SessionContext,\n): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForSession(cwd, \"list\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n // Orchestration is delegated to core's `loadSessionEntries`. To preserve\n // the existing stderr surface (\"Skipped <sid>: <reason>\" and\n // \"Warning: skipped suspect check for <sid>: events.jsonl unreadable\"),\n // map onSkip / onWarning on the CLI side.\n const now = new Date();\n const records: SessionListRecord[] = (\n await loadSessionEntries(paths, {\n now,\n onWarning: (w, sid) => printReplayWarning(w, sid),\n onSkip: (sid, reason) => printSessionListSkip(sid, reason),\n })\n ).map((entry) => ({\n sessionId: entry.sessionId,\n session: entry.session,\n suspect: entry.suspect,\n suspectReason: entry.suspectReason,\n }));\n\n if (records.length === 0) {\n printNoSessions(options);\n return;\n }\n\n // started_at desc using Date.parse to normalize across timezone offsets;\n // a lexicographic compare would swap two timestamps that point at the same\n // instant when their offsets differ.\n records.sort(\n (a, b) => Date.parse(b.session.session.started_at) - Date.parse(a.session.session.started_at),\n );\n\n const filtered =\n options.status !== undefined\n ? records.filter((r) => r.session.session.status === options.status)\n : records;\n\n if (filtered.length === 0) {\n printNoSessions(options);\n return;\n }\n\n if (options.json === true) {\n console.log(\n JSON.stringify(\n filtered.map((r) => ({\n ...r.session.session,\n suspect: r.suspect,\n suspect_reason: r.suspectReason,\n })),\n null,\n 2,\n ),\n );\n } else {\n printSessionListText(filtered);\n }\n}\n\n/**\n * Programmatic entry for `basou session show <id>`. See {@link runSessionList}\n * for the split pattern rationale.\n */\nexport async function runSessionShow(\n idInput: string,\n options: SessionShowOptions,\n ctx: SessionContext = {},\n): Promise<void> {\n try {\n await doRunSessionShow(idInput, options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunSessionShow(\n idInput: string,\n options: SessionShowOptions,\n ctx: SessionContext,\n): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForSession(cwd, \"show\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const sessionId = await resolveSessionId(paths, idInput);\n\n const sessionDir = join(paths.sessions, sessionId);\n const sessionYamlPath = join(sessionDir, \"session.yaml\");\n let session: Session;\n try {\n const raw = await readYamlFile(sessionYamlPath);\n session = SessionSchema.parse(raw);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(`Session not found: ${idInput}`);\n }\n throw new Error(\"Failed to read session\", { cause: error });\n }\n\n const events = await readAllEvents(sessionDir, {\n onWarning: (w) => printReplayWarning(w, sessionId),\n });\n\n if (options.json === true) {\n console.log(JSON.stringify({ session: session.session, events }, null, 2));\n return;\n }\n\n const now = ctx.nowProvider?.() ?? new Date();\n printSessionShowText(session, events, options, repositoryRoot, now);\n}\n\nfunction suspectLabel(reason: string | null): string {\n if (reason === \"events_say_ended_but_yaml_running\") return \" ⚠ ended (yaml stale)\";\n if (reason === \"running_no_end_event\") return \" ⚠ no end event\";\n return \"\";\n}\n\nfunction printSessionListText(records: SessionListRecord[]): void {\n // Grow the SHORT_ID column to the first length where every prefix is\n // unique. Without this an ambiguous prefix would copy-paste from the list\n // and fail `resolveSessionId` with \"Ambiguous session id\".\n const shortLen = computeUniquePrefixLen(records.map((r) => r.sessionId));\n const rows = records.map((r) => {\n const sid = sliceShort(r.sessionId, shortLen);\n const status = `${r.session.session.status}${suspectLabel(r.suspectReason)}`;\n const source = r.session.session.source.kind;\n const startedAt = r.session.session.started_at;\n const fileCount = r.session.session.related_files.length;\n const filesSuffix = fileCount > 0 ? ` (${fileCount} files)` : \"\";\n const label = (r.session.session.label ?? \"\") + filesSuffix;\n return { sid, status, source, startedAt, label };\n });\n\n const widths = {\n sid: maxLen(\n rows.map((r) => r.sid),\n \"SHORT_ID\".length,\n ),\n status: maxLen(\n rows.map((r) => r.status),\n \"STATUS\".length,\n ),\n source: maxLen(\n rows.map((r) => r.source),\n \"SOURCE\".length,\n ),\n startedAt: maxLen(\n rows.map((r) => r.startedAt),\n \"STARTED_AT\".length,\n ),\n };\n\n console.log(\n `${pad(\"SHORT_ID\", widths.sid)} ${pad(\"STATUS\", widths.status)} ${pad(\"SOURCE\", widths.source)} ${pad(\"STARTED_AT\", widths.startedAt)} LABEL`,\n );\n for (const row of rows) {\n console.log(\n `${pad(row.sid, widths.sid)} ${pad(row.status, widths.status)} ${pad(row.source, widths.source)} ${pad(row.startedAt, widths.startedAt)} ${row.label}`,\n );\n }\n}\n\nfunction printSessionShowText(\n session: Session,\n events: Event[],\n options: SessionShowOptions,\n repositoryRoot: string,\n now: Date,\n): void {\n const s = session.session;\n console.log(`Session: ${s.id} (status: ${s.status})`);\n console.log(`Source: ${s.source.kind} (v${s.source.version})`);\n console.log(`Workspace: ${s.workspace_id}`);\n console.log(`Started at: ${s.started_at}`);\n if (s.ended_at !== undefined) {\n console.log(`Ended at: ${s.ended_at}`);\n }\n console.log(`Working dir: ${formatWorkingDir(s.working_directory, repositoryRoot, options)}`);\n const invocationArgs = s.invocation.args.length > 0 ? ` ${s.invocation.args.join(\" \")}` : \"\";\n console.log(`Invocation: ${s.invocation.command}${invocationArgs}`);\n if (s.invocation.exit_code !== null) {\n console.log(`Exit code: ${s.invocation.exit_code}`);\n }\n if (s.label !== undefined) {\n console.log(`Label: ${s.label}`);\n }\n console.log(`Related files: ${formatRelatedFiles(s.related_files)}`);\n\n console.log(\"\");\n console.log(`Events: ${events.length} total`);\n const counts = countByType(events);\n for (const [type, n] of counts) {\n console.log(` ${pad(`${type}:`, 24)} ${n}`);\n }\n\n console.log(\"\");\n console.log(`Work: ${formatSessionWork(session, events, now)}`);\n\n if (events.length === 0) return;\n\n const last = options.last ?? 5;\n const showAll = options.events === true && options.last === undefined;\n const slice = showAll ? events : events.slice(-last);\n const heading = showAll ? \"All events:\" : `Last ${slice.length} events:`;\n console.log(\"\");\n console.log(heading);\n for (const ev of slice) {\n console.log(` ${formatEventLine(ev)}`);\n }\n}\n\n/**\n * One-line work summary for `session show`: output volume + action counts +\n * time proxies, reusing the same per-session computation as `basou stats`.\n * `command n/a (import)` flags sources whose shell time is unrecorded.\n */\nfunction formatSessionWork(session: Session, events: Event[], now: Date): string {\n const w = sessionWorkStatsFromEvents(session.session.id, session.session, events, now);\n const parts: string[] = [];\n if (w.tokens.output > 0) parts.push(`${w.tokens.output.toLocaleString(\"en-US\")} output tokens`);\n parts.push(`${w.commandCount} cmd / ${w.fileChangedCount} files / ${w.decisionCount} dec`);\n const activeBasis = w.activeTimeBasis === \"engaged-turns\" ? \"turns\" : \"events\";\n parts.push(`active ${formatDurationMs(w.activeTimeMs)} (${activeBasis})`);\n if (w.availability.machineActive) {\n parts.push(`machine ${formatDurationMs(w.machineActiveTimeMs)}`);\n }\n parts.push(`span ${formatDurationMs(w.sessionSpanMs)}${w.open ? \" (open)\" : \"\"}`);\n parts.push(\n w.availability.commandTime\n ? `command ${formatDurationMs(w.commandTimeMs)}`\n : \"command n/a (import)\",\n );\n return parts.join(\", \");\n}\n\nfunction formatWorkingDir(\n workingDir: string,\n repositoryRoot: string,\n options: SessionShowOptions,\n): string {\n if (options.fullPath === true) return workingDir;\n\n // v0.3 sanitized sessions write `working_directory` as a relative form\n // (`~/projects/foo`, `src/sub`, `.`, etc.) rather than the absolute\n // path the older write paths used. path.relative against a relative\n // input would silently resolve it against process.cwd and produce\n // nonsense like `<cwd>/~/projects/foo`, so the relative form must be\n // surfaced verbatim. The one literal we collapse is `.`, which means\n // \"the session ran at the repo root\" — same semantic as an absolute\n // workingDir equal to repositoryRoot.\n if (!isAbsolute(workingDir)) {\n if (workingDir === \".\") return \"<repository_root>\";\n return workingDir;\n }\n\n if (workingDir === repositoryRoot) return \"<repository_root>\";\n const rel = relative(repositoryRoot, workingDir);\n if (rel.length === 0 || rel === \".\") return \"<repository_root>\";\n // Outside-repo working directories surface as a `../...` relative path\n // rather than the absolute path so the default-display contract holds\n // even for sessions recorded from a sibling checkout. `--full-path` is\n // the explicit opt-in for the absolute form.\n if (rel.startsWith(\"..\")) return rel;\n return `./${rel}`;\n}\n\nfunction formatRelatedFiles(files: readonly string[]): string {\n if (files.length === 0) return \"0 paths\";\n const head = files.slice(0, 3).join(\", \");\n const remaining = files.length - 3;\n if (remaining <= 0) return `${files.length} paths (${head})`;\n return `${files.length} paths (${head}, ... +${remaining} more)`;\n}\n\nfunction countByType(events: readonly Event[]): Array<[string, number]> {\n const map = new Map<string, number>();\n for (const ev of events) {\n map.set(ev.type, (map.get(ev.type) ?? 0) + 1);\n }\n return [...map.entries()];\n}\n\nfunction formatEventLine(ev: Event): string {\n return `${ev.occurred_at} [${ev.source}] ${ev.type} ${eventVariantSummary(ev)}`;\n}\n\nfunction eventVariantSummary(ev: Event): string {\n switch (ev.type) {\n case \"command_executed\": {\n const argsPart = ev.args.length > 0 ? ` ${ev.args.join(\" \")}` : \"\";\n const exitPart = ev.exit_code === null ? \"exit=signal\" : `exit=${ev.exit_code}`;\n return `${ev.command}${argsPart} (${exitPart}, ${ev.duration_ms}ms)`;\n }\n case \"git_snapshot\":\n return `branch=${ev.branch} dirty=${ev.dirty}`;\n case \"file_changed\":\n return `${ev.change_type} ${ev.path}`;\n case \"session_status_changed\":\n return `${ev.from} -> ${ev.to}`;\n case \"session_started\":\n return \"(start)\";\n case \"session_ended\":\n return ev.exit_code !== undefined ? `exit_code=${ev.exit_code}` : \"(end)\";\n case \"approval_requested\":\n return `${ev.action.kind} risk=${ev.risk_level}`;\n case \"approval_approved\":\n return ev.resolver !== undefined ? `by ${ev.resolver}` : \"(approved)\";\n case \"approval_rejected\":\n return ev.resolver !== undefined ? `by ${ev.resolver}: ${ev.reason}` : ev.reason;\n case \"approval_expired\":\n return `approval=${ev.approval_id}`;\n case \"decision_recorded\":\n return ev.title;\n case \"task_created\":\n return ev.title;\n case \"task_status_changed\":\n return `${ev.from} -> ${ev.to}`;\n case \"task_reconciled\": {\n const createdPart =\n ev.removed_created_in_session !== null ? \"1 created_in_session\" : \"0 created_in_session\";\n return `task ${shortTaskId(ev.task_id)}: cleared ${ev.removed_linked_sessions.length} linked + ${createdPart}`;\n }\n case \"task_linkage_refreshed\": {\n const added = ev.added_linked_sessions.length;\n const removed = ev.removed_linked_sessions.length;\n const final = ev.final_count !== undefined ? ` final=${ev.final_count}` : \"\";\n return `task ${shortTaskId(ev.task_id)}: +${added} / -${removed} linked${final}`;\n }\n case \"task_deleted\":\n return `task ${shortTaskId(ev.task_id)}: ${ev.title} (deleted)`;\n case \"task_archived\":\n return `task ${shortTaskId(ev.task_id)}: ${ev.title} (archived)`;\n case \"note_added\":\n return ev.body.length > 80 ? `${ev.body.slice(0, 77)}...` : ev.body;\n case \"adapter_output\":\n return `${ev.stream} \"${ev.summary}\" raw_ref=${ev.raw_ref}`;\n }\n}\n\nfunction shortId(id: string): string {\n return sliceShort(id, SHORT_ID_BASE_LEN);\n}\n\nfunction shortTaskId(id: string): string {\n if (id.startsWith(TASK_PREFIX)) {\n return id.slice(TASK_PREFIX.length, TASK_PREFIX.length + SHORT_ID_BASE_LEN);\n }\n return id.slice(0, SHORT_ID_BASE_LEN);\n}\n\nfunction sliceShort(id: string, len: number): string {\n if (id.startsWith(SES_PREFIX)) {\n return id.slice(SES_PREFIX.length, SES_PREFIX.length + len);\n }\n return id.slice(0, len);\n}\n\n/**\n * Find the smallest length where every short_id derived from `sessionIds`\n * is unique. Starts at {@link SHORT_ID_BASE_LEN} and grows by 2 chars at a\n * time (mirroring git's automatic abbreviation behaviour). Caps at the full\n * ULID body length so a pathological collision still terminates.\n */\nfunction computeUniquePrefixLen(sessionIds: readonly string[]): number {\n if (sessionIds.length <= 1) return SHORT_ID_BASE_LEN;\n for (let len = SHORT_ID_BASE_LEN; len <= SHORT_ID_MAX_LEN; len += 2) {\n const seen = new Set<string>();\n let collided = false;\n for (const sid of sessionIds) {\n const key = sliceShort(sid, len);\n if (seen.has(key)) {\n collided = true;\n break;\n }\n seen.add(key);\n }\n if (!collided) return len;\n }\n return SHORT_ID_MAX_LEN;\n}\n\nfunction pad(value: string, width: number): string {\n return value.length >= width ? value : value + \" \".repeat(width - value.length);\n}\n\nfunction maxLen(values: readonly string[], floor: number): number {\n let max = floor;\n for (const v of values) if (v.length > max) max = v.length;\n return max;\n}\n\nasync function resolveRepositoryRootForSession(\n cwd: string,\n subcmd: \"list\" | \"show\" | \"import\" | \"note\" | \"rechain\",\n): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\n `Not a git repository. Run 'git init' first, then re-run 'basou session ${subcmd}'.`,\n { cause: error },\n );\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n\nfunction parsePositiveInt(raw: string): number {\n const n = Number.parseInt(raw, 10);\n if (!Number.isInteger(n) || n < 1 || raw.trim() !== String(n)) {\n throw new Error(`Invalid number: ${raw}`);\n }\n return n;\n}\n\nfunction parseSessionStatus(raw: string): SessionStatus {\n const result = SessionStatusSchema.safeParse(raw);\n if (!result.success) {\n throw new Error(`Invalid session status: ${raw}. Valid values: ${STATUS_VALUES.join(\", \")}`);\n }\n return result.data;\n}\n\nfunction printNoSessions(options: SessionListOptions): void {\n if (options.json === true) {\n console.log(\"[]\");\n } else {\n console.log(\"No sessions found.\");\n }\n}\n\n// ----------------------------------------------------------------------------\n// session import\n// ----------------------------------------------------------------------------\n\nexport type SessionImportOptions = {\n format: \"json\";\n from: string;\n label?: string;\n task?: string;\n dryRun?: boolean;\n json?: boolean;\n verbose?: boolean;\n};\n\n/**\n * Programmatic entry for `basou session import`. Mirrors the wrapper /\n * pure-runner split used by list / show so tests can target either layer.\n */\nexport async function runSessionImport(\n options: SessionImportOptions,\n ctx: SessionContext = {},\n): Promise<void> {\n try {\n await doRunSessionImport(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunSessionImport(\n options: SessionImportOptions,\n ctx: SessionContext,\n): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForSession(cwd, \"import\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const manifest = await readManifest(paths);\n\n const rawBody = await readInputFile(options.from);\n const json = parseJsonStrict(rawBody);\n\n const parsed = SessionImportPayloadSchema.safeParse(json);\n if (!parsed.success) {\n throw new Error(\"Invalid import payload\", { cause: parsed.error });\n }\n\n if (parsed.data.schema_version !== \"0.1.0\") {\n throw new Error(`Unsupported import schema_version: ${parsed.data.schema_version}`);\n }\n\n const importOptions: ImportSessionOptions = { dryRun: options.dryRun === true };\n if (options.label !== undefined) importOptions.labelOverride = options.label;\n if (options.task !== undefined) {\n importOptions.taskIdOverride = await resolveTaskId(paths, options.task);\n }\n\n const result = await importSessionFromJson(paths, manifest, parsed.data, importOptions);\n\n // Path sanitize visibility: the importer rewrites absolute / homedir\n // prefixes inside related_files[] and working_directory so the operator-\n // private layout does not leak into local state. Surface a single-line\n // warning when anything was actually rewritten — silence on zero so the\n // happy path stays quiet. The warning fires for dry-run too so the\n // operator can preview the rewrite before committing.\n const sanitizeReport = result.pathSanitizeReport;\n if (sanitizeReport.relatedFiles > 0 || sanitizeReport.workingDirectoryRewritten) {\n const wdCount = sanitizeReport.workingDirectoryRewritten ? 1 : 0;\n console.error(\n `Imported session: ${sanitizeReport.relatedFiles + wdCount} path(s) sanitized (related_files: ${sanitizeReport.relatedFiles}, working_directory: ${wdCount})`,\n );\n }\n\n printSessionImportResult(options, result);\n}\n\nasync function readInputFile(path: string): Promise<string> {\n try {\n return await readFile(path, \"utf8\");\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Import source not found\", { cause: error });\n }\n if (findErrorCode(error, \"EISDIR\")) {\n throw new Error(\"Import source is not a file\", { cause: error });\n }\n throw new Error(\"Failed to read import source\", { cause: error });\n }\n}\n\nfunction parseJsonStrict(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch (error: unknown) {\n throw new Error(\"Failed to parse import JSON\", { cause: error });\n }\n}\n\nfunction parseImportFormat(raw: string): \"json\" {\n if (raw !== \"json\") {\n throw new InvalidArgumentError(`Unsupported format: ${raw}. Valid values: json`);\n }\n return \"json\";\n}\n\nfunction parseLabelOverride(raw: string): string {\n if (raw.length === 0) {\n throw new InvalidArgumentError(\"Label must not be empty\");\n }\n return raw;\n}\n\nfunction parseTaskIdOverride(raw: string): string {\n if (raw.length === 0) {\n throw new InvalidArgumentError(\"Task id is empty\");\n }\n return raw;\n}\n\nfunction printSessionImportResult(\n options: SessionImportOptions,\n result: ImportSessionResult,\n): void {\n const isDry = options.dryRun === true;\n const sid = shortId(result.sessionId);\n if (options.json === true) {\n console.log(\n JSON.stringify({\n session_id: result.sessionId,\n event_count: result.eventCount,\n dry_run: isDry,\n source: { kind: result.finalSourceKind, version: \"0.1.0\" },\n status: result.finalStatus,\n }),\n );\n return;\n }\n\n if (isDry) {\n console.log(\n `Dry run: would import ${result.eventCount} events into ${sid} (illustrative ID; not reserved, no files written)`,\n );\n return;\n }\n\n console.log(\n `Imported session ${sid} (${result.eventCount} events) from ${basename(options.from)}`,\n );\n}\n\n// ----------------------------------------------------------------------------\n// session note\n// ----------------------------------------------------------------------------\n\nconst NOTE_BODY_PREVIEW_LIMIT = 80;\nconst NOTE_BODY_PREVIEW_HEAD = 77;\n\nexport type SessionNoteOptions = {\n body?: string;\n fromFile?: string;\n json?: boolean;\n verbose?: boolean;\n};\n\n/**\n * Programmatic entry for `basou session note <session_id>`. Appends a single\n * `note_added` event to an existing attachable session. `session.yaml` is\n * deliberately NOT modified.\n */\nexport async function runSessionNote(\n sessionIdInput: string,\n options: SessionNoteOptions,\n ctx: SessionContext = {},\n): Promise<void> {\n try {\n await doRunSessionNote(sessionIdInput, options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunSessionNote(\n sessionIdInput: string,\n options: SessionNoteOptions,\n ctx: SessionContext,\n): Promise<void> {\n const hasBody = options.body !== undefined;\n const hasFromFile = options.fromFile !== undefined;\n if (!hasBody && !hasFromFile) {\n throw new Error(\"Provide --body or --from-file\");\n }\n if (hasBody && hasFromFile) {\n throw new Error(\"--body and --from-file are mutually exclusive\");\n }\n // The stdin pipe path is not supported in v0.1. Surface a dedicated\n // pathless error before any disk I/O so the failure mode is obvious.\n if (hasFromFile && options.fromFile === \"-\") {\n throw new Error(\"--from-file - (stdin) is not supported in v0.1\");\n }\n\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForSession(cwd, \"note\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const sessionId = await resolveSessionId(paths, sessionIdInput);\n\n const body = hasBody ? (options.body as string) : await readNoteFile(options.fromFile as string);\n if (body.length === 0) {\n throw new Error(\"Note body is empty\");\n }\n\n const occurredAt = new Date().toISOString();\n const sesId = sessionId as `ses_${string}`;\n\n // Per-session lock guards the events.jsonl append + status read window\n // against a concurrent writer (decision record / task attach / another\n // session note on the same id). The lock is the caller's responsibility:\n // appendEventToExistingSession holds no lock so we can compose larger\n // critical sections (e.g. attach-flavoured task commands) under the same\n // lock without re-entrant deadlock.\n const sessionLock = await acquireLock(paths, \"session\", sesId);\n let result: Awaited<ReturnType<typeof appendEventToExistingSession>>;\n try {\n result = await appendEventToExistingSession({\n paths,\n sessionId: sesId,\n eventBuilder: (eventId) =>\n ({\n schema_version: \"0.1.0\",\n id: eventId,\n session_id: sesId,\n occurred_at: occurredAt,\n source: \"local-cli\",\n type: \"note_added\",\n body,\n }) as Event,\n });\n } finally {\n await sessionLock.release();\n }\n\n printSessionNoteResult(options, sessionId, result.eventId, result.sessionStatus, body);\n}\n\nasync function readNoteFile(path: string): Promise<string> {\n try {\n return await readFile(path, \"utf8\");\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Note source not found\", { cause: error });\n }\n if (findErrorCode(error, \"EISDIR\")) {\n throw new Error(\"Note source is not a file\", { cause: error });\n }\n throw new Error(\"Failed to read note source\", { cause: error });\n }\n}\n\nfunction parseNoteBodyOption(raw: string): string {\n if (raw.length === 0) {\n throw new InvalidArgumentError(\"--body must not be empty\");\n }\n return raw;\n}\n\nfunction printSessionNoteResult(\n options: SessionNoteOptions,\n sessionId: string,\n eventId: string,\n sessionStatus: SessionStatus,\n body: string,\n): void {\n const sid = shortId(sessionId);\n if (options.json === true) {\n console.log(\n JSON.stringify({\n event_id: eventId,\n session_id: sessionId,\n session_status: sessionStatus,\n body_length: body.length,\n }),\n );\n return;\n }\n const preview =\n body.length > NOTE_BODY_PREVIEW_LIMIT ? `${body.slice(0, NOTE_BODY_PREVIEW_HEAD)}...` : body;\n console.log(`Added note to session ${sid} (${sessionStatus}): ${preview}`);\n}\n\n/**\n * Programmatic entry for `basou session rechain` that owns process exit\n * state. Tests should prefer {@link doRunSessionRechain} for the success\n * path.\n */\nexport async function runSessionRechain(\n options: SessionRechainOptions,\n ctx: SessionContext = {},\n): Promise<void> {\n try {\n await doRunSessionRechain(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * Runner for `session rechain`. A WRITE command, so an explicit selector is\n * required (`--session <id>` or `--all`). Per-session outcomes are collected\n * into rows; an I/O failure on one session becomes an `error` row and the\n * sweep CONTINUES, so one unreadable directory cannot hide the rest of the\n * report. Exit is non-zero when any session was found `tampered` or errored\n * operationally; plain skips and successes exit 0.\n */\nexport async function doRunSessionRechain(\n options: SessionRechainOptions,\n ctx: SessionContext,\n): Promise<void> {\n if (options.session !== undefined && options.all === true) {\n throw new Error(\"Specify either --session <id> or --all, not both\");\n }\n if (options.session === undefined && options.all !== true) {\n throw new Error(\"Specify --session <id> or --all\");\n }\n\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForSession(cwd, \"rechain\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const sessionIds =\n options.session !== undefined\n ? [await resolveSessionId(paths, options.session)]\n : await enumerateSessionDirs(paths);\n\n const dryRun = options.dryRun === true;\n const rows: RechainRow[] = [];\n for (const sessionId of sessionIds) {\n let outcome: RechainResult;\n try {\n outcome = await rechainSessionInPlace(paths, sessionId, { dryRun });\n } catch (error: unknown) {\n rows.push({\n session_id: sessionId,\n status: \"error\",\n message: error instanceof Error ? error.message : \"Unknown error\",\n });\n continue;\n }\n if (outcome.status === \"rechained\") {\n rows.push({ session_id: sessionId, status: \"rechained\", event_count: outcome.eventCount });\n } else {\n rows.push({ session_id: sessionId, status: \"skipped\", reason: outcome.reason });\n }\n }\n\n const tamperedCount = rows.filter((r) => r.reason === \"tampered\").length;\n const errorCount = rows.filter((r) => r.status === \"error\").length;\n\n if (options.json === true) {\n console.log(JSON.stringify(rows, null, 2));\n } else {\n for (const row of rows) {\n console.log(`${row.session_id} ${renderRechainRow(row, dryRun)}`);\n }\n const rechained = rows.filter((r) => r.status === \"rechained\").length;\n const skipped = rows.filter((r) => r.status === \"skipped\").length;\n console.log(\n `Sessions: ${rows.length} total — ${rechained} ${dryRun ? \"would be rechained\" : \"rechained\"}, ` +\n `${skipped} skipped, ${errorCount} errors`,\n );\n }\n\n // A tampered session or an operational failure must be visible in the\n // exit status; ordinary skips (already chained / live / empty) are not\n // failures.\n if (tamperedCount > 0 || errorCount > 0) {\n process.exitCode = 1;\n }\n}\n\nfunction renderRechainRow(row: RechainRow, dryRun: boolean): string {\n switch (row.status) {\n case \"rechained\":\n return `${dryRun ? \"would rechain\" : \"rechained\"} (${row.event_count} events)`;\n case \"skipped\":\n return row.reason === \"tampered\"\n ? \"skipped (TAMPERED — inspect with 'basou verify')\"\n : `skipped (${row.reason})`;\n case \"error\":\n return `error (${row.message})`;\n }\n}\n","/**\n * Coarse human duration from milliseconds: \"3h 05m\" / \"12m 30s\" / \"8s\".\n * Shared by the work-stats surfaces (`basou stats`, `basou session show`) so\n * they format identically.\n */\nexport function formatDurationMs(ms: number): string {\n const totalSeconds = Math.round(ms / 1000);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n if (hours > 0) return `${hours}h ${String(minutes).padStart(2, \"0\")}m`;\n if (minutes > 0) return `${minutes}m ${String(seconds).padStart(2, \"0\")}s`;\n return `${seconds}s`;\n}\n","import {\n assertBasouRootSafe,\n basouPaths,\n computeWorkStats,\n findErrorCode,\n resolveRepositoryRoot,\n type SourceWorkStats,\n type WorkStatsResult,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport {\n isVerbose,\n printReplayWarning,\n printSessionSkip,\n renderCliError,\n} from \"../lib/error-render.js\";\nimport { formatDurationMs } from \"../lib/format-duration.js\";\n\nexport type StatsOptions = {\n json?: boolean;\n bySource?: boolean;\n byDay?: boolean;\n verbose?: boolean;\n};\n\nexport type StatsContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n /** Defaults to `() => new Date()`. Injectable for tests. */\n nowProvider?: () => Date;\n};\n\n/**\n * Register `basou stats`: an honest \"how much did the AI work\" report. It\n * leads with output VOLUME (tokens + action counts), which is the most direct\n * signal, and reports TIME measures as labeled proxies.\n */\nexport function registerStatsCommand(program: Command): void {\n program\n .command(\"stats\")\n .description(\"Report how much the AI worked (output volume + time proxies) across sessions\")\n .option(\"--by-source\", \"Break the totals down by session source kind\")\n .option(\"--by-day\", \"Break billable time and volume down by calendar day\")\n .option(\"--json\", \"Output the full stats as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: StatsOptions) => {\n await runStats(options);\n });\n}\n\n/** Programmatic entry that owns `process.exitCode`. Tests prefer {@link doRunStats}. */\nexport async function runStats(options: StatsOptions, ctx: StatsContext = {}): Promise<void> {\n try {\n await doRunStats(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/** Pure runner: resolve the workspace, aggregate, and print (text or JSON). */\nexport async function doRunStats(options: StatsOptions, ctx: StatsContext): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForStats(cwd);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const now = ctx.nowProvider?.() ?? new Date();\n const result = await computeWorkStats({\n paths,\n now,\n onWarning: (w, sid) => printReplayWarning(w, sid),\n onSessionSkip: (sid, reason) => printSessionSkip(sid, reason),\n });\n\n if (options.json === true) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n printStatsText(result, options.bySource === true, options.byDay === true);\n}\n\nfunction printStatsText(result: WorkStatsResult, bySource: boolean, byDay: boolean): void {\n const t = result.totals;\n const statusPart =\n result.byStatus.length > 0\n ? ` (${result.byStatus.map((s) => `${s.status} ${s.count}`).join(\", \")})`\n : \"\";\n console.log(`Sessions: ${t.sessionCount}${statusPart}`);\n\n console.log(\"\");\n console.log(\"Volume (what the AI produced):\");\n const tokenSessions = result.sessions.filter((s) => s.availability.tokens).length;\n const tokenCaveat =\n t.tokensAvailable && tokenSessions < t.sessionCount\n ? ` (token data on ${tokenSessions} of ${t.sessionCount} sessions)`\n : t.tokensAvailable\n ? \"\"\n : \" (no token data captured; re-import to backfill)\";\n console.log(` Output tokens: ${formatInt(t.tokens.output)}${tokenCaveat}`);\n if (t.tokens.reasoning > 0) {\n console.log(` Reasoning tokens: ${formatInt(t.tokens.reasoning)} (Codex)`);\n }\n console.log(\n ` Actions: ${t.commandCount} commands, ${t.fileChangedCount} files, ${t.decisionCount} decisions`,\n );\n\n console.log(\"\");\n console.log(\"Time (proxies for human harness labor; active = billing primary):\");\n const turnSessions = result.sessions.filter((s) => s.activeTimeBasis === \"engaged-turns\").length;\n const basisCaveat =\n turnSessions === t.sessionCount\n ? \"engaged turns\"\n : turnSessions === 0\n ? \"event stream; re-import to capture conversation\"\n : `engaged turns on ${turnSessions} of ${t.sessionCount} sessions, event stream on the rest`;\n console.log(\n ` Billable active: ${formatDurationMs(t.billableActiveTimeMs)} (union; ${basisCaveat}; idle gaps > 5m excluded; tz ${result.timeZone})`,\n );\n if (t.activeTimeMs !== t.billableActiveTimeMs) {\n console.log(\n ` Summed: ${formatDurationMs(t.activeTimeMs)} (per-session sum; concurrent sessions double-counted)`,\n );\n }\n if (t.machineActiveAvailable) {\n const machineSessions = result.sessions.filter((s) => s.availability.machineActive).length;\n console.log(\n ` Model working: ${formatDurationMs(t.machineActiveTimeMs)} (model compute, subset of active; Codex turn duration on ${machineSessions} of ${t.sessionCount} sessions; summed, not wall-clock-deduped)`,\n );\n }\n const openPart = t.openSessionCount > 0 ? `; ${t.openSessionCount} open counted to now` : \"\";\n console.log(\n ` Span: ${formatDurationMs(t.sessionSpanMs)} (total elapsed${openPart})`,\n );\n const cmdCaveat = t.commandTimeReliable\n ? \"\"\n : \"; some sessions (e.g. claude-code-import) report 0 shell time\";\n console.log(\n ` Command: ${formatDurationMs(t.commandTimeMs)} (real shell execution${cmdCaveat})`,\n );\n\n if (bySource && result.bySource.length > 0) {\n console.log(\"\");\n console.log(\"By source:\");\n for (const s of result.bySource) {\n console.log(` ${s.sourceKind}: ${describeSource(s)}`);\n }\n }\n\n if (byDay && result.byDay.length > 0) {\n console.log(\"\");\n console.log(\"By day (billable time x volume):\");\n for (const d of result.byDay) {\n const machine =\n d.machineActiveTimeMs > 0 ? ` (model ${formatDurationMs(d.machineActiveTimeMs)})` : \"\";\n console.log(\n ` ${d.date}: ${formatDurationMs(d.billableActiveTimeMs)} active${machine}, ${formatInt(d.tokens.output)} out tok, ${d.commandCount} cmd / ${d.fileChangedCount} files / ${d.decisionCount} dec`,\n );\n }\n }\n}\n\nfunction describeSource(s: SourceWorkStats): string {\n const cmd = s.commandTimeReliable ? formatDurationMs(s.commandTimeMs) : \"n/a\";\n const tokens = s.tokensAvailable ? `${formatInt(s.tokens.output)} out tok` : \"no tokens\";\n const machine = s.machineActiveAvailable\n ? `, model ${formatDurationMs(s.machineActiveTimeMs)}`\n : \"\";\n return `${s.sessionCount} sessions, ${tokens}, active ${formatDurationMs(s.activeTimeMs)}${machine}, command ${cmd}`;\n}\n\n/** \"1,234,567\" — thousands-separated, fixed en-US so output is deterministic. */\nfunction formatInt(n: number): string {\n return n.toLocaleString(\"en-US\");\n}\n\nasync function resolveRepositoryRootForStats(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\"Not a git repository. Run 'git init' first, then re-run 'basou stats'.\", {\n cause: error,\n });\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n","import {\n assertBasouRootSafe,\n basouPaths,\n buildStatusSnapshot,\n findErrorCode,\n type Manifest,\n readManifest,\n resolveRepositoryRoot,\n type StatusSnapshot,\n writeStatus,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport { isVerbose, renderCliError } from \"../lib/error-render.js\";\n\nexport type StatusOptions = {\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type StatusContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n};\n\n/**\n * Register `basou status` on a commander program. The command outputs a\n * human-readable summary by default, or a JSON document when `--json` is\n * given. In both modes `.basou/status.json` is rewritten as a side effect.\n */\nexport function registerStatusCommand(program: Command): void {\n program\n .command(\"status\")\n .description(\"Show the current Basou workspace status\")\n .option(\"--json\", \"Output the snapshot as JSON to stdout\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: StatusOptions) => {\n await runStatus(options);\n });\n}\n\n/**\n * Programmatic entry that mutates process state (`exitCode`, stderr).\n * Exported for tests, but tests should prefer {@link doRunStatus} when they\n * only need to assert on success behaviour or thrown errors.\n */\nexport async function runStatus(options: StatusOptions, ctx: StatusContext = {}): Promise<void> {\n try {\n await doRunStatus(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * Pure runner: resolves inputs, performs the status snapshot, writes\n * `status.json`, and prints output. On any failure throws an Error whose\n * `message` is pathless; native fs / parse errors are attached as `cause`.\n * Exported for tests so they can assert on thrown errors without touching\n * `process.exitCode`.\n */\nexport async function doRunStatus(options: StatusOptions, ctx: StatusContext): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForStatus(cwd);\n const paths = basouPaths(repositoryRoot);\n\n // Pre-condition: refuse to operate on a swapped/non-directory .basou root\n // before we ever touch a file. Treat ENOENT (root absent) the same way as\n // a missing manifest below — both mean \"workspace not initialized\".\n try {\n await assertBasouRootSafe(paths.root);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n\n let manifest: Manifest;\n try {\n manifest = await readManifest(paths);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n // ZodError's `message` echoes invalid input values verbatim, which can\n // include path-like strings if a user-edited manifest contains them.\n // Wrap in a fixed pathless message and surface only the cause's\n // constructor name in verbose mode via the shared renderCliError helper.\n throw new Error(\"Failed to read workspace manifest\", { cause: error });\n }\n\n const snapshot = await buildStatusSnapshot({ manifest, paths });\n await writeStatus(paths, snapshot);\n\n if (options.json === true) {\n console.log(JSON.stringify(snapshot, null, 2));\n } else {\n renderTextStatus(snapshot);\n }\n}\n\nfunction renderTextStatus(s: StatusSnapshot): void {\n console.log(`Workspace: ${s.workspace.name} (${s.workspace.id})`);\n // The label changed from \"Basou version\" to \"Spec version\" in v0.3.1\n // because the field tracks the workspace data-format spec\n // (`basou_version` literal-locked to \"0.1.0\") and was repeatedly\n // mistaken for the release version returned by `basou --version`. The\n // wire payload field name (= `workspace.basou_version`) stays the same\n // so JSON consumers are unaffected; only the human-readable label\n // moves.\n console.log(`Spec version: ${s.workspace.basou_version}`);\n console.log(`Generated at: ${s.generated_at}`);\n const dp = s.directories_present;\n const total = Object.keys(dp).length;\n const present = Object.values(dp).filter((v) => v === true).length;\n console.log(`Subdirectories present: ${present}/${total}`);\n}\n\n/**\n * Wrap the core git capability so the CLI surfaces the command-specific\n * \"Run 'git init' first, then re-run 'basou status'.\" suffix while the\n * capability layer remains command-agnostic.\n */\nasync function resolveRepositoryRootForStatus(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\"Not a git repository. Run 'git init' first, then re-run 'basou status'.\", {\n cause: error,\n });\n }\n throw error;\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport {\n archiveTask,\n assertBasouRootSafe,\n basouPaths,\n createTaskWithEvent,\n deleteTask,\n type Event,\n editTask,\n enumerateArchivedTaskIds,\n findErrorCode,\n loadSessionEntries,\n loadTaskEntries,\n type PrefixedId,\n prefixedUlid,\n type ReconcileFailure,\n type ReconcileResult,\n type RefreshLinkageResult,\n readManifest,\n readTaskFile,\n readTaskFileWithArchiveFallback,\n reconcileAllTasks,\n reconcileTask,\n refreshTaskLinkedSessions,\n replayEvents,\n resolveRepositoryRoot,\n resolveSessionId,\n resolveTaskId,\n type SessionEntry,\n type SessionStatus,\n type TaskDocument,\n type TaskReconciledEvent,\n type TaskStatus,\n TaskStatusSchema,\n TaskWriteAfterEventError,\n updateTaskStatusWithEvent,\n} from \"@basou/core\";\nimport { type Command, InvalidArgumentError } from \"commander\";\nimport {\n type ErrorClassifier,\n failedToFinalizeClassifier,\n isVerbose,\n printReplayWarning,\n printTaskSkip,\n renderCliError,\n shortSessionId,\n shortTaskId,\n} from \"../lib/error-render.js\";\n\nconst STATUS_VALUES = TaskStatusSchema.options;\n\n// ============================================================================\n// Public registration\n// ============================================================================\n\nexport type TaskNewOptions = {\n title: string;\n label?: string;\n status?: TaskStatus;\n /**\n * ISO-8601 timestamp written into `task.md.updated_at` when status is a\n * terminal value (done / cancelled). Lets the operator backdate a\n * retroactively-recorded completed task so `task.md` reflects the\n * actual completion moment while `events.jsonl` keeps recording time.\n * Rejected (exit 1) when supplied with a non-terminal status.\n */\n completedAt?: string;\n session?: string;\n description?: string;\n fromFile?: string;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type TaskListOptions = {\n status?: TaskStatus;\n includeArchived?: boolean;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type TaskShowOptions = {\n json?: boolean;\n events?: boolean;\n last?: number;\n verbose?: boolean;\n};\n\nexport type TaskStatusOptions = {\n session?: string;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type TaskReconcileOptions = {\n task?: string;\n write?: boolean;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type TaskRefreshLinkageOptions = {\n write?: boolean;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type TaskEditOptions = {\n title?: string;\n status?: TaskStatus;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type TaskDeleteOptions = {\n yes?: boolean;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type TaskArchiveOptions = {\n yes?: boolean;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type TaskContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n /** Defaults to `() => new Date()`. Injectable for tests. */\n nowProvider?: () => Date;\n};\n\nexport function registerTaskCommand(program: Command): void {\n const task = program\n .command(\"task\")\n .description(\"Manage Basou tasks (purpose units that span sessions)\");\n\n task\n .command(\"new\")\n .description(\"Create a new task and fire a task_created event\")\n .requiredOption(\"--title <text>\", \"Task title\", parseTitle)\n .option(\"--label <text>\", \"Optional label for the task\", parseLabel)\n .option(\n \"--status <status>\",\n `Initial status (one of: ${STATUS_VALUES.join(\", \")}; default planned). For done/cancelled the orchestrator also emits a task_status_changed event so the audit trail records the implicit transition.`,\n parseInitialTaskStatus,\n )\n .option(\n \"--completed-at <iso>\",\n \"ISO-8601 timestamp to record as the task's updated_at when --status is done or cancelled (rejected otherwise)\",\n parseIsoTimestampOption,\n )\n .option(\"--session <session_id>\", \"Attach to existing session; otherwise ad-hoc\")\n .option(\"--description <text>\", \"Task description body (inline)\", parseDescriptionOption)\n .option(\"--from-file <path>\", \"Read description body from a file\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: TaskNewOptions) => {\n await runTaskNew(options);\n });\n\n task\n .command(\"list\")\n .description(\"List tasks in the current workspace (newest first)\")\n .option(\n \"--status <status>\",\n `Filter by task status (one of: ${STATUS_VALUES.join(\", \")})`,\n parseTaskStatusFilter,\n )\n .option(\"--include-archived\", \"Also list tasks under .basou/tasks/archive/ (hidden by default)\")\n .option(\"--json\", \"Output the list as a JSON array\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: TaskListOptions) => {\n await runTaskList(options);\n });\n\n task\n .command(\"show <task_id>\")\n .description(\"Show a task with its metadata, linked sessions, and events\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--events\", \"Show all related events instead of trailing few\")\n .option(\"--last <n>\", \"Number of trailing events to display (default: 5)\", parsePositiveInt)\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (id: string, options: TaskShowOptions) => {\n await runTaskShow(id, options);\n });\n\n task\n .command(\"status <task_id> <new_status>\")\n .description(\"Change task status and fire a task_status_changed event\")\n .option(\"--session <session_id>\", \"Attach to existing session; otherwise ad-hoc\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (taskIdInput: string, newStatusInput: string, options: TaskStatusOptions) => {\n await runTaskStatus(taskIdInput, newStatusInput, options);\n });\n\n task\n .command(\"reconcile\")\n .description(\n \"Dry-run audit of task session references; use --write to repair broken refs. Forward sync (events -> task.md linked_sessions) is out of scope.\",\n )\n .option(\"--task <task_id>\", \"Limit to a single task (otherwise scan all)\")\n .option(\"--write\", \"Apply repairs (default: dry-run)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"-v, --verbose\", \"Show error causes and broken session_id values\")\n .action(async (options: TaskReconcileOptions) => {\n await runTaskReconcile(options);\n });\n\n task\n .command(\"refresh-linkage <task_id>\")\n .description(\n \"Re-derive task.md linked_sessions[] from session.yaml.task_id matches across the workspace (forward sync events -> task.md). Dry-run default; use --write to apply.\",\n )\n .option(\"--write\", \"Apply the refresh (default: dry-run)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (taskIdInput: string, options: TaskRefreshLinkageOptions) => {\n await runTaskRefreshLinkage(taskIdInput, options);\n });\n\n task\n .command(\"edit <task_id>\")\n .description(\n \"Update --title and/or --status on an existing task. Status changes fire a task_status_changed event; title changes update task.md only (no event).\",\n )\n .option(\"--title <text>\", \"New title (must be non-empty)\", parseTitle)\n .option(\n \"--status <status>\",\n `New status (one of: ${STATUS_VALUES.join(\", \")}); routed through STATUS_TRANSITIONS so only valid edges are accepted`,\n parseInitialTaskStatus,\n )\n .option(\"--json\", \"Output as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (taskIdInput: string, options: TaskEditOptions) => {\n await runTaskEdit(taskIdInput, options);\n });\n\n task\n .command(\"delete <task_id>\")\n .description(\n \"Hard-delete a task.md file and fire a task_deleted event. Requires confirmation by default; use --yes to skip the prompt.\",\n )\n .option(\"--yes\", \"Skip the confirmation prompt (required when stdin is not a TTY)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (taskIdInput: string, options: TaskDeleteOptions) => {\n await runTaskDelete(taskIdInput, options);\n });\n\n task\n .command(\"archive <task_id>\")\n .description(\n \"Move task.md into .basou/tasks/archive/ and fire a task_archived event. Requires confirmation by default; use --yes to skip the prompt.\",\n )\n .option(\"--yes\", \"Skip the confirmation prompt (required when stdin is not a TTY)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (taskIdInput: string, options: TaskArchiveOptions) => {\n await runTaskArchive(taskIdInput, options);\n });\n}\n\n// ============================================================================\n// task new\n// ============================================================================\n\nexport async function runTaskNew(options: TaskNewOptions, ctx: TaskContext = {}): Promise<void> {\n try {\n await doRunTaskNew(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options), classifiers: TASK_CLASSIFIERS });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunTaskNew(options: TaskNewOptions, ctx: TaskContext): Promise<void> {\n if (options.description !== undefined && options.fromFile !== undefined) {\n throw new Error(\"--description and --from-file are mutually exclusive\");\n }\n if (options.fromFile === \"-\") {\n throw new Error(\"--from-file - (stdin) is not supported in v0.1\");\n }\n\n const initialStatus = options.status ?? \"planned\";\n // `--completed-at` only makes sense paired with a terminal status. Catching\n // the mismatch up front avoids ambiguity about whether the override would\n // still be honored on a planned/in_progress task (= it wouldn't).\n if (options.completedAt !== undefined && !isTerminalStatusForCli(initialStatus)) {\n throw new Error(\"--completed-at requires --status done or cancelled\");\n }\n\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForTask(cwd, \"new\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const description =\n options.description !== undefined\n ? options.description\n : options.fromFile !== undefined\n ? await readDescriptionFile(options.fromFile)\n : \"\";\n\n const now = ctx.nowProvider !== undefined ? ctx.nowProvider() : new Date();\n const occurredAt = now.toISOString();\n const taskId = prefixedUlid(\"task\");\n\n if (options.session !== undefined) {\n const sessionId = (await resolveSessionId(paths, options.session)) as PrefixedId<\"ses\">;\n const result = await createTaskWithEvent({\n mode: \"attach\",\n paths,\n occurredAt,\n sessionId,\n taskId,\n title: options.title,\n ...(options.label !== undefined ? { label: options.label } : {}),\n initialStatus,\n description,\n ...(options.completedAt !== undefined ? { completedAt: options.completedAt } : {}),\n });\n printTaskNewResult(options, {\n mode: \"attached\",\n taskId: result.taskId,\n eventId: result.eventId,\n sessionId: result.sessionId,\n sessionStatus: result.sessionStatus,\n title: options.title,\n ...(options.label !== undefined ? { label: options.label } : {}),\n status: initialStatus,\n occurredAt,\n ...(options.completedAt !== undefined ? { completedAt: options.completedAt } : {}),\n descriptionLength: description.length,\n });\n return;\n }\n\n const manifest = await readManifest(paths);\n const result = await createTaskWithEvent({\n mode: \"ad-hoc\",\n paths,\n manifest,\n occurredAt,\n taskId,\n title: options.title,\n ...(options.label !== undefined ? { label: options.label } : {}),\n initialStatus,\n description,\n workingDirectory: repositoryRoot,\n ...(options.completedAt !== undefined ? { completedAt: options.completedAt } : {}),\n });\n printTaskNewResult(options, {\n mode: \"ad-hoc\",\n taskId: result.taskId,\n eventId: result.eventId,\n sessionId: result.sessionId,\n sessionStatus: result.sessionStatus,\n title: options.title,\n ...(options.label !== undefined ? { label: options.label } : {}),\n status: initialStatus,\n occurredAt,\n ...(options.completedAt !== undefined ? { completedAt: options.completedAt } : {}),\n descriptionLength: description.length,\n });\n}\n\nfunction isTerminalStatusForCli(status: TaskStatus): boolean {\n return status === \"done\" || status === \"cancelled\";\n}\n\ntype TaskNewPrint = {\n mode: \"ad-hoc\" | \"attached\";\n taskId: string;\n eventId: string;\n sessionId: string;\n sessionStatus: SessionStatus;\n title: string;\n label?: string;\n status: TaskStatus;\n occurredAt: string;\n completedAt?: string;\n descriptionLength: number;\n};\n\nfunction printTaskNewResult(options: TaskNewOptions, result: TaskNewPrint): void {\n if (options.json === true) {\n console.log(\n JSON.stringify({\n task_id: result.taskId,\n event_id: result.eventId,\n session_id: result.sessionId,\n session_status: result.sessionStatus,\n mode: result.mode,\n title: result.title,\n label: result.label ?? null,\n status: result.status,\n recorded_at: result.occurredAt,\n completed_at: result.completedAt ?? null,\n description_length: result.descriptionLength,\n }),\n );\n return;\n }\n const shortSes = shortSessionId(result.sessionId);\n const created =\n result.mode === \"ad-hoc\"\n ? `Created ${result.taskId} in ad-hoc session ${shortSes}`\n : `Created ${result.taskId} in session ${shortSes} (${result.sessionStatus})`;\n console.log(created);\n console.log(` Title: ${result.title}`);\n // For terminal initial statuses surface both the recording time (= the\n // ad-hoc session timestamp = now) and the supplied completion time so the\n // operator can tell at a glance that the audit trail (events.jsonl)\n // reflects the former while task.md.updated_at reflects the latter.\n if (result.completedAt !== undefined) {\n console.log(\n ` Status: ${result.status} (recorded at ${result.occurredAt}, completed at ${result.completedAt})`,\n );\n } else {\n console.log(` Status: ${result.status}`);\n }\n console.log(` Label: ${result.label ?? \"(none)\"}`);\n}\n\n// ============================================================================\n// task list\n// ============================================================================\n\nexport async function runTaskList(options: TaskListOptions, ctx: TaskContext = {}): Promise<void> {\n try {\n await doRunTaskList(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options), classifiers: TASK_CLASSIFIERS });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunTaskList(options: TaskListOptions, ctx: TaskContext): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForTask(cwd, \"list\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const entries = await loadTaskEntries(paths, {\n onSkip: (id, reason) => printTaskSkip(id, reason),\n });\n // Archive entries are read from `<paths.tasks>/archive/` directly (no\n // dedicated loader yet — call sites are rare). Marshalling them through a\n // separate scan keeps the default `task list` path fast (no extra readdir\n // when the operator does not opt in).\n const archivedEntries: { doc: TaskDocument; archived: true }[] = [];\n if (options.includeArchived === true) {\n const archivedIds = await enumerateArchivedTaskIds(paths);\n for (const id of archivedIds) {\n try {\n const { doc } = await readTaskFileWithArchiveFallback(paths, id);\n archivedEntries.push({ doc, archived: true });\n } catch {\n // Skip unreadable archive entries — keep the list output usable\n // when one file is corrupt rather than aborting the run.\n }\n }\n }\n const combined = [...entries, ...archivedEntries.map((a) => a.doc)];\n const archivedIdSet = new Set(archivedEntries.map((a) => a.doc.task.task.id));\n // loadTaskEntries returns asc by created_at; reverse for newest-first display.\n const ordered = [...combined].sort(\n (a, b) => Date.parse(b.task.task.created_at) - Date.parse(a.task.task.created_at),\n );\n const filtered =\n options.status !== undefined\n ? ordered.filter((t) => t.task.task.status === options.status)\n : ordered;\n\n if (filtered.length === 0) {\n if (options.json === true) {\n console.log(\"[]\");\n } else {\n console.log(\"No tasks found.\");\n }\n return;\n }\n\n if (options.json === true) {\n console.log(\n JSON.stringify(\n filtered.map((t) => ({\n task_id: t.task.task.id,\n title: t.task.task.title,\n label: t.task.task.label ?? null,\n status: t.task.task.status,\n created_at: t.task.task.created_at,\n updated_at: t.task.task.updated_at,\n linked_session_count: t.task.task.linked_sessions.length,\n archived: archivedIdSet.has(t.task.task.id),\n })),\n null,\n 2,\n ),\n );\n return;\n }\n printTaskListText(filtered, archivedIdSet);\n}\n\nfunction printTaskListText(\n entries: ReadonlyArray<TaskDocument>,\n archivedIds: ReadonlySet<string>,\n): void {\n const rows = entries.map((t) => ({\n sid: shortTaskId(t.task.task.id),\n status: t.task.task.status,\n createdAt: t.task.task.created_at,\n label: t.task.task.label ?? \"(none)\",\n // Mark archived entries with a leading [archived] tag so the operator\n // can distinguish them from live tasks when --include-archived is on.\n title: archivedIds.has(t.task.task.id) ? `[archived] ${t.task.task.title}` : t.task.task.title,\n linkedCount: String(t.task.task.linked_sessions.length),\n }));\n const widths = {\n sid: maxLen(\n rows.map((r) => r.sid),\n \"SHORT_ID\".length,\n ),\n status: maxLen(\n rows.map((r) => r.status),\n \"STATUS\".length,\n ),\n createdAt: maxLen(\n rows.map((r) => r.createdAt),\n \"CREATED_AT\".length,\n ),\n linkedCount: maxLen(\n rows.map((r) => r.linkedCount),\n \"LINKS\".length,\n ),\n label: maxLen(\n rows.map((r) => r.label),\n \"LABEL\".length,\n ),\n };\n console.log(\n `${pad(\"SHORT_ID\", widths.sid)} ${pad(\"STATUS\", widths.status)} ${pad(\"CREATED_AT\", widths.createdAt)} ${pad(\"LINKS\", widths.linkedCount)} ${pad(\"LABEL\", widths.label)} TITLE`,\n );\n for (const r of rows) {\n console.log(\n `${pad(r.sid, widths.sid)} ${pad(r.status, widths.status)} ${pad(r.createdAt, widths.createdAt)} ${pad(r.linkedCount, widths.linkedCount)} ${pad(r.label, widths.label)} ${r.title}`,\n );\n }\n}\n\n// ============================================================================\n// task show\n// ============================================================================\n\nexport async function runTaskShow(\n idInput: string,\n options: TaskShowOptions,\n ctx: TaskContext = {},\n): Promise<void> {\n try {\n await doRunTaskShow(idInput, options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options), classifiers: TASK_CLASSIFIERS });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunTaskShow(\n idInput: string,\n options: TaskShowOptions,\n ctx: TaskContext,\n): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForTask(cwd, \"show\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const taskId = await resolveTaskId(paths, idInput, { includeArchived: true });\n const { doc, archived } = await readTaskFileWithArchiveFallback(paths, taskId);\n\n // Collect events related to this task by replaying every session's\n // events.jsonl and filtering by task_id. Could be optimised via an\n // index.json cache later; v0.1 accepts the linear scan.\n const sessions = await loadSessionEntries(paths, { now: new Date() });\n const events: Event[] = [];\n const linkedSessionIds = new Set<string>(doc.task.task.linked_sessions);\n // Replay warnings (malformed JSON / schema violations / partial trailing\n // lines) and unreadable events.jsonl files must reach the operator so\n // silent gaps in the events history don't go unnoticed.\n for (const s of sessions) {\n const sessionDir = join(paths.sessions, s.sessionId);\n try {\n for await (const ev of replayEvents(sessionDir, {\n onWarning: (w) => printReplayWarning(w, s.sessionId),\n })) {\n if (\n (ev.type === \"task_created\" ||\n ev.type === \"task_status_changed\" ||\n ev.type === \"task_reconciled\" ||\n ev.type === \"task_linkage_refreshed\" ||\n ev.type === \"task_deleted\" ||\n ev.type === \"task_archived\") &&\n ev.task_id === taskId\n ) {\n events.push(ev);\n linkedSessionIds.add(s.sessionId);\n }\n }\n } catch (error: unknown) {\n // I/O failure (events.jsonl unreadable). The renderer still works on\n // task.md metadata alone, but the operator must know events from this\n // session are missing from the aggregate.\n const short = shortSessionId(s.sessionId);\n const suffix = error instanceof Error ? `: ${error.message}` : \"\";\n console.error(`Warning: events unavailable for session ${short}${suffix}`);\n }\n }\n events.sort((a, b) => Date.parse(a.occurred_at) - Date.parse(b.occurred_at));\n\n if (options.json === true) {\n console.log(\n JSON.stringify(\n {\n task: doc.task.task,\n body: doc.body,\n linked_sessions: [...linkedSessionIds],\n archived,\n events,\n },\n null,\n 2,\n ),\n );\n return;\n }\n\n printTaskShowText(doc, [...linkedSessionIds], events, sessions, options, archived);\n}\n\nfunction printTaskShowText(\n doc: TaskDocument,\n linkedSessions: string[],\n events: ReadonlyArray<Event>,\n sessionEntries: ReadonlyArray<SessionEntry>,\n options: TaskShowOptions,\n archived: boolean,\n): void {\n const t = doc.task.task;\n const archivedTag = archived ? \" [archived]\" : \"\";\n console.log(`Task: ${t.id}${archivedTag}`);\n console.log(` Title: ${t.title}`);\n console.log(` Status: ${t.status}`);\n console.log(` Label: ${t.label ?? \"(none)\"}`);\n console.log(` Created at: ${t.created_at}`);\n console.log(` Updated at: ${t.updated_at}`);\n console.log(` Workspace: ${t.workspace_id}`);\n console.log(\"\");\n console.log(`Linked sessions (${linkedSessions.length}):`);\n const sessionStatusMap = new Map<string, string>(\n sessionEntries.map((s) => [s.sessionId, s.session.session.status]),\n );\n for (const sid of linkedSessions) {\n const status = sessionStatusMap.get(sid) ?? \"unknown\";\n console.log(` ${sid} (${status})`);\n }\n console.log(\"\");\n console.log(\"Description:\");\n if (doc.body.length === 0) {\n console.log(\"(no description)\");\n } else {\n console.log(doc.body);\n }\n console.log(\"\");\n console.log(`Events: ${events.length} total`);\n if (events.length === 0) return;\n const showAll = options.events === true && options.last === undefined;\n const last = options.last ?? 5;\n const slice = showAll ? events : events.slice(-last);\n const heading = showAll ? \"All events:\" : `Last ${slice.length} events:`;\n console.log(\"\");\n console.log(heading);\n const verbose = isVerbose(options);\n for (const ev of slice) {\n console.log(` ${formatTaskEvent(ev)}`);\n if (verbose && ev.type === \"task_reconciled\") {\n for (const line of formatTaskReconciledDetails(ev)) {\n console.log(line);\n }\n }\n }\n}\n\nfunction formatTaskEvent(ev: Event): string {\n if (ev.type === \"task_created\") {\n return `${ev.occurred_at} [${ev.source}] task_created ${ev.title}`;\n }\n if (ev.type === \"task_status_changed\") {\n return `${ev.occurred_at} [${ev.source}] task_status_changed ${ev.from} -> ${ev.to}`;\n }\n if (ev.type === \"task_reconciled\") {\n const removedCount =\n (ev.removed_created_in_session !== null ? 1 : 0) + ev.removed_linked_sessions.length;\n return `${ev.occurred_at} [${ev.source}] task_reconciled ${removedCount} broken ref${removedCount === 1 ? \"\" : \"s\"} (use -v for details)`;\n }\n if (ev.type === \"task_linkage_refreshed\") {\n const added = ev.added_linked_sessions.length;\n const removed = ev.removed_linked_sessions.length;\n const finalPart = ev.final_count !== undefined ? `, final=${ev.final_count}` : \"\";\n return `${ev.occurred_at} [${ev.source}] task_linkage_refreshed +${added} / -${removed}${finalPart}`;\n }\n if (ev.type === \"task_deleted\") {\n return `${ev.occurred_at} [${ev.source}] task_deleted ${ev.title}`;\n }\n if (ev.type === \"task_archived\") {\n return `${ev.occurred_at} [${ev.source}] task_archived ${ev.title}`;\n }\n return `${ev.occurred_at} [${ev.source}] ${ev.type}`;\n}\n\nfunction formatTaskReconciledDetails(ev: TaskReconciledEvent): string[] {\n const lines: string[] = [];\n if (ev.removed_created_in_session !== null) {\n lines.push(` removed_created_in_session: ${ev.removed_created_in_session}`);\n }\n if (ev.created_in_session_replacement !== null) {\n lines.push(` created_in_session_replacement: ${ev.created_in_session_replacement}`);\n }\n if (ev.removed_linked_sessions.length > 0) {\n lines.push(\" removed_linked_sessions:\");\n for (const sid of ev.removed_linked_sessions) {\n lines.push(` - ${sid}`);\n }\n }\n return lines;\n}\n\n// ============================================================================\n// task status\n// ============================================================================\n\nexport async function runTaskStatus(\n taskIdInput: string,\n newStatusInput: string,\n options: TaskStatusOptions,\n ctx: TaskContext = {},\n): Promise<void> {\n try {\n await doRunTaskStatus(taskIdInput, newStatusInput, options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options), classifiers: TASK_CLASSIFIERS });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunTaskStatus(\n taskIdInput: string,\n newStatusInput: string,\n options: TaskStatusOptions,\n ctx: TaskContext,\n): Promise<void> {\n if (taskIdInput.trim().length === 0) {\n throw new Error(\"Task id is empty\");\n }\n const newStatus = parseTaskStatusPositional(newStatusInput);\n\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForTask(cwd, \"status\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const taskId = (await resolveTaskId(paths, taskIdInput)) as PrefixedId<\"task\">;\n const now = ctx.nowProvider !== undefined ? ctx.nowProvider() : new Date();\n const occurredAt = now.toISOString();\n\n if (options.session !== undefined) {\n const sessionId = (await resolveSessionId(paths, options.session)) as PrefixedId<\"ses\">;\n const result = await updateTaskStatusWithEvent({\n mode: \"attach\",\n paths,\n occurredAt,\n sessionId,\n taskId,\n newStatus,\n });\n printTaskStatusResult(options, {\n mode: \"attached\",\n taskId: result.taskId,\n eventId: result.eventId,\n sessionId: result.sessionId,\n sessionStatus: result.sessionStatus,\n previousStatus: result.previousStatus,\n newStatus: result.newStatus,\n });\n return;\n }\n\n const manifest = await readManifest(paths);\n const result = await updateTaskStatusWithEvent({\n mode: \"ad-hoc\",\n paths,\n manifest,\n occurredAt,\n taskId,\n newStatus,\n workingDirectory: repositoryRoot,\n });\n printTaskStatusResult(options, {\n mode: \"ad-hoc\",\n taskId: result.taskId,\n eventId: result.eventId,\n sessionId: result.sessionId,\n sessionStatus: result.sessionStatus,\n previousStatus: result.previousStatus,\n newStatus: result.newStatus,\n });\n}\n\ntype TaskStatusPrint = {\n mode: \"ad-hoc\" | \"attached\";\n taskId: string;\n eventId: string;\n sessionId: string;\n sessionStatus: SessionStatus;\n previousStatus: TaskStatus;\n newStatus: TaskStatus;\n};\n\nfunction printTaskStatusResult(options: TaskStatusOptions, result: TaskStatusPrint): void {\n if (options.json === true) {\n console.log(\n JSON.stringify({\n task_id: result.taskId,\n event_id: result.eventId,\n session_id: result.sessionId,\n session_status: result.sessionStatus,\n mode: result.mode,\n previous_status: result.previousStatus,\n new_status: result.newStatus,\n }),\n );\n return;\n }\n const sid = shortSessionId(result.sessionId);\n console.log(\n `Updated ${result.taskId} status: ${result.previousStatus} -> ${result.newStatus} (in session ${sid})`,\n );\n}\n\n// ============================================================================\n// task reconcile\n// ============================================================================\n\nexport async function runTaskReconcile(\n options: TaskReconcileOptions,\n ctx: TaskContext = {},\n): Promise<void> {\n try {\n await doRunTaskReconcile(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options), classifiers: TASK_CLASSIFIERS });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunTaskReconcile(\n options: TaskReconcileOptions,\n ctx: TaskContext,\n): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForTask(cwd, \"reconcile\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n const manifest = await readManifest(paths);\n const nowProvider = ctx.nowProvider ?? ((): Date => new Date());\n const write = options.write === true;\n const verbose = isVerbose(options);\n const json = options.json === true;\n\n if (options.task !== undefined) {\n const taskId = (await resolveTaskId(paths, options.task)) as PrefixedId<\"task\">;\n const result = await reconcileTask(paths, manifest, {\n taskId,\n occurredAt: nowProvider().toISOString(),\n workingDirectory: repositoryRoot,\n write,\n scope: \"single\",\n });\n if (json) {\n printReconcileJson({ dryRun: !write, scanned: 1, results: [result], failed: [] });\n } else {\n await printReconcileSingleText(result, paths, { write, verbose });\n }\n return;\n }\n\n const all = await reconcileAllTasks(paths, manifest, {\n occurredAt: () => nowProvider().toISOString(),\n workingDirectory: repositoryRoot,\n write,\n });\n if (json) {\n printReconcileJson({\n dryRun: !write,\n scanned: all.scanned,\n results: all.results,\n failed: all.failed,\n });\n } else {\n printReconcileAllText(all.results, all.failed, all.scanned, { write, verbose });\n }\n if (all.failed.length > 0) {\n process.exitCode = 1;\n }\n}\n\nfunction printReconcileJson(input: {\n dryRun: boolean;\n scanned: number;\n results: ReadonlyArray<ReconcileResult>;\n failed: ReadonlyArray<ReconcileFailure>;\n}): void {\n console.log(\n JSON.stringify(\n {\n dry_run: input.dryRun,\n scanned: input.scanned,\n reconciled: input.results.map((r) => ({\n task_id: r.taskId,\n removed_created_in_session: r.brokenCreatedInSession,\n created_in_session_replacement:\n r.brokenCreatedInSession !== null && r.reconcileSession !== null\n ? r.reconcileSession.sessionId\n : null,\n removed_linked_sessions: r.brokenLinkedSessions,\n reconcile_session_id: r.reconcileSession?.sessionId ?? null,\n event_id: r.reconcileSession?.eventId ?? null,\n })),\n failed: input.failed.map((f) => ({\n task_id: f.taskId,\n error_class: f.errorClass,\n phase: f.phase,\n })),\n },\n null,\n 2,\n ),\n );\n}\n\nasync function printReconcileSingleText(\n result: ReconcileResult,\n paths: ReturnType<typeof basouPaths>,\n options: { write: boolean; verbose: boolean },\n): Promise<void> {\n if (result.clean) {\n // For the --task path with no broken refs we report counts of reachable\n // references so the operator gets a positive audit confirmation rather\n // than a bare \"ok\". Re-read task.md cheaply; the core API already did\n // the integrity work so this is just for the display string.\n let createdCount = 0;\n let linkedCount = 0;\n try {\n const doc = await readTaskFile(paths, result.taskId);\n createdCount = 1;\n linkedCount = doc.task.task.linked_sessions.length;\n } catch {\n // If the file became unreadable between reconcileTask and here just\n // fall back to a less detailed message rather than crashing the run.\n }\n console.log(\n `${result.taskId}: no broken refs (${createdCount} created_in_session + ${linkedCount} linked_sessions, all reachable).`,\n );\n return;\n }\n if (options.write) {\n const sessionPart =\n result.reconcileSession !== null\n ? ` (in session ${shortSessionId(result.reconcileSession.sessionId)})`\n : \"\";\n console.log(`Reconciled ${result.taskId}: ${describeReconcileSummary(result)}${sessionPart}.`);\n return;\n }\n const summary = describeBrokenSummary(result, \"task\", options.verbose);\n console.log(`(dry-run) Would reconcile ${result.taskId}: ${summary}`);\n console.log(\"Note: events -> task.md forward sync is handled by `basou task refresh-linkage`.\");\n console.log(\"Re-run with --write to apply.\");\n}\n\nfunction printReconcileAllText(\n results: ReadonlyArray<ReconcileResult>,\n failed: ReadonlyArray<ReconcileFailure>,\n scanned: number,\n options: { write: boolean; verbose: boolean },\n): void {\n if (results.length === 0 && failed.length === 0) {\n console.log(`Scanned ${scanned} tasks, no broken refs detected.`);\n return;\n }\n\n let totalBrokenRefs = 0;\n for (const r of results) {\n totalBrokenRefs += r.brokenLinkedSessions.length + (r.brokenCreatedInSession !== null ? 1 : 0);\n }\n\n if (options.write) {\n for (const r of results) {\n const sessionPart =\n r.reconcileSession !== null\n ? ` (in session ${shortSessionId(r.reconcileSession.sessionId)})`\n : \"\";\n console.log(`Reconciled ${r.taskId}: ${describeReconcileSummary(r)}${sessionPart}`);\n }\n for (const f of failed) {\n const phase = f.phase ?? \"unknown\";\n console.error(\n `Failed to reconcile ${f.taskId}: ${f.errorClass} (phase: ${phase}); see Caused by with -v`,\n );\n }\n const reconciledCount = results.length;\n const reconciledRefs = totalBrokenRefs;\n const reconciledPart = `reconciled ${reconciledCount} task${reconciledCount === 1 ? \"\" : \"s\"} (${reconciledRefs} broken ref${reconciledRefs === 1 ? \"\" : \"s\"})`;\n const failedPart =\n failed.length === 0 ? \"\" : `, ${failed.length} task${failed.length === 1 ? \"\" : \"s\"} failed`;\n console.log(`Scanned ${scanned} tasks, ${reconciledPart}${failedPart}.`);\n if (failed.length > 0) {\n console.error(\"(exit code 1)\");\n }\n return;\n }\n\n // dry-run with broken refs\n for (const r of results) {\n const summary = describeBrokenSummary(r, \"all\", options.verbose);\n console.log(`(dry-run) Would reconcile ${r.taskId}: ${summary}`);\n }\n console.log(\n `Scanned ${scanned} tasks, would reconcile ${results.length} task${results.length === 1 ? \"\" : \"s\"} (${totalBrokenRefs} broken ref${totalBrokenRefs === 1 ? \"\" : \"s\"}).`,\n );\n console.log(\"Note: events -> task.md forward sync is handled by `basou task refresh-linkage`.\");\n console.log(\"Re-run with --write to apply.\");\n}\n\nfunction describeReconcileSummary(r: ReconcileResult): string {\n const linkedCount = r.brokenLinkedSessions.length;\n const parts: string[] = [];\n if (r.brokenCreatedInSession !== null) {\n parts.push(\"replaced created_in_session\");\n }\n if (linkedCount > 0) {\n parts.push(`removed ${linkedCount} linked_sessions entr${linkedCount === 1 ? \"y\" : \"ies\"}`);\n }\n return parts.join(\" + \");\n}\n\nfunction describeBrokenSummary(\n r: ReconcileResult,\n scope: \"all\" | \"task\",\n verbose: boolean,\n): string {\n const showIds = scope === \"task\" || verbose;\n const parts: string[] = [];\n if (r.brokenCreatedInSession !== null) {\n parts.push(\n showIds\n ? `broken created_in_session ${formatSessionIdForDisplay(r.brokenCreatedInSession, verbose, scope)}`\n : \"broken created_in_session\",\n );\n }\n const linkedCount = r.brokenLinkedSessions.length;\n if (linkedCount > 0) {\n if (showIds) {\n const ids = r.brokenLinkedSessions\n .map((id) => formatSessionIdForDisplay(id, verbose, scope))\n .join(\", \");\n parts.push(`${linkedCount} linked_sessions entr${linkedCount === 1 ? \"y\" : \"ies\"} [${ids}]`);\n } else {\n parts.push(`${linkedCount} linked_sessions entr${linkedCount === 1 ? \"y\" : \"ies\"}`);\n }\n }\n return parts.join(\" + \");\n}\n\nfunction formatSessionIdForDisplay(id: string, verbose: boolean, scope: \"all\" | \"task\"): string {\n if (verbose && scope === \"task\") return id;\n return `ses_${shortSessionId(id)}`;\n}\n\n// ============================================================================\n// task refresh-linkage\n// ============================================================================\n\nexport async function runTaskRefreshLinkage(\n taskIdInput: string,\n options: TaskRefreshLinkageOptions,\n ctx: TaskContext = {},\n): Promise<void> {\n try {\n await doRunTaskRefreshLinkage(taskIdInput, options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options), classifiers: TASK_CLASSIFIERS });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunTaskRefreshLinkage(\n taskIdInput: string,\n options: TaskRefreshLinkageOptions,\n ctx: TaskContext,\n): Promise<void> {\n if (taskIdInput.trim().length === 0) {\n throw new Error(\"Task id is empty\");\n }\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForTask(cwd, \"refresh-linkage\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n const manifest = await readManifest(paths);\n const taskId = (await resolveTaskId(paths, taskIdInput)) as PrefixedId<\"task\">;\n const nowProvider = ctx.nowProvider ?? ((): Date => new Date());\n const write = options.write === true;\n\n const result = await refreshTaskLinkedSessions(paths, manifest, {\n taskId,\n occurredAt: nowProvider().toISOString(),\n workingDirectory: repositoryRoot,\n write,\n });\n\n if (options.json === true) {\n printRefreshLinkageJson(result, { dryRun: !write });\n return;\n }\n printRefreshLinkageText(result, { dryRun: !write });\n}\n\nfunction printRefreshLinkageJson(result: RefreshLinkageResult, input: { dryRun: boolean }): void {\n console.log(\n JSON.stringify(\n {\n task_id: result.taskId,\n clean: result.clean,\n dry_run: input.dryRun,\n added_linked_sessions: result.addedLinkedSessions,\n removed_linked_sessions: result.removedLinkedSessions,\n final_count: result.finalCount,\n refresh_session_id: result.refreshSession?.sessionId ?? null,\n event_id: result.refreshSession?.eventId ?? null,\n },\n null,\n 2,\n ),\n );\n}\n\nfunction printRefreshLinkageText(result: RefreshLinkageResult, input: { dryRun: boolean }): void {\n if (result.clean) {\n console.log(\n `${result.taskId}: linked_sessions already fresh (${result.finalCount} entr${result.finalCount === 1 ? \"y\" : \"ies\"}).`,\n );\n return;\n }\n const addedCount = result.addedLinkedSessions.length;\n const removedCount = result.removedLinkedSessions.length;\n const summaryParts: string[] = [];\n if (addedCount > 0) {\n summaryParts.push(`+${addedCount} added`);\n }\n if (removedCount > 0) {\n summaryParts.push(`-${removedCount} removed`);\n }\n const summary = summaryParts.join(\", \");\n if (input.dryRun) {\n console.log(`(dry-run) Would refresh ${result.taskId} linked_sessions: ${summary}.`);\n console.log(\"Re-run with --write to apply.\");\n return;\n }\n const sid =\n result.refreshSession !== null\n ? ` (in session ${shortSessionId(result.refreshSession.sessionId)})`\n : \"\";\n console.log(\n `Refreshed ${result.taskId} linked_sessions: ${summary}${sid}; final count ${result.finalCount}.`,\n );\n}\n\n// ============================================================================\n// task edit / delete / archive\n// ============================================================================\n\nexport async function runTaskEdit(\n taskIdInput: string,\n options: TaskEditOptions,\n ctx: TaskContext = {},\n): Promise<void> {\n try {\n await doRunTaskEdit(taskIdInput, options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options), classifiers: TASK_CLASSIFIERS });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunTaskEdit(\n taskIdInput: string,\n options: TaskEditOptions,\n ctx: TaskContext,\n): Promise<void> {\n if (taskIdInput.trim().length === 0) {\n throw new Error(\"Task id is empty\");\n }\n if (options.title === undefined && options.status === undefined) {\n throw new Error(\"Nothing to edit: provide --title or --status\");\n }\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForTask(cwd, \"edit\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n const manifest = await readManifest(paths);\n const taskId = (await resolveTaskId(paths, taskIdInput)) as PrefixedId<\"task\">;\n const now = ctx.nowProvider !== undefined ? ctx.nowProvider() : new Date();\n const occurredAt = now.toISOString();\n\n const result = await editTask({\n paths,\n taskId,\n occurredAt,\n manifest,\n workingDirectory: repositoryRoot,\n ...(options.title !== undefined ? { title: options.title } : {}),\n ...(options.status !== undefined ? { newStatus: options.status } : {}),\n });\n\n if (options.json === true) {\n console.log(\n JSON.stringify({\n task_id: result.taskId,\n title_updated: result.titleUpdated,\n status_updated: result.statusUpdated,\n previous_status: result.previousStatus,\n new_status: result.newStatus,\n status_change_session_id: result.statusChangeSession?.sessionId ?? null,\n status_change_event_id: result.statusChangeSession?.eventId ?? null,\n }),\n );\n return;\n }\n if (result.statusUpdated) {\n const sid =\n result.statusChangeSession !== null\n ? ` (in session ${shortSessionId(result.statusChangeSession.sessionId)})`\n : \"\";\n console.log(\n `Updated ${result.taskId} status: ${result.previousStatus} -> ${result.newStatus}${sid}`,\n );\n }\n if (result.titleUpdated) {\n console.log(`Updated ${result.taskId} title.`);\n }\n if (!result.statusUpdated && !result.titleUpdated) {\n // Both fields were supplied but matched the current values exactly —\n // tell the operator the task was already in the requested state.\n console.log(`No changes for ${result.taskId}.`);\n }\n}\n\nexport async function runTaskDelete(\n taskIdInput: string,\n options: TaskDeleteOptions,\n ctx: TaskContext = {},\n): Promise<void> {\n try {\n await doRunTaskDelete(taskIdInput, options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options), classifiers: TASK_CLASSIFIERS });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunTaskDelete(\n taskIdInput: string,\n options: TaskDeleteOptions,\n ctx: TaskContext,\n): Promise<void> {\n if (taskIdInput.trim().length === 0) {\n throw new Error(\"Task id is empty\");\n }\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForTask(cwd, \"delete\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n const manifest = await readManifest(paths);\n const taskId = (await resolveTaskId(paths, taskIdInput)) as PrefixedId<\"task\">;\n\n if (options.yes !== true) {\n await confirmDestructiveAction(\"delete\", taskId);\n }\n\n const now = ctx.nowProvider !== undefined ? ctx.nowProvider() : new Date();\n const occurredAt = now.toISOString();\n const result = await deleteTask({\n paths,\n manifest,\n taskId,\n occurredAt,\n workingDirectory: repositoryRoot,\n });\n\n if (options.json === true) {\n console.log(\n JSON.stringify({\n task_id: result.taskId,\n title: result.title,\n session_id: result.sessionId,\n event_id: result.eventId,\n }),\n );\n return;\n }\n console.log(\n `Deleted ${result.taskId} (\"${result.title}\") in ad-hoc session ${shortSessionId(result.sessionId)}.`,\n );\n}\n\nexport async function runTaskArchive(\n taskIdInput: string,\n options: TaskArchiveOptions,\n ctx: TaskContext = {},\n): Promise<void> {\n try {\n await doRunTaskArchive(taskIdInput, options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options), classifiers: TASK_CLASSIFIERS });\n process.exitCode = 1;\n }\n}\n\nexport async function doRunTaskArchive(\n taskIdInput: string,\n options: TaskArchiveOptions,\n ctx: TaskContext,\n): Promise<void> {\n if (taskIdInput.trim().length === 0) {\n throw new Error(\"Task id is empty\");\n }\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForTask(cwd, \"archive\");\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n const manifest = await readManifest(paths);\n const taskId = (await resolveTaskId(paths, taskIdInput)) as PrefixedId<\"task\">;\n\n if (options.yes !== true) {\n await confirmDestructiveAction(\"archive\", taskId);\n }\n\n const now = ctx.nowProvider !== undefined ? ctx.nowProvider() : new Date();\n const occurredAt = now.toISOString();\n const result = await archiveTask({\n paths,\n manifest,\n taskId,\n occurredAt,\n workingDirectory: repositoryRoot,\n });\n\n if (options.json === true) {\n console.log(\n JSON.stringify({\n task_id: result.taskId,\n title: result.title,\n session_id: result.sessionId,\n event_id: result.eventId,\n }),\n );\n return;\n }\n console.log(\n `Archived ${result.taskId} (\"${result.title}\") in ad-hoc session ${shortSessionId(result.sessionId)}.`,\n );\n}\n\n/**\n * Read a single y/N answer from stdin when stdin is a TTY. Refuses to wait\n * for input when stdin is not a TTY (operator must pass --yes explicitly),\n * so piping `echo y | basou task delete` cannot accidentally trigger a\n * destructive action.\n */\nasync function confirmDestructiveAction(\n action: \"delete\" | \"archive\",\n taskId: string,\n): Promise<void> {\n if (process.stdin.isTTY !== true) {\n throw new Error(`Refusing to ${action} without TTY; rerun with --yes to skip confirmation.`);\n }\n const verb = action === \"delete\" ? \"Delete\" : \"Archive\";\n process.stdout.write(`${verb} task \\`${taskId}\\`? [y/N] `);\n const answer = await readSingleLineFromStdin();\n const normalized = answer.trim().toLowerCase();\n if (normalized !== \"y\" && normalized !== \"yes\") {\n throw new Error(`${verb} aborted by user.`);\n }\n}\n\nasync function readSingleLineFromStdin(): Promise<string> {\n const { createInterface } = await import(\"node:readline/promises\");\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n try {\n const line = await rl.question(\"\");\n return line;\n } finally {\n rl.close();\n }\n}\n\n// ============================================================================\n// option converters\n// ============================================================================\n\nfunction parseTitle(raw: string): string {\n if (raw.length === 0) {\n throw new InvalidArgumentError(\"Title must not be empty\");\n }\n return raw;\n}\n\nfunction parseLabel(raw: string): string {\n if (raw.length === 0) {\n throw new InvalidArgumentError(\"Label must not be empty\");\n }\n return raw;\n}\n\nfunction parseInitialTaskStatus(raw: string): TaskStatus {\n const result = TaskStatusSchema.safeParse(raw);\n if (!result.success) {\n throw new InvalidArgumentError(\n `Initial task status must be one of: ${STATUS_VALUES.join(\", \")}`,\n );\n }\n return result.data;\n}\n\nconst ISO_DATE_RE = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/;\n\nfunction parseIsoTimestampOption(raw: string): string {\n // Mirror the IsoTimestampSchema accepted form: date + time + explicit\n // zone designator. We rely on Date.parse for content validation and the\n // regex above for shape so misformed inputs are rejected before we hand\n // the string to the orchestrator's downstream parsers.\n if (!ISO_DATE_RE.test(raw) || Number.isNaN(Date.parse(raw))) {\n throw new InvalidArgumentError(\n \"Invalid --completed-at value; expected ISO-8601 timestamp like 2026-05-10T12:34:56+09:00\",\n );\n }\n return raw;\n}\n\nfunction parseTaskStatusFilter(raw: string): TaskStatus {\n const result = TaskStatusSchema.safeParse(raw);\n if (!result.success) {\n throw new InvalidArgumentError(\n `Invalid task status: ${raw}. Valid values: ${STATUS_VALUES.join(\", \")}`,\n );\n }\n return result.data;\n}\n\nfunction parseTaskStatusPositional(raw: string): TaskStatus {\n const result = TaskStatusSchema.safeParse(raw);\n if (!result.success) {\n throw new Error(`Invalid task status: ${raw}. Valid values: ${STATUS_VALUES.join(\", \")}`);\n }\n return result.data;\n}\n\nfunction parseDescriptionOption(raw: string): string {\n if (raw.length === 0) {\n throw new InvalidArgumentError(\"Description must not be empty\");\n }\n return raw;\n}\n\nfunction parsePositiveInt(raw: string): number {\n const n = Number.parseInt(raw, 10);\n if (!Number.isInteger(n) || n < 1 || raw.trim() !== String(n)) {\n throw new InvalidArgumentError(`Invalid number: ${raw}`);\n }\n return n;\n}\n\n// ============================================================================\n// IO helpers\n// ============================================================================\n\nasync function readDescriptionFile(path: string): Promise<string> {\n try {\n return await readFile(path, \"utf8\");\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Description source not found\", { cause: error });\n }\n if (findErrorCode(error, \"EISDIR\")) {\n throw new Error(\"Description source is not a file\", { cause: error });\n }\n throw new Error(\"Failed to read description source\", { cause: error });\n }\n}\n\nasync function resolveRepositoryRootForTask(\n cwd: string,\n subcmd:\n | \"new\"\n | \"list\"\n | \"show\"\n | \"status\"\n | \"reconcile\"\n | \"refresh-linkage\"\n | \"edit\"\n | \"delete\"\n | \"archive\",\n): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\n `Not a git repository. Run 'git init' first, then re-run 'basou task ${subcmd}'.`,\n { cause: error },\n );\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n\n/**\n * Task-specific classifier for {@link TaskWriteAfterEventError}. The\n * generic renderer ({@link renderCliError}) already prints the underlying\n * `error.message`; this classifier appends the two task-specific lines\n * that explain WHICH artefact is in unsafe state and the manual-repair\n * hint. Combined with {@link failedToFinalizeClassifier} from the shared\n * lib so both error classes are surfaced consistently across `task new`,\n * `task status`, `task reconcile`, etc.\n */\nconst taskWriteAfterEventClassifier: ErrorClassifier = {\n match: (error) => error instanceof TaskWriteAfterEventError,\n additionalLines: (error) => {\n const e = error as TaskWriteAfterEventError;\n const sid = shortSessionId(e.sessionId);\n const tid = shortTaskId(e.taskId);\n const unsafeArtefact = describeUnsafeArtefact(e.phase, tid, sid);\n const warning = describeWriteFailureWarning(e.phase);\n const hint =\n e.phase === \"reconcile-concurrent\"\n ? \"re-run `basou task reconcile`\"\n : e.phase === \"linkage-refresh-concurrent\"\n ? \"re-run `basou task refresh-linkage`\"\n : \"manual repair required; see `basou task show -v` for event payload\";\n return [\n `Recorded ${e.eventId} in session ${sid}; ${unsafeArtefact} is in unsafe state; do not rerun`,\n `Warning: ${warning}; events.jsonl is consistent; ${hint}`,\n ];\n },\n};\n\nconst TASK_CLASSIFIERS: readonly ErrorClassifier[] = [\n taskWriteAfterEventClassifier,\n failedToFinalizeClassifier,\n];\n\nfunction describeUnsafeArtefact(\n phase: TaskWriteAfterEventError[\"phase\"],\n tid: string,\n sid: string,\n): string {\n switch (phase) {\n case \"create\":\n return `task ${tid} file`;\n case \"overwrite\":\n return `task ${tid} file`;\n case \"link-session\":\n return \"session-task linkage\";\n case \"reconcile\":\n return `task ${tid} file (reconcile incomplete)`;\n case \"reconcile-finalize\":\n return `reconcile session ${sid} (finalize incomplete)`;\n case \"reconcile-concurrent\":\n return `task ${tid} file (concurrent modification detected)`;\n case \"linkage-refresh\":\n return `task ${tid} file (linkage refresh incomplete)`;\n case \"linkage-refresh-finalize\":\n return `linkage refresh session ${sid} (finalize incomplete)`;\n case \"linkage-refresh-concurrent\":\n return `task ${tid} file (concurrent modification detected)`;\n case \"delete\":\n return `task ${tid} file (delete incomplete; file still on disk)`;\n case \"archive\":\n return `task ${tid} file (archive incomplete; check tasks/ and tasks/archive/)`;\n }\n}\n\nfunction describeWriteFailureWarning(phase: TaskWriteAfterEventError[\"phase\"]): string {\n switch (phase) {\n case \"create\":\n return \"task.md creation failed\";\n case \"overwrite\":\n return \"task.md update failed\";\n case \"link-session\":\n return \"session.yaml task_id update failed\";\n case \"reconcile\":\n return \"task.md reconciliation failed\";\n case \"reconcile-finalize\":\n return \"reconcile session finalize failed (session.yaml status update)\";\n case \"reconcile-concurrent\":\n return \"task.md was modified concurrently; re-run reconcile to retry\";\n case \"linkage-refresh\":\n return \"task.md linkage refresh write failed\";\n case \"linkage-refresh-finalize\":\n return \"linkage refresh session finalize failed (session.yaml status update)\";\n case \"linkage-refresh-concurrent\":\n return \"task.md was modified concurrently; re-run refresh-linkage to retry\";\n case \"delete\":\n return \"task.md unlink failed after task_deleted event committed\";\n case \"archive\":\n return \"task.md move to archive/ failed after task_archived event committed\";\n }\n}\n\nfunction pad(value: string, width: number): string {\n return value.length >= width ? value : value + \" \".repeat(width - value.length);\n}\n\nfunction maxLen(values: readonly string[], floor: number): number {\n let max = floor;\n for (const v of values) if (v.length > max) max = v.length;\n return max;\n}\n","import {\n assertBasouRootSafe,\n basouPaths,\n type ChainVerdict,\n enumerateSessionDirs,\n findErrorCode,\n resolveRepositoryRoot,\n resolveSessionId,\n verifyEventsChain,\n} from \"@basou/core\";\nimport type { Command } from \"commander\";\nimport { isVerbose, renderCliError } from \"../lib/error-render.js\";\n\nexport type VerifyOptions = {\n session?: string;\n all?: boolean;\n json?: boolean;\n verbose?: boolean;\n};\n\nexport type VerifyContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n};\n\n/** One row of `basou verify` output: a session id and its chain verdict. */\nexport type VerifyRow = {\n session_id: string;\n status: ChainVerdict[\"status\"];\n event_count: number;\n reason?: ChainVerdict[\"reason\"];\n line?: number;\n};\n\n/** Wire `basou verify` onto `program`. */\nexport function registerVerifyCommand(program: Command): void {\n program\n .command(\"verify\")\n .description(\"Verify the tamper-evidence hash chain of sessions' event logs (read-only)\")\n .option(\"--session <id>\", \"Verify a single session (unique id prefix accepted)\")\n .option(\"--all\", \"Verify every session (the default when --session is omitted)\")\n .option(\"--json\", \"Output the verdicts as JSON\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (opts: VerifyOptions) => {\n await runVerify(opts);\n });\n}\n\nexport async function runVerify(options: VerifyOptions, ctx: VerifyContext = {}): Promise<void> {\n try {\n await doRunVerify(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\nasync function doRunVerify(options: VerifyOptions, ctx: VerifyContext): Promise<void> {\n if (options.session !== undefined && options.all === true) {\n throw new Error(\"Specify either --session <id> or --all, not both\");\n }\n\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForVerify(cwd);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const sessionIds =\n options.session !== undefined\n ? [await resolveSessionId(paths, options.session)]\n : await enumerateSessionDirs(paths);\n\n const rows: VerifyRow[] = [];\n for (const sessionId of sessionIds) {\n const verdict = await verifyEventsChain(paths, sessionId);\n rows.push({\n session_id: sessionId,\n status: verdict.status,\n event_count: verdict.eventCount,\n ...(verdict.reason !== undefined ? { reason: verdict.reason } : {}),\n ...(verdict.line !== undefined ? { line: verdict.line } : {}),\n });\n }\n\n const tamperedCount = rows.filter((r) => r.status === \"tampered\").length;\n\n if (options.json === true) {\n console.log(JSON.stringify(rows, null, 2));\n } else {\n for (const row of rows) {\n console.log(`${row.session_id} ${renderVerdict(row)}`);\n }\n const tally = (status: VerifyRow[\"status\"]): number =>\n rows.filter((r) => r.status === status).length;\n console.log(\n `Sessions: ${rows.length} total — ${tally(\"verified\")} verified, ` +\n `${tally(\"unchained\")} unchained, ${tally(\"empty\")} empty, ` +\n `${tally(\"incomplete\")} incomplete, ${tally(\"in_progress\")} in_progress, ` +\n `${tamperedCount} tampered`,\n );\n }\n\n // Only a real integrity break fails the command; unchained / empty /\n // incomplete / in_progress are informational states.\n if (tamperedCount > 0) {\n process.exitCode = 1;\n }\n}\n\nfunction renderVerdict(row: VerifyRow): string {\n switch (row.status) {\n case \"verified\":\n return `verified (${row.event_count} events)`;\n case \"tampered\":\n return row.line !== undefined\n ? `TAMPERED (${row.reason} at line ${row.line})`\n : `TAMPERED (${row.reason})`;\n case \"incomplete\":\n return \"incomplete (session.yaml missing; re-import to repair)\";\n case \"in_progress\":\n return `in_progress (${row.event_count} events; live session, anchor written at finalize)`;\n case \"unchained\":\n return \"unchained (session created before event-log chaining)\";\n case \"empty\":\n return \"empty\";\n }\n}\n\nasync function resolveRepositoryRootForVerify(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\"Not a git repository. Run 'git init' first, then re-run 'basou verify'.\", {\n cause: error,\n });\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n","import { spawn } from \"node:child_process\";\nimport { assertBasouRootSafe, basouPaths, findErrorCode, resolveRepositoryRoot } from \"@basou/core\";\nimport { type Command, InvalidArgumentError } from \"commander\";\nimport { isVerbose, renderCliError } from \"../lib/error-render.js\";\nimport { startViewServer, type ViewServerDeps, type ViewServerHandle } from \"../lib/view-server.js\";\n\nconst DEFAULT_PORT = 4319;\n\nexport type ViewOptions = {\n port?: number;\n open?: boolean;\n verbose?: boolean;\n};\n\nexport type ViewContext = {\n /** Defaults to `process.cwd()`. Injectable for tests. */\n cwd?: string;\n /** Defaults to `() => new Date()`. Injectable for tests. */\n nowProvider?: () => Date;\n /** Override the `~/.claude/projects` root used by imports. */\n claudeProjectsDir?: string;\n /** Override the `~/.codex/sessions` root used by imports. */\n codexSessionsDir?: string;\n /** Override how the browser is opened (tests pass a no-op). */\n openBrowser?: (url: string) => void;\n /** Resolves the keep-alive wait, so tests can stop the server without a signal. */\n signal?: AbortSignal;\n /** Called once the server is listening, with its handle (for tests). */\n onListening?: (handle: ViewServerHandle) => void;\n};\n\nfunction parsePort(value: string): number {\n const port = Number.parseInt(value, 10);\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new InvalidArgumentError(\"Port must be an integer between 1 and 65535.\");\n }\n return port;\n}\n\n/**\n * Wire `basou view` onto `program`. Starts a localhost-only web UI for\n * browsing provenance and running imports / regeneration by clicking.\n */\nexport function registerViewCommand(program: Command): void {\n program\n .command(\"view\")\n .description(\"Open a local web UI to browse provenance and run imports (localhost only)\")\n .option(\"--port <number>\", \"Port to listen on (default 4319)\", parsePort)\n .option(\"--no-open\", \"Do not open the browser automatically\")\n .option(\"-v, --verbose\", \"Show error causes\")\n .action(async (options: ViewOptions) => {\n await runView(options);\n });\n}\n\n/** Programmatic entry that owns `process.exitCode`. Tests prefer {@link doRunView}. */\nexport async function runView(options: ViewOptions, ctx: ViewContext = {}): Promise<void> {\n try {\n await doRunView(options, ctx);\n } catch (error: unknown) {\n renderCliError(error, { verbose: isVerbose(options) });\n process.exitCode = 1;\n }\n}\n\n/**\n * Pure runner: resolve the workspace, start the server, open the browser, and\n * keep running until SIGINT / SIGTERM (or an injected abort signal). The\n * server is always closed on the way out.\n */\nexport async function doRunView(options: ViewOptions, ctx: ViewContext): Promise<void> {\n const cwd = ctx.cwd ?? process.cwd();\n const repositoryRoot = await resolveRepositoryRootForView(cwd);\n const paths = basouPaths(repositoryRoot);\n await assertWorkspaceInitialized(paths.root);\n\n const deps: ViewServerDeps = {\n paths,\n repoRoot: repositoryRoot,\n importCtx: {\n cwd: repositoryRoot,\n ...(ctx.claudeProjectsDir !== undefined ? { claudeProjectsDir: ctx.claudeProjectsDir } : {}),\n ...(ctx.codexSessionsDir !== undefined ? { codexSessionsDir: ctx.codexSessionsDir } : {}),\n },\n nowProvider: ctx.nowProvider ?? (() => new Date()),\n };\n\n const port = options.port ?? DEFAULT_PORT;\n const handle = await startListening(port, deps);\n\n // Everything past listen runs under try/finally so a throw from the browser\n // launch or the onListening callback still closes the server.\n try {\n console.log(`basou view running at ${handle.url}`);\n console.log(\n \"Localhost only, no authentication. Do not expose this port beyond your machine. Press Ctrl+C to stop.\",\n );\n\n if (options.open !== false) {\n openInBrowser(handle.url, ctx.openBrowser);\n }\n ctx.onListening?.(handle);\n\n await waitForShutdown(ctx.signal);\n } finally {\n await handle.close();\n }\n}\n\nasync function startListening(port: number, deps: ViewServerDeps): Promise<ViewServerHandle> {\n try {\n return await startViewServer({ port, deps });\n } catch (error: unknown) {\n if (findErrorCode(error, \"EADDRINUSE\")) {\n throw new Error(`Port ${port} is already in use. Pass --port <n> to choose another.`, {\n cause: error,\n });\n }\n throw error;\n }\n}\n\nfunction openInBrowser(url: string, override?: (url: string) => void): void {\n if (override !== undefined) {\n override(url);\n return;\n }\n if (process.platform !== \"darwin\") return; // print-only elsewhere\n try {\n const child = spawn(\"open\", [url], { stdio: \"ignore\", detached: true });\n child.on(\"error\", () => {}); // browser launch is best-effort\n child.unref();\n } catch {\n // ignore: the URL is already printed\n }\n}\n\n/** Resolve once the process is asked to stop (signal) or the injected abort fires. */\nfunction waitForShutdown(signal: AbortSignal | undefined): Promise<void> {\n return new Promise((resolve) => {\n const cleanup = (): void => {\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n signal?.removeEventListener(\"abort\", onAbort);\n };\n const onSignal = (): void => {\n cleanup();\n resolve();\n };\n const onAbort = (): void => {\n cleanup();\n resolve();\n };\n process.on(\"SIGINT\", onSignal);\n process.on(\"SIGTERM\", onSignal);\n if (signal !== undefined) {\n if (signal.aborted) {\n cleanup();\n resolve();\n return;\n }\n signal.addEventListener(\"abort\", onAbort);\n }\n });\n}\n\nasync function resolveRepositoryRootForView(cwd: string): Promise<string> {\n try {\n return await resolveRepositoryRoot(cwd);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Not a git repository\") {\n throw new Error(\"Not a git repository. Run 'git init' first, then re-run 'basou view'.\", {\n cause: error,\n });\n }\n throw error;\n }\n}\n\nasync function assertWorkspaceInitialized(basouRoot: string): Promise<void> {\n try {\n await assertBasouRootSafe(basouRoot);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n throw new Error(\"Workspace not initialized. Run 'basou init' first.\");\n }\n throw error;\n }\n}\n","import { createServer, type IncomingMessage, type Server, type ServerResponse } from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\nimport { join } from \"node:path\";\nimport {\n type BasouPaths,\n computeWorkStats,\n enumerateApprovals,\n findErrorCode,\n isLazyExpired,\n loadApproval,\n loadSessionEntries,\n loadTaskEntries,\n type Manifest,\n readAllEvents,\n readManifest,\n readMarkdownFile,\n readSessionYaml,\n readTaskFile,\n renderDecisions,\n renderHandoff,\n} from \"@basou/core\";\nimport type { ImportContext } from \"../commands/import.js\";\nimport {\n importClaudeCode,\n importCodex,\n type RefreshActionOptions,\n refreshAll,\n regenerateDecisions,\n regenerateHandoff,\n} from \"./provenance-actions.js\";\nimport { VIEW_HTML } from \"./view-ui.js\";\n\n/** Everything the request handlers need; resolved once when the server starts. */\nexport type ViewServerDeps = {\n paths: BasouPaths;\n repoRoot: string;\n importCtx: ImportContext;\n nowProvider: () => Date;\n};\n\n/** A running view server, with the means to stop it. */\nexport type ViewServerHandle = {\n url: string;\n port: number;\n close: () => Promise<void>;\n};\n\n/** A handler-level failure that maps to a specific HTTP status (vs a 500). */\nclass HttpError extends Error {\n constructor(\n readonly status: number,\n message: string,\n ) {\n super(message);\n }\n}\n\nconst MAX_BODY_BYTES = 64 * 1024;\n\n/**\n * Start a localhost-only provenance viewer. Binds 127.0.0.1, serves a single\n * inline HTML page at `/` and a small JSON API under `/api/*`. Resolves once\n * listening (rejects on a bind error such as EADDRINUSE).\n */\nexport function startViewServer(opts: {\n port: number;\n host?: string;\n deps: ViewServerDeps;\n}): Promise<ViewServerHandle> {\n const { port, host = \"127.0.0.1\", deps } = opts;\n // Mutating POSTs swap process-global console (import capture); serialize them\n // so concurrent requests from a reloaded tab never interleave.\n let actionQueue: Promise<unknown> = Promise.resolve();\n const runExclusive = <T>(fn: () => Promise<T>): Promise<T> => {\n const result = actionQueue.then(fn, fn);\n actionQueue = result.then(\n () => undefined,\n () => undefined,\n );\n return result;\n };\n\n let boundPort = port;\n const getPort = (): number => boundPort;\n\n return new Promise((resolve, reject) => {\n const server = createServer((req, res) => {\n handleRequest(req, res, deps, getPort, runExclusive).catch((error: unknown) => {\n sendError(res, error instanceof HttpError ? error.status : 500, pathlessMessage(error));\n });\n });\n server.on(\"error\", reject);\n server.listen(port, host, () => {\n const address = server.address();\n boundPort = isAddressInfo(address) ? address.port : port;\n server.off(\"error\", reject);\n resolve({\n url: `http://${host}:${boundPort}`,\n port: boundPort,\n close: () => closeServer(server),\n });\n });\n });\n}\n\nfunction isAddressInfo(value: string | AddressInfo | null): value is AddressInfo {\n return value !== null && typeof value === \"object\";\n}\n\nfunction closeServer(server: Server): Promise<void> {\n return new Promise((resolve) => {\n server.close(() => resolve());\n // Force-terminate any in-flight connection (e.g. a client holding a POST\n // body open) so close() resolves promptly instead of hanging shutdown.\n server.closeAllConnections();\n });\n}\n\nasync function handleRequest(\n req: IncomingMessage,\n res: ServerResponse,\n deps: ViewServerDeps,\n getPort: () => number,\n runExclusive: <T>(fn: () => Promise<T>) => Promise<T>,\n): Promise<void> {\n const method = req.method ?? \"GET\";\n const url = new URL(req.url ?? \"/\", \"http://localhost\");\n const pathname = url.pathname;\n\n if (!hostAllowed(req, getPort())) {\n sendError(res, 403, \"Forbidden: host not allowed\");\n return;\n }\n\n if (method === \"GET\") {\n await handleGet(res, pathname, deps);\n return;\n }\n if (method === \"POST\") {\n if (!originAllowed(req, getPort())) {\n sendError(res, 403, \"Forbidden: cross-origin request\");\n return;\n }\n const body = await readBody(req);\n await handlePost(res, pathname, body, deps, runExclusive);\n return;\n }\n sendError(res, 405, \"Method not allowed\");\n}\n\nasync function handleGet(\n res: ServerResponse,\n pathname: string,\n deps: ViewServerDeps,\n): Promise<void> {\n if (pathname === \"/\") {\n sendHtml(res, VIEW_HTML);\n return;\n }\n if (pathname === \"/api/overview\") {\n sendJson(res, 200, await overview(deps));\n return;\n }\n if (pathname === \"/api/sessions\") {\n sendJson(res, 200, await sessionsList(deps));\n return;\n }\n const sessionId = matchId(pathname, \"/api/sessions/\");\n if (sessionId !== null) {\n sendJson(res, 200, await sessionDetail(deps, sessionId));\n return;\n }\n if (pathname === \"/api/tasks\") {\n sendJson(res, 200, await tasksList(deps));\n return;\n }\n const taskId = matchId(pathname, \"/api/tasks/\");\n if (taskId !== null) {\n sendJson(res, 200, await taskDetail(deps, taskId));\n return;\n }\n if (pathname === \"/api/decisions\") {\n sendJson(res, 200, await decisionsView(deps));\n return;\n }\n if (pathname === \"/api/approvals\") {\n sendJson(res, 200, await approvalsView(deps));\n return;\n }\n if (pathname === \"/api/handoff\") {\n sendJson(res, 200, await handoffView(deps));\n return;\n }\n if (pathname === \"/api/stats\") {\n sendJson(res, 200, await computeWorkStats({ paths: deps.paths, now: deps.nowProvider() }));\n return;\n }\n sendError(res, 404, \"Not found\");\n}\n\nasync function handlePost(\n res: ServerResponse,\n pathname: string,\n body: Record<string, unknown>,\n deps: ViewServerDeps,\n runExclusive: <T>(fn: () => Promise<T>) => Promise<T>,\n): Promise<void> {\n const nowIso = deps.nowProvider().toISOString();\n const actionOptions = readActionOptions(body);\n\n if (pathname === \"/api/refresh\") {\n const result = await runExclusive(() =>\n refreshAll({ options: actionOptions, ctx: deps.importCtx, paths: deps.paths, nowIso }),\n );\n sendJson(res, 200, result);\n return;\n }\n if (pathname === \"/api/import/claude-code\") {\n sendJson(res, 200, await runExclusive(() => importClaudeCode(actionOptions, deps.importCtx)));\n return;\n }\n if (pathname === \"/api/import/codex\") {\n sendJson(res, 200, await runExclusive(() => importCodex(actionOptions, deps.importCtx)));\n return;\n }\n if (pathname === \"/api/handoff/generate\") {\n sendJson(res, 200, await runExclusive(() => regenerateHandoff(deps.paths, nowIso)));\n return;\n }\n if (pathname === \"/api/decisions/generate\") {\n sendJson(res, 200, await runExclusive(() => regenerateDecisions(deps.paths, nowIso)));\n return;\n }\n sendError(res, 404, \"Not found\");\n}\n\n// --- handlers -------------------------------------------------------------\n\nasync function overview(deps: ViewServerDeps): Promise<Record<string, unknown>> {\n let manifest: Manifest;\n try {\n manifest = await readManifest(deps.paths);\n } catch (error: unknown) {\n if (findErrorCode(error, \"ENOENT\")) {\n return { initialized: false, repoRoot: deps.repoRoot };\n }\n throw error;\n }\n const nowIso = deps.nowProvider().toISOString();\n const handoff = await renderHandoff({ paths: deps.paths, nowIso });\n const approvals = await enumerateApprovals(deps.paths);\n return {\n initialized: true,\n repoRoot: deps.repoRoot,\n workspace: {\n id: manifest.workspace.id,\n name: manifest.workspace.name,\n basouVersion: manifest.basou_version,\n },\n counts: {\n sessions: handoff.sessionCount,\n suspectSessions: handoff.suspectCount,\n tasks: handoff.taskCount,\n pendingTasks: handoff.pendingTaskCount,\n decisions: handoff.decisionCount,\n approvalsPending: approvals.pending.length,\n approvalsResolved: approvals.resolved.length,\n },\n generatedAt: nowIso,\n };\n}\n\nasync function sessionsList(deps: ViewServerDeps): Promise<Record<string, unknown>> {\n const entries = await loadSessionEntries(deps.paths, { now: deps.nowProvider() });\n // loadSessionEntries returns oldest-first; show newest-first.\n const sessions = entries\n .map((entry) => ({\n sessionId: entry.sessionId,\n label: entry.session.session.label ?? null,\n status: entry.session.session.status,\n sourceKind: entry.session.session.source.kind,\n startedAt: entry.session.session.started_at,\n endedAt: entry.session.session.ended_at ?? null,\n suspect: entry.suspect,\n suspectReason: entry.suspectReason,\n taskId: entry.session.session.task_id ?? null,\n relatedFilesCount: entry.session.session.related_files.length,\n }))\n .reverse();\n return { sessions };\n}\n\nasync function sessionDetail(\n deps: ViewServerDeps,\n sessionId: string,\n): Promise<Record<string, unknown>> {\n let session: Awaited<ReturnType<typeof readSessionYaml>>;\n try {\n session = await readSessionYaml(deps.paths, sessionId);\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"YAML file not found\") {\n throw new HttpError(404, \"Session not found\");\n }\n throw error;\n }\n // An unreadable events.jsonl must not 500 the detail view; surface the\n // session with an empty, flagged-degraded timeline (mirrors the list path).\n try {\n const events = await readAllEvents(join(deps.paths.sessions, sessionId));\n return { session, events };\n } catch {\n return { session, events: [], degraded: true };\n }\n}\n\nasync function tasksList(deps: ViewServerDeps): Promise<Record<string, unknown>> {\n const entries = await loadTaskEntries(deps.paths);\n return { tasks: entries.map((entry) => entry.task).reverse() };\n}\n\nasync function taskDetail(deps: ViewServerDeps, taskId: string): Promise<Record<string, unknown>> {\n try {\n const doc = await readTaskFile(deps.paths, taskId);\n return { task: doc.task, body: doc.body };\n } catch (error: unknown) {\n if (error instanceof Error && error.message === \"Task file not found\") {\n throw new HttpError(404, \"Task not found\");\n }\n throw error;\n }\n}\n\nasync function decisionsView(deps: ViewServerDeps): Promise<Record<string, unknown>> {\n // Prefer the on-disk decisions.md so hand-edited content (outside the\n // generated markers) is shown, mirroring the handoff view; fall back to a\n // fresh render when the file does not exist yet.\n const fromDisk = await readMarkdownFile(deps.paths.files.decisions);\n if (fromDisk !== null) {\n return { body: fromDisk, fromDisk: true };\n }\n const nowIso = deps.nowProvider().toISOString();\n const result = await renderDecisions({ paths: deps.paths, nowIso });\n return { body: result.body, decisionCount: result.decisionCount, fromDisk: false };\n}\n\nasync function approvalsView(deps: ViewServerDeps): Promise<Record<string, unknown>> {\n const now = deps.nowProvider();\n const ids = await enumerateApprovals(deps.paths);\n const toViews = async (list: string[]): Promise<Array<Record<string, unknown>>> => {\n const views: Array<Record<string, unknown>> = [];\n for (const id of list) {\n const loaded = await loadApproval(deps.paths, id);\n if (loaded === null) continue;\n views.push({ id, expired: isLazyExpired(loaded.approval, now), approval: loaded.approval });\n }\n return views;\n };\n return { pending: await toViews(ids.pending), resolved: await toViews(ids.resolved) };\n}\n\nasync function handoffView(deps: ViewServerDeps): Promise<Record<string, unknown>> {\n const fromDisk = await readMarkdownFile(deps.paths.files.handoff);\n if (fromDisk !== null) {\n return { body: fromDisk, fromDisk: true };\n }\n const nowIso = deps.nowProvider().toISOString();\n const result = await renderHandoff({ paths: deps.paths, nowIso });\n return { body: result.body, fromDisk: false };\n}\n\n// --- request helpers ------------------------------------------------------\n\nfunction readActionOptions(body: Record<string, unknown>): RefreshActionOptions {\n const options: RefreshActionOptions = {};\n // Accept `project` as a single string (the UI sends one) or an array of\n // strings (multi-root callers); normalize to a non-empty string[].\n const project = normalizeProject(body.project);\n if (project.length > 0) options.project = project;\n if (body.force === true) options.force = true;\n if (body.dryRun === true) options.dryRun = true;\n return options;\n}\n\n/** Coerce a request body `project` field into a list of non-empty path strings. */\nfunction normalizeProject(value: unknown): string[] {\n const raw = Array.isArray(value) ? value : [value];\n return raw.filter((p): p is string => typeof p === \"string\" && p.length > 0);\n}\n\nfunction hostAllowed(req: IncomingMessage, port: number): boolean {\n const host = req.headers.host;\n return host === `127.0.0.1:${port}` || host === `localhost:${port}`;\n}\n\nfunction originAllowed(req: IncomingMessage, port: number): boolean {\n const origin = req.headers.origin;\n if (origin === undefined) return true; // non-browser client (curl, tests)\n return origin === `http://127.0.0.1:${port}` || origin === `http://localhost:${port}`;\n}\n\nasync function readBody(req: IncomingMessage): Promise<Record<string, unknown>> {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of req) {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));\n size += buf.length;\n if (size > MAX_BODY_BYTES) throw new HttpError(413, \"Request body too large\");\n chunks.push(buf);\n }\n const raw = Buffer.concat(chunks).toString(\"utf8\").trim();\n if (raw.length === 0) return {};\n try {\n const parsed: unknown = JSON.parse(raw);\n if (parsed !== null && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n } catch {\n // fall through to the shared 400 below\n }\n throw new HttpError(400, \"Invalid JSON body\");\n}\n\nfunction matchId(pathname: string, prefix: string): string | null {\n if (!pathname.startsWith(prefix)) return null;\n const encoded = pathname.slice(prefix.length);\n if (encoded.length === 0 || encoded.includes(\"/\")) return null;\n let id: string;\n try {\n id = decodeURIComponent(encoded);\n } catch {\n return null; // malformed percent-escape\n }\n // Reject anything that could escape the storage root once decoded: a path\n // separator (incl. the percent-encoded `%2f` that slips past the check\n // above) or a `.`/`..` segment. Ids are otherwise opaque to this layer.\n if (\n id.length === 0 ||\n id.includes(\"/\") ||\n id.includes(\"\\\\\") ||\n id.includes(\"\\0\") ||\n id === \".\" ||\n id === \"..\"\n ) {\n return null;\n }\n return id;\n}\n\nfunction sendJson(res: ServerResponse, status: number, data: unknown): void {\n const body = JSON.stringify(data);\n res.writeHead(status, {\n \"Content-Type\": \"application/json; charset=utf-8\",\n \"Cache-Control\": \"no-store\",\n });\n res.end(body);\n}\n\nfunction sendHtml(res: ServerResponse, html: string): void {\n res.writeHead(200, {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"no-store\",\n });\n res.end(html);\n}\n\nfunction sendError(res: ServerResponse, status: number, message: string): void {\n if (res.headersSent) {\n res.end();\n return;\n }\n sendJson(res, status, { error: message });\n}\n\n/**\n * A pathless, audience-safe message: the Error's own message is already\n * pathless by the codebase's convention; native fs errors are wrapped before\n * they reach here. Falls back to a generic string for non-Error throws.\n */\nfunction pathlessMessage(error: unknown): string {\n return error instanceof Error ? error.message : \"Internal error\";\n}\n","/**\n * The single-page UI for `basou view`, served verbatim at `GET /`. Kept as one\n * inline string so the CLI build needs no asset pipeline. All data is rendered\n * with createElement / textContent (never innerHTML), so session, task, and\n * command content cannot inject markup. The embedded script deliberately uses\n * no template literals (this file is itself a template literal).\n */\nexport const VIEW_HTML = `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<title>basou view</title>\n<style>\n :root { color-scheme: light dark; }\n * { box-sizing: border-box; }\n body { margin: 0; font: 14px/1.5 system-ui, -apple-system, Segoe UI, sans-serif; }\n header { padding: 10px 16px; border-bottom: 1px solid #8884; display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center; }\n header h1 { font-size: 15px; margin: 0 12px 0 0; font-weight: 700; }\n header .grow { flex: 1; }\n input[type=text] { padding: 4px 8px; border: 1px solid #8886; border-radius: 6px; min-width: 280px; font: inherit; }\n button { padding: 4px 10px; border: 1px solid #8886; border-radius: 6px; background: #8881; cursor: pointer; font: inherit; }\n button.primary { background: #2563eb; color: #fff; border-color: #2563eb; }\n button:disabled { opacity: .5; cursor: default; }\n label.chk { font-size: 13px; opacity: .85; }\n #status { padding: 6px 16px; font-size: 13px; min-height: 20px; border-bottom: 1px solid #8884; white-space: pre-wrap; }\n #status.err { color: #dc2626; }\n nav { display: flex; gap: 2px; padding: 6px 12px; border-bottom: 1px solid #8884; flex-wrap: wrap; }\n nav button { border: none; border-radius: 6px; background: transparent; }\n nav button.active { background: #2563eb22; font-weight: 600; }\n main { display: grid; grid-template-columns: minmax(220px, 320px) 1fr; min-height: 60vh; }\n main.single { grid-template-columns: 1fr; }\n #list { border-right: 1px solid #8884; overflow: auto; max-height: 80vh; }\n #list .row { padding: 8px 12px; border-bottom: 1px solid #8883; cursor: pointer; }\n #list .row:hover { background: #8881; }\n #list .row.active { background: #2563eb22; }\n #list .row .meta { font-size: 12px; opacity: .7; }\n #detail { padding: 12px 16px; overflow: auto; max-height: 80vh; }\n .badge { display: inline-block; padding: 0 6px; border-radius: 6px; background: #8882; font-size: 12px; }\n .badge.warn { background: #f59e0b33; }\n pre { background: #8881; padding: 12px; border-radius: 8px; overflow: auto; white-space: pre-wrap; word-break: break-word; }\n table.kv { border-collapse: collapse; }\n table.kv td { padding: 2px 10px 2px 0; vertical-align: top; }\n table.kv td.k { opacity: .7; }\n .cards { display: flex; flex-wrap: wrap; gap: 10px; }\n .card { border: 1px solid #8884; border-radius: 8px; padding: 10px 14px; min-width: 120px; }\n .card .n { font-size: 22px; font-weight: 700; }\n .card .l { font-size: 12px; opacity: .7; }\n .tl { border-left: 2px solid #8885; margin-left: 6px; padding-left: 12px; }\n .tl .ev { margin-bottom: 8px; }\n .tl .ev .t { font-size: 12px; opacity: .65; }\n .muted { opacity: .6; }\n</style>\n</head>\n<body>\n<header>\n <h1>basou view</h1>\n <input type=\"text\" id=\"project\" placeholder=\"source root (optional override)\" />\n <button class=\"primary\" id=\"btn-refresh\">Refresh all</button>\n <button id=\"btn-import-claude\">Import claude-code</button>\n <button id=\"btn-import-codex\">Import codex</button>\n <button id=\"btn-gen-handoff\">Regenerate handoff</button>\n <button id=\"btn-gen-decisions\">Regenerate decisions</button>\n <span class=\"grow\"></span>\n <label class=\"chk\"><input type=\"checkbox\" id=\"opt-force\" /> force</label>\n <label class=\"chk\"><input type=\"checkbox\" id=\"opt-dry\" /> dry-run</label>\n</header>\n<div id=\"status\"></div>\n<nav id=\"tabs\"></nav>\n<main id=\"main\">\n <div id=\"list\"></div>\n <div id=\"detail\"></div>\n</main>\n<script>\n(function () {\n var TABS = ['overview', 'stats', 'sessions', 'tasks', 'decisions', 'approvals', 'handoff'];\n var state = { tab: 'overview', repoRoot: '' };\n\n function $(id) { return document.getElementById(id); }\n function clear(node) { while (node.firstChild) node.removeChild(node.firstChild); }\n\n function el(tag, attrs, children) {\n var node = document.createElement(tag);\n if (attrs) {\n for (var k in attrs) {\n if (!Object.prototype.hasOwnProperty.call(attrs, k)) continue;\n if (k === 'class') node.className = attrs[k];\n else if (k === 'text') node.textContent = attrs[k];\n else if (k.slice(0, 2) === 'on') node.addEventListener(k.slice(2), attrs[k]);\n else node.setAttribute(k, attrs[k]);\n }\n }\n if (children) {\n for (var i = 0; i < children.length; i++) {\n var c = children[i];\n if (c === null || c === undefined) continue;\n node.appendChild(typeof c === 'string' ? document.createTextNode(c) : c);\n }\n }\n return node;\n }\n\n function setStatus(msg, isErr) {\n var s = $('status');\n s.textContent = msg || '';\n s.className = isErr ? 'err' : '';\n }\n\n function fetchJson(path, opts) {\n return fetch(path, opts).then(function (res) {\n return res.text().then(function (text) {\n var data = null;\n try { data = text ? JSON.parse(text) : null; } catch (e) { data = null; }\n if (!res.ok) {\n var m = data && data.error ? data.error : ('HTTP ' + res.status);\n throw new Error(m);\n }\n return data;\n });\n });\n }\n\n function single(on) { $('main').className = on ? 'single' : ''; if (on) clear($('list')); }\n\n // --- action bar ---------------------------------------------------------\n\n function actionBody() {\n var body = {};\n var project = $('project').value.trim();\n if (project) body.project = project;\n if ($('opt-force').checked) body.force = true;\n if ($('opt-dry').checked) body.dryRun = true;\n return body;\n }\n\n function setBusy(busy) {\n var ids = ['btn-refresh', 'btn-import-claude', 'btn-import-codex', 'btn-gen-handoff', 'btn-gen-decisions'];\n for (var i = 0; i < ids.length; i++) $(ids[i]).disabled = busy;\n }\n\n function post(path, label) {\n setBusy(true);\n setStatus(label + '...', false);\n fetchJson(path, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(actionBody())\n }).then(function (data) {\n setStatus(label + ' done: ' + summarize(data), false);\n loadTab(state.tab);\n }).catch(function (err) {\n setStatus(label + ' failed: ' + err.message, true);\n }).then(function () { setBusy(false); });\n }\n\n function summarize(data) {\n if (!data) return 'ok';\n if (data.claudeCode || data.codex) {\n return 'claude-code ' + imp(data.claudeCode) + ', codex ' + imp(data.codex)\n + (data.handoff && data.handoff.status === 'generated' ? '; handoff+decisions regenerated' : '');\n }\n if (data.status === 'ran') return imp(data);\n if (data.status === 'skipped') return 'skipped (' + data.reason + ')';\n if (typeof data.sessionCount === 'number') return 'sessions ' + data.sessionCount + ', decisions ' + data.decisionCount;\n if (typeof data.decisionCount === 'number') return 'decisions ' + data.decisionCount;\n return 'ok';\n }\n function imp(o) {\n if (!o) return '-';\n if (o.status === 'skipped') return 'skipped';\n return (o.dryRun ? 'would import ' : 'imported ') + o.importedCount + ' (' + o.eventTotal + ' events)';\n }\n\n // --- tabs ---------------------------------------------------------------\n\n function buildTabs() {\n var nav = $('tabs');\n clear(nav);\n TABS.forEach(function (name) {\n nav.appendChild(el('button', {\n class: name === state.tab ? 'active' : '',\n text: name,\n onclick: function () { loadTab(name); }\n }));\n });\n }\n\n function loadTab(name) {\n state.tab = name;\n buildTabs();\n clear($('detail'));\n clear($('list'));\n if (name === 'overview') return loadOverview();\n if (name === 'stats') return loadStats();\n if (name === 'sessions') return loadSessions();\n if (name === 'tasks') return loadTasks();\n if (name === 'decisions') return loadMarkdown('/api/decisions', 'decisions');\n if (name === 'approvals') return loadApprovals();\n if (name === 'handoff') return loadMarkdown('/api/handoff', 'handoff');\n }\n\n function fail(err) { setStatus(err.message, true); }\n\n function loadOverview() {\n single(true);\n fetchJson('/api/overview').then(function (d) {\n var detail = $('detail');\n if (!d || d.initialized === false) {\n detail.appendChild(el('p', { class: 'muted', text: 'Workspace not initialized.' }));\n return;\n }\n // Leave the project field empty by default so refresh / import use the\n // manifest's import.source_roots (then the repo root) -- pre-filling the\n // repo root here would send it as an explicit --project and silently\n // override multi-root source roots. The field is an optional override.\n state.repoRoot = d.repoRoot || '';\n detail.appendChild(el('p', {}, [\n el('strong', { text: d.workspace.name }), ' ',\n el('span', { class: 'muted', text: d.workspace.id })\n ]));\n var c = d.counts;\n var cards = el('div', { class: 'cards' }, [\n card(c.sessions, 'sessions'),\n card(c.suspectSessions, 'suspect'),\n card(c.tasks, 'tasks'),\n card(c.pendingTasks, 'pending tasks'),\n card(c.decisions, 'decisions'),\n card(c.approvalsPending, 'approvals pending')\n ]);\n detail.appendChild(cards);\n detail.appendChild(el('p', { class: 'muted', text: 'repo: ' + d.repoRoot }));\n }).catch(fail);\n }\n function card(n, label) {\n return el('div', { class: 'card' }, [\n el('div', { class: 'n', text: String(n) }),\n el('div', { class: 'l', text: label })\n ]);\n }\n\n function numfmt(n) { return (n || 0).toLocaleString('en-US'); }\n function fmtDur(ms) {\n var s = Math.round((ms || 0) / 1000);\n var h = Math.floor(s / 3600), m = Math.floor((s % 3600) / 60), sec = s % 60;\n if (h > 0) return h + 'h ' + (m < 10 ? '0' : '') + m + 'm';\n if (m > 0) return m + 'm ' + (sec < 10 ? '0' : '') + sec + 's';\n return sec + 's';\n }\n function kvrow(k, v) {\n return el('tr', {}, [el('td', { class: 'k', text: k }), el('td', { text: v })]);\n }\n\n function loadStats() {\n single(true);\n fetchJson('/api/stats').then(function (d) {\n var detail = $('detail');\n var t = d.totals;\n detail.appendChild(el('p', { text: 'Sessions: ' + t.sessionCount }));\n detail.appendChild(el('h3', { text: 'Volume (what the AI produced)' }));\n detail.appendChild(el('div', { class: 'cards' }, [\n card(numfmt(t.tokens.output), 'output tokens'),\n (t.tokens.reasoning > 0 ? card(numfmt(t.tokens.reasoning), 'reasoning tokens') : null),\n card(t.commandCount, 'commands'),\n card(t.fileChangedCount, 'files'),\n card(t.decisionCount, 'decisions')\n ]));\n var sessions = d.sessions || [];\n var tokenSessions = sessions.filter(function (s) { return s.availability && s.availability.tokens; }).length;\n if (!t.tokensAvailable) {\n detail.appendChild(el('p', { class: 'muted', text: 'No token data captured; re-import to backfill.' }));\n } else if (tokenSessions < t.sessionCount) {\n detail.appendChild(el('p', { class: 'muted', text: 'Token data on ' + tokenSessions + ' of ' + t.sessionCount + ' sessions; re-import to backfill the rest.' }));\n }\n var degraded = sessions.filter(function (s) { return s.eventsUnreadable; }).length;\n if (degraded > 0) {\n detail.appendChild(el('p', { class: 'muted', text: degraded + ' session(s) had unreadable event logs; their counts are incomplete.' }));\n }\n detail.appendChild(el('h3', { text: 'Time (human harness labor; active = billing primary)' }));\n var turnSessions = sessions.filter(function (s) { return s.activeTimeBasis === 'engaged-turns'; }).length;\n var basisNote = turnSessions === t.sessionCount ? 'engaged turns' : (turnSessions === 0 ? 'event stream; re-import to capture conversation' : 'engaged turns on ' + turnSessions + ' of ' + t.sessionCount + ' sessions');\n var timeRows = [kvrow('billable active', fmtDur(t.billableActiveTimeMs) + ' (union; ' + basisNote + '; idle gaps > 5m excluded; tz ' + d.timeZone + ')')];\n if (t.activeTimeMs !== t.billableActiveTimeMs) {\n timeRows.push(kvrow('summed', fmtDur(t.activeTimeMs) + ' (concurrent sessions double-counted)'));\n }\n if (t.machineActiveAvailable) {\n var machineSessions = sessions.filter(function (s) { return s.availability && s.availability.machineActive; }).length;\n timeRows.push(kvrow('model working', fmtDur(t.machineActiveTimeMs) + ' (model compute, subset of active; Codex turn duration on ' + machineSessions + ' of ' + t.sessionCount + ' sessions; not wall-clock-deduped)'));\n }\n timeRows.push(kvrow('span', fmtDur(t.sessionSpanMs) + (t.openSessionCount > 0 ? ' (' + t.openSessionCount + ' open)' : '')));\n timeRows.push(kvrow('command', fmtDur(t.commandTimeMs) + (t.commandTimeReliable ? '' : ' (some sessions report 0)')));\n detail.appendChild(el('table', { class: 'kv' }, [el('tbody', {}, timeRows)]));\n if (d.bySource && d.bySource.length) {\n detail.appendChild(el('h3', { text: 'By source' }));\n d.bySource.forEach(function (s) {\n var cmd = s.commandTimeReliable ? fmtDur(s.commandTimeMs) : 'n/a';\n var machine = s.machineActiveAvailable ? ', model ' + fmtDur(s.machineActiveTimeMs) : '';\n detail.appendChild(el('div', { class: 'row' }, [\n el('span', { text: s.sourceKind + ': ' + s.sessionCount + ' sessions, ' + numfmt(s.tokens.output) + ' out tok, active ' + fmtDur(s.activeTimeMs) + machine + ', command ' + cmd })\n ]));\n });\n }\n if (d.byDay && d.byDay.length) {\n detail.appendChild(el('h3', { text: 'By day (billable time x volume)' }));\n d.byDay.forEach(function (day) {\n var dayMachine = day.machineActiveTimeMs > 0 ? ' (model ' + fmtDur(day.machineActiveTimeMs) + ')' : '';\n detail.appendChild(el('div', { class: 'row' }, [\n el('span', { text: day.date + ': ' + fmtDur(day.billableActiveTimeMs) + ' active' + dayMachine + ', ' + numfmt(day.tokens.output) + ' out tok, ' + day.commandCount + ' cmd / ' + day.fileChangedCount + ' files / ' + day.decisionCount + ' dec' })\n ]));\n });\n }\n }).catch(fail);\n }\n\n function loadSessions() {\n single(false);\n fetchJson('/api/sessions').then(function (d) {\n var list = $('list');\n var rows = (d && d.sessions) || [];\n if (rows.length === 0) { list.appendChild(el('div', { class: 'row muted', text: 'no sessions' })); return; }\n rows.forEach(function (s) {\n var row = el('div', { class: 'row', onclick: function () { selectSession(row, s.sessionId); } }, [\n el('div', { text: s.label || s.sessionId }),\n el('div', { class: 'meta', text: s.sourceKind + ' ' + s.status + (s.suspect ? ' suspect' : '') })\n ]);\n list.appendChild(row);\n });\n }).catch(fail);\n }\n function selectSession(row, id) {\n var rows = $('list').querySelectorAll('.row');\n for (var i = 0; i < rows.length; i++) rows[i].classList.remove('active');\n row.classList.add('active');\n var detail = $('detail');\n clear(detail);\n fetchJson('/api/sessions/' + encodeURIComponent(id)).then(function (d) {\n var s = d.session.session;\n detail.appendChild(el('h3', { text: s.label || id }));\n detail.appendChild(kv([\n ['status', s.status], ['source', s.source.kind], ['started', s.started_at],\n ['ended', s.ended_at || '-'], ['workdir', s.working_directory]\n ]));\n if (d.degraded) detail.appendChild(el('p', { class: 'badge warn', text: 'events unreadable' }));\n var events = d.events || [];\n detail.appendChild(el('p', { class: 'muted', text: events.length + ' events' }));\n var tl = el('div', { class: 'tl' }, []);\n events.forEach(function (ev) {\n tl.appendChild(el('div', { class: 'ev' }, [\n el('div', { class: 't', text: ev.occurred_at + ' ' + ev.type }),\n el('div', { text: eventSummary(ev) })\n ]));\n });\n detail.appendChild(tl);\n }).catch(fail);\n }\n function eventSummary(ev) {\n if (ev.type === 'command_executed') {\n var cmd = (ev.args && ev.args.length) ? ev.args.join(' ') : ev.command;\n var ex = (ev.exit_code === null || ev.exit_code === undefined) ? '' : ' (exit ' + ev.exit_code + ')';\n return cmd + ex;\n }\n if (ev.type === 'file_changed') return ev.path + ' [' + ev.change_type + ']';\n if (ev.type === 'decision_recorded') return ev.title || '';\n return '';\n }\n\n function loadTasks() {\n single(false);\n fetchJson('/api/tasks').then(function (d) {\n var list = $('list');\n var rows = (d && d.tasks) || [];\n if (rows.length === 0) { list.appendChild(el('div', { class: 'row muted', text: 'no tasks' })); return; }\n rows.forEach(function (t) {\n var row = el('div', { class: 'row', onclick: function () { selectTask(row, t.id); } }, [\n el('div', { text: t.title || t.label || t.id }),\n el('div', { class: 'meta', text: String(t.status || '') })\n ]);\n list.appendChild(row);\n });\n }).catch(fail);\n }\n function selectTask(row, id) {\n var rows = $('list').querySelectorAll('.row');\n for (var i = 0; i < rows.length; i++) rows[i].classList.remove('active');\n row.classList.add('active');\n var detail = $('detail');\n clear(detail);\n fetchJson('/api/tasks/' + encodeURIComponent(id)).then(function (d) {\n detail.appendChild(el('h3', { text: (d.task && (d.task.title || d.task.label)) || id }));\n detail.appendChild(el('pre', { text: JSON.stringify(d.task, null, 2) }));\n if (d.body) detail.appendChild(el('pre', { text: d.body }));\n }).catch(fail);\n }\n\n function loadMarkdown(path, label) {\n single(true);\n fetchJson(path).then(function (d) {\n var detail = $('detail');\n var count = (typeof d.decisionCount === 'number') ? (' (' + d.decisionCount + ' decisions)') : '';\n detail.appendChild(el('p', { class: 'muted', text: label + count }));\n detail.appendChild(el('pre', { text: (d && d.body) || '(empty)' }));\n }).catch(fail);\n }\n\n function loadApprovals() {\n single(true);\n fetchJson('/api/approvals').then(function (d) {\n var detail = $('detail');\n var groups = [['pending', d.pending || []], ['resolved', d.resolved || []]];\n groups.forEach(function (g) {\n detail.appendChild(el('h3', { text: g[0] + ' (' + g[1].length + ')' }));\n if (g[1].length === 0) { detail.appendChild(el('p', { class: 'muted', text: 'none' })); return; }\n g[1].forEach(function (a) {\n detail.appendChild(el('div', { class: 'row' }, [\n el('span', { text: a.id + ' ' }),\n el('span', { class: a.expired ? 'badge warn' : 'badge', text: a.expired ? 'expired' : (a.approval && a.approval.status) || '' })\n ]));\n });\n });\n }).catch(fail);\n }\n\n function kv(pairs) {\n var tbody = el('tbody', {}, pairs.map(function (p) {\n return el('tr', {}, [el('td', { class: 'k', text: p[0] }), el('td', { text: String(p[1]) })]);\n }));\n return el('table', { class: 'kv' }, [tbody]);\n }\n\n // --- wire up ------------------------------------------------------------\n\n $('btn-refresh').addEventListener('click', function () { post('/api/refresh', 'Refresh all'); });\n $('btn-import-claude').addEventListener('click', function () { post('/api/import/claude-code', 'Import claude-code'); });\n $('btn-import-codex').addEventListener('click', function () { post('/api/import/codex', 'Import codex'); });\n $('btn-gen-handoff').addEventListener('click', function () { post('/api/handoff/generate', 'Regenerate handoff'); });\n $('btn-gen-decisions').addEventListener('click', function () { post('/api/decisions/generate', 'Regenerate decisions'); });\n\n buildTabs();\n loadTab('overview');\n})();\n</script>\n</body>\n</html>`;\n","import { isVerbose, renderCliError } from \"./lib/error-render.js\";\nimport { buildProgram } from \"./program.js\";\n\n// Thin binary entry: construction lives in the side-effect-free ./program.ts\n// (so the docs generator can import `buildProgram` and introspect the command\n// surface without triggering a parse); this file owns the single argv parse.\nconst program = buildProgram();\n\nprogram.parseAsync(process.argv).catch((err: unknown) => {\n // Top-level safety net: never print the Error object directly because\n // Node's util.inspect recursively expands `error.cause`, which can carry\n // absolute paths from native fs errors. Delegates to the shared pathless\n // renderer; verbose mode is gated on BASOU_DEBUG only since the failure\n // bypassed the subcommand handler that owns the `-v` flag.\n renderCliError(err, { verbose: isVerbose(undefined) });\n process.exit(1);\n});\n"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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","names":["program","id","acquireLock","assertBasouRootSafe","basouPaths","findErrorCode","prefixedUlid","resolveRepositoryRoot","program","basouPaths","assertWorkspaceInitialized","prefixedUlid","acquireLock","resolveRepositoryRoot","assertBasouRootSafe","findErrorCode","assertBasouRootSafe","basouPaths","findErrorCode","resolveRepositoryRoot","program","basouPaths","assertWorkspaceInitialized","resolveRepositoryRoot","assertBasouRootSafe","findErrorCode","join","acquireLock","assertBasouRootSafe","basouPaths","prefixedUlid","readManifest","readYamlFile","resolveRepositoryRoot","program","basouPaths","assertBasouRootSafe","readManifest","prefixedUlid","join","acquireLock","readYamlFile","resolveRepositoryRoot","assertBasouRootSafe","basouPaths","findErrorCode","readMarkdownFile","renderWithMarkers","resolveRepositoryRoot","writeMarkdownFile","program","basouPaths","assertWorkspaceInitialized","readMarkdownFile","renderWithMarkers","writeMarkdownFile","resolveRepositoryRoot","assertBasouRootSafe","findErrorCode","homedir","join","assertBasouRootSafe","basouPaths","findErrorCode","readManifest","readSessionYaml","resolveRepositoryRoot","SES_PREFIX","SHORT_ID_LEN","program","join","homedir","basouPaths","assertWorkspaceInitialized","readManifest","payload","readSessionYaml","findErrorCode","shortId","resolveRepositoryRoot","assertBasouRootSafe","basename","resolve","resolveRepositoryRoot","program","basename","resolve","resolveRepositoryRoot","assertBasouRootSafe","basouPaths","findErrorCode","resolveRepositoryRoot","InvalidArgumentError","readMarkdownFile","renderDecisions","renderHandoff","renderWithMarkers","writeMarkdownFile","renderHandoff","readMarkdownFile","writeMarkdownFile","renderWithMarkers","renderDecisions","readdir","stat","homedir","join","findErrorCode","join","homedir","readdir","findErrorCode","stat","collectPath","InvalidArgumentError","resolve","program","basouPaths","assertWorkspaceInitialized","resolveRepositoryRoot","assertBasouRootSafe","findErrorCode","mkdir","homedir","join","acquireLock","assertBasouRootSafe","basouPaths","ChildProcessRunner","coreAppendChainedEvent","finalizeSessionYaml","getSnapshot","overwriteYamlFile","prefixedUlid","readManifest","readYamlFile","resolveRepositoryRoot","SessionSchema","sanitizeWorkingDirectory","writeYamlFile","program","ChildProcessRunner","basouPaths","assertBasouRootSafe","readManifest","prefixedUlid","join","mkdir","coreAppendChainedEvent","buildInitialSession","writeYamlFile","tryAppendGitSnapshot","acquireLock","mutateSessionYaml","finalizeSessionAsFailed","homedir","decideFinalStatus","finalizeSessionYaml","signalToExitCode","SIGNUM_MAP","getSnapshot","normalizeGitSnapshotSkipMessage","sanitizeWorkingDirectory","readYamlFile","SessionSchema","overwriteYamlFile","resolveRepositoryRoot","readFile","basename","join","relative","acquireLock","appendEventToExistingSession","assertBasouRootSafe","basouPaths","enumerateSessionDirs","findErrorCode","importSessionFromJson","readManifest","readYamlFile","resolveRepositoryRoot","resolveSessionId","SessionImportPayloadSchema","SessionSchema","InvalidArgumentError","SES_PREFIX","TASK_PREFIX","SHORT_ID_BASE_LEN","SHORT_ID_MAX_LEN","STATUS_VALUES","program","basouPaths","assertWorkspaceInitialized","resolveSessionId","join","readYamlFile","SessionSchema","findErrorCode","computeUniquePrefixLen","sliceShort","maxLen","pad","relative","shortTaskId","shortId","resolveRepositoryRoot","assertBasouRootSafe","readManifest","SessionImportPayloadSchema","importOptions","importSessionFromJson","readFile","InvalidArgumentError","basename","acquireLock","appendEventToExistingSession","enumerateSessionDirs","assertBasouRootSafe","basouPaths","findErrorCode","resolveRepositoryRoot","program","basouPaths","assertWorkspaceInitialized","resolveRepositoryRoot","assertBasouRootSafe","findErrorCode","assertBasouRootSafe","basouPaths","findErrorCode","readManifest","resolveRepositoryRoot","program","basouPaths","assertBasouRootSafe","findErrorCode","readManifest","resolveRepositoryRoot","readFile","join","assertBasouRootSafe","basouPaths","findErrorCode","loadSessionEntries","prefixedUlid","readManifest","replayEvents","resolveRepositoryRoot","resolveSessionId","resolveTaskId","InvalidArgumentError","STATUS_VALUES","program","parseTitle","parsePositiveInt","basouPaths","assertWorkspaceInitialized","prefixedUlid","resolveSessionId","result","readManifest","maxLen","pad","resolveTaskId","loadSessionEntries","join","replayEvents","createInterface","InvalidArgumentError","readFile","findErrorCode","resolveRepositoryRoot","assertBasouRootSafe","assertBasouRootSafe","basouPaths","enumerateSessionDirs","findErrorCode","resolveRepositoryRoot","resolveSessionId","program","basouPaths","assertWorkspaceInitialized","resolveSessionId","enumerateSessionDirs","resolveRepositoryRoot","assertBasouRootSafe","findErrorCode","assertBasouRootSafe","basouPaths","findErrorCode","resolveRepositoryRoot","InvalidArgumentError","join","computeWorkStats","enumerateApprovals","findErrorCode","isLazyExpired","loadApproval","loadSessionEntries","loadTaskEntries","readAllEvents","readManifest","readMarkdownFile","readSessionYaml","readTaskFile","renderDecisions","renderHandoff","resolve","computeWorkStats","readManifest","findErrorCode","renderHandoff","enumerateApprovals","loadSessionEntries","readSessionYaml","readAllEvents","join","loadTaskEntries","readTaskFile","readMarkdownFile","renderDecisions","loadApproval","isLazyExpired","InvalidArgumentError","program","basouPaths","assertWorkspaceInitialized","findErrorCode","resolve","resolveRepositoryRoot","assertBasouRootSafe","require","program"]}
|