cyber-mux 0.3.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/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","names":["resolveTemplateSource"],"sources":["../src/output.ts","../src/cli-error.ts","../src/cli-options.ts","../src/prompt.ts","../src/template-capture.ts","../src/template-edit.ts","../src/template-session.ts","../src/worktree-session.ts","../src/cli.ts"],"sourcesContent":["import { homedir } from 'node:os'\nimport { sep } from 'node:path'\n\n/**\n * A path with the caller's home directory collapsed to `~` — for HUMAN output only. Every worktree\n * of a repo shares a long home-rooted prefix, so the table spends width on a string the reader\n * already knows. JSON output must NEVER pass through here: a consumer needs the absolute path.\n *\n * The match is on a path BOUNDARY, not a prefix — `/home/unionalX` is not under `/home/unional`, so\n * only `$HOME` itself and `$HOME/...` are rewritten. A home of `/` collapses nothing, since every\n * absolute path would otherwise become `~`.\n */\nexport function tildify(path: string, home: string = homedir()): string {\n\tif (!home || home === sep || home === '/') return path\n\tif (path === home) return '~'\n\tfor (const s of new Set([sep, '/'])) {\n\t\tif (path.startsWith(home + s)) return `~${path.slice(home.length)}`\n\t}\n\treturn path\n}\n\nfunction printJson(data: unknown) {\n\tconsole.log(JSON.stringify(data, null, 2))\n}\n\nexport function printFields(fields: Record<string, string | null | undefined>): void {\n\tconst entries = Object.entries(fields).filter(([, v]) => v != null) as [string, string][]\n\tif (entries.length === 0) return\n\tconst width = Math.max(...entries.map(([k]) => k.length))\n\tfor (const [key, val] of entries) {\n\t\tconsole.log(`${key.padEnd(width)} ${val}`)\n\t}\n}\n\n/**\n * A #9 contextual-disclosure suggestion: an obvious next move the caller can take, named as data\n * rather than prose. `message` says what is worth doing; `command` is the concrete invocation that\n * does it. Dynamic parts are the caller's OWN values (a name they passed, a branch they named), never\n * a guessed id.\n */\nexport type HelpEntry = { message: string; command: string }\n\n/**\n * Render #9 suggestions as a `help[N]:` block on stdout — inside the structured payload, the stream an\n * agent reads, not stderr it never does. Each entry is a message line and its command, indented under\n * it. Prints NOTHING for an empty list: a self-contained result owes no suggestion (#9's\n * omit-when-self-contained rule), so the block never appears as noise.\n */\nexport function printHelp(entries: HelpEntry[]): void {\n\tentries.forEach((entry, i) => {\n\t\tconsole.log(`help[${i}]: ${entry.message}`)\n\t\tconsole.log(` -> ${entry.command}`)\n\t})\n}\n\nexport function printTable<T>(items: T[], cols: { label: string; get: (item: T) => string }[]): void {\n\tif (items.length === 0) {\n\t\tconsole.log('(none)')\n\t\treturn\n\t}\n\tconst widths = cols.map((c) => Math.max(c.label.length, ...items.map((i) => c.get(i).length)))\n\tconsole.log(cols.map((c, i) => c.label.toUpperCase().padEnd(widths[i]!)).join(' '))\n\tconsole.log(widths.map((w) => '-'.repeat(w)).join(' '))\n\tfor (const item of items) {\n\t\tconsole.log(cols.map((c, i) => c.get(item).padEnd(widths[i]!)).join(' '))\n\t}\n}\n\nfunction getFormat(): string | undefined {\n\tconst argv = process.argv\n\tconst fmtIdx = argv.indexOf('--format')\n\tif (fmtIdx !== -1) return argv[fmtIdx + 1]\n\tif (argv.includes('--json')) return 'json' // hidden backward-compat alias\n\treturn undefined\n}\n\n/**\n * Whether the caller asked for machine-readable output. Exported because `output()` is not the only\n * writer that owes it: a structured ERROR is rendered by `reportError` (`cli-error.ts`) rather than\n * through `output()`, and it has to honor `--format json` exactly as the success path does. Both write\n * stdout — AXI's stream for everything the agent consumes, errors included.\n */\nexport function isJsonOutput(): boolean {\n\treturn getFormat() === 'json'\n}\n\n// True when the caller is a script or agent — suppress interactive prompts.\nexport function isAutomatedOutput(): boolean {\n\tconst fmt = getFormat()\n\treturn fmt === 'json' || fmt === 'agent'\n}\n\nexport function output(data: unknown, readable: () => void): void {\n\tif (isJsonOutput()) printJson(data)\n\telse readable()\n}\n","import { isJsonOutput } from './output.ts'\n\n/**\n * The error surface — AXI's #6, made concrete.\n *\n * Every failure is a STRUCTURED, CODED error on **stdout**, because stdout is the stream AXI reserves\n * for what the agent consumes — data, errors and suggestions alike — while stderr is defined as debug\n * the agent does not read. A report whose whole purpose is telling a caller what went wrong and how to\n * fix it is the last thing that belongs on the ignored stream. This does not muddy the payload: a verb\n * either succeeds and writes its result or fails and writes its error, never both, so the exit code\n * tells the two apart before anything is parsed.\n *\n * Three things every error carries, and they are not decoration:\n * - a **stable `code`** a script matches on, so one failure mode is told from another without parsing\n * prose (`no-mux` is not `pane-not-found` is not `ambiguous-pane`);\n * - a **`help`** line naming THIS CLI's command that fixes it — never \"see --help\", and never a\n * dependency's own name: an agent handed a raw tmux/herdr diagnostic cannot act on it through\n * cyber-mux, so a backend's text is TRANSLATED here rather than forwarded;\n * - an **`exit`** code that separates a usage error (2 — a missing or malformed argument, whose fix is\n * a different invocation) from a genuine operation failure (1).\n */\nexport class CliError extends Error {\n\tconstructor(\n\t\treadonly code: string,\n\t\tmessage: string,\n\t\treadonly help: string,\n\t\treadonly exit: 1 | 2,\n\t\t/** Extra structured fields the JSON form carries beside code/message/help — e.g. an ambiguity's\n\t\t * candidates. Never free-text; a machine reads these. */\n\t\treadonly extra?: Record<string, unknown> | undefined,\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'CliError'\n\t}\n}\n\n/** The stable code the ambiguity error carries, in both formats — what a caller matches on. */\nexport const AMBIGUOUS_CODE = 'ambiguous-pane'\n\n/** One candidate of an ambiguous locator: what tells it apart, and what retries it. */\nexport interface PaneCandidate {\n\tid: string\n\tlabel: string | null\n\tcwd: string | null\n}\n\n/**\n * An ambiguous locator — a `CliError` like any other, so the one renderer and the one verb-boundary\n * catch handle it with no special case, and so a caller sees the same `{ code, help, exit }` shape it\n * sees for every other failure.\n *\n * It is THROWN rather than reported where it is found: reporting in place would mean exiting from\n * inside `resolveTarget`, and a verb's own catch-all could then flatten an exit-2 ambiguity into an\n * exit-1 generic failure behind its back. A typed error is what makes the ambiguity visible to every\n * catch it passes through, so each one rethrows it deliberately instead of swallowing it by accident.\n *\n * Each candidate carries its id, its label and its cwd: the id is the RETRY — paste it back and the\n * ambiguity is gone, since an id outranks every name — and the cwd is what actually tells three panes\n * all labeled `worker` apart.\n */\nexport class AmbiguousPaneError extends CliError {\n\tconstructor(\n\t\treadonly locator: string,\n\t\treadonly candidates: PaneCandidate[],\n\t) {\n\t\tsuper(\n\t\t\tAMBIGUOUS_CODE,\n\t\t\t`\"${locator}\" matches ${candidates.length} panes — an id resolves it`,\n\t\t\t`retry with one of the ids: ${candidates.map((c) => c.id).join(' ')}`,\n\t\t\t2,\n\t\t\t{ candidates },\n\t\t)\n\t\tthis.name = 'AmbiguousPaneError'\n\t}\n}\n\n/**\n * The ONE renderer — every coded failure reaches stdout through here, and exits.\n *\n * `--format json` emits the machine form: a single `{ error: { code, message, help, ...extra } }`\n * object, the stable code first, no free-text prose beside it. The readable form leads its human line\n * with the same `code` token a script branches on — so a person scanning the terminal sees exactly\n * what a `--format json` consumer matches on — then the `help` line, then (for an ambiguity) one line\n * per candidate: `<id> <label> <cwd>`, the id-first shape whose first column is the retry.\n */\nexport function reportError(e: CliError): never {\n\tif (isJsonOutput()) {\n\t\tconsole.log(JSON.stringify({ error: { code: e.code, message: e.message, help: e.help, ...e.extra } }, null, 2))\n\t} else {\n\t\t// The code leads the human line too: the stable token is the point of the whole surface, so it\n\t\t// belongs where a person reads as much as where a script matches — not hidden in the JSON alone.\n\t\tconsole.log(`error: ${e.code}: ${e.message}`)\n\t\tconsole.log(`help: ${e.help}`)\n\t\tconst candidates = e.extra?.['candidates'] as PaneCandidate[] | undefined\n\t\tif (candidates) {\n\t\t\tfor (const c of candidates) console.log(` ${c.id} ${c.label ?? ''} ${c.cwd ?? ''}`)\n\t\t}\n\t}\n\tprocess.exit(e.exit)\n}\n","import { InvalidArgumentError, Option } from 'commander'\n\n/** Output format shared by every command: `text` (human), `json`, or `agent`. */\nexport const FORMAT_OPTION: Option = new Option('--format <format>', 'Output format').choices(['text', 'json', 'agent'])\n\n/**\n * Accumulate one `--env KEY=VALUE` into the running map. Repeatable: commander calls this once per\n * flag, threading the previous map through, so `--env A=1 --env B=2` collects both. Rejecting a\n * malformed pair from HERE — the parser, before the action runs — is what makes \"rejected before any\n * side effect\" hold on every verb, worktree-creating ones included. The KEY is everything before the\n * first `=`, the VALUE everything after it: a value may contain `=` (a URL query, a base64 pad) and a\n * KEY may not, so the first `=` is the only unambiguous split. A missing `=` is malformed; a present\n * `=` with nothing after it is a deliberate empty value, not an error.\n */\nfunction collectEnv(pair: string, previous: Record<string, string> = {}): Record<string, string> {\n\tconst eq = pair.indexOf('=')\n\tif (eq <= 0) throw new InvalidArgumentError(`expected KEY=VALUE, got \"${pair}\"`)\n\treturn { ...previous, [pair.slice(0, eq)]: pair.slice(eq + 1) }\n}\n\n/**\n * `--env KEY=VALUE`, repeatable — the CLI door to the seam's env option, on every verb that opens a\n * pane. One shared Option so the collector, the split rule, and the rejection are defined once and\n * every verb inherits them, the way `AT_OPTION`/`LABEL_OPTION` are shared. Conflicts with `--template`,\n * whose template owns its own panes' env; the two verbs that carry `--template` refuse the pair.\n */\nexport const ENV_OPTION: Option = new Option('--env <pair>', 'Environment variable KEY=VALUE (repeatable)')\n\t.argParser(collectEnv)\n\t.conflicts('template')\n\n/** Placement for a newly opened pane, matching `MuxPlacement`. */\nexport const AT_OPTION: Option = new Option('--at <placement>', 'Where to place the new pane').choices([\n\t'pane:right',\n\t'pane:down',\n\t'tab',\n\t'workspace',\n])\n\n/**\n * Name for whatever `--at` opens. Host-neutral because every backend names every tier: on herdr a\n * workspace/tab/pane label, on tmux a window name (where `workspace` and `tab` both collapse to a\n * Window) or a pane title.\n */\nexport const LABEL_OPTION: Option = new Option('--label <label>', 'Name for the opened workspace/tab/pane')\n","import { createInterface } from 'node:readline/promises'\n\n/**\n * The interactive seam — a line asked of a human, injected for exactly the reason `Exec` and\n * `TemplateStore` are: `template edit` is a conversation, and a conversation reaching for\n * `process.stdin` directly would make it the one verb `cli.test.ts` cannot drive.\n *\n * **This is the package's first async seam, and deliberately its narrowest.** `Exec` is synchronous\n * by construction and every adapter is built on that; nothing here changes it. A prompt cannot be\n * synchronous, so it gets its own seam rather than widening that one — no adapter, no backend and no\n * pure module ever sees this type, and the async reaches exactly one command's action.\n */\nexport interface Prompt {\n\t/**\n\t * Ask one question and resolve to the line typed.\n\t *\n\t * `undefined` means the human is GONE — EOF, a closed stream, Ctrl-D — and is a distinct answer\n\t * from `''` (they pressed Enter). The caller must stop asking on `undefined`; continuing would\n\t * spin through every remaining question against a dead stream.\n\t *\n\t * `initial` is pre-filled into the editable line, so answering \"the same but one flag different\"\n\t * is an edit rather than a retype. Best-effort: a stream that cannot pre-fill still asks.\n\t */\n\task(question: string, initial?: string): Promise<string | undefined>\n\t/** Release the terminal. Safe to call twice; the caller does so in a `finally`. */\n\tclose(): void\n}\n\n/**\n * Opening a prompt is a FACTORY rather than a live `Prompt` on `Deps`, and that is load-bearing: a\n * readline interface holds stdin open from the moment it exists, so building one at program-assembly\n * time would make every unrelated verb — `list`, `doctor`, `send` — hang instead of exiting. Only the\n * command that actually converses calls this.\n */\nexport type OpenPrompt = () => Prompt\n\nexport const realPrompt: OpenPrompt = () => {\n\tconst rl = createInterface({ input: process.stdin, output: process.stdout })\n\t// Latched rather than checked per-question: once the stream is gone it stays gone, and a flag read\n\t// before each `question` is what keeps a walk from issuing N doomed reads after the first EOF.\n\tlet closed = false\n\trl.on('close', () => {\n\t\tclosed = true\n\t})\n\treturn {\n\t\tasync ask(question, initial) {\n\t\t\tif (closed) return undefined\n\t\t\t// Raced against `close` because readline's own question promise never settles on Ctrl-D — it\n\t\t\t// emits `close` and leaves the caller awaiting forever. Whichever lands first wins, so an EOF\n\t\t\t// mid-question surfaces as `undefined` rather than a hung CLI.\n\t\t\treturn await new Promise<string | undefined>((resolve) => {\n\t\t\t\tlet settled = false\n\t\t\t\tconst settle = (value: string | undefined) => {\n\t\t\t\t\tif (settled) return\n\t\t\t\t\tsettled = true\n\t\t\t\t\trl.off('close', onClose)\n\t\t\t\t\tresolve(value)\n\t\t\t\t}\n\t\t\t\tconst onClose = () => settle(undefined)\n\t\t\t\trl.once('close', onClose)\n\t\t\t\trl.question(question).then(settle, () => settle(undefined))\n\t\t\t\t// AFTER `question`, which is what puts the text in the editable line rather than printing it.\n\t\t\t\tif (initial) rl.write(initial)\n\t\t\t})\n\t\t},\n\t\tclose: () => rl.close(),\n\t}\n}\n","import { relative, sep } from 'node:path'\nimport type { PaneRect, RegionPane, WorkspaceTab } from './mux.ts'\nimport type { PaneNode, SplitNode, TabNode, Template, TemplateNode } from './template.ts'\n\n/**\n * A live region, run backwards into a template — `template save`. PURE, like `template.ts` and for the\n * same reason: the hard part here is geometry, not I/O, and keeping every seam out means the n-ary\n * lowering, the ratio arithmetic and the ambiguous-grid rule are all testable with plain numbers and\n * no multiplexer at all.\n *\n * This is `desugar`'s inverse, and the fact that both directions land on the same canonical tree —\n * the right-comb — is the evidence the schema is coherent rather than arbitrary. Exporting a region\n * that `arrange: even-horizontal` built gives back that comb, ratios and all.\n *\n * **What it recovers, and what it cannot.** Geometry, labels and dirs. NEVER commands — and the\n * reason is portability, not availability. A backend CAN often say what is running: herdr's\n * `pane process-info` hands back full argv for a pane's whole foreground tree, and `/proc` gets there\n * from a pid on any backend. What none of them can give back is a command worth writing into a\n * template, because what they report is the RESOLVED command line, not the one a human typed:\n * `nr web dev` comes back as `node /run/user/1000/fnm_multishells/4223_1784479278417/bin/nr web dev`,\n * a path carrying a uid, a pid and a timestamp that is dead on the next machine and often on the next\n * login. An idle pane reports its shell, and a `claude` pane reports exactly `claude` with the flags\n * that made it that session already gone.\n *\n * A template is a statement about how a project is worked on, meant to be checked in and run\n * elsewhere; a machine-local argv is the opposite of that, and `apply` SUBMITS whatever `command`\n * says, so a wrong one fails by executing something. Absent beats wrong here, exactly as it does for\n * a pane's `label`. A template out of this module is a DRAFT with `command` left for the author.\n */\n\n/** A partition of the region — the same shape as `TemplateNode`, before panes become `PaneNode`s. */\ntype RegionTree = RegionLeaf | RegionSplit\n\ninterface RegionLeaf {\n\ttype: 'pane'\n\tpane: RegionPane\n}\n\ninterface RegionSplit {\n\ttype: 'split'\n\tdirection: 'right' | 'down'\n\tratio?: number | undefined\n\tfirst: RegionTree\n\tsecond: RegionTree\n}\n\nexport interface TemplateCapture {\n\ttemplate: Template\n\t/**\n\t * What the capture could not express, for the caller to print. Returned rather than written to\n\t * stderr so this module stays pure and the rules stay testable without capturing output.\n\t */\n\twarnings: string[]\n}\n\nconst right = (rect: PaneRect): number => rect.x + rect.width\nconst bottom = (rect: PaneRect): number => rect.y + rect.height\n\n/**\n * The axis a cut runs along. `right` means a vertical divider with panes side by side — the schema's\n * vocabulary, where the name says where the NEW pane goes rather than which way the divider lies.\n */\ninterface Axis {\n\tdirection: 'right' | 'down'\n\t/** Where a pane starts on this axis. */\n\tstart: (rect: PaneRect) => number\n\t/** Where a pane ends on this axis. */\n\tend: (rect: PaneRect) => number\n}\n\nconst HORIZONTAL: Axis = { direction: 'right', start: (r) => r.x, end: right }\nconst VERTICAL: Axis = { direction: 'down', start: (r) => r.y, end: bottom }\n\ninterface Cut {\n\tdirection: 'right' | 'down'\n\tratio: number\n\tfirst: RegionPane[]\n\tsecond: RegionPane[]\n}\n\n/**\n * The lowest cut on this axis that separates the panes cleanly, or `undefined` if none does.\n *\n * Taking the LOWEST rather than any is what produces a right-comb for an n-ary row: three panes side\n * by side cut first into `[a][b c]`, then `[b][c]` — the exact tree `desugar`'s `comb` emits for\n * `arrange: even-horizontal`, reached from the opposite direction.\n *\n * A candidate is any pane's start edge. It separates cleanly when every pane lies wholly before it\n * or wholly after it, and both sides have something in them.\n */\nfunction findCut(panes: RegionPane[], axis: Axis): Cut | undefined {\n\tconst candidates = [...new Set(panes.map((p) => axis.start(p.rect)))].sort((a, b) => a - b)\n\tfor (const at of candidates) {\n\t\tconst first = panes.filter((p) => axis.end(p.rect) <= at)\n\t\tconst second = panes.filter((p) => axis.start(p.rect) >= at)\n\t\tif (first.length === 0 || second.length === 0) continue\n\t\t// Anything straddling the line lands in neither group, so the counts not adding up IS the\n\t\t// \"this cut crosses a pane\" test — no separate overlap check needed.\n\t\tif (first.length + second.length !== panes.length) continue\n\t\treturn { direction: axis.direction, ratio: ratioOf(panes, second, axis), first, second }\n\t}\n\treturn undefined\n}\n\n/**\n * The fraction of the split region kept by `first` — the schema's `ratio`.\n *\n * Measured as the COMPLEMENT of what `second` occupies, over the whole region: `1 - second/total`.\n * The obvious `first / (first + second)` is subtly wrong on any backend that draws a divider, and\n * the arithmetic says why — tmux splitting a 50-row region reports 34 + 15, with the 51st row eaten\n * by the divider. `first / (first + second)` reads 34/49 = 0.69; the true split was 0.7, and the\n * divider row belongs to neither pane's height while still costing the region a row.\n *\n * Taking the complement puts that row back where the backend's own arithmetic puts it: tmux's `-l`\n * sizes the NEW pane, so `second` is exactly the fraction asked for and `first` keeps the rest,\n * divider included. That reads 1 - 15/50 = 0.7 — the number the split was actually made with. On a\n * backend with no divider (herdr) the two formulas agree, so nothing is traded for the fix.\n *\n * Both checked against live binaries: this recovers tmux's `-l 40%`/`-l 30%` splits as 0.6/0.7\n * exactly, and reproduces herdr's to within the cell it rounds to.\n */\nfunction ratioOf(all: RegionPane[], second: RegionPane[], axis: Axis): number {\n\tconst total = extent(all, axis)\n\tif (total <= 0) return 0.5\n\treturn 1 - extent(second, axis) / total\n}\n\n/** How far a group of panes reaches along an axis — its bounding box on that axis. */\nfunction extent(panes: RegionPane[], axis: Axis): number {\n\tconst starts = panes.map((p) => axis.start(p.rect))\n\tconst ends = panes.map((p) => axis.end(p.rect))\n\treturn Math.max(...ends) - Math.min(...starts)\n}\n\n/**\n * Cut the region into a binary tree, recursively.\n *\n * **`right` is tried before `down`, and the order is load-bearing on a grid.** A 2x2 is genuinely\n * ambiguous — cutting it vertically first and horizontally first both describe the same screen, and\n * neither is more true. Columns-then-rows is the tie-break because that is what `desugar`'s `tiled`\n * emits, so a tiled pool exports back as the tree it was built from rather than its transpose.\n *\n * A region no cut separates cannot come out of a multiplexer: both backends build regions BY\n * splitting, so every region they can report is guillotine-cuttable by construction. Reaching the\n * throw means the geometry did not come from where we think it did — which is worth saying loudly\n * rather than papering over with a tree that misplaces the user's panes.\n */\nfunction partition(panes: RegionPane[]): RegionTree {\n\tif (panes.length === 1) return { type: 'pane', pane: panes[0]! }\n\tconst cut = findCut(panes, HORIZONTAL) ?? findCut(panes, VERTICAL)\n\tif (!cut) {\n\t\tthrow new Error(\n\t\t\t`this region's panes do not form a splittable tree (${panes.length} panes: ${panes.map((p) => p.id).join(', ')}) — ` +\n\t\t\t\t'export can only capture a region built by splitting',\n\t\t)\n\t}\n\tconst node: RegionSplit = {\n\t\ttype: 'split',\n\t\tdirection: cut.direction,\n\t\tfirst: partition(cut.first),\n\t\tsecond: partition(cut.second),\n\t}\n\tconst ratio = roundRatio(cut.ratio)\n\t// An even split is the schema's DEFAULT, so an even cut emits no ratio at all rather than `0.5`.\n\t// Keeps an exported grid as clean as the hand-written one it should match.\n\tif (ratio !== 0.5) node.ratio = ratio\n\treturn node\n}\n\n/**\n * Two decimals, and clamped strictly inside `(0, 1)`.\n *\n * Two because the emitted template is meant to be READ and edited: a 3-pane row wants `0.33`, not\n * `0.33167`, and the cell it costs is invisible. The clamp is the guard on a degenerate capture — a\n * pane one cell wide in a wide region rounds to `0`, which `validateTemplate` rejects outright, so an\n * export of a real screen would emit a template that fails its own validator.\n */\nfunction roundRatio(ratio: number): number {\n\tconst rounded = Math.round(ratio * 100) / 100\n\treturn Math.min(0.99, Math.max(0.01, rounded))\n}\n\n/**\n * The `dir` a pane's cwd becomes: relative to the root, or `undefined` when it IS the root or sits\n * outside it. Apply's injection run backwards — apply joins `cwd + dir`, so export subtracts.\n *\n * The schema forbids `cwd` outright, so a pane outside the root has nowhere to put its location and\n * genuinely loses it. That is reported as a warning rather than dropped in silence, and never\n * emitted as a `..` path: `dir` must stay under the apply-time target, so a template that escaped it\n * would fail validation on the way back in.\n */\nfunction toDir(\n\tpaneCwd: string | undefined,\n\trootCwd: string | undefined,\n): { dir?: string | undefined; outside: boolean } {\n\tif (!paneCwd || !rootCwd) return { outside: false }\n\tconst rel = relative(rootCwd, paneCwd)\n\tif (rel === '') return { outside: false }\n\tif (rel.startsWith('..') || rel.split(sep).includes('..')) return { outside: true }\n\treturn { dir: rel, outside: false }\n}\n\n/** The pane sitting on the region's own root — follow `first` down, exactly as `firstPane` does. */\nfunction rootOf(tree: RegionTree): RegionPane {\n\treturn tree.type === 'pane' ? tree.pane : rootOf(tree.first)\n}\n\nexport interface CaptureTemplateOptions {\n\t/** The template's `name` — validated by the caller, since a name is also a lookup key. */\n\tname: string\n\tdescription?: string | undefined\n}\n\n/**\n * Capture a region into a template.\n *\n * The root pane's cwd becomes the template's implicit target — every other pane's `dir` is measured\n * from it — because that is precisely what apply injects `--cwd` as. A pane elsewhere on the disk\n * cannot be expressed and says so in `warnings`.\n */\nexport function captureTemplate(panes: RegionPane[], opts: CaptureTemplateOptions): TemplateCapture {\n\tif (panes.length === 0) throw new Error('a capture needs at least one pane — this region reported none')\n\tconst tree = partition(panes)\n\tconst ctx = context(rootOf(tree).cwd)\n\tconst template = shell(opts)\n\ttemplate.root = convert(tree, ctx)\n\treturn { template, warnings: ctx.warnings }\n}\n\n/**\n * Capture a whole workspace into a `tabs` template — the exact inverse of the tabs walk, and\n * `captureTemplate` one level up rather than a second derivation: each tab's tree comes off the SAME\n * `partition`, because a tab is a region and the geometry rules cannot depend on how many of them\n * there are.\n *\n * One thing is workspace-WIDE rather than per-tab, and it follows from what the schema already says:\n * the target is the FIRST tab's root pane, because that is the pane apply's `--cwd` opens the\n * workspace at, so every tab's `dir` is measured from that one root.\n */\nexport function captureWorkspaceTemplate(tabs: WorkspaceTab[], opts: CaptureTemplateOptions): TemplateCapture {\n\tif (tabs.length === 0) throw new Error('a workspace capture needs at least one tab — this workspace reported none')\n\tconst trees = tabs.map((tab) => {\n\t\tif (tab.panes.length === 0) {\n\t\t\tthrow new Error(`a capture needs at least one pane — tab ${tab.id} reported none`)\n\t\t}\n\t\treturn partition(tab.panes)\n\t})\n\tconst ctx = context(rootOf(trees[0]!).cwd)\n\tconst template = shell(opts)\n\ttemplate.tabs = tabs.map((tab, index) => {\n\t\tconst node: TabNode = {}\n\t\t// The label the tab carries, verbatim — never a workspace parsed back out of it. On a backend\n\t\t// with no workspace tier this is the composed `<workspace> - <tab>` the walk wrote, and\n\t\t// `acme - beta - main` reads as two different groupings under every split rule, so recovering one\n\t\t// is guessing. The grouping came from the tag; this is a human's to read and to fix up by hand.\n\t\tif (tab.label) node.label = tab.label\n\t\tnode.root = convert(trees[index]!, ctx)\n\t\treturn node\n\t})\n\treturn { template, warnings: ctx.warnings }\n}\n\n/** The template every capture starts from — the fields that owe nothing to the geometry. */\nfunction shell(opts: CaptureTemplateOptions): Template {\n\tconst template: Template = { name: opts.name }\n\tif (opts.description) template.description = opts.description\n\treturn template\n}\n\n/**\n * What converting a tree needs to know that the tree itself does not carry: the target the `dir`s are\n * measured from, and somewhere to say what could not be expressed.\n *\n * Shared by both captures deliberately — a workspace's `dir`s are measured from ONE root, so threading\n * one context through every tab is what makes them so.\n */\ninterface CaptureContext {\n\trootCwd: string | undefined\n\twarnings: string[]\n}\n\nfunction context(rootCwd: string | undefined): CaptureContext {\n\treturn { rootCwd, warnings: [] }\n}\n\nfunction toPaneNode(pane: RegionPane, ctx: CaptureContext): PaneNode {\n\tconst node: PaneNode = { type: 'pane' }\n\t// A label two panes share is captured onto BOTH, verbatim. It got there because a human renamed the\n\t// pane by hand, which is the exact fact this capture exists to preserve — dropping it would report\n\t// \"no label\" where there is one, against the absent-rather-than-false rule the rest of this node\n\t// follows. Nothing keys on a label, so a shared one is a name two panes have, not a collision.\n\tif (pane.label) node.label = pane.label\n\tconst { dir, outside } = toDir(pane.cwd, ctx.rootCwd)\n\tif (dir) node.dir = dir\n\tif (outside) {\n\t\tctx.warnings.push(\n\t\t\t`pane ${pane.id}${pane.label ? ` (\"${pane.label}\")` : ''} runs in ${pane.cwd}, which is not under the ` +\n\t\t\t\t`captured root ${ctx.rootCwd} — a template cannot pin a directory, so this pane is captured without one`,\n\t\t)\n\t}\n\treturn node\n}\n\n/**\n * A partition into schema nodes. `command` is never emitted and there is no branch here that could\n * emit one: what a backend can report about a running pane is a resolved, machine-local command line\n * rather than a portable one (the module doc has the why), so a capture at any tier is a DRAFT with\n * `command` left for the author.\n */\nfunction convert(node: RegionTree, ctx: CaptureContext): TemplateNode {\n\tif (node.type === 'pane') return toPaneNode(node.pane, ctx)\n\tconst split: SplitNode = {\n\t\ttype: 'split',\n\t\tdirection: node.direction,\n\t\tfirst: convert(node.first, ctx),\n\t\tsecond: convert(node.second, ctx),\n\t}\n\tif (node.ratio !== undefined) split.ratio = node.ratio\n\treturn split\n}\n","import {\n\tcollectPanes,\n\ttype FlatPane,\n\tresolveTree,\n\ttype TabNode,\n\ttype Template,\n\ttype TemplateNode,\n\ttype TemplateTree,\n} from './template.ts'\n\n/**\n * The edit plan behind `template edit` — what to ask about, and where each answer goes back. PURE,\n * like `template.ts` and `template-capture.ts` and for the same reason: the hard part is addressing a\n * pane inside two different spellings of the same tree, and keeping every seam out means that\n * addressing is testable with plain objects and no terminal at all.\n *\n * **This is why the prompting lives in `cli.ts` and not here.** A guided edit is a conversation, which\n * is inherently stateful and async; the decision of WHAT to ask and WHERE to put the answer is\n * neither. Splitting them at that line keeps the whole interesting half hermetic — every rule below\n * is pinned by a unit test that never opens stdin.\n *\n * **The one rule that shapes everything: a template's SPELLING survives the edit.** A template says\n * its geometry either as an explicit `root` tree or as the flat `panes` + `arrange` sugar, and those\n * are not interchangeable to the human who wrote one. The obvious implementation — desugar, edit the\n * tree, write the tree back — would silently rewrite a hand-written 4-line flat template into a\n * nested `split` tree nobody wants to read. So both `planEdits` and `applyEdits` walk the SOURCE\n * shape and never call `resolveTree`, and a flat template comes back out flat.\n */\n\n/** A field a guided edit can fill. `command` is the reason this verb exists — a capture lands with\n * none (see `template-capture.ts`) — but the addressing is field-agnostic, so adding one later is a\n * new member here and nothing else. */\nexport type EditField = 'command' | 'label'\n\n/**\n * One pane, as something to ask about: where it lives, and what it says now.\n *\n * `index` is the pane's ordinal in APPLY order — `collectPanes`'s depth-first `first`-before-`second`\n * walk, which is the order the manifest reports and commands submit in (`template-session.ts`'s\n * `ordered`). That is deliberate rather than convenient: the number this prompt shows the author has\n * to be the number they see in the manifest afterwards, or the two views name different panes.\n */\nexport interface EditSlot {\n\t/** Which tab, for a `tabs` template; absent for a single-region one. */\n\ttab?: number\n\t/** The tab's own label, carried so a prompt can show it without re-walking the template. */\n\ttabLabel?: string | undefined\n\t/** Ordinal within this tab, in apply order. */\n\tindex: number\n\t/**\n\t * Where the pane sits on screen, in words — `top-left`, `right`, `center`.\n\t *\n\t * The one thing that actually answers \"which pane am I being asked about?\", which an ordinal and a\n\t * label cannot: apply order is a tree walk, not a reading order, so pane 2 of a 2x2 is the pane\n\t * BELOW pane 1 rather than the one beside it. Absent when the tab holds one pane (there is nothing\n\t * to tell apart) or when the geometry cannot be resolved.\n\t */\n\tposition?: string\n\tlabel?: string\n\tdir?: string\n\tcommand?: string\n}\n\n/** A pane's share of its tab, as fractions of the whole — the unit square, never cells. */\nexport interface UnitRect {\n\tx: number\n\ty: number\n\twidth: number\n\theight: number\n}\n\n/**\n * One answer, addressed back to the slot it came from.\n *\n * `value: undefined` CLEARS the field rather than meaning \"no answer\" — a slot the author left alone\n * yields no `EditAnswer` at all. Keeping \"unset it\" and \"did not say\" as different things is what\n * lets `applyEdits` be a total function of its answers: it never has to guess whether an absent\n * value meant erase or skip.\n */\nexport interface EditAnswer {\n\ttab?: number\n\tindex: number\n\tfield: EditField\n\tvalue: string | undefined\n}\n\n/**\n * A tree's panes in apply order, as references INTO the template.\n *\n * The two spellings converge here and nowhere else. For the flat sugar the panes are already a list\n * in the order `desugar` lays them out — both `comb` and `tiled` slice contiguously and preserve\n * order, so the array index IS the apply ordinal (pinned by a test, since that is a property of\n * `desugar` this module depends on rather than one it owns). For the explicit tree it is\n * `collectPanes` on `root`, which is the very walk apply uses.\n *\n * Returning references is the whole trick: `applyEdits` clones the template first, then mutates\n * what this hands back, so a write lands in the clone's own `panes[]` or `root` subtree without this\n * module ever knowing which spelling it was.\n */\nfunction treePanes(tree: TemplateTree): FlatPane[] {\n\tif (tree.root) return collectPanes(tree.root)\n\treturn tree.panes ?? []\n}\n\n/**\n * Where every pane in a tree lands, as fractions of the tab — the geometry a template DETERMINES,\n * computed the same way apply builds it.\n *\n * `ratio` is the fraction kept by `first` (the original pane), so a `right` split at 0.6 puts `first`\n * in the left 60% and `second` in what is left. Splitting the remainder rather than multiplying by\n * `1 - ratio` is what keeps a comb exact: three even panes come out at exactly 1/3 each instead of\n * drifting on the last one.\n *\n * Unit fractions rather than cells because a template has no size — it is applied to whatever region\n * it is given, and the only honest thing to say is a proportion.\n */\nfunction layout(node: TemplateNode, rect: UnitRect, acc: UnitRect[] = []): UnitRect[] {\n\tif (node.type === 'pane') {\n\t\tacc.push(rect)\n\t\treturn acc\n\t}\n\tconst ratio = node.ratio ?? 0.5\n\tif (node.direction === 'right') {\n\t\tconst width = rect.width * ratio\n\t\tlayout(node.first, { ...rect, width }, acc)\n\t\tlayout(node.second, { ...rect, x: rect.x + width, width: rect.width - width }, acc)\n\t} else {\n\t\tconst height = rect.height * ratio\n\t\tlayout(node.first, { ...rect, height }, acc)\n\t\tlayout(node.second, { ...rect, y: rect.y + height, height: rect.height - height }, acc)\n\t}\n\treturn acc\n}\n\n/**\n * A rect in words, from where its CENTER falls on a 3x3 grid.\n *\n * Thirds rather than halves because halves cannot name a middle: a row of three panes would come out\n * `left`, `left`, `right`, which is worse than saying nothing. Reading the center rather than the\n * edges is what makes an uneven split still land in the band a human would point at — a pane taking\n * the left 60% is `left`, not straddling.\n *\n * Deliberately coarse. This is a hint that tells two panes apart on one screen, not a coordinate; a\n * template with a dozen panes will repeat a word, and the ordinal is still what identifies a pane.\n */\nexport function describePosition(rect: UnitRect): string {\n\tconst column = band(rect.x + rect.width / 2, 'left', 'center', 'right')\n\tconst row = band(rect.y + rect.height / 2, 'top', 'middle', 'bottom')\n\tif (row === 'middle') return column === 'center' ? 'center' : column\n\tif (column === 'center') return row\n\treturn `${row}-${column}`\n}\n\nfunction band(center: number, low: string, mid: string, high: string): string {\n\tif (center < 1 / 3) return low\n\tif (center > 2 / 3) return high\n\treturn mid\n}\n\n/**\n * Each pane's position, in apply order — or nothing at all.\n *\n * Empty for a single-pane tree, because \"center\" said of the only pane is noise rather than a\n * bearing. Empty too when the tree cannot be resolved: this is a display hint, and a template\n * malformed enough to defeat `resolveTree` should still be walkable rather than refused HERE, where\n * the error would name the wrong thing. Validation is the caller's job and already ran.\n */\nfunction positionsOf(tree: Template | TabNode): string[] {\n\tlet rects: UnitRect[]\n\ttry {\n\t\trects = layout(resolveTree(tree), { x: 0, y: 0, width: 1, height: 1 })\n\t} catch {\n\t\treturn []\n\t}\n\treturn rects.length < 2 ? [] : rects.map(describePosition)\n}\n\n/**\n * Every pane worth asking about, in the order a walk should ask.\n *\n * Tabs in order, panes within each tab in apply order — the same traversal `walkTabs` submits\n * commands in, so an author filling this top to bottom is filling it in the order it will run.\n */\nexport function planEdits(template: Template): EditSlot[] {\n\tconst slots: EditSlot[] = []\n\tif (template.tabs) {\n\t\ttemplate.tabs.forEach((tab, index) => {\n\t\t\tconst positions = positionsOf(tab)\n\t\t\tfor (const [ordinal, pane] of treePanes(tab).entries()) {\n\t\t\t\tslots.push({ tab: index, tabLabel: tab.label, index: ordinal, ...at(positions, ordinal), ...fields(pane) })\n\t\t\t}\n\t\t})\n\t\treturn slots\n\t}\n\tconst positions = positionsOf(template)\n\tfor (const [ordinal, pane] of treePanes(template).entries()) {\n\t\tslots.push({ index: ordinal, ...at(positions, ordinal), ...fields(pane) })\n\t}\n\treturn slots\n}\n\n/** A position when there is one — absent rather than an empty string, like every other slot field. */\nfunction at(positions: string[], ordinal: number): { position?: string } {\n\tconst position = positions[ordinal]\n\treturn position ? { position } : {}\n}\n\n/** What a slot reports about a pane — the fields a prompt shows, never the pane object itself. */\nfunction fields(pane: FlatPane): Pick<EditSlot, 'label' | 'dir' | 'command'> {\n\tconst out: Pick<EditSlot, 'label' | 'dir' | 'command'> = {}\n\tif (pane.label !== undefined) out.label = pane.label\n\tif (pane.dir !== undefined) out.dir = pane.dir\n\tif (pane.command !== undefined) out.command = pane.command\n\treturn out\n}\n\n/**\n * The template with every answer written in — a NEW template, never the one passed in.\n *\n * Cloning rather than mutating is what makes `--dry-run` free and a failed validation harmless: the\n * caller still holds the original, so a refusal to write costs nothing and there is no half-edited\n * template to roll back. It also means an answer addressed at a pane that does not exist is caught\n * before anything is written, which is the only way this can fail.\n *\n * Everything not addressed is carried through verbatim, including keys this schema does not know\n * about — `structuredClone` copies the parsed JSON, so an edit is genuinely a field-level change and\n * never a re-serialization that quietly drops what it did not understand.\n */\nexport function applyEdits(template: Template, answers: EditAnswer[]): Template {\n\tconst next = structuredClone(template)\n\tfor (const answer of answers) {\n\t\tconst tree: TemplateTree | undefined = answer.tab === undefined ? next : next.tabs?.[answer.tab]\n\t\tif (!tree) throw new Error(`this template has no tab ${answer.tab}`)\n\t\tconst pane = treePanes(tree)[answer.index]\n\t\tif (!pane) {\n\t\t\tconst where = answer.tab === undefined ? 'this template' : `tab ${answer.tab}`\n\t\t\tthrow new Error(`${where} has no pane ${answer.index}`)\n\t\t}\n\t\tif (answer.value === undefined) delete pane[answer.field]\n\t\telse pane[answer.field] = answer.value\n\t}\n\treturn next\n}\n\n/**\n * The token that ADDRESSES a pane on the command line — `3`, or `2.3` in a tabs template. Both\n * 1-based, because they are read and typed by humans and agents rather than indexed by code.\n *\n * This is what the listing prints in its `pane` column and what `--set` takes, deliberately the same\n * string: an agent's loop is list-then-act, and a listing whose identifiers cannot be pasted straight\n * into the next command forces it to derive them. Panes are addressed by ORDINAL and never by label,\n * because a label is explicitly a name two panes may share (`PaneNode.label`) — an ambiguous selector\n * in a non-interactive API is a silent wrong-pane write.\n */\nexport function slotRef(slot: EditSlot): string {\n\treturn slot.tab === undefined ? `${slot.index + 1}` : `${slot.tab + 1}.${slot.index + 1}`\n}\n\n/** One `--set <ref>=<value>`, parsed. `value: undefined` clears, exactly as `-` does interactively. */\nexport interface SetSpec {\n\tref: string\n\tvalue: string | undefined\n}\n\n/**\n * Parse a `--set` argument into a reference and a value.\n *\n * Split on the FIRST `=` only, so a command containing one (`--set 1=FOO=bar make`) keeps it. An\n * empty value clears the field — the flag spelling of the walk's `-`, and unambiguous here because a\n * shell already distinguishes `--set 1=` from omitting the flag.\n */\nexport function parseSet(spec: string): SetSpec {\n\tconst at = spec.indexOf('=')\n\tif (at === -1) throw new Error(`--set needs <pane>=<value>, got \"${spec}\"`)\n\tconst ref = spec.slice(0, at).trim()\n\tif (ref === '') throw new Error(`--set needs a pane before the \"=\", got \"${spec}\"`)\n\tconst value = spec.slice(at + 1)\n\treturn { ref, value: value === '' ? undefined : value }\n}\n\n/**\n * Turn `--set` specs into answers against a known set of slots.\n *\n * Every reference is resolved BEFORE any answer is produced, so a batch naming one bad pane writes\n * none of them — a partial application of a multi-pane edit is the worst outcome available here,\n * since the caller cannot tell which half landed without re-reading the file.\n *\n * A value equal to what the pane already says yields no answer at all, which is what makes a re-run\n * of the same `--set` a no-op rather than a rewrite (AXI's idempotent-mutation rule).\n */\nexport function resolveSets(slots: EditSlot[], specs: SetSpec[], field: EditField): EditAnswer[] {\n\tconst byRef = new Map(slots.map((slot) => [slotRef(slot), slot]))\n\tconst answers: EditAnswer[] = []\n\tfor (const spec of specs) {\n\t\tconst slot = byRef.get(spec.ref)\n\t\tif (!slot) {\n\t\t\tthrow new Error(\n\t\t\t\t`no pane \"${spec.ref}\" in this template — it has ${slots.length} ` +\n\t\t\t\t\t`${slots.length === 1 ? 'pane' : 'panes'}: ${[...byRef.keys()].join(', ')}`,\n\t\t\t)\n\t\t}\n\t\tif (spec.value === slot[field]) continue\n\t\tconst answer: EditAnswer = { index: slot.index, field, value: spec.value }\n\t\tif (slot.tab !== undefined) answer.tab = slot.tab\n\t\tanswers.push(answer)\n\t}\n\treturn answers\n}\n\n/**\n * How a typed line becomes an answer — the prompt's one piece of vocabulary, here rather than in\n * `cli.ts` so it is pinned by a unit test alongside the rules it serves.\n *\n * Three cases, and the empty one is the important one: a guided walk shows every pane, so the author\n * passes through panes they do not want to touch far more often than ones they do. Enter therefore\n * has to mean KEEP, which leaves \"erase this\" needing a spelling of its own — `-`, because it is one\n * keystroke and is not a plausible command. A literal `-` is reachable by quoting it.\n */\nexport type EditInput = { kind: 'keep' } | { kind: 'set'; value: string }\n\nexport function readEditInput(line: string): EditInput {\n\tconst trimmed = line.trim()\n\tif (trimmed === '') return { kind: 'keep' }\n\tif (trimmed === '-') return { kind: 'set', value: '' }\n\tif (trimmed === \"'-'\" || trimmed === '\"-\"') return { kind: 'set', value: '-' }\n\treturn { kind: 'set', value: trimmed }\n}\n\n/**\n * The answers a walk produces, given what each slot was told — the pure core of the conversation.\n *\n * A `set` to the empty string is what CLEARS the field, which is why `readEditInput` maps `-` to it:\n * the schema has no use for `command: \"\"` (apply skips a falsy command anyway, see `submitCommands`),\n * so storing one would be storing a lie about a pane that runs nothing. An answer equal to what the\n * pane already says is dropped entirely, so a walk where the author pressed Enter through everything\n * reports zero changes rather than N no-op writes.\n */\nexport function toAnswers(slots: EditSlot[], inputs: EditInput[], field: EditField): EditAnswer[] {\n\tconst answers: EditAnswer[] = []\n\tfor (const [index, slot] of slots.entries()) {\n\t\tconst input = inputs[index]\n\t\tif (!input || input.kind === 'keep') continue\n\t\tconst value = input.value === '' ? undefined : input.value\n\t\tif (value === slot[field]) continue\n\t\tconst answer: EditAnswer = { index: slot.index, field, value }\n\t\tif (slot.tab !== undefined) answer.tab = slot.tab\n\t\tanswers.push(answer)\n\t}\n\treturn answers\n}\n","import { join } from 'node:path'\nimport { envFallback } from './env-fallback.ts'\nimport type { Exec } from './exec.ts'\nimport type { MuxAdapter, MuxPlacement, MuxTarget, OpenedPane } from './mux.ts'\nimport type { NewId } from './new-id.ts'\nimport {\n\tcollectPanes,\n\tfirstPane,\n\ttype PaneNode,\n\tresolveTree,\n\ttype TabNode,\n\ttype Template,\n\ttype TemplateNode,\n} from './template.ts'\n\n/**\n * Templates × sessions — the walk, and the only module that knows both halves. `template.ts` stays pure\n * and owes nothing to the mux; `mux.ts` stays a pure mux seam that owes nothing to templates.\n * Compiling one into the other is a third concern, and it lives here — exactly what\n * `worktree-session.ts` is to `worktree.ts` + `mux.ts`.\n *\n * The engine is cyber-mux's own: a tree-walk emitting `open`/`submit` against the PORTABLE\n * `MuxAdapter` verbs, never a backend's native template primitive. herdr's `template.apply` drops\n * out entirely rather than being deferred — it is a socket verb (this codebase speaks herdr's CLI,\n * synchronously, on purpose) and, more importantly, it is unique in the field: tmux, cmux, WezTerm\n * and screen have nothing equivalent. Leaning on it would mean the good path existing on exactly one\n * backend while every other backend needs this walk anyway. The capability a multiplexer must supply\n * is \"split THIS pane, that way\" — that is the whole ask, and it is `MuxOpenOptions.from`.\n */\n\n/** One pane the apply created — `label` is the key a higher layer addresses it by. */\nexport interface TemplatePaneReport {\n\tlabel: string | null\n\tpane: string\n\t/** The pane's resolved working directory: the apply-time cwd joined with the node's `dir`. */\n\tdir: string\n\tcommand: string | null\n\t/**\n\t * Which tab of the template this pane landed in, by its INDEX — the same argument `workspace` makes\n\t * one level down: a consumer grouping a tabs template's panes by tab needs something to group on.\n\t * `null` from a single-tab (`root`/`panes`) template — absent rather than an invented tab, since\n\t * such a template said nothing about tabs at all.\n\t *\n\t * The index rather than the tab's `label`, because a label is OPTIONAL (a tab may leave its name to\n\t * the backend) and a grouping key that is sometimes absent cannot group. The index is total and\n\t * collision-free, and it cannot be confused with the `null` a single-tab template reports, which a\n\t * label could be (a tab labeled `\"1\"` and a tab at index 1 would read alike). The label stays\n\t * recoverable from the template the manifest already names.\n\t */\n\ttab: number | null\n}\n\n/**\n * The whole handoff. `--format json` emits this, and it is the complete machine-readable answer to\n * \"which panes exist and what are they for\" — a dispatcher built on it needs NO new cyber-mux\n * surface, since it addresses panes through `read`/`submit`/`exists`/`focus`/`list`, which all\n * already exist.\n */\nexport interface TemplateManifest {\n\ttemplate: string\n\t/** The injected target — the apply-time cwd. Never anything the template said. */\n\tcwd: string\n\t/** `null` on tmux, matching how `reportOpenedWorktree` already reports it. */\n\tworkspace: string | null\n\tpanes: TemplatePaneReport[]\n}\n\n/**\n * A walk that threw partway. Carries the manifest of what WAS built, because apply does not roll\n * back: rolling back would mean killing panes, and a kill is not obviously safer than a half-built\n * template the caller can see and finish. This is the price of owning the engine rather than\n * delegating to an atomic tree-apply, and it is paid uniformly — a guarantee only herdr could make\n * is not a guarantee cyber-mux can offer.\n */\nexport class TemplateApplyError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\treadonly manifest: TemplateManifest,\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'TemplateApplyError'\n\t}\n}\n\ninterface WalkContext {\n\texec: Exec\n\tadapter: MuxAdapter\n\tcwd: string\n\tname: string\n\tworkspace: string | null\n\tdirExists: (path: string) => boolean\n\t/**\n\t * Whether the \"this backend cannot size a split\" warning has already been written. Shared across\n\t * every tab of an apply rather than per tab: the warning is about the BACKEND, so one apply says it\n\t * once however many tabs it opens.\n\t */\n\twarnedRatio: boolean\n}\n\n/**\n * One tab of an apply, with everything the report needs about it. A single-tab template is ONE of\n * these with a `null` index — the multi-tab walk is the same walk, run per tab, rather than a second\n * engine that could drift from it.\n */\ninterface TabState {\n\ttree: TemplateNode\n\t/** The tab's index in the template; `null` for a single-tab template, which has no tab tier. */\n\tindex: number | null\n\t/** The pane the tab's tree is built AGAINST — its own root region, never another tab's pane. */\n\troot: MuxTarget\n\t/**\n\t * Where the root pane ACTUALLY sits. Not derived — supplied by whoever opened the region, because\n\t * only they know. The root leaf is the one pane no split ever births, so `open --template` can place\n\t * it at `cwd + dir` while `worktree add --template` cannot: the worktree's workspace must open at the\n\t * worktree root, which is what the binding pins. Reporting `cwd + dir` regardless would make the\n\t * manifest claim a location nothing ever opened.\n\t */\n\trootDir: string\n\t/**\n\t * Whether the root pane's `env` was already set natively when the region was opened. Supplied by\n\t * whoever opened it, never inferred: it is true at every tier of `open` on both backends, and\n\t * false on exactly one route — herdr's `worktree create`, whose params carry no `env` at all. Only\n\t * the false case is prefixed, so the native routes can never double-apply.\n\t */\n\trootEnvHonored: boolean\n\t/** Template order — `first` before `second`; the order the manifest reports and commands submit in. */\n\tordered: PaneNode[]\n\t/** The leaf riding the region's own pane — the one leaf no split ever births. */\n\trootLeaf: PaneNode\n\t/** Recorded at each pane's BIRTH, so a throw later still reports every pane that actually exists. */\n\tpaneOf: Map<PaneNode, string>\n}\n\n/** A tab's bookkeeping, with its root pane already open and its root leaf pinned to that pane. */\nfunction tabState(\n\ttree: TemplateNode,\n\tindex: number | null,\n\troot: MuxTarget,\n\trootDir: string,\n\trootEnvHonored: boolean,\n): TabState {\n\tconst rootLeaf = firstPane(tree)\n\treturn {\n\t\ttree,\n\t\tindex,\n\t\troot,\n\t\trootDir,\n\t\trootEnvHonored,\n\t\tordered: collectPanes(tree),\n\t\trootLeaf,\n\t\t// The root leaf rides the region's own pane; every other leaf is born by exactly one split.\n\t\tpaneOf: new Map([[rootLeaf, root.id]]),\n\t}\n}\n\n/** A pane's resolved cwd: the apply-time target, joined with the node's relative `dir`. */\nfunction resolveDir(cwd: string, dir: string | undefined): string {\n\treturn dir ? join(cwd, dir) : cwd\n}\n\n/**\n * Every `dir` the template names, checked against the REAL target before anything is opened. A\n * branch that predates a directory is a real case, so the error names the pane and the resolved path\n * rather than just failing a mkdir somewhere.\n *\n * Up front, not per-pane-at-birth: a predictable error should not cost a half-built pool.\n */\nexport function assertTemplateDirs(tree: TemplateNode, cwd: string, dirExists: (path: string) => boolean): void {\n\tfor (const pane of collectPanes(tree)) {\n\t\tif (pane.dir === undefined) continue\n\t\tconst resolved = resolveDir(cwd, pane.dir)\n\t\tif (!dirExists(resolved)) {\n\t\t\tthrow new Error(`template pane \"${pane.label ?? '(unlabeled)'}\": directory does not exist — ${resolved}`)\n\t\t}\n\t}\n}\n\nexport interface OpenTemplateOptions {\n\t/** The injected target directory. */\n\tcwd: string\n\t/** Defaults to `workspace` — a fresh space is empty by construction. */\n\tat?: MuxPlacement | undefined\n\tlabel?: string | undefined\n\tdirExists: (path: string) => boolean\n\t/** Injected id source for the opaque tab-grouping id a `tabs` template mints — the seam that keeps\n\t * this a pure function rather than a caller of `node:crypto`. Unused by a single-region template. */\n\tnewId: NewId\n\t/** Passed to the region's own `open` for a `pane:*` placement; see `MuxOpenOptions.from`. */\n\tfrom?: MuxTarget | undefined\n}\n\n/**\n * Open a region and build the template inside it — `open --template`.\n *\n * The region opens BLANK (no `launch`) and its pane becomes the tree's root region: not a wasted\n * pane to close, but the pane the walk splits INTO. That is why nothing is launched here — the\n * template owns what runs.\n *\n * The manifest's `workspace` is whatever the region's own `open` landed in — the workspace it\n * created at the default `workspace` placement, or the one it landed inside at a `tab`/`pane:*`\n * placement. `null` only when the backend has no workspace tier (tmux) and so had nothing to report.\n * This is occupancy, not a worktree binding: `open` groups no repo, and a caller must not read a\n * workspace here as evidence that it did.\n */\nexport function openTemplate(\n\texec: Exec,\n\tadapter: MuxAdapter,\n\ttemplate: Template,\n\topts: OpenTemplateOptions,\n): TemplateManifest {\n\tif (template.tabs) return openTabsTemplate(exec, adapter, template, template.tabs, opts)\n\tconst tree = resolveTree(template)\n\t// Before the region is opened, so a missing dir opens nothing at all.\n\tassertTemplateDirs(tree, opts.cwd, opts.dirExists)\n\t// The root leaf sits on the region's OWN pane — no split ever births it — so its dir and env have\n\t// to ride in on this open or they are lost. Both are native at every tier on both backends, so\n\t// this route honors them exactly. No `launch`: commands are submitted last, together.\n\tconst rootLeaf = firstPane(tree)\n\tconst rootDir = resolveDir(opts.cwd, rootLeaf.dir)\n\tconst root = adapter.open(exec, {\n\t\tcwd: rootDir,\n\t\tat: opts.at ?? 'workspace',\n\t\tlabel: opts.label,\n\t\tenv: rootLeaf.env,\n\t\tfrom: opts.from,\n\t})\n\treturn walk(tabState(tree, null, root, rootDir, true), {\n\t\texec,\n\t\tadapter,\n\t\tcwd: opts.cwd,\n\t\tname: template.name,\n\t\t// The whole point of widening `open`'s return: before it carried a workspace, this was a\n\t\t// hardcoded null and the manifest could never report one, even on a backend that had just\n\t\t// opened a real workspace.\n\t\tworkspace: root.workspace ?? null,\n\t\tdirExists: opts.dirExists,\n\t\twarnedRatio: false,\n\t})\n}\n\n/**\n * The workspace label a tabs apply groups under: what the caller asked for, or the template's own\n * name. Never shortened, anywhere — it is the label the caller already chose, so the caller owns its\n * length, and not shortening is what makes a collision between two workspaces that shorten alike\n * impossible rather than merely handled.\n */\nfunction workspaceLabelOf(template: Template, label: string | undefined): string {\n\treturn label ?? template.name\n}\n\n/** The first tab's region, however the route in question came by it. */\ninterface FirstTab {\n\t/**\n\t * An `OpenedPane`, not a bare handle: the walk groups this tab like every other, and grouping\n\t * addresses the TAB. Both routes already hold it — `open --template` from the open it just ran,\n\t * `worktree add --template` from the one the worktree verbs ran — so requiring it here takes nothing\n\t * from either and is what lets the first tab be grouped rather than left out.\n\t */\n\troot: OpenedPane\n\trootDir: string\n\trootEnvHonored: boolean\n}\n\n/**\n * A workspace of N tabs — the single-tab walk, wrapped, with the inner walk unchanged and run once\n * per tab. Every later tab opens INSIDE the workspace at the `tab` placement; no tab is ever a split\n * of another tab's pane, which is the whole difference between a workspace of tabs and one tab of\n * panes.\n *\n * `firstTab` is the ONE thing the two routes differ in, and the reason they share this walk rather\n * than owning two that could drift: `open --template` opens the workspace and hands back its region,\n * while `worktree add --template` already HAS one — the worktree's own workspace, which that route\n * forced the placement for — so the first tab builds into it rather than opening a second.\n *\n * Every tab is opened and every split built BEFORE the first command is submitted — the single-tab\n * ordering, scaled: a split lands mid-render if it targets a pane already running an interactive\n * agent, and a tab is opened blank for exactly the reason a region is.\n */\nfunction walkTabs(\n\tctx: WalkContext,\n\ttabs: TabNode[],\n\ttrees: TemplateNode[],\n\tworkspaceLabel: string,\n\tgroup: string,\n\tfirstTab: () => FirstTab,\n): TemplateManifest {\n\tconst built: TabState[] = []\n\ttry {\n\t\ttrees.forEach((tree, index) => {\n\t\t\tlet opened: OpenedPane\n\t\t\tif (index === 0) {\n\t\t\t\tconst first = firstTab()\n\t\t\t\topened = first.root\n\t\t\t\tbuilt.push(tabState(tree, 0, first.root, first.rootDir, first.rootEnvHonored))\n\t\t\t\t// The one tab no backend can name at birth, named HERE — in the walk both routes share —\n\t\t\t\t// rather than in either route's own `firstTab`. The scenarios this serves say \"when it is\n\t\t\t\t// applied\", naming no route, so a route that could forget this is a scenario that is\n\t\t\t\t// silently false on it. Only the shared path makes forgetting impossible.\n\t\t\t\t//\n\t\t\t\t// Runs AFTER `firstTab()` because that is what settles the tier signal: `open --template`\n\t\t\t\t// learns it from the open it just ran, and `tabLabelFor` reads it to decide whether the\n\t\t\t\t// workspace is carried into the name.\n\t\t\t\t//\n\t\t\t\t// `opened.tab`, NEVER `opened.id`: the pane id would be green on tmux (which resolves a\n\t\t\t\t// pane in a window target) and silently broken on herdr (`tab_not_found`, discarded),\n\t\t\t\t// leaving the root tab named `1` with nothing raised.\n\t\t\t\tconst name = tabLabelFor(ctx, tabs[0]!, workspaceLabel)\n\t\t\t\tif (name !== undefined) ctx.adapter.rename(ctx.exec, { id: opened.tab }, 'tab', name)\n\t\t\t} else {\n\t\t\t\tconst rootLeaf = firstPane(tree)\n\t\t\t\tconst rootDir = resolveDir(ctx.cwd, rootLeaf.dir)\n\t\t\t\topened = ctx.adapter.open(ctx.exec, {\n\t\t\t\t\tcwd: rootDir,\n\t\t\t\t\t// A real tab in the workspace the first tab established — never a `pane:*` placement,\n\t\t\t\t\t// which would make this tab a split of the tab before it.\n\t\t\t\t\tat: 'tab',\n\t\t\t\t\t// Anchored to THAT workspace, and this is what `ctx.workspace` is for at open time rather\n\t\t\t\t\t// than only in the report: a bare `tab` placement is resolved by every backend against the\n\t\t\t\t\t// space the USER is looking at, so without this the first tab landed in the new workspace\n\t\t\t\t\t// and tabs 2..N landed beside the pane the command was RUN from.\n\t\t\t\t\t// `undefined` on a backend with no workspace tier (tmux) — there is no second space for a\n\t\t\t\t\t// tab to land in the wrong one of, so there is nothing to anchor to.\n\t\t\t\t\twithin: ctx.workspace ?? undefined,\n\t\t\t\t\t// Named at BIRTH: every tab but a new workspace's root can be, on both backends.\n\t\t\t\t\tlabel: tabLabelFor(ctx, tabs[index]!, workspaceLabel),\n\t\t\t\t\tenv: rootLeaf.env,\n\t\t\t\t})\n\t\t\t\t// `open` sets env natively at every tier on both backends, so no tab ever needs the prefix.\n\t\t\t\tbuilt.push(tabState(tree, index, opened, rootDir, true))\n\t\t\t}\n\t\t\t// EVERY tab, the first one included, and through the verb rather than `open`'s option — which\n\t\t\t// is the whole reason grouping is a verb. The first tab's region may have been opened before\n\t\t\t// this walk ever ran (`worktree add --template`), so an option on `open` could only ever have\n\t\t\t// covered tabs 2..N, and a group missing the workspace's own first tab is worse than no\n\t\t\t// group: `save --workspace` would confidently round-trip a 3-tab workspace as 2. Grouping\n\t\t\t// here means the route that opened the region cannot change what the template means.\n\t\t\t//\n\t\t\t// The tab's OWN name, never `tabLabelFor`'s composed display name: where the backend has no\n\t\t\t// workspace tier the display name is `<workspace> - <tab>`, so the backend's single name\n\t\t\t// field no longer holds the original. Handing the composed one here would re-prefix it on\n\t\t\t// every round trip. `undefined` when the tab left its name to the backend — nothing to store.\n\t\t\tctx.adapter.group(ctx.exec, { id: opened.tab }, group, tabs[index]!.label)\n\t\t\t// Against THIS tab's own root pane — the id threaded through every split of this tree.\n\t\t\tbuildGeometry(built[index]!, ctx)\n\t\t})\n\t} catch (err) {\n\t\t// Unchanged, one level up: apply does not roll back, so the tabs already built are reported and\n\t\t// nothing is killed. Adding a level does not buy an atomicity the node never offered.\n\t\tthrow new TemplateApplyError(err instanceof Error ? err.message : String(err), report(ctx, built))\n\t}\n\n\tsubmitCommands(built, ctx)\n\treturn report(ctx, built)\n}\n\n/** `open --template` with a tabs template: the first tab opens the workspace the rest live in. */\nfunction openTabsTemplate(\n\texec: Exec,\n\tadapter: MuxAdapter,\n\ttemplate: Template,\n\ttabs: TabNode[],\n\topts: OpenTemplateOptions,\n): TemplateManifest {\n\tconst trees = tabs.map((tab) => resolveTree(tab))\n\t// Every tab's dirs, before ANY tab is opened — a predictable error must not cost a half-built\n\t// workspace any more than it costs a half-built region.\n\tfor (const tree of trees) assertTemplateDirs(tree, opts.cwd, opts.dirExists)\n\n\t// The machine's carrier for the grouping, and the reason the label never has to be parsed back:\n\t// an opaque id no one reads FOR its content. A backend with a real workspace tier ignores it, that\n\t// tier already being the group.\n\tconst group = opts.newId()\n\tconst workspaceLabel = workspaceLabelOf(template, opts.label)\n\tconst ctx: WalkContext = {\n\t\texec,\n\t\tadapter,\n\t\tcwd: opts.cwd,\n\t\tname: template.name,\n\t\t// Set from the first tab's own open, below — whatever the backend says it landed in.\n\t\tworkspace: null,\n\t\tdirExists: opts.dirExists,\n\t\twarnedRatio: false,\n\t}\n\n\treturn walkTabs(ctx, tabs, trees, workspaceLabel, group, () => {\n\t\tconst rootLeaf = firstPane(trees[0]!)\n\t\tconst rootDir = resolveDir(opts.cwd, rootLeaf.dir)\n\t\tconst opened = adapter.open(exec, {\n\t\t\tcwd: rootDir,\n\t\t\tat: opts.at ?? 'workspace',\n\t\t\t// The WORKSPACE's name, not this tab's: at the `workspace` placement `label` names the space\n\t\t\t// being opened, and on a backend with a real tier that is the workspace itself. The tab under\n\t\t\t// it is named just below, once the backend has told us which kind of backend it is.\n\t\t\tlabel: workspaceLabel,\n\t\t\tenv: rootLeaf.env,\n\t\t\tfrom: opts.from,\n\t\t})\n\t\t// The tier signal, read from what the backend ACTUALLY reported rather than from its name: a\n\t\t// workspace on the open means this backend has a tier to have landed in; absent means it has\n\t\t// none (tmux). Set here because only this route can learn it — the worktree route is TOLD its\n\t\t// workspace by the caller that opened the region. Either way it is settled before `walkTabs`\n\t\t// names this tab, which is what turns on exactly this.\n\t\tctx.workspace = opened.workspace ?? null\n\t\treturn { root: opened, rootDir, rootEnvHonored: true }\n\t})\n}\n\n/**\n * A tab's label, as a human reads it.\n *\n * Where the backend has no workspace tier (tmux, which collapses workspace and tab onto one Window),\n * the workspace is carried into the label — `<workspace> - <tab>` — because the template's tabs would\n * otherwise land as an unlabeled pile with nothing marking them as one pool. Where the backend HAS the\n * tier (herdr), its UI already groups by the real workspace label, so a prefix would be redundant\n * noise and the tab carries its own label alone. The concept maps onto what the backend actually has.\n *\n * The workspace label goes in whole — never shortened. It is the label the caller already chose, so\n * the caller owns its length, and not shortening is what makes a collision between two workspaces that\n * shorten alike impossible rather than merely handled.\n *\n * This is the human's carrier only. The machine reads `workspaceGroup`, never this — the label is\n * ambiguous under every split rule (\"acme - beta - main\"), so it is written and never parsed back.\n */\nfunction tabLabelFor(ctx: WalkContext, tab: TabNode, workspaceLabel: string): string | undefined {\n\t// A tab may leave its name to the backend — matching `--label` omitted everywhere else, the\n\t// backend's own default then stands, and there is nothing to prefix.\n\tif (tab.label === undefined) return undefined\n\tif (ctx.workspace !== null) return tab.label\n\treturn `${workspaceLabel} - ${tab.label}`\n}\n\n/**\n * The pane that will sit on a region's own root pane — whoever opens that region must carry this\n * pane's `env` (and, where it can, its `dir`), because no split ever births it.\n *\n * For a tabs template that is the FIRST tab's root leaf: the first tab is the one built into the\n * region the caller opens, and every later tab opens its own space (carrying its own root leaf's env\n * at that open). Resolving the template itself here would desugar a `panes` list a tabs template does\n * not have.\n */\nexport function templateRootPane(template: Template): PaneNode {\n\treturn firstPane(resolveTree(template.tabs ? template.tabs[0]! : template))\n}\n\nexport interface ApplyTemplateOptions {\n\t/**\n\t * An ALREADY-OPEN blank region whose pane is the tree's root — e.g. a worktree's workspace.\n\t *\n\t * An `OpenedPane` rather than a bare handle, because a tabs template groups this region's tab like\n\t * every other tab it builds, and grouping addresses the tab. The caller that opened the region\n\t * already holds it — every backend reports the tab an open landed in — so requiring it costs\n\t * nothing and is what keeps the workspace's own first tab inside the group.\n\t */\n\troot: OpenedPane\n\tcwd: string\n\t/** The backend workspace the region lives in, when the backend binds one; `null` on tmux. */\n\tworkspace: string | null\n\t/**\n\t * Whether the root pane's `env` was already set when this region was opened. Required rather than\n\t * defaulted: only the caller that opened the region knows, and guessing wrong either drops the env\n\t * silently or applies it twice.\n\t */\n\trootEnvHonored: boolean\n\tdirExists: (path: string) => boolean\n\t/** Injected id source for the opaque tab-grouping id a `tabs` template mints; see\n\t * `OpenTemplateOptions.newId`. Unused by a single-region apply. */\n\tnewId: NewId\n\t/**\n\t * The label the region was opened under — the workspace's name, which a tabs template carries into\n\t * each later tab's label on a backend with no workspace tier. Only the caller that opened the region\n\t * knows what it named it; omitted, the template's own name stands, matching `open --template`'s\n\t * default.\n\t */\n\tlabel?: string | undefined\n}\n\n/**\n * Build a template inside a region someone else already opened — `worktree add --template`, where the\n * worktree's own workspace IS the region and its root pane is the tree's root.\n */\nexport function applyTemplateToRegion(\n\texec: Exec,\n\tadapter: MuxAdapter,\n\ttemplate: Template,\n\topts: ApplyTemplateOptions,\n): TemplateManifest {\n\tif (template.tabs) return applyTabsToRegion(exec, adapter, template, template.tabs, opts)\n\tconst tree = resolveTree(template)\n\tassertTemplateDirs(tree, opts.cwd, opts.dirExists)\n\t// The region was opened by someone whose own contract fixed its cwd — a worktree's workspace opens\n\t// at the worktree root, because that is what the binding pins. So a root leaf's `dir` genuinely\n\t// cannot be honored on this route. Degrade and warn, never silently drop: the caller is told which\n\t// pane lost its dir, and the manifest below reports where that pane REALLY is. stderr, so stdout\n\t// stays machine-readable.\n\tconst rootLeaf = firstPane(tree)\n\tif (rootLeaf.dir !== undefined) {\n\t\tprocess.stderr.write(\n\t\t\t`the template's root pane \"${rootLeaf.label ?? '(unlabeled)'}\" cannot start in \"${rootLeaf.dir}\" — ` +\n\t\t\t\t`the region opens at ${opts.cwd}\\n`,\n\t\t)\n\t}\n\t// Where it actually is, not where the template asked for.\n\treturn walk(tabState(tree, null, opts.root, opts.cwd, opts.rootEnvHonored), {\n\t\texec,\n\t\tadapter,\n\t\tcwd: opts.cwd,\n\t\tname: template.name,\n\t\tworkspace: opts.workspace,\n\t\tdirExists: opts.dirExists,\n\t\twarnedRatio: false,\n\t})\n}\n\n/**\n * `worktree add --template` with a tabs template: the workspace already EXISTS — that route forces the\n * `workspace` placement and opened one for the worktree — so a set of tabs has somewhere to live and\n * needs no second workspace. The first tab is built INTO that region; every later tab opens as a tab\n * in it. That one difference is the whole of what separates this route from `open --template`.\n */\nfunction applyTabsToRegion(\n\texec: Exec,\n\tadapter: MuxAdapter,\n\ttemplate: Template,\n\ttabs: TabNode[],\n\topts: ApplyTemplateOptions,\n): TemplateManifest {\n\tconst trees = tabs.map((tab) => resolveTree(tab))\n\tfor (const tree of trees) assertTemplateDirs(tree, opts.cwd, opts.dirExists)\n\n\tconst ctx: WalkContext = {\n\t\texec,\n\t\tadapter,\n\t\tcwd: opts.cwd,\n\t\tname: template.name,\n\t\t// Already known on this route, from the caller that opened the region — no first open has to\n\t\t// report it, and it is the same tier signal the tab labels turn on.\n\t\tworkspace: opts.workspace,\n\t\tdirExists: opts.dirExists,\n\t\twarnedRatio: false,\n\t}\n\n\t// The first tab's root leaf rides a region whose cwd another contract already fixed — the worktree\n\t// root, which the binding pins — so its `dir` cannot be honored, exactly as on the single-tab\n\t// route. Same degrade, same warning, for the same reason.\n\tconst rootLeaf = firstPane(trees[0]!)\n\tif (rootLeaf.dir !== undefined) {\n\t\tprocess.stderr.write(\n\t\t\t`the template's root pane \"${rootLeaf.label ?? '(unlabeled)'}\" cannot start in \"${rootLeaf.dir}\" — ` +\n\t\t\t\t`the region opens at ${opts.cwd}\\n`,\n\t\t)\n\t}\n\n\t// Grouped exactly as `open --template` is, and by the same walk: the route that opened the region\n\t// cannot change what the template means. Nothing has to be threaded through the worktree verbs to\n\t// make this work — `opts.root` is the region they opened, and it carries its own tab, which is all\n\t// grouping an already-open space needs.\n\treturn walkTabs(ctx, tabs, trees, workspaceLabelOf(template, opts.label), opts.newId(), () => ({\n\t\t// The region that already exists. Where it actually is, not where the template asked for.\n\t\troot: opts.root,\n\t\trootDir: opts.cwd,\n\t\trootEnvHonored: opts.rootEnvHonored,\n\t}))\n}\n\n/**\n * The walk: geometry depth-first against NAMED panes, then every command, last.\n *\n * **Geometry before commands is deliberate ordering, not incidental.** `open`'s `launch` couples\n * creation to launching, so reusing it would mean splitting a pane already running an interactive\n * agent — the split lands mid-render, and the ratio is computed against a pane whose child is\n * reflowing. Opening every pane blank first makes the whole geometry phase side-effect-free from the\n * agent's point of view.\n */\nfunction walk(tab: TabState, ctx: WalkContext): TemplateManifest {\n\tconst tabs = [tab]\n\ttry {\n\t\tbuildGeometry(tab, ctx)\n\t} catch (err) {\n\t\t// No rollback, no kill — report what was built and let the caller finish or close it.\n\t\tthrow new TemplateApplyError(err instanceof Error ? err.message : String(err), report(ctx, tabs))\n\t}\n\tsubmitCommands(tabs, ctx)\n\treturn report(ctx, tabs)\n}\n\n/**\n * One tab's geometry: depth-first against NAMED panes, opening every pane blank. Submits nothing —\n * the caller does that once EVERY tab is built, which is what lets the multi-tab walk hold the same\n * \"no split ever lands on a pane mid-render\" guarantee the single-tab walk holds.\n */\nfunction buildGeometry(tab: TabState, ctx: WalkContext): void {\n\t// A backend that cannot size a split takes its own default and we say so ONCE — a wrong-looking\n\t// split is not worth failing an otherwise-correct pool over, and the schema is backend-agnostic,\n\t// so a template's validity cannot depend on which multiplexer happens to be running.\n\tconst sizeSplit = (ratio: number | undefined): number | undefined => {\n\t\tif (ratio == null) return undefined\n\t\tif (ctx.adapter.canSizeSplits) return ratio\n\t\tif (!ctx.warnedRatio) {\n\t\t\tctx.warnedRatio = true\n\t\t\tprocess.stderr.write(`${ctx.adapter.name} cannot size a split — every ratio in this template takes its default\\n`)\n\t\t}\n\t\treturn undefined\n\t}\n\n\tconst build = (node: TemplateNode, paneId: string): void => {\n\t\tif (node.type === 'pane') return\n\t\t// The new pane becomes `second`'s region, and the leaf that ends up sitting on it is\n\t\t// `firstPane(second)` — so THAT leaf's dir and env are what this split must carry, since a\n\t\t// pane's cwd and env can only be set at its birth.\n\t\tconst born = firstPane(node.second)\n\t\tconst created = ctx.adapter.open(ctx.exec, {\n\t\t\tcwd: resolveDir(ctx.cwd, born.dir),\n\t\t\tat: node.direction === 'down' ? 'pane:down' : 'pane:right',\n\t\t\t// Always named. Neither backend's default splits the CALLER: herdr's `--current` falls back\n\t\t\t// to the UI-focused pane, and tmux always splits the session's active pane. Both track the\n\t\t\t// user, not us — and a tree walk must split a pane created three steps ago regardless.\n\t\t\t// In a tabs walk this is also what keeps a tab's splits inside THAT tab: the id threaded from\n\t\t\t// here is the tab's own root pane, so no split can wander into the tab opened before it.\n\t\t\tfrom: { id: paneId },\n\t\t\tratio: sizeSplit(node.ratio),\n\t\t\tenv: born.env,\n\t\t\tlabel: born.label,\n\t\t})\n\t\t// Recorded at BIRTH, so a throw later still reports every pane that actually exists.\n\t\ttab.paneOf.set(born, created.id)\n\t\tbuild(node.first, paneId)\n\t\tbuild(node.second, created.id)\n\t}\n\n\tbuild(tab.tree, tab.root.id)\n}\n\n/**\n * The manifest, across every tab built so far. ONE FLAT pane list — the tab is a field on each pane\n * rather than a second nesting a consumer has to walk. The unique handle is the pane `id`; `label` is\n * a name two panes may share, and the tab is reported by INDEX rather than by either.\n */\nfunction report(ctx: WalkContext, tabs: TabState[]): TemplateManifest {\n\treturn {\n\t\ttemplate: ctx.name,\n\t\tcwd: ctx.cwd,\n\t\tworkspace: ctx.workspace,\n\t\tpanes: tabs.flatMap((tab) =>\n\t\t\ttab.ordered\n\t\t\t\t.filter((pane) => tab.paneOf.has(pane))\n\t\t\t\t.map((pane) => ({\n\t\t\t\t\tlabel: pane.label ?? null,\n\t\t\t\t\tpane: tab.paneOf.get(pane)!,\n\t\t\t\t\t// The root pane reports where it WAS opened, which is not always where its `dir` asked\n\t\t\t\t\t// for; every other pane was born by a split that took its resolved dir verbatim. The\n\t\t\t\t\t// manifest is the answer to \"which panes exist and what are they for\", so a claim it\n\t\t\t\t\t// cannot back is worse than a feature it does not have.\n\t\t\t\t\tdir: pane === tab.rootLeaf ? tab.rootDir : resolveDir(ctx.cwd, pane.dir),\n\t\t\t\t\tcommand: pane.command ?? null,\n\t\t\t\t\ttab: tab.index,\n\t\t\t\t})),\n\t\t),\n\t}\n}\n\n/**\n * Every command, last — and across every tab, in template order, tab by tab. Only reachable once all\n * geometry is built: a split lands mid-render if it targets a pane already running an interactive\n * agent, and that reason does not weaken because the pane sits in another tab.\n */\nfunction submitCommands(tabs: TabState[], ctx: WalkContext): void {\n\tfor (const tab of tabs) {\n\t\t// The root pane's env compensation, when the region open could not carry it natively — the ONE\n\t\t// pane that can need it, since every other is born by a split, which carries env at birth on both\n\t\t// backends. Reachable only on herdr's worktree route; every native route set env already and must\n\t\t// NOT be prefixed on top of it. The prefix-or-warn RULE is the seam's (`env-fallback.ts`); what\n\t\t// this node owns is the scoping — root pane only, and the warning once rather than per pane.\n\t\tconst rootFallback = tab.rootEnvHonored ? undefined : envFallback(tab.rootLeaf.env, tab.rootLeaf.command)\n\t\tif (rootFallback?.kind === 'dropped') {\n\t\t\t// Nothing to prefix — the fallback only works by riding on a command line. Degrade and warn,\n\t\t\t// never silently drop; stderr, so stdout stays machine-readable.\n\t\t\tprocess.stderr.write(\n\t\t\t\t`the template's root pane \"${tab.rootLeaf.label ?? '(unlabeled)'}\" has env (${rootFallback.variables.join(', ')}) ` +\n\t\t\t\t\t'but no command to carry it — this backend cannot set env on the region it opens\\n',\n\t\t\t)\n\t\t}\n\n\t\tfor (const pane of tab.ordered) {\n\t\t\t// The root pane's command may have been rewritten to carry its env; every other pane runs verbatim.\n\t\t\tconst command = pane === tab.rootLeaf && rootFallback?.kind === 'carried' ? rootFallback.command : pane.command\n\t\t\tif (!command) continue\n\t\t\tctx.adapter.submit(ctx.exec, { id: tab.paneOf.get(pane)! }, command)\n\t\t}\n\t}\n}\n","import type { Exec } from './exec.ts'\nimport type { MuxAdapter, MuxPlacement, MuxTarget, OpenedPane } from './mux.ts'\nimport {\n\tgitWorktreeAdapter,\n\tlistWorktreesFromGit,\n\tnormalizeWorktreePath,\n\tremoveWorktreeSafely,\n\ttype Worktree,\n\ttype WorktreeEntry,\n} from './worktree.ts'\n\n/**\n * Worktrees × sessions — the routing policy, and the only module that knows both halves. `worktree.ts`\n * stays a pure git adapter that owes nothing to the session seam; `mux.ts` stays a pure mux seam\n * that owes nothing to git. Deciding between them is a third concern, and it lives here.\n */\n\n/** A worktree that has been opened somewhere — the product of every routing decision below. */\nexport interface OpenedWorktree {\n\tworktree: Worktree\n\t/**\n\t * The opened root pane, and the tab it sits in. Both routes report the tab — the binding route from\n\t * the backend's own worktree envelope, the plain-git fallback from `open` — so a caller handed this\n\t * region can address its tab (to group it, to name it) without reaching for the pane id, which\n\t * resolves on tmux and is refused by herdr.\n\t */\n\ttarget: OpenedPane\n\t/** The workspace bound to the worktree; absent when it opened ungrouped. */\n\tworkspace?: string | undefined\n\t/**\n\t * The backend COULD have bound this worktree to a workspace, but the route taken did not — i.e. a\n\t * caller on herdr asked for a pane or tab placement, which its `worktree create` cannot serve.\n\t * Never true on a backend with no binding at all (tmux), where no grouping was ever on offer:\n\t * there is nothing to report about a feature the backend does not have.\n\t */\n\tdegraded: boolean\n\t/**\n\t * Whether a requested `env` actually reached the opened root pane. `false` ONLY on herdr's binding\n\t * route, whose `worktree create` has no `env` param at all (unlike `workspace`/`tab`/`pane\n\t * create`) and rejects the flag outright. Vacuously `true` when no env was asked for.\n\t *\n\t * Reported rather than solved here because the remedy is a *command* — prefixing `env K=V` onto\n\t * what the pane runs — and this module opens panes; it does not decide what they run. Only the\n\t * route taken knows this fact, which is why it is reported rather than inferred by the caller.\n\t */\n\tenvHonored: boolean\n}\n\n/**\n * Grouping is possible only where the backend binds AND the caller asked for a workspace — herdr's\n * `worktree create` ALWAYS opens a workspace, so it cannot serve a pane or tab placement.\n */\nfunction canBind(adapter: MuxAdapter, at: MuxPlacement | undefined): boolean {\n\treturn Boolean(adapter.worktree) && at === 'workspace'\n}\n\n/** True only where a group was on offer and the placement is what cost us it. */\nfunction isDegraded(adapter: MuxAdapter, at: MuxPlacement | undefined): boolean {\n\treturn Boolean(adapter.worktree) && !canBind(adapter, at)\n}\n\n/**\n * Create a worktree and open it.\n *\n * Routes through the backend's own primitive when it can bind (grouped), and otherwise falls back to\n * `git worktree add` plus a plain `open()`. The fallback is a complete, useful outcome — a worktree\n * open in a split pane — just not a grouped one, so it is REPORTED (`degraded`), never refused.\n * Refusing would make identical flags succeed on tmux and fail on herdr, which is exactly the\n * backend leak this seam exists to prevent.\n */\nexport function addAndOpenWorktree(\n\texec: Exec,\n\tadapter: MuxAdapter,\n\topts: {\n\t\tprimaryRoot: string\n\t\tbranch: string\n\t\tpath: string\n\t\tbase?: string | undefined\n\t\tlaunch?: string | undefined\n\t\t/** Environment set in the opened root pane at birth — native at every tier on both backends. */\n\t\tenv?: Record<string, string> | undefined\n\t\tat?: MuxPlacement | undefined\n\t\tlabel?: string | undefined\n\t\t/** Passed to `open` for a `pane:*` placement; see `MuxOpenOptions.from`. */\n\t\tfrom?: MuxTarget | undefined\n\t},\n): OpenedWorktree {\n\tif (canBind(adapter, opts.at)) {\n\t\tconst created = adapter.worktree!.createInWorkspace(exec, {\n\t\t\tprimaryRoot: opts.primaryRoot,\n\t\t\tbranch: opts.branch,\n\t\t\tpath: opts.path,\n\t\t\tbase: opts.base,\n\t\t\tlaunch: opts.launch,\n\t\t\tenv: opts.env,\n\t\t\tlabel: opts.label,\n\t\t})\n\t\t// herdr's `worktree create` takes no env — the adapter accepts `env` and does not emit it, so\n\t\t// say so rather than let the caller assume it landed.\n\t\treturn { ...created, degraded: false, envHonored: !opts.env }\n\t}\n\tconst worktree = gitWorktreeAdapter.add(exec, {\n\t\tprimaryRoot: opts.primaryRoot,\n\t\tpath: opts.path,\n\t\tbranch: opts.branch,\n\t\tbase: opts.base,\n\t})\n\tconst target = adapter.open(exec, {\n\t\tcwd: worktree.root,\n\t\tlaunch: opts.launch,\n\t\tenv: opts.env,\n\t\tat: opts.at,\n\t\tlabel: opts.label,\n\t\tfrom: opts.from,\n\t})\n\t// This route goes through `open`, where env is native at every tier on both backends.\n\treturn { worktree, target, degraded: isDegraded(adapter, opts.at), envHonored: true }\n}\n\n/**\n * Open an EXISTING worktree — the remedy that groups one a bare `worktree add` created earlier, so\n * \"add now, group later\" is a real story rather than a dead end.\n */\nexport function openExistingWorktree(\n\texec: Exec,\n\tadapter: MuxAdapter,\n\topts: {\n\t\tprimaryRoot: string\n\t\tpath: string\n\t\tlaunch?: string | undefined\n\t\t/** Environment set in the opened root pane; honored natively on the `open` route, compensated on the bind route. */\n\t\tenv?: Record<string, string> | undefined\n\t\tat?: MuxPlacement | undefined\n\t\tlabel?: string | undefined\n\t\t/** Passed to `open` for a `pane:*` placement; see `MuxOpenOptions.from`. */\n\t\tfrom?: MuxTarget | undefined\n\t},\n): OpenedWorktree {\n\tconst at = opts.at ?? 'workspace'\n\tif (canBind(adapter, at)) {\n\t\tconst opened = adapter.worktree!.openInWorkspace(exec, {\n\t\t\tprimaryRoot: opts.primaryRoot,\n\t\t\tpath: opts.path,\n\t\t\tlaunch: opts.launch,\n\t\t\tenv: opts.env,\n\t\t\tlabel: opts.label,\n\t\t})\n\t\t// herdr's `worktree open` takes no env — the adapter compensates on the launch and reports the\n\t\t// drop here, exactly as the create route does, so a caller cannot assume env landed.\n\t\treturn { ...opened, degraded: false, envHonored: !opts.env }\n\t}\n\tconst root = normalizeWorktreePath(opts.path)\n\tconst target = adapter.open(exec, {\n\t\tcwd: root,\n\t\tlaunch: opts.launch,\n\t\tenv: opts.env,\n\t\tat,\n\t\tlabel: opts.label,\n\t\tfrom: opts.from,\n\t})\n\t// This route goes through `open`, where env is native at every tier on both backends.\n\t// The branch is git's answer, not the backend's — same rule as `listWorktrees`.\n\tconst branch = listWorktreesFromGit(exec, opts.primaryRoot).find((entry) => entry.root === root)?.branch\n\treturn { worktree: { root, branch: branch ?? '' }, target, degraded: isDegraded(adapter, at), envHonored: true }\n}\n\n/**\n * Every worktree of the repo, with the workspace each is open in.\n *\n * The facts come from git on EVERY backend and the backend contributes only the binding, joined by\n * normalized path. A backend that also enumerates worktrees is merely re-reading git, so letting it\n * answer would let two backends report a different branch for the same worktree — this is\n * structurally incapable of that.\n */\nexport function listWorktrees(\n\texec: Exec,\n\tadapter: MuxAdapter | undefined,\n\topts: { primaryRoot: string },\n): WorktreeEntry[] {\n\tconst bindings = adapter?.worktree?.bindings(exec, { primaryRoot: opts.primaryRoot })\n\treturn listWorktreesFromGit(exec, opts.primaryRoot).map((entry) => {\n\t\tconst workspace = bindings?.get(entry.root)\n\t\treturn workspace ? { ...entry, workspace } : entry\n\t})\n}\n\n/**\n * Remove a worktree, with identical gates on every backend: refuse the primary checkout (absolute),\n * tolerate one already gone from disk, refuse uncommitted changes unless `force`.\n *\n * Removal is never handed to the backend — only the binding's release is. See\n * `WorktreeWorkspaceCapability` for why, and `removeWorktreeSafely` for why the ordering of that\n * release is a specified property rather than an incidental one.\n */\nexport function removeWorktree(\n\texec: Exec,\n\tadapter: MuxAdapter | undefined,\n\tpath: string,\n\topts: { primaryRoot: string; force?: boolean | undefined },\n): void {\n\tconst capability = adapter?.worktree\n\tconst workspace = capability?.bindings(exec, { primaryRoot: opts.primaryRoot }).get(normalizeWorktreePath(path))\n\tremoveWorktreeSafely(exec, path, {\n\t\tprimaryRoot: opts.primaryRoot,\n\t\tforce: opts.force,\n\t\treleaseBinding: capability && workspace ? () => capability.releaseWorkspace(exec, workspace) : undefined,\n\t})\n}\n","import { join } from 'node:path'\nimport { Command, CommanderError, Option } from 'commander'\nimport { callerPane, resolveMuxAdapter } from './backend.ts'\nimport { AmbiguousPaneError, CliError, reportError } from './cli-error.ts'\nimport { AT_OPTION, ENV_OPTION, FORMAT_OPTION, LABEL_OPTION } from './cli-options.ts'\nimport { type Exec, nodeExec } from './exec.ts'\nimport type { LivePane, MuxAdapter, MuxPlacement, MuxTarget } from './mux.ts'\nimport { currentPane, probeMultiplexer } from './mux-probe.ts'\nimport { nodeNewId } from './new-id.ts'\nimport { type HelpEntry, isAutomatedOutput, output, printFields, printHelp, printTable, tildify } from './output.ts'\nimport { type OpenPrompt, realPrompt } from './prompt.ts'\nimport {\n\tcollectPanes,\n\tisValidTemplateName,\n\tparseTemplate,\n\tresolveTree,\n\ttype Template,\n\tvalidateTemplate,\n} from './template.ts'\nimport { captureTemplate, captureWorkspaceTemplate } from './template-capture.ts'\nimport {\n\tapplyEdits,\n\ttype EditAnswer,\n\ttype EditField,\n\ttype EditInput,\n\ttype EditSlot,\n\tparseSet,\n\tplanEdits,\n\treadEditInput,\n\tresolveSets,\n\tslotRef,\n\ttoAnswers,\n} from './template-edit.ts'\nimport {\n\tapplyTemplateToRegion,\n\topenTemplate,\n\tTemplateApplyError,\n\ttype TemplateManifest,\n\ttemplateRootPane,\n} from './template-session.ts'\nimport {\n\tlistTemplates,\n\tnodeTemplateStore,\n\ttype ResolvedTemplate,\n\tresolveTemplate as resolveTemplateSource,\n\ttype TemplateStore,\n\ttemplateDirs,\n} from './template-store.ts'\nimport {\n\tgitWorktreeAdapter,\n\tisWorktreeRemovable,\n\tpruneWorktrees,\n\tresolvePrimaryRoot,\n\tresolveWorktreePath,\n\tWorktreeGitError,\n} from './worktree.ts'\nimport {\n\taddAndOpenWorktree,\n\tlistWorktrees,\n\ttype OpenedWorktree,\n\topenExistingWorktree,\n\tremoveWorktree,\n} from './worktree-session.ts'\n\n// NOTE: the verb surface below is provisional — the behavior spec is the next milestone and may\n// rename verbs, adjust flags, or split concerns (e.g. move `nudge` behind its own group).\n\n/** The env/exec pair every command resolves the backend and multiplexer through — injected so the\n * CLI can be driven deterministically in tests, the same seam every adapter already takes. */\nexport interface CliDeps {\n\tenv: NodeJS.ProcessEnv\n\texec: Exec\n\t/** The filesystem half, for the `template` group — injected for the same reason `exec` is: it is the\n\t * only way `template` can be driven hermetically in tests, with no real templates on disk. Optional\n\t * at this boundary so a caller that drives no template command need not know the seam exists. */\n\tstore?: TemplateStore | undefined\n\t/** The interactive half, for `template edit` — injected for the same reason `store` is, and a\n\t * FACTORY rather than a live prompt so no other verb pays stdin for its existence (`prompt.ts`\n\t * has the why). */\n\tprompt?: OpenPrompt | undefined\n}\n\n/** `CliDeps` with every optional dep resolved — what each command is actually handed. */\ninterface Deps {\n\tenv: NodeJS.ProcessEnv\n\texec: Exec\n\tstore: TemplateStore\n\tprompt: OpenPrompt\n}\n\nconst DEFAULT_DEPS: CliDeps = { env: process.env, exec: nodeExec, store: nodeTemplateStore, prompt: realPrompt }\n\n/**\n * Resolve the adapter for the multiplexer this process is inside, failing with a coded `no-mux` error\n * when there is none. The underlying throw is TRANSLATED, never forwarded — `resolveMuxAdapter`\n * names `$TMUX`/`$HERDR_ENV`, which is backend plumbing an agent driving cyber-mux cannot act on; the\n * help names how to get a backend through this CLI instead.\n */\nfunction adapter(deps: Deps): MuxAdapter {\n\ttry {\n\t\treturn resolveMuxAdapter(deps.env, deps.exec)\n\t} catch {\n\t\tthrow noMux()\n\t}\n}\n\n/** No multiplexer around this process — an operation failure (exit 1), not a usage error. */\nfunction noMux(): CliError {\n\treturn new CliError(\n\t\t'no-mux',\n\t\t'no multiplexer detected around this process',\n\t\t'run cyber-mux inside tmux or herdr, or set CYBER_MUX to name one',\n\t\t1,\n\t)\n}\n\n/** A locator that resolved to no live pane — a pane verb's not-found. Exit 1: a real operation\n * failure, distinct from a malformed argument. */\nfunction paneNotFound(locator: string): CliError {\n\treturn new CliError(\n\t\t'pane-not-found',\n\t\t`pane \"${locator}\" matched no live pane`,\n\t\t'list the live panes with: cyber-mux list',\n\t\t1,\n\t)\n}\n\n/** A malformed template name — a usage error (exit 2): the fix is a different name, nothing was\n * attempted. The same family a missing required argument is in. */\nfunction invalidTemplateName(name: string): CliError {\n\treturn new CliError(\n\t\t'invalid-template-name',\n\t\t`invalid template name \"${name}\" — a name must match [a-z0-9][a-z0-9-]* and be a plain filename stem`,\n\t\t'use a lowercase stem like pool-4',\n\t\t2,\n\t)\n}\n\n/**\n * A git/worktree operation that refused or failed — exit 1. A coded surface already on its way out (a\n * `no-mux`, a resolved-template error, an apply failure) passes through untouched rather than being\n * flattened into this generic one. A `WorktreeGitError` is this CLI's own worktree text (a refusal\n * naming `--force`, a primary-checkout guard), which is kept because the frozen worktree refusals are\n * asserted on it. Anything else reaching here comes from the session adapter opening/binding the\n * worktree's pane (`session.tmux.ts`/`session.herdr.ts`) and embeds the backend's own name plus its raw\n * stderr (`withReason`, `exec.lastError`) — AXI #6 forbids leaking a dependency's name or text, so that\n * detail is not load-bearing for the agent and goes to stderr as a diagnostic only; stdout carries this\n * CLI's own coded, translated error.\n */\nfunction reportWorktreeFailure(err: unknown): never {\n\tif (err instanceof CliError) reportError(err)\n\tif (err instanceof WorktreeGitError) {\n\t\treportError(new CliError('worktree-failed', err.message, 'check the worktree path and its state, then re-run', 1))\n\t}\n\tif (err instanceof Error && err.message) process.stderr.write(`${err.message}\\n`)\n\treportError(\n\t\tnew CliError(\n\t\t\t'worktree-failed',\n\t\t\t'the worktree operation failed',\n\t\t\t'check the worktree path and its state, then re-run',\n\t\t\t1,\n\t\t),\n\t)\n}\n\n/**\n * Resolve a locator — a pane id or a human label — to the one pane it names.\n *\n * **Id first, then name.** An id can never be made to mean something else by a person renaming an\n * unrelated pane, so every caller that passes ids today keeps working no matter what anyone labels.\n * That also makes ambiguity a fuzzy-tier condition only: an id hit and a label hit are not peers, so\n * they are not candidates to choose between — the same ladder git, Docker and tmux resolve targets by.\n *\n * **An id is recognized by EXISTENCE, never by syntax.** The question asked is \"does a live pane carry\n * this id?\", not \"does this string look like an id?\". Docker sniffs shape (`sg-` → an id) and it is\n * the cheaper rule, refused here: encoding a backend's id format in the CLI is exactly the backend\n * leak this seam exists to prevent, and every new backend would owe a new syntax rule. It is also\n * wrong on a real case — `%9` is id-SHAPED, but if no pane carries it as an id and one carries it as a\n * label, a sniffer reports a missing pane while the live list finds the label.\n *\n * One `listPanes` read answers both halves, so name support costs the id path a single query and no\n * behavior. The SEAM is untouched: adapters keep receiving concrete ids, and never learn that a name\n * was ever involved.\n *\n * A locator matching NOTHING resolves to itself, deliberately — it is handed to the backend as an id\n * and takes the verb's existing not-found path (exit 1). Failing here instead would make every verb's\n * \"no such pane\" message this function's to write.\n */\nfunction resolveTarget(deps: Deps, a: MuxAdapter, locator: string): MuxTarget {\n\tlet panes: LivePane[]\n\ttry {\n\t\tpanes = a.listPanes(deps.exec)\n\t} catch {\n\t\t// A listing that cannot be read must not deny an id that would have worked — the id path never\n\t\t// needed this query. Degrade to the pre-resolution behavior rather than failing the verb.\n\t\treturn { id: locator }\n\t}\n\tif (panes.some((p) => p.id === locator)) return { id: locator }\n\tconst named = panes.filter((p) => p.label === locator)\n\tif (named.length === 1) return { id: named[0]!.id }\n\t// Guessing (first match, most recent, the focused one) would act on a pane the caller never named,\n\t// which is worse than making them look. The caller is present and is the only one who can say.\n\tif (named.length > 1) {\n\t\tthrow new AmbiguousPaneError(\n\t\t\tlocator,\n\t\t\tnamed.map((p) => ({ id: p.id, label: p.label ?? null, cwd: p.cwd ?? null })),\n\t\t)\n\t}\n\treturn { id: locator }\n}\n\n/**\n * Wrap a verb's action so ANY coded failure reports itself on stdout and exits — the one place that\n * turns a `CliError` (an ambiguity, a `no-mux`, a `pane-not-found`, a template refusal) into output, for\n * every verb.\n *\n * Here rather than deeper so the report is the OUTERMOST thing a verb does: by the time it runs, every\n * inner catch-all has already had its chance to rethrow, and nothing can convert an exit-2 usage error\n * into an exit-1 generic failure behind its back. A non-`CliError` is a bug, not a surface — it is\n * rethrown to the top-level handler rather than dressed up as a coded failure.\n */\nfunction guarded<A extends unknown[]>(action: (...args: A) => void): (...args: A) => void {\n\treturn (...args: A) => {\n\t\ttry {\n\t\t\taction(...args)\n\t\t} catch (err) {\n\t\t\tif (err instanceof CliError) reportError(err)\n\t\t\tthrow err\n\t\t}\n\t}\n}\n\n/**\n * `guarded` for an action that awaits — the same contract, and separate rather than a widening of it.\n *\n * Making `guarded` return `void | Promise<void>` would put an ignored promise behind every sync verb's\n * action, where a rejection would escape the guard entirely and surface as an unhandled rejection\n * instead of a coded error. Two functions keeps the sync path provably sync; commander's own\n * `parseAsync` (already what `main` calls) awaits whichever it gets.\n */\nfunction guardedAsync<A extends unknown[]>(action: (...args: A) => Promise<void>): (...args: A) => Promise<void> {\n\treturn async (...args: A) => {\n\t\ttry {\n\t\t\tawait action(...args)\n\t\t} catch (err) {\n\t\t\tif (err instanceof CliError) reportError(err)\n\t\t\tthrow err\n\t\t}\n\t}\n}\n\n/**\n * Run a pane verb's body, translating a backend throw into a `pane-not-found` on the way out.\n *\n * `resolveTarget` hands an unmatched locator to the backend as an id, so a bad target surfaces as the\n * backend's OWN diagnostic — which must never reach the caller: an agent handed a tmux/herdr error\n * cannot act on it through cyber-mux. A `CliError` already on its way out (a `no-mux` from `adapter`,\n * an ambiguity from `resolveTarget`) is a coded surface and passes through untouched; anything else is\n * the multiplexer's raw failure and becomes this CLI's own code and help instead.\n */\nfunction paneVerb(locator: string, body: () => void): void {\n\ttry {\n\t\tbody()\n\t} catch (err) {\n\t\tif (err instanceof CliError) throw err\n\t\tthrow paneNotFound(locator)\n\t}\n}\n\n/**\n * The backend when there is one, `undefined` when there is not — unlike `adapter`, which fails. For\n * verbs whose subject is git (`worktree list`/`remove`): a multiplexer can only ever add to the\n * answer, so its absence must not deny one.\n */\nfunction optionalAdapter(deps: Deps): MuxAdapter | undefined {\n\ttry {\n\t\treturn resolveMuxAdapter(deps.env, deps.exec)\n\t} catch {\n\t\treturn undefined\n\t}\n}\n\n/**\n * One shape for every verb that opens a worktree. `printFields` drops nullish entries, so a bare\n * `worktree add` — which opens nothing — prints exactly what it always did.\n *\n * When the chosen placement cost the workspace grouping, the backend could have grouped this worktree\n * and did not — worth saying out loud. Per axi/'s #9 that next move rides in the payload on STDOUT as\n * a `help[N]:` block, not on stderr the agent never reads; `workspace: null` is the machine-readable\n * half of the same report. `regroupCommand` is the caller's own verb re-stated with `--at workspace`,\n * so the flag that would have grouped it is named as a concrete command. Emitted only when a grouping\n * was actually lost (#9's omit-when-self-contained rule), so `help` never rides along otherwise.\n */\nfunction reportOpenedWorktree(opened: OpenedWorktree, regroupCommand: string): void {\n\tconst help: HelpEntry[] = opened.degraded\n\t\t? [{ message: 'opened ungrouped — pass --at workspace to group it with the repo', command: regroupCommand }]\n\t\t: []\n\toutput(\n\t\t{\n\t\t\troot: opened.worktree.root,\n\t\t\tbranch: opened.worktree.branch,\n\t\t\tpane: opened.target.id,\n\t\t\tworkspace: opened.workspace ?? null,\n\t\t\t...(help.length ? { help } : {}),\n\t\t},\n\t\t() => {\n\t\t\tprintFields({\n\t\t\t\troot: opened.worktree.root,\n\t\t\t\tbranch: opened.worktree.branch,\n\t\t\t\tpane: opened.target.id,\n\t\t\t\tworkspace: opened.workspace,\n\t\t\t})\n\t\t\tprintHelp(help)\n\t\t},\n\t)\n}\n\n/**\n * `--template`, the exact sibling of `--launch`: both answer \"what runs in the space you are opening\",\n * one for a single pane and one for a pool. Mutually exclusive by construction — commander rejects\n * the pair rather than picking a winner.\n */\nfunction templateOption(): Option {\n\t// Conflicts with both `--launch` (one command line for the space) and `--env` (the template owns\n\t// its own panes' env) — each answers \"what is in the space you are opening\", and a template names\n\t// all of it.\n\treturn new Option('--template <name>', 'Named template to build in the opened space').conflicts(['launch', 'env'])\n}\n\n/**\n * Resolve, parse and validate a template — the whole answer BEFORE any side effect. A typo in a\n * template name must never leave a worktree behind, and an invalid template must not either, so every\n * caller runs this before it opens or creates anything.\n */\nfunction resolveTemplate(\n\tdeps: Deps,\n\topts: { name?: string | undefined; file?: string | undefined },\n): ResolvedTemplate & { template: Template } {\n\t// A malformed NAME is a usage error (exit 2), and it is caught HERE — before `resolveTemplateSource` reads —\n\t// so it is told apart from a well-formed name that simply resolves nowhere (exit 1, below). The name\n\t// is a lookup key that must also be a filename; `../../../etc/pwd` must never get as far as a read.\n\tif (opts.name !== undefined && opts.file === undefined && !isValidTemplateName(opts.name)) {\n\t\tthrow invalidTemplateName(opts.name)\n\t}\n\tlet resolved: ResolvedTemplate\n\ttry {\n\t\tresolved = resolveTemplateSource({\n\t\t\tname: opts.name,\n\t\t\tfile: opts.file,\n\t\t\tstore: deps.store,\n\t\t\texec: deps.exec,\n\t\t\tenv: deps.env,\n\t\t})\n\t} catch (err) {\n\t\t// A well-formed name that resolves nowhere is a failed lookup, not malformed input (exit 1). The\n\t\t// message is this CLI's own — it names the directories it searched — so it is kept, not a backend's.\n\t\tthrow new CliError(\n\t\t\t'template-not-found',\n\t\t\terr instanceof Error ? err.message : String(err),\n\t\t\t'list the templates resolvable from here with: cyber-mux template list',\n\t\t\t1,\n\t\t)\n\t}\n\tlet parsed: unknown\n\ttry {\n\t\tparsed = parseTemplate(resolved.raw)\n\t} catch (err) {\n\t\tthrow new CliError(\n\t\t\t'invalid-template',\n\t\t\t`${resolved.path}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t'fix the template JSON, then re-run',\n\t\t\t1,\n\t\t)\n\t}\n\t// A template's CONTENT being invalid is a predicate answer (exit 1), not a usage error — the\n\t// invocation was well-formed, the fix is to the file. Every error at once, one per line, each naming\n\t// its own JSON path — first-only would make a template with three mistakes take three runs to fix.\n\tconst errors = validateTemplate(parsed, resolved.stem)\n\tif (errors.length > 0) {\n\t\tthrow new CliError('invalid-template', errors.join('\\n'), 'fix the fields named above, then re-run', 1)\n\t}\n\treturn { ...resolved, template: parsed as Template }\n}\n\n/** The apply manifest — the handoff. `printFields`/`printTable` for humans, the raw object for json. */\nfunction reportManifest(manifest: TemplateManifest, extra: Record<string, string | null> = {}): void {\n\toutput({ ...extra, ...manifest }, () => {\n\t\tprintFields({ ...extra, template: manifest.template, cwd: manifest.cwd, workspace: manifest.workspace })\n\t\tprintTable(manifest.panes, [\n\t\t\t{ label: 'label', get: (p) => p.label ?? '' },\n\t\t\t{ label: 'pane', get: (p) => p.pane },\n\t\t\t{ label: 'dir', get: (p) => p.dir },\n\t\t\t{ label: 'command', get: (p) => p.command ?? '' },\n\t\t])\n\t})\n}\n\n/**\n * A walk that threw reports what it BUILT and exits 1, killing nothing. Rolling back would mean\n * killing panes, and a kill is not obviously safer than a half-built template the caller can see and\n * finish.\n */\nfunction reportApplyFailure(err: unknown, extra: Record<string, string | null> = {}): never {\n\tif (err instanceof TemplateApplyError) {\n\t\t// The manifest is the WHOLE of stdout — one result payload, with the failed pane named inside it,\n\t\t// never a second structured error concatenated after it. The message is supplementary debug, so it\n\t\t// goes to stderr: moving it to stdout would break the \"stdout carries exactly one payload\" invariant\n\t\t// the stream decision rests on.\n\t\treportManifest(err.manifest, extra)\n\t\tprocess.stderr.write(`${err.message}\\n`)\n\t\tprocess.exit(1)\n\t}\n\t// A totally-failed apply that produced no result — a predictable pre-open failure (a missing dir\n\t// names the pane and the resolved path). Its message is this CLI's own text, exit 1.\n\tthrow new CliError(\n\t\t'template-apply-failed',\n\t\terr instanceof Error ? err.message : String(err),\n\t\t'check the template and the target directory, then re-run',\n\t\t1,\n\t)\n}\n\nfunction templateListCommand(deps: Deps): Command {\n\treturn new Command('list')\n\t\t.description('Every template resolvable from here, with its source and pane count')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\tguarded(() => {\n\t\t\t\tconst dirs = templateDirs(deps.exec, deps.env)\n\t\t\t\tconst templates = listTemplates(deps.store, dirs).map((entry) => {\n\t\t\t\t\t// A template that does not parse still LISTS — `list` answers \"what is here\", and\n\t\t\t\t\t// `validate` answers \"is it any good\". Conflating them would hide a broken file entirely.\n\t\t\t\t\tlet panes = 0\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst raw = deps.store.read(entry.path)\n\t\t\t\t\t\tif (raw) panes = collectPanes(resolveTree(parseTemplate(raw) as Template)).length\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tpanes = 0\n\t\t\t\t\t}\n\t\t\t\t\treturn { ...entry, panes }\n\t\t\t\t})\n\t\t\t\toutput({ templates }, () =>\n\t\t\t\t\tprintTable(templates, [\n\t\t\t\t\t\t{ label: 'name', get: (l) => l.name },\n\t\t\t\t\t\t{ label: 'source', get: (l) => l.source },\n\t\t\t\t\t\t{ label: 'panes', get: (l) => String(l.panes) },\n\t\t\t\t\t\t{ label: 'shadowed', get: (l) => (l.shadowed ? 'yes' : '') },\n\t\t\t\t\t]),\n\t\t\t\t)\n\t\t\t}),\n\t\t)\n}\n\nfunction templateShowCommand(deps: Deps): Command {\n\treturn new Command('show')\n\t\t.description('Print a resolved template as JSON')\n\t\t.argument('[name]', 'Template name')\n\t\t.option('--file <path>', 'Read this path instead, skipping resolution entirely')\n\t\t.option('--desugar', 'Print the canonical tree panes/arrange expands to — exactly what apply builds')\n\t\t.action(\n\t\t\tguarded((name: string | undefined, opts: { file?: string | undefined; desugar?: boolean | undefined }) => {\n\t\t\t\tif (!name && !opts.file) {\n\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t'missing-argument',\n\t\t\t\t\t\t'template show needs a template name or --file <path>',\n\t\t\t\t\t\t'pass a template name, or --file <path>',\n\t\t\t\t\t\t2,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tconst { template } = resolveTemplate(deps, { name, file: opts.file })\n\t\t\t\t// One desugarer, so `--desugar` and the walk can never disagree about what a flat template means.\n\t\t\t\tconsole.log(JSON.stringify(opts.desugar ? resolveTree(template) : template, null, 2))\n\t\t\t}),\n\t\t)\n}\n\nfunction templateValidateCommand(deps: Deps): Command {\n\treturn new Command('validate')\n\t\t.description('Validate a template — exit 0 valid, 1 invalid, every error at once with a JSON path')\n\t\t.argument('[name]', 'Template name')\n\t\t.option('--file <path>', 'Validate this path instead, skipping resolution entirely')\n\t\t.action(\n\t\t\tguarded((name: string | undefined, opts: { file?: string | undefined }) => {\n\t\t\t\tif (!name && !opts.file) {\n\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t'missing-argument',\n\t\t\t\t\t\t'template validate needs a template name or --file <path>',\n\t\t\t\t\t\t'pass a template name, or --file <path>',\n\t\t\t\t\t\t2,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\t// resolveTemplate already fails with every error, one per line. Reaching here means valid, and\n\t\t\t\t// a valid template says nothing at all — this is the CI hook, so silence is the pass signal.\n\t\t\t\tresolveTemplate(deps, { name, file: opts.file })\n\t\t\t}),\n\t\t)\n}\n\n/**\n * `save` is the one verb here that reads a multiplexer rather than a file, and the only one that\n * WRITES: it captures a live region into a named template, so a pool built by hand once can be named\n * rather than hand-written. That is the schema's one real authoring cost — a 4+ pane grid needs\n * nested `split` nodes nobody wants to type.\n *\n * **What it saves is a draft, and the file says so.** A capture recovers geometry, labels and dirs;\n * it never recovers commands, because what a backend can report about a running pane is a resolved,\n * machine-local command line rather than a portable one (`template-capture.ts` has the why). A saved\n * template therefore lands with no `command` on any pane\n * and is immediately listed by `template list` alongside finished ones, so the draft has to announce\n * itself IN the file — hence the `description` default. Saying it only on stderr would put the\n * warning everywhere except where the reader is.\n *\n * `--to` defaults to `repo`, matching resolution's own precedence: a template is a statement about\n * how the PROJECT is worked on, and that is the copy worth having by default.\n *\n * **`save`'s subject is a REGION and stays one.** `--workspace` widens it to every tab of the\n * workspace the caller's region sits in — one captured tab per live tab, each with its own derived\n * tree, the exact inverse of the tabs walk. It is opt-in rather than the default because widening the\n * default silently would rewrite what `save` has always meant for every caller already relying on it.\n * The bare form does not stay quiet about the narrowing, though: capturing one tab of three notes on\n * stderr what it left out, rather than letting a caller believe a 3-tab workspace round-trips from a\n * 1-tab template.\n */\nfunction templateSaveCommand(deps: Deps): Command {\n\treturn new Command('save')\n\t\t.description('Capture the live region around a pane into a named template')\n\t\t.argument('<name>', 'Name for the captured template')\n\t\t.option('--from <pane>', \"Pane whose region to capture; defaults to this process's own pane\")\n\t\t.option('--workspace', \"Capture every tab of the caller's workspace, as a tabs template\")\n\t\t.option('--description <text>', 'Description to record in the template')\n\t\t.addOption(\n\t\t\tnew Option('--to <source>', 'Which templates directory to write to').choices(['repo', 'user']).default('repo'),\n\t\t)\n\t\t.option('--force', 'Overwrite an existing template of this name')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.addHelpText(\n\t\t\t'after',\n\t\t\t'\\nA capture recovers geometry, labels and dirs — NOT commands. A backend can often say what is\\n' +\n\t\t\t\t'RUNNING, but it reports the resolved command line rather than the one you typed (`nr web dev`\\n' +\n\t\t\t\t'comes back as `node /run/user/1000/fnm_multishells/.../bin/nr web dev`), which is not portable\\n' +\n\t\t\t\t'to another machine — so every pane is saved without one.\\n' +\n\t\t\t\t'\\nFill them in before the template is worth applying:\\n' +\n\t\t\t\t' cyber-mux template edit <name> # list the panes\\n' +\n\t\t\t\t' cyber-mux template edit <name> --set 1=claude # fill one in',\n\t\t)\n\t\t.action(\n\t\t\tguarded(\n\t\t\t\t(\n\t\t\t\t\tname: string,\n\t\t\t\t\topts: {\n\t\t\t\t\t\tfrom?: string | undefined\n\t\t\t\t\t\tworkspace?: boolean | undefined\n\t\t\t\t\t\tdescription?: string | undefined\n\t\t\t\t\t\tto: 'repo' | 'user'\n\t\t\t\t\t\tforce?: boolean | undefined\n\t\t\t\t\t},\n\t\t\t\t) => {\n\t\t\t\t\t// Before the multiplexer is touched: a name is a lookup key that must also be a filename, so an\n\t\t\t\t\t// unusable one should not cost a region read to find out. A usage error (exit 2), the same\n\t\t\t\t\t// malformed-name family `show` refuses at 2.\n\t\t\t\t\tif (!isValidTemplateName(name)) throw invalidTemplateName(name)\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst path = join(templateDirs(deps.exec, deps.env)[opts.to], `${name}.json`)\n\t\t\t\t\t\t// Checked BEFORE the capture, so a refusal costs nothing — and refused by default, because a\n\t\t\t\t\t\t// template is hand-edited after it is saved (the commands are added by hand) and silently\n\t\t\t\t\t\t// overwriting one would throw that work away.\n\t\t\t\t\t\tif (!opts.force && deps.store.read(path) !== null) {\n\t\t\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t\t\t'template-exists',\n\t\t\t\t\t\t\t\t`template \"${name}\" already exists at ${path} — pass --force to overwrite it`,\n\t\t\t\t\t\t\t\t're-run with --force to replace it',\n\t\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\t\t// Both geometry reads are optional capabilities, exactly as the worktree binding is — and\n\t\t\t\t\t\t// each mode asks only for the one it needs, so a backend is never refused for lacking a\n\t\t\t\t\t\t// member this run would not have called. A backend that cannot answer cannot be captured\n\t\t\t\t\t\t// and there is nothing to degrade to, so this refuses NAMING the backend rather than\n\t\t\t\t\t\t// guessing a tree.\n\t\t\t\t\t\tconst describeRegion = a.regions?.describeRegion\n\t\t\t\t\t\tif (!opts.workspace && !describeRegion) {\n\t\t\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t\t\t'backend-unsupported',\n\t\t\t\t\t\t\t\t`${a.name} cannot report a region's geometry — template save needs a backend that can`,\n\t\t\t\t\t\t\t\t'run template save on a backend that reports geometry (tmux or herdr)',\n\t\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst describeWorkspace = a.regions?.describeWorkspace\n\t\t\t\t\t\tif (opts.workspace && !describeWorkspace) {\n\t\t\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t\t\t'backend-unsupported',\n\t\t\t\t\t\t\t\t`${a.name} cannot enumerate a workspace's tabs — template save --workspace needs a backend that can`,\n\t\t\t\t\t\t\t\t'run template save --workspace on a backend that enumerates tabs (tmux or herdr)',\n\t\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// `--from` names a pane explicitly; otherwise capture around the pane THIS process sits in,\n\t\t\t\t\t\t// which is what makes a bare `template save pool-4` mean \"the screen I am looking at\".\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// Through the same resolver every flat verb uses, rather than the `{ id: opts.from }` this\n\t\t\t\t\t\t// built inline: `--from` is a pane locator like any other, and a name that works on `read`\n\t\t\t\t\t\t// and silently means nothing here is the drift a second spelling guarantees. The caller's\n\t\t\t\t\t\t// OWN pane needs no resolution — `callerPane` already answers with a concrete id.\n\t\t\t\t\t\tconst target = opts.from ? resolveTarget(deps, a, opts.from) : callerPane(a, deps.env)\n\t\t\t\t\t\tif (!target) {\n\t\t\t\t\t\t\t// A required parameter is missing, not an operation that failed — a usage error (exit 2).\n\t\t\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t\t\t'missing-pane',\n\t\t\t\t\t\t\t\t'template save needs a pane to capture the region around — pass --from <pane>, or run it inside one',\n\t\t\t\t\t\t\t\t'pass --from <pane>, or run template save inside a pane',\n\t\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst captureOpts = { name, description: opts.description ?? CAPTURED_DESCRIPTION }\n\t\t\t\t\t\tconst { template, warnings } = opts.workspace\n\t\t\t\t\t\t\t? captureWorkspaceTemplate(describeWorkspace!(deps.exec, target), captureOpts)\n\t\t\t\t\t\t\t: captureTemplate(describeRegion!(deps.exec, target), captureOpts)\n\t\t\t\t\t\tdeps.store.write(path, `${JSON.stringify(template, null, 2)}\\n`)\n\t\t\t\t\t\t// A capture warning (a dir outside the repo root) is a diagnostic, not part of the answer —\n\t\t\t\t\t\t// it stays on stderr, where `capture.feature` pins it. The PAYLOAD is stdout.\n\t\t\t\t\t\tfor (const warning of warnings) process.stderr.write(`${warning}\\n`)\n\t\t\t\t\t\t// save's stdout is a structured payload: a `path` field, plus a `help[N]:` block only when a\n\t\t\t\t\t\t// bare save left tabs behind (#9's reveal-a-truncated-list, omitted otherwise). This replaces\n\t\t\t\t\t\t// the bare path, so programmatic composition reads `--format json | jq -r .path` instead.\n\t\t\t\t\t\tconst entry = opts.workspace ? null : noteTabsLeftOut(deps, a, target, name)\n\t\t\t\t\t\tconst help: HelpEntry[] = entry ? [entry] : []\n\t\t\t\t\t\toutput({ path, ...(help.length ? { help } : {}) }, () => {\n\t\t\t\t\t\t\tprintFields({ path })\n\t\t\t\t\t\t\tprintHelp(help)\n\t\t\t\t\t\t})\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t// A coded failure (the refusals above, an ambiguity, a no-mux) is already a surface and\n\t\t\t\t\t\t// passes through to `guarded`. Anything else is a capture that could not produce a tree — a\n\t\t\t\t\t\t// region no splits could have built, or an empty one — reported under this CLI's own code,\n\t\t\t\t\t\t// never the backend's raw text. Exit 1: the capture failed, the invocation was well-formed.\n\t\t\t\t\t\tif (err instanceof CliError) throw err\n\t\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t\t'unsplittable-region',\n\t\t\t\t\t\t\t'this region could not be captured — it is not a tree any sequence of splits could have produced',\n\t\t\t\t\t\t\t'template save can only capture a region built by splitting',\n\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t\t)\n}\n\n/**\n * What a bare `save` left behind: a `help` entry when the caller's workspace holds tabs this capture\n * did not take, so the capture is honest about its own scope rather than letting a caller believe a\n * 3-tab workspace round-trips from a 1-tab template.\n *\n * Per axi/'s #9 this reveal rides in `save`'s stdout payload as a `help[N]:` block, not on stderr the\n * agent never reads — programmatic composition reads the path from `--format json`, not bare stdout.\n * It is a NOTE rather than a refusal: the template the caller asked for is correct and is already\n * written. Which is also why this is best-effort — a workspace read that fails or that the backend\n * cannot do at all returns `null` (no entry), costing the caller a courtesy, not their capture. An\n * untagged window on a backend with no workspace tier reports one tab and yields nothing, which is\n * right — a window nobody grouped is a workspace of one, and nothing was left out. The `command`\n * re-states the caller's own `name` with `--workspace`, the flag that captures every tab.\n */\nfunction noteTabsLeftOut(deps: Deps, adapter: MuxAdapter, target: MuxTarget, name: string): HelpEntry | null {\n\tconst describeWorkspace = adapter.regions?.describeWorkspace\n\tif (!describeWorkspace) return null\n\tlet tabs: number\n\ttry {\n\t\ttabs = describeWorkspace(deps.exec, target).length\n\t} catch {\n\t\treturn null\n\t}\n\tif (tabs <= 1) return null\n\treturn {\n\t\tmessage:\n\t\t\t`this pane's workspace holds ${tabs} tabs — only the caller's own region was captured. ` +\n\t\t\t'Pass --workspace to capture every tab of it',\n\t\tcommand: `cyber-mux template save ${name} --workspace`,\n\t}\n}\n\n/**\n * The default `description` on a captured template — the draft warning, written where the reader\n * actually is. A saved capture is listed by `template list` next to finished templates and shows up in\n * `template show`, so a note that only ever reached the terminal that ran `save` would be gone by the\n * time anyone reads the file. Overridden by `--description`, since an author who names the template's\n * purpose has said something more useful than this.\n */\nconst CAPTURED_DESCRIPTION = 'Captured from a live region — geometry only; add a command to each pane.'\n\n/**\n * `edit` is `save`'s other half, and exists because of what `save` cannot do: a capture recovers\n * geometry, labels and dirs and lands with no `command` on any pane (`template-capture.ts` has the\n * why), so a saved template is a draft that is worth nothing until every command is filled in. Doing\n * that by hand means opening JSON and counting braces to work out which leaf is the pane on the left.\n *\n * **Three modes, and the DEFAULT is the one an agent uses.** AXI's no-interactive-prompts rule is not\n * a preference here — a verb whose only mode is a conversation is unusable by the caller this CLI is\n * built for, and a prompt against a pipe hangs with nothing on screen to say why. So:\n *\n * - bare — LIST the panes and what each says. AXI #8's content-first home view, and the half of the\n * agent's loop that makes the other half possible: the `pane` column prints exactly the token\n * `--set` takes, so acting on the listing is a paste rather than a derivation.\n * - `--set <pane>=<value>` — the mutation, complete with flags alone, repeatable, idempotent.\n * - `--interactive` — the guided walk, for a human filling a fresh capture in one pass.\n *\n * **Line-based rather than a TUI even in the interactive mode.** A full-screen editor would need a\n * rendering dependency in a package that has exactly one, and a raw-mode event loop the synchronous\n * `Exec` seam every other verb is built on cannot express.\n *\n * **Nothing is written until every answer is in and the result validates.** `applyEdits` clones, so a\n * refusal costs the author nothing and there is never a half-edited template on disk — which is what\n * lets Ctrl-D mean \"abandon this\" rather than \"commit whatever I happened to have typed\", and what\n * makes a `--set` batch naming one bad pane write none of them.\n */\nfunction templateEditCommand(deps: Deps): Command {\n\treturn new Command('edit')\n\t\t.description('Show a template’s panes, and fill them in with --set or --interactive')\n\t\t.argument('[name]', 'Template name')\n\t\t.option('--file <path>', 'Edit this path instead, skipping resolution entirely')\n\t\t.option(\n\t\t\t'--set <pane=value>',\n\t\t\t'Set the field on a pane, e.g. --set 1=claude (repeatable; empty value clears)',\n\t\t\t(value: string, previous: string[]) => [...previous, value],\n\t\t\t[] as string[],\n\t\t)\n\t\t.option('-i, --interactive', 'Ask one question per pane instead, pre-filling the current value')\n\t\t.addOption(\n\t\t\tnew Option('--field <field>', 'Which field --set and --interactive write')\n\t\t\t\t.choices(['command', 'label'])\n\t\t\t\t.default('command'),\n\t\t)\n\t\t.option('--dry-run', 'Print the edited template instead of writing it')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.addHelpText(\n\t\t\t'after',\n\t\t\t'\\nPanes are addressed by ordinal, never by label (two panes may share one): \"3\" in a\\n' +\n\t\t\t\t'single-region template, \"2.3\" for tab 2 pane 3. Run the bare form to see them.\\n' +\n\t\t\t\t'\\nExamples\\n' +\n\t\t\t\t' cyber-mux template edit pool-4 # list the panes\\n' +\n\t\t\t\t' cyber-mux template edit pool-4 --set 1=claude # fill one in\\n' +\n\t\t\t\t' cyber-mux template edit pool-4 --set 2=\"pnpm dev\" --set 3= # set two, clear one\\n' +\n\t\t\t\t' cyber-mux template edit pool-4 --field label --set 1=planner\\n' +\n\t\t\t\t' cyber-mux template edit pool-4 --interactive # one prompt per pane',\n\t\t)\n\t\t.action(\n\t\t\tguardedAsync(\n\t\t\t\tasync (\n\t\t\t\t\tname: string | undefined,\n\t\t\t\t\topts: {\n\t\t\t\t\t\tfile?: string\n\t\t\t\t\t\tset: string[]\n\t\t\t\t\t\tinteractive?: boolean\n\t\t\t\t\t\tfield: EditField\n\t\t\t\t\t\tdryRun?: boolean\n\t\t\t\t\t\tformat?: string\n\t\t\t\t\t},\n\t\t\t\t) => {\n\t\t\t\t\tif (!name && !opts.file) {\n\t\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t\t'missing-argument',\n\t\t\t\t\t\t\t'template edit needs a template name or --file <path>',\n\t\t\t\t\t\t\t'pass a template name, or --file <path>',\n\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\t// Two ways of saying what to write, given together, cannot be reconciled — the same\n\t\t\t\t\t// malformed-input family `--template` with `--launch` is in (exit 2).\n\t\t\t\t\tif (opts.interactive && opts.set.length > 0) {\n\t\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t\t'conflicting-options',\n\t\t\t\t\t\t\t'template edit takes --set or --interactive, not both',\n\t\t\t\t\t\t\t'pass --set for a scripted edit, or --interactive to be asked pane by pane',\n\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tconst resolved = resolveTemplate(deps, { name, file: opts.file })\n\t\t\t\t\tconst slots = planEdits(resolved.template)\n\t\t\t\t\tif (slots.length === 0) {\n\t\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t\t'empty-template',\n\t\t\t\t\t\t\t`template \"${resolved.stem}\" declares no panes to edit`,\n\t\t\t\t\t\t\t'check the template with: cyber-mux template validate',\n\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\t// The bare form MUTATES NOTHING. It is the listing, so an agent that runs the verb to find\n\t\t\t\t\t// out what is there cannot accidentally change anything by doing so.\n\t\t\t\t\tif (!opts.interactive && opts.set.length === 0) {\n\t\t\t\t\t\tprintSlots(resolved, slots, opts.field)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconst answers = opts.interactive\n\t\t\t\t\t\t? await interactiveAnswers(deps, resolved, slots, opts.field)\n\t\t\t\t\t\t: setAnswers(slots, opts.set, opts.field)\n\t\t\t\t\tconst edited = applyEdits(resolved.template, answers)\n\t\t\t\t\t// Belt-and-braces, and honestly so: `resolveTemplate` already validated on the way in, and\n\t\t\t\t\t// neither field this verb offers can be made invalid (both are free strings), so today this\n\t\t\t\t\t// cannot fire. It is here because `--field` is the seam that grows — a `dir` can escape the\n\t\t\t\t\t// apply-time root and a `ratio` can leave `(0,1)`, and the moment one of those is offered\n\t\t\t\t\t// this is the check that stops an answer from writing a template apply would then refuse.\n\t\t\t\t\tconst errors = validateTemplate(edited, resolved.stem)\n\t\t\t\t\tif (errors.length > 0) {\n\t\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t\t'invalid-template',\n\t\t\t\t\t\t\t`those answers would make \"${resolved.stem}\" invalid:\\n${errors.join('\\n')}`,\n\t\t\t\t\t\t\t'give a value the schema accepts',\n\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tif (opts.dryRun) {\n\t\t\t\t\t\tconsole.log(JSON.stringify(edited, null, 2))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\t// Unchanged writes nothing at all, and exits 0 — AXI's idempotent-mutation rule. Re-running the\n\t\t\t\t\t// same `--set` is a no-op rather than an error, and a walk the author pressed Enter through\n\t\t\t\t\t// leaves the file's mtime alone: a template is checked in, and a no-op edit that dirtied the\n\t\t\t\t\t// working tree would show up as a change in review that is not one.\n\t\t\t\t\tif (answers.length > 0) deps.store.write(resolved.path, `${JSON.stringify(edited, null, 2)}\\n`)\n\t\t\t\t\toutput({ path: resolved.path, changed: answers.length }, () =>\n\t\t\t\t\t\tprintFields({ path: resolved.path, changed: String(answers.length) }),\n\t\t\t\t\t)\n\t\t\t\t},\n\t\t\t),\n\t\t)\n}\n\n/**\n * The listing — AXI #8's content-first view, and the first half of an agent's list-then-act loop.\n *\n * The `pane` column is `slotRef`, which is verbatim what `--set` takes: an identifier a caller has to\n * transform before reusing is an identifier that invites transforming it wrong. `position` is here\n * for the same reason it is in the prompt — apply order is a tree walk, not a reading order, so an\n * ordinal alone cannot tell a caller which pane on screen it is about to write to.\n */\nfunction printSlots(resolved: ResolvedTemplate & { template: Template }, slots: EditSlot[], field: EditField): void {\n\tconst missing = slots.filter((slot) => slot[field] === undefined)\n\tconst panes = slots.map((slot) => ({\n\t\tpane: slotRef(slot),\n\t\ttab: slot.tabLabel ?? (slot.tab === undefined ? '' : String(slot.tab + 1)),\n\t\tposition: slot.position ?? '',\n\t\tlabel: slot.label ?? '',\n\t\tdir: slot.dir ?? '',\n\t\tcommand: slot.command ?? '',\n\t}))\n\t// #9 disclosure: what to do next, parameterized rather than guessed. The name is echoed back from\n\t// what the caller actually passed, so the suggestion is runnable as printed.\n\tconst subject = resolved.source === 'file' ? `--file ${resolved.path}` : resolved.stem\n\tconst help: HelpEntry[] = []\n\tif (missing.length > 0) {\n\t\thelp.push({\n\t\t\tmessage: `${missing.length} of ${slots.length} panes have no ${field} — a template applies without one, but the pane just sits at a shell`,\n\t\t\tcommand: `cyber-mux template edit ${subject} --set ${slotRef(missing[0]!)}=<${field}>`,\n\t\t})\n\t}\n\thelp.push({\n\t\tmessage: 'Fill them in one prompt at a time, with the current value pre-filled',\n\t\tcommand: `cyber-mux template edit ${subject} --interactive`,\n\t})\n\toutput({ path: resolved.path, field, panes, help }, () => {\n\t\tprintFields({ template: resolved.stem, path: tildify(resolved.path), source: resolved.source })\n\t\tprintTable(panes, [\n\t\t\t{ label: 'pane', get: (p) => p.pane },\n\t\t\t// Dropped entirely for a single-region template rather than printed empty — a column of blanks\n\t\t\t// is a claim that there is a tab tier to think about, and there is not.\n\t\t\t...(resolved.template.tabs ? [{ label: 'tab', get: (p: (typeof panes)[number]) => p.tab }] : []),\n\t\t\t{ label: 'position', get: (p) => p.position },\n\t\t\t{ label: 'label', get: (p) => p.label },\n\t\t\t{ label: 'dir', get: (p) => p.dir },\n\t\t\t{ label: field, get: (p) => (field === 'label' ? p.label : p.command) },\n\t\t])\n\t\tprintHelp(help)\n\t})\n}\n\n/**\n * `--set` resolved against the listing's own identifiers.\n *\n * The parse and the lookup both throw plain `Error`s from the pure module; they become coded usage\n * errors HERE, at the boundary that owns exit codes. Exit 2 rather than 1 for the same reason\n * `invalidTemplateName` is a 2: the fix is a different argument, and nothing was attempted.\n */\nfunction setAnswers(slots: EditSlot[], specs: string[], field: EditField): EditAnswer[] {\n\ttry {\n\t\treturn resolveSets(slots, specs.map(parseSet), field)\n\t} catch (err) {\n\t\tthrow new CliError(\n\t\t\t'invalid-set',\n\t\t\terr instanceof Error ? err.message : String(err),\n\t\t\t'list the panes and their identifiers with: cyber-mux template edit <name>',\n\t\t\t2,\n\t\t)\n\t}\n}\n\n/**\n * The guided walk's answers — the interactive mode's whole body, kept out of the action so the two\n * mutation paths meet at exactly one place (`applyEdits`) and cannot drift on validation or writing.\n */\nasync function interactiveAnswers(\n\tdeps: Deps,\n\tresolved: ResolvedTemplate & { template: Template },\n\tslots: EditSlot[],\n\tfield: EditField,\n): Promise<EditAnswer[]> {\n\t// A prompt against a pipe would block forever with nothing on screen to say why — the one failure\n\t// mode an agent driving this CLI cannot diagnose or escape. `--format json|agent` is refused for the\n\t// same reason even on a tty: a caller asking for machine output has said it is not a human.\n\tif (!process.stdin.isTTY || isAutomatedOutput()) {\n\t\tthrow new CliError(\n\t\t\t'not-interactive',\n\t\t\t'template edit --interactive asks questions and needs a terminal',\n\t\t\t'set the values directly instead: cyber-mux template edit <name> --set <pane>=<value>',\n\t\t\t2,\n\t\t)\n\t}\n\tconst inputs = await askSlots(deps, resolved, slots, field)\n\t// `undefined` is Ctrl-D — the human left. Nothing is written, and it is a failure rather than a\n\t// quiet success so a caller that wrapped this can tell an abandoned edit from a finished one.\n\tif (!inputs) {\n\t\tthrow new CliError(\n\t\t\t'edit-aborted',\n\t\t\t`edit of \"${resolved.stem}\" abandoned — nothing was written`,\n\t\t\t'run it again to start over',\n\t\t\t1,\n\t\t)\n\t}\n\treturn toAnswers(slots, inputs, field)\n}\n\n/**\n * The walk itself: a header, then one question per pane, in apply order.\n *\n * Returns `undefined` the moment the prompt reports EOF, rather than collecting a partial list —\n * \"the human left\" has to reach the caller as one fact, and a short array would be indistinguishable\n * from a walk where the last few panes were skipped.\n *\n * The prompt is closed in a `finally` because it owns stdin: a throw from anywhere in the walk that\n * left it open would hang the process at exit with no output, turning a diagnosable error into a\n * silent freeze.\n */\nasync function askSlots(\n\tdeps: Deps,\n\tresolved: ResolvedTemplate & { template: Template },\n\tslots: EditSlot[],\n\tfield: EditField,\n): Promise<EditInput[] | undefined> {\n\tconst tabs = resolved.template.tabs?.length\n\tconst scope = tabs ? `${tabs} tabs, ${slots.length} panes` : `${slots.length} panes`\n\tprocess.stdout.write(`\\n${resolved.stem} — ${scope} (${resolved.source}: ${tildify(resolved.path)})\\n`)\n\tprocess.stdout.write(`Enter keeps, \"-\" clears, Ctrl-D abandons.\\n\\n`)\n\tconst prompt = deps.prompt()\n\tconst inputs: EditInput[] = []\n\ttry {\n\t\tlet tab: number | undefined\n\t\tfor (const slot of slots) {\n\t\t\t// Printed only when it CHANGES, so a single-region template shows no tab header at all and a\n\t\t\t// tabs template shows each one once — the grouping the author sees matches the one in the file.\n\t\t\tif (slot.tab !== undefined && slot.tab !== tab) {\n\t\t\t\ttab = slot.tab\n\t\t\t\t// The count is the tab's OWN, not the walk's — a tabs template's panes are numbered within\n\t\t\t\t// each tab, so \"4 panes\" here is what the ordinals below actually run to.\n\t\t\t\tconst panes = slots.filter((other) => other.tab === tab).length\n\t\t\t\tconst label = slot.tabLabel ? ` \"${slot.tabLabel}\"` : ''\n\t\t\t\tprocess.stdout.write(` tab ${tab + 1}${label} (${panes} ${panes === 1 ? 'pane' : 'panes'})\\n`)\n\t\t\t}\n\t\t\tconst line = await prompt.ask(` ${describeSlot(slot, field)} `, slot[field])\n\t\t\tif (line === undefined) return undefined\n\t\t\tinputs.push(readEditInput(line))\n\t\t}\n\t} finally {\n\t\tprompt.close()\n\t}\n\treturn inputs\n}\n\n/**\n * One pane's prompt text: which pane, what already identifies it, and the field being asked for.\n *\n * The context shown is every field EXCEPT the one being edited — a pane is told apart by its dir and\n * its label, and echoing the current value here would duplicate what the pre-filled line already\n * shows. Panes carry no identity of their own beyond their ordinal (a label is a name two panes may\n * share, by design), so the ordinal always leads.\n *\n * **The position leads the rest of the context**, because it is the only part that answers the\n * question the author is actually asking — which pane on my screen is this? Apply order is a tree\n * walk rather than a reading order, so pane 2 of a 2x2 is the one BELOW pane 1, not the one beside\n * it; without a bearing the ordinal alone invites filling the right command into the wrong pane.\n */\nfunction describeSlot(slot: EditSlot, field: EditField): string {\n\tconst context = [\n\t\tslot.position ?? null,\n\t\tslot.label !== undefined && field !== 'label' ? `label: ${slot.label}` : null,\n\t\tslot.dir !== undefined ? `dir: ${slot.dir}` : null,\n\t\tslot.command !== undefined && field !== 'command' ? `command: ${slot.command}` : null,\n\t].filter((part) => part !== null)\n\tconst indent = slot.tab === undefined ? '' : ' '\n\treturn `${indent}pane ${slot.index + 1}${context.length ? ` (${context.join(', ')})` : ''} ${field}?`\n}\n\n/**\n * The `template` group manages templates — there is deliberately no `template apply`. Applying is what\n * `open` and `worktree add` already do, told to build N panes instead of one, so it is `--template` on\n * those verbs.\n *\n * `list` / `show` / `validate` take a FILE as their subject and touch no multiplexer. `save` is the\n * exception in both respects — it reads a live region and writes a file — and it belongs here anyway:\n * it AUTHORS a template, which is what this group is for.\n */\nfunction templateCommand(deps: Deps): Command {\n\tconst cmd = new Command('template').description('Manage named templates (apply one with open/worktree --template)')\n\tcmd.addCommand(templateListCommand(deps))\n\tcmd.addCommand(templateShowCommand(deps))\n\tcmd.addCommand(templateValidateCommand(deps))\n\tcmd.addCommand(templateSaveCommand(deps))\n\tcmd.addCommand(templateEditCommand(deps))\n\treturn cmd\n}\n\nfunction doctorCommand(deps: Deps): Command {\n\treturn new Command('doctor')\n\t\t.description('Probe the multiplexer, self pane, and backend; print fast-path pins')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(() => {\n\t\t\tconst probe = probeMultiplexer(deps.exec, deps.env)\n\t\t\tconst self = currentPane(deps.env)\n\t\t\tlet backend = 'none'\n\t\t\ttry {\n\t\t\t\tbackend = resolveMuxAdapter(deps.env, deps.exec).name\n\t\t\t} catch {\n\t\t\t\t// no backend — reported as 'none'\n\t\t\t}\n\t\t\tconst data = {\n\t\t\t\tmux: probe.mux,\n\t\t\t\tvia: probe.via,\n\t\t\t\tpane: self?.pane ?? probe.pane ?? null,\n\t\t\t\tbackend,\n\t\t\t}\n\t\t\toutput(data, () => {\n\t\t\t\tprintFields({\n\t\t\t\t\tmultiplexer: data.mux,\n\t\t\t\t\t'detected via': data.via,\n\t\t\t\t\tpane: data.pane ?? '(none)',\n\t\t\t\t\tbackend: data.backend,\n\t\t\t\t})\n\t\t\t\tif (self) {\n\t\t\t\t\tconsole.log('')\n\t\t\t\t\tconsole.log('Pin the fast-path to skip detection:')\n\t\t\t\t\tconsole.log(` export CYBER_MUX=${self.mux} CYBER_MUX_PANE=${self.pane}`)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n}\n\nfunction modeCommand(deps: Deps): Command {\n\treturn new Command('mode')\n\t\t.description('Report the detected session backend (tmux / herdr / none)')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(() => {\n\t\t\tlet name = 'none'\n\t\t\ttry {\n\t\t\t\tname = resolveMuxAdapter(deps.env, deps.exec).name\n\t\t\t} catch {\n\t\t\t\t// no backend — reported as 'none'\n\t\t\t}\n\t\t\toutput({ backend: name }, () => console.log(name))\n\t\t})\n}\n\nfunction openCommand(deps: Deps): Command {\n\treturn new Command('open')\n\t\t.description('Open a new pane/tab/workspace, optionally launching a command in it')\n\t\t.option('--launch <command>', 'Command line to run in the new pane')\n\t\t.addOption(templateOption())\n\t\t.option('--cwd <path>', 'Working directory for the new pane', process.cwd())\n\t\t.addOption(AT_OPTION)\n\t\t.addOption(ENV_OPTION)\n\t\t.addOption(LABEL_OPTION)\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\tguarded(\n\t\t\t\t(opts: {\n\t\t\t\t\tlaunch?: string | undefined\n\t\t\t\t\ttemplate?: string | undefined\n\t\t\t\t\tcwd: string\n\t\t\t\t\tat?: MuxPlacement | undefined\n\t\t\t\t\tenv?: Record<string, string> | undefined\n\t\t\t\t\tlabel?: string | undefined\n\t\t\t\t}) => {\n\t\t\t\t\tif (opts.template) {\n\t\t\t\t\t\t// Resolve and validate BEFORE touching a backend, so an unresolvable name opens nothing.\n\t\t\t\t\t\tconst { template } = resolveTemplate(deps, { name: opts.template })\n\t\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\treportManifest(\n\t\t\t\t\t\t\t\topenTemplate(deps.exec, a, template, {\n\t\t\t\t\t\t\t\t\tcwd: opts.cwd,\n\t\t\t\t\t\t\t\t\t// A fresh space is empty by construction, which is why the pool defaults there.\n\t\t\t\t\t\t\t\t\tat: opts.at ?? 'workspace',\n\t\t\t\t\t\t\t\t\tlabel: opts.label ?? template.name,\n\t\t\t\t\t\t\t\t\tdirExists: deps.store.dirExists,\n\t\t\t\t\t\t\t\t\tnewId: nodeNewId,\n\t\t\t\t\t\t\t\t\tfrom: callerPane(a, deps.env),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\treportApplyFailure(err)\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\tconst t = a.open(deps.exec, {\n\t\t\t\t\t\tcwd: opts.cwd,\n\t\t\t\t\t\tlaunch: opts.launch,\n\t\t\t\t\t\tat: opts.at,\n\t\t\t\t\t\tenv: opts.env,\n\t\t\t\t\t\tlabel: opts.label,\n\t\t\t\t\t\tfrom: callerPane(a, deps.env),\n\t\t\t\t\t})\n\t\t\t\t\t// The workspace rides in on the open itself — the backend answered when the pane was born, so\n\t\t\t\t\t// reporting it asks nothing extra; hiding it would discard a fact already in hand. `?? null`\n\t\t\t\t\t// on the JSON side only, matching `reportOpenedWorktree`: absent is the seam's meaning, null\n\t\t\t\t\t// is its spelling at the machine-readable boundary.\n\t\t\t\t\toutput({ pane: t.id, workspace: t.workspace ?? null }, () =>\n\t\t\t\t\t\tprintFields({ pane: t.id, workspace: t.workspace }),\n\t\t\t\t\t)\n\t\t\t\t},\n\t\t\t),\n\t\t)\n}\n\n/** The `send` group: drive a pane's input WITHOUT taking its turn. Neither subcommand presses an\n * Enter the caller did not write — supplying one is `submit`'s job. Bare `cyber-mux send` is\n * incomplete input, not a content request: it is answered with help on stdout and exit 2 (a usage\n * error — a missing required parameter; see the AXI note in `.agents/spec/axi/README.md`). */\nfunction sendCommand(deps: Deps): Command {\n\tconst send = new Command('send').description('Drive a pane without taking its turn (text | keys)')\n\tsend.addCommand(\n\t\tnew Command('text')\n\t\t\t.description('Type literal text into a pane, pressing no Enter (a key-named word is typed, not pressed)')\n\t\t\t.argument('<pane>', 'Target pane id')\n\t\t\t.argument('<text>', 'Literal text to type')\n\t\t\t.addOption(FORMAT_OPTION)\n\t\t\t.action(\n\t\t\t\tguarded((pane: string, text: string) => {\n\t\t\t\t\tpaneVerb(pane, () => {\n\t\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\t\ta.sendText(deps.exec, resolveTarget(deps, a, pane), text)\n\t\t\t\t\t})\n\t\t\t\t}),\n\t\t\t),\n\t)\n\tsend.addCommand(\n\t\tnew Command('keys')\n\t\t\t.description('Press named keys in a pane, typing nothing (Up, Enter, Escape, C-c, F1 …)')\n\t\t\t.argument('<pane>', 'Target pane id')\n\t\t\t.argument(\n\t\t\t\t'<keys...>',\n\t\t\t\t'Key names, in order — core vocabulary is portable, anything else is passed to the backend as-is',\n\t\t\t)\n\t\t\t.addOption(FORMAT_OPTION)\n\t\t\t.action(\n\t\t\t\tguarded((pane: string, keys: string[]) => {\n\t\t\t\t\tpaneVerb(pane, () => {\n\t\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\t\ta.sendKeys(deps.exec, resolveTarget(deps, a, pane), keys)\n\t\t\t\t\t})\n\t\t\t\t}),\n\t\t\t),\n\t)\n\treturn send\n}\n\nfunction submitCommand(deps: Deps): Command {\n\treturn new Command('submit')\n\t\t.description(\"Take a pane's turn: type the text if given, then always press Enter (no text = bare-Enter flush)\")\n\t\t.argument('<pane>', 'Target pane id')\n\t\t.argument('[text]', 'Text to type before Enter; omit to flush an already-staged buffer without retyping it')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\tguarded((pane: string, text: string | undefined) => {\n\t\t\t\tpaneVerb(pane, () => {\n\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\ta.submit(deps.exec, resolveTarget(deps, a, pane), text)\n\t\t\t\t})\n\t\t\t}),\n\t\t)\n}\n\nfunction readCommand(deps: Deps): Command {\n\treturn new Command('read')\n\t\t.description(\"Capture a pane's output\")\n\t\t.argument('<pane>', 'Target pane id')\n\t\t.option('--lines <n>', 'Trailing lines to capture', (v) => Number.parseInt(v, 10))\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\tguarded((pane: string, opts: { lines?: number | undefined }) => {\n\t\t\t\tpaneVerb(pane, () => {\n\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\tconst t = resolveTarget(deps, a, pane)\n\t\t\t\t\t// A failed read captures nothing — there are no bytes for an error to land amid, so `paneVerb`\n\t\t\t\t\t// throwing here means stdout is the structured error alone, with no partial pane output before it.\n\t\t\t\t\tconst out = a.read(deps.exec, t, opts.lines != null ? { lines: opts.lines } : undefined)\n\t\t\t\t\tprocess.stdout.write(out.endsWith('\\n') ? out : `${out}\\n`)\n\t\t\t\t})\n\t\t\t}),\n\t\t)\n}\n\nfunction focusCommand(deps: Deps): Command {\n\treturn new Command('focus')\n\t\t.description('Beam the attached client to a pane')\n\t\t.argument('<pane>', 'Target pane id')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\tguarded((pane: string) => {\n\t\t\t\tpaneVerb(pane, () => {\n\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\ta.focus(deps.exec, resolveTarget(deps, a, pane))\n\t\t\t\t})\n\t\t\t}),\n\t\t)\n}\n\nfunction closeCommand(deps: Deps): Command {\n\treturn new Command('close')\n\t\t.description('Close a pane')\n\t\t.argument('<pane>', 'Target pane id')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\tguarded((pane: string) => {\n\t\t\t\tpaneVerb(pane, () => {\n\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\ta.teardown(deps.exec, resolveTarget(deps, a, pane))\n\t\t\t\t})\n\t\t\t}),\n\t\t)\n}\n\nfunction listCommand(deps: Deps): Command {\n\treturn new Command('list')\n\t\t.description('Enumerate every live pane the current backend can see')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\tguarded(() => {\n\t\t\t\tconst panes = adapter(deps).listPanes(deps.exec)\n\t\t\t\toutput({ panes }, () =>\n\t\t\t\t\tprintTable(panes, [\n\t\t\t\t\t\t{ label: 'pane', get: (p) => p.id },\n\t\t\t\t\t\t// `label` takes the slot `mux` held. Every row of one listing reports the same mux — one\n\t\t\t\t\t\t// adapter is selected per session, so the column is constant by construction and\n\t\t\t\t\t\t// discriminates nothing. The label is what a caller now types INSTEAD of the id, so it is\n\t\t\t\t\t\t// the fact this row exists to carry. `doctor` is where the backend is a live question.\n\t\t\t\t\t\t{ label: 'label', get: (p) => p.label ?? '' },\n\t\t\t\t\t\t{ label: 'harness', get: (p) => p.harness ?? '' },\n\t\t\t\t\t\t{ label: 'cwd', get: (p) => p.cwd ?? '' },\n\t\t\t\t\t]),\n\t\t\t\t)\n\t\t\t}),\n\t\t)\n}\n\nfunction existsCommand(deps: Deps): Command {\n\treturn new Command('exists')\n\t\t.description('Probe whether a single pane is still live (exit 0 = live, 1 = gone)')\n\t\t.argument('<pane>', 'Target pane id')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\tguarded((pane: string) => {\n\t\t\t\tconst a = adapter(deps)\n\t\t\t\t// Resolution runs BEFORE any output: an ambiguous locator throws out of here, so `live`/`gone`\n\t\t\t\t// is never printed for a question that has no single pane to be about.\n\t\t\t\tconst t = resolveTarget(deps, a, pane)\n\t\t\t\tconst live = a.paneExists(deps.exec, t)\n\t\t\t\toutput({ pane, live }, () => console.log(live ? 'live' : 'gone'))\n\t\t\t\tif (!live) process.exit(1)\n\t\t\t}),\n\t\t)\n}\n\nfunction worktreeAddCommand(deps: Deps): Command {\n\treturn new Command('add')\n\t\t.description('Create a git worktree, and open it when given a placement — grouped where the backend can')\n\t\t.requiredOption('--branch <branch>', 'Branch to create the worktree on')\n\t\t.option('--path <path>', 'Where to check out the worktree (default: a sibling of the primary checkout)')\n\t\t.option('--base <ref>', 'Start point for the new branch (default: the current HEAD)')\n\t\t.option('--launch <command>', 'Command to run in the opened pane; implies --at workspace')\n\t\t.addOption(templateOption())\n\t\t.addOption(AT_OPTION)\n\t\t.addOption(ENV_OPTION)\n\t\t.addOption(LABEL_OPTION)\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\t(opts: {\n\t\t\t\tbranch: string\n\t\t\t\tpath?: string | undefined\n\t\t\t\tbase?: string | undefined\n\t\t\t\tlaunch?: string | undefined\n\t\t\t\ttemplate?: string | undefined\n\t\t\t\tat?: MuxPlacement | undefined\n\t\t\t\tenv?: Record<string, string> | undefined\n\t\t\t\tlabel?: string | undefined\n\t\t\t}) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst primaryRoot = resolvePrimaryRoot(deps.exec)\n\t\t\t\t\t// The primary flow this feature exists for. Resolve and validate FIRST: a typo in a\n\t\t\t\t\t// template name, or a template that sets a cwd, must not leave a worktree behind.\n\t\t\t\t\tif (opts.template) {\n\t\t\t\t\t\tconst { template } = resolveTemplate(deps, { name: opts.template })\n\t\t\t\t\t\tconst path = opts.path ?? resolveWorktreePath(primaryRoot, opts.branch)\n\t\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\t\t// No `launch`: the worktree's workspace opens blank and its root pane becomes the\n\t\t\t\t\t\t// tree's root region — not a wasted pane, the one the walk splits into. Its `env`\n\t\t\t\t\t\t// must ride in HERE, though: no split ever births that pane, so this is the only\n\t\t\t\t\t\t// call that can set it.\n\t\t\t\t\t\tconst opened = addAndOpenWorktree(deps.exec, a, {\n\t\t\t\t\t\t\tprimaryRoot,\n\t\t\t\t\t\t\tbranch: opts.branch,\n\t\t\t\t\t\t\tpath,\n\t\t\t\t\t\t\tbase: opts.base,\n\t\t\t\t\t\t\tenv: templateRootPane(template).env,\n\t\t\t\t\t\t\tat: 'workspace',\n\t\t\t\t\t\t\tlabel: opts.label ?? template.name,\n\t\t\t\t\t\t\tfrom: callerPane(a, deps.env),\n\t\t\t\t\t\t})\n\t\t\t\t\t\tconst extra = { root: opened.worktree.root, branch: opened.worktree.branch }\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\treportManifest(\n\t\t\t\t\t\t\t\tapplyTemplateToRegion(deps.exec, a, template, {\n\t\t\t\t\t\t\t\t\troot: opened.target,\n\t\t\t\t\t\t\t\t\tcwd: opened.worktree.root,\n\t\t\t\t\t\t\t\t\tworkspace: opened.workspace ?? null,\n\t\t\t\t\t\t\t\t\t// The same label the workspace was just opened under — a tabs template carries\n\t\t\t\t\t\t\t\t\t// it into each later tab's name where the backend has no workspace tier.\n\t\t\t\t\t\t\t\t\tlabel: opts.label ?? template.name,\n\t\t\t\t\t\t\t\t\t// The route that opened the region is the only thing that knows whether it\n\t\t\t\t\t\t\t\t\t// could carry the root pane's env; the walk falls back to a prefix when not.\n\t\t\t\t\t\t\t\t\trootEnvHonored: opened.envHonored,\n\t\t\t\t\t\t\t\t\tdirExists: deps.store.dirExists,\n\t\t\t\t\t\t\t\t\tnewId: nodeNewId,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\textra,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\treportApplyFailure(err, extra)\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconst path = opts.path ?? resolveWorktreePath(primaryRoot, opts.branch)\n\t\t\t\t\t// With no placement asked for AND nothing to put IN a pane, this IS a git operation: it\n\t\t\t\t\t// creates a checkout, opens nothing, and needs no multiplexer to be inside of. There is\n\t\t\t\t\t// nothing to group because nothing was opened — `worktree open` groups it later. `--env`\n\t\t\t\t\t// joins `--launch` in this guard: asking for something in a pane is asking for the pane,\n\t\t\t\t\t// so it can no longer be a bare add.\n\t\t\t\t\tif (!opts.at && !opts.launch && !opts.env) {\n\t\t\t\t\t\tconst wt = gitWorktreeAdapter.add(deps.exec, { primaryRoot, path, branch: opts.branch, base: opts.base })\n\t\t\t\t\t\toutput({ root: wt.root, branch: wt.branch, pane: null, workspace: null }, () =>\n\t\t\t\t\t\t\tprintFields({ root: wt.root, branch: wt.branch }),\n\t\t\t\t\t\t)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\t// A launch or an env with no placement wants its own space, not a pane crowding the\n\t\t\t\t\t// caller's — and `workspace` is the only placement a backend can bind a worktree to.\n\t\t\t\t\tconst at = opts.at ?? 'workspace'\n\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\treportOpenedWorktree(\n\t\t\t\t\t\taddAndOpenWorktree(deps.exec, a, {\n\t\t\t\t\t\t\tprimaryRoot,\n\t\t\t\t\t\t\tbranch: opts.branch,\n\t\t\t\t\t\t\tpath,\n\t\t\t\t\t\t\tbase: opts.base,\n\t\t\t\t\t\t\tlaunch: opts.launch,\n\t\t\t\t\t\t\tenv: opts.env,\n\t\t\t\t\t\t\tat,\n\t\t\t\t\t\t\tlabel: opts.label,\n\t\t\t\t\t\t\tfrom: callerPane(a, deps.env),\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t`cyber-mux worktree add --branch ${opts.branch} --at workspace`,\n\t\t\t\t\t)\n\t\t\t\t} catch (err) {\n\t\t\t\t\treportWorktreeFailure(err)\n\t\t\t\t}\n\t\t\t},\n\t\t)\n}\n\nfunction worktreeOpenCommand(deps: Deps): Command {\n\treturn new Command('open')\n\t\t.description('Open an existing git worktree — groups it with the repo where the backend can bind')\n\t\t.argument('<path>', 'Worktree path to open')\n\t\t.option('--launch <command>', 'Command to run in the opened pane')\n\t\t.addOption(AT_OPTION)\n\t\t.addOption(ENV_OPTION)\n\t\t.addOption(LABEL_OPTION)\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\t(\n\t\t\t\tpath: string,\n\t\t\t\topts: {\n\t\t\t\t\tlaunch?: string | undefined\n\t\t\t\t\tat?: MuxPlacement | undefined\n\t\t\t\t\tenv?: Record<string, string> | undefined\n\t\t\t\t\tlabel?: string | undefined\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst primaryRoot = resolvePrimaryRoot(deps.exec)\n\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\treportOpenedWorktree(\n\t\t\t\t\t\topenExistingWorktree(deps.exec, a, {\n\t\t\t\t\t\t\tprimaryRoot,\n\t\t\t\t\t\t\tpath,\n\t\t\t\t\t\t\tlaunch: opts.launch,\n\t\t\t\t\t\t\tenv: opts.env,\n\t\t\t\t\t\t\tat: opts.at,\n\t\t\t\t\t\t\tlabel: opts.label,\n\t\t\t\t\t\t\tfrom: callerPane(a, deps.env),\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t`cyber-mux worktree open ${path} --at workspace`,\n\t\t\t\t\t)\n\t\t\t\t} catch (err) {\n\t\t\t\t\treportWorktreeFailure(err)\n\t\t\t\t}\n\t\t\t},\n\t\t)\n}\n\nfunction worktreeListCommand(deps: Deps): Command {\n\treturn new Command('list')\n\t\t.description(\n\t\t\t'Every worktree of the repo, and the workspace each is open in — BRANCH is marked \"(*)\" for the primary checkout (every other row is a linked worktree) or \"(removable)\" when the worktree looks disposable (its branch is merged into the default branch, the checkout is clean, and nothing is open in it), and ROOT is marked \"(gone)\" when the checkout no longer exists on disk (git can prune it)',\n\t\t)\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(() => {\n\t\t\ttry {\n\t\t\t\tconst primaryRoot = resolvePrimaryRoot(deps.exec)\n\t\t\t\tconst worktrees = listWorktrees(deps.exec, optionalAdapter(deps), { primaryRoot })\n\t\t\t\toutput({ worktrees }, () =>\n\t\t\t\t\tprintTable(worktrees, [\n\t\t\t\t\t\t// `linked` is one BIT, so it does not earn a column: the primary checkout — the single\n\t\t\t\t\t\t// row where it is false — is marked in BRANCH instead. The field itself stays intact in\n\t\t\t\t\t\t// `--format json`, where a consumer reads the boolean rather than the marker.\n\t\t\t\t\t\t// `(removable)` is the disposability COMPOSITE — merged AND clean AND unoccupied — compressed to\n\t\t\t\t\t\t// one word, and it rides on BRANCH because the branch is what carries the work that landed.\n\t\t\t\t\t\t// Its inputs (`merged`, `dirty`) stay raw and unmarked in `--format json`, where a consumer\n\t\t\t\t\t\t// composes its own policy rather than inheriting this one.\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: 'branch',\n\t\t\t\t\t\t\tget: (w) =>\n\t\t\t\t\t\t\t\t`${w.branch ?? '(detached)'}${w.linked ? (isWorktreeRemovable(w) ? ' (removable)' : '') : ' (*)'}`,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t// `prunable` is likewise one bit, and a rarer one — the marker rides on ROOT because the\n\t\t\t\t\t\t// path is the thing that is actually gone. `(gone)` is git's own word for a target that\n\t\t\t\t\t\t// vanished (`branch -vv` prints it), where \"stale\" would read as merely out of date.\n\t\t\t\t\t\t{ label: 'root', get: (w) => `${tildify(w.root)}${w.prunable ? ' (gone)' : ''}` },\n\t\t\t\t\t\t{ label: 'workspace', get: (w) => w.workspace ?? '' },\n\t\t\t\t\t]),\n\t\t\t\t)\n\t\t\t} catch (err) {\n\t\t\t\treportWorktreeFailure(err)\n\t\t\t}\n\t\t})\n}\n\nfunction worktreeRemoveCommand(deps: Deps): Command {\n\treturn new Command('remove')\n\t\t.description('Remove a git worktree — refuses the primary checkout and uncommitted changes unless --force')\n\t\t.argument('<path>', 'Worktree path to remove')\n\t\t.option('--force', 'Discard uncommitted changes in the worktree')\n\t\t.action((path: string, opts: { force?: boolean | undefined }) => {\n\t\t\ttry {\n\t\t\t\tconst primaryRoot = resolvePrimaryRoot(deps.exec)\n\t\t\t\tremoveWorktree(deps.exec, optionalAdapter(deps), path, { primaryRoot, force: opts.force })\n\t\t\t} catch (err) {\n\t\t\t\treportWorktreeFailure(err)\n\t\t\t}\n\t\t})\n}\n\n/**\n * The bulk remove — every candidate `worktree list` already marks `(removable)`, gone in one call\n * instead of one `worktree remove` per path.\n *\n * **Bare form previews, `--force` applies.** The gate is destructive (it discards checkouts,\n * irreversibly), so the default has to be the side-effect-free one — a caller can run this to see\n * what WOULD go, exactly as `template edit`'s bare form lists rather than mutates. `--force` here is\n * \"actually do it\", not `removeWorktreeSafely`'s \"discard uncommitted changes\": prune's candidates\n * are already clean by construction (`isWorktreeRemovable` requires `dirty === false`), so there is\n * nothing for that meaning to apply to.\n */\nfunction worktreePruneCommand(deps: Deps): Command {\n\treturn new Command('prune')\n\t\t.description(\n\t\t\t'Remove every disposable worktree in one call — the same gate `worktree list` marks \"(removable)\" with. Bare form previews the candidates; pass --force to actually remove them',\n\t\t)\n\t\t.option('--force', 'Remove the candidates instead of only previewing them')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action((opts: { force?: boolean | undefined }) => {\n\t\t\ttry {\n\t\t\t\tconst primaryRoot = resolvePrimaryRoot(deps.exec)\n\t\t\t\tconst result = pruneWorktrees(deps.exec, primaryRoot, { dryRun: !opts.force })\n\t\t\t\tconst removed = result.removed.map((entry) => ({ root: entry.root, branch: entry.branch ?? null }))\n\t\t\t\tconst skipped = result.skipped.map((s) => ({\n\t\t\t\t\troot: s.entry.root,\n\t\t\t\t\tbranch: s.entry.branch ?? null,\n\t\t\t\t\treason: s.reason,\n\t\t\t\t}))\n\t\t\t\toutput({ applied: Boolean(opts.force), removed, skipped }, () => {\n\t\t\t\t\tprintTable(removed, [\n\t\t\t\t\t\t{ label: opts.force ? 'removed' : 'would remove', get: (r) => tildify(r.root) },\n\t\t\t\t\t\t{ label: 'branch', get: (r) => r.branch ?? '(detached)' },\n\t\t\t\t\t])\n\t\t\t\t\tif (skipped.length > 0) {\n\t\t\t\t\t\tprintTable(skipped, [\n\t\t\t\t\t\t\t{ label: 'skipped', get: (s) => tildify(s.root) },\n\t\t\t\t\t\t\t{ label: 'reason', get: (s) => s.reason },\n\t\t\t\t\t\t])\n\t\t\t\t\t}\n\t\t\t\t\tif (!opts.force && removed.length > 0) {\n\t\t\t\t\t\tprintHelp([\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmessage: `${removed.length} worktree${removed.length === 1 ? '' : 's'} would be removed`,\n\t\t\t\t\t\t\t\tcommand: 'cyber-mux worktree prune --force',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t])\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t} catch (err) {\n\t\t\t\treportWorktreeFailure(err)\n\t\t\t}\n\t\t})\n}\n\nfunction worktreeCommand(deps: Deps): Command {\n\tconst cmd = new Command('worktree').description('Git worktree helpers for spawning/tearing down a session')\n\tcmd.addCommand(worktreeAddCommand(deps))\n\tcmd.addCommand(worktreeOpenCommand(deps))\n\tcmd.addCommand(worktreeListCommand(deps))\n\tcmd.addCommand(worktreeRemoveCommand(deps))\n\tcmd.addCommand(worktreePruneCommand(deps))\n\treturn cmd\n}\n\n/**\n * Translate a commander-level rejection into the SAME coded error surface every verb uses. commander's\n * own failures — a flag the command does not define, a required argument the parser never received, two\n * mutually-exclusive flags — are USAGE errors: the fix is a different invocation, not a retry, so they\n * exit 2, and they belong on stdout under a stable code exactly as an operation failure does.\n *\n * The callback is attached per command, so `command` is the SUBCOMMAND actually invoked — which is what\n * lets an unknown flag be rejected against that subcommand's own flags (`template list` does not share\n * `template save`'s), and the offending flag be named beside them so the agent self-corrects in one turn\n * rather than a second `--help` round trip.\n */\nfunction handleCommanderError(command: Command, err: CommanderError): never {\n\t// An explicit `--help`/`--version` is not an error: help is already on stdout, exit 0, and no flag\n\t// validation ever rejects `--help` on any command.\n\tif (err.code === 'commander.helpDisplayed' || err.code === 'commander.version') process.exit(err.exitCode)\n\t// A bare group (`cyber-mux send` with no subcommand, or a bare `cyber-mux`) is incomplete input, not\n\t// a content request: its help belongs on stdout — the stream the agent reads — and it exits 2, the\n\t// status that separates bad input from a failed operation.\n\tif (err.code === 'commander.help') {\n\t\tprocess.stdout.write(command.helpInformation())\n\t\tprocess.exit(2)\n\t}\n\tif (err.code === 'commander.unknownOption') reportError(unknownFlagError(command, err))\n\tif (err.code === 'commander.missingArgument') reportError(missingArgumentError(command, err))\n\tif (err.code === 'commander.conflictingOption' || err.code === 'commander.excessArguments') {\n\t\treportError(\n\t\t\tnew CliError('usage-error', usageMessage(err), 'pass only one of the conflicting flags, then re-run', 2),\n\t\t)\n\t}\n\t// Anything else (an invalid --at choice, an unknown subcommand) keeps commander's own behavior:\n\t// re-thrown to the top-level handler, which honors the exit code commander chose.\n\tthrow err\n}\n\n/** commander's raw message minus its own `error: ` prefix — its own CLI's text, safe to surface. */\nfunction usageMessage(err: CommanderError): string {\n\treturn (err.message ?? '').replace(/^error:\\s*/, '')\n}\n\n/** An unknown flag, named beside the command's OWN valid flags, so the agent self-corrects in one turn. */\nfunction unknownFlagError(command: Command, err: CommanderError): CliError {\n\tconst flag = err.message.match(/'([^']+)'/)?.[1] ?? 'the flag'\n\tconst valid = command.options.map((o) => o.long ?? o.short).filter((f): f is string => Boolean(f))\n\treturn new CliError(\n\t\t'unknown-flag',\n\t\t`unknown flag ${flag} for ${command.name()}`,\n\t\tvalid.length > 0 ? `valid flags for ${command.name()}: ${valid.join(' ')}` : `${command.name()} takes no flags`,\n\t\t2,\n\t)\n}\n\n/** A required argument the parser never received — a usage error naming the missing argument. */\nfunction missingArgumentError(command: Command, err: CommanderError): CliError {\n\tconst arg = err.message.match(/'([^']+)'/)?.[1] ?? 'an argument'\n\treturn new CliError(\n\t\t'missing-argument',\n\t\t`missing required argument: ${arg}`,\n\t\t`provide ${arg}: cyber-mux ${command.name()} <${arg}>`,\n\t\t2,\n\t)\n}\n\n/**\n * Every command in the tree gets a translating `exitOverride` — NOT inherited by subcommands, so it is\n * walked. Without it `cyber-mux send` with no subcommand would `process.exit` straight from the group\n * and kill the caller's process (in tests, the runner itself); with the plain default it would throw a\n * bare `CommanderError`. This routes commander's own rejections through the coded error surface, so a\n * missing argument or unknown flag reaches the caller as an exit-2 structured error on stdout, exactly\n * as an ambiguity or a `no-mux` does.\n */\nfunction exitOverrideTree(command: Command): Command {\n\tcommand.exitOverride((err) => handleCommanderError(command, err))\n\tfor (const sub of command.commands) exitOverrideTree(sub)\n\treturn command\n}\n\n/** Assembles the full command tree against the given deps (real env/exec in production, fakes in\n * tests). Every command in the tree gets `exitOverride()`, so commander throws a `CommanderError`\n * instead of calling `process.exit` directly and a rejection (an invalid `--at` choice, a missing\n * argument, a bare `send`) is catchable both here and in tests, rather than killing the test\n * runner's own process. */\nexport function buildProgram(cliDeps: CliDeps = DEFAULT_DEPS): Command {\n\tconst deps: Deps = {\n\t\tenv: cliDeps.env,\n\t\texec: cliDeps.exec,\n\t\tstore: cliDeps.store ?? nodeTemplateStore,\n\t\tprompt: cliDeps.prompt ?? realPrompt,\n\t}\n\tconst program = new Command()\n\t\t.name('cyber-mux')\n\t\t.description('Cross-multiplexer pane control — one contract over tmux and herdr')\n\t\t.version('0.0.0')\n\n\tprogram.addCommand(doctorCommand(deps))\n\tprogram.addCommand(modeCommand(deps))\n\tprogram.addCommand(openCommand(deps))\n\tprogram.addCommand(sendCommand(deps))\n\tprogram.addCommand(submitCommand(deps))\n\tprogram.addCommand(readCommand(deps))\n\tprogram.addCommand(focusCommand(deps))\n\tprogram.addCommand(closeCommand(deps))\n\tprogram.addCommand(listCommand(deps))\n\tprogram.addCommand(existsCommand(deps))\n\tprogram.addCommand(worktreeCommand(deps))\n\tprogram.addCommand(templateCommand(deps))\n\n\treturn exitOverrideTree(program)\n}\n\n/** The real CLI entry point — called explicitly by `bin/cyber-mux.mjs`, never as an import-time\n * side effect, so importing this module (e.g. from tests) never runs the real CLI. */\nexport async function main(): Promise<void> {\n\ttry {\n\t\tawait buildProgram().parseAsync(process.argv)\n\t} catch (err) {\n\t\t// A coded failure that reached here unguarded still owes the caller its structured error on stdout.\n\t\tif (err instanceof CliError) reportError(err)\n\t\t// A commander rejection `handleCommanderError` re-threw (an invalid --at choice, an unknown\n\t\t// subcommand): commander already wrote its own text to stderr, so honor the exit code it chose and\n\t\t// add nothing — re-printing would double it.\n\t\tif (err instanceof CommanderError) process.exit(err.exitCode)\n\t\tprocess.stderr.write(`${err instanceof Error ? err.message : String(err)}\\n`)\n\t\tprocess.exit(1)\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.mjs","names":["resolveTemplateSource"],"sources":["../src/output.ts","../src/cli-error.ts","../src/cli-options.ts","../src/prompt.ts","../src/template-capture.ts","../src/template-edit.ts","../src/template-session.ts","../src/worktree-session.ts","../src/cli.ts"],"sourcesContent":["import { homedir } from 'node:os'\nimport { sep } from 'node:path'\n\n/**\n * A path with the caller's home directory collapsed to `~` — for HUMAN output only. Every worktree\n * of a repo shares a long home-rooted prefix, so the table spends width on a string the reader\n * already knows. JSON output must NEVER pass through here: a consumer needs the absolute path.\n *\n * The match is on a path BOUNDARY, not a prefix — `/home/unionalX` is not under `/home/unional`, so\n * only `$HOME` itself and `$HOME/...` are rewritten. A home of `/` collapses nothing, since every\n * absolute path would otherwise become `~`.\n */\nexport function tildify(path: string, home: string = homedir()): string {\n\tif (!home || home === sep || home === '/') return path\n\tif (path === home) return '~'\n\tfor (const s of new Set([sep, '/'])) {\n\t\tif (path.startsWith(home + s)) return `~${path.slice(home.length)}`\n\t}\n\treturn path\n}\n\nfunction printJson(data: unknown) {\n\tconsole.log(JSON.stringify(data, null, 2))\n}\n\nexport function printFields(fields: Record<string, string | null | undefined>): void {\n\tconst entries = Object.entries(fields).filter(([, v]) => v != null) as [string, string][]\n\tif (entries.length === 0) return\n\tconst width = Math.max(...entries.map(([k]) => k.length))\n\tfor (const [key, val] of entries) {\n\t\tconsole.log(`${key.padEnd(width)} ${val}`)\n\t}\n}\n\n/**\n * A #9 contextual-disclosure suggestion: an obvious next move the caller can take, named as data\n * rather than prose. `message` says what is worth doing; `command` is the concrete invocation that\n * does it. Dynamic parts are the caller's OWN values (a name they passed, a branch they named), never\n * a guessed id.\n */\nexport type HelpEntry = { message: string; command: string }\n\n/**\n * Render #9 suggestions as a `help[N]:` block on stdout — inside the structured payload, the stream an\n * agent reads, not stderr it never does. Each entry is a message line and its command, indented under\n * it. Prints NOTHING for an empty list: a self-contained result owes no suggestion (#9's\n * omit-when-self-contained rule), so the block never appears as noise.\n */\nexport function printHelp(entries: HelpEntry[]): void {\n\tentries.forEach((entry, i) => {\n\t\tconsole.log(`help[${i}]: ${entry.message}`)\n\t\tconsole.log(` -> ${entry.command}`)\n\t})\n}\n\nexport function printTable<T>(items: T[], cols: { label: string; get: (item: T) => string }[]): void {\n\tif (items.length === 0) {\n\t\tconsole.log('(none)')\n\t\treturn\n\t}\n\tconst widths = cols.map((c) => Math.max(c.label.length, ...items.map((i) => c.get(i).length)))\n\tconsole.log(cols.map((c, i) => c.label.toUpperCase().padEnd(widths[i]!)).join(' '))\n\tconsole.log(widths.map((w) => '-'.repeat(w)).join(' '))\n\tfor (const item of items) {\n\t\tconsole.log(cols.map((c, i) => c.get(item).padEnd(widths[i]!)).join(' '))\n\t}\n}\n\nfunction getFormat(): string | undefined {\n\tconst argv = process.argv\n\tconst fmtIdx = argv.indexOf('--format')\n\tif (fmtIdx !== -1) return argv[fmtIdx + 1]\n\tif (argv.includes('--json')) return 'json' // hidden backward-compat alias\n\treturn undefined\n}\n\n/**\n * Whether the caller asked for machine-readable output. Exported because `output()` is not the only\n * writer that owes it: a structured ERROR is rendered by `reportError` (`cli-error.ts`) rather than\n * through `output()`, and it has to honor `--format json` exactly as the success path does. Both write\n * stdout — AXI's stream for everything the agent consumes, errors included.\n */\nexport function isJsonOutput(): boolean {\n\treturn getFormat() === 'json'\n}\n\n// True when the caller is a script or agent — suppress interactive prompts.\nexport function isAutomatedOutput(): boolean {\n\tconst fmt = getFormat()\n\treturn fmt === 'json' || fmt === 'agent'\n}\n\nexport function output(data: unknown, readable: () => void): void {\n\tif (isJsonOutput()) printJson(data)\n\telse readable()\n}\n","import { isJsonOutput } from './output.ts'\n\n/**\n * The error surface — AXI's #6, made concrete.\n *\n * Every failure is a STRUCTURED, CODED error on **stdout**, because stdout is the stream AXI reserves\n * for what the agent consumes — data, errors and suggestions alike — while stderr is defined as debug\n * the agent does not read. A report whose whole purpose is telling a caller what went wrong and how to\n * fix it is the last thing that belongs on the ignored stream. This does not muddy the payload: a verb\n * either succeeds and writes its result or fails and writes its error, never both, so the exit code\n * tells the two apart before anything is parsed.\n *\n * Three things every error carries, and they are not decoration:\n * - a **stable `code`** a script matches on, so one failure mode is told from another without parsing\n * prose (`no-mux` is not `pane-not-found` is not `ambiguous-pane`);\n * - a **`help`** line naming THIS CLI's command that fixes it — never \"see --help\", and never a\n * dependency's own name: an agent handed a raw tmux/herdr diagnostic cannot act on it through\n * cyber-mux, so a backend's text is TRANSLATED here rather than forwarded;\n * - an **`exit`** code that separates a usage error (2 — a missing or malformed argument, whose fix is\n * a different invocation) from a genuine operation failure (1).\n */\nexport class CliError extends Error {\n\tconstructor(\n\t\treadonly code: string,\n\t\tmessage: string,\n\t\treadonly help: string,\n\t\treadonly exit: 1 | 2,\n\t\t/** Extra structured fields the JSON form carries beside code/message/help — e.g. an ambiguity's\n\t\t * candidates. Never free-text; a machine reads these. */\n\t\treadonly extra?: Record<string, unknown> | undefined,\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'CliError'\n\t}\n}\n\n/** The stable code the ambiguity error carries, in both formats — what a caller matches on. */\nexport const AMBIGUOUS_CODE = 'ambiguous-pane'\n\n/** One candidate of an ambiguous locator: what tells it apart, and what retries it. */\nexport interface PaneCandidate {\n\tid: string\n\tlabel: string | null\n\tcwd: string | null\n}\n\n/**\n * An ambiguous locator — a `CliError` like any other, so the one renderer and the one verb-boundary\n * catch handle it with no special case, and so a caller sees the same `{ code, help, exit }` shape it\n * sees for every other failure.\n *\n * It is THROWN rather than reported where it is found: reporting in place would mean exiting from\n * inside `resolveTarget`, and a verb's own catch-all could then flatten an exit-2 ambiguity into an\n * exit-1 generic failure behind its back. A typed error is what makes the ambiguity visible to every\n * catch it passes through, so each one rethrows it deliberately instead of swallowing it by accident.\n *\n * Each candidate carries its id, its label and its cwd: the id is the RETRY — paste it back and the\n * ambiguity is gone, since an id outranks every name — and the cwd is what actually tells three panes\n * all labeled `worker` apart.\n */\nexport class AmbiguousPaneError extends CliError {\n\tconstructor(\n\t\treadonly locator: string,\n\t\treadonly candidates: PaneCandidate[],\n\t) {\n\t\tsuper(\n\t\t\tAMBIGUOUS_CODE,\n\t\t\t`\"${locator}\" matches ${candidates.length} panes — an id resolves it`,\n\t\t\t`retry with one of the ids: ${candidates.map((c) => c.id).join(' ')}`,\n\t\t\t2,\n\t\t\t{ candidates },\n\t\t)\n\t\tthis.name = 'AmbiguousPaneError'\n\t}\n}\n\n/** The stable code a missing-pane usage error carries — the same code FAMILY as the ambiguity: both\n * are exit-2 usage errors whose fix is a different pane argument, and both hand the caller the live\n * panes to retry with rather than sending them on a second round trip. */\nexport const MISSING_PANE_CODE = 'missing-pane'\n\n/**\n * A pane verb invoked with no `<pane>` at all — a usage error (exit 2), the same shape the ambiguity\n * uses. The old \"having called no backend\" guarantee is deliberately gone (CR 95): the backend IS\n * queried so the live panes can be listed as candidates, since the caller's deterministic next move\n * after \"missing pane\" is `cyber-mux list`. Folding that answer into the error collapses a two-turn\n * correction into one, exactly as the ambiguity report already does.\n *\n * Carries its `candidates` in `extra` under the same key `AmbiguousPaneError` uses, so the one\n * renderer prints them `<id> <label> <cwd>` with no special case. When the backend could NOT be\n * enumerated the list is empty and the help points at `cyber-mux list` instead of the ids.\n */\nexport class MissingPaneError extends CliError {\n\tconstructor(readonly candidates: PaneCandidate[]) {\n\t\tsuper(\n\t\t\tMISSING_PANE_CODE,\n\t\t\t'no pane given — this command needs a target pane',\n\t\t\tcandidates.length > 0\n\t\t\t\t? `pass one of the ids below: ${candidates.map((c) => c.id).join(' ')}`\n\t\t\t\t: 'list the live panes with: cyber-mux list',\n\t\t\t2,\n\t\t\t{ candidates },\n\t\t)\n\t\tthis.name = 'MissingPaneError'\n\t}\n}\n\n/**\n * The ONE renderer — every coded failure reaches stdout through here, and exits.\n *\n * `--format json` emits the machine form: a single `{ error: { code, message, help, ...extra } }`\n * object, the stable code first, no free-text prose beside it. The readable form leads its human line\n * with the same `code` token a script branches on — so a person scanning the terminal sees exactly\n * what a `--format json` consumer matches on — then the `help` line, then (for an ambiguity) one line\n * per candidate: `<id> <label> <cwd>`, the id-first shape whose first column is the retry.\n */\nexport function reportError(e: CliError): never {\n\tif (isJsonOutput()) {\n\t\tconsole.log(JSON.stringify({ error: { code: e.code, message: e.message, help: e.help, ...e.extra } }, null, 2))\n\t} else {\n\t\t// The code leads the human line too: the stable token is the point of the whole surface, so it\n\t\t// belongs where a person reads as much as where a script matches — not hidden in the JSON alone.\n\t\tconsole.log(`error: ${e.code}: ${e.message}`)\n\t\tconsole.log(`help: ${e.help}`)\n\t\tconst candidates = e.extra?.['candidates'] as PaneCandidate[] | undefined\n\t\tif (candidates) {\n\t\t\tfor (const c of candidates) console.log(` ${c.id} ${c.label ?? ''} ${c.cwd ?? ''}`)\n\t\t}\n\t}\n\tprocess.exit(e.exit)\n}\n","import { InvalidArgumentError, Option } from 'commander'\n\n/** Output format shared by every command: `text` (human), `json`, or `agent`. */\nexport const FORMAT_OPTION: Option = new Option('--format <format>', 'Output format').choices(['text', 'json', 'agent'])\n\n/**\n * Accumulate one `--env KEY=VALUE` into the running map. Repeatable: commander calls this once per\n * flag, threading the previous map through, so `--env A=1 --env B=2` collects both. Rejecting a\n * malformed pair from HERE — the parser, before the action runs — is what makes \"rejected before any\n * side effect\" hold on every verb, worktree-creating ones included. The KEY is everything before the\n * first `=`, the VALUE everything after it: a value may contain `=` (a URL query, a base64 pad) and a\n * KEY may not, so the first `=` is the only unambiguous split. A missing `=` is malformed; a present\n * `=` with nothing after it is a deliberate empty value, not an error.\n */\nfunction collectEnv(pair: string, previous: Record<string, string> = {}): Record<string, string> {\n\tconst eq = pair.indexOf('=')\n\tif (eq <= 0) throw new InvalidArgumentError(`expected KEY=VALUE, got \"${pair}\"`)\n\treturn { ...previous, [pair.slice(0, eq)]: pair.slice(eq + 1) }\n}\n\n/**\n * `--env KEY=VALUE`, repeatable — the CLI door to the seam's env option, on every verb that opens a\n * pane. One shared Option so the collector, the split rule, and the rejection are defined once and\n * every verb inherits them, the way `AT_OPTION`/`LABEL_OPTION` are shared. Conflicts with `--template`,\n * whose template owns its own panes' env; the two verbs that carry `--template` refuse the pair.\n */\nexport const ENV_OPTION: Option = new Option('--env <pair>', 'Environment variable KEY=VALUE (repeatable)')\n\t.argParser(collectEnv)\n\t.conflicts('template')\n\n/** Placement for a newly opened pane, matching `MuxPlacement`. */\nexport const AT_OPTION: Option = new Option('--at <placement>', 'Where to place the new pane').choices([\n\t'pane:right',\n\t'pane:down',\n\t'tab',\n\t'workspace',\n])\n\n/**\n * Name for whatever `--at` opens. Host-neutral because every backend names every tier: on herdr a\n * workspace/tab/pane label, on tmux a window name (where `workspace` and `tab` both collapse to a\n * Window) or a pane title.\n */\nexport const LABEL_OPTION: Option = new Option('--label <label>', 'Name for the opened workspace/tab/pane')\n","import { createInterface } from 'node:readline/promises'\n\n/**\n * The interactive seam — a line asked of a human, injected for exactly the reason `Exec` and\n * `TemplateStore` are: `template edit` is a conversation, and a conversation reaching for\n * `process.stdin` directly would make it the one verb `cli.test.ts` cannot drive.\n *\n * **This is the package's first async seam, and deliberately its narrowest.** `Exec` is synchronous\n * by construction and every adapter is built on that; nothing here changes it. A prompt cannot be\n * synchronous, so it gets its own seam rather than widening that one — no adapter, no backend and no\n * pure module ever sees this type, and the async reaches exactly one command's action.\n */\nexport interface Prompt {\n\t/**\n\t * Ask one question and resolve to the line typed.\n\t *\n\t * `undefined` means the human is GONE — EOF, a closed stream, Ctrl-D — and is a distinct answer\n\t * from `''` (they pressed Enter). The caller must stop asking on `undefined`; continuing would\n\t * spin through every remaining question against a dead stream.\n\t *\n\t * `initial` is pre-filled into the editable line, so answering \"the same but one flag different\"\n\t * is an edit rather than a retype. Best-effort: a stream that cannot pre-fill still asks.\n\t */\n\task(question: string, initial?: string): Promise<string | undefined>\n\t/** Release the terminal. Safe to call twice; the caller does so in a `finally`. */\n\tclose(): void\n}\n\n/**\n * Opening a prompt is a FACTORY rather than a live `Prompt` on `Deps`, and that is load-bearing: a\n * readline interface holds stdin open from the moment it exists, so building one at program-assembly\n * time would make every unrelated verb — `list`, `doctor`, `send` — hang instead of exiting. Only the\n * command that actually converses calls this.\n */\nexport type OpenPrompt = () => Prompt\n\nexport const realPrompt: OpenPrompt = () => {\n\tconst rl = createInterface({ input: process.stdin, output: process.stdout })\n\t// Latched rather than checked per-question: once the stream is gone it stays gone, and a flag read\n\t// before each `question` is what keeps a walk from issuing N doomed reads after the first EOF.\n\tlet closed = false\n\trl.on('close', () => {\n\t\tclosed = true\n\t})\n\treturn {\n\t\tasync ask(question, initial) {\n\t\t\tif (closed) return undefined\n\t\t\t// Raced against `close` because readline's own question promise never settles on Ctrl-D — it\n\t\t\t// emits `close` and leaves the caller awaiting forever. Whichever lands first wins, so an EOF\n\t\t\t// mid-question surfaces as `undefined` rather than a hung CLI.\n\t\t\treturn await new Promise<string | undefined>((resolve) => {\n\t\t\t\tlet settled = false\n\t\t\t\tconst settle = (value: string | undefined) => {\n\t\t\t\t\tif (settled) return\n\t\t\t\t\tsettled = true\n\t\t\t\t\trl.off('close', onClose)\n\t\t\t\t\tresolve(value)\n\t\t\t\t}\n\t\t\t\tconst onClose = () => settle(undefined)\n\t\t\t\trl.once('close', onClose)\n\t\t\t\trl.question(question).then(settle, () => settle(undefined))\n\t\t\t\t// AFTER `question`, which is what puts the text in the editable line rather than printing it.\n\t\t\t\tif (initial) rl.write(initial)\n\t\t\t})\n\t\t},\n\t\tclose: () => rl.close(),\n\t}\n}\n","import { relative, sep } from 'node:path'\nimport type { Exec } from './exec.ts'\nimport type { MuxAdapter, MuxTarget, PaneRect, RegionPane, WorkspaceTab } from './mux.ts'\nimport type { PaneNode, SplitNode, TabNode, Template, TemplateNode } from './template.ts'\n\n/**\n * A live region, run backwards into a template — `template save`. PURE, like `template.ts` and for the\n * same reason: the hard part here is geometry, not I/O, and keeping every seam out means the n-ary\n * lowering, the ratio arithmetic and the ambiguous-grid rule are all testable with plain numbers and\n * no multiplexer at all.\n *\n * This is `desugar`'s inverse, and the fact that both directions land on the same canonical tree —\n * the right-comb — is the evidence the schema is coherent rather than arbitrary. Exporting a region\n * that `arrange: even-horizontal` built gives back that comb, ratios and all.\n *\n * **What it recovers, and what it cannot.** Geometry, labels and dirs. NEVER commands — and the\n * reason is portability, not availability. A backend CAN often say what is running: herdr's\n * `pane process-info` hands back full argv for a pane's whole foreground tree, and `/proc` gets there\n * from a pid on any backend. What none of them can give back is a command worth writing into a\n * template, because what they report is the RESOLVED command line, not the one a human typed:\n * `nr web dev` comes back as `node /run/user/1000/fnm_multishells/4223_1784479278417/bin/nr web dev`,\n * a path carrying a uid, a pid and a timestamp that is dead on the next machine and often on the next\n * login. An idle pane reports its shell, and a `claude` pane reports exactly `claude` with the flags\n * that made it that session already gone.\n *\n * A template is a statement about how a project is worked on, meant to be checked in and run\n * elsewhere; a machine-local argv is the opposite of that, and `apply` SUBMITS whatever `command`\n * says, so a wrong one fails by executing something. Absent beats wrong here, exactly as it does for\n * a pane's `label`. A template out of this module is a DRAFT with `command` left for the author.\n */\n\n/** A partition of the region — the same shape as `TemplateNode`, before panes become `PaneNode`s. */\ntype RegionTree = RegionLeaf | RegionSplit\n\ninterface RegionLeaf {\n\ttype: 'pane'\n\tpane: RegionPane\n}\n\ninterface RegionSplit {\n\ttype: 'split'\n\tdirection: 'right' | 'down'\n\tratio?: number | undefined\n\tfirst: RegionTree\n\tsecond: RegionTree\n}\n\nexport interface TemplateCapture {\n\ttemplate: Template\n\t/**\n\t * What the capture could not express, for the caller to print. Returned rather than written to\n\t * stderr so this module stays pure and the rules stay testable without capturing output.\n\t */\n\twarnings: string[]\n}\n\nconst right = (rect: PaneRect): number => rect.x + rect.width\nconst bottom = (rect: PaneRect): number => rect.y + rect.height\n\n/**\n * The axis a cut runs along. `right` means a vertical divider with panes side by side — the schema's\n * vocabulary, where the name says where the NEW pane goes rather than which way the divider lies.\n */\ninterface Axis {\n\tdirection: 'right' | 'down'\n\t/** Where a pane starts on this axis. */\n\tstart: (rect: PaneRect) => number\n\t/** Where a pane ends on this axis. */\n\tend: (rect: PaneRect) => number\n}\n\nconst HORIZONTAL: Axis = { direction: 'right', start: (r) => r.x, end: right }\nconst VERTICAL: Axis = { direction: 'down', start: (r) => r.y, end: bottom }\n\ninterface Cut {\n\tdirection: 'right' | 'down'\n\tratio: number\n\tfirst: RegionPane[]\n\tsecond: RegionPane[]\n}\n\n/**\n * The lowest cut on this axis that separates the panes cleanly, or `undefined` if none does.\n *\n * Taking the LOWEST rather than any is what produces a right-comb for an n-ary row: three panes side\n * by side cut first into `[a][b c]`, then `[b][c]` — the exact tree `desugar`'s `comb` emits for\n * `arrange: even-horizontal`, reached from the opposite direction.\n *\n * A candidate is any pane's start edge. It separates cleanly when every pane lies wholly before it\n * or wholly after it, and both sides have something in them.\n */\nfunction findCut(panes: RegionPane[], axis: Axis): Cut | undefined {\n\tconst candidates = [...new Set(panes.map((p) => axis.start(p.rect)))].sort((a, b) => a - b)\n\tfor (const at of candidates) {\n\t\tconst first = panes.filter((p) => axis.end(p.rect) <= at)\n\t\tconst second = panes.filter((p) => axis.start(p.rect) >= at)\n\t\tif (first.length === 0 || second.length === 0) continue\n\t\t// Anything straddling the line lands in neither group, so the counts not adding up IS the\n\t\t// \"this cut crosses a pane\" test — no separate overlap check needed.\n\t\tif (first.length + second.length !== panes.length) continue\n\t\treturn { direction: axis.direction, ratio: ratioOf(panes, second, axis), first, second }\n\t}\n\treturn undefined\n}\n\n/**\n * The fraction of the split region kept by `first` — the schema's `ratio`.\n *\n * Measured as the COMPLEMENT of what `second` occupies, over the whole region: `1 - second/total`.\n * The obvious `first / (first + second)` is subtly wrong on any backend that draws a divider, and\n * the arithmetic says why — tmux splitting a 50-row region reports 34 + 15, with the 51st row eaten\n * by the divider. `first / (first + second)` reads 34/49 = 0.69; the true split was 0.7, and the\n * divider row belongs to neither pane's height while still costing the region a row.\n *\n * Taking the complement puts that row back where the backend's own arithmetic puts it: tmux's `-l`\n * sizes the NEW pane, so `second` is exactly the fraction asked for and `first` keeps the rest,\n * divider included. That reads 1 - 15/50 = 0.7 — the number the split was actually made with. On a\n * backend with no divider (herdr) the two formulas agree, so nothing is traded for the fix.\n *\n * Both checked against live binaries: this recovers tmux's `-l 40%`/`-l 30%` splits as 0.6/0.7\n * exactly, and reproduces herdr's to within the cell it rounds to.\n */\nfunction ratioOf(all: RegionPane[], second: RegionPane[], axis: Axis): number {\n\tconst total = extent(all, axis)\n\tif (total <= 0) return 0.5\n\treturn 1 - extent(second, axis) / total\n}\n\n/** How far a group of panes reaches along an axis — its bounding box on that axis. */\nfunction extent(panes: RegionPane[], axis: Axis): number {\n\tconst starts = panes.map((p) => axis.start(p.rect))\n\tconst ends = panes.map((p) => axis.end(p.rect))\n\treturn Math.max(...ends) - Math.min(...starts)\n}\n\n/**\n * Cut the region into a binary tree, recursively.\n *\n * **`right` is tried before `down`, and the order is load-bearing on a grid.** A 2x2 is genuinely\n * ambiguous — cutting it vertically first and horizontally first both describe the same screen, and\n * neither is more true. Columns-then-rows is the tie-break because that is what `desugar`'s `tiled`\n * emits, so a tiled pool exports back as the tree it was built from rather than its transpose.\n *\n * A region no cut separates cannot come out of a multiplexer: both backends build regions BY\n * splitting, so every region they can report is guillotine-cuttable by construction. Reaching the\n * throw means the geometry did not come from where we think it did — which is worth saying loudly\n * rather than papering over with a tree that misplaces the user's panes.\n */\nfunction partition(panes: RegionPane[]): RegionTree {\n\tif (panes.length === 1) return { type: 'pane', pane: panes[0]! }\n\tconst cut = findCut(panes, HORIZONTAL) ?? findCut(panes, VERTICAL)\n\tif (!cut) {\n\t\tthrow new Error(\n\t\t\t`this region's panes do not form a splittable tree (${panes.length} panes: ${panes.map((p) => p.id).join(', ')}) — ` +\n\t\t\t\t'export can only capture a region built by splitting',\n\t\t)\n\t}\n\tconst node: RegionSplit = {\n\t\ttype: 'split',\n\t\tdirection: cut.direction,\n\t\tfirst: partition(cut.first),\n\t\tsecond: partition(cut.second),\n\t}\n\tconst ratio = roundRatio(cut.ratio)\n\t// An even split is the schema's DEFAULT, so an even cut emits no ratio at all rather than `0.5`.\n\t// Keeps an exported grid as clean as the hand-written one it should match.\n\tif (ratio !== 0.5) node.ratio = ratio\n\treturn node\n}\n\n/**\n * Two decimals, and clamped strictly inside `(0, 1)`.\n *\n * Two because the emitted template is meant to be READ and edited: a 3-pane row wants `0.33`, not\n * `0.33167`, and the cell it costs is invisible. The clamp is the guard on a degenerate capture — a\n * pane one cell wide in a wide region rounds to `0`, which `validateTemplate` rejects outright, so an\n * export of a real screen would emit a template that fails its own validator.\n */\nfunction roundRatio(ratio: number): number {\n\tconst rounded = Math.round(ratio * 100) / 100\n\treturn Math.min(0.99, Math.max(0.01, rounded))\n}\n\n/**\n * The `dir` a pane's cwd becomes: relative to the root, or `undefined` when it IS the root or sits\n * outside it. Apply's injection run backwards — apply joins `cwd + dir`, so export subtracts.\n *\n * The schema forbids `cwd` outright, so a pane outside the root has nowhere to put its location and\n * genuinely loses it. That is reported as a warning rather than dropped in silence, and never\n * emitted as a `..` path: `dir` must stay under the apply-time target, so a template that escaped it\n * would fail validation on the way back in.\n */\nfunction toDir(\n\tpaneCwd: string | undefined,\n\trootCwd: string | undefined,\n): { dir?: string | undefined; outside: boolean } {\n\tif (!paneCwd || !rootCwd) return { outside: false }\n\tconst rel = relative(rootCwd, paneCwd)\n\tif (rel === '') return { outside: false }\n\tif (rel.startsWith('..') || rel.split(sep).includes('..')) return { outside: true }\n\treturn { dir: rel, outside: false }\n}\n\n/** The pane sitting on the region's own root — follow `first` down, exactly as `firstPane` does. */\nfunction rootOf(tree: RegionTree): RegionPane {\n\treturn tree.type === 'pane' ? tree.pane : rootOf(tree.first)\n}\n\nexport interface CaptureTemplateOptions {\n\t/** The template's `name` — validated by the caller, since a name is also a lookup key. */\n\tname: string\n\tdescription?: string | undefined\n}\n\n/**\n * Capture a region into a template.\n *\n * The root pane's cwd becomes the template's implicit target — every other pane's `dir` is measured\n * from it — because that is precisely what apply injects `--cwd` as. A pane elsewhere on the disk\n * cannot be expressed and says so in `warnings`.\n */\nexport function captureTemplate(panes: RegionPane[], opts: CaptureTemplateOptions): TemplateCapture {\n\tif (panes.length === 0) throw new Error('a capture needs at least one pane — this region reported none')\n\tconst tree = partition(panes)\n\tconst ctx = context(rootOf(tree).cwd)\n\tconst template = shell(opts)\n\ttemplate.root = convert(tree, ctx)\n\treturn { template, warnings: ctx.warnings }\n}\n\n/**\n * Capture a whole workspace into a `tabs` template — the exact inverse of the tabs walk, and\n * `captureTemplate` one level up rather than a second derivation: each tab's tree comes off the SAME\n * `partition`, because a tab is a region and the geometry rules cannot depend on how many of them\n * there are.\n *\n * One thing is workspace-WIDE rather than per-tab, and it follows from what the schema already says:\n * the target is the FIRST tab's root pane, because that is the pane apply's `--cwd` opens the\n * workspace at, so every tab's `dir` is measured from that one root.\n */\nexport function captureWorkspaceTemplate(tabs: WorkspaceTab[], opts: CaptureTemplateOptions): TemplateCapture {\n\tif (tabs.length === 0) throw new Error('a workspace capture needs at least one tab — this workspace reported none')\n\tconst trees = tabs.map((tab) => {\n\t\tif (tab.panes.length === 0) {\n\t\t\tthrow new Error(`a capture needs at least one pane — tab ${tab.id} reported none`)\n\t\t}\n\t\treturn partition(tab.panes)\n\t})\n\tconst ctx = context(rootOf(trees[0]!).cwd)\n\tconst template = shell(opts)\n\ttemplate.tabs = tabs.map((tab, index) => {\n\t\tconst node: TabNode = {}\n\t\t// The label the tab carries, verbatim — never a workspace parsed back out of it. On a backend\n\t\t// with no workspace tier this is the composed `<workspace> - <tab>` the walk wrote, and\n\t\t// `acme - beta - main` reads as two different groupings under every split rule, so recovering one\n\t\t// is guessing. The grouping came from the tag; this is a human's to read and to fix up by hand.\n\t\tif (tab.label) node.label = tab.label\n\t\tnode.root = convert(trees[index]!, ctx)\n\t\treturn node\n\t})\n\treturn { template, warnings: ctx.warnings }\n}\n\n/** The template every capture starts from — the fields that owe nothing to the geometry. */\nfunction shell(opts: CaptureTemplateOptions): Template {\n\tconst template: Template = { name: opts.name }\n\tif (opts.description) template.description = opts.description\n\treturn template\n}\n\n/**\n * What converting a tree needs to know that the tree itself does not carry: the target the `dir`s are\n * measured from, and somewhere to say what could not be expressed.\n *\n * Shared by both captures deliberately — a workspace's `dir`s are measured from ONE root, so threading\n * one context through every tab is what makes them so.\n */\ninterface CaptureContext {\n\trootCwd: string | undefined\n\twarnings: string[]\n}\n\nfunction context(rootCwd: string | undefined): CaptureContext {\n\treturn { rootCwd, warnings: [] }\n}\n\nfunction toPaneNode(pane: RegionPane, ctx: CaptureContext): PaneNode {\n\tconst node: PaneNode = { type: 'pane' }\n\t// A label two panes share is captured onto BOTH, verbatim. It got there because a human renamed the\n\t// pane by hand, which is the exact fact this capture exists to preserve — dropping it would report\n\t// \"no label\" where there is one, against the absent-rather-than-false rule the rest of this node\n\t// follows. Nothing keys on a label, so a shared one is a name two panes have, not a collision.\n\tif (pane.label) node.label = pane.label\n\tconst { dir, outside } = toDir(pane.cwd, ctx.rootCwd)\n\tif (dir) node.dir = dir\n\tif (outside) {\n\t\tctx.warnings.push(\n\t\t\t`pane ${pane.id}${pane.label ? ` (\"${pane.label}\")` : ''} runs in ${pane.cwd}, which is not under the ` +\n\t\t\t\t`captured root ${ctx.rootCwd} — a template cannot pin a directory, so this pane is captured without one`,\n\t\t)\n\t}\n\treturn node\n}\n\n/**\n * A partition into schema nodes. `command` is never emitted and there is no branch here that could\n * emit one: what a backend can report about a running pane is a resolved, machine-local command line\n * rather than a portable one (the module doc has the why), so a capture at any tier is a DRAFT with\n * `command` left for the author.\n */\nfunction convert(node: RegionTree, ctx: CaptureContext): TemplateNode {\n\tif (node.type === 'pane') return toPaneNode(node.pane, ctx)\n\tconst split: SplitNode = {\n\t\ttype: 'split',\n\t\tdirection: node.direction,\n\t\tfirst: convert(node.first, ctx),\n\t\tsecond: convert(node.second, ctx),\n\t}\n\tif (node.ratio !== undefined) split.ratio = node.ratio\n\treturn split\n}\n\n/**\n * A capture asked of a backend that lacks the optional geometry seam it needs — no `describeRegion`\n * for a region capture, no `describeWorkspace` for a `--workspace` one. An absent optional seam member\n * is a refusal, never a guess: a backend that cannot answer cannot be captured and there is nothing to\n * degrade to.\n *\n * PORTABLE and exit-code-free by design. The DECISION to refuse is the library's and lives here, at\n * the one place that sees the adapter — the pure `captureTemplate` above takes rectangles already read\n * and could never make it. How the refusal SURFACES — the exit code, the fix hint, the exact sentence\n * — is the CLI's, which catches this and re-raises its own `backend-unsupported` error. `capability`\n * names which seam was missing so the caller composes the right message without re-deriving it, and\n * the terse `message` is a factual log line, not the user-facing copy.\n */\nexport class CaptureUnsupportedError extends Error {\n\tconstructor(\n\t\treadonly backend: string,\n\t\treadonly capability: 'region' | 'workspace',\n\t) {\n\t\tsuper(\n\t\t\tcapability === 'region'\n\t\t\t\t? `${backend} cannot report a region's geometry`\n\t\t\t\t: `${backend} cannot enumerate a workspace's tabs`,\n\t\t)\n\t\tthis.name = 'CaptureUnsupportedError'\n\t}\n}\n\n/**\n * Read the live region around `target` through the adapter and derive its template — the\n * surface-independent orchestrator `template save` drives, and the single home of the region-capture\n * refusal. The optional `regions` seam is where a backend says whether it can report geometry at all;\n * a backend without `describeRegion` is refused HERE (`CaptureUnsupportedError`), before any read,\n * because the pure `captureTemplate` it would feed cannot see the adapter and so cannot make that\n * call. A backend that CAN report reads its region and hands the rectangles to the pure capture\n * unchanged.\n */\nexport function deriveRegionCapture(\n\tadapter: MuxAdapter,\n\texec: Exec,\n\ttarget: MuxTarget,\n\topts: CaptureTemplateOptions,\n): TemplateCapture {\n\tconst describeRegion = adapter.regions?.describeRegion\n\tif (!describeRegion) throw new CaptureUnsupportedError(adapter.name, 'region')\n\treturn captureTemplate(describeRegion(exec, target), opts)\n}\n\n/**\n * Read every tab of the workspace `target` sits in through the adapter and derive a `tabs` template —\n * the `--workspace` orchestrator, and the single home of the workspace-capture refusal. Same shape as\n * `deriveRegionCapture`, one member over: a backend without `describeWorkspace` cannot enumerate a\n * workspace's tabs and is refused HERE (`CaptureUnsupportedError`), before any read.\n */\nexport function deriveWorkspaceCapture(\n\tadapter: MuxAdapter,\n\texec: Exec,\n\ttarget: MuxTarget,\n\topts: CaptureTemplateOptions,\n): TemplateCapture {\n\tconst describeWorkspace = adapter.regions?.describeWorkspace\n\tif (!describeWorkspace) throw new CaptureUnsupportedError(adapter.name, 'workspace')\n\treturn captureWorkspaceTemplate(describeWorkspace(exec, target), opts)\n}\n","import {\n\tcollectPanes,\n\ttype FlatPane,\n\tresolveTree,\n\ttype TabNode,\n\ttype Template,\n\ttype TemplateNode,\n\ttype TemplateTree,\n} from './template.ts'\n\n/**\n * The edit plan behind `template edit` — what to ask about, and where each answer goes back. PURE,\n * like `template.ts` and `template-capture.ts` and for the same reason: the hard part is addressing a\n * pane inside two different spellings of the same tree, and keeping every seam out means that\n * addressing is testable with plain objects and no terminal at all.\n *\n * **This is why the prompting lives in `cli.ts` and not here.** A guided edit is a conversation, which\n * is inherently stateful and async; the decision of WHAT to ask and WHERE to put the answer is\n * neither. Splitting them at that line keeps the whole interesting half hermetic — every rule below\n * is pinned by a unit test that never opens stdin.\n *\n * **The one rule that shapes everything: a template's SPELLING survives the edit.** A template says\n * its geometry either as an explicit `root` tree or as the flat `panes` + `arrange` sugar, and those\n * are not interchangeable to the human who wrote one. The obvious implementation — desugar, edit the\n * tree, write the tree back — would silently rewrite a hand-written 4-line flat template into a\n * nested `split` tree nobody wants to read. So both `planEdits` and `applyEdits` walk the SOURCE\n * shape and never call `resolveTree`, and a flat template comes back out flat.\n */\n\n/** A field a guided edit can fill. `command` is the reason this verb exists — a capture lands with\n * none (see `template-capture.ts`) — but the addressing is field-agnostic, so adding one later is a\n * new member here and nothing else. */\nexport type EditField = 'command' | 'label'\n\n/**\n * One pane, as something to ask about: where it lives, and what it says now.\n *\n * `index` is the pane's ordinal in APPLY order — `collectPanes`'s depth-first `first`-before-`second`\n * walk, which is the order the manifest reports and commands submit in (`template-session.ts`'s\n * `ordered`). That is deliberate rather than convenient: the number this prompt shows the author has\n * to be the number they see in the manifest afterwards, or the two views name different panes.\n */\nexport interface EditSlot {\n\t/** Which tab, for a `tabs` template; absent for a single-region one. */\n\ttab?: number\n\t/** The tab's own label, carried so a prompt can show it without re-walking the template. */\n\ttabLabel?: string | undefined\n\t/** Ordinal within this tab, in apply order. */\n\tindex: number\n\t/**\n\t * Where the pane sits on screen, in words — `top-left`, `right`, `center`.\n\t *\n\t * The one thing that actually answers \"which pane am I being asked about?\", which an ordinal and a\n\t * label cannot: apply order is a tree walk, not a reading order, so pane 2 of a 2x2 is the pane\n\t * BELOW pane 1 rather than the one beside it. Absent when the tab holds one pane (there is nothing\n\t * to tell apart) or when the geometry cannot be resolved.\n\t */\n\tposition?: string\n\tlabel?: string\n\tdir?: string\n\tcommand?: string\n}\n\n/** A pane's share of its tab, as fractions of the whole — the unit square, never cells. */\nexport interface UnitRect {\n\tx: number\n\ty: number\n\twidth: number\n\theight: number\n}\n\n/**\n * One answer, addressed back to the slot it came from.\n *\n * `value: undefined` CLEARS the field rather than meaning \"no answer\" — a slot the author left alone\n * yields no `EditAnswer` at all. Keeping \"unset it\" and \"did not say\" as different things is what\n * lets `applyEdits` be a total function of its answers: it never has to guess whether an absent\n * value meant erase or skip.\n */\nexport interface EditAnswer {\n\ttab?: number\n\tindex: number\n\tfield: EditField\n\tvalue: string | undefined\n}\n\n/**\n * A tree's panes in apply order, as references INTO the template.\n *\n * The two spellings converge here and nowhere else. For the flat sugar the panes are already a list\n * in the order `desugar` lays them out — both `comb` and `tiled` slice contiguously and preserve\n * order, so the array index IS the apply ordinal (pinned by a test, since that is a property of\n * `desugar` this module depends on rather than one it owns). For the explicit tree it is\n * `collectPanes` on `root`, which is the very walk apply uses.\n *\n * Returning references is the whole trick: `applyEdits` clones the template first, then mutates\n * what this hands back, so a write lands in the clone's own `panes[]` or `root` subtree without this\n * module ever knowing which spelling it was.\n */\nfunction treePanes(tree: TemplateTree): FlatPane[] {\n\tif (tree.root) return collectPanes(tree.root)\n\treturn tree.panes ?? []\n}\n\n/**\n * Where every pane in a tree lands, as fractions of the tab — the geometry a template DETERMINES,\n * computed the same way apply builds it.\n *\n * `ratio` is the fraction kept by `first` (the original pane), so a `right` split at 0.6 puts `first`\n * in the left 60% and `second` in what is left. Splitting the remainder rather than multiplying by\n * `1 - ratio` is what keeps a comb exact: three even panes come out at exactly 1/3 each instead of\n * drifting on the last one.\n *\n * Unit fractions rather than cells because a template has no size — it is applied to whatever region\n * it is given, and the only honest thing to say is a proportion.\n */\nfunction layout(node: TemplateNode, rect: UnitRect, acc: UnitRect[] = []): UnitRect[] {\n\tif (node.type === 'pane') {\n\t\tacc.push(rect)\n\t\treturn acc\n\t}\n\tconst ratio = node.ratio ?? 0.5\n\tif (node.direction === 'right') {\n\t\tconst width = rect.width * ratio\n\t\tlayout(node.first, { ...rect, width }, acc)\n\t\tlayout(node.second, { ...rect, x: rect.x + width, width: rect.width - width }, acc)\n\t} else {\n\t\tconst height = rect.height * ratio\n\t\tlayout(node.first, { ...rect, height }, acc)\n\t\tlayout(node.second, { ...rect, y: rect.y + height, height: rect.height - height }, acc)\n\t}\n\treturn acc\n}\n\n/**\n * A rect in words, from where its CENTER falls on a 3x3 grid.\n *\n * Thirds rather than halves because halves cannot name a middle: a row of three panes would come out\n * `left`, `left`, `right`, which is worse than saying nothing. Reading the center rather than the\n * edges is what makes an uneven split still land in the band a human would point at — a pane taking\n * the left 60% is `left`, not straddling.\n *\n * Deliberately coarse. This is a hint that tells two panes apart on one screen, not a coordinate; a\n * template with a dozen panes will repeat a word, and the ordinal is still what identifies a pane.\n */\nexport function describePosition(rect: UnitRect): string {\n\tconst column = band(rect.x + rect.width / 2, 'left', 'center', 'right')\n\tconst row = band(rect.y + rect.height / 2, 'top', 'middle', 'bottom')\n\tif (row === 'middle') return column === 'center' ? 'center' : column\n\tif (column === 'center') return row\n\treturn `${row}-${column}`\n}\n\nfunction band(center: number, low: string, mid: string, high: string): string {\n\tif (center < 1 / 3) return low\n\tif (center > 2 / 3) return high\n\treturn mid\n}\n\n/**\n * Each pane's position, in apply order — or nothing at all.\n *\n * Empty for a single-pane tree, because \"center\" said of the only pane is noise rather than a\n * bearing. Empty too when the tree cannot be resolved: this is a display hint, and a template\n * malformed enough to defeat `resolveTree` should still be walkable rather than refused HERE, where\n * the error would name the wrong thing. Validation is the caller's job and already ran.\n */\nfunction positionsOf(tree: Template | TabNode): string[] {\n\tlet rects: UnitRect[]\n\ttry {\n\t\trects = layout(resolveTree(tree), { x: 0, y: 0, width: 1, height: 1 })\n\t} catch {\n\t\treturn []\n\t}\n\treturn rects.length < 2 ? [] : rects.map(describePosition)\n}\n\n/**\n * Every pane worth asking about, in the order a walk should ask.\n *\n * Tabs in order, panes within each tab in apply order — the same traversal `walkTabs` submits\n * commands in, so an author filling this top to bottom is filling it in the order it will run.\n */\nexport function planEdits(template: Template): EditSlot[] {\n\tconst slots: EditSlot[] = []\n\tif (template.tabs) {\n\t\ttemplate.tabs.forEach((tab, index) => {\n\t\t\tconst positions = positionsOf(tab)\n\t\t\tfor (const [ordinal, pane] of treePanes(tab).entries()) {\n\t\t\t\tslots.push({ tab: index, tabLabel: tab.label, index: ordinal, ...at(positions, ordinal), ...fields(pane) })\n\t\t\t}\n\t\t})\n\t\treturn slots\n\t}\n\tconst positions = positionsOf(template)\n\tfor (const [ordinal, pane] of treePanes(template).entries()) {\n\t\tslots.push({ index: ordinal, ...at(positions, ordinal), ...fields(pane) })\n\t}\n\treturn slots\n}\n\n/** A position when there is one — absent rather than an empty string, like every other slot field. */\nfunction at(positions: string[], ordinal: number): { position?: string } {\n\tconst position = positions[ordinal]\n\treturn position ? { position } : {}\n}\n\n/** What a slot reports about a pane — the fields a prompt shows, never the pane object itself. */\nfunction fields(pane: FlatPane): Pick<EditSlot, 'label' | 'dir' | 'command'> {\n\tconst out: Pick<EditSlot, 'label' | 'dir' | 'command'> = {}\n\tif (pane.label !== undefined) out.label = pane.label\n\tif (pane.dir !== undefined) out.dir = pane.dir\n\tif (pane.command !== undefined) out.command = pane.command\n\treturn out\n}\n\n/**\n * The template with every answer written in — a NEW template, never the one passed in.\n *\n * Cloning rather than mutating is what makes `--dry-run` free and a failed validation harmless: the\n * caller still holds the original, so a refusal to write costs nothing and there is no half-edited\n * template to roll back. It also means an answer addressed at a pane that does not exist is caught\n * before anything is written, which is the only way this can fail.\n *\n * Everything not addressed is carried through verbatim, including keys this schema does not know\n * about — `structuredClone` copies the parsed JSON, so an edit is genuinely a field-level change and\n * never a re-serialization that quietly drops what it did not understand.\n */\nexport function applyEdits(template: Template, answers: EditAnswer[]): Template {\n\tconst next = structuredClone(template)\n\tfor (const answer of answers) {\n\t\tconst tree: TemplateTree | undefined = answer.tab === undefined ? next : next.tabs?.[answer.tab]\n\t\tif (!tree) throw new Error(`this template has no tab ${answer.tab}`)\n\t\tconst pane = treePanes(tree)[answer.index]\n\t\tif (!pane) {\n\t\t\tconst where = answer.tab === undefined ? 'this template' : `tab ${answer.tab}`\n\t\t\tthrow new Error(`${where} has no pane ${answer.index}`)\n\t\t}\n\t\tif (answer.value === undefined) delete pane[answer.field]\n\t\telse pane[answer.field] = answer.value\n\t}\n\treturn next\n}\n\n/**\n * The token that ADDRESSES a pane on the command line — `3`, or `2.3` in a tabs template. Both\n * 1-based, because they are read and typed by humans and agents rather than indexed by code.\n *\n * This is what the listing prints in its `pane` column and what `--set` takes, deliberately the same\n * string: an agent's loop is list-then-act, and a listing whose identifiers cannot be pasted straight\n * into the next command forces it to derive them. Panes are addressed by ORDINAL and never by label,\n * because a label is explicitly a name two panes may share (`PaneNode.label`) — an ambiguous selector\n * in a non-interactive API is a silent wrong-pane write.\n */\nexport function slotRef(slot: EditSlot): string {\n\treturn slot.tab === undefined ? `${slot.index + 1}` : `${slot.tab + 1}.${slot.index + 1}`\n}\n\n/** One `--set <ref>=<value>`, parsed. `value: undefined` clears, exactly as `-` does interactively. */\nexport interface SetSpec {\n\tref: string\n\tvalue: string | undefined\n}\n\n/**\n * Parse a `--set` argument into a reference and a value.\n *\n * Split on the FIRST `=` only, so a command containing one (`--set 1=FOO=bar make`) keeps it. An\n * empty value clears the field — the flag spelling of the walk's `-`, and unambiguous here because a\n * shell already distinguishes `--set 1=` from omitting the flag.\n */\nexport function parseSet(spec: string): SetSpec {\n\tconst at = spec.indexOf('=')\n\tif (at === -1) throw new Error(`--set needs <pane>=<value>, got \"${spec}\"`)\n\tconst ref = spec.slice(0, at).trim()\n\tif (ref === '') throw new Error(`--set needs a pane before the \"=\", got \"${spec}\"`)\n\tconst value = spec.slice(at + 1)\n\treturn { ref, value: value === '' ? undefined : value }\n}\n\n/**\n * Turn `--set` specs into answers against a known set of slots.\n *\n * Every reference is resolved BEFORE any answer is produced, so a batch naming one bad pane writes\n * none of them — a partial application of a multi-pane edit is the worst outcome available here,\n * since the caller cannot tell which half landed without re-reading the file.\n *\n * A value equal to what the pane already says yields no answer at all, which is what makes a re-run\n * of the same `--set` a no-op rather than a rewrite (AXI's idempotent-mutation rule).\n */\nexport function resolveSets(slots: EditSlot[], specs: SetSpec[], field: EditField): EditAnswer[] {\n\tconst byRef = new Map(slots.map((slot) => [slotRef(slot), slot]))\n\tconst answers: EditAnswer[] = []\n\tfor (const spec of specs) {\n\t\tconst slot = byRef.get(spec.ref)\n\t\tif (!slot) {\n\t\t\tthrow new Error(\n\t\t\t\t`no pane \"${spec.ref}\" in this template — it has ${slots.length} ` +\n\t\t\t\t\t`${slots.length === 1 ? 'pane' : 'panes'}: ${[...byRef.keys()].join(', ')}`,\n\t\t\t)\n\t\t}\n\t\tif (spec.value === slot[field]) continue\n\t\tconst answer: EditAnswer = { index: slot.index, field, value: spec.value }\n\t\tif (slot.tab !== undefined) answer.tab = slot.tab\n\t\tanswers.push(answer)\n\t}\n\treturn answers\n}\n\n/**\n * How a typed line becomes an answer — the prompt's one piece of vocabulary, here rather than in\n * `cli.ts` so it is pinned by a unit test alongside the rules it serves.\n *\n * Three cases, and the empty one is the important one: a guided walk shows every pane, so the author\n * passes through panes they do not want to touch far more often than ones they do. Enter therefore\n * has to mean KEEP, which leaves \"erase this\" needing a spelling of its own — `-`, because it is one\n * keystroke and is not a plausible command. A literal `-` is reachable by quoting it.\n */\nexport type EditInput = { kind: 'keep' } | { kind: 'set'; value: string }\n\nexport function readEditInput(line: string): EditInput {\n\tconst trimmed = line.trim()\n\tif (trimmed === '') return { kind: 'keep' }\n\tif (trimmed === '-') return { kind: 'set', value: '' }\n\tif (trimmed === \"'-'\" || trimmed === '\"-\"') return { kind: 'set', value: '-' }\n\treturn { kind: 'set', value: trimmed }\n}\n\n/**\n * The answers a walk produces, given what each slot was told — the pure core of the conversation.\n *\n * A `set` to the empty string is what CLEARS the field, which is why `readEditInput` maps `-` to it:\n * the schema has no use for `command: \"\"` (apply skips a falsy command anyway, see `submitCommands`),\n * so storing one would be storing a lie about a pane that runs nothing. An answer equal to what the\n * pane already says is dropped entirely, so a walk where the author pressed Enter through everything\n * reports zero changes rather than N no-op writes.\n */\nexport function toAnswers(slots: EditSlot[], inputs: EditInput[], field: EditField): EditAnswer[] {\n\tconst answers: EditAnswer[] = []\n\tfor (const [index, slot] of slots.entries()) {\n\t\tconst input = inputs[index]\n\t\tif (!input || input.kind === 'keep') continue\n\t\tconst value = input.value === '' ? undefined : input.value\n\t\tif (value === slot[field]) continue\n\t\tconst answer: EditAnswer = { index: slot.index, field, value }\n\t\tif (slot.tab !== undefined) answer.tab = slot.tab\n\t\tanswers.push(answer)\n\t}\n\treturn answers\n}\n","import { join } from 'node:path'\nimport { envFallback } from './env-fallback.ts'\nimport type { Exec } from './exec.ts'\nimport type { MuxAdapter, MuxPlacement, MuxTarget, OpenedPane } from './mux.ts'\nimport type { NewId } from './new-id.ts'\nimport {\n\tcollectPanes,\n\tfirstPane,\n\ttype PaneNode,\n\tresolveTree,\n\ttype TabNode,\n\ttype Template,\n\ttype TemplateNode,\n} from './template.ts'\n\n/**\n * Templates × sessions — the walk, and the only module that knows both halves. `template.ts` stays pure\n * and owes nothing to the mux; `mux.ts` stays a pure mux seam that owes nothing to templates.\n * Compiling one into the other is a third concern, and it lives here — exactly what\n * `worktree-session.ts` is to `worktree.ts` + `mux.ts`.\n *\n * The engine is cyber-mux's own: a tree-walk emitting `open`/`submit` against the PORTABLE\n * `MuxAdapter` verbs, never a backend's native template primitive. herdr's `template.apply` drops\n * out entirely rather than being deferred — it is a socket verb (this codebase speaks herdr's CLI,\n * synchronously, on purpose) and, more importantly, it is unique in the field: tmux, cmux, WezTerm\n * and screen have nothing equivalent. Leaning on it would mean the good path existing on exactly one\n * backend while every other backend needs this walk anyway. The capability a multiplexer must supply\n * is \"split THIS pane, that way\" — that is the whole ask, and it is `MuxOpenOptions.from`.\n */\n\n/** One pane the apply created — `label` is the key a higher layer addresses it by. */\nexport interface TemplatePaneReport {\n\tlabel: string | null\n\tpane: string\n\t/** The pane's resolved working directory: the apply-time cwd joined with the node's `dir`. */\n\tdir: string\n\tcommand: string | null\n\t/**\n\t * Which tab of the template this pane landed in, by its INDEX — the same argument `workspace` makes\n\t * one level down: a consumer grouping a tabs template's panes by tab needs something to group on.\n\t * `null` from a single-tab (`root`/`panes`) template — absent rather than an invented tab, since\n\t * such a template said nothing about tabs at all.\n\t *\n\t * The index rather than the tab's `label`, because a label is OPTIONAL (a tab may leave its name to\n\t * the backend) and a grouping key that is sometimes absent cannot group. The index is total and\n\t * collision-free, and it cannot be confused with the `null` a single-tab template reports, which a\n\t * label could be (a tab labeled `\"1\"` and a tab at index 1 would read alike). The label stays\n\t * recoverable from the template the manifest already names.\n\t */\n\ttab: number | null\n}\n\n/**\n * The whole handoff. `--format json` emits this, and it is the complete machine-readable answer to\n * \"which panes exist and what are they for\" — a dispatcher built on it needs NO new cyber-mux\n * surface, since it addresses panes through `read`/`submit`/`exists`/`focus`/`list`, which all\n * already exist.\n */\nexport interface TemplateManifest {\n\ttemplate: string\n\t/** The injected target — the apply-time cwd. Never anything the template said. */\n\tcwd: string\n\t/** `null` on tmux, matching how `reportOpenedWorktree` already reports it. */\n\tworkspace: string | null\n\tpanes: TemplatePaneReport[]\n}\n\n/**\n * A walk that threw partway. Carries the manifest of what WAS built, because apply does not roll\n * back: rolling back would mean killing panes, and a kill is not obviously safer than a half-built\n * template the caller can see and finish. This is the price of owning the engine rather than\n * delegating to an atomic tree-apply, and it is paid uniformly — a guarantee only herdr could make\n * is not a guarantee cyber-mux can offer.\n */\nexport class TemplateApplyError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\treadonly manifest: TemplateManifest,\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'TemplateApplyError'\n\t}\n}\n\ninterface WalkContext {\n\texec: Exec\n\tadapter: MuxAdapter\n\tcwd: string\n\tname: string\n\tworkspace: string | null\n\tdirExists: (path: string) => boolean\n\t/**\n\t * Whether the \"this backend cannot size a split\" warning has already been written. Shared across\n\t * every tab of an apply rather than per tab: the warning is about the BACKEND, so one apply says it\n\t * once however many tabs it opens.\n\t */\n\twarnedRatio: boolean\n}\n\n/**\n * One tab of an apply, with everything the report needs about it. A single-tab template is ONE of\n * these with a `null` index — the multi-tab walk is the same walk, run per tab, rather than a second\n * engine that could drift from it.\n */\ninterface TabState {\n\ttree: TemplateNode\n\t/** The tab's index in the template; `null` for a single-tab template, which has no tab tier. */\n\tindex: number | null\n\t/** The pane the tab's tree is built AGAINST — its own root region, never another tab's pane. */\n\troot: MuxTarget\n\t/**\n\t * Where the root pane ACTUALLY sits. Not derived — supplied by whoever opened the region, because\n\t * only they know. The root leaf is the one pane no split ever births, so `open --template` can place\n\t * it at `cwd + dir` while `worktree add --template` cannot: the worktree's workspace must open at the\n\t * worktree root, which is what the binding pins. Reporting `cwd + dir` regardless would make the\n\t * manifest claim a location nothing ever opened.\n\t */\n\trootDir: string\n\t/**\n\t * Whether the root pane's `env` was already set natively when the region was opened. Supplied by\n\t * whoever opened it, never inferred: it is true at every tier of `open` on both backends, and\n\t * false on exactly one route — herdr's `worktree create`, whose params carry no `env` at all. Only\n\t * the false case is prefixed, so the native routes can never double-apply.\n\t */\n\trootEnvHonored: boolean\n\t/** Template order — `first` before `second`; the order the manifest reports and commands submit in. */\n\tordered: PaneNode[]\n\t/** The leaf riding the region's own pane — the one leaf no split ever births. */\n\trootLeaf: PaneNode\n\t/** Recorded at each pane's BIRTH, so a throw later still reports every pane that actually exists. */\n\tpaneOf: Map<PaneNode, string>\n}\n\n/** A tab's bookkeeping, with its root pane already open and its root leaf pinned to that pane. */\nfunction tabState(\n\ttree: TemplateNode,\n\tindex: number | null,\n\troot: MuxTarget,\n\trootDir: string,\n\trootEnvHonored: boolean,\n): TabState {\n\tconst rootLeaf = firstPane(tree)\n\treturn {\n\t\ttree,\n\t\tindex,\n\t\troot,\n\t\trootDir,\n\t\trootEnvHonored,\n\t\tordered: collectPanes(tree),\n\t\trootLeaf,\n\t\t// The root leaf rides the region's own pane; every other leaf is born by exactly one split.\n\t\tpaneOf: new Map([[rootLeaf, root.id]]),\n\t}\n}\n\n/** A pane's resolved cwd: the apply-time target, joined with the node's relative `dir`. */\nfunction resolveDir(cwd: string, dir: string | undefined): string {\n\treturn dir ? join(cwd, dir) : cwd\n}\n\n/**\n * Every `dir` the template names, checked against the REAL target before anything is opened. A\n * branch that predates a directory is a real case, so the error names the pane and the resolved path\n * rather than just failing a mkdir somewhere.\n *\n * Up front, not per-pane-at-birth: a predictable error should not cost a half-built pool.\n */\nexport function assertTemplateDirs(tree: TemplateNode, cwd: string, dirExists: (path: string) => boolean): void {\n\tfor (const pane of collectPanes(tree)) {\n\t\tif (pane.dir === undefined) continue\n\t\tconst resolved = resolveDir(cwd, pane.dir)\n\t\tif (!dirExists(resolved)) {\n\t\t\tthrow new Error(`template pane \"${pane.label ?? '(unlabeled)'}\": directory does not exist — ${resolved}`)\n\t\t}\n\t}\n}\n\nexport interface OpenTemplateOptions {\n\t/** The injected target directory. */\n\tcwd: string\n\t/** Defaults to `workspace` — a fresh space is empty by construction. */\n\tat?: MuxPlacement | undefined\n\tlabel?: string | undefined\n\tdirExists: (path: string) => boolean\n\t/** Injected id source for the opaque tab-grouping id a `tabs` template mints — the seam that keeps\n\t * this a pure function rather than a caller of `node:crypto`. Unused by a single-region template. */\n\tnewId: NewId\n\t/** Passed to the region's own `open` for a `pane:*` placement; see `MuxOpenOptions.from`. */\n\tfrom?: MuxTarget | undefined\n}\n\n/**\n * Open a region and build the template inside it — `open --template`.\n *\n * The region opens BLANK (no `launch`) and its pane becomes the tree's root region: not a wasted\n * pane to close, but the pane the walk splits INTO. That is why nothing is launched here — the\n * template owns what runs.\n *\n * The manifest's `workspace` is whatever the region's own `open` landed in — the workspace it\n * created at the default `workspace` placement, or the one it landed inside at a `tab`/`pane:*`\n * placement. `null` only when the backend has no workspace tier (tmux) and so had nothing to report.\n * This is occupancy, not a worktree binding: `open` groups no repo, and a caller must not read a\n * workspace here as evidence that it did.\n */\nexport function openTemplate(\n\texec: Exec,\n\tadapter: MuxAdapter,\n\ttemplate: Template,\n\topts: OpenTemplateOptions,\n): TemplateManifest {\n\tif (template.tabs) return openTabsTemplate(exec, adapter, template, template.tabs, opts)\n\tconst tree = resolveTree(template)\n\t// Before the region is opened, so a missing dir opens nothing at all.\n\tassertTemplateDirs(tree, opts.cwd, opts.dirExists)\n\t// The root leaf sits on the region's OWN pane — no split ever births it — so its dir and env have\n\t// to ride in on this open or they are lost. Both are native at every tier on both backends, so\n\t// this route honors them exactly. No `launch`: commands are submitted last, together.\n\tconst rootLeaf = firstPane(tree)\n\tconst rootDir = resolveDir(opts.cwd, rootLeaf.dir)\n\tconst root = adapter.open(exec, {\n\t\tcwd: rootDir,\n\t\tat: opts.at ?? 'workspace',\n\t\tlabel: opts.label,\n\t\tenv: rootLeaf.env,\n\t\tfrom: opts.from,\n\t})\n\treturn walk(tabState(tree, null, root, rootDir, true), {\n\t\texec,\n\t\tadapter,\n\t\tcwd: opts.cwd,\n\t\tname: template.name,\n\t\t// The whole point of widening `open`'s return: before it carried a workspace, this was a\n\t\t// hardcoded null and the manifest could never report one, even on a backend that had just\n\t\t// opened a real workspace.\n\t\tworkspace: root.workspace ?? null,\n\t\tdirExists: opts.dirExists,\n\t\twarnedRatio: false,\n\t})\n}\n\n/**\n * The workspace label a tabs apply groups under: what the caller asked for, or the template's own\n * name. Never shortened, anywhere — it is the label the caller already chose, so the caller owns its\n * length, and not shortening is what makes a collision between two workspaces that shorten alike\n * impossible rather than merely handled.\n */\nfunction workspaceLabelOf(template: Template, label: string | undefined): string {\n\treturn label ?? template.name\n}\n\n/** The first tab's region, however the route in question came by it. */\ninterface FirstTab {\n\t/**\n\t * An `OpenedPane`, not a bare handle: the walk groups this tab like every other, and grouping\n\t * addresses the TAB. Both routes already hold it — `open --template` from the open it just ran,\n\t * `worktree add --template` from the one the worktree verbs ran — so requiring it here takes nothing\n\t * from either and is what lets the first tab be grouped rather than left out.\n\t */\n\troot: OpenedPane\n\trootDir: string\n\trootEnvHonored: boolean\n}\n\n/**\n * A workspace of N tabs — the single-tab walk, wrapped, with the inner walk unchanged and run once\n * per tab. Every later tab opens INSIDE the workspace at the `tab` placement; no tab is ever a split\n * of another tab's pane, which is the whole difference between a workspace of tabs and one tab of\n * panes.\n *\n * `firstTab` is the ONE thing the two routes differ in, and the reason they share this walk rather\n * than owning two that could drift: `open --template` opens the workspace and hands back its region,\n * while `worktree add --template` already HAS one — the worktree's own workspace, which that route\n * forced the placement for — so the first tab builds into it rather than opening a second.\n *\n * Every tab is opened and every split built BEFORE the first command is submitted — the single-tab\n * ordering, scaled: a split lands mid-render if it targets a pane already running an interactive\n * agent, and a tab is opened blank for exactly the reason a region is.\n */\nfunction walkTabs(\n\tctx: WalkContext,\n\ttabs: TabNode[],\n\ttrees: TemplateNode[],\n\tworkspaceLabel: string,\n\tgroup: string,\n\tfirstTab: () => FirstTab,\n): TemplateManifest {\n\tconst built: TabState[] = []\n\ttry {\n\t\ttrees.forEach((tree, index) => {\n\t\t\tlet opened: OpenedPane\n\t\t\tif (index === 0) {\n\t\t\t\tconst first = firstTab()\n\t\t\t\topened = first.root\n\t\t\t\tbuilt.push(tabState(tree, 0, first.root, first.rootDir, first.rootEnvHonored))\n\t\t\t\t// The one tab no backend can name at birth, named HERE — in the walk both routes share —\n\t\t\t\t// rather than in either route's own `firstTab`. The scenarios this serves say \"when it is\n\t\t\t\t// applied\", naming no route, so a route that could forget this is a scenario that is\n\t\t\t\t// silently false on it. Only the shared path makes forgetting impossible.\n\t\t\t\t//\n\t\t\t\t// Runs AFTER `firstTab()` because that is what settles the tier signal: `open --template`\n\t\t\t\t// learns it from the open it just ran, and `tabLabelFor` reads it to decide whether the\n\t\t\t\t// workspace is carried into the name.\n\t\t\t\t//\n\t\t\t\t// `opened.tab`, NEVER `opened.id`: the pane id would be green on tmux (which resolves a\n\t\t\t\t// pane in a window target) and silently broken on herdr (`tab_not_found`, discarded),\n\t\t\t\t// leaving the root tab named `1` with nothing raised.\n\t\t\t\tconst name = tabLabelFor(ctx, tabs[0]!, workspaceLabel)\n\t\t\t\tif (name !== undefined) ctx.adapter.rename(ctx.exec, { id: opened.tab }, 'tab', name)\n\t\t\t} else {\n\t\t\t\tconst rootLeaf = firstPane(tree)\n\t\t\t\tconst rootDir = resolveDir(ctx.cwd, rootLeaf.dir)\n\t\t\t\topened = ctx.adapter.open(ctx.exec, {\n\t\t\t\t\tcwd: rootDir,\n\t\t\t\t\t// A real tab in the workspace the first tab established — never a `pane:*` placement,\n\t\t\t\t\t// which would make this tab a split of the tab before it.\n\t\t\t\t\tat: 'tab',\n\t\t\t\t\t// Anchored to THAT workspace, and this is what `ctx.workspace` is for at open time rather\n\t\t\t\t\t// than only in the report: a bare `tab` placement is resolved by every backend against the\n\t\t\t\t\t// space the USER is looking at, so without this the first tab landed in the new workspace\n\t\t\t\t\t// and tabs 2..N landed beside the pane the command was RUN from.\n\t\t\t\t\t// `undefined` on a backend with no workspace tier (tmux) — there is no second space for a\n\t\t\t\t\t// tab to land in the wrong one of, so there is nothing to anchor to.\n\t\t\t\t\twithin: ctx.workspace ?? undefined,\n\t\t\t\t\t// Named at BIRTH: every tab but a new workspace's root can be, on both backends.\n\t\t\t\t\tlabel: tabLabelFor(ctx, tabs[index]!, workspaceLabel),\n\t\t\t\t\tenv: rootLeaf.env,\n\t\t\t\t})\n\t\t\t\t// `open` sets env natively at every tier on both backends, so no tab ever needs the prefix.\n\t\t\t\tbuilt.push(tabState(tree, index, opened, rootDir, true))\n\t\t\t}\n\t\t\t// EVERY tab, the first one included, and through the verb rather than `open`'s option — which\n\t\t\t// is the whole reason grouping is a verb. The first tab's region may have been opened before\n\t\t\t// this walk ever ran (`worktree add --template`), so an option on `open` could only ever have\n\t\t\t// covered tabs 2..N, and a group missing the workspace's own first tab is worse than no\n\t\t\t// group: `save --workspace` would confidently round-trip a 3-tab workspace as 2. Grouping\n\t\t\t// here means the route that opened the region cannot change what the template means.\n\t\t\t//\n\t\t\t// The tab's OWN name, never `tabLabelFor`'s composed display name: where the backend has no\n\t\t\t// workspace tier the display name is `<workspace> - <tab>`, so the backend's single name\n\t\t\t// field no longer holds the original. Handing the composed one here would re-prefix it on\n\t\t\t// every round trip. `undefined` when the tab left its name to the backend — nothing to store.\n\t\t\tctx.adapter.group(ctx.exec, { id: opened.tab }, group, tabs[index]!.label)\n\t\t\t// Against THIS tab's own root pane — the id threaded through every split of this tree.\n\t\t\tbuildGeometry(built[index]!, ctx)\n\t\t})\n\t} catch (err) {\n\t\t// Unchanged, one level up: apply does not roll back, so the tabs already built are reported and\n\t\t// nothing is killed. Adding a level does not buy an atomicity the node never offered.\n\t\tthrow new TemplateApplyError(err instanceof Error ? err.message : String(err), report(ctx, built))\n\t}\n\n\tsubmitCommands(built, ctx)\n\treturn report(ctx, built)\n}\n\n/** `open --template` with a tabs template: the first tab opens the workspace the rest live in. */\nfunction openTabsTemplate(\n\texec: Exec,\n\tadapter: MuxAdapter,\n\ttemplate: Template,\n\ttabs: TabNode[],\n\topts: OpenTemplateOptions,\n): TemplateManifest {\n\tconst trees = tabs.map((tab) => resolveTree(tab))\n\t// Every tab's dirs, before ANY tab is opened — a predictable error must not cost a half-built\n\t// workspace any more than it costs a half-built region.\n\tfor (const tree of trees) assertTemplateDirs(tree, opts.cwd, opts.dirExists)\n\n\t// The machine's carrier for the grouping, and the reason the label never has to be parsed back:\n\t// an opaque id no one reads FOR its content. A backend with a real workspace tier ignores it, that\n\t// tier already being the group.\n\tconst group = opts.newId()\n\tconst workspaceLabel = workspaceLabelOf(template, opts.label)\n\tconst ctx: WalkContext = {\n\t\texec,\n\t\tadapter,\n\t\tcwd: opts.cwd,\n\t\tname: template.name,\n\t\t// Set from the first tab's own open, below — whatever the backend says it landed in.\n\t\tworkspace: null,\n\t\tdirExists: opts.dirExists,\n\t\twarnedRatio: false,\n\t}\n\n\treturn walkTabs(ctx, tabs, trees, workspaceLabel, group, () => {\n\t\tconst rootLeaf = firstPane(trees[0]!)\n\t\tconst rootDir = resolveDir(opts.cwd, rootLeaf.dir)\n\t\tconst opened = adapter.open(exec, {\n\t\t\tcwd: rootDir,\n\t\t\tat: opts.at ?? 'workspace',\n\t\t\t// The WORKSPACE's name, not this tab's: at the `workspace` placement `label` names the space\n\t\t\t// being opened, and on a backend with a real tier that is the workspace itself. The tab under\n\t\t\t// it is named just below, once the backend has told us which kind of backend it is.\n\t\t\tlabel: workspaceLabel,\n\t\t\tenv: rootLeaf.env,\n\t\t\tfrom: opts.from,\n\t\t})\n\t\t// The tier signal, read from what the backend ACTUALLY reported rather than from its name: a\n\t\t// workspace on the open means this backend has a tier to have landed in; absent means it has\n\t\t// none (tmux). Set here because only this route can learn it — the worktree route is TOLD its\n\t\t// workspace by the caller that opened the region. Either way it is settled before `walkTabs`\n\t\t// names this tab, which is what turns on exactly this.\n\t\tctx.workspace = opened.workspace ?? null\n\t\treturn { root: opened, rootDir, rootEnvHonored: true }\n\t})\n}\n\n/**\n * A tab's label, as a human reads it.\n *\n * Where the backend has no workspace tier (tmux, which collapses workspace and tab onto one Window),\n * the workspace is carried into the label — `<workspace> - <tab>` — because the template's tabs would\n * otherwise land as an unlabeled pile with nothing marking them as one pool. Where the backend HAS the\n * tier (herdr), its UI already groups by the real workspace label, so a prefix would be redundant\n * noise and the tab carries its own label alone. The concept maps onto what the backend actually has.\n *\n * The workspace label goes in whole — never shortened. It is the label the caller already chose, so\n * the caller owns its length, and not shortening is what makes a collision between two workspaces that\n * shorten alike impossible rather than merely handled.\n *\n * This is the human's carrier only. The machine reads `workspaceGroup`, never this — the label is\n * ambiguous under every split rule (\"acme - beta - main\"), so it is written and never parsed back.\n */\nfunction tabLabelFor(ctx: WalkContext, tab: TabNode, workspaceLabel: string): string | undefined {\n\t// A tab may leave its name to the backend — matching `--label` omitted everywhere else, the\n\t// backend's own default then stands, and there is nothing to prefix.\n\tif (tab.label === undefined) return undefined\n\tif (ctx.workspace !== null) return tab.label\n\treturn `${workspaceLabel} - ${tab.label}`\n}\n\n/**\n * The pane that will sit on a region's own root pane — whoever opens that region must carry this\n * pane's `env` (and, where it can, its `dir`), because no split ever births it.\n *\n * For a tabs template that is the FIRST tab's root leaf: the first tab is the one built into the\n * region the caller opens, and every later tab opens its own space (carrying its own root leaf's env\n * at that open). Resolving the template itself here would desugar a `panes` list a tabs template does\n * not have.\n */\nexport function templateRootPane(template: Template): PaneNode {\n\treturn firstPane(resolveTree(template.tabs ? template.tabs[0]! : template))\n}\n\nexport interface ApplyTemplateOptions {\n\t/**\n\t * An ALREADY-OPEN blank region whose pane is the tree's root — e.g. a worktree's workspace.\n\t *\n\t * An `OpenedPane` rather than a bare handle, because a tabs template groups this region's tab like\n\t * every other tab it builds, and grouping addresses the tab. The caller that opened the region\n\t * already holds it — every backend reports the tab an open landed in — so requiring it costs\n\t * nothing and is what keeps the workspace's own first tab inside the group.\n\t */\n\troot: OpenedPane\n\tcwd: string\n\t/** The backend workspace the region lives in, when the backend binds one; `null` on tmux. */\n\tworkspace: string | null\n\t/**\n\t * Whether the root pane's `env` was already set when this region was opened. Required rather than\n\t * defaulted: only the caller that opened the region knows, and guessing wrong either drops the env\n\t * silently or applies it twice.\n\t */\n\trootEnvHonored: boolean\n\tdirExists: (path: string) => boolean\n\t/** Injected id source for the opaque tab-grouping id a `tabs` template mints; see\n\t * `OpenTemplateOptions.newId`. Unused by a single-region apply. */\n\tnewId: NewId\n\t/**\n\t * The label the region was opened under — the workspace's name, which a tabs template carries into\n\t * each later tab's label on a backend with no workspace tier. Only the caller that opened the region\n\t * knows what it named it; omitted, the template's own name stands, matching `open --template`'s\n\t * default.\n\t */\n\tlabel?: string | undefined\n}\n\n/**\n * Build a template inside a region someone else already opened — `worktree add --template`, where the\n * worktree's own workspace IS the region and its root pane is the tree's root.\n */\nexport function applyTemplateToRegion(\n\texec: Exec,\n\tadapter: MuxAdapter,\n\ttemplate: Template,\n\topts: ApplyTemplateOptions,\n): TemplateManifest {\n\tif (template.tabs) return applyTabsToRegion(exec, adapter, template, template.tabs, opts)\n\tconst tree = resolveTree(template)\n\tassertTemplateDirs(tree, opts.cwd, opts.dirExists)\n\t// The region was opened by someone whose own contract fixed its cwd — a worktree's workspace opens\n\t// at the worktree root, because that is what the binding pins. So a root leaf's `dir` genuinely\n\t// cannot be honored on this route. Degrade and warn, never silently drop: the caller is told which\n\t// pane lost its dir, and the manifest below reports where that pane REALLY is. stderr, so stdout\n\t// stays machine-readable.\n\tconst rootLeaf = firstPane(tree)\n\tif (rootLeaf.dir !== undefined) {\n\t\tprocess.stderr.write(\n\t\t\t`the template's root pane \"${rootLeaf.label ?? '(unlabeled)'}\" cannot start in \"${rootLeaf.dir}\" — ` +\n\t\t\t\t`the region opens at ${opts.cwd}\\n`,\n\t\t)\n\t}\n\t// Where it actually is, not where the template asked for.\n\treturn walk(tabState(tree, null, opts.root, opts.cwd, opts.rootEnvHonored), {\n\t\texec,\n\t\tadapter,\n\t\tcwd: opts.cwd,\n\t\tname: template.name,\n\t\tworkspace: opts.workspace,\n\t\tdirExists: opts.dirExists,\n\t\twarnedRatio: false,\n\t})\n}\n\n/**\n * `worktree add --template` with a tabs template: the workspace already EXISTS — that route forces the\n * `workspace` placement and opened one for the worktree — so a set of tabs has somewhere to live and\n * needs no second workspace. The first tab is built INTO that region; every later tab opens as a tab\n * in it. That one difference is the whole of what separates this route from `open --template`.\n */\nfunction applyTabsToRegion(\n\texec: Exec,\n\tadapter: MuxAdapter,\n\ttemplate: Template,\n\ttabs: TabNode[],\n\topts: ApplyTemplateOptions,\n): TemplateManifest {\n\tconst trees = tabs.map((tab) => resolveTree(tab))\n\tfor (const tree of trees) assertTemplateDirs(tree, opts.cwd, opts.dirExists)\n\n\tconst ctx: WalkContext = {\n\t\texec,\n\t\tadapter,\n\t\tcwd: opts.cwd,\n\t\tname: template.name,\n\t\t// Already known on this route, from the caller that opened the region — no first open has to\n\t\t// report it, and it is the same tier signal the tab labels turn on.\n\t\tworkspace: opts.workspace,\n\t\tdirExists: opts.dirExists,\n\t\twarnedRatio: false,\n\t}\n\n\t// The first tab's root leaf rides a region whose cwd another contract already fixed — the worktree\n\t// root, which the binding pins — so its `dir` cannot be honored, exactly as on the single-tab\n\t// route. Same degrade, same warning, for the same reason.\n\tconst rootLeaf = firstPane(trees[0]!)\n\tif (rootLeaf.dir !== undefined) {\n\t\tprocess.stderr.write(\n\t\t\t`the template's root pane \"${rootLeaf.label ?? '(unlabeled)'}\" cannot start in \"${rootLeaf.dir}\" — ` +\n\t\t\t\t`the region opens at ${opts.cwd}\\n`,\n\t\t)\n\t}\n\n\t// Grouped exactly as `open --template` is, and by the same walk: the route that opened the region\n\t// cannot change what the template means. Nothing has to be threaded through the worktree verbs to\n\t// make this work — `opts.root` is the region they opened, and it carries its own tab, which is all\n\t// grouping an already-open space needs.\n\treturn walkTabs(ctx, tabs, trees, workspaceLabelOf(template, opts.label), opts.newId(), () => ({\n\t\t// The region that already exists. Where it actually is, not where the template asked for.\n\t\troot: opts.root,\n\t\trootDir: opts.cwd,\n\t\trootEnvHonored: opts.rootEnvHonored,\n\t}))\n}\n\n/**\n * The walk: geometry depth-first against NAMED panes, then every command, last.\n *\n * **Geometry before commands is deliberate ordering, not incidental.** `open`'s `launch` couples\n * creation to launching, so reusing it would mean splitting a pane already running an interactive\n * agent — the split lands mid-render, and the ratio is computed against a pane whose child is\n * reflowing. Opening every pane blank first makes the whole geometry phase side-effect-free from the\n * agent's point of view.\n */\nfunction walk(tab: TabState, ctx: WalkContext): TemplateManifest {\n\tconst tabs = [tab]\n\ttry {\n\t\tbuildGeometry(tab, ctx)\n\t} catch (err) {\n\t\t// No rollback, no kill — report what was built and let the caller finish or close it.\n\t\tthrow new TemplateApplyError(err instanceof Error ? err.message : String(err), report(ctx, tabs))\n\t}\n\tsubmitCommands(tabs, ctx)\n\treturn report(ctx, tabs)\n}\n\n/**\n * One tab's geometry: depth-first against NAMED panes, opening every pane blank. Submits nothing —\n * the caller does that once EVERY tab is built, which is what lets the multi-tab walk hold the same\n * \"no split ever lands on a pane mid-render\" guarantee the single-tab walk holds.\n */\nfunction buildGeometry(tab: TabState, ctx: WalkContext): void {\n\t// A backend that cannot size a split takes its own default and we say so ONCE — a wrong-looking\n\t// split is not worth failing an otherwise-correct pool over, and the schema is backend-agnostic,\n\t// so a template's validity cannot depend on which multiplexer happens to be running.\n\tconst sizeSplit = (ratio: number | undefined): number | undefined => {\n\t\tif (ratio == null) return undefined\n\t\tif (ctx.adapter.canSizeSplits) return ratio\n\t\tif (!ctx.warnedRatio) {\n\t\t\tctx.warnedRatio = true\n\t\t\tprocess.stderr.write(`${ctx.adapter.name} cannot size a split — every ratio in this template takes its default\\n`)\n\t\t}\n\t\treturn undefined\n\t}\n\n\tconst build = (node: TemplateNode, paneId: string): void => {\n\t\tif (node.type === 'pane') return\n\t\t// The new pane becomes `second`'s region, and the leaf that ends up sitting on it is\n\t\t// `firstPane(second)` — so THAT leaf's dir and env are what this split must carry, since a\n\t\t// pane's cwd and env can only be set at its birth.\n\t\tconst born = firstPane(node.second)\n\t\tconst created = ctx.adapter.open(ctx.exec, {\n\t\t\tcwd: resolveDir(ctx.cwd, born.dir),\n\t\t\tat: node.direction === 'down' ? 'pane:down' : 'pane:right',\n\t\t\t// Always named. Neither backend's default splits the CALLER: herdr's `--current` falls back\n\t\t\t// to the UI-focused pane, and tmux always splits the session's active pane. Both track the\n\t\t\t// user, not us — and a tree walk must split a pane created three steps ago regardless.\n\t\t\t// In a tabs walk this is also what keeps a tab's splits inside THAT tab: the id threaded from\n\t\t\t// here is the tab's own root pane, so no split can wander into the tab opened before it.\n\t\t\tfrom: { id: paneId },\n\t\t\tratio: sizeSplit(node.ratio),\n\t\t\tenv: born.env,\n\t\t\tlabel: born.label,\n\t\t})\n\t\t// Recorded at BIRTH, so a throw later still reports every pane that actually exists.\n\t\ttab.paneOf.set(born, created.id)\n\t\tbuild(node.first, paneId)\n\t\tbuild(node.second, created.id)\n\t}\n\n\tbuild(tab.tree, tab.root.id)\n}\n\n/**\n * The manifest, across every tab built so far. ONE FLAT pane list — the tab is a field on each pane\n * rather than a second nesting a consumer has to walk. The unique handle is the pane `id`; `label` is\n * a name two panes may share, and the tab is reported by INDEX rather than by either.\n */\nfunction report(ctx: WalkContext, tabs: TabState[]): TemplateManifest {\n\treturn {\n\t\ttemplate: ctx.name,\n\t\tcwd: ctx.cwd,\n\t\tworkspace: ctx.workspace,\n\t\tpanes: tabs.flatMap((tab) =>\n\t\t\ttab.ordered\n\t\t\t\t.filter((pane) => tab.paneOf.has(pane))\n\t\t\t\t.map((pane) => ({\n\t\t\t\t\tlabel: pane.label ?? null,\n\t\t\t\t\tpane: tab.paneOf.get(pane)!,\n\t\t\t\t\t// The root pane reports where it WAS opened, which is not always where its `dir` asked\n\t\t\t\t\t// for; every other pane was born by a split that took its resolved dir verbatim. The\n\t\t\t\t\t// manifest is the answer to \"which panes exist and what are they for\", so a claim it\n\t\t\t\t\t// cannot back is worse than a feature it does not have.\n\t\t\t\t\tdir: pane === tab.rootLeaf ? tab.rootDir : resolveDir(ctx.cwd, pane.dir),\n\t\t\t\t\tcommand: pane.command ?? null,\n\t\t\t\t\ttab: tab.index,\n\t\t\t\t})),\n\t\t),\n\t}\n}\n\n/**\n * Every command, last — and across every tab, in template order, tab by tab. Only reachable once all\n * geometry is built: a split lands mid-render if it targets a pane already running an interactive\n * agent, and that reason does not weaken because the pane sits in another tab.\n */\nfunction submitCommands(tabs: TabState[], ctx: WalkContext): void {\n\tfor (const tab of tabs) {\n\t\t// The root pane's env compensation, when the region open could not carry it natively — the ONE\n\t\t// pane that can need it, since every other is born by a split, which carries env at birth on both\n\t\t// backends. Reachable only on herdr's worktree route; every native route set env already and must\n\t\t// NOT be prefixed on top of it. The prefix-or-warn RULE is the seam's (`env-fallback.ts`); what\n\t\t// this node owns is the scoping — root pane only, and the warning once rather than per pane.\n\t\tconst rootFallback = tab.rootEnvHonored ? undefined : envFallback(tab.rootLeaf.env, tab.rootLeaf.command)\n\t\tif (rootFallback?.kind === 'dropped') {\n\t\t\t// Nothing to prefix — the fallback only works by riding on a command line. Degrade and warn,\n\t\t\t// never silently drop; stderr, so stdout stays machine-readable.\n\t\t\tprocess.stderr.write(\n\t\t\t\t`the template's root pane \"${tab.rootLeaf.label ?? '(unlabeled)'}\" has env (${rootFallback.variables.join(', ')}) ` +\n\t\t\t\t\t'but no command to carry it — this backend cannot set env on the region it opens\\n',\n\t\t\t)\n\t\t}\n\n\t\tfor (const pane of tab.ordered) {\n\t\t\t// The root pane's command may have been rewritten to carry its env; every other pane runs verbatim.\n\t\t\tconst command = pane === tab.rootLeaf && rootFallback?.kind === 'carried' ? rootFallback.command : pane.command\n\t\t\tif (!command) continue\n\t\t\tctx.adapter.submit(ctx.exec, { id: tab.paneOf.get(pane)! }, command)\n\t\t}\n\t}\n}\n","import type { Exec } from './exec.ts'\nimport type { MuxAdapter, MuxPlacement, MuxTarget, OpenedPane } from './mux.ts'\nimport {\n\tgitWorktreeAdapter,\n\tlistWorktreesFromGit,\n\tnormalizeWorktreePath,\n\tremoveWorktreeSafely,\n\ttype Worktree,\n\ttype WorktreeEntry,\n} from './worktree.ts'\n\n/**\n * Worktrees × sessions — the routing policy, and the only module that knows both halves. `worktree.ts`\n * stays a pure git adapter that owes nothing to the session seam; `mux.ts` stays a pure mux seam\n * that owes nothing to git. Deciding between them is a third concern, and it lives here.\n */\n\n/** A worktree that has been opened somewhere — the product of every routing decision below. */\nexport interface OpenedWorktree {\n\tworktree: Worktree\n\t/**\n\t * The opened root pane, and the tab it sits in. Both routes report the tab — the binding route from\n\t * the backend's own worktree envelope, the plain-git fallback from `open` — so a caller handed this\n\t * region can address its tab (to group it, to name it) without reaching for the pane id, which\n\t * resolves on tmux and is refused by herdr.\n\t */\n\ttarget: OpenedPane\n\t/** The workspace bound to the worktree; absent when it opened ungrouped. */\n\tworkspace?: string | undefined\n\t/**\n\t * The backend COULD have bound this worktree to a workspace, but the route taken did not — i.e. a\n\t * caller on herdr asked for a pane or tab placement, which its `worktree create` cannot serve.\n\t * Never true on a backend with no binding at all (tmux), where no grouping was ever on offer:\n\t * there is nothing to report about a feature the backend does not have.\n\t */\n\tdegraded: boolean\n\t/**\n\t * Whether a requested `env` actually reached the opened root pane. `false` ONLY on herdr's binding\n\t * route, whose `worktree create` has no `env` param at all (unlike `workspace`/`tab`/`pane\n\t * create`) and rejects the flag outright. Vacuously `true` when no env was asked for.\n\t *\n\t * Reported rather than solved here because the remedy is a *command* — prefixing `env K=V` onto\n\t * what the pane runs — and this module opens panes; it does not decide what they run. Only the\n\t * route taken knows this fact, which is why it is reported rather than inferred by the caller.\n\t */\n\tenvHonored: boolean\n}\n\n/**\n * Grouping is possible only where the backend binds AND the caller asked for a workspace — herdr's\n * `worktree create` ALWAYS opens a workspace, so it cannot serve a pane or tab placement.\n */\nfunction canBind(adapter: MuxAdapter, at: MuxPlacement | undefined): boolean {\n\treturn Boolean(adapter.worktree) && at === 'workspace'\n}\n\n/** True only where a group was on offer and the placement is what cost us it. */\nfunction isDegraded(adapter: MuxAdapter, at: MuxPlacement | undefined): boolean {\n\treturn Boolean(adapter.worktree) && !canBind(adapter, at)\n}\n\n/**\n * Create a worktree and open it.\n *\n * Routes through the backend's own primitive when it can bind (grouped), and otherwise falls back to\n * `git worktree add` plus a plain `open()`. The fallback is a complete, useful outcome — a worktree\n * open in a split pane — just not a grouped one, so it is REPORTED (`degraded`), never refused.\n * Refusing would make identical flags succeed on tmux and fail on herdr, which is exactly the\n * backend leak this seam exists to prevent.\n */\nexport function addAndOpenWorktree(\n\texec: Exec,\n\tadapter: MuxAdapter,\n\topts: {\n\t\tprimaryRoot: string\n\t\tbranch: string\n\t\tpath: string\n\t\tbase?: string | undefined\n\t\tlaunch?: string | undefined\n\t\t/** Environment set in the opened root pane at birth — native at every tier on both backends. */\n\t\tenv?: Record<string, string> | undefined\n\t\tat?: MuxPlacement | undefined\n\t\tlabel?: string | undefined\n\t\t/** Passed to `open` for a `pane:*` placement; see `MuxOpenOptions.from`. */\n\t\tfrom?: MuxTarget | undefined\n\t},\n): OpenedWorktree {\n\tif (canBind(adapter, opts.at)) {\n\t\tconst created = adapter.worktree!.createInWorkspace(exec, {\n\t\t\tprimaryRoot: opts.primaryRoot,\n\t\t\tbranch: opts.branch,\n\t\t\tpath: opts.path,\n\t\t\tbase: opts.base,\n\t\t\tlaunch: opts.launch,\n\t\t\tenv: opts.env,\n\t\t\tlabel: opts.label,\n\t\t})\n\t\t// herdr's `worktree create` takes no env — the adapter accepts `env` and does not emit it, so\n\t\t// say so rather than let the caller assume it landed.\n\t\treturn { ...created, degraded: false, envHonored: !opts.env }\n\t}\n\tconst worktree = gitWorktreeAdapter.add(exec, {\n\t\tprimaryRoot: opts.primaryRoot,\n\t\tpath: opts.path,\n\t\tbranch: opts.branch,\n\t\tbase: opts.base,\n\t})\n\tconst target = adapter.open(exec, {\n\t\tcwd: worktree.root,\n\t\tlaunch: opts.launch,\n\t\tenv: opts.env,\n\t\tat: opts.at,\n\t\tlabel: opts.label,\n\t\tfrom: opts.from,\n\t})\n\t// This route goes through `open`, where env is native at every tier on both backends.\n\treturn { worktree, target, degraded: isDegraded(adapter, opts.at), envHonored: true }\n}\n\n/**\n * Open an EXISTING worktree — the remedy that groups one a bare `worktree add` created earlier, so\n * \"add now, group later\" is a real story rather than a dead end.\n */\nexport function openExistingWorktree(\n\texec: Exec,\n\tadapter: MuxAdapter,\n\topts: {\n\t\tprimaryRoot: string\n\t\tpath: string\n\t\tlaunch?: string | undefined\n\t\t/** Environment set in the opened root pane; honored natively on the `open` route, compensated on the bind route. */\n\t\tenv?: Record<string, string> | undefined\n\t\tat?: MuxPlacement | undefined\n\t\tlabel?: string | undefined\n\t\t/** Passed to `open` for a `pane:*` placement; see `MuxOpenOptions.from`. */\n\t\tfrom?: MuxTarget | undefined\n\t},\n): OpenedWorktree {\n\tconst at = opts.at ?? 'workspace'\n\tif (canBind(adapter, at)) {\n\t\tconst opened = adapter.worktree!.openInWorkspace(exec, {\n\t\t\tprimaryRoot: opts.primaryRoot,\n\t\t\tpath: opts.path,\n\t\t\tlaunch: opts.launch,\n\t\t\tenv: opts.env,\n\t\t\tlabel: opts.label,\n\t\t})\n\t\t// herdr's `worktree open` takes no env — the adapter compensates on the launch and reports the\n\t\t// drop here, exactly as the create route does, so a caller cannot assume env landed.\n\t\treturn { ...opened, degraded: false, envHonored: !opts.env }\n\t}\n\tconst root = normalizeWorktreePath(opts.path)\n\tconst target = adapter.open(exec, {\n\t\tcwd: root,\n\t\tlaunch: opts.launch,\n\t\tenv: opts.env,\n\t\tat,\n\t\tlabel: opts.label,\n\t\tfrom: opts.from,\n\t})\n\t// This route goes through `open`, where env is native at every tier on both backends.\n\t// The branch is git's answer, not the backend's — same rule as `listWorktrees`.\n\tconst branch = listWorktreesFromGit(exec, opts.primaryRoot).find((entry) => entry.root === root)?.branch\n\treturn { worktree: { root, branch: branch ?? '' }, target, degraded: isDegraded(adapter, at), envHonored: true }\n}\n\n/**\n * Every worktree of the repo, with the workspace each is open in.\n *\n * The facts come from git on EVERY backend and the backend contributes only the binding, joined by\n * normalized path. A backend that also enumerates worktrees is merely re-reading git, so letting it\n * answer would let two backends report a different branch for the same worktree — this is\n * structurally incapable of that.\n */\nexport function listWorktrees(\n\texec: Exec,\n\tadapter: MuxAdapter | undefined,\n\topts: { primaryRoot: string },\n): WorktreeEntry[] {\n\tconst bindings = adapter?.worktree?.bindings(exec, { primaryRoot: opts.primaryRoot })\n\treturn listWorktreesFromGit(exec, opts.primaryRoot).map((entry) => {\n\t\tconst workspace = bindings?.get(entry.root)\n\t\treturn workspace ? { ...entry, workspace } : entry\n\t})\n}\n\n/**\n * Remove a worktree, with identical gates on every backend: refuse the primary checkout (absolute),\n * tolerate one already gone from disk, refuse uncommitted changes unless `force`.\n *\n * Removal is never handed to the backend — only the binding's release is. See\n * `WorktreeWorkspaceCapability` for why, and `removeWorktreeSafely` for why the ordering of that\n * release is a specified property rather than an incidental one.\n */\nexport function removeWorktree(\n\texec: Exec,\n\tadapter: MuxAdapter | undefined,\n\tpath: string,\n\topts: { primaryRoot: string; force?: boolean | undefined },\n): void {\n\tconst capability = adapter?.worktree\n\tconst workspace = capability?.bindings(exec, { primaryRoot: opts.primaryRoot }).get(normalizeWorktreePath(path))\n\tremoveWorktreeSafely(exec, path, {\n\t\tprimaryRoot: opts.primaryRoot,\n\t\tforce: opts.force,\n\t\treleaseBinding: capability && workspace ? () => capability.releaseWorkspace(exec, workspace) : undefined,\n\t})\n}\n","import { join } from 'node:path'\nimport { Command, CommanderError, Option } from 'commander'\nimport { AgentLifecycleUnsupportedError, deriveAgentWait } from './agent.ts'\nimport { callerPane, resolveMuxAdapter } from './backend.ts'\nimport { AmbiguousPaneError, CliError, MissingPaneError, reportError } from './cli-error.ts'\nimport { AT_OPTION, ENV_OPTION, FORMAT_OPTION, LABEL_OPTION } from './cli-options.ts'\nimport { type Exec, nodeExec } from './exec.ts'\nimport type { AgentStatus, LivePane, MuxAdapter, MuxPlacement, MuxTarget } from './mux.ts'\nimport { currentPane, probeMultiplexer } from './mux-probe.ts'\nimport { nodeNewId } from './new-id.ts'\nimport { type HelpEntry, isAutomatedOutput, output, printFields, printHelp, printTable, tildify } from './output.ts'\nimport { type OpenPrompt, realPrompt } from './prompt.ts'\nimport {\n\tcollectPanes,\n\tisValidTemplateName,\n\tparseTemplate,\n\tresolveTree,\n\ttype Template,\n\tvalidateTemplate,\n} from './template.ts'\nimport { CaptureUnsupportedError, deriveRegionCapture, deriveWorkspaceCapture } from './template-capture.ts'\nimport {\n\tapplyEdits,\n\ttype EditAnswer,\n\ttype EditField,\n\ttype EditInput,\n\ttype EditSlot,\n\tparseSet,\n\tplanEdits,\n\treadEditInput,\n\tresolveSets,\n\tslotRef,\n\ttoAnswers,\n} from './template-edit.ts'\nimport {\n\tapplyTemplateToRegion,\n\topenTemplate,\n\tTemplateApplyError,\n\ttype TemplateManifest,\n\ttemplateRootPane,\n} from './template-session.ts'\nimport {\n\tlistTemplates,\n\tnodeTemplateStore,\n\ttype ResolvedTemplate,\n\tresolveTemplate as resolveTemplateSource,\n\ttype TemplateStore,\n\ttemplateDirs,\n} from './template-store.ts'\nimport {\n\tgitWorktreeAdapter,\n\tisWorktreeRemovable,\n\tprovisionWorktree,\n\tpruneWorktrees,\n\tresolvePrimaryRoot,\n\tresolveWorktreePath,\n\tWorktreeGitError,\n} from './worktree.ts'\nimport {\n\taddAndOpenWorktree,\n\tlistWorktrees,\n\ttype OpenedWorktree,\n\topenExistingWorktree,\n\tremoveWorktree,\n} from './worktree-session.ts'\n\n// NOTE: the verb surface below is provisional — the behavior spec is the next milestone and may\n// rename verbs, adjust flags, or split concerns (e.g. move `nudge` behind its own group).\n\n/** The env/exec pair every command resolves the backend and multiplexer through — injected so the\n * CLI can be driven deterministically in tests, the same seam every adapter already takes. */\nexport interface CliDeps {\n\tenv: NodeJS.ProcessEnv\n\texec: Exec\n\t/** The filesystem half, for the `template` group — injected for the same reason `exec` is: it is the\n\t * only way `template` can be driven hermetically in tests, with no real templates on disk. Optional\n\t * at this boundary so a caller that drives no template command need not know the seam exists. */\n\tstore?: TemplateStore | undefined\n\t/** The interactive half, for `template edit` — injected for the same reason `store` is, and a\n\t * FACTORY rather than a live prompt so no other verb pays stdin for its existence (`prompt.ts`\n\t * has the why). */\n\tprompt?: OpenPrompt | undefined\n}\n\n/** `CliDeps` with every optional dep resolved — what each command is actually handed. */\ninterface Deps {\n\tenv: NodeJS.ProcessEnv\n\texec: Exec\n\tstore: TemplateStore\n\tprompt: OpenPrompt\n}\n\nconst DEFAULT_DEPS: CliDeps = { env: process.env, exec: nodeExec, store: nodeTemplateStore, prompt: realPrompt }\n\n/**\n * Resolve the adapter for the multiplexer this process is inside, failing with a coded `no-mux` error\n * when there is none. The underlying throw is TRANSLATED, never forwarded — `resolveMuxAdapter`\n * names `$TMUX`/`$HERDR_ENV`, which is backend plumbing an agent driving cyber-mux cannot act on; the\n * help names how to get a backend through this CLI instead.\n */\nfunction adapter(deps: Deps): MuxAdapter {\n\ttry {\n\t\treturn resolveMuxAdapter(deps.env, deps.exec)\n\t} catch {\n\t\tthrow noMux()\n\t}\n}\n\n/** No multiplexer around this process — an operation failure (exit 1), not a usage error. */\nfunction noMux(): CliError {\n\treturn new CliError(\n\t\t'no-mux',\n\t\t'no multiplexer detected around this process',\n\t\t'run cyber-mux inside tmux or herdr, or set CYBER_MUX to name one',\n\t\t1,\n\t)\n}\n\n/** A locator that resolved to no live pane — a pane verb's not-found. Exit 1: a real operation\n * failure, distinct from a malformed argument. */\nfunction paneNotFound(locator: string): CliError {\n\treturn new CliError(\n\t\t'pane-not-found',\n\t\t`pane \"${locator}\" matched no live pane`,\n\t\t'list the live panes with: cyber-mux list',\n\t\t1,\n\t)\n}\n\n/**\n * `send text`/`send keys` given a pane but no payload — a usage error (exit 2), the fix is to add the\n * payload. The payload argument is optional at the parser (`[text]`/`[keys...]`) only so a bare\n * `send text` resolves its MISSING pane through `resolveTarget` and lists candidates rather than\n * tripping commander's own payload-missing error first; once a pane is resolved, an absent payload is\n * caught here so the operation never runs on nothing.\n */\nfunction missingSendPayload(verb: 'text' | 'keys'): CliError {\n\treturn verb === 'text'\n\t\t? new CliError(\n\t\t\t\t'missing-argument',\n\t\t\t\t'send text needs the text to type',\n\t\t\t\t'pass the text: cyber-mux send text <pane> <text>',\n\t\t\t\t2,\n\t\t\t)\n\t\t: new CliError(\n\t\t\t\t'missing-argument',\n\t\t\t\t'send keys needs at least one key to press',\n\t\t\t\t'pass one or more keys: cyber-mux send keys <pane> <keys...>',\n\t\t\t\t2,\n\t\t\t)\n}\n\n/** A malformed template name — a usage error (exit 2): the fix is a different name, nothing was\n * attempted. The same family a missing required argument is in. */\nfunction invalidTemplateName(name: string): CliError {\n\treturn new CliError(\n\t\t'invalid-template-name',\n\t\t`invalid template name \"${name}\" — a name must match [a-z0-9][a-z0-9-]* and be a plain filename stem`,\n\t\t'use a lowercase stem like pool-4',\n\t\t2,\n\t)\n}\n\n/**\n * A git/worktree operation that refused or failed — exit 1. A coded surface already on its way out (a\n * `no-mux`, a resolved-template error, an apply failure) passes through untouched rather than being\n * flattened into this generic one. A `WorktreeGitError` is this CLI's own worktree text (a refusal\n * naming `--force`, a primary-checkout guard), which is kept because the frozen worktree refusals are\n * asserted on it. Anything else reaching here comes from the session adapter opening/binding the\n * worktree's pane (`session.tmux.ts`/`session.herdr.ts`) and embeds the backend's own name plus its raw\n * stderr (`withReason`, `exec.lastError`) — AXI #6 forbids leaking a dependency's name or text, so that\n * detail is not load-bearing for the agent and goes to stderr as a diagnostic only; stdout carries this\n * CLI's own coded, translated error.\n */\nfunction reportWorktreeFailure(err: unknown): never {\n\tif (err instanceof CliError) reportError(err)\n\tif (err instanceof WorktreeGitError) {\n\t\treportError(new CliError('worktree-failed', err.message, 'check the worktree path and its state, then re-run', 1))\n\t}\n\tif (err instanceof Error && err.message) process.stderr.write(`${err.message}\\n`)\n\treportError(\n\t\tnew CliError(\n\t\t\t'worktree-failed',\n\t\t\t'the worktree operation failed',\n\t\t\t'check the worktree path and its state, then re-run',\n\t\t\t1,\n\t\t),\n\t)\n}\n\n/**\n * Resolve a locator — a pane id or a human label — to the one pane it names.\n *\n * **Id first, then name.** An id can never be made to mean something else by a person renaming an\n * unrelated pane, so every caller that passes ids today keeps working no matter what anyone labels.\n * That also makes ambiguity a fuzzy-tier condition only: an id hit and a label hit are not peers, so\n * they are not candidates to choose between — the same ladder git, Docker and tmux resolve targets by.\n *\n * **An id is recognized by EXISTENCE, never by syntax.** The question asked is \"does a live pane carry\n * this id?\", not \"does this string look like an id?\". Docker sniffs shape (`sg-` → an id) and it is\n * the cheaper rule, refused here: encoding a backend's id format in the CLI is exactly the backend\n * leak this seam exists to prevent, and every new backend would owe a new syntax rule. It is also\n * wrong on a real case — `%9` is id-SHAPED, but if no pane carries it as an id and one carries it as a\n * label, a sniffer reports a missing pane while the live list finds the label.\n *\n * One `listPanes` read answers both halves, so name support costs the id path a single query and no\n * behavior. The SEAM is untouched: adapters keep receiving concrete ids, and never learn that a name\n * was ever involved.\n *\n * A locator matching NOTHING resolves to itself, deliberately — it is handed to the backend as an id\n * and takes the verb's existing not-found path (exit 1). Failing here instead would make every verb's\n * \"no such pane\" message this function's to write.\n */\nfunction resolveTarget(deps: Deps, a: MuxAdapter, locator: string | undefined): MuxTarget {\n\t// No locator at all is a usage error (exit 2), and it is caught HERE — the single chokepoint every\n\t// pane verb resolves through — so one throw covers them all. The old \"no backend called\" guarantee\n\t// is deliberately gone (CR 95): the live panes ARE enumerated so they can be listed as candidates,\n\t// the caller's deterministic next move after \"missing pane\" folded into the error. A listing that\n\t// cannot be read costs the candidates, not the error — the missing pane is still reported.\n\tif (!locator) {\n\t\tlet listed: LivePane[] = []\n\t\ttry {\n\t\t\tlisted = a.listPanes(deps.exec)\n\t\t} catch {\n\t\t\t// Cannot enumerate; the error carries no candidates and points at `cyber-mux list` instead.\n\t\t}\n\t\tthrow new MissingPaneError(listed.map((p) => ({ id: p.id, label: p.label ?? null, cwd: p.cwd ?? null })))\n\t}\n\tlet panes: LivePane[]\n\ttry {\n\t\tpanes = a.listPanes(deps.exec)\n\t} catch {\n\t\t// A listing that cannot be read must not deny an id that would have worked — the id path never\n\t\t// needed this query. Degrade to the pre-resolution behavior rather than failing the verb.\n\t\treturn { id: locator }\n\t}\n\tif (panes.some((p) => p.id === locator)) return { id: locator }\n\tconst named = panes.filter((p) => p.label === locator)\n\tif (named.length === 1) return { id: named[0]!.id }\n\t// Guessing (first match, most recent, the focused one) would act on a pane the caller never named,\n\t// which is worse than making them look. The caller is present and is the only one who can say.\n\tif (named.length > 1) {\n\t\tthrow new AmbiguousPaneError(\n\t\t\tlocator,\n\t\t\tnamed.map((p) => ({ id: p.id, label: p.label ?? null, cwd: p.cwd ?? null })),\n\t\t)\n\t}\n\treturn { id: locator }\n}\n\n/**\n * Wrap a verb's action so ANY coded failure reports itself on stdout and exits — the one place that\n * turns a `CliError` (an ambiguity, a `no-mux`, a `pane-not-found`, a template refusal) into output, for\n * every verb.\n *\n * Here rather than deeper so the report is the OUTERMOST thing a verb does: by the time it runs, every\n * inner catch-all has already had its chance to rethrow, and nothing can convert an exit-2 usage error\n * into an exit-1 generic failure behind its back. A non-`CliError` is a bug, not a surface — it is\n * rethrown to the top-level handler rather than dressed up as a coded failure.\n */\nfunction guarded<A extends unknown[]>(action: (...args: A) => void): (...args: A) => void {\n\treturn (...args: A) => {\n\t\ttry {\n\t\t\taction(...args)\n\t\t} catch (err) {\n\t\t\tif (err instanceof CliError) reportError(err)\n\t\t\tthrow err\n\t\t}\n\t}\n}\n\n/**\n * `guarded` for an action that awaits — the same contract, and separate rather than a widening of it.\n *\n * Making `guarded` return `void | Promise<void>` would put an ignored promise behind every sync verb's\n * action, where a rejection would escape the guard entirely and surface as an unhandled rejection\n * instead of a coded error. Two functions keeps the sync path provably sync; commander's own\n * `parseAsync` (already what `main` calls) awaits whichever it gets.\n */\nfunction guardedAsync<A extends unknown[]>(action: (...args: A) => Promise<void>): (...args: A) => Promise<void> {\n\treturn async (...args: A) => {\n\t\ttry {\n\t\t\tawait action(...args)\n\t\t} catch (err) {\n\t\t\tif (err instanceof CliError) reportError(err)\n\t\t\tthrow err\n\t\t}\n\t}\n}\n\n/**\n * Run a pane verb's body, translating a backend throw into a `pane-not-found` on the way out.\n *\n * `resolveTarget` hands an unmatched locator to the backend as an id, so a bad target surfaces as the\n * backend's OWN diagnostic — which must never reach the caller: an agent handed a tmux/herdr error\n * cannot act on it through cyber-mux. A `CliError` already on its way out (a `no-mux` from `adapter`,\n * an ambiguity from `resolveTarget`) is a coded surface and passes through untouched; anything else is\n * the multiplexer's raw failure and becomes this CLI's own code and help instead.\n */\nfunction paneVerb(locator: string | undefined, body: () => void): void {\n\ttry {\n\t\tbody()\n\t} catch (err) {\n\t\tif (err instanceof CliError) throw err\n\t\t// A missing locator is pre-empted by `resolveTarget`'s `MissingPaneError` (a `CliError`, rethrown\n\t\t// above), so reaching here means a locator WAS given and the backend rejected it as a pane.\n\t\tthrow paneNotFound(locator ?? '')\n\t}\n}\n\n/**\n * The backend when there is one, `undefined` when there is not — unlike `adapter`, which fails. For\n * verbs whose subject is git (`worktree list`/`remove`): a multiplexer can only ever add to the\n * answer, so its absence must not deny one.\n */\nfunction optionalAdapter(deps: Deps): MuxAdapter | undefined {\n\ttry {\n\t\treturn resolveMuxAdapter(deps.env, deps.exec)\n\t} catch {\n\t\treturn undefined\n\t}\n}\n\n/**\n * One shape for every verb that opens a worktree. `printFields` drops nullish entries, so a bare\n * `worktree add` — which opens nothing — prints exactly what it always did.\n *\n * When the chosen placement cost the workspace grouping, the backend could have grouped this worktree\n * and did not — worth saying out loud. Per axi/'s #9 that next move rides in the payload on STDOUT as\n * a `help[N]:` block, not on stderr the agent never reads; `workspace: null` is the machine-readable\n * half of the same report. `regroupCommand` is the caller's own verb re-stated with `--at workspace`,\n * so the flag that would have grouped it is named as a concrete command. Emitted only when a grouping\n * was actually lost (#9's omit-when-self-contained rule), so `help` never rides along otherwise.\n */\nfunction reportOpenedWorktree(opened: OpenedWorktree, regroupCommand: string): void {\n\tconst help: HelpEntry[] = opened.degraded\n\t\t? [{ message: 'opened ungrouped — pass --at workspace to group it with the repo', command: regroupCommand }]\n\t\t: []\n\toutput(\n\t\t{\n\t\t\troot: opened.worktree.root,\n\t\t\tbranch: opened.worktree.branch,\n\t\t\tpane: opened.target.id,\n\t\t\tworkspace: opened.workspace ?? null,\n\t\t\t...(help.length ? { help } : {}),\n\t\t},\n\t\t() => {\n\t\t\tprintFields({\n\t\t\t\troot: opened.worktree.root,\n\t\t\t\tbranch: opened.worktree.branch,\n\t\t\t\tpane: opened.target.id,\n\t\t\t\tworkspace: opened.workspace,\n\t\t\t})\n\t\t\tprintHelp(help)\n\t\t},\n\t)\n}\n\n/**\n * `--template`, the exact sibling of `--launch`: both answer \"what runs in the space you are opening\",\n * one for a single pane and one for a pool. Mutually exclusive by construction — commander rejects\n * the pair rather than picking a winner.\n */\nfunction templateOption(): Option {\n\t// Conflicts with both `--launch` (one command line for the space) and `--env` (the template owns\n\t// its own panes' env) — each answers \"what is in the space you are opening\", and a template names\n\t// all of it.\n\treturn new Option('--template <name>', 'Named template to build in the opened space').conflicts(['launch', 'env'])\n}\n\n/**\n * Resolve, parse and validate a template — the whole answer BEFORE any side effect. A typo in a\n * template name must never leave a worktree behind, and an invalid template must not either, so every\n * caller runs this before it opens or creates anything.\n */\nfunction resolveTemplate(\n\tdeps: Deps,\n\topts: { name?: string | undefined; file?: string | undefined },\n): ResolvedTemplate & { template: Template } {\n\t// A malformed NAME is a usage error (exit 2), and it is caught HERE — before `resolveTemplateSource` reads —\n\t// so it is told apart from a well-formed name that simply resolves nowhere (exit 1, below). The name\n\t// is a lookup key that must also be a filename; `../../../etc/pwd` must never get as far as a read.\n\tif (opts.name !== undefined && opts.file === undefined && !isValidTemplateName(opts.name)) {\n\t\tthrow invalidTemplateName(opts.name)\n\t}\n\tlet resolved: ResolvedTemplate\n\ttry {\n\t\tresolved = resolveTemplateSource({\n\t\t\tname: opts.name,\n\t\t\tfile: opts.file,\n\t\t\tstore: deps.store,\n\t\t\texec: deps.exec,\n\t\t\tenv: deps.env,\n\t\t})\n\t} catch (err) {\n\t\t// A well-formed name that resolves nowhere is a failed lookup, not malformed input (exit 1). The\n\t\t// message is this CLI's own — it names the directories it searched — so it is kept, not a backend's.\n\t\tthrow new CliError(\n\t\t\t'template-not-found',\n\t\t\terr instanceof Error ? err.message : String(err),\n\t\t\t'list the templates resolvable from here with: cyber-mux template list',\n\t\t\t1,\n\t\t)\n\t}\n\tlet parsed: unknown\n\ttry {\n\t\tparsed = parseTemplate(resolved.raw)\n\t} catch (err) {\n\t\tthrow new CliError(\n\t\t\t'invalid-template',\n\t\t\t`${resolved.path}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t'fix the template JSON, then re-run',\n\t\t\t1,\n\t\t)\n\t}\n\t// A template's CONTENT being invalid is a predicate answer (exit 1), not a usage error — the\n\t// invocation was well-formed, the fix is to the file. Every error at once, one per line, each naming\n\t// its own JSON path — first-only would make a template with three mistakes take three runs to fix.\n\tconst errors = validateTemplate(parsed, resolved.stem)\n\tif (errors.length > 0) {\n\t\tthrow new CliError('invalid-template', errors.join('\\n'), 'fix the fields named above, then re-run', 1)\n\t}\n\treturn { ...resolved, template: parsed as Template }\n}\n\n/** The apply manifest — the handoff. `printFields`/`printTable` for humans, the raw object for json. */\nfunction reportManifest(manifest: TemplateManifest, extra: Record<string, string | null> = {}): void {\n\toutput({ ...extra, ...manifest }, () => {\n\t\tprintFields({ ...extra, template: manifest.template, cwd: manifest.cwd, workspace: manifest.workspace })\n\t\tprintTable(manifest.panes, [\n\t\t\t{ label: 'label', get: (p) => p.label ?? '' },\n\t\t\t{ label: 'pane', get: (p) => p.pane },\n\t\t\t{ label: 'dir', get: (p) => p.dir },\n\t\t\t{ label: 'command', get: (p) => p.command ?? '' },\n\t\t])\n\t})\n}\n\n/**\n * A walk that threw reports what it BUILT and exits 1, killing nothing. Rolling back would mean\n * killing panes, and a kill is not obviously safer than a half-built template the caller can see and\n * finish.\n */\nfunction reportApplyFailure(err: unknown, extra: Record<string, string | null> = {}): never {\n\tif (err instanceof TemplateApplyError) {\n\t\t// The manifest is the WHOLE of stdout — one result payload, with the failed pane named inside it,\n\t\t// never a second structured error concatenated after it. The message is supplementary debug, so it\n\t\t// goes to stderr: moving it to stdout would break the \"stdout carries exactly one payload\" invariant\n\t\t// the stream decision rests on.\n\t\treportManifest(err.manifest, extra)\n\t\tprocess.stderr.write(`${err.message}\\n`)\n\t\tprocess.exit(1)\n\t}\n\t// A totally-failed apply that produced no result — a predictable pre-open failure (a missing dir\n\t// names the pane and the resolved path). Its message is this CLI's own text, exit 1.\n\tthrow new CliError(\n\t\t'template-apply-failed',\n\t\terr instanceof Error ? err.message : String(err),\n\t\t'check the template and the target directory, then re-run',\n\t\t1,\n\t)\n}\n\nfunction templateListCommand(deps: Deps): Command {\n\treturn new Command('list')\n\t\t.description('Every template resolvable from here, with its source and pane count')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\tguarded(() => {\n\t\t\t\tconst dirs = templateDirs(deps.exec, deps.env)\n\t\t\t\tconst templates = listTemplates(deps.store, dirs).map((entry) => {\n\t\t\t\t\t// A template that does not parse still LISTS — `list` answers \"what is here\", and\n\t\t\t\t\t// `validate` answers \"is it any good\". Conflating them would hide a broken file entirely.\n\t\t\t\t\tlet panes = 0\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst raw = deps.store.read(entry.path)\n\t\t\t\t\t\tif (raw) panes = collectPanes(resolveTree(parseTemplate(raw) as Template)).length\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tpanes = 0\n\t\t\t\t\t}\n\t\t\t\t\treturn { ...entry, panes }\n\t\t\t\t})\n\t\t\t\toutput({ templates }, () =>\n\t\t\t\t\tprintTable(templates, [\n\t\t\t\t\t\t{ label: 'name', get: (l) => l.name },\n\t\t\t\t\t\t{ label: 'source', get: (l) => l.source },\n\t\t\t\t\t\t{ label: 'panes', get: (l) => String(l.panes) },\n\t\t\t\t\t\t{ label: 'shadowed', get: (l) => (l.shadowed ? 'yes' : '') },\n\t\t\t\t\t]),\n\t\t\t\t)\n\t\t\t}),\n\t\t)\n}\n\nfunction templateShowCommand(deps: Deps): Command {\n\treturn new Command('show')\n\t\t.description('Print a resolved template as JSON')\n\t\t.argument('[name]', 'Template name')\n\t\t.option('--file <path>', 'Read this path instead, skipping resolution entirely')\n\t\t.option('--desugar', 'Print the canonical tree panes/arrange expands to — exactly what apply builds')\n\t\t.action(\n\t\t\tguarded((name: string | undefined, opts: { file?: string | undefined; desugar?: boolean | undefined }) => {\n\t\t\t\tif (!name && !opts.file) {\n\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t'missing-argument',\n\t\t\t\t\t\t'template show needs a template name or --file <path>',\n\t\t\t\t\t\t'pass a template name, or --file <path>',\n\t\t\t\t\t\t2,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tconst { template } = resolveTemplate(deps, { name, file: opts.file })\n\t\t\t\t// One desugarer, so `--desugar` and the walk can never disagree about what a flat template means.\n\t\t\t\tconsole.log(JSON.stringify(opts.desugar ? resolveTree(template) : template, null, 2))\n\t\t\t}),\n\t\t)\n}\n\nfunction templateValidateCommand(deps: Deps): Command {\n\treturn new Command('validate')\n\t\t.description('Validate a template — exit 0 valid, 1 invalid, every error at once with a JSON path')\n\t\t.argument('[name]', 'Template name')\n\t\t.option('--file <path>', 'Validate this path instead, skipping resolution entirely')\n\t\t.action(\n\t\t\tguarded((name: string | undefined, opts: { file?: string | undefined }) => {\n\t\t\t\tif (!name && !opts.file) {\n\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t'missing-argument',\n\t\t\t\t\t\t'template validate needs a template name or --file <path>',\n\t\t\t\t\t\t'pass a template name, or --file <path>',\n\t\t\t\t\t\t2,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\t// resolveTemplate already fails with every error, one per line. Reaching here means valid, and\n\t\t\t\t// a valid template says nothing at all — this is the CI hook, so silence is the pass signal.\n\t\t\t\tresolveTemplate(deps, { name, file: opts.file })\n\t\t\t}),\n\t\t)\n}\n\n/**\n * `save` is the one verb here that reads a multiplexer rather than a file, and the only one that\n * WRITES: it captures a live region into a named template, so a pool built by hand once can be named\n * rather than hand-written. That is the schema's one real authoring cost — a 4+ pane grid needs\n * nested `split` nodes nobody wants to type.\n *\n * **What it saves is a draft, and the file says so.** A capture recovers geometry, labels and dirs;\n * it never recovers commands, because what a backend can report about a running pane is a resolved,\n * machine-local command line rather than a portable one (`template-capture.ts` has the why). A saved\n * template therefore lands with no `command` on any pane\n * and is immediately listed by `template list` alongside finished ones, so the draft has to announce\n * itself IN the file — hence the `description` default. Saying it only on stderr would put the\n * warning everywhere except where the reader is.\n *\n * `--to` defaults to `repo`, matching resolution's own precedence: a template is a statement about\n * how the PROJECT is worked on, and that is the copy worth having by default.\n *\n * **`save`'s subject is a REGION and stays one.** `--workspace` widens it to every tab of the\n * workspace the caller's region sits in — one captured tab per live tab, each with its own derived\n * tree, the exact inverse of the tabs walk. It is opt-in rather than the default because widening the\n * default silently would rewrite what `save` has always meant for every caller already relying on it.\n * The bare form does not stay quiet about the narrowing, though: capturing one tab of three notes on\n * stderr what it left out, rather than letting a caller believe a 3-tab workspace round-trips from a\n * 1-tab template.\n */\nfunction templateSaveCommand(deps: Deps): Command {\n\treturn new Command('save')\n\t\t.description('Capture the live region around a pane into a named template')\n\t\t.argument('<name>', 'Name for the captured template')\n\t\t.option('--from <pane>', \"Pane whose region to capture; defaults to this process's own pane\")\n\t\t.option('--workspace', \"Capture every tab of the caller's workspace, as a tabs template\")\n\t\t.option('--description <text>', 'Description to record in the template')\n\t\t.addOption(\n\t\t\tnew Option('--to <source>', 'Which templates directory to write to').choices(['repo', 'user']).default('repo'),\n\t\t)\n\t\t.option('--force', 'Overwrite an existing template of this name')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.addHelpText(\n\t\t\t'after',\n\t\t\t'\\nA capture recovers geometry, labels and dirs — NOT commands. A backend can often say what is\\n' +\n\t\t\t\t'RUNNING, but it reports the resolved command line rather than the one you typed (`nr web dev`\\n' +\n\t\t\t\t'comes back as `node /run/user/1000/fnm_multishells/.../bin/nr web dev`), which is not portable\\n' +\n\t\t\t\t'to another machine — so every pane is saved without one.\\n' +\n\t\t\t\t'\\nFill them in before the template is worth applying:\\n' +\n\t\t\t\t' cyber-mux template edit <name> # list the panes\\n' +\n\t\t\t\t' cyber-mux template edit <name> --set 1=claude # fill one in',\n\t\t)\n\t\t.action(\n\t\t\tguarded(\n\t\t\t\t(\n\t\t\t\t\tname: string,\n\t\t\t\t\topts: {\n\t\t\t\t\t\tfrom?: string | undefined\n\t\t\t\t\t\tworkspace?: boolean | undefined\n\t\t\t\t\t\tdescription?: string | undefined\n\t\t\t\t\t\tto: 'repo' | 'user'\n\t\t\t\t\t\tforce?: boolean | undefined\n\t\t\t\t\t},\n\t\t\t\t) => {\n\t\t\t\t\t// Before the multiplexer is touched: a name is a lookup key that must also be a filename, so an\n\t\t\t\t\t// unusable one should not cost a region read to find out. A usage error (exit 2), the same\n\t\t\t\t\t// malformed-name family `show` refuses at 2.\n\t\t\t\t\tif (!isValidTemplateName(name)) throw invalidTemplateName(name)\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst path = join(templateDirs(deps.exec, deps.env)[opts.to], `${name}.json`)\n\t\t\t\t\t\t// Checked BEFORE the capture, so a refusal costs nothing — and refused by default, because a\n\t\t\t\t\t\t// template is hand-edited after it is saved (the commands are added by hand) and silently\n\t\t\t\t\t\t// overwriting one would throw that work away.\n\t\t\t\t\t\tif (!opts.force && deps.store.read(path) !== null) {\n\t\t\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t\t\t'template-exists',\n\t\t\t\t\t\t\t\t`template \"${name}\" already exists at ${path} — pass --force to overwrite it`,\n\t\t\t\t\t\t\t\t're-run with --force to replace it',\n\t\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\t\t// The geometry-capability refusal is UNCONDITIONAL and so outranks the missing-pane usage\n\t\t\t\t\t\t// error below: a backend that cannot report geometry (or enumerate a workspace) cannot be\n\t\t\t\t\t\t// captured for ANY pane, so no --from rescues it. Telling such a caller to \"pass --from\"\n\t\t\t\t\t\t// would send them down a dead end — pass it, rerun, and get exit 1 anyway. So the\n\t\t\t\t\t\t// backend-unsupported refusal (exit 1) is raised BEFORE the target is resolved. The DECISION\n\t\t\t\t\t\t// stays in the library: throw its typed `CaptureUnsupportedError`, mapped to\n\t\t\t\t\t\t// `backend-unsupported` in the catch below, so the message and exit code are single-source.\n\t\t\t\t\t\t// Each mode asks only for the member it needs (a backend is never refused for lacking one\n\t\t\t\t\t\t// this run would not call), matching the derive orchestrator's own check.\n\t\t\t\t\t\tif (!(opts.workspace ? a.regions?.describeWorkspace : a.regions?.describeRegion)) {\n\t\t\t\t\t\t\tthrow new CaptureUnsupportedError(a.name, opts.workspace ? 'workspace' : 'region')\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// `--from` names a pane explicitly; otherwise capture around the pane THIS process sits in,\n\t\t\t\t\t\t// which is what makes a bare `template save pool-4` mean \"the screen I am looking at\".\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// Through the same resolver every flat verb uses, rather than the `{ id: opts.from }` this\n\t\t\t\t\t\t// built inline: `--from` is a pane locator like any other, and a name that works on `read`\n\t\t\t\t\t\t// and silently means nothing here is the drift a second spelling guarantees. The caller's\n\t\t\t\t\t\t// OWN pane needs no resolution — `callerPane` already answers with a concrete id.\n\t\t\t\t\t\tconst target = opts.from ? resolveTarget(deps, a, opts.from) : callerPane(a, deps.env)\n\t\t\t\t\t\tif (!target) {\n\t\t\t\t\t\t\t// A required parameter is missing, not an operation that failed — a usage error (exit 2).\n\t\t\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t\t\t'missing-pane',\n\t\t\t\t\t\t\t\t'template save needs a pane to capture the region around — pass --from <pane>, or run it inside one',\n\t\t\t\t\t\t\t\t'pass --from <pane>, or run template save inside a pane',\n\t\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst captureOpts = { name, description: opts.description ?? CAPTURED_DESCRIPTION }\n\t\t\t\t\t\t// The orchestrators re-check the same seam member and refuse the same way — that check is\n\t\t\t\t\t\t// their own library contract (it is what makes the template/capture refusal provable at that\n\t\t\t\t\t\t// node, independent of this verb). The early guard above only fixes the ORDER relative to the\n\t\t\t\t\t\t// missing-pane error; reaching here, the member is already known present.\n\t\t\t\t\t\tconst { template, warnings } = opts.workspace\n\t\t\t\t\t\t\t? deriveWorkspaceCapture(a, deps.exec, target, captureOpts)\n\t\t\t\t\t\t\t: deriveRegionCapture(a, deps.exec, target, captureOpts)\n\t\t\t\t\t\tdeps.store.write(path, `${JSON.stringify(template, null, 2)}\\n`)\n\t\t\t\t\t\t// A capture warning (a dir outside the repo root) is a diagnostic, not part of the answer —\n\t\t\t\t\t\t// it stays on stderr, where `capture.feature` pins it. The PAYLOAD is stdout.\n\t\t\t\t\t\tfor (const warning of warnings) process.stderr.write(`${warning}\\n`)\n\t\t\t\t\t\t// save's stdout is a structured payload: a `path` field, plus a `help[N]:` block only when a\n\t\t\t\t\t\t// bare save left tabs behind (#9's reveal-a-truncated-list, omitted otherwise). This replaces\n\t\t\t\t\t\t// the bare path, so programmatic composition reads `--format json | jq -r .path` instead.\n\t\t\t\t\t\tconst entry = opts.workspace ? null : noteTabsLeftOut(deps, a, target, name)\n\t\t\t\t\t\tconst help: HelpEntry[] = entry ? [entry] : []\n\t\t\t\t\t\toutput({ path, ...(help.length ? { help } : {}) }, () => {\n\t\t\t\t\t\t\tprintFields({ path })\n\t\t\t\t\t\t\tprintHelp(help)\n\t\t\t\t\t\t})\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t// A coded failure (the refusals above, an ambiguity, a no-mux) is already a surface and\n\t\t\t\t\t\t// passes through to `guarded`. Anything else is a capture that could not produce a tree — a\n\t\t\t\t\t\t// region no splits could have built, or an empty one — reported under this CLI's own code,\n\t\t\t\t\t\t// never the backend's raw text. Exit 1: the capture failed, the invocation was well-formed.\n\t\t\t\t\t\tif (err instanceof CliError) throw err\n\t\t\t\t\t\t// The library's geometry-capability refusal: the DECISION is the orchestrator's; the exit\n\t\t\t\t\t\t// code, the fix hint and the exact sentence are this CLI's, composed from the backend name\n\t\t\t\t\t\t// and which seam was missing. Exit 1 — a genuine operation failure, not a usage error.\n\t\t\t\t\t\tif (err instanceof CaptureUnsupportedError) throw backendUnsupported(err)\n\t\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t\t'unsplittable-region',\n\t\t\t\t\t\t\t'this region could not be captured — it is not a tree any sequence of splits could have produced',\n\t\t\t\t\t\t\t'template save can only capture a region built by splitting',\n\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t\t)\n}\n\n/**\n * What a bare `save` left behind: a `help` entry when the caller's workspace holds tabs this capture\n * did not take, so the capture is honest about its own scope rather than letting a caller believe a\n * 3-tab workspace round-trips from a 1-tab template.\n *\n * Per axi/'s #9 this reveal rides in `save`'s stdout payload as a `help[N]:` block, not on stderr the\n * agent never reads — programmatic composition reads the path from `--format json`, not bare stdout.\n * It is a NOTE rather than a refusal: the template the caller asked for is correct and is already\n * written. Which is also why this is best-effort — a workspace read that fails or that the backend\n * cannot do at all returns `null` (no entry), costing the caller a courtesy, not their capture. An\n * untagged window on a backend with no workspace tier reports one tab and yields nothing, which is\n * right — a window nobody grouped is a workspace of one, and nothing was left out. The `command`\n * re-states the caller's own `name` with `--workspace`, the flag that captures every tab.\n */\n/**\n * The CLI surface of the library's geometry-capability refusal: exit 1 (a genuine operation failure,\n * not a usage error), naming the backend, with the flag-specific fix hint. The DECISION to refuse is\n * the orchestrator's (`CaptureUnsupportedError`); this composes only the presentation from the two\n * structured fields the error carries, so the sentence lives in one place per surface.\n */\nfunction backendUnsupported(err: CaptureUnsupportedError): CliError {\n\treturn err.capability === 'region'\n\t\t? new CliError(\n\t\t\t\t'backend-unsupported',\n\t\t\t\t`${err.backend} cannot report a region's geometry — template save needs a backend that can`,\n\t\t\t\t'run template save on a backend that reports geometry (tmux or herdr)',\n\t\t\t\t1,\n\t\t\t)\n\t\t: new CliError(\n\t\t\t\t'backend-unsupported',\n\t\t\t\t`${err.backend} cannot enumerate a workspace's tabs — template save --workspace needs a backend that can`,\n\t\t\t\t'run template save --workspace on a backend that enumerates tabs (tmux or herdr)',\n\t\t\t\t1,\n\t\t\t)\n}\n\nfunction noteTabsLeftOut(deps: Deps, adapter: MuxAdapter, target: MuxTarget, name: string): HelpEntry | null {\n\tconst describeWorkspace = adapter.regions?.describeWorkspace\n\tif (!describeWorkspace) return null\n\tlet tabs: number\n\ttry {\n\t\ttabs = describeWorkspace(deps.exec, target).length\n\t} catch {\n\t\treturn null\n\t}\n\tif (tabs <= 1) return null\n\treturn {\n\t\tmessage:\n\t\t\t`this pane's workspace holds ${tabs} tabs — only the caller's own region was captured. ` +\n\t\t\t'Pass --workspace to capture every tab of it',\n\t\tcommand: `cyber-mux template save ${name} --workspace`,\n\t}\n}\n\n/**\n * The default `description` on a captured template — the draft warning, written where the reader\n * actually is. A saved capture is listed by `template list` next to finished templates and shows up in\n * `template show`, so a note that only ever reached the terminal that ran `save` would be gone by the\n * time anyone reads the file. Overridden by `--description`, since an author who names the template's\n * purpose has said something more useful than this.\n */\nconst CAPTURED_DESCRIPTION = 'Captured from a live region — geometry only; add a command to each pane.'\n\n/**\n * `edit` is `save`'s other half, and exists because of what `save` cannot do: a capture recovers\n * geometry, labels and dirs and lands with no `command` on any pane (`template-capture.ts` has the\n * why), so a saved template is a draft that is worth nothing until every command is filled in. Doing\n * that by hand means opening JSON and counting braces to work out which leaf is the pane on the left.\n *\n * **Three modes, and the DEFAULT is the one an agent uses.** AXI's no-interactive-prompts rule is not\n * a preference here — a verb whose only mode is a conversation is unusable by the caller this CLI is\n * built for, and a prompt against a pipe hangs with nothing on screen to say why. So:\n *\n * - bare — LIST the panes and what each says. AXI #8's content-first home view, and the half of the\n * agent's loop that makes the other half possible: the `pane` column prints exactly the token\n * `--set` takes, so acting on the listing is a paste rather than a derivation.\n * - `--set <pane>=<value>` — the mutation, complete with flags alone, repeatable, idempotent.\n * - `--interactive` — the guided walk, for a human filling a fresh capture in one pass.\n *\n * **Line-based rather than a TUI even in the interactive mode.** A full-screen editor would need a\n * rendering dependency in a package that has exactly one, and a raw-mode event loop the synchronous\n * `Exec` seam every other verb is built on cannot express.\n *\n * **Nothing is written until every answer is in and the result validates.** `applyEdits` clones, so a\n * refusal costs the author nothing and there is never a half-edited template on disk — which is what\n * lets Ctrl-D mean \"abandon this\" rather than \"commit whatever I happened to have typed\", and what\n * makes a `--set` batch naming one bad pane write none of them.\n */\nfunction templateEditCommand(deps: Deps): Command {\n\treturn new Command('edit')\n\t\t.description('Show a template’s panes, and fill them in with --set or --interactive')\n\t\t.argument('[name]', 'Template name')\n\t\t.option('--file <path>', 'Edit this path instead, skipping resolution entirely')\n\t\t.option(\n\t\t\t'--set <pane=value>',\n\t\t\t'Set the field on a pane, e.g. --set 1=claude (repeatable; empty value clears)',\n\t\t\t(value: string, previous: string[]) => [...previous, value],\n\t\t\t[] as string[],\n\t\t)\n\t\t.option('-i, --interactive', 'Ask one question per pane instead, pre-filling the current value')\n\t\t.addOption(\n\t\t\tnew Option('--field <field>', 'Which field --set and --interactive write')\n\t\t\t\t.choices(['command', 'label'])\n\t\t\t\t.default('command'),\n\t\t)\n\t\t.option('--dry-run', 'Print the edited template instead of writing it')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.addHelpText(\n\t\t\t'after',\n\t\t\t'\\nPanes are addressed by ordinal, never by label (two panes may share one): \"3\" in a\\n' +\n\t\t\t\t'single-region template, \"2.3\" for tab 2 pane 3. Run the bare form to see them.\\n' +\n\t\t\t\t'\\nExamples\\n' +\n\t\t\t\t' cyber-mux template edit pool-4 # list the panes\\n' +\n\t\t\t\t' cyber-mux template edit pool-4 --set 1=claude # fill one in\\n' +\n\t\t\t\t' cyber-mux template edit pool-4 --set 2=\"pnpm dev\" --set 3= # set two, clear one\\n' +\n\t\t\t\t' cyber-mux template edit pool-4 --field label --set 1=planner\\n' +\n\t\t\t\t' cyber-mux template edit pool-4 --interactive # one prompt per pane',\n\t\t)\n\t\t.action(\n\t\t\tguardedAsync(\n\t\t\t\tasync (\n\t\t\t\t\tname: string | undefined,\n\t\t\t\t\topts: {\n\t\t\t\t\t\tfile?: string\n\t\t\t\t\t\tset: string[]\n\t\t\t\t\t\tinteractive?: boolean\n\t\t\t\t\t\tfield: EditField\n\t\t\t\t\t\tdryRun?: boolean\n\t\t\t\t\t\tformat?: string\n\t\t\t\t\t},\n\t\t\t\t) => {\n\t\t\t\t\tif (!name && !opts.file) {\n\t\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t\t'missing-argument',\n\t\t\t\t\t\t\t'template edit needs a template name or --file <path>',\n\t\t\t\t\t\t\t'pass a template name, or --file <path>',\n\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\t// Two ways of saying what to write, given together, cannot be reconciled — the same\n\t\t\t\t\t// malformed-input family `--template` with `--launch` is in (exit 2).\n\t\t\t\t\tif (opts.interactive && opts.set.length > 0) {\n\t\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t\t'conflicting-options',\n\t\t\t\t\t\t\t'template edit takes --set or --interactive, not both',\n\t\t\t\t\t\t\t'pass --set for a scripted edit, or --interactive to be asked pane by pane',\n\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tconst resolved = resolveTemplate(deps, { name, file: opts.file })\n\t\t\t\t\tconst slots = planEdits(resolved.template)\n\t\t\t\t\tif (slots.length === 0) {\n\t\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t\t'empty-template',\n\t\t\t\t\t\t\t`template \"${resolved.stem}\" declares no panes to edit`,\n\t\t\t\t\t\t\t'check the template with: cyber-mux template validate',\n\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\t// The bare form MUTATES NOTHING. It is the listing, so an agent that runs the verb to find\n\t\t\t\t\t// out what is there cannot accidentally change anything by doing so.\n\t\t\t\t\tif (!opts.interactive && opts.set.length === 0) {\n\t\t\t\t\t\tprintSlots(resolved, slots, opts.field)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconst answers = opts.interactive\n\t\t\t\t\t\t? await interactiveAnswers(deps, resolved, slots, opts.field)\n\t\t\t\t\t\t: setAnswers(slots, opts.set, opts.field)\n\t\t\t\t\tconst edited = applyEdits(resolved.template, answers)\n\t\t\t\t\t// Belt-and-braces, and honestly so: `resolveTemplate` already validated on the way in, and\n\t\t\t\t\t// neither field this verb offers can be made invalid (both are free strings), so today this\n\t\t\t\t\t// cannot fire. It is here because `--field` is the seam that grows — a `dir` can escape the\n\t\t\t\t\t// apply-time root and a `ratio` can leave `(0,1)`, and the moment one of those is offered\n\t\t\t\t\t// this is the check that stops an answer from writing a template apply would then refuse.\n\t\t\t\t\tconst errors = validateTemplate(edited, resolved.stem)\n\t\t\t\t\tif (errors.length > 0) {\n\t\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t\t'invalid-template',\n\t\t\t\t\t\t\t`those answers would make \"${resolved.stem}\" invalid:\\n${errors.join('\\n')}`,\n\t\t\t\t\t\t\t'give a value the schema accepts',\n\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tif (opts.dryRun) {\n\t\t\t\t\t\tconsole.log(JSON.stringify(edited, null, 2))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\t// Unchanged writes nothing at all, and exits 0 — AXI's idempotent-mutation rule. Re-running the\n\t\t\t\t\t// same `--set` is a no-op rather than an error, and a walk the author pressed Enter through\n\t\t\t\t\t// leaves the file's mtime alone: a template is checked in, and a no-op edit that dirtied the\n\t\t\t\t\t// working tree would show up as a change in review that is not one.\n\t\t\t\t\tif (answers.length > 0) deps.store.write(resolved.path, `${JSON.stringify(edited, null, 2)}\\n`)\n\t\t\t\t\toutput({ path: resolved.path, changed: answers.length }, () =>\n\t\t\t\t\t\tprintFields({ path: resolved.path, changed: String(answers.length) }),\n\t\t\t\t\t)\n\t\t\t\t},\n\t\t\t),\n\t\t)\n}\n\n/**\n * The listing — AXI #8's content-first view, and the first half of an agent's list-then-act loop.\n *\n * The `pane` column is `slotRef`, which is verbatim what `--set` takes: an identifier a caller has to\n * transform before reusing is an identifier that invites transforming it wrong. `position` is here\n * for the same reason it is in the prompt — apply order is a tree walk, not a reading order, so an\n * ordinal alone cannot tell a caller which pane on screen it is about to write to.\n */\nfunction printSlots(resolved: ResolvedTemplate & { template: Template }, slots: EditSlot[], field: EditField): void {\n\tconst missing = slots.filter((slot) => slot[field] === undefined)\n\tconst panes = slots.map((slot) => ({\n\t\tpane: slotRef(slot),\n\t\ttab: slot.tabLabel ?? (slot.tab === undefined ? '' : String(slot.tab + 1)),\n\t\tposition: slot.position ?? '',\n\t\tlabel: slot.label ?? '',\n\t\tdir: slot.dir ?? '',\n\t\tcommand: slot.command ?? '',\n\t}))\n\t// #9 disclosure: what to do next, parameterized rather than guessed. The name is echoed back from\n\t// what the caller actually passed, so the suggestion is runnable as printed.\n\tconst subject = resolved.source === 'file' ? `--file ${resolved.path}` : resolved.stem\n\tconst help: HelpEntry[] = []\n\tif (missing.length > 0) {\n\t\thelp.push({\n\t\t\tmessage: `${missing.length} of ${slots.length} panes have no ${field} — a template applies without one, but the pane just sits at a shell`,\n\t\t\tcommand: `cyber-mux template edit ${subject} --set ${slotRef(missing[0]!)}=<${field}>`,\n\t\t})\n\t}\n\thelp.push({\n\t\tmessage: 'Fill them in one prompt at a time, with the current value pre-filled',\n\t\tcommand: `cyber-mux template edit ${subject} --interactive`,\n\t})\n\toutput({ path: resolved.path, field, panes, help }, () => {\n\t\tprintFields({ template: resolved.stem, path: tildify(resolved.path), source: resolved.source })\n\t\tprintTable(panes, [\n\t\t\t{ label: 'pane', get: (p) => p.pane },\n\t\t\t// Dropped entirely for a single-region template rather than printed empty — a column of blanks\n\t\t\t// is a claim that there is a tab tier to think about, and there is not.\n\t\t\t...(resolved.template.tabs ? [{ label: 'tab', get: (p: (typeof panes)[number]) => p.tab }] : []),\n\t\t\t{ label: 'position', get: (p) => p.position },\n\t\t\t{ label: 'label', get: (p) => p.label },\n\t\t\t{ label: 'dir', get: (p) => p.dir },\n\t\t\t{ label: field, get: (p) => (field === 'label' ? p.label : p.command) },\n\t\t])\n\t\tprintHelp(help)\n\t})\n}\n\n/**\n * `--set` resolved against the listing's own identifiers.\n *\n * The parse and the lookup both throw plain `Error`s from the pure module; they become coded usage\n * errors HERE, at the boundary that owns exit codes. Exit 2 rather than 1 for the same reason\n * `invalidTemplateName` is a 2: the fix is a different argument, and nothing was attempted.\n */\nfunction setAnswers(slots: EditSlot[], specs: string[], field: EditField): EditAnswer[] {\n\ttry {\n\t\treturn resolveSets(slots, specs.map(parseSet), field)\n\t} catch (err) {\n\t\tthrow new CliError(\n\t\t\t'invalid-set',\n\t\t\terr instanceof Error ? err.message : String(err),\n\t\t\t'list the panes and their identifiers with: cyber-mux template edit <name>',\n\t\t\t2,\n\t\t)\n\t}\n}\n\n/**\n * The guided walk's answers — the interactive mode's whole body, kept out of the action so the two\n * mutation paths meet at exactly one place (`applyEdits`) and cannot drift on validation or writing.\n */\nasync function interactiveAnswers(\n\tdeps: Deps,\n\tresolved: ResolvedTemplate & { template: Template },\n\tslots: EditSlot[],\n\tfield: EditField,\n): Promise<EditAnswer[]> {\n\t// A prompt against a pipe would block forever with nothing on screen to say why — the one failure\n\t// mode an agent driving this CLI cannot diagnose or escape. `--format json|agent` is refused for the\n\t// same reason even on a tty: a caller asking for machine output has said it is not a human.\n\tif (!process.stdin.isTTY || isAutomatedOutput()) {\n\t\tthrow new CliError(\n\t\t\t'not-interactive',\n\t\t\t'template edit --interactive asks questions and needs a terminal',\n\t\t\t'set the values directly instead: cyber-mux template edit <name> --set <pane>=<value>',\n\t\t\t2,\n\t\t)\n\t}\n\tconst inputs = await askSlots(deps, resolved, slots, field)\n\t// `undefined` is Ctrl-D — the human left. Nothing is written, and it is a failure rather than a\n\t// quiet success so a caller that wrapped this can tell an abandoned edit from a finished one.\n\tif (!inputs) {\n\t\tthrow new CliError(\n\t\t\t'edit-aborted',\n\t\t\t`edit of \"${resolved.stem}\" abandoned — nothing was written`,\n\t\t\t'run it again to start over',\n\t\t\t1,\n\t\t)\n\t}\n\treturn toAnswers(slots, inputs, field)\n}\n\n/**\n * The walk itself: a header, then one question per pane, in apply order.\n *\n * Returns `undefined` the moment the prompt reports EOF, rather than collecting a partial list —\n * \"the human left\" has to reach the caller as one fact, and a short array would be indistinguishable\n * from a walk where the last few panes were skipped.\n *\n * The prompt is closed in a `finally` because it owns stdin: a throw from anywhere in the walk that\n * left it open would hang the process at exit with no output, turning a diagnosable error into a\n * silent freeze.\n */\nasync function askSlots(\n\tdeps: Deps,\n\tresolved: ResolvedTemplate & { template: Template },\n\tslots: EditSlot[],\n\tfield: EditField,\n): Promise<EditInput[] | undefined> {\n\tconst tabs = resolved.template.tabs?.length\n\tconst scope = tabs ? `${tabs} tabs, ${slots.length} panes` : `${slots.length} panes`\n\tprocess.stdout.write(`\\n${resolved.stem} — ${scope} (${resolved.source}: ${tildify(resolved.path)})\\n`)\n\tprocess.stdout.write(`Enter keeps, \"-\" clears, Ctrl-D abandons.\\n\\n`)\n\tconst prompt = deps.prompt()\n\tconst inputs: EditInput[] = []\n\ttry {\n\t\tlet tab: number | undefined\n\t\tfor (const slot of slots) {\n\t\t\t// Printed only when it CHANGES, so a single-region template shows no tab header at all and a\n\t\t\t// tabs template shows each one once — the grouping the author sees matches the one in the file.\n\t\t\tif (slot.tab !== undefined && slot.tab !== tab) {\n\t\t\t\ttab = slot.tab\n\t\t\t\t// The count is the tab's OWN, not the walk's — a tabs template's panes are numbered within\n\t\t\t\t// each tab, so \"4 panes\" here is what the ordinals below actually run to.\n\t\t\t\tconst panes = slots.filter((other) => other.tab === tab).length\n\t\t\t\tconst label = slot.tabLabel ? ` \"${slot.tabLabel}\"` : ''\n\t\t\t\tprocess.stdout.write(` tab ${tab + 1}${label} (${panes} ${panes === 1 ? 'pane' : 'panes'})\\n`)\n\t\t\t}\n\t\t\tconst line = await prompt.ask(` ${describeSlot(slot, field)} `, slot[field])\n\t\t\tif (line === undefined) return undefined\n\t\t\tinputs.push(readEditInput(line))\n\t\t}\n\t} finally {\n\t\tprompt.close()\n\t}\n\treturn inputs\n}\n\n/**\n * One pane's prompt text: which pane, what already identifies it, and the field being asked for.\n *\n * The context shown is every field EXCEPT the one being edited — a pane is told apart by its dir and\n * its label, and echoing the current value here would duplicate what the pre-filled line already\n * shows. Panes carry no identity of their own beyond their ordinal (a label is a name two panes may\n * share, by design), so the ordinal always leads.\n *\n * **The position leads the rest of the context**, because it is the only part that answers the\n * question the author is actually asking — which pane on my screen is this? Apply order is a tree\n * walk rather than a reading order, so pane 2 of a 2x2 is the one BELOW pane 1, not the one beside\n * it; without a bearing the ordinal alone invites filling the right command into the wrong pane.\n */\nfunction describeSlot(slot: EditSlot, field: EditField): string {\n\tconst context = [\n\t\tslot.position ?? null,\n\t\tslot.label !== undefined && field !== 'label' ? `label: ${slot.label}` : null,\n\t\tslot.dir !== undefined ? `dir: ${slot.dir}` : null,\n\t\tslot.command !== undefined && field !== 'command' ? `command: ${slot.command}` : null,\n\t].filter((part) => part !== null)\n\tconst indent = slot.tab === undefined ? '' : ' '\n\treturn `${indent}pane ${slot.index + 1}${context.length ? ` (${context.join(', ')})` : ''} ${field}?`\n}\n\n/**\n * The `template` group manages templates — there is deliberately no `template apply`. Applying is what\n * `open` and `worktree add` already do, told to build N panes instead of one, so it is `--template` on\n * those verbs.\n *\n * `list` / `show` / `validate` take a FILE as their subject and touch no multiplexer. `save` is the\n * exception in both respects — it reads a live region and writes a file — and it belongs here anyway:\n * it AUTHORS a template, which is what this group is for.\n */\nfunction templateCommand(deps: Deps): Command {\n\tconst cmd = new Command('template').description('Manage named templates (apply one with open/worktree --template)')\n\tcmd.addCommand(templateListCommand(deps))\n\tcmd.addCommand(templateShowCommand(deps))\n\tcmd.addCommand(templateValidateCommand(deps))\n\tcmd.addCommand(templateSaveCommand(deps))\n\tcmd.addCommand(templateEditCommand(deps))\n\treturn cmd\n}\n\nfunction doctorCommand(deps: Deps): Command {\n\treturn new Command('doctor')\n\t\t.description('Probe the multiplexer, self pane, and backend; print fast-path pins')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(() => {\n\t\t\tconst probe = probeMultiplexer(deps.exec, deps.env)\n\t\t\tconst self = currentPane(deps.env)\n\t\t\tlet backend = 'none'\n\t\t\ttry {\n\t\t\t\tbackend = resolveMuxAdapter(deps.env, deps.exec).name\n\t\t\t} catch {\n\t\t\t\t// no backend — reported as 'none'\n\t\t\t}\n\t\t\tconst data = {\n\t\t\t\tmux: probe.mux,\n\t\t\t\tvia: probe.via,\n\t\t\t\tpane: self?.pane ?? probe.pane ?? null,\n\t\t\t\tbackend,\n\t\t\t}\n\t\t\toutput(data, () => {\n\t\t\t\tprintFields({\n\t\t\t\t\tmultiplexer: data.mux,\n\t\t\t\t\t'detected via': data.via,\n\t\t\t\t\tpane: data.pane ?? '(none)',\n\t\t\t\t\tbackend: data.backend,\n\t\t\t\t})\n\t\t\t\tif (self) {\n\t\t\t\t\tconsole.log('')\n\t\t\t\t\tconsole.log('Pin the fast-path to skip detection:')\n\t\t\t\t\tconsole.log(` export CYBER_MUX=${self.mux} CYBER_MUX_PANE=${self.pane}`)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n}\n\nfunction modeCommand(deps: Deps): Command {\n\treturn new Command('mode')\n\t\t.description('Report the detected session backend (tmux / herdr / none)')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(() => {\n\t\t\tlet name = 'none'\n\t\t\ttry {\n\t\t\t\tname = resolveMuxAdapter(deps.env, deps.exec).name\n\t\t\t} catch {\n\t\t\t\t// no backend — reported as 'none'\n\t\t\t}\n\t\t\toutput({ backend: name }, () => console.log(name))\n\t\t})\n}\n\nfunction openCommand(deps: Deps): Command {\n\treturn new Command('open')\n\t\t.description('Open a new pane/tab/workspace, optionally launching a command in it')\n\t\t.option('--launch <command>', 'Command line to run in the new pane')\n\t\t.addOption(templateOption())\n\t\t.option('--cwd <path>', 'Working directory for the new pane', process.cwd())\n\t\t.addOption(AT_OPTION)\n\t\t.addOption(ENV_OPTION)\n\t\t.addOption(LABEL_OPTION)\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\tguarded(\n\t\t\t\t(opts: {\n\t\t\t\t\tlaunch?: string | undefined\n\t\t\t\t\ttemplate?: string | undefined\n\t\t\t\t\tcwd: string\n\t\t\t\t\tat?: MuxPlacement | undefined\n\t\t\t\t\tenv?: Record<string, string> | undefined\n\t\t\t\t\tlabel?: string | undefined\n\t\t\t\t}) => {\n\t\t\t\t\tif (opts.template) {\n\t\t\t\t\t\t// Resolve and validate BEFORE touching a backend, so an unresolvable name opens nothing.\n\t\t\t\t\t\tconst { template } = resolveTemplate(deps, { name: opts.template })\n\t\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\treportManifest(\n\t\t\t\t\t\t\t\topenTemplate(deps.exec, a, template, {\n\t\t\t\t\t\t\t\t\tcwd: opts.cwd,\n\t\t\t\t\t\t\t\t\t// A fresh space is empty by construction, which is why the pool defaults there.\n\t\t\t\t\t\t\t\t\tat: opts.at ?? 'workspace',\n\t\t\t\t\t\t\t\t\tlabel: opts.label ?? template.name,\n\t\t\t\t\t\t\t\t\tdirExists: deps.store.dirExists,\n\t\t\t\t\t\t\t\t\tnewId: nodeNewId,\n\t\t\t\t\t\t\t\t\tfrom: callerPane(a, deps.env),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\treportApplyFailure(err)\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\tconst t = a.open(deps.exec, {\n\t\t\t\t\t\tcwd: opts.cwd,\n\t\t\t\t\t\tlaunch: opts.launch,\n\t\t\t\t\t\tat: opts.at,\n\t\t\t\t\t\tenv: opts.env,\n\t\t\t\t\t\tlabel: opts.label,\n\t\t\t\t\t\tfrom: callerPane(a, deps.env),\n\t\t\t\t\t})\n\t\t\t\t\t// The workspace rides in on the open itself — the backend answered when the pane was born, so\n\t\t\t\t\t// reporting it asks nothing extra; hiding it would discard a fact already in hand. `?? null`\n\t\t\t\t\t// on the JSON side only, matching `reportOpenedWorktree`: absent is the seam's meaning, null\n\t\t\t\t\t// is its spelling at the machine-readable boundary.\n\t\t\t\t\toutput({ pane: t.id, workspace: t.workspace ?? null }, () =>\n\t\t\t\t\t\tprintFields({ pane: t.id, workspace: t.workspace }),\n\t\t\t\t\t)\n\t\t\t\t},\n\t\t\t),\n\t\t)\n}\n\n/** The `send` group: drive a pane's input WITHOUT taking its turn. Neither subcommand presses an\n * Enter the caller did not write — supplying one is `submit`'s job. Bare `cyber-mux send` is\n * incomplete input, not a content request: it is answered with help on stdout and exit 2 (a usage\n * error — a missing required parameter; see the AXI note in `.agents/spec/axi/README.md`). */\nfunction sendCommand(deps: Deps): Command {\n\tconst send = new Command('send').description('Drive a pane without taking its turn (text | keys)')\n\tsend.addCommand(\n\t\tnew Command('text')\n\t\t\t.description('Type literal text into a pane, pressing no Enter (a key-named word is typed, not pressed)')\n\t\t\t.argument('[pane]', 'Target pane id')\n\t\t\t.argument('[text]', 'Literal text to type')\n\t\t\t.addOption(FORMAT_OPTION)\n\t\t\t.action(\n\t\t\t\tguarded((pane: string | undefined, text: string | undefined) => {\n\t\t\t\t\tpaneVerb(pane, () => {\n\t\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\t\t// A missing pane resolves to a candidate listing here (exit 2); an absent text with a pane\n\t\t\t\t\t\t// given is its own usage error, caught after resolution so the pane check outranks it.\n\t\t\t\t\t\tconst target = resolveTarget(deps, a, pane)\n\t\t\t\t\t\tif (text === undefined) throw missingSendPayload('text')\n\t\t\t\t\t\ta.sendText(deps.exec, target, text)\n\t\t\t\t\t})\n\t\t\t\t}),\n\t\t\t),\n\t)\n\tsend.addCommand(\n\t\tnew Command('keys')\n\t\t\t.description('Press named keys in a pane, typing nothing (Up, Enter, Escape, C-c, F1 …)')\n\t\t\t.argument('[pane]', 'Target pane id')\n\t\t\t.argument(\n\t\t\t\t'[keys...]',\n\t\t\t\t'Key names, in order — core vocabulary is portable, anything else is passed to the backend as-is',\n\t\t\t)\n\t\t\t.addOption(FORMAT_OPTION)\n\t\t\t.action(\n\t\t\t\tguarded((pane: string | undefined, keys: string[]) => {\n\t\t\t\t\tpaneVerb(pane, () => {\n\t\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\t\tconst target = resolveTarget(deps, a, pane)\n\t\t\t\t\t\tif (keys.length === 0) throw missingSendPayload('keys')\n\t\t\t\t\t\ta.sendKeys(deps.exec, target, keys)\n\t\t\t\t\t})\n\t\t\t\t}),\n\t\t\t),\n\t)\n\treturn send\n}\n\nfunction submitCommand(deps: Deps): Command {\n\treturn new Command('submit')\n\t\t.description(\"Take a pane's turn: type the text if given, then always press Enter (no text = bare-Enter flush)\")\n\t\t.argument('[pane]', 'Target pane id')\n\t\t.argument('[text]', 'Text to type before Enter; omit to flush an already-staged buffer without retyping it')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\tguarded((pane: string | undefined, text: string | undefined) => {\n\t\t\t\tpaneVerb(pane, () => {\n\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\ta.submit(deps.exec, resolveTarget(deps, a, pane), text)\n\t\t\t\t})\n\t\t\t}),\n\t\t)\n}\n\nfunction readCommand(deps: Deps): Command {\n\treturn new Command('read')\n\t\t.description(\"Capture a pane's output\")\n\t\t.argument('[pane]', 'Target pane id')\n\t\t.option('--lines <n>', 'Trailing lines to capture', (v) => Number.parseInt(v, 10))\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\tguarded((pane: string | undefined, opts: { lines?: number | undefined }) => {\n\t\t\t\tpaneVerb(pane, () => {\n\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\tconst t = resolveTarget(deps, a, pane)\n\t\t\t\t\t// A failed read captures nothing — there are no bytes for an error to land amid, so `paneVerb`\n\t\t\t\t\t// throwing here means stdout is the structured error alone, with no partial pane output before it.\n\t\t\t\t\tconst out = a.read(deps.exec, t, opts.lines != null ? { lines: opts.lines } : undefined)\n\t\t\t\t\tprocess.stdout.write(out.endsWith('\\n') ? out : `${out}\\n`)\n\t\t\t\t})\n\t\t\t}),\n\t\t)\n}\n\n/** The default deadline a bare `wait` takes. Named, not spelled inline, so the help text and the value\n * cannot drift. Chosen to be long enough for a harness to boot and print, short enough that an agent\n * that guessed the wrong pattern gets its answer back inside one turn. */\nconst DEFAULT_WAIT_TIMEOUT_MS = 30_000\n\n/**\n * The `wait` verb: block until a pane PRINTS something, or the deadline passes.\n *\n * Agent-first in the two ways that matter here. First, the verdict is in the EXIT CODE — 0 matched, 1\n * timed out — so a shell caller branches without parsing anything, exactly as `exists` separates live\n * from gone. Second, a timeout is a normal answer and prints the same `{matched, output}` payload a\n * match does, so an agent that guessed wrong sees what the pane actually said instead of an error with\n * the evidence thrown away.\n *\n * It is its own verb rather than `read --wait <pattern>` because the two answer different questions —\n * `read` reports a snapshot and always succeeds; this one asserts a condition and can fail — and folding\n * them would make `read`'s exit code depend on a flag.\n *\n * The PATTERN is validated before the pane is resolved, which is the one place this verb orders its two\n * usage errors: a missing pattern is answered without a `listPanes` round trip, and candidate panes are\n * no use to a caller that has not said what it is waiting for. A missing PANE then takes the same\n * `MissingPaneError` (candidates listed) every other pane verb takes, from the one chokepoint that owns\n * it — which is why `[pane]` is optional at the parser and required in fact.\n */\nfunction waitCommand(deps: Deps): Command {\n\treturn new Command('wait')\n\t\t.description(\"Block until a pane's output matches, or the timeout elapses (exit 0 = matched, 1 = timed out)\")\n\t\t.argument('[pane]', 'Target pane id')\n\t\t.option('--match <text>', 'Literal substring to wait for')\n\t\t.option('--regex <pattern>', 'Regular expression to wait for (backend dialect; prefer --match)')\n\t\t.option(\n\t\t\t'--timeout <ms>',\n\t\t\t`Give up after this many ms (default ${DEFAULT_WAIT_TIMEOUT_MS})`,\n\t\t\t(v) => Number.parseInt(v, 10),\n\t\t\tDEFAULT_WAIT_TIMEOUT_MS,\n\t\t)\n\t\t.option('--lines <n>', 'Restrict the searched snapshot to this many trailing lines', (v) => Number.parseInt(v, 10))\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\tguardedAsync(\n\t\t\t\tasync (\n\t\t\t\t\tpane: string | undefined,\n\t\t\t\t\topts: {\n\t\t\t\t\t\tmatch?: string | undefined\n\t\t\t\t\t\tregex?: string | undefined\n\t\t\t\t\t\ttimeout: number\n\t\t\t\t\t\tlines?: number | undefined\n\t\t\t\t\t},\n\t\t\t\t) => {\n\t\t\t\t\tconst pattern = waitPattern(opts)\n\t\t\t\t\tif (!Number.isFinite(opts.timeout) || opts.timeout < 0) throw invalidWaitTimeout(opts.timeout)\n\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\t// Resolution runs BEFORE the wait: an ambiguous locator must not consume the whole timeout\n\t\t\t\t\t// before reporting that the question had no single pane to be about.\n\t\t\t\t\tconst t = resolveTarget(deps, a, pane)\n\t\t\t\t\tconst result = await a\n\t\t\t\t\t\t.waitForOutput(deps.exec, t, {\n\t\t\t\t\t\t\t...pattern,\n\t\t\t\t\t\t\ttimeoutMs: opts.timeout,\n\t\t\t\t\t\t\t...(opts.lines != null ? { lines: opts.lines } : {}),\n\t\t\t\t\t\t})\n\t\t\t\t\t\t// A gone pane throws out of the seam; it is this CLI's `pane-not-found`, not a raw backend\n\t\t\t\t\t\t// diagnostic — `paneVerb`'s translation, applied to an async body.\n\t\t\t\t\t\t.catch((err) => {\n\t\t\t\t\t\t\tif (err instanceof CliError) throw err\n\t\t\t\t\t\t\t// A missing locator never reaches here — `resolveTarget` already threw its\n\t\t\t\t\t\t\t// `MissingPaneError` above — so this is `paneVerb`'s translation applied to an async\n\t\t\t\t\t\t\t// body: a backend throw becomes this CLI's own coded not-found.\n\t\t\t\t\t\t\tthrow paneNotFound(pane ?? '')\n\t\t\t\t\t\t})\n\t\t\t\t\toutput({ pane: t.id, ...result }, () => {\n\t\t\t\t\t\tprintFields({\n\t\t\t\t\t\t\tpane: t.id,\n\t\t\t\t\t\t\tmatched: String(result.matched),\n\t\t\t\t\t\t\tline: result.matchedLine ?? null,\n\t\t\t\t\t\t})\n\t\t\t\t\t})\n\t\t\t\t\tif (!result.matched) process.exit(1)\n\t\t\t\t},\n\t\t\t),\n\t\t)\n}\n\n/** Exactly one of `--match`/`--regex`, as the seam requires — refused HERE so the caller gets this CLI's\n * coded usage error (exit 2, the fix is a different invocation) rather than the seam's bare throw. */\nfunction waitPattern(opts: { match?: string | undefined; regex?: string | undefined }): {\n\tmatch?: string\n\tregex?: string\n} {\n\tif (opts.match != null && opts.regex != null) {\n\t\tthrow new CliError(\n\t\t\t'usage-error',\n\t\t\t'--match and --regex are mutually exclusive',\n\t\t\t'pass one pattern: cyber-mux wait <pane> --match <text>',\n\t\t\t2,\n\t\t)\n\t}\n\tif (opts.match != null) return { match: opts.match }\n\tif (opts.regex != null) {\n\t\ttry {\n\t\t\tnew RegExp(opts.regex)\n\t\t} catch {\n\t\t\tthrow new CliError(\n\t\t\t\t'usage-error',\n\t\t\t\t`--regex is not a valid expression: ${opts.regex}`,\n\t\t\t\t'pass a valid pattern, or a literal with --match instead',\n\t\t\t\t2,\n\t\t\t)\n\t\t}\n\t\treturn { regex: opts.regex }\n\t}\n\tthrow new CliError(\n\t\t'usage-error',\n\t\t'wait needs a pattern — pass --match or --regex',\n\t\t'wait for a literal: cyber-mux wait <pane> --match <text>',\n\t\t2,\n\t)\n}\n\n/** A `--timeout` that is not a non-negative number — a usage error: nothing was attempted, and the fix\n * is a different invocation. */\nfunction invalidWaitTimeout(timeout: number): CliError {\n\treturn new CliError(\n\t\t'usage-error',\n\t\t`--timeout must be a non-negative number of milliseconds — got ${timeout}`,\n\t\t'pass milliseconds: cyber-mux wait <pane> --match <text> --timeout 30000',\n\t\t2,\n\t)\n}\n\nfunction focusCommand(deps: Deps): Command {\n\treturn new Command('focus')\n\t\t.description('Beam the attached client to a pane')\n\t\t.argument('[pane]', 'Target pane id')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\tguarded((pane: string | undefined) => {\n\t\t\t\tpaneVerb(pane, () => {\n\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\ta.focus(deps.exec, resolveTarget(deps, a, pane))\n\t\t\t\t})\n\t\t\t}),\n\t\t)\n}\n\nfunction closeCommand(deps: Deps): Command {\n\treturn new Command('close')\n\t\t.description('Close a pane')\n\t\t.argument('[pane]', 'Target pane id')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\tguarded((pane: string | undefined) => {\n\t\t\t\tpaneVerb(pane, () => {\n\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\ta.teardown(deps.exec, resolveTarget(deps, a, pane))\n\t\t\t\t})\n\t\t\t}),\n\t\t)\n}\n\nfunction listCommand(deps: Deps): Command {\n\treturn new Command('list')\n\t\t.description('Enumerate every live pane the current backend can see')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\tguarded(() => {\n\t\t\t\tconst panes = adapter(deps).listPanes(deps.exec)\n\t\t\t\t// The agent-status column earns its slot only when a pane actually carries the field — true on\n\t\t\t\t// herdr (the one backend with a per-pane agent-state feed), constant-absent on tmux/wezterm/\n\t\t\t\t// zellij. A constant-absent column discriminates nothing (axi.md #2, the same rule that drops\n\t\t\t\t// the constant `mux` column), so it is suppressed on those backends rather than printed empty.\n\t\t\t\t// The JSON payload keeps `agentStatus` per pane regardless — column suppression is a\n\t\t\t\t// human-table concern, and a structured consumer reads the field straight off the pane.\n\t\t\t\tconst hasAgent = panes.some((p) => p.agentStatus !== undefined)\n\t\t\t\tconst cols: { label: string; get: (p: LivePane) => string }[] = [\n\t\t\t\t\t{ label: 'pane', get: (p) => p.id },\n\t\t\t\t\t// `label` takes the slot `mux` held. Every row of one listing reports the same mux — one\n\t\t\t\t\t// adapter is selected per session, so the column is constant by construction and\n\t\t\t\t\t// discriminates nothing. The label is what a caller now types INSTEAD of the id, so it is\n\t\t\t\t\t// the fact this row exists to carry. `doctor` is where the backend is a live question.\n\t\t\t\t\t{ label: 'label', get: (p) => p.label ?? '' },\n\t\t\t\t\t{ label: 'harness', get: (p) => p.harness ?? '' },\n\t\t\t\t\t{ label: 'cwd', get: (p) => p.cwd ?? '' },\n\t\t\t\t]\n\t\t\t\tif (hasAgent) cols.push({ label: 'agent', get: (p) => p.agentStatus ?? '' })\n\t\t\t\toutput({ panes }, () => printTable(panes, cols))\n\t\t\t}),\n\t\t)\n}\n\nfunction existsCommand(deps: Deps): Command {\n\treturn new Command('exists')\n\t\t.description('Probe whether a single pane is still live (exit 0 = live, 1 = gone)')\n\t\t.argument('[pane]', 'Target pane id')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\tguarded((pane: string | undefined) => {\n\t\t\t\tconst a = adapter(deps)\n\t\t\t\t// Resolution runs BEFORE any output: an ambiguous locator throws out of here, so `live`/`gone`\n\t\t\t\t// is never printed for a question that has no single pane to be about.\n\t\t\t\tconst t = resolveTarget(deps, a, pane)\n\t\t\t\tconst live = a.paneExists(deps.exec, t)\n\t\t\t\toutput({ pane, live }, () => console.log(live ? 'live' : 'gone'))\n\t\t\t\tif (!live) process.exit(1)\n\t\t\t}),\n\t\t)\n}\n\n/**\n * The CLI surface of the library's agent-wait refusal: exit 1 (a genuine operation failure, not a\n * usage error), naming the backend, with a fix hint pointing at the herdr-only constraint. The\n * DECISION to refuse is the orchestrator's (`AgentLifecycleUnsupportedError`); this composes only the\n * presentation, so the sentence lives in one place — the exact mirror of how `backendUnsupported`\n * surfaces `CaptureUnsupportedError` for `template save`.\n */\nfunction agentUnsupported(err: AgentLifecycleUnsupportedError): CliError {\n\treturn new CliError(\n\t\t'backend-unsupported',\n\t\t`${err.backend} cannot wait on agent-lifecycle state — agent wait needs a backend with a native per-pane agent-state feed (herdr)`,\n\t\t'run agent wait on herdr, the only backend with a native agent-state feed',\n\t\t1,\n\t)\n}\n\n/**\n * `agent status <pane>` — a SNAPSHOT that degrades, never refuses. It resolves a pane through the\n * shared ladder and prints its `agentStatus`, a fact independent of whether the backend can WAIT on it\n * (that is `agent wait`'s herdr-only capability). A backend with no agent-state feed still answers\n * truthfully — the pane, with no status — and exits 0: refusing here would turn a caller away from a\n * fact the backend CAN answer (which pane this is) because of one it can't (what its agent is doing),\n * and the two are independent.\n */\nfunction agentStatusCommand(deps: Deps): Command {\n\treturn new Command('status')\n\t\t.description(\"Print a pane's agent-lifecycle status (herdr); degrades to no status on a backend with no feed\")\n\t\t.argument('[pane]', 'Target pane id or label')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\tguarded((pane: string | undefined) => {\n\t\t\t\tconst a = adapter(deps)\n\t\t\t\tconst target = resolveTarget(deps, a, pane)\n\t\t\t\t// The status rides on the same live listing a name resolves from. A listing that cannot be\n\t\t\t\t// read degrades to \"no status\" rather than failing the snapshot — the pane is still named.\n\t\t\t\tlet agentStatus: AgentStatus | undefined\n\t\t\t\ttry {\n\t\t\t\t\tagentStatus = a.listPanes(deps.exec).find((p) => p.id === target.id)?.agentStatus\n\t\t\t\t} catch {\n\t\t\t\t\tagentStatus = undefined\n\t\t\t\t}\n\t\t\t\toutput({ pane: target.id, agentStatus: agentStatus ?? null }, () =>\n\t\t\t\t\tprintFields({ pane: target.id, agentStatus }),\n\t\t\t\t)\n\t\t\t}),\n\t\t)\n}\n\n/**\n * `agent wait <pane>` — a blocking DRIVE of herdr's native `agent wait`, or a refusal naming the\n * backend on one without the capability. Unlike `agent status`, waiting has no truthful degrade, so a\n * backend with no agent-lifecycle primitive is refused (`backend-unsupported`, exit 1) rather than\n * answered with a guess — the exact mirror of how `template save` refuses a geometry-incapable backend.\n *\n * The refusal is checked BEFORE the pane is resolved so a name that resolves nowhere never masks the\n * herdr-only refusal; the orchestrator (`deriveAgentWait`) re-checks the same seam member, that check\n * being its own library contract. `--until` is repeatable (omit to take herdr's default set) and\n * `--timeout` is optional (omit for an indefinite wait).\n */\nfunction agentWaitCommand(deps: Deps): Command {\n\treturn new Command('wait')\n\t\t.description(\"Block until a pane's agent reaches a state (herdr); refused on a backend with no agent-state feed\")\n\t\t.argument('[pane]', 'Target pane id or label')\n\t\t.option(\n\t\t\t'--until <status...>',\n\t\t\t'Agent states any of which ends the wait (idle, working, blocked, done, unknown); omit for herdr’s default',\n\t\t)\n\t\t.option('--timeout <ms>', 'Milliseconds before the wait gives up; omit to wait indefinitely', (v) =>\n\t\t\tNumber.parseInt(v, 10),\n\t\t)\n\t\t.addOption(FORMAT_OPTION)\n\t\t.addHelpText(\n\t\t\t'after',\n\t\t\t'\\nagent wait drives a native per-pane agent-state feed, which only herdr has — tmux, wezterm and\\n' +\n\t\t\t\t'zellij are refused with backend-unsupported. Use agent status for a snapshot that works everywhere.',\n\t\t)\n\t\t.action(\n\t\t\tguarded((pane: string | undefined, opts: { until?: string[] | undefined; timeout?: number | undefined }) => {\n\t\t\t\tconst a = adapter(deps)\n\t\t\t\t// Refuse a backend with no agent-lifecycle capability up front — the library's decision,\n\t\t\t\t// surfaced here as backend-unsupported. Checked before the pane is resolved so it outranks any\n\t\t\t\t// resolution outcome, and kept out of the try below so it is never re-dressed as a wait failure.\n\t\t\t\tif (!a.agentLifecycle) throw agentUnsupported(new AgentLifecycleUnsupportedError(a.name))\n\t\t\t\tconst target = resolveTarget(deps, a, pane)\n\t\t\t\tlet reached: AgentStatus\n\t\t\t\ttry {\n\t\t\t\t\treached = deriveAgentWait(a, deps.exec, target, {\n\t\t\t\t\t\tuntil: opts.until as AgentStatus[] | undefined,\n\t\t\t\t\t\ttimeoutMs: opts.timeout,\n\t\t\t\t\t})\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (err instanceof CliError) throw err\n\t\t\t\t\t// Belt-and-braces: the early guard already refused a capability-less backend, but the\n\t\t\t\t\t// orchestrator re-checks as its own contract, so honor its typed refusal here too.\n\t\t\t\t\tif (err instanceof AgentLifecycleUnsupportedError) throw agentUnsupported(err)\n\t\t\t\t\t// A wait the backend accepted but could not complete (an unparseable envelope, a lost pane).\n\t\t\t\t\tthrow new CliError(\n\t\t\t\t\t\t'agent-wait-failed',\n\t\t\t\t\t\terr instanceof Error ? err.message : String(err),\n\t\t\t\t\t\t'check the pane still exists with: cyber-mux exists <pane>',\n\t\t\t\t\t\t1,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\toutput({ pane: target.id, agentStatus: reached }, () => console.log(reached))\n\t\t\t}),\n\t\t)\n}\n\n/**\n * The `agent` group reaches the herdr agent-lifecycle capability: `status` (a snapshot that degrades\n * truthfully) and `wait` (a blocking drive of herdr's native wait, refused on every backend without\n * it). The state feed itself is herdr's; this group is how the CLI reads and blocks on it.\n */\nfunction agentCommand(deps: Deps): Command {\n\tconst cmd = new Command('agent').description(\"Inspect and wait on a pane's agent-lifecycle state (herdr)\")\n\tcmd.addCommand(agentStatusCommand(deps))\n\tcmd.addCommand(agentWaitCommand(deps))\n\treturn cmd\n}\n\nfunction worktreeAddCommand(deps: Deps): Command {\n\treturn new Command('add')\n\t\t.description('Create a git worktree, and open it when given a placement — grouped where the backend can')\n\t\t.requiredOption('--branch <branch>', 'Branch to create the worktree on')\n\t\t.option('--path <path>', 'Where to check out the worktree (default: a sibling of the primary checkout)')\n\t\t.option('--base <ref>', 'Start point for the new branch (default: the current HEAD)')\n\t\t.option('--launch <command>', 'Command to run in the opened pane; implies --at workspace')\n\t\t.addOption(templateOption())\n\t\t.addOption(AT_OPTION)\n\t\t.addOption(ENV_OPTION)\n\t\t.addOption(LABEL_OPTION)\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\t(opts: {\n\t\t\t\tbranch: string\n\t\t\t\tpath?: string | undefined\n\t\t\t\tbase?: string | undefined\n\t\t\t\tlaunch?: string | undefined\n\t\t\t\ttemplate?: string | undefined\n\t\t\t\tat?: MuxPlacement | undefined\n\t\t\t\tenv?: Record<string, string> | undefined\n\t\t\t\tlabel?: string | undefined\n\t\t\t}) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst primaryRoot = resolvePrimaryRoot(deps.exec)\n\t\t\t\t\t// The primary flow this feature exists for. Resolve and validate FIRST: a typo in a\n\t\t\t\t\t// template name, or a template that sets a cwd, must not leave a worktree behind.\n\t\t\t\t\tif (opts.template) {\n\t\t\t\t\t\tconst { template } = resolveTemplate(deps, { name: opts.template })\n\t\t\t\t\t\tconst path = opts.path ?? resolveWorktreePath(primaryRoot, opts.branch)\n\t\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\t\t// No `launch`: the worktree's workspace opens blank and its root pane becomes the\n\t\t\t\t\t\t// tree's root region — not a wasted pane, the one the walk splits into. Its `env`\n\t\t\t\t\t\t// must ride in HERE, though: no split ever births that pane, so this is the only\n\t\t\t\t\t\t// call that can set it.\n\t\t\t\t\t\tconst opened = addAndOpenWorktree(deps.exec, a, {\n\t\t\t\t\t\t\tprimaryRoot,\n\t\t\t\t\t\t\tbranch: opts.branch,\n\t\t\t\t\t\t\tpath,\n\t\t\t\t\t\t\tbase: opts.base,\n\t\t\t\t\t\t\tenv: templateRootPane(template).env,\n\t\t\t\t\t\t\tat: 'workspace',\n\t\t\t\t\t\t\tlabel: opts.label ?? template.name,\n\t\t\t\t\t\t\tfrom: callerPane(a, deps.env),\n\t\t\t\t\t\t})\n\t\t\t\t\t\tconst extra = { root: opened.worktree.root, branch: opened.worktree.branch }\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\treportManifest(\n\t\t\t\t\t\t\t\tapplyTemplateToRegion(deps.exec, a, template, {\n\t\t\t\t\t\t\t\t\troot: opened.target,\n\t\t\t\t\t\t\t\t\tcwd: opened.worktree.root,\n\t\t\t\t\t\t\t\t\tworkspace: opened.workspace ?? null,\n\t\t\t\t\t\t\t\t\t// The same label the workspace was just opened under — a tabs template carries\n\t\t\t\t\t\t\t\t\t// it into each later tab's name where the backend has no workspace tier.\n\t\t\t\t\t\t\t\t\tlabel: opts.label ?? template.name,\n\t\t\t\t\t\t\t\t\t// The route that opened the region is the only thing that knows whether it\n\t\t\t\t\t\t\t\t\t// could carry the root pane's env; the walk falls back to a prefix when not.\n\t\t\t\t\t\t\t\t\trootEnvHonored: opened.envHonored,\n\t\t\t\t\t\t\t\t\tdirExists: deps.store.dirExists,\n\t\t\t\t\t\t\t\t\tnewId: nodeNewId,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\textra,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\treportApplyFailure(err, extra)\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconst path = opts.path ?? resolveWorktreePath(primaryRoot, opts.branch)\n\t\t\t\t\t// With no placement asked for AND nothing to put IN a pane, this IS a git operation: it\n\t\t\t\t\t// creates a checkout, opens nothing, and needs no multiplexer to be inside of. There is\n\t\t\t\t\t// nothing to group because nothing was opened — `worktree open` groups it later. `--env`\n\t\t\t\t\t// joins `--launch` in this guard: asking for something in a pane is asking for the pane,\n\t\t\t\t\t// so it can no longer be a bare add.\n\t\t\t\t\tif (!opts.at && !opts.launch && !opts.env) {\n\t\t\t\t\t\tconst wt = gitWorktreeAdapter.add(deps.exec, { primaryRoot, path, branch: opts.branch, base: opts.base })\n\t\t\t\t\t\toutput({ root: wt.root, branch: wt.branch, pane: null, workspace: null }, () =>\n\t\t\t\t\t\t\tprintFields({ root: wt.root, branch: wt.branch }),\n\t\t\t\t\t\t)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\t// A launch or an env with no placement wants its own space, not a pane crowding the\n\t\t\t\t\t// caller's — and `workspace` is the only placement a backend can bind a worktree to.\n\t\t\t\t\tconst at = opts.at ?? 'workspace'\n\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\treportOpenedWorktree(\n\t\t\t\t\t\taddAndOpenWorktree(deps.exec, a, {\n\t\t\t\t\t\t\tprimaryRoot,\n\t\t\t\t\t\t\tbranch: opts.branch,\n\t\t\t\t\t\t\tpath,\n\t\t\t\t\t\t\tbase: opts.base,\n\t\t\t\t\t\t\tlaunch: opts.launch,\n\t\t\t\t\t\t\tenv: opts.env,\n\t\t\t\t\t\t\tat,\n\t\t\t\t\t\t\tlabel: opts.label,\n\t\t\t\t\t\t\tfrom: callerPane(a, deps.env),\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t`cyber-mux worktree add --branch ${opts.branch} --at workspace`,\n\t\t\t\t\t)\n\t\t\t\t} catch (err) {\n\t\t\t\t\treportWorktreeFailure(err)\n\t\t\t\t}\n\t\t\t},\n\t\t)\n}\n\n/**\n * `worktree provision` — reuse a free worktree or create a fresh one, the CLI wiring of the\n * `provisionWorktree` seam. The verb uses the DEFAULT availability gate (`isWorktreeRemovable`, the\n * exact set `worktree list` marks `(removable)` and `prune` removes) and offers NO flag to inject a\n * host predicate — that is the surface divergence from the library seam, which takes one. A host that\n * must exclude a live-session worktree calls `WorktreeApi.provision` directly. It reports what it did\n * (`reused` | `created`), the worktree, and on reuse the recycled entry — its prior branch and the\n * workspace it was open in; `printFields` drops the nullish reuse fields on a create.\n */\nfunction worktreeProvisionCommand(deps: Deps): Command {\n\treturn new Command('provision')\n\t\t.description(\n\t\t\t'Reuse a free worktree or create a fresh one — the default-gate wiring of the provision seam (a worktree `list` marks \"(removable)\"). Reports whether it reused or created',\n\t\t)\n\t\t.requiredOption('--branch <branch>', 'Branch the provisioned worktree ends up on')\n\t\t.option('--base <ref>', 'Start point for the fresh branch (default: the resolved default branch, then HEAD)')\n\t\t.option(\n\t\t\t'--path <path>',\n\t\t\t'Where a fresh checkout goes when none is free to reuse (default: a sibling of the primary checkout)',\n\t\t)\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action((opts: { branch: string; base?: string | undefined; path?: string | undefined }) => {\n\t\t\ttry {\n\t\t\t\tconst primaryRoot = resolvePrimaryRoot(deps.exec)\n\t\t\t\tconst path = opts.path ?? resolveWorktreePath(primaryRoot, opts.branch)\n\t\t\t\tconst result = provisionWorktree(deps.exec, primaryRoot, {\n\t\t\t\t\tcreate: { path, branch: opts.branch, base: opts.base },\n\t\t\t\t})\n\t\t\t\tconst reused = result.reused\n\t\t\t\t\t? {\n\t\t\t\t\t\t\troot: result.reused.root,\n\t\t\t\t\t\t\tbranch: result.reused.branch ?? null,\n\t\t\t\t\t\t\tworkspace: result.reused.workspace ?? null,\n\t\t\t\t\t\t}\n\t\t\t\t\t: null\n\t\t\t\toutput({ action: result.action, root: result.worktree.root, branch: result.worktree.branch, reused }, () =>\n\t\t\t\t\tprintFields({\n\t\t\t\t\t\taction: result.action,\n\t\t\t\t\t\troot: result.worktree.root,\n\t\t\t\t\t\tbranch: result.worktree.branch,\n\t\t\t\t\t\t'reused-from': reused ? (reused.branch ?? '(detached)') : undefined,\n\t\t\t\t\t\t'reused-workspace': reused?.workspace ?? undefined,\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t} catch (err) {\n\t\t\t\treportWorktreeFailure(err)\n\t\t\t}\n\t\t})\n}\n\nfunction worktreeOpenCommand(deps: Deps): Command {\n\treturn new Command('open')\n\t\t.description('Open an existing git worktree — groups it with the repo where the backend can bind')\n\t\t.argument('<path>', 'Worktree path to open')\n\t\t.option('--launch <command>', 'Command to run in the opened pane')\n\t\t.addOption(AT_OPTION)\n\t\t.addOption(ENV_OPTION)\n\t\t.addOption(LABEL_OPTION)\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(\n\t\t\t(\n\t\t\t\tpath: string,\n\t\t\t\topts: {\n\t\t\t\t\tlaunch?: string | undefined\n\t\t\t\t\tat?: MuxPlacement | undefined\n\t\t\t\t\tenv?: Record<string, string> | undefined\n\t\t\t\t\tlabel?: string | undefined\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst primaryRoot = resolvePrimaryRoot(deps.exec)\n\t\t\t\t\tconst a = adapter(deps)\n\t\t\t\t\treportOpenedWorktree(\n\t\t\t\t\t\topenExistingWorktree(deps.exec, a, {\n\t\t\t\t\t\t\tprimaryRoot,\n\t\t\t\t\t\t\tpath,\n\t\t\t\t\t\t\tlaunch: opts.launch,\n\t\t\t\t\t\t\tenv: opts.env,\n\t\t\t\t\t\t\tat: opts.at,\n\t\t\t\t\t\t\tlabel: opts.label,\n\t\t\t\t\t\t\tfrom: callerPane(a, deps.env),\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t`cyber-mux worktree open ${path} --at workspace`,\n\t\t\t\t\t)\n\t\t\t\t} catch (err) {\n\t\t\t\t\treportWorktreeFailure(err)\n\t\t\t\t}\n\t\t\t},\n\t\t)\n}\n\nfunction worktreeListCommand(deps: Deps): Command {\n\treturn new Command('list')\n\t\t.description(\n\t\t\t'Every worktree of the repo, and the workspace each is open in — BRANCH is marked \"(*)\" for the primary checkout (every other row is a linked worktree) or \"(removable)\" when the worktree looks disposable (its branch is merged into the default branch, the checkout is clean, and nothing is open in it), and ROOT is marked \"(gone)\" when the checkout no longer exists on disk (git can prune it)',\n\t\t)\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action(() => {\n\t\t\ttry {\n\t\t\t\tconst primaryRoot = resolvePrimaryRoot(deps.exec)\n\t\t\t\tconst worktrees = listWorktrees(deps.exec, optionalAdapter(deps), { primaryRoot })\n\t\t\t\toutput({ worktrees }, () =>\n\t\t\t\t\tprintTable(worktrees, [\n\t\t\t\t\t\t// `linked` is one BIT, so it does not earn a column: the primary checkout — the single\n\t\t\t\t\t\t// row where it is false — is marked in BRANCH instead. The field itself stays intact in\n\t\t\t\t\t\t// `--format json`, where a consumer reads the boolean rather than the marker.\n\t\t\t\t\t\t// `(removable)` is the disposability COMPOSITE — merged AND clean AND unoccupied — compressed to\n\t\t\t\t\t\t// one word, and it rides on BRANCH because the branch is what carries the work that landed.\n\t\t\t\t\t\t// Its inputs (`merged`, `dirty`) stay raw and unmarked in `--format json`, where a consumer\n\t\t\t\t\t\t// composes its own policy rather than inheriting this one.\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: 'branch',\n\t\t\t\t\t\t\tget: (w) =>\n\t\t\t\t\t\t\t\t`${w.branch ?? '(detached)'}${w.linked ? (isWorktreeRemovable(w) ? ' (removable)' : '') : ' (*)'}`,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t// `prunable` is likewise one bit, and a rarer one — the marker rides on ROOT because the\n\t\t\t\t\t\t// path is the thing that is actually gone. `(gone)` is git's own word for a target that\n\t\t\t\t\t\t// vanished (`branch -vv` prints it), where \"stale\" would read as merely out of date.\n\t\t\t\t\t\t{ label: 'root', get: (w) => `${tildify(w.root)}${w.prunable ? ' (gone)' : ''}` },\n\t\t\t\t\t\t{ label: 'workspace', get: (w) => w.workspace ?? '' },\n\t\t\t\t\t]),\n\t\t\t\t)\n\t\t\t} catch (err) {\n\t\t\t\treportWorktreeFailure(err)\n\t\t\t}\n\t\t})\n}\n\nfunction worktreeRemoveCommand(deps: Deps): Command {\n\treturn new Command('remove')\n\t\t.description('Remove a git worktree — refuses the primary checkout and uncommitted changes unless --force')\n\t\t.argument('<path>', 'Worktree path to remove')\n\t\t.option('--force', 'Discard uncommitted changes in the worktree')\n\t\t.action((path: string, opts: { force?: boolean | undefined }) => {\n\t\t\ttry {\n\t\t\t\tconst primaryRoot = resolvePrimaryRoot(deps.exec)\n\t\t\t\tremoveWorktree(deps.exec, optionalAdapter(deps), path, { primaryRoot, force: opts.force })\n\t\t\t} catch (err) {\n\t\t\t\treportWorktreeFailure(err)\n\t\t\t}\n\t\t})\n}\n\n/**\n * The bulk remove — every candidate `worktree list` already marks `(removable)`, gone in one call\n * instead of one `worktree remove` per path.\n *\n * **Bare form previews, `--force` applies.** The gate is destructive (it discards checkouts,\n * irreversibly), so the default has to be the side-effect-free one — a caller can run this to see\n * what WOULD go, exactly as `template edit`'s bare form lists rather than mutates. `--force` here is\n * \"actually do it\", not `removeWorktreeSafely`'s \"discard uncommitted changes\": prune's candidates\n * are already clean by construction (`isWorktreeRemovable` requires `dirty === false`), so there is\n * nothing for that meaning to apply to.\n */\nfunction worktreePruneCommand(deps: Deps): Command {\n\treturn new Command('prune')\n\t\t.description(\n\t\t\t'Remove every disposable worktree in one call — the same gate `worktree list` marks \"(removable)\" with. Bare form previews the candidates; pass --force to actually remove them',\n\t\t)\n\t\t.option('--force', 'Remove the candidates instead of only previewing them')\n\t\t.addOption(FORMAT_OPTION)\n\t\t.action((opts: { force?: boolean | undefined }) => {\n\t\t\ttry {\n\t\t\t\tconst primaryRoot = resolvePrimaryRoot(deps.exec)\n\t\t\t\tconst result = pruneWorktrees(deps.exec, primaryRoot, { dryRun: !opts.force })\n\t\t\t\tconst removed = result.removed.map((entry) => ({ root: entry.root, branch: entry.branch ?? null }))\n\t\t\t\tconst skipped = result.skipped.map((s) => ({\n\t\t\t\t\troot: s.entry.root,\n\t\t\t\t\tbranch: s.entry.branch ?? null,\n\t\t\t\t\treason: s.reason,\n\t\t\t\t}))\n\t\t\t\toutput({ applied: Boolean(opts.force), removed, skipped }, () => {\n\t\t\t\t\tprintTable(removed, [\n\t\t\t\t\t\t{ label: opts.force ? 'removed' : 'would remove', get: (r) => tildify(r.root) },\n\t\t\t\t\t\t{ label: 'branch', get: (r) => r.branch ?? '(detached)' },\n\t\t\t\t\t])\n\t\t\t\t\tif (skipped.length > 0) {\n\t\t\t\t\t\tprintTable(skipped, [\n\t\t\t\t\t\t\t{ label: 'skipped', get: (s) => tildify(s.root) },\n\t\t\t\t\t\t\t{ label: 'reason', get: (s) => s.reason },\n\t\t\t\t\t\t])\n\t\t\t\t\t}\n\t\t\t\t\tif (!opts.force && removed.length > 0) {\n\t\t\t\t\t\tprintHelp([\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmessage: `${removed.length} worktree${removed.length === 1 ? '' : 's'} would be removed`,\n\t\t\t\t\t\t\t\tcommand: 'cyber-mux worktree prune --force',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t])\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t} catch (err) {\n\t\t\t\treportWorktreeFailure(err)\n\t\t\t}\n\t\t})\n}\n\nfunction worktreeCommand(deps: Deps): Command {\n\tconst cmd = new Command('worktree').description('Git worktree helpers for spawning/tearing down a session')\n\tcmd.addCommand(worktreeAddCommand(deps))\n\tcmd.addCommand(worktreeProvisionCommand(deps))\n\tcmd.addCommand(worktreeOpenCommand(deps))\n\tcmd.addCommand(worktreeListCommand(deps))\n\tcmd.addCommand(worktreeRemoveCommand(deps))\n\tcmd.addCommand(worktreePruneCommand(deps))\n\treturn cmd\n}\n\n/**\n * Translate a commander-level rejection into the SAME coded error surface every verb uses. commander's\n * own failures — a flag the command does not define, a required argument the parser never received, two\n * mutually-exclusive flags — are USAGE errors: the fix is a different invocation, not a retry, so they\n * exit 2, and they belong on stdout under a stable code exactly as an operation failure does.\n *\n * The callback is attached per command, so `command` is the SUBCOMMAND actually invoked — which is what\n * lets an unknown flag be rejected against that subcommand's own flags (`template list` does not share\n * `template save`'s), and the offending flag be named beside them so the agent self-corrects in one turn\n * rather than a second `--help` round trip.\n */\nfunction handleCommanderError(command: Command, err: CommanderError): never {\n\t// An explicit `--help`/`--version` is not an error: help is already on stdout, exit 0, and no flag\n\t// validation ever rejects `--help` on any command.\n\tif (err.code === 'commander.helpDisplayed' || err.code === 'commander.version') process.exit(err.exitCode)\n\t// A bare group (`cyber-mux send` with no subcommand, or a bare `cyber-mux`) is incomplete input, not\n\t// a content request: its help belongs on stdout — the stream the agent reads — and it exits 2, the\n\t// status that separates bad input from a failed operation.\n\tif (err.code === 'commander.help') {\n\t\tprocess.stdout.write(command.helpInformation())\n\t\tprocess.exit(2)\n\t}\n\tif (err.code === 'commander.unknownOption') reportError(unknownFlagError(command, err))\n\tif (err.code === 'commander.missingArgument') reportError(missingArgumentError(command, err))\n\tif (err.code === 'commander.conflictingOption' || err.code === 'commander.excessArguments') {\n\t\treportError(\n\t\t\tnew CliError('usage-error', usageMessage(err), 'pass only one of the conflicting flags, then re-run', 2),\n\t\t)\n\t}\n\t// Anything else (an invalid --at choice, an unknown subcommand) keeps commander's own behavior:\n\t// re-thrown to the top-level handler, which honors the exit code commander chose.\n\tthrow err\n}\n\n/** commander's raw message minus its own `error: ` prefix — its own CLI's text, safe to surface. */\nfunction usageMessage(err: CommanderError): string {\n\treturn (err.message ?? '').replace(/^error:\\s*/, '')\n}\n\n/** An unknown flag, named beside the command's OWN valid flags, so the agent self-corrects in one turn. */\nfunction unknownFlagError(command: Command, err: CommanderError): CliError {\n\tconst flag = err.message.match(/'([^']+)'/)?.[1] ?? 'the flag'\n\tconst valid = command.options.map((o) => o.long ?? o.short).filter((f): f is string => Boolean(f))\n\treturn new CliError(\n\t\t'unknown-flag',\n\t\t`unknown flag ${flag} for ${command.name()}`,\n\t\tvalid.length > 0 ? `valid flags for ${command.name()}: ${valid.join(' ')}` : `${command.name()} takes no flags`,\n\t\t2,\n\t)\n}\n\n/** A required argument the parser never received — a usage error naming the missing argument. */\nfunction missingArgumentError(command: Command, err: CommanderError): CliError {\n\tconst arg = err.message.match(/'([^']+)'/)?.[1] ?? 'an argument'\n\treturn new CliError(\n\t\t'missing-argument',\n\t\t`missing required argument: ${arg}`,\n\t\t`provide ${arg}: cyber-mux ${command.name()} <${arg}>`,\n\t\t2,\n\t)\n}\n\n/**\n * Every command in the tree gets a translating `exitOverride` — NOT inherited by subcommands, so it is\n * walked. Without it `cyber-mux send` with no subcommand would `process.exit` straight from the group\n * and kill the caller's process (in tests, the runner itself); with the plain default it would throw a\n * bare `CommanderError`. This routes commander's own rejections through the coded error surface, so a\n * missing argument or unknown flag reaches the caller as an exit-2 structured error on stdout, exactly\n * as an ambiguity or a `no-mux` does.\n */\nfunction exitOverrideTree(command: Command): Command {\n\tcommand.exitOverride((err) => handleCommanderError(command, err))\n\tfor (const sub of command.commands) exitOverrideTree(sub)\n\treturn command\n}\n\n/** Assembles the full command tree against the given deps (real env/exec in production, fakes in\n * tests). Every command in the tree gets `exitOverride()`, so commander throws a `CommanderError`\n * instead of calling `process.exit` directly and a rejection (an invalid `--at` choice, a missing\n * argument, a bare `send`) is catchable both here and in tests, rather than killing the test\n * runner's own process. */\nexport function buildProgram(cliDeps: CliDeps = DEFAULT_DEPS): Command {\n\tconst deps: Deps = {\n\t\tenv: cliDeps.env,\n\t\texec: cliDeps.exec,\n\t\tstore: cliDeps.store ?? nodeTemplateStore,\n\t\tprompt: cliDeps.prompt ?? realPrompt,\n\t}\n\tconst program = new Command()\n\t\t.name('cyber-mux')\n\t\t.description('Cross-multiplexer pane control — one contract over tmux and herdr')\n\t\t.version('0.0.0')\n\n\tprogram.addCommand(doctorCommand(deps))\n\tprogram.addCommand(modeCommand(deps))\n\tprogram.addCommand(openCommand(deps))\n\tprogram.addCommand(sendCommand(deps))\n\tprogram.addCommand(submitCommand(deps))\n\tprogram.addCommand(readCommand(deps))\n\tprogram.addCommand(waitCommand(deps))\n\tprogram.addCommand(focusCommand(deps))\n\tprogram.addCommand(closeCommand(deps))\n\tprogram.addCommand(listCommand(deps))\n\tprogram.addCommand(existsCommand(deps))\n\tprogram.addCommand(worktreeCommand(deps))\n\tprogram.addCommand(templateCommand(deps))\n\tprogram.addCommand(agentCommand(deps))\n\n\treturn exitOverrideTree(program)\n}\n\n/** The real CLI entry point — called explicitly by `bin/cyber-mux.mjs`, never as an import-time\n * side effect, so importing this module (e.g. from tests) never runs the real CLI. */\nexport async function main(): Promise<void> {\n\ttry {\n\t\tawait buildProgram().parseAsync(process.argv)\n\t} catch (err) {\n\t\t// A coded failure that reached here unguarded still owes the caller its structured error on stdout.\n\t\tif (err instanceof CliError) reportError(err)\n\t\t// A commander rejection `handleCommanderError` re-threw (an invalid --at choice, an unknown\n\t\t// subcommand): commander already wrote its own text to stderr, so honor the exit code it chose and\n\t\t// add nothing — re-printing would double it.\n\t\tif (err instanceof CommanderError) process.exit(err.exitCode)\n\t\tprocess.stderr.write(`${err instanceof Error ? err.message : String(err)}\\n`)\n\t\tprocess.exit(1)\n\t}\n}\n"],"mappings":"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"}