@titan-design/active-work 0.2.0 → 0.4.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/README.md +2 -2
- package/dist/aw.js +75 -32
- package/dist/aw.js.map +1 -1
- package/dist/{chunk-FM2KVFDO.js → chunk-BK25ASXA.js} +393 -232
- package/dist/chunk-BK25ASXA.js.map +1 -0
- package/dist/cli.js +3581 -1333
- package/dist/cli.js.map +1 -1
- package/dist/dashboard/index.html +13 -5
- package/docs/cli-reference.md +1090 -0
- package/package.json +21 -2
- package/scripts/gen-cli-reference.mjs +23 -2
- package/dist/chunk-FM2KVFDO.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/paths.ts","../src/registry/index.ts","../src/registry/types.ts","../src/errors.ts","../src/launcher-args.ts","../src/commands/_open-helpers.ts","../src/schemas/brief.ts","../src/utils/registered-worktrees.ts","../src/schemas/artifacts.ts","../src/utils/yaml-io.ts","../src/utils/artifact-hash.ts","../src/utils/fs-atomic.ts","../src/utils/coerce-dates.ts","../src/bootstrap/prompt.ts","../src/schemas/task.ts","../src/sessions/open-loops.ts","../src/schemas/session.ts","../src/notes/note-file.ts","../src/schemas/note.ts","../src/utils/gray-matter-io.ts","../src/commands/source-add.ts","../src/utils/today.ts","../src/sessions/lease.ts","../src/schemas/lease.ts","../src/server/lifecycle.ts","../src/utils/git-gh.ts","../src/commands/open.ts","../src/bootstrap/archive-tasks.ts","../src/utils/global-config.ts","../src/commands/resume.ts","../src/sessions/resolve-session-location.ts","../src/utils/color.ts"],"sourcesContent":["import os from 'node:os';\nimport path from 'node:path';\nimport envPaths from 'env-paths';\n\nconst PROJECT_NAME = 'active-work';\n\nfunction paths(): ReturnType<typeof envPaths> {\n return envPaths(PROJECT_NAME, { suffix: '' });\n}\n\n/**\n * Replace a leading `~` with the user's home directory.\n *\n * Returns the input unchanged when it does not start with `~`.\n */\nexport function expandTilde(p: string): string {\n if (p === '~') return os.homedir();\n if (p.startsWith('~/')) return path.join(os.homedir(), p.slice(2));\n return p;\n}\n\n/**\n * Resolve the root directory for initiative data.\n *\n * Honors `ACTIVE_ROOT` (with `~` expansion) when set; otherwise falls back to\n * the XDG data path provided by `env-paths`.\n */\nexport function getActiveRoot(): string {\n const override = process.env.ACTIVE_ROOT;\n if (override && override.length > 0) {\n return path.resolve(expandTilde(override));\n }\n return paths().data;\n}\n\n/** Resolve the XDG state directory used for ephemeral runtime state. */\nexport function getStateRoot(): string {\n return paths().log;\n}\n\n/** Resolve the XDG config directory used for user-level config files. */\nexport function getConfigRoot(): string {\n return paths().config;\n}\n\n/** Resolve the XDG cache directory. */\nexport function getCacheRoot(): string {\n return paths().cache;\n}\n\n/** Resolve the directory for a single initiative by slug. */\nexport function getInitiativeDir(slug: string): string {\n return path.join(getActiveRoot(), slug);\n}\n\n/** Resolve the path of the advisory lockfile for an initiative. */\nexport function getLockPath(slug: string): string {\n return path.join(getInitiativeDir(slug), '.lock');\n}\n\n/**\n * Resolve the root directory for the cross-initiative Drain miner store\n * (AW-28): `templates.yml`, `occurrences.jsonl`, and per-tool-type Drain-tree\n * snapshots. Lives under `getActiveRoot()` so `ACTIVE_ROOT` overrides and test\n * isolation keep working, but outside any single initiative's directory since\n * it spans transcripts across all initiatives.\n */\nexport function getMinerRoot(): string {\n return path.join(getActiveRoot(), '.miner');\n}\n","import { createRegistry, type CommandRegistry } from '@titan-design/registry';\nimport type { AnyCommand, CommandContext } from './types.js';\n\n/**\n * One registry instance for the process. The package models a registry as an\n * instance rather than a module singleton so a product can own several;\n * active-work has exactly one, and this module is where that choice lives.\n */\nexport const registry: CommandRegistry<CommandContext> = createRegistry<CommandContext>();\n\nexport function register(cmd: AnyCommand): void {\n registry.register(cmd);\n}\n\nexport type { CommandRegistry } from '@titan-design/registry';\nexport type { Command, AnyCommand, CommandContext, CliMeta, CliOption } from './types.js';\nexport { defineCommand } from './types.js';\nexport type { JsonEnvelope } from '@titan-design/registry';\nexport { successEnvelope, errorEnvelope } from '@titan-design/registry';\n","/**\n * active-work's binding of `@titan-design/registry` (AW-a).\n *\n * The package's `Command` carries a third type parameter for the context, so\n * every command would otherwise have to spell out `Command<A, R, CommandContext>`.\n * These aliases bind it once, which is why all 60 command modules import from\n * here unchanged. The package is the implementation; this file is the product's\n * dialect of it.\n */\nimport type {\n AnyCommand as PkgAnyCommand,\n BaseContext,\n Command as PkgCommand,\n} from '@titan-design/registry';\nimport { defineCommand as pkgDefineCommand } from '@titan-design/registry';\n\nexport interface CommandContext extends BaseContext {\n activeRoot: string;\n // The user's shell working directory, populated by interactive surfaces\n // (the CLI dispatcher and `aw` launcher). Left undefined by the daemon /\n // MCP server, whose process cwd is not the user's — those callers must pass\n // an explicit `cwd` arg to opt into cwd-based resolution.\n cwd?: string;\n}\n\nexport type Command<Args = unknown, Result = unknown> = PkgCommand<Args, Result, CommandContext>;\nexport type AnyCommand = PkgAnyCommand<CommandContext>;\n\nexport function defineCommand<Args, Result>(cmd: Command<Args, Result>): Command<Args, Result> {\n return pkgDefineCommand<Args, Result, CommandContext>(cmd);\n}\n\nexport type { CliMeta, CliOption } from '@titan-design/registry';\n","/**\n * Typed error hierarchy + sysexits exit codes.\n *\n * EXIT codes follow BSD `sysexits.h` so the CLI dispatcher and JSON envelope\n * surface a consistent, machine-readable status across human and tooling output.\n */\n\nexport const EXIT = {\n OK: 0,\n GENERIC: 1,\n USAGE: 64, // EX_USAGE\n DATAERR: 65, // EX_DATAERR — invalid input data / validation\n NOINPUT: 66, // EX_NOINPUT — file/initiative not found\n UNAVAILABLE: 69, // EX_UNAVAILABLE — daemon unreachable\n SOFTWARE: 70, // EX_SOFTWARE — internal bug\n CONFIG: 78, // EX_CONFIG — bad config\n} as const;\n\nexport class ActiveWorkError extends Error {\n readonly code: number = EXIT.GENERIC;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'ActiveWorkError';\n }\n}\n\nexport class ValidationError extends ActiveWorkError {\n override readonly code: number = EXIT.DATAERR;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'ValidationError';\n }\n}\n\nexport class NotFoundError extends ActiveWorkError {\n override readonly code: number = EXIT.NOINPUT;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'NotFoundError';\n }\n}\n\nexport class UsageError extends ActiveWorkError {\n override readonly code: number = EXIT.USAGE;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'UsageError';\n }\n}\n\nexport class DaemonError extends ActiveWorkError {\n override readonly code: number = EXIT.UNAVAILABLE;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'DaemonError';\n }\n}\n\nexport class ConfigError extends ActiveWorkError {\n override readonly code: number = EXIT.CONFIG;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'ConfigError';\n }\n}\n\nexport class SoftwareError extends ActiveWorkError {\n override readonly code: number = EXIT.SOFTWARE;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'SoftwareError';\n }\n}\n\nexport function isActiveWorkError(err: unknown): err is ActiveWorkError {\n return err instanceof ActiveWorkError;\n}\n\nexport function formatError(err: unknown): { message: string; code: number } {\n if (err instanceof ActiveWorkError) {\n return { message: err.message, code: err.code };\n }\n if (err instanceof Error) {\n return { message: err.message, code: EXIT.GENERIC };\n }\n return { message: String(err), code: EXIT.GENERIC };\n}\n","/**\n * Pure helpers for assembling the `claude` argv the `aw` launcher spawns.\n * Kept side-effect-free (no top-level `main()`) so they are unit-testable\n * without executing the launcher on import.\n */\n\n/**\n * Merge an initiative's brief-declared channels with a caller-supplied set of\n * defaults (typically the user's global config — see `utils/global-config.ts`).\n * Defaults come first, de-duplicated by exact target string so a brief that\n * redundantly lists a default doesn't double it up on the command line.\n */\nexport function mergeChannels(\n defaultChannels: string[] | undefined,\n briefChannels: string[] | undefined,\n): string[] {\n const merged = [...(defaultChannels ?? []), ...(briefChannels ?? [])];\n return [...new Set(merged)];\n}\n\n/**\n * Build the channel flags for an initiative's MCP push channels.\n *\n * Each frontmatter `channels` entry is a target: an explicit\n * `server:<name>` / `plugin:<name>@<marketplace>`, or a bare server name that\n * is normalized to `server:<name>`.\n *\n * The two target kinds take different flags, and the choice is not cosmetic.\n * Claude Code's channel gate only has an allowlist path for plugin targets:\n * `plugin:` entries go under `--channels`, which is satisfied by an\n * `allowedChannelPlugins` entry in managed settings, while `server:` entries\n * have no allowlist path at all and must use the dev flag. Routing a properly\n * allowlisted plugin through the dev flag still works, but re-triggers the\n * development-channels dialog that packaging it as a plugin exists to avoid.\n *\n * Both flags are variadic, so callers must keep the prompt behind a `--`.\n */\nexport function buildChannelArgs(channels: string[] | undefined): string[] {\n if (!channels || channels.length === 0) return [];\n const targets = channels.map((raw) => (/^(server|plugin):/.test(raw) ? raw : `server:${raw}`));\n const plugins = targets.filter((t) => t.startsWith('plugin:'));\n const servers = targets.filter((t) => !t.startsWith('plugin:'));\n return [\n ...(plugins.length > 0 ? ['--channels', ...plugins] : []),\n ...(servers.length > 0 ? ['--dangerously-load-development-channels', ...servers] : []),\n ];\n}\n\n/**\n * Assemble the full `claude` argv. The prompt always follows a `--` so the\n * variadic channel flags can never swallow it as a channel target — the bug\n * that made `aw <slug>` collide the channel name with the bootstrap prompt.\n */\nexport function buildClaudeArgs(prompt: string, channels?: string[]): string[] {\n return [...buildChannelArgs(channels), '--', prompt];\n}\n\n/**\n * `--adhoc` is the canonical spelling; `--ad-hoc` is accepted as an alias so\n * the natural hyphenated form doesn't trip the unknown-flag guard below.\n */\nexport const ADHOC_FLAGS = ['--adhoc', '--ad-hoc'];\n\nexport interface LauncherFlags {\n pick: boolean;\n adhoc: boolean;\n positional: string[];\n /** True when a positional looks like an unknown flag, or more than one slug was given. */\n usageError: boolean;\n}\n\n/**\n * Parse the `aw` launcher flags out of `argv.slice(2)`. Pure and\n * side-effect-free so the flag handling — including the `--adhoc` / `--ad-hoc`\n * alias — is unit-testable without executing the launcher.\n */\nexport function parseLauncherFlags(args: string[]): LauncherFlags {\n const known = new Set(['--pick', ...ADHOC_FLAGS]);\n const positional = args.filter((a) => !known.has(a));\n return {\n pick: args.includes('--pick'),\n adhoc: args.some((a) => ADHOC_FLAGS.includes(a)),\n positional,\n usageError: positional.some((a) => a.startsWith('-')) || positional.length > 1,\n };\n}\n","import { promises as fs } from 'node:fs';\nimport type { Dirent } from 'node:fs';\nimport path from 'node:path';\nimport { BriefFrontmatterSchema } from '../schemas/brief.js';\nimport { expandTilde } from '../utils/paths.js';\nimport { readRegisteredWorktrees, defaultWorktreePath } from '../utils/registered-worktrees.js';\nimport { NotFoundError } from '../errors.js';\nimport { readMarkdownWithSchema } from '../bootstrap/prompt.js';\n\n/** List initiative slugs (immediate, non-dotfile subdirectories of the root). */\nexport async function listInitiativeSlugs(activeRoot: string): Promise<string[]> {\n let entries: Dirent[];\n try {\n entries = await fs.readdir(activeRoot, { withFileTypes: true });\n } catch {\n return [];\n }\n return entries\n .filter((e) => e.isDirectory() && !e.name.startsWith('.'))\n .map((e) => e.name)\n .sort();\n}\n\n/**\n * Resolve a user-supplied slug (exact or unique prefix) to a full slug.\n * Throws NotFoundError on no match, and on an ambiguous prefix.\n */\nexport async function resolveSlug(activeRoot: string, input: string): Promise<string> {\n const slugs = await listInitiativeSlugs(activeRoot);\n if (slugs.includes(input)) return input;\n const matches = slugs.filter((s) => s.startsWith(input));\n if (matches.length === 1) return matches[0]!;\n if (matches.length > 1) {\n throw new NotFoundError(`Ambiguous slug '${input}'. Candidates: ${matches.join(', ')}`);\n }\n if (slugs.length === 0) {\n throw new NotFoundError(`No initiatives found under ${activeRoot}`);\n }\n throw new NotFoundError(`No initiative matches '${input}'. Known: ${slugs.join(', ')}`);\n}\n\n/**\n * The initiative's own directory under the active root — where an interactive\n * Claude session launches, always, regardless of what worktrees are\n * registered. Used by the `aw` launcher and `resume`.\n *\n * Deliberately not `resolveCwdHint`. Registering a worktree is a statement\n * about where *dispatched agents* need to run (they must be in a git repo to\n * commit); it is not a request to move the operator's own sessions out of the\n * initiative's notes and state. Those two were one value until AW-115, so\n * `active-work worktree set relay ~/projects/relay` — run to fix relay's\n * dispatch — silently relocated every subsequent `aw relay` as well.\n */\nexport function resolveLaunchCwd(activeRoot: string, slug: string): string {\n return path.join(activeRoot, slug);\n}\n\n/**\n * The initiative's preferred registered worktree, or its active-root directory\n * when none is registered.\n *\n * This is the *dispatch* answer, surfaced as `cwd_hint` on `open`'s JSON\n * envelope and consumed by out-of-process callers that need a git checkout —\n * relay's daemon resolves a voice-dispatched item's working directory this way\n * (`daemon/src/initiative.ts`). The launcher deliberately does not use it; see\n * `resolveLaunchCwd`.\n */\nexport async function resolveCwdHint(activeRoot: string, slug: string): Promise<string> {\n const registered = await readRegisteredWorktrees(path.join(activeRoot, slug));\n const preferred = defaultWorktreePath(registered);\n return preferred === null ? path.join(activeRoot, slug) : expandTilde(preferred);\n}\n\n/** True when `child` is `parent` itself or nested beneath it. */\nfunction isInside(child: string, parent: string): boolean {\n const rel = path.relative(parent, child);\n return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));\n}\n\n/**\n * Canonicalize a path via `realpath`, falling back to a lexical resolve when\n * the path doesn't exist yet. Needed because `process.cwd()` returns the\n * symlink-resolved path on macOS (e.g. `/var` → `/private/var`) while a brief\n * may store the un-resolved form — matching them requires both canonicalized.\n */\nasync function canonicalize(p: string): Promise<string> {\n try {\n return await fs.realpath(p);\n } catch {\n return path.resolve(p);\n }\n}\n\nexport interface CwdMatch {\n slug: string;\n worktreePath: string;\n}\n\n/**\n * Resolve an initiative from a working directory by matching it against every\n * initiative's worktree paths. When `cwd` sits inside more than one worktree\n * (e.g. nested checkouts) the deepest — longest — worktree path wins. Returns\n * the matched slug and (display-form) worktree path, or null when nothing\n * matches or two initiatives tie at the same depth (ambiguous → fall back to\n * the picker).\n *\n * Both sides are canonicalized with `realpath` so symlinked paths still match.\n * Relative worktree paths are skipped, since they cannot be compared against\n * an absolute cwd deterministically.\n */\nexport async function resolveSlugFromCwd(\n activeRoot: string,\n cwd: string,\n): Promise<CwdMatch | null> {\n const resolvedCwd = await canonicalize(cwd);\n const slugs = await listInitiativeSlugs(activeRoot);\n let best: { slug: string; worktreePath: string; depth: number } | null = null;\n let tiedAtBest = false;\n\n for (const slug of slugs) {\n const briefPath = path.join(activeRoot, slug, 'brief.md');\n try {\n // Read purely as a validity gate: an initiative whose brief will not\n // parse is skipped rather than resolved into.\n await readMarkdownWithSchema(briefPath, BriefFrontmatterSchema);\n } catch {\n continue;\n }\n // Only *registered* worktrees resolve a cwd. Swept ones are observations,\n // not a claim that this directory belongs to the initiative (AW-67).\n const registered = await readRegisteredWorktrees(path.join(activeRoot, slug));\n for (const entry of registered) {\n const displayPath = expandTilde(entry.path);\n if (!path.isAbsolute(displayPath)) continue;\n const canonical = await canonicalize(displayPath);\n if (!isInside(resolvedCwd, canonical)) continue;\n const depth = canonical.length;\n if (best === null || depth > best.depth) {\n best = { slug, worktreePath: displayPath, depth };\n tiedAtBest = false;\n } else if (depth === best.depth && slug !== best.slug) {\n tiedAtBest = true;\n }\n }\n }\n\n if (best === null || tiedAtBest) return null;\n return { slug: best.slug, worktreePath: best.worktreePath };\n}\n","import { z } from 'zod';\n\nconst ISO_DATE_REGEX = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nconst isValidIsoDate = (value: string): boolean => {\n if (!ISO_DATE_REGEX.test(value)) return false;\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) return false;\n // Reject dates like 2026-02-30 that JS happily rolls forward.\n return parsed.toISOString().slice(0, 10) === value;\n};\n\nconst isoDate = z\n .string()\n .refine(isValidIsoDate, { message: 'Must be a valid zero-padded YYYY-MM-DD date' });\n\nconst positiveInt = z.number().int().positive();\n\n// Exported so `task add` can validate a hand-edited `task_seq` against the same\n// rule the brief is written with, and reject it with a message that names the\n// field — whole-brief validation only ever produces an anonymous zod dump.\nexport const TaskSeqSchema = positiveInt;\n\n// `worktrees` lived here until schema v4 (AW-67). It now shares one list with\n// the swept worktrees in `artifacts.yml`; see `src/schemas/artifacts.ts`.\n\n// An MCP push-channel target enabled at `aw`/`open` launch via\n// `claude --dangerously-load-development-channels <target>`. Accepts an\n// explicit `server:<name>` / `plugin:<name>@<marketplace>` target, or a bare\n// server name that is normalized to `server:<name>` by the launcher. Exported\n// so the global config schema (`utils/global-config.ts`) validates its own\n// `channels` list against the same rule instead of a hand-rolled copy.\nexport const channelTarget = z\n .string()\n .min(1)\n .regex(/^(?:(?:server|plugin):.+|[A-Za-z0-9_-]+)$/, {\n message:\n 'channel must be a target like \"server:voltras\", \"plugin:name@marketplace\", or a bare server name',\n });\n\nexport const BriefFrontmatterSchema = z\n .object({\n schema_version: positiveInt,\n title: z.string().min(1),\n updated: isoDate,\n state: z.enum(['focused', 'backburner', 'paused', 'done']),\n rank: positiveInt.optional(),\n paused_since: isoDate.optional(),\n restart_trigger: z.string().min(1).optional(),\n ship_target: z.string().optional(),\n owner: z.string().optional(),\n task_prefix: z\n .string()\n .min(1)\n .regex(/^[A-Z][A-Z0-9]*$/, {\n message: 'task_prefix must be uppercase letters/digits starting with a letter',\n }),\n channels: z.array(channelTarget).optional(),\n // High-water mark for task ids: the largest numeric suffix ever issued\n // for this initiative's task_prefix. Optional so pre-existing brief.md\n // files (written before this field existed) keep validating; task.add\n // falls back to scanning on-disk task files when it's absent. Only\n // task.delete writes this field (AW-94) — and only when removing the\n // current highest id — so task.add itself never rewrites brief.md.\n task_seq: TaskSeqSchema.optional(),\n })\n .superRefine((value, ctx) => {\n if (value.state === 'focused' && value.rank === undefined) {\n ctx.addIssue({\n code: 'custom',\n path: ['rank'],\n message: 'rank is required when state is \"focused\"',\n });\n }\n if (value.state === 'paused') {\n if (value.paused_since === undefined) {\n ctx.addIssue({\n code: 'custom',\n path: ['paused_since'],\n message: 'paused_since is required when state is \"paused\"',\n });\n }\n if (value.restart_trigger === undefined) {\n ctx.addIssue({\n code: 'custom',\n path: ['restart_trigger'],\n message: 'restart_trigger is required when state is \"paused\"',\n });\n }\n }\n });\n\nexport type BriefFrontmatter = z.infer<typeof BriefFrontmatterSchema>;\n","/**\n * Reading and writing the registered half of `artifacts.worktrees[]` (AW-67).\n *\n * Worktrees used to live in two places: `brief.worktrees` (curated, keyed by\n * name) and `artifacts.worktrees[]` (swept from git by `wrap`). They now share\n * one list, distinguished by whether an entry carries a `name` — see\n * `src/schemas/artifacts.ts`.\n *\n * Every caller that used to read `brief.worktrees` goes through here, so the\n * \"registered means named\" rule is stated once. A second implementation that\n * disagreed would make `aw` resolve a cwd the launcher never intended.\n */\n\nimport { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { ArtifactsSchema, type Artifacts, type WorktreeEntry } from '../schemas/artifacts.js';\nimport { readYaml, writeYaml } from './yaml-io.js';\n\n/** A worktree an operator registered: identical to an entry, but named. */\nexport type RegisteredWorktree = WorktreeEntry & { name: string };\n\nexport function artifactsPathFor(initiativeDir: string): string {\n return path.join(initiativeDir, 'artifacts.yml');\n}\n\nconst EMPTY: Artifacts = { branches: [], stashes: [], worktrees: [] };\n\n/** Missing file reads as empty; a malformed one still throws. */\nexport async function readArtifactsFile(initiativeDir: string): Promise<Artifacts> {\n const file = artifactsPathFor(initiativeDir);\n try {\n await fs.access(file);\n } catch {\n return { ...EMPTY, branches: [], stashes: [], worktrees: [] };\n }\n return readYaml(file, ArtifactsSchema);\n}\n\nexport function registeredOf(artifacts: Artifacts): RegisteredWorktree[] {\n return artifacts.worktrees.filter(\n (entry): entry is RegisteredWorktree => entry.name !== undefined,\n );\n}\n\n/**\n * Registered worktrees for an initiative. Never throws for a missing or\n * unreadable artifacts.yml — a brief that cannot be paired with artifacts\n * simply has no registered worktrees, which is what callers scanning every\n * initiative need in order to skip it rather than abort the scan.\n */\nexport async function readRegisteredWorktrees(\n initiativeDir: string,\n): Promise<RegisteredWorktree[]> {\n try {\n return registeredOf(await readArtifactsFile(initiativeDir));\n } catch {\n return [];\n }\n}\n\n/**\n * The worktree `aw <slug>` should start in: the explicit default, or the only\n * registered worktree when there is exactly one. Null when neither holds, so\n * the caller can fall back to the initiative directory.\n */\nexport function defaultWorktreePath(registered: RegisteredWorktree[]): string | null {\n const explicit = registered.find((entry) => entry.default === true);\n if (explicit) return explicit.path;\n return registered.length === 1 ? registered[0]!.path : null;\n}\n\nexport async function writeArtifactsFile(\n initiativeDir: string,\n artifacts: Artifacts,\n): Promise<void> {\n await writeYaml(artifactsPathFor(initiativeDir), artifacts, ArtifactsSchema);\n}\n","import { z } from 'zod';\n\n/**\n * Schema v2 (AW-15): `artifacts.yml` carries only durable identifiers.\n *\n * - `prs[]` was dropped. PR state is derived live via `gh pr list --head <branch>`\n * in `artifact.status` (see `src/commands/artifact-status.ts`); persisting it\n * only led to stale snapshots that agents kept hand-editing.\n * - `branches[]` gained an optional `note` for \"why this branch is worth\n * tracking\" context. The `last_commit` field is gone — it's derivable from\n * git at read time.\n * - `stashes[].message` was renamed to `label` for consistency, `created` was\n * dropped (stashes are ephemeral and the data lived in git anyway), and\n * `sha` was added so callers can record it if known.\n *\n * `worktrees[]` follows the same rule. It persists identity (`path`, `repo`,\n * `branch`) plus the one thing git cannot tell you — `holding`, what work the\n * worktree is parked on. Dirty/clean, files changed, and ahead/behind are\n * deliberately absent: they are read live from git in `artifact.status` via\n * `src/utils/git-worktrees.ts`. A persisted copy is wrong the moment anyone\n * touches the tree.\n *\n * This field is additive with a default, so pre-existing `artifacts.yml`\n * files keep validating untouched — no migration needed.\n */\n\nexport const BranchEntrySchema = z.object({\n repo: z.string().min(1),\n name: z.string().min(1),\n note: z.string().optional(),\n});\n\nexport const StashEntrySchema = z.object({\n repo: z.string().min(1),\n label: z.string().min(1),\n sha: z.string().optional(),\n});\n\n/**\n * Schema v4 (AW-67): `brief.worktrees` collapsed into this list, so a worktree\n * has exactly one home.\n *\n * The two records had different jobs, and merging them without a marker would\n * have quietly changed launcher behavior: `brief.worktrees` was the *curated*\n * set an operator registered, and it is what `aw` resolves a cwd against, while\n * this list is *swept* automatically by `wrap` from whatever git reports.\n * Letting every swept worktree become a cwd-resolution target would make `aw`\n * ambiguous in repos it had never been told about.\n *\n * `name` is that marker. An entry with a `name` is registered — the operator\n * labelled it, it participates in cwd resolution, and it may be `default`. An\n * entry without one was merely observed. `worktree.set` promotes an observed\n * entry by giving it a name rather than creating a duplicate.\n */\nexport const WorktreeEntrySchema = z.object({\n path: z.string().min(1),\n repo: z.string().min(1),\n branch: z.string().min(1).optional(),\n holding: z.string().min(1).optional(),\n pr: z.number().int().positive().optional(),\n note: z.string().optional(),\n /** Operator's label. Present only on registered worktrees. */\n name: z.string().min(1).optional(),\n /** The worktree `aw <slug>` starts in. Only meaningful alongside `name`. */\n default: z.boolean().optional(),\n});\n\nexport const ArtifactsSchema = z\n .object({\n branches: z.array(BranchEntrySchema).default([]),\n stashes: z.array(StashEntrySchema).default([]),\n worktrees: z.array(WorktreeEntrySchema).default([]),\n })\n .superRefine((value, ctx) => {\n // Both invariants used to be free: names were object keys in the brief, and\n // only one entry could carry `default` because the writer rebuilt the map.\n // In a flat list they have to be enforced.\n const names = new Set<string>();\n let defaults = 0;\n value.worktrees.forEach((entry, i) => {\n if (entry.name !== undefined) {\n if (names.has(entry.name)) {\n ctx.addIssue({\n code: 'custom',\n path: ['worktrees', i, 'name'],\n message: `duplicate worktree name: ${entry.name}`,\n });\n }\n names.add(entry.name);\n }\n if (entry.default === true) {\n defaults += 1;\n if (entry.name === undefined) {\n ctx.addIssue({\n code: 'custom',\n path: ['worktrees', i, 'default'],\n message: 'default requires a named worktree',\n });\n }\n }\n });\n if (defaults > 1) {\n ctx.addIssue({\n code: 'custom',\n path: ['worktrees'],\n message: 'at most one worktree may be default',\n });\n }\n });\n\nexport type BranchEntry = z.infer<typeof BranchEntrySchema>;\nexport type StashEntry = z.infer<typeof StashEntrySchema>;\nexport type WorktreeEntry = z.infer<typeof WorktreeEntrySchema>;\nexport type Artifacts = z.infer<typeof ArtifactsSchema>;\n","import { promises as fs } from 'node:fs';\nimport YAML from 'yaml';\nimport type { ZodType } from 'zod';\nimport { classifyStructuredArtifact, recordArtifactHash } from './artifact-hash.js';\nimport { atomicWrite } from './fs-atomic.js';\nimport { coerceDates } from './coerce-dates.js';\n\n/**\n * Read and parse a YAML file, validating its contents against `schema`.\n *\n * Throws when the file is unreadable, the YAML is malformed, or the parsed\n * value does not satisfy `schema`. Validation errors include the file path\n * to help locate the offending file.\n */\nexport async function readYaml<T>(filePath: string, schema: ZodType<T>): Promise<T> {\n const raw = await fs.readFile(filePath, 'utf8');\n let parsed: unknown;\n try {\n parsed = YAML.parse(raw);\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n throw new Error(`Failed to parse YAML at ${filePath}: ${reason}`);\n }\n const coerced = coerceDates(parsed);\n const result = schema.safeParse(coerced);\n if (!result.success) {\n throw new Error(`Schema validation failed for ${filePath}: ${result.error.message}`);\n }\n return result.data;\n}\n\n/**\n * Write `data` as YAML to `filePath` atomically after validating `schema`.\n *\n * Validation runs before any disk write so an invalid object never lands on\n * disk.\n */\nexport async function writeYaml<T>(filePath: string, data: T, schema: ZodType<T>): Promise<void> {\n const result = schema.safeParse(data);\n if (!result.success) {\n throw new Error(`Schema validation failed for ${filePath}: ${result.error.message}`);\n }\n const yaml = YAML.stringify(result.data);\n await atomicWrite(filePath, yaml);\n const artifact = classifyStructuredArtifact(filePath);\n if (artifact) await recordArtifactHash(artifact.initiativeDir, artifact.relPath, yaml);\n}\n","import { createHash } from 'node:crypto';\nimport { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport YAML from 'yaml';\nimport { atomicWrite } from './fs-atomic.js';\n\nconst MANIFEST_FILENAME = '.artifact-hashes.yml';\n\n/**\n * Which structured artifacts get drift-tracked, and their manifest key.\n *\n * Sessions and notes are intentionally excluded — only the files CLAUDE.md\n * calls \"CLI-only\" (tasks/*.yml, artifacts.yml, brief frontmatter) are in\n * scope for AW-66.\n */\nexport function classifyStructuredArtifact(\n filePath: string,\n): { initiativeDir: string; relPath: string } | null {\n const base = path.basename(filePath);\n const dir = path.dirname(filePath);\n if (base === 'artifacts.yml' || base === 'brief.md') {\n return { initiativeDir: dir, relPath: base };\n }\n if (base.endsWith('.yml') && path.basename(dir) === 'tasks') {\n return { initiativeDir: path.dirname(dir), relPath: path.posix.join('tasks', base) };\n }\n return null;\n}\n\nexport function hashContent(content: string): string {\n return createHash('sha256').update(content, 'utf8').digest('hex');\n}\n\nasync function readManifest(initiativeDir: string): Promise<Record<string, string>> {\n const manifestPath = path.join(initiativeDir, MANIFEST_FILENAME);\n let raw: string;\n try {\n raw = await fs.readFile(manifestPath, 'utf8');\n } catch {\n return {};\n }\n let parsed: unknown;\n try {\n parsed = YAML.parse(raw);\n } catch {\n return {};\n }\n if (!parsed || typeof parsed !== 'object') return {};\n return parsed as Record<string, string>;\n}\n\n/** Manifest of `relPath -> sha256(content)` for every tracked artifact that has been CLI-written. */\nexport async function readArtifactHashes(initiativeDir: string): Promise<Record<string, string>> {\n return readManifest(initiativeDir);\n}\n\n/**\n * Record the hash of `content` for `relPath` in the initiative's manifest.\n *\n * Called from inside `writeYaml`/`writeFrontmatter` right after the real\n * write, so every CLI write path tracks itself with no call-site changes.\n */\nexport async function recordArtifactHash(\n initiativeDir: string,\n relPath: string,\n content: string,\n): Promise<void> {\n const manifest = await readManifest(initiativeDir);\n manifest[relPath] = hashContent(content);\n const manifestPath = path.join(initiativeDir, MANIFEST_FILENAME);\n await atomicWrite(manifestPath, YAML.stringify(manifest));\n}\n","import { randomBytes } from 'node:crypto';\nimport { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport lockfile from 'proper-lockfile';\n\n/**\n * Write `content` to `targetPath` atomically.\n *\n * Strategy: write to a sibling temp file, `fsync` the file, then `rename` to\n * the destination. The temp file lives in the same directory so the rename\n * stays within one filesystem (a requirement for atomic rename on POSIX).\n */\nexport async function atomicWrite(targetPath: string, content: string | Buffer): Promise<void> {\n const dir = path.dirname(targetPath);\n const base = path.basename(targetPath);\n const suffix = `${process.pid}.${randomBytes(6).toString('hex')}`;\n const tempPath = path.join(dir, `${base}.tmp.${suffix}`);\n\n let handle: fs.FileHandle | undefined;\n try {\n handle = await fs.open(tempPath, 'wx');\n await handle.writeFile(content);\n await handle.sync();\n } finally {\n if (handle) await handle.close();\n }\n\n try {\n await fs.rename(tempPath, targetPath);\n } catch (err) {\n await fs.rm(tempPath, { force: true });\n throw err;\n }\n}\n\n/**\n * Run `fn` while holding an advisory lock on `lockTarget`.\n *\n * Uses `proper-lockfile` with `realpath: false` so the target need not exist.\n * The lock is always released, even when `fn` rejects.\n */\nexport async function withFileLock<T>(lockTarget: string, fn: () => Promise<T>): Promise<T> {\n await fs.mkdir(path.dirname(lockTarget), { recursive: true });\n const release = await lockfile.lock(lockTarget, {\n realpath: false,\n retries: { retries: 5, factor: 1.5, minTimeout: 50 },\n });\n try {\n return await fn();\n } finally {\n await release();\n }\n}\n","/**\n * YAML parsers (js-yaml inside gray-matter; the `yaml` package) parse bare\n * ISO 8601 timestamps into JavaScript Date instances by default. Our zod\n * schemas validate dates as YYYY-MM-DD or ISO 8601 STRINGS — so we re-coerce\n * any Date we find back into the appropriate string form before validation.\n *\n * A midnight-UTC Date round-trips as YYYY-MM-DD; any non-midnight Date\n * round-trips as the full ISO 8601 string. The heuristic matches the two\n * schema shapes we have (date-only fields like `updated`, ISO fields like\n * `started`/`ended`/`last_checked`).\n */\n\nfunction dateToString(d: Date): string {\n if (\n d.getUTCHours() === 0 &&\n d.getUTCMinutes() === 0 &&\n d.getUTCSeconds() === 0 &&\n d.getUTCMilliseconds() === 0\n ) {\n return d.toISOString().slice(0, 10);\n }\n return d.toISOString();\n}\n\nexport function coerceDates(value: unknown): unknown {\n if (value instanceof Date) {\n return dateToString(value);\n }\n if (Array.isArray(value)) {\n return value.map(coerceDates);\n }\n if (value !== null && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n out[k] = coerceDates(v);\n }\n return out;\n }\n return value;\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { BriefFrontmatterSchema, type BriefFrontmatter } from '../schemas/brief.js';\nimport { TaskSchema, type Task } from '../schemas/task.js';\nimport {\n ArtifactsSchema,\n type Artifacts,\n type BranchEntry,\n type WorktreeEntry,\n} from '../schemas/artifacts.js';\nimport {\n deriveOpenLoopsFrom,\n deriveResolvedLoopsFrom,\n loadSessionsFromDir,\n normalizePrRef,\n type LoadedSession,\n type LoadedSessions,\n type MalformedSession,\n type OpenLoop,\n type ResolvedLoop,\n} from '../sessions/open-loops.js';\nimport { loadNotesFromDir, type LoadedNote, type LoadedNotes } from '../notes/note-file.js';\nimport { readLiveLeases, type LiveSibling, type SiblingProbe } from '../sessions/lease.js';\nimport { readYaml } from '../utils/yaml-io.js';\nimport {\n getGhRunner,\n getGitRunner,\n resolveLocalRepoPath,\n resolveOrgRepo,\n} from '../utils/git-gh.js';\nimport { today, nowIso } from '../utils/today.js';\nimport { NotFoundError } from '../errors.js';\nimport YAML from 'yaml';\nimport type { ZodType } from 'zod';\n\nconst BRIEF_BODY_MAX_LINES = 40;\nconst SESSION_BODY_MAX_LINES = 25;\nconst DEFAULT_TOP_N_TASKS = 5;\nconst DEFAULT_RECENTLY_DONE_DAYS = 14;\n\nconst RECENT_THRESHOLD_DAYS = 14;\nconst MS_PER_HOUR = 1000 * 60 * 60;\nconst MS_PER_DAY = MS_PER_HOUR * 24;\n\nexport interface LiveBranchStatus {\n repo: string;\n name: string;\n note?: string;\n present: boolean;\n last_commit_iso: string | null;\n ahead: number | null;\n behind: number | null;\n pr: {\n number: number;\n state: string;\n title: string;\n url: string;\n checks?: string;\n } | null;\n}\n\nexport type LiveStatusFetcher = (branches: BranchEntry[]) => Promise<LiveBranchStatus[]>;\n\n/** Re-exported so callers can type a sibling list without reaching into `sessions/`. */\nexport type SiblingSession = LiveSibling;\nexport type { SiblingProbe };\n\nexport interface BootstrapInput {\n /** Active root directory. Used to resolve the initiative dir. */\n activeRoot: string;\n slug: string;\n /** Injectable \"now\" for deterministic tests. Defaults to `new Date()`. */\n now?: Date;\n /** Cap for top open tasks shown. Defaults to 5. */\n topNTasks?: number;\n /** Window for the \"recently done\" section. Defaults to 14 days. */\n recentlyDoneDays?: number;\n /**\n * When `true` (default), the bootstrap pulls live branch/PR state via\n * `git` + `gh`. When `false`, only the static `artifacts.yml` data is\n * rendered — useful for offline contexts and fast-path test runs.\n */\n includeLiveStatus?: boolean;\n /**\n * Optional fetcher override (DI). Defaults to a built-in walker that\n * shells out via the shared `git`/`gh` runners. The walker is bounded\n * (~10 branches) and swallows per-branch errors; render falls back to\n * static when the whole fetch throws.\n */\n liveStatusFetcher?: LiveStatusFetcher;\n /**\n * Task ids the caller archived just before this bootstrap (AW-8). Rendered as\n * a short housekeeping note so the session knows they left the active list;\n * the actual file moves happen in the `open` command, not here.\n */\n archivedTaskIds?: string[];\n /**\n * When `true`, frame the session as ad-hoc work related to the workstream\n * rather than a continuation of its handoff / top task. The same context is\n * rendered, but the opening and closing directives tell the session to treat\n * it as background and await the user's specific ad-hoc task (AW-20).\n */\n adhoc?: boolean;\n /**\n * When `true` (default), probe for other sessions holding a lease on this\n * initiative and warn about them at the top of the prompt (CC-9).\n */\n detectSiblings?: boolean;\n /**\n * Optional probe override (DI). Defaults to reading the lease directory under\n * the active root. A probe that throws is treated as \"no siblings\" — this\n * section is advisory and must never be able to fail a bootstrap.\n */\n siblingProbe?: SiblingProbe;\n /** This session's own lease, excluded from the sibling list. */\n ownLeaseId?: string;\n}\n\nexport interface BootstrapMetadata {\n slug: string;\n brief_title: string;\n last_session?: { filename: string; ended: string };\n time_since_last_session_human?: string;\n open_task_count: number;\n open_loop_count: number;\n recently_done_count: number;\n bootstrap_at: string;\n /** Number of sibling sessions rendered; absent when none were found. */\n sibling_sessions?: number;\n}\n\nexport interface BootstrapOutput {\n prompt: string;\n metadata: BootstrapMetadata;\n}\n\nconst FRONTMATTER_DELIM = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/;\n\n/**\n * Read a markdown file with YAML frontmatter and validate the frontmatter\n * against `schema`.\n *\n * We parse the YAML block using the `yaml` package (eemeli/yaml) rather than\n * relying on gray-matter, because gray-matter's js-yaml backend converts\n * bare YAML dates (e.g. `updated: 2026-05-10`) into JavaScript `Date`\n * instances. Our schemas validate `YYYY-MM-DD` strings, so we want the raw\n * lexical form preserved.\n */\nexport async function readMarkdownWithSchema<T>(\n filePath: string,\n schema: ZodType<T>,\n): Promise<{ frontmatter: T; body: string }> {\n const raw = await fs.readFile(filePath, 'utf8');\n const match = FRONTMATTER_DELIM.exec(raw);\n let frontmatterText = '';\n let body = raw;\n if (match) {\n frontmatterText = match[1] ?? '';\n body = match[2] ?? '';\n }\n const parsed = frontmatterText ? YAML.parse(frontmatterText) : {};\n const result = schema.safeParse(parsed);\n if (!result.success) {\n throw new Error(`Frontmatter validation failed for ${filePath}: ${result.error.message}`);\n }\n return { frontmatter: result.data, body };\n}\n\n/**\n * Order sessions newest first, breaking `ended` ties on `started` so a long\n * mainline session that overlaps a short parallel one still sorts ahead of it.\n */\nfunction compareSessionsNewestFirst(a: LoadedSession, b: LoadedSession): number {\n const endedDelta =\n new Date(b.frontmatter.ended).getTime() - new Date(a.frontmatter.ended).getTime();\n if (endedDelta !== 0) return endedDelta;\n return new Date(b.frontmatter.started).getTime() - new Date(a.frontmatter.started).getTime();\n}\n\n/**\n * Every session for an initiative, newest first, regardless of track.\n *\n * Parsing is delegated to `loadSessionsFromDir` — the same loader derivation\n * uses — so bootstrap can never render a session whose loops the ledger\n * dropped, or vice versa. Unparseable files are not skipped silently: they\n * come back as `malformed` and are surfaced in the Open loops heading.\n */\nasync function loadSessionsNewestFirst(initiativeDir: string): Promise<LoadedSessions> {\n const { sessions, malformed } = await loadSessionsFromDir(initiativeDir);\n return { sessions: [...sessions].sort(compareSessionsNewestFirst), malformed };\n}\n\n/** A task file that would not parse. Mirrors `MalformedSession`. */\nexport interface MalformedTask {\n /** Filename including extension; a malformed file may have no usable id. */\n file: string;\n reason: string;\n}\n\nexport interface LoadedTasks {\n tasks: Task[];\n malformed: MalformedTask[];\n}\n\nfunction describe(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/**\n * Read every task file under `initiativeDir/tasks`.\n *\n * A file that would not parse is *not* the same as a task that does not exist:\n * dropping it silently shrinks the open list, so the next session works a stale\n * top task and never learns why. Malformed entries travel back to the caller\n * the way `loadSessionsFromDir` returns `malformed`.\n */\nasync function loadTasks(initiativeDir: string): Promise<LoadedTasks> {\n const tasksDir = path.join(initiativeDir, 'tasks');\n let entries: string[];\n try {\n entries = await fs.readdir(tasksDir);\n } catch {\n return { tasks: [], malformed: [] };\n }\n const ymlFiles = entries.filter((n) => n.endsWith('.yml') || n.endsWith('.yaml'));\n const tasks: Task[] = [];\n const malformed: MalformedTask[] = [];\n for (const filename of ymlFiles) {\n const fullPath = path.join(tasksDir, filename);\n try {\n tasks.push(await readYaml(fullPath, TaskSchema));\n } catch (err) {\n malformed.push({ file: filename, reason: describe(err) });\n }\n }\n return { tasks, malformed };\n}\n\nexport interface LoadedArtifacts {\n artifacts: Artifacts;\n /** Set only when `artifacts.yml` exists but could not be read or parsed. */\n error?: string;\n}\n\nfunction isMissingFile(err: unknown): boolean {\n return (err as NodeJS.ErrnoException | null)?.code === 'ENOENT';\n}\n\n/**\n * Read `artifacts.yml`, keeping \"no artifacts yet\" distinct from \"the file is\n * broken\".\n *\n * Both used to render as an empty ledger, which is the worst possible outcome:\n * a corrupted file quietly claims there are no open branches or stashes, and\n * the session starts by assuming clean ground it does not have.\n */\nasync function loadArtifacts(initiativeDir: string): Promise<LoadedArtifacts> {\n const artifactsPath = path.join(initiativeDir, 'artifacts.yml');\n const empty: Artifacts = { branches: [], stashes: [], worktrees: [] };\n try {\n return { artifacts: await readYaml(artifactsPath, ArtifactsSchema) };\n } catch (err) {\n if (isMissingFile(err)) return { artifacts: empty };\n return { artifacts: empty, error: describe(err) };\n }\n}\n\n/**\n * Keep the first `max` non-blank lines of `body`, marking the cut.\n *\n * The marker is not decoration: an excerpt that ends mid-thought reads as the\n * whole thought, so the reader has to be told both that content was dropped and\n * which file holds the rest. `source` is a real path for exactly that reason.\n */\nfunction truncateLines(body: string, max: number, source: string): string {\n const lines = body.split('\\n');\n const trimmed: string[] = [];\n let count = 0;\n let consumed = 0;\n for (const line of lines) {\n if (count >= max) break;\n trimmed.push(line);\n consumed++;\n if (line.trim().length > 0) count++;\n }\n const dropped = lines.slice(consumed).filter((l) => l.trim().length > 0).length;\n const kept = trimmed.join('\\n').replace(/\\s+$/, '');\n if (dropped === 0) return kept;\n return `${kept}\\n…(+${dropped} lines — see ${source})`;\n}\n\n/**\n * Format the time between `from` and `now` as a human string.\n *\n * Thresholds:\n * - < 1h → \"just now\"\n * - < 24h → \"X hours ago\"\n * - < 14d → \"X days ago\"\n * - >= 14d → \"X days ago — likely needs context refresher\"\n */\nexport function formatTimeSince(from: Date, now: Date): string {\n const diffMs = now.getTime() - from.getTime();\n if (diffMs < MS_PER_HOUR) return 'just now';\n if (diffMs < MS_PER_DAY) {\n const hours = Math.floor(diffMs / MS_PER_HOUR);\n return `${hours} hour${hours === 1 ? '' : 's'} ago`;\n }\n const days = Math.floor(diffMs / MS_PER_DAY);\n const base = `${days} day${days === 1 ? '' : 's'} ago`;\n if (days >= RECENT_THRESHOLD_DAYS) {\n return `${base} — likely needs context refresher`;\n }\n return base;\n}\n\nfunction compareTasksByPriority(a: Task, b: Task): number {\n if (a.priority !== b.priority) return a.priority - b.priority;\n return a.id.localeCompare(b.id);\n}\n\nfunction nonBlankLines(text: string | undefined): string[] {\n if (!text) return [];\n return text\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n}\n\nfunction firstLine(text: string | undefined): string | undefined {\n return nonBlankLines(text)[0];\n}\n\nconst TASK_SUMMARY_MAX_LINES = 2;\nconst TASK_SUMMARY_MAX_CHARS = 200;\n\n/**\n * Collapse `lines` into one bounded summary line, marking anything left behind.\n *\n * Same reasoning as `truncateLines`: a silently clipped excerpt reads as the\n * whole thought, so the cut is marked and paired with the command that prints\n * the field untruncated.\n */\nfunction summarizeField(label: string, lines: string[], pointer: string): string {\n const kept = lines.slice(0, TASK_SUMMARY_MAX_LINES);\n const joined = kept.join(' ');\n const clamped =\n joined.length > TASK_SUMMARY_MAX_CHARS\n ? joined\n .slice(0, TASK_SUMMARY_MAX_CHARS)\n .replace(/\\s+\\S*$/, '')\n .trimEnd()\n : joined;\n // A mid-line cut still leaves content on that line, so it counts as remaining.\n const remaining = lines.length - kept.length + (clamped === joined ? 0 : 1);\n if (remaining === 0) return `${label}${clamped}`;\n const noun = remaining === 1 ? 'line' : 'lines';\n return `${label}${clamped}…(+${remaining} ${noun} — see ${pointer})`;\n}\n\n/**\n * The line under a task title answers \"what does finishing this look like?\".\n *\n * `done_when` answers it directly, so it wins. But roughly half the open tasks\n * in a real initiative have no `done_when`, and there a blank line reads as \"no\n * context exists\" when the notes are sitting right there on disk — so notes\n * become a bounded, marked fallback rather than nothing. Neither form is the\n * record of truth: both point at the command that prints the field in full.\n */\nfunction renderTaskSummary(task: Task, slug: string): string | undefined {\n const pointer = `\\`active-work task list ${slug} --json\\``;\n const doneWhen = nonBlankLines(task.done_when);\n if (doneWhen.length > 0) {\n return summarizeField('done when: ', doneWhen, pointer);\n }\n const notes = nonBlankLines(task.notes);\n if (notes.length > 0) return summarizeField('notes: ', notes, pointer);\n return undefined;\n}\n\nfunction renderTaskLine(idx: number, task: Task, slug: string): string {\n const meta: string[] = [`priority ${task.priority}`];\n if (task.severity) meta.push(`severity ${task.severity}`);\n if (task.estimate !== undefined) meta.push(`est ${task.estimate}`);\n let line = `${idx}. [${task.id}] (${meta.join(', ')}) ${task.title}`;\n const summary = renderTaskSummary(task, slug);\n if (summary) line += `\\n ${summary}`;\n return line;\n}\n\nfunction renderTopTasks(\n tasks: Task[],\n topN: number,\n slug: string,\n): { body: string; count: number } {\n const openTasks = tasks.filter((t) => t.status === 'open').sort(compareTasksByPriority);\n if (openTasks.length === 0) {\n return { body: '_No open tasks._', count: 0 };\n }\n const shown = openTasks.slice(0, topN);\n return {\n body: shown.map((task, i) => renderTaskLine(i + 1, task, slug)).join('\\n'),\n count: openTasks.length,\n };\n}\n\n/**\n * Recently-done tasks are backward-looking: they cost tokens in every bootstrap\n * but are rarely acted on. A count plus the exact lookup command keeps the\n * signal (\"this much shipped here\") at fixed size and lets the agent pull the\n * detail on the rare occasion it matters.\n */\nfunction renderRecentlyDone(\n tasks: Task[],\n windowDays: number,\n now: Date,\n slug: string,\n): { body: string | null; count: number } {\n const cutoff = now.getTime() - windowDays * MS_PER_DAY;\n const done = tasks\n .filter((t) => t.status === 'done' && t.done_at)\n .filter((t) => {\n const ts = new Date(t.done_at as string).getTime();\n return Number.isFinite(ts) && ts >= cutoff;\n })\n .sort((a, b) => (a.done_at! < b.done_at! ? 1 : -1));\n if (done.length === 0) return { body: null, count: 0 };\n const noun = done.length === 1 ? 'task' : 'tasks';\n const body =\n `${done.length} ${noun} completed — ` +\n `\\`active-work task list ${slug} --status done --json\\``;\n return { body, count: done.length };\n}\n\n/**\n * Notes are capped by count, never by age. A process lesson from six months ago\n * is precisely the one about to be re-learned the hard way, so it must not\n * scroll out of the bootstrap the way \"recently done\" does. The cap keeps the\n * section bounded; one compact line each keeps it cheap.\n */\nconst DURABLE_NOTES_LIMIT = 12;\n\nfunction renderNoteLine(note: LoadedNote): string {\n const { kind, title, created } = note.frontmatter;\n return `- [${kind}] ${title} (${created})`;\n}\n\nfunction renderDurableNotes(loaded: LoadedNotes, slug: string): string | null {\n const { notes, malformed } = loaded;\n if (notes.length === 0 && malformed.length === 0) return null;\n const shown = notes.slice(0, DURABLE_NOTES_LIMIT);\n const lines = shown.map(renderNoteLine);\n const overflow = notes.length - shown.length;\n if (overflow > 0) {\n lines.push(`(+${overflow} older — \\`active-work note list ${slug}\\`)`);\n }\n if (malformed.length > 0) {\n lines.push(\n `(${malformed.length} note file(s) unreadable — run \\`active-work note list ${slug}\\`)`,\n );\n }\n const heading =\n overflow > 0\n ? `# Durable notes (newest ${shown.length} of ${notes.length})`\n : `# Durable notes (${notes.length})`;\n return `${heading}\\n${lines.join('\\n')}`;\n}\n\n/**\n * An empty ledger has two very different meanings and the operator has to be\n * able to tell them apart: a session that ran `wrap --no-loops` positively\n * asserted nothing was hanging, whereas an empty derivation may simply mean\n * nobody ever filed a ledger. Rendering both as \"nothing hanging\" makes the\n * assertion worthless, which is what `no_loops` exists to prevent.\n */\nfunction renderNoOpenLoops(newestSession: LoadedSession | undefined): string {\n if (newestSession?.frontmatter.no_loops === true) {\n return `Nothing hanging — the ${endedDate(newestSession.ended)} session asserted the ledger is clear.`;\n }\n return 'Nothing hanging — no unresolved loops, but no session has asserted the ledger is clear.';\n}\n\n/**\n * A file that would not parse both drops the loops it opened and re-opens the\n * ones it closed, so a silently short ledger is worse than a noisy one.\n */\nfunction malformedNote(malformed: MalformedSession[]): string {\n if (malformed.length === 0) return '';\n return ` (${malformed.length} session file(s) unreadable — run \\`active-work doctor\\`)`;\n}\n\n/**\n * A task file that would not parse is missing from the list entirely, so the\n * heading has to say so — otherwise a shorter list looks like less work.\n */\nfunction malformedTaskNote(malformed: MalformedTask[]): string {\n if (malformed.length === 0) return '';\n const files = malformed.map((m) => m.file).join(', ');\n return ` — ${malformed.length} task file(s) unreadable (${files}); run \\`active-work doctor\\``;\n}\n\n/**\n * Whether the text already opens with `ref`, so prefixing would print it twice.\n *\n * Only a match at the head counts. A loop filed against `AW-65` whose text\n * opens `AW-59 is done` is a ledger/text *disagreement* the operator needs to\n * see, not noise to collapse — suppressing there would hide which task the loop\n * actually concerns. The trailing boundary check keeps `AW-2` from matching text\n * about `AW-28` (AW-71).\n */\nfunction textOpensWithRef(text: string, ref: string, kind: OpenLoop['kind']): boolean {\n const head = text.replace(/^\\s*(PR\\s*)?#?/i, '');\n // A pasted `.../pull/57` at the head is the same restatement in another form.\n if (kind === 'pr' && normalizePrRef(head.split(/\\s/)[0] ?? '') === ref) return true;\n if (!head.toLowerCase().startsWith(ref.toLowerCase())) return false;\n const next = head.charAt(ref.length);\n return next === '' || !/[A-Za-z0-9]/.test(next);\n}\n\n/** Prefix the loop text with its target so a task/PR loop is actionable at a glance. */\nfunction loopLabel(loop: OpenLoop): string {\n if (loop.targetRef === undefined) return loop.text;\n const ref = loop.kind === 'pr' ? normalizePrRef(loop.targetRef) : loop.targetRef;\n if (textOpensWithRef(loop.text, ref, loop.kind)) return loop.text;\n return loop.kind === 'pr' ? `PR #${ref} ${loop.text}` : `${ref} ${loop.text}`;\n}\n\n/**\n * Loops are already unresolved and oldest-first; `ageDays` comes from the\n * derivation so the render never recomputes time. The full `ref` is printed\n * rather than an abbreviated session id because it is the handle `wrap\n * --resolve` takes.\n */\nfunction renderOpenLoops(\n loops: OpenLoop[],\n malformed: MalformedSession[],\n newestSession: LoadedSession | undefined,\n): string {\n const note = malformedNote(malformed);\n if (loops.length === 0) {\n return `# Open loops${note}\\n${renderNoOpenLoops(newestSession)}`;\n }\n const labels = loops.map(loopLabel);\n const ageWidth = Math.max(...loops.map((l) => String(l.ageDays).length));\n const labelWidth = Math.max(...labels.map((l) => l.length));\n const lines = loops.map((loop, i) => {\n const age = `[${String(loop.ageDays).padStart(ageWidth)}d]`;\n const label = labels[i]!.padEnd(labelWidth);\n const from = loop.openedAt.slice(0, 10);\n return `- ${age} ${label} (from ${from}, ref ${loop.ref})`;\n });\n const oldest = loops[0]!.ageDays;\n return `# Open loops (${loops.length} hanging, oldest ${oldest}d)${note}\\n${lines.join('\\n')}`;\n}\n\nconst WRAP_DIRECTIVE =\n 'Update tasks via `active-work task done` and close the session out via `active-work wrap` when wrapping up — it records the session, files the loops you leave open, and stamps the brief in one step.';\n\n/**\n * A hanging loop is thread continuity nobody else will pick up, so it outranks\n * the general backlog — the backlog is still there next session, whereas the\n * context that makes a loop cheap to close decays.\n *\n * The loop-first half is only emitted when the ledger actually has entries:\n * with zero loops the render above already said \"nothing hanging\", and telling\n * a session to triage loops would send it hunting for something that isn't\n * there.\n */\nfunction renderClosingInstruction(openLoops: OpenLoop[]): string {\n if (openLoops.length === 0) {\n return `Work the top task unless redirected. ${WRAP_DIRECTIVE}`;\n }\n const count = openLoops.length;\n const noun = count === 1 ? 'loop' : 'loops';\n const verb = count === 1 ? 'is' : 'are';\n return (\n `Start with the open ${noun}: ${count} ${verb} still hanging from prior sessions, ` +\n `and unfinished threads take precedence over the backlog. Work them first, citing each ` +\n `one by the \\`ref\\` printed under \"Open loops\", and pass every loop you settle to ` +\n `\\`active-work wrap --resolves\\` with outcome \\`done\\` or \\`abandoned\\` — deciding not to ` +\n `do a loop still closes it. Once the loops are handled, or if the user redirects, work ` +\n `the top task by priority. ${WRAP_DIRECTIVE}`\n );\n}\n\n/**\n * Only abandonments are rendered, and only recent ones. A loop closed `done`\n * needs no explanation — the work happened. A loop closed `abandoned` is a\n * decision not to do something, and a future session that cannot see it will\n * propose the abandoned thing again.\n */\nfunction renderAbandonedLoops(resolved: ResolvedLoop[], windowDays: number): string | null {\n const abandoned = resolved.filter(\n (loop) => loop.outcome === 'abandoned' && loop.ageDays <= windowDays,\n );\n if (abandoned.length === 0) return null;\n const lines = abandoned.map((loop) => {\n const head = `- ${loop.text} (dropped ${loop.closedAt.slice(0, 10)})`;\n return loop.note ? `${head}\\n why: ${loop.note}` : head;\n });\n return `# Abandoned in the last ${windowDays} days (${abandoned.length})\\n${lines.join('\\n')}`;\n}\n\nconst LIVE_RENDER_LIMIT = 10;\n\nfunction renderStaticBranchLine(branch: BranchEntry): string {\n const head = `- ${branch.name} (${branch.repo})`;\n return branch.note ? `${head} — ${branch.note}` : head;\n}\n\n/**\n * The PR title and url were fetched and then dropped, which made the branch\n * block un-actionable: `PR #12 OPEN` tells a session nothing about what the PR\n * is for and gives it nowhere to look. The same goes for `last_commit_iso` —\n * without it, a branch that has been idle for two months reads identically to\n * one touched an hour ago. Both are carried on the line now; the url goes on a\n * continuation line so the primary line stays scannable.\n */\nfunction renderLiveBranchLine(status: LiveBranchStatus): string {\n const parts: string[] = [`- ${status.name} (${status.repo})`];\n if (!status.present) {\n parts.push('[missing locally]');\n } else if (status.ahead !== null && status.behind !== null) {\n parts.push(`+${status.ahead}/-${status.behind}`);\n }\n if (status.last_commit_iso) {\n parts.push(`last commit ${status.last_commit_iso.slice(0, 10)}`);\n }\n if (status.pr) {\n const checks = status.pr.checks ? ` ${status.pr.checks}` : '';\n parts.push(`PR #${status.pr.number} ${status.pr.state}${checks}`);\n }\n let line = parts.join(' ');\n if (status.note) line += ` — ${status.note}`;\n if (status.pr) {\n line += `\\n PR: ${status.pr.title} — ${status.pr.url}`;\n }\n return line;\n}\n\nconst WORKTREE_RENDER_LIMIT = 8;\n\nfunction renderWorktreeLine(entry: WorktreeEntry): string {\n const parts: string[] = [`- ${entry.name}${entry.default ? ' (default)' : ''}: ${entry.path}`];\n if (entry.branch) parts.push(`[${entry.branch}]`);\n if (entry.pr) parts.push(`PR #${entry.pr}`);\n const trailer = entry.holding ?? entry.note;\n return trailer ? `${parts.join(' ')} — ${trailer}` : parts.join(' ');\n}\n\n/**\n * Only *registered* worktrees get a line.\n *\n * `worktrees[]` mixes two populations (see `src/schemas/artifacts.ts`): entries\n * the operator named and registered — these resolve `aw <slug>`'s cwd — and\n * entries `wrap` merely swept out of git. Listing every swept tree would bury\n * the two the session actually launches into under a pile of unrelated repos\n * the operator never asked about. The observed ones still get counted, so their\n * existence is visible without their noise, and the count names the command\n * that shows them.\n */\nfunction renderWorktrees(artifacts: Artifacts, slug: string): string | null {\n const registered = artifacts.worktrees.filter((w) => w.name !== undefined);\n const observed = artifacts.worktrees.length - registered.length;\n if (registered.length === 0 && observed === 0) return null;\n\n const lines: string[] = [];\n const shown = registered.slice(0, WORKTREE_RENDER_LIMIT);\n if (shown.length > 0) {\n lines.push(...shown.map(renderWorktreeLine));\n } else {\n lines.push('_None registered._');\n }\n const overflow = registered.length - shown.length;\n if (overflow > 0) {\n lines.push(`(+${overflow} more registered — \\`active-work artifact list ${slug}\\`)`);\n }\n if (observed > 0) {\n const noun = observed === 1 ? 'worktree' : 'worktrees';\n lines.push(\n `(+${observed} observed ${noun} swept from git, not registered — \\`active-work artifact list ${slug}\\`)`,\n );\n }\n return `Worktrees (registered):\\n${lines.join('\\n')}`;\n}\n\nfunction renderStashes(artifacts: Artifacts): string | null {\n if (artifacts.stashes.length === 0) return null;\n return artifacts.stashes\n .map((s) => `- ${s.repo}: ${s.label}${s.sha ? ` (${s.sha.slice(0, 12)})` : ''}`)\n .join('\\n');\n}\n\nfunction renderStaticArtifacts(artifacts: Artifacts, slug: string): string | null {\n const sections: string[] = [];\n if (artifacts.branches.length > 0) {\n const branchLines = artifacts.branches.map(renderStaticBranchLine).join('\\n');\n sections.push(`Branches:\\n${branchLines}`);\n }\n const worktreeBody = renderWorktrees(artifacts, slug);\n if (worktreeBody) sections.push(worktreeBody);\n const stashBody = renderStashes(artifacts);\n if (stashBody) sections.push(`Stashes:\\n${stashBody}`);\n return sections.length > 0 ? sections.join('\\n\\n') : null;\n}\n\nfunction renderLiveArtifacts(\n artifacts: Artifacts,\n statuses: LiveBranchStatus[],\n slug: string,\n): string | null {\n const sections: string[] = [];\n if (statuses.length > 0) {\n const shown = statuses.slice(0, LIVE_RENDER_LIMIT);\n const lines = shown.map(renderLiveBranchLine).join('\\n');\n const overflow = statuses.length - shown.length;\n const suffix = overflow > 0 ? `\\n(+${overflow} more)` : '';\n sections.push(`Branches (live):\\n${lines}${suffix}`);\n } else if (artifacts.branches.length > 0) {\n const branchLines = artifacts.branches.map(renderStaticBranchLine).join('\\n');\n sections.push(`Branches:\\n${branchLines}`);\n }\n const worktreeBody = renderWorktrees(artifacts, slug);\n if (worktreeBody) sections.push(worktreeBody);\n const stashBody = renderStashes(artifacts);\n if (stashBody) sections.push(`Stashes:\\n${stashBody}`);\n return sections.length > 0 ? sections.join('\\n\\n') : null;\n}\n\n/**\n * Default fetcher used when the caller doesn't supply one. Mirrors the\n * read logic in `artifact.status` but is bounded in parallelism and\n * swallows per-branch errors silently — bootstrap never throws on artifact\n * issues.\n */\nasync function defaultLiveStatusFetcher(branches: BranchEntry[]): Promise<LiveBranchStatus[]> {\n const results: LiveBranchStatus[] = [];\n const limit = Math.min(branches.length, LIVE_RENDER_LIMIT);\n for (let i = 0; i < limit; i++) {\n results.push(await fetchOne(branches[i]!));\n }\n return results;\n}\n\nasync function fetchOne(branch: BranchEntry): Promise<LiveBranchStatus> {\n const out: LiveBranchStatus = {\n repo: branch.repo,\n name: branch.name,\n ...(branch.note ? { note: branch.note } : {}),\n present: false,\n last_commit_iso: null,\n ahead: null,\n behind: null,\n pr: null,\n };\n const repoPath = resolveLocalRepoPath(branch.repo);\n const git = getGitRunner();\n const gh = getGhRunner();\n\n if (repoPath) {\n try {\n const exists = await git('git', [\n '-C',\n repoPath,\n 'rev-parse',\n '--verify',\n `refs/heads/${branch.name}`,\n ]);\n out.present = exists.code === 0;\n } catch {\n // leave present=false\n }\n if (out.present) {\n try {\n const lc = await git('git', ['-C', repoPath, 'log', '-1', '--format=%cI', branch.name]);\n if (lc.code === 0) {\n const s = lc.stdout.trim();\n out.last_commit_iso = s.length > 0 ? s : null;\n }\n } catch {\n // skip\n }\n for (const base of ['main', 'master']) {\n try {\n const verify = await git('git', [\n '-C',\n repoPath,\n 'rev-parse',\n '--verify',\n `refs/remotes/origin/${base}`,\n ]);\n if (verify.code !== 0) continue;\n const counts = await git('git', [\n '-C',\n repoPath,\n 'rev-list',\n '--left-right',\n '--count',\n `origin/${base}...${branch.name}`,\n ]);\n if (counts.code === 0) {\n const parts = counts.stdout.trim().split(/\\s+/);\n if (parts.length === 2) {\n const b = Number(parts[0]);\n const a = Number(parts[1]);\n if (Number.isFinite(a) && Number.isFinite(b)) {\n out.ahead = a;\n out.behind = b;\n }\n }\n }\n break;\n } catch {\n // continue / give up\n }\n }\n }\n }\n\n try {\n const orgRepo = await resolveOrgRepo(branch.repo);\n if (orgRepo) {\n const res = await gh('gh', [\n 'pr',\n 'list',\n '--head',\n branch.name,\n '--repo',\n orgRepo,\n '--json',\n 'number,state,title,url,statusCheckRollup',\n '--limit',\n '1',\n ]);\n if (res.code === 0) {\n const parsed = JSON.parse(res.stdout) as Array<{\n number?: number;\n state?: string;\n title?: string;\n url?: string;\n statusCheckRollup?: Array<{ conclusion?: string; state?: string }>;\n }>;\n if (Array.isArray(parsed) && parsed.length > 0) {\n const first = parsed[0]!;\n if (\n typeof first.number === 'number' &&\n typeof first.state === 'string' &&\n typeof first.title === 'string' &&\n typeof first.url === 'string'\n ) {\n const rollup = first.statusCheckRollup ?? [];\n let pass = 0;\n let fail = 0;\n let pending = 0;\n for (const entry of rollup) {\n const tag = (entry.conclusion ?? entry.state ?? '').toUpperCase();\n if (tag === 'SUCCESS') pass++;\n else if (tag === 'FAILURE' || tag === 'CANCELLED' || tag === 'TIMED_OUT') fail++;\n else pending++;\n }\n let checks: string | undefined;\n if (rollup.length > 0) {\n if (fail > 0) checks = `fail (${fail}/${rollup.length})`;\n else if (pending > 0) checks = `pending (${pending}/${rollup.length})`;\n else checks = `pass (${pass}/${rollup.length})`;\n }\n out.pr = {\n number: first.number,\n state: first.state,\n title: first.title,\n url: first.url,\n ...(checks ? { checks } : {}),\n };\n }\n }\n }\n }\n } catch {\n // PR lookup is best-effort; leave out.pr as null.\n }\n\n return out;\n}\n\nfunction endedDate(iso: string): string {\n return iso.slice(0, 10);\n}\n\n/**\n * Sessions on a non-canonical track that ended after the narrative session\n * (the one rendered in `# Last session`).\n *\n * These ran alongside the mainline thread, so they're worth surfacing — but\n * only as pointers: full bodies would crowd out the mainline context. The\n * narrative session itself is excluded so it isn't both the mainline block\n * and a parallel pointer (matters when it was chosen via the no-canonical\n * fallback, since it's then a non-canonical session too).\n */\nfunction selectParallelSessions(\n sessions: LoadedSession[],\n narrativeSession: LoadedSession | undefined,\n): LoadedSession[] {\n if (!narrativeSession) return [];\n const cutoff = new Date(narrativeSession.frontmatter.ended).getTime();\n return sessions.filter(\n (s) =>\n s !== narrativeSession &&\n s.frontmatter.track !== 'canonical' &&\n new Date(s.frontmatter.ended).getTime() > cutoff,\n );\n}\n\nfunction renderParallelSessions(sessions: LoadedSession[]): string | null {\n if (sessions.length === 0) return null;\n const lines = sessions.map((s) => {\n const { ended, session_id, track } = s.frontmatter;\n const summary = firstLine(s.body) ?? '_(empty session body)_';\n return `- ${endedDate(ended)} (${track}, ${session_id}) — ${summary}`;\n });\n return `# Parallel sessions since then\\n${lines.join('\\n')}`;\n}\n\nconst MS_PER_MINUTE = 60_000;\n\n/**\n * Short elapsed form for sibling sessions (\"just started\", \"12m\", \"2h 5m\").\n *\n * `formatTimeSince` is the house helper for everything else in this file, but\n * its floor is one hour (\"just now\"), and sibling sessions are minutes old\n * almost by definition — the whole point is that the other one is *still\n * running*. Rendering every one of them as \"just now\" would erase the only\n * ordering signal the operator has for deciding which session started first.\n */\nexport function formatElapsedShort(from: Date, now: Date): string {\n const diffMs = now.getTime() - from.getTime();\n if (!Number.isFinite(diffMs) || diffMs < MS_PER_MINUTE) return 'just started';\n const minutes = Math.floor(diffMs / MS_PER_MINUTE);\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n const rest = minutes % 60;\n return rest === 0 ? `${hours}h ago` : `${hours}h ${rest}m ago`;\n}\n\n/**\n * Whether one of the initiative's push channels is agent-chat.\n *\n * Targets arrive in the three shapes `buildChannelArgs` accepts — a bare server\n * name, `server:<name>`, `plugin:<name>@<marketplace>` — so the name is matched\n * after stripping the prefix and any marketplace suffix.\n */\nfunction hasAgentChatChannel(brief: BriefFrontmatter): boolean {\n return (brief.channels ?? []).some((raw) => {\n const name = raw.replace(/^(?:server|plugin):/, '').split('@')[0] ?? '';\n return name === 'agent-chat';\n });\n}\n\n/**\n * One line per sibling, with confidence wording matched to the lease mode.\n *\n * The distinction is the whole point of having two modes: a `launcher` lease\n * names a process we just signalled, so it can be stated as fact, while a\n * `oneshot` lease is a TTL guess about a process that left no handle behind.\n * Rendering the guess in the same voice as the fact would train the reader to\n * discount both.\n */\nfunction renderSiblingLine(sibling: SiblingSession, now: Date): string {\n const elapsed = formatElapsedShort(new Date(sibling.started), now);\n const where = `in \\`${sibling.cwd}\\``;\n if (sibling.mode === 'launcher') {\n const pid = sibling.pid === undefined ? '' : ` (pid ${sibling.pid})`;\n return `- started ${elapsed} ${where} — launched via \\`aw\\`, process still running${pid}.`;\n }\n return `- bootstrapped ${elapsed} ${where} — no live process to confirm, so it may have already exited.`;\n}\n\nconst SIBLING_HEADING = '# Another session may already be live on this initiative';\n\n/**\n * Warn, at t=0, that this may be the second session on the same initiative.\n *\n * Pure: the probe happens in `assembleBootstrap`. Renders nothing when there\n * are no siblings — with an empty list the prompt must be byte-identical to one\n * assembled without this feature at all.\n */\nexport function renderSiblingSessions(\n siblings: SiblingSession[],\n brief: BriefFrontmatter,\n topTaskTitle: string | undefined,\n now: Date,\n): string {\n if (siblings.length === 0) return '';\n const lines = siblings.map((s) => renderSiblingLine(s, now));\n const topTask = topTaskTitle ? ` (\"${topTaskTitle}\")` : '';\n lines.push(\n `Before starting the top task${topTask}, ask the user which session owns it. ` +\n 'If this is the second session, take distinct scope and record it with ' +\n '`active-work wrap --track adhoc` — not `canonical`, which would bury the ' +\n \"other session's mainline thread in the next bootstrap.\",\n );\n if (hasAgentChatChannel(brief)) {\n lines.push(\n 'This initiative carries an agent-chat channel: register under a name that ' +\n 'distinguishes you from the other session and coordinate scope there.',\n );\n }\n return `${SIBLING_HEADING}\\n${lines.join('\\n')}`;\n}\n\n/**\n * Surface a non-`focused` initiative state.\n *\n * Bootstrap otherwise reads identically for a paused initiative and a focused\n * one, so a session resumed on a backburnered or paused workstream picks up its\n * top task and starts executing — exactly the thing pausing it was meant to\n * stop. `restart_trigger` is included because it is the condition the operator\n * wrote down as \"what would make this current again\", and it is the only way\n * the session can tell whether resuming is actually warranted.\n */\nfunction renderBriefState(brief: BriefFrontmatter, now: Date): string | null {\n if (brief.state === 'focused') return null;\n const lines: string[] = [];\n if (brief.paused_since) {\n const since = formatTimeSince(new Date(brief.paused_since), now);\n lines.push(`Paused since ${brief.paused_since} (${since}).`);\n }\n if (brief.restart_trigger) {\n lines.push(`Restart trigger: ${brief.restart_trigger}`);\n }\n lines.push(\n `This initiative is \\`${brief.state}\\`, not \\`focused\\` — confirm with the user before treating its tasks as current work.`,\n );\n return `# Initiative state: ${brief.state}\\n${lines.join('\\n')}`;\n}\n\nasync function loadBrief(\n initiativeDir: string,\n slug: string,\n): Promise<{ frontmatter: BriefFrontmatter; body: string }> {\n const briefPath = path.join(initiativeDir, 'brief.md');\n try {\n return await readMarkdownWithSchema(briefPath, BriefFrontmatterSchema);\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n throw new NotFoundError(`Initiative '${slug}' has no readable brief.md (${reason})`);\n }\n}\n\n/**\n * Build the bootstrap prompt for `slug`.\n *\n * The prompt is composed entirely from files under the initiative directory;\n * missing artifacts (no sessions yet, no open tasks, no PRs) degrade\n * gracefully to omitted or \"none\" sections.\n */\nexport async function assembleBootstrap(input: BootstrapInput): Promise<BootstrapOutput> {\n const {\n activeRoot,\n slug,\n now = new Date(),\n topNTasks = DEFAULT_TOP_N_TASKS,\n recentlyDoneDays = DEFAULT_RECENTLY_DONE_DAYS,\n includeLiveStatus = true,\n liveStatusFetcher,\n archivedTaskIds,\n adhoc = false,\n detectSiblings = true,\n siblingProbe = readLiveLeases,\n ownLeaseId,\n } = input;\n\n const initiativeDir = path.join(activeRoot, slug);\n const { frontmatter: brief, body: briefBody } = await loadBrief(initiativeDir, slug);\n\n const [loaded, loadedTasks, loadedArtifacts, notes] = await Promise.all([\n loadSessionsNewestFirst(initiativeDir),\n loadTasks(initiativeDir),\n loadArtifacts(initiativeDir),\n loadNotesFromDir(initiativeDir),\n ]);\n const { sessions, malformed } = loaded;\n const { tasks, malformed: malformedTasks } = loadedTasks;\n const { artifacts, error: artifactsError } = loadedArtifacts;\n\n // `mergedPrs` is deliberately unsupplied: derivation must stay offline\n // because bootstrap runs it on every launch.\n const openLoops = deriveOpenLoopsFrom(loaded, { now, tasks });\n const resolvedLoops = deriveResolvedLoopsFrom(loaded, { now, tasks });\n\n const latestCanonical = sessions.find((s) => s.frontmatter.track === 'canonical');\n // No canonical session recorded for this initiative — fall back to the\n // newest session of any track rather than reporting \"no sessions\" when\n // sidecar/adhoc sessions exist (AW-42).\n const narrativeSession = latestCanonical ?? sessions[0];\n const usedFallbackTrack = !latestCanonical && narrativeSession !== undefined;\n const parallelBody = renderParallelSessions(selectParallelSessions(sessions, narrativeSession));\n const briefExcerpt =\n truncateLines(briefBody, BRIEF_BODY_MAX_LINES, path.join(initiativeDir, 'brief.md')) ||\n '_(no brief body)_';\n const { body: tasksBody, count: openTaskCount } = renderTopTasks(tasks, topNTasks, slug);\n const { body: recentlyDoneBody, count: recentlyDoneCount } = renderRecentlyDone(\n tasks,\n recentlyDoneDays,\n now,\n slug,\n );\n let artifactsBody: string | null = null;\n if (!includeLiveStatus || artifacts.branches.length === 0) {\n artifactsBody = renderStaticArtifacts(artifacts, slug);\n } else {\n const fetcher = liveStatusFetcher ?? defaultLiveStatusFetcher;\n try {\n const statuses = await fetcher(artifacts.branches);\n artifactsBody = renderLiveArtifacts(artifacts, statuses, slug);\n } catch {\n // Live fetch failed entirely — degrade to static rendering.\n artifactsBody = renderStaticArtifacts(artifacts, slug);\n }\n }\n\n const timeSinceHuman = narrativeSession\n ? formatTimeSince(new Date(narrativeSession.frontmatter.ended), now)\n : undefined;\n\n // Fail open, exactly like the live-status fetcher above: a probe that throws\n // (unreadable lease dir, hostile permissions) degrades to \"no siblings\"\n // rather than costing the caller their whole bootstrap.\n let siblings: SiblingSession[] = [];\n if (detectSiblings) {\n try {\n siblings = await siblingProbe({\n activeRoot,\n slug,\n now,\n ...(ownLeaseId ? { excludeLeaseId: ownLeaseId } : {}),\n });\n } catch {\n siblings = [];\n }\n }\n const topTaskTitle = tasks\n .filter((t) => t.status === 'open')\n .sort(compareTasksByPriority)[0]?.title;\n\n const sections: string[] = [];\n sections.push(\n adhoc\n ? `Starting an ad-hoc session on \\`${slug}\\` (${brief.title}). This session is scoped to ad-hoc work related to this workstream — not necessarily its handoff or current top task. The context below is background so you're oriented; wait for the user to describe the specific ad-hoc task before acting.`\n : `Starting a session on \\`${slug}\\` (${brief.title}).`,\n );\n const siblingBody = renderSiblingSessions(siblings, brief, topTaskTitle, now);\n if (siblingBody) sections.push(siblingBody);\n const stateBody = renderBriefState(brief, now);\n if (stateBody) sections.push(stateBody);\n sections.push(`# Why we're doing this\\n${briefExcerpt}`);\n sections.push(renderOpenLoops(openLoops, malformed, sessions[0]));\n\n const abandonedBody = renderAbandonedLoops(resolvedLoops, recentlyDoneDays);\n if (abandonedBody) sections.push(abandonedBody);\n\n if (narrativeSession) {\n const sessionExcerpt =\n truncateLines(\n narrativeSession.body,\n SESSION_BODY_MAX_LINES,\n path.join(initiativeDir, 'sessions', `${narrativeSession.sessionFile}.md`),\n ) || '_(empty session body)_';\n const ended = endedDate(narrativeSession.frontmatter.ended);\n // Label the heading with the track when it's not canonical, so a\n // fallback session (no canonical recorded yet) isn't mistaken for\n // mainline continuity.\n const trackLabel = usedFallbackTrack ? ` (${narrativeSession.frontmatter.track})` : '';\n sections.push(\n `# Last session${trackLabel} (${ended}, ${narrativeSession.frontmatter.session_id}) — ${timeSinceHuman}\\n${sessionExcerpt}`,\n );\n } else {\n sections.push(`# Last session\\nNo previous sessions recorded.`);\n }\n\n if (parallelBody) sections.push(parallelBody);\n\n sections.push(\n `# Tasks (top ${topNTasks} open by priority)${malformedTaskNote(malformedTasks)}\\n${tasksBody}`,\n );\n\n if (recentlyDoneBody) {\n sections.push(`# Recently done (last ${recentlyDoneDays} days)\\n${recentlyDoneBody}`);\n }\n\n if (archivedTaskIds && archivedTaskIds.length > 0) {\n sections.push(\n `# Archived (housekeeping)\\nMoved ${archivedTaskIds.length} stale done task(s) to tasks/archive/: ${archivedTaskIds.join(', ')}`,\n );\n }\n\n const notesBody = renderDurableNotes(notes, slug);\n if (notesBody) sections.push(notesBody);\n\n if (artifactsError) {\n const artifactsPath = path.join(initiativeDir, 'artifacts.yml');\n sections.push(\n `# Open artifacts\\n_${artifactsPath} exists but could not be read (${artifactsError}). Branch and stash context is MISSING from this bootstrap — do not treat the working tree as clean. Run \\`active-work doctor\\`._`,\n );\n } else if (artifactsBody) {\n sections.push(`# Open artifacts\\n${artifactsBody}`);\n }\n\n const bootstrapAt = nowIso();\n const todayStr = today();\n const contextLines = [`- Today: ${todayStr}`, `- Bootstrap: ${bootstrapAt}`];\n if (timeSinceHuman) {\n contextLines.push(`- Time since last session: ${timeSinceHuman}`);\n }\n sections.push(`# Context\\n${contextLines.join('\\n')}`);\n\n sections.push(\n adhoc\n ? `This is an ad-hoc session: treat the context above as background, not a directive. Do not assume we're continuing the top task or the handoff — the user will describe the specific ad-hoc task. Once they do, work it with the workstream context in mind. If it turns out to be substantive, still capture it via \\`active-work task add\\` / \\`active-work wrap --track adhoc\\`. The \\`--track adhoc\\` flag is required: this session runs alongside the mainline thread, and recording it as canonical would bury the real last session for the next bootstrap.`\n : renderClosingInstruction(openLoops),\n );\n\n const prompt = sections.join('\\n\\n') + '\\n';\n\n const metadata: BootstrapMetadata = {\n slug,\n brief_title: brief.title,\n open_task_count: openTaskCount,\n open_loop_count: openLoops.length,\n recently_done_count: recentlyDoneCount,\n bootstrap_at: bootstrapAt,\n };\n if (narrativeSession) {\n metadata.last_session = {\n filename: `${narrativeSession.sessionFile}.md`,\n ended: narrativeSession.frontmatter.ended,\n };\n }\n if (timeSinceHuman) {\n metadata.time_since_last_session_human = timeSinceHuman;\n }\n if (siblings.length > 0) {\n metadata.sibling_sessions = siblings.length;\n }\n\n return { prompt, metadata };\n}\n","import { z } from 'zod';\n\nconst ISO_DATE_REGEX = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nconst isValidIsoDate = (value: string): boolean => {\n if (!ISO_DATE_REGEX.test(value)) return false;\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) return false;\n return parsed.toISOString().slice(0, 10) === value;\n};\n\nconst isoDate = z\n .string()\n .refine(isValidIsoDate, { message: 'Must be a valid zero-padded YYYY-MM-DD date' });\n\nconst isoDateOrNull = z.union([isoDate, z.null()]);\n\nexport const TaskSchema = z.object({\n id: z.string().regex(/^[A-Z][A-Z0-9]*-\\d+$/, {\n message: 'id must match /^[A-Z][A-Z0-9]*-\\\\d+$/ (e.g. EC-1)',\n }),\n title: z.string().min(1),\n priority: z.number().int().positive(),\n severity: z.enum(['critical', 'high', 'medium', 'low']).optional(),\n estimate: z.number().positive().optional(),\n done_when: z.string().min(1).optional(),\n status: z.enum(['open', 'done']),\n tags: z.array(z.string()).optional(),\n notes: z.string().optional(),\n created: isoDate,\n updated: isoDate,\n done_at: isoDateOrNull,\n});\n\nexport type Task = z.infer<typeof TaskSchema>;\n","/**\n * Open loops are *derived*, never stored: each session records the loops it\n * opens (`next_steps`) and the loops it closes (`resolves`), and live state is\n * whatever is left unresolved. There is no denormalized copy, so there is\n * nothing that can go stale.\n *\n * Derivation deliberately ignores `track` — ad-hoc and sidecar sessions open\n * real loops. `track` only selects which session is the narrative \"last\n * mainline session\"; it must not gate the ledger.\n */\n\nimport { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport YAML from 'yaml';\nimport {\n SessionFrontmatterSchema,\n type NextStep,\n type SessionFrontmatter,\n} from '../schemas/session.js';\nimport type { Task } from '../schemas/task.js';\n\nconst MS_PER_DAY = 24 * 60 * 60 * 1000;\nconst FRONTMATTER_DELIM = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/;\n\nexport interface OpenLoop {\n /**\n * Global reference: `<session file stem>#<next_step id>`. The stem, not\n * `session_id`: a session that records more than once produces several files\n * sharing one `session_id` (`pickAvailableFilename` appends `-1`, `-2`), so\n * only the filename is unique within an initiative.\n */\n ref: string;\n text: string;\n kind: 'task' | 'pr' | 'prose';\n /** The yaml `ref` field of the next_step (task id or PR number), when present. */\n targetRef?: string;\n /** Session filename without `.md` — the identity half of `ref`. */\n sessionFile: string;\n /** Frontmatter `session_id`, kept for display; not unique. */\n sessionId: string;\n /** ISO timestamp — the originating session's `ended`. */\n openedAt: string;\n /** Whole days between `openedAt` and the injected `now`. */\n ageDays: number;\n}\n\nexport interface DeriveOptions {\n /** Injected for determinism; this module never calls `new Date()`. */\n now: Date;\n /** Auto-closes `kind: 'task'` loops whose `ref` names a done task. */\n tasks?: Task[];\n /**\n * PR refs known merged, supplied by the caller. Derivation stays pure and\n * offline (bootstrap runs it on every launch) and `artifacts.yml` persists no\n * PR state, so without this list PR loops stay open until resolved manually.\n */\n mergedPrs?: string[];\n}\n\n/**\n * Why a `resolves` entry did not close a loop. The kinds have different\n * remedies, so they must not be conflated: `missing` is a bad ref, `not-prior`\n * is a correct ref filed too early (re-file it from a later session), `self` is\n * a session trying to close its own loop.\n */\nexport type DanglingKind = 'missing' | 'not-prior' | 'self';\n\nexport interface DanglingResolve {\n /** Stem of the session file that recorded the bad `resolves` entry. */\n sessionFile: string;\n ref: string;\n kind: DanglingKind;\n}\n\n/** A file under `sessions/` that could not be parsed as a session. */\nexport interface MalformedSession {\n /** Filename including `.md`; a malformed file may have no usable identity. */\n file: string;\n reason: string;\n}\n\nexport interface SessionIssues {\n dangling: DanglingResolve[];\n malformed: MalformedSession[];\n}\n\n/**\n * A loop that was closed, and how.\n *\n * `outcome` and `note` were write-only until AW-59: derivation reduced every\n * resolve to the bare fact that a ref had closed, so a loop deliberately\n * abandoned — with the reason the schema *requires* for exactly that case —\n * explained itself to nobody. An abandonment is a decision, and decisions are\n * the part of a ledger worth keeping.\n */\nexport interface ResolvedLoop {\n ref: string;\n text: string;\n kind: 'task' | 'pr' | 'prose';\n outcome: 'done' | 'abandoned';\n note?: string;\n /** Stem of the session that opened the loop. */\n sessionFile: string;\n /** Stem of the session that closed it. */\n closedBy: string;\n openedAt: string;\n /** ISO timestamp — the closing session's `ended`. */\n closedAt: string;\n /** Whole days between `closedAt` and the injected `now`. */\n ageDays: number;\n}\n\n/**\n * A session file that parsed. This is the single in-memory representation of a\n * session: bootstrap renders from it and derivation reasons over it, so the two\n * can never disagree about which files parsed or what they contained.\n */\nexport interface LoadedSession {\n /** Filename without `.md` — the identity half of a loop `ref`. */\n sessionFile: string;\n sessionId: string;\n ended: string;\n endedMs: number;\n frontmatter: SessionFrontmatter;\n /** Markdown after the frontmatter block; rendered by bootstrap. */\n body: string;\n}\n\n/** Everything one pass over `sessions/` yielded, including what it could not read. */\nexport interface LoadedSessions {\n sessions: LoadedSession[];\n malformed: MalformedSession[];\n}\n\ninterface LoopEntry {\n ref: string;\n step: NextStep;\n session: LoadedSession;\n}\n\n/** How one loop was closed, carried through derivation instead of discarded. */\ninterface Resolution {\n outcome: 'done' | 'abandoned';\n note?: string;\n closedBy: string;\n closedAt: string;\n /** `closedAt` as an instant. Ordering must never compare the raw strings. */\n closedAtMs: number;\n}\n\ninterface Analysis {\n loops: LoopEntry[];\n resolutions: Map<string, Resolution>;\n dangling: DanglingResolve[];\n malformed: MalformedSession[];\n}\n\ntype LoadResult = { ok: true; session: LoadedSession } | { ok: false; problem: MalformedSession };\n\nfunction describe(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/**\n * Best-effort by contract — never throws. But an unparseable file is *not* the\n * same as an absent one: skipping it silently drops the loops it opened and\n * re-opens the ones it closed, so the reason travels back to the caller.\n */\nasync function loadSession(fullPath: string, sessionFile: string): Promise<LoadResult> {\n const fail = (reason: string): LoadResult => ({\n ok: false,\n problem: { file: `${sessionFile}.md`, reason },\n });\n let raw: string;\n try {\n raw = await fs.readFile(fullPath, 'utf8');\n } catch (err) {\n return fail(`unreadable: ${describe(err)}`);\n }\n const match = FRONTMATTER_DELIM.exec(raw);\n if (!match) return fail('no frontmatter block');\n let parsed: unknown;\n try {\n parsed = YAML.parse(match[1] ?? '');\n } catch (err) {\n return fail(`invalid YAML: ${describe(err)}`);\n }\n const result = SessionFrontmatterSchema.safeParse(parsed);\n if (!result.success) return fail(`invalid frontmatter: ${summarizeIssues(result.error)}`);\n return { ok: true, session: toLoadedSession(sessionFile, result.data, match[2] ?? '') };\n}\n\nfunction summarizeIssues(error: {\n issues: readonly { readonly path: readonly PropertyKey[]; readonly message: string }[];\n}): string {\n return error.issues\n .map((issue) => `${issue.path.join('.') || '(root)'}: ${issue.message}`)\n .join(', ');\n}\n\nfunction toLoadedSession(\n sessionFile: string,\n frontmatter: SessionFrontmatter,\n body: string,\n): LoadedSession {\n return {\n sessionFile,\n sessionId: frontmatter.session_id,\n ended: frontmatter.ended,\n endedMs: new Date(frontmatter.ended).getTime(),\n frontmatter,\n body,\n };\n}\n\n/**\n * Read every session under `initiativeDir/sessions`, filename-ascending.\n *\n * The one loader for session files. Callers that need a different order sort a\n * copy; this order is what makes `dangling` reporting stable.\n */\nexport async function loadSessionsFromDir(initiativeDir: string): Promise<LoadedSessions> {\n const sessionsDir = path.join(initiativeDir, 'sessions');\n let entries: string[];\n try {\n entries = await fs.readdir(sessionsDir);\n } catch {\n return { sessions: [], malformed: [] };\n }\n const sessions: LoadedSession[] = [];\n const malformed: MalformedSession[] = [];\n for (const filename of entries.filter((n) => n.endsWith('.md')).sort()) {\n const result = await loadSession(\n path.join(sessionsDir, filename),\n filename.slice(0, -'.md'.length),\n );\n if (result.ok) sessions.push(result.session);\n else malformed.push(result.problem);\n }\n return { sessions, malformed };\n}\n\nfunction indexLoops(sessions: LoadedSession[]): Map<string, LoopEntry> {\n const loops = new Map<string, LoopEntry>();\n for (const session of sessions) {\n for (const step of session.frontmatter.next_steps) {\n // Filename stems are unique by construction, so no ref can collide.\n loops.set(`${session.sessionFile}#${step.id}`, {\n ref: `${session.sessionFile}#${step.id}`,\n step,\n session,\n });\n }\n }\n return loops;\n}\n\nfunction refStem(ref: string): string {\n const hash = ref.indexOf('#');\n return hash < 0 ? ref : ref.slice(0, hash);\n}\n\n/**\n * Classify one `resolves` entry, returning null when it legitimately closes.\n *\n * Only a *strictly* earlier session may close a loop. `<=` let a session close\n * its own loop (defeating the empty-ledger gate) and let two sessions sharing\n * an `ended` close each other's loops in a cycle, both silently.\n *\n * Same-`session_id` targets are rejected too: `pickAvailableFilename` parks a\n * colliding record at `<stem>-1.md`, so a self-directed resolve lands on the\n * *earlier* file and would silently close a different record's live loop.\n */\nfunction classifyResolve(\n ref: string,\n session: LoadedSession,\n loops: Map<string, LoopEntry>,\n): DanglingKind | null {\n if (refStem(ref) === session.sessionFile) return 'self';\n const target = loops.get(ref);\n if (!target) return 'missing';\n if (target.session.sessionId === session.sessionId) return 'self';\n if (target.session.endedMs >= session.endedMs) return 'not-prior';\n return null;\n}\n\n/**\n * Later resolutions win. Two sessions may both close one loop — the ledger\n * permits it — and the most recent statement of outcome is the current one.\n *\n * \"Most recent\" is compared as an instant, never as the raw `ended` string:\n * `iso8601` accepts any timezone offset, so `2026-05-12T02:00:00-07:00` and\n * `2026-05-12T09:00:00Z` are the same moment while sorting seven hours apart\n * lexicographically. Comparing strings picks the wrong outcome for exactly the\n * distinction this carries — done versus abandoned.\n */\nfunction applyResolves(\n sessions: LoadedSession[],\n loops: Map<string, LoopEntry>,\n): { resolutions: Map<string, Resolution>; dangling: DanglingResolve[] } {\n const resolutions = new Map<string, Resolution>();\n const dangling: DanglingResolve[] = [];\n for (const session of sessions) {\n for (const entry of session.frontmatter.resolves) {\n const kind = classifyResolve(entry.ref, session, loops);\n if (kind !== null) {\n dangling.push({ sessionFile: session.sessionFile, ref: entry.ref, kind });\n continue;\n }\n const existing = resolutions.get(entry.ref);\n if (existing && existing.closedAtMs > session.endedMs) continue;\n resolutions.set(entry.ref, {\n outcome: entry.outcome,\n ...(entry.note !== undefined ? { note: entry.note } : {}),\n closedBy: session.sessionFile,\n closedAt: session.frontmatter.ended,\n closedAtMs: session.endedMs,\n });\n }\n }\n return { resolutions, dangling };\n}\n\nfunction analyzeLoaded({ sessions, malformed }: LoadedSessions): Analysis {\n const loops = indexLoops(sessions);\n const { resolutions, dangling } = applyResolves(sessions, loops);\n return { loops: [...loops.values()], resolutions, dangling, malformed };\n}\n\nasync function analyze(initiativeDir: string): Promise<Analysis> {\n return analyzeLoaded(await loadSessionsFromDir(initiativeDir));\n}\n\n/**\n * `#57`, `57`, and a full `https://github.com/o/r/pull/57` URL are all the same\n * PR. Whoever files a loop pastes whichever form is to hand, so both the\n * merged-PR matching below and the bootstrap's label depend on collapsing them\n * — an un-collapsed URL rendered as `PR #https://github.com/...` (AW-71).\n */\nexport function normalizePrRef(ref: string): string {\n const trimmed = ref.trim();\n const fromUrl = /\\/pull\\/(\\d+)/.exec(trimmed);\n return fromUrl?.[1] ?? trimmed.replace(/^#/, '');\n}\n\nfunction isAutoResolved(entry: LoopEntry, opts: DeriveOptions): boolean {\n const target = entry.step.ref;\n if (target === undefined) return false;\n if (entry.step.kind === 'task' && opts.tasks) {\n return opts.tasks.some((t) => t.id === target && t.status === 'done');\n }\n if (entry.step.kind === 'pr' && opts.mergedPrs) {\n const wanted = normalizePrRef(target);\n return opts.mergedPrs.some((ref) => normalizePrRef(ref) === wanted);\n }\n return false;\n}\n\nfunction toOpenLoop(entry: LoopEntry, now: Date): OpenLoop {\n const ageMs = now.getTime() - entry.session.endedMs;\n return {\n ref: entry.ref,\n text: entry.step.text,\n ...(entry.step.ref !== undefined ? { targetRef: entry.step.ref } : {}),\n kind: entry.step.kind,\n sessionFile: entry.session.sessionFile,\n sessionId: entry.session.sessionId,\n openedAt: entry.session.ended,\n ageDays: Math.max(0, Math.floor(ageMs / MS_PER_DAY)),\n };\n}\n\n/**\n * Unresolved loops from already-parsed sessions, oldest first.\n *\n * Callers holding a `loadSessionsFromDir` result (bootstrap does — it renders\n * the same sessions) use this so the files are read and parsed exactly once.\n */\nexport function deriveOpenLoopsFrom(loaded: LoadedSessions, opts: DeriveOptions): OpenLoop[] {\n const { loops, resolutions } = analyzeLoaded(loaded);\n return loops\n .filter((entry) => !resolutions.has(entry.ref) && !isAutoResolved(entry, opts))\n .map((entry) => toOpenLoop(entry, opts.now))\n .sort(\n (a, b) =>\n new Date(a.openedAt).getTime() - new Date(b.openedAt).getTime() ||\n a.ref.localeCompare(b.ref),\n );\n}\n\n/** Unresolved loops for an initiative, oldest first. */\nexport async function deriveOpenLoops(\n initiativeDir: string,\n opts: DeriveOptions,\n): Promise<OpenLoop[]> {\n return deriveOpenLoopsFrom(await loadSessionsFromDir(initiativeDir), opts);\n}\n\nfunction toResolvedLoop(entry: LoopEntry, resolution: Resolution, now: Date): ResolvedLoop {\n const ageMs = now.getTime() - new Date(resolution.closedAt).getTime();\n return {\n ref: entry.ref,\n text: entry.step.text,\n kind: entry.step.kind,\n outcome: resolution.outcome,\n ...(resolution.note !== undefined ? { note: resolution.note } : {}),\n sessionFile: entry.session.sessionFile,\n closedBy: resolution.closedBy,\n openedAt: entry.session.ended,\n closedAt: resolution.closedAt,\n ageDays: Math.max(0, Math.floor(ageMs / MS_PER_DAY)),\n };\n}\n\n/**\n * Loops that were explicitly closed, newest first.\n *\n * Excludes auto-resolution (a done task, a merged PR): those carry no stated\n * outcome or reason, and inferring \"done\" for them would put words in the\n * operator's mouth.\n */\nexport function deriveResolvedLoopsFrom(\n loaded: LoadedSessions,\n opts: DeriveOptions,\n): ResolvedLoop[] {\n const { loops, resolutions } = analyzeLoaded(loaded);\n return loops\n .flatMap((entry) => {\n const resolution = resolutions.get(entry.ref);\n return resolution ? [toResolvedLoop(entry, resolution, opts.now)] : [];\n })\n .sort(\n (a, b) =>\n new Date(b.closedAt).getTime() - new Date(a.closedAt).getTime() ||\n a.ref.localeCompare(b.ref),\n );\n}\n\n/** Explicitly closed loops for an initiative, newest first. */\nexport async function deriveResolvedLoops(\n initiativeDir: string,\n opts: DeriveOptions,\n): Promise<ResolvedLoop[]> {\n return deriveResolvedLoopsFrom(await loadSessionsFromDir(initiativeDir), opts);\n}\n\n/** `resolves` entries that did not close a loop, each tagged with why. */\nexport async function findDanglingResolves(initiativeDir: string): Promise<DanglingResolve[]> {\n const { dangling } = await analyze(initiativeDir);\n return dangling;\n}\n\n/**\n * Everything derivation had to work around: rejected `resolves` and session\n * files it could not read. Callers that only render loops can ignore this, but\n * something must report it — a malformed file both drops its own loops and\n * re-opens the ones it closed, and that is invisible in the ledger itself.\n */\nexport async function findSessionIssues(initiativeDir: string): Promise<SessionIssues> {\n const { dangling, malformed } = await analyze(initiativeDir);\n return { dangling, malformed };\n}\n","import { z } from 'zod';\n\n// Accepts standard ISO 8601 datetimes with timezone (Z or ±HH:MM), optional fractional seconds.\nconst ISO_8601_REGEX = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/;\n\nconst isValidIso8601 = (value: string): boolean => {\n if (!ISO_8601_REGEX.test(value)) return false;\n const parsed = new Date(value);\n return !Number.isNaN(parsed.getTime());\n};\n\nconst iso8601 = z\n .string()\n .refine(isValidIso8601, { message: 'Must be a valid ISO 8601 datetime with timezone' });\n\n// A loop is closed by a `resolves` entry matching `<session file stem>#<id>`.\n// Both halves of that reference must therefore avoid `#` (the separator) and\n// whitespace; `session_id` must also avoid `/`, since it becomes part of the\n// filename. Without this, a loop filed as `step 1` can never be resolved.\nconst REF_SEGMENT_REGEX = /^[^#\\s/]+$/;\nconst REF_SEGMENT_MESSAGE = 'must not contain whitespace, \"#\" or \"/\"';\n\n/** `session_id`; also the tail of every session filename. */\nexport const SessionIdSchema = z\n .string()\n .min(1)\n .regex(REF_SEGMENT_REGEX, { message: `session_id ${REF_SEGMENT_MESSAGE}` });\n\n/**\n * A loop this session opened. `id` is unique within the session; the global\n * reference used by `resolves` is `<session file stem>#<id>` — the filename,\n * not `session_id`, because one session can record several files.\n */\nexport const NextStepSchema = z.object({\n id: z\n .string()\n .min(1)\n .regex(REF_SEGMENT_REGEX, { message: `next_steps id ${REF_SEGMENT_MESSAGE}` }),\n text: z.string().min(1),\n kind: z.enum(['task', 'pr', 'prose']),\n ref: z.string().min(1).optional(),\n});\n\n/** A loop opened by a prior session that this session closed. */\nexport const SessionResolveSchema = z.object({\n ref: z.string().regex(/^[^#\\s]+#[^#\\s]+$/, {\n message: \"ref must be '<session file stem>#<next_step id>'\",\n }),\n outcome: z.enum(['done', 'abandoned']),\n note: z.string().min(1).optional(),\n});\n\ntype NextStepInput = z.infer<typeof NextStepSchema>;\ntype ResolveInput = z.infer<typeof SessionResolveSchema>;\n\nfunction checkUniqueStepIds(steps: NextStepInput[], ctx: z.RefinementCtx): void {\n const seen = new Set<string>();\n steps.forEach((step, index) => {\n if (seen.has(step.id)) {\n ctx.addIssue({\n code: 'custom',\n path: ['next_steps', index, 'id'],\n message: `next_steps ids must be unique within a session: ${step.id}`,\n });\n }\n seen.add(step.id);\n });\n}\n\nfunction checkAbandonedHasNote(entries: ResolveInput[], ctx: z.RefinementCtx): void {\n entries.forEach((entry, index) => {\n if (entry.outcome === 'abandoned' && entry.note === undefined) {\n ctx.addIssue({\n code: 'custom',\n path: ['resolves', index, 'note'],\n message: 'note is required when outcome is \"abandoned\"',\n });\n }\n });\n}\n\nexport const SessionFrontmatterSchema = z\n .object({\n session_id: SessionIdSchema,\n started: iso8601,\n ended: iso8601,\n track: z.enum(['canonical', 'sidecar', 'adhoc']),\n next_steps: z.array(NextStepSchema).default([]),\n resolves: z.array(SessionResolveSchema).default([]),\n // Written only by `wrap --no-loops`. An empty ledger alone cannot say\n // whether nothing was hanging or nothing was filed; this marker does.\n no_loops: z.literal(true).optional(),\n // The session that spawned this one (AW-26). Set for agent-chat peers,\n // whose parentage is known only to the spawning hook — a peer runs as its\n // own `claude` process, so nothing in its transcript records who asked for\n // it. Built-in subagents are linked in the miner index instead, where the\n // relationship *is* derivable from the transcript tree.\n parent_session_id: SessionIdSchema.optional(),\n })\n .superRefine((value, ctx) => {\n const started = new Date(value.started).getTime();\n const ended = new Date(value.ended).getTime();\n if (Number.isFinite(started) && Number.isFinite(ended) && ended < started) {\n ctx.addIssue({\n code: 'custom',\n path: ['ended'],\n message: 'ended must be greater than or equal to started',\n });\n }\n checkUniqueStepIds(value.next_steps, ctx);\n checkAbandonedHasNote(value.resolves, ctx);\n if (value.no_loops === true && (value.next_steps.length > 0 || value.resolves.length > 0)) {\n ctx.addIssue({\n code: 'custom',\n path: ['no_loops'],\n message: 'no_loops cannot be set alongside next_steps or resolves',\n });\n }\n });\n\nexport type NextStep = z.infer<typeof NextStepSchema>;\nexport type SessionResolve = z.infer<typeof SessionResolveSchema>;\nexport type SessionFrontmatter = z.infer<typeof SessionFrontmatterSchema>;\n","/**\n * Durable notes are the non-actionable half of what a session leaves behind:\n * process lessons, gotchas, decisions. Anything actionable becomes a task; this\n * is everything else that a future session would want to know and that no task\n * would ever carry.\n *\n * They live under `sources/notes/` as frontmatter + markdown, one file per\n * note. Unlike sessions they never age out of the bootstrap — a process lesson\n * from months ago is exactly the one that gets re-learned the hard way.\n */\n\nimport { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { NoteFrontmatterSchema, type NoteFrontmatter } from '../schemas/note.js';\nimport { readFrontmatter, writeFrontmatter } from '../utils/gray-matter-io.js';\nimport { slugifyLabel } from '../commands/source-add.js';\n\n/** A note file that parsed and validated. */\nexport interface LoadedNote {\n /** Filename including `.md`. */\n filename: string;\n path: string;\n frontmatter: NoteFrontmatter;\n body: string;\n}\n\n/** A file under `sources/notes/` that could not be read as a note. */\nexport interface MalformedNote {\n file: string;\n reason: string;\n}\n\nexport interface LoadedNotes {\n notes: LoadedNote[];\n malformed: MalformedNote[];\n}\n\n/** Resolve the notes directory for an initiative directory. */\nexport function getNotesDir(initiativeDir: string): string {\n return path.join(initiativeDir, 'sources', 'notes');\n}\n\n/**\n * Newest first. Filenames start with `created`, so a descending filename sort\n * orders by date and breaks ties on the title slug — deterministic without\n * depending on mtime.\n */\nfunction compareNewestFirst(a: LoadedNote, b: LoadedNote): number {\n return b.filename.localeCompare(a.filename);\n}\n\n/**\n * Read every note for an initiative, newest first.\n *\n * Never throws: a missing `sources/notes/` yields an empty result, and a file\n * that will not parse comes back as `malformed` rather than vanishing. A note\n * silently dropped is knowledge silently lost, which is the failure mode the\n * whole feature exists to prevent.\n */\nexport async function loadNotesFromDir(initiativeDir: string): Promise<LoadedNotes> {\n const dir = getNotesDir(initiativeDir);\n let entries: string[];\n try {\n entries = await fs.readdir(dir);\n } catch {\n return { notes: [], malformed: [] };\n }\n const notes: LoadedNote[] = [];\n const malformed: MalformedNote[] = [];\n for (const filename of entries.filter((n) => n.endsWith('.md')).sort()) {\n const fullPath = path.join(dir, filename);\n try {\n const { frontmatter, body } = await readFrontmatter(fullPath, NoteFrontmatterSchema);\n notes.push({ filename, path: fullPath, frontmatter, body });\n } catch (err) {\n malformed.push({\n file: filename,\n reason: err instanceof Error ? err.message : String(err),\n });\n }\n }\n return { notes: notes.sort(compareNewestFirst), malformed };\n}\n\nexport interface NoteWriteResult {\n path: string;\n filename: string;\n}\n\nasync function exists(p: string): Promise<boolean> {\n try {\n await fs.access(p);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Two notes filed the same day under the same title are two notes, not one —\n * park the second beside the first rather than overwriting knowledge already\n * captured.\n */\nasync function pickAvailableFilename(dir: string, baseName: string): Promise<string> {\n if (!(await exists(path.join(dir, `${baseName}.md`)))) return `${baseName}.md`;\n for (let i = 1; i < 10_000; i++) {\n const candidate = `${baseName}-${i}.md`;\n if (!(await exists(path.join(dir, candidate)))) return candidate;\n }\n throw new Error(`Could not find an available filename for ${baseName}`);\n}\n\n/**\n * Write `<initiativeDir>/sources/notes/<created>-<title-slug>.md`, validating\n * the frontmatter first.\n */\nexport async function writeNoteFile(\n initiativeDir: string,\n frontmatter: NoteFrontmatter,\n body: string,\n): Promise<NoteWriteResult> {\n const dir = getNotesDir(initiativeDir);\n await fs.mkdir(dir, { recursive: true });\n const baseName = `${frontmatter.created}-${slugifyLabel(frontmatter.title)}`;\n const filename = await pickAvailableFilename(dir, baseName);\n const fullPath = path.join(dir, filename);\n await writeFrontmatter(fullPath, frontmatter, body, NoteFrontmatterSchema);\n return { path: fullPath, filename };\n}\n","import { z } from 'zod';\n\nconst ISO_DATE_REGEX = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nconst isValidIsoDate = (value: string): boolean => {\n if (!ISO_DATE_REGEX.test(value)) return false;\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) return false;\n // Reject dates like 2026-02-30 that JS happily rolls forward.\n return parsed.toISOString().slice(0, 10) === value;\n};\n\nconst isoDate = z\n .string()\n .refine(isValidIsoDate, { message: 'Must be a valid zero-padded YYYY-MM-DD date' });\n\n/**\n * What a note is for. Actionable work becomes a task; these four cover the\n * durable knowledge a session leaves behind that no task would carry:\n * `process` (how to work), `gotcha` (what bit us), `fyi` (context worth\n * keeping), `decision` (what we settled and why).\n */\nexport const NoteKindSchema = z.enum(['process', 'gotcha', 'fyi', 'decision']);\n\n/**\n * Titles are slugified into filenames, so an unbounded one yields a path no\n * one can read, type, or safely check out on every filesystem.\n *\n * Enforced at write time only. The read path stays permissive so notes filed\n * before the bound existed still load — `doctor` surfaces those instead of the\n * loader dropping captured knowledge on the floor.\n */\nexport const NOTE_TITLE_MAX_LENGTH = 120;\n\nexport const NoteFrontmatterSchema = z.object({\n kind: NoteKindSchema,\n title: z.string().min(1),\n created: isoDate,\n tags: z.array(z.string().min(1)).optional(),\n});\n\nexport type NoteKind = z.infer<typeof NoteKindSchema>;\nexport type NoteFrontmatter = z.infer<typeof NoteFrontmatterSchema>;\n","import { promises as fs } from 'node:fs';\nimport matter from 'gray-matter';\nimport type { ZodType } from 'zod';\nimport { classifyStructuredArtifact, recordArtifactHash } from './artifact-hash.js';\nimport { atomicWrite } from './fs-atomic.js';\nimport { coerceDates } from './coerce-dates.js';\n\nexport interface FrontmatterFile<T> {\n frontmatter: T;\n body: string;\n}\n\n/**\n * Read a markdown file with YAML frontmatter and validate the frontmatter\n * against `schema`.\n *\n * Throws when the file is unreadable or the frontmatter does not satisfy the\n * schema. Errors include the file path so the caller can act on them.\n */\nexport async function readFrontmatter<T>(\n filePath: string,\n schema: ZodType<T>,\n): Promise<FrontmatterFile<T>> {\n const raw = await fs.readFile(filePath, 'utf8');\n const parsed = matter(raw);\n const coerced = coerceDates(parsed.data);\n const result = schema.safeParse(coerced);\n if (!result.success) {\n throw new Error(`Frontmatter validation failed for ${filePath}: ${result.error.message}`);\n }\n return { frontmatter: result.data, body: parsed.content };\n}\n\n/**\n * Read a markdown file's frontmatter without schema validation.\n *\n * Used by repair-style flows (e.g. `active-work set`) that need to fix files whose\n * frontmatter is currently invalid.\n */\nexport async function readRawFrontmatter(\n filePath: string,\n): Promise<{ frontmatter: Record<string, unknown>; body: string }> {\n const raw = await fs.readFile(filePath, 'utf8');\n const parsed = matter(raw);\n const coerced = coerceDates(parsed.data) as Record<string, unknown>;\n return {\n frontmatter: { ...coerced },\n body: parsed.content,\n };\n}\n\n/**\n * Validate `frontmatter` against `schema`, then atomically write the\n * combined frontmatter + body to `filePath`.\n */\nexport async function writeFrontmatter<T>(\n filePath: string,\n frontmatter: T,\n body: string,\n schema: ZodType<T>,\n): Promise<void> {\n const result = schema.safeParse(frontmatter);\n if (!result.success) {\n throw new Error(`Frontmatter validation failed for ${filePath}: ${result.error.message}`);\n }\n const stringified = matter.stringify(body, result.data as object);\n await atomicWrite(filePath, stringified);\n const artifact = classifyStructuredArtifact(filePath);\n if (artifact) await recordArtifactHash(artifact.initiativeDir, artifact.relPath, stringified);\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { z } from 'zod';\nimport { getInitiativeDir } from '../utils/paths.js';\nimport { today } from '../utils/today.js';\nimport { ValidationError, NotFoundError } from '../errors.js';\nimport { defineCommand } from '../registry/index.js';\n\nconst ArgsSchema = z.object({\n slug: z.string().min(1),\n file: z.string().min(1),\n type: z.enum(['pr', 'deepdive', 'session', 'pointer']),\n label: z.string().optional(),\n topic: z.string().optional(),\n pr_number: z.number().int().positive().optional(),\n date: z.string().optional(),\n force: z.boolean().optional(),\n});\n\nconst ResultSchema = z.object({\n moved_to: z.string(),\n noop: z.boolean().optional(),\n});\n\ntype Args = z.infer<typeof ArgsSchema>;\ntype Result = z.infer<typeof ResultSchema>;\n\n/**\n * Slugify a label or topic for use in a filename.\n *\n * Lowercases, replaces non-alphanumeric runs with `-`, trims leading/trailing\n * dashes. Falls back to `untitled` when the result is empty.\n */\nexport function slugifyLabel(input: string): string {\n const cleaned = input\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n return cleaned.length > 0 ? cleaned : 'untitled';\n}\n\nfunction deriveFilename(args: Args): string {\n switch (args.type) {\n case 'pr': {\n if (args.pr_number === undefined) {\n throw new ValidationError('source.add type=pr requires --pr-number');\n }\n if (!args.label) {\n throw new ValidationError('source.add type=pr requires --label');\n }\n return `pr-${args.pr_number}-${slugifyLabel(args.label)}.md`;\n }\n case 'deepdive': {\n if (!args.topic) {\n throw new ValidationError('source.add type=deepdive requires --topic');\n }\n return `deepdive-${slugifyLabel(args.topic)}.md`;\n }\n case 'session': {\n if (!args.label) {\n throw new ValidationError('source.add type=session requires --label');\n }\n const date = args.date ?? today();\n return `${date}-${slugifyLabel(args.label)}.md`;\n }\n case 'pointer': {\n if (!args.label) {\n throw new ValidationError('source.add type=pointer requires --label');\n }\n return `${slugifyLabel(args.label)}.md`;\n }\n }\n}\n\nasync function pathExists(p: string): Promise<boolean> {\n try {\n await fs.access(p);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function movePath(src: string, dest: string): Promise<void> {\n try {\n await fs.rename(src, dest);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'EXDEV') {\n await fs.copyFile(src, dest);\n await fs.unlink(src);\n return;\n }\n throw err;\n }\n}\n\nexport default defineCommand<Args, Result>({\n name: 'source.add',\n description: 'Move a source file into <slug>/sources/ with a conventional filename.',\n args: ArgsSchema,\n result: ResultSchema,\n cli: {\n positional: ['slug', 'file'],\n options: {\n type: {\n long: '--type',\n description: 'Source type: pr | deepdive | session | pointer',\n required: true,\n },\n label: { long: '--label', description: 'Short label (slugified into filename)' },\n topic: { long: '--topic', description: 'Topic for deepdive type' },\n pr_number: { long: '--pr-number', description: 'PR number for type=pr' },\n date: { long: '--date', description: 'Date YYYY-MM-DD for type=session' },\n force: { long: '--force', description: 'Overwrite if target exists' },\n },\n },\n async run(args) {\n const sourcePath = path.resolve(args.file);\n if (!(await pathExists(sourcePath))) {\n throw new NotFoundError(`source file not found: ${sourcePath}`);\n }\n\n const filename = deriveFilename(args);\n const sourcesDir = path.join(getInitiativeDir(args.slug), 'sources');\n const targetPath = path.join(sourcesDir, filename);\n\n if (path.resolve(sourcePath) === path.resolve(targetPath)) {\n return { moved_to: targetPath, noop: true };\n }\n\n await fs.mkdir(sourcesDir, { recursive: true });\n\n if ((await pathExists(targetPath)) && !args.force) {\n throw new ValidationError(`target already exists: ${targetPath} (use --force to overwrite)`);\n }\n\n await movePath(sourcePath, targetPath);\n return { moved_to: targetPath };\n },\n});\n","/** Return today's local date as `YYYY-MM-DD`. */\nexport function today(): string {\n const now = new Date();\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const day = String(now.getDate()).padStart(2, '0');\n return `${year}-${month}-${day}`;\n}\n\n/** Return the current instant as an ISO 8601 string with millisecond precision. */\nexport function nowIso(): string {\n return new Date().toISOString();\n}\n","/**\n * Session leases — the t=0 signal that another session may already be live on\n * an initiative.\n *\n * A lease is a small JSON file under `<activeRoot>/.sessions/<slug>/`. The\n * directory is dot-prefixed on purpose: `listInitiativeSlugs` (both copies —\n * `src/commands/_open-helpers.ts` and `src/lint/index.ts`) skips dot entries,\n * so leases are invisible to the picker, the linter, doctor's initiative walk,\n * and the artifact hashing. They sit under the active root rather than the XDG\n * state root because `ACTIVE_ROOT` is the one path tests can redirect, which\n * makes every lease write hermetic by construction.\n *\n * Nothing here may ever throw at a caller: bootstrap runs on every launch, and\n * a warning that can fail the launch is worse than no warning. Every read path\n * degrades to \"no siblings\".\n *\n * A `launcher` lease's liveness rests on `kill(pid, 0)`, which only proves\n * *some* process holds that pid — pids get recycled, sometimes within\n * minutes. `pid_comm` (see `schemas/lease.ts`) is the belt to that\n * suspenders: the command name recorded at write time, re-checked at read\n * time, so a lease surviving its own process (a hard kill, a crash, a closed\n * terminal) can't be mistaken for a live sibling once its pid lands on\n * something unrelated.\n *\n * This module imports nothing from `src/commands/` so the commands can depend\n * on it freely.\n */\nimport { promises as fs, unlinkSync } from 'node:fs';\nimport { randomBytes } from 'node:crypto';\nimport path from 'node:path';\nimport { LeaseSchema, type Lease, type LeaseMode } from '../schemas/lease.js';\nimport { getProcessCommand, isProcessAlive } from '../server/lifecycle.js';\n\n/**\n * How long a `oneshot` lease is assumed to represent a live session.\n *\n * There is no process to probe on that path, so this is the whole liveness\n * rule. 90 minutes is a working-session length: long enough that a sibling\n * started before lunch still warns, short enough that yesterday's `open`\n * doesn't.\n */\nexport const ONESHOT_TTL_MS = 90 * 60_000;\n\n/**\n * Backstop for `launcher` leases, whose liveness is otherwise a live pid.\n *\n * Pids are recycled. On a machine up for weeks, a lease left behind by a\n * crashed `aw` can end up naming an unrelated live process forever, and the\n * warning then never goes away. 36h is well past any real session.\n */\nexport const LAUNCHER_MAX_AGE_MS = 36 * 60 * 60_000;\n\nconst LEASE_DIR_NAME = '.sessions';\n\n/** `<activeRoot>/.sessions/<slug>` — the lease directory for one initiative. */\nexport function leaseDir(activeRoot: string, slug: string): string {\n return path.join(activeRoot, LEASE_DIR_NAME, slug);\n}\n\nfunction leasePath(activeRoot: string, slug: string, leaseId: string): string {\n return path.join(leaseDir(activeRoot, slug), `${leaseId}.json`);\n}\n\nexport interface AcquireLeaseInput {\n activeRoot: string;\n slug: string;\n cwd: string;\n mode: LeaseMode;\n /** Required in practice for `launcher` mode; ignored otherwise. */\n pid?: number;\n label?: string;\n /** Injectable clock for tests. */\n now?: Date;\n /** Injectable identity probe for tests; defaults to a real `ps -o comm=`. */\n getComm?: (pid: number) => string | null;\n}\n\nexport interface AcquiredLease {\n leaseId: string;\n release: () => Promise<void>;\n}\n\n/** Write a lease file and hand back its id plus a release handle. */\nexport async function acquireLease(input: AcquireLeaseInput): Promise<AcquiredLease> {\n const {\n activeRoot,\n slug,\n cwd,\n mode,\n pid,\n label,\n now = new Date(),\n getComm = getProcessCommand,\n } = input;\n const leaseId = randomBytes(8).toString('hex');\n // Best-effort identity snapshot: recorded now, compared against on every\n // future liveness check so a recycled pid can't read as this session.\n const pidComm = mode === 'launcher' && pid !== undefined ? getComm(pid) : null;\n const lease: Lease = LeaseSchema.parse({\n lease_id: leaseId,\n slug,\n cwd,\n mode,\n ...(mode === 'launcher' && pid !== undefined ? { pid } : {}),\n ...(pidComm ? { pid_comm: pidComm } : {}),\n started: now.toISOString(),\n ...(label ? { label } : {}),\n });\n await fs.mkdir(leaseDir(activeRoot, slug), { recursive: true });\n await fs.writeFile(leasePath(activeRoot, slug, leaseId), JSON.stringify(lease, null, 2), 'utf8');\n return {\n leaseId,\n release: () => releaseLease(activeRoot, slug, leaseId),\n };\n}\n\nfunction isIgnorableUnlinkError(err: unknown): boolean {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n return code === 'ENOENT';\n}\n\n/** Remove a lease file. A lease that is already gone is a success. */\nexport async function releaseLease(\n activeRoot: string,\n slug: string,\n leaseId: string,\n): Promise<void> {\n try {\n await fs.unlink(leasePath(activeRoot, slug, leaseId));\n } catch (err) {\n if (!isIgnorableUnlinkError(err)) throw err;\n }\n}\n\n/**\n * Synchronous release, for `process.on('exit')`.\n *\n * An exit handler cannot await, so the async form is unusable there — and that\n * handler is the only cleanup that still runs when `aw` is torn down by the\n * signal that Ctrl-C sends to the whole foreground process group. Swallows\n * everything: a failed unlink at exit must not change the exit code.\n */\nexport function releaseLeaseSync(activeRoot: string, slug: string, leaseId: string): void {\n try {\n unlinkSync(leasePath(activeRoot, slug, leaseId));\n } catch {\n // Already gone, or unwritable. Either way the process is leaving.\n }\n}\n\n/** A lease that currently looks live. What the bootstrap renderer consumes. */\nexport interface LiveSibling {\n lease_id: string;\n cwd: string;\n mode: LeaseMode;\n started: string;\n pid?: number;\n label?: string;\n}\n\nexport interface ReadLiveLeasesInput {\n activeRoot: string;\n slug: string;\n now?: Date;\n /** The caller's own lease, which is never its own sibling. */\n excludeLeaseId?: string;\n /** Injectable liveness probe; defaults to a real `kill(pid, 0)`. */\n isAlive?: (pid: number) => boolean;\n /** Injectable identity probe; defaults to a real `ps -o comm=`. */\n getComm?: (pid: number) => string | null;\n}\n\nexport type SiblingProbe = (input: ReadLiveLeasesInput) => Promise<LiveSibling[]>;\n\nfunction isLive(\n lease: Lease,\n now: Date,\n isAlive: (pid: number) => boolean,\n getComm: (pid: number) => string | null,\n): boolean {\n const ageMs = now.getTime() - new Date(lease.started).getTime();\n if (lease.mode === 'oneshot') return ageMs < ONESHOT_TTL_MS;\n if (lease.pid === undefined) return false;\n // Age check first: a stale lease whose pid has been recycled would otherwise\n // read as live forever.\n if (ageMs >= LAUNCHER_MAX_AGE_MS) return false;\n if (!isAlive(lease.pid)) return false;\n // A live pid isn't necessarily *this* process: the OS can recycle a pid\n // faster than LAUNCHER_MAX_AGE_MS allows for (e.g. within the same boot\n // session). Recorded identity beats a bare pid check when we have it.\n if (lease.pid_comm === undefined) return true;\n return getComm(lease.pid) === lease.pid_comm;\n}\n\nfunction toSibling(lease: Lease): LiveSibling {\n return {\n lease_id: lease.lease_id,\n cwd: lease.cwd,\n mode: lease.mode,\n started: lease.started,\n ...(lease.pid !== undefined ? { pid: lease.pid } : {}),\n ...(lease.label !== undefined ? { label: lease.label } : {}),\n };\n}\n\nasync function readOneLease(file: string): Promise<Lease | null> {\n try {\n const raw = await fs.readFile(file, 'utf8');\n const parsed = LeaseSchema.safeParse(JSON.parse(raw));\n return parsed.success ? parsed.data : null;\n } catch {\n return null;\n }\n}\n\nasync function unlinkQuietly(file: string): Promise<void> {\n try {\n await fs.unlink(file);\n } catch {\n // Another session may have swept it already; that is the desired end state.\n }\n}\n\n/**\n * Every lease for `slug` that still looks live, sweeping the ones that don't.\n *\n * Opportunistic pruning is what keeps the directory from growing without a\n * background job: whoever next bootstraps the initiative pays for the cleanup.\n * A malformed file is swept the same way — it can never become live, and\n * leaving it there means re-parsing garbage on every launch.\n *\n * Returns `[]` on any unexpected failure. Callers are on the bootstrap path.\n */\nexport async function readLiveLeases(input: ReadLiveLeasesInput): Promise<LiveSibling[]> {\n const {\n activeRoot,\n slug,\n now = new Date(),\n excludeLeaseId,\n isAlive = isProcessAlive,\n getComm = getProcessCommand,\n } = input;\n try {\n const dir = leaseDir(activeRoot, slug);\n let entries: string[];\n try {\n entries = await fs.readdir(dir);\n } catch {\n return [];\n }\n const live: LiveSibling[] = [];\n for (const name of entries) {\n if (!name.endsWith('.json')) continue;\n const file = path.join(dir, name);\n const lease = await readOneLease(file);\n if (!lease || !isLive(lease, now, isAlive, getComm)) {\n await unlinkQuietly(file);\n continue;\n }\n if (lease.lease_id === excludeLeaseId) continue;\n live.push(toSibling(lease));\n }\n return live.sort((a, b) => a.started.localeCompare(b.started));\n } catch {\n return [];\n }\n}\n\nexport interface LeaseSweepResult {\n live: number;\n pruned: number;\n /** Set when the sweep could not complete (e.g. the directory is unreadable). */\n error?: string;\n}\n\n/**\n * Sweep every slug's lease directory, reporting live vs. pruned counts.\n *\n * Used by `doctor`; the pruning is the same opportunistic pass `readLiveLeases`\n * makes, so running it here just moves the cleanup earlier.\n */\nexport async function sweepAllLeases(\n activeRoot: string,\n options: {\n now?: Date;\n isAlive?: (pid: number) => boolean;\n getComm?: (pid: number) => string | null;\n } = {},\n): Promise<LeaseSweepResult> {\n const root = path.join(activeRoot, LEASE_DIR_NAME);\n let slugs: string[];\n try {\n const entries = await fs.readdir(root, { withFileTypes: true });\n slugs = entries.filter((e) => e.isDirectory()).map((e) => e.name);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') return { live: 0, pruned: 0 };\n return { live: 0, pruned: 0, error: (err as Error).message };\n }\n let live = 0;\n let before = 0;\n for (const slug of slugs) {\n try {\n const names = await fs.readdir(leaseDir(activeRoot, slug));\n before += names.filter((n) => n.endsWith('.json')).length;\n live += (await readLiveLeases({ activeRoot, slug, ...options })).length;\n } catch (err) {\n return { live, pruned: Math.max(before - live, 0), error: (err as Error).message };\n }\n }\n return { live, pruned: Math.max(before - live, 0) };\n}\n","import { z } from 'zod';\n\n// Accepts standard ISO 8601 datetimes with timezone (Z or ±HH:MM), optional\n// fractional seconds. Mirrors `src/schemas/session.ts`, deliberately duplicated\n// rather than shared: the session schema's refinements are about the loop\n// ledger, and a lease has no business inheriting them.\nconst ISO_8601_REGEX = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/;\n\nconst isValidIso8601 = (value: string): boolean => {\n if (!ISO_8601_REGEX.test(value)) return false;\n const parsed = new Date(value);\n return !Number.isNaN(parsed.getTime());\n};\n\nconst iso8601 = z\n .string()\n .refine(isValidIso8601, { message: 'Must be a valid ISO 8601 datetime with timezone' });\n\n/**\n * How the lease was written, which is also how much its liveness can be\n * trusted.\n *\n * `launcher` — written by `aw`, whose own process lifetime brackets the Claude\n * session it spawned. `pid` is that process, so liveness is a *fact*.\n *\n * `oneshot` — written by `open` on the MCP / bare-CLI path, where the writing\n * process exits as soon as it has produced the prompt. There is nothing to\n * signal, so liveness is a TTL *guess* and must be rendered as one.\n */\nexport const LeaseModeSchema = z.enum(['launcher', 'oneshot']);\n\nexport const LeaseSchema = z.object({\n /** Random hex; also the filename stem (`<lease_id>.json`). */\n lease_id: z.string().min(1),\n slug: z.string().min(1),\n /** The launch cwd, so a sibling can be told apart from a second checkout. */\n cwd: z.string().min(1),\n mode: LeaseModeSchema,\n /** Present only for `launcher` leases — the `aw` process to probe. */\n pid: z.number().int().positive().optional(),\n /**\n * `pid`'s command name (e.g. `node`) at the moment the lease was written.\n * Lets liveness checking tell \"still the same process\" apart from \"the OS\n * recycled this pid onto something unrelated\" — `kill(pid, 0)` alone can't.\n * Best-effort: absent when the lookup failed, in which case liveness falls\n * back to the pid check alone.\n */\n pid_comm: z.string().min(1).optional(),\n started: iso8601,\n /** Human/role hint carried for future use (e.g. an agent-chat name). */\n label: z.string().min(1).optional(),\n});\n\nexport type LeaseMode = z.infer<typeof LeaseModeSchema>;\nexport type Lease = z.infer<typeof LeaseSchema>;\n","/**\n * active-work's binding of `@titan-design/daemon`'s pid lifecycle (AW-a).\n *\n * The package takes an explicit `DaemonPaths` so one process can own several\n * daemons; active-work has exactly one, rooted at `getStateRoot()`. Binding\n * that here is why the eight modules importing `writePidFile`, `readPidFile`,\n * `removePidFile`, `probeHealth` and friends are unchanged.\n *\n * `resolveDaemonPort` and the typed `DaemonHealth` stay local: the port comes\n * from active-work's own `AW_PORT` convention, and the package deliberately\n * types `/health` as an open record because the index payload below is this\n * product's extension rather than part of the daemon contract.\n */\nimport {\n daemonPaths,\n probeHealth as pkgProbeHealth,\n readPidFile as pkgReadPidFile,\n removePidFile as pkgRemovePidFile,\n writePidFile as pkgWritePidFile,\n type DaemonPaths,\n} from '@titan-design/daemon';\nimport { getStateRoot } from '../utils/paths.js';\nimport type { HealthIndexState } from './health.js';\n\nexport { DEFAULT_DAEMON_PORT, getProcessCommand, isProcessAlive } from '@titan-design/daemon';\nexport type { DaemonMeta, PidFileContents } from '@titan-design/daemon';\n\n/** Resolved per call rather than once, because tests move the state root between cases. */\nexport function paths(): DaemonPaths {\n return daemonPaths(getStateRoot());\n}\n\nexport async function writePidFile(\n pid: number,\n meta: { port: number; version: string; started: string },\n): Promise<void> {\n await pkgWritePidFile(paths(), pid, meta);\n}\n\nexport async function readPidFile(): ReturnType<typeof pkgReadPidFile> {\n return pkgReadPidFile(paths());\n}\n\nexport async function removePidFile(expectedPid: number): Promise<boolean> {\n return pkgRemovePidFile(paths(), expectedPid);\n}\n\n/**\n * The port a daemon would be listening on absent an explicit `--port`.\n *\n * Callers that have lost the PID file still need somewhere to aim a health\n * probe; the installed launchd/systemd unit runs `mcp serve` with no port\n * argument, so this is the port in practice.\n */\nexport function resolveDaemonPort(): number {\n const envPort = process.env.AW_PORT;\n if (envPort) {\n const n = Number.parseInt(envPort, 10);\n if (Number.isFinite(n)) return n;\n }\n return 7400;\n}\n\nexport interface DaemonHealth {\n version: string;\n pid: number;\n uptime_ms: number;\n port: number;\n /** Absent on a daemon predating the session index, or one not indexing. */\n index?: HealthIndexState | null;\n}\n\n/** GET `/health` on the loopback daemon; null on any failure. */\nexport async function probeHealth(port: number): Promise<DaemonHealth | null> {\n return (await pkgProbeHealth(port)) as DaemonHealth | null;\n}\n","import { spawn } from 'node:child_process';\nimport path from 'node:path';\nimport { expandTilde } from './paths.js';\n\n/**\n * Live-pull helpers for AW-15 `artifact.status` / `artifact.prune`.\n *\n * Everything in this module is failure-tolerant: callers want partial data\n * with per-branch error strings, not a single thrown exception that aborts\n * the entire status sweep. The runners are exposed as injectable DI hooks so\n * tests can stub them without spawning subprocesses.\n */\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nexport interface CommandResult {\n code: number | null;\n stdout: string;\n stderr: string;\n}\n\nexport type CommandRunner = (\n bin: string,\n args: string[],\n opts?: { cwd?: string; timeoutMs?: number },\n) => Promise<CommandResult>;\n\nconst defaultRunner: CommandRunner = (bin, args, opts = {}) =>\n new Promise<CommandResult>((resolve, reject) => {\n const child = spawn(bin, args, {\n cwd: opts.cwd,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n const stdoutChunks: Buffer[] = [];\n const stderrChunks: Buffer[] = [];\n let settled = false;\n const timer = setTimeout(() => {\n if (settled) return;\n settled = true;\n child.kill('SIGKILL');\n reject(new Error(`${bin} timed out after ${opts.timeoutMs ?? DEFAULT_TIMEOUT_MS}ms`));\n }, opts.timeoutMs ?? DEFAULT_TIMEOUT_MS);\n child.stdout?.on('data', (chunk: Buffer) => stdoutChunks.push(chunk));\n child.stderr?.on('data', (chunk: Buffer) => stderrChunks.push(chunk));\n child.on('error', (err) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n reject(err);\n });\n child.on('close', (code) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n resolve({\n code,\n stdout: Buffer.concat(stdoutChunks).toString('utf8'),\n stderr: Buffer.concat(stderrChunks).toString('utf8'),\n });\n });\n });\n\nlet gitRunner: CommandRunner = defaultRunner;\nlet ghRunner: CommandRunner = defaultRunner;\n\nexport function setGitRunner(next: CommandRunner): void {\n gitRunner = next;\n}\n\nexport function setGhRunner(next: CommandRunner): void {\n ghRunner = next;\n}\n\nexport function resetRunners(): void {\n gitRunner = defaultRunner;\n ghRunner = defaultRunner;\n}\n\nexport function getGitRunner(): CommandRunner {\n return gitRunner;\n}\n\nexport function getGhRunner(): CommandRunner {\n return ghRunner;\n}\n\n/**\n * True when `repo` looks like a bare `org/repo` GitHub spec rather than a\n * filesystem path.\n *\n * Heuristic: exactly one slash, no leading `/`, `~`, or `.`, and no whitespace.\n * `~/code/sample` has a tilde, `./foo/bar` has a dot, `/abs/path` starts with\n * `/` — all of those are treated as paths.\n */\nexport function looksLikeOrgRepo(repo: string): boolean {\n if (!repo) return false;\n if (repo.startsWith('/') || repo.startsWith('~') || repo.startsWith('.')) return false;\n if (/\\s/.test(repo)) return false;\n const slashCount = (repo.match(/\\//g) ?? []).length;\n return slashCount === 1;\n}\n\n/**\n * Resolve a `branches[].repo` value (which may be a local path or `org/repo`)\n * to an absolute filesystem path. Returns `null` when the value looks like\n * an `org/repo` spec (no local clone to operate on).\n */\nexport function resolveLocalRepoPath(repo: string): string | null {\n if (looksLikeOrgRepo(repo)) return null;\n return path.resolve(expandTilde(repo));\n}\n\n/**\n * Run `git -C <repoPath> remote get-url origin` and derive `org/repo` from\n * the URL. Supports https, ssh, and git:// URLs. Returns null if the URL\n * can't be parsed or the call fails.\n */\nexport async function deriveOrgRepoFromPath(repoPath: string): Promise<string | null> {\n try {\n const res = await gitRunner('git', ['-C', repoPath, 'remote', 'get-url', 'origin']);\n if (res.code !== 0) return null;\n return parseOrgRepoFromRemoteUrl(res.stdout.trim());\n } catch {\n return null;\n }\n}\n\n/** Parse `org/repo` out of a git remote URL. Exported for testing. */\nexport function parseOrgRepoFromRemoteUrl(url: string): string | null {\n // https://github.com/org/repo(.git)?\n // git@github.com:org/repo(.git)?\n // ssh://git@github.com/org/repo(.git)?\n const trimmed = url.trim().replace(/\\.git$/, '');\n const sshMatch = /^[^@]+@[^:]+:([^/]+)\\/(.+)$/.exec(trimmed);\n if (sshMatch) return `${sshMatch[1]}/${sshMatch[2]}`;\n try {\n const u = new URL(trimmed);\n const parts = u.pathname.replace(/^\\//, '').split('/');\n if (parts.length >= 2 && parts[0] && parts[1]) {\n return `${parts[0]}/${parts[1]}`;\n }\n } catch {\n // not a parseable URL\n }\n return null;\n}\n\n/**\n * Resolve `repo` to an `org/repo` string suitable for `gh`. If `repo` already\n * looks like `org/repo`, return it unchanged. Otherwise treat it as a local\n * path and derive from `git remote`. Returns null when neither route works.\n */\nexport async function resolveOrgRepo(repo: string): Promise<string | null> {\n if (looksLikeOrgRepo(repo)) return repo;\n const localPath = resolveLocalRepoPath(repo);\n if (!localPath) return null;\n return deriveOrgRepoFromPath(localPath);\n}\n","import path from 'node:path';\nimport { z } from 'zod';\nimport { BriefFrontmatterSchema, type BriefFrontmatter } from '../schemas/brief.js';\nimport { getActiveRoot } from '../utils/paths.js';\nimport { defineCommand } from '../registry/index.js';\nimport {\n assembleBootstrap,\n readMarkdownWithSchema,\n type BootstrapMetadata,\n} from '../bootstrap/prompt.js';\nimport { archiveStaleTasks } from '../bootstrap/archive-tasks.js';\nimport { mergeChannels } from '../launcher-args.js';\nimport { resolveDefaultChannels } from '../utils/global-config.js';\nimport { acquireLease } from '../sessions/lease.js';\nimport {\n listInitiativeSlugs,\n resolveSlug,\n resolveSlugFromCwd,\n resolveCwdHint,\n} from './_open-helpers.js';\n\n/** Done tasks older than this are auto-archived on bootstrap (AW-8). */\nconst ARCHIVE_DONE_AFTER_DAYS = 30;\n\nconst ArgsSchema = z.object({\n slug: z.string().min(1).optional(),\n offline: z.boolean().optional(),\n // Directory used to auto-resolve an initiative when no slug is given.\n // Defaults to the process cwd; callers that do not share the user's shell\n // cwd (the daemon / MCP server) must pass this explicitly.\n cwd: z.string().min(1).optional(),\n // Force the picker even when the cwd matches an initiative's worktree.\n pick: z.boolean().optional(),\n // Frame the bootstrap prompt as ad-hoc work related to the workstream rather\n // than a continuation of its handoff / top task.\n adhoc: z.boolean().optional(),\n // Skip the sibling-session probe (and the lease write that goes with it).\n no_sibling_check: z.boolean().optional(),\n // Internal: `aw` calls this command in-process and holds a `launcher` lease\n // of its own for the same session, so it suppresses the oneshot lease here\n // rather than writing a second one that would then look like a sibling.\n lease_mode: z.literal('defer').optional(),\n});\n\nconst InitiativeSummarySchema = z.object({\n slug: z.string(),\n title: z.string(),\n state: z.enum(['focused', 'backburner', 'paused', 'done']),\n rank: z.number().int().positive().optional(),\n});\n\nconst PickerResultSchema = z.object({\n picker: z.literal(true),\n initiatives: z.array(InitiativeSummarySchema),\n});\n\nconst OpenResultSchema = z.object({\n slug: z.string(),\n prompt: z.string(),\n cwd_hint: z.string(),\n channels: z.array(z.string()).optional(),\n metadata: z.object({\n slug: z.string(),\n brief_title: z.string(),\n last_session: z.object({ filename: z.string(), ended: z.string() }).optional(),\n time_since_last_session_human: z.string().optional(),\n open_task_count: z.number().int().nonnegative(),\n recently_done_count: z.number().int().nonnegative(),\n bootstrap_at: z.string(),\n sibling_sessions: z.number().int().nonnegative().optional(),\n }),\n // How the initiative was selected: an explicit/prefix slug, or a match\n // between the caller's cwd and one of the initiative's worktrees.\n resolved_from: z.enum(['slug', 'cwd']).optional(),\n});\n\nconst ResultSchema = z.union([OpenResultSchema, PickerResultSchema]);\n\ntype OpenArgs = z.infer<typeof ArgsSchema>;\ntype OpenResult = z.infer<typeof ResultSchema>;\n\ninterface InitiativeSummary {\n slug: string;\n title: string;\n state: BriefFrontmatter['state'];\n rank?: number;\n}\n\nconst STATE_ORDER: Record<BriefFrontmatter['state'], number> = {\n focused: 0,\n backburner: 1,\n paused: 2,\n done: 3,\n};\n\nasync function loadInitiativeSummary(\n activeRoot: string,\n slug: string,\n): Promise<InitiativeSummary | null> {\n const briefPath = path.join(activeRoot, slug, 'brief.md');\n try {\n const { frontmatter } = await readMarkdownWithSchema(briefPath, BriefFrontmatterSchema);\n return {\n slug,\n title: frontmatter.title,\n state: frontmatter.state,\n rank: frontmatter.rank,\n };\n } catch {\n return null;\n }\n}\n\nfunction compareInitiatives(a: InitiativeSummary, b: InitiativeSummary): number {\n const stateDiff = STATE_ORDER[a.state] - STATE_ORDER[b.state];\n if (stateDiff !== 0) return stateDiff;\n if (a.rank !== undefined && b.rank !== undefined && a.rank !== b.rank) {\n return a.rank - b.rank;\n }\n if (a.rank !== undefined && b.rank === undefined) return -1;\n if (a.rank === undefined && b.rank !== undefined) return 1;\n return a.slug.localeCompare(b.slug);\n}\n\nasync function collectInitiatives(activeRoot: string): Promise<InitiativeSummary[]> {\n const slugs = await listInitiativeSlugs(activeRoot);\n const summaries: InitiativeSummary[] = [];\n for (const slug of slugs) {\n const summary = await loadInitiativeSummary(activeRoot, slug);\n if (summary) summaries.push(summary);\n }\n summaries.sort(compareInitiatives);\n return summaries;\n}\n\n/**\n * Claim a `oneshot` lease for the session this bootstrap is about to start.\n *\n * \"Oneshot\" because this process has no idea how long the session it is\n * priming will live — it prints a prompt and exits — so the lease is a TTL\n * guess that `readLiveLeases` renders with the appropriate hedge. Failure is\n * swallowed: a lease we could not write costs a future warning, whereas a\n * throw here costs the caller their bootstrap.\n */\nasync function claimOneshotLease(activeRoot: string, slug: string, cwd: string): Promise<void> {\n try {\n await acquireLease({ activeRoot, slug, cwd, mode: 'oneshot' });\n } catch {\n // Advisory only.\n }\n}\n\nasync function bootstrapInitiative(\n activeRoot: string,\n slug: string,\n opts: {\n offline?: boolean;\n resolvedFrom: 'slug' | 'cwd';\n cwdHintOverride?: string;\n adhoc?: boolean;\n detectSiblings?: boolean;\n deferLease?: boolean;\n },\n): Promise<OpenResult & { metadata: BootstrapMetadata }> {\n const briefPath = path.join(activeRoot, slug, 'brief.md');\n const { frontmatter: brief } = await readMarkdownWithSchema(briefPath, BriefFrontmatterSchema);\n // When we resolved via cwd, launch in the worktree the user was standing in,\n // not the brief's default worktree.\n const cwdHint = opts.cwdHintOverride ?? (await resolveCwdHint(activeRoot, slug));\n const archivedTaskIds = await archiveStaleTasks(path.join(activeRoot, slug), {\n retentionDays: ARCHIVE_DONE_AFTER_DAYS,\n now: new Date(),\n });\n const detectSiblings = opts.detectSiblings !== false;\n const { prompt, metadata } = await assembleBootstrap({\n activeRoot,\n slug,\n includeLiveStatus: !opts.offline,\n archivedTaskIds,\n adhoc: opts.adhoc,\n detectSiblings,\n ...(process.env.AW_LEASE_ID ? { ownLeaseId: process.env.AW_LEASE_ID } : {}),\n });\n // After the probe, so this session never warns about itself.\n if (detectSiblings && !opts.deferLease) {\n await claimOneshotLease(activeRoot, slug, cwdHint);\n }\n const defaultChannels = await resolveDefaultChannels();\n return {\n slug,\n prompt,\n cwd_hint: cwdHint,\n channels: mergeChannels(defaultChannels, brief.channels),\n metadata,\n resolved_from: opts.resolvedFrom,\n };\n}\n\nconst openCommand = defineCommand<OpenArgs, OpenResult>({\n name: 'open',\n description:\n \"Bootstrap a Claude session for an initiative. Without a slug, resolves the initiative whose worktree contains the caller's cwd; falls back to the picker list when nothing matches.\",\n args: ArgsSchema,\n result: ResultSchema,\n cli: {\n positional: ['slug'],\n options: {\n offline: {\n long: '--offline',\n description: 'Skip the live `gh`/`git` artifact lookup; render artifacts statically.',\n },\n cwd: {\n long: '--cwd',\n description:\n 'Directory to resolve the initiative from when no slug is given (default: current directory).',\n },\n pick: {\n long: '--pick',\n description:\n 'Always return the picker list; skip resolving the initiative from the current directory.',\n },\n adhoc: {\n long: '--adhoc',\n description:\n 'Frame the prompt as ad-hoc work on the workstream (awaiting the user’s task), not a continuation of the handoff / top task.',\n },\n no_sibling_check: {\n long: '--no-sibling-check',\n description:\n 'Skip the check for another session already live on this initiative, and do not record a lease for this one.',\n },\n },\n usage:\n 'active-work open [slug] [--offline] [--cwd <dir>] [--pick] [--adhoc] [--no-sibling-check]',\n },\n async run(args, ctx) {\n const activeRoot = ctx.activeRoot ?? getActiveRoot();\n // `--offline` is a promise that this bootstrap touches nothing outside the\n // active root; the sibling probe is local I/O, but honoring the flag keeps\n // the fast path a single, predictable read set.\n const detectSiblings = !args.no_sibling_check && !args.offline;\n const deferLease = args.lease_mode === 'defer';\n\n if (args.slug) {\n const slug = await resolveSlug(activeRoot, args.slug);\n return bootstrapInitiative(activeRoot, slug, {\n offline: args.offline,\n resolvedFrom: 'slug',\n adhoc: args.adhoc,\n detectSiblings,\n deferLease,\n });\n }\n\n // No slug: infer the initiative from the caller's working directory,\n // unless the caller explicitly asked for the picker. The cwd comes from\n // the caller's args or the interactive-surface context; when neither is\n // set (e.g. a daemon/MCP caller) we skip resolution and show the picker.\n const cwd = args.cwd ?? ctx.cwd;\n if (!args.pick && cwd) {\n const matched = await resolveSlugFromCwd(activeRoot, cwd);\n if (matched) {\n return bootstrapInitiative(activeRoot, matched.slug, {\n offline: args.offline,\n resolvedFrom: 'cwd',\n cwdHintOverride: matched.worktreePath,\n adhoc: args.adhoc,\n detectSiblings,\n deferLease,\n });\n }\n }\n\n const initiatives = await collectInitiatives(activeRoot);\n return { picker: true, initiatives };\n },\n});\n\nexport default openCommand;\n","/**\n * Auto-archive stale done tasks during bootstrap (AW-8).\n *\n * A `done` task whose `done_at` is older than `retentionDays` is moved from\n * `tasks/<id>.yml` into `tasks/archive/<id>.yml`. Every task reader filters by\n * the `.yml`/`.yaml` extension, so the `archive/` subdirectory is naturally\n * excluded from the active list while the file is preserved for recovery.\n *\n * Best-effort: unreadable/malformed task files and per-file move failures are\n * skipped rather than aborting the bootstrap.\n */\nimport { promises as fsp } from 'node:fs';\nimport path from 'node:path';\nimport { readYaml } from '../utils/yaml-io.js';\nimport { TaskSchema } from '../schemas/task.js';\n\nconst MS_PER_DAY = 86_400_000;\n\nexport interface ArchiveStaleTasksOptions {\n /** Done tasks whose `done_at` is older than this many days are archived. */\n retentionDays: number;\n /** Reference time (injectable for tests). */\n now: Date;\n}\n\n/**\n * Move stale done tasks into `tasks/archive/`. Returns the archived task ids\n * (sorted). A non-positive `retentionDays` disables archiving.\n */\nexport async function archiveStaleTasks(\n initiativeDir: string,\n opts: ArchiveStaleTasksOptions,\n): Promise<string[]> {\n if (!(opts.retentionDays > 0)) return [];\n const tasksDir = path.join(initiativeDir, 'tasks');\n let entries: string[];\n try {\n entries = await fsp.readdir(tasksDir);\n } catch {\n return [];\n }\n const ymlFiles = entries.filter((n) => n.endsWith('.yml') || n.endsWith('.yaml'));\n const cutoffMs = opts.now.getTime() - opts.retentionDays * MS_PER_DAY;\n const archiveDir = path.join(tasksDir, 'archive');\n const archived: string[] = [];\n\n for (const filename of ymlFiles) {\n const fullPath = path.join(tasksDir, filename);\n let doneAt: string | null;\n let id: string;\n try {\n const task = await readYaml(fullPath, TaskSchema);\n if (task.status !== 'done' || !task.done_at) continue;\n doneAt = task.done_at;\n id = task.id;\n } catch {\n continue; // malformed / unreadable — leave it in place\n }\n const doneMs = new Date(doneAt).getTime();\n if (Number.isNaN(doneMs) || doneMs > cutoffMs) continue;\n try {\n await fsp.mkdir(archiveDir, { recursive: true });\n await fsp.rename(fullPath, path.join(archiveDir, filename));\n archived.push(id);\n } catch {\n // best-effort: skip files we can't move\n }\n }\n return archived.sort();\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { z } from 'zod';\nimport { channelTarget } from '../schemas/brief.js';\nimport { getConfigRoot } from './paths.js';\n\n/**\n * User-level config at `<configRoot>/config.json` — shared across every\n * initiative, unlike `brief.md`'s per-initiative `channels` field. Only\n * `channels` is modeled here today; `discovery` (written by `setup`'s config\n * stub) isn't read from disk anywhere yet, so it's deliberately left out of\n * this schema rather than validated and then ignored.\n */\nexport const GlobalConfigSchema = z.object({\n channels: z.array(channelTarget).optional(),\n});\n\nexport type GlobalConfig = z.infer<typeof GlobalConfigSchema>;\n\n/**\n * Channels loaded on every `aw`/`open` launch when the user's config.json\n * doesn't say otherwise. agent-chat is here so a fresh install still gets a\n * working bus without hand-editing config.json first — see the \"Agent\n * Coordination\" policy in the global CLAUDE.md.\n */\nexport const FALLBACK_DEFAULT_CHANNELS: string[] = ['plugin:agent-chat@agent-chat-local'];\n\n/**\n * Read and validate `<configRoot>/config.json`. Fails open: a missing file,\n * unparsable JSON, or a `channels` entry that doesn't validate all fall back\n * to `{}` rather than throwing — a malformed global config should degrade to\n * defaults, not break every `aw` launch.\n */\nexport async function readGlobalConfig(\n configRoot: string = getConfigRoot(),\n): Promise<GlobalConfig> {\n let raw: string;\n try {\n raw = await fs.readFile(path.join(configRoot, 'config.json'), 'utf8');\n } catch {\n return {};\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return {};\n }\n const result = GlobalConfigSchema.safeParse(parsed);\n return result.success ? result.data : {};\n}\n\n/** The channel defaults to merge with a brief's own: config.json's `channels` if set, else the fallback. */\nexport async function resolveDefaultChannels(configRoot?: string): Promise<string[]> {\n const config = await readGlobalConfig(configRoot);\n return config.channels && config.channels.length > 0\n ? config.channels\n : FALLBACK_DEFAULT_CHANNELS;\n}\n","import { z } from 'zod';\nimport { NotFoundError } from '../errors.js';\nimport { defineCommand } from '../registry/index.js';\nimport { resolveSessionLocation } from '../sessions/resolve-session-location.js';\n\nconst ArgsSchema = z.object({\n session_id: z.string().min(1),\n});\n\nconst ResultSchema = z.object({\n session_id: z.string(),\n cwd: z.string(),\n source: z.enum(['active-work', 'claude-projects']),\n slug: z.string().optional(),\n});\n\nexport default defineCommand({\n name: 'resume',\n description:\n 'Resolve the working directory a Claude session id belongs to, so `claude --resume` can be run from the right place.',\n args: ArgsSchema,\n result: ResultSchema,\n cli: {\n positional: ['session_id'],\n usage: 'active-work resume <session_id>',\n },\n async run(args, ctx) {\n const resolved = await resolveSessionLocation(ctx.activeRoot, args.session_id);\n if (!resolved) {\n throw new NotFoundError(\n `No session found for '${args.session_id}' in active-work sessions or ~/.claude/projects.`,\n );\n }\n return { session_id: args.session_id, ...resolved };\n },\n});\n","import { promises as fs } from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport matter from 'gray-matter';\nimport { listInitiativeSlugs, resolveLaunchCwd } from '../commands/_open-helpers.js';\n\nexport interface ResolvedSessionLocation {\n cwd: string;\n source: 'active-work' | 'claude-projects';\n /** Set only when `source` is `active-work`. */\n slug?: string;\n}\n\n/**\n * Search every initiative's `sessions/*.md` for a frontmatter `session_id`\n * match. Filenames carry the id as a suffix (`session-file.ts`), so filtering\n * on that first avoids parsing every session file, but the frontmatter is\n * still the source of truth — a suffix match alone isn't proof.\n */\nasync function findInActiveWork(\n activeRoot: string,\n sessionId: string,\n): Promise<{ slug: string; cwd: string } | null> {\n for (const slug of await listInitiativeSlugs(activeRoot)) {\n const sessionsDir = path.join(activeRoot, slug, 'sessions');\n let filenames: string[];\n try {\n filenames = await fs.readdir(sessionsDir);\n } catch {\n continue;\n }\n for (const filename of filenames) {\n if (!filename.endsWith('.md') || !filename.includes(sessionId)) continue;\n let raw: string;\n try {\n raw = await fs.readFile(path.join(sessionsDir, filename), 'utf8');\n } catch {\n continue;\n }\n const { data } = matter(raw);\n if (data.session_id === sessionId) {\n return { slug, cwd: resolveLaunchCwd(activeRoot, slug) };\n }\n }\n }\n return null;\n}\n\n/** Root of Claude Code's per-project transcript store. Honors `CLAUDE_PROJECTS_ROOT` for tests. */\nfunction transcriptsRoot(): string {\n return process.env.CLAUDE_PROJECTS_ROOT ?? path.join(os.homedir(), '.claude', 'projects');\n}\n\n/** The first `cwd` field found in a transcript's JSONL lines, if any. */\nasync function extractCwd(filePath: string): Promise<string | null> {\n const raw = await fs.readFile(filePath, 'utf8');\n for (const line of raw.split('\\n')) {\n if (!line) continue;\n let record: unknown;\n try {\n record = JSON.parse(line);\n } catch {\n continue;\n }\n if (record && typeof record === 'object') {\n const cwd = (record as Record<string, unknown>).cwd;\n if (typeof cwd === 'string' && cwd.length > 0) return cwd;\n }\n }\n return null;\n}\n\n/**\n * Claude Code names each transcript file after its session id\n * (`<project-dir>/<session_id>.jsonl`), so the lookup is a direct filename\n * match across project dirs rather than a scan of every transcript's content.\n */\nasync function findInClaudeProjects(sessionId: string): Promise<string | null> {\n const root = transcriptsRoot();\n let projectDirs: string[];\n try {\n projectDirs = await fs.readdir(root);\n } catch {\n return null;\n }\n const targetName = `${sessionId}.jsonl`;\n for (const dir of projectDirs) {\n const candidate = path.join(root, dir, targetName);\n try {\n await fs.access(candidate);\n } catch {\n continue;\n }\n const cwd = await extractCwd(candidate);\n if (cwd) return cwd;\n }\n return null;\n}\n\n/**\n * Resolve the working directory a session id belongs to: active-work's own\n * session log first (giving the initiative's directory, where `aw` launches\n * every session), then a direct filename match under `~/.claude/projects` for\n * sessions active-work never tracked — there the transcript's recorded `cwd`\n * is the answer, since such a session may have run anywhere.\n */\nexport async function resolveSessionLocation(\n activeRoot: string,\n sessionId: string,\n): Promise<ResolvedSessionLocation | null> {\n const viaActiveWork = await findInActiveWork(activeRoot, sessionId);\n if (viaActiveWork) {\n return { cwd: viaActiveWork.cwd, source: 'active-work', slug: viaActiveWork.slug };\n }\n const viaProjects = await findInClaudeProjects(sessionId);\n if (viaProjects) {\n return { cwd: viaProjects, source: 'claude-projects' };\n }\n return null;\n}\n","import pc from 'picocolors';\n\n/**\n * Lightweight color wrapper that respects `NO_COLOR` and TTY detection.\n *\n * If `NO_COLOR` is set or stdout is not a TTY (e.g. piped output or test\n * runners), every helper returns its input unchanged so JSON and human\n * output stay free of escape codes when they would only add noise.\n */\nconst enabled = !('NO_COLOR' in process.env) && process.stdout.isTTY === true;\n\nconst identity = (s: string): string => s;\n\nexport const color = {\n enabled,\n bold: enabled ? pc.bold : identity,\n dim: enabled ? pc.dim : identity,\n green: enabled ? pc.green : identity,\n yellow: enabled ? pc.yellow : identity,\n red: enabled ? pc.red : identity,\n cyan: enabled ? pc.cyan : identity,\n gray: enabled ? pc.gray : identity,\n};\n"],"mappings":"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","names":["fs","path","fs","path","z","fs","YAML","fs","path","path","path","fs","fs","YAML","path","fs","fs","path","z","ISO_DATE_REGEX","isValidIsoDate","isoDate","fs","path","YAML","z","fs","YAML","path","fs","path","z","ISO_DATE_REGEX","isValidIsoDate","isoDate","fs","fs","fs","path","z","z","fs","path","path","fs","fs","randomBytes","path","z","ISO_8601_REGEX","isValidIso8601","iso8601","paths","paths","path","randomBytes","fs","path","path","YAML","MS_PER_DAY","FRONTMATTER_DELIM","fs","describe","path","exists","fs","path","path","z","path","MS_PER_DAY","path","fs","path","z","z","fs","path","ArgsSchema","z","ResultSchema","path","z","fs","os","path","matter","path","fs","matter","os","ArgsSchema","z","ResultSchema"]}
|