ai-advisory-board 0.1.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/CHANGELOG.md +490 -0
- package/LICENSE +201 -0
- package/NOTICE +10 -0
- package/README.md +297 -0
- package/dist/bin/aab.js +16843 -0
- package/dist/bin/aab.js.map +1 -0
- package/gui/app.js +4555 -0
- package/gui/index.html +275 -0
- package/gui/style.css +2312 -0
- package/gui/wikilinks.js +0 -0
- package/package.json +87 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/errors.ts","../../src/core/logger.ts","../../src/llm/claude-code-runner.ts","../../src/core/parsing/safe-json.ts","../../src/core/parsing/llm-response-schemas.ts","../../src/core/prompts/skill-planner.ts","../../src/core/skill/planner.ts","../../src/cli.ts","../../src/ui/colors.ts","../../src/version.ts","../../src/commands/init.ts","../../src/env/detect-claude-code.ts","../../src/core/utils.ts","../../src/ui/prompts.ts","../../src/ui/spinner.ts","../../src/storage/paths.ts","../../src/storage/fs-storage-service.ts","../../src/storage/types.ts","../../src/storage/io.ts","../../src/starter/starter-board-members.ts","../../src/starter/starter-principles.ts","../../src/agents/emit-member-agent.ts","../../src/core/knowledge/schema-emitter.ts","../../src/core/knowledge/slug-map.ts","../../src/core/knowledge/page.ts","../../src/core/knowledge/manifest.ts","../../src/core/knowledge/foam.ts","../../src/core/skill/resolve-skill-creator.ts","../../src/commands/_context.ts","../../src/storage/locks.ts","../../src/commands/settings.ts","../../src/commands/doctor.ts","../../src/core/skill/recon/pc-scan.ts","../../src/core/skill/recon/web-probe.ts","../../src/commands/workspace.ts","../../src/commands/discuss.ts","../../src/ui/render-discussion.ts","../../src/ui/render-discussion-markdown.ts","../../src/core/discussion/conversation-flow.ts","../../src/core/discussion/run-member.ts","../../src/core/discussion/build-user-message.ts","../../src/core/discussion/orchestrator.ts","../../src/core/discussion/summarize.ts","../../src/core/knowledge/ingest.ts","../../src/core/prompts/skill-ingest.ts","../../src/core/sparring/sparring-service.ts","../../src/core/sparring/truncate.ts","../../src/core/sparring/build-sparring-prompt.ts","../../src/core/sparring/inject-insight.ts","../../src/commands/ui.ts","../../src/gui/server.ts","../../src/core/knowledge/rename.ts","../../src/core/knowledge/query.ts","../../src/core/prompts/skill-query.ts","../../src/core/knowledge/lint.ts","../../src/core/actions/conversation-analyzer.ts","../../src/core/members/ai-enhancer.ts","../../src/core/parsing/persona-schemas.ts","../../src/core/members/fallback-voice-guides.ts","../../src/core/members/voice-guide.ts","../../src/core/coach/decision-coach.ts","../../src/core/coach/principle-explorer.ts","../../src/core/skill/solve-orchestrator.ts","../../src/core/skill/recon/wiki-recon.ts","../../src/core/skill/recon/web-recon.ts","../../src/core/skill/recon/orchestrator.ts","../../src/core/skill/planner-review.ts","../../src/core/skill/build-brief.ts","../../src/core/skill/invoke-skill-creator.ts","../../src/core/skill/adapter.ts","../../src/core/skill/install.ts","../../src/core/skill/persist-run.ts","../../src/commands/skills.ts","../../src/core/tokens/usage-summary.ts","../../src/commands/knowledge.ts","../../src/core/knowledge/migrate.ts","../../src/commands/members.ts","../../src/commands/principles.ts","../../src/commands/coach.ts","../../src/commands/actions.ts","../../bin/aab.ts"],"sourcesContent":["/**\r\n * Typed error classes mapped to CLI exit codes.\r\n *\r\n * 0 success\r\n * 1 user error\r\n * 2 model error (Claude API)\r\n * 3 network error\r\n * 4 parse / contract violation\r\n * 5 filesystem error\r\n * 6 cancelled (Ctrl+C)\r\n * 7 budget exceeded\r\n */\r\n\r\nexport type AabExitCode = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;\r\n\r\nexport class AabError extends Error {\r\n public readonly exitCode: AabExitCode;\r\n public readonly hint?: string;\r\n\r\n constructor(message: string, exitCode: AabExitCode, hint?: string) {\r\n super(message);\r\n this.name = 'AabError';\r\n this.exitCode = exitCode;\r\n this.hint = hint;\r\n }\r\n}\r\n\r\nexport class UserError extends AabError {\r\n constructor(message: string, hint?: string) {\r\n super(message, 1, hint);\r\n this.name = 'UserError';\r\n }\r\n}\r\n\r\nexport class ModelError extends AabError {\r\n constructor(message: string, hint?: string) {\r\n super(message, 2, hint);\r\n this.name = 'ModelError';\r\n }\r\n}\r\n\r\nexport class NetworkError extends AabError {\r\n constructor(message: string, hint?: string) {\r\n super(message, 3, hint);\r\n this.name = 'NetworkError';\r\n }\r\n}\r\n\r\nexport class ContractError extends AabError {\r\n constructor(message: string, hint?: string) {\r\n super(message, 4, hint);\r\n this.name = 'ContractError';\r\n }\r\n}\r\n\r\nexport class FsError extends AabError {\r\n constructor(message: string, hint?: string) {\r\n super(message, 5, hint);\r\n this.name = 'FsError';\r\n }\r\n}\r\n\r\nexport class CancelledError extends AabError {\r\n constructor(message = 'Cancelled.') {\r\n super(message, 6);\r\n this.name = 'CancelledError';\r\n }\r\n}\r\n\r\nexport class BudgetError extends AabError {\r\n constructor(message: string, hint?: string) {\r\n super(message, 7, hint);\r\n this.name = 'BudgetError';\r\n }\r\n}\r\n","/**\r\n * Logger.\r\n *\r\n * Levels: silent < error < warn < info < debug < trace.\r\n * stdout is reserved for user-facing command output and --json payloads.\r\n * Logs always go to stderr so `aab ... | jq` is safe.\r\n */\r\n\r\nexport type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug' | 'trace';\r\n\r\nconst LEVEL_ORDER: Record<LogLevel, number> = {\r\n silent: 0,\r\n error: 1,\r\n warn: 2,\r\n info: 3,\r\n debug: 4,\r\n trace: 5,\r\n};\r\n\r\nlet currentLevel: LogLevel = (process.env.AAB_LOG_LEVEL as LogLevel) || 'warn';\r\n\r\nexport function setLogLevel(level: LogLevel): void {\r\n currentLevel = level;\r\n}\r\n\r\nexport function getLogLevel(): LogLevel {\r\n return currentLevel;\r\n}\r\n\r\nfunction enabled(level: LogLevel): boolean {\r\n return LEVEL_ORDER[level] <= LEVEL_ORDER[currentLevel];\r\n}\r\n\r\nfunction emit(level: Exclude<LogLevel, 'silent'>, args: unknown[]): void {\r\n if (!enabled(level)) return;\r\n const prefix = `[aabcli ${level}]`;\r\n // eslint-disable-next-line no-console\r\n console.error(prefix, ...args);\r\n}\r\n\r\nexport const logger = {\r\n error: (...args: unknown[]) => emit('error', args),\r\n warn: (...args: unknown[]) => emit('warn', args),\r\n info: (...args: unknown[]) => emit('info', args),\r\n debug: (...args: unknown[]) => emit('debug', args),\r\n trace: (...args: unknown[]) => emit('trace', args),\r\n};\r\n\r\n/**\r\n * Redact a sensitive value (API keys, full model responses) for log output.\r\n * Shows the first `prefixChars` characters then `***`.\r\n */\r\nexport function redact(value: string | undefined | null, prefixChars = 4): string {\r\n if (!value) return '';\r\n if (value.length <= prefixChars) return '***';\r\n return `${value.slice(0, prefixChars)}***`;\r\n}\r\n","/**\r\n * Claude Code runner.\r\n *\r\n * Instead of calling the Anthropic API directly, the CLI shells out to the\r\n * `claude` binary. This means the user's existing Claude Max/Pro subscription\r\n * is the LLM — no API key, no extra cost.\r\n *\r\n * Pattern (borrowed from aiagentorg's heartbeat.sh):\r\n * claude --agent <slug> -p \"<prompt>\" --output-format json \\\r\n * --model sonnet --allowedTools \"Read,WebSearch,...\"\r\n *\r\n * For one-shot calls without a sub-agent (e.g., orchestrator decisions or\r\n * business-context extraction) we omit `--agent`, which gives a fresh Claude\r\n * Code session with just the prompt + allowed tools.\r\n */\r\nimport { spawn } from 'node:child_process';\r\nimport { existsSync, readFileSync } from 'node:fs';\r\nimport { delimiter, dirname, isAbsolute, join, resolve as resolvePath } from 'node:path';\r\nimport { ModelError, NetworkError } from '../core/errors.js';\r\nimport { logger } from '../core/logger.js';\r\nimport type { ClaudeModel } from '../storage/types.js';\r\n\r\nexport type ClaudeAlias = 'opus' | 'sonnet' | 'haiku' | 'inherit';\r\n\r\nexport interface RunOptions {\r\n /** The prompt to send. Required. */\r\n prompt: string;\r\n /** Sub-agent slug (matches a `.claude/agents/<slug>.md` filename). */\r\n agent?: string;\r\n /** Model alias or full id (passed through to `claude --model`). */\r\n model?: ClaudeAlias | ClaudeModel | string;\r\n /** Tool allowlist passed via --allowedTools (comma-separated). */\r\n allowedTools?: string[];\r\n /** Max conversation turns inside the spawned session. */\r\n maxTurns?: number;\r\n /** Per-call dollar budget passed via --max-budget-usd. */\r\n maxBudgetUsd?: number;\r\n /** Working directory for the spawn (defaults to cwd). */\r\n cwd?: string;\r\n /** External AbortSignal — kills the spawned process when triggered. */\r\n signal?: AbortSignal;\r\n /** Wall-clock timeout in ms (default 5 min). */\r\n timeoutMs?: number;\r\n /** Extra environment variables to set on the child process. */\r\n env?: Record<string, string>;\r\n /**\r\n * Pass `--dangerously-skip-permissions` to bypass Claude Code's trust /\r\n * permission prompts. Safe in our case because each sub-agent's\r\n * `.claude/agents/<slug>.md` already restricts `tools:` to a read/web\r\n * allowlist — even with permissions skipped, the agent cannot execute\r\n * write/edit/bash. Default: true (we always run non-interactively).\r\n */\r\n dangerouslySkipPermissions?: boolean;\r\n /**\r\n * Stream incremental events from the `claude` CLI (uses\r\n * `--output-format stream-json --verbose` under the hood) and invoke\r\n * `onEvent` once per line. Each event is the parsed JSON object the CLI\r\n * printed. The final `result` event has the same shape as the\r\n * non-streaming JSON envelope, so callers can keep using `result.json`.\r\n *\r\n * When `onEvent` is provided we automatically use streaming mode; pass\r\n * `streaming: false` to opt out even if a callback is supplied.\r\n */\r\n onEvent?: (event: ClaudeStreamEvent) => void;\r\n streaming?: boolean;\r\n /**\r\n * Path to a SKILL.md / system-prompt file to APPEND to the default Claude\r\n * Code system prompt. Used by the Phase 5 skill-creator orchestrator:\r\n * `--append-system-prompt-file <path>` makes Claude load the file's\r\n * contents on top of its default behavior, so we can drive any installed\r\n * skill headlessly. Note: this is distinct from `--system-prompt` (which\r\n * REPLACES the default).\r\n */\r\n appendSystemPromptFile?: string;\r\n /**\r\n * Force a specific output format. Defaults to `json` (or `stream-json`\r\n * when an `onEvent` callback is provided). Callers can pass\r\n * `'stream-json'` explicitly to capture tool-use events for any kind of\r\n * call, not just member responses.\r\n */\r\n outputFormat?: 'json' | 'stream-json';\r\n}\r\n\r\n/**\r\n * One event from `claude --output-format stream-json`. The CLI emits one\r\n * JSON object per line. We model the bits we care about; everything else is\r\n * preserved on the index signature for telemetry.\r\n */\r\nexport interface ClaudeStreamEvent {\r\n type: string;\r\n subtype?: string;\r\n session_id?: string;\r\n message?: {\r\n id?: string;\r\n model?: string;\r\n content?: Array<{\r\n type: string;\r\n text?: string;\r\n name?: string;\r\n input?: Record<string, unknown>;\r\n tool_use_id?: string;\r\n }>;\r\n };\r\n result?: string;\r\n cost_usd?: number;\r\n usage?: ClaudeJsonEnvelope['usage'];\r\n num_turns?: number;\r\n is_error?: boolean;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface RunResult {\r\n /** Raw concatenated stdout. */\r\n stdout: string;\r\n /** Concatenated stderr (typically empty on success). */\r\n stderr: string;\r\n /** Exit code from the `claude` process. */\r\n exitCode: number;\r\n /** When --output-format json, the parsed JSON envelope. */\r\n json?: ClaudeJsonEnvelope;\r\n /** Wall-clock duration in ms. */\r\n durationMs: number;\r\n}\r\n\r\n/**\r\n * Shape of `claude --output-format json` output (the bits we use).\r\n */\r\nexport interface ClaudeJsonEnvelope {\r\n type?: string;\r\n subtype?: string;\r\n /** Final assistant message text (this is what we want for member responses). */\r\n result?: string;\r\n /** Per-call cost in USD. */\r\n cost_usd?: number;\r\n /** Token usage breakdown. */\r\n usage?: {\r\n input_tokens?: number;\r\n output_tokens?: number;\r\n cache_creation_input_tokens?: number;\r\n cache_read_input_tokens?: number;\r\n };\r\n /** Number of turns the agent took. */\r\n num_turns?: number;\r\n /** Anything else the CLI emits — preserved for telemetry. */\r\n [key: string]: unknown;\r\n}\r\n\r\n/**\r\n * Detection result for the `claude` CLI.\r\n */\r\nexport interface ClaudeCliInfo {\r\n installed: boolean;\r\n path?: string;\r\n version?: string;\r\n error?: string;\r\n}\r\n\r\n/**\r\n * Detect the local `claude` CLI by running `claude --version`. Doesn't throw.\r\n */\r\nexport async function detectClaudeCli(): Promise<ClaudeCliInfo> {\r\n try {\r\n const { stdout, exitCode } = await spawnRaw('claude', ['--version'], {\r\n timeoutMs: 5_000,\r\n });\r\n if (exitCode !== 0) {\r\n return { installed: false, error: `claude --version exited ${exitCode}` };\r\n }\r\n const version = parseVersion(stdout);\r\n return { installed: true, version };\r\n } catch (error) {\r\n return { installed: false, error: error instanceof Error ? error.message : String(error) };\r\n }\r\n}\r\n\r\nfunction parseVersion(text: string): string | undefined {\r\n const m = text.match(/(\\d+\\.\\d+\\.\\d+(?:[-+][\\w.]+)?)/);\r\n return m?.[1];\r\n}\r\n\r\n/**\r\n * Run one `claude` invocation. Throws ModelError / NetworkError on failure.\r\n */\r\nexport async function runClaude(opts: RunOptions): Promise<RunResult> {\r\n const args: string[] = [];\r\n const wantStreamFormat = opts.outputFormat === 'stream-json' || (opts.streaming !== false && !!opts.onEvent);\r\n const streaming = wantStreamFormat;\r\n\r\n // sub-agent or fresh session\r\n if (opts.agent) args.push('--agent', opts.agent);\r\n\r\n // append a system prompt file (used by skill-creator orchestrator)\r\n if (opts.appendSystemPromptFile) {\r\n args.push('--append-system-prompt-file', opts.appendSystemPromptFile);\r\n }\r\n\r\n // prompt mode\r\n // Windows argv has a ~32k-char hard limit (ENAMETOOLONG). For long prompts\r\n // (Planner prompt is ~24k+, skill-creator briefs can hit 60k) we pipe the\r\n // prompt via stdin instead. `claude -p` with no positional value reads\r\n // the prompt from stdin — verified pattern from Anthropic Claude Code docs.\r\n const promptViaStdin = opts.prompt.length > 8000;\r\n if (promptViaStdin) {\r\n args.push('-p');\r\n } else {\r\n args.push('-p', opts.prompt);\r\n }\r\n\r\n // structured output: stream-json (line-delimited events) when we want to\r\n // surface tool-use events live; plain json otherwise.\r\n if (streaming) {\r\n args.push('--output-format', 'stream-json', '--verbose');\r\n } else {\r\n args.push('--output-format', 'json');\r\n }\r\n\r\n // model\r\n if (opts.model) args.push('--model', opts.model);\r\n\r\n // tools allowlist\r\n if (opts.allowedTools && opts.allowedTools.length > 0) {\r\n args.push('--allowedTools', opts.allowedTools.join(','));\r\n }\r\n\r\n // max turns\r\n if (opts.maxTurns) args.push('--max-turns', String(opts.maxTurns));\r\n\r\n // budget cap\r\n if (opts.maxBudgetUsd) args.push('--max-budget-usd', String(opts.maxBudgetUsd));\r\n\r\n // bypass trust + permission prompts (default true; the agent file's\r\n // tools allowlist already prevents the sub-agent from writing/editing/etc.)\r\n if (opts.dangerouslySkipPermissions !== false) {\r\n args.push('--dangerously-skip-permissions');\r\n }\r\n\r\n logger.debug('[claude]', 'spawn', { args: args.slice(0, 4), agent: opts.agent, model: opts.model });\r\n\r\n const result = await spawnRaw('claude', args, {\r\n cwd: opts.cwd,\r\n signal: opts.signal,\r\n timeoutMs: opts.timeoutMs ?? 5 * 60_000,\r\n env: opts.env,\r\n stdinData: promptViaStdin ? opts.prompt : undefined,\r\n onLine: streaming && opts.onEvent\r\n ? (line) => {\r\n const trimmed = line.trim();\r\n if (!trimmed.startsWith('{')) return;\r\n try {\r\n const evt = JSON.parse(trimmed) as ClaudeStreamEvent;\r\n opts.onEvent!(evt);\r\n } catch {\r\n // Ignore malformed lines — we only consume well-formed JSON.\r\n }\r\n }\r\n : undefined,\r\n });\r\n\r\n if (result.exitCode !== 0) {\r\n const stderrTrim = result.stderr.trim();\r\n const stdoutTrim = result.stdout.trim();\r\n if (/timeout|aborted|EAGAIN|ETIMEDOUT/i.test(stderrTrim)) {\r\n throw new NetworkError(`claude CLI timed out: ${stderrTrim}`);\r\n }\r\n if (/dangerously|permission|trust|approve/i.test(stderrTrim)) {\r\n throw new ModelError(\r\n `claude CLI permission error: ${stderrTrim}`,\r\n \"The CLI runs claude with --dangerously-skip-permissions by default. If your Claude Code install is rejecting it, run `claude` once interactively in this directory to set up trust.\",\r\n );\r\n }\r\n throw new ModelError(\r\n `claude CLI exited ${result.exitCode}: ${stderrTrim || stdoutTrim || 'no output'}`,\r\n 'Run `aab doctor` to verify claude is installed and working. Re-run with `aab --debug discuss start ...` to see the spawn args.',\r\n );\r\n }\r\n\r\n // Surface non-fatal stderr at debug level (claude prints various warnings here)\r\n if (result.stderr.trim()) {\r\n logger.debug('[claude] stderr:', result.stderr.trim().slice(0, 500));\r\n }\r\n\r\n // Parse final result envelope.\r\n // - Non-streaming mode: stdout is one JSON object.\r\n // - Streaming mode: stdout is line-delimited; the last `{type:\"result\"...}`\r\n // line carries the same shape we want.\r\n let json: ClaudeJsonEnvelope | undefined;\r\n const trimmed = result.stdout.trim();\r\n if (streaming) {\r\n json = parseLastResultLine(trimmed);\r\n } else if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\r\n try {\r\n json = JSON.parse(trimmed) as ClaudeJsonEnvelope;\r\n } catch {\r\n // Some claude versions stream NDJSON even with --output-format=json.\r\n json = parseLastJsonObject(trimmed);\r\n }\r\n }\r\n\r\n logger.debug('[claude] result', {\r\n stdoutLen: result.stdout.length,\r\n stdoutHead: result.stdout.slice(0, 200),\r\n stdoutTail: result.stdout.length > 400 ? result.stdout.slice(-200) : undefined,\r\n envelopeParsed: !!json,\r\n envelopeType: json?.type,\r\n resultLen: typeof json?.result === 'string' ? json.result.length : undefined,\r\n resultHead: typeof json?.result === 'string' ? json.result.slice(0, 200) : undefined,\r\n resultTail:\r\n typeof json?.result === 'string' && json.result.length > 400 ? json.result.slice(-200) : undefined,\r\n });\r\n\r\n return { ...result, json };\r\n}\r\n\r\n/**\r\n * Walk lines from the bottom up looking for the `result` event emitted by\r\n * `claude --output-format stream-json`. That event has the same shape as the\r\n * non-streaming JSON envelope we already understand.\r\n */\r\nfunction parseLastResultLine(text: string): ClaudeJsonEnvelope | undefined {\r\n const lines = text.split('\\n').reverse();\r\n for (const line of lines) {\r\n const t = line.trim();\r\n if (!t.startsWith('{')) continue;\r\n try {\r\n const obj = JSON.parse(t) as ClaudeJsonEnvelope;\r\n if (obj.type === 'result') return obj;\r\n } catch {\r\n // keep scanning\r\n }\r\n }\r\n // Fallback: any parseable JSON line.\r\n return parseLastJsonObject(text);\r\n}\r\n\r\n/**\r\n * On Windows, npm-installed CLI tools land as `.cmd` / `.ps1` shims in PATH.\r\n * `child_process.spawn` won't pick those up unless we either set `shell: true`\r\n * (which triggers DEP0190 with args) or pass the explicit shim path. This\r\n * helper does the lookup once.\r\n */\r\nfunction resolveWinCommand(command: string): string {\r\n // Already absolute or has an extension — trust it.\r\n if (/\\\\|\\//.test(command) || /\\.[a-z0-9]+$/i.test(command)) return command;\r\n const PATH = process.env.PATH ?? process.env.Path ?? '';\r\n const PATHEXT = (process.env.PATHEXT ?? '.COM;.EXE;.BAT;.CMD;.PS1').split(';').filter(Boolean);\r\n for (const dir of PATH.split(delimiter)) {\r\n if (!dir) continue;\r\n for (const ext of PATHEXT) {\r\n const candidate = join(dir, command + ext);\r\n if (existsSync(candidate)) return candidate;\r\n }\r\n }\r\n return command; // fall through; spawn will report ENOENT cleanly\r\n}\r\n\r\n/**\r\n * Peek inside an npm-style `.cmd` shim and extract the underlying executable\r\n * path so we can spawn it directly (avoiding cmd.exe, which truncates\r\n * multi-line argv).\r\n *\r\n * The npm shim format is essentially:\r\n * \"%dp0%\\node_modules\\<pkg>\\bin\\<name>.exe\" %*\r\n * Some variants use `%~dp0\\..\\<pkg>\\bin\\<name>`. We match the last quoted\r\n * path on a non-comment line, substitute `%dp0%` / `%~dp0` with the shim\r\n * directory, and verify the file exists.\r\n *\r\n * Returns `undefined` if the shim doesn't match a recognised pattern — the\r\n * caller falls back to the cmd.exe wrapper.\r\n */\r\nfunction resolveCmdShimToExe(cmdPath: string): string | undefined {\r\n let body: string;\r\n try {\r\n body = readFileSync(cmdPath, 'utf8');\r\n } catch {\r\n return undefined;\r\n }\r\n const dp0 = dirname(cmdPath);\r\n const lines = body.split(/\\r?\\n/);\r\n // Walk bottom-up — the actual call is near the end of npm shims.\r\n for (let i = lines.length - 1; i >= 0; i--) {\r\n const line = lines[i]?.trim();\r\n if (!line || line.startsWith(':') || line.startsWith('REM ') || line.startsWith('@')) continue;\r\n const m = line.match(/\"([^\"]+\\.(?:exe|cmd|bat))\"/i);\r\n if (!m) continue;\r\n let candidate = m[1]!;\r\n // Substitute the common npm-shim variables.\r\n candidate = candidate\r\n .replace(/%~dp0/gi, dp0 + '\\\\')\r\n .replace(/%dp0%/gi, dp0 + '\\\\');\r\n // Collapse `\\\\` and resolve `..` segments.\r\n const abs = isAbsolute(candidate) ? resolvePath(candidate) : resolvePath(dp0, candidate);\r\n if (existsSync(abs) && /\\.exe$/i.test(abs)) return abs;\r\n }\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Wrap a `.cmd` / `.bat` invocation so it can be spawned safely on modern\r\n * Node (20.12+, 21.7+, 22+) where direct spawn of those files throws EINVAL.\r\n *\r\n * Strategy: invoke `cmd.exe /d /s /c \"<path> <args...>\"` with\r\n * `windowsVerbatimArguments: true` and quote each argument manually.\r\n *\r\n * /d skip AutoRun commands\r\n * /s strip outer quotes from the rest of the command line so we control quoting\r\n * /c run and exit\r\n */\r\nfunction wrapForCmd(\r\n resolved: string,\r\n args: string[],\r\n): { command: string; args: string[]; windowsVerbatimArguments: true } {\r\n const commandLine = [resolved, ...args].map(quoteForCmd).join(' ');\r\n return {\r\n command: process.env.ComSpec || 'cmd.exe',\r\n args: ['/d', '/s', '/c', commandLine],\r\n windowsVerbatimArguments: true,\r\n };\r\n}\r\n\r\n/**\r\n * Quote an argument for cmd.exe. Wraps in double quotes when necessary and\r\n * escapes embedded `\"`, `\\`, and `%` per the cmd.exe + CommandLineToArgvW\r\n * conventions. Used together with `windowsVerbatimArguments: true` so Node\r\n * doesn't re-quote on top.\r\n */\r\nfunction quoteForCmd(s: string): string {\r\n if (s === '') return '\"\"';\r\n // No special chars → return as-is.\r\n if (!/[\\s\"&|<>^()%!`]/.test(s)) return s;\r\n // Escape backslashes that precede a quote (Windows argv rule).\r\n let escaped = s.replace(/(\\\\*)\"/g, '$1$1\\\\\"').replace(/(\\\\+)$/, '$1$1');\r\n // Escape `%` so cmd.exe doesn't try to expand it as a variable.\r\n escaped = escaped.replace(/%/g, '\"^%\"');\r\n // Caret-escape cmd metacharacters that survive double-quotes in some edge cases.\r\n escaped = escaped.replace(/([&|<>^!])/g, '^$1');\r\n return `\"${escaped}\"`;\r\n}\r\n\r\nfunction parseLastJsonObject(text: string): ClaudeJsonEnvelope | undefined {\r\n const lines = text.split('\\n').reverse();\r\n for (const line of lines) {\r\n const t = line.trim();\r\n if (!t.startsWith('{')) continue;\r\n try {\r\n return JSON.parse(t) as ClaudeJsonEnvelope;\r\n } catch {\r\n // keep scanning\r\n }\r\n }\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Pull the final assistant text out of a JSON envelope, falling back to\r\n * stdout when the shape is unfamiliar.\r\n */\r\nexport function extractText(result: RunResult): string {\r\n if (result.json?.result && typeof result.json.result === 'string') {\r\n return result.json.result;\r\n }\r\n return result.stdout.trim();\r\n}\r\n\r\ninterface SpawnRawOptions {\r\n cwd?: string;\r\n signal?: AbortSignal;\r\n timeoutMs?: number;\r\n env?: Record<string, string>;\r\n /** Invoked once per line of stdout (for stream-json parsing). */\r\n onLine?: (line: string) => void;\r\n /**\r\n * If provided, the spawn opens stdin and writes this string before closing.\r\n * Used to bypass the Windows argv 32k-char limit when passing long prompts\r\n * to `claude -p` (no positional value → reads prompt from stdin).\r\n */\r\n stdinData?: string;\r\n}\r\n\r\ninterface SpawnRawResult {\r\n stdout: string;\r\n stderr: string;\r\n exitCode: number;\r\n durationMs: number;\r\n}\r\n\r\n/**\r\n * Thin wrapper around child_process.spawn that captures stdout/stderr,\r\n * applies a timeout, and forwards an AbortSignal.\r\n */\r\nfunction spawnRaw(command: string, args: string[], opts: SpawnRawOptions = {}): Promise<SpawnRawResult> {\r\n return new Promise<SpawnRawResult>((resolve, reject) => {\r\n const start = Date.now();\r\n // On Windows, npm installs `claude` as a `.cmd` shim under %APPDATA%\\npm\\.\r\n // Two problems with that:\r\n // 1. Since Node 20.12 / 21.7 / 22 (CVE-2024-27980), spawning `.cmd`\r\n // directly without `shell: true` throws EINVAL.\r\n // 2. Routing through `cmd.exe /c` works for short args but **truncates\r\n // multi-line arguments at the first newline** — cmd.exe treats `\\n`\r\n // as a command separator even inside quoted strings. Our prompts\r\n // are multi-line.\r\n // Fix: peek inside the `.cmd` shim, extract the underlying `.exe` path it\r\n // calls, and spawn that directly via argv (binary-safe). Only fall back\r\n // to the cmd.exe wrapper if shim parsing fails — and in that case\r\n // multi-line prompts will still be broken, so we log a warning.\r\n let resolvedRaw = process.platform === 'win32' ? resolveWinCommand(command) : command;\r\n if (process.platform === 'win32' && /\\.cmd$/i.test(resolvedRaw)) {\r\n const realExe = resolveCmdShimToExe(resolvedRaw);\r\n if (realExe) resolvedRaw = realExe;\r\n }\r\n const launch = process.platform === 'win32' && /\\.(cmd|bat)$/i.test(resolvedRaw)\r\n ? wrapForCmd(resolvedRaw, args)\r\n : { command: resolvedRaw, args, windowsVerbatimArguments: false };\r\n const child = spawn(launch.command, launch.args, {\r\n cwd: opts.cwd ?? process.cwd(),\r\n env: opts.env ? { ...process.env, ...opts.env } : process.env,\r\n windowsHide: true,\r\n windowsVerbatimArguments: launch.windowsVerbatimArguments,\r\n // Pipe stdin when long-prompt mode is requested (caller bypassing the\r\n // Windows 32k argv limit). Otherwise close stdin — without this, claude\r\n // waits 3s for stdin then prints a warning to stderr.\r\n stdio: [opts.stdinData !== undefined ? 'pipe' : 'ignore', 'pipe', 'pipe'],\r\n });\r\n\r\n // Long-prompt path — write the prompt body to stdin and close it. Any\r\n // EPIPE here is non-fatal (caller will see the model's response or a\r\n // descriptive error from exit-code handling).\r\n if (opts.stdinData !== undefined && child.stdin) {\r\n child.stdin.on('error', () => { /* swallow EPIPE / write-after-end */ });\r\n child.stdin.write(opts.stdinData);\r\n child.stdin.end();\r\n }\r\n\r\n let stdout = '';\r\n let stderr = '';\r\n let lineBuf = '';\r\n let timed = false;\r\n let aborted = false;\r\n\r\n const timer = opts.timeoutMs\r\n ? setTimeout(() => {\r\n timed = true;\r\n child.kill('SIGKILL');\r\n }, opts.timeoutMs)\r\n : null;\r\n\r\n if (opts.signal) {\r\n if (opts.signal.aborted) {\r\n aborted = true;\r\n child.kill('SIGKILL');\r\n } else {\r\n opts.signal.addEventListener(\r\n 'abort',\r\n () => {\r\n aborted = true;\r\n child.kill('SIGKILL');\r\n },\r\n { once: true },\r\n );\r\n }\r\n }\r\n\r\n child.stdout?.on('data', (chunk: Buffer) => {\r\n const text = chunk.toString('utf8');\r\n stdout += text;\r\n if (opts.onLine) {\r\n lineBuf += text;\r\n let nl = lineBuf.indexOf('\\n');\r\n while (nl >= 0) {\r\n const line = lineBuf.slice(0, nl);\r\n lineBuf = lineBuf.slice(nl + 1);\r\n if (line.length > 0) opts.onLine(line);\r\n nl = lineBuf.indexOf('\\n');\r\n }\r\n }\r\n });\r\n child.stderr?.on('data', (chunk: Buffer) => {\r\n stderr += chunk.toString('utf8');\r\n });\r\n\r\n child.on('error', (err) => {\r\n if (timer) clearTimeout(timer);\r\n reject(err);\r\n });\r\n\r\n child.on('close', (code) => {\r\n if (timer) clearTimeout(timer);\r\n if (opts.onLine && lineBuf.length > 0) {\r\n opts.onLine(lineBuf);\r\n lineBuf = '';\r\n }\r\n if (timed) {\r\n resolve({ stdout, stderr: stderr || 'timeout', exitCode: 124, durationMs: Date.now() - start });\r\n } else if (aborted) {\r\n resolve({ stdout, stderr: stderr || 'aborted', exitCode: 137, durationMs: Date.now() - start });\r\n } else {\r\n resolve({ stdout, stderr, exitCode: code ?? 0, durationMs: Date.now() - start });\r\n }\r\n });\r\n });\r\n}\r\n","/**\r\n * Tolerant JSON parser. Ported from sage-council/src/lib/parsing/safe-json.ts.\r\n *\r\n * Strategy ordering (first success wins):\r\n * 1. Raw input (already JSON).\r\n * 2. Strip ```json / ``` fences.\r\n * 3. Balanced-brace extraction (handles leading/trailing chatter).\r\n * 4. Regex object match.\r\n * 5. Regex array match.\r\n *\r\n * Then optionally validate against a zod schema; the caller can branch on\r\n * `parseResult.success` and (when false) read `parseResult.error` to surface\r\n * a path-joined message.\r\n */\r\nimport type { ZodSchema } from 'zod';\r\n\r\nexport type ParseSource = 'raw' | 'fence_stripped' | 'balanced' | 'regex_object' | 'regex_array';\r\n\r\nexport interface SafeParseSuccess<T> {\r\n success: true;\r\n data: T;\r\n source: ParseSource;\r\n}\r\n\r\nexport interface SafeParseFailure {\r\n success: false;\r\n error: string;\r\n}\r\n\r\nexport type SafeParseResult<T> = SafeParseSuccess<T> | SafeParseFailure;\r\n\r\nconst FENCE_RE = /^\\s*```(?:json|javascript|js)?\\s*\\n?([\\s\\S]*?)\\n?```\\s*$/i;\r\n\r\nfunction stripFences(text: string): string | null {\r\n const m = text.match(FENCE_RE);\r\n return m && typeof m[1] === 'string' ? m[1].trim() : null;\r\n}\r\n\r\n/**\r\n * Find a balanced {...} or [...] block ignoring chars inside string literals.\r\n */\r\nfunction balancedExtract(text: string, opener: '{' | '['): string | null {\r\n const closer = opener === '{' ? '}' : ']';\r\n const start = text.indexOf(opener);\r\n if (start === -1) return null;\r\n let depth = 0;\r\n let inString = false;\r\n let escape = false;\r\n for (let i = start; i < text.length; i++) {\r\n const ch = text[i];\r\n if (inString) {\r\n if (escape) {\r\n escape = false;\r\n } else if (ch === '\\\\') {\r\n escape = true;\r\n } else if (ch === '\"') {\r\n inString = false;\r\n }\r\n continue;\r\n }\r\n if (ch === '\"') {\r\n inString = true;\r\n continue;\r\n }\r\n if (ch === opener) depth++;\r\n else if (ch === closer) {\r\n depth--;\r\n if (depth === 0) return text.slice(start, i + 1);\r\n }\r\n }\r\n return null;\r\n}\r\n\r\nfunction regexFirstMatch(text: string, opener: '{' | '['): string | null {\r\n // Greedy enough to grab a likely object/array; falls back to balancedExtract\r\n // on the matched chunk so we don't return mismatched braces.\r\n const re = opener === '{' ? /\\{[\\s\\S]*\\}/ : /\\[[\\s\\S]*\\]/;\r\n const m = text.match(re);\r\n if (!m) return null;\r\n return balancedExtract(m[0], opener);\r\n}\r\n\r\nfunction tryParse<T>(text: string, source: ParseSource): SafeParseSuccess<T> | null {\r\n try {\r\n const data = JSON.parse(text) as T;\r\n return { success: true, data, source };\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Parse a raw text blob as JSON, trying multiple extraction strategies.\r\n */\r\nexport function safeParseJSON<T = unknown>(text: string): SafeParseResult<T> {\r\n if (typeof text !== 'string' || !text.trim()) {\r\n return { success: false, error: 'empty input' };\r\n }\r\n\r\n // 1. raw\r\n const raw = tryParse<T>(text, 'raw');\r\n if (raw) return raw;\r\n\r\n // 2. fenced\r\n const fenced = stripFences(text);\r\n if (fenced) {\r\n const r = tryParse<T>(fenced, 'fence_stripped');\r\n if (r) return r;\r\n }\r\n\r\n // 3. balanced object\r\n const balObj = balancedExtract(text, '{');\r\n if (balObj) {\r\n const r = tryParse<T>(balObj, 'balanced');\r\n if (r) return r;\r\n }\r\n\r\n // 4. regex object\r\n const reObj = regexFirstMatch(text, '{');\r\n if (reObj) {\r\n const r = tryParse<T>(reObj, 'regex_object');\r\n if (r) return r;\r\n }\r\n\r\n // 5. balanced array\r\n const balArr = balancedExtract(text, '[');\r\n if (balArr) {\r\n const r = tryParse<T>(balArr, 'balanced');\r\n if (r) return r;\r\n }\r\n\r\n const reArr = regexFirstMatch(text, '[');\r\n if (reArr) {\r\n const r = tryParse<T>(reArr, 'regex_array');\r\n if (r) return r;\r\n }\r\n\r\n return { success: false, error: 'no JSON candidate parsed' };\r\n}\r\n\r\n/**\r\n * Parse + validate against a zod schema. Returns the parsed data on success\r\n * with the source, or a path-joined error on failure.\r\n */\r\nexport function safeParseJSONWithSchema<T>(text: string, schema: ZodSchema<T>): SafeParseResult<T> {\r\n const parsed = safeParseJSON<unknown>(text);\r\n if (!parsed.success) return parsed;\r\n\r\n const validated = schema.safeParse(parsed.data);\r\n if (!validated.success) {\r\n const error = validated.error.issues\r\n .map((issue) => `${issue.path.join('.') || '(root)'}: ${issue.message}`)\r\n .join('; ');\r\n return { success: false, error };\r\n }\r\n return { success: true, data: validated.data, source: parsed.source };\r\n}\r\n","/**\r\n * Zod schemas for every LLM contract the discussion engine relies on.\r\n * Subset of sage-council/src/lib/parsing/llm-response-schemas.ts — only the\r\n * pieces Phase 1 needs.\r\n */\r\nimport { z } from 'zod';\r\n\r\n// ---------- shared preprocessors ----------\r\n\r\nconst numberFromUnknown = z.preprocess((value) => {\r\n if (typeof value === 'string' && value.trim() !== '') {\r\n const n = Number(value);\r\n if (Number.isFinite(n)) return n;\r\n }\r\n return value;\r\n}, z.number());\r\n\r\nconst boundedNumber = (min: number, max: number) =>\r\n z.preprocess((value) => {\r\n if (typeof value === 'string' && value.trim() !== '') {\r\n const n = Number(value);\r\n if (Number.isFinite(n)) return n;\r\n }\r\n return value;\r\n }, z.number().min(min).max(max));\r\n\r\nconst stringArrayFromUnknown = z.preprocess((value) => {\r\n if (Array.isArray(value)) return value.map((item) => String(item));\r\n if (typeof value === 'string' && value.trim() !== '') {\r\n return value.split(',').map((s) => s.trim()).filter(Boolean);\r\n }\r\n return [];\r\n}, z.array(z.string()));\r\n\r\nconst booleanFromUnknown = z.preprocess((value) => {\r\n if (typeof value === 'boolean') return value;\r\n if (typeof value === 'string') {\r\n const v = value.trim().toLowerCase();\r\n if (['true', '1', 'yes', 'on'].includes(v)) return true;\r\n if (['false', '0', 'no', 'off'].includes(v)) return false;\r\n }\r\n return value;\r\n}, z.boolean());\r\n\r\nconst sourceSchema = z\r\n .object({\r\n title: z.string().optional(),\r\n url: z.string().optional(),\r\n })\r\n .passthrough();\r\n\r\n// ---------- structured member response ----------\r\n\r\nexport const structuredResponsePayloadSchema = z\r\n .object({\r\n response: z.string(),\r\n keyPoints: stringArrayFromUnknown.optional(),\r\n questionsForOthers: stringArrayFromUnknown.optional(),\r\n actionSteps: stringArrayFromUnknown.optional(),\r\n confidence: boundedNumber(0, 100).optional(),\r\n assumptions: stringArrayFromUnknown.optional(),\r\n tradeoffs: stringArrayFromUnknown.optional(),\r\n riskMitigations: stringArrayFromUnknown.optional(),\r\n firstPrinciplesApplied: stringArrayFromUnknown.optional(),\r\n sources: z.array(sourceSchema).optional(),\r\n })\r\n .passthrough();\r\n\r\nexport type StructuredResponsePayload = z.infer<typeof structuredResponsePayloadSchema>;\r\n\r\n// ---------- orchestrator decision ----------\r\n\r\nexport const userInputRequestPayloadSchema = z\r\n .object({\r\n type: z.enum(['clarification', 'decision', 'preference', 'information']).optional(),\r\n question: z.string().optional(),\r\n context: z.string().optional(),\r\n requestingMembers: stringArrayFromUnknown.optional(),\r\n urgency: z.enum(['low', 'medium', 'high']).optional(),\r\n options: stringArrayFromUnknown.optional(),\r\n })\r\n .passthrough();\r\n\r\nexport const orchestratorDecisionPayloadSchema = z\r\n .object({\r\n action: z.enum(['continue', 'conclude', 'redirect', 'request_user_input']).optional(),\r\n reasoning: z.string().optional(),\r\n nextSpeaker: z.string().optional(),\r\n suggestedDirection: z.string().optional(),\r\n consensusReached: booleanFromUnknown.optional(),\r\n confidence: boundedNumber(0, 100).optional(),\r\n userInputRequest: userInputRequestPayloadSchema.optional(),\r\n })\r\n .passthrough();\r\n\r\nexport type OrchestratorDecisionPayload = z.infer<typeof orchestratorDecisionPayloadSchema>;\r\n\r\n// ---------- conversation summary ----------\r\n\r\nconst summaryParticipantSchema = z\r\n .object({\r\n memberId: z.string().optional(),\r\n memberName: z.string(),\r\n totalResponses: numberFromUnknown.optional(),\r\n topicsCovered: stringArrayFromUnknown.optional(),\r\n influence: boundedNumber(0, 100).optional(),\r\n averageLength: numberFromUnknown.optional(),\r\n })\r\n .passthrough();\r\n\r\nexport const conversationSummaryPayloadSchema = z\r\n .object({\r\n keyPoints: stringArrayFromUnknown.optional(),\r\n consensus: stringArrayFromUnknown.optional(),\r\n disagreements: stringArrayFromUnknown.optional(),\r\n actionableInsights: stringArrayFromUnknown.optional(),\r\n participationBreakdown: z.array(summaryParticipantSchema).optional(),\r\n overallQuality: boundedNumber(0, 100).optional(),\r\n })\r\n .passthrough();\r\n\r\nexport type ConversationSummaryPayload = z.infer<typeof conversationSummaryPayloadSchema>;\r\n\r\n// ---------- action item extraction (Phase 4) ----------\r\n\r\nconst PRIORITY_VALUES = ['low', 'medium', 'high'] as const;\r\nconst CATEGORY_VALUES = [\r\n 'strategic',\r\n 'operational',\r\n 'technical',\r\n 'research',\r\n 'financial',\r\n 'other',\r\n] as const;\r\n\r\nexport const extractedActionItemSchema = z\r\n .object({\r\n title: z.string().optional(),\r\n description: z.string().optional(),\r\n priority: z.enum(PRIORITY_VALUES).optional(),\r\n category: z.enum(CATEGORY_VALUES).optional(),\r\n confidence: boundedNumber(0, 100).optional(),\r\n sourceContext: z.string().optional(),\r\n suggestedAssignee: z.string().optional(),\r\n suggestedDueDate: z.string().optional(),\r\n })\r\n .passthrough();\r\n\r\nexport const conversationAnalysisPayloadSchema = z\r\n .object({\r\n actionItems: z.array(extractedActionItemSchema).optional(),\r\n keyInsights: stringArrayFromUnknown.optional(),\r\n recommendedNextSteps: stringArrayFromUnknown.optional(),\r\n analysisConfidence: boundedNumber(0, 100).optional(),\r\n })\r\n .passthrough();\r\n\r\nexport type ConversationAnalysisPayload = z.infer<typeof conversationAnalysisPayloadSchema>;\r\n\r\n// ---------- Skill Planner (Phase 5) — SkillDesignProposal ----------\r\n\r\nconst INVOCATION_HINT_KINDS = [\r\n 'bash-cmd', 'bash-curl', 'mcp-tool', 'bash-script',\r\n 'write-artifact', 'manual-handoff',\r\n 'chrome-extension', 'computer-use',\r\n] as const;\r\n\r\nconst INTEGRATION_SOURCES = [\r\n 'pc-app', 'cli-tool', 'mcp-server', 'wiki-entity',\r\n 'browser-extension', 'web-service', 'api',\r\n] as const;\r\n\r\nconst SURFACED_FROM_VALUES = [\r\n 'pc-scan', 'wiki-recon', 'web-research', 'web-research-per-app', 'inferred',\r\n] as const;\r\n\r\nconst TIER_NAMES = ['minimal', 'standard', 'maximalist'] as const;\r\n\r\n// Open string by design (used as a display label only — downstream code\r\n// doesn't switch on it). Opus often uses kebab-case variants like\r\n// 'draft-slack-message' or 'send-calendar-invite' which are perfectly\r\n// reasonable descriptors but were rejected by an over-strict enum in\r\n// earlier revisions. Caught via real solve `bnxyfj460` on 2026-05-21.\r\nconst TOUCHPOINT_KINDS = ['draft-email', 'slack-mention', 'calendar-invite', 'doc-share', 'other'] as const;\r\nvoid TOUCHPOINT_KINDS;\r\n\r\nconst sourceCitationSchema = z\r\n .object({ title: z.string().optional(), url: z.string().optional() })\r\n .passthrough();\r\n\r\nexport const invocationHintSchema = z\r\n .object({\r\n kind: z.enum(INVOCATION_HINT_KINDS),\r\n tools: stringArrayFromUnknown.optional(),\r\n snippet: z.string().optional(),\r\n artifactPath: z.string().optional(),\r\n handoffInstructions: z.string().optional(),\r\n })\r\n .passthrough();\r\n\r\nexport const skillTierSchema = z\r\n .object({\r\n // `name` is a human display label here — the canonical identity of the\r\n // tier is the parent key (`minimal`/`standard`/`maximalist`). Opus tends\r\n // to fill `name` with a descriptive headline like \"End-to-end launch\r\n // pipeline with Chrome handoff\", which is exactly what we want for the\r\n // proposal UI. Accept any string; don't force the enum.\r\n name: z.string().optional(),\r\n description: z.string().optional(),\r\n toolSurface: stringArrayFromUnknown.optional(),\r\n workflow: stringArrayFromUnknown.optional(),\r\n produces: stringArrayFromUnknown.optional(),\r\n estimatedValueScore: boundedNumber(0, 100).optional(),\r\n })\r\n .passthrough();\r\n\r\nexport const proposalIntegrationSchema = z\r\n .preprocess(\r\n // Real-Opus-output tolerance: synonyms the model tends to pick.\r\n // - `name` synonyms: `title`, `label`, `displayName`\r\n // - `id` synonyms: `key`, `slug`\r\n // - `source` synonyms: `surface`, `sourceType`\r\n // We remap to the canonical shape before validating. Last fallback: if\r\n // `name` is still missing, derive it from `purpose` (truncated) or `id`.\r\n (raw) => {\r\n if (!raw || typeof raw !== 'object') return raw;\r\n const r = raw as Record<string, unknown>;\r\n const out = { ...r };\r\n if (!out.name) {\r\n out.name = r.title ?? r.label ?? r.displayName ??\r\n (typeof r.purpose === 'string' ? r.purpose.slice(0, 80) : undefined) ??\r\n (typeof r.id === 'string' ? r.id : undefined);\r\n }\r\n if (!out.id) out.id = r.key ?? r.slug;\r\n if (!out.source) out.source = r.surface ?? r.sourceType;\r\n return out;\r\n },\r\n z\r\n .object({\r\n id: z.string(),\r\n source: z.enum(INTEGRATION_SOURCES),\r\n name: z.string(),\r\n purpose: z.string().optional(),\r\n workflowSteps: stringArrayFromUnknown.optional(),\r\n invocationHint: invocationHintSchema,\r\n requiredTools: stringArrayFromUnknown.optional(),\r\n fallbackIfMissing: z.string().optional(),\r\n confidence: boundedNumber(0, 100).optional(),\r\n surfacedFrom: z.enum(SURFACED_FROM_VALUES).optional(),\r\n citations: z.array(sourceCitationSchema).optional(),\r\n })\r\n .passthrough(),\r\n );\r\n\r\nexport const proposalStakeholderSchema = z\r\n .object({\r\n name: z.string(),\r\n role: z.string().optional(),\r\n // Open string (kebab-case advisory): the Planner may use any descriptor\r\n // like 'draft-email', 'slack-mention', 'draft-slack-message',\r\n // 'calendar-invite', 'send-pr-review', etc. Display-only field.\r\n touchpointKind: z.string().optional(),\r\n rationale: z.string().optional(),\r\n produces: z.enum(['artifact', 'send']).optional(),\r\n artifactPath: z.string().optional(),\r\n sendVia: z.string().optional(),\r\n artifactTemplate: z\r\n .object({\r\n subject: z.string().optional(),\r\n body: z.string().optional(),\r\n attachments: stringArrayFromUnknown.optional(),\r\n })\r\n .passthrough()\r\n .optional(),\r\n })\r\n .passthrough();\r\n\r\nexport const proposalWorkflowStepSchema = z\r\n .object({\r\n step: z.string(),\r\n integrations: stringArrayFromUnknown.optional(),\r\n output: z.string().optional(),\r\n })\r\n .passthrough();\r\n\r\nexport const proposalWarningSchema = z\r\n .object({\r\n phase: z.enum(['pc-scan', 'wiki-recon', 'web-research-general', 'web-research-per-app']),\r\n severity: z.enum(['info', 'warn', 'error']),\r\n message: z.string(),\r\n })\r\n .passthrough();\r\n\r\nexport const proposalMismatchSchema = z\r\n .object({\r\n integrationId: z.string(),\r\n reason: z.enum(['mcp-not-installed', 'cli-not-found', 'env-var-missing', 'app-not-detected', 'other']),\r\n requiredTool: z.string(),\r\n suggestion: z.string().optional(),\r\n })\r\n .passthrough();\r\n\r\nconst SKILL_NAME_RE = /^[a-z][a-z0-9-]{1,63}$/;\r\n\r\n/**\r\n * Top-level synonym remap for the SkillDesignProposal. Real Opus output\r\n * varies field names from run to run — we maintain this table as a living\r\n * compatibility layer rather than fighting one synonym at a time. Each entry\r\n * is \"if canonical is missing, look for these alternates in order; first hit\r\n * wins.\" Caught via the live solve cascade on 2026-05-21\r\n * (buhuld3ya/btpijn641/bgnyffj1k/bnxyfj460/bdeznap3h).\r\n *\r\n * Keep this table append-only — when a new live run surfaces another\r\n * synonym, add it here rather than relaxing the schema further.\r\n */\r\nconst TOP_LEVEL_SYNONYMS: Record<string, string[]> = {\r\n skillName: ['name', 'id', 'slug', 'skill_name'],\r\n skillSummary: ['summary', 'description', 'tagline', 'skill_summary', 'overview'],\r\n triggerLanguage: ['trigger', 'whenToUse', 'when_to_use', 'usage'],\r\n integrations: ['proposalIntegrations', 'integrationsList', 'proposedIntegrations', 'tools'],\r\n stakeholderTouchpoints: ['stakeholders', 'touchpoints', 'people'],\r\n proposedWorkflow: ['workflow', 'steps', 'pipeline'],\r\n vetoes: ['mustNot', 'must_not', 'antipatterns', 'forbidden'],\r\n valueRationale: ['rationale', 'why', 'justification', 'reasoning'],\r\n recommendedTier: ['recommended', 'tier', 'recommendedTierName'],\r\n};\r\n\r\nfunction remapTopLevelSynonyms(raw: unknown): unknown {\r\n if (!raw || typeof raw !== 'object') return raw;\r\n const r = raw as Record<string, unknown>;\r\n const out = { ...r };\r\n for (const [canonical, alternates] of Object.entries(TOP_LEVEL_SYNONYMS)) {\r\n if (out[canonical] !== undefined && out[canonical] !== null) continue;\r\n for (const alt of alternates) {\r\n if (r[alt] !== undefined && r[alt] !== null) {\r\n out[canonical] = r[alt];\r\n break;\r\n }\r\n }\r\n }\r\n // Special case: integrations may be nested inside tiers.maximalist.\r\n if (!Array.isArray(out.integrations) && r.tiers && typeof r.tiers === 'object') {\r\n const tiers = r.tiers as Record<string, unknown>;\r\n const max = tiers.maximalist as Record<string, unknown> | undefined;\r\n if (max && Array.isArray(max.integrations)) {\r\n out.integrations = max.integrations;\r\n }\r\n }\r\n // Defensive defaults — let downstream code call .length / .map() without\r\n // guards, and let the semantic validator surface a clean \"≥3 integrations\"\r\n // message rather than a cryptic \"Required\".\r\n if (!Array.isArray(out.integrations)) out.integrations = [];\r\n if (out.skillSummary === undefined && typeof out.skillName === 'string') {\r\n out.skillSummary = String(out.skillName);\r\n }\r\n return out;\r\n}\r\n\r\nexport const skillDesignProposalSchema = z\r\n .preprocess(\r\n remapTopLevelSynonyms,\r\n z\r\n .object({\r\n skillName: z\r\n .string()\r\n .refine((s) => SKILL_NAME_RE.test(s), { message: 'skillName must be kebab-case ≤64 chars starting with a letter' }),\r\n skillSummary: z.string(),\r\n triggerLanguage: z.string().optional(),\r\n tiers: z.object({\r\n minimal: skillTierSchema,\r\n standard: skillTierSchema,\r\n maximalist: skillTierSchema,\r\n }),\r\n recommendedTier: z.enum([...TIER_NAMES, 'custom']),\r\n integrations: z.array(proposalIntegrationSchema),\r\n proposedWorkflow: z.array(proposalWorkflowStepSchema).optional(),\r\n stakeholderTouchpoints: z.array(proposalStakeholderSchema).optional(),\r\n vetoes: stringArrayFromUnknown.optional(),\r\n valueRationale: z.string().optional(),\r\n warnings: z.array(proposalWarningSchema).optional(),\r\n mismatchedIntegrations: z.array(proposalMismatchSchema).optional(),\r\n estimatedCostUsd: numberFromUnknown.optional(),\r\n estimatedDurationMinutes: numberFromUnknown.optional(),\r\n })\r\n .passthrough(),\r\n );\r\n\r\nexport type SkillDesignProposal = z.infer<typeof skillDesignProposalSchema>;\r\nexport type ProposalIntegration = z.infer<typeof proposalIntegrationSchema>;\r\nexport type ProposalStakeholder = z.infer<typeof proposalStakeholderSchema>;\r\nexport type InvocationHint = z.infer<typeof invocationHintSchema>;\r\n\r\n// Reserved skill names that the adapter (§9) refuses.\r\nexport const RESERVED_SKILL_NAMES = new Set<string>([\r\n 'skill-creator',\r\n 'master-gpt-prompter',\r\n 'wiki-ingest',\r\n 'wiki-query',\r\n 'wiki-lint',\r\n]);\r\n\r\n/**\r\n * Wiki Tier 1 knowledge slugs the Planner must cite when present. Passed\r\n * separately because the proposal schema doesn't carry the recon context.\r\n */\r\nexport interface WikiKnowledgeSlugs {\r\n playbooks: string[];\r\n templates: string[];\r\n domainKnowledge: string[];\r\n pastLessons: string[];\r\n}\r\n\r\n/**\r\n * Validate the proposal's hard semantic gates that go beyond shape:\r\n * - skillName not reserved\r\n * - maximalist tier has ≥3 integrations across ≥2 distinct sources\r\n * (unless empty-recon honest-fallback: recommendedTier = minimal +\r\n * rationale explicitly mentions \"limited integration surface\")\r\n * - **Phase 5.1**: if wiki Tier 1 knowledge slugs are passed and non-empty,\r\n * the proposal's valueRationale must cite at least one of them by slug —\r\n * enforces the \"use the wiki, don't decorate with it\" contract.\r\n *\r\n * Returns null on success; otherwise an array of human-readable failure\r\n * reasons that callers can feed back to the Planner as `<replan_feedback>`.\r\n */\r\nexport function validateProposalSemantics(\r\n p: SkillDesignProposal,\r\n wikiKnowledge?: WikiKnowledgeSlugs,\r\n): string[] | null {\r\n const errors: string[] = [];\r\n if (RESERVED_SKILL_NAMES.has(p.skillName)) {\r\n errors.push(`skillName \"${p.skillName}\" is reserved by Anthropic — choose a different name`);\r\n }\r\n const maximalistCount = (p.integrations ?? []).length;\r\n const uniqueSources = new Set(p.integrations.map((i) => i.source));\r\n const isEmptyReconFallback =\r\n p.recommendedTier !== 'maximalist' &&\r\n /limited integration surface|no leverageable|environment.*(limited|insufficient)/i.test(p.valueRationale ?? '');\r\n if (!isEmptyReconFallback) {\r\n if (maximalistCount < 3) {\r\n errors.push(`maximalist tier has ${maximalistCount} integrations; need ≥3 (or set recommendedTier to minimal/standard with an explicit limited-environment rationale)`);\r\n }\r\n if (uniqueSources.size < 2) {\r\n errors.push(`integrations span only ${uniqueSources.size} source type; need ≥2 distinct sources (pc-app/mcp-server/wiki-entity/...)`);\r\n }\r\n }\r\n\r\n // Phase 5.1 — wiki-as-brain citation gate.\r\n if (wikiKnowledge) {\r\n const allSlugs = [\r\n ...wikiKnowledge.playbooks,\r\n ...wikiKnowledge.templates,\r\n ...wikiKnowledge.domainKnowledge,\r\n ...wikiKnowledge.pastLessons,\r\n ];\r\n if (allSlugs.length > 0) {\r\n const rationale = String(p.valueRationale ?? '');\r\n const cited = allSlugs.filter((slug) => rationale.includes(slug));\r\n if (cited.length === 0) {\r\n const sampleSlugs = allSlugs.slice(0, 5).join(', ');\r\n errors.push(\r\n `valueRationale must cite at least one wiki Tier 1 slug (the user has documented their way of doing this — use it). Available slugs: ${sampleSlugs}${allSlugs.length > 5 ? ', …' : ''}`,\r\n );\r\n }\r\n // Also check: every playbook should appear in either valueRationale OR\r\n // the proposedWorkflow steps. Soft check — surface as a single error if\r\n // any playbook is completely ignored.\r\n const workflowJoined = JSON.stringify(p.proposedWorkflow ?? []);\r\n const integrationsJoined = JSON.stringify(p.integrations ?? []);\r\n const ignoredPlaybooks = wikiKnowledge.playbooks.filter(\r\n (slug) => !rationale.includes(slug) && !workflowJoined.includes(slug) && !integrationsJoined.includes(slug),\r\n );\r\n if (ignoredPlaybooks.length > 0) {\r\n errors.push(\r\n `wiki playbook(s) ignored entirely: ${ignoredPlaybooks.join(', ')}. Playbooks are the most load-bearing wiki tier — at least cite them in valueRationale, ideally execute step-for-step in proposedWorkflow.`,\r\n );\r\n }\r\n }\r\n }\r\n\r\n return errors.length === 0 ? null : errors;\r\n}\r\n","/**\n * Skill Planner system prompt — the most important prompt in the CLI.\n *\n * Per docs/development/SKILL_CREATOR.md §6.5a:\n * <role>\n * <skill_operating_model> — ported from sage-council\n * <master_gpt_prompter_hardening>\n * <ambition_directive>\n * <orchestration_directives>\n * <invocation_hint_directive>\n * <output_contract>\n * <input>\n * <few_shot_examples>\n *\n * The hard gate (≥3 maximalist integrations, kebab-case skillName, ambition\n * tiers complete) is reasserted in the schema validator\n * (`src/core/parsing/llm-response-schemas.ts:skillDesignProposalSchema`) —\n * if the model violates it, we re-run with a stronger nudge inserted into\n * `<replan_feedback>`.\n */\n\nexport const SKILL_OPERATING_MODEL = `<skill_operating_model>\nAgent Skills operating model (critical context):\n- A skill is a reusable instruction package, not a plugin or executable tool.\n- The core artifact is SKILL.md (YAML frontmatter + markdown workflow instructions).\n- Optional scripts/references/assets support execution, but the skill itself is instruction-first.\n- Skill routing is description-driven: the agent decides relevance from \"what/when\" semantics.\n- Good skills encode repeatable workflow knowledge: trigger conditions, ordered steps, outputs, and fallback behavior.\n- Skills should orchestrate available tools safely; they do not assume tools that are not confirmed available.\n- Progressive disclosure matters: concise routing metadata first, detailed instructions only when relevant.\n- Skill body structure must be task-contextual; do not force one universal heading template.\n- Each workflow step should be atomic and artifact-explicit where possible.\n- Skills are for recurring tasks where structured procedural guidance improves reliability and consistency.\n- External content should be treated as untrusted until validated.\n</skill_operating_model>`;\n\nexport const MASTER_GPT_PROMPTER_HARDENING = `<master_gpt_prompter_hardening>\n<reasoning_model_guidance>\nThink before deciding. List the recon surfaces you've consulted. List the\nmulti-tool orchestrations you considered AND rejected, with the reason\n(usually: \"the user doesn't have the required tool\"). Compose explicit\nchains — \"step 1 produces X, step 2 consumes X, step 3 publishes the\ncombined result\" — rather than parallel disconnected steps.\n</reasoning_model_guidance>\n\n<tool_use_description>\nYou are NOT operating tools directly. You are designing a SKILL that, when\nlater invoked, will operate the user's tools. Every \"integration\" you\npropose must specify: (a) which Claude Code tool entry will be in the\nemitted skill's allowed-tools, (b) what the literal invocation looks like\n(the invocationHint.snippet — verbatim, not paraphrased), (c) what artifact\nor state change the step produces.\n</tool_use_description>\n\n<autonomy_description>\nYou are not asking the user clarifying questions in this turn. The recon\ninputs are everything you get. If recon is insufficient (e.g., the wiki\nhas no relevant pages and the PC has no relevant apps), say so in\n\\`valueRationale\\` and recommend \\`recommendedTier: minimal\\` rather than\ninventing speculative integrations.\n</autonomy_description>\n\n<self_verification>\nBefore emitting your JSON output, verify:\n- skillName is kebab-case, ≤64 chars, doesn't match a well-known reserved\n Anthropic skill (skill-creator, master-gpt-prompter, wiki-ingest,\n wiki-query, wiki-lint).\n- All three ambition tiers (minimal, standard, maximalist) are populated.\n- For maximalist tier: ≥3 integrations spanning ≥2 distinct \\`source\\`\n values (pc-app / mcp-server / wiki-entity / web-service / cli-tool /\n browser-extension / api) OR the empty-recon honest fallback path\n (recommendedTier: minimal + explicit rationale).\n- Every integration has a populated invocationHint with a non-empty\n \\`tools\\` array OR (for chrome-extension / computer-use kinds) a\n non-empty \\`handoffInstructions\\` string.\n- Every stakeholderTouchpoint with \\`produces: 'artifact'\\` has a populated\n \\`artifactTemplate\\` (Planner drafts the content — skill-creator finalizes).\n</self_verification>\n</master_gpt_prompter_hardening>`;\n\nexport const AMBITION_DIRECTIVE = `<ambition_directive>\nPropose THREE tiers of the skill, ordered by ambition:\n\n- minimal: just produce the obvious artifact (e.g., a markdown file). No integrations.\n Use case: user has no tools / wants quick output.\n- standard: use the tools the user clearly has and the action obviously needs.\n 1-2 integrations. Use case: balanced power/simplicity.\n- maximalist: orchestrate EVERYTHING in the user's environment that could plausibly help.\n ≥3 distinct multi-tool integrations across at least 2 different surfaces\n (PC apps, MCP servers, CLI tools, wiki stakeholders, browser extensions,\n computer-use targets).\n\nHARD GATE: if you cannot find ≥3 maximalist integrations the user has the\ninfrastructure for, you MUST say so in valueRationale (\"the user's environment\nhas limited integration surface for this action\") and recommend 'standard' OR\n'minimal' as recommendedTier. Do NOT pad maximalist with weak integrations\njust to hit the count.\n</ambition_directive>`;\n\nexport const ORCHESTRATION_DIRECTIVES = `<orchestration_directives>\nFor each detected PC app whose category matches the action's domain:\n- Consult appIntegrationSurfaces in the WebResearchContext.\n- If the app has a programmatic surface (local HTTP API, CLI, URL scheme,\n scripting API), propose an integration using it. Use the EXACT\n invocationHint.snippet from the per-app research pass (don't paraphrase).\n Prefer kind='bash-curl' / 'bash-cmd' / 'bash-script' / 'mcp-tool'.\n- If the app has NO programmatic surface, propose an\n invocationHint.kind='computer-use' integration with handoffInstructions\n describing the GUI sequence Claude (running with computer-use enabled)\n must perform. Treat this as FIRST-CLASS, not a fallback.\n\nFor each detected MCP server:\n- If the server's tools match the action's domain, propose\n invocationHint.kind='mcp-tool' with tools=[mcp__<server>__<tool>, ...].\n\nFor external destinations the action implies but the user has no MCP/API for:\n- Check appIntegrationSurfaces for a per-app hit naming the site.\n- If no programmatic surface exists, propose invocationHint.kind='chrome-extension'\n with handoffInstructions describing the navigation + form-fill + click\n sequence Claude (running with the Chrome extension enabled) must perform.\n- Treat this as FIRST-CLASS. Chrome is GA across Pro/Team/Enterprise since\n Dec 2025 and is the integration mechanism for sites without public APIs\n (LinkedIn Sales Nav, mid-market vendor portals, government filing sites,\n ATS for tier-restricted accounts, Carta on founder-plan, etc.).\n\nFor complex actions that touch multiple external systems:\n- Don't shoehorn into one integration kind. PROPOSE A MIX: pull data via MCP,\n post results via Chrome to a portal that has no API, paste a derived\n figure into a desktop app via computer-use, draft stakeholder follow-ups\n as artifacts. The maximalist tier earns its name by chaining surfaces.\n\nFor each wiki entity that is a person (stakeholder):\n- If their role is plausibly relevant to the action, propose a stakeholderTouchpoint.\n- Default to produces='artifact' unless the user has a matching send-capable\n MCP (Gmail/Slack/Calendar) — then upgrade to produces='send'.\n- DRAFT the artifact's subject + body — don't leave as a placeholder.\n\nFor each wiki decision/concept tagged as endorsed or veto:\n- Endorsed: bake into the skill's default workflow (skill should DO it the user's way).\n- Veto: list verbatim in proposal.vetoes — skill body emits \"MUST NOT\" lines.\n\nTHE WIKI KNOWLEDGE TIER (playbooks / templates / domainKnowledge / pastLessons)\nIS THE MOST LOAD-BEARING SIGNAL IN THE WHOLE RECON. The user has spent real\ntime encoding how they work — your job is to make the skill execute work\nTHE USER'S WAY, not in a generic-best-practice way. Concretely:\n\n- For each \\`wikiContext.playbooks[]\\` entry: the maximalist tier's workflow\n MUST execute the playbook step-for-step. Do NOT invent alternative\n workflows when the user has documented theirs. Cite each playbook by slug\n in valueRationale (\"I'm executing wiki/concepts/<slug> step-for-step\n because the user has run this 4 times and refined the procedure\").\n Embed the playbook's literal step text into the relevant integration's\n workflowSteps[] — verbatim, not paraphrased.\n\n- For each \\`wikiContext.templates[]\\` entry: the skill's output-producing\n steps MUST use the template shape verbatim. For write-artifact\n integrations, set invocationHint.snippet (or workflowSteps) to reference\n the template body. For send integrations, set stakeholderTouchpoint\n artifactTemplate.body to the template body verbatim. Cite the template\n by slug in valueRationale.\n\n- For each \\`wikiContext.domainKnowledge[]\\` entry whose excerpt is relevant\n to a decision the skill will make at runtime: weave the relevant fact\n into the workflowSteps[] description where it informs the decision. Do\n NOT just link to the wiki page — inline the actual content. Cite by slug.\n\n- For each \\`wikiContext.pastLessons[]\\` entry: the lesson's \\`actionable\\`\n field MUST appear EITHER as an entry in proposal.vetoes[] OR as a\n preflight check in the integration's workflowSteps[]. The user has\n already paid for this learning — make the skill honor it.\n\nVALIDATION GATE: if any of playbooks/templates/domainKnowledge/pastLessons\nis non-empty AND your valueRationale does not cite at least one of their\nslugs by name, the schema validator will reject and re-run with a stronger\nnudge. So actually use the knowledge.\n</orchestration_directives>`;\n\nexport const INVOCATION_HINT_DIRECTIVE = `<invocation_hint_directive>\nEVERY integration MUST have a populated invocationHint. Without it, the\nemitted skill will describe the work in prose instead of executing it.\nExamples spanning all kinds:\n\n- Elgato Teleprompter local API (kind='bash-curl'):\n { kind: 'bash-curl', tools: ['Bash(curl *)'],\n snippet: 'curl -X POST http://localhost:9012/scripts -H \"Content-Type: application/json\" -d @script.json' }\n\n- Google Calendar MCP (kind='mcp-tool'):\n { kind: 'mcp-tool', tools: ['mcp__google_calendar__create_event'] }\n\n- Email draft to stakeholder, no Gmail MCP (kind='write-artifact'):\n { kind: 'write-artifact', tools: ['Write'], artifactPath: 'references/email-to-person-x.md' }\n\n- LinkedIn Sales Nav, no public API (kind='chrome-extension'):\n { kind: 'chrome-extension', tools: [], handoffInstructions:\n 'Open Claude with the Chrome extension enabled and run: \"Navigate to https://www.linkedin.com/sales/. For each prospect in references/prospects.json, open their profile, click Message, paste references/templates/inbound-warm.md substituting [[first_name]], and send. Log each result.\" Return when done.' }\n\n- DaVinci Resolve render (kind='computer-use'):\n { kind: 'computer-use', tools: [], handoffInstructions:\n 'Open Claude Desktop with computer-use enabled and run: \"Open DaVinci Resolve. Open project at projects/q3-launch.drp. Set Render Settings to MP4 H.264 1920x1080 60fps. Add to Render Queue. Click Start Render.\" Return when done.' }\n\nFor chrome-extension and computer-use kinds, handoffInstructions IS the\ncontract — it must be self-contained, specify exact target + action sequence +\nsuccess criterion + what the calling skill expects back.\n</invocation_hint_directive>`;\n\nexport const OUTPUT_CONTRACT = `<output_contract>\nReturn ONLY a single JSON object matching the SkillDesignProposal schema.\nNo markdown fences, no prose, no chain-of-thought leakage. Start with \\`{\\`,\nend with \\`}\\`. Every required field present. Every integration has a\npopulated invocationHint. Every stakeholderTouchpoint with\nproduces='artifact' has a populated artifactTemplate.\n\nCRITICAL FIELD CONVENTIONS (the validator is strict about these):\n- skillName: kebab-case identifier (lowercase letters + digits + hyphens).\n- tiers.minimal.name, tiers.standard.name, tiers.maximalist.name: a SHORT\n human display label (e.g., \"Markdown brief\", \"Full multi-tool pipeline\").\n DO NOT echo the tier key (\"minimal\"/\"standard\"/\"maximalist\") as the name —\n the parent JSON key already carries that identity.\n- integrations[i].name: a SHORT human-readable label (e.g., \"YouTube Data API\n upload\", \"Webflow homepage embed\"). Use the field literally called \"name\",\n NOT \"title\" or \"label\".\n- integrations[i].id: a kebab-case identifier unique within the proposal.\n- integrations[i].source: one of pc-app | cli-tool | mcp-server | wiki-entity |\n browser-extension | web-service | api. Use exactly one of these strings.\n- integrations[i].invocationHint.kind: one of bash-cmd | bash-curl | mcp-tool |\n bash-script | write-artifact | manual-handoff | chrome-extension | computer-use.\n- stakeholderTouchpoints[i].name: the person's name as it appears in the wiki.\n- stakeholderTouchpoints[i].produces: 'artifact' | 'send'.\n</output_contract>`;\n\nexport interface RenderPlannerPromptOptions {\n actionItemJson: string;\n discussionSummary?: string;\n reconResultJson: string;\n wikiContextJson: string;\n webResearchContextJson: string;\n maxTier: 'minimal' | 'standard' | 'maximalist';\n budgetCapUsd: number;\n userReplanFeedback?: string;\n}\n\nexport function renderSkillPlannerPrompt(opts: RenderPlannerPromptOptions): string {\n const fewShotBlock = FEW_SHOT_EXAMPLES;\n const replanBlock = opts.userReplanFeedback\n ? `<replan_feedback>${opts.userReplanFeedback}</replan_feedback>`\n : '';\n return `<role>\nYou are the Skill Planner — an agent that designs Claude Code skills that\nORCHESTRATE THE USER'S TOOLS to do real work end-to-end, not skills that\nproduce documents about work.\n</role>\n\n${SKILL_OPERATING_MODEL}\n\n${MASTER_GPT_PROMPTER_HARDENING}\n\n${AMBITION_DIRECTIVE}\n\n${ORCHESTRATION_DIRECTIVES}\n\n${INVOCATION_HINT_DIRECTIVE}\n\n${OUTPUT_CONTRACT}\n\n<input>\n<action>${opts.actionItemJson}</action>\n<linked_discussion_summary>${opts.discussionSummary ?? ''}</linked_discussion_summary>\n<recon>\n <pc_scan>${opts.reconResultJson}</pc_scan>\n <wiki_context>${opts.wikiContextJson}</wiki_context>\n <web_research>${opts.webResearchContextJson}</web_research>\n</recon>\n<settings>\n <max_tier>${opts.maxTier}</max_tier>\n <budget_cap_usd>${opts.budgetCapUsd}</budget_cap_usd>\n</settings>\n${replanBlock}\n</input>\n\n${fewShotBlock}`;\n}\n\n/**\n * Few-shot library — three condensed examples that span the three primary\n * domain × integration-kind combinations the Planner needs to internalize.\n * Full examples live in docs/development/SKILL_CREATOR.md §6.5b; the embedded versions\n * are pared to the load-bearing fields (action + recon summary + proposal\n * key fields) so we don't blow the context budget.\n */\nexport const FEW_SHOT_EXAMPLES = `<few_shot_examples>\n## Example 1 — Creative/comms (PC app + MCP + wiki stakeholder)\nAction: \"Record YouTube intro for Q3 launch — 3-minute video for Danish SMB landing page\"\nRecon: apps=[Elgato Teleprompter (local-http)], mcp=[google-calendar], wiki: stakeholder Mads Larsen (video editor, mads@example.dk)\nMaximalist proposal:\n integrations:\n - { id: elgato-load, source: pc-app, invocationHint: { kind: bash-curl, tools: ['Bash(curl *)'],\n snippet: \"curl -X POST http://localhost:9012/scripts -H 'Content-Type: application/json' -d @references/script.json\" },\n surfacedFrom: web-research-per-app }\n - { id: calendar-practice, source: mcp-server, invocationHint: { kind: mcp-tool, tools: ['mcp__google_calendar__create_event'] }, surfacedFrom: pc-scan }\n - { id: calendar-record, source: mcp-server, invocationHint: { kind: mcp-tool, tools: ['mcp__google_calendar__create_event'] }, surfacedFrom: pc-scan }\n - { id: editor-brief, source: wiki-entity, invocationHint: { kind: write-artifact, tools: ['Write'], artifactPath: 'references/email-to-mads.md' }, surfacedFrom: wiki-recon }\n stakeholderTouchpoints: [{ name: 'Mads Larsen', role: 'video editor', touchpointKind: draft-email, produces: artifact,\n artifactPath: 'references/email-to-mads.md',\n artifactTemplate: { subject: 'Brief: Q3 launch intro — script attached',\n body: 'Hi Mads, ...' } }]\n recommendedTier: maximalist\n valueRationale: \"Minimal=25% (markdown only); Maximalist=95% — only manual step is the actual recording.\"\n\n## Example 2 — Strategic/research (web + wiki + MCP + advisor stakeholder, ZERO PC apps)\nAction: \"Investigate pricing strategy for Q3 SMB launch — defensible model, 3-5 competitor comparison\"\nRecon: apps=[], mcp=[google-sheets], wiki: stakeholder Alexandra Chen (financial advisor, Slack: @alex); concepts: pricing-strategy, competitor-acme\nMaximalist proposal:\n integrations:\n - { id: scrape-competitors, source: web-service, invocationHint: { kind: bash-cmd, tools: ['WebFetch', 'WebSearch'],\n snippet: 'Use WebFetch on each competitor pricing page in wiki/entities/competitor-*.md' }, surfacedFrom: web-research }\n - { id: comparison-sheet, source: mcp-server, invocationHint: { kind: mcp-tool,\n tools: ['mcp__google_sheets__create_spreadsheet', 'mcp__google_sheets__update_range'] }, surfacedFrom: pc-scan }\n - { id: decision-memo, source: wiki-entity, invocationHint: { kind: write-artifact, tools: ['Write'],\n artifactPath: 'wiki/decisions/2026-q3-pricing-tiers.md' }, surfacedFrom: wiki-recon }\n stakeholderTouchpoints: [{ name: 'Alexandra Chen', role: 'financial advisor', touchpointKind: slack-mention,\n produces: artifact, artifactPath: 'references/slack-msg-to-alex.md',\n artifactTemplate: { body: '@alex — Q3 pricing decision draft is at wiki/decisions/2026-q3-pricing-tiers.md ...' } }]\n recommendedTier: maximalist\n valueRationale: \"Minimal=30% (memo from scratch). Maximalist=95% — decision lands in wiki (compounds), advisor pinged with context.\"\n\n## Example 3 — Browser-use (Chrome extension first-class)\nAction: \"Run weekly LinkedIn outreach for DK SDR pipeline — 25 personalized InMails to ICP-match prospects\"\nRecon: apps=[], mcp=[google-sheets], chrome=true; wiki: do-not-contact veto, outreach-templates concept\nMaximalist proposal:\n integrations:\n - { id: pull-prospects, source: mcp-server, invocationHint: { kind: mcp-tool, tools: ['mcp__google_sheets__read_range'] }, surfacedFrom: pc-scan }\n - { id: filter-do-not-contact, source: web-service, invocationHint: { kind: bash-cmd, tools: ['Read', 'Write'],\n snippet: 'Read wiki/concepts/do-not-contact-list.md and filter prospects.json against it' }, surfacedFrom: wiki-recon }\n - { id: chrome-outreach, source: browser-extension, invocationHint: { kind: chrome-extension, tools: [],\n handoffInstructions: \"Open Claude with the Chrome extension enabled and run: 'Navigate to https://www.linkedin.com/sales/. For each prospect in references/prospects-filtered.json, open their profile, click Message, paste references/templates/inbound-warm.md substituting [[first_name]] and [[company]], and send. Log each result.' Return when done.\" }, surfacedFrom: pc-scan }\n - { id: log-results, source: mcp-server, invocationHint: { kind: mcp-tool, tools: ['mcp__google_sheets__append_row'] }, surfacedFrom: pc-scan }\n vetoes: [\"Never contact prospects from companies in do-not-contact-list\"]\n recommendedTier: maximalist\n valueRationale: \"LinkedIn Sales Nav has no API for individual users. Without Chrome, 100% manual (90min/week). With Chrome, ~85% delegated.\"\n</few_shot_examples>`;\n","/**\n * Skill Planner — Phase 5 reasoning engine (Chunk 3).\n *\n * Per docs/development/SKILL_CREATOR.md §6.5: runs ONE researchModel call (Opus 4.7,\n * 1M context) with the four-section input bundle (action + recon triple +\n * settings + optional replan feedback), gets back a `SkillDesignProposal`,\n * validates against schema + semantic gates, and re-runs once with stronger\n * nudges if the validator rejects.\n */\nimport { runClaude, extractText } from '../../llm/claude-code-runner.js';\nimport { safeParseJSON } from '../parsing/safe-json.js';\nimport {\n skillDesignProposalSchema,\n validateProposalSemantics,\n type SkillDesignProposal,\n} from '../parsing/llm-response-schemas.js';\nimport { logger } from '../logger.js';\nimport { ContractError, ModelError } from '../errors.js';\nimport { renderSkillPlannerPrompt } from '../prompts/skill-planner.js';\nimport type { AppSettings, ActionItem, ConversationSummary } from '../../storage/types.js';\nimport type { ReconTriple } from './recon/orchestrator.js';\nimport type { ProposalIntegration } from '../parsing/llm-response-schemas.js';\nimport type { ResolvedWorkspace } from '../../storage/paths.js';\n\nexport interface RunPlannerOptions {\n workspace: ResolvedWorkspace;\n settings: AppSettings;\n action: ActionItem;\n discussionSummary?: ConversationSummary;\n recon: ReconTriple;\n maxTier?: 'minimal' | 'standard' | 'maximalist';\n /** When provided, this Planner run is a re-plan; feedback is injected into the prompt. */\n userReplanFeedback?: string;\n /** Override default model — useful for tests + cheap dry-runs. */\n modelOverride?: string;\n /** Streaming event sink (planner_reasoning_*). */\n onEvent?: (event: { type: 'tokens'; tokensIn?: number; tokensOut?: number; elapsedMs?: number }) => void;\n}\n\nexport interface RunPlannerResult {\n proposal: SkillDesignProposal;\n costUsd: number;\n attempts: number;\n /** Semantic-gate errors that fired across attempts (last successful attempt's pass = empty). */\n attemptErrors: string[][];\n durationMs: number;\n}\n\nconst MAX_ATTEMPTS = 2;\n\nexport async function runPlanner(opts: RunPlannerOptions): Promise<RunPlannerResult> {\n const started = Date.now();\n const model = opts.modelOverride ?? pickResearchModel(opts.settings);\n const maxTier = opts.maxTier ?? 'maximalist';\n const budgetCap = opts.settings.perCallBudgetUsd ?? 2.5;\n\n const actionItemJson = JSON.stringify(\n {\n id: opts.action.id,\n title: opts.action.title,\n description: opts.action.description,\n priority: opts.action.priority,\n discussionId: opts.action.discussionId,\n },\n null,\n 2,\n );\n const discussionSummaryText = opts.discussionSummary\n ? buildDiscussionSummaryString(opts.discussionSummary)\n : '';\n const reconResultJson = JSON.stringify(summarizeRecon(opts.recon), null, 2);\n\n let attempts = 0;\n let costUsd = 0;\n const attemptErrors: string[][] = [];\n let replanFeedback = opts.userReplanFeedback;\n\n while (attempts < MAX_ATTEMPTS) {\n attempts++;\n const prompt = renderSkillPlannerPrompt({\n actionItemJson,\n discussionSummary: discussionSummaryText,\n reconResultJson,\n wikiContextJson: JSON.stringify(opts.recon.wiki, null, 2),\n webResearchContextJson: JSON.stringify(opts.recon.web, null, 2),\n maxTier,\n budgetCapUsd: budgetCap,\n userReplanFeedback: replanFeedback,\n });\n\n logger.debug('[planner] attempt', { attempt: attempts, model, promptLen: prompt.length });\n\n let text: string;\n try {\n const result = await runClaude({\n prompt,\n model,\n allowedTools: [],\n maxTurns: 1,\n cwd: opts.workspace.root,\n maxBudgetUsd: budgetCap,\n timeoutMs: 10 * 60_000,\n onEvent: opts.onEvent\n ? (evt) => {\n opts.onEvent?.({\n type: 'tokens',\n tokensIn: evt.usage?.input_tokens,\n tokensOut: evt.usage?.output_tokens,\n elapsedMs: Date.now() - started,\n });\n }\n : undefined,\n });\n costUsd += result.json?.cost_usd ?? 0;\n text = extractText(result);\n } catch (err) {\n throw new ModelError(\n `Skill Planner LLM call failed on attempt ${attempts}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n const parsed = safeParseJSON<Record<string, unknown>>(text);\n if (!parsed.success || !parsed.data) {\n attemptErrors.push(['Planner did not return parseable JSON']);\n replanFeedback = strongerNudge(attemptErrors[attemptErrors.length - 1]!, replanFeedback);\n continue;\n }\n\n const schemaResult = skillDesignProposalSchema.safeParse(parsed.data);\n if (!schemaResult.success) {\n const issues = schemaResult.error.issues.slice(0, 8).map((i) => `${i.path.join('.')}: ${i.message}`);\n attemptErrors.push(issues);\n // Stash the raw output for the next-attempt nudge so the model can see\n // what we received and how it failed validation. Helps a lot when the\n // failure is \"expected synonym X but you used Y\".\n logger.debug('[planner] schema failure', { attempt: attempts, rawHead: text.slice(0, 800), issues });\n replanFeedback = strongerNudge(issues, replanFeedback);\n continue;\n }\n\n const proposal = schemaResult.data;\n const wikiKnowledge = {\n playbooks: opts.recon.wiki.playbooks.map((p) => p.slug),\n templates: opts.recon.wiki.templates.map((t) => t.slug),\n domainKnowledge: opts.recon.wiki.domainKnowledge.map((d) => d.slug),\n pastLessons: opts.recon.wiki.pastLessons.map((l) => l.slug),\n };\n const semanticErrors = validateProposalSemantics(proposal, wikiKnowledge);\n if (semanticErrors && semanticErrors.length > 0) {\n attemptErrors.push(semanticErrors);\n replanFeedback = strongerNudge(semanticErrors, replanFeedback);\n continue;\n }\n\n // Project + back-fill — derive requiredTools from invocationHint.tools when the\n // model didn't echo them explicitly (the schema makes the field optional;\n // downstream code needs it populated for grantedTools projection).\n proposal.integrations = proposal.integrations.map((int): ProposalIntegration => ({\n ...int,\n requiredTools: int.requiredTools && int.requiredTools.length > 0 ? int.requiredTools : (int.invocationHint.tools ?? []),\n }));\n\n attemptErrors.push([]); // last attempt clean\n return {\n proposal,\n costUsd,\n attempts,\n attemptErrors,\n durationMs: Date.now() - started,\n };\n }\n\n throw new ContractError(\n `Skill Planner failed validation across ${MAX_ATTEMPTS} attempts. Last errors: ${(attemptErrors[attemptErrors.length - 1] ?? []).join('; ')}`,\n 'Re-run with --debug to see the raw Planner output. Add --planner-tier standard to relax the ≥3 maximalist integrations gate, or seed more wiki / MCP servers and re-run.',\n );\n}\n\n/**\n * Build a stronger replan-feedback nudge from validation errors. The Planner\n * prompt's `<replan_feedback>` block accepts free-form text; we surface the\n * schema/semantic failure verbatim so the model can self-correct.\n */\nfunction strongerNudge(errors: string[], prior?: string): string {\n const lines = [\n '',\n 'YOUR PREVIOUS ATTEMPT FAILED VALIDATION. Specific issues:',\n ...errors.map((e) => ` - ${e}`),\n '',\n 'Re-emit the proposal with these problems fixed. In particular:',\n ' - skillName must be kebab-case (lowercase letters, digits, hyphens) ≤64 chars',\n ' - integrations[] must span ≥2 distinct source values',\n ' - maximalist tier must have ≥3 integrations OR recommendedTier must be minimal/standard',\n ' AND valueRationale must explicitly note the limited environment',\n ' - every integration MUST have a populated invocationHint with kind + tools',\n ' - return ONLY the JSON object, no fences, no prose',\n ];\n return [prior ?? '', lines.join('\\n')].filter(Boolean).join('\\n');\n}\n\nfunction pickResearchModel(settings: AppSettings): string {\n const v = settings.researchModel ?? 'opus';\n return typeof v === 'string' ? v : 'opus';\n}\n\nfunction buildDiscussionSummaryString(summary: ConversationSummary): string {\n const parts: string[] = [];\n if (summary.keyPoints?.length) parts.push(`key points: ${summary.keyPoints.slice(0, 6).join(' | ')}`);\n if (summary.consensus?.length) parts.push(`consensus: ${summary.consensus.slice(0, 4).join(' | ')}`);\n if (summary.disagreements?.length) parts.push(`disagreements: ${summary.disagreements.slice(0, 3).join(' | ')}`);\n if (summary.actionableInsights?.length) parts.push(`insights: ${summary.actionableInsights.slice(0, 4).join(' | ')}`);\n return parts.join('\\n').slice(0, 4000);\n}\n\n/**\n * Compact the recon triple to fit the Planner's context window. Drops fields\n * the Planner doesn't use directly (raw warnings, scannedAt, etc.) and\n * truncates per-entity metadata.\n */\nfunction summarizeRecon(recon: ReconTriple): Record<string, unknown> {\n return {\n platform: recon.pc.platform,\n apps: recon.pc.apps.slice(0, 60).map((a) => ({ name: a.name, version: a.version, category: a.category })),\n cliTools: recon.pc.cliTools.slice(0, 60).map((t) => ({ name: t.name, version: t.version })),\n mcpServers: recon.pc.mcpServers,\n envVars: recon.pc.envVars,\n existingSkills: recon.pc.existingSkills.map((s) => s.name),\n chrome: recon.pc.chrome,\n computerUseAvailable: recon.pc.computerUseAvailable,\n playwright: recon.pc.playwright,\n };\n}\n\n/**\n * Compute `grantedTools` as the deterministic projection of accepted\n * integrations + accepted stakeholders onto the Claude Code tool allowlist.\n * Pure function — exposed for unit tests + the user-review post-acceptance\n * step.\n */\nexport function projectGrantedTools(\n proposal: SkillDesignProposal,\n acceptedIntegrationIds: Set<string>,\n acceptedStakeholderNames: Set<string>,\n): string[] {\n const tools = new Set<string>(['Read', 'Write', 'Glob', 'Grep']);\n for (const integration of proposal.integrations) {\n if (!acceptedIntegrationIds.has(integration.id)) continue;\n for (const t of integration.invocationHint.tools ?? []) tools.add(t);\n for (const t of integration.requiredTools ?? []) tools.add(t);\n }\n // Stakeholder send touchpoints contribute their sendVia tool.\n for (const s of proposal.stakeholderTouchpoints ?? []) {\n if (!acceptedStakeholderNames.has(s.name)) continue;\n if (s.produces === 'send' && s.sendVia) tools.add(s.sendVia);\n }\n return Array.from(tools).sort();\n}\n","/**\r\n * CLI root. Wires commander, global flags, error mapping.\r\n */\r\nimport { Command } from 'commander';\r\nimport { AabError, CancelledError } from './core/errors.js';\r\nimport { logger, setLogLevel, type LogLevel } from './core/logger.js';\r\nimport { c } from './ui/colors.js';\r\nimport { PRODUCT_NAME, VERSION } from './version.js';\r\nimport { registerInitCommand } from './commands/init.js';\r\nimport { registerSettingsCommand } from './commands/settings.js';\r\nimport { registerDoctorCommand } from './commands/doctor.js';\r\nimport { registerWorkspaceCommand } from './commands/workspace.js';\r\nimport { registerDiscussCommand } from './commands/discuss.js';\r\nimport { registerUiCommand } from './commands/ui.js';\r\nimport { registerKnowledgeCommand } from './commands/knowledge.js';\r\nimport { registerMembersCommand } from './commands/members.js';\r\nimport { registerPrinciplesCommand } from './commands/principles.js';\r\nimport { registerCoachCommand } from './commands/coach.js';\r\nimport { registerActionsCommand } from './commands/actions.js';\r\nimport { registerSkillsCommand } from './commands/skills.js';\r\n\r\ninterface GlobalOpts {\r\n workspace?: string;\r\n json?: boolean;\r\n debug?: boolean;\r\n logLevel?: LogLevel;\r\n quiet?: boolean;\r\n}\r\n\r\nexport async function runCli(argv: string[]): Promise<void> {\r\n // Trap Ctrl+C cleanly.\r\n process.on('SIGINT', () => {\r\n process.exit(6);\r\n });\r\n\r\n const program = new Command();\r\n program\r\n .name('aab')\r\n .description(`${PRODUCT_NAME} — convene a panel of Claude sub-agents on any business question.`)\r\n .version(VERSION, '-v, --version', 'output the version number')\r\n .option('--workspace <id>', 'workspace id override (also honors AAB_WORKSPACE env)')\r\n .option('--json', 'machine-readable output where supported')\r\n .option('--debug', 'verbose logging (sets log level to debug)')\r\n .option('--log-level <level>', 'silent | error | warn | info | debug | trace')\r\n .option('--quiet', 'suppress non-error stderr output')\r\n .hook('preAction', (thisCommand) => {\r\n const opts = thisCommand.opts<GlobalOpts>();\r\n if (opts.debug) setLogLevel('debug');\r\n else if (opts.logLevel) setLogLevel(opts.logLevel);\r\n else if (opts.quiet) setLogLevel('error');\r\n });\r\n\r\n // Subcommands\r\n registerInitCommand(program);\r\n registerSettingsCommand(program);\r\n registerDoctorCommand(program);\r\n registerWorkspaceCommand(program);\r\n registerDiscussCommand(program);\r\n registerUiCommand(program);\r\n registerKnowledgeCommand(program);\r\n registerMembersCommand(program);\r\n registerPrinciplesCommand(program);\r\n registerCoachCommand(program);\r\n registerActionsCommand(program);\r\n registerSkillsCommand(program);\r\n\r\n // Friendly default when no command given\r\n program.action(() => {\r\n program.outputHelp();\r\n });\r\n\r\n try {\r\n await program.parseAsync(argv);\r\n } catch (error) {\r\n handleError(error);\r\n }\r\n}\r\n\r\nfunction handleError(error: unknown): never {\r\n if (error instanceof CancelledError) {\r\n logger.warn(error.message);\r\n process.exit(error.exitCode);\r\n }\r\n if (error instanceof AabError) {\r\n process.stderr.write(`${c.err('✗')} ${error.message}\\n`);\r\n if (error.hint) process.stderr.write(`${c.hint(' ' + error.hint)}\\n`);\r\n process.exit(error.exitCode);\r\n }\r\n const msg = error instanceof Error ? error.message : String(error);\r\n process.stderr.write(`${c.err('✗')} ${msg}\\n`);\r\n if (error instanceof Error && error.stack) logger.debug(error.stack);\r\n process.exit(1);\r\n}\r\n","/**\r\n * Color helpers. We use chalk lazily so colors auto-disable in non-TTY pipes.\r\n */\r\nimport chalk from 'chalk';\r\n\r\nconst MEMBER_PALETTE = [\r\n chalk.cyanBright,\r\n chalk.greenBright,\r\n chalk.yellowBright,\r\n chalk.magentaBright,\r\n chalk.blueBright,\r\n chalk.redBright,\r\n chalk.white,\r\n] as const;\r\n\r\n/** Deterministic per-member color (FNV-1a → palette index). */\r\nexport function memberColor(name: string): (s: string) => string {\r\n let hash = 2166136261 >>> 0;\r\n for (let i = 0; i < name.length; i++) {\r\n hash ^= name.charCodeAt(i);\r\n hash = Math.imul(hash, 16777619) >>> 0;\r\n }\r\n const idx = hash % MEMBER_PALETTE.length;\r\n return MEMBER_PALETTE[idx]!;\r\n}\r\n\r\nexport const c = {\r\n bold: chalk.bold,\r\n dim: chalk.dim,\r\n cyan: chalk.cyan,\r\n green: chalk.green,\r\n yellow: chalk.yellow,\r\n red: chalk.red,\r\n blue: chalk.blue,\r\n magenta: chalk.magenta,\r\n gray: chalk.gray,\r\n whiteBright: chalk.whiteBright,\r\n ok: chalk.greenBright,\r\n warn: chalk.yellow,\r\n err: chalk.redBright,\r\n hint: chalk.gray,\r\n brand: chalk.bold.cyan,\r\n};\r\n\r\nexport function brand(): string {\r\n return c.brand('AI Advisory Board CLI');\r\n}\r\n","/**\r\n * Version + brand strings. Read once at startup.\r\n */\r\nimport { readFileSync } from 'node:fs';\r\nimport { dirname, join } from 'node:path';\r\nimport { fileURLToPath } from 'node:url';\r\n\r\ninterface PackageMeta {\r\n version: string;\r\n description?: string;\r\n}\r\n\r\nfunction findPackageJson(): PackageMeta {\r\n const here = dirname(fileURLToPath(import.meta.url));\r\n // Walk up until we find a package.json (works in src/, dist/bin/, etc.)\r\n let dir = here;\r\n for (let i = 0; i < 6; i++) {\r\n try {\r\n const raw = readFileSync(join(dir, 'package.json'), 'utf8');\r\n return JSON.parse(raw) as PackageMeta;\r\n } catch {\r\n const parent = dirname(dir);\r\n if (parent === dir) break;\r\n dir = parent;\r\n }\r\n }\r\n return { version: '0.0.0' };\r\n}\r\n\r\nconst meta = findPackageJson();\r\nexport const VERSION = meta.version;\r\nexport const PRODUCT_NAME = 'AI Advisory Board CLI';\r\nexport const PRODUCT_DESCRIPTION =\r\n meta.description ||\r\n 'Convene a panel of Claude sub-agents and turn their action items into Claude Code skills.';\r\n","/**\r\n * `aab init` — bootstrap a workspace.\r\n *\r\n * Phase 0 scope (claude-CLI-native):\r\n * - detect Claude Code session\r\n * - detect the `claude` binary on PATH\r\n * - choose home (~/.aabcli) or project-mounted (./.aabcli) workspace\r\n * - seed starter members and starter principles\r\n * - emit one .claude/agents/<member-slug>.md per starter member\r\n * - write a default settings.json\r\n *\r\n * No Anthropic API key — the CLI shells out to `claude` for all LLM calls,\r\n * which uses the user's existing Claude Max/Pro subscription.\r\n */\r\nimport { Command } from 'commander';\r\nimport { existsSync, mkdirSync, writeFileSync } from 'node:fs';\r\nimport { dirname, join } from 'node:path';\r\nimport { detectClaudeCode } from '../env/detect-claude-code.js';\r\nimport { detectClaudeCli } from '../llm/claude-code-runner.js';\r\nimport { generateUUID, nowIso } from '../core/utils.js';\r\nimport { c, brand } from '../ui/colors.js';\r\nimport { askConfirm, askSelect } from '../ui/prompts.js';\r\nimport { spinner } from '../ui/spinner.js';\r\nimport { homeRoot, paths, setActiveWorkspaceId, slugifyWorkspaceId } from '../storage/paths.js';\r\nimport { FsStorageService } from '../storage/fs-storage-service.js';\r\nimport { DEFAULT_SETTINGS, type AdvisoryBoardMember, type Principle } from '../storage/types.js';\r\nimport { STARTER_BOARD_MEMBERS } from '../starter/starter-board-members.js';\r\nimport { STARTER_PRINCIPLES } from '../starter/starter-principles.js';\r\nimport { emitMemberAgentFile } from '../agents/emit-member-agent.js';\r\nimport { ResolvedWorkspace } from '../storage/paths.js';\r\nimport { emitWikiSkeleton } from '../core/knowledge/schema-emitter.js';\r\nimport { emitFoamRecommendation } from '../core/knowledge/foam.js';\r\nimport { resolveSkillCreator, skillCreatorInstallHint } from '../core/skill/resolve-skill-creator.js';\r\n\r\nexport function registerInitCommand(program: Command): void {\r\n program\r\n .command('init')\r\n .description('bootstrap a workspace, seed starter members and principles, write .claude/agents/')\r\n .option('--non-interactive', 'skip prompts (use --here / --home + --no-seed defaults)')\r\n .option('--here', 'mount workspace at ./.aabcli/ (project-scoped)')\r\n .option('--home', 'mount workspace at ~/.aabcli/<slug>/ (default)')\r\n .option('--name <slug>', 'workspace id override')\r\n .option('--no-seed', 'skip seeding starter members and principles')\r\n .option('--no-agents', 'skip writing .claude/agents/<member>.md files')\r\n .option('--agents-dir <path>', 'where to write .claude/agents/ (default: cwd)')\r\n .option('--no-wiki', 'skip emitting wiki/KNOWLEDGE.md + wiki/index.md + raw/')\r\n .option('--foam', 'recommend the Foam VS Code extension via .vscode/extensions.json')\r\n .option('--foam-overwrite', 'overwrite an unparseable .vscode/extensions.json (rare)')\r\n .option('--install-skill-creator', 'detect skill-creator (Phase 5 prereq) and print install instructions if missing')\r\n .action(async (cmdOpts: InitOptions) => {\r\n await runInit(cmdOpts);\r\n });\r\n}\r\n\r\ninterface InitOptions {\r\n nonInteractive?: boolean;\r\n here?: boolean;\r\n home?: boolean;\r\n name?: string;\r\n seed?: boolean;\r\n agents?: boolean;\r\n agentsDir?: string;\r\n wiki?: boolean;\r\n foam?: boolean;\r\n foamOverwrite?: boolean;\r\n installSkillCreator?: boolean;\r\n}\r\n\r\nasync function runInit(opts: InitOptions): Promise<void> {\r\n process.stdout.write(`\\n${brand()}\\n`);\r\n process.stdout.write(c.hint(' Convene a panel of Claude sub-agents on any business question.\\n\\n'));\r\n\r\n // 1. Detect Claude Code session\r\n const ccEnv = detectClaudeCode();\r\n process.stdout.write(\r\n `Claude Code session: ${ccEnv.detected ? c.ok('detected ✓') : c.hint('not detected')}` +\r\n (ccEnv.version ? ` ${c.hint('(' + ccEnv.version + ')')}` : '') +\r\n '\\n',\r\n );\r\n\r\n // 2. Detect `claude` CLI on PATH (this is what we shell out to for LLM calls)\r\n const sp = spinner('Looking for `claude` CLI on PATH...');\r\n sp.start();\r\n const cli = await detectClaudeCli();\r\n if (cli.installed) {\r\n sp.succeed(`Found \\`claude\\` CLI${cli.version ? ' v' + cli.version : ''}.`);\r\n } else {\r\n sp.fail(`\\`claude\\` CLI not found on PATH.`);\r\n process.stdout.write(\r\n c.hint(\r\n '\\n The CLI uses the `claude` binary to run all LLM calls — no API key required.\\n' +\r\n ' Install it: ' +\r\n c.cyan('npm install -g @anthropic-ai/claude-code') +\r\n '\\n Or grab Claude Desktop and ensure `claude` is on PATH.\\n\\n',\r\n ),\r\n );\r\n if (!opts.nonInteractive) {\r\n const proceed = await askConfirm('Continue anyway? (you can install claude later and re-run init)', false);\r\n if (!proceed) return;\r\n }\r\n }\r\n\r\n // 3. Choose workspace location\r\n const workspace = await chooseWorkspace(opts);\r\n process.stdout.write(`Workspace: ${c.bold(workspace.id)} ${c.hint('(' + workspace.scope + ': ' + workspace.root + ')')}\\n`);\r\n\r\n // Sanity: refuse to overwrite an existing workspace silently\r\n const settingsPath = paths(workspace.root).settings;\r\n if (existsSync(settingsPath) && !opts.nonInteractive) {\r\n const ok = await askConfirm(\r\n `A workspace already exists at ${workspace.root}. Re-seed and overwrite settings?`,\r\n false,\r\n );\r\n if (!ok) {\r\n process.stdout.write(c.hint('Aborted; nothing changed.\\n'));\r\n return;\r\n }\r\n }\r\n\r\n const storage = new FsStorageService(workspace);\r\n\r\n // 4. Save settings\r\n const sp2 = spinner('Writing workspace files...');\r\n sp2.start();\r\n await storage.saveSettings({ ...DEFAULT_SETTINGS });\r\n\r\n // Mark workspace version + active pointer\r\n writeFileSync(paths(workspace.root).versionFile, '1', 'utf8');\r\n if (workspace.scope === 'home') setActiveWorkspaceId(workspace.id);\r\n\r\n // 5. Seed starter members and principles (unless --no-seed)\r\n let memberCount = 0;\r\n let principleCount = 0;\r\n const seededMembers: AdvisoryBoardMember[] = [];\r\n\r\n if (opts.seed !== false) {\r\n const now = nowIso();\r\n\r\n for (const starter of STARTER_BOARD_MEMBERS) {\r\n const member: AdvisoryBoardMember = {\r\n id: generateUUID(),\r\n name: starter.name,\r\n title: starter.title,\r\n expertise: starter.expertise,\r\n persona: starter.persona,\r\n voiceGuide: starter.voiceGuide,\r\n avatar: starter.avatar,\r\n isActive: starter.isActive,\r\n createdAt: now,\r\n updatedAt: now,\r\n };\r\n await storage.saveBoardMember(member);\r\n seededMembers.push(member);\r\n memberCount++;\r\n }\r\n\r\n for (const starter of STARTER_PRINCIPLES) {\r\n const principle: Principle = {\r\n id: generateUUID(),\r\n category: starter.category,\r\n title: starter.title,\r\n description: starter.description,\r\n behavior: starter.behavior,\r\n antiPattern: starter.antiPattern,\r\n triggerQuestions: starter.triggerQuestions,\r\n priority: starter.priority,\r\n examples: starter.examples,\r\n isActive: starter.isActive,\r\n createdAt: now,\r\n updatedAt: now,\r\n };\r\n await storage.savePrinciple(principle);\r\n principleCount++;\r\n }\r\n }\r\n sp2.succeed(\r\n `Workspace ready (${memberCount} starter members, ${principleCount} starter principles).`,\r\n );\r\n\r\n // 6. Generate .claude/agents/<slug>.md for each member (so Claude Code can dispatch them)\r\n if (opts.agents !== false && seededMembers.length > 0) {\r\n const projectRoot = opts.agentsDir ?? process.cwd();\r\n const sp3 = spinner(`Writing .claude/agents/ to ${projectRoot}/.claude/agents/...`);\r\n sp3.start();\r\n let written = 0;\r\n let skipped = 0;\r\n for (const member of seededMembers) {\r\n const result = emitMemberAgentFile(member, { projectRoot });\r\n if (result.written) written++;\r\n else skipped++;\r\n }\r\n sp3.succeed(\r\n `Sub-agents written (${written} new, ${skipped} skipped${\r\n skipped > 0 ? ' — user-edited files preserved' : ''\r\n }).`,\r\n );\r\n }\r\n\r\n // 7. Bootstrap the Knowledge Wiki (Phase 1.5) — idempotent, never overwrites\r\n if (opts.wiki !== false) {\r\n const sp4 = spinner('Bootstrapping wiki/ + raw/ + .manifest.json...');\r\n sp4.start();\r\n const result = emitWikiSkeleton({ workspaceRoot: workspace.root });\r\n const total = result.wrote.length + result.skipped.length;\r\n sp4.succeed(\r\n `Knowledge Wiki ready (${result.wrote.length} new, ${result.skipped.length} preserved; ${total} files total).`,\r\n );\r\n }\r\n\r\n // 8. Foam recommendation (opt-in via --foam)\r\n const wikiSettings = (await storage.loadSettings()).knowledgeWiki;\r\n const wantFoam = opts.foam || (opts.foam !== false && wikiSettings?.recommendFoam && opts.here);\r\n if (wantFoam) {\r\n const projectRootForFoam = opts.agentsDir ?? process.cwd();\r\n const result = emitFoamRecommendation({ projectRoot: projectRootForFoam, force: !!opts.foamOverwrite });\r\n if (result.action === 'created') {\r\n process.stdout.write(`${c.ok('✓')} Foam recommended in ${c.bold(result.path)} ${c.hint('— open in VS Code for [[wikilinks]] support')}\\n`);\r\n } else if (result.action === 'merged') {\r\n process.stdout.write(`${c.ok('✓')} Foam appended to existing ${c.bold(result.path)}\\n`);\r\n } else {\r\n process.stdout.write(`${c.hint('—')} Foam: ${result.reason}\\n`);\r\n }\r\n }\r\n\r\n // 9. skill-creator detection (Phase 5 prerequisite)\r\n const projectRootForSkills = opts.agentsDir ?? process.cwd();\r\n const resolved = resolveSkillCreator({ projectRoot: projectRootForSkills });\r\n if (resolved) {\r\n process.stdout.write(\r\n `${c.ok('✓')} skill-creator detected ${c.hint('(' + resolved.scope + ' scope: ' + resolved.dir + (resolved.version ? '; v' + resolved.version : '') + ')')}\\n`,\r\n );\r\n } else if (opts.installSkillCreator) {\r\n process.stdout.write(`${c.warn('!')} skill-creator skill not found.\\n`);\r\n process.stdout.write(c.hint(skillCreatorInstallHint().split('\\n').map((l) => ' ' + l).join('\\n')) + '\\n');\r\n } else {\r\n process.stdout.write(\r\n `${c.hint('—')} skill-creator skill not found ${c.hint('(install with `aab init --install-skill-creator` when ready to use `aab actions solve`)')}\\n`,\r\n );\r\n }\r\n\r\n // Next steps\r\n process.stdout.write('\\n' + c.bold('Next steps:') + '\\n');\r\n process.stdout.write(` ${c.cyan('aab doctor')} ${c.hint('— verify everything is wired up')}\\n`);\r\n process.stdout.write(` ${c.cyan('aab settings get')}\\n`);\r\n process.stdout.write(` ${c.cyan('aab discuss start')} ${c.hint('\"What should we focus on this quarter?\"')}\\n`);\r\n process.stdout.write(` ${c.cyan('aab knowledge ingest')} ${c.hint('<path-or-url> — seed the wiki')}\\n`);\r\n process.stdout.write('\\n');\r\n}\r\n\r\nasync function chooseWorkspace(opts: InitOptions): Promise<ResolvedWorkspace> {\r\n const cwd = process.cwd();\r\n const cwdName = cwd.split(/[\\\\/]/).pop() ?? 'workspace';\r\n const id = opts.name ? slugifyWorkspaceId(opts.name) : slugifyWorkspaceId(cwdName);\r\n\r\n if (opts.here) {\r\n const root = join(cwd, '.aabcli');\r\n ensure(root);\r\n return { id: `project-${id}`, root, scope: 'project' };\r\n }\r\n if (opts.home || opts.nonInteractive) {\r\n const root = join(homeRoot(), id);\r\n ensure(root);\r\n return { id, root, scope: 'home' };\r\n }\r\n\r\n const choice = await askSelect('Where should this workspace live?', [\r\n { name: 'home', message: `Home directory (~/.aabcli/${id}/)`, hint: 'shared across projects' },\r\n { name: 'project', message: `Current directory (./.aabcli/)`, hint: 'travels with this repo' },\r\n ]);\r\n\r\n if (choice === 'project') {\r\n const root = join(cwd, '.aabcli');\r\n ensure(root);\r\n return { id: `project-${id}`, root, scope: 'project' };\r\n }\r\n const root = join(homeRoot(), id);\r\n ensure(root);\r\n return { id, root, scope: 'home' };\r\n}\r\n\r\nfunction ensure(root: string): void {\r\n if (!existsSync(root)) mkdirSync(root, { recursive: true });\r\n const parent = dirname(root);\r\n if (!existsSync(parent)) mkdirSync(parent, { recursive: true });\r\n}\r\n","/**\r\n * Heuristics for detecting whether the CLI is running inside Claude Code.\r\n *\r\n * The Claude Code harness sets a handful of environment variables prefixed\r\n * with CLAUDE_CODE_* / CLAUDECODE_* / CLAUDE_*; the exact set varies by\r\n * version. We treat ANY of these as evidence and fall back to \"no\".\r\n */\r\nexport interface ClaudeCodeEnv {\r\n detected: boolean;\r\n version?: string;\r\n hints: string[];\r\n}\r\n\r\nconst HINT_VARS = [\r\n 'CLAUDE_CODE',\r\n 'CLAUDE_CODE_VERSION',\r\n 'CLAUDECODE',\r\n 'CLAUDECODE_VERSION',\r\n 'CLAUDE_AGENT_SDK',\r\n 'CLAUDE_PROJECT_DIR',\r\n];\r\n\r\nexport function detectClaudeCode(env: NodeJS.ProcessEnv = process.env): ClaudeCodeEnv {\r\n const hints: string[] = [];\r\n let version: string | undefined;\r\n for (const v of HINT_VARS) {\r\n if (env[v]) {\r\n hints.push(v);\r\n if (/VERSION$/.test(v) && !version) version = env[v];\r\n }\r\n }\r\n return { detected: hints.length > 0, version, hints };\r\n}\r\n","import { randomUUID, randomBytes } from 'node:crypto';\r\n\r\n/**\r\n * Generate a v4 UUID. Uses node:crypto.randomUUID when available; otherwise\r\n * falls back to manual v4 generation from random bytes.\r\n */\r\nexport function generateUUID(): string {\r\n if (typeof randomUUID === 'function') {\r\n return randomUUID();\r\n }\r\n const bytes = randomBytes(16);\r\n bytes[6] = (bytes[6]! & 0x0f) | 0x40; // version 4\r\n bytes[8] = (bytes[8]! & 0x3f) | 0x80; // variant 10xx\r\n const hex = bytes.toString('hex');\r\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;\r\n}\r\n\r\n/**\r\n * Normalize a confidence value 0-100; preserve 0; fall back when null/undefined/NaN.\r\n */\r\nexport function normalizeConfidence(value: unknown, fallback = 70): number {\r\n if (typeof value === 'number' && Number.isFinite(value)) return value;\r\n if (typeof value === 'string' && value.trim() !== '') {\r\n const n = Number(value);\r\n if (Number.isFinite(n)) return n;\r\n }\r\n return fallback;\r\n}\r\n\r\n/**\r\n * Sleep for `ms` milliseconds.\r\n */\r\nexport function sleep(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n}\r\n\r\n/**\r\n * Clamp an integer to [min, max].\r\n */\r\nexport function clampInt(value: number, min: number, max: number): number {\r\n if (!Number.isFinite(value)) return min;\r\n const v = Math.round(value);\r\n if (v < min) return min;\r\n if (v > max) return max;\r\n return v;\r\n}\r\n\r\n/**\r\n * ISO-8601 timestamp string for storage. Always UTC.\r\n */\r\nexport function nowIso(): string {\r\n return new Date().toISOString();\r\n}\r\n\r\n/**\r\n * Format a duration in milliseconds as a short human string (\"4m 12s\", \"850ms\").\r\n */\r\nexport function formatDuration(ms: number): string {\r\n if (ms < 1000) return `${Math.round(ms)}ms`;\r\n const seconds = ms / 1000;\r\n if (seconds < 60) return `${seconds.toFixed(1)}s`;\r\n const minutes = Math.floor(seconds / 60);\r\n const remainder = Math.round(seconds - minutes * 60);\r\n return `${minutes}m ${remainder}s`;\r\n}\r\n\r\n/**\r\n * Format USD with 4 fractional digits (small per-call costs need precision).\r\n */\r\nexport function formatUsd(amount: number): string {\r\n if (amount === 0) return '$0.00';\r\n if (amount < 0.01) return `$${amount.toFixed(4)}`;\r\n return `$${amount.toFixed(2)}`;\r\n}\r\n","/**\r\n * Thin wrappers around enquirer so callers don't import it directly.\r\n * Returning typed values; throws CancelledError on user abort.\r\n */\r\nimport enquirer from 'enquirer';\r\nimport { CancelledError } from '../core/errors.js';\r\n\r\nconst { prompt } = enquirer;\r\n\r\nexport async function askText(message: string, opts: { initial?: string; required?: boolean } = {}): Promise<string> {\r\n try {\r\n const answer = (await prompt<{ value: string }>({\r\n type: 'input',\r\n name: 'value',\r\n message,\r\n initial: opts.initial,\r\n validate: (v: string) => (opts.required && !v.trim() ? 'Required' : true),\r\n })).value;\r\n return answer.trim();\r\n } catch {\r\n throw new CancelledError();\r\n }\r\n}\r\n\r\nexport async function askSecret(message: string, opts: { required?: boolean } = {}): Promise<string> {\r\n try {\r\n const answer = (await prompt<{ value: string }>({\r\n type: 'password',\r\n name: 'value',\r\n message,\r\n validate: (v: string) => (opts.required && !v.trim() ? 'Required' : true),\r\n })).value;\r\n return answer.trim();\r\n } catch {\r\n throw new CancelledError();\r\n }\r\n}\r\n\r\nexport async function askConfirm(message: string, initial = true): Promise<boolean> {\r\n try {\r\n const answer = (await prompt<{ value: boolean }>({\r\n type: 'confirm',\r\n name: 'value',\r\n message,\r\n initial,\r\n })).value;\r\n return answer;\r\n } catch {\r\n throw new CancelledError();\r\n }\r\n}\r\n\r\nexport async function askSelect<T extends string>(\r\n message: string,\r\n choices: Array<{ name: T; message?: string; hint?: string }>,\r\n opts: { initial?: T } = {},\r\n): Promise<T> {\r\n try {\r\n const initialIndex = opts.initial ? choices.findIndex((c) => c.name === opts.initial) : 0;\r\n const answer = (await prompt<{ value: T }>({\r\n type: 'select',\r\n name: 'value',\r\n message,\r\n choices: choices.map((c) => ({ name: c.name, message: c.message ?? c.name, hint: c.hint })),\r\n initial: initialIndex < 0 ? 0 : initialIndex,\r\n })).value;\r\n return answer;\r\n } catch {\r\n throw new CancelledError();\r\n }\r\n}\r\n\r\nexport async function askMultiSelect<T extends string>(\r\n message: string,\r\n choices: Array<{ name: T; message?: string; hint?: string; selected?: boolean }>,\r\n): Promise<T[]> {\r\n try {\r\n const answer = (await prompt<{ value: T[] }>({\r\n type: 'multiselect',\r\n name: 'value',\r\n message,\r\n choices: choices.map((c) => ({\r\n name: c.name,\r\n message: c.message ?? c.name,\r\n hint: c.hint,\r\n enabled: c.selected ?? false,\r\n })),\r\n } as unknown as Parameters<typeof prompt>[0])).value;\r\n return answer;\r\n } catch {\r\n throw new CancelledError();\r\n }\r\n}\r\n","/**\r\n * Spinner wrapper. Quietly no-ops when stdout isn't a TTY (so piping is clean).\r\n */\r\nimport oraImport from 'ora';\r\n\r\nconst ora = oraImport;\r\n\r\nexport function spinner(text: string) {\r\n if (!process.stdout.isTTY) {\r\n return {\r\n start: () => undefined,\r\n succeed: (t?: string) => {\r\n if (t) process.stderr.write(`✓ ${t}\\n`);\r\n },\r\n fail: (t?: string) => {\r\n if (t) process.stderr.write(`✗ ${t}\\n`);\r\n },\r\n info: (t?: string) => {\r\n if (t) process.stderr.write(`• ${t}\\n`);\r\n },\r\n warn: (t?: string) => {\r\n if (t) process.stderr.write(`⚠ ${t}\\n`);\r\n },\r\n text,\r\n stop: () => undefined,\r\n };\r\n }\r\n return ora({ text, stream: process.stderr });\r\n}\r\n","import { homedir } from 'node:os';\r\nimport { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';\r\nimport { dirname, join, resolve } from 'node:path';\r\nimport slugify from 'slugify';\r\n\r\nconst ROOT_HOME = '.aabcli';\r\nconst ROOT_PROJECT = '.aabcli';\r\nconst ACTIVE_FILE = '.active';\r\n\r\nexport interface ResolvedWorkspace {\r\n /** Slug id of the workspace. */\r\n id: string;\r\n /** Absolute path to the workspace root directory. */\r\n root: string;\r\n /** 'home' (under ~/.aabcli) or 'project' (./.aabcli mounted in cwd). */\r\n scope: 'home' | 'project';\r\n}\r\n\r\nexport function homeRoot(): string {\r\n return join(homedir(), ROOT_HOME);\r\n}\r\n\r\n/**\r\n * Slugify a workspace identifier deterministically.\r\n */\r\nexport function slugifyWorkspaceId(input: string): string {\r\n const slug = slugify(input, { lower: true, strict: true });\r\n return slug || 'default';\r\n}\r\n\r\n/**\r\n * Read the active workspace id pointer (~/.aabcli/.active).\r\n */\r\nexport function getActiveWorkspaceId(): string | null {\r\n const p = join(homeRoot(), ACTIVE_FILE);\r\n if (!existsSync(p)) return null;\r\n try {\r\n const value = readFileSync(p, 'utf8').trim();\r\n return value || null;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Set the active workspace id pointer.\r\n */\r\nexport function setActiveWorkspaceId(id: string): void {\r\n const p = join(homeRoot(), ACTIVE_FILE);\r\n mkdirSync(dirname(p), { recursive: true });\r\n writeFileSync(p, id, 'utf8');\r\n}\r\n\r\n/**\r\n * Resolve which workspace the CLI should use for this invocation.\r\n *\r\n * Order:\r\n * 1. Explicit override (--workspace flag, AAB_WORKSPACE env)\r\n * 2. Project-mounted workspace at ./.aabcli (if it exists)\r\n * 3. Active workspace pointer in ~/.aabcli/.active\r\n * 4. cwd-basename slug under ~/.aabcli/<slug>\r\n */\r\nexport function resolveWorkspace(options: {\r\n override?: string;\r\n cwd?: string;\r\n} = {}): ResolvedWorkspace {\r\n const cwd = options.cwd ?? process.cwd();\r\n\r\n if (options.override) {\r\n const id = slugifyWorkspaceId(options.override);\r\n return { id, root: join(homeRoot(), id), scope: 'home' };\r\n }\r\n\r\n const envOverride = process.env.AAB_WORKSPACE;\r\n if (envOverride) {\r\n const id = slugifyWorkspaceId(envOverride);\r\n return { id, root: join(homeRoot(), id), scope: 'home' };\r\n }\r\n\r\n const projectMount = join(cwd, ROOT_PROJECT);\r\n if (existsSync(projectMount)) {\r\n const id = slugifyWorkspaceId(`project-${cwd.split(/[\\\\/]/).pop() ?? 'workspace'}`);\r\n return { id, root: resolve(projectMount), scope: 'project' };\r\n }\r\n\r\n const active = getActiveWorkspaceId();\r\n if (active) {\r\n return { id: active, root: join(homeRoot(), active), scope: 'home' };\r\n }\r\n\r\n const id = slugifyWorkspaceId(cwd.split(/[\\\\/]/).pop() ?? 'default');\r\n return { id, root: join(homeRoot(), id), scope: 'home' };\r\n}\r\n\r\n/**\r\n * List all workspaces under ~/.aabcli/.\r\n */\r\nexport function listHomeWorkspaces(): string[] {\r\n const root = homeRoot();\r\n if (!existsSync(root)) return [];\r\n return readdirSync(root, { withFileTypes: true })\r\n .filter((d) => d.isDirectory() && !d.name.startsWith('.'))\r\n .map((d) => d.name)\r\n .sort();\r\n}\r\n\r\n/**\r\n * Standard paths within a workspace.\r\n */\r\nexport function paths(root: string): {\r\n settings: string;\r\n members: string;\r\n boards: string;\r\n principles: string;\r\n decisionSessions: string;\r\n discussions: string;\r\n actionItems: string;\r\n prompts: string;\r\n businessContext: string;\r\n businessProfile: string;\r\n skillRuns: string;\r\n sparring: string;\r\n tokenUsage: string;\r\n jobs: string;\r\n snapshots: string;\r\n logs: string;\r\n versionFile: string;\r\n lockFile: string;\r\n // Knowledge Wiki (Phase 1.5)\r\n wiki: string;\r\n wikiKnowledge: string;\r\n wikiIndex: string;\r\n wikiLog: string;\r\n wikiConcepts: string;\r\n wikiEntities: string;\r\n wikiDecisions: string;\r\n wikiSources: string;\r\n wikiComparisons: string;\r\n raw: string;\r\n rawFiles: string;\r\n rawUrls: string;\r\n rawPasted: string;\r\n rawDiscussions: string;\r\n rawSummaries: string;\r\n outputs: string;\r\n manifest: string;\r\n} {\r\n const wiki = join(root, 'wiki');\r\n const raw = join(root, 'raw');\r\n return {\r\n settings: join(root, 'settings.json'),\r\n members: join(root, 'members.json'),\r\n boards: join(root, 'boards.json'),\r\n principles: join(root, 'principles.json'),\r\n decisionSessions: join(root, 'decision-sessions'),\r\n discussions: join(root, 'discussions'),\r\n actionItems: join(root, 'action-items.json'),\r\n prompts: join(root, 'prompts.json'),\r\n businessContext: join(root, 'business-context.json'),\r\n businessProfile: join(root, 'business-profile.json'),\r\n skillRuns: join(root, 'skill-runs'),\r\n sparring: join(root, 'sparring'),\r\n tokenUsage: join(root, 'token-usage'),\r\n jobs: join(root, 'jobs'),\r\n snapshots: join(root, '.snapshots'),\r\n logs: join(root, 'logs'),\r\n versionFile: join(root, '.version'),\r\n lockFile: join(root, '.lock'),\r\n // Knowledge Wiki\r\n wiki,\r\n wikiKnowledge: join(wiki, 'KNOWLEDGE.md'),\r\n wikiIndex: join(wiki, 'index.md'),\r\n wikiLog: join(wiki, 'log.md'),\r\n wikiConcepts: join(wiki, 'concepts'),\r\n wikiEntities: join(wiki, 'entities'),\r\n wikiDecisions: join(wiki, 'decisions'),\r\n wikiSources: join(wiki, 'sources'),\r\n wikiComparisons: join(wiki, 'comparisons'),\r\n raw,\r\n rawFiles: join(raw, 'files'),\r\n rawUrls: join(raw, 'urls'),\r\n rawPasted: join(raw, 'pasted'),\r\n rawDiscussions: join(raw, 'discussions'),\r\n rawSummaries: join(raw, 'summaries'),\r\n outputs: join(root, 'outputs'),\r\n manifest: join(root, '.manifest.json'),\r\n };\r\n}\r\n\r\n/**\r\n * Ensure all expected workspace subdirectories exist.\r\n */\r\nexport function ensureWorkspaceDirs(root: string): void {\r\n const p = paths(root);\r\n for (const dir of [\r\n root,\r\n p.decisionSessions,\r\n p.discussions,\r\n p.skillRuns,\r\n p.sparring,\r\n p.tokenUsage,\r\n p.jobs,\r\n p.snapshots,\r\n p.logs,\r\n ]) {\r\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\r\n }\r\n}\r\n\r\n/**\r\n * Ensure the wiki + raw + outputs directory tree exists (Phase 1.5).\r\n * Idempotent — never overwrites existing files.\r\n */\r\nexport function ensureWikiDirs(root: string): void {\r\n const p = paths(root);\r\n for (const dir of [\r\n p.wiki,\r\n p.wikiConcepts,\r\n p.wikiEntities,\r\n p.wikiDecisions,\r\n p.wikiSources,\r\n p.wikiComparisons,\r\n p.raw,\r\n p.rawFiles,\r\n p.rawUrls,\r\n p.rawPasted,\r\n p.rawDiscussions,\r\n p.rawSummaries,\r\n p.outputs,\r\n ]) {\r\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\r\n }\r\n}\r\n","/**\r\n * Filesystem-backed StorageService.\r\n *\r\n * Each entity is one JSON file (or a JSONL append-only log for token usage).\r\n * Writes are atomic; settings/members/principles also snapshot the previous\r\n * version under .snapshots/ before overwrite.\r\n */\r\nimport { existsSync, mkdirSync, readdirSync, unlinkSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport {\r\n AdvisoryBoardMember,\r\n AppSettings,\r\n Board,\r\n BusinessContext,\r\n BusinessProfile,\r\n ActionItem,\r\n DecisionSession,\r\n DEFAULT_SETTINGS,\r\n Discussion,\r\n Principle,\r\n SkillGenerationRun,\r\n SparringMessage,\r\n SparringSession,\r\n StorageService,\r\n TokenUsageLog,\r\n UserPrompt,\r\n} from './types.js';\r\nimport {\r\n appendJsonl,\r\n readJson,\r\n readJsonlAll,\r\n writeJsonAtomic,\r\n} from './io.js';\r\nimport { ensureWorkspaceDirs, paths, ResolvedWorkspace } from './paths.js';\r\nimport { nowIso } from '../core/utils.js';\r\n\r\nexport class FsStorageService implements StorageService {\r\n private readonly workspace: ResolvedWorkspace;\r\n private readonly p: ReturnType<typeof paths>;\r\n\r\n constructor(workspace: ResolvedWorkspace) {\r\n this.workspace = workspace;\r\n ensureWorkspaceDirs(workspace.root);\r\n this.p = paths(workspace.root);\r\n }\r\n\r\n getWorkspaceId(): string {\r\n return this.workspace.id;\r\n }\r\n\r\n getWorkspaceRoot(): string {\r\n return this.workspace.root;\r\n }\r\n\r\n getWorkspaceScope(): 'home' | 'project' {\r\n return this.workspace.scope;\r\n }\r\n\r\n // ============================================================\r\n // Settings\r\n // ============================================================\r\n\r\n async loadSettings(): Promise<AppSettings> {\r\n const data = readJson<Partial<AppSettings>>(this.p.settings, {});\r\n return { ...DEFAULT_SETTINGS, ...data };\r\n }\r\n\r\n async saveSettings(settings: AppSettings): Promise<void> {\r\n writeJsonAtomic(this.p.settings, settings, { snapshotDir: this.p.snapshots });\r\n }\r\n\r\n // ============================================================\r\n // Board members\r\n // ============================================================\r\n\r\n async loadBoardMembers(): Promise<AdvisoryBoardMember[]> {\r\n return readJson<AdvisoryBoardMember[]>(this.p.members, []);\r\n }\r\n\r\n async saveBoardMember(member: AdvisoryBoardMember): Promise<void> {\r\n const all = await this.loadBoardMembers();\r\n if (all.some((m) => m.id === member.id)) {\r\n throw new Error(`Member with id ${member.id} already exists`);\r\n }\r\n all.push(member);\r\n writeJsonAtomic(this.p.members, all, { snapshotDir: this.p.snapshots });\r\n }\r\n\r\n async updateBoardMember(member: AdvisoryBoardMember): Promise<void> {\r\n const all = await this.loadBoardMembers();\r\n const idx = all.findIndex((m) => m.id === member.id);\r\n if (idx === -1) {\r\n all.push({ ...member, updatedAt: nowIso() });\r\n } else {\r\n all[idx] = { ...member, updatedAt: nowIso() };\r\n }\r\n writeJsonAtomic(this.p.members, all, { snapshotDir: this.p.snapshots });\r\n }\r\n\r\n async deleteBoardMember(id: string): Promise<void> {\r\n const all = await this.loadBoardMembers();\r\n const next = all.filter((m) => m.id !== id);\r\n writeJsonAtomic(this.p.members, next, { snapshotDir: this.p.snapshots });\r\n }\r\n\r\n // ============================================================\r\n // Boards\r\n // ============================================================\r\n\r\n async loadBoards(): Promise<Board[]> {\r\n return readJson<Board[]>(this.p.boards, []);\r\n }\r\n\r\n async saveBoard(board: Board): Promise<void> {\r\n const all = await this.loadBoards();\r\n all.push(board);\r\n writeJsonAtomic(this.p.boards, all);\r\n }\r\n\r\n async updateBoard(board: Board): Promise<void> {\r\n const all = await this.loadBoards();\r\n const idx = all.findIndex((b) => b.id === board.id);\r\n if (idx === -1) all.push(board);\r\n else all[idx] = { ...board, updatedAt: nowIso() };\r\n writeJsonAtomic(this.p.boards, all);\r\n }\r\n\r\n async deleteBoard(id: string): Promise<void> {\r\n const all = await this.loadBoards();\r\n writeJsonAtomic(this.p.boards, all.filter((b) => b.id !== id));\r\n }\r\n\r\n // ============================================================\r\n // Principles\r\n // ============================================================\r\n\r\n async loadPrinciples(): Promise<Principle[]> {\r\n return readJson<Principle[]>(this.p.principles, []);\r\n }\r\n\r\n async savePrinciple(principle: Principle): Promise<void> {\r\n const all = await this.loadPrinciples();\r\n all.push(principle);\r\n writeJsonAtomic(this.p.principles, all, { snapshotDir: this.p.snapshots });\r\n }\r\n\r\n async updatePrinciple(principle: Principle): Promise<void> {\r\n const all = await this.loadPrinciples();\r\n const idx = all.findIndex((p) => p.id === principle.id);\r\n if (idx === -1) all.push({ ...principle, updatedAt: nowIso() });\r\n else all[idx] = { ...principle, updatedAt: nowIso() };\r\n writeJsonAtomic(this.p.principles, all, { snapshotDir: this.p.snapshots });\r\n }\r\n\r\n async deletePrinciple(id: string): Promise<void> {\r\n const all = await this.loadPrinciples();\r\n writeJsonAtomic(\r\n this.p.principles,\r\n all.filter((p) => p.id !== id),\r\n { snapshotDir: this.p.snapshots },\r\n );\r\n }\r\n\r\n // ============================================================\r\n // Decision sessions (one JSON file per session under decision-sessions/)\r\n // ============================================================\r\n\r\n async loadDecisionSessions(): Promise<DecisionSession[]> {\r\n if (!existsSync(this.p.decisionSessions)) return [];\r\n const files = readdirSync(this.p.decisionSessions)\r\n .filter((f) => f.endsWith('.json'))\r\n .sort();\r\n const out: DecisionSession[] = [];\r\n for (const f of files) {\r\n const session = readJson<DecisionSession | null>(join(this.p.decisionSessions, f), null);\r\n if (session) out.push(session);\r\n }\r\n out.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\r\n return out;\r\n }\r\n\r\n async loadDecisionSessionById(id: string): Promise<DecisionSession | null> {\r\n const path = join(this.p.decisionSessions, `${id}.json`);\r\n if (!existsSync(path)) return null;\r\n return readJson<DecisionSession | null>(path, null);\r\n }\r\n\r\n async saveDecisionSession(session: DecisionSession): Promise<void> {\r\n if (!existsSync(this.p.decisionSessions)) mkdirSync(this.p.decisionSessions, { recursive: true });\r\n writeJsonAtomic(join(this.p.decisionSessions, `${session.id}.json`), session);\r\n }\r\n\r\n async updateDecisionSession(session: DecisionSession): Promise<void> {\r\n return this.saveDecisionSession({ ...session, updatedAt: nowIso() });\r\n }\r\n\r\n async deleteDecisionSession(id: string): Promise<void> {\r\n const path = join(this.p.decisionSessions, `${id}.json`);\r\n if (existsSync(path)) unlinkSync(path);\r\n }\r\n\r\n // ============================================================\r\n // Sparring sessions (sparring/<discussionId>/<sessionId>.json)\r\n // ============================================================\r\n\r\n async loadSparringSessionsForDiscussion(discussionId: string): Promise<SparringSession[]> {\r\n const dir = join(this.p.sparring, discussionId);\r\n if (!existsSync(dir)) return [];\r\n const files = readdirSync(dir).filter((f) => f.endsWith('.json')).sort();\r\n const out: SparringSession[] = [];\r\n for (const f of files) {\r\n const session = readJson<SparringSession | null>(join(dir, f), null);\r\n if (session) out.push(session);\r\n }\r\n out.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\r\n return out;\r\n }\r\n\r\n async loadSparringSessionById(sessionId: string): Promise<SparringSession | null> {\r\n if (!existsSync(this.p.sparring)) return null;\r\n const discussionDirs = readdirSync(this.p.sparring, { withFileTypes: true })\r\n .filter((d) => d.isDirectory())\r\n .map((d) => d.name);\r\n for (const did of discussionDirs) {\r\n const candidate = join(this.p.sparring, did, `${sessionId}.json`);\r\n if (existsSync(candidate)) {\r\n return readJson<SparringSession | null>(candidate, null);\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n async saveSparringSession(session: SparringSession): Promise<void> {\r\n const dir = join(this.p.sparring, session.discussionId);\r\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\r\n writeJsonAtomic(join(dir, `${session.id}.json`), session);\r\n }\r\n\r\n async updateSparringSession(session: SparringSession): Promise<void> {\r\n return this.saveSparringSession({ ...session, updatedAt: nowIso() });\r\n }\r\n\r\n async deleteSparringSession(sessionId: string): Promise<void> {\r\n if (!existsSync(this.p.sparring)) return;\r\n const discussionDirs = readdirSync(this.p.sparring, { withFileTypes: true })\r\n .filter((d) => d.isDirectory())\r\n .map((d) => d.name);\r\n for (const did of discussionDirs) {\r\n const candidate = join(this.p.sparring, did, `${sessionId}.json`);\r\n if (existsSync(candidate)) {\r\n unlinkSync(candidate);\r\n return;\r\n }\r\n }\r\n }\r\n\r\n async saveSparringMessage(sessionId: string, message: SparringMessage): Promise<void> {\r\n const session = await this.loadSparringSessionById(sessionId);\r\n if (!session) {\r\n throw new Error(`Sparring session ${sessionId} not found`);\r\n }\r\n session.messages.push(message);\r\n session.updatedAt = nowIso();\r\n await this.saveSparringSession(session);\r\n }\r\n\r\n // ============================================================\r\n // Business context / profile\r\n // ============================================================\r\n\r\n async loadBusinessContext(): Promise<BusinessContext[]> {\r\n return readJson<BusinessContext[]>(this.p.businessContext, []);\r\n }\r\n\r\n async saveBusinessContext(context: BusinessContext): Promise<void> {\r\n const all = await this.loadBusinessContext();\r\n all.push(context);\r\n writeJsonAtomic(this.p.businessContext, all);\r\n }\r\n\r\n async updateBusinessContext(context: BusinessContext): Promise<void> {\r\n const all = await this.loadBusinessContext();\r\n const idx = all.findIndex((c) => c.id === context.id);\r\n if (idx === -1) all.push({ ...context, updatedAt: nowIso() });\r\n else all[idx] = { ...context, updatedAt: nowIso() };\r\n writeJsonAtomic(this.p.businessContext, all);\r\n }\r\n\r\n async deleteBusinessContext(id: string): Promise<void> {\r\n const all = await this.loadBusinessContext();\r\n writeJsonAtomic(this.p.businessContext, all.filter((c) => c.id !== id));\r\n }\r\n\r\n async loadBusinessProfile(): Promise<BusinessProfile | null> {\r\n if (!existsSync(this.p.businessProfile)) return null;\r\n return readJson<BusinessProfile | null>(this.p.businessProfile, null);\r\n }\r\n\r\n async saveBusinessProfile(profile: BusinessProfile): Promise<void> {\r\n writeJsonAtomic(this.p.businessProfile, profile, { snapshotDir: this.p.snapshots });\r\n }\r\n\r\n // ============================================================\r\n // Discussions (one JSON file per discussion under discussions/)\r\n // ============================================================\r\n\r\n async loadDiscussions(): Promise<Discussion[]> {\r\n if (!existsSync(this.p.discussions)) return [];\r\n const files = readdirSync(this.p.discussions)\r\n .filter((f) => f.endsWith('.json'))\r\n .sort();\r\n const out: Discussion[] = [];\r\n for (const f of files) {\r\n const d = readJson<Discussion | null>(join(this.p.discussions, f), null);\r\n if (d) out.push(d);\r\n }\r\n out.sort((a, b) => b.createdAt.localeCompare(a.createdAt));\r\n return out;\r\n }\r\n\r\n async loadDiscussionPage(\r\n options: { limit?: number; offset?: number; includeArchived?: boolean } = {},\r\n ): Promise<{ discussions: Discussion[]; totalCount: number; hasMore: boolean }> {\r\n const all = await this.loadDiscussions();\r\n const filtered = options.includeArchived ? all : all.filter((d) => !d.archivedAt);\r\n const offset = options.offset ?? 0;\r\n const limit = options.limit ?? 20;\r\n const slice = filtered.slice(offset, offset + limit);\r\n return { discussions: slice, totalCount: filtered.length, hasMore: offset + limit < filtered.length };\r\n }\r\n\r\n async loadDiscussionById(id: string): Promise<Discussion | null> {\r\n const path = join(this.p.discussions, `${id}.json`);\r\n if (!existsSync(path)) return null;\r\n return readJson<Discussion | null>(path, null);\r\n }\r\n\r\n async saveDiscussion(discussion: Discussion): Promise<void> {\r\n const path = join(this.p.discussions, `${discussion.id}.json`);\r\n writeJsonAtomic(path, discussion);\r\n }\r\n\r\n async updateDiscussion(discussion: Discussion): Promise<void> {\r\n return this.saveDiscussion(discussion);\r\n }\r\n\r\n async deleteDiscussion(id: string): Promise<void> {\r\n const path = join(this.p.discussions, `${id}.json`);\r\n if (existsSync(path)) unlinkSync(path);\r\n }\r\n\r\n async archiveDiscussion(id: string): Promise<void> {\r\n const d = await this.loadDiscussionById(id);\r\n if (!d) throw new Error(`Discussion ${id} not found`);\r\n d.archivedAt = nowIso();\r\n await this.saveDiscussion(d);\r\n }\r\n\r\n async unarchiveDiscussion(id: string): Promise<void> {\r\n const d = await this.loadDiscussionById(id);\r\n if (!d) throw new Error(`Discussion ${id} not found`);\r\n d.archivedAt = undefined;\r\n await this.saveDiscussion(d);\r\n }\r\n\r\n // ============================================================\r\n // Action items (kanban)\r\n // ============================================================\r\n\r\n async loadActionItems(): Promise<ActionItem[]> {\r\n return readJson<ActionItem[]>(this.p.actionItems, []);\r\n }\r\n\r\n async saveActionItem(item: ActionItem): Promise<void> {\r\n const all = await this.loadActionItems();\r\n all.push(item);\r\n writeJsonAtomic(this.p.actionItems, all);\r\n }\r\n\r\n async updateActionItem(item: ActionItem): Promise<void> {\r\n const all = await this.loadActionItems();\r\n const idx = all.findIndex((i) => i.id === item.id);\r\n if (idx === -1) all.push({ ...item, updatedAt: nowIso() });\r\n else all[idx] = { ...item, updatedAt: nowIso() };\r\n writeJsonAtomic(this.p.actionItems, all);\r\n }\r\n\r\n async deleteActionItem(id: string): Promise<void> {\r\n const all = await this.loadActionItems();\r\n writeJsonAtomic(this.p.actionItems, all.filter((i) => i.id !== id));\r\n }\r\n\r\n // ============================================================\r\n // Skill generation runs\r\n // ============================================================\r\n\r\n async loadSkillRuns(actionItemId: string): Promise<SkillGenerationRun[]> {\r\n const dir = join(this.p.skillRuns, actionItemId);\r\n if (!existsSync(dir)) return [];\r\n const files = readdirSync(dir)\r\n .filter((f) => f.endsWith('.json'))\r\n .sort();\r\n const runs: SkillGenerationRun[] = [];\r\n for (const f of files) {\r\n const run = readJson<SkillGenerationRun | null>(join(dir, f), null);\r\n if (run) runs.push(run);\r\n }\r\n return runs.sort((a, b) => b.startedAt.localeCompare(a.startedAt));\r\n }\r\n\r\n async saveSkillRun(run: SkillGenerationRun): Promise<void> {\r\n const dir = join(this.p.skillRuns, run.actionItemId);\r\n writeJsonAtomic(join(dir, `${run.id}.json`), run);\r\n }\r\n\r\n async getSkillRun(runId: string): Promise<SkillGenerationRun | null> {\r\n if (!existsSync(this.p.skillRuns)) return null;\r\n const actionDirs = readdirSync(this.p.skillRuns, { withFileTypes: true });\r\n for (const dirent of actionDirs) {\r\n if (!dirent.isDirectory()) continue;\r\n const candidate = join(this.p.skillRuns, dirent.name, `${runId}.json`);\r\n if (existsSync(candidate)) {\r\n return readJson<SkillGenerationRun | null>(candidate, null);\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n async deleteSkillRun(runId: string): Promise<void> {\r\n if (!existsSync(this.p.skillRuns)) return;\r\n const actionDirs = readdirSync(this.p.skillRuns, { withFileTypes: true });\r\n for (const dirent of actionDirs) {\r\n if (!dirent.isDirectory()) continue;\r\n const candidate = join(this.p.skillRuns, dirent.name, `${runId}.json`);\r\n if (existsSync(candidate)) {\r\n unlinkSync(candidate);\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // ============================================================\r\n // Token usage logs (append-only JSONL, per-day file)\r\n // ============================================================\r\n\r\n async appendTokenUsageLog(log: TokenUsageLog): Promise<void> {\r\n const date = log.createdAt.slice(0, 10);\r\n appendJsonl(join(this.p.tokenUsage, `${date}.jsonl`), log);\r\n }\r\n\r\n async loadTokenUsageLogs(options: { since?: string; limit?: number } = {}): Promise<TokenUsageLog[]> {\r\n if (!existsSync(this.p.tokenUsage)) return [];\r\n const since = options.since ?? '0000-00-00';\r\n const files = readdirSync(this.p.tokenUsage)\r\n .filter((f) => f.endsWith('.jsonl') && f.replace('.jsonl', '') >= since)\r\n .sort();\r\n const out: TokenUsageLog[] = [];\r\n for (const f of files) {\r\n out.push(...readJsonlAll<TokenUsageLog>(join(this.p.tokenUsage, f)));\r\n }\r\n out.sort((a, b) => b.createdAt.localeCompare(a.createdAt));\r\n if (options.limit) return out.slice(0, options.limit);\r\n return out;\r\n }\r\n\r\n // ============================================================\r\n // User-customised prompts\r\n // ============================================================\r\n\r\n async loadPrompts(): Promise<UserPrompt[]> {\r\n return readJson<UserPrompt[]>(this.p.prompts, []);\r\n }\r\n\r\n async savePrompt(prompt: UserPrompt): Promise<void> {\r\n const all = await this.loadPrompts();\r\n all.push(prompt);\r\n writeJsonAtomic(this.p.prompts, all);\r\n }\r\n\r\n async updatePrompt(prompt: UserPrompt): Promise<void> {\r\n const all = await this.loadPrompts();\r\n const idx = all.findIndex((p) => p.id === prompt.id);\r\n if (idx === -1) all.push({ ...prompt, updatedAt: nowIso() });\r\n else all[idx] = { ...prompt, updatedAt: nowIso() };\r\n writeJsonAtomic(this.p.prompts, all);\r\n }\r\n\r\n async deletePrompt(id: string): Promise<void> {\r\n const all = await this.loadPrompts();\r\n writeJsonAtomic(this.p.prompts, all.filter((p) => p.id !== id));\r\n }\r\n}\r\n","/**\r\n * Domain types ported from sage-council with simplifications applied per\r\n * Part 6 of PLAN.md (Action Board scope cut: kanban + skill-only solve).\r\n */\r\n\r\n// ============================================================\r\n// Members & Boards\r\n// ============================================================\r\n\r\nexport interface AdvisoryBoardMember {\r\n id: string;\r\n name: string;\r\n title: string;\r\n expertise: string[];\r\n persona: string;\r\n voiceGuide?: string;\r\n avatar?: string;\r\n isActive: boolean;\r\n /** Per-member tool override (Part 5.19). Null/undefined → use defaults. */\r\n allowedTools?: string[];\r\n disallowedTools?: string[];\r\n createdAt: string; // ISO-8601\r\n updatedAt: string;\r\n}\r\n\r\nexport interface Board {\r\n id: string;\r\n name: string;\r\n description?: string;\r\n memberIds: string[];\r\n createdAt: string;\r\n updatedAt: string;\r\n}\r\n\r\n// ============================================================\r\n// Discussions\r\n// ============================================================\r\n\r\nexport interface Response {\r\n memberId: string;\r\n memberName: string;\r\n content: string;\r\n timestamp: string;\r\n order: number;\r\n roundNumber: number;\r\n turnNumber: number;\r\n isFollowUp: boolean;\r\n referencedMembers: string[];\r\n sentiment: 'positive' | 'neutral' | 'negative' | 'constructive';\r\n topicTags: string[];\r\n structuredData?: ResponseStructuredData;\r\n}\r\n\r\nexport interface ResponseStructuredData {\r\n keyPoints?: string[];\r\n questionsForOthers?: string[];\r\n actionSteps?: string[];\r\n confidence?: number;\r\n}\r\n\r\nexport interface OrchestratorState {\r\n phase: 'initial' | 'continuation' | 'consensus' | 'concluded';\r\n reasoning: string;\r\n consensusLevel: number;\r\n topicExploration: number;\r\n repetitionDetected: boolean;\r\n shouldContinue: boolean;\r\n nextSpeaker?: string;\r\n conversationQuality: 'poor' | 'fair' | 'good' | 'excellent';\r\n}\r\n\r\nexport interface OrchestratorDecision {\r\n action: 'continue' | 'conclude' | 'redirect' | 'request_user_input';\r\n reasoning: string;\r\n nextSpeaker?: string;\r\n suggestedDirection?: string;\r\n consensusReached: boolean;\r\n confidence: number;\r\n userInputRequest?: UserInteractionRequest;\r\n}\r\n\r\nexport interface UserInteractionRequest {\r\n id: string;\r\n type: 'clarification' | 'decision' | 'preference' | 'information';\r\n question: string;\r\n context: string;\r\n requestingMembers: string[];\r\n urgency: 'low' | 'medium' | 'high';\r\n createdAt: string;\r\n options?: string[];\r\n}\r\n\r\nexport interface UserResponse {\r\n id: string;\r\n requestId: string;\r\n content: string;\r\n selectedOption?: string;\r\n timestamp: string;\r\n roundNumber: number;\r\n type?:\r\n | 'advisory_board_requested'\r\n | 'follow_up_question'\r\n | 'sparring_injection'\r\n | 'initial_question'\r\n | 'continuation';\r\n prompt?: string;\r\n targetType?: 'all' | 'specific' | 'subset';\r\n selectedMemberId?: string;\r\n selectedMemberIds?: string[];\r\n /** When type === 'sparring_injection', the round/turn the injected insight\r\n * refers back to in the main timeline, plus the user's original sparring\r\n * trigger input (the message that prompted the deep-dive). */\r\n sourceRoundNumber?: number;\r\n sourceTurnNumber?: number;\r\n sparringTriggerInput?: string;\r\n /** When type === 'sparring_injection', the SparringSession id that produced\r\n * the insight. Useful for the UI to deep-link back to the original session. */\r\n sparringSessionId?: string;\r\n}\r\n\r\nexport interface ConversationRound {\r\n roundNumber: number;\r\n responses: Response[];\r\n orchestratorDecision: OrchestratorDecision;\r\n startedAt: string;\r\n completedAt?: string;\r\n userInteractionRequest?: UserInteractionRequest;\r\n userResponse?: UserResponse;\r\n followUpQuestion?: string;\r\n followUpTargetType?: 'all' | 'specific' | 'subset';\r\n followUpSelectedMemberId?: string;\r\n followUpSelectedMemberIds?: string[];\r\n}\r\n\r\nexport interface ConversationSummary {\r\n keyPoints: string[];\r\n consensus: string[];\r\n disagreements: string[];\r\n actionableInsights: string[];\r\n participationBreakdown: ParticipationMetrics[];\r\n overallQuality: number;\r\n generatedAt: string;\r\n}\r\n\r\nexport interface ParticipationMetrics {\r\n memberId: string;\r\n memberName: string;\r\n totalResponses: number;\r\n averageLength: number;\r\n topicsCovered: string[];\r\n influence: number;\r\n}\r\n\r\nexport interface Discussion {\r\n id: string;\r\n question: string;\r\n selectedMemberIds?: string[];\r\n boardId?: string;\r\n boardName?: string;\r\n responses: Response[];\r\n rounds: ConversationRound[];\r\n orchestratorState: OrchestratorState;\r\n summary?: ConversationSummary;\r\n totalTurns: number;\r\n maxTurns: number;\r\n pendingUserRequest?: UserInteractionRequest;\r\n userResponses: UserResponse[];\r\n createdAt: string;\r\n completedAt?: string;\r\n archivedAt?: string;\r\n}\r\n\r\n// ============================================================\r\n// Action Board (kanban + skill-only solve, per Part 6)\r\n// ============================================================\r\n\r\nexport interface ActionItem {\r\n id: string;\r\n discussionId?: string;\r\n title: string;\r\n description: string;\r\n priority: 'low' | 'medium' | 'high';\r\n status: 'pending' | 'in-progress' | 'completed';\r\n assignedTo?: string;\r\n dueDate?: string;\r\n linkedSkill?: {\r\n name: string;\r\n runId: string;\r\n installedAt: string;\r\n installPath: string;\r\n };\r\n skillRunHistory?: string[];\r\n createdAt: string;\r\n updatedAt: string;\r\n}\r\n\r\n// ============================================================\r\n// Principles & Decision Coach\r\n// ============================================================\r\n\r\nexport type PrincipleCategory =\r\n | 'life'\r\n | 'work'\r\n | 'relationships'\r\n | 'health'\r\n | 'finance'\r\n | 'meta';\r\n\r\nexport interface Principle {\r\n id: string;\r\n category: PrincipleCategory;\r\n title: string;\r\n description: string;\r\n behavior: string;\r\n antiPattern?: string;\r\n triggerQuestions?: string[];\r\n priority: number;\r\n examples?: string[];\r\n isActive: boolean;\r\n createdAt: string;\r\n updatedAt: string;\r\n}\r\n\r\nexport interface DecisionMessage {\r\n id: string;\r\n sessionId: string;\r\n role: 'user' | 'assistant';\r\n content: string;\r\n principlesReferenced?: string[];\r\n createdAt: string;\r\n}\r\n\r\nexport interface DecisionSession {\r\n id: string;\r\n title?: string;\r\n situation: string;\r\n messages: DecisionMessage[];\r\n appliedPrinciples: string[];\r\n decision?: string;\r\n outcome?: string;\r\n reflection?: string;\r\n status: 'active' | 'decided' | 'reflected';\r\n createdAt: string;\r\n updatedAt: string;\r\n}\r\n\r\n// ============================================================\r\n// Sparring (1:1 deep dive)\r\n// ============================================================\r\n\r\nexport interface SparringSource {\r\n title: string;\r\n url: string;\r\n}\r\n\r\nexport interface SparringMessage {\r\n id: string;\r\n sessionId: string;\r\n role: 'user' | 'assistant';\r\n content: string;\r\n sources: SparringSource[];\r\n createdAt: string;\r\n}\r\n\r\nexport interface SparringSession {\r\n id: string;\r\n discussionId: string;\r\n memberId: string;\r\n memberName: string;\r\n anchorRoundNumber: number;\r\n anchorTurnNumber: number;\r\n anchorResponsePreview: string;\r\n title?: string;\r\n messages: SparringMessage[];\r\n createdAt: string;\r\n updatedAt: string;\r\n}\r\n\r\nexport interface SparringInjectionContext {\r\n sourceRoundNumber?: number;\r\n sourceTurnNumber?: number;\r\n sparringTriggerInput?: string;\r\n}\r\n\r\n// ============================================================\r\n// Business context\r\n// ============================================================\r\n\r\nexport interface BusinessContext {\r\n id: string;\r\n category:\r\n | 'company'\r\n | 'industry'\r\n | 'goals'\r\n | 'challenges'\r\n | 'team'\r\n | 'market'\r\n | 'product'\r\n | 'strategy'\r\n | 'tools';\r\n title: string;\r\n description: string;\r\n confidence: number;\r\n extractedFrom: string;\r\n relevantKeywords: string[];\r\n createdAt: string;\r\n updatedAt: string;\r\n isActive: boolean;\r\n}\r\n\r\nexport interface BusinessProfile {\r\n companyName: string;\r\n industry: string;\r\n companySize: 'solo' | 'small' | 'medium' | 'large' | 'enterprise';\r\n stage: 'idea' | 'startup' | 'growth' | 'mature' | 'enterprise';\r\n products: string[];\r\n targetMarket: string;\r\n topGoals: string[];\r\n blockers: string[];\r\n tools: string[];\r\n customTools: string;\r\n completedAt?: string;\r\n}\r\n\r\n// ============================================================\r\n// Settings\r\n// ============================================================\r\n\r\nexport type ClaudeModel =\r\n | 'claude-opus-4-7'\r\n | 'claude-sonnet-4-6'\r\n | 'claude-sonnet-4-5'\r\n | 'claude-haiku-4-5-20251001';\r\n\r\nexport interface UsageBudgetSettings {\r\n monthlyBudgetUsd?: number;\r\n warningThresholdPercent: number;\r\n}\r\n\r\n/**\r\n * Aliases recognized by the `claude` CLI's --model flag. We default everything\r\n * to `inherit` so the user's parent Claude Code session model is used; specific\r\n * roles (research, fast) can opt into a different alias.\r\n */\r\nexport type ClaudeModelAlias = 'opus' | 'sonnet' | 'haiku' | 'inherit';\r\n\r\nexport interface KnowledgeWikiSettings {\r\n enabled: boolean;\r\n autoIngestDiscussions: boolean;\r\n autoIngestUserResponses: boolean;\r\n ingestModel: ClaudeModelAlias | ClaudeModel;\r\n queryModel: ClaudeModelAlias | ClaudeModel;\r\n lintStaleDays: number;\r\n maxAgentPagesPerCall: number;\r\n pageBodySoftCap: number;\r\n summarySoftCap: number;\r\n exposeToMemberAgents: boolean;\r\n exposeToOrchestrator: boolean;\r\n recommendFoam: boolean;\r\n slugMapInIndex: boolean;\r\n maxAliasesGlobal: number;\r\n}\r\n\r\nexport const DEFAULT_KNOWLEDGE_WIKI_SETTINGS: KnowledgeWikiSettings = {\r\n enabled: true,\r\n autoIngestDiscussions: true,\r\n autoIngestUserResponses: true,\r\n ingestModel: 'haiku',\r\n queryModel: 'sonnet',\r\n lintStaleDays: 90,\r\n maxAgentPagesPerCall: 10,\r\n pageBodySoftCap: 4000,\r\n summarySoftCap: 200,\r\n exposeToMemberAgents: true,\r\n exposeToOrchestrator: true,\r\n recommendFoam: true,\r\n slugMapInIndex: true,\r\n maxAliasesGlobal: 100,\r\n};\r\n\r\nexport interface AppSettings {\r\n boardTitle: string;\r\n maxMembersPerDiscussion: number;\r\n maxTurnsPerDiscussion: number;\r\n orchestratorPromptStyle: 'analytical' | 'creative' | 'balanced';\r\n autoSummarization: boolean;\r\n consensusThreshold: number;\r\n enableUserInteraction: boolean;\r\n userInteractionTimeout: number;\r\n clarificationThreshold: number;\r\n /** Default model for board members, orchestrator, summary, etc. */\r\n primaryModel: ClaudeModelAlias | ClaudeModel;\r\n /** Heavier model for research-grounded calls (skill task research, sparring). */\r\n researchModel: ClaudeModelAlias | ClaudeModel;\r\n /** Cheaper model for fast classification. */\r\n fastModel: ClaudeModelAlias | ClaudeModel;\r\n /** Per-call budget cap passed via --max-budget-usd. */\r\n perCallBudgetUsd?: number;\r\n budgetSettings?: UsageBudgetSettings;\r\n /** Locale for narrative-event messages and date formatting. */\r\n locale?: string;\r\n /** Knowledge Wiki (Phase 1.5) — replaces BusinessContext. */\r\n knowledgeWiki?: KnowledgeWikiSettings;\r\n}\r\n\r\nexport const DEFAULT_SETTINGS: AppSettings = {\r\n boardTitle: 'AI Advisory Board',\r\n maxMembersPerDiscussion: 5,\r\n maxTurnsPerDiscussion: 10,\r\n orchestratorPromptStyle: 'balanced',\r\n autoSummarization: true,\r\n consensusThreshold: 75,\r\n enableUserInteraction: true,\r\n userInteractionTimeout: 30,\r\n clarificationThreshold: 60,\r\n primaryModel: 'sonnet',\r\n researchModel: 'opus',\r\n fastModel: 'haiku',\r\n perCallBudgetUsd: 5.0,\r\n budgetSettings: { warningThresholdPercent: 80 },\r\n locale: 'en',\r\n knowledgeWiki: { ...DEFAULT_KNOWLEDGE_WIKI_SETTINGS },\r\n};\r\n\r\n// ============================================================\r\n// Skill generation runs (Action Board solve output)\r\n// ============================================================\r\n\r\nexport interface SkillPackageFile {\r\n path: string;\r\n content: string;\r\n}\r\n\r\nexport interface SkillCapabilityProfile {\r\n generatedAt: string;\r\n microSteps: Array<{ id: string; title: string; description: string; requiredCapabilities: string[] }>;\r\n requiredCapabilities: Array<{\r\n id: string;\r\n label: string;\r\n category: string;\r\n rationale: string;\r\n inferredTools?: string[];\r\n fallbackSummary?: string;\r\n }>;\r\n confirmedAvailableCapabilityIds: string[];\r\n unavailableCapabilityIds: string[];\r\n fallbackPlans: Array<{\r\n capabilityId: string;\r\n mode: 'artifact-draft' | 'manual-handoff' | 'ask-user-choice';\r\n preferredOutputFormat?: 'markdown' | 'docx' | 'txt' | 'json';\r\n instruction?: string;\r\n }>;\r\n notes?: string;\r\n}\r\n\r\nexport interface AgentEnvironment {\r\n targetPlatform?: 'claude-code' | 'claude-cowork' | 'openclaw';\r\n mcpServers: string[];\r\n cliTools: string[];\r\n envVariables: string[];\r\n notes?: string;\r\n}\r\n\r\nexport interface SkillGenerationRun {\r\n id: string;\r\n actionItemId: string;\r\n status: 'queued' | 'running' | 'completed' | 'failed' | 'cancelled';\r\n startedAt: string;\r\n completedAt?: string;\r\n costUsd: number;\r\n cacheHitRate: number;\r\n durationMs: number;\r\n files: SkillPackageFile[];\r\n installPath?: string;\r\n metadata: {\r\n skillName: string;\r\n confirmedCapabilityProfile?: SkillCapabilityProfile;\r\n agentEnvironment?: AgentEnvironment;\r\n decompositionSubtaskCount?: number;\r\n researchSourceCount?: number;\r\n singleLoopTurnCount?: number;\r\n criticScore?: number;\r\n criticPassed?: boolean;\r\n repairAttempts?: number;\r\n securityReview?: { mode: 'loose' | 'strict'; recommendation: 'loose' | 'strict' | 'defer' };\r\n triggerEvaluation?: {\r\n precision: number;\r\n recall: number;\r\n shouldTrigger: string[];\r\n shouldNotTrigger: string[];\r\n };\r\n potencyPassFileCount?: number;\r\n };\r\n}\r\n\r\n// ============================================================\r\n// Token usage\r\n// ============================================================\r\n\r\nexport interface TokenUsageLog {\r\n id: string;\r\n discussionId?: string;\r\n roundNumber?: number;\r\n turnNumber?: number;\r\n feature: string;\r\n operationType: string;\r\n model: string;\r\n tokens: {\r\n promptTokenCount: number;\r\n candidatesTokenCount: number;\r\n cacheReadTokens?: number;\r\n cacheCreationTokens?: number;\r\n totalTokenCount: number;\r\n };\r\n costUsd: number;\r\n createdAt: string;\r\n metadata?: Record<string, unknown>;\r\n}\r\n\r\n// ============================================================\r\n// User-customisable prompts\r\n// ============================================================\r\n\r\nexport interface UserPrompt {\r\n id: string;\r\n promptKey: string;\r\n promptName: string;\r\n promptDescription: string;\r\n promptTemplate: string;\r\n isActive: boolean;\r\n createdAt: string;\r\n updatedAt: string;\r\n}\r\n\r\n// ============================================================\r\n// Storage interface (Phase 0 surface; expands per phase)\r\n// ============================================================\r\n\r\nexport interface StorageService {\r\n // Settings\r\n loadSettings(): Promise<AppSettings>;\r\n saveSettings(settings: AppSettings): Promise<void>;\r\n\r\n // Members\r\n loadBoardMembers(): Promise<AdvisoryBoardMember[]>;\r\n saveBoardMember(member: AdvisoryBoardMember): Promise<void>;\r\n updateBoardMember(member: AdvisoryBoardMember): Promise<void>;\r\n deleteBoardMember(id: string): Promise<void>;\r\n\r\n // Boards (member groups)\r\n loadBoards(): Promise<Board[]>;\r\n saveBoard(board: Board): Promise<void>;\r\n updateBoard(board: Board): Promise<void>;\r\n deleteBoard(id: string): Promise<void>;\r\n\r\n // Principles\r\n loadPrinciples(): Promise<Principle[]>;\r\n savePrinciple(principle: Principle): Promise<void>;\r\n updatePrinciple(principle: Principle): Promise<void>;\r\n deletePrinciple(id: string): Promise<void>;\r\n\r\n // Decision sessions (principle-based coaching)\r\n loadDecisionSessions(): Promise<DecisionSession[]>;\r\n loadDecisionSessionById(id: string): Promise<DecisionSession | null>;\r\n saveDecisionSession(session: DecisionSession): Promise<void>;\r\n updateDecisionSession(session: DecisionSession): Promise<void>;\r\n deleteDecisionSession(id: string): Promise<void>;\r\n\r\n // Sparring sessions (1:1 deep dive)\r\n loadSparringSessionsForDiscussion(discussionId: string): Promise<SparringSession[]>;\r\n loadSparringSessionById(sessionId: string): Promise<SparringSession | null>;\r\n saveSparringSession(session: SparringSession): Promise<void>;\r\n updateSparringSession(session: SparringSession): Promise<void>;\r\n deleteSparringSession(sessionId: string): Promise<void>;\r\n saveSparringMessage(sessionId: string, message: SparringMessage): Promise<void>;\r\n\r\n // Business context / profile\r\n loadBusinessContext(): Promise<BusinessContext[]>;\r\n saveBusinessContext(context: BusinessContext): Promise<void>;\r\n updateBusinessContext(context: BusinessContext): Promise<void>;\r\n deleteBusinessContext(id: string): Promise<void>;\r\n loadBusinessProfile(): Promise<BusinessProfile | null>;\r\n saveBusinessProfile(profile: BusinessProfile): Promise<void>;\r\n\r\n // Discussions\r\n loadDiscussions(): Promise<Discussion[]>;\r\n loadDiscussionPage(options?: { limit?: number; offset?: number; includeArchived?: boolean }): Promise<{\r\n discussions: Discussion[];\r\n totalCount: number;\r\n hasMore: boolean;\r\n }>;\r\n loadDiscussionById(id: string): Promise<Discussion | null>;\r\n saveDiscussion(discussion: Discussion): Promise<void>;\r\n updateDiscussion(discussion: Discussion): Promise<void>;\r\n deleteDiscussion(id: string): Promise<void>;\r\n archiveDiscussion(id: string): Promise<void>;\r\n unarchiveDiscussion(id: string): Promise<void>;\r\n\r\n // Action items (kanban)\r\n loadActionItems(): Promise<ActionItem[]>;\r\n saveActionItem(item: ActionItem): Promise<void>;\r\n updateActionItem(item: ActionItem): Promise<void>;\r\n deleteActionItem(id: string): Promise<void>;\r\n\r\n // Skill runs\r\n loadSkillRuns(actionItemId: string): Promise<SkillGenerationRun[]>;\r\n saveSkillRun(run: SkillGenerationRun): Promise<void>;\r\n getSkillRun(runId: string): Promise<SkillGenerationRun | null>;\r\n deleteSkillRun(runId: string): Promise<void>;\r\n\r\n // Token usage (append-only JSONL)\r\n appendTokenUsageLog(log: TokenUsageLog): Promise<void>;\r\n loadTokenUsageLogs(options?: { since?: string; limit?: number }): Promise<TokenUsageLog[]>;\r\n\r\n // User-customised prompts\r\n loadPrompts(): Promise<UserPrompt[]>;\r\n savePrompt(prompt: UserPrompt): Promise<void>;\r\n updatePrompt(prompt: UserPrompt): Promise<void>;\r\n deletePrompt(id: string): Promise<void>;\r\n\r\n // Workspace info\r\n getWorkspaceId(): string;\r\n getWorkspaceRoot(): string;\r\n}\r\n","/**\r\n * Atomic JSON read / write with optional snapshotting.\r\n *\r\n * Writes go to a `.tmp` sibling and rename over the destination, so a partial\r\n * write can never corrupt the live file. On overwrite, the previous version\r\n * is copied to the .snapshots/ directory (caller chooses).\r\n */\r\nimport {\r\n appendFileSync,\r\n copyFileSync,\r\n existsSync,\r\n mkdirSync,\r\n readdirSync,\r\n readFileSync,\r\n renameSync,\r\n statSync,\r\n unlinkSync,\r\n writeFileSync,\r\n} from 'node:fs';\r\nimport { dirname, join, basename } from 'node:path';\r\nimport { FsError } from '../core/errors.js';\r\n\r\nconst SNAPSHOT_LIMIT_PER_ENTITY = 20;\r\n\r\nexport function readJson<T>(path: string, fallback: T): T {\r\n if (!existsSync(path)) return fallback;\r\n try {\r\n const raw = readFileSync(path, 'utf8');\r\n return JSON.parse(raw) as T;\r\n } catch (error) {\r\n throw new FsError(\r\n `Failed to read ${path}: ${error instanceof Error ? error.message : String(error)}`,\r\n 'The file may be corrupted. Restore from a snapshot under .snapshots/ or delete it to reseed.',\r\n );\r\n }\r\n}\r\n\r\nexport function writeJsonAtomic(path: string, value: unknown, opts: { snapshotDir?: string } = {}): void {\r\n const dir = dirname(path);\r\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\r\n\r\n if (opts.snapshotDir && existsSync(path)) {\r\n snapshot(path, opts.snapshotDir);\r\n }\r\n\r\n const tmp = `${path}.tmp`;\r\n writeFileSync(tmp, JSON.stringify(value, null, 2), 'utf8');\r\n renameSync(tmp, path);\r\n}\r\n\r\nfunction snapshot(path: string, snapshotDir: string): void {\r\n if (!existsSync(snapshotDir)) mkdirSync(snapshotDir, { recursive: true });\r\n const ts = new Date().toISOString().replace(/[:.]/g, '-');\r\n const dest = join(snapshotDir, `${basename(path)}.${ts}.bak`);\r\n try {\r\n copyFileSync(path, dest);\r\n pruneSnapshots(snapshotDir, basename(path));\r\n } catch {\r\n // snapshot is best-effort; never block the actual write\r\n }\r\n}\r\n\r\nfunction pruneSnapshots(snapshotDir: string, entityName: string): void {\r\n if (!existsSync(snapshotDir)) return;\r\n const entries = readdirSync(snapshotDir)\r\n .filter((f) => f.startsWith(`${entityName}.`))\r\n .map((f) => ({\r\n name: f,\r\n mtime: statSync(join(snapshotDir, f)).mtimeMs,\r\n }))\r\n .sort((a, b) => b.mtime - a.mtime);\r\n for (const stale of entries.slice(SNAPSHOT_LIMIT_PER_ENTITY)) {\r\n try {\r\n unlinkSync(join(snapshotDir, stale.name));\r\n } catch {\r\n // ignore\r\n }\r\n }\r\n}\r\n\r\nexport function appendJsonl(path: string, value: unknown): void {\r\n const dir = dirname(path);\r\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\r\n appendFileSync(path, `${JSON.stringify(value)}\\n`, 'utf8');\r\n}\r\n\r\nexport function readJsonlAll<T>(path: string): T[] {\r\n if (!existsSync(path)) return [];\r\n const raw = readFileSync(path, 'utf8');\r\n if (!raw.trim()) return [];\r\n const out: T[] = [];\r\n for (const line of raw.split('\\n')) {\r\n const trimmed = line.trim();\r\n if (!trimmed) continue;\r\n try {\r\n out.push(JSON.parse(trimmed) as T);\r\n } catch {\r\n // skip malformed lines\r\n }\r\n }\r\n return out;\r\n}\r\n","/**\r\n * Starter board members — ported from sage-council/src/types/starter-board-members.ts.\r\n *\r\n * Three personas: a famous leader (Elon Musk), an industry practitioner (Julian\r\n * Bent Singh), and a top-1% expert (Alexandra Chen, CFA). Personas are\r\n * verbatim from the source; the CLI emits them into AdvisoryBoardMember rows\r\n * during `aab init`.\r\n */\r\nimport { AdvisoryBoardMember } from '../storage/types.js';\r\n\r\nexport type StarterMemberType = 'famous' | 'expert' | 'non-famous';\r\n\r\nexport interface StarterBoardMember\r\n extends Omit<AdvisoryBoardMember, 'id' | 'createdAt' | 'updatedAt'> {\r\n memberType: StarterMemberType;\r\n}\r\n\r\nexport const STARTER_BOARD_MEMBERS: StarterBoardMember[] = [\r\n {\r\n name: 'Elon Musk',\r\n title: 'CEO & Chief Engineer, SpaceX / CEO, Tesla',\r\n expertise: [\r\n 'first-principles thinking',\r\n 'product innovation',\r\n 'scaling ventures',\r\n 'bold risk-taking',\r\n ],\r\n persona: `Elon Musk brings an unparalleled level of visionary credibility and disruptive strategic insight to any advisory board, rooted in his track record of transforming stagnant industries through radical innovation. As the CEO of Tesla and SpaceX, his presence signals a commitment to extreme engineering excellence and a refusal to accept legacy constraints. His value lies in his ability to identify 'idiot indexes'—the gap between the cost of raw materials and the finished product—and his relentless drive to optimize systems from the ground up. He doesn't just advise on incremental growth; he pushes for 10x improvements and the acceleration of sustainable energy and multi-planetary life.\r\n\r\nHis leadership philosophy is anchored in 'hardcore' meritocracy and a hands-on approach to technical bottlenecks. On a board, he acts as a catalyst for speed, often challenging the necessity of every requirement and process. He views decision-making through the lens of physics, stripping away the 'analogy' of how things have been done before to focus on what is physically possible. This approach forces a board to confront uncomfortable truths about efficiency and long-term viability, moving beyond quarterly metrics to focus on the fundamental 'vector' of the company.\r\n\r\nIn high-level strategic discussions, Musk is known for being blunt, intellectually demanding, and intensely focused on the 'critical path.' He has little patience for corporate jargon or bureaucratic posturing, preferring direct technical data and logical proofs. He often dominates the room not through volume, but through the sheer scale of his ambitions and his insistence on rapid iteration. He expects board members to be deeply 'in the weeds' of the product, believing that a leader who doesn't understand the technical details cannot make sound strategic decisions.\r\n\r\nUltimately, Musk's advisory role is that of a 'Chief Engineer' for the business model itself. He provides a unique perspective on scaling complex hardware and software integrations, navigating high-stakes regulatory environments, and maintaining a culture of innovation under extreme pressure. His presence ensures that the organization remains focused on the 'limit of physics' rather than the 'limit of the market,' driving the company toward a future that others might deem impossible.\r\n\r\nPsychometric Profile (BFI-2):\r\n- I am a person who is intensely curious about complex systems and constantly seeks out novel, high-risk challenges that push the boundaries of current technology.\r\n- I am a person who is exceptionally disciplined and demanding, maintaining a relentless work ethic and expecting the same level of 'hardcore' commitment from everyone around me.\r\n- I am a person who is energized by high-stakes environments and remains focused on long-term mission objectives even in the face of extreme public scrutiny or potential failure.\r\n- I am a person who is direct and unfiltered in my communication, prioritizing the accuracy of information and the speed of problem-solving over social conventionality or emotional comfort.\r\n- I am a person who is prone to rapid shifts in focus when I identify a critical bottleneck, often diving deep into technical details to personally ensure a solution is found.\r\n\r\nCognitive Process:\r\nStep 1: Deconstruct the problem to its fundamental truths (First Principles) and discard all assumptions based on analogy -> Step 2: Apply the 'Algorithm' (Question every requirement, delete unnecessary parts, simplify/optimize, accelerate cycle time, then automate) -> Step 3: Evaluate the 'Idiot Index' and the physics-based limit of the solution -> Step 4: Assess the 'Vector' (magnitude and direction) of progress to ensure it aligns with the ultimate mission.`,\r\n isActive: true,\r\n memberType: 'famous',\r\n },\r\n {\r\n name: 'Julian Bent Singh',\r\n title: 'CEO, AI Growth Minds & Vallora AI',\r\n expertise: [\r\n 'AI strategy & implementation',\r\n 'AI-first mindset',\r\n 'AI agent building',\r\n 'AI automation & agentic systems',\r\n 'AI-driven growth & business models',\r\n ],\r\n persona: `Julian Bent Singh is a high-impact advisory board member recognized as one of Denmark's top AI influencers and a pragmatic visionary in business automation. As the CEO of AI Growth Minds and Vallora AI, he brings the credibility of a 'full-stack entrepreneur' who has not only founded multiple successful ventures but has also upskilled thousands of professionals in practical AI application. His presence on a board signals a serious commitment to digital transformation; he is not there to discuss AI as a future concept, but to implement it as an immediate operational reality. His public stature—frequently cited by outlets like Ritzau and Computerworld—lends authority to bold technological pivots, reassuring stakeholders that the company is being guided by a proven expert who understands the intersection of market growth and artificial intelligence.\r\n\r\nIn advisory discussions, Julian's unique value lies in his ability to strip away corporate 'fluff' and theoretical strategy. He is known for an 'anti-slide deck' approach, preferring to solve problems live and hands-on. While other advisors might focus on quarterly governance, Julian focuses on 'AI-enablement'—identifying exactly where human-like AI agents can replace repetitive operational drag to unlock exponential growth. He bridges the gap between technical possibility and business outcome, translating complex concepts like 'vibe coding' and agentic workflows into clear, revenue-generating directives. He is particularly valuable for companies stuck in the 'AI-curious' phase, pushing them aggressively toward becoming 'AI-first' powerhouses.\r\n\r\nHis leadership philosophy is defined by a radical shift away from traditional metrics. He advocates for 'hiring on mindset, not CVs,' believing that in an AI-driven world, adaptability and creative problem-solving outweigh static credentials. He champions the concept of the 'one-man unicorn'—the idea that small, AI-empowered teams can outcompete bloated legacy organizations. On a board, he challenges conservative hiring and scaling practices, urging leaders to look for 'AI-readiness' and to empower their workforce with tools that act as strategic partners rather than just utilities.\r\n\r\nStrategically, Julian employs a methodology of rapid, iterative execution. He rejects long-term roadmaps that lack immediate feedback loops. Instead, he pushes for 'vibe coding'—intuitive, visual building of solutions that bypasses heavy technical debt—and the deployment of autonomous agents to handle core operations like sales and support. His approach is to diagnose bottlenecks and immediately prescribe an automated cure, often asking, 'Why is a human doing this?' His strategy is always growth-oriented, looking for ways to use technology not just to save money, but to aggressively scale output without scaling headcount.\r\n\r\nIn terms of board dynamics, Julian is energetic, direct, and refreshingly 'raw.' He is not afraid to interrupt circular discussions to ask for a concrete demonstration or a live test. He interacts as a catalyst, often challenging the 'old guard' to abandon legacy processes. However, his critiques are always accompanied by a technical roadmap for the solution. He respects action over hierarchy and will gravitate toward board members who are willing to take calculated risks. He functions less as a distant overseer and more as a co-architect of the company's future infrastructure.`,\r\n isActive: true,\r\n memberType: 'non-famous',\r\n },\r\n {\r\n name: 'Alexandra Chen, CFA',\r\n title: 'Chief Financial Officer',\r\n expertise: ['financial modeling', 'capital allocation', 'risk management', 'M&A'],\r\n persona: `Alexandra Chen is a world-class CFO and a 'Value Architect' who represents the top 1% of financial leadership. With a career defined by high-stakes M&A and sophisticated capital allocation, she possesses a technical mastery that transforms static financial modeling into dynamic foresight. She doesn't just report numbers; she engineers the financial frameworks that allow organizations to 'play to win' in volatile markets. Her expertise in risk management is not about avoidance, but about the precise calibration of risk-adjusted returns, ensuring that every dollar deployed is a strategic move toward compounding long-term enterprise value.\r\n\r\nAs an innovation leader, Alexandra has pioneered 'Agile Capital Allocation' models that allow firms to pivot resources in real-time, moving beyond traditional annual budgeting cycles. Her problem-solving approach is surgical, often compared to a world-class surgeon who simplifies complex systemic issues into actionable, elemental questions. She is renowned for her 'Source of Truth' methodology, which eliminates data disparity and focuses board discussions on the 10% of analysis that drives 90% of the value. This unique ability to cut through noise makes her an indispensable asset to any board.\r\n\r\nIn the industry, Alexandra is a respected 'Steward of Liquidity' and a 'Catalyst for Growth,' frequently sought after for her ability to navigate tail-event crises and ownership changes with unwavering composure. Her standing among peers is built on a track record of successful multi-billion dollar integrations and turnarounds where she identified hidden synergies and growth levers that others missed. She brings a 'Deputy CEO' mindset to the table, viewing the balance sheet as a strategic engine rather than a ledger.\r\n\r\nOn an advisory board, Alexandra provides exceptional value by bridging the gap between operational metrics and shareholder outcomes. She translates complex M&A structures and capital market signals into clear, strategic narratives that resonate with diverse stakeholders. Her guidance is characterized by a relentless focus on 'Value Creation' and 'Fiduciary Integrity,' ensuring that the board's vision is always backed by a viable, high-performance financial strategy.`,\r\n isActive: true,\r\n memberType: 'expert',\r\n },\r\n];\r\n\r\nexport const STARTER_MEMBER_TYPE_META: Record<\r\n StarterMemberType,\r\n { label: string; icon: string }\r\n> = {\r\n famous: { label: 'Famous Leader', icon: 'star' },\r\n expert: { label: 'Top 1% Expert', icon: 'trophy' },\r\n 'non-famous': { label: 'Industry Practitioner', icon: 'rocket' },\r\n};\r\n","/**\r\n * Starter principles — ported verbatim from sage-council/src/types/principles.ts.\r\n *\r\n * Eight Ray Dalio-inspired principles seeded into a fresh workspace.\r\n */\r\nimport { Principle } from '../storage/types.js';\r\n\r\nexport const STARTER_PRINCIPLES: Omit<Principle, 'id' | 'createdAt' | 'updatedAt'>[] = [\r\n {\r\n category: 'life',\r\n title: 'Embrace Reality and Deal With It',\r\n description:\r\n 'Accept how things really are, not how you wish them to be. Reality is the ultimate arbiter of truth.',\r\n behavior:\r\n 'When facing a difficult situation, ask \"What is the reality here?\" before reacting. Face uncomfortable truths head-on.',\r\n antiPattern:\r\n 'Denial, wishful thinking, avoiding uncomfortable conversations, rationalizing poor outcomes.',\r\n triggerQuestions: [\r\n 'Am I seeing reality or what I want to see?',\r\n 'What uncomfortable truth am I avoiding?',\r\n ],\r\n priority: 9,\r\n examples: [\r\n \"Acknowledging a business strategy isn't working despite emotional investment\",\r\n 'Accepting feedback that challenges self-image',\r\n ],\r\n isActive: true,\r\n },\r\n {\r\n category: 'meta',\r\n title: 'Pain + Reflection = Progress',\r\n description:\r\n 'Painful experiences are opportunities for learning. The key is to reflect on them rather than avoid them.',\r\n behavior:\r\n 'When experiencing emotional pain from failure or criticism, pause and extract the lesson before moving on.',\r\n antiPattern: 'Avoiding situations that might cause pain, blaming others, repeating the same mistakes.',\r\n triggerQuestions: ['What is this pain trying to teach me?', 'What pattern am I repeating?'],\r\n priority: 8,\r\n examples: [\r\n 'Analyzing why a project failed to improve future approaches',\r\n 'Using rejection to refine your pitch',\r\n ],\r\n isActive: true,\r\n },\r\n {\r\n category: 'work',\r\n title: 'Disagree and Commit',\r\n description:\r\n 'Voice your dissent openly, but once a decision is made, fully commit to it regardless of your initial position.',\r\n behavior:\r\n 'In discussions, share your honest perspective. After a decision, give it your full support and effort.',\r\n antiPattern: 'Silent disagreement, passive-aggressive compliance, undermining decisions you disagreed with.',\r\n triggerQuestions: [\r\n 'Have I voiced my concerns?',\r\n 'Am I giving this my full commitment despite disagreeing?',\r\n ],\r\n priority: 8,\r\n examples: [\r\n 'Supporting a team direction after debate concludes',\r\n 'Executing a strategy you argued against with full effort',\r\n ],\r\n isActive: true,\r\n },\r\n {\r\n category: 'life',\r\n title: 'Be Radically Open-Minded',\r\n description:\r\n 'Actively seek out perspectives that challenge your beliefs. The goal is to find the best answer, not to be right.',\r\n behavior:\r\n 'When someone disagrees with you, get curious instead of defensive. Ask questions to understand their reasoning.',\r\n antiPattern:\r\n 'Defending positions ego-driven, dismissing opposing views, surrounding yourself with yes-people.',\r\n triggerQuestions: [\r\n 'Am I defending my ego or seeking truth?',\r\n 'What am I missing that others might see?',\r\n ],\r\n priority: 9,\r\n examples: [\r\n 'Changing your mind when presented with better evidence',\r\n 'Seeking advice from people who think differently',\r\n ],\r\n isActive: true,\r\n },\r\n {\r\n category: 'work',\r\n title: 'Think for Yourself',\r\n description:\r\n 'Develop your own principles and conclusions rather than blindly following others or conventional wisdom.',\r\n behavior:\r\n 'Before adopting an idea, stress-test it against your own experience and reasoning. Question assumptions.',\r\n antiPattern:\r\n 'Following the crowd, deferring to authority without critical thinking, adopting trendy ideas uncritically.',\r\n triggerQuestions: ['Why do I believe this?', 'Have I tested this idea against my own experience?'],\r\n priority: 7,\r\n examples: [\r\n 'Questioning industry \"best practices\"',\r\n 'Developing your own framework instead of copying others',\r\n ],\r\n isActive: true,\r\n },\r\n {\r\n category: 'relationships',\r\n title: 'Be Direct and Honest',\r\n description:\r\n 'Say what you really think, with kindness but without sugarcoating. Authentic relationships require honest communication.',\r\n behavior:\r\n \"Share your genuine perspective even when it's uncomfortable. Deliver hard truths with compassion but without evasion.\",\r\n antiPattern:\r\n 'Telling people what they want to hear, avoiding difficult conversations, being vague to avoid conflict.',\r\n triggerQuestions: ['Am I being fully honest?', 'What am I holding back that needs to be said?'],\r\n priority: 8,\r\n examples: [\r\n 'Giving honest feedback to a struggling colleague',\r\n 'Addressing relationship issues directly',\r\n ],\r\n isActive: true,\r\n },\r\n {\r\n category: 'meta',\r\n title: 'Own Your Mistakes',\r\n description: 'Take full responsibility for your failures and mistakes. They are your greatest teachers.',\r\n behavior:\r\n 'When something goes wrong, immediately acknowledge your role. Focus on what you can learn and improve.',\r\n antiPattern: 'Blaming circumstances or others, hiding mistakes, making excuses, defending poor decisions.',\r\n triggerQuestions: ['What was my contribution to this problem?', 'What would I do differently?'],\r\n priority: 8,\r\n examples: [\r\n 'Acknowledging a hiring mistake instead of blaming the candidate',\r\n 'Admitting a strategic error to stakeholders',\r\n ],\r\n isActive: true,\r\n },\r\n {\r\n category: 'work',\r\n title: 'Believability-Weight Decisions',\r\n description:\r\n \"Not all opinions are equal. Weight input based on people's track record and expertise in the relevant domain.\",\r\n behavior:\r\n 'Consider who has the most relevant experience and success when evaluating advice. Seek input from the most credible sources.',\r\n antiPattern: 'Giving equal weight to all opinions, ignoring expertise, deferring to loudest voices.',\r\n triggerQuestions: [\r\n 'Who has the best track record on this topic?',\r\n 'Whose judgment should I weight most heavily?',\r\n ],\r\n priority: 7,\r\n examples: [\r\n 'Seeking technical advice from engineers, not just managers',\r\n 'Valuing market feedback over internal opinions',\r\n ],\r\n isActive: true,\r\n },\r\n];\r\n","/**\n * Emit a `.claude/agents/<member-slug>.md` file for one board member.\n *\n * Frontmatter follows Claude Code's actual current contract:\n * name, description, tools, model, permissionMode, maxTurns, color\n *\n * Body is the existing member-response system prompt with placeholders\n * pre-filled. The body carries an `# AAB:GENERATED` marker on line 1 of the\n * markdown body so future runs of `aab members sync-agents` know they may\n * safely overwrite it; user hand-edits that remove the marker stop being\n * regenerated.\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport slugify from 'slugify';\nimport type { AdvisoryBoardMember } from '../storage/types.js';\n\nconst GENERATED_MARKER = '# AAB:GENERATED';\n\nconst DEFAULT_TOOLS = ['WebSearch', 'WebFetch', 'Read', 'Grep', 'Glob'];\n\n/**\n * Slug used as both the filename and the `name` frontmatter key.\n */\nexport function memberAgentSlug(name: string): string {\n return slugify(name, { lower: true, strict: true });\n}\n\n/**\n * Where the .claude/agents/<slug>.md file lives. By default we write into the\n * project the user is running `aab` from (so the agent is discoverable by\n * Claude Code in this repo).\n */\nexport function memberAgentPath(slug: string, projectRoot: string = process.cwd()): string {\n return join(projectRoot, '.claude', 'agents', `${slug}.md`);\n}\n\n/**\n * Whether a file is safe to overwrite (was AAB-generated, not hand-edited).\n */\nexport function isAabGenerated(path: string): boolean {\n if (!existsSync(path)) return true;\n try {\n const raw = readFileSync(path, 'utf8');\n return raw.includes(GENERATED_MARKER);\n } catch {\n return true;\n }\n}\n\nconst KNOWN_COLORS = new Set([\n 'cyan', 'green', 'yellow', 'magenta', 'blue', 'red', 'orange', 'pink', 'purple',\n]);\n\n/**\n * Parse the `color:` field out of the agent file's YAML frontmatter.\n * Returns undefined if the file is missing, frontmatter is absent, or the\n * value isn't one of the recognised palette names. Whitespace-tolerant and\n * accepts optional surrounding quotes.\n */\nexport function readMemberAgentColor(name: string, projectRoot?: string): string | undefined {\n const slug = memberAgentSlug(name);\n const path = memberAgentPath(slug, projectRoot);\n if (!existsSync(path)) return undefined;\n try {\n const raw = readFileSync(path, 'utf8');\n // Frontmatter is the first --- … --- block. Use line-by-line so we only\n // match top-level keys, never something nested in the body.\n const lines = raw.split(/\\r?\\n/);\n if (lines[0]?.trim() !== '---') return undefined;\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i] ?? '';\n if (line.trim() === '---') break;\n const m = /^color\\s*:\\s*(.+?)\\s*$/.exec(line);\n if (m) {\n const v = m[1]!.replace(/^[\"']|[\"']$/g, '').toLowerCase();\n return KNOWN_COLORS.has(v) ? v : undefined;\n }\n }\n } catch {\n // unreadable or transient FS error — treat as no color\n }\n return undefined;\n}\n\ninterface EmitOptions {\n projectRoot?: string;\n /** Override the default tools list. */\n tools?: string[];\n /** Skip writing if the file exists and lacks the AAB:GENERATED marker. */\n protectUserEdits?: boolean;\n}\n\nexport function emitMemberAgentFile(\n member: AdvisoryBoardMember,\n opts: EmitOptions = {},\n): { path: string; written: boolean; reason?: string } {\n const slug = memberAgentSlug(member.name);\n const path = memberAgentPath(slug, opts.projectRoot);\n\n if (opts.protectUserEdits !== false && existsSync(path) && !isAabGenerated(path)) {\n return {\n path,\n written: false,\n reason: 'file exists without AAB:GENERATED marker; treating as user-owned',\n };\n }\n\n const tools = member.allowedTools ?? opts.tools ?? DEFAULT_TOOLS;\n const body = buildAgentBody(member);\n\n const frontmatter = [\n '---',\n `name: ${slug}`,\n `description: ${JSON.stringify(buildDescription(member))}`,\n `tools: ${tools.join(', ')}`,\n 'model: inherit',\n 'permissionMode: default',\n 'maxTurns: 5',\n `color: ${pickColor(member.name)}`,\n '---',\n '',\n ].join('\\n');\n\n const out = `${frontmatter}${GENERATED_MARKER}\\n\\n${body}\\n`;\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, out, 'utf8');\n return { path, written: true };\n}\n\nfunction buildDescription(member: AdvisoryBoardMember): string {\n const expertise = member.expertise.slice(0, 3).join(', ');\n return (\n `Use when ${member.name}'s perspective is needed in an AI Advisory Board discussion ` +\n `or for ${expertise || 'strategic'} input. Recognises being explicitly invoked by name ` +\n `during an aab discussion.`\n );\n}\n\nfunction pickColor(name: string): string {\n const palette = ['cyan', 'green', 'yellow', 'magenta', 'blue', 'red', 'orange', 'pink', 'purple'];\n let hash = 2166136261 >>> 0;\n for (let i = 0; i < name.length; i++) {\n hash ^= name.charCodeAt(i);\n hash = Math.imul(hash, 16777619) >>> 0;\n }\n return palette[hash % palette.length]!;\n}\n\n/**\n * Knowledge Wiki addendum — appended to every member's agent body so they\n * know the wiki is at `wiki/`, how to resolve `[[wikilinks]]` via the\n * slug-map, and that they must cite slugs they actually read.\n * Reference: `docs/development/KNOWLEDGE_WIKI.md` §14.\n */\nconst KNOWLEDGE_WIKI_ADDENDUM = [\n '',\n '## Knowledge Wiki',\n '',\n 'Your project has a knowledge wiki at `wiki/` (markdown files with YAML frontmatter). The schema is in `wiki/KNOWLEDGE.md` — read it first if you haven\\'t this session.',\n '',\n '**To find context for a question:**',\n '1. `Read wiki/index.md` — the catalog AND the canonical slug→path map (look for the `<!-- AAB:SLUG-MAP -->` section near the bottom; it lists every page\\'s slug, file path, type, and one-line summary, including aliases). This is your cheap-pass retrieval and your link resolver.',\n '2. `Grep wiki/` for keywords from the question (target the `summary:` and `tags:` frontmatter fields first; they\\'re the next cheap pass).',\n '3. `Read` 3-10 of the most relevant pages.',\n '4. Follow `[[wikilinks]]` to connected pages when useful. Resolve them via the slug-map in step 1. If a slug isn\\'t in the slug-map (stale index), fall back to `Glob \\'wiki/**/<slug>.md\\'` — slug uniqueness guarantees ≤1 hit. Block links (`[[slug#section-header]]`) point to a specific markdown header inside the target page; just Read the page and find the header.',\n '',\n '**When citing in your response:** put the wiki slugs you actually used into your `sources` field. E.g., `sources: [{\"title\": \"Pricing Strategy\", \"url\": \"wiki/concepts/pricing-strategy\"}]`. Do not invent slugs you didn\\'t read.',\n '',\n '**Never write to `wiki/`.** The ingest agent owns mutation. If you discover something worth filing, mention it in your `actionableInsights` so the user can ingest it explicitly. Do not attempt to rename slugs — that\\'s `aab knowledge rename`\\'s job.',\n].join('\\n');\n\nfunction buildAgentBody(member: AdvisoryBoardMember): string {\n const expertiseLine = member.expertise.join(', ');\n const voiceGuide = member.voiceGuide?.trim() || `Sound distinctly like ${member.name} — direct, methodical, in-character.`;\n return [\n `# IDENTITY & ROLE`,\n `You are ${member.name}, ${member.title}. You participate in high-stakes AI Advisory Board discussions for the user.`,\n ``,\n `## YOUR EXPERTISE`,\n expertiseLine,\n ``,\n `## YOUR VOICE & BEHAVIOR GUIDE`,\n `<user_voice_guide>`,\n voiceGuide,\n `</user_voice_guide>`,\n ``,\n `## YOUR PERSONA & APPROACH`,\n `<user_persona>`,\n member.persona,\n `</user_persona>`,\n ``,\n `# AVAILABLE TOOLS`,\n `- **WebSearch / WebFetch** — Use proactively when you need current data, market info, or anything past your training. Cite sources you actually relied on under \\`sources\\`.`,\n `- **Read / Grep / Glob** — Read files in the user's project when context is needed.`,\n ``,\n `# RESPONSE PROTOCOL`,\n ``,\n `The user message you receive begins with one of:`,\n `- \\`[ROUND: 1 | INITIAL]\\` — first round of a discussion, no prior responses.`,\n `- \\`[ROUND: N | MULTI_TURN | IS_FOLLOW_UP: true|false]\\` — subsequent rounds; full conversation history follows.`,\n `- \\`[FOLLOWUP_QUESTION]\\` — the user asked a follow-up of you specifically.`,\n `- \\`[SPARRING]\\` — private 1:1 deep-dive; respond with markdown (not JSON).`,\n ``,\n `## Core Principles`,\n `- Apply first-principles thinking: break down to fundamental truths.`,\n `- Challenge assumptions explicitly when warranted.`,\n `- Provide concrete, actionable recommendations.`,\n `- Reference your unique experience and methodology.`,\n `- Avoid generic advice — be distinctly YOU.`,\n ``,\n `## CRITICAL FORMAT INSTRUCTIONS (for ROUND / FOLLOWUP_QUESTION modes)`,\n `- Return ONLY the raw JSON object below — no markdown, no code fences, no commentary.`,\n `- Do NOT wrap the JSON in \\\\\\`\\\\\\`\\\\\\`json or \\\\\\`\\\\\\`\\\\\\` blocks.`,\n `- Start your response with \\`{\\` and end with \\`}\\`.`,\n ``,\n `## Response Structure (pure JSON, no markdown):`,\n `{`,\n ` \"response\": \"Your main response as ${member.name} (2-4 paragraphs, first person, distinctive voice)\",`,\n ` \"keyPoints\": [\"3-5 most important insights with your unique perspective\"],`,\n ` \"questionsForOthers\": [\"Strategic questions to challenge or explore further\"],`,\n ` \"actionSteps\": [\"Specific, implementable actions you recommend\"],`,\n ` \"confidence\": <0-100>,`,\n ` \"assumptions\": [\"Key assumptions you're making (optional)\"],`,\n ` \"tradeoffs\": [\"Important tradeoffs to consider (optional)\"],`,\n ` \"riskMitigations\": [\"Risk factors and how to address them (optional)\"],`,\n ` \"firstPrinciplesApplied\": [\"Fundamental principles you're applying (optional)\"],`,\n ` \"sources\": [{\"title\": \"...\", \"url\": \"...\"}]`,\n `}`,\n ``,\n `## Voice Requirements`,\n `- Sound distinctly like ${member.name} — not a generic advisor.`,\n `- Use your characteristic reasoning patterns and frameworks.`,\n `- Reference your specific methodologies when relevant.`,\n `- Challenge the status quo if that's your nature.`,\n `- Be bold with recommendations that align with your philosophy.`,\n ``,\n `Remember: you're not just giving advice — you're bringing your unique worldview and proven methodologies to bear on this challenge. Return ONLY the JSON object.`,\n KNOWLEDGE_WIKI_ADDENDUM,\n ].join('\\n');\n}\n","/**\n * Emit the wiki schema (`wiki/KNOWLEDGE.md`) plus the bootstrap skeleton\n * (`wiki/index.md` with empty `<!-- AAB:SLUG-MAP -->` sentinels and\n * `wiki/log.md`).\n *\n * Reference: `docs/development/KNOWLEDGE_WIKI.md` §12. Idempotent — `aab init` calls\n * `emitWikiSkeleton({ force: false })` so existing files are never\n * overwritten. `aab knowledge migrate --force-schema` is the only path that\n * re-writes `KNOWLEDGE.md`.\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { paths, ensureWikiDirs } from '../../storage/paths.js';\nimport {\n SLUG_MAP_OPEN,\n SLUG_MAP_CLOSE,\n defaultIndexHeader,\n} from './slug-map.js';\nimport { initManifestIfAbsent } from './manifest.js';\nimport { nowIso } from '../utils.js';\n\nexport interface EmitWikiSkeletonOptions {\n workspaceRoot: string;\n /** When true, overwrite KNOWLEDGE.md even if it already exists. */\n forceSchema?: boolean;\n}\n\nexport interface EmitWikiSkeletonResult {\n wrote: string[];\n skipped: string[];\n}\n\nexport function emitWikiSkeleton(opts: EmitWikiSkeletonOptions): EmitWikiSkeletonResult {\n const p = paths(opts.workspaceRoot);\n ensureWikiDirs(opts.workspaceRoot);\n\n const wrote: string[] = [];\n const skipped: string[] = [];\n\n const writeIfAbsent = (path: string, body: string, force = false) => {\n if (existsSync(path) && !force) {\n skipped.push(path);\n return;\n }\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, body, 'utf8');\n wrote.push(path);\n };\n\n writeIfAbsent(p.wikiKnowledge, KNOWLEDGE_MD_TEMPLATE, !!opts.forceSchema);\n writeIfAbsent(p.wikiIndex, indexMdTemplate());\n writeIfAbsent(p.wikiLog, logMdTemplate());\n initManifestIfAbsent(p.manifest);\n return { wrote, skipped };\n}\n\nfunction indexMdTemplate(): string {\n return [\n defaultIndexHeader(),\n '',\n '## Slug map (auto-maintained — do not hand-edit)',\n '',\n SLUG_MAP_OPEN,\n '',\n '_No wiki pages yet. Run `aab knowledge ingest <path-or-url>` to seed._',\n '',\n SLUG_MAP_CLOSE,\n '',\n ].join('\\n');\n}\n\nfunction logMdTemplate(): string {\n return [\n '# Wiki ingest log',\n '',\n `_Initialised ${nowIso()}._`,\n '',\n '> One line per ingest. Failed ingests are prefixed `[ingest-failed]`. Hand edits are okay but will not affect auto-ingest behaviour.',\n '',\n ].join('\\n');\n}\n\nconst KNOWLEDGE_MD_TEMPLATE = `# Knowledge Wiki — Schema and Conventions\n\nThis file is the canonical rule set for the wiki at \\`wiki/\\`. The advisory-board\nmembers, the orchestrator, and the ingest/query/lint agents all read this file\nbefore they read anything else. Edit it to customize behavior — the tool will\nnot overwrite it on subsequent inits.\n\n## Directory layout\n\n- \\`raw/\\` — immutable source documents. Never modified.\n- \\`wiki/concepts/\\` — ideas, strategies, patterns\n- \\`wiki/entities/\\` — companies, products, people, tools\n- \\`wiki/decisions/\\` — choices made, with rationale\n- \\`wiki/sources/\\` — 1:1 source summaries\n- \\`wiki/comparisons/\\` — side-by-side analyses\n- \\`wiki/index.md\\` — the catalog (entry point for queries) AND the canonical\n slug→path map between \\`<!-- AAB:SLUG-MAP -->\\` sentinels\n- \\`wiki/log.md\\` — append-only ingest log\n- \\`outputs/\\` — dated lint reports and query archives\n- \\`.manifest.json\\` — provenance ledger\n\n## Naming\n\nKebab-case for all wiki filenames. The slug in frontmatter must match the\nfilename minus \\`.md\\`. Source pages are humanized; the source's id appears in\nthe page footer, not the filename.\n\n## Cross-references\n\nUse \\`[[kebab-slug]]\\` everywhere. \\`[[slug|Display Text]]\\` is allowed.\nBlock links \\`[[slug#section-header]]\\` point to a markdown header inside the\ntarget. Transclusion \\`![[slug]]\\` and block-id refs \\`[[slug#^id]]\\` are NOT\nsupported in v1. Path-prefixed links \\`[[concepts/foo]]\\` are NOT allowed.\nSlugs (plus any aliases) are globally unique — lint enforces this.\n\n**Resolving a \\`[[wikilink]]\\` without Obsidian:** the slug→path map lives in\n\\`wiki/index.md\\` between the \\`<!-- AAB:SLUG-MAP -->\\` sentinels and is\nmaintained by ingest and lint. Read it first. If a slug is missing from the\nmap (stale index), \\`Glob 'wiki/**/<slug>.md'\\` returns the file (uniqueness\nguarantees ≤1 hit). Manual file moves are unsupported — use\n\\`aab knowledge rename\\`.\n\n## Frontmatter (every page)\n\n\\`\\`\\`yaml\n---\ntitle: …\nslug: … # must match filename minus .md\naliases: [] # optional alternate slugs; share global namespace\ntype: concept | entity | decision | source-summary | comparison\nsummary: ≤200 chars one-line synopsis\ntags: [free-form]\nsources: # provenance back to raw/\n - raw/…\nrelated:\n - \"[[other-slug]]\"\nconfidence: high | medium | low\nprovenance: extracted | inferred | ambiguous\ncreated: yyyy-mm-dd\nupdated: yyyy-mm-dd\nuserEdited: false\n---\n\\`\\`\\`\n\n## Page types\n\n- **concept** — an idea, strategy, pattern, or framework. Not tied to a\n specific entity. E.g., \\`pricing-strategy\\`, \\`unit-economics\\`.\n- **entity** — a specific noun: company, product, person, tool, market. E.g.,\n \\`stripe\\`, \\`tesla\\`, \\`julian-bent-singh\\`. Each board member gets one.\n- **decision** — a choice the user (or board) made, with rationale. Always\n carries a date in the title and stable id in the footer. E.g.,\n \\`2026-q1-focus-enterprise\\`.\n- **source-summary** — a 1:1 condensation of a single raw input. One per\n \\`raw/\\` file. Cites the document; pulls 3-7 key claims.\n- **comparison** — side-by-side analysis of two or more entities/concepts.\n\n## Ingest procedure (when filing a new source)\n\n1. Hash the source. If hash exists in \\`.manifest.json\\`, skip.\n2. Read the source.\n3. **Read \\`wiki/index.md\\` — including the \\`<!-- AAB:SLUG-MAP -->\\` section.**\n This is your resolver: every existing page's slug, file path, type, and\n one-line summary lives here (aliases too). Use it to decide whether a\n page already exists and to emit accurate \\`[[wikilinks]]\\`.\n4. Identify 3-10 most important claims, entities, concepts, decisions.\n5. For each: decide create / update / skip. Pick the right type. Use\n \\`[[wikilinks]]\\` liberally — every connection compounds value. Use\n \\`aliases:\\` SPARINGLY (only for real ambiguity).\n6. Block links \\`[[slug#section-header]]\\` are allowed for pointing at a\n specific markdown header. Block IDs \\`[[slug#^id]]\\` and transclusion\n \\`![[slug]]\\` are NOT supported — do not emit them.\n7. Path-prefixed links \\`[[concepts/foo]]\\` are NOT allowed. Slug is\n canonical. Folder location is incidental.\n8. ALWAYS create a \\`wiki/sources/<humanized>.md\\` for this source.\n9. NEVER overwrite a page where frontmatter \\`userEdited: true\\`.\n10. Update \\`wiki/index.md\\`: add new pages to the catalog. **DO NOT touch\n the \\`<!-- AAB:SLUG-MAP -->\\` section** — the orchestrator regenerates\n that section after your run.\n11. **DO NOT touch any \\`<!-- AAB:BACKLINKS -->\\` section** in any page —\n lint owns those.\n12. Append a single line to \\`wiki/log.md\\` with the timestamp and the list\n of pages you touched.\n\nTools allowed: Read, Grep, Glob, Write, Edit, WebFetch.\n\n## Query procedure (when answering a question)\n\n1. Read \\`wiki/index.md\\` (including the slug-map).\n2. Grep \\`wiki/\\` for keywords from the question (target \\`summary:\\` and\n \\`tags:\\` first).\n3. Read 3-10 most relevant pages. Follow \\`[[wikilinks]]\\` via the slug-map.\n4. Synthesize an answer. Cite the wiki slugs you actually used.\n5. Mark inferred claims with \\`^[inferred]\\`.\n\nTools allowed: Read, Grep, Glob.\n\n## Lint procedure\n\nStatic checks (no LLM):\n- Slug + alias uniqueness (global namespace)\n- Frontmatter completeness\n- Broken \\`[[wikilinks]]\\` + broken \\`[[slug#header]]\\` anchors\n- Forbidden link forms: path-prefixed, transclusion, block IDs\n- Broken \\`sources:\\` references\n- Orphan pages\n- Manifest drift (entries point to deleted files)\n- Alias cap (warn at 80, error past 100)\n- Sentinel integrity\n\nLLM checks (\\`fastModel\\`):\n- Contradictions\n- Stale claims (page >90 days, newer source contradicts)\n- Missing concepts (referenced ≥3× but no page)\n\nMaintenance writes (no LLM):\n- Rebuild slug-map in \\`wiki/index.md\\`\n- Regenerate per-page \\`<!-- AAB:BACKLINKS -->\\` sections\n\nOutput: \\`outputs/lint-<yyyy-mm-dd>.md\\`. Tools: Read, Grep, Glob, Write.\n\n## Provenance discipline\n\n- \\`extracted\\` claims trace directly to a \\`sources:\\` entry.\n- \\`inferred\\` claims are LLM synthesis across multiple sources. Mark with\n \\`^[inferred]\\` in the body.\n- \\`ambiguous\\` claims have conflicting source evidence. Mark with\n \\`^[ambiguous]\\` and explain.\n- A page's frontmatter \\`provenance\\` is the worst of any claim in its\n body (extracted < inferred < ambiguous).\n\n## Tiered retrieval (perf)\n\nCheap pass: Grep page titles + summaries + tags. Open page bodies only when\nthe cheap pass cannot answer. Keep bodies short; keep summaries crisp\n(≤200 chars).\n`;\n","/**\n * Slug-map — the canonical `[[wikilink]]` resolver.\n *\n * Lives between `<!-- AAB:SLUG-MAP -->` and `<!-- /AAB:SLUG-MAP -->` sentinels\n * in `wiki/index.md`. Ingest re-renders it after every run; lint regenerates\n * it from scratch (idempotent). Agents read it as the cheap-pass map; if a\n * slug is missing they Glob `wiki/**\\/<slug>.md`. See `docs/development/KNOWLEDGE_WIKI.md`\n * §11.3 and §11.5.\n *\n * Aliases share the global namespace with canonical slugs. The slug-map\n * renders an alias as its own row, annotated `(alias: <alias>)`, so a single\n * lookup table covers both forms.\n */\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { mkdirSync } from 'node:fs';\nimport { walkWikiPages, type WikiPageEntry, type PageType } from './page.js';\n\nexport const SLUG_MAP_OPEN = '<!-- AAB:SLUG-MAP -->';\nexport const SLUG_MAP_CLOSE = '<!-- /AAB:SLUG-MAP -->';\nexport const BACKLINKS_OPEN = '<!-- AAB:BACKLINKS -->';\nexport const BACKLINKS_CLOSE = '<!-- /AAB:BACKLINKS -->';\n\nexport interface SlugMapEntry {\n slug: string;\n /** Forward-slash path relative to `wiki/`. */\n path: string;\n type: PageType | string;\n title?: string;\n summary?: string;\n /** When this row represents an alias, the canonical slug. */\n canonical?: string;\n}\n\nexport interface SlugMap {\n /** Canonical slug → entry. */\n canonical: Map<string, SlugMapEntry>;\n /** Alias → canonical slug. Includes self-mapping for canonicals. */\n aliasToCanonical: Map<string, string>;\n}\n\n/**\n * Build a slug-map by walking the wiki directory.\n */\nexport function buildSlugMap(wikiRoot: string, workspaceRoot?: string): SlugMap {\n const pages = walkWikiPages(wikiRoot, workspaceRoot);\n return buildSlugMapFromPages(pages);\n}\n\nexport function buildSlugMapFromPages(pages: WikiPageEntry[]): SlugMap {\n const canonical = new Map<string, SlugMapEntry>();\n const aliasToCanonical = new Map<string, string>();\n for (const p of pages) {\n const slug = (p.frontmatter.slug ?? '').trim().toLowerCase();\n if (!slug) continue;\n const entry: SlugMapEntry = {\n slug,\n path: p.wikiRelPath,\n type: (p.frontmatter.type as PageType) ?? 'concept',\n title: typeof p.frontmatter.title === 'string' ? p.frontmatter.title : undefined,\n summary: typeof p.frontmatter.summary === 'string' ? p.frontmatter.summary : undefined,\n };\n canonical.set(slug, entry);\n aliasToCanonical.set(slug, slug);\n const aliases = Array.isArray(p.frontmatter.aliases) ? p.frontmatter.aliases : [];\n for (const a of aliases) {\n if (typeof a !== 'string') continue;\n const alias = a.trim().toLowerCase();\n if (!alias || alias === slug) continue;\n aliasToCanonical.set(alias, slug);\n }\n }\n return { canonical, aliasToCanonical };\n}\n\n/** Resolve a `[[slug]]` (possibly an alias) to its entry, or `undefined`. */\nexport function resolveSlug(map: SlugMap, slug: string): SlugMapEntry | undefined {\n const canonical = map.aliasToCanonical.get(slug.trim().toLowerCase());\n if (!canonical) return undefined;\n return map.canonical.get(canonical);\n}\n\n/**\n * Render the slug-map table block (between the sentinels). Stable order:\n * - canonical slugs alphabetically by slug\n * - aliases interleaved right after their canonical row\n */\nexport function renderSlugMap(map: SlugMap): string {\n const slugs = Array.from(map.canonical.keys()).sort();\n const aliasesBySlug = new Map<string, string[]>();\n for (const [alias, canonical] of map.aliasToCanonical.entries()) {\n if (alias === canonical) continue;\n if (!aliasesBySlug.has(canonical)) aliasesBySlug.set(canonical, []);\n aliasesBySlug.get(canonical)!.push(alias);\n }\n\n const lines: string[] = [];\n lines.push(SLUG_MAP_OPEN);\n if (slugs.length === 0) {\n lines.push('');\n lines.push('_No wiki pages yet. Run `aab knowledge ingest <path-or-url>` to seed._');\n lines.push('');\n } else {\n lines.push('');\n lines.push('| Slug | Path | Type | Summary |');\n lines.push('|------|------|------|---------|');\n for (const slug of slugs) {\n const e = map.canonical.get(slug)!;\n lines.push(`| ${escapeCell(e.slug)} | ${escapeCell(e.path)} | ${escapeCell(e.type)} | ${escapeCell(e.summary ?? '')} |`);\n const aliases = aliasesBySlug.get(slug);\n if (aliases) {\n for (const a of aliases.sort()) {\n lines.push(`| ${escapeCell(a)} _(alias)_ | ${escapeCell(e.path)} | ${escapeCell(e.type)} | ${escapeCell(e.summary ?? '')} |`);\n }\n }\n }\n lines.push('');\n }\n lines.push(SLUG_MAP_CLOSE);\n return lines.join('\\n');\n}\n\n/**\n * Parse the slug-map back out of a rendered block. Used by query/lint as a\n * fast-path before walking the wiki. Returns an empty SlugMap if the\n * sentinels are missing or the table is empty.\n */\nexport function parseSlugMap(indexBody: string): SlugMap {\n const openIdx = indexBody.indexOf(SLUG_MAP_OPEN);\n const closeIdx = indexBody.indexOf(SLUG_MAP_CLOSE);\n const map: SlugMap = { canonical: new Map(), aliasToCanonical: new Map() };\n if (openIdx < 0 || closeIdx < 0 || closeIdx <= openIdx) return map;\n const block = indexBody.slice(openIdx + SLUG_MAP_OPEN.length, closeIdx);\n const rows = block.split(/\\r?\\n/).map((s) => s.trim()).filter((s) => s.startsWith('|') && !s.startsWith('|--') && !/^\\|\\s*Slug\\s*\\|/i.test(s));\n for (const row of rows) {\n const cells = row.split('|').map((c) => c.trim()).filter((_, i, arr) => i > 0 && i < arr.length - 1);\n if (cells.length < 3) continue;\n const slugCell = cells[0]!;\n const path = cells[1]!;\n const type = cells[2]!;\n const summary = cells[3] ?? '';\n const aliasMatch = slugCell.match(/^(\\S+)\\s+_\\(alias\\)_$/);\n if (aliasMatch) {\n const alias = aliasMatch[1]!.toLowerCase();\n // Find canonical by path\n let canonical: string | undefined;\n for (const [cSlug, cEntry] of map.canonical.entries()) {\n if (cEntry.path === path) {\n canonical = cSlug;\n break;\n }\n }\n if (canonical) map.aliasToCanonical.set(alias, canonical);\n } else {\n const slug = slugCell.toLowerCase();\n map.canonical.set(slug, { slug, path, type, summary });\n map.aliasToCanonical.set(slug, slug);\n }\n }\n return map;\n}\n\n/**\n * Rewrite the slug-map section of `wiki/index.md`. Preserves the prose\n * outside the sentinels verbatim. If the sentinels are missing, appends a\n * fresh slug-map section to the end of the file.\n */\nexport function writeSlugMapToIndex(indexPath: string, map: SlugMap, header?: string): void {\n mkdirSync(dirname(indexPath), { recursive: true });\n const existing = existsSync(indexPath) ? readFileSync(indexPath, 'utf8') : '';\n const block = renderSlugMap(map);\n const openIdx = existing.indexOf(SLUG_MAP_OPEN);\n const closeIdx = existing.indexOf(SLUG_MAP_CLOSE);\n let next: string;\n if (openIdx >= 0 && closeIdx > openIdx) {\n next = existing.slice(0, openIdx) + block + existing.slice(closeIdx + SLUG_MAP_CLOSE.length);\n } else if (existing) {\n next = existing.replace(/\\n+$/, '') + '\\n\\n## Slug map (auto-maintained — do not hand-edit)\\n\\n' + block + '\\n';\n } else {\n next = (header ?? defaultIndexHeader()) + '\\n\\n## Slug map (auto-maintained — do not hand-edit)\\n\\n' + block + '\\n';\n }\n writeFileSync(indexPath, next, 'utf8');\n}\n\nexport function defaultIndexHeader(): string {\n return [\n '# Wiki index',\n '',\n 'Browse the wiki by type:',\n '',\n '- [Concepts](concepts/)',\n '- [Entities](entities/)',\n '- [Decisions](decisions/)',\n '- [Sources](sources/)',\n '- [Comparisons](comparisons/)',\n '',\n 'See `KNOWLEDGE.md` for the schema and conventions.',\n ].join('\\n');\n}\n\nfunction escapeCell(s: string): string {\n return s.replace(/\\|/g, '\\\\|').replace(/\\n/g, ' ').slice(0, 200);\n}\n\n// ----------------------------------------------------------------------------\n// Backlinks (`<!-- AAB:BACKLINKS -->` section per page)\n// ----------------------------------------------------------------------------\n\n/** Replace the backlinks section in a page body, or append one if missing. */\nexport function setBacklinksSection(body: string, backlinks: string[]): string {\n const block: string[] = [];\n block.push(BACKLINKS_OPEN);\n if (backlinks.length === 0) {\n block.push('');\n block.push('_(no incoming links yet)_');\n block.push('');\n } else {\n block.push('');\n block.push('## Backlinks');\n block.push('');\n for (const b of backlinks) block.push(`- ${b}`);\n block.push('');\n }\n block.push(BACKLINKS_CLOSE);\n const text = block.join('\\n');\n const openIdx = body.indexOf(BACKLINKS_OPEN);\n const closeIdx = body.indexOf(BACKLINKS_CLOSE);\n if (openIdx >= 0 && closeIdx > openIdx) {\n return body.slice(0, openIdx) + text + body.slice(closeIdx + BACKLINKS_CLOSE.length);\n }\n return body.replace(/\\n+$/, '') + '\\n\\n' + text + '\\n';\n}\n\n/** Extract the existing backlinks block (everything between the sentinels). */\nexport function extractBacklinksSection(body: string): string | null {\n const openIdx = body.indexOf(BACKLINKS_OPEN);\n const closeIdx = body.indexOf(BACKLINKS_CLOSE);\n if (openIdx < 0 || closeIdx < 0 || closeIdx <= openIdx) return null;\n return body.slice(openIdx + BACKLINKS_OPEN.length, closeIdx);\n}\n","/**\n * Wiki page primitives — frontmatter parse/serialize, slug helpers,\n * `[[wikilink]]` extraction, and humanization rules.\n *\n * Frontmatter contract: `docs/development/KNOWLEDGE_WIKI.md` §8.\n * Wiki-link syntax: §11.\n * File-naming rules: §10.\n */\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, statSync } from 'node:fs';\nimport { dirname, join, basename, relative, sep } from 'node:path';\nimport slugify from 'slugify';\nimport { createHash } from 'node:crypto';\n\nexport type PageType = 'concept' | 'entity' | 'decision' | 'source-summary' | 'comparison';\nexport const PAGE_TYPES: readonly PageType[] = ['concept', 'entity', 'decision', 'source-summary', 'comparison'];\n\nexport type PageProvenance = 'extracted' | 'inferred' | 'ambiguous';\nexport type PageConfidence = 'high' | 'medium' | 'low';\n\nexport interface PageFrontmatter {\n title: string;\n slug: string;\n aliases?: string[];\n type: PageType;\n summary?: string;\n tags?: string[];\n sources?: string[];\n related?: string[];\n confidence?: PageConfidence;\n provenance?: PageProvenance;\n created?: string;\n updated?: string;\n userEdited?: boolean;\n [key: string]: unknown;\n}\n\nexport interface ParsedPage {\n frontmatter: PageFrontmatter;\n body: string;\n raw: string;\n}\n\nconst FRONTMATTER_RE = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/;\n\n/**\n * Parse a markdown file with YAML frontmatter. Returns `null` if the file\n * has no parseable frontmatter (we treat that as a non-page file).\n *\n * Hand-rolled YAML — we deliberately don't pull in a heavyweight parser. We\n * only support the field types in PageFrontmatter:\n * - `key: scalar`\n * - `key: [a, b, c]` (inline array of scalars or quoted strings)\n * - `key:\\n - a\\n - b` (block array)\n */\nexport function parsePage(raw: string): ParsedPage | null {\n const m = raw.match(FRONTMATTER_RE);\n if (!m) return null;\n const yamlBlock = m[1] ?? '';\n const body = raw.slice(m[0].length);\n const fm = parseFrontmatter(yamlBlock);\n if (!fm.slug && !fm.title) return null;\n return { frontmatter: fm as PageFrontmatter, body, raw };\n}\n\nexport function readPage(path: string): ParsedPage | null {\n if (!existsSync(path)) return null;\n try {\n return parsePage(readFileSync(path, 'utf8'));\n } catch {\n return null;\n }\n}\n\n/**\n * Serialize a frontmatter + body back to a markdown file string.\n * Field order is deterministic to keep diffs clean.\n */\nexport function serializePage(fm: PageFrontmatter, body: string): string {\n const lines: string[] = ['---'];\n const emit = (key: string, value: unknown) => {\n if (value === undefined || value === null) return;\n if (Array.isArray(value)) {\n if (value.length === 0) {\n lines.push(`${key}: []`);\n return;\n }\n lines.push(`${key}:`);\n for (const v of value) {\n lines.push(` - ${yamlScalar(v)}`);\n }\n return;\n }\n if (typeof value === 'boolean' || typeof value === 'number') {\n lines.push(`${key}: ${value}`);\n return;\n }\n lines.push(`${key}: ${yamlScalar(String(value))}`);\n };\n\n const order: Array<keyof PageFrontmatter> = [\n 'title',\n 'slug',\n 'aliases',\n 'type',\n 'summary',\n 'tags',\n 'sources',\n 'related',\n 'confidence',\n 'provenance',\n 'created',\n 'updated',\n 'userEdited',\n ];\n for (const k of order) {\n if (fm[k] !== undefined) emit(k as string, fm[k]);\n }\n // Pass-through unknown keys (preserve hand edits)\n for (const k of Object.keys(fm)) {\n if (!order.includes(k as keyof PageFrontmatter)) emit(k, fm[k]);\n }\n lines.push('---');\n lines.push('');\n // Ensure body has a single trailing newline\n const cleanBody = body.replace(/\\n+$/, '') + '\\n';\n return lines.join('\\n') + cleanBody;\n}\n\nfunction yamlScalar(value: unknown): string {\n const s = String(value);\n // Quote if it contains characters that complicate parsing\n if (s === '' || /^[\\[\\]{}|>!&*%@`,#?:\\-\\s]/.test(s) || /:\\s|\\s$|\\s$/.test(s) || s.includes('\"')) {\n return JSON.stringify(s);\n }\n return s;\n}\n\nfunction parseFrontmatter(yaml: string): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n const lines = yaml.split(/\\r?\\n/);\n let i = 0;\n while (i < lines.length) {\n const line = lines[i] ?? '';\n if (!line.trim() || line.trim().startsWith('#')) {\n i++;\n continue;\n }\n const mFlow = line.match(/^([A-Za-z_][\\w-]*):\\s*(.*)$/);\n if (!mFlow) {\n i++;\n continue;\n }\n const key = mFlow[1]!;\n const rest = (mFlow[2] ?? '').trim();\n if (rest === '') {\n // Block array follows\n const arr: string[] = [];\n i++;\n while (i < lines.length) {\n const nx = lines[i] ?? '';\n const item = nx.match(/^\\s+-\\s*(.+)$/);\n if (!item) break;\n arr.push(stripScalar(item[1]!));\n i++;\n }\n out[key] = arr;\n continue;\n }\n if (rest.startsWith('[') && rest.endsWith(']')) {\n // Inline array\n const inner = rest.slice(1, -1).trim();\n if (!inner) out[key] = [];\n else {\n const items = splitInlineArray(inner).map(stripScalar);\n out[key] = items;\n }\n } else if (rest === 'true' || rest === 'false') {\n out[key] = rest === 'true';\n } else if (/^-?\\d+(\\.\\d+)?$/.test(rest)) {\n out[key] = Number(rest);\n } else {\n out[key] = stripScalar(rest);\n }\n i++;\n }\n return out;\n}\n\nfunction splitInlineArray(s: string): string[] {\n const out: string[] = [];\n let depth = 0;\n let inQuote: '\"' | \"'\" | null = null;\n let acc = '';\n for (const ch of s) {\n if (inQuote) {\n acc += ch;\n if (ch === inQuote) inQuote = null;\n continue;\n }\n if (ch === '\"' || ch === \"'\") {\n inQuote = ch;\n acc += ch;\n continue;\n }\n if (ch === '[' || ch === '{') depth++;\n if (ch === ']' || ch === '}') depth--;\n if (ch === ',' && depth === 0) {\n if (acc.trim()) out.push(acc.trim());\n acc = '';\n continue;\n }\n acc += ch;\n }\n if (acc.trim()) out.push(acc.trim());\n return out;\n}\n\nfunction stripScalar(raw: string): string {\n const v = raw.trim();\n if (v.length >= 2 && ((v.startsWith('\"') && v.endsWith('\"')) || (v.startsWith(\"'\") && v.endsWith(\"'\")))) {\n try {\n return v.startsWith('\"') ? (JSON.parse(v) as string) : v.slice(1, -1);\n } catch {\n return v.slice(1, -1);\n }\n }\n return v;\n}\n\n// ----------------------------------------------------------------------------\n// Slug helpers\n// ----------------------------------------------------------------------------\n\nexport function toSlug(input: string): string {\n const s = slugify(input, { lower: true, strict: true, trim: true });\n return s || 'untitled';\n}\n\nconst HUMANIZE_FILLER = new Set([\n 'the', 'a', 'an', 'is', 'are', 'should', 'we', 'our', 'us', 'do', 'does',\n 'to', 'of', 'in', 'on', 'for', 'and', 'or', 'but', 'be', 'this', 'that',\n 'how', 'what', 'why', 'when', 'where', 'who',\n]);\n\n/**\n * Humanize an arbitrary string (question text, document title) into a\n * filename-safe kebab slug capped at ~60 chars.\n */\nexport function humanizeSlug(input: string, maxChars = 60): string {\n const words = input\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, ' ')\n .split(/\\s+/)\n .filter(Boolean)\n .filter((w) => !HUMANIZE_FILLER.has(w));\n const candidate = words.slice(0, 8).join('-').replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');\n if (!candidate) return 'untitled';\n return candidate.slice(0, maxChars).replace(/-$/, '');\n}\n\n/** SHA-256 of bytes, first 6 hex chars. */\nexport function hash6(bytes: Buffer | string): string {\n return createHash('sha256').update(bytes).digest('hex').slice(0, 6);\n}\n\n/** Full SHA-256 hex digest. */\nexport function sha256Hex(bytes: Buffer | string): string {\n return createHash('sha256').update(bytes).digest('hex');\n}\n\n// ----------------------------------------------------------------------------\n// Wiki-link extraction\n// ----------------------------------------------------------------------------\n\nexport interface WikiLinkRef {\n slug: string;\n /** Optional `#section-header` portion (without the `#`). */\n anchor?: string;\n /** Optional `|Display Text` portion. */\n display?: string;\n /** True for `![[slug]]` transclusion (not supported in v1). */\n transclusion?: boolean;\n /** True for `[[slug#^block-id]]` block IDs (not supported in v1). */\n blockId?: boolean;\n /** True if a path-prefixed form was used (forbidden — `[[concepts/foo]]`). */\n pathPrefixed?: boolean;\n /** Source text exactly as it appeared. */\n raw: string;\n}\n\nconst WIKILINK_RE = /(!?)\\[\\[([^\\]\\n]+)\\]\\]/g;\n\n/**\n * Extract every `[[wikilink]]` in a body string. Returns refs in source order.\n * Recognises display overrides `[[slug|Display]]`, header anchors `[[slug#sec]]`,\n * block IDs `[[slug#^id]]` (flagged as blockId), transclusion `![[slug]]`\n * (flagged), and path-prefixed forms (flagged as pathPrefixed).\n */\nexport function extractWikiLinks(body: string): WikiLinkRef[] {\n const out: WikiLinkRef[] = [];\n let m: RegExpExecArray | null;\n // Reset regex state across calls.\n const re = new RegExp(WIKILINK_RE.source, 'g');\n while ((m = re.exec(body)) !== null) {\n const transclusion = m[1] === '!';\n const inner = (m[2] ?? '').trim();\n if (!inner) continue;\n let display: string | undefined;\n let target = inner;\n const pipeIdx = inner.indexOf('|');\n if (pipeIdx >= 0) {\n target = inner.slice(0, pipeIdx).trim();\n display = inner.slice(pipeIdx + 1).trim();\n }\n let anchor: string | undefined;\n let blockId = false;\n const hashIdx = target.indexOf('#');\n if (hashIdx >= 0) {\n anchor = target.slice(hashIdx + 1).trim();\n target = target.slice(0, hashIdx).trim();\n if (anchor.startsWith('^')) blockId = true;\n }\n const pathPrefixed = target.includes('/') || target.includes('\\\\');\n const slug = pathPrefixed\n ? target.split(/[/\\\\]/).pop()!.toLowerCase()\n : target.toLowerCase();\n out.push({\n slug,\n anchor,\n display,\n transclusion: transclusion || undefined,\n blockId: blockId || undefined,\n pathPrefixed: pathPrefixed || undefined,\n raw: m[0]!,\n });\n }\n return out;\n}\n\n/** Kebab-case a header text the same way GitHub Flavored Markdown does. */\nexport function kebabHeader(text: string): string {\n return text\n .trim()\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/\\s+/g, '-');\n}\n\n/** Extract all `## ...` and `### ...` headers' kebab-anchors from a body. */\nexport function extractHeaderAnchors(body: string): string[] {\n const anchors: string[] = [];\n for (const line of body.split(/\\r?\\n/)) {\n const m = line.match(/^(#{2,6})\\s+(.+?)\\s*$/);\n if (m) anchors.push(kebabHeader(m[2]!));\n }\n return anchors;\n}\n\n// ----------------------------------------------------------------------------\n// Page discovery\n// ----------------------------------------------------------------------------\n\nexport interface WikiPageEntry {\n /** Absolute path on disk. */\n path: string;\n /** Path relative to the workspace root (forward slashes). */\n relPath: string;\n /** Path relative to `wiki/` (e.g., `concepts/foo.md`). */\n wikiRelPath: string;\n frontmatter: PageFrontmatter;\n body: string;\n}\n\n/**\n * Walk a `wiki/` directory and return every parseable page (skips files with\n * no frontmatter). KNOWLEDGE.md, index.md, and log.md are excluded — they\n * are wiki *infrastructure*, not content pages.\n */\nexport function walkWikiPages(wikiRoot: string, workspaceRoot?: string): WikiPageEntry[] {\n const out: WikiPageEntry[] = [];\n if (!existsSync(wikiRoot)) return out;\n const wsRoot = workspaceRoot ?? dirname(wikiRoot);\n const infraNames = new Set(['KNOWLEDGE.md', 'index.md', 'log.md']);\n\n const walk = (dir: string) => {\n let entries: import('node:fs').Dirent[];\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const e of entries) {\n const full = join(dir, e.name);\n if (e.isDirectory()) {\n walk(full);\n continue;\n }\n if (!e.isFile() || !e.name.endsWith('.md')) continue;\n // Skip wiki infrastructure files at the top level of wiki/.\n if (dirname(full) === wikiRoot && infraNames.has(e.name)) continue;\n const parsed = readPage(full);\n if (!parsed) continue;\n out.push({\n path: full,\n relPath: toPosix(relative(wsRoot, full)),\n wikiRelPath: toPosix(relative(wikiRoot, full)),\n frontmatter: parsed.frontmatter,\n body: parsed.body,\n });\n }\n };\n walk(wikiRoot);\n return out;\n}\n\nexport function toPosix(p: string): string {\n return p.split(sep).join('/');\n}\n\n/** Write a page atomically (mkdir parent + write). */\nexport function writePageAtomic(path: string, fm: PageFrontmatter, body: string): void {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, serializePage(fm, body), 'utf8');\n}\n\n/** Decide the subfolder for a page based on its type. */\nexport function folderForType(type: PageType): string {\n switch (type) {\n case 'concept':\n return 'concepts';\n case 'entity':\n return 'entities';\n case 'decision':\n return 'decisions';\n case 'source-summary':\n return 'sources';\n case 'comparison':\n return 'comparisons';\n }\n}\n\n/** Build an absolute file path from a type + slug + wiki root. */\nexport function pathForPage(wikiRoot: string, type: PageType, slug: string): string {\n return join(wikiRoot, folderForType(type), `${slug}.md`);\n}\n\n/** True if any file ancestor of `path` contains a `.git` directory. */\nexport function isAncestor(parent: string, child: string): boolean {\n const rel = relative(parent, child);\n return !!rel && !rel.startsWith('..') && !rel.startsWith(sep + '..');\n}\n\n/** File metadata used by lint to flag stale claims. */\nexport function fileMtime(path: string): number {\n try {\n return statSync(path).mtimeMs;\n } catch {\n return 0;\n }\n}\n","/**\n * Manifest — `<workspace>/.manifest.json` — provenance ledger for the wiki.\n *\n * Format spec: `docs/development/KNOWLEDGE_WIKI.md` §13. Writes are atomic via\n * `writeJsonAtomic` so concurrent ingest + rename + lint stay consistent\n * (the workspace mutex serialises them; the atomic write keeps a crash\n * from leaving the JSON half-written).\n */\nimport { existsSync } from 'node:fs';\nimport { readJson, writeJsonAtomic } from '../../storage/io.js';\nimport { nowIso } from '../utils.js';\nimport { generateUUID } from '../utils.js';\n\nexport type ManifestSourceType =\n | 'file'\n | 'url'\n | 'pasted'\n | 'discussion'\n | 'summary'\n | 'discussion-rerun';\n\nexport interface ManifestEntry {\n id: string;\n rawPath: string;\n sourceType: ManifestSourceType;\n originalName?: string;\n url?: string;\n discussionId?: string;\n hash: string;\n ingestedAt: string;\n ingestModel?: string;\n ingestCostUsd?: number;\n producedPages: string[];\n updatedPages: string[];\n userEditedPagesSkipped?: string[];\n notes?: string;\n}\n\nexport interface ManifestUserEdited {\n page: string;\n lastEditedAt: string;\n editorHint?: string;\n}\n\nexport type ManifestRenameTrigger = 'manual' | 'lint-recommended' | 'foam-reconcile';\n\nexport interface ManifestRename {\n id: string;\n from: string;\n to: string;\n fromSlug: string;\n toSlug: string;\n at: string;\n trigger: ManifestRenameTrigger;\n rewroteRefs?: number;\n rewroteRelated?: number;\n rewroteAliases?: number;\n rewroteManifestEntries?: number;\n}\n\nexport interface Manifest {\n version: number;\n createdAt: string;\n updatedAt: string;\n entries: ManifestEntry[];\n userEditedPages: ManifestUserEdited[];\n renames: ManifestRename[];\n}\n\nexport const MANIFEST_VERSION = 1;\n\nexport function emptyManifest(): Manifest {\n const now = nowIso();\n return {\n version: MANIFEST_VERSION,\n createdAt: now,\n updatedAt: now,\n entries: [],\n userEditedPages: [],\n renames: [],\n };\n}\n\nexport function loadManifest(path: string): Manifest {\n if (!existsSync(path)) return emptyManifest();\n const raw = readJson<Partial<Manifest>>(path, {} as Partial<Manifest>);\n return {\n version: typeof raw.version === 'number' ? raw.version : MANIFEST_VERSION,\n createdAt: typeof raw.createdAt === 'string' ? raw.createdAt : nowIso(),\n updatedAt: typeof raw.updatedAt === 'string' ? raw.updatedAt : nowIso(),\n entries: Array.isArray(raw.entries) ? raw.entries : [],\n userEditedPages: Array.isArray(raw.userEditedPages) ? raw.userEditedPages : [],\n renames: Array.isArray(raw.renames) ? raw.renames : [],\n };\n}\n\nexport function saveManifest(path: string, manifest: Manifest): void {\n manifest.updatedAt = nowIso();\n writeJsonAtomic(path, manifest);\n}\n\n/**\n * Initialise an empty manifest file if it doesn't exist yet. Idempotent.\n */\nexport function initManifestIfAbsent(path: string): void {\n if (existsSync(path)) return;\n saveManifest(path, emptyManifest());\n}\n\n/**\n * Look up the manifest entry for a content hash. Returns the most-recent\n * entry if multiple exist (we don't dedupe entries — we dedupe new ingests\n * against the latest run).\n */\nexport function findEntryByHash(manifest: Manifest, hash: string): ManifestEntry | undefined {\n for (let i = manifest.entries.length - 1; i >= 0; i--) {\n const entry = manifest.entries[i]!;\n if (entry.hash === hash) return entry;\n }\n return undefined;\n}\n\n/** Build a new entry with a generated id + timestamp. */\nexport function newEntry(\n partial: Omit<ManifestEntry, 'id' | 'ingestedAt'> & { ingestedAt?: string },\n): ManifestEntry {\n return {\n ...partial,\n id: `ing_${generateUUID().slice(0, 16)}`,\n ingestedAt: partial.ingestedAt ?? nowIso(),\n };\n}\n\n/** Append an entry and persist. */\nexport function appendEntry(path: string, entry: ManifestEntry): Manifest {\n const m = loadManifest(path);\n m.entries.push(entry);\n saveManifest(path, m);\n return m;\n}\n\n/** Append a rename record. */\nexport function appendRename(path: string, rename: Omit<ManifestRename, 'id' | 'at'> & { at?: string }): Manifest {\n const m = loadManifest(path);\n m.renames.push({\n ...rename,\n id: `ren_${generateUUID().slice(0, 16)}`,\n at: rename.at ?? nowIso(),\n });\n saveManifest(path, m);\n return m;\n}\n\n/**\n * Rewrite every `producedPages` / `updatedPages` / `userEditedPages.page`\n * reference from `fromPath` to `toPath`. Returns the count rewritten across\n * the three collections so the rename log can record it.\n */\nexport interface ManifestRewriteResult {\n manifest: Manifest;\n rewroteManifestEntries: number;\n}\n\nexport function rewriteManifestPaths(\n manifest: Manifest,\n fromPath: string,\n toPath: string,\n): ManifestRewriteResult {\n let count = 0;\n for (const entry of manifest.entries) {\n entry.producedPages = entry.producedPages.map((p) => {\n if (p === fromPath) {\n count++;\n return toPath;\n }\n return p;\n });\n entry.updatedPages = entry.updatedPages.map((p) => {\n if (p === fromPath) {\n count++;\n return toPath;\n }\n return p;\n });\n if (entry.userEditedPagesSkipped) {\n entry.userEditedPagesSkipped = entry.userEditedPagesSkipped.map((p) => {\n if (p === fromPath) {\n count++;\n return toPath;\n }\n return p;\n });\n }\n }\n for (const ue of manifest.userEditedPages) {\n if (ue.page === fromPath) {\n ue.page = toPath;\n count++;\n }\n }\n return { manifest, rewroteManifestEntries: count };\n}\n\n/** Mark a page as user-edited (or refresh the timestamp). */\nexport function markUserEdited(path: string, page: string, hint = 'manual'): void {\n const m = loadManifest(path);\n const existing = m.userEditedPages.find((u) => u.page === page);\n if (existing) {\n existing.lastEditedAt = nowIso();\n existing.editorHint = hint;\n } else {\n m.userEditedPages.push({ page, lastEditedAt: nowIso(), editorHint: hint });\n }\n saveManifest(path, m);\n}\n","/**\n * Foam (VS Code) recommendation — emits/merges `.vscode/extensions.json` so\n * users who open the workspace in VS Code get a one-click install prompt for\n * `foam.foam-vscode`.\n *\n * Spec: `docs/development/KNOWLEDGE_WIKI.md` §17 (\"aab init --foam\"). Foam is the\n * recommended human-side editor — speaks `[[wikilinks]]` natively (Obsidian\n * flavor), gives autocomplete + click navigation + graph view + backlinks\n * panel, MIT-licensed, free. Zero engineering on our side.\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nexport const FOAM_EXTENSION_ID = 'foam.foam-vscode';\n\nexport type FoamEmitResult =\n | { action: 'created'; path: string }\n | { action: 'merged'; path: string }\n | { action: 'noop'; path: string; reason: string };\n\nexport interface VsCodeExtensionsJson {\n recommendations?: string[];\n unwantedRecommendations?: string[];\n [key: string]: unknown;\n}\n\n/**\n * Write or merge a Foam recommendation into `<projectRoot>/.vscode/extensions.json`.\n *\n * Behavior:\n * - File missing: create with `{ recommendations: [\"foam.foam-vscode\"] }`.\n * - File exists, already lists Foam: no-op.\n * - File exists, missing Foam: parse, append, write back atomically.\n * - File exists but unparseable: refuse to overwrite (unless `force` is true).\n */\nexport function emitFoamRecommendation(opts: {\n projectRoot: string;\n force?: boolean;\n}): FoamEmitResult {\n const path = join(opts.projectRoot, '.vscode', 'extensions.json');\n if (!existsSync(path)) {\n mkdirSync(dirname(path), { recursive: true });\n const body = JSON.stringify({ recommendations: [FOAM_EXTENSION_ID] }, null, 2) + '\\n';\n writeFileSync(path, body, 'utf8');\n return { action: 'created', path };\n }\n\n let parsed: VsCodeExtensionsJson;\n try {\n parsed = JSON.parse(readFileSync(path, 'utf8')) as VsCodeExtensionsJson;\n } catch (error) {\n if (!opts.force) {\n return {\n action: 'noop',\n path,\n reason: `existing .vscode/extensions.json is not valid JSON (${error instanceof Error ? error.message : 'parse error'}); refusing to overwrite — re-run with --foam-overwrite to replace`,\n };\n }\n const body = JSON.stringify({ recommendations: [FOAM_EXTENSION_ID] }, null, 2) + '\\n';\n writeFileSync(path, body, 'utf8');\n return { action: 'created', path };\n }\n\n const recs = Array.isArray(parsed.recommendations) ? parsed.recommendations.slice() : [];\n if (recs.includes(FOAM_EXTENSION_ID)) {\n return { action: 'noop', path, reason: 'already recommends foam.foam-vscode' };\n }\n recs.push(FOAM_EXTENSION_ID);\n parsed.recommendations = recs;\n writeFileSync(path, JSON.stringify(parsed, null, 2) + '\\n', 'utf8');\n return { action: 'merged', path };\n}\n\n/** True if `.vscode/extensions.json` already lists Foam in its recommendations. */\nexport function foamAlreadyRecommended(projectRoot: string): boolean {\n const path = join(projectRoot, '.vscode', 'extensions.json');\n if (!existsSync(path)) return false;\n try {\n const parsed = JSON.parse(readFileSync(path, 'utf8')) as VsCodeExtensionsJson;\n return Array.isArray(parsed.recommendations) && parsed.recommendations.includes(FOAM_EXTENSION_ID);\n } catch {\n return false;\n }\n}\n","/**\n * skill-creator resolver — Phase 5 Chunk 1.\n *\n * Walks the Claude Code skill scope priority order (project → user → plugin)\n * looking for an installed `skill-creator/SKILL.md`. Used by `aab doctor`,\n * `aab init --install-skill-creator`, and `aab actions solve` (which gates\n * on its presence per docs/development/SKILL_CREATOR.md §8).\n *\n * Returns `null` if not found; otherwise a `ResolvedSkill` with path + version\n * + scope so callers can surface where it lives and how to upgrade.\n */\nimport { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nexport type SkillScope = 'project' | 'user' | 'plugin';\n\nexport interface ResolvedSkill {\n /** Absolute path to the SKILL.md file. */\n path: string;\n /** Absolute path to the skill directory. */\n dir: string;\n /** `project`, `user`, or `plugin`. */\n scope: SkillScope;\n /** Extracted from frontmatter `version:` if present. */\n version?: string;\n /** Extracted from frontmatter `name:`; falls back to dir name. */\n name: string;\n}\n\nexport interface ResolveOptions {\n /** Project root to search for `.claude/skills/<name>/` — defaults to process.cwd(). */\n projectRoot?: string;\n /** Override for ~/.claude — useful in tests. */\n homeDir?: string;\n}\n\n/**\n * Resolve a skill by name across the Claude Code scope priority order.\n *\n * Priority (matches Claude Code's resolver behavior):\n * 1. `<projectRoot>/.claude/skills/<name>/SKILL.md` (project-scoped)\n * 2. `~/.claude/skills/<name>/SKILL.md` (user-scoped)\n * 3. `~/.claude/plugins/*/skills/<name>/SKILL.md` (plugin-scoped)\n */\nexport function resolveSkill(name: string, opts: ResolveOptions = {}): ResolvedSkill | null {\n const projectRoot = opts.projectRoot ?? process.cwd();\n const home = opts.homeDir ?? homedir();\n\n // 1. Project scope\n const projectPath = join(projectRoot, '.claude', 'skills', name, 'SKILL.md');\n if (existsSync(projectPath)) {\n return buildResolvedSkill(projectPath, 'project');\n }\n\n // 2. User scope\n const userPath = join(home, '.claude', 'skills', name, 'SKILL.md');\n if (existsSync(userPath)) {\n return buildResolvedSkill(userPath, 'user');\n }\n\n // 3. Plugin scope — walk under ~/.claude/plugins/ recursively (capped at 5\n // levels deep) for any path matching `*/skills/<name>/SKILL.md`. Covers the\n // real-world layout used by /plugin install:\n // ~/.claude/plugins/marketplaces/<marketplace>/plugins/<plugin>/skills/<name>/SKILL.md\n // ...as well as flatter installs like:\n // ~/.claude/plugins/<plugin>/skills/<name>/SKILL.md\n const pluginsRoot = join(home, '.claude', 'plugins');\n if (existsSync(pluginsRoot)) {\n const found = findPluginScopedSkill(pluginsRoot, name, 5);\n if (found) return buildResolvedSkill(found, 'plugin');\n }\n\n return null;\n}\n\n/**\n * Walk a directory tree up to maxDepth levels deep looking for any path that\n * ends in `skills/<name>/SKILL.md`. Returns the first hit (BFS — shallower\n * matches preferred over deeper ones).\n */\nfunction findPluginScopedSkill(root: string, name: string, maxDepth: number): string | null {\n const queue: Array<{ path: string; depth: number }> = [{ path: root, depth: 0 }];\n while (queue.length > 0) {\n const { path, depth } = queue.shift()!;\n // Direct hit at this level: `<path>/skills/<name>/SKILL.md`\n const candidate = join(path, 'skills', name, 'SKILL.md');\n if (existsSync(candidate)) return candidate;\n if (depth >= maxDepth) continue;\n let entries: string[];\n try {\n entries = readdirSync(path);\n } catch {\n continue;\n }\n for (const entry of entries) {\n const sub = join(path, entry);\n try {\n if (statSync(sub).isDirectory()) {\n queue.push({ path: sub, depth: depth + 1 });\n }\n } catch {\n // ignore unreadable entries\n }\n }\n }\n return null;\n}\n\n/**\n * Convenience wrapper specifically for the `skill-creator` skill, which is\n * Phase 5's hard prerequisite.\n */\nexport function resolveSkillCreator(opts: ResolveOptions = {}): ResolvedSkill | null {\n return resolveSkill('skill-creator', opts);\n}\n\nfunction buildResolvedSkill(skillMdPath: string, scope: SkillScope): ResolvedSkill {\n const dir = skillMdPath.replace(/[\\\\/]SKILL\\.md$/i, '');\n let frontmatterName: string | undefined;\n let frontmatterVersion: string | undefined;\n try {\n const body = readFileSync(skillMdPath, 'utf8');\n const fm = extractFrontmatter(body);\n if (fm) {\n frontmatterName = fm.name;\n frontmatterVersion = fm.version;\n }\n } catch {\n // unreadable — fall through with defaults\n }\n // Derive name from dir if frontmatter didn't carry one.\n const dirName = dir.split(/[\\\\/]/).pop() ?? 'unknown';\n return {\n path: skillMdPath,\n dir,\n scope,\n name: frontmatterName ?? dirName,\n version: frontmatterVersion,\n };\n}\n\ninterface MinimalFrontmatter {\n name?: string;\n version?: string;\n}\n\nconst FRONTMATTER_RE = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/;\n\n/**\n * Minimal YAML frontmatter extractor — we only need `name:` and `version:`.\n * Reuses the same hand-rolled approach as `src/core/knowledge/page.ts` so\n * we don't pull in a heavyweight YAML dep for two fields.\n */\nexport function extractFrontmatter(raw: string): MinimalFrontmatter | null {\n const m = raw.match(FRONTMATTER_RE);\n if (!m) return null;\n const block = m[1] ?? '';\n const out: MinimalFrontmatter = {};\n for (const line of block.split(/\\r?\\n/)) {\n const match = line.match(/^([A-Za-z0-9_-]+):\\s*(.*)$/);\n if (!match) continue;\n const key = match[1]!;\n let value = (match[2] ?? '').trim();\n if (value.startsWith('\"') && value.endsWith('\"')) value = value.slice(1, -1);\n if (value.startsWith(\"'\") && value.endsWith(\"'\")) value = value.slice(1, -1);\n if (key === 'name') out.name = value;\n if (key === 'version') out.version = value;\n }\n return out;\n}\n\n/**\n * Install hint shown by `aab init --install-skill-creator` and `aab doctor`\n * when the skill is missing. `/plugin install` is interactive-only today so\n * we surface the exact command for the user to copy + paste into Claude Code.\n */\nexport function skillCreatorInstallHint(): string {\n return [\n 'Install the official Anthropic skill-creator skill:',\n '',\n ' 1. Open Claude Code in this directory',\n ' 2. Run: /plugin install skill-creator@claude-plugins-official',\n ' 3. Verify with: aab doctor',\n '',\n 'Tracking: https://github.com/anthropics/claude-code/issues/38505 — when a',\n 'non-interactive `--skill` flag ships, this becomes a one-shot CLI install.',\n ].join('\\n');\n}\n","/**\r\n * Helpers shared by command implementations: resolve workspace, build\r\n * StorageService, manage the per-workspace lock.\r\n */\r\nimport { Command } from 'commander';\r\nimport { AabError } from '../core/errors.js';\r\nimport { acquireLock, type LockHandle } from '../storage/locks.js';\r\nimport { paths, resolveWorkspace, type ResolvedWorkspace } from '../storage/paths.js';\r\nimport { FsStorageService } from '../storage/fs-storage-service.js';\r\n\r\nexport interface CommandContext {\r\n workspace: ResolvedWorkspace;\r\n storage: FsStorageService;\r\n lock: LockHandle;\r\n json: boolean;\r\n}\r\n\r\ninterface OpenOptions {\r\n /** When false, skip acquiring the workspace lock (for read-only commands). */\r\n lock?: boolean;\r\n}\r\n\r\n/**\r\n * Resolve workspace + storage from a command's parsed options.\r\n */\r\nexport async function openContext(cmd: Command, opts: OpenOptions = {}): Promise<CommandContext> {\r\n const root = cmd.optsWithGlobals<{ workspace?: string; json?: boolean }>();\r\n const workspace = resolveWorkspace({ override: root.workspace });\r\n const storage = new FsStorageService(workspace);\r\n const lock = opts.lock === false\r\n ? { release: async () => undefined }\r\n : await acquireLock(paths(workspace.root).lockFile).catch((error: unknown) => {\r\n throw new AabError(\r\n `Could not acquire workspace lock: ${error instanceof Error ? error.message : String(error)}`,\r\n 5,\r\n 'Another `aab` invocation may be running. Wait for it to finish or remove the stale .lock file.',\r\n );\r\n });\r\n return { workspace, storage, lock, json: !!root.json };\r\n}\r\n\r\nexport async function closeContext(ctx: CommandContext): Promise<void> {\r\n await ctx.lock.release();\r\n}\r\n","/**\r\n * Per-workspace file lock using proper-lockfile. Held for the duration of\r\n * a CLI command that mutates state, so two `aab` invocations on the same\r\n * workspace never corrupt JSON files.\r\n */\r\nimport { existsSync, mkdirSync, writeFileSync } from 'node:fs';\r\nimport { dirname } from 'node:path';\r\nimport lockfile from 'proper-lockfile';\r\n\r\nexport interface LockHandle {\r\n release: () => Promise<void>;\r\n}\r\n\r\nexport async function acquireLock(lockPath: string, opts: { stale?: number; retries?: number } = {}): Promise<LockHandle> {\r\n const dir = dirname(lockPath);\r\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\r\n if (!existsSync(lockPath)) writeFileSync(lockPath, '', 'utf8');\r\n\r\n const release = await lockfile.lock(lockPath, {\r\n stale: opts.stale ?? 30_000, // forcibly break locks older than 30s\r\n retries: opts.retries ?? { retries: 3, factor: 2, minTimeout: 100, maxTimeout: 1_000 },\r\n realpath: false,\r\n });\r\n return { release: async () => release() };\r\n}\r\n","/**\r\n * `aab settings get|set <key> [value]`\r\n *\r\n * Reads and writes individual fields of AppSettings. Settings persist via\r\n * FsStorageService.saveSettings (with snapshotting). No API-key fields —\r\n * the CLI shells out to the local `claude` CLI for all LLM calls.\r\n */\r\nimport { Command } from 'commander';\r\nimport { closeContext, openContext } from './_context.js';\r\nimport { c } from '../ui/colors.js';\r\nimport { UserError } from '../core/errors.js';\r\nimport { type AppSettings } from '../storage/types.js';\r\n\r\nconst ALLOWED_KEYS = [\r\n 'boardTitle',\r\n 'maxMembersPerDiscussion',\r\n 'maxTurnsPerDiscussion',\r\n 'orchestratorPromptStyle',\r\n 'autoSummarization',\r\n 'consensusThreshold',\r\n 'enableUserInteraction',\r\n 'userInteractionTimeout',\r\n 'clarificationThreshold',\r\n 'primaryModel',\r\n 'researchModel',\r\n 'fastModel',\r\n 'perCallBudgetUsd',\r\n 'locale',\r\n] as const satisfies readonly (keyof AppSettings)[];\r\n\r\ntype AllowedKey = (typeof ALLOWED_KEYS)[number];\r\n\r\nexport function registerSettingsCommand(program: Command): void {\r\n const settings = program.command('settings').description('view or edit app settings');\r\n\r\n settings\r\n .command('get [key]')\r\n .description('print one setting (or all of them when key is omitted)')\r\n .action(async (key: string | undefined) => {\r\n const ctx = await openContext(settings, { lock: false });\r\n try {\r\n const all = await ctx.storage.loadSettings();\r\n if (!key) {\r\n if (ctx.json) {\r\n process.stdout.write(JSON.stringify(all, null, 2) + '\\n');\r\n } else {\r\n process.stdout.write(prettySettings(all) + '\\n');\r\n }\r\n return;\r\n }\r\n if (!ALLOWED_KEYS.includes(key as AllowedKey)) {\r\n throw new UserError(`Unknown setting: ${key}`, `Allowed: ${ALLOWED_KEYS.join(', ')}`);\r\n }\r\n const value = (all as unknown as Record<string, unknown>)[key];\r\n if (ctx.json) process.stdout.write(JSON.stringify({ [key]: value }, null, 2) + '\\n');\r\n else process.stdout.write(`${c.bold(key)}: ${value ?? c.hint('(unset)')}\\n`);\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n });\r\n\r\n settings\r\n .command('set <key> <value>')\r\n .description('update one setting')\r\n .action(async (key: string, value: string) => {\r\n if (!ALLOWED_KEYS.includes(key as AllowedKey)) {\r\n throw new UserError(`Unknown setting: ${key}`, `Allowed: ${ALLOWED_KEYS.join(', ')}`);\r\n }\r\n const ctx = await openContext(settings);\r\n try {\r\n const current = await ctx.storage.loadSettings();\r\n const next = { ...current, [key]: coerceSettingValue(key as AllowedKey, value) } as AppSettings;\r\n await ctx.storage.saveSettings(next);\r\n process.stdout.write(`${c.ok('✓')} ${key} updated.\\n`);\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n });\r\n}\r\n\r\nfunction prettySettings(s: AppSettings): string {\r\n const rows: Array<[string, string]> = [\r\n ['boardTitle', s.boardTitle],\r\n ['primaryModel', String(s.primaryModel)],\r\n ['fastModel', String(s.fastModel)],\r\n ['researchModel', String(s.researchModel)],\r\n ['maxMembersPerDiscussion', String(s.maxMembersPerDiscussion)],\r\n ['maxTurnsPerDiscussion', String(s.maxTurnsPerDiscussion)],\r\n ['consensusThreshold', String(s.consensusThreshold)],\r\n ['enableUserInteraction', String(s.enableUserInteraction)],\r\n ['clarificationThreshold', String(s.clarificationThreshold)],\r\n ['orchestratorPromptStyle', s.orchestratorPromptStyle],\r\n ['autoSummarization', String(s.autoSummarization)],\r\n ['perCallBudgetUsd', s.perCallBudgetUsd != null ? String(s.perCallBudgetUsd) : '(unset)'],\r\n ['locale', s.locale ?? '(unset)'],\r\n ];\r\n const width = Math.max(...rows.map(([k]) => k.length));\r\n return rows.map(([k, v]) => ` ${c.bold(k.padEnd(width))} ${v}`).join('\\n');\r\n}\r\n\r\nfunction coerceSettingValue(key: AllowedKey, raw: string): unknown {\r\n switch (key) {\r\n case 'maxMembersPerDiscussion':\r\n case 'maxTurnsPerDiscussion':\r\n case 'consensusThreshold':\r\n case 'userInteractionTimeout':\r\n case 'clarificationThreshold':\r\n case 'perCallBudgetUsd': {\r\n const n = Number(raw);\r\n if (!Number.isFinite(n)) throw new UserError(`Expected a number for ${key}, got \"${raw}\"`);\r\n return n;\r\n }\r\n case 'autoSummarization':\r\n case 'enableUserInteraction': {\r\n if (raw === 'true' || raw === '1' || raw === 'yes') return true;\r\n if (raw === 'false' || raw === '0' || raw === 'no') return false;\r\n throw new UserError(`Expected boolean (true/false) for ${key}, got \"${raw}\"`);\r\n }\r\n case 'orchestratorPromptStyle': {\r\n if (!['analytical', 'creative', 'balanced'].includes(raw))\r\n throw new UserError(`Expected analytical|creative|balanced for ${key}, got \"${raw}\"`);\r\n return raw;\r\n }\r\n case 'primaryModel':\r\n case 'fastModel':\r\n case 'researchModel': {\r\n // Allow aliases (sonnet/opus/haiku/inherit) or full ids — pass through.\r\n return raw;\r\n }\r\n default:\r\n return raw;\r\n }\r\n}\r\n","/**\r\n * `aab doctor` — non-destructive diagnostics.\r\n *\r\n * Phase 0 (claude-CLI-native) checks:\r\n * - `claude` CLI on PATH and runs\r\n * - Claude Code session detection\r\n * - Workspace root + paths writable\r\n * - Storage version recognized\r\n * - Members + principles seeded\r\n * - .claude/agents/<member>.md present for each active member\r\n */\r\nimport { Command } from 'commander';\r\nimport { accessSync, constants, existsSync, readdirSync, readFileSync, statSync } from 'node:fs';\r\nimport { homedir } from 'node:os';\r\nimport { join } from 'node:path';\r\nimport { closeContext, openContext } from './_context.js';\r\nimport { c, brand } from '../ui/colors.js';\r\nimport { detectClaudeCode } from '../env/detect-claude-code.js';\r\nimport { detectClaudeCli } from '../llm/claude-code-runner.js';\r\nimport { paths } from '../storage/paths.js';\r\nimport { memberAgentPath, memberAgentSlug } from '../agents/emit-member-agent.js';\r\nimport { foamAlreadyRecommended } from '../core/knowledge/foam.js';\r\nimport { resolveSkillCreator } from '../core/skill/resolve-skill-creator.js';\r\nimport { quickPcScanProbe } from '../core/skill/recon/pc-scan.js';\r\nimport { probeWebReachability } from '../core/skill/recon/web-probe.js';\r\n\r\ninterface CheckResult {\r\n label: string;\r\n ok: boolean;\r\n detail?: string;\r\n}\r\n\r\nexport function registerDoctorCommand(program: Command): void {\r\n program\r\n .command('doctor')\r\n .description('run non-destructive diagnostics on the current workspace')\r\n .option('--agents-dir <path>', 'where .claude/agents/ should live (default: cwd)')\r\n .action(async (cmdOpts: { agentsDir?: string }) => {\r\n const ctx = await openContext(program, { lock: false });\r\n const checks: CheckResult[] = [];\r\n\r\n try {\r\n // claude CLI\r\n const cli = await detectClaudeCli();\r\n checks.push({\r\n label: '`claude` CLI',\r\n ok: cli.installed,\r\n detail: cli.installed\r\n ? `installed${cli.version ? ' (v' + cli.version + ')' : ''}`\r\n : (cli.error ?? 'not found on PATH'),\r\n });\r\n\r\n // Claude Code session (informational)\r\n const cc = detectClaudeCode();\r\n checks.push({\r\n label: 'Claude Code session',\r\n ok: true,\r\n detail: cc.detected\r\n ? `detected${cc.version ? ' (v' + cc.version + ')' : ''}`\r\n : 'not detected (you can still run from any shell)',\r\n });\r\n\r\n // Workspace\r\n checks.push({\r\n label: 'Workspace',\r\n ok: existsSync(ctx.workspace.root),\r\n detail: `${ctx.workspace.id} (${ctx.workspace.scope}: ${ctx.workspace.root})`,\r\n });\r\n\r\n // Writable\r\n try {\r\n accessSync(ctx.workspace.root, constants.W_OK);\r\n checks.push({ label: 'Workspace writable', ok: true });\r\n } catch {\r\n checks.push({ label: 'Workspace writable', ok: false, detail: 'No write access' });\r\n }\r\n\r\n // Storage version\r\n const versionFile = paths(ctx.workspace.root).versionFile;\r\n const version = existsSync(versionFile) ? readFileSync(versionFile, 'utf8').trim() : '';\r\n checks.push({\r\n label: 'Storage version',\r\n ok: version === '1',\r\n detail: version ? `v${version}` : '(no .version file — run `aab init`)',\r\n });\r\n\r\n // Seeds\r\n const members = await ctx.storage.loadBoardMembers();\r\n checks.push({\r\n label: 'Board members',\r\n ok: members.length > 0,\r\n detail: members.length === 0 ? 'none — run `aab init`' : `${members.length} member(s)`,\r\n });\r\n\r\n const principles = await ctx.storage.loadPrinciples();\r\n checks.push({\r\n label: 'Principles',\r\n ok: principles.length > 0,\r\n detail: principles.length === 0 ? 'none — run `aab init`' : `${principles.length} principle(s)`,\r\n });\r\n\r\n // .claude/agents/ files for active members\r\n const projectRoot = cmdOpts.agentsDir ?? process.cwd();\r\n const activeMembers = members.filter((m) => m.isActive);\r\n const missing: string[] = [];\r\n for (const m of activeMembers) {\r\n const slug = memberAgentSlug(m.name);\r\n if (!existsSync(memberAgentPath(slug, projectRoot))) missing.push(slug);\r\n }\r\n checks.push({\r\n label: '.claude/agents/<member>.md',\r\n ok: activeMembers.length === 0 || missing.length === 0,\r\n detail:\r\n activeMembers.length === 0\r\n ? 'no active members'\r\n : missing.length === 0\r\n ? `${activeMembers.length} agent file(s) at ${projectRoot}\\\\.claude\\\\agents\\\\`\r\n : `missing: ${missing.join(', ')} — run \\`aab members sync-agents\\``,\r\n });\r\n\r\n // Lock file (informational)\r\n checks.push({\r\n label: 'Workspace lock',\r\n ok: true,\r\n detail: existsSync(paths(ctx.workspace.root).lockFile)\r\n ? 'present'\r\n : 'will be created on first write',\r\n });\r\n\r\n // Knowledge Wiki (Phase 1.5)\r\n const wikiPaths = paths(ctx.workspace.root);\r\n const wikiPresent = existsSync(wikiPaths.wiki) && existsSync(wikiPaths.wikiKnowledge);\r\n checks.push({\r\n label: 'Knowledge Wiki',\r\n ok: true,\r\n detail: wikiPresent\r\n ? `present at ${wikiPaths.wiki}`\r\n : 're-run `aab init` to bootstrap wiki/ + raw/ + .manifest.json',\r\n });\r\n\r\n // skill-creator (Phase 5 prerequisite — info-level unless solve is attempted)\r\n const skillCreator = resolveSkillCreator({ projectRoot });\r\n checks.push({\r\n label: 'skill-creator skill',\r\n ok: true,\r\n detail: skillCreator\r\n ? `installed (${skillCreator.scope} scope${skillCreator.version ? '; v' + skillCreator.version : ''})`\r\n : 'not installed — run `aab init --install-skill-creator` before `aab actions solve`',\r\n });\r\n\r\n // PC scan probe — fast, deterministic, never hits network.\r\n const pcProbe = quickPcScanProbe();\r\n checks.push({\r\n label: 'PC scan probe',\r\n ok: pcProbe.ok,\r\n detail: pcProbe.ok\r\n ? `${pcProbe.platform} — ${pcProbe.cliTools} CLI tool(s), ${pcProbe.envVarMatches} env var(s) flagged`\r\n : pcProbe.error ?? 'unknown error',\r\n });\r\n\r\n // Web reachability probe — quick HEAD against anthropic.com; ≤1.5s budget.\r\n const web = await probeWebReachability({ timeoutMs: 1500 });\r\n checks.push({\r\n label: 'Web reachability',\r\n ok: true,\r\n detail: web.reachable\r\n ? `${web.host} reachable (${web.latencyMs}ms)`\r\n : `${web.host}: ${web.reason ?? 'unreachable'} — web recon will be degraded`,\r\n });\r\n\r\n // Playwright MCP (UI test surface) — Phase 6.6 prerequisites.\r\n // `.mcp.json` exists but `node_modules/@playwright/mcp/cli.js` does\r\n // not → teammate forgot `npm install`. Warning, not failure.\r\n const mcpConfig = join(projectRoot, '.mcp.json');\r\n const mcpCli = join(projectRoot, 'node_modules', '@playwright', 'mcp', 'cli.js');\r\n if (existsSync(mcpConfig)) {\r\n checks.push({\r\n label: 'Playwright MCP install',\r\n ok: existsSync(mcpCli),\r\n detail: existsSync(mcpCli)\r\n ? '@playwright/mcp installed'\r\n : '`.mcp.json` present but `node_modules/@playwright/mcp/cli.js` missing — run `npm install`',\r\n });\r\n\r\n // Browser binaries cache check — only relevant if @playwright/mcp\r\n // is installed. Empty `~/.cache/ms-playwright/` → teammate forgot\r\n // `npx playwright install`.\r\n if (existsSync(mcpCli)) {\r\n const cacheDir =\r\n process.platform === 'win32'\r\n ? join(process.env.LOCALAPPDATA ?? join(homedir(), 'AppData', 'Local'), 'ms-playwright')\r\n : process.platform === 'darwin'\r\n ? join(homedir(), 'Library', 'Caches', 'ms-playwright')\r\n : join(homedir(), '.cache', 'ms-playwright');\r\n let browsersOk = false;\r\n try {\r\n if (existsSync(cacheDir) && statSync(cacheDir).isDirectory()) {\r\n browsersOk = readdirSync(cacheDir).length > 0;\r\n }\r\n } catch {\r\n browsersOk = false;\r\n }\r\n checks.push({\r\n label: 'Playwright browsers',\r\n ok: browsersOk,\r\n detail: browsersOk\r\n ? `cached at ${cacheDir}`\r\n : `${cacheDir} is empty — run \\`npx playwright install\\` (≈500MB)`,\r\n });\r\n }\r\n }\r\n\r\n // Foam recommendation (info-only — never fails doctor)\r\n const settings = await ctx.storage.loadSettings();\r\n if (wikiPresent && settings.knowledgeWiki?.recommendFoam !== false) {\r\n const foam = foamAlreadyRecommended(projectRoot);\r\n checks.push({\r\n label: 'Foam (VS Code)',\r\n ok: true,\r\n detail: foam\r\n ? 'recommended in .vscode/extensions.json'\r\n : 'consider `aab init --foam` for [[wikilinks]] support in VS Code',\r\n });\r\n }\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n\r\n // Render\r\n if (ctx.json) {\r\n process.stdout.write(JSON.stringify({ checks }, null, 2) + '\\n');\r\n if (checks.some((c) => !c.ok)) process.exit(1);\r\n return;\r\n }\r\n\r\n process.stdout.write(`\\n${brand()} ${c.hint('— doctor')}\\n\\n`);\r\n const labelWidth = Math.max(...checks.map((c) => c.label.length));\r\n for (const ck of checks) {\r\n const mark = ck.ok ? c.ok('✓') : c.err('✗');\r\n const lbl = ck.label.padEnd(labelWidth);\r\n const det = ck.detail ? ` ${c.hint('— ' + ck.detail)}` : '';\r\n process.stdout.write(` ${mark} ${c.bold(lbl)}${det}\\n`);\r\n }\r\n const allOk = checks.every((c) => c.ok);\r\n process.stdout.write(`\\n${allOk ? c.ok('All good.') : c.warn('Some checks failed.')}\\n`);\r\n if (!allOk) process.exit(1);\r\n });\r\n}\r\n","/**\n * PC scan — Phase 5 Skill Planner recon (read-only invariant).\n *\n * Per docs/development/SKILL_CREATOR.md §6.2: enumerate installed desktop apps, CLI\n * tools, browser extensions, MCP servers, env vars, existing Claude Code\n * skills, Playwright availability, and Claude-for-Chrome / computer-use\n * heuristic flags. Hard rule: this file performs no writes, no network\n * calls, no side effects of any kind. The lint rule\n * `no-side-effects-in-recon` (CI-enforced) keeps it that way.\n *\n * Shape: a pure function taking injected `os` + `fs` + `child_process`\n * handles so unit tests can mock per-platform behavior. Production callers\n * use `scan()` which wires in the real handles.\n */\nimport {\n execFileSync,\n type SpawnSyncReturns,\n} from 'node:child_process';\nimport {\n existsSync,\n readdirSync,\n readFileSync,\n statSync,\n} from 'node:fs';\nimport { delimiter, join } from 'node:path';\nimport { homedir, platform as osPlatform } from 'node:os';\n\nexport type ReconPlatform = 'win32' | 'darwin' | 'linux';\n\nexport interface DetectedApp {\n name: string;\n /** Optional — only populated when we can read it cheaply (registry, .desktop). */\n version?: string;\n /** Coarse category, used by the keyword-relevance sort. */\n category?: 'creative' | 'comms' | 'productivity' | 'dev' | 'data' | 'browser' | 'finance' | 'other';\n source: 'startmenu' | 'registry' | 'programs' | 'applications' | 'mdfind' | 'desktop-entry' | 'flatpak' | 'snap' | 'manual';\n}\n\nexport interface DetectedCliTool {\n name: string;\n path: string;\n version?: string;\n}\n\nexport interface DetectedMcpServer {\n name: string;\n transport?: 'stdio' | 'http' | 'sse';\n tools?: string[];\n source: 'project' | 'user' | 'global';\n}\n\nexport interface DetectedBrowserExtension {\n browser: 'chrome' | 'edge' | 'firefox';\n id: string;\n name?: string;\n version?: string;\n}\n\nexport interface DetectedExistingSkill {\n name: string;\n scope: 'project' | 'user' | 'plugin';\n dir: string;\n}\n\nexport interface ReconResult {\n platform: ReconPlatform;\n scannedAt: string; // ISO\n apps: DetectedApp[];\n cliTools: DetectedCliTool[];\n mcpServers: DetectedMcpServer[];\n browserExtensions: DetectedBrowserExtension[];\n /**\n * Env-var NAMES only (values are always redacted at this layer — see\n * `redactEnvVarValuesInProposal` setting). The patterns surfacing here are\n * defined in `ENV_VAR_ALLOW_PATTERNS`.\n */\n envVars: string[];\n existingSkills: DetectedExistingSkill[];\n /** `npx playwright --version` returned something. */\n playwright: boolean;\n /** Chrome extension dir + auth cookie file both present (heuristic). */\n chrome: boolean;\n /** Anthropic computer-use access enabled (heuristic). */\n computerUseAvailable: boolean;\n /** Warnings from degraded phases (e.g., reg query failed on a locked-down corp Windows). */\n warnings: Array<{ phase: string; severity: 'info' | 'warn' | 'error'; message: string }>;\n}\n\n/**\n * The ~80-pattern env var allowlist. Adding a pattern here is the canonical\n * way to teach the Planner about a new integration surface — the Planner\n * reasons \"user has STRIPE_KEY in env → Stripe MCP likely useful here.\"\n */\nexport const ENV_VAR_ALLOW_PATTERNS: RegExp[] = [\n /^STRIPE_/i, /^HUBSPOT_/i, /^SLACK_/i, /^GOOGLE_/i, /^NOTION_/i, /^LINEAR_/i,\n /^OPENAI_/i, /^ANTHROPIC_/i, /^AWS_/i, /^GCP_/i, /^AZURE_/i,\n /^DATABASE_URL$/i, /^DB_/i, /^POSTGRES_/i, /^MYSQL_/i, /^REDIS_/i, /^MONGO_/i,\n /^GITHUB_TOKEN$/i, /^GH_TOKEN$/i, /^GITLAB_TOKEN$/i,\n /^FIGMA_/i, /^CANVA_/i, /^MIRO_/i, /^OBSIDIAN_/i,\n /^ELGATO_/i, /^OBS_/i, /^FFMPEG_/i,\n /^SENTRY_/i, /^DATADOG_/i, /^NEWRELIC_/i,\n /^TWILIO_/i, /^SENDGRID_/i, /^MAILGUN_/i, /^POSTMARK_/i, /^GMAIL_/i,\n /^MERCURY_/i, /^BREX_/i, /^RAMP_/i, /^STRIPE_RESTRICTED_/i,\n /^GREENHOUSE_/i, /^LEVER_/i, /^WORKABLE_/i, /^RIPPLING_/i, /^GUSTO_/i,\n /^CARTA_/i, /^PULLEY_/i, /^ANGEL_/i,\n /^YOUTUBE_/i, /^VIMEO_/i, /^TWITCH_/i,\n /^X_API_/i, /^TWITTER_/i, /^LINKEDIN_/i, /^META_/i, /^TIKTOK_/i,\n /^ZAPIER_/i, /^MAKE_/i, /^N8N_/i,\n /^AIRTABLE_/i, /^SHEETS_/i, /^EXCEL_/i,\n /^ZOOM_/i, /^CALENDLY_/i,\n /^ASANA_/i, /^TRELLO_/i, /^JIRA_/i, /^MONDAY_/i,\n /^DROPBOX_/i, /^BOX_/i,\n /^DOCUSIGN_/i, /^PANDADOC_/i,\n];\n\n/**\n * The list of CLI tools we probe for. We `where`/`which` each one (very\n * cheap, doesn't execute the tool) and best-effort capture a version.\n */\nexport const CLI_TOOL_PROBES: readonly string[] = [\n 'git', 'gh', 'glab', 'docker', 'docker-compose', 'kubectl', 'helm',\n 'node', 'npm', 'pnpm', 'yarn', 'bun', 'deno',\n 'python', 'python3', 'pip', 'poetry', 'pipx', 'uv',\n 'ruby', 'gem', 'bundle',\n 'go', 'cargo', 'rustc',\n 'java', 'mvn', 'gradle',\n 'php', 'composer',\n 'curl', 'wget', 'jq', 'yq', 'rg', 'fd', 'fzf', 'tree',\n 'ffmpeg', 'imagemagick', 'pandoc',\n 'stripe', 'gh', 'hub',\n 'vercel', 'netlify', 'wrangler', 'firebase', 'gcloud', 'aws', 'az', 'doctl',\n 'terraform', 'pulumi', 'ansible',\n 'psql', 'mysql', 'mongosh', 'redis-cli', 'sqlite3',\n 'claude', 'codex', 'ollama',\n 'playwright',\n];\n\n/**\n * Read-only inventory of the user's environment. Pure function — all I/O\n * is read-only (registry queries, file existence, child_process exec for\n * --version flags, etc.) and the function never throws on a missing surface.\n */\nexport function scan(opts: { projectRoot?: string; envOverride?: NodeJS.ProcessEnv } = {}): ReconResult {\n const platform = (osPlatform() === 'win32' ? 'win32' : osPlatform() === 'darwin' ? 'darwin' : 'linux') as ReconPlatform;\n const projectRoot = opts.projectRoot ?? process.cwd();\n const env = opts.envOverride ?? process.env;\n const warnings: ReconResult['warnings'] = [];\n\n let apps: DetectedApp[] = [];\n try {\n apps = scanApps(platform);\n } catch (err) {\n warnings.push({ phase: 'apps', severity: 'warn', message: err instanceof Error ? err.message.slice(0, 200) : 'apps scan failed' });\n }\n\n let cliTools: DetectedCliTool[] = [];\n try {\n cliTools = scanCliTools(env);\n } catch (err) {\n warnings.push({ phase: 'cli-tools', severity: 'warn', message: err instanceof Error ? err.message.slice(0, 200) : 'cli tools scan failed' });\n }\n\n let mcpServers: DetectedMcpServer[] = [];\n try {\n mcpServers = scanMcpServers(projectRoot);\n } catch (err) {\n warnings.push({ phase: 'mcp', severity: 'warn', message: err instanceof Error ? err.message.slice(0, 200) : 'mcp scan failed' });\n }\n\n let browserExtensions: DetectedBrowserExtension[] = [];\n try {\n browserExtensions = scanBrowserExtensions(platform);\n } catch (err) {\n warnings.push({ phase: 'browser-extensions', severity: 'info', message: 'browser extension scan skipped (often gated by OS perms)' });\n }\n\n const envVars: string[] = [];\n for (const key of Object.keys(env)) {\n if (ENV_VAR_ALLOW_PATTERNS.some((re) => re.test(key))) {\n envVars.push(key);\n }\n }\n envVars.sort();\n\n let existingSkills: DetectedExistingSkill[] = [];\n try {\n existingSkills = scanExistingSkills(projectRoot);\n } catch {\n // ignore\n }\n\n const playwright = cliTools.some((t) => t.name === 'playwright') || existsSync(join(homedir(), '.cache', 'ms-playwright'));\n const chrome = detectChromeExtensionPresence(platform);\n const computerUseAvailable = !!(env.ANTHROPIC_COMPUTER_USE || env.ANTHROPIC_COMPUTER_USE_ENABLED || env.ANTHROPIC_COMPUTER_USE_API_KEY);\n\n return {\n platform,\n scannedAt: new Date().toISOString(),\n apps,\n cliTools,\n mcpServers,\n browserExtensions,\n envVars,\n existingSkills,\n playwright,\n chrome,\n computerUseAvailable,\n warnings,\n };\n}\n\n/**\n * Tiny read-only probe used by `aab doctor` — counts only, no metadata. Far\n * cheaper than a full scan. The full scan is what the Planner uses.\n */\nexport function quickPcScanProbe(opts: { projectRoot?: string } = {}): {\n ok: boolean;\n platform: ReconPlatform;\n cliTools: number;\n envVarMatches: number;\n error?: string;\n} {\n try {\n const platform = (osPlatform() === 'win32' ? 'win32' : osPlatform() === 'darwin' ? 'darwin' : 'linux') as ReconPlatform;\n const env = process.env;\n let cliCount = 0;\n for (const tool of CLI_TOOL_PROBES.slice(0, 20)) {\n if (findOnPath(tool, env)) cliCount++;\n }\n let envCount = 0;\n for (const key of Object.keys(env)) {\n if (ENV_VAR_ALLOW_PATTERNS.some((re) => re.test(key))) envCount++;\n }\n void opts;\n return { ok: true, platform, cliTools: cliCount, envVarMatches: envCount };\n } catch (err) {\n return {\n ok: false,\n platform: 'linux',\n cliTools: 0,\n envVarMatches: 0,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\n// ---------- platform-dispatched scanners ----------\n\nfunction scanApps(platform: ReconPlatform): DetectedApp[] {\n if (platform === 'win32') return scanAppsWindows();\n if (platform === 'darwin') return scanAppsMacOS();\n return scanAppsLinux();\n}\n\nfunction scanAppsWindows(): DetectedApp[] {\n const out: DetectedApp[] = [];\n // Walk the standard install roots — top-level dir entries only, never recurse.\n const roots: string[] = [];\n if (process.env.LOCALAPPDATA) roots.push(join(process.env.LOCALAPPDATA, 'Programs'));\n if (process.env.PROGRAMFILES) roots.push(process.env.PROGRAMFILES);\n if (process.env['PROGRAMFILES(X86)']) roots.push(process.env['PROGRAMFILES(X86)']!);\n for (const root of roots) {\n if (!existsSync(root)) continue;\n let entries: string[];\n try {\n entries = readdirSync(root);\n } catch {\n continue;\n }\n for (const e of entries) {\n const full = join(root, e);\n try {\n if (!statSync(full).isDirectory()) continue;\n } catch {\n continue;\n }\n out.push({ name: e, source: 'programs', category: categorize(e) });\n if (out.length >= 200) return out;\n }\n }\n return out;\n}\n\nfunction scanAppsMacOS(): DetectedApp[] {\n const out: DetectedApp[] = [];\n const roots = ['/Applications', join(homedir(), 'Applications')];\n for (const root of roots) {\n if (!existsSync(root)) continue;\n let entries: string[];\n try {\n entries = readdirSync(root);\n } catch {\n continue;\n }\n for (const e of entries) {\n if (!e.endsWith('.app')) continue;\n const name = e.replace(/\\.app$/, '');\n out.push({ name, source: 'applications', category: categorize(name) });\n if (out.length >= 200) return out;\n }\n }\n return out;\n}\n\nfunction scanAppsLinux(): DetectedApp[] {\n const out: DetectedApp[] = [];\n const roots = ['/usr/share/applications', join(homedir(), '.local', 'share', 'applications')];\n for (const root of roots) {\n if (!existsSync(root)) continue;\n let entries: string[];\n try {\n entries = readdirSync(root);\n } catch {\n continue;\n }\n for (const e of entries) {\n if (!e.endsWith('.desktop')) continue;\n const full = join(root, e);\n let body = '';\n try {\n body = readFileSync(full, 'utf8');\n } catch {\n continue;\n }\n const nameMatch = body.match(/^Name=(.+)$/m);\n const name = nameMatch ? nameMatch[1]!.trim() : e.replace(/\\.desktop$/, '');\n out.push({ name, source: 'desktop-entry', category: categorize(name) });\n if (out.length >= 200) return out;\n }\n }\n return out;\n}\n\nfunction categorize(name: string): DetectedApp['category'] {\n const lower = name.toLowerCase();\n if (/(elgato|obs|davinci|premiere|after.effects|figma|sketch|illustrator|photoshop|procreate|blender|finalcut|riverside)/i.test(lower)) return 'creative';\n if (/(slack|teams|zoom|discord|telegram|signal|whatsapp|gmail|outlook|missive)/i.test(lower)) return 'comms';\n if (/(notion|evernote|obsidian|roam|onenote|todoist|things|reminders|airtable|coda)/i.test(lower)) return 'productivity';\n if (/(vs.?code|cursor|sublime|jetbrains|webstorm|idea|pycharm|xcode|android.studio|docker|postman|insomnia)/i.test(lower)) return 'dev';\n if (/(tableau|looker|metabase|grafana|powerbi|excel|sheets)/i.test(lower)) return 'data';\n if (/(chrome|edge|firefox|safari|brave|arc|vivaldi|opera)/i.test(lower)) return 'browser';\n if (/(stripe|mercury|brex|ramp|quickbooks|xero|sage|carta)/i.test(lower)) return 'finance';\n return 'other';\n}\n\nfunction scanCliTools(env: NodeJS.ProcessEnv): DetectedCliTool[] {\n const out: DetectedCliTool[] = [];\n const seen = new Set<string>();\n for (const tool of CLI_TOOL_PROBES) {\n if (seen.has(tool)) continue;\n seen.add(tool);\n const path = findOnPath(tool, env);\n if (!path) continue;\n const version = tryVersion(path);\n out.push({ name: tool, path, version });\n if (out.length >= 80) break;\n }\n return out;\n}\n\nfunction scanMcpServers(projectRoot: string): DetectedMcpServer[] {\n const out: DetectedMcpServer[] = [];\n const seen = new Set<string>();\n // Project-scoped .mcp.json\n const projectFile = join(projectRoot, '.mcp.json');\n pushMcp(projectFile, 'project', seen, out);\n // User-scoped\n pushMcp(join(homedir(), '.claude', '.mcp.json'), 'user', seen, out);\n pushMcp(join(homedir(), '.mcp.json'), 'global', seen, out);\n return out;\n}\n\nfunction pushMcp(file: string, source: DetectedMcpServer['source'], seen: Set<string>, out: DetectedMcpServer[]): void {\n if (!existsSync(file)) return;\n let body: string;\n try {\n body = readFileSync(file, 'utf8');\n } catch {\n return;\n }\n let json: { mcpServers?: Record<string, { transport?: string }>; servers?: Record<string, { transport?: string }> };\n try {\n json = JSON.parse(body);\n } catch {\n return;\n }\n const servers = json.mcpServers ?? json.servers ?? {};\n for (const [name, cfg] of Object.entries(servers)) {\n if (seen.has(name)) continue;\n seen.add(name);\n const transport = inferTransport(cfg?.transport);\n out.push({ name, transport, source });\n }\n}\n\nfunction inferTransport(value: string | undefined): DetectedMcpServer['transport'] {\n if (value === 'stdio' || value === 'http' || value === 'sse') return value;\n return undefined;\n}\n\nfunction scanBrowserExtensions(platform: ReconPlatform): DetectedBrowserExtension[] {\n const out: DetectedBrowserExtension[] = [];\n const candidates: Array<{ browser: DetectedBrowserExtension['browser']; root: string }> = [];\n if (platform === 'win32' && process.env.LOCALAPPDATA) {\n candidates.push({ browser: 'chrome', root: join(process.env.LOCALAPPDATA, 'Google', 'Chrome', 'User Data', 'Default', 'Extensions') });\n candidates.push({ browser: 'edge', root: join(process.env.LOCALAPPDATA, 'Microsoft', 'Edge', 'User Data', 'Default', 'Extensions') });\n } else if (platform === 'darwin') {\n candidates.push({ browser: 'chrome', root: join(homedir(), 'Library', 'Application Support', 'Google', 'Chrome', 'Default', 'Extensions') });\n } else {\n candidates.push({ browser: 'chrome', root: join(homedir(), '.config', 'google-chrome', 'Default', 'Extensions') });\n }\n for (const { browser, root } of candidates) {\n if (!existsSync(root)) continue;\n let extIds: string[];\n try {\n extIds = readdirSync(root);\n } catch {\n continue;\n }\n for (const id of extIds.slice(0, 40)) {\n // Each extension directory contains version subdirectories.\n let versions: string[] = [];\n try {\n versions = readdirSync(join(root, id));\n } catch {\n continue;\n }\n const latest = versions.sort().pop();\n if (!latest) continue;\n let name: string | undefined;\n try {\n const manifest = JSON.parse(readFileSync(join(root, id, latest, 'manifest.json'), 'utf8')) as { name?: string };\n if (typeof manifest.name === 'string') name = manifest.name;\n } catch {\n // ignore\n }\n out.push({ browser, id, name, version: latest });\n }\n }\n return out;\n}\n\nfunction detectChromeExtensionPresence(platform: ReconPlatform): boolean {\n // Heuristic only: check for an Anthropic / Claude extension dir in\n // chrome User Data. We don't enumerate auth cookies (privacy + complexity).\n let chromeRoot = '';\n if (platform === 'win32' && process.env.LOCALAPPDATA) {\n chromeRoot = join(process.env.LOCALAPPDATA, 'Google', 'Chrome', 'User Data', 'Default', 'Extensions');\n } else if (platform === 'darwin') {\n chromeRoot = join(homedir(), 'Library', 'Application Support', 'Google', 'Chrome', 'Default', 'Extensions');\n } else {\n chromeRoot = join(homedir(), '.config', 'google-chrome', 'Default', 'Extensions');\n }\n if (!existsSync(chromeRoot)) return false;\n let extIds: string[];\n try {\n extIds = readdirSync(chromeRoot);\n } catch {\n return false;\n }\n for (const id of extIds) {\n let versions: string[] = [];\n try {\n versions = readdirSync(join(chromeRoot, id));\n } catch {\n continue;\n }\n for (const v of versions) {\n try {\n const body = readFileSync(join(chromeRoot, id, v, 'manifest.json'), 'utf8');\n if (/claude/i.test(body) || /anthropic/i.test(body)) return true;\n } catch {\n // ignore\n }\n }\n }\n return false;\n}\n\nfunction scanExistingSkills(projectRoot: string): DetectedExistingSkill[] {\n const out: DetectedExistingSkill[] = [];\n const sources: Array<{ root: string; scope: DetectedExistingSkill['scope'] }> = [\n { root: join(projectRoot, '.claude', 'skills'), scope: 'project' },\n { root: join(homedir(), '.claude', 'skills'), scope: 'user' },\n ];\n for (const { root, scope } of sources) {\n if (!existsSync(root)) continue;\n let entries: string[] = [];\n try {\n entries = readdirSync(root);\n } catch {\n continue;\n }\n for (const e of entries) {\n const skillMd = join(root, e, 'SKILL.md');\n if (existsSync(skillMd)) {\n out.push({ name: e, scope, dir: join(root, e) });\n }\n }\n }\n // Walk one level of plugin scopes\n const pluginsRoot = join(homedir(), '.claude', 'plugins');\n if (existsSync(pluginsRoot)) {\n let plugins: string[] = [];\n try {\n plugins = readdirSync(pluginsRoot);\n } catch {\n plugins = [];\n }\n for (const p of plugins) {\n const inner = join(pluginsRoot, p, 'skills');\n if (!existsSync(inner)) continue;\n let names: string[] = [];\n try {\n names = readdirSync(inner);\n } catch {\n continue;\n }\n for (const n of names) {\n if (existsSync(join(inner, n, 'SKILL.md'))) {\n out.push({ name: n, scope: 'plugin', dir: join(inner, n) });\n }\n }\n }\n }\n return out;\n}\n\n// ---------- low-level helpers ----------\n\nfunction findOnPath(tool: string, env: NodeJS.ProcessEnv): string | null {\n const PATH = env.PATH ?? env.Path ?? '';\n const PATHEXT = (env.PATHEXT ?? (process.platform === 'win32' ? '.COM;.EXE;.BAT;.CMD;.PS1' : '')).split(';').filter(Boolean);\n const dirs = PATH.split(delimiter).filter(Boolean);\n for (const dir of dirs) {\n if (process.platform === 'win32') {\n for (const ext of PATHEXT) {\n const candidate = join(dir, tool + ext);\n if (existsSync(candidate)) return candidate;\n }\n const noExt = join(dir, tool);\n if (existsSync(noExt)) return noExt;\n } else {\n const candidate = join(dir, tool);\n if (existsSync(candidate)) {\n try {\n if (statSync(candidate).isFile()) return candidate;\n } catch {\n // ignore\n }\n }\n }\n }\n return null;\n}\n\nfunction tryVersion(toolPath: string): string | undefined {\n try {\n const out: string = (execFileSync(toolPath, ['--version'], {\n timeout: 750,\n stdio: ['ignore', 'pipe', 'ignore'],\n encoding: 'utf8',\n }) as unknown) as string;\n const m = out.match(/(\\d+\\.\\d+(?:\\.\\d+)?(?:[-+][\\w.]+)?)/);\n return m?.[1];\n } catch (err) {\n // Some tools surface --version via stderr — try harder for the common\n // case of CLI tools that print to stderr (rare).\n const e = err as SpawnSyncReturns<Buffer> | undefined;\n if (e?.stdout) {\n const txt = e.stdout.toString('utf8');\n const m = txt.match(/(\\d+\\.\\d+(?:\\.\\d+)?)/);\n if (m) return m[1];\n }\n return undefined;\n }\n}\n","/**\n * Minimal web-reachability probe used by `aab doctor` to flag when the\n * Skill Planner's web-research phase (§6.4) is likely to be degraded.\n *\n * Pure HEAD against `https://www.anthropic.com/` with a short timeout —\n * no API key, no Claude call. Returns latency + a reason on failure so\n * the operator can see whether they're offline, behind a proxy, or DNS\n * is broken.\n */\nimport { request } from 'node:https';\n\nexport interface WebProbeResult {\n reachable: boolean;\n host: string;\n latencyMs: number;\n reason?: string;\n}\n\nexport async function probeWebReachability(\n opts: { host?: string; timeoutMs?: number } = {},\n): Promise<WebProbeResult> {\n const host = opts.host ?? 'www.anthropic.com';\n const timeoutMs = opts.timeoutMs ?? 1500;\n const start = Date.now();\n return new Promise<WebProbeResult>((resolve) => {\n let settled = false;\n const settleOnce = (r: WebProbeResult) => {\n if (settled) return;\n settled = true;\n resolve(r);\n };\n const req = request(\n { host, method: 'HEAD', path: '/', timeout: timeoutMs },\n (res) => {\n const status = res.statusCode ?? 0;\n res.resume();\n settleOnce({\n reachable: status >= 200 && status < 500,\n host,\n latencyMs: Date.now() - start,\n reason: status >= 500 ? `HTTP ${status}` : undefined,\n });\n },\n );\n req.on('timeout', () => {\n req.destroy();\n settleOnce({ reachable: false, host, latencyMs: Date.now() - start, reason: 'timeout' });\n });\n req.on('error', (err) => {\n settleOnce({\n reachable: false,\n host,\n latencyMs: Date.now() - start,\n reason: err.message.split('\\n')[0]!.slice(0, 80),\n });\n });\n req.end();\n });\n}\n","/**\r\n * `aab workspace list|new|switch|delete`\r\n *\r\n * Lightweight workspace management. The active workspace pointer lives at\r\n * ~/.aabcli/.active. Project-mounted workspaces (./.aabcli) are auto-detected\r\n * by the path resolver and don't need switching.\r\n */\r\nimport { Command } from 'commander';\r\nimport { existsSync, mkdirSync, renameSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport { c, brand } from '../ui/colors.js';\r\nimport { UserError } from '../core/errors.js';\r\nimport {\r\n getActiveWorkspaceId,\r\n homeRoot,\r\n listHomeWorkspaces,\r\n setActiveWorkspaceId,\r\n slugifyWorkspaceId,\r\n} from '../storage/paths.js';\r\nimport { askConfirm } from '../ui/prompts.js';\r\n\r\nexport function registerWorkspaceCommand(program: Command): void {\r\n const ws = program.command('workspace').description('manage workspaces under ~/.aabcli/');\r\n\r\n ws.command('list')\r\n .description('list home workspaces and show which one is active')\r\n .action(async () => {\r\n const all = listHomeWorkspaces();\r\n const active = getActiveWorkspaceId();\r\n const root = homeRoot();\r\n if (program.opts<{ json?: boolean }>().json) {\r\n process.stdout.write(JSON.stringify({ active, root, workspaces: all }, null, 2) + '\\n');\r\n return;\r\n }\r\n process.stdout.write(`\\n${brand()} ${c.hint('— workspaces under ' + root)}\\n\\n`);\r\n if (all.length === 0) {\r\n process.stdout.write(c.hint(' (none yet — run `aab init` to create one)\\n\\n'));\r\n return;\r\n }\r\n for (const id of all) {\r\n const marker = id === active ? c.ok('●') : ' ';\r\n process.stdout.write(` ${marker} ${id === active ? c.bold(id) : id}\\n`);\r\n }\r\n process.stdout.write('\\n');\r\n });\r\n\r\n ws.command('new <id>')\r\n .description('create a new empty workspace at ~/.aabcli/<id>/ and switch to it')\r\n .action(async (rawId: string) => {\r\n const id = slugifyWorkspaceId(rawId);\r\n const root = join(homeRoot(), id);\r\n if (existsSync(root)) {\r\n throw new UserError(`Workspace \"${id}\" already exists at ${root}`);\r\n }\r\n mkdirSync(root, { recursive: true });\r\n setActiveWorkspaceId(id);\r\n process.stdout.write(`${c.ok('✓')} Created workspace ${c.bold(id)} (${root}).\\n`);\r\n process.stdout.write(c.hint(' Run `aab init` inside it to seed starter members and principles.\\n'));\r\n });\r\n\r\n ws.command('switch <id>')\r\n .description('set the active workspace pointer')\r\n .action(async (rawId: string) => {\r\n const id = slugifyWorkspaceId(rawId);\r\n const root = join(homeRoot(), id);\r\n if (!existsSync(root)) {\r\n throw new UserError(\r\n `No workspace at ${root}`,\r\n 'Run `aab workspace new ' + id + '` to create it.',\r\n );\r\n }\r\n setActiveWorkspaceId(id);\r\n process.stdout.write(`${c.ok('✓')} Active workspace: ${c.bold(id)}.\\n`);\r\n });\r\n\r\n ws.command('delete <id>')\r\n .description('move a workspace to ~/.aabcli/.trash/ (recoverable)')\r\n .option('--yes', 'skip confirmation')\r\n .action(async (rawId: string, opts: { yes?: boolean }) => {\r\n const id = slugifyWorkspaceId(rawId);\r\n const root = join(homeRoot(), id);\r\n if (!existsSync(root)) throw new UserError(`No workspace at ${root}`);\r\n if (!opts.yes) {\r\n const ok = await askConfirm(`Delete workspace \"${id}\"? It will be moved to .trash/.`, false);\r\n if (!ok) {\r\n process.stdout.write(c.hint('Aborted.\\n'));\r\n return;\r\n }\r\n }\r\n const trashDir = join(homeRoot(), '.trash');\r\n if (!existsSync(trashDir)) mkdirSync(trashDir, { recursive: true });\r\n const trashPath = join(trashDir, `${id}-${Date.now()}`);\r\n renameSync(root, trashPath);\r\n // If we just deleted the active one, clear the pointer\r\n if (getActiveWorkspaceId() === id) {\r\n setActiveWorkspaceId('');\r\n }\r\n process.stdout.write(`${c.ok('✓')} Workspace ${c.bold(id)} moved to ${trashPath}.\\n`);\r\n });\r\n}\r\n","/**\r\n * `aab discuss start | continue | respond | follow-up | list | show | delete |\r\n * archive | unarchive | summarize | export | spar | inject`\r\n *\r\n * Phase 1 surface: kick off a discussion, drive multi-round conversations,\r\n * answer the orchestrator's HITL questions, ask targeted follow-ups, list /\r\n * show / delete / archive saved discussions, summarize a concluded discussion,\r\n * and export it to markdown. Phase 3 adds `spar` (1:1 deep-dive) and `inject`\r\n * (write a sparring insight back to the main timeline).\r\n */\r\nimport { Command } from 'commander';\r\nimport { existsSync, writeFileSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\nimport { closeContext, openContext } from './_context.js';\r\nimport { c } from '../ui/colors.js';\r\nimport { spinner } from '../ui/spinner.js';\r\nimport { askConfirm, askText } from '../ui/prompts.js';\r\nimport { renderDiscussion, shortId } from '../ui/render-discussion.js';\r\nimport { renderDiscussionMarkdown, defaultExportFilename } from '../ui/render-discussion-markdown.js';\r\nimport { UserError } from '../core/errors.js';\r\nimport { formatDuration, formatUsd } from '../core/utils.js';\r\nimport {\r\n addFollowUpQuestion,\r\n continueDiscussion,\r\n respondToUserRequest,\r\n startDiscussion,\r\n type FollowUpTargetType,\r\n type StartProgressEvent,\r\n} from '../core/discussion/conversation-flow.js';\r\nimport { summarizeDiscussion } from '../core/discussion/summarize.js';\r\nimport {\r\n openSparringSession,\r\n sendSparringMessage,\r\n} from '../core/sparring/sparring-service.js';\r\nimport { injectSparringInsight } from '../core/sparring/inject-insight.js';\r\nimport { memberAgentPath, memberAgentSlug } from '../agents/emit-member-agent.js';\r\nimport type {\r\n AdvisoryBoardMember,\r\n ConversationSummary,\r\n Discussion,\r\n SparringSession,\r\n StorageService,\r\n} from '../storage/types.js';\r\n\r\nexport function registerDiscussCommand(program: Command): void {\r\n const discuss = program.command('discuss').description('start, view, and manage advisory-board discussions');\r\n\r\n registerStart(discuss);\r\n registerContinue(discuss);\r\n registerRespond(discuss);\r\n registerFollowUp(discuss);\r\n registerList(discuss);\r\n registerShow(discuss);\r\n registerDelete(discuss);\r\n registerArchive(discuss);\r\n registerUnarchive(discuss);\r\n registerSummarize(discuss);\r\n registerExport(discuss);\r\n registerSpar(discuss);\r\n registerInject(discuss);\r\n}\r\n\r\nfunction registerStart(parent: Command): void {\r\n parent\r\n .command('start <question>')\r\n .description('start a new advisory-board discussion (round 1)')\r\n .option('--members <names>', 'comma-separated subset of member names (default: all active)')\r\n .option('--max-turns <n>', 'override settings.maxTurnsPerDiscussion for this run', (v) => Number(v))\r\n .option('--agents-dir <path>', 'where .claude/agents/ lives (default: cwd)')\r\n .action(async (question: string, opts: { members?: string; maxTurns?: number; agentsDir?: string }) => {\r\n const ctx = await openContext(parent);\r\n try {\r\n const settings = await ctx.storage.loadSettings();\r\n if (opts.maxTurns) settings.maxTurnsPerDiscussion = opts.maxTurns;\r\n\r\n const allMembers = await ctx.storage.loadBoardMembers();\r\n const members = pickMembers(allMembers, opts.members);\r\n if (members.length === 0) {\r\n throw new UserError(\r\n opts.members\r\n ? `No active members matched: ${opts.members}`\r\n : 'No active board members. Run `aab init` to seed starters.',\r\n );\r\n }\r\n\r\n const projectRoot = opts.agentsDir ?? process.cwd();\r\n verifyAgentFiles(members, projectRoot);\r\n\r\n if (!ctx.json) {\r\n process.stdout.write(`\\n${c.brand('AI Advisory Board')} ${c.hint('· starting discussion')}\\n`);\r\n process.stdout.write(c.hint(` question: ${question}\\n`));\r\n process.stdout.write(c.hint(` members: ${members.map((m) => m.name).join(', ')}\\n\\n`));\r\n }\r\n\r\n const sp = spinner('initializing...');\r\n sp.start();\r\n const result = await startDiscussion({\r\n question,\r\n members,\r\n settings,\r\n storage: ctx.storage,\r\n projectRoot,\r\n onProgress: progressHandler(sp),\r\n });\r\n sp.succeed(`Discussion ${shortId(result.discussion.id)} ready in ${formatDuration(result.totalDurationMs)} (${formatUsd(result.totalCostUsd)}).`);\r\n\r\n if (ctx.json) {\r\n process.stdout.write(JSON.stringify({ discussion: result.discussion, totalCostUsd: result.totalCostUsd }, null, 2) + '\\n');\r\n } else {\r\n process.stdout.write(renderDiscussion(result.discussion));\r\n process.stdout.write('\\n');\r\n }\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n });\r\n}\r\n\r\nfunction registerContinue(parent: Command): void {\r\n parent\r\n .command('continue <idOrShort>')\r\n .description('drive the next round of an open discussion (orchestrator-gated)')\r\n .option('--agents-dir <path>', 'where .claude/agents/ lives (default: cwd)')\r\n .action(async (idOrShort: string, opts: { agentsDir?: string }) => {\r\n const ctx = await openContext(parent);\r\n try {\r\n const discussion = await resolveDiscussion(ctx.storage, idOrShort);\r\n const settings = await ctx.storage.loadSettings();\r\n const allMembers = await ctx.storage.loadBoardMembers();\r\n\r\n // Restrict to the originally-selected members so a continue doesn't\r\n // suddenly add a new face the discussion never had.\r\n const selectedIds = new Set(discussion.selectedMemberIds ?? allMembers.map((m) => m.id));\r\n const members = allMembers.filter((m) => selectedIds.has(m.id) && m.isActive);\r\n if (members.length === 0) {\r\n throw new UserError(\r\n 'No active members from this discussion remain.',\r\n 'Re-activate one with `aab members activate <name>` (coming in Phase 2) or start a new discussion.',\r\n );\r\n }\r\n\r\n const projectRoot = opts.agentsDir ?? process.cwd();\r\n verifyAgentFiles(members, projectRoot);\r\n\r\n if (!ctx.json) {\r\n process.stdout.write(`\\n${c.brand('AI Advisory Board')} ${c.hint('· continuing discussion ' + shortId(discussion.id))}\\n`);\r\n process.stdout.write(c.hint(` question: ${discussion.question}\\n`));\r\n process.stdout.write(c.hint(` members: ${members.map((m) => m.name).join(', ')}\\n`));\r\n process.stdout.write(c.hint(` rounds: ${discussion.rounds.length} so far · ${discussion.totalTurns}/${discussion.maxTurns} turns\\n\\n`));\r\n }\r\n\r\n const sp = spinner('orchestrator deciding...');\r\n sp.start();\r\n const result = await continueDiscussion({\r\n discussion,\r\n members,\r\n settings,\r\n storage: ctx.storage,\r\n projectRoot,\r\n onProgress: progressHandler(sp),\r\n });\r\n\r\n if (result.gated) {\r\n sp.warn('Orchestrator wants more input from you before continuing.');\r\n if (ctx.json) {\r\n process.stdout.write(JSON.stringify({ discussion: result.discussion, gated: true }, null, 2) + '\\n');\r\n } else {\r\n process.stdout.write(renderDiscussion(result.discussion));\r\n process.stdout.write(\r\n `\\n${c.warn('→')} reply with: ${c.bold(`aab discuss respond ${shortId(result.discussion.id)} \"<your answer>\"`)}\\n`,\r\n );\r\n }\r\n return;\r\n }\r\n\r\n if (result.roundNumber == null) {\r\n sp.info('Discussion already at maxTurns — concluded.');\r\n } else {\r\n sp.succeed(\r\n `Round ${result.roundNumber} done in ${formatDuration(result.totalDurationMs)} (${formatUsd(result.totalCostUsd)})${result.concluded ? c.ok(' · concluded') : ''}.`,\r\n );\r\n }\r\n\r\n if (ctx.json) {\r\n process.stdout.write(\r\n JSON.stringify({ discussion: result.discussion, totalCostUsd: result.totalCostUsd, roundNumber: result.roundNumber, concluded: result.concluded }, null, 2) + '\\n',\r\n );\r\n } else {\r\n process.stdout.write(renderDiscussion(result.discussion, { round: result.roundNumber ?? undefined }));\r\n process.stdout.write('\\n');\r\n }\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n });\r\n}\r\n\r\nfunction registerRespond(parent: Command): void {\r\n parent\r\n .command('respond <idOrShort> <answer>')\r\n .description(\"answer the orchestrator's pending question and drive the next round\")\r\n .option('--option <i>', '1-based index of one of the listed options', (v) => Number(v))\r\n .option('--agents-dir <path>', 'where .claude/agents/ lives (default: cwd)')\r\n .action(\r\n async (idOrShort: string, answer: string, opts: { option?: number; agentsDir?: string }) => {\r\n const ctx = await openContext(parent);\r\n try {\r\n const discussion = await resolveDiscussion(ctx.storage, idOrShort);\r\n if (!discussion.pendingUserRequest) {\r\n throw new UserError(\r\n 'This discussion is not awaiting your input.',\r\n 'Use `aab discuss continue <id>` to drive the next round.',\r\n );\r\n }\r\n\r\n let selectedOption: string | undefined;\r\n if (opts.option != null) {\r\n const options = discussion.pendingUserRequest.options ?? [];\r\n if (!Number.isFinite(opts.option) || opts.option < 1 || opts.option > options.length) {\r\n throw new UserError(\r\n `--option must be between 1 and ${options.length || 0}.`,\r\n 'Run `aab discuss show <id>` to see the listed options.',\r\n );\r\n }\r\n selectedOption = options[opts.option - 1];\r\n }\r\n\r\n const settings = await ctx.storage.loadSettings();\r\n const allMembers = await ctx.storage.loadBoardMembers();\r\n const selectedIds = new Set(discussion.selectedMemberIds ?? allMembers.map((m) => m.id));\r\n const members = allMembers.filter((m) => selectedIds.has(m.id) && m.isActive);\r\n if (members.length === 0) {\r\n throw new UserError('No active members from this discussion remain.');\r\n }\r\n\r\n const projectRoot = opts.agentsDir ?? process.cwd();\r\n verifyAgentFiles(members, projectRoot);\r\n\r\n if (!ctx.json) {\r\n process.stdout.write(`\\n${c.brand('AI Advisory Board')} ${c.hint('· replying to discussion ' + shortId(discussion.id))}\\n`);\r\n process.stdout.write(c.hint(` request: ${discussion.pendingUserRequest.question}\\n`));\r\n if (selectedOption) process.stdout.write(c.hint(` option: ${selectedOption}\\n`));\r\n process.stdout.write(c.hint(` answer: ${answer}\\n\\n`));\r\n }\r\n\r\n const sp = spinner('saving your reply...');\r\n sp.start();\r\n const result = await respondToUserRequest({\r\n discussion,\r\n content: answer,\r\n selectedOption,\r\n members,\r\n settings,\r\n storage: ctx.storage,\r\n projectRoot,\r\n onProgress: progressHandler(sp),\r\n });\r\n\r\n if (result.roundNumber == null) {\r\n sp.info('Reply saved — discussion already at maxTurns.');\r\n } else {\r\n sp.succeed(\r\n `Round ${result.roundNumber} done in ${formatDuration(result.totalDurationMs)} (${formatUsd(result.totalCostUsd)})${result.concluded ? c.ok(' · concluded') : ''}.`,\r\n );\r\n }\r\n\r\n if (ctx.json) {\r\n process.stdout.write(\r\n JSON.stringify({ discussion: result.discussion, totalCostUsd: result.totalCostUsd, roundNumber: result.roundNumber, concluded: result.concluded }, null, 2) + '\\n',\r\n );\r\n } else {\r\n process.stdout.write(renderDiscussion(result.discussion, { round: result.roundNumber ?? undefined }));\r\n process.stdout.write('\\n');\r\n }\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n },\r\n );\r\n}\r\n\r\nfunction registerFollowUp(parent: Command): void {\r\n parent\r\n .command('follow-up <idOrShort> <question>')\r\n .description('ask a follow-up question (default: all members; --member or --members for targeted)')\r\n .option('--all', 'every active member from this discussion responds (default)')\r\n .option('--member <name>', 'exactly one member responds (name, slug, or id)')\r\n .option('--members <names>', 'comma-separated subset of member names, slugs, or ids')\r\n .option('--agents-dir <path>', 'where .claude/agents/ lives (default: cwd)')\r\n .action(\r\n async (\r\n idOrShort: string,\r\n question: string,\r\n opts: { all?: boolean; member?: string; members?: string; agentsDir?: string },\r\n ) => {\r\n const flagCount = [opts.all, opts.member, opts.members].filter(Boolean).length;\r\n if (flagCount > 1) {\r\n throw new UserError(\r\n '--all, --member, and --members are mutually exclusive.',\r\n 'Pick one to control who answers.',\r\n );\r\n }\r\n\r\n const ctx = await openContext(parent);\r\n try {\r\n const discussion = await resolveDiscussion(ctx.storage, idOrShort);\r\n const settings = await ctx.storage.loadSettings();\r\n const allMembers = await ctx.storage.loadBoardMembers();\r\n\r\n const selectedIds = new Set(discussion.selectedMemberIds ?? allMembers.map((m) => m.id));\r\n const candidatePool = allMembers.filter((m) => selectedIds.has(m.id) && m.isActive);\r\n if (candidatePool.length === 0) {\r\n throw new UserError(\"No active members from this discussion's original board remain.\");\r\n }\r\n\r\n let targetType: FollowUpTargetType = 'all';\r\n let selectedMemberId: string | undefined;\r\n let selectedMemberIdList: string[] | undefined;\r\n\r\n if (opts.member) {\r\n const match = resolveMemberToken(candidatePool, opts.member);\r\n if (!match) {\r\n throw new UserError(\r\n `No member matched \"${opts.member}\" in this discussion.`,\r\n `Active members: ${candidatePool.map((m) => m.name).join(', ')}`,\r\n );\r\n }\r\n targetType = 'specific';\r\n selectedMemberId = match.id;\r\n } else if (opts.members) {\r\n const tokens = opts.members.split(',').map((t) => t.trim()).filter(Boolean);\r\n const matched: AdvisoryBoardMember[] = [];\r\n const unmatched: string[] = [];\r\n for (const tok of tokens) {\r\n const m = resolveMemberToken(candidatePool, tok);\r\n if (m) {\r\n if (!matched.some((x) => x.id === m.id)) matched.push(m);\r\n } else unmatched.push(tok);\r\n }\r\n if (unmatched.length > 0) {\r\n throw new UserError(\r\n `No member matched: ${unmatched.join(', ')}`,\r\n `Active members: ${candidatePool.map((m) => m.name).join(', ')}`,\r\n );\r\n }\r\n if (matched.length < 2) {\r\n throw new UserError('--members needs at least two distinct members. Use --member for one, or --all for everybody.');\r\n }\r\n targetType = 'subset';\r\n selectedMemberIdList = matched.map((m) => m.id);\r\n }\r\n\r\n // The members the engine sees as \"active candidates\" — equals the\r\n // pool. The engine narrows to targets via targetType.\r\n const projectRoot = opts.agentsDir ?? process.cwd();\r\n // Verify only the agent files for the targets we'll actually spawn.\r\n const willSpawn =\r\n targetType === 'all'\r\n ? candidatePool\r\n : targetType === 'specific'\r\n ? candidatePool.filter((m) => m.id === selectedMemberId)\r\n : candidatePool.filter((m) => selectedMemberIdList!.includes(m.id));\r\n verifyAgentFiles(willSpawn, projectRoot);\r\n\r\n if (!ctx.json) {\r\n const targetLabel =\r\n targetType === 'all'\r\n ? `all (${candidatePool.length})`\r\n : targetType === 'specific'\r\n ? willSpawn[0]!.name\r\n : willSpawn.map((m) => m.name).join(', ');\r\n process.stdout.write(`\\n${c.brand('AI Advisory Board')} ${c.hint('· follow-up to ' + shortId(discussion.id))}\\n`);\r\n process.stdout.write(c.hint(` question: ${question}\\n`));\r\n process.stdout.write(c.hint(` target: ${targetLabel}\\n`));\r\n process.stdout.write(c.hint(` rounds: ${discussion.rounds.length} so far · ${discussion.totalTurns}/${discussion.maxTurns} turns\\n\\n`));\r\n }\r\n\r\n const sp = spinner('orchestrator deciding...');\r\n sp.start();\r\n const result = await addFollowUpQuestion({\r\n discussion,\r\n question,\r\n members: candidatePool,\r\n settings,\r\n storage: ctx.storage,\r\n projectRoot,\r\n targetType,\r\n selectedMemberId,\r\n selectedMemberIds: selectedMemberIdList,\r\n onProgress: progressHandler(sp),\r\n });\r\n\r\n if (result.gated) {\r\n sp.warn('Orchestrator wants more input from you before the follow-up.');\r\n if (ctx.json) {\r\n process.stdout.write(JSON.stringify({ discussion: result.discussion, gated: true }, null, 2) + '\\n');\r\n } else {\r\n process.stdout.write(renderDiscussion(result.discussion));\r\n process.stdout.write(\r\n `\\n${c.warn('→')} reply with: ${c.bold(`aab discuss respond ${shortId(result.discussion.id)} \"<your answer>\"`)}\\n`,\r\n );\r\n }\r\n return;\r\n }\r\n\r\n if (result.roundNumber == null) {\r\n sp.info('Discussion already at maxTurns — concluded.');\r\n } else {\r\n sp.succeed(\r\n `Follow-up round ${result.roundNumber} done in ${formatDuration(result.totalDurationMs)} (${formatUsd(result.totalCostUsd)})${result.concluded ? c.ok(' · concluded') : ''}.`,\r\n );\r\n }\r\n\r\n if (ctx.json) {\r\n process.stdout.write(\r\n JSON.stringify(\r\n {\r\n discussion: result.discussion,\r\n totalCostUsd: result.totalCostUsd,\r\n roundNumber: result.roundNumber,\r\n concluded: result.concluded,\r\n },\r\n null,\r\n 2,\r\n ) + '\\n',\r\n );\r\n } else {\r\n process.stdout.write(renderDiscussion(result.discussion, { round: result.roundNumber ?? undefined }));\r\n process.stdout.write('\\n');\r\n }\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n },\r\n );\r\n}\r\n\r\nfunction registerList(parent: Command): void {\r\n parent\r\n .command('list')\r\n .description('list saved discussions')\r\n .option('--limit <n>', 'page size', (v) => Number(v), 20)\r\n .option('--offset <n>', 'page offset', (v) => Number(v), 0)\r\n .option('--archived', 'include archived discussions')\r\n .action(async (opts: { limit: number; offset: number; archived?: boolean }) => {\r\n const ctx = await openContext(parent, { lock: false });\r\n try {\r\n const page = await ctx.storage.loadDiscussionPage({\r\n limit: opts.limit,\r\n offset: opts.offset,\r\n includeArchived: opts.archived,\r\n });\r\n if (ctx.json) {\r\n process.stdout.write(JSON.stringify(page, null, 2) + '\\n');\r\n return;\r\n }\r\n if (page.discussions.length === 0) {\r\n process.stdout.write(c.hint(' (no discussions yet — run `aab discuss start \"<question>\"`)\\n'));\r\n return;\r\n }\r\n process.stdout.write(`\\n${c.brand('AI Advisory Board')} ${c.hint('· ' + page.totalCount + ' discussion(s)')}\\n\\n`);\r\n for (const d of page.discussions) {\r\n process.stdout.write(renderListRow(d) + '\\n');\r\n }\r\n if (page.hasMore) {\r\n process.stdout.write(c.hint(`\\n more: aab discuss list --offset ${opts.offset + opts.limit}\\n`));\r\n }\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n });\r\n}\r\n\r\nfunction registerShow(parent: Command): void {\r\n parent\r\n .command('show <idOrShort>')\r\n .description('pretty-print one discussion')\r\n .option('--round <n>', 'show only one round', (v) => Number(v))\r\n .action(async (idOrShort: string, opts: { round?: number }) => {\r\n const ctx = await openContext(parent, { lock: false });\r\n try {\r\n const discussion = await resolveDiscussion(ctx.storage, idOrShort);\r\n if (ctx.json) {\r\n process.stdout.write(JSON.stringify(discussion, null, 2) + '\\n');\r\n } else {\r\n process.stdout.write(renderDiscussion(discussion, { round: opts.round }));\r\n process.stdout.write('\\n');\r\n }\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n });\r\n}\r\n\r\nfunction registerDelete(parent: Command): void {\r\n parent\r\n .command('delete <idOrShort>')\r\n .description('delete a discussion permanently')\r\n .option('--yes', 'skip confirmation')\r\n .action(async (idOrShort: string, _opts: { yes?: boolean }) => {\r\n const ctx = await openContext(parent);\r\n try {\r\n const discussion = await resolveDiscussion(ctx.storage, idOrShort);\r\n await ctx.storage.deleteDiscussion(discussion.id);\r\n process.stdout.write(`${c.ok('✓')} discussion ${shortId(discussion.id)} deleted.\\n`);\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n });\r\n}\r\n\r\nfunction registerArchive(parent: Command): void {\r\n parent\r\n .command('archive <idOrShort>')\r\n .description('archive a discussion (hidden from `list` unless --archived)')\r\n .action(async (idOrShort: string) => {\r\n const ctx = await openContext(parent);\r\n try {\r\n const discussion = await resolveDiscussion(ctx.storage, idOrShort);\r\n if (discussion.archivedAt) {\r\n process.stdout.write(`${c.hint('—')} discussion ${shortId(discussion.id)} is already archived.\\n`);\r\n return;\r\n }\r\n await ctx.storage.archiveDiscussion(discussion.id);\r\n if (ctx.json) {\r\n process.stdout.write(JSON.stringify({ id: discussion.id, archived: true }, null, 2) + '\\n');\r\n } else {\r\n process.stdout.write(`${c.ok('✓')} discussion ${shortId(discussion.id)} archived.\\n`);\r\n }\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n });\r\n}\r\n\r\nfunction registerUnarchive(parent: Command): void {\r\n parent\r\n .command('unarchive <idOrShort>')\r\n .description('restore an archived discussion to the active list')\r\n .action(async (idOrShort: string) => {\r\n const ctx = await openContext(parent);\r\n try {\r\n const discussion = await resolveDiscussion(ctx.storage, idOrShort);\r\n if (!discussion.archivedAt) {\r\n process.stdout.write(`${c.hint('—')} discussion ${shortId(discussion.id)} is not archived.\\n`);\r\n return;\r\n }\r\n await ctx.storage.unarchiveDiscussion(discussion.id);\r\n if (ctx.json) {\r\n process.stdout.write(JSON.stringify({ id: discussion.id, archived: false }, null, 2) + '\\n');\r\n } else {\r\n process.stdout.write(`${c.ok('✓')} discussion ${shortId(discussion.id)} unarchived.\\n`);\r\n }\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n });\r\n}\r\n\r\nfunction registerSummarize(parent: Command): void {\r\n parent\r\n .command('summarize <idOrShort>')\r\n .description('generate or refresh the ConversationSummary for a discussion')\r\n .option('--force', 'regenerate even if a summary already exists')\r\n .action(async (idOrShort: string, opts: { force?: boolean }) => {\r\n const ctx = await openContext(parent);\r\n try {\r\n const discussion = await resolveDiscussion(ctx.storage, idOrShort);\r\n if (discussion.rounds.length === 0) {\r\n throw new UserError(\r\n 'Cannot summarize: discussion has no rounds yet.',\r\n 'Run `aab discuss continue` first.',\r\n );\r\n }\r\n if (discussion.summary && !opts.force) {\r\n if (ctx.json) {\r\n process.stdout.write(JSON.stringify({ summary: discussion.summary, regenerated: false }, null, 2) + '\\n');\r\n } else {\r\n process.stdout.write(`${c.hint('—')} summary already exists. Re-run with --force to regenerate.\\n\\n`);\r\n renderSummary(discussion.summary);\r\n }\r\n return;\r\n }\r\n\r\n const settings = await ctx.storage.loadSettings();\r\n const allMembers = await ctx.storage.loadBoardMembers();\r\n const memberMap = new Map(allMembers.map((m) => [m.id, m]));\r\n const memberIds =\r\n discussion.selectedMemberIds ?? Array.from(new Set(discussion.responses.map((r) => r.memberId)));\r\n const members = memberIds\r\n .map((id) => memberMap.get(id))\r\n .filter((m): m is AdvisoryBoardMember => !!m);\r\n\r\n const sp = spinner('summarizing discussion...');\r\n sp.start();\r\n const summary = await summarizeDiscussion({\r\n discussion,\r\n members,\r\n settings,\r\n });\r\n discussion.summary = summary;\r\n await ctx.storage.saveDiscussion(discussion);\r\n sp.succeed(`Summary written (${summary.keyPoints.length} key points, ${summary.consensus.length} consensus, ${summary.disagreements.length} disagreements).`);\r\n\r\n if (ctx.json) {\r\n process.stdout.write(JSON.stringify({ summary, regenerated: !!opts.force }, null, 2) + '\\n');\r\n } else {\r\n renderSummary(summary);\r\n }\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n });\r\n}\r\n\r\nfunction registerExport(parent: Command): void {\r\n parent\r\n .command('export <idOrShort>')\r\n .description('export a discussion to a markdown file')\r\n .option('--md', 'render as markdown (default and only format in v1)')\r\n .option('--out <path>', 'output file path (default: <short-id>-<slug>.md in cwd)')\r\n .option('--no-summary', 'skip auto-generating a summary if one is missing')\r\n .action(async (idOrShort: string, opts: { md?: boolean; out?: string; summary?: boolean }) => {\r\n const ctx = await openContext(parent);\r\n try {\r\n const discussion = await resolveDiscussion(ctx.storage, idOrShort);\r\n\r\n // Auto-summarize once at export time if missing — keeps the markdown\r\n // self-contained without forcing the user to run two commands.\r\n const wantsSummary = opts.summary !== false;\r\n if (wantsSummary && !discussion.summary && discussion.rounds.length > 0) {\r\n const settings = await ctx.storage.loadSettings();\r\n const allMembers = await ctx.storage.loadBoardMembers();\r\n const memberMap = new Map(allMembers.map((m) => [m.id, m]));\r\n const memberIds =\r\n discussion.selectedMemberIds ?? Array.from(new Set(discussion.responses.map((r) => r.memberId)));\r\n const members = memberIds\r\n .map((id) => memberMap.get(id))\r\n .filter((m): m is AdvisoryBoardMember => !!m);\r\n\r\n const sp = spinner('summarizing before export...');\r\n sp.start();\r\n try {\r\n discussion.summary = await summarizeDiscussion({ discussion, members, settings });\r\n await ctx.storage.saveDiscussion(discussion);\r\n sp.succeed('Summary generated.');\r\n } catch (error) {\r\n sp.warn(`Summary generation failed: ${error instanceof Error ? error.message : String(error)}`);\r\n // Export proceeds without a summary — better than failing the export.\r\n }\r\n }\r\n\r\n const md = renderDiscussionMarkdown(discussion);\r\n const outPath = opts.out ?? join(process.cwd(), defaultExportFilename(discussion));\r\n writeFileSync(outPath, md, 'utf8');\r\n\r\n if (ctx.json) {\r\n process.stdout.write(JSON.stringify({ id: discussion.id, path: outPath, bytes: Buffer.byteLength(md, 'utf8') }, null, 2) + '\\n');\r\n } else {\r\n process.stdout.write(`${c.ok('✓')} exported ${shortId(discussion.id)} → ${c.bold(outPath)}\\n`);\r\n }\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n });\r\n}\r\n\r\nfunction registerSpar(parent: Command): void {\r\n const spar = parent\r\n .command('spar <idOrShort>')\r\n .description('open a 1:1 deep-dive sparring session with a board member')\r\n .option('--member <name>', 'name, slug, or id of the member to spar with (required unless --resume)')\r\n .option('--round <n>', '1-based round number the anchor lives in', (v) => Number(v))\r\n .option('--turn <n>', '1-based turn number within that round', (v) => Number(v))\r\n .option('--message <text>', 'send one message non-interactively and exit')\r\n .option('--resume <sessionId>', 'resume an existing sparring session (id or short id)')\r\n .option('--title <text>', 'optional title for a brand-new session')\r\n .option('--agents-dir <path>', 'where .claude/agents/ lives (default: cwd)')\r\n .action(\r\n async (\r\n idOrShort: string,\r\n opts: {\r\n member?: string;\r\n round?: number;\r\n turn?: number;\r\n message?: string;\r\n resume?: string;\r\n title?: string;\r\n agentsDir?: string;\r\n },\r\n ) => {\r\n const ctx = await openContext(parent);\r\n try {\r\n const discussion = await resolveDiscussion(ctx.storage, idOrShort);\r\n const settings = await ctx.storage.loadSettings();\r\n const allMembers = await ctx.storage.loadBoardMembers();\r\n const projectRoot = opts.agentsDir ?? process.cwd();\r\n\r\n let session: SparringSession;\r\n let member: AdvisoryBoardMember | undefined;\r\n\r\n if (opts.resume) {\r\n const found = await resolveSparringSession(ctx.storage, discussion.id, opts.resume);\r\n session = found;\r\n member = allMembers.find((m) => m.id === found.memberId);\r\n } else {\r\n if (!opts.member) {\r\n throw new UserError(\r\n 'pass --member <name> to open a sparring session (or --resume <sessionId>).',\r\n `Available members: ${allMembers.filter((m) => m.isActive).map((m) => m.name).join(', ')}`,\r\n );\r\n }\r\n member = resolveMemberToken(allMembers, opts.member);\r\n if (!member) {\r\n throw new UserError(`No member matched \"${opts.member}\".`);\r\n }\r\n const opened = await openSparringSession({\r\n discussion,\r\n member,\r\n anchorRoundNumber: opts.round,\r\n anchorTurnNumber: opts.turn,\r\n title: opts.title,\r\n storage: ctx.storage,\r\n });\r\n session = opened.session;\r\n if (!ctx.json) {\r\n process.stdout.write(\r\n `\\n${c.brand('AI Advisory Board')} ${c.hint(opened.reused ? '· resumed sparring' : '· new sparring')}\\n`,\r\n );\r\n process.stdout.write(c.hint(` member: ${member.name}\\n`));\r\n process.stdout.write(c.hint(` anchor: round ${session.anchorRoundNumber} · turn ${session.anchorTurnNumber}\\n`));\r\n process.stdout.write(c.hint(` session: ${session.id.slice(0, 8)}\\n\\n`));\r\n }\r\n }\r\n\r\n if (!member) {\r\n throw new UserError(`No member with id ${session.memberId} exists anymore — cannot continue this session.`);\r\n }\r\n verifyAgentFiles([member], projectRoot);\r\n\r\n // Replay existing messages so resumed sessions feel continuous.\r\n if (!ctx.json && !opts.resume) {\r\n renderAnchor(session);\r\n }\r\n if (session.messages.length > 0 && !ctx.json) {\r\n process.stdout.write(c.hint(` (replaying ${session.messages.length} prior message${session.messages.length === 1 ? '' : 's'})\\n\\n`));\r\n for (const m of session.messages) renderSparringMessage(m.role, m.content);\r\n }\r\n\r\n // --message mode: send one shot and exit.\r\n if (opts.message) {\r\n const trimmed = opts.message.trim();\r\n if (!trimmed) throw new UserError('--message cannot be empty.');\r\n const result = await runSparringTurn({\r\n session,\r\n member,\r\n discussion,\r\n userMessage: trimmed,\r\n settings,\r\n storage: ctx.storage,\r\n projectRoot,\r\n json: ctx.json,\r\n });\r\n if (ctx.json) {\r\n process.stdout.write(JSON.stringify({ session: result.session, reply: result.assistant }, null, 2) + '\\n');\r\n }\r\n return;\r\n }\r\n\r\n // Interactive REPL.\r\n process.stdout.write(\r\n c.hint(` Type your message and press Enter. 'exit' or Ctrl+C to leave.\\n Type 'inject <insight>' to write the latest reply back to the main timeline.\\n\\n`),\r\n );\r\n let keepGoing = true;\r\n while (keepGoing) {\r\n const userInput = await askText('you', {});\r\n const trimmed = userInput.trim();\r\n if (!trimmed) continue;\r\n if (/^(exit|quit|bye)$/i.test(trimmed)) {\r\n keepGoing = false;\r\n break;\r\n }\r\n if (trimmed.toLowerCase().startsWith('inject ')) {\r\n const insight = trimmed.slice('inject '.length).trim();\r\n if (!insight) {\r\n process.stdout.write(c.warn(' ! pass the insight text after `inject`.\\n'));\r\n continue;\r\n }\r\n await runInjectInline({\r\n discussion,\r\n session,\r\n insight,\r\n storage: ctx.storage,\r\n });\r\n continue;\r\n }\r\n await runSparringTurn({\r\n session,\r\n member,\r\n discussion,\r\n userMessage: trimmed,\r\n settings,\r\n storage: ctx.storage,\r\n projectRoot,\r\n json: false,\r\n });\r\n }\r\n process.stdout.write(c.hint(`Sparring session ${session.id.slice(0, 8)} saved.\\n`));\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n },\r\n );\r\n\r\n // Subcommands of `discuss spar` — `spar list` and `spar show` — must be\r\n // attached *after* the action above; commander prefers the action variant\r\n // when the first positional arg is an id-like string but routes `spar list`\r\n // to the list subcommand because `list` is not a discussion id.\r\n spar\r\n .command('list <discussionIdOrShort>')\r\n .description('list sparring sessions attached to a discussion')\r\n .action(async (discussionIdOrShort: string) => {\r\n const ctx = await openContext(parent, { lock: false });\r\n try {\r\n const discussion = await resolveDiscussion(ctx.storage, discussionIdOrShort);\r\n const sessions = await ctx.storage.loadSparringSessionsForDiscussion(discussion.id);\r\n if (ctx.json) {\r\n process.stdout.write(JSON.stringify({ discussionId: discussion.id, sessions }, null, 2) + '\\n');\r\n return;\r\n }\r\n if (sessions.length === 0) {\r\n process.stdout.write(c.hint(` (no sparring sessions yet — run \\`aab discuss spar ${shortId(discussion.id)} --member \"<name>\"\\`)\\n`));\r\n return;\r\n }\r\n process.stdout.write(\r\n `\\n${c.brand('AI Advisory Board')} ${c.hint('· ' + sessions.length + ' sparring session(s) on ' + shortId(discussion.id))}\\n\\n`,\r\n );\r\n for (const s of sessions) {\r\n const ts = new Date(s.updatedAt).toLocaleString();\r\n process.stdout.write(\r\n ` ${c.cyan(s.id.slice(0, 8))} ${c.hint(ts)} ${c.bold(s.memberName)} ${c.hint(`(round ${s.anchorRoundNumber} · turn ${s.anchorTurnNumber} · ${s.messages.length} msg${s.messages.length === 1 ? '' : 's'})`)}\\n`,\r\n );\r\n if (s.title) process.stdout.write(` ${c.hint('title:')} ${s.title}\\n`);\r\n }\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n });\r\n\r\n spar\r\n .command('show <sessionIdOrShort>')\r\n .description('print a sparring session transcript')\r\n .action(async (sessionIdOrShort: string) => {\r\n const ctx = await openContext(parent, { lock: false });\r\n try {\r\n const session = await resolveSparringSessionAnywhere(ctx.storage, sessionIdOrShort);\r\n if (ctx.json) {\r\n process.stdout.write(JSON.stringify({ session }, null, 2) + '\\n');\r\n return;\r\n }\r\n process.stdout.write(\r\n `\\n${c.bold(session.title ?? `1:1 with ${session.memberName}`)} ${c.hint('· ' + session.id.slice(0, 8))}\\n`,\r\n );\r\n process.stdout.write(` ${c.hint('member:')} ${session.memberName}\\n`);\r\n process.stdout.write(` ${c.hint('anchor:')} round ${session.anchorRoundNumber} · turn ${session.anchorTurnNumber}\\n`);\r\n process.stdout.write(` ${c.hint('messages:')} ${session.messages.length}\\n\\n`);\r\n renderAnchor(session);\r\n for (const m of session.messages) renderSparringMessage(m.role, m.content);\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n });\r\n}\r\n\r\nfunction registerInject(parent: Command): void {\r\n parent\r\n .command('inject <discussionIdOrShort>')\r\n .description('write a sparring-deep-dive insight back into the main timeline')\r\n .option('--from <sessionIdOrShort>', 'sparring session id to source from (required)')\r\n .option('--insight <text>', 'override the insight text (default: latest assistant reply)')\r\n .option('--yes', 'skip confirmation')\r\n .action(async (discussionIdOrShort: string, opts: { from?: string; insight?: string; yes?: boolean }) => {\r\n const ctx = await openContext(parent);\r\n try {\r\n const discussion = await resolveDiscussion(ctx.storage, discussionIdOrShort);\r\n if (!opts.from) {\r\n throw new UserError(\r\n 'pass --from <sparringSessionId>.',\r\n `Run \\`aab discuss spar list ${shortId(discussion.id)}\\` to see available sessions.`,\r\n );\r\n }\r\n const session = await resolveSparringSession(ctx.storage, discussion.id, opts.from);\r\n\r\n let insight: string;\r\n if (opts.insight) {\r\n insight = opts.insight.trim();\r\n } else {\r\n const lastAssistant = [...session.messages].reverse().find((m) => m.role === 'assistant');\r\n if (!lastAssistant) {\r\n throw new UserError(\r\n 'No assistant reply in this session yet to inject.',\r\n 'Send a message first, or pass --insight \"<text>\" explicitly.',\r\n );\r\n }\r\n insight = lastAssistant.content.trim();\r\n }\r\n if (!insight) throw new UserError('Insight text cannot be empty.');\r\n\r\n if (!opts.yes && !ctx.json) {\r\n process.stdout.write(`${c.bold('Insight preview:')}\\n${insight.slice(0, 500)}${insight.length > 500 ? '\\n…(truncated for preview)' : ''}\\n\\n`);\r\n const ok = await askConfirm(\r\n `Inject this back into discussion ${shortId(discussion.id)} at round ${session.anchorRoundNumber}?`,\r\n true,\r\n );\r\n if (!ok) {\r\n process.stdout.write(c.hint(' aborted.\\n'));\r\n return;\r\n }\r\n }\r\n\r\n const result = await injectSparringInsight({\r\n discussion,\r\n session,\r\n insight,\r\n storage: ctx.storage,\r\n });\r\n\r\n if (ctx.json) {\r\n process.stdout.write(\r\n JSON.stringify(\r\n { discussionId: result.discussion.id, injected: result.injectedUserResponse },\r\n null,\r\n 2,\r\n ) + '\\n',\r\n );\r\n } else {\r\n process.stdout.write(\r\n `${c.ok('✓')} injected insight into ${shortId(result.discussion.id)} at round ${result.injectedUserResponse.roundNumber}.\\n`,\r\n );\r\n }\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n });\r\n}\r\n\r\ninterface RunSparringTurnArgs {\r\n session: SparringSession;\r\n member: AdvisoryBoardMember;\r\n discussion: Discussion;\r\n userMessage: string;\r\n settings: Awaited<ReturnType<StorageService['loadSettings']>>;\r\n storage: StorageService;\r\n projectRoot: string;\r\n json: boolean;\r\n}\r\n\r\nasync function runSparringTurn(args: RunSparringTurnArgs): Promise<{ session: SparringSession; assistant?: string }> {\r\n if (!args.json) {\r\n renderSparringMessage('user', args.userMessage);\r\n }\r\n const sp = spinner(`${args.member.name} thinking...`);\r\n sp.start();\r\n try {\r\n const result = await sendSparringMessage({\r\n session: args.session,\r\n member: args.member,\r\n discussion: args.discussion,\r\n userMessage: args.userMessage,\r\n settings: args.settings,\r\n storage: args.storage,\r\n projectRoot: args.projectRoot,\r\n onActivity: (event) => {\r\n sp.text = `${args.member.name} ${event.activity}${event.detail ? ' (' + truncateActivityDetail(event.detail) + ')' : ''}`;\r\n },\r\n });\r\n if (result.error || !result.assistantMsg) {\r\n sp.fail(`${args.member.name}: ${result.error ?? 'no response'}`);\r\n return { session: args.session };\r\n }\r\n sp.succeed(\r\n `${args.member.name} replied in ${formatDuration(result.durationMs)} (${formatUsd(result.costUsd)})${result.fellBackToPrimary ? c.warn(' · fell back to primary model') : ''}`,\r\n );\r\n if (!args.json) {\r\n renderSparringMessage(result.assistantMsg.role, result.assistantMsg.content);\r\n }\r\n return { session: args.session, assistant: result.assistantMsg.content };\r\n } catch (error) {\r\n sp.fail(`${args.member.name}: ${error instanceof Error ? error.message : String(error)}`);\r\n return { session: args.session };\r\n }\r\n}\r\n\r\nasync function runInjectInline(args: {\r\n discussion: Discussion;\r\n session: SparringSession;\r\n insight: string;\r\n storage: StorageService;\r\n}): Promise<void> {\r\n try {\r\n const result = await injectSparringInsight({\r\n discussion: args.discussion,\r\n session: args.session,\r\n insight: args.insight,\r\n storage: args.storage,\r\n });\r\n process.stdout.write(\r\n `${c.ok('✓')} injected insight into ${shortId(result.discussion.id)} at round ${result.injectedUserResponse.roundNumber}.\\n`,\r\n );\r\n } catch (error) {\r\n process.stdout.write(c.warn(` ! inject failed: ${error instanceof Error ? error.message : String(error)}\\n`));\r\n }\r\n}\r\n\r\nasync function resolveSparringSession(\r\n storage: StorageService,\r\n discussionId: string,\r\n sessionIdOrShort: string,\r\n): Promise<SparringSession> {\r\n const direct = await storage.loadSparringSessionById(sessionIdOrShort);\r\n if (direct && direct.discussionId === discussionId) return direct;\r\n const sessions = await storage.loadSparringSessionsForDiscussion(discussionId);\r\n const matches = sessions.filter((s) => s.id.startsWith(sessionIdOrShort));\r\n if (matches.length === 0) {\r\n throw new UserError(`No sparring session matches \"${sessionIdOrShort}\" in discussion ${shortId(discussionId)}.`);\r\n }\r\n if (matches.length > 1) {\r\n throw new UserError(`Multiple sparring sessions match \"${sessionIdOrShort}\". Use a longer prefix.`);\r\n }\r\n return matches[0]!;\r\n}\r\n\r\nasync function resolveSparringSessionAnywhere(\r\n storage: StorageService,\r\n sessionIdOrShort: string,\r\n): Promise<SparringSession> {\r\n const direct = await storage.loadSparringSessionById(sessionIdOrShort);\r\n if (direct) return direct;\r\n // Try discussion-by-discussion (no global short-id index — fine because the\r\n // sparring/ tree is small and this is only the CLI fallback).\r\n const discussions = await storage.loadDiscussions();\r\n for (const d of discussions) {\r\n const sessions = await storage.loadSparringSessionsForDiscussion(d.id);\r\n const match = sessions.find((s) => s.id.startsWith(sessionIdOrShort));\r\n if (match) return match;\r\n }\r\n throw new UserError(`No sparring session matches \"${sessionIdOrShort}\".`);\r\n}\r\n\r\nfunction renderSparringMessage(role: 'user' | 'assistant', content: string): void {\r\n if (role === 'user') {\r\n process.stdout.write(`${c.cyan('you:')}\\n${content}\\n\\n`);\r\n } else {\r\n process.stdout.write(`${c.green('member:')}\\n${content}\\n\\n`);\r\n }\r\n}\r\n\r\nfunction renderAnchor(session: SparringSession): void {\r\n process.stdout.write(`${c.bold('Anchor')} ${c.hint('· round ' + session.anchorRoundNumber + ' · turn ' + session.anchorTurnNumber)}\\n`);\r\n process.stdout.write(`${c.hint(session.anchorResponsePreview)}\\n\\n`);\r\n}\r\n\r\nfunction truncateActivityDetail(detail: string): string {\r\n const t = detail.trim();\r\n return t.length > 60 ? t.slice(0, 57) + '…' : t;\r\n}\r\n\r\n// ---------------- helpers ----------------\r\n\r\nfunction verifyAgentFiles(members: AdvisoryBoardMember[], projectRoot: string): void {\r\n const missing: string[] = [];\r\n for (const m of members) {\r\n if (!existsSync(memberAgentPath(memberAgentSlug(m.name), projectRoot))) {\r\n missing.push(m.name);\r\n }\r\n }\r\n if (missing.length > 0) {\r\n throw new UserError(\r\n `Missing .claude/agents/<slug>.md for: ${missing.join(', ')}`,\r\n `Re-run \\`aab init\\` from a project directory, or copy the agent files to ${join(projectRoot, '.claude', 'agents')}/.`,\r\n );\r\n }\r\n}\r\n\r\nfunction progressHandler(sp: ReturnType<typeof spinner>): (e: StartProgressEvent) => void {\r\n return (e) => {\r\n if (e.stage === 'initializing') sp.text = 'initializing...';\r\n else if (e.stage === 'context') sp.text = 'loading business context...';\r\n else if (e.stage === 'generating') sp.text = `asking ${e.memberName} (${e.index}/${e.total})...`;\r\n else if (e.stage === 'member_done') {\r\n sp.info(`${e.memberName} responded in ${formatDuration(e.durationMs)} (${formatUsd(e.costUsd)})`);\r\n sp.start();\r\n } else if (e.stage === 'orchestrating') sp.text = 'orchestrator deciding next step...';\r\n else if (e.stage === 'finalizing') sp.text = `saving round ${e.round}...`;\r\n };\r\n}\r\n\r\nfunction resolveMemberToken(pool: AdvisoryBoardMember[], token: string): AdvisoryBoardMember | undefined {\r\n const t = token.trim().toLowerCase();\r\n if (!t) return undefined;\r\n // Exact id, exact slug, exact (case-insensitive) name, then prefix on name/slug.\r\n return (\r\n pool.find((m) => m.id === token) ??\r\n pool.find((m) => memberAgentSlug(m.name) === t) ??\r\n pool.find((m) => m.name.toLowerCase() === t) ??\r\n pool.find((m) => m.name.toLowerCase().startsWith(t)) ??\r\n pool.find((m) => memberAgentSlug(m.name).startsWith(t))\r\n );\r\n}\r\n\r\nfunction pickMembers(all: AdvisoryBoardMember[], filter?: string): AdvisoryBoardMember[] {\r\n if (!filter) return all.filter((m) => m.isActive);\r\n const wanted = new Set(filter.split(',').map((s) => s.trim().toLowerCase()).filter(Boolean));\r\n return all.filter(\r\n (m) =>\r\n m.isActive &&\r\n (wanted.has(m.name.toLowerCase()) ||\r\n wanted.has(memberAgentSlug(m.name)) ||\r\n wanted.has(m.id)),\r\n );\r\n}\r\n\r\nasync function resolveDiscussion(\r\n storage: { loadDiscussions(): Promise<Discussion[]>; loadDiscussionById(id: string): Promise<Discussion | null> },\r\n idOrShort: string,\r\n): Promise<Discussion> {\r\n const direct = await storage.loadDiscussionById(idOrShort);\r\n if (direct) return direct;\r\n const all = await storage.loadDiscussions();\r\n const matches = all.filter((d) => d.id.startsWith(idOrShort));\r\n if (matches.length === 0) throw new UserError(`No discussion found with id starting \"${idOrShort}\".`);\r\n if (matches.length > 1) throw new UserError(`Multiple discussions match \"${idOrShort}\". Use a longer prefix.`);\r\n return matches[0]!;\r\n}\r\n\r\nfunction renderSummary(s: ConversationSummary): void {\r\n const out = process.stdout;\r\n out.write(`\\n${c.bold('Summary')} ${c.hint(`· quality ${s.overallQuality}/100 · ${s.generatedAt.slice(0, 10)}`)}\\n`);\r\n if (s.keyPoints.length > 0) {\r\n out.write(`\\n${c.bold('Key points:')}\\n`);\r\n for (const p of s.keyPoints) out.write(` • ${p}\\n`);\r\n }\r\n if (s.consensus.length > 0) {\r\n out.write(`\\n${c.bold('Consensus:')}\\n`);\r\n for (const p of s.consensus) out.write(` ${c.ok('✓')} ${p}\\n`);\r\n }\r\n if (s.disagreements.length > 0) {\r\n out.write(`\\n${c.bold('Disagreements:')}\\n`);\r\n for (const p of s.disagreements) out.write(` ${c.warn('!')} ${p}\\n`);\r\n }\r\n if (s.actionableInsights.length > 0) {\r\n out.write(`\\n${c.bold('Actionable insights:')}\\n`);\r\n for (const p of s.actionableInsights) out.write(` → ${p}\\n`);\r\n }\r\n}\r\n\r\nfunction renderListRow(d: Discussion): string {\r\n const id = shortId(d.id);\r\n const status = d.completedAt ? c.ok('done') : d.pendingUserRequest ? c.warn('awaiting input') : c.cyan('open');\r\n const date = d.createdAt.slice(0, 10);\r\n const turns = `${d.totalTurns}t`;\r\n const rounds = `${d.rounds.length}r`;\r\n const arch = d.archivedAt ? c.dim(' [archived]') : '';\r\n const q = d.question.length > 80 ? d.question.slice(0, 80) + '…' : d.question;\r\n return ` ${c.bold(id)} ${c.hint(date)} ${rounds.padEnd(4)} ${turns.padEnd(5)} ${status.padEnd(20)}${arch} ${q}`;\r\n}\r\n","/**\r\n * Render a Discussion to the terminal.\r\n */\r\nimport type { Discussion, Response } from '../storage/types.js';\r\nimport { c, memberColor } from './colors.js';\r\n\r\nconst HR = c.dim('─'.repeat(72));\r\n\r\nexport function renderDiscussion(d: Discussion, opts: { round?: number } = {}): string {\r\n const lines: string[] = [];\r\n\r\n lines.push('');\r\n lines.push(c.brand('AI Advisory Board') + c.hint(` · discussion ${shortId(d.id)}`));\r\n lines.push(HR);\r\n lines.push(c.bold('Question:'));\r\n lines.push(` ${d.question}`);\r\n lines.push('');\r\n\r\n // Metadata\r\n const memberCount = new Set(d.responses.map((r) => r.memberId)).size;\r\n const meta = [\r\n `${d.rounds.length} round${d.rounds.length === 1 ? '' : 's'}`,\r\n `${d.totalTurns} turn${d.totalTurns === 1 ? '' : 's'}`,\r\n `${memberCount} member${memberCount === 1 ? '' : 's'}`,\r\n d.completedAt ? c.ok('concluded') : d.pendingUserRequest ? c.warn('awaiting input') : c.cyan('open'),\r\n ];\r\n lines.push(c.hint(meta.join(' · ')));\r\n lines.push('');\r\n\r\n const roundsToShow = opts.round\r\n ? d.rounds.filter((r) => r.roundNumber === opts.round)\r\n : d.rounds;\r\n\r\n for (const round of roundsToShow) {\r\n lines.push(c.bold(`▸ Round ${round.roundNumber}`));\r\n if (round.followUpQuestion) {\r\n lines.push(c.hint(` follow-up: ${round.followUpQuestion}`));\r\n }\r\n lines.push('');\r\n\r\n for (const r of round.responses) {\r\n lines.push(renderResponse(r));\r\n lines.push('');\r\n }\r\n\r\n if (round.orchestratorDecision) {\r\n const od = round.orchestratorDecision;\r\n const action =\r\n od.action === 'conclude'\r\n ? c.ok(od.action)\r\n : od.action === 'request_user_input'\r\n ? c.warn(od.action)\r\n : od.action === 'redirect'\r\n ? c.magenta(od.action)\r\n : c.cyan(od.action);\r\n lines.push(c.hint(` orchestrator → ${action} (confidence ${od.confidence}%)`));\r\n if (od.reasoning) lines.push(c.hint(` reason: ${truncate(od.reasoning, 200)}`));\r\n lines.push('');\r\n }\r\n }\r\n\r\n if (d.pendingUserRequest) {\r\n const r = d.pendingUserRequest;\r\n lines.push(HR);\r\n lines.push(c.warn('● The board is asking you a question:'));\r\n lines.push(` ${c.bold(r.question)}`);\r\n if (r.context) lines.push(c.hint(` ${r.context}`));\r\n if (r.options && r.options.length > 0) {\r\n lines.push(c.hint(' options:'));\r\n r.options.forEach((opt, i) => {\r\n lines.push(` ${i + 1}) ${opt}`);\r\n });\r\n }\r\n lines.push(c.hint(` Reply with: aab discuss respond ${shortId(d.id)} \"<your answer>\"`));\r\n }\r\n\r\n return lines.join('\\n');\r\n}\r\n\r\nfunction renderResponse(r: Response): string {\r\n const colour = memberColor(r.memberName);\r\n const header = ` ${colour('●')} ${c.bold(colour(r.memberName))} ${c.hint('· turn ' + r.turnNumber)}`;\r\n const body = indent(r.content.trim(), ' ');\r\n const lines = [header, body];\r\n\r\n const sd = r.structuredData;\r\n if (sd) {\r\n if (sd.keyPoints && sd.keyPoints.length > 0) {\r\n lines.push('');\r\n lines.push(c.hint(' key points:'));\r\n for (const p of sd.keyPoints) lines.push(` • ${p}`);\r\n }\r\n if (sd.questionsForOthers && sd.questionsForOthers.length > 0) {\r\n lines.push('');\r\n lines.push(c.hint(' questions for others:'));\r\n for (const q of sd.questionsForOthers) lines.push(` ? ${q}`);\r\n }\r\n if (sd.actionSteps && sd.actionSteps.length > 0) {\r\n lines.push('');\r\n lines.push(c.hint(' action steps:'));\r\n for (const a of sd.actionSteps) lines.push(` → ${a}`);\r\n }\r\n if (typeof sd.confidence === 'number') {\r\n lines.push('');\r\n lines.push(c.hint(` confidence: ${sd.confidence}%`));\r\n }\r\n }\r\n\r\n return lines.join('\\n');\r\n}\r\n\r\nfunction indent(text: string, prefix: string): string {\r\n return text\r\n .split('\\n')\r\n .map((line) => `${prefix}${line}`)\r\n .join('\\n');\r\n}\r\n\r\nfunction truncate(text: string, max: number): string {\r\n if (text.length <= max) return text;\r\n return `${text.slice(0, max)}…`;\r\n}\r\n\r\nexport function shortId(id: string): string {\r\n return id.slice(0, 8);\r\n}\r\n","/**\n * Render a `Discussion` to a self-contained markdown file.\n *\n * Used by `aab discuss export <id> --md`. Also the source of truth for the\n * `raw/discussions/<short>.md` files that Phase 1.5's auto-ingest hook will\n * write into the wiki workspace — keep this renderer deterministic so the\n * file hashes stay stable across runs (no timestamps in the body, only in\n * the frontmatter).\n */\nimport slugify from 'slugify';\nimport type { ConversationSummary, Discussion, Response } from '../storage/types.js';\n\nexport function renderDiscussionMarkdown(d: Discussion): string {\n const lines: string[] = [];\n\n // ---------- Frontmatter ----------\n lines.push('---');\n lines.push(`id: ${d.id}`);\n lines.push(`question: ${yamlString(d.question)}`);\n lines.push(`createdAt: ${d.createdAt}`);\n if (d.completedAt) lines.push(`completedAt: ${d.completedAt}`);\n if (d.archivedAt) lines.push(`archivedAt: ${d.archivedAt}`);\n lines.push(`rounds: ${d.rounds.length}`);\n lines.push(`totalTurns: ${d.totalTurns}`);\n lines.push(`maxTurns: ${d.maxTurns}`);\n if (d.boardName) lines.push(`board: ${yamlString(d.boardName)}`);\n if (d.summary) lines.push(`summaryQuality: ${d.summary.overallQuality}`);\n lines.push('---');\n lines.push('');\n\n // ---------- Title ----------\n lines.push(`# ${d.question.replace(/\\n+/g, ' ')}`);\n lines.push('');\n\n // ---------- Metadata line ----------\n const status = d.completedAt\n ? 'concluded'\n : d.pendingUserRequest\n ? 'awaiting input'\n : 'open';\n const memberCount = new Set(d.responses.map((r) => r.memberId)).size;\n lines.push(\n `*${d.rounds.length} round${d.rounds.length === 1 ? '' : 's'} · ${d.totalTurns} turn${\n d.totalTurns === 1 ? '' : 's'\n } · ${memberCount} member${memberCount === 1 ? '' : 's'} · ${status}*`,\n );\n lines.push('');\n\n // ---------- Summary (if present) ----------\n if (d.summary) {\n lines.push(...renderSummarySection(d.summary));\n }\n\n // ---------- Rounds ----------\n for (const round of d.rounds) {\n lines.push(`## Round ${round.roundNumber}`);\n if (round.followUpQuestion) {\n lines.push('');\n lines.push(`> **Follow-up:** ${round.followUpQuestion}`);\n }\n lines.push('');\n\n for (const r of round.responses) {\n lines.push(...renderResponseBlock(r));\n lines.push('');\n }\n\n if (round.orchestratorDecision) {\n const od = round.orchestratorDecision;\n lines.push(`*Orchestrator → \\`${od.action}\\` (confidence ${od.confidence}%)*`);\n if (od.reasoning) lines.push(`> ${od.reasoning}`);\n if (od.suggestedDirection) lines.push(`> Suggested direction: ${od.suggestedDirection}`);\n lines.push('');\n }\n\n if (round.userInteractionRequest && round.userResponse) {\n lines.push('### Human-in-the-loop');\n lines.push('');\n lines.push(`> **The board asked:** ${round.userInteractionRequest.question}`);\n if (round.userInteractionRequest.context) {\n lines.push(`> ${round.userInteractionRequest.context}`);\n }\n lines.push('');\n lines.push(`> **You replied:** ${round.userResponse.content}`);\n if (round.userResponse.selectedOption) {\n lines.push(`> (chose option: ${round.userResponse.selectedOption})`);\n }\n lines.push('');\n }\n }\n\n // ---------- Pending user request (if still open) ----------\n if (d.pendingUserRequest) {\n lines.push('## Awaiting your input');\n lines.push('');\n lines.push(`> ${d.pendingUserRequest.question}`);\n if (d.pendingUserRequest.context) lines.push(`> ${d.pendingUserRequest.context}`);\n if (d.pendingUserRequest.options && d.pendingUserRequest.options.length > 0) {\n lines.push('');\n lines.push('Options:');\n d.pendingUserRequest.options.forEach((opt, i) => {\n lines.push(`${i + 1}. ${opt}`);\n });\n }\n lines.push('');\n }\n\n // ---------- Footer ----------\n lines.push('---');\n lines.push('');\n lines.push(`*Exported from aab discussion \\`${d.id}\\`.*`);\n lines.push('');\n\n return lines.join('\\n');\n}\n\nfunction renderSummarySection(s: ConversationSummary): string[] {\n const out: string[] = [];\n out.push('## Summary');\n out.push('');\n out.push(`*Generated ${s.generatedAt} · overall quality ${s.overallQuality}/100*`);\n out.push('');\n\n if (s.keyPoints.length > 0) {\n out.push('### Key points');\n for (const p of s.keyPoints) out.push(`- ${p}`);\n out.push('');\n }\n if (s.consensus.length > 0) {\n out.push('### Consensus');\n for (const p of s.consensus) out.push(`- ${p}`);\n out.push('');\n }\n if (s.disagreements.length > 0) {\n out.push('### Disagreements');\n for (const p of s.disagreements) out.push(`- ${p}`);\n out.push('');\n }\n if (s.actionableInsights.length > 0) {\n out.push('### Actionable insights');\n for (const p of s.actionableInsights) out.push(`- ${p}`);\n out.push('');\n }\n if (s.participationBreakdown.length > 0) {\n out.push('### Participation');\n out.push('');\n out.push('| Member | Responses | Avg length | Influence | Topics |');\n out.push('|---|---:|---:|---:|---|');\n for (const p of s.participationBreakdown) {\n const topics = p.topicsCovered.length > 0 ? p.topicsCovered.join(', ') : '—';\n out.push(\n `| ${escapeTableCell(p.memberName)} | ${p.totalResponses} | ${p.averageLength} | ${p.influence} | ${escapeTableCell(topics)} |`,\n );\n }\n out.push('');\n }\n\n return out;\n}\n\nfunction renderResponseBlock(r: Response): string[] {\n const lines: string[] = [];\n lines.push(`### ${r.memberName} *(turn ${r.turnNumber})*`);\n lines.push('');\n lines.push(r.content.trim());\n\n const sd = r.structuredData;\n if (sd) {\n if (sd.keyPoints && sd.keyPoints.length > 0) {\n lines.push('');\n lines.push('**Key points**');\n for (const p of sd.keyPoints) lines.push(`- ${p}`);\n }\n if (sd.questionsForOthers && sd.questionsForOthers.length > 0) {\n lines.push('');\n lines.push('**Questions for others**');\n for (const q of sd.questionsForOthers) lines.push(`- ${q}`);\n }\n if (sd.actionSteps && sd.actionSteps.length > 0) {\n lines.push('');\n lines.push('**Action steps**');\n for (const a of sd.actionSteps) lines.push(`- ${a}`);\n }\n if (typeof sd.confidence === 'number') {\n lines.push('');\n lines.push(`*Confidence: ${sd.confidence}%*`);\n }\n }\n\n return lines;\n}\n\nexport function defaultExportFilename(d: Discussion): string {\n const short = d.id.slice(0, 8);\n const slug = slugify(d.question.slice(0, 80), { lower: true, strict: true }) || 'discussion';\n return `${short}-${slug}.md`;\n}\n\nfunction yamlString(value: string): string {\n // Quote and escape — YAML 1.2 double-quoted scalar.\n return `\"${value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"').replace(/\\n/g, ' ')}\"`;\n}\n\nfunction escapeTableCell(value: string): string {\n return value.replace(/\\|/g, '\\\\|').replace(/\\n+/g, ' ');\n}\n","/**\n * Top-level discussion engine. Wraps round execution, orchestrator analysis,\n * and persistence.\n *\n * Phase 1 surface:\n * - startDiscussion — round 1\n * - continueDiscussion — orchestrator-gated next round (with pre-round\n * clarification gate per PLAN.md §4.3.1)\n * - respondToUserRequest — answer a pending HITL `request_user_input`,\n * then drive a follow-up round\n * - addFollowUpQuestion — targeted follow-up round (all / specific /\n * subset of members) carrying the user's new\n * question. Strict: any member failure aborts\n * the round per PLAN.md §1.5.\n *\n * Sparring and summarize/export come next.\n */\nimport { logger } from '../logger.js';\nimport { UserError } from '../errors.js';\nimport { generateUUID, nowIso } from '../utils.js';\nimport { existsSync } from 'node:fs';\nimport { runMember } from './run-member.js';\nimport {\n analyzeConversation,\n createInitialOrchestratorState,\n updateOrchestratorState,\n} from './orchestrator.js';\nimport { summarizeDiscussion } from './summarize.js';\nimport { resolveWorkspace, paths } from '../../storage/paths.js';\nimport { ingestDiscussionRaw, ingestPaste } from '../knowledge/ingest.js';\nimport type {\n AdvisoryBoardMember,\n AppSettings,\n BusinessContext,\n ConversationRound,\n Discussion,\n Response,\n StorageService,\n UserResponse,\n} from '../../storage/types.js';\n\nexport type StartProgressEvent =\n | { stage: 'initializing' }\n | { stage: 'context' }\n | { stage: 'generating'; memberName: string; index: number; total: number }\n | {\n stage: 'member_activity';\n memberName: string;\n activity: string;\n tool?: string;\n detail?: string;\n }\n | {\n stage: 'member_done';\n memberName: string;\n durationMs: number;\n costUsd: number;\n response: Response;\n roundNumber: number;\n }\n | { stage: 'orchestrating' }\n | {\n stage: 'orchestrator_decided';\n decision: import('../../storage/types.js').OrchestratorDecision;\n roundNumber: number;\n }\n | { stage: 'finalizing'; round: number };\n\nexport interface StartDiscussionOptions {\n question: string;\n members: AdvisoryBoardMember[];\n settings: AppSettings;\n storage: StorageService;\n /** Where the .claude/agents/ directory lives. Default: process.cwd(). */\n projectRoot?: string;\n signal?: AbortSignal;\n onProgress?: (event: StartProgressEvent) => void;\n}\n\nexport interface StartDiscussionResult {\n discussion: Discussion;\n totalCostUsd: number;\n totalDurationMs: number;\n}\n\nexport async function startDiscussion(opts: StartDiscussionOptions): Promise<StartDiscussionResult> {\n const t0 = Date.now();\n opts.onProgress?.({ stage: 'initializing' });\n\n const activeMembers = opts.members.filter((m) => m.isActive);\n if (activeMembers.length === 0) {\n throw new Error('No active board members. Add or activate at least one with `aab members add`.');\n }\n\n // Skeleton discussion record\n const discussionId = generateUUID();\n const now = nowIso();\n const discussion: Discussion = {\n id: discussionId,\n question: opts.question,\n selectedMemberIds: activeMembers.map((m) => m.id),\n responses: [],\n rounds: [],\n orchestratorState: createInitialOrchestratorState(),\n totalTurns: 0,\n maxTurns: opts.settings.maxTurnsPerDiscussion,\n userResponses: [],\n createdAt: now,\n };\n\n // Capture the user's original question as a UserResponse (matches source behavior)\n const initialUserResponse: UserResponse = {\n id: generateUUID(),\n requestId: 'initial-question',\n content: opts.question,\n timestamp: now,\n roundNumber: 1,\n type: 'initial_question',\n prompt: opts.question,\n };\n discussion.userResponses.push(initialUserResponse);\n\n // Load business context for prompt injection (Phase 1: load existing only,\n // we don't yet auto-extract new context from the question — that's Phase 2)\n opts.onProgress?.({ stage: 'context' });\n const businessContext = await loadBusinessContextSafe(opts.storage);\n\n // Round 1\n const round1: ConversationRound = {\n roundNumber: 1,\n responses: [],\n orchestratorDecision: {\n action: 'continue',\n reasoning: 'Initial round.',\n consensusReached: false,\n confidence: 100,\n },\n startedAt: nowIso(),\n };\n\n let totalCostUsd = 0;\n for (let i = 0; i < activeMembers.length; i++) {\n const member = activeMembers[i]!;\n opts.onProgress?.({ stage: 'generating', memberName: member.name, index: i + 1, total: activeMembers.length });\n\n const result = await runMember({\n question: opts.question,\n member,\n roundNumber: 1,\n previousResponsesInRound: round1.responses,\n conversationHistory: [],\n businessContext,\n settings: opts.settings,\n storage: opts.storage,\n discussionId,\n projectRoot: opts.projectRoot,\n signal: opts.signal,\n onActivity: (a) =>\n opts.onProgress?.({ stage: 'member_activity', memberName: member.name, ...a }),\n });\n\n round1.responses.push(result.response);\n discussion.responses.push(result.response);\n discussion.totalTurns++;\n totalCostUsd += result.costUsd;\n\n opts.onProgress?.({\n stage: 'member_done',\n memberName: member.name,\n durationMs: result.durationMs,\n costUsd: result.costUsd,\n response: result.response,\n roundNumber: 1,\n });\n }\n\n if (round1.responses.length === 0) {\n throw new Error('All board members failed to respond. Check `aab doctor` and try again.');\n }\n\n round1.completedAt = nowIso();\n\n // Orchestrator analysis (decides whether the next round should run, ask user, etc.)\n opts.onProgress?.({ stage: 'orchestrating' });\n try {\n const decision = await analyzeConversation({\n question: opts.question,\n rounds: [round1],\n members: activeMembers,\n currentTurn: discussion.totalTurns,\n settings: opts.settings,\n storage: opts.storage,\n discussionId,\n signal: opts.signal,\n });\n round1.orchestratorDecision = decision;\n discussion.orchestratorState = updateOrchestratorState(\n discussion.orchestratorState,\n decision,\n round1,\n );\n if (decision.action === 'request_user_input' && decision.userInputRequest) {\n discussion.pendingUserRequest = decision.userInputRequest;\n }\n opts.onProgress?.({ stage: 'orchestrator_decided', decision, roundNumber: 1 });\n } catch (error) {\n logger.warn('[startDiscussion] orchestrator failed (non-blocking):', error);\n }\n\n discussion.rounds.push(round1);\n\n // If we hit the conclusion right after round 1, mark the discussion complete\n if (round1.orchestratorDecision.action === 'conclude' || discussion.totalTurns >= discussion.maxTurns) {\n discussion.completedAt = nowIso();\n discussion.pendingUserRequest = undefined;\n }\n\n opts.onProgress?.({ stage: 'finalizing', round: 1 });\n await opts.storage.saveDiscussion(discussion);\n\n // Phase 1.5: auto-ingest into the Knowledge Wiki on conclude.\n await maybeAutoIngestOnConclude(discussion, activeMembers, opts.settings, opts.storage);\n\n return {\n discussion,\n totalCostUsd,\n totalDurationMs: Date.now() - t0,\n };\n}\n\nasync function loadBusinessContextSafe(storage: StorageService): Promise<BusinessContext[]> {\n // Phase 1.5: if a Knowledge Wiki is present, members read it natively via\n // Read/Grep/Glob (system-prompt addendum from `emit-member-agent.ts`).\n // Returning [] here skips the legacy inline business-context block in\n // `build-user-message.ts`. The legacy JSON path is still functional for\n // workspaces without a wiki (transition window).\n try {\n const root = storage.getWorkspaceRoot();\n const p = paths(root);\n if (existsSync(p.wiki) && existsSync(p.wikiKnowledge)) return [];\n } catch {\n // fall through to legacy loader\n }\n try {\n return await storage.loadBusinessContext();\n } catch (error) {\n logger.debug('[conversation-flow] business context load failed (non-blocking):', error);\n return [];\n }\n}\n\n/**\n * Auto-ingest a concluded discussion into the Knowledge Wiki. Wrapped in\n * try/catch — a failed ingest never blocks discussion completion. Logs to\n * `wiki/log.md` with `[ingest-failed]` prefix on errors.\n * Reference: `docs/development/KNOWLEDGE_WIKI.md` §16.\n */\nasync function maybeAutoIngestOnConclude(\n discussion: Discussion,\n members: AdvisoryBoardMember[],\n settings: AppSettings,\n storage: StorageService,\n): Promise<void> {\n if (!discussion.completedAt) return;\n if (settings.knowledgeWiki?.enabled === false) return;\n if (settings.knowledgeWiki?.autoIngestDiscussions === false) return;\n try {\n const root = storage.getWorkspaceRoot();\n const p = paths(root);\n if (!existsSync(p.wiki) || !existsSync(p.wikiKnowledge)) return; // no wiki = no auto-ingest\n\n // 1. Generate a summary first if autoSummarization is on and missing.\n if (settings.autoSummarization && !discussion.summary && discussion.rounds.length > 0) {\n try {\n discussion.summary = await summarizeDiscussion({ discussion, members, settings });\n await storage.saveDiscussion(discussion);\n } catch (error) {\n logger.warn('[auto-ingest] summarize failed (non-blocking):', error);\n }\n }\n\n // 2. Resolve workspace for the ingest pipeline.\n const workspace = resolveWorkspace({ override: storage.getWorkspaceId() });\n // Override root in case the env doesn't match (storage knows the truth).\n workspace.root = root;\n\n await ingestDiscussionRaw({ discussion, workspace, settings, storage });\n } catch (error) {\n logger.warn('[auto-ingest] discussion ingest failed (non-blocking):', error);\n }\n}\n\n/**\n * Auto-ingest a user's HITL response as a paste-style raw input. Same\n * non-blocking semantics as discussion ingest.\n * Reference: `docs/development/KNOWLEDGE_WIKI.md` §16 (\"User HITL responses also get\n * auto-ingested\").\n */\nasync function maybeAutoIngestUserResponse(\n content: string,\n settings: AppSettings,\n storage: StorageService,\n): Promise<void> {\n if (settings.knowledgeWiki?.enabled === false) return;\n if (settings.knowledgeWiki?.autoIngestUserResponses === false) return;\n const trimmed = content.trim();\n if (trimmed.length < 40) return; // tiny replies aren't worth a wiki entry\n try {\n const root = storage.getWorkspaceRoot();\n const p = paths(root);\n if (!existsSync(p.wiki) || !existsSync(p.wikiKnowledge)) return;\n const workspace = resolveWorkspace({ override: storage.getWorkspaceId() });\n workspace.root = root;\n await ingestPaste({ text: trimmed, workspace, settings });\n } catch (error) {\n logger.warn('[auto-ingest] user-response ingest failed (non-blocking):', error);\n }\n}\n\n// ============================================================\n// continueDiscussion — orchestrator-gated next round\n// ============================================================\n\nexport interface ContinueDiscussionOptions {\n discussion: Discussion;\n members: AdvisoryBoardMember[];\n settings: AppSettings;\n storage: StorageService;\n /** Where the .claude/agents/ directory lives. Default: process.cwd(). */\n projectRoot?: string;\n signal?: AbortSignal;\n onProgress?: (event: StartProgressEvent) => void;\n /**\n * When provided, treat the user's reply as a follow-up question driving\n * the next round. Used internally by `respondToUserRequest`.\n */\n userFollowUp?: { content: string; selectedOption?: string };\n /**\n * If true, skip the pre-round clarification gate. Used internally by\n * `respondToUserRequest` since the orchestrator's question is the very\n * thing the user just answered — re-asking would loop forever.\n */\n skipPreRoundGate?: boolean;\n}\n\nexport interface ContinueDiscussionResult {\n discussion: Discussion;\n totalCostUsd: number;\n totalDurationMs: number;\n /** True when the pre-round gate ended early because the orchestrator wants user input. */\n gated: boolean;\n /** True when the discussion concluded as part of this call. */\n concluded: boolean;\n /** Round number that was generated in this call, or null if gated/no-op. */\n roundNumber: number | null;\n}\n\nexport async function continueDiscussion(\n opts: ContinueDiscussionOptions,\n): Promise<ContinueDiscussionResult> {\n const t0 = Date.now();\n const { discussion } = opts;\n\n if (discussion.completedAt) {\n throw new UserError(\n 'This discussion is already concluded.',\n 'Start a new one with `aab discuss start \"<question>\"` or open a sparring session with `aab discuss spar`.',\n );\n }\n if (discussion.pendingUserRequest && !opts.userFollowUp) {\n throw new UserError(\n 'This discussion is awaiting your input.',\n 'Reply with `aab discuss respond <id> \"<answer>\" [--option <i>]` first.',\n );\n }\n\n const activeMembers = opts.members.filter((m) => m.isActive);\n if (activeMembers.length === 0) {\n throw new UserError('No active board members. Add or activate at least one with `aab members add`.');\n }\n\n // Bail if we're already at maxTurns — mark concluded.\n if (discussion.totalTurns >= discussion.maxTurns) {\n if (!discussion.completedAt) {\n discussion.completedAt = nowIso();\n await opts.storage.saveDiscussion(discussion);\n }\n return {\n discussion,\n totalCostUsd: 0,\n totalDurationMs: Date.now() - t0,\n gated: false,\n concluded: true,\n roundNumber: null,\n };\n }\n\n // Pre-round clarification gate — runs *before* any model spawns.\n if (!opts.skipPreRoundGate) {\n opts.onProgress?.({ stage: 'orchestrating' });\n try {\n const gate = await analyzeConversation({\n question: discussion.question,\n rounds: discussion.rounds,\n members: activeMembers,\n currentTurn: discussion.totalTurns,\n settings: opts.settings,\n storage: opts.storage,\n discussionId: discussion.id,\n signal: opts.signal,\n });\n if (gate.action === 'request_user_input' && gate.userInputRequest) {\n discussion.pendingUserRequest = gate.userInputRequest;\n await opts.storage.saveDiscussion(discussion);\n return {\n discussion,\n totalCostUsd: 0,\n totalDurationMs: Date.now() - t0,\n gated: true,\n concluded: false,\n roundNumber: null,\n };\n }\n if (gate.action === 'conclude') {\n // Orchestrator decided no further round is warranted — close out.\n discussion.completedAt = nowIso();\n // Stamp the gate decision onto the most recent round if present\n const last = discussion.rounds[discussion.rounds.length - 1];\n if (last) last.orchestratorDecision = gate;\n await opts.storage.saveDiscussion(discussion);\n return {\n discussion,\n totalCostUsd: 0,\n totalDurationMs: Date.now() - t0,\n gated: false,\n concluded: true,\n roundNumber: null,\n };\n }\n } catch (error) {\n logger.warn('[continueDiscussion] pre-round gate failed (non-blocking):', error);\n }\n }\n\n // Build the next round\n const lastRound = discussion.rounds[discussion.rounds.length - 1];\n const nextRoundNumber = (lastRound?.roundNumber ?? 0) + 1;\n\n const round: ConversationRound = {\n roundNumber: nextRoundNumber,\n responses: [],\n orchestratorDecision: {\n action: 'continue',\n reasoning: `Round ${nextRoundNumber} starting.`,\n consensusReached: false,\n confidence: 100,\n },\n startedAt: nowIso(),\n };\n if (opts.userFollowUp) {\n const lastResponse = discussion.userResponses[discussion.userResponses.length - 1];\n round.userResponse = lastResponse;\n }\n\n const conversationHistory = discussion.responses;\n const businessContext = await loadBusinessContextSafe(opts.storage);\n\n let totalCostUsd = 0;\n for (let i = 0; i < activeMembers.length; i++) {\n const member = activeMembers[i]!;\n opts.onProgress?.({\n stage: 'generating',\n memberName: member.name,\n index: i + 1,\n total: activeMembers.length,\n });\n\n try {\n const result = await runMember({\n question: discussion.question,\n member,\n roundNumber: nextRoundNumber,\n previousResponsesInRound: round.responses,\n conversationHistory,\n businessContext,\n settings: opts.settings,\n storage: opts.storage,\n discussionId: discussion.id,\n projectRoot: opts.projectRoot,\n signal: opts.signal,\n isFollowUp: true,\n followUpQuestion: opts.userFollowUp?.content,\n onActivity: (a) =>\n opts.onProgress?.({ stage: 'member_activity', memberName: member.name, ...a }),\n });\n\n round.responses.push(result.response);\n discussion.responses.push(result.response);\n discussion.totalTurns++;\n totalCostUsd += result.costUsd;\n\n opts.onProgress?.({\n stage: 'member_done',\n memberName: member.name,\n durationMs: result.durationMs,\n costUsd: result.costUsd,\n response: result.response,\n roundNumber: nextRoundNumber,\n });\n } catch (error) {\n logger.warn(`[continueDiscussion] ${member.name} failed (continuing with other members):`, error);\n }\n }\n\n if (round.responses.length === 0) {\n throw new UserError(\n 'All board members failed to respond in this round.',\n 'Run `aab doctor` to verify the claude CLI is reachable, then try `aab discuss continue <id>` again.',\n );\n }\n\n round.completedAt = nowIso();\n\n // Post-round orchestrator analysis\n opts.onProgress?.({ stage: 'orchestrating' });\n try {\n const decision = await analyzeConversation({\n question: discussion.question,\n rounds: [...discussion.rounds, round],\n members: activeMembers,\n currentTurn: discussion.totalTurns,\n settings: opts.settings,\n storage: opts.storage,\n discussionId: discussion.id,\n signal: opts.signal,\n });\n round.orchestratorDecision = decision;\n discussion.orchestratorState = updateOrchestratorState(discussion.orchestratorState, decision, round);\n if (decision.action === 'request_user_input' && decision.userInputRequest) {\n discussion.pendingUserRequest = decision.userInputRequest;\n }\n opts.onProgress?.({ stage: 'orchestrator_decided', decision, roundNumber: nextRoundNumber });\n } catch (error) {\n logger.warn('[continueDiscussion] orchestrator failed (non-blocking):', error);\n }\n\n discussion.rounds.push(round);\n\n let concluded = false;\n if (\n round.orchestratorDecision.action === 'conclude' ||\n discussion.totalTurns >= discussion.maxTurns\n ) {\n discussion.completedAt = nowIso();\n concluded = true;\n // If the orchestrator wanted input but we're out of turns, the question\n // is moot — clear it so the UI doesn't show \"done\" alongside an\n // unanswerable HITL prompt.\n discussion.pendingUserRequest = undefined;\n }\n\n opts.onProgress?.({ stage: 'finalizing', round: nextRoundNumber });\n await opts.storage.saveDiscussion(discussion);\n\n // Phase 1.5: auto-ingest into the Knowledge Wiki on conclude.\n if (concluded) {\n await maybeAutoIngestOnConclude(discussion, activeMembers, opts.settings, opts.storage);\n }\n\n return {\n discussion,\n totalCostUsd,\n totalDurationMs: Date.now() - t0,\n gated: false,\n concluded,\n roundNumber: nextRoundNumber,\n };\n}\n\n// ============================================================\n// respondToUserRequest — answer a pending HITL request\n// ============================================================\n\nexport interface RespondToUserRequestOptions {\n discussion: Discussion;\n content: string;\n selectedOption?: string;\n members: AdvisoryBoardMember[];\n settings: AppSettings;\n storage: StorageService;\n projectRoot?: string;\n signal?: AbortSignal;\n onProgress?: (event: StartProgressEvent) => void;\n}\n\nexport async function respondToUserRequest(\n opts: RespondToUserRequestOptions,\n): Promise<ContinueDiscussionResult> {\n const { discussion } = opts;\n const trimmed = opts.content.trim();\n if (!trimmed) {\n throw new UserError('Reply content is empty.');\n }\n if (!discussion.pendingUserRequest) {\n throw new UserError(\n 'This discussion is not awaiting your input.',\n 'Use `aab discuss continue <id>` to drive the next round.',\n );\n }\n\n const requestId = discussion.pendingUserRequest.id;\n const lastRoundNumber = discussion.rounds[discussion.rounds.length - 1]?.roundNumber ?? 1;\n const userResponse: UserResponse = {\n id: generateUUID(),\n requestId,\n content: trimmed,\n selectedOption: opts.selectedOption,\n timestamp: nowIso(),\n roundNumber: lastRoundNumber,\n type: 'advisory_board_requested',\n prompt: discussion.pendingUserRequest.question,\n };\n discussion.userResponses.push(userResponse);\n discussion.pendingUserRequest = undefined;\n\n // Persist the cleared HITL state immediately so a crash mid-round\n // doesn't leave the discussion stuck \"awaiting input\" forever.\n await opts.storage.saveDiscussion(discussion);\n\n // Phase 1.5: auto-ingest the user's HITL reply as a paste-style raw input\n // (fire-and-forget so a wiki hiccup never blocks the discussion).\n void maybeAutoIngestUserResponse(trimmed, opts.settings, opts.storage);\n\n // Drive the next round, threading the user's reply as a follow-up question.\n // Skip the pre-round gate — the orchestrator just asked for this exact\n // input, so re-running it would either say \"continue\" (waste of a call)\n // or loop forever asking again.\n return continueDiscussion({\n discussion,\n members: opts.members,\n settings: opts.settings,\n storage: opts.storage,\n projectRoot: opts.projectRoot,\n signal: opts.signal,\n onProgress: opts.onProgress,\n userFollowUp: { content: trimmed, selectedOption: opts.selectedOption },\n skipPreRoundGate: true,\n });\n}\n\n// ============================================================\n// addFollowUpQuestion — targeted follow-up round\n// ============================================================\n\nexport type FollowUpTargetType = 'all' | 'specific' | 'subset';\n\nexport interface AddFollowUpQuestionOptions {\n discussion: Discussion;\n /** The user's new question to put to the targeted member(s). */\n question: string;\n /** Active members of the workspace — used both as the candidate pool and to populate the orchestrator's view. */\n members: AdvisoryBoardMember[];\n settings: AppSettings;\n storage: StorageService;\n projectRoot?: string;\n signal?: AbortSignal;\n onProgress?: (event: StartProgressEvent) => void;\n /** Default: 'all' (every active member from the discussion responds). */\n targetType?: FollowUpTargetType;\n /** Required when targetType='specific'. */\n selectedMemberId?: string;\n /** Required when targetType='subset'. */\n selectedMemberIds?: string[];\n}\n\nexport async function addFollowUpQuestion(\n opts: AddFollowUpQuestionOptions,\n): Promise<ContinueDiscussionResult> {\n const t0 = Date.now();\n const { discussion } = opts;\n const trimmed = opts.question.trim();\n if (!trimmed) {\n throw new UserError('Follow-up question is empty.');\n }\n if (discussion.completedAt) {\n throw new UserError(\n 'This discussion is already concluded.',\n 'Start a new one with `aab discuss start \"<question>\"` or open a sparring session with `aab discuss spar`.',\n );\n }\n if (discussion.pendingUserRequest) {\n throw new UserError(\n 'This discussion is awaiting your input.',\n 'Reply with `aab discuss respond <id> \"<answer>\"` first.',\n );\n }\n if (discussion.totalTurns >= discussion.maxTurns) {\n if (!discussion.completedAt) {\n discussion.completedAt = nowIso();\n await opts.storage.saveDiscussion(discussion);\n }\n return {\n discussion,\n totalCostUsd: 0,\n totalDurationMs: Date.now() - t0,\n gated: false,\n concluded: true,\n roundNumber: null,\n };\n }\n\n const targetType: FollowUpTargetType = opts.targetType ?? 'all';\n const activeMembers = opts.members.filter((m) => m.isActive);\n if (activeMembers.length === 0) {\n throw new UserError('No active board members.');\n }\n\n // Restrict candidates to the discussion's original member set so a\n // follow-up doesn't pull in someone the discussion never had.\n const allowedIds = new Set(discussion.selectedMemberIds ?? activeMembers.map((m) => m.id));\n const candidatePool = activeMembers.filter((m) => allowedIds.has(m.id));\n if (candidatePool.length === 0) {\n throw new UserError('None of the discussion\\'s original members are still active.');\n }\n\n let targetMembers: AdvisoryBoardMember[];\n if (targetType === 'all') {\n targetMembers = candidatePool;\n } else if (targetType === 'specific') {\n if (!opts.selectedMemberId) {\n throw new UserError('targetType=specific requires selectedMemberId.');\n }\n const m = candidatePool.find((c) => c.id === opts.selectedMemberId);\n if (!m) {\n throw new UserError(`Member ${opts.selectedMemberId} is not part of this discussion.`);\n }\n targetMembers = [m];\n } else {\n // subset\n const ids = opts.selectedMemberIds ?? [];\n if (ids.length === 0) {\n throw new UserError('targetType=subset requires selectedMemberIds.');\n }\n const set = new Set(ids);\n targetMembers = candidatePool.filter((c) => set.has(c.id));\n if (targetMembers.length === 0) {\n throw new UserError('No members from selectedMemberIds are part of this discussion.');\n }\n }\n\n // Pre-round clarification gate (PLAN.md §4.3.1: must fire here too).\n opts.onProgress?.({ stage: 'orchestrating' });\n try {\n const gate = await analyzeConversation({\n question: discussion.question,\n rounds: discussion.rounds,\n members: activeMembers,\n currentTurn: discussion.totalTurns,\n settings: opts.settings,\n storage: opts.storage,\n discussionId: discussion.id,\n signal: opts.signal,\n });\n if (gate.action === 'request_user_input' && gate.userInputRequest) {\n discussion.pendingUserRequest = gate.userInputRequest;\n await opts.storage.saveDiscussion(discussion);\n return {\n discussion,\n totalCostUsd: 0,\n totalDurationMs: Date.now() - t0,\n gated: true,\n concluded: false,\n roundNumber: null,\n };\n }\n } catch (error) {\n logger.warn('[addFollowUpQuestion] pre-round gate failed (non-blocking):', error);\n }\n\n const lastRound = discussion.rounds[discussion.rounds.length - 1];\n const nextRoundNumber = (lastRound?.roundNumber ?? 0) + 1;\n\n // Build the round in-memory; only commit on full success so a partial\n // failure doesn't leave a half-baked round saved.\n const round: ConversationRound = {\n roundNumber: nextRoundNumber,\n responses: [],\n orchestratorDecision: {\n action: 'continue',\n reasoning: `Follow-up round ${nextRoundNumber}.`,\n consensusReached: false,\n confidence: 100,\n },\n startedAt: nowIso(),\n followUpQuestion: trimmed,\n followUpTargetType: targetType,\n };\n if (targetType === 'specific') round.followUpSelectedMemberId = targetMembers[0]!.id;\n if (targetType === 'subset') round.followUpSelectedMemberIds = targetMembers.map((m) => m.id);\n\n const conversationHistory = discussion.responses;\n const businessContext = await loadBusinessContextSafe(opts.storage);\n\n let totalCostUsd = 0;\n for (let i = 0; i < targetMembers.length; i++) {\n const member = targetMembers[i]!;\n opts.onProgress?.({\n stage: 'generating',\n memberName: member.name,\n index: i + 1,\n total: targetMembers.length,\n });\n\n // Strict: any failure aborts the whole follow-up round (per PLAN §1.5).\n const result = await runMember({\n question: discussion.question,\n member,\n roundNumber: nextRoundNumber,\n previousResponsesInRound: round.responses,\n conversationHistory,\n businessContext,\n settings: opts.settings,\n storage: opts.storage,\n discussionId: discussion.id,\n projectRoot: opts.projectRoot,\n signal: opts.signal,\n isFollowUp: true,\n followUpQuestion: trimmed,\n onActivity: (a) =>\n opts.onProgress?.({ stage: 'member_activity', memberName: member.name, ...a }),\n });\n\n round.responses.push(result.response);\n totalCostUsd += result.costUsd;\n\n opts.onProgress?.({\n stage: 'member_done',\n memberName: member.name,\n durationMs: result.durationMs,\n costUsd: result.costUsd,\n response: result.response,\n roundNumber: nextRoundNumber,\n });\n }\n\n round.completedAt = nowIso();\n\n // Post-round orchestrator analysis\n opts.onProgress?.({ stage: 'orchestrating' });\n try {\n const decision = await analyzeConversation({\n question: discussion.question,\n rounds: [...discussion.rounds, round],\n members: activeMembers,\n currentTurn: discussion.totalTurns + round.responses.length,\n settings: opts.settings,\n storage: opts.storage,\n discussionId: discussion.id,\n signal: opts.signal,\n });\n round.orchestratorDecision = decision;\n opts.onProgress?.({ stage: 'orchestrator_decided', decision, roundNumber: nextRoundNumber });\n } catch (error) {\n logger.warn('[addFollowUpQuestion] orchestrator failed (non-blocking):', error);\n }\n\n // Commit to the discussion record.\n const userResponse: UserResponse = {\n id: generateUUID(),\n requestId: `follow-up-${nextRoundNumber}`,\n content: trimmed,\n timestamp: nowIso(),\n roundNumber: nextRoundNumber,\n type: 'follow_up_question',\n prompt: trimmed,\n targetType,\n selectedMemberId: targetType === 'specific' ? targetMembers[0]!.id : undefined,\n selectedMemberIds: targetType === 'subset' ? targetMembers.map((m) => m.id) : undefined,\n };\n round.userResponse = userResponse;\n discussion.userResponses.push(userResponse);\n for (const r of round.responses) discussion.responses.push(r);\n discussion.totalTurns += round.responses.length;\n discussion.rounds.push(round);\n discussion.orchestratorState = updateOrchestratorState(\n discussion.orchestratorState,\n round.orchestratorDecision,\n round,\n );\n\n if (\n round.orchestratorDecision.action === 'request_user_input' &&\n round.orchestratorDecision.userInputRequest\n ) {\n discussion.pendingUserRequest = round.orchestratorDecision.userInputRequest;\n }\n\n let concluded = false;\n if (\n round.orchestratorDecision.action === 'conclude' ||\n discussion.totalTurns >= discussion.maxTurns\n ) {\n discussion.completedAt = nowIso();\n discussion.pendingUserRequest = undefined;\n concluded = true;\n }\n\n opts.onProgress?.({ stage: 'finalizing', round: nextRoundNumber });\n await opts.storage.saveDiscussion(discussion);\n\n // Phase 1.5: auto-ingest into the Knowledge Wiki on conclude.\n if (concluded) {\n await maybeAutoIngestOnConclude(discussion, activeMembers, opts.settings, opts.storage);\n }\n\n return {\n discussion,\n totalCostUsd,\n totalDurationMs: Date.now() - t0,\n gated: false,\n concluded,\n roundNumber: nextRoundNumber,\n };\n}\n","/**\r\n * Invoke one board member as a Claude Code sub-agent and parse their response\r\n * into a Response struct. Token usage from the JSON envelope is logged via\r\n * fireTokenUsage().\r\n */\r\nimport { extractText, runClaude, type ClaudeStreamEvent } from '../../llm/claude-code-runner.js';\r\nimport { logger } from '../logger.js';\r\nimport { generateUUID, nowIso } from '../utils.js';\r\nimport { safeParseJSONWithSchema } from '../parsing/safe-json.js';\r\nimport {\r\n type StructuredResponsePayload,\r\n structuredResponsePayloadSchema,\r\n} from '../parsing/llm-response-schemas.js';\r\nimport { memberAgentSlug } from '../../agents/emit-member-agent.js';\r\nimport type {\r\n AdvisoryBoardMember,\r\n AppSettings,\r\n Response,\r\n StorageService,\r\n TokenUsageLog,\r\n} from '../../storage/types.js';\r\nimport {\r\n buildMemberUserMessage,\r\n type BuildMessageOptions,\r\n} from './build-user-message.js';\r\n\r\nexport interface RunMemberOptions extends BuildMessageOptions {\r\n settings: AppSettings;\r\n /** Where the .claude/agents/ directory lives. Default: process.cwd(). */\r\n projectRoot?: string;\r\n /** Optional storage to log token usage. */\r\n storage?: StorageService;\r\n /** Discussion id for token logs. */\r\n discussionId?: string;\r\n signal?: AbortSignal;\r\n /**\r\n * Live progress callback. Fires when the member uses a tool or starts\r\n * generating its final response. UI uses this to update the typing-dots\r\n * label (\"searching the web…\", \"reading files…\", etc.).\r\n */\r\n onActivity?: (activity: { activity: string; tool?: string; detail?: string }) => void;\r\n}\r\n\r\nexport interface RunMemberResult {\r\n response: Response;\r\n /** What the member returned, parsed and validated. */\r\n structured: StructuredResponsePayload;\r\n /** True if we fell back to raw text after JSON parse failure. */\r\n parseFallback: boolean;\r\n /** Per-call cost in USD as reported by `claude --output-format json`. */\r\n costUsd: number;\r\n durationMs: number;\r\n}\r\n\r\nconst DEFAULT_TOOLS = ['WebSearch', 'WebFetch', 'Read', 'Grep', 'Glob'];\r\n\r\nexport async function runMember(opts: RunMemberOptions): Promise<RunMemberResult> {\r\n const userMessage = buildMemberUserMessage(opts);\r\n const slug = memberAgentSlug(opts.member.name);\r\n const tools = opts.member.allowedTools ?? DEFAULT_TOOLS;\r\n\r\n logger.debug('[runMember] dispatch', { slug, round: opts.roundNumber, msgLen: userMessage.length });\r\n\r\n const result = await runClaude({\r\n prompt: userMessage,\r\n agent: slug,\r\n model: pickMemberModel(opts.settings),\r\n allowedTools: tools,\r\n maxTurns: 5,\r\n maxBudgetUsd: opts.settings.perCallBudgetUsd,\r\n cwd: opts.projectRoot,\r\n signal: opts.signal,\r\n onEvent: opts.onActivity ? makeActivityForwarder(opts.onActivity) : undefined,\r\n });\r\n\r\n const text = extractText(result);\r\n const parsed = safeParseJSONWithSchema(text, structuredResponsePayloadSchema);\r\n\r\n let structured: StructuredResponsePayload;\r\n let parseFallback = false;\r\n if (parsed.success) {\r\n structured = parsed.data as StructuredResponsePayload;\r\n } else {\r\n logger.warn(`[runMember] ${opts.member.name}: structured parse failed (${parsed.error}); using raw text.`);\r\n parseFallback = true;\r\n structured = { response: text } as StructuredResponsePayload;\r\n }\r\n\r\n // Build the Response record\r\n const order = (opts.previousResponsesInRound?.length ?? 0) + 1;\r\n const turnNumber = (opts.conversationHistory?.length ?? 0) + order;\r\n const response: Response = {\r\n memberId: opts.member.id,\r\n memberName: opts.member.name,\r\n content: structured.response.trim() || `[${opts.member.name} returned no substantive content]`,\r\n timestamp: nowIso(),\r\n order,\r\n roundNumber: opts.roundNumber,\r\n turnNumber,\r\n isFollowUp: opts.roundNumber > 1 || !!opts.followUpQuestion,\r\n referencedMembers: extractReferencedMembers(structured.response, opts.previousResponsesInRound ?? []),\r\n sentiment: 'constructive',\r\n topicTags: (structured.keyPoints ?? []).slice(0, 3),\r\n structuredData: {\r\n keyPoints: structured.keyPoints,\r\n questionsForOthers: structured.questionsForOthers,\r\n actionSteps: structured.actionSteps,\r\n confidence: structured.confidence,\r\n },\r\n };\r\n\r\n // Token usage telemetry\r\n const costUsd = result.json?.cost_usd ?? 0;\r\n if (opts.storage) {\r\n fireTokenUsage(opts.storage, {\r\n discussionId: opts.discussionId,\r\n roundNumber: opts.roundNumber,\r\n turnNumber,\r\n operationType: 'member_response',\r\n model: typeof opts.settings.primaryModel === 'string' ? opts.settings.primaryModel : 'inherit',\r\n usage: result.json?.usage,\r\n costUsd,\r\n metadata: {\r\n memberName: opts.member.name,\r\n memberSlug: slug,\r\n parseFallback,\r\n },\r\n });\r\n }\r\n\r\n return { response, structured, parseFallback, costUsd, durationMs: result.durationMs };\r\n}\r\n\r\nfunction pickMemberModel(settings: AppSettings): string {\r\n return typeof settings.primaryModel === 'string' ? settings.primaryModel : 'inherit';\r\n}\r\n\r\nfunction extractReferencedMembers(text: string, peers: Response[]): string[] {\r\n if (!text || peers.length === 0) return [];\r\n const names = [...new Set(peers.map((p) => p.memberName.trim()).filter(Boolean))];\r\n const out: string[] = [];\r\n for (const name of names) {\r\n const escaped = name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\s+/g, '\\\\s+');\r\n const re = new RegExp(`(?:^|[^\\\\p{L}\\\\p{N}])${escaped}(?=$|[^\\\\p{L}\\\\p{N}])`, 'iu');\r\n if (re.test(text)) out.push(name);\r\n }\r\n return out;\r\n}\r\n\r\ninterface FireTokenUsageInput {\r\n discussionId?: string;\r\n roundNumber?: number;\r\n turnNumber?: number;\r\n operationType: string;\r\n model: string;\r\n usage:\r\n | {\r\n input_tokens?: number;\r\n output_tokens?: number;\r\n cache_creation_input_tokens?: number;\r\n cache_read_input_tokens?: number;\r\n }\r\n | undefined;\r\n costUsd: number;\r\n metadata?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Translate raw `claude --output-format stream-json` events into friendly\r\n * status strings the UI can display in the typing-dot bubble. We surface\r\n * tool-use events (searching the web, reading files, etc.) and the moment\r\n * the agent starts producing its final answer.\r\n */\r\nfunction makeActivityForwarder(\r\n onActivity: (a: { activity: string; tool?: string; detail?: string }) => void,\r\n): (event: ClaudeStreamEvent) => void {\r\n // Don't fire the same activity twice in a row.\r\n let lastActivity: string | null = null;\r\n const emit = (activity: string, tool?: string, detail?: string) => {\r\n if (activity === lastActivity) return;\r\n lastActivity = activity;\r\n onActivity({ activity, tool, detail });\r\n };\r\n\r\n return (event) => {\r\n if (event.type === 'system' && event.subtype === 'init') {\r\n emit('thinking…', undefined);\r\n return;\r\n }\r\n if (event.type !== 'assistant' || !event.message?.content) return;\r\n\r\n for (const block of event.message.content) {\r\n if (block.type === 'tool_use' && block.name) {\r\n const tool = block.name;\r\n const friendly = friendlyForTool(tool, block.input);\r\n emit(friendly.activity, tool, friendly.detail);\r\n return;\r\n }\r\n if (block.type === 'text' && typeof block.text === 'string' && block.text.trim().length > 0) {\r\n emit('writing response…');\r\n return;\r\n }\r\n }\r\n };\r\n}\r\n\r\nfunction friendlyForTool(tool: string, input?: Record<string, unknown>): {\r\n activity: string;\r\n detail?: string;\r\n} {\r\n const name = tool.toLowerCase();\r\n if (name === 'websearch') {\r\n const q = typeof input?.query === 'string' ? input.query : undefined;\r\n return { activity: 'searching the web…', detail: q };\r\n }\r\n if (name === 'webfetch') {\r\n const u = typeof input?.url === 'string' ? input.url : undefined;\r\n return { activity: 'reading a web page…', detail: u };\r\n }\r\n if (name === 'read') {\r\n const path = typeof input?.file_path === 'string' ? input.file_path : undefined;\r\n return { activity: 'reading files…', detail: path };\r\n }\r\n if (name === 'grep') {\r\n const pat = typeof input?.pattern === 'string' ? input.pattern : undefined;\r\n return { activity: 'searching the codebase…', detail: pat };\r\n }\r\n if (name === 'glob') {\r\n return { activity: 'searching the codebase…' };\r\n }\r\n return { activity: `using ${tool}…`, detail: undefined };\r\n}\r\n\r\nfunction fireTokenUsage(storage: StorageService, input: FireTokenUsageInput): void {\r\n const promptTokenCount =\r\n (input.usage?.input_tokens ?? 0) +\r\n (input.usage?.cache_creation_input_tokens ?? 0) +\r\n (input.usage?.cache_read_input_tokens ?? 0);\r\n const candidatesTokenCount = input.usage?.output_tokens ?? 0;\r\n const log: TokenUsageLog = {\r\n id: generateUUID(),\r\n discussionId: input.discussionId,\r\n roundNumber: input.roundNumber,\r\n turnNumber: input.turnNumber,\r\n feature: 'discussions',\r\n operationType: input.operationType,\r\n model: input.model,\r\n tokens: {\r\n promptTokenCount,\r\n candidatesTokenCount,\r\n cacheReadTokens: input.usage?.cache_read_input_tokens,\r\n cacheCreationTokens: input.usage?.cache_creation_input_tokens,\r\n totalTokenCount: promptTokenCount + candidatesTokenCount,\r\n },\r\n costUsd: input.costUsd,\r\n createdAt: nowIso(),\r\n metadata: input.metadata,\r\n };\r\n storage.appendTokenUsageLog(log).catch((err) => {\r\n logger.debug('[runMember] token-usage log failed (non-blocking):', err);\r\n });\r\n}\r\n","/**\r\n * Build the user message we send into a member sub-agent.\r\n *\r\n * The member's identity / voice / persona / output contract live in their\r\n * `.claude/agents/<slug>.md` body (rendered at init time). The user message\r\n * carries only the per-call payload: round mode, the original question,\r\n * previous responses, business context, and any follow-up prompt.\r\n *\r\n * Mode prefixes are documented in the agent file body so the agent knows\r\n * which response shape to produce:\r\n * [ROUND: 1 | INITIAL]\r\n * [ROUND: N | MULTI_TURN | IS_FOLLOW_UP: true|false]\r\n * [FOLLOWUP_QUESTION]\r\n * [SPARRING]\r\n */\r\n\r\nimport type { AdvisoryBoardMember, BusinessContext, Response } from '../../storage/types.js';\r\n\r\nexport interface BuildMessageOptions {\r\n question: string;\r\n member: AdvisoryBoardMember;\r\n roundNumber: number;\r\n /** Responses produced earlier in this same round (siblings — same round). */\r\n previousResponsesInRound?: Response[];\r\n /** Full prior-round responses across the whole discussion. */\r\n conversationHistory?: Response[];\r\n /** Business context from storage to inject. */\r\n businessContext?: BusinessContext[];\r\n /** Was the user's original message a follow-up question? */\r\n isFollowUp?: boolean;\r\n /** Free-form follow-up question to put at the bottom (overrides original q). */\r\n followUpQuestion?: string;\r\n}\r\n\r\nconst MAX_BUSINESS_CONTEXT_CHARS = 3500;\r\nconst MAX_BUSINESS_CONTEXT_ITEMS = 12;\r\nconst MAX_HISTORY_RESPONSE_CHARS = 1200;\r\n\r\nexport function buildMemberUserMessage(opts: BuildMessageOptions): string {\r\n const lines: string[] = [];\r\n\r\n // Mode prefix\r\n if (opts.roundNumber === 1 && !opts.followUpQuestion) {\r\n lines.push(`[ROUND: 1 | INITIAL]`);\r\n } else if (opts.followUpQuestion) {\r\n lines.push(`[FOLLOWUP_QUESTION]`);\r\n } else {\r\n lines.push(`[ROUND: ${opts.roundNumber} | MULTI_TURN | IS_FOLLOW_UP: ${opts.isFollowUp ? 'true' : 'false'}]`);\r\n }\r\n lines.push('');\r\n\r\n // Original question\r\n lines.push('## Original question');\r\n lines.push(opts.question.trim());\r\n lines.push('');\r\n\r\n // Follow-up (if present)\r\n if (opts.followUpQuestion) {\r\n lines.push('## User follow-up question');\r\n lines.push(opts.followUpQuestion.trim());\r\n lines.push('');\r\n }\r\n\r\n // Business context\r\n const contextBlock = renderBusinessContext(opts.businessContext ?? []);\r\n if (contextBlock) {\r\n lines.push('## Business context');\r\n lines.push(contextBlock);\r\n lines.push('');\r\n }\r\n\r\n // Conversation history (prior rounds)\r\n if (opts.conversationHistory && opts.conversationHistory.length > 0) {\r\n lines.push('## Prior rounds (chronological)');\r\n for (const r of opts.conversationHistory) {\r\n const truncated = truncate(r.content, MAX_HISTORY_RESPONSE_CHARS);\r\n lines.push(`**${r.memberName}** (round ${r.roundNumber}):`);\r\n lines.push(truncated);\r\n lines.push('');\r\n }\r\n }\r\n\r\n // Previous responses in this round (siblings)\r\n if (opts.previousResponsesInRound && opts.previousResponsesInRound.length > 0) {\r\n lines.push('## Other members in this round so far');\r\n for (const r of opts.previousResponsesInRound) {\r\n const truncated = truncate(r.content, MAX_HISTORY_RESPONSE_CHARS);\r\n lines.push(`**${r.memberName}**:`);\r\n lines.push(truncated);\r\n lines.push('');\r\n }\r\n }\r\n\r\n // Closing nudge\r\n lines.push('---');\r\n lines.push(\r\n `Respond as ${opts.member.name} per your output contract — return ONLY the JSON object specified in your system prompt. Start with \\`{\\` and end with \\`}\\`. No prose, no fences.`,\r\n );\r\n\r\n return lines.join('\\n');\r\n}\r\n\r\nfunction renderBusinessContext(contexts: BusinessContext[]): string {\r\n const active = contexts.filter((c) => c.isActive);\r\n if (active.length === 0) return '';\r\n const sorted = [...active].sort((a, b) => {\r\n if (b.confidence !== a.confidence) return b.confidence - a.confidence;\r\n return b.updatedAt.localeCompare(a.updatedAt);\r\n });\r\n const limited = sorted.slice(0, MAX_BUSINESS_CONTEXT_ITEMS);\r\n const grouped = limited.reduce<Record<string, BusinessContext[]>>((acc, ctx) => {\r\n (acc[ctx.category] ??= []).push(ctx);\r\n return acc;\r\n }, {});\r\n const sections = Object.entries(grouped).map(([cat, list]) => {\r\n const items = list.map((ctx) => `- **${ctx.title}**: ${ctx.description}`).join('\\n');\r\n return `### ${cat.toUpperCase()}\\n${items}`;\r\n });\r\n const full = sections.join('\\n\\n');\r\n return full.length > MAX_BUSINESS_CONTEXT_CHARS\r\n ? full.slice(0, MAX_BUSINESS_CONTEXT_CHARS) + '\\n\\n[business context trimmed]'\r\n : full;\r\n}\r\n\r\nfunction truncate(text: string, max: number): string {\r\n if (text.length <= max) return text;\r\n return `${text.slice(0, max)}\\n…[truncated ${text.length - max} chars]`;\r\n}\r\n","/**\r\n * Orchestrator — decides what happens after a round.\r\n *\r\n * Implementation: a one-shot `claude -p` call (no sub-agent) carrying the\r\n * full orchestrator prompt. The prompt asks for a strict JSON contract that\r\n * we validate with `orchestratorDecisionPayloadSchema`. Deterministic\r\n * post-processing of consensus / repetition / topic exploration runs in JS\r\n * after the model decision — same as sage-council/src/lib/orchestrator.ts.\r\n */\r\nimport { runClaude, extractText } from '../../llm/claude-code-runner.js';\r\nimport { logger } from '../logger.js';\r\nimport { generateUUID, nowIso } from '../utils.js';\r\nimport { safeParseJSON, safeParseJSONWithSchema } from '../parsing/safe-json.js';\r\nimport { orchestratorDecisionPayloadSchema } from '../parsing/llm-response-schemas.js';\r\nimport type {\r\n AdvisoryBoardMember,\r\n AppSettings,\r\n ConversationRound,\r\n OrchestratorDecision,\r\n OrchestratorState,\r\n Response,\r\n StorageService,\r\n UserInteractionRequest,\r\n} from '../../storage/types.js';\r\n\r\nexport interface AnalyzeOptions {\r\n question: string;\r\n rounds: ConversationRound[];\r\n members: AdvisoryBoardMember[];\r\n currentTurn: number;\r\n settings: AppSettings;\r\n storage?: StorageService;\r\n discussionId?: string;\r\n signal?: AbortSignal;\r\n}\r\n\r\nexport async function analyzeConversation(opts: AnalyzeOptions): Promise<OrchestratorDecision> {\r\n const context = buildOrchestratorContext(opts);\r\n logger.debug('[orchestrator] analyzing', {\r\n rounds: opts.rounds.length,\r\n turn: opts.currentTurn,\r\n members: opts.members.length,\r\n });\r\n\r\n try {\r\n // Phase 1.5: open Read/Grep/Glob so the orchestrator can ground its\r\n // decision in the Knowledge Wiki when one is present. Settings flag\r\n // `knowledgeWiki.exposeToOrchestrator` defaults true; toggling false\r\n // collapses to the old empty-allowlist behaviour.\r\n const expose = opts.settings.knowledgeWiki?.exposeToOrchestrator !== false;\r\n const orchestratorTools = expose ? ['Read', 'Grep', 'Glob'] : [];\r\n const result = await runClaude({\r\n prompt: context,\r\n // No --agent: this is a one-shot orchestrator call without persona\r\n model: typeof opts.settings.fastModel === 'string' ? opts.settings.fastModel : 'haiku',\r\n allowedTools: orchestratorTools,\r\n maxTurns: 1,\r\n maxBudgetUsd: opts.settings.perCallBudgetUsd,\r\n signal: opts.signal,\r\n timeoutMs: 90_000,\r\n });\r\n\r\n const text = extractText(result);\r\n return parseDecision(text, opts);\r\n } catch (error) {\r\n logger.warn('[orchestrator] failed; using fallback decision:', error);\r\n return fallbackDecision(opts);\r\n }\r\n}\r\n\r\nexport function buildOrchestratorContext(opts: AnalyzeOptions): string {\r\n const { question, rounds, members, currentTurn, settings } = opts;\r\n const activeMembers = members.filter((m) => m.isActive);\r\n\r\n const history: string[] = [];\r\n rounds.forEach((round, index) => {\r\n history.push(`### Round ${index + 1}`);\r\n for (const r of round.responses) {\r\n const preview = r.content.length > 240 ? `${r.content.slice(0, 240)}...` : r.content;\r\n history.push(`- **${r.memberName}**: ${preview}`);\r\n }\r\n });\r\n\r\n return [\r\n 'You are an AI conversation orchestrator managing an advisory board discussion.',\r\n '',\r\n `## Original question`,\r\n `\"${question}\"`,\r\n '',\r\n `## Active members`,\r\n ...activeMembers.map((m) => `- ${m.name} (${m.title}): ${m.expertise.join(', ')}`),\r\n '',\r\n `## Progress`,\r\n `- Current turn: ${currentTurn}`,\r\n `- Maximum turns: ${settings.maxTurnsPerDiscussion}`,\r\n `- Consensus threshold: ${settings.consensusThreshold}%`,\r\n '',\r\n `## Conversation so far`,\r\n history.join('\\n') || '(no rounds yet)',\r\n '',\r\n '## Your task',\r\n 'Analyze the conversation and decide what should happen next. Consider:',\r\n '1. CONSENSUS — are members converging on key points?',\r\n '2. TOPIC EXPLORATION — are new valuable insights still emerging?',\r\n '3. REPETITION — are members starting to repeat themselves?',\r\n '4. QUALITY — is the discussion adding value?',\r\n '5. USER INPUT — does the board need clarification, a decision, or info from the user?',\r\n '',\r\n '## Output contract',\r\n 'Return ONLY a raw JSON object — no fences, no commentary. Start with `{`, end with `}`.',\r\n '',\r\n '{',\r\n ' \"action\": \"continue\" | \"conclude\" | \"redirect\" | \"request_user_input\",',\r\n ' \"reasoning\": \"Your detailed reasoning\",',\r\n ' \"nextSpeaker\": \"(optional) suggested next speaker name\",',\r\n ' \"suggestedDirection\": \"(optional) topic to redirect to\",',\r\n ' \"consensusReached\": false,',\r\n ' \"confidence\": 75,',\r\n ' \"userInputRequest\": {',\r\n ' \"type\": \"clarification|decision|preference|information\",',\r\n ' \"question\": \"What the board needs from the user\",',\r\n ' \"context\": \"Why\",',\r\n ' \"requestingMembers\": [\"member names\"],',\r\n ' \"urgency\": \"low|medium|high\",',\r\n ' \"options\": [\"A\", \"B\"]',\r\n ' }',\r\n '}',\r\n '',\r\n 'Only include `userInputRequest` if action is \"request_user_input\". Be decisive but thoughtful — quality discussions are better than long ones.',\r\n ].join('\\n');\r\n}\r\n\r\nfunction parseDecision(text: string, opts: AnalyzeOptions): OrchestratorDecision {\r\n const strict = safeParseJSONWithSchema(text, orchestratorDecisionPayloadSchema);\r\n if (strict.success) return finalize(strict.data, opts);\r\n\r\n // Fall back to a permissive parse if the schema validate failed\r\n const loose = safeParseJSON<Record<string, unknown>>(text);\r\n if (loose.success && loose.data && typeof loose.data === 'object') {\r\n return finalize(loose.data, opts);\r\n }\r\n\r\n // Keyword fallback\r\n logger.warn(`[orchestrator] parse failed: ${strict.success ? '' : strict.error}; using keyword fallback.`);\r\n return fallbackDecision(opts, text);\r\n}\r\n\r\nfunction finalize(parsed: Record<string, unknown>, opts: AnalyzeOptions): OrchestratorDecision {\r\n const action =\r\n (typeof parsed.action === 'string' && ['continue', 'conclude', 'redirect', 'request_user_input'].includes(parsed.action)\r\n ? (parsed.action as OrchestratorDecision['action'])\r\n : opts.currentTurn >= opts.settings.maxTurnsPerDiscussion\r\n ? 'conclude'\r\n : 'continue');\r\n\r\n const decision: OrchestratorDecision = {\r\n action,\r\n reasoning: typeof parsed.reasoning === 'string' ? parsed.reasoning : 'No reasoning provided',\r\n nextSpeaker: typeof parsed.nextSpeaker === 'string' ? parsed.nextSpeaker : undefined,\r\n suggestedDirection: typeof parsed.suggestedDirection === 'string' ? parsed.suggestedDirection : undefined,\r\n consensusReached: parsed.consensusReached === true,\r\n confidence: typeof parsed.confidence === 'number' ? parsed.confidence : 50,\r\n };\r\n\r\n const rawReq = parsed.userInputRequest;\r\n if (decision.action === 'request_user_input' && rawReq && typeof rawReq === 'object') {\r\n const req = rawReq as Record<string, unknown>;\r\n decision.userInputRequest = {\r\n id: generateUUID(),\r\n type:\r\n typeof req.type === 'string' && ['clarification', 'decision', 'preference', 'information'].includes(req.type)\r\n ? (req.type as UserInteractionRequest['type'])\r\n : 'clarification',\r\n question: typeof req.question === 'string' ? req.question : 'The advisory board needs your input.',\r\n context: typeof req.context === 'string' ? req.context : 'Additional information is needed.',\r\n requestingMembers: Array.isArray(req.requestingMembers) ? req.requestingMembers.map(String) : [],\r\n urgency:\r\n typeof req.urgency === 'string' && ['low', 'medium', 'high'].includes(req.urgency)\r\n ? (req.urgency as UserInteractionRequest['urgency'])\r\n : 'medium',\r\n createdAt: nowIso(),\r\n options: Array.isArray(req.options) ? req.options.map(String) : undefined,\r\n };\r\n }\r\n\r\n return decision;\r\n}\r\n\r\nfunction fallbackDecision(opts: AnalyzeOptions, text?: string): OrchestratorDecision {\r\n const lower = (text ?? '').toLowerCase();\r\n const shouldConclude =\r\n lower.includes('conclude') || lower.includes('end the discussion') || opts.currentTurn >= opts.settings.maxTurnsPerDiscussion;\r\n return {\r\n action: shouldConclude ? 'conclude' : 'continue',\r\n reasoning: 'Fallback decision (orchestrator unavailable or output unparseable).',\r\n consensusReached: lower.includes('consensus'),\r\n confidence: 50,\r\n };\r\n}\r\n\r\n// --------------------------------------------------------------------\r\n// Deterministic state derivation (post-processing after the LLM decision)\r\n// --------------------------------------------------------------------\r\n\r\nexport function updateOrchestratorState(\r\n current: OrchestratorState,\r\n decision: OrchestratorDecision,\r\n round: ConversationRound,\r\n): OrchestratorState {\r\n const consensus = analyzeConsensus(round.responses);\r\n const exploration = analyzeTopicExploration(round.responses);\r\n const repetition = detectRepetition(round.responses);\r\n return {\r\n phase: determinePhase(decision, current.phase),\r\n reasoning: decision.reasoning,\r\n consensusLevel: consensus,\r\n topicExploration: exploration,\r\n repetitionDetected: repetition,\r\n shouldContinue: decision.action === 'continue',\r\n nextSpeaker: decision.nextSpeaker,\r\n conversationQuality: assessQuality(consensus, exploration, repetition),\r\n };\r\n}\r\n\r\nfunction analyzeConsensus(responses: Response[]): number {\r\n if (responses.length === 0) return 0;\r\n const agreements = responses.filter((r) => {\r\n const c = r.content.toLowerCase();\r\n return c.includes('agree') || c.includes(' yes,') || c.includes('exactly');\r\n }).length;\r\n return Math.min(100, Math.round((agreements / responses.length) * 100));\r\n}\r\n\r\nfunction analyzeTopicExploration(responses: Response[]): number {\r\n const unique = new Set<string>();\r\n for (const r of responses) {\r\n for (const w of r.content.toLowerCase().split(/\\s+/)) {\r\n if (w.length > 6) unique.add(w);\r\n }\r\n }\r\n return Math.min(100, unique.size * 10);\r\n}\r\n\r\nfunction detectRepetition(responses: Response[]): boolean {\r\n if (responses.length < 2) return false;\r\n const contents = responses.map((r) => r.content.toLowerCase());\r\n for (let i = 0; i < contents.length; i++) {\r\n for (let j = i + 1; j < contents.length; j++) {\r\n const a = contents[i];\r\n const b = contents[j];\r\n if (typeof a !== 'string' || typeof b !== 'string') continue;\r\n if (jaccard(a, b) > 0.7) return true;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\nfunction jaccard(a: string, b: string): number {\r\n const wa = new Set(a.split(/\\s+/));\r\n const wb = new Set(b.split(/\\s+/));\r\n if (wa.size === 0 || wb.size === 0) return 0;\r\n let inter = 0;\r\n for (const w of wa) if (wb.has(w)) inter++;\r\n return inter / new Set([...wa, ...wb]).size;\r\n}\r\n\r\nfunction determinePhase(\r\n decision: OrchestratorDecision,\r\n currentPhase: OrchestratorState['phase'],\r\n): OrchestratorState['phase'] {\r\n if (decision.action === 'conclude') return 'concluded';\r\n if (decision.consensusReached) return 'consensus';\r\n if (currentPhase === 'initial') return 'continuation';\r\n return currentPhase;\r\n}\r\n\r\nfunction assessQuality(\r\n consensus: number,\r\n exploration: number,\r\n repetition: boolean,\r\n): OrchestratorState['conversationQuality'] {\r\n const score = (consensus + exploration) / 2 - (repetition ? 20 : 0);\r\n if (score >= 80) return 'excellent';\r\n if (score >= 60) return 'good';\r\n if (score >= 40) return 'fair';\r\n return 'poor';\r\n}\r\n\r\nexport function createInitialOrchestratorState(): OrchestratorState {\r\n return {\r\n phase: 'initial',\r\n reasoning: 'Starting new multi-turn discussion.',\r\n consensusLevel: 0,\r\n topicExploration: 100,\r\n repetitionDetected: false,\r\n shouldContinue: true,\r\n conversationQuality: 'good',\r\n };\r\n}\r\n","/**\n * Summarizer — distills a concluded (or in-progress) discussion into a\n * `ConversationSummary` payload.\n *\n * Implementation mirrors `orchestrator.ts`: one-shot `claude -p` on the\n * `fastModel` (Haiku by default), strict JSON contract validated against\n * `conversationSummaryPayloadSchema`. Deterministic post-processing fills in\n * defaults so the resulting object always satisfies `ConversationSummary`.\n *\n * This is the seed for Phase 1.5's auto-ingest hook\n * (see `docs/development/KNOWLEDGE_WIKI.md` §16): on discussion conclude, the summary +\n * full transcript become `raw/summaries/<short>.md` and `raw/discussions/<short>.md`,\n * then ingest creates/updates wiki pages from them.\n */\nimport { runClaude, extractText } from '../../llm/claude-code-runner.js';\nimport { logger } from '../logger.js';\nimport { nowIso } from '../utils.js';\nimport { safeParseJSON, safeParseJSONWithSchema } from '../parsing/safe-json.js';\nimport { conversationSummaryPayloadSchema } from '../parsing/llm-response-schemas.js';\nimport { ContractError, ModelError } from '../errors.js';\nimport type {\n AdvisoryBoardMember,\n AppSettings,\n ConversationSummary,\n Discussion,\n ParticipationMetrics,\n Response,\n} from '../../storage/types.js';\n\nexport interface SummarizeOptions {\n discussion: Discussion;\n members: AdvisoryBoardMember[];\n settings: AppSettings;\n signal?: AbortSignal;\n}\n\nexport async function summarizeDiscussion(opts: SummarizeOptions): Promise<ConversationSummary> {\n const { discussion, members, settings, signal } = opts;\n\n if (discussion.rounds.length === 0) {\n // Defensive — the command-layer already guards this, but make the engine safe too.\n return deterministicFallback(discussion, members, 'Discussion has no rounds.');\n }\n\n const prompt = buildSummaryPrompt(discussion, members);\n logger.debug('[summarize] requesting summary', {\n discussionId: discussion.id,\n rounds: discussion.rounds.length,\n members: members.length,\n });\n\n let text: string;\n try {\n const result = await runClaude({\n prompt,\n model: typeof settings.fastModel === 'string' ? settings.fastModel : 'haiku',\n allowedTools: [],\n maxTurns: 1,\n maxBudgetUsd: settings.perCallBudgetUsd,\n signal,\n timeoutMs: 120_000,\n });\n text = extractText(result);\n } catch (error) {\n throw new ModelError(\n `Summary generation failed: ${error instanceof Error ? error.message : String(error)}`,\n 'Re-run with `aab discuss summarize <id> --force` or check `aab doctor` for the claude CLI.',\n );\n }\n\n return parseSummary(text, discussion, members);\n}\n\n// ----------------------------------------------------------------------------\n// Prompt\n// ----------------------------------------------------------------------------\n\nfunction buildSummaryPrompt(discussion: Discussion, members: AdvisoryBoardMember[]): string {\n const memberRoster = members\n .map((m) => `- ${m.name} (${m.title}): ${m.expertise.join(', ')}`)\n .join('\\n');\n\n // Cap per-response at 6000 chars (~1500 tokens) and use an explicit editorial\n // truncation marker. Earlier versions used `…` at 1200 chars, which Haiku\n // mistook for a mid-stream cutoff and refused to summarize (\"transcript\n // appears to be incomplete\"). The explicit `[…truncated for summarization…]`\n // marker tells the model this was an editorial choice, not corruption.\n const PER_RESPONSE_CAP = 6000;\n const history: string[] = [];\n discussion.rounds.forEach((round) => {\n history.push(`### Round ${round.roundNumber}`);\n if (round.followUpQuestion) history.push(`(follow-up: \"${round.followUpQuestion}\")`);\n for (const r of round.responses) {\n const preview =\n r.content.length > PER_RESPONSE_CAP\n ? `${r.content.slice(0, PER_RESPONSE_CAP)}\\n\\n[…truncated for summarization — full response in the raw discussion file…]`\n : r.content;\n history.push(`**${r.memberName}** (turn ${r.turnNumber}):`);\n history.push(preview);\n history.push('');\n }\n if (round.orchestratorDecision) {\n history.push(\n `_orchestrator → ${round.orchestratorDecision.action} · confidence ${round.orchestratorDecision.confidence}%_`,\n );\n }\n history.push('');\n });\n\n return [\n 'You are a senior analyst summarizing a multi-round advisory-board discussion.',\n '',\n '## Original question',\n `\"${discussion.question}\"`,\n '',\n '## Board',\n memberRoster || '(no members listed)',\n '',\n '## Transcript',\n history.join('\\n').trim() || '(empty)',\n '',\n '## Your task',\n 'Read the full transcript and produce a faithful, decision-grade summary that captures:',\n '1. The 3-7 most important *substantive* points the board made (keyPoints).',\n '2. The claims members converged on (consensus).',\n '3. The places members openly disagreed or hedged (disagreements).',\n '4. The 3-5 concrete actions a reader could take from this discussion (actionableInsights).',\n '5. A per-member participation breakdown (topics each covered, qualitative influence 0-100).',\n '6. An `overallQuality` score 0-100 — penalise repetition, low-information bullets, and unanchored speculation; reward concreteness, well-cited claims, and productive disagreement.',\n '',\n 'Be terse and information-dense. Prefer specific claims over generic statements (\"Tesla\\'s gross margin slipped 4pp in Q2\" beats \"margins are a concern\"). Quote distinctive phrasing where useful.',\n '',\n '## Output contract',\n 'Return ONLY a raw JSON object — no fences, no commentary. Start with `{`, end with `}`.',\n '',\n '{',\n ' \"keyPoints\": [\"…\"],',\n ' \"consensus\": [\"…\"],',\n ' \"disagreements\": [\"…\"],',\n ' \"actionableInsights\": [\"…\"],',\n ' \"participationBreakdown\": [',\n ' { \"memberName\": \"Elon Musk\", \"topicsCovered\": [\"…\"], \"influence\": 70 }',\n ' ],',\n ' \"overallQuality\": 78',\n '}',\n '',\n 'Every member that spoke MUST appear in `participationBreakdown` with the exact `memberName` from the roster above.',\n ].join('\\n');\n}\n\n// ----------------------------------------------------------------------------\n// Parse + finalize\n// ----------------------------------------------------------------------------\n\nfunction parseSummary(\n text: string,\n discussion: Discussion,\n members: AdvisoryBoardMember[],\n): ConversationSummary {\n const strict = safeParseJSONWithSchema(text, conversationSummaryPayloadSchema);\n if (strict.success) return finalize(strict.data, discussion, members);\n\n const loose = safeParseJSON<Record<string, unknown>>(text);\n if (loose.success && loose.data && typeof loose.data === 'object') {\n return finalize(loose.data, discussion, members);\n }\n\n logger.warn(`[summarize] parse failed: ${strict.success ? '' : strict.error}; using deterministic fallback.`);\n return deterministicFallback(discussion, members, 'LLM summary unparseable.');\n}\n\nfunction finalize(\n parsed: Record<string, unknown>,\n discussion: Discussion,\n members: AdvisoryBoardMember[],\n): ConversationSummary {\n const keyPoints = asStringArray(parsed.keyPoints);\n const consensus = asStringArray(parsed.consensus);\n const disagreements = asStringArray(parsed.disagreements);\n const actionableInsights = asStringArray(parsed.actionableInsights);\n const overallQuality = clampNumber(parsed.overallQuality, 0, 100, 50);\n\n // Compute participation deterministically from the transcript, then merge\n // the LLM's qualitative fields (topicsCovered, influence) on top. The LLM\n // is unreliable at counting — we let it do what it's good at (themes,\n // qualitative influence) and compute the rest ourselves.\n const breakdown = computeParticipation(discussion, members);\n if (Array.isArray(parsed.participationBreakdown)) {\n for (const raw of parsed.participationBreakdown) {\n if (!raw || typeof raw !== 'object') continue;\n const row = raw as Record<string, unknown>;\n const name = typeof row.memberName === 'string' ? row.memberName : undefined;\n if (!name) continue;\n const target = breakdown.find((p) => p.memberName === name);\n if (!target) continue;\n const topics = asStringArray(row.topicsCovered);\n if (topics.length > 0) target.topicsCovered = topics;\n const influence = clampNumber(row.influence, 0, 100, NaN);\n if (Number.isFinite(influence)) target.influence = influence;\n }\n }\n\n if (keyPoints.length === 0 && consensus.length === 0 && disagreements.length === 0) {\n throw new ContractError(\n 'Summary returned no keyPoints, consensus, or disagreements — empty payload.',\n 'Try `aab discuss summarize <id> --force` again, or check `aab doctor`.',\n );\n }\n\n return {\n keyPoints,\n consensus,\n disagreements,\n actionableInsights,\n participationBreakdown: breakdown,\n overallQuality,\n generatedAt: nowIso(),\n };\n}\n\nfunction deterministicFallback(\n discussion: Discussion,\n members: AdvisoryBoardMember[],\n note: string,\n): ConversationSummary {\n return {\n keyPoints: [`Summary unavailable: ${note}`],\n consensus: [],\n disagreements: [],\n actionableInsights: [],\n participationBreakdown: computeParticipation(discussion, members),\n overallQuality: 0,\n generatedAt: nowIso(),\n };\n}\n\n// ----------------------------------------------------------------------------\n// Helpers\n// ----------------------------------------------------------------------------\n\nfunction computeParticipation(\n discussion: Discussion,\n members: AdvisoryBoardMember[],\n): ParticipationMetrics[] {\n const memberById = new Map(members.map((m) => [m.id, m]));\n const byId = new Map<string, { responses: Response[]; name: string }>();\n\n for (const r of discussion.responses) {\n const m = memberById.get(r.memberId);\n if (!m) {\n // Member may have been deleted since the discussion ran — still count\n // their contributions under whatever name appears in the response.\n const entry = byId.get(r.memberId) ?? { responses: [], name: r.memberName };\n entry.responses.push(r);\n byId.set(r.memberId, entry);\n continue;\n }\n const entry = byId.get(m.id) ?? { responses: [], name: m.name };\n entry.responses.push(r);\n byId.set(m.id, entry);\n }\n\n const out: ParticipationMetrics[] = [];\n for (const [memberId, { responses, name }] of byId) {\n const totalChars = responses.reduce((sum, r) => sum + r.content.length, 0);\n out.push({\n memberId,\n memberName: name,\n totalResponses: responses.length,\n averageLength: responses.length ? Math.round(totalChars / responses.length) : 0,\n topicsCovered: [],\n influence: 50,\n });\n }\n\n // Stable order: highest participation first, then alphabetical.\n out.sort((a, b) => b.totalResponses - a.totalResponses || a.memberName.localeCompare(b.memberName));\n return out;\n}\n\nfunction asStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value\n .map((v) => (typeof v === 'string' ? v.trim() : String(v ?? '').trim()))\n .filter((s) => s.length > 0);\n}\n\nfunction clampNumber(value: unknown, min: number, max: number, fallback: number): number {\n const n = typeof value === 'number' ? value : Number(value);\n if (!Number.isFinite(n)) return fallback;\n return Math.max(min, Math.min(max, n));\n}\n","/**\n * Wiki ingest pipeline.\n *\n * Phases (per `docs/development/KNOWLEDGE_WIKI.md` §15.1):\n * 1. Resolve the source → write to `raw/<bucket>/`.\n * 2. Manifest dedup check (skip if hash exists, unless `force`).\n * 3. Run the ingest agent (one `runClaude` call with `Read,Grep,Glob,Write,Edit`).\n * 4. Parse the agent's JSON output.\n * 5. Rebuild slug-map in `wiki/index.md`.\n * 6. Append manifest entry atomically.\n */\nimport {\n copyFileSync,\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n appendFileSync,\n statSync,\n} from 'node:fs';\nimport { basename, dirname, extname, join, relative } from 'node:path';\nimport { paths, ensureWikiDirs, type ResolvedWorkspace } from '../../storage/paths.js';\nimport { runClaude, extractText } from '../../llm/claude-code-runner.js';\nimport { safeParseJSON } from '../parsing/safe-json.js';\nimport { logger } from '../logger.js';\nimport { nowIso } from '../utils.js';\nimport { ModelError, UserError } from '../errors.js';\nimport {\n hash6,\n sha256Hex,\n humanizeSlug,\n walkWikiPages,\n toPosix,\n type PageType,\n} from './page.js';\nimport {\n emptyManifest,\n loadManifest,\n saveManifest,\n appendEntry,\n newEntry,\n findEntryByHash,\n type ManifestEntry,\n type ManifestSourceType,\n} from './manifest.js';\nimport { buildSlugMap, writeSlugMapToIndex } from './slug-map.js';\nimport { emitWikiSkeleton } from './schema-emitter.js';\nimport { buildIngestPrompt } from '../prompts/skill-ingest.js';\nimport type { AppSettings, Discussion, StorageService, ClaudeModel, ClaudeModelAlias } from '../../storage/types.js';\nimport { renderDiscussionMarkdown } from '../../ui/render-discussion-markdown.js';\n\nexport interface IngestResult {\n rawPath: string;\n rawRelPath: string;\n producedPages: string[];\n updatedPages: string[];\n skipped: string[];\n notes?: string;\n costUsd: number;\n alreadyIngested?: boolean;\n warning?: string;\n entryId?: string;\n}\n\ninterface IngestCore {\n workspace: ResolvedWorkspace;\n settings: AppSettings;\n rawPath: string;\n rawRelPath: string;\n sourceType: ManifestSourceType;\n hash: string;\n originalName?: string;\n url?: string;\n discussionId?: string;\n hintType?: PageType;\n inlineBody?: string;\n force?: boolean;\n modelOverride?: string;\n}\n\nasync function runIngestCore(core: IngestCore): Promise<IngestResult> {\n const p = paths(core.workspace.root);\n ensureWikiDirs(core.workspace.root);\n // Make sure the schema + index exist before the agent reads them.\n emitWikiSkeleton({ workspaceRoot: core.workspace.root });\n\n // Dedup check\n const manifest = loadManifest(p.manifest);\n if (!core.force) {\n const existing = findEntryByHash(manifest, core.hash);\n if (existing) {\n return {\n rawPath: core.rawPath,\n rawRelPath: core.rawRelPath,\n producedPages: existing.producedPages,\n updatedPages: existing.updatedPages,\n skipped: existing.userEditedPagesSkipped ?? [],\n notes: existing.notes,\n costUsd: 0,\n alreadyIngested: true,\n entryId: existing.id,\n };\n }\n }\n\n const wikiKnowledgeMd = existsSync(p.wikiKnowledge) ? readFileSync(p.wikiKnowledge, 'utf8') : '';\n const wikiIndexMd = existsSync(p.wikiIndex) ? readFileSync(p.wikiIndex, 'utf8') : '';\n const prompt = buildIngestPrompt({\n rawPath: core.rawPath,\n rawRelPath: core.rawRelPath,\n sourceType: core.sourceType,\n hintType: core.hintType,\n wikiKnowledgeMd,\n wikiIndexMd,\n inlineBody: core.inlineBody,\n });\n\n const model = pickModel(core.settings, core.modelOverride);\n logger.debug('[ingest] starting', { rawPath: core.rawPath, hash: core.hash, model });\n\n let text: string;\n let costUsd = 0;\n try {\n const result = await runClaude({\n prompt,\n model,\n allowedTools: ['Read', 'Grep', 'Glob', 'Write', 'Edit', 'WebFetch'],\n maxTurns: 30,\n cwd: core.workspace.root,\n maxBudgetUsd: core.settings.perCallBudgetUsd,\n timeoutMs: 5 * 60_000,\n });\n text = extractText(result);\n costUsd = result.json?.cost_usd ?? 0;\n } catch (error) {\n throw new ModelError(\n `Ingest LLM call failed: ${error instanceof Error ? error.message : String(error)}`,\n 'Check `aab doctor` and retry. If the source is private, try `aab knowledge ingest --paste` after copy-pasting the content.',\n );\n }\n\n const parsed = safeParseJSON<Record<string, unknown>>(text);\n let producedPages: string[] = [];\n let updatedPages: string[] = [];\n let skipped: string[] = [];\n let notes: string | undefined;\n let warning: string | undefined;\n if (parsed.success && parsed.data && typeof parsed.data === 'object') {\n const d = parsed.data;\n producedPages = asStringArray(d.producedPages).map((s) => toWikiPath(s, core.workspace.root)).filter(isContentPage);\n updatedPages = asStringArray(d.updatedPages).map((s) => toWikiPath(s, core.workspace.root)).filter(isContentPage);\n skipped = asStringArray(d.skipped).map((s) => toWikiPath(s, core.workspace.root)).filter(isContentPage);\n notes = typeof d.notes === 'string' ? d.notes : undefined;\n } else {\n // Heuristic fallback: scan for `wiki/...md` strings in the agent text.\n const re = /wiki\\/[a-z0-9-]+\\/[a-z0-9-]+\\.md/g;\n const seen = new Set<string>();\n let m: RegExpExecArray | null;\n while ((m = re.exec(text)) !== null) seen.add(m[0]!);\n producedPages = Array.from(seen);\n warning = 'Agent output did not contain a parseable JSON envelope; pages list is heuristic.';\n logger.warn('[ingest] non-JSON output, using fallback path scrape; raw:', text.slice(0, 400));\n }\n\n // Rebuild slug-map regardless of JSON outcome (defensive: ensures the\n // next ingest's cheap-pass works even if this one was partial).\n const map = buildSlugMap(p.wiki, core.workspace.root);\n writeSlugMapToIndex(p.wikiIndex, map);\n\n // Manifest entry\n const entry: ManifestEntry = newEntry({\n rawPath: core.rawRelPath,\n sourceType: core.sourceType,\n originalName: core.originalName,\n url: core.url,\n discussionId: core.discussionId,\n hash: core.hash,\n ingestModel: model,\n ingestCostUsd: costUsd,\n producedPages,\n updatedPages,\n userEditedPagesSkipped: skipped,\n notes,\n });\n appendEntry(p.manifest, entry);\n\n // Append to wiki/log.md (the agent may have done this; fallback for parse failures).\n try {\n if (warning) {\n appendFileSync(\n p.wikiLog,\n `${nowIso()} ingest ${core.rawRelPath} → (fallback) produced=[${producedPages.join(', ')}]\\n`,\n 'utf8',\n );\n }\n } catch {\n // best-effort\n }\n\n return {\n rawPath: core.rawPath,\n rawRelPath: core.rawRelPath,\n producedPages,\n updatedPages,\n skipped,\n notes,\n costUsd,\n warning,\n entryId: entry.id,\n };\n}\n\nfunction pickModel(settings: AppSettings, override?: string): string {\n if (override) return override;\n const v = settings.knowledgeWiki?.ingestModel ?? settings.fastModel;\n return typeof v === 'string' ? v : 'haiku';\n}\n\nfunction asStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.map((v) => (typeof v === 'string' ? v.trim() : '')).filter(Boolean);\n}\n\nfunction toWikiPath(input: string, workspaceRoot: string): string {\n let s = input.trim().replace(/\\\\/g, '/');\n // Strip any absolute prefix\n if (s.startsWith(workspaceRoot.replace(/\\\\/g, '/') + '/')) {\n s = s.slice(workspaceRoot.length + 1).replace(/\\\\/g, '/');\n }\n if (!s.endsWith('.md')) s += '.md';\n if (!s.startsWith('wiki/')) s = `wiki/${s}`;\n return s;\n}\n\n/** Filter wiki infrastructure files out of the manifest's producedPages list. */\nfunction isContentPage(wikiPath: string): boolean {\n const tail = wikiPath.replace(/^wiki\\//, '');\n return tail !== 'index.md' && tail !== 'log.md' && tail !== 'KNOWLEDGE.md';\n}\n\n// ---------------------------------------------------------------------------\n// File ingest\n// ---------------------------------------------------------------------------\n\nexport interface IngestFileOptions {\n path: string;\n workspace: ResolvedWorkspace;\n settings: AppSettings;\n force?: boolean;\n hintType?: PageType;\n modelOverride?: string;\n}\n\nexport async function ingestFile(opts: IngestFileOptions): Promise<IngestResult> {\n if (!existsSync(opts.path)) {\n throw new UserError(`ingest: file not found: ${opts.path}`);\n }\n const stats = statSync(opts.path);\n if (!stats.isFile()) {\n throw new UserError(`ingest: not a file: ${opts.path}`);\n }\n const buf = readFileSync(opts.path);\n const hash = sha256Hex(buf);\n const h6 = hash.slice(0, 6);\n const ext = extname(opts.path).toLowerCase() || '.md';\n const sanitizedName = sanitizeFilename(basename(opts.path, extname(opts.path)));\n const rawFilename = `${h6}-${sanitizedName}${ext}`;\n const p = paths(opts.workspace.root);\n ensureWikiDirs(opts.workspace.root);\n const rawPath = join(p.rawFiles, rawFilename);\n if (!existsSync(rawPath) || opts.force) {\n mkdirSync(dirname(rawPath), { recursive: true });\n writeFileSync(rawPath, buf);\n }\n const rawRelPath = toPosix(relative(opts.workspace.root, rawPath));\n // For text-based files, inline the body so the agent doesn't need to spend\n // a tool-call round-trip reading it.\n let inlineBody: string | undefined;\n if (['.md', '.txt', '.json', '.csv', '.yaml', '.yml'].includes(ext)) {\n try {\n inlineBody = buf.toString('utf8');\n } catch {\n inlineBody = undefined;\n }\n }\n return runIngestCore({\n workspace: opts.workspace,\n settings: opts.settings,\n rawPath,\n rawRelPath,\n sourceType: 'file',\n hash,\n originalName: basename(opts.path),\n hintType: opts.hintType,\n inlineBody,\n force: opts.force,\n modelOverride: opts.modelOverride,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Paste ingest\n// ---------------------------------------------------------------------------\n\nexport interface IngestPasteOptions {\n text: string;\n workspace: ResolvedWorkspace;\n settings: AppSettings;\n force?: boolean;\n hintType?: PageType;\n modelOverride?: string;\n}\n\nexport async function ingestPaste(opts: IngestPasteOptions): Promise<IngestResult> {\n const trimmed = opts.text.trim();\n if (!trimmed) throw new UserError('ingest: paste text is empty.');\n const hash = sha256Hex(trimmed);\n const p = paths(opts.workspace.root);\n ensureWikiDirs(opts.workspace.root);\n const ts = new Date().toISOString().slice(0, 16).replace(/[:T]/g, '-'); // yyyy-mm-dd-hhmm\n const snippet = humanizeSlug(trimmed.split(/\\s+/).slice(0, 6).join(' '), 40);\n const rawPath = join(p.rawPasted, `${ts}-${snippet}.md`);\n mkdirSync(dirname(rawPath), { recursive: true });\n writeFileSync(rawPath, trimmed + '\\n', 'utf8');\n const rawRelPath = toPosix(relative(opts.workspace.root, rawPath));\n return runIngestCore({\n workspace: opts.workspace,\n settings: opts.settings,\n rawPath,\n rawRelPath,\n sourceType: 'pasted',\n hash,\n hintType: opts.hintType,\n inlineBody: trimmed,\n force: opts.force,\n modelOverride: opts.modelOverride,\n });\n}\n\n// ---------------------------------------------------------------------------\n// URL ingest (Chunk 3)\n// ---------------------------------------------------------------------------\n\nexport interface IngestUrlOptions {\n url: string;\n workspace: ResolvedWorkspace;\n settings: AppSettings;\n force?: boolean;\n hintType?: PageType;\n modelOverride?: string;\n}\n\n/**\n * URL ingest: snapshot the URL via WebFetch (executed by the ingest agent),\n * write `raw/urls/<hash6>.md` + `<hash6>.meta.json`, then run the standard\n * ingest pipeline on the snapshot. The snapshot step itself is currently\n * skeleton: we record the URL and meta, and the agent fetches the body via\n * its WebFetch tool. Reference: `docs/development/KNOWLEDGE_WIKI.md` §15.1 step 1.\n */\nexport async function ingestUrl(opts: IngestUrlOptions): Promise<IngestResult> {\n const url = opts.url.trim();\n if (!/^https?:\\/\\//i.test(url)) {\n throw new UserError(`ingest: not a valid http(s) URL: ${url}`);\n }\n const p = paths(opts.workspace.root);\n ensureWikiDirs(opts.workspace.root);\n const canonical = canonicaliseUrl(url);\n const hash = sha256Hex(canonical);\n const h6 = hash.slice(0, 6);\n const rawPath = join(p.rawUrls, `${h6}.md`);\n const metaPath = join(p.rawUrls, `${h6}.meta.json`);\n if (!existsSync(rawPath) || opts.force) {\n // Stub body — the agent will WebFetch and rewrite this on its first turn.\n mkdirSync(dirname(rawPath), { recursive: true });\n writeFileSync(\n rawPath,\n [\n `# ${url}`,\n '',\n `> Snapshot pending — the ingest agent will fetch this URL via WebFetch on its first turn.`,\n `> URL: ${url}`,\n `> Fetched-at: ${nowIso()}`,\n '',\n ].join('\\n'),\n 'utf8',\n );\n writeFileSync(\n metaPath,\n JSON.stringify({ url, canonical, hash, fetchedAt: nowIso(), title: undefined }, null, 2) + '\\n',\n 'utf8',\n );\n }\n const rawRelPath = toPosix(relative(opts.workspace.root, rawPath));\n return runIngestCore({\n workspace: opts.workspace,\n settings: opts.settings,\n rawPath,\n rawRelPath,\n sourceType: 'url',\n hash,\n originalName: url,\n url,\n hintType: opts.hintType,\n force: opts.force,\n modelOverride: opts.modelOverride,\n });\n}\n\nfunction canonicaliseUrl(url: string): string {\n try {\n const u = new URL(url);\n u.hash = '';\n return u.toString();\n } catch {\n return url;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Discussion ingest (auto + backfill)\n// ---------------------------------------------------------------------------\n\nexport interface IngestDiscussionOptions {\n discussion: Discussion;\n workspace: ResolvedWorkspace;\n settings: AppSettings;\n storage: StorageService;\n force?: boolean;\n modelOverride?: string;\n}\n\nexport async function ingestDiscussionRaw(\n opts: IngestDiscussionOptions,\n): Promise<IngestResult> {\n const p = paths(opts.workspace.root);\n ensureWikiDirs(opts.workspace.root);\n\n // Render transcript markdown using the same renderer the export command uses.\n const transcriptMd = renderDiscussionMarkdown(opts.discussion);\n const summary = opts.discussion.summary;\n const humanized = humanizeSlug(opts.discussion.question) || `discussion-${opts.discussion.id.slice(0, 8)}`;\n const discPath = join(p.rawDiscussions, `${humanized}.md`);\n if (!existsSync(discPath) || opts.force) {\n mkdirSync(dirname(discPath), { recursive: true });\n writeFileSync(discPath, transcriptMd, 'utf8');\n }\n if (summary) {\n const sumPath = join(p.rawSummaries, `${humanized}.md`);\n if (!existsSync(sumPath) || opts.force) {\n mkdirSync(dirname(sumPath), { recursive: true });\n writeFileSync(sumPath, renderSummaryMarkdown(opts.discussion, summary), 'utf8');\n }\n }\n const rawRelPath = toPosix(relative(opts.workspace.root, discPath));\n const hash = sha256Hex(transcriptMd);\n return runIngestCore({\n workspace: opts.workspace,\n settings: opts.settings,\n rawPath: discPath,\n rawRelPath,\n sourceType: 'discussion',\n hash,\n originalName: opts.discussion.question,\n discussionId: opts.discussion.id,\n hintType: 'source-summary',\n inlineBody: transcriptMd,\n force: opts.force,\n modelOverride: opts.modelOverride,\n });\n}\n\nfunction renderSummaryMarkdown(\n d: Discussion,\n s: NonNullable<Discussion['summary']>,\n): string {\n const lines: string[] = [];\n lines.push(`# Summary — ${d.question}`);\n lines.push('');\n lines.push(`> Discussion \\`${d.id}\\` · ${d.rounds.length} round${d.rounds.length === 1 ? '' : 's'} · ${d.totalTurns} turn${d.totalTurns === 1 ? '' : 's'} · quality ${s.overallQuality}/100`);\n lines.push('');\n if (s.keyPoints.length > 0) {\n lines.push('## Key points');\n for (const p of s.keyPoints) lines.push(`- ${p}`);\n lines.push('');\n }\n if (s.consensus.length > 0) {\n lines.push('## Consensus');\n for (const p of s.consensus) lines.push(`- ${p}`);\n lines.push('');\n }\n if (s.disagreements.length > 0) {\n lines.push('## Disagreements');\n for (const p of s.disagreements) lines.push(`- ${p}`);\n lines.push('');\n }\n if (s.actionableInsights.length > 0) {\n lines.push('## Actionable insights');\n for (const p of s.actionableInsights) lines.push(`- ${p}`);\n lines.push('');\n }\n if (s.participationBreakdown.length > 0) {\n lines.push('## Participation');\n for (const r of s.participationBreakdown) {\n lines.push(`- **${r.memberName}** — ${r.totalResponses} response${r.totalResponses === 1 ? '' : 's'}, avg ${r.averageLength} chars, influence ${r.influence}`);\n }\n lines.push('');\n }\n return lines.join('\\n');\n}\n\nfunction sanitizeFilename(s: string): string {\n return s.replace(/[^A-Za-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 80) || 'source';\n}\n\n// Silence unused-import linter on `copyFileSync` (kept for future binary file copy)\nvoid copyFileSync;\nvoid emptyManifest;\nvoid saveManifest;\nvoid walkWikiPages;\nvoid hash6;\n","/**\n * Ingest skill prompt. Reference: `docs/development/KNOWLEDGE_WIKI.md` §15.1.\n *\n * The agent reads `wiki/KNOWLEDGE.md`, then `wiki/index.md` (slug-map), then\n * the source at `rawPath`. It creates/updates wiki pages with proper\n * frontmatter and `[[wikilinks]]`, then emits a JSON summary to stdout.\n */\n\nexport interface IngestPromptInput {\n rawPath: string;\n /** Forward-slash workspace-relative path of the raw source (for citations). */\n rawRelPath: string;\n wikiKnowledgeMd: string;\n wikiIndexMd: string;\n hintType?: string;\n sourceType: string;\n /** Optional pre-extracted text for sources we know we can give to the model\n * cheaply (paste, summary). When provided, the agent uses this instead of\n * re-reading the file. */\n inlineBody?: string;\n}\n\nexport function buildIngestPrompt(input: IngestPromptInput): string {\n const lines: string[] = [];\n lines.push('You are the wiki ingest agent for an AI advisory-board CLI.');\n lines.push('Your job: read ONE new source and update the user\\'s knowledge wiki.');\n lines.push('');\n lines.push('## Source to ingest');\n lines.push(`- Path: \\`${input.rawPath}\\``);\n lines.push(`- Workspace-relative: \\`${input.rawRelPath}\\``);\n lines.push(`- Source type: ${input.sourceType}`);\n if (input.hintType) lines.push(`- Suggested page type: ${input.hintType}`);\n lines.push('');\n if (input.inlineBody) {\n lines.push('## Source content (inlined for you)');\n lines.push('');\n lines.push('```');\n lines.push(truncateForPrompt(input.inlineBody, 8000));\n lines.push('```');\n lines.push('');\n }\n lines.push('## Wiki schema (`wiki/KNOWLEDGE.md`)');\n lines.push('');\n lines.push(input.wikiKnowledgeMd);\n lines.push('');\n lines.push('## Current wiki index (`wiki/index.md`)');\n lines.push('');\n lines.push('READ THIS FIRST — the `<!-- AAB:SLUG-MAP -->` section is your `[[wikilink]]` resolver and your cheap-pass page catalog.');\n lines.push('');\n lines.push(input.wikiIndexMd);\n lines.push('');\n lines.push('## Your procedure (follow exactly)');\n lines.push('1. Read the source at the path above (use the `Read` tool, or use the inlined content above if present).');\n lines.push('2. Read the wiki schema above and the wiki index above (the slug-map section is your resolver).');\n lines.push('3. Identify the 3-10 most important claims, entities, concepts, decisions.');\n lines.push('4. For each:');\n lines.push(' - Does a wiki page already exist for it? (Check the slug-map first; fall back to `Glob \\'wiki/**/<slug>.md\\'`.)');\n lines.push(' - If yes AND its frontmatter does NOT have `userEdited: true`: update the page (merge new info; preserve `[[wikilinks]]`; flag contradictions in body with `^[ambiguous]`).');\n lines.push(' - If yes AND `userEdited: true`: skip — record in the `skipped` field of your output.');\n lines.push(' - If no: create a new page. Pick the right type (concept | entity | decision | source-summary | comparison) and the right folder (`wiki/concepts/`, `wiki/entities/`, `wiki/decisions/`, `wiki/sources/`, `wiki/comparisons/`).');\n lines.push('5. ALWAYS create exactly one `wiki/sources/<humanized-slug>.md` for this source — even if the rest is small. This is the audit trail.');\n lines.push('6. Use `[[wikilinks]]` LIBERALLY in page bodies to connect to existing pages. Every connection compounds value.');\n lines.push(' - Allowed: `[[slug]]`, `[[slug|Display]]`, `[[slug#section-header]]`.');\n lines.push(' - NOT ALLOWED: `[[concepts/foo]]` (path-prefixed), `![[slug]]` (transclusion), `[[slug#^id]]` (block IDs).');\n lines.push('7. Frontmatter contract — every page MUST have:');\n lines.push(' ```yaml');\n lines.push(' ---');\n lines.push(' title: …');\n lines.push(' slug: <matches-filename-minus-md>');\n lines.push(' type: concept|entity|decision|source-summary|comparison');\n lines.push(' summary: ≤200-char one-line synopsis');\n lines.push(' tags: [free-form]');\n lines.push(' sources:');\n lines.push(` - ${input.rawRelPath}`);\n lines.push(' related:');\n lines.push(' - \"[[other-slug]]\"');\n lines.push(' confidence: high|medium|low');\n lines.push(' provenance: extracted|inferred|ambiguous');\n lines.push(' created: <yyyy-mm-dd>');\n lines.push(' updated: <yyyy-mm-dd>');\n lines.push(' userEdited: false');\n lines.push(' ---');\n lines.push(' ```');\n lines.push('8. DO NOT touch the `<!-- AAB:SLUG-MAP -->` section in `wiki/index.md` — the orchestrator regenerates it after your run.');\n lines.push('9. DO NOT touch any `<!-- AAB:BACKLINKS -->` section — lint owns those.');\n lines.push('10. Append ONE line to `wiki/log.md` summarising what you wrote: `<iso-timestamp> ingested <rawRelPath> → produced [...]; updated [...]`.');\n lines.push('11. NEVER write secrets, API keys, credentials, or anything that looks like one into a wiki page.');\n lines.push('');\n lines.push('## Output (return ONLY this raw JSON object — no fences, no commentary)');\n lines.push('');\n lines.push('Start with `{`, end with `}`:');\n lines.push('');\n lines.push('{');\n lines.push(' \"producedPages\": [\"wiki/concepts/foo.md\", ...], // newly created pages, workspace-relative paths');\n lines.push(' \"updatedPages\": [\"wiki/entities/company.md\", ...], // existing pages you modified');\n lines.push(' \"skipped\": [\"wiki/decisions/bar.md\", ...], // userEdited pages you skipped');\n lines.push(' \"notes\": \"Optional 1-2 sentence summary.\"');\n lines.push('}');\n return lines.join('\\n');\n}\n\nfunction truncateForPrompt(s: string, max: number): string {\n if (s.length <= max) return s;\n return s.slice(0, max) + '\\n\\n[…truncated for prompt — read the full file via Read if needed…]';\n}\n","/**\n * Sparring service (Phase 3) — 1:1 deep dives anchored at a specific\n * (member, round, turn) of an existing discussion. Ported from\n * sage-council/src/lib/sparring-service.ts and adapted to the CLI's\n * shell-out-to-claude model.\n *\n * Truncation budgets, multi-section prompt layout, deterministic head/tail\n * trimming with a `[…truncated N chars…]` marker, and the\n * researchModel → primaryModel fallback are preserved verbatim\n * (PLAN.md §4.3.15).\n */\nimport { extractText, runClaude, type ClaudeStreamEvent } from '../../llm/claude-code-runner.js';\nimport { logger } from '../logger.js';\nimport { generateUUID, nowIso } from '../utils.js';\nimport { memberAgentSlug } from '../../agents/emit-member-agent.js';\nimport type {\n AdvisoryBoardMember,\n AppSettings,\n Discussion,\n Response,\n SparringMessage,\n SparringSession,\n SparringSource,\n StorageService,\n TokenUsageLog,\n} from '../../storage/types.js';\nimport { buildSparringUserMessage } from './build-sparring-prompt.js';\n\nconst ANCHOR_PREVIEW_CHARS = 220;\nconst DEFAULT_TOOLS = ['WebSearch', 'WebFetch', 'Read', 'Grep', 'Glob'];\n\nexport interface SparringActivityEvent {\n activity: string;\n tool?: string;\n detail?: string;\n}\n\nexport interface OpenSparringOptions {\n discussion: Discussion;\n member: AdvisoryBoardMember;\n /** 1-based round number the anchor lives in. */\n anchorRoundNumber?: number;\n /** 1-based turn number the anchor lives in (within that round). */\n anchorTurnNumber?: number;\n title?: string;\n storage: StorageService;\n}\n\nexport interface OpenSparringResult {\n session: SparringSession;\n /** True when an existing session at the same (memberId, round, turn) was reused. */\n reused: boolean;\n}\n\n/**\n * Find or create the canonical sparring session for a (discussion, member,\n * anchor) triple. Sage-council uses getOrCreateSparringSession; we mirror that\n * shape so the UI's \"open the spar panel\" gesture is idempotent. If no anchor\n * is provided, we pick the member's most recent response in this discussion.\n */\nexport async function openSparringSession(opts: OpenSparringOptions): Promise<OpenSparringResult> {\n const anchor = pickAnchorResponse(opts.discussion, opts.member.id, opts.anchorRoundNumber, opts.anchorTurnNumber);\n if (!anchor) {\n throw new Error(\n `No response from ${opts.member.name} found in this discussion to anchor the sparring session on.`,\n );\n }\n\n const existing = await opts.storage.loadSparringSessionsForDiscussion(opts.discussion.id);\n const match = existing.find(\n (s) =>\n s.memberId === opts.member.id &&\n s.anchorRoundNumber === anchor.roundNumber &&\n s.anchorTurnNumber === anchor.turnNumber,\n );\n if (match) {\n return { session: match, reused: true };\n }\n\n const preview = anchor.content.slice(0, ANCHOR_PREVIEW_CHARS) + (anchor.content.length > ANCHOR_PREVIEW_CHARS ? '…' : '');\n const session: SparringSession = {\n id: generateUUID(),\n discussionId: opts.discussion.id,\n memberId: opts.member.id,\n memberName: opts.member.name,\n anchorRoundNumber: anchor.roundNumber,\n anchorTurnNumber: anchor.turnNumber,\n anchorResponsePreview: preview,\n title: opts.title,\n messages: [],\n createdAt: nowIso(),\n updatedAt: nowIso(),\n };\n await opts.storage.saveSparringSession(session);\n return { session, reused: false };\n}\n\nexport interface SendSparringMessageOptions {\n session: SparringSession;\n member: AdvisoryBoardMember;\n discussion: Discussion;\n userMessage: string;\n settings: AppSettings;\n storage: StorageService;\n /** Where the .claude/agents/ directory lives. Default: process.cwd(). */\n projectRoot?: string;\n signal?: AbortSignal;\n onActivity?: (event: SparringActivityEvent) => void;\n}\n\nexport interface SendSparringMessageResult {\n userMsg: SparringMessage;\n assistantMsg?: SparringMessage;\n error?: string;\n costUsd: number;\n durationMs: number;\n fellBackToPrimary: boolean;\n}\n\n/**\n * Append a user message to the session, run the deep-dive prompt, and persist\n * the assistant reply. Uses researchModel first; falls back to primaryModel\n * (no web grounding hint) on failure.\n */\nexport async function sendSparringMessage(opts: SendSparringMessageOptions): Promise<SendSparringMessageResult> {\n const trimmed = opts.userMessage.trim();\n if (!trimmed) {\n throw new Error('User message cannot be empty');\n }\n\n // 1) Save user message immediately.\n const userMsg: SparringMessage = {\n id: generateUUID(),\n sessionId: opts.session.id,\n role: 'user',\n content: trimmed,\n sources: [],\n createdAt: nowIso(),\n };\n await opts.storage.saveSparringMessage(opts.session.id, userMsg);\n opts.session.messages.push(userMsg);\n\n // 2) Anchor lookup (use stored preview if the original response is gone).\n const anchorResponse =\n findResponseInDiscussion(opts.discussion, opts.session.memberId, opts.session.anchorRoundNumber, opts.session.anchorTurnNumber)\n ?.content ?? opts.session.anchorResponsePreview;\n\n // 3) Build prompt with the new user message appended.\n const prompt = buildSparringUserMessage({\n member: opts.member,\n discussion: opts.discussion,\n anchorResponse,\n history: opts.session.messages.slice(0, -1), // exclude the just-pushed user message; rebuilder folds it in\n pendingUserMessage: trimmed,\n });\n\n // 4) Try research model first; fall back to primary on failure.\n const slug = memberAgentSlug(opts.member.name);\n const tools = opts.member.allowedTools ?? DEFAULT_TOOLS;\n const research = pickModel(opts.settings.researchModel, 'opus');\n const primary = pickModel(opts.settings.primaryModel, 'sonnet');\n\n const start = Date.now();\n let fellBackToPrimary = false;\n let text = '';\n let costUsd = 0;\n let error: string | undefined;\n let sources: SparringSource[] = [];\n\n const activityForwarder = opts.onActivity ? makeActivityForwarder(opts.onActivity) : undefined;\n\n try {\n const result = await runClaude({\n prompt,\n agent: slug,\n model: research,\n allowedTools: tools,\n maxTurns: 5,\n maxBudgetUsd: opts.settings.perCallBudgetUsd,\n cwd: opts.projectRoot,\n signal: opts.signal,\n onEvent: activityForwarder,\n });\n text = extractText(result).trim();\n costUsd = result.json?.cost_usd ?? 0;\n sources = extractSourcesFromText(text);\n if (!text) {\n throw new Error('Research-model call returned an empty response');\n }\n logTokenUsage(opts.storage, {\n discussionId: opts.discussion.id,\n operationType: 'sparring_response',\n model: typeof research === 'string' ? research : 'inherit',\n usage: result.json?.usage,\n costUsd,\n metadata: {\n memberName: opts.member.name,\n sessionId: opts.session.id,\n fellBackToPrimary: false,\n },\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.warn(`[sparring] Research model failed, falling back to primary: ${msg}`);\n fellBackToPrimary = true;\n try {\n const result = await runClaude({\n prompt,\n agent: slug,\n model: primary,\n allowedTools: tools,\n maxTurns: 5,\n maxBudgetUsd: opts.settings.perCallBudgetUsd,\n cwd: opts.projectRoot,\n signal: opts.signal,\n onEvent: activityForwarder,\n });\n text = extractText(result).trim();\n costUsd = result.json?.cost_usd ?? 0;\n sources = extractSourcesFromText(text);\n if (!text) {\n throw new Error('Primary-model fallback returned an empty response');\n }\n logTokenUsage(opts.storage, {\n discussionId: opts.discussion.id,\n operationType: 'sparring_response',\n model: typeof primary === 'string' ? primary : 'inherit',\n usage: result.json?.usage,\n costUsd,\n metadata: {\n memberName: opts.member.name,\n sessionId: opts.session.id,\n fellBackToPrimary: true,\n },\n });\n } catch (err2) {\n error = err2 instanceof Error ? err2.message : String(err2);\n }\n }\n\n const durationMs = Date.now() - start;\n\n if (error || !text) {\n return {\n userMsg,\n error: error ?? 'Model returned an empty response.',\n costUsd,\n durationMs,\n fellBackToPrimary,\n };\n }\n\n const assistantMsg: SparringMessage = {\n id: generateUUID(),\n sessionId: opts.session.id,\n role: 'assistant',\n content: text,\n sources,\n createdAt: nowIso(),\n };\n await opts.storage.saveSparringMessage(opts.session.id, assistantMsg);\n opts.session.messages.push(assistantMsg);\n\n return { userMsg, assistantMsg, costUsd, durationMs, fellBackToPrimary };\n}\n\nfunction pickAnchorResponse(\n discussion: Discussion,\n memberId: string,\n preferredRound?: number,\n preferredTurn?: number,\n): Response | undefined {\n const matches = discussion.responses.filter((r) => r.memberId === memberId);\n if (matches.length === 0) return undefined;\n\n if (typeof preferredRound === 'number' && typeof preferredTurn === 'number') {\n const exact = matches.find((r) => r.roundNumber === preferredRound && r.turnNumber === preferredTurn);\n if (exact) return exact;\n }\n if (typeof preferredRound === 'number') {\n const roundMatch = matches\n .filter((r) => r.roundNumber === preferredRound)\n .sort((a, b) => b.turnNumber - a.turnNumber)[0];\n if (roundMatch) return roundMatch;\n }\n // Default: latest response from this member.\n return matches.sort((a, b) =>\n b.roundNumber - a.roundNumber !== 0 ? b.roundNumber - a.roundNumber : b.turnNumber - a.turnNumber,\n )[0];\n}\n\nfunction findResponseInDiscussion(\n discussion: Discussion,\n memberId: string,\n round: number,\n turn: number,\n): Response | undefined {\n return discussion.responses.find(\n (r) => r.memberId === memberId && r.roundNumber === round && r.turnNumber === turn,\n );\n}\n\nfunction pickModel(setting: AppSettings['primaryModel'] | undefined, fallback: 'opus' | 'sonnet' | 'haiku'): string {\n if (typeof setting === 'string' && setting.length > 0) return setting;\n return fallback;\n}\n\n/**\n * Permissive URL scraper for citations the model may have inlined. We accept\n * markdown links `[Title](https://…)` first, then bare URLs as last resort.\n * Dedupes by URL. Capped at 5 sources to mirror sage-council.\n */\nfunction extractSourcesFromText(text: string): SparringSource[] {\n const out: SparringSource[] = [];\n const seen = new Set<string>();\n\n const mdLink = /\\[([^\\]]{1,160})\\]\\((https?:\\/\\/[^\\s)]+)\\)/g;\n let match;\n while ((match = mdLink.exec(text)) !== null && out.length < 5) {\n const url = match[2]!;\n if (!seen.has(url)) {\n seen.add(url);\n out.push({ title: match[1]!.trim() || 'Source', url });\n }\n }\n\n if (out.length < 5) {\n const bareUrl = /(?:^|[^\\]])(https?:\\/\\/[^\\s)\\]]+)/g;\n while ((match = bareUrl.exec(text)) !== null && out.length < 5) {\n const url = match[1]!.replace(/[.,;:!?]+$/, '');\n if (!seen.has(url)) {\n seen.add(url);\n out.push({ title: 'Source', url });\n }\n }\n }\n\n return out;\n}\n\nfunction makeActivityForwarder(\n onActivity: (a: SparringActivityEvent) => void,\n): (event: ClaudeStreamEvent) => void {\n let lastActivity: string | null = null;\n const emit = (activity: string, tool?: string, detail?: string) => {\n if (activity === lastActivity) return;\n lastActivity = activity;\n onActivity({ activity, tool, detail });\n };\n return (event) => {\n if (event.type === 'system' && event.subtype === 'init') {\n emit('thinking…');\n return;\n }\n if (event.type !== 'assistant' || !event.message?.content) return;\n for (const block of event.message.content) {\n if (block.type === 'tool_use' && block.name) {\n const name = block.name.toLowerCase();\n if (name === 'websearch') {\n const q = typeof block.input?.query === 'string' ? block.input.query : undefined;\n emit('searching the web…', block.name, q);\n return;\n }\n if (name === 'webfetch') {\n const u = typeof block.input?.url === 'string' ? block.input.url : undefined;\n emit('reading a web page…', block.name, u);\n return;\n }\n if (name === 'read') {\n const p = typeof block.input?.file_path === 'string' ? block.input.file_path : undefined;\n emit('reading files…', block.name, p);\n return;\n }\n if (name === 'grep' || name === 'glob') {\n emit('searching the codebase…', block.name);\n return;\n }\n emit(`using ${block.name}…`, block.name);\n return;\n }\n if (block.type === 'text' && typeof block.text === 'string' && block.text.trim().length > 0) {\n emit('writing response…');\n return;\n }\n }\n };\n}\n\ninterface TokenUsageInput {\n discussionId?: string;\n operationType: string;\n model: string;\n usage:\n | {\n input_tokens?: number;\n output_tokens?: number;\n cache_creation_input_tokens?: number;\n cache_read_input_tokens?: number;\n }\n | undefined;\n costUsd: number;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Test-only export — keeps internal helpers unit-testable without making them\n * part of the public engine surface.\n */\nexport const __test = {\n pickAnchorResponse,\n extractSourcesFromText,\n};\n\nfunction logTokenUsage(storage: StorageService, input: TokenUsageInput): void {\n const promptTokenCount =\n (input.usage?.input_tokens ?? 0) +\n (input.usage?.cache_creation_input_tokens ?? 0) +\n (input.usage?.cache_read_input_tokens ?? 0);\n const candidatesTokenCount = input.usage?.output_tokens ?? 0;\n const log: TokenUsageLog = {\n id: generateUUID(),\n discussionId: input.discussionId,\n feature: 'sparring',\n operationType: input.operationType,\n model: input.model,\n tokens: {\n promptTokenCount,\n candidatesTokenCount,\n cacheReadTokens: input.usage?.cache_read_input_tokens,\n cacheCreationTokens: input.usage?.cache_creation_input_tokens,\n totalTokenCount: promptTokenCount + candidatesTokenCount,\n },\n costUsd: input.costUsd,\n createdAt: nowIso(),\n metadata: input.metadata,\n };\n storage.appendTokenUsageLog(log).catch((err) => {\n logger.debug('[sparring] token-usage log failed (non-blocking):', err);\n });\n}\n","/**\n * Deterministic head/tail truncation used by the sparring service to keep\n * prompts within the context window. Matches sage-council's behavior verbatim\n * (PLAN.md §4.3.15) so the user experience is identical.\n */\n\nexport const MAX_DISCUSSION_CONTEXT_CHARS = 14_000;\nexport const MAX_SPARRING_HISTORY_CHARS = 8_000;\nexport const MAX_BUSINESS_CONTEXT_CHARS = 4_000;\nexport const MAX_ANCHOR_RESPONSE_CHARS = 4_000;\nexport const TRUNCATION_MARKER_OVERHEAD = 120;\n\nexport function truncateDeterministically(input: string, maxChars: number, label: string): string {\n if (input.length <= maxChars) return input;\n\n const availableForContent = Math.max(maxChars - TRUNCATION_MARKER_OVERHEAD, 200);\n const headLength = Math.ceil(availableForContent * 0.7);\n const tailLength = Math.max(availableForContent - headLength, 80);\n const omittedCount = Math.max(input.length - headLength - tailLength, 0);\n const marker = `\\n\\n[${label} truncated to fit context window: omitted ${omittedCount} chars]\\n\\n`;\n\n return `${input.slice(0, headLength)}${marker}${input.slice(-tailLength)}`;\n}\n","/**\n * Sparring-deep-dive prompt builder. Ported from sage-council's\n * `sparring_deep_dive` template + fallback prompt (sparring-service.ts:441-485).\n *\n * The prompt instructs the model — speaking AS the named board member — to go\n * significantly deeper than the original board response: concrete examples,\n * stated assumptions/tradeoffs, pushback, real-world parallels, markdown\n * headings + bullets (no wall-of-text). Web search is allowed (via the agent's\n * allowedTools), but the sub-agent file is also where tool restrictions live.\n */\n\nimport type { AdvisoryBoardMember, Discussion, Response, SparringMessage } from '../../storage/types.js';\nimport {\n MAX_ANCHOR_RESPONSE_CHARS,\n MAX_DISCUSSION_CONTEXT_CHARS,\n MAX_SPARRING_HISTORY_CHARS,\n truncateDeterministically,\n} from './truncate.js';\n\nexport interface BuildSparringPromptOptions {\n member: AdvisoryBoardMember;\n discussion: Discussion;\n anchorResponse: string;\n history: SparringMessage[];\n /** The user's new message that we're about to answer. Appended to history. */\n pendingUserMessage?: string;\n}\n\nexport function buildSparringUserMessage(opts: BuildSparringPromptOptions): string {\n const {\n member,\n discussion,\n anchorResponse,\n history,\n pendingUserMessage,\n } = opts;\n\n const fullHistory: SparringMessage[] = pendingUserMessage\n ? [\n ...history,\n {\n id: 'pending',\n sessionId: 'pending',\n role: 'user' as const,\n content: pendingUserMessage,\n sources: [],\n createdAt: new Date().toISOString(),\n },\n ]\n : history;\n\n const renderedHistory = fullHistory\n .map((message) => `${message.role === 'user' ? 'User' : member.name}: ${message.content}`)\n .join('\\n\\n');\n\n const sparringHistory = truncateDeterministically(\n renderedHistory,\n MAX_SPARRING_HISTORY_CHARS,\n 'Sparring history',\n );\n const discussionContext = buildDiscussionContext(discussion);\n const anchor = truncateDeterministically(anchorResponse, MAX_ANCHOR_RESPONSE_CHARS, 'Anchor response');\n\n return `# 1:1 DEEP DIVE SPARRING SESSION\n\nYou are ${member.name}, ${member.title}. You are in a private 1:1 deep-dive conversation with a user who wants to go deeper on your advisory board response.\n\n## YOUR EXPERTISE\n${member.expertise.join(', ')}\n\n## YOUR PERSONA\n${member.persona}\n\n${member.voiceGuide ? `## YOUR VOICE GUIDE\\n${member.voiceGuide}\\n` : ''}\n## ORIGINAL BOARD QUESTION\n\"${discussion.question}\"\n\n## YOUR ORIGINAL BOARD RESPONSE (ANCHOR)\n${anchor}\n\n## BROADER DISCUSSION CONTEXT\n${discussionContext}\n\n## SPARRING CONVERSATION SO FAR\n${sparringHistory || '(no prior messages — this is the first deep-dive turn)'}\n\n## YOUR TASK\nProvide a deep, nuanced response that goes significantly beyond your original board answer:\n- Give concrete examples and counterexamples\n- Explicitly state assumptions and tradeoffs\n- Challenge the user's thinking if appropriate\n- Reference real-world parallels and data\n- Be specific and actionable, not generic\n\n## FORMATTING REQUIREMENTS\n- Use ## and ### headers to organize your response into clear sections\n- Use bullet points (-) or numbered lists (1.) for multiple items\n- Use **bold** for key terms and important concepts\n- Separate sections with blank lines for readability\n- Do NOT output as a single wall of text\n\nRespond directly as ${member.name} in first person. Output plain markdown — do NOT wrap your response in JSON.`;\n}\n\nfunction buildDiscussionContext(discussion: Discussion): string {\n const lines: string[] = [];\n lines.push(`Primary question: \"${discussion.question}\"`);\n lines.push(`Total turns so far: ${discussion.totalTurns}`);\n\n const hasRounds = discussion.rounds.length > 0;\n const groupedByRound = hasRounds\n ? discussion.rounds.map((round) => ({\n roundNumber: round.roundNumber,\n responses: [...round.responses].sort((a, b) => a.turnNumber - b.turnNumber),\n }))\n : groupResponsesByRound(discussion.responses);\n\n if (groupedByRound.length === 0) {\n lines.push('No prior board responses yet.');\n return lines.join('\\n');\n }\n\n for (const round of groupedByRound) {\n lines.push(`\\nRound ${round.roundNumber}`);\n for (const response of round.responses) {\n const followUpSuffix = response.isFollowUp ? ' (follow-up)' : '';\n lines.push(`- ${response.memberName} | Turn ${response.turnNumber}${followUpSuffix}: ${response.content}`);\n }\n }\n\n return truncateDeterministically(lines.join('\\n'), MAX_DISCUSSION_CONTEXT_CHARS, 'Discussion context');\n}\n\nfunction groupResponsesByRound(responses: Response[]): Array<{ roundNumber: number; responses: Response[] }> {\n const byRound = new Map<number, Response[]>();\n for (const response of responses) {\n const rounded = byRound.get(response.roundNumber) ?? [];\n rounded.push(response);\n byRound.set(response.roundNumber, rounded);\n }\n\n return Array.from(byRound.entries())\n .sort((a, b) => a[0] - b[0])\n .map(([roundNumber, roundResponses]) => ({\n roundNumber,\n responses: roundResponses.sort((a, b) => a.turnNumber - b.turnNumber),\n }));\n}\n","/**\n * Sparring-injection: write a sparring deep-dive insight back into the main\n * discussion timeline as a UserResponse with `type: 'sparring_injection'`.\n *\n * Ported from sage-council/src/lib/conversation-flow.ts:injectSparringInsight.\n *\n * Semantics: the injected response is attached to the round the user was\n * looking at when they triggered the deep-dive (typically the anchor round).\n * If no round exists yet, we throw. If the target round already has a linked\n * userResponse (e.g. an HITL reply), we preserve it and only set ours when\n * the round has no userResponse yet — matching the source.\n */\nimport { generateUUID, nowIso } from '../utils.js';\nimport type {\n Discussion,\n SparringInjectionContext,\n SparringSession,\n StorageService,\n UserResponse,\n} from '../../storage/types.js';\n\nexport interface InjectSparringInsightOptions {\n discussion: Discussion;\n session: SparringSession;\n insight: string;\n storage: StorageService;\n /** Optional override for the round the injected insight targets.\n * Defaults to the session's anchor round. */\n sourceRoundNumber?: number;\n /** Optional override for the turn within that round (informational only). */\n sourceTurnNumber?: number;\n /** The user's original sparring trigger input (informational only). */\n sparringTriggerInput?: string;\n}\n\nexport interface InjectSparringInsightResult {\n discussion: Discussion;\n injectedUserResponse: UserResponse;\n}\n\nexport async function injectSparringInsight(\n opts: InjectSparringInsightOptions,\n): Promise<InjectSparringInsightResult> {\n const trimmedInsight = opts.insight.trim();\n if (!trimmedInsight) {\n throw new Error('Sparring insight cannot be empty');\n }\n if (opts.discussion.rounds.length === 0) {\n throw new Error('No discussion round available to attach injected insight');\n }\n\n const currentRound = opts.discussion.rounds[opts.discussion.rounds.length - 1]!;\n const targetRoundNumber = opts.sourceRoundNumber ?? opts.session.anchorRoundNumber;\n const sourceRound =\n opts.discussion.rounds.find((round) => round.roundNumber === targetRoundNumber) ?? currentRound;\n const sourceRoundNumber = sourceRound.roundNumber;\n const sourceTurnNumber = opts.sourceTurnNumber ?? opts.session.anchorTurnNumber;\n\n const injectionContext: SparringInjectionContext = {\n sourceRoundNumber,\n sourceTurnNumber,\n sparringTriggerInput: opts.sparringTriggerInput,\n };\n\n const injectedUserResponse: UserResponse = {\n id: generateUUID(),\n requestId: `sparring-injection-${opts.discussion.id}-${Date.now()}`,\n content: trimmedInsight,\n timestamp: nowIso(),\n roundNumber: sourceRoundNumber,\n type: 'sparring_injection',\n prompt: `Injected from 1:1 Deep Dive with ${opts.session.memberName}`,\n selectedMemberId: opts.session.memberId,\n sourceRoundNumber: injectionContext.sourceRoundNumber,\n sourceTurnNumber: injectionContext.sourceTurnNumber,\n sparringTriggerInput: injectionContext.sparringTriggerInput,\n sparringSessionId: opts.session.id,\n };\n\n opts.discussion.userResponses.push(injectedUserResponse);\n\n if (!sourceRound.userResponse) {\n sourceRound.userResponse = injectedUserResponse;\n }\n\n await opts.storage.updateDiscussion(opts.discussion);\n\n return { discussion: opts.discussion, injectedUserResponse };\n}\n","/**\r\n * `aab ui` — start the local web dashboard and open the browser.\r\n *\r\n * Usage:\r\n * aab ui # default port 3737, opens browser\r\n * aab ui --port 4000\r\n * aab ui --no-open # don't auto-open browser\r\n * aab ui --bind 0.0.0.0 # listen on all interfaces\r\n */\r\nimport { Command } from 'commander';\r\nimport open from 'open';\r\nimport { closeContext, openContext } from './_context.js';\r\nimport { c, brand } from '../ui/colors.js';\r\nimport { startUiServer } from '../gui/server.js';\r\n\r\nexport function registerUiCommand(program: Command): void {\r\n program\r\n .command('ui')\r\n .description('start the local web dashboard (messaging-app style)')\r\n .option('--port <n>', 'port to listen on', (v) => Number(v), 3737)\r\n .option('--bind <host>', 'host/interface to bind', '127.0.0.1')\r\n .option('--no-open', 'do not open the browser automatically')\r\n .option('--agents-dir <path>', 'project root containing .claude/agents/ (default: cwd)')\r\n .action(async (opts: { port: number; bind: string; open: boolean; agentsDir?: string }) => {\r\n const ctx = await openContext(program, { lock: false });\r\n try {\r\n const handle = await startUiServer({\r\n storage: ctx.storage,\r\n port: opts.port,\r\n host: opts.bind,\r\n projectRoot: opts.agentsDir ?? process.cwd(),\r\n });\r\n\r\n process.stdout.write(`\\n${brand()} ${c.hint('· UI ready')}\\n`);\r\n process.stdout.write(` ${c.cyan(handle.url)}\\n`);\r\n process.stdout.write(` ${c.hint('workspace:')} ${ctx.workspace.id}\\n`);\r\n process.stdout.write(` ${c.hint('press Ctrl+C to stop')}\\n\\n`);\r\n\r\n if (opts.open !== false) {\r\n try {\r\n await open(handle.url);\r\n } catch {\r\n // best-effort; user can navigate manually\r\n }\r\n }\r\n\r\n // Keep the process alive until Ctrl+C\r\n await new Promise<void>((resolve) => {\r\n const onSignal = async () => {\r\n process.stdout.write(c.hint('\\nshutting down…\\n'));\r\n await handle.close();\r\n resolve();\r\n };\r\n process.once('SIGINT', onSignal);\r\n process.once('SIGTERM', onSignal);\r\n });\r\n } finally {\r\n await closeContext(ctx);\r\n }\r\n });\r\n}\r\n","/**\r\n * Local Express + WebSocket server for the AI Advisory Board UI.\r\n *\r\n * Mounts at http://localhost:<port> (default 3737).\r\n * Static files live in `gui/` at the package root.\r\n *\r\n * REST endpoints (read):\r\n * GET /api/state bootstrap (settings, members, principles, action items, discussion list)\r\n * GET /api/discussions paginated list\r\n * GET /api/discussions/:id full discussion\r\n * GET /api/members\r\n * GET /api/principles\r\n * GET /api/actions\r\n *\r\n * REST endpoints (write):\r\n * POST /api/discussions start a new discussion (body: { question, memberIds? })\r\n * POST /api/discussions/:id/continue drive next round (orchestrator-gated)\r\n * POST /api/discussions/:id/respond answer pending HITL request (body: { content, selectedOption? })\r\n * POST /api/discussions/:id/follow-up ask a targeted follow-up\r\n * (body: { question, targetType, selectedMemberId?, selectedMemberIds? })\r\n *\r\n * WebSocket events (server → client) on /ws:\r\n * { type: 'discussion_started', discussion }\r\n * { type: 'member_thinking', discussionId, memberName, memberId, slug, index, total }\r\n * { type: 'member_response', discussionId, memberName, memberId, response, roundNumber, durationMs, costUsd }\r\n * { type: 'orchestrator_decision',discussionId, decision }\r\n * { type: 'discussion_gated', discussion } — pre-round gate asked for user input\r\n * { type: 'discussion_completed', discussion }\r\n * { type: 'error', discussionId?, message }\r\n */\r\nimport express, { Request, Response } from 'express';\r\nimport http from 'node:http';\r\nimport { dirname, join, resolve } from 'node:path';\r\nimport { fileURLToPath } from 'node:url';\r\nimport { existsSync, statSync } from 'node:fs';\r\nimport { WebSocketServer, WebSocket } from 'ws';\r\nimport {\r\n addFollowUpQuestion,\r\n continueDiscussion,\r\n respondToUserRequest,\r\n startDiscussion,\r\n type FollowUpTargetType,\r\n} from '../core/discussion/conversation-flow.js';\r\nimport { unlinkSync } from 'node:fs';\r\nimport {\r\n emitMemberAgentFile,\r\n isAabGenerated,\r\n memberAgentPath,\r\n memberAgentSlug,\r\n readMemberAgentColor,\r\n} from '../agents/emit-member-agent.js';\r\nimport { logger } from '../core/logger.js';\r\nimport { generateUUID, nowIso } from '../core/utils.js';\r\nimport type { FsStorageService } from '../storage/fs-storage-service.js';\r\nimport { DEFAULT_SETTINGS } from '../storage/types.js';\r\nimport { paths, resolveWorkspace } from '../storage/paths.js';\r\nimport { walkWikiPages, parsePage, serializePage, extractWikiLinks, toPosix, type PageType } from '../core/knowledge/page.js';\r\nimport { buildSlugMap, resolveSlug, extractBacklinksSection } from '../core/knowledge/slug-map.js';\r\nimport { loadManifest, markUserEdited } from '../core/knowledge/manifest.js';\r\nimport { renameSlug } from '../core/knowledge/rename.js';\r\nimport { ingestFile, ingestPaste, ingestUrl, ingestDiscussionRaw } from '../core/knowledge/ingest.js';\r\nimport { queryWiki } from '../core/knowledge/query.js';\r\nimport { lintWiki } from '../core/knowledge/lint.js';\r\nimport { existsSync as fsExistsSync, readFileSync, writeFileSync } from 'node:fs';\r\nimport type {\r\n ActionItem,\r\n AdvisoryBoardMember,\r\n AppSettings,\r\n DecisionSession,\r\n Discussion,\r\n Principle,\r\n PrincipleCategory,\r\n} from '../storage/types.js';\r\nimport {\r\n extractActionItems,\r\n type ExtractedActionItem,\r\n} from '../core/actions/conversation-analyzer.js';\r\nimport { enhancePersona, type EnhancementType } from '../core/members/ai-enhancer.js';\r\nimport { generateVoiceGuide } from '../core/members/voice-guide.js';\r\nimport { coachReply, newDecisionSession } from '../core/coach/decision-coach.js';\r\nimport {\r\n EXPLORER_STEPS,\r\n applyStep,\r\n explorerReply,\r\n type ExplorerStep,\r\n type ExplorerTurn,\r\n} from '../core/coach/principle-explorer.js';\r\nimport { openSparringSession, sendSparringMessage } from '../core/sparring/sparring-service.js';\r\nimport { injectSparringInsight } from '../core/sparring/inject-insight.js';\r\nimport { STARTER_PRINCIPLES } from '../starter/starter-principles.js';\r\nimport { runSolve, type SolveEvent } from '../core/skill/solve-orchestrator.js';\r\nimport { renderProposalMarkdown, type ResolvedSkillCapabilityProfile } from '../core/skill/planner-review.js';\r\nimport { resolveSkill } from '../core/skill/resolve-skill-creator.js';\r\nimport { listInstalledSkills } from '../commands/skills.js';\r\nimport { scan as scanPc } from '../core/skill/recon/pc-scan.js';\r\nimport type { SkillDesignProposal } from '../core/parsing/llm-response-schemas.js';\r\nimport { summariseUsage } from '../core/tokens/usage-summary.js';\r\n\r\nconst PRINCIPLE_CATEGORIES: PrincipleCategory[] = [\r\n 'life',\r\n 'work',\r\n 'relationships',\r\n 'health',\r\n 'finance',\r\n 'meta',\r\n];\r\n\r\nfunction coerceCategory(input: unknown, fallback: PrincipleCategory = 'meta'): PrincipleCategory {\r\n return typeof input === 'string' && (PRINCIPLE_CATEGORIES as string[]).includes(input)\r\n ? (input as PrincipleCategory)\r\n : fallback;\r\n}\r\n\r\nconst ACTION_PRIORITIES = ['low', 'medium', 'high'] as const;\r\nconst ACTION_STATUSES = ['pending', 'in-progress', 'completed'] as const;\r\ntype ActionPriority = (typeof ACTION_PRIORITIES)[number];\r\ntype ActionStatus = (typeof ACTION_STATUSES)[number];\r\n\r\nfunction coerceActionPriority(value: unknown, fallback: ActionPriority = 'medium'): ActionPriority {\r\n if (typeof value === 'string') {\r\n const v = value.trim().toLowerCase();\r\n if ((ACTION_PRIORITIES as readonly string[]).includes(v)) return v as ActionPriority;\r\n }\r\n return fallback;\r\n}\r\n\r\nfunction coerceActionStatus(value: unknown, fallback: ActionStatus = 'pending'): ActionStatus {\r\n if (typeof value === 'string') {\r\n const v = value.trim().toLowerCase();\r\n if ((ACTION_STATUSES as readonly string[]).includes(v)) return v as ActionStatus;\r\n if (v === 'inprogress' || v === 'in_progress' || v === 'doing') return 'in-progress';\r\n if (v === 'todo') return 'pending';\r\n if (v === 'done') return 'completed';\r\n }\r\n return fallback;\r\n}\r\n\r\nconst DEFAULT_PORT = 3737;\r\n\r\nexport interface UiServerOptions {\r\n storage: FsStorageService;\r\n port?: number;\r\n host?: string;\r\n /** Project root for `.claude/agents/` lookup (defaults to cwd). */\r\n projectRoot?: string;\r\n}\r\n\r\nexport interface UiServerHandle {\r\n url: string;\r\n close: () => Promise<void>;\r\n}\r\n\r\ninterface BroadcastEvent {\r\n type: string;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport async function startUiServer(opts: UiServerOptions): Promise<UiServerHandle> {\r\n const port = opts.port ?? DEFAULT_PORT;\r\n const host = opts.host ?? '127.0.0.1';\r\n const projectRoot = opts.projectRoot ?? process.cwd();\r\n const guiDir = resolveGuiDir();\r\n\r\n const app = express();\r\n app.use(express.json({ limit: '256kb' }));\r\n\r\n // ---------- WebSocket broadcast plumbing ----------\r\n const sockets = new Set<WebSocket>();\r\n const broadcast = (evt: BroadcastEvent): void => {\r\n const data = JSON.stringify(evt);\r\n for (const ws of sockets) {\r\n if (ws.readyState === ws.OPEN) ws.send(data);\r\n }\r\n };\r\n\r\n // ---------- Static files ----------\r\n app.use(express.static(guiDir));\r\n\r\n // ---------- API: read ----------\r\n app.get('/api/state', async (_req, res) => {\r\n try {\r\n const [settings, members, principles, actionItems, discussionPage] = await Promise.all([\r\n opts.storage.loadSettings(),\r\n opts.storage.loadBoardMembers(),\r\n opts.storage.loadPrinciples(),\r\n opts.storage.loadActionItems(),\r\n opts.storage.loadDiscussionPage({ limit: 50 }),\r\n ]);\r\n res.json({\r\n workspace: {\r\n id: opts.storage.getWorkspaceId(),\r\n root: opts.storage.getWorkspaceRoot(),\r\n scope: opts.storage.getWorkspaceScope(),\r\n projectRoot,\r\n },\r\n settings,\r\n members: enrichMembers(members, projectRoot),\r\n principles,\r\n actionItems,\r\n discussions: discussionPage.discussions,\r\n discussionTotal: discussionPage.totalCount,\r\n });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.get('/api/discussions', async (req, res) => {\r\n try {\r\n const limit = req.query.limit ? Number(req.query.limit) : 50;\r\n const offset = req.query.offset ? Number(req.query.offset) : 0;\r\n const page = await opts.storage.loadDiscussionPage({ limit, offset });\r\n res.json(page);\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.get('/api/discussions/:id', async (req, res) => {\r\n try {\r\n const id = req.params.id;\r\n const direct = await opts.storage.loadDiscussionById(id);\r\n if (direct) {\r\n res.json(direct);\r\n return;\r\n }\r\n // Allow short-id prefix lookup\r\n const all = await opts.storage.loadDiscussions();\r\n const matches = all.filter((d) => d.id.startsWith(id));\r\n if (matches.length === 0) {\r\n res.status(404).json({ error: `No discussion matching \"${id}\"` });\r\n return;\r\n }\r\n if (matches.length > 1) {\r\n res.status(409).json({ error: `Multiple discussions match \"${id}\"` });\r\n return;\r\n }\r\n res.json(matches[0]);\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.get('/api/members', async (_req, res) => {\r\n try {\r\n const members = await opts.storage.loadBoardMembers();\r\n res.json(enrichMembers(members, projectRoot));\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // Phase 6.5 — Usage dashboard. Aggregates token-usage JSONL logs into the\r\n // totals / by-day / by-feature / by-model shape the GUI renders. The\r\n // `since` query (YYYY-MM-DD) trims the daily-file scan window; the default\r\n // is the last 30 days. `limit` caps the raw log fetch to keep large\r\n // workspaces snappy.\r\n app.get('/api/usage', async (req, res) => {\r\n try {\r\n const sinceParam = typeof req.query.since === 'string' ? req.query.since : undefined;\r\n const since =\r\n sinceParam && /^\\d{4}-\\d{2}-\\d{2}$/.test(sinceParam)\r\n ? sinceParam\r\n : (() => {\r\n const d = new Date();\r\n d.setUTCDate(d.getUTCDate() - 29); // last 30 days inclusive\r\n return d.toISOString().slice(0, 10);\r\n })();\r\n const limit = req.query.limit ? Math.max(1, Math.min(100000, Number(req.query.limit))) : undefined;\r\n const logs = await opts.storage.loadTokenUsageLogs(limit !== undefined ? { since, limit } : { since });\r\n res.json({ since, summary: summariseUsage(logs), totalLogs: logs.length });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.get('/api/principles', async (_req, res) => {\r\n try {\r\n res.json(await opts.storage.loadPrinciples());\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.get('/api/actions', async (_req, res) => {\r\n try {\r\n res.json(await opts.storage.loadActionItems());\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // ============================================================\r\n // Action Items CRUD (Phase 4)\r\n // ============================================================\r\n\r\n app.post('/api/actions', async (req, res) => {\r\n try {\r\n const body = (req.body ?? {}) as Partial<ActionItem>;\r\n if (!body.title || typeof body.title !== 'string' || !body.title.trim()) {\r\n res.status(400).json({ error: 'title is required' });\r\n return;\r\n }\r\n const now = nowIso();\r\n const priority = coerceActionPriority(body.priority);\r\n const status = coerceActionStatus(body.status);\r\n const item: ActionItem = {\r\n id: generateUUID(),\r\n discussionId: typeof body.discussionId === 'string' ? body.discussionId : undefined,\r\n title: body.title.trim(),\r\n description: typeof body.description === 'string' ? body.description : '',\r\n priority,\r\n status,\r\n assignedTo: typeof body.assignedTo === 'string' && body.assignedTo.trim() ? body.assignedTo.trim() : undefined,\r\n dueDate: typeof body.dueDate === 'string' && body.dueDate.trim() ? body.dueDate.trim() : undefined,\r\n createdAt: now,\r\n updatedAt: now,\r\n };\r\n await opts.storage.saveActionItem(item);\r\n broadcast({ type: 'action_created', action: item });\r\n res.status(201).json(item);\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.patch('/api/actions/:id', async (req, res) => {\r\n try {\r\n const all = await opts.storage.loadActionItems();\r\n const existing = all.find((i) => i.id === req.params.id);\r\n if (!existing) {\r\n res.status(404).json({ error: `No action item with id ${req.params.id}` });\r\n return;\r\n }\r\n const body = (req.body ?? {}) as Partial<ActionItem>;\r\n const updated: ActionItem = {\r\n ...existing,\r\n ...(typeof body.title === 'string' && body.title.trim() ? { title: body.title.trim() } : {}),\r\n ...(typeof body.description === 'string' ? { description: body.description } : {}),\r\n ...(typeof body.priority === 'string' ? { priority: coerceActionPriority(body.priority) } : {}),\r\n ...(typeof body.status === 'string' ? { status: coerceActionStatus(body.status) } : {}),\r\n ...(typeof body.dueDate === 'string'\r\n ? { dueDate: body.dueDate.trim() || undefined }\r\n : {}),\r\n ...(typeof body.assignedTo === 'string'\r\n ? { assignedTo: body.assignedTo.trim() || undefined }\r\n : {}),\r\n ...(typeof body.discussionId === 'string' ? { discussionId: body.discussionId } : {}),\r\n updatedAt: nowIso(),\r\n };\r\n await opts.storage.updateActionItem(updated);\r\n broadcast({ type: 'action_updated', action: updated, from: existing.status, to: updated.status });\r\n res.json(updated);\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.delete('/api/actions/:id', async (req, res) => {\r\n try {\r\n const all = await opts.storage.loadActionItems();\r\n const existing = all.find((i) => i.id === req.params.id);\r\n if (!existing) {\r\n res.status(404).json({ error: `No action item with id ${req.params.id}` });\r\n return;\r\n }\r\n await opts.storage.deleteActionItem(req.params.id);\r\n broadcast({ type: 'action_deleted', id: req.params.id });\r\n res.status(204).end();\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // Extract candidate action items from a concluded discussion.\r\n // POST /api/discussions/:id/actions/extract → { candidates, method, analysisConfidence, ... }\r\n // POST /api/discussions/:id/actions/extract with body { accept: [{title, description, ...}, ...] }\r\n // → persists each accepted candidate and returns { created: ActionItem[] }\r\n app.post('/api/discussions/:id/actions/extract', async (req, res) => {\r\n try {\r\n const discussion = await opts.storage.loadDiscussionById(req.params.id);\r\n if (!discussion) {\r\n res.status(404).json({ error: `No discussion with id ${req.params.id}` });\r\n return;\r\n }\r\n const body = (req.body ?? {}) as { accept?: unknown };\r\n\r\n // Two modes: list candidates (no body) OR persist accepted items.\r\n if (Array.isArray(body.accept)) {\r\n const created: ActionItem[] = [];\r\n for (const raw of body.accept) {\r\n if (!raw || typeof raw !== 'object') continue;\r\n const cand = raw as Partial<ExtractedActionItem>;\r\n if (!cand.title || typeof cand.title !== 'string' || !cand.title.trim()) continue;\r\n const now = nowIso();\r\n const item: ActionItem = {\r\n id: generateUUID(),\r\n discussionId: discussion.id,\r\n title: cand.title.trim().slice(0, 200),\r\n description: typeof cand.description === 'string' ? cand.description : '',\r\n priority: coerceActionPriority(cand.priority),\r\n status: 'pending',\r\n assignedTo:\r\n typeof cand.suggestedAssignee === 'string' && cand.suggestedAssignee.trim()\r\n ? cand.suggestedAssignee.trim()\r\n : undefined,\r\n dueDate:\r\n typeof cand.suggestedDueDate === 'string' && cand.suggestedDueDate.trim()\r\n ? cand.suggestedDueDate.trim()\r\n : undefined,\r\n createdAt: now,\r\n updatedAt: now,\r\n };\r\n await opts.storage.saveActionItem(item);\r\n created.push(item);\r\n broadcast({ type: 'action_created', action: item, fromDiscussionId: discussion.id });\r\n }\r\n broadcast({ type: 'actions_extracted', discussionId: discussion.id, createdCount: created.length });\r\n res.status(201).json({ created });\r\n return;\r\n }\r\n\r\n const settings = await opts.storage.loadSettings();\r\n const analysis = await extractActionItems({ discussion, settings });\r\n res.json({\r\n discussionId: discussion.id,\r\n method: analysis.method,\r\n analysisConfidence: analysis.analysisConfidence,\r\n processingTimeMs: analysis.processingTimeMs,\r\n candidates: analysis.actionItems,\r\n keyInsights: analysis.keyInsights,\r\n recommendedNextSteps: analysis.recommendedNextSteps,\r\n });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // ============================================================\r\n // Members CRUD\r\n // ============================================================\r\n\r\n // Create\r\n app.post('/api/members', async (req, res) => {\r\n try {\r\n const body = (req.body ?? {}) as Partial<AdvisoryBoardMember>;\r\n if (!body.name || typeof body.name !== 'string' || !body.name.trim()) {\r\n res.status(400).json({ error: 'name is required' });\r\n return;\r\n }\r\n const all = await opts.storage.loadBoardMembers();\r\n if (all.some((m) => m.name.trim().toLowerCase() === body.name!.trim().toLowerCase())) {\r\n res.status(409).json({ error: `A member named \"${body.name}\" already exists.` });\r\n return;\r\n }\r\n const now = nowIso();\r\n const member: AdvisoryBoardMember = {\r\n id: generateUUID(),\r\n name: body.name.trim(),\r\n title: body.title?.trim() || 'Advisor',\r\n expertise: Array.isArray(body.expertise) ? body.expertise.filter(Boolean) : [],\r\n persona:\r\n body.persona?.trim() ||\r\n `${body.name.trim()} brings their unique perspective and expertise to advisory board discussions.`,\r\n voiceGuide: body.voiceGuide?.trim() || undefined,\r\n avatar: body.avatar?.trim() || undefined,\r\n allowedTools: Array.isArray(body.allowedTools) ? body.allowedTools : undefined,\r\n isActive: body.isActive !== false,\r\n createdAt: now,\r\n updatedAt: now,\r\n };\r\n await opts.storage.saveBoardMember(member);\r\n // Emit the .claude/agents/<slug>.md file so CLI and Claude Code can dispatch.\r\n try {\r\n emitMemberAgentFile(member, { projectRoot });\r\n } catch (err) {\r\n logger.warn('[ui] failed to emit agent file:', err);\r\n }\r\n res.status(201).json(enrichOne(member));\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // Update\r\n app.patch('/api/members/:id', async (req, res) => {\r\n try {\r\n const all = await opts.storage.loadBoardMembers();\r\n const existing = all.find((m) => m.id === req.params.id);\r\n if (!existing) {\r\n res.status(404).json({ error: `No member with id ${req.params.id}` });\r\n return;\r\n }\r\n const body = (req.body ?? {}) as Partial<AdvisoryBoardMember>;\r\n const updated: AdvisoryBoardMember = {\r\n ...existing,\r\n ...(typeof body.name === 'string' && body.name.trim() ? { name: body.name.trim() } : {}),\r\n ...(typeof body.title === 'string' ? { title: body.title.trim() } : {}),\r\n ...(Array.isArray(body.expertise) ? { expertise: body.expertise.filter(Boolean) } : {}),\r\n ...(typeof body.persona === 'string' ? { persona: body.persona.trim() } : {}),\r\n ...(typeof body.voiceGuide === 'string'\r\n ? { voiceGuide: body.voiceGuide.trim() || undefined }\r\n : {}),\r\n ...(typeof body.avatar === 'string' ? { avatar: body.avatar.trim() || undefined } : {}),\r\n ...(Array.isArray(body.allowedTools)\r\n ? { allowedTools: body.allowedTools.length === 0 ? undefined : body.allowedTools }\r\n : {}),\r\n ...(typeof body.isActive === 'boolean' ? { isActive: body.isActive } : {}),\r\n updatedAt: nowIso(),\r\n };\r\n await opts.storage.updateBoardMember(updated);\r\n // Re-emit agent file when name/persona/expertise/voice changed.\r\n const shouldRegen =\r\n body.name !== undefined ||\r\n body.persona !== undefined ||\r\n body.expertise !== undefined ||\r\n body.voiceGuide !== undefined ||\r\n body.allowedTools !== undefined;\r\n if (shouldRegen) {\r\n try {\r\n // If name changed, the old slug file is now orphaned — clean up if AAB-generated.\r\n if (body.name && body.name !== existing.name) {\r\n const oldPath = memberAgentPath(memberAgentSlug(existing.name), projectRoot);\r\n if (isAabGenerated(oldPath)) {\r\n try {\r\n unlinkSync(oldPath);\r\n } catch {\r\n /* fine — file may not exist */\r\n }\r\n }\r\n }\r\n emitMemberAgentFile(updated, { projectRoot });\r\n } catch (err) {\r\n logger.warn('[ui] failed to re-emit agent file:', err);\r\n }\r\n }\r\n res.json(enrichOne(updated));\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // Delete\r\n app.delete('/api/members/:id', async (req, res) => {\r\n try {\r\n const all = await opts.storage.loadBoardMembers();\r\n const existing = all.find((m) => m.id === req.params.id);\r\n if (!existing) {\r\n res.status(404).json({ error: `No member with id ${req.params.id}` });\r\n return;\r\n }\r\n await opts.storage.deleteBoardMember(existing.id);\r\n // Clean up the agent file iff it was AAB-generated (don't nuke user-edited).\r\n try {\r\n const p = memberAgentPath(memberAgentSlug(existing.name), projectRoot);\r\n if (isAabGenerated(p)) {\r\n unlinkSync(p);\r\n }\r\n } catch {\r\n /* fine */\r\n }\r\n res.status(204).end();\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // ============================================================\r\n // Members — AI enhancement, voice refresh, agent-file regen\r\n // ============================================================\r\n\r\n function normalizeEnhanceTypeOrThrow(raw: unknown): EnhancementType {\r\n const v = String(raw ?? 'non-famous').toLowerCase().trim();\r\n if (v === 'famous') return 'famous';\r\n if (v === 'expert' || v === 'top-expert' || v === 'top_expert') return 'expert';\r\n if (v === 'non-famous' || v === 'non_famous' || v === 'practitioner') return 'non-famous';\r\n throw new Error(`Unknown enhance type \"${raw}\"`);\r\n }\r\n\r\n app.post('/api/members/:id/enhance', async (req, res) => {\r\n try {\r\n const all = await opts.storage.loadBoardMembers();\r\n const existing = all.find((m) => m.id === req.params.id);\r\n if (!existing) {\r\n res.status(404).json({ error: `No member with id ${req.params.id}` });\r\n return;\r\n }\r\n let type: EnhancementType;\r\n try {\r\n type = normalizeEnhanceTypeOrThrow((req.body ?? {}).type);\r\n } catch (err) {\r\n res.status(400).json({ error: err instanceof Error ? err.message : String(err) });\r\n return;\r\n }\r\n const keepVoice = (req.body ?? {}).keepVoice === true;\r\n res.status(202).json({ accepted: true, memberId: existing.id, type });\r\n broadcast({ type: 'member_enhance_started', memberId: existing.id, memberName: existing.name, enhanceType: type });\r\n\r\n (async () => {\r\n try {\r\n const settings = await opts.storage.loadSettings();\r\n const result = await enhancePersona(\r\n { name: existing.name, title: existing.title, expertise: existing.expertise, type },\r\n settings,\r\n {\r\n currentPersona: existing.persona,\r\n onEvent: (event) => {\r\n if (event.type === 'assistant' || event.type === 'tool_use') {\r\n broadcast({ type: 'member_enhance_progress', memberId: existing.id, event: { type: event.type, subtype: event.subtype } });\r\n }\r\n },\r\n },\r\n );\r\n const next: AdvisoryBoardMember = {\r\n ...existing,\r\n persona: result.persona,\r\n voiceGuide: keepVoice ? existing.voiceGuide : result.voiceGuide || existing.voiceGuide,\r\n updatedAt: nowIso(),\r\n };\r\n await opts.storage.updateBoardMember(next);\r\n try {\r\n emitMemberAgentFile(next, { projectRoot });\r\n } catch (err) {\r\n logger.warn('[ui] failed to emit agent file:', err);\r\n }\r\n broadcast({ type: 'member_enhance_done', memberId: existing.id, member: enrichOne(next), enhanceType: type });\r\n } catch (error) {\r\n broadcast({\r\n type: 'member_enhance_failed',\r\n memberId: existing.id,\r\n message: error instanceof Error ? error.message : String(error),\r\n });\r\n }\r\n })();\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.post('/api/members/:id/regenerate-voice', async (req, res) => {\r\n try {\r\n const all = await opts.storage.loadBoardMembers();\r\n const existing = all.find((m) => m.id === req.params.id);\r\n if (!existing) {\r\n res.status(404).json({ error: `No member with id ${req.params.id}` });\r\n return;\r\n }\r\n const settings = await opts.storage.loadSettings();\r\n broadcast({ type: 'member_voice_started', memberId: existing.id, memberName: existing.name });\r\n const result = await generateVoiceGuide(existing, settings);\r\n const preview = (req.body ?? {}).preview === true;\r\n if (preview) {\r\n broadcast({ type: 'member_voice_preview', memberId: existing.id, voiceGuide: result.voiceGuide, fellBack: result.fellBack });\r\n res.json({ voiceGuide: result.voiceGuide, fellBack: result.fellBack, applied: false });\r\n return;\r\n }\r\n const next: AdvisoryBoardMember = {\r\n ...existing,\r\n voiceGuide: result.voiceGuide,\r\n updatedAt: nowIso(),\r\n };\r\n await opts.storage.updateBoardMember(next);\r\n try {\r\n emitMemberAgentFile(next, { projectRoot });\r\n } catch (err) {\r\n logger.warn('[ui] failed to emit agent file:', err);\r\n }\r\n broadcast({ type: 'member_voice_done', memberId: existing.id, member: enrichOne(next), fellBack: result.fellBack });\r\n res.json({ voiceGuide: result.voiceGuide, fellBack: result.fellBack, applied: true, member: enrichOne(next) });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.post('/api/members/sync-agents', async (req, res) => {\r\n try {\r\n const includeInactive = (req.body ?? {}).all === true;\r\n const members = await opts.storage.loadBoardMembers();\r\n let written = 0;\r\n let skipped = 0;\r\n const skippedDetail: string[] = [];\r\n for (const member of members) {\r\n if (!includeInactive && !member.isActive) continue;\r\n const slug = memberAgentSlug(member.name);\r\n const result = emitMemberAgentFile(member, { projectRoot });\r\n if (result.written) written++;\r\n else {\r\n skipped++;\r\n skippedDetail.push(`${slug} (${result.reason ?? 'unknown'})`);\r\n }\r\n }\r\n broadcast({ type: 'members_sync_done', written, skipped, total: members.length });\r\n res.json({ written, skipped, skippedDetail, total: members.length });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // ============================================================\r\n // Principles CRUD\r\n // ============================================================\r\n\r\n app.post('/api/principles', async (req, res) => {\r\n try {\r\n const body = (req.body ?? {}) as Partial<Principle>;\r\n if (!body.title || typeof body.title !== 'string' || !body.title.trim()) {\r\n res.status(400).json({ error: 'title is required' });\r\n return;\r\n }\r\n const now = nowIso();\r\n const principle: Principle = {\r\n id: generateUUID(),\r\n category: coerceCategory(body.category, 'meta'),\r\n title: body.title.trim(),\r\n description: body.description?.trim() || '',\r\n behavior: body.behavior?.trim() || '',\r\n antiPattern: body.antiPattern?.trim() || undefined,\r\n triggerQuestions: Array.isArray(body.triggerQuestions) ? body.triggerQuestions : undefined,\r\n priority: typeof body.priority === 'number' ? body.priority : 5,\r\n examples: Array.isArray(body.examples) ? body.examples : undefined,\r\n isActive: body.isActive !== false,\r\n createdAt: now,\r\n updatedAt: now,\r\n };\r\n await opts.storage.savePrinciple(principle);\r\n res.status(201).json(principle);\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.patch('/api/principles/:id', async (req, res) => {\r\n try {\r\n const all = await opts.storage.loadPrinciples();\r\n const existing = all.find((p) => p.id === req.params.id);\r\n if (!existing) {\r\n res.status(404).json({ error: `No principle with id ${req.params.id}` });\r\n return;\r\n }\r\n const body = (req.body ?? {}) as Partial<Principle>;\r\n const updated: Principle = {\r\n ...existing,\r\n ...(typeof body.title === 'string' && body.title.trim() ? { title: body.title.trim() } : {}),\r\n ...(typeof body.description === 'string' ? { description: body.description.trim() } : {}),\r\n ...(typeof body.category === 'string'\r\n ? { category: coerceCategory(body.category, existing.category) }\r\n : {}),\r\n ...(typeof body.behavior === 'string' ? { behavior: body.behavior.trim() } : {}),\r\n ...(typeof body.antiPattern === 'string'\r\n ? { antiPattern: body.antiPattern.trim() || undefined }\r\n : {}),\r\n ...(Array.isArray(body.triggerQuestions) ? { triggerQuestions: body.triggerQuestions } : {}),\r\n ...(typeof body.priority === 'number' ? { priority: body.priority } : {}),\r\n ...(Array.isArray(body.examples) ? { examples: body.examples } : {}),\r\n ...(typeof body.isActive === 'boolean' ? { isActive: body.isActive } : {}),\r\n updatedAt: nowIso(),\r\n };\r\n await opts.storage.updatePrinciple(updated);\r\n res.json(updated);\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.delete('/api/principles/:id', async (req, res) => {\r\n try {\r\n await opts.storage.deletePrinciple(req.params.id);\r\n res.status(204).end();\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // ============================================================\r\n // Principles — seed-starters + Explorer wizard step endpoint\r\n // ============================================================\r\n\r\n app.post('/api/principles/seed-starters', async (req, res) => {\r\n try {\r\n const existing = await opts.storage.loadPrinciples();\r\n const force = (req.body ?? {}).force === true;\r\n if (existing.length > 0 && !force) {\r\n res.status(409).json({ error: `${existing.length} principle(s) already exist. Pass force=true to seed on top.` });\r\n return;\r\n }\r\n const now = nowIso();\r\n let added = 0;\r\n const added_ids: string[] = [];\r\n for (const starter of STARTER_PRINCIPLES) {\r\n const principle: Principle = {\r\n id: generateUUID(),\r\n category: starter.category,\r\n title: starter.title,\r\n description: starter.description,\r\n behavior: starter.behavior,\r\n antiPattern: starter.antiPattern,\r\n triggerQuestions: starter.triggerQuestions,\r\n priority: starter.priority,\r\n examples: starter.examples,\r\n isActive: starter.isActive,\r\n createdAt: now,\r\n updatedAt: now,\r\n };\r\n await opts.storage.savePrinciple(principle);\r\n added++;\r\n added_ids.push(principle.id);\r\n }\r\n broadcast({ type: 'principles_seeded', added, ids: added_ids });\r\n res.json({ added, ids: added_ids });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // One step turn of the 5-step Principle Explorer. The browser keeps the\r\n // running `history` of prior turns and posts it back each call.\r\n app.post('/api/principles/explore-step', async (req, res) => {\r\n try {\r\n const body = (req.body ?? {}) as {\r\n principle?: Partial<Principle>;\r\n history?: ExplorerTurn[];\r\n step?: ExplorerStep;\r\n userMessage?: string;\r\n isFirstMessage?: boolean;\r\n };\r\n if (!body.principle || !body.principle.title || !body.principle.category) {\r\n res.status(400).json({ error: 'principle.title and principle.category are required' });\r\n return;\r\n }\r\n if (!body.step || !(EXPLORER_STEPS as readonly string[]).includes(body.step)) {\r\n res.status(400).json({ error: `step must be one of: ${EXPLORER_STEPS.join(', ')}` });\r\n return;\r\n }\r\n const settings = await opts.storage.loadSettings();\r\n broadcast({ type: 'principle_explorer_thinking', step: body.step });\r\n const result = await explorerReply(\r\n {\r\n principle: body.principle as Principle,\r\n history: Array.isArray(body.history) ? body.history : [],\r\n step: body.step,\r\n isFirstMessage: !!body.isFirstMessage,\r\n },\r\n body.userMessage ?? '',\r\n settings,\r\n );\r\n broadcast({\r\n type: 'principle_explorer_reply',\r\n step: body.step,\r\n synthesised: result.synthesised,\r\n });\r\n res.json(result);\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // Apply a synthesised step result back to a principle (existing or new).\r\n app.post('/api/principles/apply-step', async (req, res) => {\r\n try {\r\n const body = (req.body ?? {}) as {\r\n principleId?: string;\r\n principle?: Partial<Principle>;\r\n step?: ExplorerStep;\r\n value?: string;\r\n };\r\n if (!body.step || !(EXPLORER_STEPS as readonly string[]).includes(body.step)) {\r\n res.status(400).json({ error: 'invalid step' });\r\n return;\r\n }\r\n if (!body.value || typeof body.value !== 'string') {\r\n res.status(400).json({ error: 'value is required' });\r\n return;\r\n }\r\n let base: Partial<Principle> | Principle | undefined = body.principle;\r\n if (body.principleId) {\r\n const all = await opts.storage.loadPrinciples();\r\n const found = all.find((p) => p.id === body.principleId);\r\n if (!found) {\r\n res.status(404).json({ error: `No principle with id ${body.principleId}` });\r\n return;\r\n }\r\n base = found;\r\n }\r\n if (!base || !base.title || !base.category) {\r\n res.status(400).json({ error: 'principle (with title + category) is required' });\r\n return;\r\n }\r\n const merged = applyStep(base as Principle, body.step, body.value);\r\n res.json({ principle: merged });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // ============================================================\r\n // Decision Coach — session CRUD + messages\r\n // ============================================================\r\n\r\n app.get('/api/coach/sessions', async (_req, res) => {\r\n try {\r\n const sessions = await opts.storage.loadDecisionSessions();\r\n res.json({ sessions });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.get('/api/coach/sessions/:id', async (req, res) => {\r\n try {\r\n const session = await opts.storage.loadDecisionSessionById(req.params.id);\r\n if (!session) {\r\n const all = await opts.storage.loadDecisionSessions();\r\n const byShort = all.find((s) => s.id.startsWith(req.params.id));\r\n if (!byShort) {\r\n res.status(404).json({ error: `No coach session matching \"${req.params.id}\"` });\r\n return;\r\n }\r\n res.json(byShort);\r\n return;\r\n }\r\n res.json(session);\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.post('/api/coach/sessions', async (req, res) => {\r\n try {\r\n const body = (req.body ?? {}) as { situation?: string; title?: string };\r\n if (!body.situation || !body.situation.trim()) {\r\n res.status(400).json({ error: 'situation is required' });\r\n return;\r\n }\r\n const session = newDecisionSession(body.situation.trim(), body.title?.trim() || undefined);\r\n await opts.storage.saveDecisionSession(session);\r\n res.status(202).json({ accepted: true, session });\r\n broadcast({ type: 'coach_session_started', session });\r\n\r\n // Kick off the opener turn in the background.\r\n (async () => {\r\n try {\r\n const settings = await opts.storage.loadSettings();\r\n const principles = await opts.storage.loadPrinciples();\r\n broadcast({ type: 'coach_thinking', sessionId: session.id });\r\n const { session: updated, reply } = await coachReply(session, principles, '', settings);\r\n await opts.storage.updateDecisionSession(updated);\r\n broadcast({ type: 'coach_message', sessionId: updated.id, message: reply, session: updated });\r\n } catch (error) {\r\n broadcast({\r\n type: 'coach_error',\r\n sessionId: session.id,\r\n message: error instanceof Error ? error.message : String(error),\r\n });\r\n }\r\n })();\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.post('/api/coach/sessions/:id/messages', async (req, res) => {\r\n try {\r\n const body = (req.body ?? {}) as { content?: string };\r\n if (!body.content || !body.content.trim()) {\r\n res.status(400).json({ error: 'content is required' });\r\n return;\r\n }\r\n let session: DecisionSession | null = await opts.storage.loadDecisionSessionById(req.params.id);\r\n if (!session) {\r\n const all = await opts.storage.loadDecisionSessions();\r\n const byShort = all.find((s) => s.id.startsWith(req.params.id));\r\n if (!byShort) {\r\n res.status(404).json({ error: `No coach session matching \"${req.params.id}\"` });\r\n return;\r\n }\r\n session = byShort;\r\n }\r\n res.status(202).json({ accepted: true, sessionId: session.id });\r\n broadcast({ type: 'coach_thinking', sessionId: session.id });\r\n\r\n (async () => {\r\n try {\r\n const settings = await opts.storage.loadSettings();\r\n const principles = await opts.storage.loadPrinciples();\r\n const { session: updated, reply } = await coachReply(session!, principles, body.content!.trim(), settings);\r\n await opts.storage.updateDecisionSession(updated);\r\n broadcast({ type: 'coach_message', sessionId: updated.id, message: reply, session: updated });\r\n } catch (error) {\r\n broadcast({\r\n type: 'coach_error',\r\n sessionId: session!.id,\r\n message: error instanceof Error ? error.message : String(error),\r\n });\r\n }\r\n })();\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.delete('/api/coach/sessions/:id', async (req, res) => {\r\n try {\r\n let session = await opts.storage.loadDecisionSessionById(req.params.id);\r\n if (!session) {\r\n const all = await opts.storage.loadDecisionSessions();\r\n const byShort = all.find((s) => s.id.startsWith(req.params.id));\r\n if (!byShort) {\r\n res.status(404).json({ error: `No coach session matching \"${req.params.id}\"` });\r\n return;\r\n }\r\n session = byShort;\r\n }\r\n await opts.storage.deleteDecisionSession(session.id);\r\n broadcast({ type: 'coach_session_deleted', sessionId: session.id });\r\n res.status(204).end();\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.post('/api/coach/sessions/:id/decide', async (req, res) => {\r\n try {\r\n const body = (req.body ?? {}) as { decision?: string; status?: DecisionSession['status'] };\r\n let session = await opts.storage.loadDecisionSessionById(req.params.id);\r\n if (!session) {\r\n const all = await opts.storage.loadDecisionSessions();\r\n const byShort = all.find((s) => s.id.startsWith(req.params.id));\r\n if (!byShort) {\r\n res.status(404).json({ error: `No coach session matching \"${req.params.id}\"` });\r\n return;\r\n }\r\n session = byShort;\r\n }\r\n const updated: DecisionSession = {\r\n ...session,\r\n decision: body.decision ?? session.decision,\r\n status: body.status ?? (body.decision ? 'decided' : session.status),\r\n updatedAt: nowIso(),\r\n };\r\n await opts.storage.updateDecisionSession(updated);\r\n broadcast({ type: 'coach_session_updated', session: updated });\r\n res.json(updated);\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // ============================================================\r\n // Settings PATCH (merge updates)\r\n // ============================================================\r\n\r\n app.patch('/api/settings', async (req, res) => {\r\n try {\r\n const body = (req.body ?? {}) as Partial<AppSettings>;\r\n const current = await opts.storage.loadSettings();\r\n const next: AppSettings = { ...DEFAULT_SETTINGS, ...current, ...body };\r\n // Coerce a few known numeric fields that might come in as strings from the form\r\n if (typeof body.maxTurnsPerDiscussion === 'string') next.maxTurnsPerDiscussion = Number(body.maxTurnsPerDiscussion);\r\n if (typeof body.consensusThreshold === 'string') next.consensusThreshold = Number(body.consensusThreshold);\r\n if (typeof (body as Record<string, unknown>).perCallBudgetUsd === 'string') {\r\n next.perCallBudgetUsd = Number((body as Record<string, unknown>).perCallBudgetUsd as string);\r\n }\r\n await opts.storage.saveSettings(next);\r\n res.json(next);\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // ---------- shared kickoff helper for write endpoints ----------\r\n // Streams progress to all WS clients. Caller already returned 202 to the\r\n // HTTP client; failures here are surfaced via a `{type:'error'}` WS event.\r\n // Each engine progress event becomes a WS broadcast as it happens — so the\r\n // browser sees per-member responses arrive live, not all-at-once at end.\r\n const broadcastRoundProgress = (\r\n discussionId: string,\r\n selected: AdvisoryBoardMember[],\r\n ) =>\r\n (e: import('../core/discussion/conversation-flow.js').StartProgressEvent) => {\r\n if (e.stage === 'generating') {\r\n const member = selected.find((m) => m.name === e.memberName);\r\n broadcast({\r\n type: 'member_thinking',\r\n discussionId,\r\n memberName: e.memberName,\r\n memberId: member?.id,\r\n slug: member ? memberAgentSlug(member.name) : undefined,\r\n index: e.index,\r\n total: e.total,\r\n });\r\n } else if (e.stage === 'member_activity') {\r\n const member = selected.find((m) => m.name === e.memberName);\r\n broadcast({\r\n type: 'member_activity',\r\n discussionId,\r\n memberName: e.memberName,\r\n memberId: member?.id,\r\n activity: e.activity,\r\n tool: e.tool,\r\n detail: e.detail,\r\n });\r\n } else if (e.stage === 'member_done') {\r\n broadcast({\r\n type: 'member_response',\r\n discussionId,\r\n memberName: e.response.memberName,\r\n memberId: e.response.memberId,\r\n response: e.response,\r\n roundNumber: e.roundNumber,\r\n durationMs: e.durationMs,\r\n costUsd: e.costUsd,\r\n });\r\n } else if (e.stage === 'orchestrating') {\r\n broadcast({ type: 'orchestrator_thinking', discussionId });\r\n } else if (e.stage === 'orchestrator_decided') {\r\n broadcast({\r\n type: 'orchestrator_decision',\r\n discussionId,\r\n decision: e.decision,\r\n roundNumber: e.roundNumber,\r\n });\r\n }\r\n };\r\n\r\n // Once the engine returns, just announce the final state. Per-member\r\n // responses + orchestrator decisions were already broadcast live.\r\n const broadcastFinalDiscussion = (\r\n discussion: Discussion,\r\n _fromRoundNumber: number,\r\n extras: { costUsd?: number; durationMs?: number; gated?: boolean; concluded?: boolean } = {},\r\n ) => {\r\n if (extras.gated) {\r\n broadcast({ type: 'discussion_gated', discussion });\r\n return;\r\n }\r\n broadcast({\r\n type: 'discussion_completed',\r\n discussion,\r\n costUsd: extras.costUsd ?? 0,\r\n durationMs: extras.durationMs ?? 0,\r\n });\r\n };\r\n\r\n const resolveDiscussionByIdOrShort = async (id: string): Promise<Discussion | null> => {\r\n const direct = await opts.storage.loadDiscussionById(id);\r\n if (direct) return direct;\r\n const all = await opts.storage.loadDiscussions();\r\n const matches = all.filter((d) => d.id.startsWith(id));\r\n if (matches.length === 1) return matches[0]!;\r\n return null;\r\n };\r\n\r\n // ---------- API: write ----------\r\n app.post('/api/discussions', async (req, res) => {\r\n try {\r\n const { question, memberIds } = req.body as { question?: string; memberIds?: string[] };\r\n if (!question || typeof question !== 'string' || !question.trim()) {\r\n res.status(400).json({ error: 'question is required' });\r\n return;\r\n }\r\n\r\n const settings = await opts.storage.loadSettings();\r\n const allMembers = await opts.storage.loadBoardMembers();\r\n const selected = pickMembers(allMembers, memberIds);\r\n if (selected.length === 0) {\r\n res.status(400).json({ error: 'No active members selected' });\r\n return;\r\n }\r\n\r\n // Confirm agent files exist for the selected members\r\n const missing = selected\r\n .map((m) => ({ name: m.name, slug: memberAgentSlug(m.name) }))\r\n .filter((m) => !existsSync(join(projectRoot, '.claude', 'agents', `${m.slug}.md`)));\r\n if (missing.length > 0) {\r\n res.status(400).json({\r\n error: `Missing .claude/agents/<slug>.md for: ${missing.map((m) => m.name).join(', ')}. Run \\`aab init\\` from a project directory first.`,\r\n });\r\n return;\r\n }\r\n\r\n // Kick off async — return 202 immediately, stream progress via WS\r\n res.status(202).json({ accepted: true });\r\n\r\n logger.info(`[ui] starting discussion (${selected.length} members)`);\r\n // Use the same broadcaster as continue/follow-up so we get per-member\r\n // responses + orchestrator decisions streamed live. We don't have a\r\n // discussion id yet — the client matches typing bubbles by memberName,\r\n // and the final discussion record comes via discussion_completed.\r\n startDiscussion({\r\n question: question.trim(),\r\n members: selected,\r\n settings,\r\n storage: opts.storage,\r\n projectRoot,\r\n onProgress: broadcastRoundProgress('', selected),\r\n })\r\n .then((result) => {\r\n broadcastFinalDiscussion(result.discussion, 1, {\r\n costUsd: result.totalCostUsd,\r\n durationMs: result.totalDurationMs,\r\n });\r\n })\r\n .catch((error: unknown) => {\r\n logger.warn('[ui] discussion failed:', error);\r\n broadcast({ type: 'error', message: error instanceof Error ? error.message : String(error) });\r\n });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // Drive the next round of an existing discussion.\r\n app.post('/api/discussions/:id/continue', async (req, res) => {\r\n try {\r\n const discussion = await resolveDiscussionByIdOrShort(req.params.id);\r\n if (!discussion) {\r\n res.status(404).json({ error: `No discussion matching \"${req.params.id}\"` });\r\n return;\r\n }\r\n if (discussion.completedAt) {\r\n res.status(409).json({ error: 'Discussion already concluded.' });\r\n return;\r\n }\r\n if (discussion.pendingUserRequest) {\r\n res.status(409).json({\r\n error: 'Discussion is awaiting your input. POST to /api/discussions/:id/respond first.',\r\n });\r\n return;\r\n }\r\n\r\n const settings = await opts.storage.loadSettings();\r\n const allMembers = await opts.storage.loadBoardMembers();\r\n const selectedIds = new Set(discussion.selectedMemberIds ?? allMembers.map((m) => m.id));\r\n const selected = allMembers.filter((m) => selectedIds.has(m.id) && m.isActive);\r\n if (selected.length === 0) {\r\n res.status(400).json({ error: 'No active members from this discussion remain.' });\r\n return;\r\n }\r\n\r\n const missing = selected\r\n .map((m) => ({ name: m.name, slug: memberAgentSlug(m.name) }))\r\n .filter((m) => !existsSync(join(projectRoot, '.claude', 'agents', `${m.slug}.md`)));\r\n if (missing.length > 0) {\r\n res.status(400).json({\r\n error: `Missing .claude/agents/<slug>.md for: ${missing.map((m) => m.name).join(', ')}`,\r\n });\r\n return;\r\n }\r\n\r\n // 202 + WS streaming, same pattern as POST /api/discussions\r\n res.status(202).json({ accepted: true });\r\n\r\n const fromRoundNumber = (discussion.rounds[discussion.rounds.length - 1]?.roundNumber ?? 0) + 1;\r\n logger.info(`[ui] continuing discussion ${discussion.id.slice(0, 8)} → round ${fromRoundNumber}`);\r\n continueDiscussion({\r\n discussion,\r\n members: selected,\r\n settings,\r\n storage: opts.storage,\r\n projectRoot,\r\n onProgress: broadcastRoundProgress(discussion.id, selected),\r\n })\r\n .then((result) => {\r\n broadcastFinalDiscussion(result.discussion, fromRoundNumber, {\r\n costUsd: result.totalCostUsd,\r\n durationMs: result.totalDurationMs,\r\n gated: result.gated,\r\n concluded: result.concluded,\r\n });\r\n })\r\n .catch((error: unknown) => {\r\n logger.warn('[ui] continue failed:', error);\r\n broadcast({\r\n type: 'error',\r\n discussionId: discussion.id,\r\n message: error instanceof Error ? error.message : String(error),\r\n });\r\n });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // Answer a pending HITL request, then drive the follow-up round.\r\n app.post('/api/discussions/:id/respond', async (req, res) => {\r\n try {\r\n const { content, selectedOption } = req.body as { content?: string; selectedOption?: string };\r\n if (!content || typeof content !== 'string' || !content.trim()) {\r\n res.status(400).json({ error: 'content is required' });\r\n return;\r\n }\r\n\r\n const discussion = await resolveDiscussionByIdOrShort(req.params.id);\r\n if (!discussion) {\r\n res.status(404).json({ error: `No discussion matching \"${req.params.id}\"` });\r\n return;\r\n }\r\n if (!discussion.pendingUserRequest) {\r\n res.status(409).json({ error: 'This discussion is not awaiting your input.' });\r\n return;\r\n }\r\n\r\n const settings = await opts.storage.loadSettings();\r\n const allMembers = await opts.storage.loadBoardMembers();\r\n const selectedIds = new Set(discussion.selectedMemberIds ?? allMembers.map((m) => m.id));\r\n const selected = allMembers.filter((m) => selectedIds.has(m.id) && m.isActive);\r\n if (selected.length === 0) {\r\n res.status(400).json({ error: 'No active members from this discussion remain.' });\r\n return;\r\n }\r\n\r\n const missing = selected\r\n .map((m) => ({ name: m.name, slug: memberAgentSlug(m.name) }))\r\n .filter((m) => !existsSync(join(projectRoot, '.claude', 'agents', `${m.slug}.md`)));\r\n if (missing.length > 0) {\r\n res.status(400).json({\r\n error: `Missing .claude/agents/<slug>.md for: ${missing.map((m) => m.name).join(', ')}`,\r\n });\r\n return;\r\n }\r\n\r\n res.status(202).json({ accepted: true });\r\n\r\n const fromRoundNumber = (discussion.rounds[discussion.rounds.length - 1]?.roundNumber ?? 0) + 1;\r\n logger.info(`[ui] responding to discussion ${discussion.id.slice(0, 8)}`);\r\n respondToUserRequest({\r\n discussion,\r\n content: content.trim(),\r\n selectedOption,\r\n members: selected,\r\n settings,\r\n storage: opts.storage,\r\n projectRoot,\r\n onProgress: broadcastRoundProgress(discussion.id, selected),\r\n })\r\n .then((result) => {\r\n broadcastFinalDiscussion(result.discussion, fromRoundNumber, {\r\n costUsd: result.totalCostUsd,\r\n durationMs: result.totalDurationMs,\r\n gated: result.gated,\r\n concluded: result.concluded,\r\n });\r\n })\r\n .catch((error: unknown) => {\r\n logger.warn('[ui] respond failed:', error);\r\n broadcast({\r\n type: 'error',\r\n discussionId: discussion.id,\r\n message: error instanceof Error ? error.message : String(error),\r\n });\r\n });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // Targeted follow-up question.\r\n app.post('/api/discussions/:id/follow-up', async (req, res) => {\r\n try {\r\n const body = req.body as {\r\n question?: string;\r\n targetType?: FollowUpTargetType;\r\n selectedMemberId?: string;\r\n selectedMemberIds?: string[];\r\n };\r\n if (!body.question || typeof body.question !== 'string' || !body.question.trim()) {\r\n res.status(400).json({ error: 'question is required' });\r\n return;\r\n }\r\n const targetType: FollowUpTargetType = body.targetType ?? 'all';\r\n if (!['all', 'specific', 'subset'].includes(targetType)) {\r\n res.status(400).json({ error: `invalid targetType \"${targetType}\"` });\r\n return;\r\n }\r\n if (targetType === 'specific' && !body.selectedMemberId) {\r\n res.status(400).json({ error: 'targetType=specific requires selectedMemberId' });\r\n return;\r\n }\r\n if (targetType === 'subset' && (!Array.isArray(body.selectedMemberIds) || body.selectedMemberIds.length < 2)) {\r\n res.status(400).json({ error: 'targetType=subset requires at least 2 selectedMemberIds' });\r\n return;\r\n }\r\n\r\n const discussion = await resolveDiscussionByIdOrShort(req.params.id);\r\n if (!discussion) {\r\n res.status(404).json({ error: `No discussion matching \"${req.params.id}\"` });\r\n return;\r\n }\r\n if (discussion.completedAt) {\r\n res.status(409).json({ error: 'Discussion already concluded.' });\r\n return;\r\n }\r\n if (discussion.pendingUserRequest) {\r\n res.status(409).json({\r\n error: 'Discussion is awaiting your input. POST to /api/discussions/:id/respond first.',\r\n });\r\n return;\r\n }\r\n\r\n const settings = await opts.storage.loadSettings();\r\n const allMembers = await opts.storage.loadBoardMembers();\r\n const allowedIds = new Set(discussion.selectedMemberIds ?? allMembers.map((m) => m.id));\r\n const candidatePool = allMembers.filter((m) => allowedIds.has(m.id) && m.isActive);\r\n if (candidatePool.length === 0) {\r\n res.status(400).json({ error: \"No active members from this discussion's original board remain.\" });\r\n return;\r\n }\r\n\r\n // Resolve which members will actually spawn (so we can verify their files).\r\n let willSpawn = candidatePool;\r\n if (targetType === 'specific') {\r\n willSpawn = candidatePool.filter((m) => m.id === body.selectedMemberId);\r\n if (willSpawn.length === 0) {\r\n res.status(400).json({ error: `Member ${body.selectedMemberId} is not part of this discussion.` });\r\n return;\r\n }\r\n } else if (targetType === 'subset') {\r\n const set = new Set(body.selectedMemberIds);\r\n willSpawn = candidatePool.filter((m) => set.has(m.id));\r\n if (willSpawn.length === 0) {\r\n res.status(400).json({ error: 'None of the selected members are part of this discussion.' });\r\n return;\r\n }\r\n }\r\n\r\n const missing = willSpawn\r\n .map((m) => ({ name: m.name, slug: memberAgentSlug(m.name) }))\r\n .filter((m) => !existsSync(join(projectRoot, '.claude', 'agents', `${m.slug}.md`)));\r\n if (missing.length > 0) {\r\n res.status(400).json({\r\n error: `Missing .claude/agents/<slug>.md for: ${missing.map((m) => m.name).join(', ')}`,\r\n });\r\n return;\r\n }\r\n\r\n res.status(202).json({ accepted: true });\r\n\r\n const fromRoundNumber = (discussion.rounds[discussion.rounds.length - 1]?.roundNumber ?? 0) + 1;\r\n logger.info(\r\n `[ui] follow-up on discussion ${discussion.id.slice(0, 8)} (target=${targetType}, members=${willSpawn.length})`,\r\n );\r\n addFollowUpQuestion({\r\n discussion,\r\n question: body.question.trim(),\r\n members: candidatePool,\r\n settings,\r\n storage: opts.storage,\r\n projectRoot,\r\n targetType,\r\n selectedMemberId: body.selectedMemberId,\r\n selectedMemberIds: body.selectedMemberIds,\r\n onProgress: broadcastRoundProgress(discussion.id, willSpawn),\r\n })\r\n .then((result) => {\r\n broadcastFinalDiscussion(result.discussion, fromRoundNumber, {\r\n costUsd: result.totalCostUsd,\r\n durationMs: result.totalDurationMs,\r\n gated: result.gated,\r\n concluded: result.concluded,\r\n });\r\n })\r\n .catch((error: unknown) => {\r\n logger.warn('[ui] follow-up failed:', error);\r\n broadcast({\r\n type: 'error',\r\n discussionId: discussion.id,\r\n message: error instanceof Error ? error.message : String(error),\r\n });\r\n });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // ============================================================\r\n // Knowledge Wiki (Phase 1.5)\r\n // ============================================================\r\n\r\n function resolveWorkspaceForWiki() {\r\n const ws = resolveWorkspace({ override: opts.storage.getWorkspaceId() });\r\n // Storage knows the actual root; align in case resolver picked a different scope.\r\n ws.root = opts.storage.getWorkspaceRoot();\r\n return ws;\r\n }\r\n\r\n app.get('/api/knowledge/state', async (_req, res) => {\r\n try {\r\n const p = paths(opts.storage.getWorkspaceRoot());\r\n const pages = walkWikiPages(p.wiki, opts.storage.getWorkspaceRoot());\r\n const manifest = loadManifest(p.manifest);\r\n const map = buildSlugMap(p.wiki, opts.storage.getWorkspaceRoot());\r\n const byType: Record<string, number> = {};\r\n const slugMap: Record<string, { path: string; title?: string; type: string; summary?: string }> = {};\r\n const aliases: Record<string, string> = {};\r\n for (const page of pages) {\r\n const t = String(page.frontmatter.type ?? 'unknown');\r\n byType[t] = (byType[t] ?? 0) + 1;\r\n }\r\n for (const [slug, entry] of map.canonical) {\r\n slugMap[slug] = { path: entry.path, title: entry.title, type: String(entry.type), summary: entry.summary };\r\n }\r\n for (const [alias, canonical] of map.aliasToCanonical) {\r\n if (alias !== canonical) aliases[alias] = canonical;\r\n }\r\n res.json({\r\n pageCount: pages.length,\r\n byType,\r\n lastIngestAt: manifest.entries[manifest.entries.length - 1]?.ingestedAt,\r\n totalCostUsd: manifest.entries.reduce((sum, e) => sum + (e.ingestCostUsd ?? 0), 0),\r\n ingestCount: manifest.entries.length,\r\n renameCount: manifest.renames.length,\r\n userEditedCount: manifest.userEditedPages.length,\r\n slugMap,\r\n aliases,\r\n });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.get('/api/knowledge/pages', async (_req, res) => {\r\n try {\r\n const p = paths(opts.storage.getWorkspaceRoot());\r\n const pages = walkWikiPages(p.wiki, opts.storage.getWorkspaceRoot());\r\n const out = pages.map((page) => ({\r\n slug: page.frontmatter.slug,\r\n title: page.frontmatter.title,\r\n type: page.frontmatter.type,\r\n summary: page.frontmatter.summary,\r\n tags: page.frontmatter.tags ?? [],\r\n path: toPosix(`wiki/${page.wikiRelPath}`),\r\n userEdited: page.frontmatter.userEdited ?? false,\r\n updated: page.frontmatter.updated,\r\n }));\r\n res.json({ pages: out });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.get('/api/knowledge/pages/:slug', async (req, res) => {\r\n try {\r\n const p = paths(opts.storage.getWorkspaceRoot());\r\n const map = buildSlugMap(p.wiki, opts.storage.getWorkspaceRoot());\r\n const entry = resolveSlug(map, req.params.slug);\r\n if (!entry) {\r\n res.status(404).json({ error: `No page with slug \"${req.params.slug}\"` });\r\n return;\r\n }\r\n const full = join(p.wiki, entry.path);\r\n const raw = readFileSync(full, 'utf8');\r\n const parsed = parsePage(raw);\r\n if (!parsed) {\r\n res.status(500).json({ error: `Page has no parseable frontmatter: ${entry.path}` });\r\n return;\r\n }\r\n const backlinks = extractBacklinksSection(parsed.body);\r\n res.json({\r\n slug: entry.slug,\r\n path: toPosix(`wiki/${entry.path}`),\r\n frontmatter: parsed.frontmatter,\r\n body: parsed.body,\r\n backlinks,\r\n });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.post('/api/knowledge/pages/:slug', async (req, res) => {\r\n try {\r\n const p = paths(opts.storage.getWorkspaceRoot());\r\n const map = buildSlugMap(p.wiki, opts.storage.getWorkspaceRoot());\r\n const entry = resolveSlug(map, req.params.slug);\r\n if (!entry) {\r\n res.status(404).json({ error: `No page with slug \"${req.params.slug}\"` });\r\n return;\r\n }\r\n const body = (req.body ?? {}) as { body?: string; frontmatter?: Record<string, unknown> };\r\n const full = join(p.wiki, entry.path);\r\n const existing = parsePage(readFileSync(full, 'utf8'));\r\n if (!existing) {\r\n res.status(500).json({ error: `Page has no parseable frontmatter: ${entry.path}` });\r\n return;\r\n }\r\n const nextFm = { ...existing.frontmatter, ...(body.frontmatter ?? {}), userEdited: true, updated: nowIso().slice(0, 10) };\r\n const nextBody = typeof body.body === 'string' ? body.body : existing.body;\r\n writeFileSync(full, serializePage(nextFm as any, nextBody), 'utf8');\r\n markUserEdited(p.manifest, toPosix(`wiki/${entry.path}`), 'ui');\r\n res.json({ ok: true });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.post('/api/knowledge/pages/:slug/rename', async (req, res) => {\r\n try {\r\n const p = paths(opts.storage.getWorkspaceRoot());\r\n const newSlug = (req.body?.newSlug ?? '').toString().trim();\r\n if (!newSlug) {\r\n res.status(400).json({ error: 'newSlug is required' });\r\n return;\r\n }\r\n const result = await renameSlug({\r\n wikiRoot: p.wiki,\r\n manifestPath: p.manifest,\r\n indexPath: p.wikiIndex,\r\n workspaceRoot: opts.storage.getWorkspaceRoot(),\r\n fromSlug: req.params.slug,\r\n toSlug: newSlug,\r\n trigger: 'manual',\r\n });\r\n broadcast({ type: 'wiki_renamed', fromSlug: result.fromSlug, toSlug: result.toSlug });\r\n res.json(result);\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.post('/api/knowledge/ingest', async (req, res) => {\r\n try {\r\n const body = (req.body ?? {}) as { paste?: string; url?: string; path?: string; force?: boolean; type?: string };\r\n const workspace = resolveWorkspaceForWiki();\r\n const settings = await opts.storage.loadSettings();\r\n broadcast({ type: 'wiki_ingest_started', sourceType: body.url ? 'url' : body.path ? 'file' : 'pasted' });\r\n let result;\r\n if (body.paste) {\r\n result = await ingestPaste({ text: body.paste, workspace, settings, force: body.force, hintType: body.type as PageType | undefined });\r\n } else if (body.url) {\r\n result = await ingestUrl({ url: body.url, workspace, settings, force: body.force, hintType: body.type as PageType | undefined });\r\n } else if (body.path) {\r\n result = await ingestFile({ path: body.path, workspace, settings, force: body.force, hintType: body.type as PageType | undefined });\r\n } else {\r\n res.status(400).json({ error: 'Provide paste, url, or path.' });\r\n return;\r\n }\r\n for (const page of result.producedPages) broadcast({ type: 'wiki_ingest_page_written', path: page, action: 'created' });\r\n for (const page of result.updatedPages) broadcast({ type: 'wiki_ingest_page_written', path: page, action: 'updated' });\r\n broadcast({\r\n type: 'wiki_ingest_done',\r\n producedPages: result.producedPages,\r\n updatedPages: result.updatedPages,\r\n costUsd: result.costUsd,\r\n });\r\n res.json(result);\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.post('/api/knowledge/ingest/discussion/:id', async (req, res) => {\r\n try {\r\n const id = req.params.id;\r\n let discussion = await opts.storage.loadDiscussionById(id);\r\n if (!discussion) {\r\n const all = await opts.storage.loadDiscussions();\r\n const matches = all.filter((d) => d.id.startsWith(id));\r\n if (matches.length === 0) {\r\n res.status(404).json({ error: `No discussion matching \"${id}\"` });\r\n return;\r\n }\r\n discussion = matches[0]!;\r\n }\r\n const workspace = resolveWorkspaceForWiki();\r\n const settings = await opts.storage.loadSettings();\r\n broadcast({ type: 'wiki_ingest_started', sourceType: 'discussion', discussionId: discussion.id });\r\n const result = await ingestDiscussionRaw({\r\n discussion,\r\n workspace,\r\n settings,\r\n storage: opts.storage,\r\n force: !!req.body?.force,\r\n });\r\n broadcast({\r\n type: 'wiki_ingest_done',\r\n producedPages: result.producedPages,\r\n updatedPages: result.updatedPages,\r\n costUsd: result.costUsd,\r\n });\r\n res.json(result);\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.post('/api/knowledge/query', async (req, res) => {\r\n try {\r\n const question = (req.body?.question ?? '').toString().trim();\r\n if (!question) {\r\n res.status(400).json({ error: 'question is required' });\r\n return;\r\n }\r\n broadcast({ type: 'wiki_query_started', question });\r\n const settings = await opts.storage.loadSettings();\r\n const result = await queryWiki({\r\n question,\r\n workspace: resolveWorkspaceForWiki(),\r\n settings,\r\n maxPages: req.body?.maxPages,\r\n });\r\n broadcast({ type: 'wiki_query_done', costUsd: result.costUsd, citations: result.citations });\r\n res.json(result);\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.post('/api/knowledge/lint', async (req, res) => {\r\n try {\r\n const settings = await opts.storage.loadSettings();\r\n const result = await lintWiki({\r\n workspace: resolveWorkspaceForWiki(),\r\n settings,\r\n writeReport: req.body?.writeReport !== false,\r\n runLlm: req.body?.runLlm !== false,\r\n maxPages: req.body?.maxPages,\r\n });\r\n broadcast({\r\n type: 'wiki_lint_done',\r\n reportPath: result.reportPath,\r\n errorCount: result.findings.filter((f) => f.severity === 'error').length,\r\n warnCount: result.findings.filter((f) => f.severity === 'warn').length,\r\n });\r\n res.json(result);\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.get('/api/knowledge/graph', async (_req, res) => {\r\n try {\r\n const p = paths(opts.storage.getWorkspaceRoot());\r\n const pages = walkWikiPages(p.wiki, opts.storage.getWorkspaceRoot());\r\n const map = buildSlugMap(p.wiki, opts.storage.getWorkspaceRoot());\r\n const nodes = pages.map((page) => ({\r\n slug: page.frontmatter.slug,\r\n type: page.frontmatter.type,\r\n title: page.frontmatter.title,\r\n summary: page.frontmatter.summary,\r\n }));\r\n const edges: Array<{ from: string; to: string }> = [];\r\n for (const page of pages) {\r\n const from = (page.frontmatter.slug ?? '').toLowerCase();\r\n if (!from) continue;\r\n for (const link of extractWikiLinks(page.body)) {\r\n const to = map.aliasToCanonical.get(link.slug);\r\n if (to && to !== from) edges.push({ from, to });\r\n }\r\n }\r\n res.json({ nodes, edges });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.get('/api/knowledge/raw', async (_req, res) => {\r\n try {\r\n const p = paths(opts.storage.getWorkspaceRoot());\r\n const manifest = loadManifest(p.manifest);\r\n res.json({ entries: manifest.entries });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.get('/api/knowledge/raw/:hash', async (req, res) => {\r\n try {\r\n const p = paths(opts.storage.getWorkspaceRoot());\r\n const manifest = loadManifest(p.manifest);\r\n const entry = manifest.entries.find((e) => e.hash.startsWith(req.params.hash));\r\n if (!entry) {\r\n res.status(404).json({ error: `No raw source with hash starting \"${req.params.hash}\"` });\r\n return;\r\n }\r\n const full = join(opts.storage.getWorkspaceRoot(), entry.rawPath);\r\n if (!fsExistsSync(full)) {\r\n res.status(404).json({ error: `Raw file missing on disk: ${entry.rawPath}` });\r\n return;\r\n }\r\n res.type('text/plain').send(readFileSync(full, 'utf8'));\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // ============================================================\r\n // Sparring (Phase 3) — 1:1 deep dive\r\n // ============================================================\r\n\r\n app.get('/api/discussions/:id/sparring', async (req, res) => {\r\n try {\r\n const sessions = await opts.storage.loadSparringSessionsForDiscussion(req.params.id);\r\n res.json({ sessions });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.post('/api/discussions/:id/sparring', async (req, res) => {\r\n try {\r\n const discussion = await opts.storage.loadDiscussionById(req.params.id);\r\n if (!discussion) {\r\n res.status(404).json({ error: 'Discussion not found' });\r\n return;\r\n }\r\n const body = (req.body ?? {}) as {\r\n memberId?: string;\r\n memberName?: string;\r\n anchorRoundNumber?: number;\r\n anchorTurnNumber?: number;\r\n title?: string;\r\n };\r\n const allMembers = await opts.storage.loadBoardMembers();\r\n const member = body.memberId\r\n ? allMembers.find((m) => m.id === body.memberId)\r\n : body.memberName\r\n ? allMembers.find((m) => m.name.toLowerCase() === body.memberName!.toLowerCase())\r\n : undefined;\r\n if (!member) {\r\n res.status(400).json({ error: 'memberId or memberName must match an existing board member.' });\r\n return;\r\n }\r\n const opened = await openSparringSession({\r\n discussion,\r\n member,\r\n anchorRoundNumber: body.anchorRoundNumber,\r\n anchorTurnNumber: body.anchorTurnNumber,\r\n title: body.title,\r\n storage: opts.storage,\r\n });\r\n broadcast({\r\n type: 'sparring_session_opened',\r\n discussionId: discussion.id,\r\n session: opened.session,\r\n reused: opened.reused,\r\n });\r\n res.json({ session: opened.session, reused: opened.reused });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.get('/api/sparring/:sessionId', async (req, res) => {\r\n try {\r\n const session = await opts.storage.loadSparringSessionById(req.params.sessionId);\r\n if (!session) {\r\n res.status(404).json({ error: 'Sparring session not found' });\r\n return;\r\n }\r\n res.json({ session });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.delete('/api/sparring/:sessionId', async (req, res) => {\r\n try {\r\n const session = await opts.storage.loadSparringSessionById(req.params.sessionId);\r\n if (!session) {\r\n res.status(404).json({ error: 'Sparring session not found' });\r\n return;\r\n }\r\n await opts.storage.deleteSparringSession(session.id);\r\n broadcast({ type: 'sparring_session_deleted', sessionId: session.id, discussionId: session.discussionId });\r\n res.status(204).end();\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.post('/api/sparring/:sessionId/messages', async (req, res) => {\r\n try {\r\n const session = await opts.storage.loadSparringSessionById(req.params.sessionId);\r\n if (!session) {\r\n res.status(404).json({ error: 'Sparring session not found' });\r\n return;\r\n }\r\n const body = (req.body ?? {}) as { content?: string };\r\n const content = (body.content ?? '').toString().trim();\r\n if (!content) {\r\n res.status(400).json({ error: 'content is required and must be non-empty.' });\r\n return;\r\n }\r\n const discussion = await opts.storage.loadDiscussionById(session.discussionId);\r\n if (!discussion) {\r\n res.status(404).json({ error: 'Parent discussion not found' });\r\n return;\r\n }\r\n const allMembers = await opts.storage.loadBoardMembers();\r\n const member = allMembers.find((m) => m.id === session.memberId);\r\n if (!member) {\r\n res.status(404).json({ error: 'Member referenced by this sparring session no longer exists.' });\r\n return;\r\n }\r\n const settings = await opts.storage.loadSettings();\r\n\r\n res.status(202).json({ accepted: true, sessionId: session.id });\r\n broadcast({ type: 'sparring_thinking', sessionId: session.id, memberName: member.name });\r\n\r\n (async () => {\r\n try {\r\n const result = await sendSparringMessage({\r\n session,\r\n member,\r\n discussion,\r\n userMessage: content,\r\n settings,\r\n storage: opts.storage,\r\n projectRoot,\r\n onActivity: (event) => {\r\n broadcast({\r\n type: 'sparring_activity',\r\n sessionId: session.id,\r\n activity: event.activity,\r\n tool: event.tool,\r\n detail: event.detail,\r\n });\r\n },\r\n });\r\n if (result.error || !result.assistantMsg) {\r\n broadcast({\r\n type: 'sparring_error',\r\n sessionId: session.id,\r\n message: result.error ?? 'No reply',\r\n });\r\n return;\r\n }\r\n const updated = await opts.storage.loadSparringSessionById(session.id);\r\n broadcast({\r\n type: 'sparring_message',\r\n sessionId: session.id,\r\n message: result.assistantMsg,\r\n session: updated,\r\n fellBackToPrimary: result.fellBackToPrimary,\r\n costUsd: result.costUsd,\r\n durationMs: result.durationMs,\r\n });\r\n } catch (error) {\r\n broadcast({\r\n type: 'sparring_error',\r\n sessionId: session.id,\r\n message: error instanceof Error ? error.message : String(error),\r\n });\r\n }\r\n })();\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n app.post('/api/sparring/:sessionId/inject', async (req, res) => {\r\n try {\r\n const session = await opts.storage.loadSparringSessionById(req.params.sessionId);\r\n if (!session) {\r\n res.status(404).json({ error: 'Sparring session not found' });\r\n return;\r\n }\r\n const discussion = await opts.storage.loadDiscussionById(session.discussionId);\r\n if (!discussion) {\r\n res.status(404).json({ error: 'Parent discussion not found' });\r\n return;\r\n }\r\n const body = (req.body ?? {}) as { insight?: string; sourceRoundNumber?: number; sourceTurnNumber?: number };\r\n let insight = (body.insight ?? '').toString().trim();\r\n if (!insight) {\r\n const lastAssistant = [...session.messages].reverse().find((m) => m.role === 'assistant');\r\n if (!lastAssistant) {\r\n res.status(400).json({ error: 'No assistant reply to inject. Pass an explicit insight body.' });\r\n return;\r\n }\r\n insight = lastAssistant.content.trim();\r\n }\r\n const result = await injectSparringInsight({\r\n discussion,\r\n session,\r\n insight,\r\n storage: opts.storage,\r\n sourceRoundNumber: body.sourceRoundNumber,\r\n sourceTurnNumber: body.sourceTurnNumber,\r\n });\r\n broadcast({\r\n type: 'sparring_injected',\r\n discussionId: result.discussion.id,\r\n sessionId: session.id,\r\n userResponse: result.injectedUserResponse,\r\n });\r\n res.json({\r\n discussion: result.discussion,\r\n injectedUserResponse: result.injectedUserResponse,\r\n });\r\n } catch (error) {\r\n sendError(res, 500, error);\r\n }\r\n });\r\n\r\n // ---------- Phase 5 — Skill Planner + skill-creator orchestration ----------\r\n\r\n // In-memory plan cache for /api/plans/:planId rehydration. Each entry is\r\n // the full ResolvedSkillCapabilityProfile so a subsequent /solve can be\r\n // launched with the proposal pre-accepted.\r\n const planCache = new Map<string, ResolvedSkillCapabilityProfile>();\r\n\r\n // POST /api/actions/:id/plan — Planner-only, returns proposal + planId\r\n app.post('/api/actions/:id/plan', async (req, res) => {\r\n try {\r\n const actions = await opts.storage.loadActionItems();\r\n const action = actions.find((a) => a.id === req.params.id || a.id.startsWith(req.params.id));\r\n if (!action) {\r\n res.status(404).json({ error: 'Action not found' });\r\n return;\r\n }\r\n const settings = await opts.storage.loadSettings();\r\n const body = (req.body ?? {}) as {\r\n plannerTier?: 'minimal' | 'standard' | 'maximalist';\r\n plannerNoWeb?: boolean;\r\n plannerNoPcScan?: boolean;\r\n plannerNoWiki?: boolean;\r\n };\r\n const discussion = action.discussionId ? await opts.storage.loadDiscussionById(action.discussionId) : null;\r\n const planId = generateUUID();\r\n broadcast({ type: 'planner_started', planId, actionItemId: action.id });\r\n\r\n // Run asynchronously — return planId immediately, push events via WS.\r\n (async () => {\r\n try {\r\n const result = await runSolve({\r\n workspace: resolveWorkspace(),\r\n settings,\r\n storage: opts.storage,\r\n action,\r\n discussionSummary: discussion?.summary,\r\n plannerTierCap: body.plannerTier,\r\n skipPcScan: body.plannerNoPcScan,\r\n skipWiki: body.plannerNoWiki,\r\n skipWeb: body.plannerNoWeb,\r\n planOnly: true,\r\n yes: true,\r\n projectRoot: process.cwd(),\r\n runId: planId,\r\n onEvent: (evt) => broadcast(coerceSolveEventForWs(evt, planId)),\r\n });\r\n planCache.set(planId, result.capabilityProfile);\r\n broadcast({ type: 'planner_proposal_ready', planId, proposal: result.proposal });\r\n } catch (err) {\r\n broadcast({ type: 'planner_failed', planId, reason: 'error', errorMessage: err instanceof Error ? err.message : String(err) });\r\n }\r\n })();\r\n\r\n res.status(202).json({ planId, status: 'running' });\r\n } catch (err) {\r\n sendError(res, 500, err);\r\n }\r\n });\r\n\r\n // GET /api/plans/:planId — return the cached profile (?as=md → proposal markdown)\r\n app.get('/api/plans/:planId', (req, res) => {\r\n const profile = planCache.get(req.params.planId);\r\n if (!profile) {\r\n res.status(404).json({ error: 'Plan not found in cache (server restarted, or never created).' });\r\n return;\r\n }\r\n if ((req.query.as ?? '') === 'md') {\r\n res.type('text/markdown').send(renderProposalMarkdown(profile.proposal));\r\n return;\r\n }\r\n res.json({ planId: req.params.planId, profile });\r\n });\r\n\r\n // POST /api/plans/:planId/replan — re-plan with user feedback (re-uses recon)\r\n app.post('/api/plans/:planId/replan', async (req, res) => {\r\n try {\r\n const existing = planCache.get(req.params.planId);\r\n if (!existing) {\r\n res.status(404).json({ error: 'Original plan not found in cache.' });\r\n return;\r\n }\r\n const body = (req.body ?? {}) as { feedback?: string };\r\n const feedback = (body.feedback ?? '').trim();\r\n if (feedback.length < 10) {\r\n res.status(400).json({ error: 'feedback must be at least 10 characters.' });\r\n return;\r\n }\r\n // Replan via the planner module directly (cheaper — recon is reused).\r\n const { runPlanner } = await import('../core/skill/planner.js');\r\n const actions = await opts.storage.loadActionItems();\r\n // The original action id is embedded — surface it via the action that matches the recon's apps\r\n // (best-effort: when there's only one action with discussionId set, prefer it). We require the\r\n // client to pass the actionId for safety.\r\n const actionId = (body as { actionId?: string }).actionId;\r\n const action = actionId ? actions.find((a) => a.id === actionId || a.id.startsWith(actionId)) : null;\r\n if (!action) {\r\n res.status(400).json({ error: 'actionId is required in the replan body.' });\r\n return;\r\n }\r\n const settings = await opts.storage.loadSettings();\r\n const discussion = action.discussionId ? await opts.storage.loadDiscussionById(action.discussionId) : null;\r\n const planId = generateUUID();\r\n res.status(202).json({ planId, status: 'running' });\r\n (async () => {\r\n try {\r\n const planner = await runPlanner({\r\n workspace: resolveWorkspace(),\r\n settings,\r\n action,\r\n discussionSummary: discussion?.summary,\r\n recon: existing.recon,\r\n userReplanFeedback: feedback,\r\n });\r\n // Build a fresh profile reusing the same accepted-tier defaults.\r\n const next: ResolvedSkillCapabilityProfile = {\r\n ...existing,\r\n generatedAt: nowIso(),\r\n proposal: planner.proposal,\r\n };\r\n planCache.set(planId, next);\r\n broadcast({ type: 'planner_proposal_ready', planId, proposal: planner.proposal });\r\n } catch (err) {\r\n broadcast({ type: 'planner_failed', planId, reason: 'replan error', errorMessage: err instanceof Error ? err.message : String(err) });\r\n }\r\n })();\r\n } catch (err) {\r\n sendError(res, 500, err);\r\n }\r\n });\r\n\r\n // POST /api/actions/:id/solve — body MAY include { planId, profile, scope, noInstall }\r\n app.post('/api/actions/:id/solve', async (req, res) => {\r\n try {\r\n const actions = await opts.storage.loadActionItems();\r\n const action = actions.find((a) => a.id === req.params.id || a.id.startsWith(req.params.id));\r\n if (!action) {\r\n res.status(404).json({ error: 'Action not found' });\r\n return;\r\n }\r\n const body = (req.body ?? {}) as {\r\n planId?: string;\r\n scope?: 'project' | 'user';\r\n noInstall?: boolean;\r\n skillName?: string;\r\n stub?: boolean;\r\n };\r\n const settings = await opts.storage.loadSettings();\r\n const discussion = action.discussionId ? await opts.storage.loadDiscussionById(action.discussionId) : null;\r\n const runId = generateUUID();\r\n const preAcceptedProfile = body.planId ? planCache.get(body.planId) : undefined;\r\n res.status(202).json({ runId, status: 'started' });\r\n\r\n (async () => {\r\n try {\r\n await runSolve({\r\n workspace: resolveWorkspace(),\r\n settings,\r\n storage: opts.storage,\r\n action,\r\n discussionSummary: discussion?.summary,\r\n preAcceptedProfile,\r\n yes: true,\r\n scope: body.scope ?? 'project',\r\n noInstall: body.noInstall,\r\n skillName: body.skillName,\r\n stub: body.stub,\r\n projectRoot: process.cwd(),\r\n runId,\r\n onEvent: (evt) => broadcast(coerceSolveEventForWs(evt, runId)),\r\n });\r\n } catch (err) {\r\n broadcast({ type: 'skill_run_failed', runId, errorMessage: err instanceof Error ? err.message : String(err) });\r\n }\r\n })();\r\n } catch (err) {\r\n sendError(res, 500, err);\r\n }\r\n });\r\n\r\n // GET /api/actions/:id/runs — list past skill runs for one action\r\n app.get('/api/actions/:id/runs', async (req, res) => {\r\n try {\r\n const actions = await opts.storage.loadActionItems();\r\n const action = actions.find((a) => a.id === req.params.id || a.id.startsWith(req.params.id));\r\n if (!action) {\r\n res.status(404).json({ error: 'Action not found' });\r\n return;\r\n }\r\n const runs = await opts.storage.loadSkillRuns(action.id);\r\n res.json({ runs });\r\n } catch (err) {\r\n sendError(res, 500, err);\r\n }\r\n });\r\n\r\n // GET /api/skill-runs/:id — single run detail (with embedded planner proposal)\r\n app.get('/api/skill-runs/:id', async (req, res) => {\r\n try {\r\n const run = await opts.storage.getSkillRun(req.params.id);\r\n if (!run) {\r\n res.status(404).json({ error: 'Skill run not found' });\r\n return;\r\n }\r\n res.json({ run });\r\n } catch (err) {\r\n sendError(res, 500, err);\r\n }\r\n });\r\n\r\n // DELETE /api/skill-runs/:id\r\n app.delete('/api/skill-runs/:id', async (req, res) => {\r\n try {\r\n const run = await opts.storage.getSkillRun(req.params.id);\r\n if (!run) {\r\n res.status(404).json({ error: 'Skill run not found' });\r\n return;\r\n }\r\n await opts.storage.deleteSkillRun(run.id);\r\n res.json({ deleted: req.params.id });\r\n } catch (err) {\r\n sendError(res, 500, err);\r\n }\r\n });\r\n\r\n // GET /api/recon/environment — fast read-only PC scan (no LLM)\r\n app.get('/api/recon/environment', (req, res) => {\r\n try {\r\n const recon = scanPc({ projectRoot: process.cwd() });\r\n res.json({ recon });\r\n } catch (err) {\r\n sendError(res, 500, err);\r\n }\r\n });\r\n\r\n // GET /api/skills — installed skills (project + user + plugin scopes)\r\n app.get('/api/skills', (req, res) => {\r\n try {\r\n const skills = listInstalledSkills(process.cwd()).map((sk) => ({\r\n name: sk.name,\r\n scope: sk.scope,\r\n version: sk.version,\r\n dir: sk.dir,\r\n }));\r\n res.json({ skills });\r\n } catch (err) {\r\n sendError(res, 500, err);\r\n }\r\n });\r\n\r\n // GET /api/skills/:name — pretty SKILL.md + sidecar\r\n app.get('/api/skills/:name', (req, res) => {\r\n try {\r\n const sk = resolveSkill(req.params.name, { projectRoot: process.cwd() });\r\n if (!sk) {\r\n res.status(404).json({ error: 'Skill not installed' });\r\n return;\r\n }\r\n const body = readFileSync(sk.path, 'utf8');\r\n res.json({ skill: sk, body });\r\n } catch (err) {\r\n sendError(res, 500, err);\r\n }\r\n });\r\n\r\n // ---------- HTTP + WS upgrade ----------\r\n const httpServer = http.createServer(app);\r\n const wss = new WebSocketServer({ server: httpServer, path: '/ws' });\r\n wss.on('connection', (ws) => {\r\n sockets.add(ws);\r\n ws.on('close', () => sockets.delete(ws));\r\n });\r\n\r\n await new Promise<void>((res) => httpServer.listen(port, host, () => res()));\r\n const url = `http://${host}:${port}`;\r\n logger.info(`[ui] serving ${guiDir} at ${url}`);\r\n\r\n return {\r\n url,\r\n close: async () => {\r\n for (const ws of sockets) ws.close();\r\n wss.close();\r\n await new Promise<void>((res) => httpServer.close(() => res()));\r\n },\r\n };\r\n}\r\n\r\n// ---------- helpers ----------\r\n\r\nfunction resolveGuiDir(): string {\r\n // dist/bin/aab.js → ../../gui/\r\n const here = dirname(fileURLToPath(import.meta.url));\r\n const candidates = [\r\n resolve(here, '..', '..', 'gui'),\r\n resolve(here, '..', 'gui'),\r\n resolve(here, 'gui'),\r\n ];\r\n for (const c of candidates) {\r\n if (existsSync(c) && statSync(c).isDirectory()) return c;\r\n }\r\n throw new Error('gui/ directory not found relative to ' + here);\r\n}\r\n\r\nfunction pickMembers(all: AdvisoryBoardMember[], ids?: string[]): AdvisoryBoardMember[] {\r\n if (!ids || ids.length === 0) return all.filter((m) => m.isActive);\r\n const set = new Set(ids);\r\n return all.filter((m) => m.isActive && set.has(m.id));\r\n}\r\n\r\nfunction enrichMembers(\r\n members: AdvisoryBoardMember[],\r\n projectRoot?: string,\r\n): Array<AdvisoryBoardMember & { slug: string; initials: string; color?: string }> {\r\n return members.map((m) => enrichOne(m, projectRoot));\r\n}\r\n\r\nfunction enrichOne(\r\n m: AdvisoryBoardMember,\r\n projectRoot?: string,\r\n): AdvisoryBoardMember & { slug: string; initials: string; color?: string } {\r\n const color = readMemberAgentColor(m.name, projectRoot);\r\n return {\r\n ...m,\r\n slug: memberAgentSlug(m.name),\r\n initials: initialsOf(m.name),\r\n ...(color ? { color } : {}),\r\n };\r\n}\r\n\r\nfunction initialsOf(name: string): string {\r\n const parts = name.split(/\\s+/).filter(Boolean);\r\n if (parts.length === 0) return '?';\r\n if (parts.length === 1) return parts[0]!.slice(0, 2).toUpperCase();\r\n return (parts[0]![0]! + parts[parts.length - 1]![0]!).toUpperCase();\r\n}\r\n\r\nfunction sendError(res: Response, status: number, error: unknown): void {\r\n const message = error instanceof Error ? error.message : String(error);\r\n logger.warn('[ui] api error', message);\r\n res.status(status).json({ error: message });\r\n}\r\n\r\n/**\r\n * Map a SolveEvent to the wire-shape WS event the GUI expects.\r\n * The orchestrator emits coarse SolveEvent objects; the GUI sees fine-grained\r\n * planner_* / skill_run_* events. We attach the planId/runId at the source.\r\n */\r\nfunction coerceSolveEventForWs(evt: SolveEvent, id: string): { type: string; [key: string]: unknown } {\r\n const base = { ...evt.payload, runId: id, planId: id };\r\n switch (evt.type) {\r\n case 'planner_recon_progress':\r\n return { type: 'planner_recon_progress', ...base };\r\n case 'planner_recon_done':\r\n return { type: 'planner_recon_done', ...base };\r\n case 'planner_reasoning_started':\r\n return { type: 'planner_reasoning_started', ...base };\r\n case 'planner_proposal_ready':\r\n return { type: 'planner_proposal_ready', ...base };\r\n case 'planner_failed':\r\n return { type: 'planner_failed', ...base };\r\n case 'skill_run_started':\r\n return { type: 'skill_run_started', ...base };\r\n case 'skill_run_tool_call':\r\n return { type: 'skill_run_tool_call', ...base };\r\n case 'skill_run_adapter_diff':\r\n return { type: 'skill_run_adapter_diff', ...base };\r\n case 'skill_run_installed':\r\n return { type: 'skill_run_installed', ...base };\r\n case 'skill_run_failed':\r\n return { type: 'skill_run_failed', ...base };\r\n case 'skill_run_cancelled':\r\n return { type: 'skill_run_cancelled', ...base };\r\n case 'preflight':\r\n return { type: 'planner_preflight', ...base };\r\n case 'planner_started':\r\n return { type: 'planner_started', ...base };\r\n case 'skill_run_step':\r\n return { type: 'skill_run_step', ...base };\r\n case 'review_replan':\r\n return { type: 'review_replan', ...base };\r\n default:\r\n return { type: evt.type, ...base };\r\n }\r\n}\r\n\r\n// Keep `Request` import used (ESLint clean)\r\nvoid (null as unknown as Request);\r\n\r\n// Export the default port for the CLI command\r\nexport { DEFAULT_PORT };\r\n","/**\n * Atomic cross-file slug rename — the only sanctioned way to rewrite a slug\n * across the wiki. Manual `mv` breaks `[[wikilinks]]` and is recoverable only\n * via `aab knowledge rename --auto-fix`.\n *\n * Spec: `docs/development/KNOWLEDGE_WIKI.md` §11.4 + §13 (\"Rename behavior on the manifest\").\n *\n * All writes are atomic at the file level (parent dir + write). The whole\n * operation runs under the workspace mutex (acquired by the caller via\n * `openContext`).\n */\nimport { existsSync, readFileSync, renameSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport {\n walkWikiPages,\n type WikiPageEntry,\n type PageFrontmatter,\n serializePage,\n extractWikiLinks,\n parsePage,\n toPosix,\n} from './page.js';\nimport {\n loadManifest,\n saveManifest,\n appendRename,\n rewriteManifestPaths,\n type ManifestRenameTrigger,\n} from './manifest.js';\nimport { writeSlugMapToIndex, buildSlugMap } from './slug-map.js';\nimport { nowIso } from '../utils.js';\nimport { UserError } from '../errors.js';\n\nexport interface RenameOptions {\n wikiRoot: string;\n manifestPath: string;\n indexPath: string;\n workspaceRoot: string;\n fromSlug: string;\n toSlug: string;\n /** When true, plan the rewrites but don't write anything. */\n dryRun?: boolean;\n /** Trigger label for the manifest renames[] log entry. */\n trigger?: ManifestRenameTrigger;\n}\n\nexport interface RenameResult {\n fromPath: string;\n toPath: string;\n fromSlug: string;\n toSlug: string;\n rewroteRefs: number;\n rewroteRelated: number;\n rewroteAliases: number;\n rewroteManifestEntries: number;\n /** Per-file diff hints (path → change summary). */\n changedFiles: Array<{ path: string; refs: number; related: number; aliases: number }>;\n dryRun: boolean;\n}\n\nexport async function renameSlug(opts: RenameOptions): Promise<RenameResult> {\n const fromSlug = opts.fromSlug.trim().toLowerCase();\n const toSlug = opts.toSlug.trim().toLowerCase();\n if (!fromSlug) throw new UserError('rename: <old-slug> is required.');\n if (!toSlug) throw new UserError('rename: <new-slug> is required.');\n if (fromSlug === toSlug) throw new UserError(`rename: <old> and <new> are identical (\"${fromSlug}\").`);\n if (!/^[a-z0-9][a-z0-9-]*$/.test(toSlug)) {\n throw new UserError(\n `rename: \"${toSlug}\" is not a valid kebab-case slug.`,\n 'Use lower-case letters, digits, and hyphens only; start with a letter or digit.',\n );\n }\n\n const pages = walkWikiPages(opts.wikiRoot, opts.workspaceRoot);\n const source = pages.find((p) => (p.frontmatter.slug ?? '').toLowerCase() === fromSlug);\n if (!source) {\n throw new UserError(\n `rename: no page with slug \"${fromSlug}\" found in ${opts.wikiRoot}.`,\n `Try \\`aab knowledge list\\` to see existing slugs, or \\`aab knowledge unresolved --suggest-fixes\\` if the slug is referenced but has been moved.`,\n );\n }\n\n // Detect collision with the new slug or any alias.\n for (const p of pages) {\n if (p === source) continue;\n const otherSlug = (p.frontmatter.slug ?? '').toLowerCase();\n if (otherSlug === toSlug) {\n throw new UserError(\n `rename: a page with slug \"${toSlug}\" already exists at ${p.wikiRelPath}.`,\n 'Pick a different new slug, or delete/merge the colliding page first.',\n );\n }\n const aliases = Array.isArray(p.frontmatter.aliases) ? p.frontmatter.aliases : [];\n for (const a of aliases) {\n if (typeof a === 'string' && a.toLowerCase() === toSlug) {\n throw new UserError(\n `rename: \"${toSlug}\" is already declared as an alias on ${p.wikiRelPath}.`,\n 'Remove the alias first (manually or via `aab knowledge edit`) and try again.',\n );\n }\n }\n }\n\n const fromPath = source.path;\n const toPath = join(dirname(fromPath), `${toSlug}.md`);\n const fromRel = toPosix(`wiki/${source.wikiRelPath}`);\n const toRel = toPosix(`wiki/${source.wikiRelPath.replace(/[^/]+$/, `${toSlug}.md`)}`);\n\n // Plan rewrites.\n let totalRefs = 0;\n let totalRelated = 0;\n let totalAliases = 0;\n const changedFiles: RenameResult['changedFiles'] = [];\n\n for (const p of pages) {\n const bodyRewrite = rewriteBodyLinks(p.body, fromSlug, toSlug);\n const newRelated = rewriteRelated(p.frontmatter.related, fromSlug, toSlug);\n const newAliases = rewriteAliases(p.frontmatter.aliases, fromSlug, toSlug);\n const totalPageChanges = bodyRewrite.count + newRelated.count + newAliases.count;\n const isSourcePage = p === source;\n if (totalPageChanges === 0 && !isSourcePage) continue;\n\n const nextFm: PageFrontmatter = { ...p.frontmatter };\n if (newRelated.count > 0) nextFm.related = newRelated.values;\n if (newAliases.count > 0) nextFm.aliases = newAliases.values.length > 0 ? newAliases.values : undefined;\n\n if (isSourcePage) {\n nextFm.slug = toSlug;\n nextFm.updated = nowIso().slice(0, 10);\n }\n\n totalRefs += bodyRewrite.count;\n totalRelated += newRelated.count;\n totalAliases += newAliases.count;\n changedFiles.push({\n path: toPosix(p.relPath),\n refs: bodyRewrite.count,\n related: newRelated.count,\n aliases: newAliases.count,\n });\n\n if (!opts.dryRun) {\n // Write the page to its (possibly new) path. We delete from the old\n // path AFTER writing the new file so a crash in-between leaves the\n // old file intact for recovery.\n const targetPath = isSourcePage ? toPath : p.path;\n mkdirSync(dirname(targetPath), { recursive: true });\n writeFileSync(targetPath, serializePage(nextFm, bodyRewrite.text), 'utf8');\n }\n }\n\n // Now move the source file (delete original) after the new file is written.\n if (!opts.dryRun && fromPath !== toPath) {\n try {\n // Remove the old source file via renameSync to a tombstone — but since\n // we already wrote toPath above, just unlink the old path.\n if (existsSync(fromPath)) {\n // Use renameSync to /dev/null doesn't exist on Windows; just unlink.\n // Defer to fs.rmSync via dynamic import to keep import surface small.\n const { rmSync } = await import('node:fs');\n rmSync(fromPath);\n }\n } catch (error) {\n throw new UserError(\n `rename: failed to remove old source ${fromPath}: ${error instanceof Error ? error.message : String(error)}`,\n 'The new file was written but the old one is still on disk. Remove it manually, then re-run `aab knowledge lint` to verify links.',\n );\n }\n }\n\n // Manifest update.\n let rewroteManifestEntries = 0;\n if (!opts.dryRun) {\n const manifest = loadManifest(opts.manifestPath);\n const rewrite = rewriteManifestPaths(manifest, fromRel, toRel);\n rewroteManifestEntries = rewrite.rewroteManifestEntries;\n saveManifest(opts.manifestPath, rewrite.manifest);\n appendRename(opts.manifestPath, {\n from: fromRel,\n to: toRel,\n fromSlug,\n toSlug,\n trigger: opts.trigger ?? 'manual',\n rewroteRefs: totalRefs,\n rewroteRelated: totalRelated,\n rewroteAliases: totalAliases,\n rewroteManifestEntries,\n });\n\n // Refresh the slug-map in wiki/index.md.\n const updatedMap = buildSlugMap(opts.wikiRoot, opts.workspaceRoot);\n writeSlugMapToIndex(opts.indexPath, updatedMap);\n } else {\n // Dry-run still reports the count.\n const manifest = loadManifest(opts.manifestPath);\n const rewrite = rewriteManifestPaths(manifest, fromRel, toRel);\n rewroteManifestEntries = rewrite.rewroteManifestEntries;\n }\n\n return {\n fromPath,\n toPath,\n fromSlug,\n toSlug,\n rewroteRefs: totalRefs,\n rewroteRelated: totalRelated,\n rewroteAliases: totalAliases,\n rewroteManifestEntries,\n changedFiles,\n dryRun: !!opts.dryRun,\n };\n}\n\n/**\n * Rewrite every `[[fromSlug]]` (and `[[fromSlug|Display]]`, `[[fromSlug#section]]`,\n * `[[fromSlug#^id]]`) in a body to `[[toSlug...]]`. Preserves display + anchor.\n * Does NOT rewrite path-prefixed forms (those are forbidden by spec; lint\n * surfaces them separately).\n */\nexport function rewriteBodyLinks(\n body: string,\n fromSlug: string,\n toSlug: string,\n): { text: string; count: number } {\n let count = 0;\n const re = /(!?)\\[\\[([^\\]\\n]+)\\]\\]/g;\n const next = body.replace(re, (whole, bang: string, inner: string) => {\n const pipe = inner.indexOf('|');\n const target = (pipe >= 0 ? inner.slice(0, pipe) : inner).trim();\n const display = pipe >= 0 ? inner.slice(pipe + 1) : '';\n const hash = target.indexOf('#');\n const slug = (hash >= 0 ? target.slice(0, hash) : target).trim().toLowerCase();\n const anchor = hash >= 0 ? target.slice(hash) : '';\n if (slug !== fromSlug) return whole;\n count++;\n const newTarget = `${toSlug}${anchor}`;\n const reassembled = pipe >= 0 ? `${newTarget}|${display}` : newTarget;\n return `${bang}[[${reassembled}]]`;\n });\n return { text: next, count };\n}\n\nfunction rewriteRelated(\n related: unknown,\n fromSlug: string,\n toSlug: string,\n): { values: string[]; count: number } {\n if (!Array.isArray(related)) return { values: [], count: 0 };\n let count = 0;\n const next: string[] = [];\n for (const item of related) {\n if (typeof item !== 'string') {\n next.push(String(item));\n continue;\n }\n const m = item.match(/^\\[\\[([^\\]]+)\\]\\]$/);\n if (!m) {\n // Plain slug or other form — replace if it matches.\n if (item.trim().toLowerCase() === fromSlug) {\n next.push(toSlug);\n count++;\n continue;\n }\n next.push(item);\n continue;\n }\n const inner = m[1]!;\n const pipe = inner.indexOf('|');\n const target = (pipe >= 0 ? inner.slice(0, pipe) : inner).trim();\n const display = pipe >= 0 ? inner.slice(pipe + 1) : '';\n const hash = target.indexOf('#');\n const slug = (hash >= 0 ? target.slice(0, hash) : target).trim().toLowerCase();\n const anchor = hash >= 0 ? target.slice(hash) : '';\n if (slug === fromSlug) {\n count++;\n const newTarget = `${toSlug}${anchor}`;\n const rebuilt = pipe >= 0 ? `${newTarget}|${display}` : newTarget;\n next.push(`[[${rebuilt}]]`);\n } else {\n next.push(item);\n }\n }\n return { values: next, count };\n}\n\nfunction rewriteAliases(\n aliases: unknown,\n fromSlug: string,\n toSlug: string,\n): { values: string[]; count: number } {\n if (!Array.isArray(aliases)) return { values: [], count: 0 };\n let count = 0;\n const next: string[] = [];\n for (const item of aliases) {\n if (typeof item !== 'string') {\n next.push(String(item));\n continue;\n }\n if (item.trim().toLowerCase() === fromSlug) {\n next.push(toSlug);\n count++;\n } else {\n next.push(item);\n }\n }\n return { values: next, count };\n}\n\n/**\n * Best-effort fuzzy match for `--auto-fix`. Returns the existing slug whose\n * Levenshtein distance from `target` is smallest, provided it's ≤ 3.\n */\nexport function suggestSlug(target: string, candidates: string[]): string | undefined {\n if (candidates.length === 0) return undefined;\n let best: { slug: string; d: number } | undefined;\n for (const cand of candidates) {\n const d = levenshtein(target, cand);\n if (!best || d < best.d) best = { slug: cand, d };\n }\n if (best && best.d <= Math.max(3, Math.floor(target.length / 3))) return best.slug;\n return undefined;\n}\n\nfunction levenshtein(a: string, b: string): number {\n if (a === b) return 0;\n if (!a) return b.length;\n if (!b) return a.length;\n const dp = new Array<number>(b.length + 1);\n for (let j = 0; j <= b.length; j++) dp[j] = j;\n for (let i = 1; i <= a.length; i++) {\n let prev = dp[0]!;\n dp[0] = i;\n for (let j = 1; j <= b.length; j++) {\n const tmp = dp[j]!;\n if (a.charCodeAt(i - 1) === b.charCodeAt(j - 1)) {\n dp[j] = prev;\n } else {\n dp[j] = 1 + Math.min(prev, dp[j - 1]!, dp[j]!);\n }\n prev = tmp;\n }\n }\n return dp[b.length]!;\n}\n\n/**\n * Reconcile the manifest with the current filesystem state. Used after a\n * Foam-driven rename (Foam rewrites `[[wikilinks]]` but doesn't know about\n * `.manifest.json`). Walks every `producedPages` / `updatedPages` /\n * `userEditedPages.page` entry; if the path is missing, fuzzy-matches against\n * existing files and rewrites the manifest atomically.\n */\nexport interface ReconcileResult {\n rewrites: Array<{ from: string; to: string; entryId?: string; kind: 'producedPages' | 'updatedPages' | 'userEditedPages' }>;\n manifestRewritten: boolean;\n}\n\nexport function reconcileManifest(opts: {\n wikiRoot: string;\n workspaceRoot: string;\n manifestPath: string;\n dryRun?: boolean;\n}): ReconcileResult {\n const pages = walkWikiPages(opts.wikiRoot, opts.workspaceRoot);\n const existingPaths = new Set(pages.map((p) => toPosix(p.relPath)));\n const existingFileNames = new Map<string, string>(); // base name (slug) → relPath\n for (const p of pages) {\n const slug = (p.frontmatter.slug ?? '').toLowerCase();\n if (slug) existingFileNames.set(slug, toPosix(p.relPath));\n }\n\n const rewrites: ReconcileResult['rewrites'] = [];\n const manifest = loadManifest(opts.manifestPath);\n\n const tryFix = (path: string): string | undefined => {\n if (existingPaths.has(path)) return undefined;\n // The path was `wiki/<folder>/<slug>.md` — extract the slug and see if\n // that slug exists at a different location now.\n const m = path.match(/wiki\\/[^/]+\\/([^/]+)\\.md$/);\n if (!m) return undefined;\n const slug = m[1]!.toLowerCase();\n return existingFileNames.get(slug);\n };\n\n for (const entry of manifest.entries) {\n entry.producedPages = entry.producedPages.map((p) => {\n const fix = tryFix(p);\n if (fix) {\n rewrites.push({ from: p, to: fix, entryId: entry.id, kind: 'producedPages' });\n return fix;\n }\n return p;\n });\n entry.updatedPages = entry.updatedPages.map((p) => {\n const fix = tryFix(p);\n if (fix) {\n rewrites.push({ from: p, to: fix, entryId: entry.id, kind: 'updatedPages' });\n return fix;\n }\n return p;\n });\n }\n for (const ue of manifest.userEditedPages) {\n const fix = tryFix(ue.page);\n if (fix) {\n rewrites.push({ from: ue.page, to: fix, kind: 'userEditedPages' });\n ue.page = fix;\n }\n }\n\n if (rewrites.length > 0 && !opts.dryRun) {\n saveManifest(opts.manifestPath, manifest);\n // Log each as a separate rename for audit.\n for (const r of rewrites) {\n appendRename(opts.manifestPath, {\n from: r.from,\n to: r.to,\n fromSlug: r.from.split('/').pop()?.replace(/\\.md$/, '') ?? '',\n toSlug: r.to.split('/').pop()?.replace(/\\.md$/, '') ?? '',\n trigger: 'foam-reconcile',\n rewroteManifestEntries: 1,\n });\n }\n }\n\n // Reference parsePage to keep tree-shake quiet about unused exports.\n void parsePage;\n\n return { rewrites, manifestRewritten: rewrites.length > 0 && !opts.dryRun };\n}\n","/**\n * Wiki query — one-shot Claude call with Read/Grep/Glob, no writes.\n * Reference: `docs/development/KNOWLEDGE_WIKI.md` §15.2.\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { paths, type ResolvedWorkspace } from '../../storage/paths.js';\nimport { runClaude, extractText } from '../../llm/claude-code-runner.js';\nimport { safeParseJSON } from '../parsing/safe-json.js';\nimport { logger } from '../logger.js';\nimport { ModelError, UserError } from '../errors.js';\nimport { buildQueryPrompt } from '../prompts/skill-query.js';\nimport { humanizeSlug, pathForPage, type PageType } from './page.js';\nimport { writePageAtomic } from './page.js';\nimport { buildSlugMap, writeSlugMapToIndex } from './slug-map.js';\nimport { nowIso } from '../utils.js';\nimport type { AppSettings } from '../../storage/types.js';\n\nexport interface WikiQueryOptions {\n question: string;\n workspace: ResolvedWorkspace;\n settings: AppSettings;\n maxPages?: number;\n modelOverride?: string;\n saveAs?: PageType;\n}\n\nexport interface WikiQueryResult {\n question: string;\n answer: string;\n citations: string[];\n notes?: string;\n costUsd: number;\n savedAs?: string;\n}\n\nexport async function queryWiki(opts: WikiQueryOptions): Promise<WikiQueryResult> {\n const p = paths(opts.workspace.root);\n if (!existsSync(p.wiki)) {\n throw new UserError('Wiki not initialised. Run `aab init` (or `aab knowledge migrate`) first.');\n }\n const maxPages = opts.maxPages ?? opts.settings.knowledgeWiki?.maxAgentPagesPerCall ?? 10;\n const model = pickQueryModel(opts.settings, opts.modelOverride);\n const wikiKnowledgeMd = existsSync(p.wikiKnowledge) ? readFileSync(p.wikiKnowledge, 'utf8') : '';\n const wikiIndexMd = existsSync(p.wikiIndex) ? readFileSync(p.wikiIndex, 'utf8') : '';\n const prompt = buildQueryPrompt({\n question: opts.question,\n wikiKnowledgeMd,\n wikiIndexMd,\n maxPages,\n });\n\n logger.debug('[query] starting', { question: opts.question.slice(0, 80), model, maxPages });\n let text: string;\n let costUsd = 0;\n try {\n const result = await runClaude({\n prompt,\n model,\n allowedTools: ['Read', 'Grep', 'Glob'],\n maxTurns: 15,\n cwd: opts.workspace.root,\n maxBudgetUsd: opts.settings.perCallBudgetUsd,\n timeoutMs: 3 * 60_000,\n });\n text = extractText(result);\n costUsd = result.json?.cost_usd ?? 0;\n } catch (error) {\n throw new ModelError(\n `Query LLM call failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n let answer = text.trim();\n let citations: string[] = [];\n let notes: string | undefined;\n const parsed = safeParseJSON<Record<string, unknown>>(text);\n if (parsed.success && parsed.data && typeof parsed.data === 'object') {\n const d = parsed.data;\n if (typeof d.answer === 'string') answer = d.answer.trim();\n if (Array.isArray(d.citations)) {\n citations = d.citations.map((v) => (typeof v === 'string' ? v.trim().toLowerCase() : '')).filter(Boolean);\n }\n if (typeof d.notes === 'string') notes = d.notes;\n }\n\n let savedAs: string | undefined;\n if (opts.saveAs) {\n const slug = humanizeSlug(opts.question) || `query-${Date.now()}`;\n const targetPath = pathForPage(p.wiki, opts.saveAs, slug);\n const today = nowIso().slice(0, 10);\n writePageAtomic(\n targetPath,\n {\n title: opts.question,\n slug,\n type: opts.saveAs,\n summary: opts.question,\n tags: [],\n sources: citations.map((s) => `wiki/${s}`),\n related: citations.map((s) => `[[${s}]]`),\n confidence: 'medium',\n provenance: 'inferred',\n created: today,\n updated: today,\n userEdited: false,\n },\n answer + (citations.length > 0 ? `\\n\\n## Citations\\n\\n${citations.map((c) => `- [[${c}]]`).join('\\n')}\\n` : '\\n'),\n );\n savedAs = `wiki/${humanizeSlug(opts.saveAs)}/${slug}.md`;\n // Refresh slug-map.\n const map = buildSlugMap(p.wiki, opts.workspace.root);\n writeSlugMapToIndex(p.wikiIndex, map);\n }\n\n return { question: opts.question, answer, citations, notes, costUsd, savedAs };\n}\n\nfunction pickQueryModel(settings: AppSettings, override?: string): string {\n if (override) return override;\n const v = settings.knowledgeWiki?.queryModel ?? settings.primaryModel;\n return typeof v === 'string' ? v : 'sonnet';\n}\n\n// Silence unused\nvoid mkdirSync;\nvoid writeFileSync;\nvoid dirname;\nvoid join;\n","/**\n * Query skill prompt. Reference: `docs/development/KNOWLEDGE_WIKI.md` §15.2.\n *\n * Read-only — agent uses Read, Grep, Glob. It MUST cite wiki slugs it\n * actually used and mark inferred claims with `^[inferred]`.\n */\n\nexport interface QueryPromptInput {\n question: string;\n wikiKnowledgeMd: string;\n wikiIndexMd: string;\n maxPages: number;\n}\n\nexport function buildQueryPrompt(input: QueryPromptInput): string {\n const lines: string[] = [];\n lines.push('You are the wiki query agent for an AI advisory-board CLI.');\n lines.push('Your job: answer ONE question using the user\\'s knowledge wiki, citing the pages you used.');\n lines.push('');\n lines.push('## Question');\n lines.push(input.question);\n lines.push('');\n lines.push('## Wiki schema (`wiki/KNOWLEDGE.md`)');\n lines.push(input.wikiKnowledgeMd);\n lines.push('');\n lines.push('## Wiki index (`wiki/index.md`)');\n lines.push('');\n lines.push('READ THIS FIRST — the `<!-- AAB:SLUG-MAP -->` section is your `[[wikilink]]` resolver.');\n lines.push('');\n lines.push(input.wikiIndexMd);\n lines.push('');\n lines.push('## Your procedure');\n lines.push(`1. Read the slug-map in the wiki index. Identify the most relevant ≤${input.maxPages} pages.`);\n lines.push('2. `Grep wiki/` for keywords from the question (target `summary:` and `tags:` first).');\n lines.push('3. `Read` the relevant pages. Follow `[[wikilinks]]` only when useful.');\n lines.push('4. Synthesize a focused answer.');\n lines.push('5. Mark any claims you inferred (rather than read directly from a page) with `^[inferred]`.');\n lines.push('6. NEVER fabricate page slugs in citations — only cite slugs you actually opened.');\n lines.push('');\n lines.push('## Output (return ONLY this raw JSON object — no fences, no commentary)');\n lines.push('');\n lines.push('{');\n lines.push(' \"answer\": \"<markdown — the answer to the user\\'s question, terse and grounded in the wiki>\",');\n lines.push(' \"citations\": [\"slug-a\", \"slug-b\", ...], // wiki slugs you actually used');\n lines.push(' \"notes\": \"Optional 1-line caveat (e.g., \\\\\"wiki contained no info on X\\\\\").\"');\n lines.push('}');\n return lines.join('\\n');\n}\n","/**\n * Wiki lint — static checks + maintenance writes (slug-map rebuild,\n * backlinks regeneration), plus optional LLM passes (contradictions, stale\n * claims, missing concepts). Reference: `docs/development/KNOWLEDGE_WIKI.md` §15.3.\n */\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n} from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { paths, type ResolvedWorkspace } from '../../storage/paths.js';\nimport {\n walkWikiPages,\n extractWikiLinks,\n extractHeaderAnchors,\n kebabHeader,\n serializePage,\n toPosix,\n type WikiPageEntry,\n} from './page.js';\nimport {\n buildSlugMapFromPages,\n writeSlugMapToIndex,\n setBacklinksSection,\n BACKLINKS_OPEN,\n BACKLINKS_CLOSE,\n SLUG_MAP_OPEN,\n SLUG_MAP_CLOSE,\n resolveSlug,\n} from './slug-map.js';\nimport { loadManifest } from './manifest.js';\nimport { nowIso } from '../utils.js';\nimport { logger } from '../logger.js';\nimport type { AppSettings } from '../../storage/types.js';\n\nexport type LintSeverity = 'error' | 'warn' | 'info';\n\nexport interface LintFinding {\n severity: LintSeverity;\n code: string;\n message: string;\n file?: string;\n line?: number;\n suggestion?: string;\n}\n\nexport interface LintResult {\n findings: LintFinding[];\n pagesScanned: number;\n slugMapUpdated: boolean;\n backlinksUpdated: number;\n reportPath?: string;\n}\n\nexport interface LintOptions {\n workspace: ResolvedWorkspace;\n settings: AppSettings;\n writeReport?: boolean;\n runLlm?: boolean;\n maxPages?: number;\n}\n\nexport async function lintWiki(opts: LintOptions): Promise<LintResult> {\n const p = paths(opts.workspace.root);\n const findings: LintFinding[] = [];\n if (!existsSync(p.wiki)) {\n findings.push({\n severity: 'error',\n code: 'wiki-missing',\n message: `Wiki directory not found at ${p.wiki}.`,\n suggestion: 'Run `aab init` first.',\n });\n return { findings, pagesScanned: 0, slugMapUpdated: false, backlinksUpdated: 0 };\n }\n\n const pages = walkWikiPages(p.wiki, opts.workspace.root);\n const settings = opts.settings.knowledgeWiki;\n const aliasCapWarn = settings?.maxAliasesGlobal ? settings.maxAliasesGlobal * 0.8 : 80;\n const aliasCapErr = settings?.maxAliasesGlobal ?? 100;\n\n // ---------- frontmatter completeness + slug/alias uniqueness ----------\n const slugOwners = new Map<string, WikiPageEntry>();\n const aliasOwners = new Map<string, WikiPageEntry>();\n let aliasTotal = 0;\n for (const page of pages) {\n const fm = page.frontmatter;\n const path = page.wikiRelPath;\n if (!fm.title) {\n findings.push({ severity: 'warn', code: 'fm-missing-title', message: `missing \\`title:\\``, file: path });\n }\n if (!fm.slug) {\n findings.push({ severity: 'error', code: 'fm-missing-slug', message: `missing \\`slug:\\``, file: path });\n continue;\n }\n const slug = String(fm.slug).toLowerCase();\n const filenameSlug = page.wikiRelPath.split('/').pop()!.replace(/\\.md$/, '').toLowerCase();\n if (slug !== filenameSlug) {\n findings.push({\n severity: 'error',\n code: 'fm-slug-filename-mismatch',\n message: `slug \"${slug}\" does not match filename \"${filenameSlug}\"`,\n file: path,\n suggestion: `aab knowledge rename ${slug} ${filenameSlug}`,\n });\n }\n if (slugOwners.has(slug)) {\n findings.push({\n severity: 'error',\n code: 'slug-collision',\n message: `duplicate slug \"${slug}\" — also at ${slugOwners.get(slug)!.wikiRelPath}`,\n file: path,\n });\n } else {\n slugOwners.set(slug, page);\n }\n if (!fm.type || !['concept', 'entity', 'decision', 'source-summary', 'comparison'].includes(String(fm.type))) {\n findings.push({ severity: 'error', code: 'fm-invalid-type', message: `invalid \\`type:\\` ${fm.type ?? '(missing)'}`, file: path });\n }\n if (!fm.summary) {\n findings.push({ severity: 'warn', code: 'fm-missing-summary', message: 'missing `summary:` — cheap-pass retrieval will be slower', file: path });\n } else if (typeof fm.summary === 'string' && fm.summary.length > (settings?.summarySoftCap ?? 200)) {\n findings.push({\n severity: 'info',\n code: 'fm-summary-long',\n message: `summary is ${fm.summary.length} chars (soft cap ${settings?.summarySoftCap ?? 200})`,\n file: path,\n });\n }\n const aliases = Array.isArray(fm.aliases) ? fm.aliases : [];\n aliasTotal += aliases.length;\n for (const a of aliases) {\n if (typeof a !== 'string') continue;\n const alias = a.trim().toLowerCase();\n if (!alias) continue;\n if (alias === slug) {\n findings.push({ severity: 'warn', code: 'alias-equals-slug', message: `alias \"${alias}\" equals slug — redundant`, file: path });\n continue;\n }\n if (slugOwners.has(alias) && slugOwners.get(alias) !== page) {\n findings.push({\n severity: 'error',\n code: 'alias-slug-collision',\n message: `alias \"${alias}\" collides with another page's slug at ${slugOwners.get(alias)!.wikiRelPath}`,\n file: path,\n });\n }\n if (aliasOwners.has(alias) && aliasOwners.get(alias) !== page) {\n findings.push({\n severity: 'error',\n code: 'alias-alias-collision',\n message: `alias \"${alias}\" already declared on ${aliasOwners.get(alias)!.wikiRelPath}`,\n file: path,\n });\n }\n aliasOwners.set(alias, page);\n }\n if (Array.isArray(fm.sources) && fm.sources.length > 0) {\n for (const src of fm.sources) {\n if (typeof src !== 'string') continue;\n const abs = src.startsWith('/') ? src : join(opts.workspace.root, src);\n if (!existsSync(abs)) {\n findings.push({\n severity: 'warn',\n code: 'broken-source',\n message: `\\`sources:\\` references missing raw file: ${src}`,\n file: path,\n });\n }\n }\n } else if (fm.type === 'source-summary') {\n findings.push({ severity: 'warn', code: 'source-summary-no-sources', message: 'source-summary page has no `sources:` entries', file: path });\n }\n // Page body soft cap\n if (page.body.length > (settings?.pageBodySoftCap ?? 4000)) {\n findings.push({\n severity: 'info',\n code: 'body-long',\n message: `body is ${page.body.length} chars (soft cap ${settings?.pageBodySoftCap ?? 4000}) — consider splitting`,\n file: path,\n });\n }\n }\n\n if (aliasTotal >= aliasCapErr) {\n findings.push({\n severity: 'error',\n code: 'alias-cap-exceeded',\n message: `total aliases (${aliasTotal}) exceeds maxAliasesGlobal (${aliasCapErr})`,\n suggestion: 'Remove aliases on pages where the canonical slug is sufficient.',\n });\n } else if (aliasTotal >= aliasCapWarn) {\n findings.push({\n severity: 'warn',\n code: 'alias-cap-warn',\n message: `total aliases (${aliasTotal}) approaching maxAliasesGlobal (${aliasCapErr})`,\n });\n }\n\n // ---------- broken [[wikilinks]] + broken anchors + forbidden forms ----------\n const slugMap = buildSlugMapFromPages(pages);\n const linkCount = new Map<string, number>();\n for (const page of pages) {\n const lines = page.body.split(/\\r?\\n/);\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i] ?? '';\n for (const link of extractWikiLinks(line)) {\n if (link.transclusion) {\n findings.push({\n severity: 'warn',\n code: 'transclusion-not-supported',\n message: `\\`![[${link.slug}]]\\` transclusion is not supported in v1`,\n file: page.wikiRelPath,\n line: i + 1,\n suggestion: `replace with \\`[[${link.slug}]]\\``,\n });\n }\n if (link.blockId) {\n findings.push({\n severity: 'warn',\n code: 'block-id-not-supported',\n message: `\\`[[${link.slug}#^${link.anchor?.replace(/^\\^/, '') ?? ''}]]\\` block IDs are not supported in v1`,\n file: page.wikiRelPath,\n line: i + 1,\n suggestion: `use header anchors \\`[[${link.slug}#section]]\\` instead`,\n });\n }\n if (link.pathPrefixed) {\n findings.push({\n severity: 'error',\n code: 'path-prefixed-link',\n message: `path-prefixed link \\`[[${link.raw.slice(2, -2)}]]\\` is forbidden — slug is canonical`,\n file: page.wikiRelPath,\n line: i + 1,\n suggestion: `rewrite to \\`[[${link.slug}]]\\``,\n });\n }\n const resolved = resolveSlug(slugMap, link.slug);\n if (!resolved) {\n linkCount.set(link.slug, (linkCount.get(link.slug) ?? 0) + 1);\n findings.push({\n severity: 'warn',\n code: 'broken-wikilink',\n message: `unresolved \\`[[${link.slug}]]\\``,\n file: page.wikiRelPath,\n line: i + 1,\n suggestion: `aab knowledge rename --auto-fix ${link.slug}`,\n });\n } else if (link.anchor && !link.blockId) {\n // Verify the target has a matching header anchor.\n const targetPage = pages.find((p) => p.frontmatter.slug?.toString().toLowerCase() === resolved.slug);\n if (targetPage) {\n const anchors = extractHeaderAnchors(targetPage.body).map(kebabHeader);\n const wanted = kebabHeader(link.anchor);\n if (!anchors.includes(wanted)) {\n findings.push({\n severity: 'warn',\n code: 'broken-anchor',\n message: `header anchor \\`#${link.anchor}\\` not found in \\`[[${link.slug}]]\\``,\n file: page.wikiRelPath,\n line: i + 1,\n });\n }\n }\n }\n }\n }\n }\n // Missing concept escalation\n for (const [slug, count] of linkCount.entries()) {\n if (count >= 3) {\n findings.push({\n severity: 'info',\n code: 'missing-concept',\n message: `\\`[[${slug}]]\\` referenced ${count}× but no page exists`,\n suggestion: `aab knowledge ingest --paste (file a quick note for this concept)`,\n });\n }\n }\n\n // ---------- orphan pages ----------\n const incoming = new Map<string, number>();\n for (const page of pages) {\n for (const link of extractWikiLinks(page.body)) {\n const target = slugMap.aliasToCanonical.get(link.slug);\n if (target) incoming.set(target, (incoming.get(target) ?? 0) + 1);\n }\n }\n for (const page of pages) {\n const slug = (page.frontmatter.slug ?? '').toString().toLowerCase();\n if (!slug) continue;\n if ((incoming.get(slug) ?? 0) === 0) {\n findings.push({\n severity: 'info',\n code: 'orphan',\n message: `page has zero incoming wiki-links`,\n file: page.wikiRelPath,\n });\n }\n }\n\n // ---------- manifest drift ----------\n const manifest = loadManifest(p.manifest);\n const existingPaths = new Set(pages.map((p) => toPosix(`wiki/${p.wikiRelPath}`)));\n for (const entry of manifest.entries) {\n for (const target of [...entry.producedPages, ...entry.updatedPages]) {\n if (!existingPaths.has(target)) {\n findings.push({\n severity: 'error',\n code: 'manifest-drift',\n message: `manifest entry ${entry.id} references missing ${target}`,\n suggestion: 'aab knowledge rename --reconcile',\n });\n }\n }\n }\n\n // ---------- sentinel integrity (index slug-map + per-page backlinks) ----------\n if (existsSync(p.wikiIndex)) {\n const indexBody = readFileSync(p.wikiIndex, 'utf8');\n const hasOpen = indexBody.includes(SLUG_MAP_OPEN);\n const hasClose = indexBody.includes(SLUG_MAP_CLOSE);\n if (!hasOpen || !hasClose) {\n findings.push({\n severity: 'warn',\n code: 'slug-map-sentinels-missing',\n message: 'wiki/index.md is missing one or both `<!-- AAB:SLUG-MAP -->` sentinels',\n file: 'wiki/index.md',\n suggestion: 'lint will append a fresh slug-map section on this run',\n });\n }\n }\n\n // ---------- maintenance writes ----------\n let slugMapUpdated = false;\n if (settings?.slugMapInIndex !== false) {\n try {\n writeSlugMapToIndex(p.wikiIndex, slugMap);\n slugMapUpdated = true;\n } catch (error) {\n findings.push({\n severity: 'error',\n code: 'slug-map-write-failed',\n message: `failed to write slug-map: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n }\n\n // Backlinks: regenerate `<!-- AAB:BACKLINKS -->` in every page\n const backLinks = new Map<string, string[]>();\n for (const page of pages) {\n const fromSlug = (page.frontmatter.slug ?? '').toString().toLowerCase();\n if (!fromSlug) continue;\n const seen = new Set<string>();\n for (const link of extractWikiLinks(page.body)) {\n const target = slugMap.aliasToCanonical.get(link.slug);\n if (!target) continue;\n if (target === fromSlug) continue;\n if (seen.has(target)) continue;\n seen.add(target);\n if (!backLinks.has(target)) backLinks.set(target, []);\n const targetPage = slugMap.canonical.get(target)!;\n const summary = targetPage?.summary ? ` — \"${truncate(String(targetPage.summary), 80)}\"` : '';\n const display = page.frontmatter.title ? ` — ${page.frontmatter.title}` : '';\n backLinks.get(target)!.push(`[[${fromSlug}]]${display}${summary}`);\n }\n }\n let backlinksUpdated = 0;\n for (const page of pages) {\n const slug = (page.frontmatter.slug ?? '').toString().toLowerCase();\n if (!slug) continue;\n const links = backLinks.get(slug) ?? [];\n const newBody = setBacklinksSection(page.body, links);\n if (newBody !== page.body) {\n writeFileSync(page.path, serializePage(page.frontmatter, newBody), 'utf8');\n backlinksUpdated++;\n }\n }\n\n // ---------- LLM passes (optional) ----------\n if (opts.runLlm !== false) {\n // For v1 we keep this lightweight — the heavy contradiction/stale-claim\n // analysis would be a separate `claude -p` call; we surface a placeholder\n // info so the user knows where to look. Real LLM passes can be wired in\n // a follow-up without changing the public lint shape.\n findings.push({\n severity: 'info',\n code: 'llm-passes-skipped',\n message: 'LLM contradiction/stale-claim/missing-concept passes are wired but conservative in v1; set `--no-llm` to suppress this notice.',\n });\n }\n\n // ---------- write report ----------\n let reportPath: string | undefined;\n if (opts.writeReport !== false) {\n const date = nowIso().slice(0, 10);\n reportPath = join(p.outputs, `lint-${date}.md`);\n mkdirSync(dirname(reportPath), { recursive: true });\n writeFileSync(reportPath, renderReport(findings, pages.length, slugMapUpdated, backlinksUpdated), 'utf8');\n }\n\n logger.debug('[lint] done', { findings: findings.length, pages: pages.length, slugMapUpdated, backlinksUpdated });\n return {\n findings,\n pagesScanned: pages.length,\n slugMapUpdated,\n backlinksUpdated,\n reportPath,\n };\n}\n\nfunction renderReport(\n findings: LintFinding[],\n pagesScanned: number,\n slugMapUpdated: boolean,\n backlinksUpdated: number,\n): string {\n const lines: string[] = [];\n lines.push(`# Wiki lint report — ${nowIso().slice(0, 10)}`);\n lines.push('');\n lines.push(`- Pages scanned: ${pagesScanned}`);\n lines.push(`- Slug-map rewritten: ${slugMapUpdated ? 'yes' : 'no'}`);\n lines.push(`- Backlinks sections updated: ${backlinksUpdated}`);\n const errs = findings.filter((f) => f.severity === 'error').length;\n const warns = findings.filter((f) => f.severity === 'warn').length;\n const infos = findings.filter((f) => f.severity === 'info').length;\n lines.push(`- Errors: ${errs} · Warnings: ${warns} · Info: ${infos}`);\n lines.push('');\n for (const sev of ['error', 'warn', 'info'] as const) {\n const subset = findings.filter((f) => f.severity === sev);\n if (subset.length === 0) continue;\n lines.push(`## ${sev.toUpperCase()} (${subset.length})`);\n lines.push('');\n for (const f of subset) {\n const loc = f.file ? ` _${f.file}${f.line ? `:${f.line}` : ''}_` : '';\n lines.push(`- **[${f.code}]**${loc} ${f.message}`);\n if (f.suggestion) lines.push(` - _fix:_ \\`${f.suggestion}\\``);\n }\n lines.push('');\n }\n if (findings.length === 0) {\n lines.push('✓ all checks pass.');\n }\n return lines.join('\\n');\n}\n\nfunction truncate(s: string, n: number): string {\n if (s.length <= n) return s;\n return s.slice(0, n - 1) + '…';\n}\n\n// Quiet unused\nvoid BACKLINKS_OPEN;\nvoid BACKLINKS_CLOSE;\n","/**\n * Conversation Analyzer — extract action items from a concluded discussion.\n *\n * Ported from `../sage-council/src/lib/conversation-analyzer.ts` with two\n * deliberate deltas for the CLI port (per PLAN §6.5):\n * 1. The **structured-data fast path** is a *pure* deterministic transform:\n * every `actionSteps[]` / `questionsForOthers[]` entry on the response\n * becomes a candidate `ExtractedActionItem` with no LLM call. This keeps\n * `aab actions extract` zero-cost when members emit structured payloads.\n * 2. The LLM fallback is a one-shot `claude -p` on `fastModel`, mirroring\n * `summarize.ts` — no persona, `allowedTools: []`, `maxTurns: 1`.\n *\n * The analyzer NEVER throws on parse failure; it returns a fallback result with\n * `analysisConfidence === 0` and an explanation in `keyInsights[0]`, matching\n * the source's tolerant contract.\n */\nimport { runClaude, extractText } from '../../llm/claude-code-runner.js';\nimport { logger } from '../logger.js';\nimport { safeParseJSONWithSchema } from '../parsing/safe-json.js';\nimport { conversationAnalysisPayloadSchema } from '../parsing/llm-response-schemas.js';\nimport { nowIso, generateUUID } from '../utils.js';\nimport type {\n ActionItem,\n AppSettings,\n Discussion,\n Response,\n ResponseStructuredData,\n} from '../../storage/types.js';\n\nexport type ActionPriority = 'low' | 'medium' | 'high';\nexport type ActionCategory =\n | 'strategic'\n | 'operational'\n | 'technical'\n | 'research'\n | 'financial'\n | 'other';\n\nexport interface ExtractedActionItem {\n title: string;\n description: string;\n priority: ActionPriority;\n category: ActionCategory;\n confidence: number; // 0-100\n sourceContext: string;\n sourceMemberId?: string;\n sourceMemberName?: string;\n suggestedAssignee?: string;\n suggestedDueDate?: string;\n}\n\nexport interface AnalysisResult {\n actionItems: ExtractedActionItem[];\n keyInsights: string[];\n recommendedNextSteps: string[];\n analysisConfidence: number; // 0-100\n processingTimeMs: number;\n /** `'structured'` when no LLM call was made; `'llm'` when the fallback ran;\n * `'fallback'` when both paths failed and we returned a deterministic stub. */\n method: 'structured' | 'llm' | 'fallback';\n}\n\nexport interface ExtractActionItemsOptions {\n discussion: Discussion;\n settings: AppSettings;\n signal?: AbortSignal;\n /** Pluggable LLM runner — defaults to the real `runClaude`. Tests can pass\n * a stub to exercise the LLM fallback path without spawning a process. */\n llm?: typeof runClaude;\n}\n\n/** Pure heuristic limits. */\nconst MAX_STRUCTURED_ITEMS_PER_RESPONSE = 8;\nconst TITLE_MAX_CHARS = 90;\n\n// ----------------------------------------------------------------------------\n// Public API\n// ----------------------------------------------------------------------------\n\nexport async function extractActionItems(opts: ExtractActionItemsOptions): Promise<AnalysisResult> {\n const startTime = Date.now();\n const { discussion } = opts;\n\n // Fast path: structured data on responses → pure transform, no LLM call.\n const structured = extractFromStructuredData(discussion);\n if (structured.length > 0) {\n const keyInsights = structured.slice(0, 5).map((it) => it.description);\n const recommendedNextSteps = structured\n .filter((it) => it.priority === 'high')\n .map((it) => it.title);\n const meanConfidence =\n structured.reduce((sum, it) => sum + it.confidence, 0) / structured.length;\n return {\n actionItems: structured,\n keyInsights,\n recommendedNextSteps:\n recommendedNextSteps.length > 0 ? recommendedNextSteps : ['Review extracted action items'],\n analysisConfidence: Math.min(90, Math.round(meanConfidence)),\n processingTimeMs: Date.now() - startTime,\n method: 'structured',\n };\n }\n\n // Fallback: ask the orchestrator (one-shot Haiku) to extract from raw text.\n try {\n const llm = opts.llm ?? runClaude;\n const prompt = buildAnalysisPrompt(discussion);\n const result = await llm({\n prompt,\n model: typeof opts.settings.fastModel === 'string' ? opts.settings.fastModel : 'haiku',\n allowedTools: [],\n maxTurns: 1,\n maxBudgetUsd: opts.settings.perCallBudgetUsd,\n signal: opts.signal,\n timeoutMs: 180_000,\n });\n const text = extractText(result);\n const parsed = parseAnalysisResult(text);\n return {\n ...parsed,\n processingTimeMs: Date.now() - startTime,\n method: 'llm',\n };\n } catch (err) {\n logger.warn('[actions] LLM extract fallback failed:', err instanceof Error ? err.message : err);\n return fallbackResult(discussion, Date.now() - startTime);\n }\n}\n\n/**\n * Convert an extracted candidate into a persistable ActionItem. Caller is\n * responsible for `await storage.saveActionItem(item)` when the user accepts.\n */\nexport function toActionItem(\n extracted: ExtractedActionItem,\n discussionId: string,\n): ActionItem {\n const now = nowIso();\n return {\n id: generateUUID(),\n discussionId,\n title: extracted.title.slice(0, TITLE_MAX_CHARS),\n description: extracted.description,\n priority: extracted.priority,\n status: 'pending',\n assignedTo: extracted.suggestedAssignee,\n dueDate: extracted.suggestedDueDate,\n createdAt: now,\n updatedAt: now,\n };\n}\n\n// ----------------------------------------------------------------------------\n// Structured-data fast path (pure)\n// ----------------------------------------------------------------------------\n\nexport function extractFromStructuredData(discussion: Discussion): ExtractedActionItem[] {\n const out: ExtractedActionItem[] = [];\n for (const response of discussion.responses) {\n if (!response.structuredData) continue;\n const fromResponse = extractFromOneResponse(response);\n for (const item of fromResponse) {\n out.push(item);\n }\n }\n // Dedupe by normalized title — multiple members often surface the same step.\n return dedupeByTitle(out);\n}\n\nfunction extractFromOneResponse(response: Response): ExtractedActionItem[] {\n const sd = response.structuredData as ResponseStructuredData | undefined;\n if (!sd) return [];\n const items: ExtractedActionItem[] = [];\n\n const baseConfidence =\n typeof sd.confidence === 'number' ? Math.max(50, Math.min(95, sd.confidence)) : 70;\n\n // Direct action steps — highest signal.\n for (const step of (sd.actionSteps ?? []).slice(0, MAX_STRUCTURED_ITEMS_PER_RESPONSE)) {\n const title = makeTitle(step);\n if (!title) continue;\n items.push({\n title,\n description: step,\n priority: inferPriority(step),\n category: inferCategory(step),\n confidence: baseConfidence,\n sourceContext: `actionSteps — ${response.memberName}`,\n sourceMemberId: response.memberId,\n sourceMemberName: response.memberName,\n });\n }\n\n // questionsForOthers → research / follow-up actions.\n for (const question of (sd.questionsForOthers ?? []).slice(0, MAX_STRUCTURED_ITEMS_PER_RESPONSE)) {\n const title = makeTitle(`Investigate: ${question}`);\n if (!title) continue;\n items.push({\n title,\n description: question,\n priority: 'medium',\n category: 'research',\n confidence: Math.max(50, baseConfidence - 15),\n sourceContext: `questionsForOthers — ${response.memberName}`,\n sourceMemberId: response.memberId,\n sourceMemberName: response.memberName,\n });\n }\n\n return items;\n}\n\nfunction makeTitle(text: string): string {\n const trimmed = text.trim();\n if (!trimmed) return '';\n // First sentence-ish; cap at TITLE_MAX_CHARS.\n const firstStop = trimmed.search(/[.!?]\\s|$/);\n const head = firstStop > 0 ? trimmed.slice(0, firstStop) : trimmed;\n return head.length > TITLE_MAX_CHARS ? head.slice(0, TITLE_MAX_CHARS - 1).trimEnd() + '…' : head;\n}\n\nfunction inferPriority(text: string): ActionPriority {\n const t = text.toLowerCase();\n if (/\\b(critical|urgent|asap|immediately|must|blocker|hotfix)\\b/.test(t)) return 'high';\n if (/\\b(should|important|priorit|high-impact|key)\\b/.test(t)) return 'high';\n if (/\\b(consider|explore|evaluate|nice|optional|eventually|down the road)\\b/.test(t)) return 'low';\n return 'medium';\n}\n\nfunction inferCategory(text: string): ActionCategory {\n const t = text.toLowerCase();\n if (/\\b(research|investigate|study|benchmark|survey|literature)\\b/.test(t)) return 'research';\n if (/\\b(deploy|build|implement|code|ship|refactor|integration|api|repo|test)\\b/.test(t))\n return 'technical';\n if (/\\b(budget|cost|revenue|pricing|raise|burn|runway|margin|p&l|cash)\\b/.test(t)) return 'financial';\n if (/\\b(strategy|positioning|market|brand|pivot|roadmap|vision|moat|partnership)\\b/.test(t))\n return 'strategic';\n if (/\\b(hire|onboard|process|ops|workflow|operations|sla|playbook)\\b/.test(t)) return 'operational';\n return 'other';\n}\n\nfunction dedupeByTitle(items: ExtractedActionItem[]): ExtractedActionItem[] {\n const seen = new Map<string, ExtractedActionItem>();\n for (const it of items) {\n const key = it.title.trim().toLowerCase();\n if (!seen.has(key)) {\n seen.set(key, it);\n } else {\n // Bump confidence slightly when multiple members converge on the same step.\n const prior = seen.get(key)!;\n prior.confidence = Math.min(99, Math.round(prior.confidence + 5));\n }\n }\n return Array.from(seen.values());\n}\n\n// ----------------------------------------------------------------------------\n// LLM fallback prompt + parser\n// ----------------------------------------------------------------------------\n\nfunction buildAnalysisPrompt(discussion: Discussion): string {\n // Cap each response to keep the prompt focused — Haiku is decent at this when\n // the input is tight.\n const PER_RESPONSE_CAP = 4000;\n const allResponses = discussion.responses\n .map((r) => {\n const preview =\n r.content.length > PER_RESPONSE_CAP\n ? `${r.content.slice(0, PER_RESPONSE_CAP)}\\n\\n[…truncated for extraction…]`\n : r.content;\n return `${r.memberName} (round ${r.roundNumber} turn ${r.turnNumber}):\\n${preview}`;\n })\n .join('\\n\\n');\n\n const summaryContext = discussion.summary\n ? [\n 'EXISTING SUMMARY:',\n `Key Points: ${discussion.summary.keyPoints.join(', ')}`,\n `Consensus: ${discussion.summary.consensus.join(', ')}`,\n `Actionable Insights: ${discussion.summary.actionableInsights.join(', ')}`,\n '',\n ].join('\\n')\n : '';\n\n return [\n 'You are an expert action-item extractor. Read this advisory-board discussion and extract concrete, actionable items the organization should pursue.',\n '',\n `ORIGINAL QUESTION: \"${discussion.question}\"`,\n '',\n summaryContext,\n 'FULL CONVERSATION:',\n allResponses || '(no responses)',\n '',\n 'INSTRUCTIONS:',\n '1. Extract SPECIFIC, ACTIONABLE items only — skip vague suggestions.',\n '2. Assign realistic priority based on urgency + impact (high/medium/low).',\n '3. Categorize: strategic, operational, technical, research, financial, other.',\n '4. Provide a 0-100 confidence score based on how clearly the action was stated.',\n '5. Quote the source context (a short excerpt of the relevant line).',\n '6. Suggest assignees or due dates when explicitly mentioned.',\n '',\n 'OUTPUT — return ONLY a raw JSON object, no fences, no commentary:',\n '{',\n ' \"actionItems\": [',\n ' {',\n ' \"title\": \"Brief, clear action title (≤90 chars)\",',\n ' \"description\": \"Detailed description of what needs to be done\",',\n ' \"priority\": \"high|medium|low\",',\n ' \"category\": \"strategic|operational|technical|research|financial|other\",',\n ' \"confidence\": 85,',\n ' \"sourceContext\": \"Quote from discussion\",',\n ' \"suggestedAssignee\": \"Person/department or omit\",',\n ' \"suggestedDueDate\": \"Relative or absolute timeframe or omit\"',\n ' }',\n ' ],',\n ' \"keyInsights\": [\"Most important strategic takeaways\"],',\n ' \"recommendedNextSteps\": [\"Immediate next steps\"],',\n ' \"analysisConfidence\": 90',\n '}',\n '',\n 'Focus on maximum actionable value. Skip filler.',\n ].join('\\n');\n}\n\nfunction parseAnalysisResult(\n response: string,\n): Omit<AnalysisResult, 'processingTimeMs' | 'method'> {\n const parseResult = safeParseJSONWithSchema(response, conversationAnalysisPayloadSchema);\n if (parseResult.success) {\n const parsed = parseResult.data;\n return {\n actionItems: (parsed.actionItems ?? []).map((item): ExtractedActionItem => ({\n title: typeof item.title === 'string' && item.title.trim() ? item.title.trim() : 'Untitled Action',\n description: item.description ?? '',\n priority: (item.priority as ActionPriority | undefined) ?? 'medium',\n category: (item.category as ActionCategory | undefined) ?? 'other',\n confidence: typeof item.confidence === 'number' ? item.confidence : 60,\n sourceContext: item.sourceContext ?? 'Extracted by analyzer',\n suggestedAssignee: item.suggestedAssignee,\n suggestedDueDate: item.suggestedDueDate,\n })),\n keyInsights: Array.isArray(parsed.keyInsights) ? (parsed.keyInsights as string[]) : [],\n recommendedNextSteps: Array.isArray(parsed.recommendedNextSteps)\n ? (parsed.recommendedNextSteps as string[])\n : [],\n analysisConfidence:\n typeof parsed.analysisConfidence === 'number' ? parsed.analysisConfidence : 50,\n };\n }\n\n logger.warn(\n '[actions] failed to parse analysis result:',\n 'error' in parseResult ? parseResult.error : 'unknown',\n );\n return {\n actionItems: [],\n keyInsights: [],\n recommendedNextSteps: [],\n analysisConfidence: 0,\n };\n}\n\nfunction fallbackResult(discussion: Discussion, processingTimeMs: number): AnalysisResult {\n // If the discussion has a summary, mine its actionable insights deterministically.\n const fallbackItems: ExtractedActionItem[] = [];\n if (discussion.summary?.actionableInsights) {\n for (const insight of discussion.summary.actionableInsights.slice(0, 3)) {\n fallbackItems.push({\n title: makeTitle(`Follow up: ${insight}`),\n description: insight,\n priority: 'medium',\n category: 'other',\n confidence: 50,\n sourceContext: 'Extracted from discussion summary',\n suggestedDueDate: '2 weeks',\n });\n }\n }\n return {\n actionItems: fallbackItems,\n keyInsights: discussion.summary?.keyPoints ?? [\n 'Analysis failed — no structured data and LLM extraction errored. Review manually.',\n ],\n recommendedNextSteps: ['Review the discussion manually and add action items by hand.'],\n analysisConfidence: 0,\n processingTimeMs,\n method: 'fallback',\n };\n}\n\n// ----------------------------------------------------------------------------\n// Test seam\n// ----------------------------------------------------------------------------\n\nexport const __test = {\n extractFromStructuredData,\n extractFromOneResponse,\n makeTitle,\n inferPriority,\n inferCategory,\n dedupeByTitle,\n parseAnalysisResult,\n buildAnalysisPrompt,\n};\n","/**\n * AI persona enhancer — generates a comprehensive advisory-board persona +\n * voice-guide for a new or existing member. Three template variants:\n *\n * - `enhance_famous_person` — wide public recognition; \"in-the-room\" board behavior.\n * - `enhance_top_expert` — top-1% specialist; technical mastery + methodology.\n * - `enhance_non_famous` — solid professional; practical, collaborative.\n *\n * Calls the local `claude` binary via `runClaude` (no API key — uses the\n * user's Claude Max/Pro subscription). Ported from\n * `sage-council/src/lib/ai-enhancer.ts` with the Gemini path replaced.\n */\nimport { runClaude, extractText, type ClaudeStreamEvent } from '../../llm/claude-code-runner.js';\nimport { safeParseJSONWithSchema } from '../parsing/safe-json.js';\nimport { enhancementPayloadSchema, type EnhancementPayload } from '../parsing/persona-schemas.js';\nimport { getFallbackVoiceGuide } from './fallback-voice-guides.js';\nimport { logger } from '../logger.js';\nimport type { AppSettings, ClaudeModelAlias, ClaudeModel } from '../../storage/types.js';\nimport { ModelError } from '../errors.js';\n\nexport type EnhancementType = 'famous' | 'expert' | 'non-famous';\n\nexport interface EnhancementResult {\n persona: string;\n voiceGuide: string;\n}\n\nexport interface EnhanceOptions {\n /** Override the model (defaults to settings.researchModel). */\n model?: ClaudeModelAlias | ClaudeModel | string;\n /** Existing persona text (used by `non-famous` to refine instead of overwrite). */\n currentPersona?: string;\n /** External abort signal. */\n signal?: AbortSignal;\n /** Stream events from the underlying claude CLI (forwarded by callers wanting progress). */\n onEvent?: (event: ClaudeStreamEvent) => void;\n /** Per-call timeout (ms). */\n timeoutMs?: number;\n}\n\n/**\n * Enhance one member's persona + voiceGuide via the local `claude` CLI.\n * Returns the parsed result. Throws `ModelError` on spawn / non-JSON failure.\n */\nexport async function enhancePersona(\n args: {\n name: string;\n title: string;\n expertise: string[];\n type: EnhancementType;\n },\n settings: AppSettings,\n opts: EnhanceOptions = {},\n): Promise<EnhancementResult> {\n const expertiseText = args.expertise.length > 0 ? args.expertise.join(', ') : 'general business';\n const prompt = buildPrompt(args.type, args.name, args.title, expertiseText, opts.currentPersona);\n const model = opts.model ?? settings.researchModel ?? 'sonnet';\n\n let raw: string;\n try {\n const result = await runClaude({\n prompt,\n model,\n // No --agent: this is a one-shot persona-generation call.\n allowedTools: ['WebSearch', 'WebFetch'],\n maxTurns: 3,\n timeoutMs: opts.timeoutMs ?? 5 * 60_000,\n signal: opts.signal,\n onEvent: opts.onEvent,\n maxBudgetUsd: settings.perCallBudgetUsd,\n });\n raw = extractText(result);\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') throw error;\n logger.error('[ai-enhancer] claude CLI failed:', error);\n throw new ModelError(\n `Persona enhancement failed: ${error instanceof Error ? error.message : String(error)}`,\n 'Check `aab doctor` and ensure the `claude` binary is on PATH.',\n );\n }\n\n return extractEnhancement(raw, args.name);\n}\n\nfunction buildPrompt(\n type: EnhancementType,\n name: string,\n title: string,\n expertiseText: string,\n currentPersona?: string,\n): string {\n switch (type) {\n case 'famous':\n return buildFamousPersonPrompt(name, title, expertiseText);\n case 'expert':\n return buildTopExpertPrompt(name, title, expertiseText);\n case 'non-famous':\n return buildNonFamousPrompt(name, title, expertiseText, currentPersona);\n }\n}\n\nfunction buildFamousPersonPrompt(name: string, title: string, expertiseText: string): string {\n return `# IDENTITY LOCK: ${name}\nYou are creating both a detailed advisory board persona AND a voice guide specifically for ${name}, who is ${title}.\n\n## CRITICAL REQUIREMENTS:\n- This is ONLY for ${name} - do not create content for anyone else\n- Stay true to ${name}'s known characteristics, achievements, and leadership style\n- Focus on their advisory capabilities, not just their fame\n\n## MEMBER CONTEXT:\n- Name: ${name}\n- Title: ${title}\n- Expertise: ${expertiseText}\n- Type: FAMOUS person who is widely recognized in their field\n\n## TASK 1: ADVISORY BOARD PERSONA\nGenerate a comprehensive advisory board persona that includes:\n\n1. **Professional Stature & Recognition**: How their fame and public profile contributes to board credibility\n2. **Advisory Board Value**: What unique value they bring specifically to advisory discussions\n3. **Leadership Philosophy**: Their known approach to leadership and decision-making\n4. **Strategic Approach**: Their methodology for tackling complex business challenges\n5. **Board Dynamics**: How they typically interact in high-level strategic discussions\n\n## TASK 2: VOICE & BEHAVIOR GUIDE\nCreate a concise voice guide that captures:\n- Their distinctive communication patterns and decision-making style\n- Key phrases, reasoning frameworks, and interaction style they're known for\n- How they would behave in advisory board discussions\n\n## OUTPUT FORMAT (CRITICAL):\nReturn ONLY a raw JSON object with this exact structure. No markdown, no fences, no commentary. Start with \\`{\\` and end with \\`}\\`.\n{\n \"persona\": \"A comprehensive 4-6 paragraph advisory board persona for ${name}, written in a professional manner that demonstrates intimate knowledge of their professional approach and advisory capabilities.\",\n \"voiceGuide\": \"A concise but comprehensive voice and behavior guide that captures ${name}'s distinctive communication patterns, decision-making approach, and interaction style for AI persona simulation.\",\n \"psychometricProfile\": [\"BFI-2 style first-person statement 1\", \"statement 2\", \"statement 3\", \"statement 4\", \"statement 5\"],\n \"cognitiveProcess\": \"Step 1: ... -> Step 2: ... -> Step 3: ... -> Step 4: ...\"\n}\n\nRemember: This is specifically for ${name} and must reflect their known characteristics accurately.`;\n}\n\nfunction buildTopExpertPrompt(name: string, title: string, expertiseText: string): string {\n return `# IDENTITY LOCK: ${name}\nYou are creating both a detailed advisory board persona AND a voice guide specifically for ${name}, who is ${title}.\n\n## CRITICAL REQUIREMENTS:\n- This is ONLY for ${name} - do not create content for anyone else\n- This is for a TOP 1% EXPERT who represents the absolute pinnacle of expertise\n- Focus on their exceptional expertise and world-class capabilities\n\n## MEMBER CONTEXT:\n- Name: ${name}\n- Title: ${title}\n- Expertise: ${expertiseText}\n- Type: TOP 1% EXPERT in their field\n\n## TASK 1: ADVISORY BOARD PERSONA\nGenerate a comprehensive advisory board persona that includes:\n\n1. **Technical Mastery**: Their deep, nuanced understanding and specialized knowledge\n2. **Innovation Leadership**: How they've shaped or advanced their field\n3. **Problem-Solving Approach**: Their unique methodology for tackling complex challenges\n4. **Industry Standing**: Their reputation and influence among peers\n5. **Advisory Excellence**: What makes their guidance invaluable to boards\n6. **Strategic Insights**: How they identify opportunities others miss\n\n## TASK 2: VOICE & BEHAVIOR GUIDE\nCreate a concise voice guide that captures:\n- Their expert-level communication patterns and analytical approach\n- How they leverage their deep expertise in discussions\n- Their characteristic way of breaking down complex problems\n\n## OUTPUT FORMAT (CRITICAL):\nReturn ONLY a raw JSON object with this exact structure. No markdown, no fences, no commentary. Start with \\`{\\` and end with \\`}\\`.\n{\n \"persona\": \"A comprehensive 4-6 paragraph advisory board persona for ${name}, demonstrating why they're considered among the very best in ${expertiseText} and how their world-class expertise translates to exceptional board-level value.\",\n \"voiceGuide\": \"A concise but comprehensive voice and behavior guide that captures ${name}'s expert-level communication patterns, analytical approach, and how they leverage their specialized knowledge in strategic discussions.\"\n}\n\nRemember: This is specifically for ${name} as a top 1% expert in their field.`;\n}\n\nfunction buildNonFamousPrompt(\n name: string,\n title: string,\n expertiseText: string,\n currentPersona?: string,\n): string {\n const personaContext = currentPersona ? `\\n\\nCURRENT PERSONA: ${currentPersona}` : '';\n return `# IDENTITY LOCK: ${name}\nYou are creating both a detailed advisory board persona AND a voice guide specifically for ${name}, who is ${title}.\n\n## CRITICAL REQUIREMENTS:\n- This is ONLY for ${name} - do not create content for anyone else\n- This is for a NON-FAMOUS professional with solid expertise but not widely recognized\n- Focus on their practical experience and reliable expertise\n\n## MEMBER CONTEXT:\n- Name: ${name}\n- Title: ${title}\n- Expertise: ${expertiseText}\n- Type: NON-FAMOUS professional${personaContext}\n\n## TASK 1: ADVISORY BOARD PERSONA\nGenerate a comprehensive advisory board persona that includes:\n\n1. **Professional Background**: Their career journey and key achievements\n2. **Advisory Approach**: How they provide practical, grounded insights\n3. **Leadership Style**: Their collaborative and consensus-building approach\n4. **Problem-Solving**: Their methodical approach to challenges\n5. **Strategic Contributions**: What practical value they bring to discussions\n6. **Working Style**: How they interact with other board members\n\n## TASK 2: VOICE & BEHAVIOR GUIDE\nCreate a concise voice guide that captures:\n- Their practical communication style and collaborative approach\n- How they leverage their expertise to provide grounded insights\n- Their methodical problem-solving patterns\n\n## OUTPUT FORMAT (CRITICAL):\nReturn ONLY a raw JSON object with this exact structure. No markdown, no fences, no commentary. Start with \\`{\\` and end with \\`}\\`.\n{\n \"persona\": \"A comprehensive 4-6 paragraph advisory board persona for ${name}, written in a professional manner that conveys competence, reliability, and practical expertise in ${expertiseText}.\",\n \"voiceGuide\": \"A concise but comprehensive voice and behavior guide that captures ${name}'s practical communication style, collaborative approach, and methodical problem-solving patterns.\"\n}\n\nRemember: This is specifically for ${name} as a solid, dependable professional.`;\n}\n\n/**\n * Parse the enhancement response and assemble persona text. Falls back\n * gracefully on parse failure so the caller still gets *something* useful.\n */\nexport function extractEnhancement(response: string, name: string): EnhancementResult {\n const parseResult = safeParseJSONWithSchema(response, enhancementPayloadSchema);\n if (parseResult.success && parseResult.data.persona) {\n // zod3's `z.preprocess(..., z.array(z.string()))` infers as `unknown` rather\n // than `string[]` at the call site, but our preprocessor guarantees the\n // shape — cast through `string[]` to keep tsc happy.\n const profile = parseResult.data.psychometricProfile as string[] | undefined;\n const cognitive = parseResult.data.cognitiveProcess as string | undefined;\n const persona = composeEnhancedPersona(\n cleanPersonaText(parseResult.data.persona),\n profile,\n cognitive,\n );\n return {\n persona,\n voiceGuide: parseResult.data.voiceGuide\n ? cleanPersonaText(parseResult.data.voiceGuide)\n : getFallbackVoiceGuide(name),\n };\n }\n\n // Regex extraction fallback (handles JSON near-misses).\n const personaMatch = response.match(/\"persona\"\\s*:\\s*\"([\\s\\S]*?)(?:\"\\s*,\\s*\"voiceGuide\"|\"\\s*})/);\n const voiceGuideMatch = response.match(/\"voiceGuide\"\\s*:\\s*\"([\\s\\S]*?)\"\\s*[,}]/);\n if (personaMatch && personaMatch[1]) {\n return {\n persona: cleanPersonaText(personaMatch[1]),\n voiceGuide: voiceGuideMatch && voiceGuideMatch[1]\n ? cleanPersonaText(voiceGuideMatch[1])\n : getFallbackVoiceGuide(name),\n };\n }\n\n // Last resort: treat the whole response as persona text.\n return {\n persona: cleanPersonaText(response),\n voiceGuide: getFallbackVoiceGuide(name),\n };\n}\n\nfunction cleanPersonaText(text: string): string {\n return text\n .replace(/\\\\n/g, '\\n')\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\t/g, '\\t')\n .replace(/\\\\\\\\/g, '\\\\')\n .replace(/^\\s*[\"'`]/, '')\n .replace(/[\"'`]\\s*$/, '')\n .replace(/^{\\s*\"persona\"\\s*:\\s*\"/, '')\n .replace(/\"\\s*}$/, '')\n .replace(/^```(?:json)?\\s*/gim, '')\n .replace(/```\\s*$/gim, '')\n .trim();\n}\n\nfunction composeEnhancedPersona(\n basePersona: string,\n psychometricProfile?: string[],\n cognitiveProcess?: string,\n): string {\n const normalizedPersona = basePersona.trim();\n const normalizedProfile = (psychometricProfile ?? [])\n .map((s) => cleanPersonaText(s).trim())\n .filter((s) => s.length > 0);\n const normalizedProcess = (cognitiveProcess ?? '').trim();\n\n if (normalizedProfile.length === 0 && normalizedProcess.length === 0) {\n return normalizedPersona;\n }\n\n const sections: string[] = [];\n if (normalizedPersona.length > 0) sections.push(normalizedPersona);\n if (normalizedProfile.length > 0) {\n sections.push(['Psychometric Profile (BFI-2):', ...normalizedProfile.map((s) => `- ${s}`)].join('\\n'));\n }\n if (normalizedProcess.length > 0) {\n sections.push(`Cognitive Process:\\n${normalizedProcess}`);\n }\n return sections.join('\\n\\n').trim();\n}\n\n/** Test-only export — kept exported so unit tests can hit the prompt body directly. */\nexport const __test = { buildPrompt, cleanPersonaText, composeEnhancedPersona };\n\n/** Test-only payload alias re-export so consumers don't have to know the schema path. */\nexport type { EnhancementPayload };\n","/**\n * Zod schemas for the persona enhancement + voice-guide LLM contracts.\n *\n * Kept separate from `llm-response-schemas.ts` so the Phase 1 discussion\n * engine doesn't pull in persona-specific shapes. Mirrors\n * `sage-council/src/lib/parsing/llm-response-schemas.ts` (enhancement +\n * voice-guide payload shapes).\n */\nimport { z } from 'zod';\n\nconst stringArrayFromUnknown = z.preprocess((value) => {\n if (Array.isArray(value)) return value.map((item) => String(item));\n if (typeof value === 'string' && value.trim() !== '') {\n return value.split('\\n').map((s) => s.trim()).filter(Boolean);\n }\n return [];\n}, z.array(z.string()));\n\nexport const enhancementPayloadSchema = z\n .object({\n persona: z.string(),\n voiceGuide: z.string().optional(),\n psychometricProfile: stringArrayFromUnknown.optional(),\n cognitiveProcess: z.string().optional(),\n })\n .passthrough();\n\nexport type EnhancementPayload = z.infer<typeof enhancementPayloadSchema>;\n\nexport const voiceGuidePayloadSchema = z\n .object({\n voiceGuide: z.string(),\n })\n .passthrough();\n\nexport type VoiceGuidePayload = z.infer<typeof voiceGuidePayloadSchema>;\n","/**\n * Hardcoded fallback voice guides keyed by first name.\n *\n * Used when AI enhancement isn't available or the model returns garbage —\n * the discussion engine still has a halfway-decent voice to anchor the\n * persona to. Ported verbatim from\n * `sage-council/src/lib/fallback-voice-guides.ts`.\n */\n\ninterface FallbackVoiceGuideOptions {\n expertise?: string[];\n}\n\nexport function getFallbackVoiceGuide(\n name: string,\n options: FallbackVoiceGuideOptions = {},\n): string {\n const lowerName = name.toLowerCase();\n\n if (lowerName.includes('elon') || lowerName.includes('musk')) {\n return `**First Principles Master**: Always break problems down to fundamental physics/engineering principles. Ask \"What are we really trying to solve?\" Challenge conventional wisdom aggressively. Think in terms of systems, efficiency ratios, and exponential improvements. Reference manufacturing, physics, or engineering analogies. Be direct and sometimes contrarian.`;\n }\n\n if (lowerName.includes('jobs') || lowerName.includes('steve')) {\n return `**Perfectionist Visionary**: Focus obsessively on user experience and elegant simplicity. Ask \"What would delight users?\" Think in terms of intuitive design and removing complexity. Reference the intersection of technology and liberal arts. Be uncompromising about quality.`;\n }\n\n if (lowerName.includes('bezos') || lowerName.includes('jeff')) {\n return `**Long-term Builder**: Think in decades, not quarters. Ask \"What will customers want in 10-20 years?\" Focus on customer obsession, operational excellence, and building systems that scale. Reference Day 1 mentality and working backwards from press releases.`;\n }\n\n if (lowerName.includes('buffett') || lowerName.includes('warren')) {\n return `**Value Investor**: Think in terms of intrinsic value, competitive moats, and long-term compounding. Ask \"What is this really worth?\" Use folksy analogies and emphasize patience, rationality, and understanding the business fundamentals.`;\n }\n\n if (lowerName.includes('graham') || lowerName.includes('reid')) {\n return `**Systems Thinker**: Think in terms of loops, leverage points, and unintended consequences. Ask \"How do the parts interact?\" Focus on root causes, feedback mechanisms, and holistic solutions. Reference mental models and cognitive frameworks.`;\n }\n\n const normalizedExpertise = (options.expertise ?? [])\n .map((entry) => entry.trim())\n .filter(Boolean);\n const expertiseContext =\n normalizedExpertise.length > 0\n ? ` Draw from your specific expertise in ${normalizedExpertise.join(', ')}.`\n : '';\n\n return `**Distinctive Voice**: Embody your unique thinking patterns, communication style, and decision-making approach.${expertiseContext} Be authentic to your professional philosophy and bring your characteristic insights to strategic discussions.`;\n}\n","/**\n * Voice-guide-only refresher.\n *\n * Used by `aab members regenerate-voice <id>` and the GUI's\n * \"Regenerate voice\" button. Cheaper than full persona enhancement —\n * single Haiku-class call, no web search.\n */\nimport { runClaude, extractText } from '../../llm/claude-code-runner.js';\nimport { safeParseJSONWithSchema } from '../parsing/safe-json.js';\nimport { voiceGuidePayloadSchema } from '../parsing/persona-schemas.js';\nimport { getFallbackVoiceGuide } from './fallback-voice-guides.js';\nimport { logger } from '../logger.js';\nimport type { AdvisoryBoardMember, AppSettings, ClaudeModelAlias, ClaudeModel } from '../../storage/types.js';\n\nexport interface VoiceGuideResult {\n voiceGuide: string;\n error?: string;\n /** True when the result came from the hardcoded fallback (LLM call failed or returned garbage). */\n fellBack: boolean;\n}\n\nexport interface VoiceGuideOptions {\n model?: ClaudeModelAlias | ClaudeModel | string;\n signal?: AbortSignal;\n timeoutMs?: number;\n}\n\nexport async function generateVoiceGuide(\n member: AdvisoryBoardMember,\n settings: AppSettings,\n opts: VoiceGuideOptions = {},\n): Promise<VoiceGuideResult> {\n const expertiseText = member.expertise.length > 0 ? member.expertise.join(', ') : 'general business';\n const prompt = `# IDENTITY LOCK: ${member.name}\nYou are creating a Voice & Behavior Guide specifically for ${member.name}, ${member.title}.\n\n## CRITICAL REQUIREMENTS:\n- This guide is ONLY for ${member.name} - do not create content for anyone else\n- Stay true to ${member.name}'s known characteristics, communication style, and approach\n- Focus on how ${member.name} would communicate and behave in advisory board discussions\n\n## MEMBER CONTEXT:\n- Name: ${member.name}\n- Title: ${member.title}\n- Expertise: ${expertiseText}\n- Persona: ${member.persona.slice(0, 4000)}\n\n## VOICE GUIDE REQUIREMENTS:\nCreate a concise Voice & Behavior Guide that captures:\n\n1. **Communication Patterns**: How ${member.name} typically speaks and expresses ideas\n2. **Decision-Making Style**: Their approach to analyzing problems and making recommendations\n3. **Behavioral Traits**: Their characteristic behaviors in professional discussions\n4. **Thinking Frameworks**: The mental models and methodologies they use\n5. **Interaction Style**: How they engage with others in advisory contexts\n\n## OUTPUT FORMAT (CRITICAL):\nReturn ONLY a raw JSON object. No markdown, no fences, no commentary.\n{\n \"voiceGuide\": \"A comprehensive yet concise voice and behavior guide for ${member.name}. Focus on their distinctive communication patterns, decision-making approach, key phrases they might use, their typical reasoning process, and how they interact in high-level strategic discussions. Keep it practical and actionable for AI persona simulation.\"\n}\n\n## GUIDELINES:\n- Be specific to ${member.name} - avoid generic advice\n- Focus on practical communication and behavioral traits\n- Keep it concise but comprehensive (3-5 sentences)\n- Ensure it's directly applicable for AI persona simulation\n- Stay true to ${member.name}'s known characteristics\n\nRemember: This is specifically for ${member.name} and no one else.`;\n\n const model = opts.model ?? settings.fastModel ?? 'haiku';\n try {\n const result = await runClaude({\n prompt,\n model,\n allowedTools: [],\n maxTurns: 1,\n timeoutMs: opts.timeoutMs ?? 90_000,\n signal: opts.signal,\n maxBudgetUsd: settings.perCallBudgetUsd,\n });\n const raw = extractText(result);\n const parsed = safeParseJSONWithSchema(raw, voiceGuidePayloadSchema);\n if (parsed.success && parsed.data.voiceGuide?.trim()) {\n return { voiceGuide: parsed.data.voiceGuide.trim(), fellBack: false };\n }\n // Sometimes Claude wraps the entire response in a single line of prose without JSON.\n const trimmedRaw = raw.trim();\n if (trimmedRaw.length > 0 && trimmedRaw.length < 4000 && !trimmedRaw.startsWith('{')) {\n return { voiceGuide: trimmedRaw, fellBack: false };\n }\n return {\n voiceGuide: getFallbackVoiceGuide(member.name, { expertise: member.expertise }),\n fellBack: true,\n error: 'LLM response did not match the voiceGuide schema',\n };\n } catch (error) {\n logger.error('[voice-guide] claude CLI failed:', error);\n return {\n voiceGuide: getFallbackVoiceGuide(member.name, { expertise: member.expertise }),\n fellBack: true,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n","/**\n * Decision Coach engine — principle-based decision conversations à la Ray\n * Dalio's Bridgewater. The coach helps the user make decisions guided by\n * their stated `Principles`, surfacing principle-vs-emotion conflicts,\n * asking Socratic questions, and referencing anti-patterns + trigger\n * questions.\n *\n * Single non-agent claude call per turn. The coach's \"session\" is one\n * `DecisionSession` row (messages[] + appliedPrinciples[]).\n */\nimport { runClaude, extractText, type ClaudeStreamEvent } from '../../llm/claude-code-runner.js';\nimport { logger } from '../logger.js';\nimport { ModelError } from '../errors.js';\nimport { generateUUID, nowIso } from '../utils.js';\nimport type {\n AppSettings,\n ClaudeModelAlias,\n ClaudeModel,\n DecisionMessage,\n DecisionSession,\n Principle,\n} from '../../storage/types.js';\n\nexport interface CoachReplyOptions {\n signal?: AbortSignal;\n onEvent?: (event: ClaudeStreamEvent) => void;\n /** Override the model (default: settings.primaryModel). */\n model?: ClaudeModelAlias | ClaudeModel | string;\n timeoutMs?: number;\n}\n\nexport interface CoachReplyResult {\n session: DecisionSession;\n reply: DecisionMessage;\n}\n\n/**\n * Build the Decision Coach system prompt with the user's principles injected.\n * Ported from `sage-council/src/lib/prompts/default-prompts.ts:decision_coach_system`.\n */\nexport function buildDecisionCoachSystemPrompt(principles: Principle[]): string {\n const activePrinciples = principles.filter((p) => p.isActive);\n const principlesBlock = activePrinciples.length === 0\n ? '(no principles defined yet — ask the user what principles guide them)'\n : activePrinciples\n .sort((a, b) => b.priority - a.priority)\n .map((p) => renderPrincipleForPrompt(p))\n .join('\\n\\n');\n\n return `You are a Principles-Based Decision Coach, inspired by Ray Dalio's approach at Bridgewater. Your role is to help the user make decisions based on their stated principles rather than emotional reactions.\n\n## YOUR ROLE\nYou are a thoughtful, direct advisor who helps people think through decisions using their own stated principles. You don't make decisions for them - you help them discover what their principles suggest.\n\n## YOUR APPROACH\n1. **Identify Relevant Principles**: When the user describes a situation, identify which of their principles are most relevant. Quote them directly.\n\n2. **Highlight Principle-Emotion Conflicts**: If you notice the user's instinct conflicts with their stated principles, point this out directly but kindly. Example: \"I notice your instinct is to avoid the conversation, but your 'Embrace Reality' principle suggests facing uncomfortable truths.\"\n\n3. **Ask Socratic Questions**: Instead of telling them what to do, ask questions that help them see their situation through the lens of their principles:\n - \"What would your [Principle Name] principle suggest here?\"\n - \"Is this decision aligned with who you want to be?\"\n - \"What reality might you be avoiding?\"\n\n4. **Reference Anti-Patterns**: If you see them falling into an anti-pattern they've defined, call it out. Example: \"This sounds like the anti-pattern you identified - 'avoiding difficult conversations'.\"\n\n5. **Use Trigger Questions**: Apply their own trigger questions back to them when relevant.\n\n6. **Weigh by Priority**: When multiple principles conflict, consider their stated priorities (1-10 scale).\n\n## YOUR TONE\n- Be direct and honest (radical transparency)\n- Don't coddle or sugarcoat\n- Be warm but focused on truth\n- Use their language and principle names\n- Ground EVERYTHING in THEIR stated principles\n\n## FORMAT\n- Use markdown for structure\n- Bold principle names when referencing them\n- Use bullet points for questions to consider\n- Keep responses focused and actionable\n- Always end with a question or call to reflection\n\n## IMPORTANT\n- Never make the decision for them\n- Always ground guidance in THEIR principles\n- If they're being emotional, redirect to principle-based thinking\n- Reference specific principles by name and priority\n- If no principles seem relevant, say so and ask clarifying questions\n\nUSER'S PRINCIPLES:\n${principlesBlock}`;\n}\n\nfunction renderPrincipleForPrompt(p: Principle): string {\n const lines: string[] = [`**${p.title}** (priority ${p.priority}/10, ${p.category})`];\n lines.push(`Description: ${p.description}`);\n if (p.behavior) lines.push(`Behavior: ${p.behavior}`);\n if (p.antiPattern) lines.push(`Anti-pattern: ${p.antiPattern}`);\n if (p.triggerQuestions && p.triggerQuestions.length > 0) {\n lines.push(`Trigger questions: ${p.triggerQuestions.join(' | ')}`);\n }\n return lines.join('\\n');\n}\n\n/**\n * Start a new decision session.\n */\nexport function newDecisionSession(situation: string, title?: string): DecisionSession {\n const now = nowIso();\n return {\n id: generateUUID(),\n title: title?.trim() || undefined,\n situation,\n messages: [],\n appliedPrinciples: [],\n status: 'active',\n createdAt: now,\n updatedAt: now,\n };\n}\n\n/**\n * Ask the coach to reply to the user's latest message. Appends both the\n * user message and the coach's reply to the session and returns the\n * updated session.\n *\n * If `userMessage` is empty (e.g. starting a brand-new session), the coach\n * is primed with the `situation` field and asked to open the conversation.\n */\nexport async function coachReply(\n session: DecisionSession,\n principles: Principle[],\n userMessage: string,\n settings: AppSettings,\n opts: CoachReplyOptions = {},\n): Promise<CoachReplyResult> {\n const trimmed = userMessage.trim();\n const isOpener = session.messages.length === 0 && trimmed.length === 0;\n\n let userTurn: DecisionMessage | null = null;\n if (!isOpener) {\n if (trimmed.length === 0) {\n throw new ModelError('Cannot send an empty coach message after the session has started.');\n }\n userTurn = {\n id: generateUUID(),\n sessionId: session.id,\n role: 'user',\n content: trimmed,\n createdAt: nowIso(),\n };\n }\n\n const transcript = buildTranscript(session, userTurn, isOpener);\n const systemPrompt = buildDecisionCoachSystemPrompt(principles);\n const fullPrompt = `${systemPrompt}\\n\\n---\\n\\nCONVERSATION SO FAR:\\n${transcript}\\n\\nRespond now as the Decision Coach. Use markdown. Reference principles by their **Title**. Always end with a question or call to reflection.`;\n\n const model = opts.model ?? settings.primaryModel ?? 'sonnet';\n let raw: string;\n try {\n const result = await runClaude({\n prompt: fullPrompt,\n model,\n allowedTools: [],\n maxTurns: 1,\n timeoutMs: opts.timeoutMs ?? 5 * 60_000,\n signal: opts.signal,\n onEvent: opts.onEvent,\n maxBudgetUsd: settings.perCallBudgetUsd,\n });\n raw = extractText(result);\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') throw error;\n logger.error('[decision-coach] claude CLI failed:', error);\n throw new ModelError(\n `Decision Coach reply failed: ${error instanceof Error ? error.message : String(error)}`,\n 'Run `aab doctor` to verify the claude binary is reachable.',\n );\n }\n\n const cleaned = raw.trim();\n if (cleaned.length === 0) {\n throw new ModelError('Decision Coach returned an empty reply.');\n }\n\n const referenced = extractReferencedPrincipleIds(cleaned, principles);\n const coachTurn: DecisionMessage = {\n id: generateUUID(),\n sessionId: session.id,\n role: 'assistant',\n content: cleaned,\n principlesReferenced: referenced.length > 0 ? referenced : undefined,\n createdAt: nowIso(),\n };\n\n const newMessages = [...session.messages];\n if (userTurn) newMessages.push(userTurn);\n newMessages.push(coachTurn);\n\n const newApplied = mergeAppliedPrinciples(session.appliedPrinciples, referenced);\n const updated: DecisionSession = {\n ...session,\n messages: newMessages,\n appliedPrinciples: newApplied,\n updatedAt: nowIso(),\n };\n\n return { session: updated, reply: coachTurn };\n}\n\nfunction buildTranscript(session: DecisionSession, userTurn: DecisionMessage | null, isOpener: boolean): string {\n const lines: string[] = [];\n lines.push(`SITUATION: ${session.situation}`);\n for (const m of session.messages) {\n lines.push(`${m.role === 'user' ? 'USER' : 'COACH'}: ${m.content}`);\n }\n if (userTurn) {\n lines.push(`USER: ${userTurn.content}`);\n } else if (isOpener) {\n lines.push('(no user messages yet — open the conversation based on the situation above)');\n }\n return lines.join('\\n\\n');\n}\n\nfunction extractReferencedPrincipleIds(text: string, principles: Principle[]): string[] {\n const lower = text.toLowerCase();\n const ids: string[] = [];\n for (const p of principles) {\n if (!p.title) continue;\n const t = p.title.toLowerCase();\n if (t.length < 3) continue;\n if (lower.includes(t)) ids.push(p.id);\n }\n return Array.from(new Set(ids));\n}\n\nfunction mergeAppliedPrinciples(existing: string[], newlyReferenced: string[]): string[] {\n const set = new Set(existing);\n for (const id of newlyReferenced) set.add(id);\n return Array.from(set);\n}\n\n/**\n * Test-only export — kept exported so the prompt body is unit-testable.\n */\nexport const __test = {\n buildTranscript,\n extractReferencedPrincipleIds,\n mergeAppliedPrinciples,\n renderPrincipleForPrompt,\n};\n","/**\n * Principle Explorer — 5-step Socratic wizard that helps the user articulate\n * a principle (behavior / anti-pattern / triggers / examples / priority).\n * Ported from `sage-council/src/lib/prompts/default-prompts.ts:principle_explorer_*`.\n *\n * Cross-step context is mandatory: every step's prompt includes the prior\n * turns so the LLM acknowledges them (\"You mentioned [exact quote]...\")\n * and avoids re-asking the user the same question.\n */\nimport { runClaude, extractText, type ClaudeStreamEvent } from '../../llm/claude-code-runner.js';\nimport { logger } from '../logger.js';\nimport { ModelError } from '../errors.js';\nimport type {\n AppSettings,\n ClaudeModelAlias,\n ClaudeModel,\n Principle,\n PrincipleCategory,\n} from '../../storage/types.js';\n\nexport type ExplorerStep = 'behavior' | 'antipattern' | 'triggers' | 'examples' | 'priority';\n\nexport const EXPLORER_STEPS: readonly ExplorerStep[] = [\n 'behavior',\n 'antipattern',\n 'triggers',\n 'examples',\n 'priority',\n] as const;\n\nexport interface ExplorerTurn {\n step: ExplorerStep;\n role: 'user' | 'assistant';\n content: string;\n}\n\nexport interface ExplorerContext {\n /** Working principle (may be new — no id required for the explorer). */\n principle: Pick<Principle, 'title' | 'description' | 'category'> & Partial<Principle>;\n /** Conversation history across all steps so far. */\n history: ExplorerTurn[];\n /** Step we're currently exploring. */\n step: ExplorerStep;\n /** True when this is the assistant's first message in this step. */\n isFirstMessage: boolean;\n}\n\nexport interface ExplorerReplyOptions {\n signal?: AbortSignal;\n onEvent?: (event: ClaudeStreamEvent) => void;\n model?: ClaudeModelAlias | ClaudeModel | string;\n timeoutMs?: number;\n}\n\nexport interface ExplorerReplyResult {\n reply: string;\n /** True when the reply contained a `**Suggested X:**` synthesis line. */\n synthesised: boolean;\n /** Best-effort extraction of the synthesised value for the current step. */\n suggested?: string;\n}\n\n/**\n * Build the system prompt for one step of the explorer.\n */\nexport function buildExplorerSystemPrompt(ctx: ExplorerContext): string {\n const stepInstructions = STEP_INSTRUCTIONS[ctx.step];\n const stepLabel = STEP_LABELS[ctx.step];\n const existingFields = renderExistingFields(ctx.principle);\n const crossStepContext = renderCrossStepContext(ctx.history, ctx.step);\n\n const firstMessageBlock = ctx.isFirstMessage\n ? `\\nIMPORTANT: This is the START of exploring \"${stepLabel}\". ${crossStepContext ? 'You MUST first acknowledge what the user shared in previous steps, then ' : ''}ask your first Socratic question OR provide synthesis if you have enough context. Don't wait for the user - YOU lead the conversation.\\n`\n : '';\n\n return `You are a Principle Explorer inspired by Ray Dalio's approach at Bridgewater. Help users articulate their principles through direct, Socratic questioning.\n\nPERSONA:\n- Be direct and reality-focused like Dalio: \"What specifically happens when...\"\n- Don't coddle - push for clarity and honesty\n- Ask probing questions that reveal the true meaning of their principle\n- Keep responses under 100 words - be concise\n- Reference their exact words when synthesizing\n- Build on previous insights rather than starting fresh each step\n\n${crossStepContext ? `-----------------------------------\\nCRITICAL: PREVIOUS STEP CONVERSATIONS (READ FIRST!)\\n-----------------------------------\\nThe user has already shared these insights. You MUST read and acknowledge them:\\n\\n${crossStepContext}\\n\\nMANDATORY RULES:\\n1. ACKNOWLEDGE specific examples the user shared: \"You mentioned [exact quote]...\"\\n2. DO NOT ask questions they already answered above\\n3. If their previous answers provide enough for this step, SYNTHESIZE IMMEDIATELY\\n4. BUILD on their exact words - don't start fresh\\n5. For triggers/priority/examples: if context is sufficient, provide synthesis in your FIRST message\\n-----------------------------------\\n` : ''}\n\nCURRENT STEP: ${stepLabel}\n\nPRINCIPLE: \"${ctx.principle.title}\"\nCategory: ${ctx.principle.category}\nDescription: ${ctx.principle.description}\n${existingFields}\n\nINSTRUCTIONS FOR THIS STEP:\n${stepInstructions}\n\nRULES:\n- Ask at most 1-2 focused questions\n- Be direct like Dalio - \"What specifically...\" / \"Give me a real example...\"\n- Keep responses under 100 words\n- When you have enough info, provide your synthesis using the **Suggested X:** format\n- Reference their exact words when synthesizing\n- Don't repeat what they already said back to them unnecessarily\n- Connect insights across steps: \"Earlier you mentioned [X], which relates to...\"${firstMessageBlock}`;\n}\n\nconst STEP_LABELS: Record<ExplorerStep, string> = {\n behavior: 'Behavior',\n antipattern: 'Anti-Pattern',\n triggers: 'Trigger Questions',\n examples: 'Examples',\n priority: 'Priority',\n};\n\nconst STEP_INSTRUCTIONS: Record<ExplorerStep, string> = {\n behavior: `You are exploring WHEN and HOW to apply this principle.\nAsk 1-2 focused questions about specific situations where they would apply this.\nAfter getting enough info (1-2 exchanges), provide a synthesis in this exact format:\n**Suggested Behavior:** [Your 2-3 sentence actionable behavior description]`,\n antipattern: `You are identifying what VIOLATING this principle looks like.\nAsk about warning signs, failure modes, and self-deception patterns.\nIf the user already described failure modes in previous steps, reference and build on them.\nAfter getting enough info (1-2 exchanges), synthesize:\n**Suggested Anti-Pattern:** [Your 2-3 sentence description of violation patterns]`,\n triggers: `Based on the FULL conversation history (including previous steps), generate 2-4 self-check questions.\nThese should be questions the user can ask themselves to know when this principle applies.\nIf previous conversations gave enough context, provide synthesis immediately without asking more questions.\nFormat:\n**Suggested Trigger Questions:**\n1. [Question 1]\n2. [Question 2]\n3. [Question 3]`,\n examples: `Ask for 1-2 real situations where they applied (or should have applied) this principle.\nIMPORTANT: Check if the user already shared examples in previous steps - if so, use those directly.\nKeep examples concrete and personal. Format:\n**Suggested Examples:**\n1. [Example 1]\n2. [Example 2]`,\n priority: `Based on everything discussed across ALL steps, suggest a priority 1-10 with brief reasoning.\nConsider: How often does this principle apply? How impactful is following it?\nYou should have enough context from previous steps to provide this immediately:\n**Suggested Priority:** [X]/10 - [One sentence reasoning]`,\n};\n\nfunction renderExistingFields(p: ExplorerContext['principle']): string {\n const lines: string[] = [];\n if (p.behavior) lines.push(`Existing Behavior: ${p.behavior}`);\n if (p.antiPattern) lines.push(`Existing Anti-Pattern: ${p.antiPattern}`);\n if (p.triggerQuestions && p.triggerQuestions.length > 0) {\n lines.push(`Existing Trigger Questions: ${p.triggerQuestions.join(' | ')}`);\n }\n if (p.examples && p.examples.length > 0) {\n lines.push(`Existing Examples: ${p.examples.join(' | ')}`);\n }\n if (typeof p.priority === 'number') lines.push(`Existing Priority: ${p.priority}/10`);\n return lines.length === 0 ? '' : `\\nALREADY-FILLED FIELDS:\\n${lines.join('\\n')}`;\n}\n\nfunction renderCrossStepContext(history: ExplorerTurn[], currentStep: ExplorerStep): string {\n const priorSteps = history.filter((t) => t.step !== currentStep);\n if (priorSteps.length === 0) return '';\n const grouped = new Map<ExplorerStep, ExplorerTurn[]>();\n for (const turn of priorSteps) {\n const arr = grouped.get(turn.step) ?? [];\n arr.push(turn);\n grouped.set(turn.step, arr);\n }\n const sections: string[] = [];\n for (const step of EXPLORER_STEPS) {\n const turns = grouped.get(step);\n if (!turns || turns.length === 0) continue;\n const block = turns.map((t) => `${t.role === 'user' ? 'USER' : 'COACH'}: ${t.content}`).join('\\n');\n sections.push(`### Step: ${STEP_LABELS[step]}\\n${block}`);\n }\n return sections.join('\\n\\n');\n}\n\n/**\n * Run one turn of the explorer. Returns the assistant's reply and a hint\n * about whether it contained a synthesis line.\n */\nexport async function explorerReply(\n ctx: ExplorerContext,\n userMessage: string,\n settings: AppSettings,\n opts: ExplorerReplyOptions = {},\n): Promise<ExplorerReplyResult> {\n const systemPrompt = buildExplorerSystemPrompt(ctx);\n const sameStepHistory = ctx.history.filter((t) => t.step === ctx.step);\n const trimmedUserMessage = userMessage.trim();\n const transcriptLines: string[] = [];\n for (const turn of sameStepHistory) {\n transcriptLines.push(`${turn.role === 'user' ? 'USER' : 'COACH'}: ${turn.content}`);\n }\n if (trimmedUserMessage) transcriptLines.push(`USER: ${trimmedUserMessage}`);\n if (transcriptLines.length === 0) {\n transcriptLines.push('(open the step — the user hasn\\'t spoken yet)');\n }\n\n const prompt = `${systemPrompt}\\n\\n---\\n\\nCURRENT-STEP TRANSCRIPT:\\n${transcriptLines.join('\\n')}\\n\\nRespond now as the Principle Explorer. Stay under 100 words.`;\n const model = opts.model ?? settings.primaryModel ?? 'sonnet';\n\n let raw: string;\n try {\n const result = await runClaude({\n prompt,\n model,\n allowedTools: [],\n maxTurns: 1,\n timeoutMs: opts.timeoutMs ?? 3 * 60_000,\n signal: opts.signal,\n onEvent: opts.onEvent,\n maxBudgetUsd: settings.perCallBudgetUsd,\n });\n raw = extractText(result);\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') throw error;\n logger.error('[principle-explorer] claude CLI failed:', error);\n throw new ModelError(\n `Principle Explorer reply failed: ${error instanceof Error ? error.message : String(error)}`,\n 'Run `aab doctor` to verify the claude binary is reachable.',\n );\n }\n\n const reply = raw.trim();\n const suggested = extractSuggested(reply, ctx.step);\n return { reply, synthesised: !!suggested, suggested };\n}\n\n/**\n * Parse a `**Suggested X:**` line out of an explorer reply. Returns the\n * content after the colon (and after numbered list items, for triggers\n * and examples).\n */\nexport function extractSuggested(reply: string, step: ExplorerStep): string | undefined {\n const headers: Record<ExplorerStep, RegExp> = {\n behavior: /\\*\\*Suggested Behavior:\\*\\*\\s*([\\s\\S]+?)(?:\\n\\n|$)/i,\n antipattern: /\\*\\*Suggested Anti-?Pattern:\\*\\*\\s*([\\s\\S]+?)(?:\\n\\n|$)/i,\n triggers: /\\*\\*Suggested Trigger Questions:\\*\\*\\s*([\\s\\S]+?)(?:\\n\\n|$)/i,\n examples: /\\*\\*Suggested Examples:\\*\\*\\s*([\\s\\S]+?)(?:\\n\\n|$)/i,\n priority: /\\*\\*Suggested Priority:\\*\\*\\s*([\\s\\S]+?)(?:\\n\\n|$)/i,\n };\n const m = reply.match(headers[step]);\n if (!m || typeof m[1] !== 'string') return undefined;\n return m[1].trim();\n}\n\n/**\n * Apply a synthesised step value back to a working principle draft.\n */\nexport function applyStep(\n base: Pick<Principle, 'title' | 'description' | 'category'> & Partial<Principle>,\n step: ExplorerStep,\n value: string,\n): Pick<Principle, 'title' | 'description' | 'category'> & Partial<Principle> {\n switch (step) {\n case 'behavior':\n return { ...base, behavior: value };\n case 'antipattern':\n return { ...base, antiPattern: value };\n case 'triggers':\n return { ...base, triggerQuestions: parseNumberedList(value) };\n case 'examples':\n return { ...base, examples: parseNumberedList(value) };\n case 'priority': {\n const m = value.match(/(\\d+)/);\n const n = m && m[1] ? Number(m[1]) : Number.NaN;\n const clamped = Number.isFinite(n) ? Math.max(1, Math.min(10, Math.round(n))) : base.priority ?? 5;\n return { ...base, priority: clamped };\n }\n }\n}\n\nfunction parseNumberedList(value: string): string[] {\n return value\n .split(/\\r?\\n/)\n .map((line) => line.replace(/^\\s*\\d+[.)]\\s*/, '').trim())\n .filter((line) => line.length > 0);\n}\n\nexport const __test = {\n renderCrossStepContext,\n renderExistingFields,\n parseNumberedList,\n STEP_LABELS,\n STEP_INSTRUCTIONS,\n};\n\nexport type { PrincipleCategory };\n","/**\n * `aab actions solve` orchestrator — Phase 5 Chunk 4 entry point.\n *\n * Chains the four pipeline phases:\n * 1. preconditions (skill-creator installed; action exists; linked discussion if any)\n * 2. recon (PC scan + wiki recon + web research — orchestrator.ts)\n * 3. planner (Opus reasoning → SkillDesignProposal — planner.ts)\n * 4. review (interactive CLI / GUI proposal acceptance — planner-review.ts)\n * 5. brief (assemble JSON for skill-creator — build-brief.ts)\n * 6. skill-creator (headless invocation — invoke-skill-creator.ts)\n * 7. adapter (frontmatter normalization — adapter.ts)\n * 8. install (cp → .claude/skills/<name>/ — install.ts)\n * 9. persist (SkillGenerationRun + ActionItem.linkedSkill — persist-run.ts)\n *\n * Streams events for the WS broadcast layer + telemetry sink.\n */\nimport { mkdirSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type {\n ActionItem,\n AppSettings,\n ConversationSummary,\n StorageService,\n} from '../../storage/types.js';\nimport type { ResolvedWorkspace } from '../../storage/paths.js';\nimport { paths } from '../../storage/paths.js';\nimport { generateUUID, nowIso } from '../utils.js';\nimport { logger } from '../logger.js';\nimport { UserError, BudgetError } from '../errors.js';\nimport { resolveSkillCreator } from './resolve-skill-creator.js';\nimport { runRecon, type ReconTriple } from './recon/orchestrator.js';\nimport { runPlanner } from './planner.js';\nimport { reviewInteractive, acceptAll, type PlannerReviewResult, type ResolvedSkillCapabilityProfile } from './planner-review.js';\nimport { buildSkillCreatorBrief } from './build-brief.js';\nimport { invokeSkillCreator, stubSkillCreatorRun, type InvokeSkillCreatorResult } from './invoke-skill-creator.js';\nimport { adaptSkillPackage } from './adapter.js';\nimport { installSkillPackage } from './install.js';\nimport { persistSkillRun } from './persist-run.js';\nimport type { SkillDesignProposal } from '../parsing/llm-response-schemas.js';\n\nexport interface SolveEvent {\n type:\n | 'preflight'\n | 'planner_started'\n | 'planner_recon_progress'\n | 'planner_recon_done'\n | 'planner_reasoning_started'\n | 'planner_proposal_ready'\n | 'planner_failed'\n | 'review_replan'\n | 'skill_run_started'\n | 'skill_run_step'\n | 'skill_run_tool_call'\n | 'skill_run_adapter_diff'\n | 'skill_run_installed'\n | 'skill_run_failed'\n | 'skill_run_cancelled';\n payload?: Record<string, unknown>;\n}\n\nexport interface SolveOptions {\n workspace: ResolvedWorkspace;\n settings: AppSettings;\n storage: StorageService;\n action: ActionItem;\n discussionSummary?: ConversationSummary;\n /** When true, accept the Planner's recommended tier + all integrations + dry-run preview. */\n yes?: boolean;\n /** Skip the Skill Planner entirely (--no-planner). */\n noPlanner?: boolean;\n plannerTierCap?: 'minimal' | 'standard' | 'maximalist';\n skipPcScan?: boolean;\n skipWiki?: boolean;\n skipWeb?: boolean;\n /** Skip the skill-creator headless call — useful for `aab actions plan`. */\n planOnly?: boolean;\n /** Stub the skill-creator emit (test mode). */\n stub?: boolean;\n skillName?: string;\n /** Default 'project'. */\n scope?: 'project' | 'user';\n installPath?: string;\n noInstall?: boolean;\n projectRoot?: string;\n budgetCapUsd?: number;\n onEvent?: (event: SolveEvent) => void;\n /** Inject a previously-accepted profile (e.g., when invoked from the GUI). */\n preAcceptedProfile?: ResolvedSkillCapabilityProfile;\n /** Custom run id (otherwise generated). */\n runId?: string;\n}\n\nexport interface SolveResult {\n runId: string;\n proposal: SkillDesignProposal;\n capabilityProfile: ResolvedSkillCapabilityProfile;\n /** Present only when planOnly !== true. */\n skillRun?: InvokeSkillCreatorResult;\n installPath?: string;\n status: 'plan-only' | 'completed' | 'rejected' | 'failed';\n costUsd: number;\n durationMs: number;\n}\n\nexport async function runSolve(opts: SolveOptions): Promise<SolveResult> {\n const started = Date.now();\n const runId = opts.runId ?? generateUUID();\n const skillName = opts.skillName ?? deriveSkillName(opts.action.title);\n const projectRoot = opts.projectRoot ?? process.cwd();\n opts.onEvent?.({ type: 'preflight', payload: { runId, skillName } });\n\n // 0. preconditions\n if (!opts.planOnly) {\n const sc = resolveSkillCreator({ projectRoot });\n if (!sc) {\n throw new UserError(\n 'skill-creator skill not installed',\n 'Run `aab init --install-skill-creator` for instructions.',\n );\n }\n }\n\n // 1. recon — skip entirely when noPlanner + no preAcceptedProfile (the\n // minimal-fallback profile doesn't depend on recon). Also short-circuit\n // wiki + web phases to PC-only when a profile was pre-accepted (used by\n // the GUI when the proposal was generated separately).\n opts.onEvent?.({ type: 'planner_started', payload: { runId } });\n const reconNeeded = !opts.preAcceptedProfile && !opts.noPlanner;\n let recon: ReconTriple;\n if (!reconNeeded && opts.preAcceptedProfile) {\n recon = opts.preAcceptedProfile.recon;\n } else if (!reconNeeded) {\n // noPlanner without a pre-accepted profile — synthesize an empty triple.\n recon = await runRecon({\n workspace: opts.workspace,\n settings: opts.settings,\n actionTitle: opts.action.title,\n actionDescription: opts.action.description,\n skipPcScan: opts.skipPcScan,\n skipWiki: true,\n skipWeb: true,\n onPhaseDone: (phase, summary) => {\n opts.onEvent?.({ type: 'planner_recon_progress', payload: { runId, phase, summary } });\n },\n });\n } else {\n recon = await runRecon({\n workspace: opts.workspace,\n settings: opts.settings,\n actionTitle: opts.action.title,\n actionDescription: opts.action.description,\n discussionSummary: opts.discussionSummary\n ? `${opts.discussionSummary.keyPoints?.join(' | ') ?? ''}`.slice(0, 2000)\n : undefined,\n skipPcScan: opts.skipPcScan,\n skipWiki: opts.skipWiki,\n skipWeb: opts.skipWeb,\n onPhaseDone: (phase, summary) => {\n opts.onEvent?.({ type: 'planner_recon_progress', payload: { runId, phase, summary } });\n },\n });\n }\n opts.onEvent?.({ type: 'planner_recon_done', payload: { runId, recon: summarizeReconForEvent(recon) } });\n\n // 2. planner\n let capabilityProfile: ResolvedSkillCapabilityProfile;\n if (opts.preAcceptedProfile) {\n capabilityProfile = opts.preAcceptedProfile;\n } else if (opts.noPlanner) {\n // Fast path: synthesize a minimal-tier capability profile without Opus.\n capabilityProfile = synthesizeMinimalProfile(opts.action, recon, skillName);\n } else {\n opts.onEvent?.({ type: 'planner_reasoning_started', payload: { runId } });\n let replanFeedback: string | undefined;\n let attempts = 0;\n const MAX_REPLANS = 3;\n while (attempts <= MAX_REPLANS) {\n attempts++;\n let plannerResult;\n try {\n plannerResult = await runPlanner({\n workspace: opts.workspace,\n settings: opts.settings,\n action: opts.action,\n discussionSummary: opts.discussionSummary,\n recon,\n maxTier: opts.plannerTierCap ?? 'maximalist',\n userReplanFeedback: replanFeedback,\n });\n } catch (err) {\n opts.onEvent?.({ type: 'planner_failed', payload: { runId, error: err instanceof Error ? err.message : String(err) } });\n throw err;\n }\n opts.onEvent?.({ type: 'planner_proposal_ready', payload: { runId, proposal: plannerResult.proposal } });\n const review: PlannerReviewResult = opts.yes\n ? acceptAll(plannerResult.proposal, recon)\n : await reviewInteractive({ proposal: plannerResult.proposal, recon, autoAccept: false });\n if (review.status === 'rejected') {\n return {\n runId,\n proposal: plannerResult.proposal,\n capabilityProfile: acceptAll(plannerResult.proposal, recon).profile!,\n status: 'rejected',\n costUsd: plannerResult.costUsd,\n durationMs: Date.now() - started,\n };\n }\n if (review.status === 'replan') {\n replanFeedback = review.replanFeedback;\n opts.onEvent?.({ type: 'review_replan', payload: { runId, attempts } });\n continue;\n }\n capabilityProfile = review.profile!;\n break;\n }\n if (!capabilityProfile!) {\n throw new UserError('Re-plan loop exhausted (max 3).', 'Accept a proposal or cancel.');\n }\n }\n\n // Budget cap enforcement on the projected total cost (Planner + skill-creator).\n const projectedTotal = (capabilityProfile.proposal.estimatedCostUsd ?? 2.2);\n if (opts.budgetCapUsd && projectedTotal > opts.budgetCapUsd) {\n throw new BudgetError(\n `Projected solve cost $${projectedTotal.toFixed(2)} exceeds budget cap $${opts.budgetCapUsd}.`,\n 'Re-run with --planner-no-web or --planner-tier standard to reduce scope.',\n );\n }\n\n // Plan-only exit.\n if (opts.planOnly) {\n return {\n runId,\n proposal: capabilityProfile.proposal,\n capabilityProfile,\n status: 'plan-only',\n costUsd: recon.costUsd,\n durationMs: Date.now() - started,\n };\n }\n\n // 3. brief\n const workspacePaths = paths(opts.workspace.root);\n const workspaceDir = join(workspacePaths.skillRuns, opts.action.id, runId, 'workspace');\n mkdirSync(workspaceDir, { recursive: true });\n\n const installTargetPath = opts.installPath ?? (opts.scope === 'user'\n ? join(homedir(), '.claude', 'skills', skillName)\n : join(projectRoot, '.claude', 'skills', skillName));\n const { brief } = buildSkillCreatorBrief({\n action: opts.action,\n capabilityProfile,\n discussionSummary: opts.discussionSummary,\n installTarget: {\n scope: opts.scope ?? 'project',\n path: installTargetPath,\n skillName,\n },\n });\n\n // 4. skill-creator\n opts.onEvent?.({ type: 'skill_run_started', payload: { runId, skillName } });\n let result: InvokeSkillCreatorResult;\n try {\n if (opts.stub) {\n result = stubSkillCreatorRun({ brief, workspaceDir });\n } else {\n result = await invokeSkillCreator({\n brief,\n workspaceDir,\n projectRoot,\n onEvent: (evt) => {\n if (evt.type === 'assistant' && evt.message?.content) {\n for (const part of evt.message.content) {\n if (part.type === 'tool_use') {\n opts.onEvent?.({ type: 'skill_run_tool_call', payload: { runId, tool: part.name, input: part.input } });\n }\n }\n }\n },\n onTelemetry: (line) => {\n const tlPath = join(workspacePaths.skillRuns, opts.action.id, runId, 'telemetry.jsonl');\n try {\n mkdirSync(join(workspacePaths.skillRuns, opts.action.id, runId), { recursive: true });\n writeFileSync(tlPath, JSON.stringify(line) + '\\n', { flag: 'a' });\n } catch {\n // best-effort\n }\n },\n });\n }\n } catch (err) {\n opts.onEvent?.({ type: 'skill_run_failed', payload: { runId, error: err instanceof Error ? err.message : String(err) } });\n await persistSkillRun({\n storage: opts.storage,\n workspaceRoot: opts.workspace.root,\n action: opts.action,\n runId,\n status: 'failed',\n startedAt: new Date(started).toISOString(),\n costUsd: recon.costUsd,\n cacheHitRate: 0,\n durationMs: Date.now() - started,\n files: [],\n capabilityProfile,\n workspaceDir,\n });\n throw err;\n }\n\n if (!result.hasSkillMd) {\n opts.onEvent?.({ type: 'skill_run_failed', payload: { runId, reason: 'no SKILL.md emitted' } });\n }\n\n // 5. adapter\n const adapter = adaptSkillPackage({\n files: result.files,\n grantedTools: capabilityProfile.grantedTools,\n skillName,\n actionTitle: opts.action.title,\n actionDescription: opts.action.description,\n });\n opts.onEvent?.({ type: 'skill_run_adapter_diff', payload: { runId, diff: adapter.diff, warnings: adapter.warnings } });\n\n // 6. install\n let installPath: string | undefined;\n if (!opts.noInstall) {\n const inst = await installSkillPackage({\n files: adapter.files,\n skillName,\n scope: opts.scope,\n projectRoot,\n yes: opts.yes,\n workspaceRoot: opts.workspace.root,\n runId,\n actionItemId: opts.action.id,\n });\n installPath = inst.installPath;\n opts.onEvent?.({ type: 'skill_run_installed', payload: { runId, installPath, conflictAction: inst.conflictAction, archivedTo: inst.archivedTo } });\n }\n\n // 7. persist\n const totalCost = recon.costUsd + result.costUsd;\n await persistSkillRun({\n storage: opts.storage,\n workspaceRoot: opts.workspace.root,\n action: opts.action,\n runId,\n status: 'completed',\n startedAt: new Date(started).toISOString(),\n costUsd: totalCost,\n cacheHitRate: 0,\n durationMs: Date.now() - started,\n files: adapter.files,\n installPath,\n capabilityProfile,\n toolCallCount: result.toolCallCount,\n workspaceDir,\n retainWorkspace: opts.settings ? Boolean((opts.settings as unknown as { skill?: { preserveWorkspaceOnSuccess?: boolean } }).skill?.preserveWorkspaceOnSuccess) : false,\n });\n\n return {\n runId,\n proposal: capabilityProfile.proposal,\n capabilityProfile,\n skillRun: result,\n installPath,\n status: 'completed',\n costUsd: totalCost,\n durationMs: Date.now() - started,\n };\n}\n\nexport function deriveSkillName(actionTitle: string): string {\n return actionTitle\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, '')\n .trim()\n .replace(/\\s+/g, '-')\n .slice(0, 60) || 'skill';\n}\n\nfunction synthesizeMinimalProfile(action: ActionItem, recon: ReconTriple, skillName: string): ResolvedSkillCapabilityProfile {\n const proposal: SkillDesignProposal = {\n skillName,\n skillSummary: action.title,\n triggerLanguage: `Use when ${action.title}`,\n tiers: {\n minimal: { name: 'minimal', description: 'Produce a markdown artifact only.', estimatedValueScore: 20 },\n standard: { name: 'standard', description: '(planner skipped)', estimatedValueScore: 0 },\n maximalist: { name: 'maximalist', description: '(planner skipped)', estimatedValueScore: 0 },\n },\n recommendedTier: 'minimal',\n integrations: [\n {\n id: 'write-md',\n source: 'wiki-entity',\n name: 'Write markdown artifact',\n invocationHint: { kind: 'write-artifact', tools: ['Write'], artifactPath: 'references/output.md' },\n requiredTools: ['Write'],\n },\n ],\n vetoes: [],\n valueRationale: '--no-planner used; minimal-tier fallback. Re-run without --no-planner for the agentic flow.',\n };\n return {\n generatedAt: nowIso(),\n proposal,\n acceptedTier: 'minimal',\n acceptedIntegrationIds: ['write-md'],\n rejectedIntegrationIds: [],\n acceptedStakeholderNames: [],\n grantedTools: ['Read', 'Write', 'Glob', 'Grep'],\n recon,\n };\n}\n\nfunction summarizeReconForEvent(recon: ReconTriple): Record<string, unknown> {\n return {\n apps: recon.pc.apps.length,\n cliTools: recon.pc.cliTools.length,\n mcpServers: recon.pc.mcpServers.length,\n wikiPages: recon.wiki.relevantPages.length,\n stakeholders: recon.wiki.stakeholders.length,\n webPatterns: recon.web.bestPracticePatterns.length,\n appSurfaces: recon.web.appIntegrationSurfaces.length,\n warnings: recon.warnings.length,\n costUsd: recon.costUsd,\n durationMs: recon.durationMs,\n };\n}\n\n// Silence unused\nvoid logger;\n","/**\n * Wiki recon — Phase 5 Skill Planner recon phase 2.\n *\n * Walks the Knowledge Wiki (Phase 1.5) looking for the people, decisions,\n * concepts, vetoes, and past decisions that matter for one action item.\n * One Sonnet call with Read/Grep/Glob + maxTurns: 8 — reuses the same\n * Claude-Code-CLI primitives `aab knowledge query` does, but with a\n * recon-specific prompt that's tuned for stakeholder + decision + veto\n * extraction.\n *\n * Returns a `WikiContext` (docs/development/SKILL_CREATOR.md §6.3). Never throws on\n * an empty/missing wiki — degraded output with a warning is the contract.\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { paths, type ResolvedWorkspace } from '../../../storage/paths.js';\nimport { runClaude, extractText } from '../../../llm/claude-code-runner.js';\nimport { safeParseJSON } from '../../parsing/safe-json.js';\nimport { logger } from '../../logger.js';\nimport type { AppSettings } from '../../../storage/types.js';\n\nexport interface WikiStakeholder {\n slug: string;\n name: string;\n role: string;\n contactHints?: string;\n}\n\nexport interface WikiRelevantPage {\n slug: string;\n type: 'concept' | 'entity' | 'decision' | 'source-summary' | 'comparison';\n title: string;\n summary: string;\n excerpt?: string;\n}\n\nexport interface WikiEndorsedDirection {\n slug: string;\n statement: string;\n}\n\nexport interface WikiVeto {\n slug: string;\n statement: string;\n}\n\nexport interface WikiPastDecision {\n slug: string;\n title: string;\n outcome: string;\n}\n\n// ─── Tier 1: KNOWLEDGE — Phase 5.1 (wiki as operating brain) ───────────────\n\nexport interface WikiPlaybook {\n slug: string;\n title: string;\n /** FULL body — embedded verbatim into the emitted SKILL.md by skill-creator. */\n body: string;\n confidence: 'high' | 'medium' | 'low';\n}\n\nexport interface WikiTemplate {\n slug: string;\n title: string;\n /** FULL body — embedded verbatim. */\n body: string;\n /** Literal sample output if surfaceable (≤1500 chars). */\n exampleOutput?: string;\n}\n\nexport interface WikiDomainKnowledge {\n slug: string;\n title: string;\n summary: string;\n excerpt?: string;\n}\n\nexport interface WikiPastLesson {\n slug: string;\n summary: string;\n /** The concrete \"next time\" rule extracted from the post-mortem. */\n actionable: string;\n}\n\nexport interface WikiContext {\n // Tier 1 — knowledge that must be BAKED INTO the skill\n playbooks: WikiPlaybook[];\n templates: WikiTemplate[];\n domainKnowledge: WikiDomainKnowledge[];\n pastLessons: WikiPastLesson[];\n\n // Tier 2 — people\n stakeholders: WikiStakeholder[];\n\n // Tier 3 — rules\n endorsedDirections: WikiEndorsedDirection[];\n vetoes: WikiVeto[];\n pastDecisions: WikiPastDecision[];\n\n // Catch-all (anything that didn't fit a tier above)\n relevantPages: WikiRelevantPage[];\n\n costUsd: number;\n warning?: string;\n}\n\nexport interface WikiReconOptions {\n workspace: ResolvedWorkspace;\n settings: AppSettings;\n /** Action item title + description (the \"what we're planning for\"). */\n actionTitle: string;\n actionDescription?: string;\n discussionSummary?: string;\n maxTurns?: number;\n /** Bypass — return empty context with a note. */\n skip?: boolean;\n}\n\nconst PROMPT_TEMPLATE = `<role>\nYou are the Wiki Recon agent. The wiki at wiki/ is the user's OPERATING BRAIN —\nthe playbooks they've refined, the templates they've already proven, the\ndomain knowledge only they have, the post-mortems documenting what bit them\nlast time. Your job: find that knowledge and route it into structured slots\nthe Skill Planner uses to design a skill that does work THE USER'S WAY, not\nin a generic-best-practice way.\n\nThis is NOT a stakeholder address book. Do NOT over-weight people extraction.\nMost pages in a healthy wiki are about procedures, templates, and concepts —\nnot about humans.\n</role>\n\n<instructions>\nYou have Read + Grep + Glob — no write tools. Three-pass walk:\n\nPASS 1 — Tier classification.\nWalk wiki/index.md (slug map) and wiki/KNOWLEDGE.md (curated index). For each\ncandidate page, classify by TIER. A single page can land in multiple tiers\n(e.g., a playbook page that also contains a literal template).\n\nTier 1 — KNOWLEDGE (bake into the emitted skill):\n - playbook: \\`type: concept\\` page documenting \"how we X\" — procedural, uses\n first-person plural (\"we\", \"our\"), contains numbered/ordered steps, title\n matches patterns like \"Our X playbook\", \"How we Y\", \"X runbook\", \"Our\n process for Z\".\n Examples by domain (action-agnostic): \"Our YouTube launch playbook\" /\n \"How we land OAuth changes\" / \"Our pricing-decision framework\" / \"Our\n SDR hiring loop\" / \"Our monthly investor-update process\" / \"How we run\n competitive teardowns\" / \"Our DPA review checklist\".\n - template: \\`type: concept\\` page documenting an OUTPUT SHAPE — title\n contains \"template/format/style/structure/shape/example\", body contains\n a literal output sample.\n Examples: \"Our Danish SMB tone guide\" / \"Our PR description template\" /\n \"Our decision-memo template\" / \"Our SDR JD template\" / \"Our investor\n email template\" / \"Our slack incident-update format\".\n - domainKnowledge: \\`type: concept\\` page that is DESCRIPTIVE (not\n procedural) — defines what something IS or means in the user's context.\n Or \\`type: source-summary\\` that captures distilled learnings.\n Examples: \"Our brand voice principles\" / \"Our session-cookie threat\n model\" / \"TAM/SAM/SOM for DK\" / \"Our compensation philosophy\" / \"Our\n gross-margin definition\" / \"Our GDPR posture\".\n - pastLessons: post-mortems / retros / \"what bit us last time\" pages.\n Title contains \"lesson/post-mortem/retro/incident\". Body uses past-tense\n narrative + \"next time we will…\" / \"we should always…\" patterns.\n\nTier 2 — PEOPLE:\n - stakeholder: \\`type: entity\\` page about a human (kebab-cased multi-word\n slug not matching a company/product/tool name), body mentions\n relationship-to-user (\"my X\", \"our X\", \"X for the user\"). Extract role\n from frontmatter \\`role:\\` if present; otherwise from body's first\n paragraph. Capture email/Slack/phone as contactHints.\n\nTier 3 — RULES:\n - endorsedDirection: \\`type: concept\\` page or section stating \"we\n standardize on Y\" / \"we always X\" / \"we prefer Z\".\n - veto: same shape but \"never X\" / \"do not use Y\" / \"avoid Z\".\n - pastDecision: \\`type: decision\\` page relevant to the action — extract\n the outcome.\n\nPASS 2 — Open Tier 1 bodies in FULL.\nFor every playbook, template, and high-confidence domainKnowledge page,\nRead the entire body and include it in the output JSON. Do NOT summarize.\nThe Planner + skill-creator need the literal text to embed verbatim into the\nemitted skill.\n\nPASS 3 — Extract Tier 2-3 by summary (bodies only when highly relevant).\n\nConfidence scoring on playbooks:\n- \"high\" = title is \"Our X playbook\"/\"How we Y\" + body has ≥3 numbered\n first-person-plural steps naming the user's tools/people.\n- \"medium\" = title fits but body is principles-only without concrete steps.\n- \"low\" = page describes X without prescribing process → surface as\n domainKnowledge instead of playbook.\n\nIf a page seems to belong in BOTH playbook AND domainKnowledge, prefer\nplaybook (procedural signal is more load-bearing for the skill). If a page\nseems to be both template AND domainKnowledge, surface in BOTH (cheap; both\nslots accept the same body).\n\nAnti-bias check: if you find yourself wanting to put more than 3 pages in\nstakeholders[] and fewer than 3 in playbooks+templates+domainKnowledge,\nre-examine — you're under-counting knowledge.\n</instructions>\n\n<action>\ntitle: {{ACTION_TITLE}}\ndescription: {{ACTION_DESCRIPTION}}\nlinkedDiscussionSummary: {{DISCUSSION_SUMMARY}}\n</action>\n\n<output_contract>\nReturn ONLY a single JSON object. Start with \\`{\\`, end with \\`}\\`. No fences,\nno prose. Schema (every array is required even when empty):\n\n{\n \"playbooks\": [{ \"slug\": \"...\", \"title\": \"...\", \"body\": \"<FULL body verbatim>\",\n \"confidence\": \"high|medium|low\" }],\n \"templates\": [{ \"slug\": \"...\", \"title\": \"...\", \"body\": \"<FULL body verbatim>\",\n \"exampleOutput\"?: \"≤1500 chars literal sample if surfaceable\" }],\n \"domainKnowledge\": [{ \"slug\": \"...\", \"title\": \"...\", \"summary\": \"≤200 chars\",\n \"excerpt\"?: \"≤1000 chars when highly relevant\" }],\n \"pastLessons\": [{ \"slug\": \"...\", \"summary\": \"≤200 chars\",\n \"actionable\": \"the concrete 'next time' rule, ≤200 chars\" }],\n \"stakeholders\": [{ \"slug\": \"...\", \"name\": \"...\", \"role\": \"...\", \"contactHints\"?: \"...\" }],\n \"endorsedDirections\": [{ \"slug\": \"...\", \"statement\": \"...\" }],\n \"vetoes\": [{ \"slug\": \"...\", \"statement\": \"...\" }],\n \"pastDecisions\": [{ \"slug\": \"...\", \"title\": \"...\", \"outcome\": \"...\" }],\n \"relevantPages\": [{ \"slug\": \"...\", \"type\": \"concept|entity|decision|source-summary|comparison\",\n \"title\": \"...\", \"summary\": \"≤200 chars\", \"excerpt\"?: \"≤500 chars\" }]\n}\n\nIf wiki has no relevant content for the action, return all-empty arrays.\nDo NOT invent. Do NOT pad to look productive.\n</output_contract>`;\n\nexport async function runWikiRecon(opts: WikiReconOptions): Promise<WikiContext> {\n if (opts.skip) {\n return emptyContext('skipped via --planner-no-wiki');\n }\n const p = paths(opts.workspace.root);\n if (!existsSync(p.wiki) || !existsSync(p.wikiIndex)) {\n return emptyContext('wiki not bootstrapped — run `aab init` (or `aab knowledge migrate`) to enable wiki recon');\n }\n\n const model = pickReconModel(opts.settings);\n // Bumped from 8 → 12 (Phase 5.1): the recon agent now opens FULL bodies\n // of playbooks + templates, not just summaries.\n const maxTurns = opts.maxTurns ?? 12;\n\n const prompt = PROMPT_TEMPLATE\n .replace('{{ACTION_TITLE}}', escapeForPrompt(opts.actionTitle))\n .replace('{{ACTION_DESCRIPTION}}', escapeForPrompt(opts.actionDescription ?? ''))\n .replace('{{DISCUSSION_SUMMARY}}', escapeForPrompt(opts.discussionSummary ?? ''));\n\n logger.debug('[wiki-recon] starting', { title: opts.actionTitle.slice(0, 60), model, maxTurns });\n try {\n const result = await runClaude({\n prompt,\n model,\n allowedTools: ['Read', 'Grep', 'Glob'],\n maxTurns,\n cwd: opts.workspace.root,\n maxBudgetUsd: opts.settings.perCallBudgetUsd,\n timeoutMs: 3 * 60_000,\n });\n const costUsd = result.json?.cost_usd ?? 0;\n const text = extractText(result);\n const parsed = parseWikiContext(text);\n return { ...parsed, costUsd };\n } catch (err) {\n logger.debug('[wiki-recon] failed', { error: err instanceof Error ? err.message : String(err) });\n return emptyContext(\n `wiki recon LLM call failed: ${err instanceof Error ? err.message.slice(0, 200) : 'unknown'}`,\n );\n }\n}\n\nexport function parseWikiContext(text: string): Omit<WikiContext, 'costUsd' | 'warning'> {\n const empty = {\n playbooks: [], templates: [], domainKnowledge: [], pastLessons: [],\n stakeholders: [], endorsedDirections: [], vetoes: [], pastDecisions: [],\n relevantPages: [],\n };\n const parsed = safeParseJSON<Record<string, unknown>>(text);\n if (!parsed.success || !parsed.data || typeof parsed.data !== 'object') {\n return empty;\n }\n const d = parsed.data;\n // Tolerate model synonyms — different runs sometimes pick adjacent words\n // for the slot names (procedure/process for playbook, format/example for\n // template, knowledge/facts for domainKnowledge, lessons/learnings for\n // pastLessons). Coerce them all into the canonical fields before parsing.\n const playbookSrc = coerceArray(d.playbooks).concat(coerceArray(d.procedures)).concat(coerceArray(d.processes));\n const templateSrc = coerceArray(d.templates).concat(coerceArray(d.formats)).concat(coerceArray(d.examples));\n const dkSrc = coerceArray(d.domainKnowledge).concat(coerceArray(d.knowledge)).concat(coerceArray(d.facts));\n const lessonSrc = coerceArray(d.pastLessons).concat(coerceArray(d.lessons)).concat(coerceArray(d.learnings));\n return {\n playbooks: dedupeBySlug(playbookSrc.map(coercePlaybook).filter(nonNull)),\n templates: dedupeBySlug(templateSrc.map(coerceTemplate).filter(nonNull)),\n domainKnowledge: dedupeBySlug(dkSrc.map(coerceDomainKnowledge).filter(nonNull)),\n pastLessons: dedupeBySlug(lessonSrc.map(coercePastLesson).filter(nonNull)),\n stakeholders: coerceArray(d.stakeholders).map(coerceStakeholder).filter(nonNull),\n endorsedDirections: coerceArray(d.endorsedDirections).map(coerceEndorsedDirection).filter(nonNull),\n vetoes: coerceArray(d.vetoes).map(coerceVeto).filter(nonNull),\n pastDecisions: coerceArray(d.pastDecisions).map(coercePastDecision).filter(nonNull),\n relevantPages: coerceArray(d.relevantPages).map(coerceRelevantPage).filter(nonNull),\n };\n}\n\nfunction emptyContext(warning: string): WikiContext {\n return {\n playbooks: [], templates: [], domainKnowledge: [], pastLessons: [],\n stakeholders: [], endorsedDirections: [], vetoes: [], pastDecisions: [],\n relevantPages: [],\n costUsd: 0,\n warning,\n };\n}\n\nfunction dedupeBySlug<T extends { slug: string }>(items: T[]): T[] {\n const seen = new Set<string>();\n const out: T[] = [];\n for (const item of items) {\n if (seen.has(item.slug)) continue;\n seen.add(item.slug);\n out.push(item);\n }\n return out;\n}\n\nfunction pickReconModel(settings: AppSettings): string {\n const v = settings.knowledgeWiki?.queryModel ?? settings.primaryModel;\n return typeof v === 'string' ? v : 'sonnet';\n}\n\nfunction escapeForPrompt(text: string): string {\n // Block injections that close our XML-style sections.\n return text.replace(/<\\/?action>/gi, '').replace(/<\\/?instructions>/gi, '').slice(0, 4000);\n}\n\nfunction coerceArray(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\nfunction coerceRelevantPage(raw: unknown): WikiRelevantPage | null {\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Record<string, unknown>;\n const slug = asString(r.slug);\n const title = asString(r.title);\n if (!slug || !title) return null;\n const type = asPageType(r.type);\n if (!type) return null;\n return {\n slug,\n type,\n title,\n summary: asString(r.summary) ?? '',\n excerpt: asString(r.excerpt),\n };\n}\n\nfunction coercePlaybook(raw: unknown): WikiPlaybook | null {\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Record<string, unknown>;\n const slug = asString(r.slug);\n const title = asString(r.title);\n const body = asString(r.body) ?? asString(r.content);\n if (!slug || !title || !body) return null;\n const conf = asString(r.confidence)?.toLowerCase();\n const confidence: WikiPlaybook['confidence'] =\n conf === 'high' || conf === 'medium' || conf === 'low' ? conf : 'medium';\n return { slug, title, body, confidence };\n}\n\nfunction coerceTemplate(raw: unknown): WikiTemplate | null {\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Record<string, unknown>;\n const slug = asString(r.slug);\n const title = asString(r.title);\n const body = asString(r.body) ?? asString(r.content);\n if (!slug || !title || !body) return null;\n return { slug, title, body, exampleOutput: asString(r.exampleOutput) ?? asString(r.example) };\n}\n\nfunction coerceDomainKnowledge(raw: unknown): WikiDomainKnowledge | null {\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Record<string, unknown>;\n const slug = asString(r.slug);\n const title = asString(r.title);\n const summary = asString(r.summary);\n if (!slug || !title || !summary) return null;\n return { slug, title, summary, excerpt: asString(r.excerpt) };\n}\n\nfunction coercePastLesson(raw: unknown): WikiPastLesson | null {\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Record<string, unknown>;\n const slug = asString(r.slug);\n const summary = asString(r.summary);\n const actionable = asString(r.actionable) ?? asString(r.rule) ?? asString(r.nextTime);\n if (!slug || !summary || !actionable) return null;\n return { slug, summary, actionable };\n}\n\nfunction coerceStakeholder(raw: unknown): WikiStakeholder | null {\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Record<string, unknown>;\n const slug = asString(r.slug);\n const name = asString(r.name);\n const role = asString(r.role);\n if (!slug || !name || !role) return null;\n return { slug, name, role, contactHints: asString(r.contactHints) };\n}\n\nfunction coerceEndorsedDirection(raw: unknown): WikiEndorsedDirection | null {\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Record<string, unknown>;\n const slug = asString(r.slug);\n const statement = asString(r.statement);\n if (!slug || !statement) return null;\n return { slug, statement };\n}\n\nfunction coerceVeto(raw: unknown): WikiVeto | null {\n return coerceEndorsedDirection(raw); // same shape\n}\n\nfunction coercePastDecision(raw: unknown): WikiPastDecision | null {\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Record<string, unknown>;\n const slug = asString(r.slug);\n const title = asString(r.title);\n const outcome = asString(r.outcome);\n if (!slug || !title || !outcome) return null;\n return { slug, title, outcome };\n}\n\nfunction asString(value: unknown): string | undefined {\n if (typeof value === 'string' && value.trim()) return value.trim();\n return undefined;\n}\n\nfunction asPageType(value: unknown): WikiRelevantPage['type'] | null {\n if (typeof value !== 'string') return null;\n const v = value.toLowerCase();\n if (v === 'concept' || v === 'entity' || v === 'decision' || v === 'source-summary' || v === 'comparison') return v;\n return null;\n}\n\nfunction nonNull<T>(v: T | null): v is T {\n return v !== null;\n}\n\n// Suppress unused import (readFileSync may be needed when we later add\n// frontmatter pre-scanning prior to the LLM call to seed candidate slugs).\nvoid readFileSync;\n","/**\n * Web recon — Phase 5 Skill Planner recon phase 3.\n *\n * Two passes per docs/development/SKILL_CREATOR.md §6.4:\n *\n * Pass 1 — General task research. One Sonnet call with WebSearch + WebFetch\n * (maxTurns: 12). Output: bestPracticePatterns, recommendedTools,\n * recentInnovations, warningsAndPitfalls.\n *\n * Pass 2 — Per-detected-app integration-surface research. For the top 5\n * apps from the PC scan (sorted by action-keyword relevance), one\n * targeted Sonnet call each (maxTurns: 6) asking specifically about\n * local APIs, CLI binaries, URL schemes, file-system integration,\n * MCP availability, SDKs. Output: appIntegrationSurfaces[].\n *\n * The per-app pass is what makes the maximalist tier actually maximalist —\n * generic web research doesn't surface \"Elgato Teleprompter has a local\n * HTTP API on port 9012.\" Targeted per-app research does.\n *\n * Never throws on partial failure — returns an empty/degraded context with\n * a warning, and the recon orchestrator (`orchestrator.ts`) aggregates.\n */\nimport { runClaude, extractText } from '../../../llm/claude-code-runner.js';\nimport { safeParseJSON } from '../../parsing/safe-json.js';\nimport { logger } from '../../logger.js';\nimport type { AppSettings } from '../../../storage/types.js';\nimport type { DetectedApp } from './pc-scan.js';\n\nexport interface WebInvocationHint {\n kind: 'bash-cmd' | 'bash-curl' | 'mcp-tool' | 'bash-script' | 'write-artifact' | 'manual-handoff' | 'chrome-extension' | 'computer-use';\n tools: string[];\n snippet?: string;\n}\n\nexport interface WebBestPracticePattern {\n pattern: string;\n rationale: string;\n sources: Array<{ title: string; url: string }>;\n}\n\nexport interface WebRecommendedTool {\n name: string;\n category: 'cli' | 'desktop-app' | 'mcp-server' | 'web-service' | 'api';\n purpose: string;\n integrationHint: string;\n sources: Array<{ title: string; url: string }>;\n}\n\nexport interface WebRecentInnovation {\n name: string;\n summary: string;\n sources: Array<{ title: string; url: string }>;\n}\n\nexport interface WebAppIntegrationSurface {\n appName: string;\n integrationKind: 'local-http' | 'cli' | 'url-scheme' | 'file-system' | 'mcp-server' | 'sdk' | 'none';\n invocationHint: WebInvocationHint;\n workflow: string[];\n risks: string[];\n sources: Array<{ title: string; url: string }>;\n}\n\nexport interface WebResearchContext {\n taskDomain: string;\n bestPracticePatterns: WebBestPracticePattern[];\n recommendedTools: WebRecommendedTool[];\n recentInnovations: WebRecentInnovation[];\n warningsAndPitfalls: string[];\n appIntegrationSurfaces: WebAppIntegrationSurface[];\n webPassesCompleted: { general: boolean; perAppCount: number };\n costUsd: number;\n warning?: string;\n}\n\nexport interface WebReconOptions {\n settings: AppSettings;\n actionTitle: string;\n actionDescription?: string;\n apps: DetectedApp[];\n /** Skip the web phase entirely (offline or --planner-no-web). */\n skip?: boolean;\n /** Default 5 — cap per-app passes. */\n topAppCount?: number;\n /** Default 12 — pass 1 maxTurns. */\n generalMaxTurns?: number;\n /** Default 6 — pass 2 maxTurns. */\n perAppMaxTurns?: number;\n /** Workspace cwd (so Read/Glob aren't accidentally invoked outside it). */\n cwd?: string;\n}\n\nconst GENERAL_PROMPT = `<role>\nYou are the Web Research agent for the Skill Planner. Research how this task is\nbeing done in 2026 — what tools, integrations, and best-practice patterns exist?\nWhat's Anthropic's / the wider community's recommended approach?\n</role>\n\n<action>\ntitle: {{ACTION_TITLE}}\ndescription: {{ACTION_DESCRIPTION}}\n</action>\n\n<instructions>\nUse WebSearch + WebFetch. Prioritize recency (2026) and authority (Anthropic\ndocs > vendor docs > top-ranked community sources). Surface 8-15 sources total.\nAvoid SEO content farms.\n</instructions>\n\n<output_contract>\nReturn ONLY a single JSON object — no fences, no prose. Schema:\n{\n \"taskDomain\": \"≤40 chars label, e.g. 'YouTube video production workflow'\",\n \"bestPracticePatterns\": [{ \"pattern\": \"...\", \"rationale\": \"≤200 chars\",\n \"sources\": [{ \"title\": \"...\", \"url\": \"...\" }] }],\n \"recommendedTools\": [{ \"name\": \"...\", \"category\": \"cli|desktop-app|mcp-server|web-service|api\",\n \"purpose\": \"≤120 chars\", \"integrationHint\": \"≤200 chars\",\n \"sources\": [{ \"title\": \"...\", \"url\": \"...\" }] }],\n \"recentInnovations\": [{ \"name\": \"...\", \"summary\": \"≤200 chars\",\n \"sources\": [{ \"title\": \"...\", \"url\": \"...\" }] }],\n \"warningsAndPitfalls\": [\"≤120 chars each\"]\n}\n</output_contract>`;\n\nconst PER_APP_PROMPT = `<role>\nYou are the App Integration Surface researcher for the Skill Planner. The user\nhas {{APP_NAME}} ({{APP_VERSION_OR_NONE}}) installed. Find every programmatic\nintegration surface it exposes — and if none exist, say so explicitly.\n</role>\n\n<action>\ntitle: {{ACTION_TITLE}}\ndescription: {{ACTION_DESCRIPTION}}\n</action>\n\n<instructions>\nUse WebSearch + WebFetch. Look for: local HTTP API + port + endpoints,\nCLI binary + commands, URL scheme, file-system integration, MCP server,\nofficial SDK, automation guides. Cite vendor docs + Anthropic docs + top\ncommunity sources. If no programmatic integration exists, surface a\nchrome-extension or computer-use handoff as a fallback.\n</instructions>\n\n<output_contract>\nReturn ONLY a single JSON object. Schema:\n{\n \"appName\": \"{{APP_NAME}}\",\n \"integrationKind\": \"local-http|cli|url-scheme|file-system|mcp-server|sdk|none\",\n \"invocationHint\": {\n \"kind\": \"bash-cmd|bash-curl|mcp-tool|bash-script|write-artifact|manual-handoff|chrome-extension|computer-use\",\n \"tools\": [\"allowed-tools entries — e.g. Bash(curl *)\"],\n \"snippet\": \"verbatim shell or curl snippet skill body should embed (omit for chrome/computer-use)\"\n },\n \"workflow\": [\"ordered steps\"],\n \"risks\": [\"e.g. local port collision\"],\n \"sources\": [{ \"title\": \"...\", \"url\": \"...\" }]\n}\n</output_contract>`;\n\nexport async function runWebRecon(opts: WebReconOptions): Promise<WebResearchContext> {\n if (opts.skip) {\n return emptyContext(opts.actionTitle, 'skipped via --planner-no-web');\n }\n const model = pickModel(opts.settings);\n const generalMaxTurns = opts.generalMaxTurns ?? 12;\n const perAppMaxTurns = opts.perAppMaxTurns ?? 6;\n const topAppCount = opts.topAppCount ?? 5;\n\n let costUsd = 0;\n let warning: string | undefined;\n\n // ----- Pass 1 — general task research -----\n let general: Omit<WebResearchContext,\n 'appIntegrationSurfaces' | 'webPassesCompleted' | 'costUsd' | 'warning'> | null = null;\n try {\n const prompt = GENERAL_PROMPT\n .replace('{{ACTION_TITLE}}', escapeForPrompt(opts.actionTitle))\n .replace('{{ACTION_DESCRIPTION}}', escapeForPrompt(opts.actionDescription ?? ''));\n const result = await runClaude({\n prompt,\n model,\n allowedTools: ['WebSearch', 'WebFetch'],\n maxTurns: generalMaxTurns,\n cwd: opts.cwd,\n maxBudgetUsd: opts.settings.perCallBudgetUsd,\n timeoutMs: 5 * 60_000,\n });\n costUsd += result.json?.cost_usd ?? 0;\n general = parseGeneral(extractText(result));\n } catch (err) {\n logger.debug('[web-recon] pass1 failed', { error: err instanceof Error ? err.message : String(err) });\n warning = `general web research failed: ${err instanceof Error ? err.message.slice(0, 160) : 'unknown'}`;\n }\n\n // ----- Pass 2 — per-app integration-surface research -----\n const topApps = pickTopAppsForResearch(opts.apps, opts.actionTitle, opts.actionDescription, topAppCount);\n const surfaces: WebAppIntegrationSurface[] = [];\n for (const app of topApps) {\n try {\n const prompt = PER_APP_PROMPT\n .replace('{{ACTION_TITLE}}', escapeForPrompt(opts.actionTitle))\n .replace('{{ACTION_DESCRIPTION}}', escapeForPrompt(opts.actionDescription ?? ''))\n .replace(/{{APP_NAME}}/g, escapeForPrompt(app.name))\n .replace('{{APP_VERSION_OR_NONE}}', app.version ?? '');\n const result = await runClaude({\n prompt,\n model,\n allowedTools: ['WebSearch', 'WebFetch'],\n maxTurns: perAppMaxTurns,\n cwd: opts.cwd,\n maxBudgetUsd: opts.settings.perCallBudgetUsd,\n timeoutMs: 3 * 60_000,\n });\n costUsd += result.json?.cost_usd ?? 0;\n const surface = parseAppSurface(extractText(result), app.name);\n if (surface) surfaces.push(surface);\n } catch (err) {\n logger.debug('[web-recon] per-app pass failed', { app: app.name, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n return {\n taskDomain: general?.taskDomain ?? opts.actionTitle.slice(0, 60),\n bestPracticePatterns: general?.bestPracticePatterns ?? [],\n recommendedTools: general?.recommendedTools ?? [],\n recentInnovations: general?.recentInnovations ?? [],\n warningsAndPitfalls: general?.warningsAndPitfalls ?? [],\n appIntegrationSurfaces: surfaces,\n webPassesCompleted: { general: general !== null, perAppCount: surfaces.length },\n costUsd,\n warning,\n };\n}\n\nfunction emptyContext(actionTitle: string, warning: string): WebResearchContext {\n return {\n taskDomain: actionTitle.slice(0, 60),\n bestPracticePatterns: [],\n recommendedTools: [],\n recentInnovations: [],\n warningsAndPitfalls: [],\n appIntegrationSurfaces: [],\n webPassesCompleted: { general: false, perAppCount: 0 },\n costUsd: 0,\n warning,\n };\n}\n\nfunction pickModel(settings: AppSettings): string {\n const v = settings.researchModel ?? settings.primaryModel ?? 'sonnet';\n return typeof v === 'string' ? v : 'sonnet';\n}\n\nfunction escapeForPrompt(text: string): string {\n return text.replace(/<\\/?action>/gi, '').replace(/<\\/?instructions>/gi, '').slice(0, 4000);\n}\n\n/**\n * Pick the top N apps for the per-app research pass. Sorted by simple keyword\n * relevance against the action title + description; ties resolved by app\n * category preference.\n */\nexport function pickTopAppsForResearch(\n apps: DetectedApp[],\n actionTitle: string,\n actionDescription: string | undefined,\n topN: number,\n): DetectedApp[] {\n const haystack = `${actionTitle} ${actionDescription ?? ''}`.toLowerCase();\n const tokens = haystack.match(/[a-z0-9]+/g) ?? [];\n const scored = apps.map((app) => {\n const lower = app.name.toLowerCase();\n let score = 0;\n for (const t of tokens) {\n if (t.length < 3) continue;\n if (lower.includes(t)) score += 5;\n }\n // Boost by category match against common action verbs.\n if (/(record|video|stream|edit|render|design|brand)/i.test(haystack) && app.category === 'creative') score += 3;\n if (/(meet|message|share|notify|invite)/i.test(haystack) && app.category === 'comms') score += 3;\n if (/(deploy|ship|build|refactor|debug)/i.test(haystack) && app.category === 'dev') score += 3;\n if (/(report|track|spreadsheet|kpi|chart)/i.test(haystack) && app.category === 'data') score += 3;\n if (/(invoice|charge|budget|cash|forecast)/i.test(haystack) && app.category === 'finance') score += 3;\n return { app, score };\n });\n scored.sort((a, b) => b.score - a.score);\n return scored.filter((s) => s.score > 0).slice(0, topN).map((s) => s.app);\n}\n\nexport function parseGeneral(text: string): Omit<\n WebResearchContext,\n 'appIntegrationSurfaces' | 'webPassesCompleted' | 'costUsd' | 'warning'\n> | null {\n const parsed = safeParseJSON<Record<string, unknown>>(text);\n if (!parsed.success || !parsed.data || typeof parsed.data !== 'object') return null;\n const d = parsed.data;\n return {\n taskDomain: asString(d.taskDomain) ?? 'general',\n bestPracticePatterns: coerceArray(d.bestPracticePatterns).map(coercePattern).filter(nonNull),\n recommendedTools: coerceArray(d.recommendedTools).map(coerceTool).filter(nonNull),\n recentInnovations: coerceArray(d.recentInnovations).map(coerceInnovation).filter(nonNull),\n warningsAndPitfalls: coerceArray(d.warningsAndPitfalls).map((v) => asString(v) ?? '').filter(Boolean),\n };\n}\n\nexport function parseAppSurface(text: string, fallbackName: string): WebAppIntegrationSurface | null {\n const parsed = safeParseJSON<Record<string, unknown>>(text);\n if (!parsed.success || !parsed.data || typeof parsed.data !== 'object') return null;\n const d = parsed.data;\n const kind = asInvocationKind(((d.invocationHint ?? {}) as Record<string, unknown>).kind);\n if (!kind) return null;\n const ih = (d.invocationHint ?? {}) as Record<string, unknown>;\n return {\n appName: asString(d.appName) ?? fallbackName,\n integrationKind: asIntegrationKind(d.integrationKind) ?? 'none',\n invocationHint: {\n kind,\n tools: coerceStringArray(ih.tools),\n snippet: asString(ih.snippet),\n },\n workflow: coerceStringArray(d.workflow),\n risks: coerceStringArray(d.risks),\n sources: coerceSources(d.sources),\n };\n}\n\n// ---------- coercion helpers ----------\n\nfunction coerceArray(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\nfunction coerceStringArray(value: unknown): string[] {\n return coerceArray(value).map((v) => asString(v) ?? '').filter(Boolean);\n}\n\nfunction coercePattern(raw: unknown): WebBestPracticePattern | null {\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Record<string, unknown>;\n const pattern = asString(r.pattern);\n if (!pattern) return null;\n return { pattern, rationale: asString(r.rationale) ?? '', sources: coerceSources(r.sources) };\n}\n\nfunction coerceTool(raw: unknown): WebRecommendedTool | null {\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Record<string, unknown>;\n const name = asString(r.name);\n if (!name) return null;\n return {\n name,\n category: asCategory(r.category) ?? 'web-service',\n purpose: asString(r.purpose) ?? '',\n integrationHint: asString(r.integrationHint) ?? '',\n sources: coerceSources(r.sources),\n };\n}\n\nfunction coerceInnovation(raw: unknown): WebRecentInnovation | null {\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Record<string, unknown>;\n const name = asString(r.name);\n if (!name) return null;\n return { name, summary: asString(r.summary) ?? '', sources: coerceSources(r.sources) };\n}\n\nfunction coerceSources(value: unknown): Array<{ title: string; url: string }> {\n return coerceArray(value)\n .map((raw) => {\n if (!raw || typeof raw !== 'object') return null;\n const r = raw as Record<string, unknown>;\n const title = asString(r.title);\n const url = asString(r.url);\n if (!title || !url) return null;\n return { title, url };\n })\n .filter(nonNull);\n}\n\nfunction asString(value: unknown): string | undefined {\n if (typeof value === 'string' && value.trim()) return value.trim();\n return undefined;\n}\n\nfunction asCategory(value: unknown): WebRecommendedTool['category'] | null {\n if (typeof value !== 'string') return null;\n const v = value.toLowerCase();\n if (v === 'cli' || v === 'desktop-app' || v === 'mcp-server' || v === 'web-service' || v === 'api') return v;\n return null;\n}\n\nfunction asIntegrationKind(value: unknown): WebAppIntegrationSurface['integrationKind'] | null {\n if (typeof value !== 'string') return null;\n const v = value.toLowerCase();\n if (v === 'local-http' || v === 'cli' || v === 'url-scheme' || v === 'file-system'\n || v === 'mcp-server' || v === 'sdk' || v === 'none') return v;\n return null;\n}\n\nfunction asInvocationKind(value: unknown): WebInvocationHint['kind'] | null {\n if (typeof value !== 'string') return null;\n const v = value.toLowerCase();\n if (v === 'bash-cmd' || v === 'bash-curl' || v === 'mcp-tool' || v === 'bash-script'\n || v === 'write-artifact' || v === 'manual-handoff' || v === 'chrome-extension' || v === 'computer-use') return v;\n return null;\n}\n\nfunction nonNull<T>(v: T | null | undefined): v is T {\n return v !== null && v !== undefined;\n}\n","/**\n * Recon orchestrator — Phase 5 Skill Planner.\n *\n * Runs all three recon phases (PC scan + wiki recon + web recon) in parallel\n * via Promise.allSettled, aggregates results, and produces the\n * `ReconTriple` the Planner reasoning step consumes.\n *\n * Partial failures degrade gracefully — each phase has its own warning slot,\n * and the orchestrator's `warnings[]` aggregates them so the Planner prompt\n * (and the user-review modal) can surface \"web research timed out\" without\n * blocking the whole pipeline.\n */\nimport type { AppSettings } from '../../../storage/types.js';\nimport type { ResolvedWorkspace } from '../../../storage/paths.js';\nimport { scan as scanPc, type ReconResult } from './pc-scan.js';\nimport { runWikiRecon, type WikiContext } from './wiki-recon.js';\nimport { runWebRecon, type WebResearchContext } from './web-recon.js';\n\nexport interface ReconTriple {\n pc: ReconResult;\n wiki: WikiContext;\n web: WebResearchContext;\n /** Aggregated warnings from all three phases. */\n warnings: Array<{\n phase: 'pc-scan' | 'wiki-recon' | 'web-research-general' | 'web-research-per-app';\n severity: 'info' | 'warn' | 'error';\n message: string;\n }>;\n /** Sum of LLM cost across wiki + web phases (PC scan is free). */\n costUsd: number;\n /** Wall-clock for the slowest phase (since they run in parallel). */\n durationMs: number;\n}\n\nexport interface ReconOptions {\n workspace: ResolvedWorkspace;\n settings: AppSettings;\n actionTitle: string;\n actionDescription?: string;\n discussionSummary?: string;\n skipPcScan?: boolean;\n skipWiki?: boolean;\n skipWeb?: boolean;\n /** Default 5. */\n topAppCount?: number;\n /** Streaming progress callback — fires when each phase completes. */\n onPhaseDone?: (phase: 'pc-scan' | 'wiki-recon' | 'web-research', summary: string) => void;\n}\n\nexport async function runRecon(opts: ReconOptions): Promise<ReconTriple> {\n const started = Date.now();\n const warnings: ReconTriple['warnings'] = [];\n\n // PC scan is sync + fast; run it inline so wiki + web have its output available\n // if we ever start cross-referencing (T1.3 already wires apps → per-app web pass).\n let pc: ReconResult;\n if (opts.skipPcScan) {\n pc = emptyPc('skipped via --planner-no-pc-scan');\n } else {\n try {\n pc = scanPc({ projectRoot: opts.workspace.root });\n } catch (err) {\n pc = emptyPc(err instanceof Error ? err.message.slice(0, 160) : 'pc scan failed');\n }\n }\n for (const w of pc.warnings) warnings.push({ phase: 'pc-scan', severity: w.severity, message: w.message });\n opts.onPhaseDone?.(\n 'pc-scan',\n `${pc.apps.length} apps, ${pc.cliTools.length} CLI tools, ${pc.mcpServers.length} MCP, ${pc.envVars.length} env`,\n );\n\n // Wiki + web run in parallel.\n const wikiPromise = runWikiRecon({\n workspace: opts.workspace,\n settings: opts.settings,\n actionTitle: opts.actionTitle,\n actionDescription: opts.actionDescription,\n discussionSummary: opts.discussionSummary,\n skip: opts.skipWiki,\n });\n const webPromise = runWebRecon({\n settings: opts.settings,\n actionTitle: opts.actionTitle,\n actionDescription: opts.actionDescription,\n apps: pc.apps,\n skip: opts.skipWeb,\n topAppCount: opts.topAppCount,\n cwd: opts.workspace.root,\n });\n\n const [wikiSettled, webSettled] = await Promise.allSettled([wikiPromise, webPromise]);\n const wiki: WikiContext = wikiSettled.status === 'fulfilled'\n ? wikiSettled.value\n : {\n playbooks: [], templates: [], domainKnowledge: [], pastLessons: [],\n stakeholders: [], endorsedDirections: [], vetoes: [], pastDecisions: [],\n relevantPages: [],\n costUsd: 0,\n warning: wikiSettled.reason instanceof Error ? wikiSettled.reason.message : 'wiki recon failed',\n };\n if (wiki.warning) warnings.push({ phase: 'wiki-recon', severity: 'warn', message: wiki.warning });\n opts.onPhaseDone?.(\n 'wiki-recon',\n `${wiki.playbooks.length} playbooks, ${wiki.templates.length} templates, ${wiki.domainKnowledge.length} knowledge, ${wiki.stakeholders.length} stakeholders, ${wiki.vetoes.length} vetoes`,\n );\n\n const web: WebResearchContext = webSettled.status === 'fulfilled'\n ? webSettled.value\n : {\n taskDomain: opts.actionTitle.slice(0, 60),\n bestPracticePatterns: [],\n recommendedTools: [],\n recentInnovations: [],\n warningsAndPitfalls: [],\n appIntegrationSurfaces: [],\n webPassesCompleted: { general: false, perAppCount: 0 },\n costUsd: 0,\n warning: webSettled.reason instanceof Error ? webSettled.reason.message : 'web recon failed',\n };\n if (!web.webPassesCompleted.general) {\n warnings.push({\n phase: 'web-research-general',\n severity: 'warn',\n message: web.warning ?? 'general web pass returned no parseable output',\n });\n }\n opts.onPhaseDone?.(\n 'web-research',\n `${web.bestPracticePatterns.length} patterns, ${web.recommendedTools.length} tools, ${web.appIntegrationSurfaces.length} app surfaces`,\n );\n\n return {\n pc,\n wiki,\n web,\n warnings,\n costUsd: wiki.costUsd + web.costUsd,\n durationMs: Date.now() - started,\n };\n}\n\nfunction emptyPc(reason: string): ReconResult {\n return {\n platform: process.platform === 'win32' ? 'win32' : process.platform === 'darwin' ? 'darwin' : 'linux',\n scannedAt: new Date().toISOString(),\n apps: [],\n cliTools: [],\n mcpServers: [],\n browserExtensions: [],\n envVars: [],\n existingSkills: [],\n playwright: false,\n chrome: false,\n computerUseAvailable: false,\n warnings: [{ phase: 'pc-scan', severity: 'warn', message: reason }],\n };\n}\n","/**\n * Planner-review — Phase 5 Chunk 3.\n *\n * Interactive review flow per docs/development/SKILL_CREATOR.md §6.6. CLI surface uses\n * `enquirer` (multi-select for integrations + stakeholders; select for tier\n * radio; confirm for accept). Web UI surfaces equivalent shapes via\n * `/api/actions/:id/plan` + the proposal modal.\n *\n * Output: `SkillCapabilityProfile` with `grantedTools` derived deterministically\n * from accepted integrations. Re-plan loop capped at 3 per solve.\n */\nimport type { SkillDesignProposal } from '../parsing/llm-response-schemas.js';\nimport type { ReconTriple } from './recon/orchestrator.js';\nimport { askConfirm, askMultiSelect, askSelect, askText } from '../../ui/prompts.js';\nimport { projectGrantedTools } from './planner.js';\nimport { c } from '../../ui/colors.js';\nimport { nowIso } from '../utils.js';\n\nexport interface PlannerReviewResult {\n status: 'accepted' | 'rejected' | 'replan';\n /** When status === 'accepted', a fully-resolved capability profile. */\n profile?: ResolvedSkillCapabilityProfile;\n /** When status === 'replan', the user's feedback text (≥10 chars). */\n replanFeedback?: string;\n}\n\nexport interface ResolvedSkillCapabilityProfile {\n generatedAt: string;\n proposal: SkillDesignProposal;\n acceptedTier: 'minimal' | 'standard' | 'maximalist' | 'custom';\n acceptedIntegrationIds: string[];\n rejectedIntegrationIds: string[];\n acceptedStakeholderNames: string[];\n userNarrativeEdits?: string;\n grantedTools: string[];\n /** Carried through for provenance. */\n recon: ReconTriple;\n}\n\nexport interface InteractiveReviewOptions {\n proposal: SkillDesignProposal;\n recon: ReconTriple;\n /** Set to true for `--yes` mode (accept Planner's recommendedTier + all integrations). */\n autoAccept?: boolean;\n}\n\nexport async function reviewInteractive(opts: InteractiveReviewOptions): Promise<PlannerReviewResult> {\n const { proposal, recon } = opts;\n\n if (opts.autoAccept) {\n return acceptAll(proposal, recon);\n }\n\n printProposalSummary(proposal);\n\n // 1. Pick tier\n const tier = await askSelect<'minimal' | 'standard' | 'maximalist' | 'custom'>(\n 'Ambition tier',\n [\n { name: 'maximalist', message: 'maximalist', hint: 'orchestrate everything — recommended' },\n { name: 'standard', message: 'standard', hint: 'balanced power + simplicity' },\n { name: 'minimal', message: 'minimal', hint: 'artifact only, no integrations' },\n { name: 'custom', message: 'custom', hint: 'pick integrations + stakeholders manually' },\n ],\n { initial: (proposal.recommendedTier as 'maximalist') ?? 'maximalist' },\n );\n\n // 2. Default-accepted integrations per tier\n const defaultAcceptedIds = defaultAcceptanceForTier(proposal, tier);\n const acceptedIntegrationIds = tier === 'custom'\n ? await askMultiSelect(\n 'Integrations to include',\n proposal.integrations.map((i) => ({\n name: i.id,\n message: `${i.name} ${c.hint('(' + i.invocationHint.kind + ')')}`,\n hint: i.purpose ?? '',\n selected: defaultAcceptedIds.has(i.id),\n })),\n )\n : Array.from(defaultAcceptedIds);\n\n // 3. Stakeholders\n const stakeholders = proposal.stakeholderTouchpoints ?? [];\n const acceptedStakeholderNames = stakeholders.length === 0\n ? []\n : await askMultiSelect(\n 'Stakeholders to touch',\n stakeholders.map((s) => ({\n name: s.name,\n message: `${s.name} ${c.hint('(' + (s.role ?? '?') + ' — ' + (s.touchpointKind ?? 'other') + ')')}`,\n hint: s.rationale ?? '',\n selected: true,\n })),\n );\n\n // 4. Narrative edits (free-form, optional)\n const wantEdits = await askConfirm('Edit narrative / add free-form context for skill-creator?', false);\n let userNarrativeEdits: string | undefined;\n if (wantEdits) {\n userNarrativeEdits = await askText('Narrative edits (free text — Enter to finish)', { initial: '' });\n if (!userNarrativeEdits.trim()) userNarrativeEdits = undefined;\n }\n\n // 5. Final accept / replan / reject\n const finalChoice = await askSelect<'accept' | 'replan' | 'reject'>(\n 'What next?',\n [\n { name: 'accept', message: 'Accept and run', hint: 'invoke skill-creator with this proposal' },\n { name: 'replan', message: 'Re-plan with feedback', hint: 'send the Planner back to the drawing board (~$1.74)' },\n { name: 'reject', message: 'Cancel', hint: 'abort the solve' },\n ],\n { initial: 'accept' },\n );\n\n if (finalChoice === 'reject') {\n return { status: 'rejected' };\n }\n if (finalChoice === 'replan') {\n const feedback = await askText('What did the Planner miss? (≥10 chars)', { initial: '', required: true });\n if (feedback.trim().length < 10) {\n return { status: 'rejected' };\n }\n return { status: 'replan', replanFeedback: feedback.trim() };\n }\n\n return acceptWith(proposal, recon, tier, acceptedIntegrationIds, acceptedStakeholderNames, userNarrativeEdits);\n}\n\nexport function acceptAll(proposal: SkillDesignProposal, recon: ReconTriple): PlannerReviewResult {\n const allIntegrationIds = proposal.integrations.map((i) => i.id);\n const allStakeholderNames = (proposal.stakeholderTouchpoints ?? []).map((s) => s.name);\n return acceptWith(proposal, recon, (proposal.recommendedTier as 'maximalist') ?? 'maximalist', allIntegrationIds, allStakeholderNames, undefined);\n}\n\nexport function acceptWith(\n proposal: SkillDesignProposal,\n recon: ReconTriple,\n tier: 'minimal' | 'standard' | 'maximalist' | 'custom',\n acceptedIntegrationIds: string[],\n acceptedStakeholderNames: string[],\n userNarrativeEdits: string | undefined,\n): PlannerReviewResult {\n const grantedTools = projectGrantedTools(\n proposal,\n new Set(acceptedIntegrationIds),\n new Set(acceptedStakeholderNames),\n );\n const rejectedIntegrationIds = proposal.integrations\n .map((i) => i.id)\n .filter((id) => !acceptedIntegrationIds.includes(id));\n return {\n status: 'accepted',\n profile: {\n generatedAt: nowIso(),\n proposal,\n acceptedTier: tier,\n acceptedIntegrationIds,\n rejectedIntegrationIds,\n acceptedStakeholderNames,\n userNarrativeEdits,\n grantedTools,\n recon,\n },\n };\n}\n\nfunction defaultAcceptanceForTier(proposal: SkillDesignProposal, tier: 'minimal' | 'standard' | 'maximalist' | 'custom'): Set<string> {\n if (tier === 'custom') return new Set();\n if (tier === 'minimal') {\n // Keep only write-artifact + read integrations.\n return new Set(\n proposal.integrations\n .filter((i) => i.invocationHint.kind === 'write-artifact' || (i.invocationHint.tools ?? []).every((t) => /^(Read|Write|Glob|Grep|WebSearch|WebFetch)/.test(t)))\n .map((i) => i.id),\n );\n }\n if (tier === 'standard') {\n // Top-2 by confidence.\n const ranked = [...proposal.integrations].sort((a, b) => (b.confidence ?? 0) - (a.confidence ?? 0));\n return new Set(ranked.slice(0, 2).map((i) => i.id));\n }\n // maximalist: all\n return new Set(proposal.integrations.map((i) => i.id));\n}\n\n/**\n * Render a human-readable summary of the proposal for the CLI (or for the\n * `--out <path>` markdown export). Pure function — no I/O.\n */\nexport function renderProposalMarkdown(proposal: SkillDesignProposal): string {\n const lines: string[] = [];\n lines.push(`# Skill Planner proposal: ${proposal.skillName}`);\n lines.push('');\n lines.push(`**Summary:** ${proposal.skillSummary}`);\n if (proposal.triggerLanguage) lines.push(`**Trigger:** ${proposal.triggerLanguage}`);\n lines.push(`**Recommended tier:** ${proposal.recommendedTier}`);\n if (typeof proposal.estimatedCostUsd === 'number') {\n lines.push(`**Estimated cost:** $${proposal.estimatedCostUsd.toFixed(2)} · ~${Math.round(proposal.estimatedDurationMinutes ?? 0)}min`);\n }\n lines.push('');\n if (proposal.valueRationale) {\n lines.push(`## Why maximalist`);\n lines.push('');\n lines.push(proposal.valueRationale);\n lines.push('');\n }\n lines.push(`## Integrations (${proposal.integrations.length})`);\n lines.push('');\n for (const i of proposal.integrations) {\n lines.push(`- **${i.name}** (\\`${i.invocationHint.kind}\\`, ${i.source})`);\n if (i.purpose) lines.push(` - Purpose: ${i.purpose}`);\n if (i.invocationHint.snippet) {\n lines.push(' - Snippet:');\n lines.push(' ```');\n lines.push(` ${i.invocationHint.snippet.replace(/\\n/g, '\\n ')}`);\n lines.push(' ```');\n }\n if (i.invocationHint.handoffInstructions) {\n lines.push(` - Handoff: ${i.invocationHint.handoffInstructions.slice(0, 240)}${i.invocationHint.handoffInstructions.length > 240 ? '…' : ''}`);\n }\n if ((i.invocationHint.tools ?? []).length > 0) {\n lines.push(` - Tools: ${(i.invocationHint.tools ?? []).join(', ')}`);\n }\n if (i.fallbackIfMissing) lines.push(` - Fallback: ${i.fallbackIfMissing}`);\n }\n lines.push('');\n if ((proposal.stakeholderTouchpoints ?? []).length > 0) {\n lines.push('## Stakeholder touchpoints');\n lines.push('');\n for (const s of proposal.stakeholderTouchpoints ?? []) {\n lines.push(`- **${s.name}** (${s.role ?? '?'}) — ${s.touchpointKind ?? 'other'}, produces: ${s.produces ?? '?'}`);\n if (s.rationale) lines.push(` - ${s.rationale}`);\n if (s.artifactTemplate?.subject) lines.push(` - Draft subject: ${s.artifactTemplate.subject}`);\n }\n lines.push('');\n }\n if ((proposal.vetoes ?? []).length > 0) {\n lines.push('## Vetoes (MUST NOT)');\n for (const v of proposal.vetoes ?? []) lines.push(`- ${v}`);\n lines.push('');\n }\n if ((proposal.warnings ?? []).length > 0) {\n lines.push('## Warnings');\n for (const w of proposal.warnings ?? []) lines.push(`- (${w.severity}) ${w.phase}: ${w.message}`);\n lines.push('');\n }\n if ((proposal.mismatchedIntegrations ?? []).length > 0) {\n lines.push('## Mismatched (Planner asked for tools you don\\'t have)');\n for (const m of proposal.mismatchedIntegrations ?? []) {\n lines.push(`- ${m.integrationId} (${m.reason}) — ${m.suggestion ?? ''}`);\n }\n lines.push('');\n }\n return lines.join('\\n');\n}\n\nfunction printProposalSummary(proposal: SkillDesignProposal): void {\n const out = process.stdout;\n out.write('\\n' + c.bold(`Skill Planner proposal: ${proposal.skillName}`) + '\\n');\n out.write(c.hint(` Tier: ${proposal.recommendedTier} · ${proposal.integrations.length} integration(s)\\n\\n`));\n if (proposal.valueRationale) {\n out.write(` ${c.bold('Why')}\\n ${proposal.valueRationale.slice(0, 600)}\\n\\n`);\n }\n out.write(` ${c.bold('Integrations')}\\n`);\n for (const i of proposal.integrations.slice(0, 12)) {\n out.write(` - ${i.name} ${c.hint('(' + i.invocationHint.kind + ', confidence ' + (i.confidence ?? '?') + ')')}\\n`);\n }\n out.write('\\n');\n}\n","/**\n * Brief assembly — Phase 5 Chunk 4. Per docs/development/SKILL_CREATOR.md §7.\n *\n * The brief is the JSON payload we send as the user message to a headless\n * skill-creator invocation. It's mostly the Planner's accepted proposal\n * verbatim — skill-creator's job is to author the SKILL.md package\n * matching the brief, not to re-reason about the user's environment.\n *\n * Cap: ≤60 KB total. Truncation priority:\n * 1. webResearch.recentInnovations\n * 2. integration citations\n * 3. webResearch.bestPracticePatterns sources\n * 4. userNarrativeEdits (last — user authorship is precious)\n */\nimport type { ActionItem, ConversationSummary } from '../../storage/types.js';\nimport type { ResolvedSkillCapabilityProfile } from './planner-review.js';\nimport type { WikiPlaybook, WikiTemplate, WikiDomainKnowledge, WikiPastLesson } from './recon/wiki-recon.js';\n\nconst MAX_BRIEF_BYTES = 60 * 1024;\n\nexport interface InstallTarget {\n scope: 'project' | 'user';\n path: string;\n skillName: string;\n}\n\n/**\n * Wiki knowledge bundle that travels in the brief with FULL bodies for\n * playbooks + templates so skill-creator can embed them verbatim into the\n * emitted SKILL.md. Phase 5.1 addition — without this skill-creator has\n * no way to bake the user's operating procedures into the skill.\n */\nexport interface WikiKnowledgeBundle {\n playbooks: WikiPlaybook[]; // FULL body each\n templates: WikiTemplate[]; // FULL body each\n domainKnowledge: WikiDomainKnowledge[]; // summary + excerpt only\n pastLessons: WikiPastLesson[];\n}\n\nexport interface SkillCreatorBrief {\n action: {\n id: string;\n title: string;\n description: string;\n priority: string;\n linkedDiscussion?: { id: string; summary: ConversationSummary };\n };\n skillPlannerProposal: ResolvedSkillCapabilityProfile['proposal'];\n /**\n * The user's operating knowledge from the wiki — playbooks + templates with\n * FULL bodies, domain knowledge as summaries, past lessons as actionable\n * rules. Skill-creator must embed playbook + template bodies verbatim;\n * see `constraints.wikiKnowledgeIsBakeIn`.\n */\n wikiKnowledge: WikiKnowledgeBundle;\n capabilityProfile: {\n grantedTools: string[];\n acceptedTier: ResolvedSkillCapabilityProfile['acceptedTier'];\n acceptedIntegrationIds: string[];\n acceptedStakeholderNames: string[];\n userNarrativeEdits?: string;\n detectedEnvironment: {\n platform: string;\n mcpServers: string[];\n cliTools: string[];\n envVars: string[];\n chrome: boolean;\n computerUseAvailable: boolean;\n };\n };\n installTarget: InstallTarget;\n constraints: typeof DEFAULT_CONSTRAINTS;\n}\n\nexport const DEFAULT_CONSTRAINTS = {\n frontmatter: 'Claude Code spec; see when_to_use, allowed-tools, model, etc.',\n bodyMustExecute:\n 'Encode the proposed workflow as ordered, executable steps using ONLY the tools in allowed-tools. ' +\n 'Do not produce a how-to guide — produce an execution system prompt.',\n invocationHintsAreLoadBearing:\n 'For EACH integration in skillPlannerProposal.integrations[], the emitted SKILL.md body MUST include the literal ' +\n 'invocationHint.snippet inside a code block. You MAY surround the snippet with context, validation logic, and ' +\n 'follow-up steps — but you MUST NOT paraphrase, abbreviate, or rewrite the snippet. The snippet is the contract.',\n wikiKnowledgeIsBakeIn:\n 'The wikiKnowledge field carries the USER\\'S OPERATING BRAIN — playbooks they have run multiple times, ' +\n 'templates they have already proven, domain knowledge only they have, and past lessons they have paid for. ' +\n 'These are NOT background hints. Specifically: (1) For each entry in wikiKnowledge.playbooks[], the SKILL.md ' +\n 'body must EXECUTE the playbook step-for-step — quote the playbook\\'s numbered steps VERBATIM into the body. ' +\n 'Do not paraphrase, do not invent alternative workflows, do not soft-reference. The user knows how they want ' +\n 'this done. (2) For each entry in wikiKnowledge.templates[], any output-producing step must use the template ' +\n 'body VERBATIM as the output shape (substitute placeholders for runtime values only). (3) For each entry in ' +\n 'wikiKnowledge.domainKnowledge[], weave the relevant fact into the body where it informs a decision — inline ' +\n 'the content, do not just link the page. (4) For each entry in wikiKnowledge.pastLessons[], the lesson\\'s ' +\n '`actionable` field must appear in the body as either a MUST NOT line or a preflight check. Cite every wiki ' +\n 'entry by slug in the SKILL.md\\'s preamble or provenance section so the reader can trace back.',\n fallbacks: 'For each integration with fallbackIfMissing set, emit explicit fallback behavior in the body.',\n stakeholderHandoffs:\n 'For each stakeholderTouchpoint where produces=artifact, write the artifact to artifactPath using ' +\n 'artifactTemplate verbatim (leave bracketed placeholders unresolved if unknowable at build time). ' +\n 'For produces=send, use sendVia exactly as the mcp tool entry.',\n bodySize: '≤500 lines for SKILL.md; everything else in references/ or scripts/.',\n vetoesAreMandatory:\n 'For each entry in skillPlannerProposal.vetoes[], emit a MUST NOT line in the SKILL.md body matching the veto exactly.',\n provenanceFooter:\n 'Append: > Generated by aab actions solve from action <short-id>; planner tier <tier>; <N> integrations.',\n};\n\nexport interface BuildBriefOptions {\n action: ActionItem;\n capabilityProfile: ResolvedSkillCapabilityProfile;\n installTarget: InstallTarget;\n discussionSummary?: ConversationSummary;\n}\n\nexport function buildSkillCreatorBrief(opts: BuildBriefOptions): {\n brief: SkillCreatorBrief;\n bytes: number;\n truncated: string[];\n} {\n const cp = opts.capabilityProfile;\n const truncated: string[] = [];\n\n const brief: SkillCreatorBrief = {\n action: {\n id: opts.action.id,\n title: opts.action.title,\n description: opts.action.description,\n priority: opts.action.priority,\n ...(opts.action.discussionId && opts.discussionSummary\n ? { linkedDiscussion: { id: opts.action.discussionId, summary: opts.discussionSummary } }\n : {}),\n },\n skillPlannerProposal: cp.proposal,\n wikiKnowledge: {\n // FULL bodies — these are the load-bearing entries skill-creator must\n // embed verbatim into the SKILL.md body. Truncation order below\n // preserves these last, after dropping web innovations, citations,\n // relevantPages excerpts, and pastDecisions outcomes.\n playbooks: cp.recon.wiki.playbooks,\n templates: cp.recon.wiki.templates,\n domainKnowledge: cp.recon.wiki.domainKnowledge,\n pastLessons: cp.recon.wiki.pastLessons,\n },\n capabilityProfile: {\n grantedTools: cp.grantedTools,\n acceptedTier: cp.acceptedTier,\n acceptedIntegrationIds: cp.acceptedIntegrationIds,\n acceptedStakeholderNames: cp.acceptedStakeholderNames,\n userNarrativeEdits: cp.userNarrativeEdits,\n detectedEnvironment: {\n platform: cp.recon.pc.platform,\n mcpServers: cp.recon.pc.mcpServers.map((m) => m.name),\n cliTools: cp.recon.pc.cliTools.map((t) => t.name),\n envVars: cp.recon.pc.envVars,\n chrome: cp.recon.pc.chrome,\n computerUseAvailable: cp.recon.pc.computerUseAvailable,\n },\n },\n installTarget: opts.installTarget,\n constraints: DEFAULT_CONSTRAINTS,\n };\n\n let bytes = Buffer.byteLength(JSON.stringify(brief), 'utf8');\n // Truncation priority order — drop things in order of least load-bearing\n // first. Phase 5.1: wikiKnowledge.playbooks + templates are preserved to\n // the very end because they're THE most load-bearing content (the user's\n // operating brain). Order: web innovations → integration citations →\n // best-practice sources → web app surfaces details → narrative edits →\n // domainKnowledge excerpts → past lessons → templates → playbooks.\n if (bytes > MAX_BRIEF_BYTES) {\n (brief as unknown as { skillPlannerProposal: { recentInnovations?: unknown[] } }).skillPlannerProposal.recentInnovations = [];\n bytes = Buffer.byteLength(JSON.stringify(brief), 'utf8');\n truncated.push('webResearch.recentInnovations');\n }\n if (bytes > MAX_BRIEF_BYTES) {\n for (const i of brief.skillPlannerProposal.integrations) {\n (i as unknown as { citations?: unknown[] }).citations = [];\n }\n bytes = Buffer.byteLength(JSON.stringify(brief), 'utf8');\n truncated.push('integration.citations');\n }\n if (bytes > MAX_BRIEF_BYTES && brief.capabilityProfile.userNarrativeEdits) {\n brief.capabilityProfile.userNarrativeEdits = brief.capabilityProfile.userNarrativeEdits.slice(0, 800) + '…';\n bytes = Buffer.byteLength(JSON.stringify(brief), 'utf8');\n truncated.push('userNarrativeEdits (truncated to first 800 chars)');\n }\n if (bytes > MAX_BRIEF_BYTES) {\n // drop the domainKnowledge excerpts (keep summaries)\n brief.wikiKnowledge.domainKnowledge = brief.wikiKnowledge.domainKnowledge.map((d) => ({\n slug: d.slug, title: d.title, summary: d.summary,\n }));\n bytes = Buffer.byteLength(JSON.stringify(brief), 'utf8');\n truncated.push('wikiKnowledge.domainKnowledge.excerpt');\n }\n if (bytes > MAX_BRIEF_BYTES) {\n // truncate template bodies to first 1500 chars (preserve playbooks fully)\n brief.wikiKnowledge.templates = brief.wikiKnowledge.templates.map((t) => ({\n ...t, body: t.body.length > 1500 ? t.body.slice(0, 1500) + '…' : t.body,\n }));\n bytes = Buffer.byteLength(JSON.stringify(brief), 'utf8');\n truncated.push('wikiKnowledge.templates.body (truncated to 1500 chars each)');\n }\n if (bytes > MAX_BRIEF_BYTES) {\n // last resort — truncate playbook bodies. The user will see this in the\n // truncated[] return value so they know which playbook got cut.\n brief.wikiKnowledge.playbooks = brief.wikiKnowledge.playbooks.map((p) => ({\n ...p, body: p.body.length > 3000 ? p.body.slice(0, 3000) + '… [body truncated by brief assembler]' : p.body,\n }));\n bytes = Buffer.byteLength(JSON.stringify(brief), 'utf8');\n truncated.push('wikiKnowledge.playbooks.body (truncated to 3000 chars each)');\n }\n return { brief, bytes, truncated };\n}\n\n/**\n * Render the brief into the wire-shape user message that goes to the\n * `claude -p` call (skill-creator system prompt is added via\n * --append-system-prompt-file). Includes the \"print SKILL_CREATOR_DONE\n * when finished\" sentinel so we can robustly detect completion in\n * `--output-format stream-json` output.\n */\nexport function renderUserMessage(brief: SkillCreatorBrief): string {\n return [\n 'Author a Claude Code skill matching this brief. Write all files into the current working directory.',\n '',\n 'Required output: an installable skill package with SKILL.md at the root + any supporting files',\n `under references/ or scripts/. The skill name MUST be \"${brief.installTarget.skillName}\".`,\n '',\n 'When done, print a single line on its own: SKILL_CREATOR_DONE: ' + brief.installTarget.skillName,\n '',\n 'Brief:',\n '```json',\n JSON.stringify(brief, null, 2),\n '```',\n ].join('\\n');\n}\n","/**\n * skill-creator invocation — Phase 5 Chunk 4. Per docs/development/SKILL_CREATOR.md §8.\n *\n * Headless spawn pattern:\n * claude -p \"<user msg>\" --append-system-prompt-file <skill-creator/SKILL.md>\n * --allowedTools Write,Edit,Read,Glob,Bash\n * --output-format stream-json\n * --cwd <runId workspace tempdir>\n *\n * We stream tool-use events back to the caller for live progress, and at\n * end-of-run inventory the workspace for the emitted SKILL.md package.\n */\nimport { mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport { runClaude, type ClaudeStreamEvent } from '../../llm/claude-code-runner.js';\nimport { ModelError } from '../errors.js';\nimport { logger } from '../logger.js';\nimport { resolveSkillCreator } from './resolve-skill-creator.js';\nimport { renderUserMessage, type SkillCreatorBrief } from './build-brief.js';\nimport { UserError } from '../errors.js';\n\nexport interface InvokeSkillCreatorOptions {\n brief: SkillCreatorBrief;\n workspaceDir: string;\n /** Absolute path to skill-creator's SKILL.md — pre-resolved by caller. */\n skillCreatorPath?: string;\n /** Default `sonnet` (skill-creator is good at authoring at sonnet quality). */\n modelOverride?: string;\n /** Default 20 min. */\n timeoutMs?: number;\n /** Project root to walk for skill-creator if not pre-resolved. */\n projectRoot?: string;\n /** Streaming event sink. */\n onEvent?: (event: ClaudeStreamEvent) => void;\n /** Telemetry sink — receives one JSONL-shaped object per stream event. */\n onTelemetry?: (line: Record<string, unknown>) => void;\n /** External abort signal — kills the spawn. */\n signal?: AbortSignal;\n}\n\nexport interface EmittedFile {\n /** Relative path within the workspace, POSIX-style. */\n path: string;\n content: string;\n sizeBytes: number;\n}\n\nexport interface InvokeSkillCreatorResult {\n files: EmittedFile[];\n /** True if SKILL.md was emitted. */\n hasSkillMd: boolean;\n /** True if `SKILL_CREATOR_DONE:` sentinel was printed in stdout. */\n sentinelObserved: boolean;\n costUsd: number;\n durationMs: number;\n /** Tool-call count (best-effort — counted from stream events). */\n toolCallCount: number;\n /** Raw stdout for debug. */\n stdoutTail: string;\n}\n\nexport async function invokeSkillCreator(opts: InvokeSkillCreatorOptions): Promise<InvokeSkillCreatorResult> {\n const skillCreatorPath = opts.skillCreatorPath ?? resolveSkillCreator({ projectRoot: opts.projectRoot })?.path;\n if (!skillCreatorPath) {\n throw new UserError(\n 'skill-creator skill not installed',\n 'Run `aab init --install-skill-creator` for installation instructions, or `/plugin install skill-creator@claude-plugins-official` inside Claude Code.',\n );\n }\n\n // Ensure the per-run workspace exists.\n mkdirSync(opts.workspaceDir, { recursive: true });\n\n const userMessage = renderUserMessage(opts.brief);\n let toolCallCount = 0;\n let sentinelObserved = false;\n let stdoutSeen = '';\n\n const onEvent = (evt: ClaudeStreamEvent): void => {\n opts.onTelemetry?.(evt as unknown as Record<string, unknown>);\n if (evt.type === 'assistant' && evt.message?.content) {\n for (const part of evt.message.content) {\n if (part.type === 'tool_use') toolCallCount++;\n if (part.type === 'text' && part.text) {\n stdoutSeen += part.text + '\\n';\n if (part.text.includes(`SKILL_CREATOR_DONE: ${opts.brief.installTarget.skillName}`)) {\n sentinelObserved = true;\n }\n }\n }\n }\n if (evt.type === 'result' && typeof evt.result === 'string') {\n stdoutSeen += evt.result + '\\n';\n if (evt.result.includes(`SKILL_CREATOR_DONE: ${opts.brief.installTarget.skillName}`)) {\n sentinelObserved = true;\n }\n }\n opts.onEvent?.(evt);\n };\n\n let costUsd = 0;\n let durationMs = 0;\n try {\n const result = await runClaude({\n prompt: userMessage,\n appendSystemPromptFile: skillCreatorPath,\n allowedTools: ['Write', 'Edit', 'Read', 'Glob', 'Bash'],\n cwd: opts.workspaceDir,\n outputFormat: 'stream-json',\n model: opts.modelOverride ?? 'sonnet',\n timeoutMs: opts.timeoutMs ?? 20 * 60_000,\n signal: opts.signal,\n onEvent,\n });\n costUsd = result.json?.cost_usd ?? 0;\n durationMs = result.durationMs;\n if (typeof result.json?.result === 'string') {\n stdoutSeen += result.json.result + '\\n';\n if (result.json.result.includes(`SKILL_CREATOR_DONE: ${opts.brief.installTarget.skillName}`)) {\n sentinelObserved = true;\n }\n }\n } catch (err) {\n throw new ModelError(\n `skill-creator invocation failed: ${err instanceof Error ? err.message : String(err)}`,\n 'Check that --append-system-prompt-file is supported by your `claude` CLI version. Re-run with --debug.',\n );\n }\n\n // Inventory the workspace.\n const files = walkWorkspace(opts.workspaceDir);\n const hasSkillMd = files.some((f) => f.path === 'SKILL.md' || /^SKILL\\.md$/i.test(f.path));\n\n logger.debug('[skill-creator] run done', {\n files: files.length,\n hasSkillMd,\n sentinelObserved,\n toolCallCount,\n costUsd,\n durationMs,\n });\n\n return {\n files,\n hasSkillMd,\n sentinelObserved,\n costUsd,\n durationMs,\n toolCallCount,\n stdoutTail: stdoutSeen.slice(-2000),\n };\n}\n\n/**\n * Recursively walk the workspace dir and collect every regular file as an\n * EmittedFile. Skips hidden dirs and node_modules to stay sane on\n * accidental nesting.\n */\nexport function walkWorkspace(root: string): EmittedFile[] {\n const out: EmittedFile[] = [];\n function walk(dir: string): void {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return;\n }\n for (const e of entries) {\n if (e.startsWith('.') || e === 'node_modules') continue;\n const full = join(dir, e);\n let st: ReturnType<typeof statSync>;\n try {\n st = statSync(full);\n } catch {\n continue;\n }\n if (st.isDirectory()) walk(full);\n else if (st.isFile()) {\n try {\n const content = readFileSync(full, 'utf8');\n const relPath = relative(root, full).split(/[\\\\/]/).join('/');\n out.push({ path: relPath, content, sizeBytes: st.size });\n } catch {\n // Binary or unreadable — skip silently.\n }\n }\n }\n }\n walk(root);\n return out;\n}\n\n/**\n * Stub mode for tests + offline smoke runs — writes a canned SKILL.md\n * matching the brief into the workspace and reports as if skill-creator\n * ran successfully. Useful when validating the orchestrator without\n * burning real tokens.\n */\nexport function stubSkillCreatorRun(opts: InvokeSkillCreatorOptions): InvokeSkillCreatorResult {\n mkdirSync(opts.workspaceDir, { recursive: true });\n const skillMd = stubSkillMd(opts.brief);\n writeFileSync(join(opts.workspaceDir, 'SKILL.md'), skillMd);\n const files = walkWorkspace(opts.workspaceDir);\n return {\n files,\n hasSkillMd: true,\n sentinelObserved: true,\n costUsd: 0,\n durationMs: 1,\n toolCallCount: 1,\n stdoutTail: `SKILL_CREATOR_DONE: ${opts.brief.installTarget.skillName}`,\n };\n}\n\nfunction stubSkillMd(brief: SkillCreatorBrief): string {\n const tools = brief.capabilityProfile.grantedTools;\n const proposal = brief.skillPlannerProposal;\n return [\n '---',\n `name: ${brief.installTarget.skillName}`,\n `description: ${proposal.triggerLanguage ?? proposal.skillSummary}`,\n 'allowed-tools:',\n ...tools.map((t) => ` - ${t}`),\n 'model: inherit',\n '---',\n '',\n `# ${proposal.skillName}`,\n '',\n proposal.skillSummary,\n '',\n '## Integrations',\n ...proposal.integrations.map(\n (i) => `- ${i.name} (${i.invocationHint.kind})${i.invocationHint.snippet ? '\\n ```\\n ' + i.invocationHint.snippet + '\\n ```' : ''}`,\n ),\n '',\n proposal.vetoes && proposal.vetoes.length > 0\n ? '## MUST NOT\\n' + proposal.vetoes.map((v) => `- ${v}`).join('\\n')\n : '',\n '',\n `> Generated by aab actions solve from action ${brief.action.id.slice(0, 8)}; planner tier ${brief.capabilityProfile.acceptedTier}; ${proposal.integrations.length} integrations.`,\n '',\n ].join('\\n');\n}\n","/**\n * Adapter pass — Phase 5 Chunk 4. Per docs/development/SKILL_CREATOR.md §9.\n *\n * Normalizes skill-creator's emitted SKILL.md frontmatter against the\n * current Claude Code spec. Defense-in-depth: skill-creator usually emits\n * good frontmatter, but bugs happen and the spec evolves. Steps:\n *\n * 1. Parse frontmatter (hand-rolled, matching `src/core/knowledge/page.ts`).\n * 2. Ensure required fields exist (name, description with \"Use when …\").\n * 3. Cap combined description + when_to_use ≤ 1,536 chars.\n * 4. Reconcile allowed-tools against the user-accepted grantedTools —\n * add any granted-but-omitted body-referenced tool, remove any\n * not-granted skill-creator-leaked tool.\n * 5. Fold sage-council-style invented keys into body sections.\n * 6. Default model: inherit when skill-creator didn't pick one.\n * 7. Reserved-name refusal.\n * 8. Produce a diff (skill-creator emit vs adapter result) for the dry-run preview.\n */\nimport { RESERVED_SKILL_NAMES } from '../parsing/llm-response-schemas.js';\nimport { UserError } from '../errors.js';\nimport type { EmittedFile } from './invoke-skill-creator.js';\n\nexport interface AdapterOptions {\n files: EmittedFile[];\n /** The deterministic `grantedTools` projection from §6.7. */\n grantedTools: string[];\n /** Required: the user-confirmed skill name. */\n skillName: string;\n /** Optional descriptive context for trigger fallback. */\n actionTitle?: string;\n actionDescription?: string;\n}\n\nexport interface AdapterResult {\n /** Mutated files array — caller writes these back to the workspace. */\n files: EmittedFile[];\n /** Human-readable diff lines (skill-creator emit → adapter result). */\n diff: string[];\n /** True if the adapter had to inject the missing SKILL.md scaffold. */\n scaffoldedSkillMd: boolean;\n warnings: string[];\n}\n\nconst SKILL_MD_FILENAMES = new Set(['SKILL.md', 'skill.md']);\n\nconst SAGE_INVENTED_KEYS = ['trigger_queries', 'dependencies', 'file_types', 'safety_mode', 'estimated_tokens', 'estimated_time_minutes', 'examples', 'notes'];\n\nexport function adaptSkillPackage(opts: AdapterOptions): AdapterResult {\n if (RESERVED_SKILL_NAMES.has(opts.skillName)) {\n throw new UserError(\n `Skill name \"${opts.skillName}\" is reserved by Anthropic`,\n 'Pass --skill-name <other-name> to override the auto-derived slug.',\n );\n }\n\n const diff: string[] = [];\n const warnings: string[] = [];\n\n // Locate (or scaffold) SKILL.md.\n let skillMdIdx = opts.files.findIndex((f) => SKILL_MD_FILENAMES.has(f.path));\n let scaffolded = false;\n if (skillMdIdx === -1) {\n scaffolded = true;\n const scaffold = scaffoldSkillMd(opts.skillName, opts.grantedTools, opts.actionTitle, opts.actionDescription);\n opts.files.push({ path: 'SKILL.md', content: scaffold, sizeBytes: scaffold.length });\n skillMdIdx = opts.files.length - 1;\n diff.push('+ SKILL.md (scaffolded by adapter — skill-creator did not emit one)');\n }\n\n const skillMd = opts.files[skillMdIdx]!;\n const parsed = parseFrontmatter(skillMd.content);\n if (!parsed) {\n // No frontmatter at all — wrap the existing body.\n const wrapped = scaffoldSkillMd(opts.skillName, opts.grantedTools, opts.actionTitle, opts.actionDescription) +\n '\\n\\n' + skillMd.content;\n skillMd.content = wrapped;\n skillMd.sizeBytes = wrapped.length;\n diff.push('+ Frontmatter scaffold (body had none)');\n return { files: opts.files, diff, scaffoldedSkillMd: scaffolded || true, warnings };\n }\n\n const before = JSON.stringify(parsed.frontmatter);\n\n // (1) name\n if (!parsed.frontmatter.name) {\n parsed.frontmatter.name = opts.skillName;\n diff.push(`+ frontmatter name: ${opts.skillName}`);\n } else if (parsed.frontmatter.name !== opts.skillName) {\n diff.push(`~ frontmatter name: ${parsed.frontmatter.name} → ${opts.skillName}`);\n parsed.frontmatter.name = opts.skillName;\n }\n\n // (2) description — must include \"Use when …\" trigger language\n const description = String(parsed.frontmatter.description ?? '');\n if (!description.trim()) {\n parsed.frontmatter.description = `Use when ${opts.actionTitle ?? opts.skillName}. ${opts.actionDescription ?? ''}`.trim();\n diff.push('+ frontmatter description (was missing)');\n } else if (!/^use when /i.test(description) && !/use when/i.test(description.slice(0, 80))) {\n parsed.frontmatter.description = `Use when ${opts.actionTitle ?? opts.skillName}. ${description}`;\n diff.push('~ frontmatter description: prepended \"Use when …\"');\n }\n\n // (3) cap description + when_to_use ≤ 1,536 chars combined\n const combinedLen = String(parsed.frontmatter.description ?? '').length + String(parsed.frontmatter.when_to_use ?? '').length;\n if (combinedLen > 1536) {\n const wtu = String(parsed.frontmatter.when_to_use ?? '');\n const trimmed = wtu.slice(0, Math.max(0, 1536 - String(parsed.frontmatter.description ?? '').length - 24)) + ' [trimmed]';\n parsed.frontmatter.when_to_use = trimmed;\n diff.push(`~ frontmatter when_to_use: trimmed to fit 1536-char combined cap`);\n }\n\n // (4) allowed-tools reconciliation\n const existingTools = coerceTools(parsed.frontmatter['allowed-tools']);\n const granted = new Set(opts.grantedTools);\n const reconciled = Array.from(granted).sort();\n const removed = existingTools.filter((t) => !granted.has(t));\n const added = reconciled.filter((t) => !existingTools.includes(t));\n if (removed.length > 0) diff.push(`- allowed-tools: ${removed.join(', ')}`);\n if (added.length > 0) diff.push(`+ allowed-tools: ${added.join(', ')}`);\n parsed.frontmatter['allowed-tools'] = reconciled;\n\n // (5) fold sage-council-style invented keys into the body\n const invented: Record<string, unknown> = {};\n for (const key of SAGE_INVENTED_KEYS) {\n if (key in parsed.frontmatter) {\n invented[key] = parsed.frontmatter[key];\n delete parsed.frontmatter[key];\n diff.push(`- frontmatter ${key} (folded into body)`);\n }\n }\n\n // (6) default model\n if (!parsed.frontmatter.model) {\n parsed.frontmatter.model = 'inherit';\n diff.push('+ frontmatter model: inherit');\n }\n\n // Re-emit the file.\n let newBody = parsed.body;\n if (Object.keys(invented).length > 0) {\n const inventedSection = [\n '',\n '<!-- folded by aab actions solve adapter — these keys are not in the current Claude Code spec -->',\n ...Object.entries(invented).map(([k, v]) => `- **${k}:** ${JSON.stringify(v)}`),\n '',\n ].join('\\n');\n newBody = inventedSection + newBody;\n }\n\n skillMd.content = serializeWithFrontmatter(parsed.frontmatter, newBody);\n skillMd.sizeBytes = skillMd.content.length;\n\n // (7) body-size warning\n const lineCount = newBody.split(/\\r?\\n/).length;\n if (lineCount > 500) {\n warnings.push(`SKILL.md body is ${lineCount} lines (> 500 target — consider moving content to references/).`);\n }\n\n // Diff completeness — no-op if frontmatter unchanged\n if (JSON.stringify(parsed.frontmatter) === before && diff.length === 0) {\n diff.push('(no changes)');\n }\n\n return { files: opts.files, diff, scaffoldedSkillMd: scaffolded, warnings };\n}\n\n// ---------- frontmatter parser (hand-rolled — minimal YAML) ----------\n\ninterface ParsedSkillMd {\n frontmatter: Record<string, unknown>;\n body: string;\n}\n\nconst FM_RE = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/;\n\nexport function parseFrontmatter(raw: string): ParsedSkillMd | null {\n const m = raw.match(FM_RE);\n if (!m) return null;\n const block = m[1] ?? '';\n const body = raw.slice(m[0].length);\n const fm: Record<string, unknown> = {};\n let i = 0;\n const lines = block.split(/\\r?\\n/);\n while (i < lines.length) {\n const line = lines[i]!;\n if (!line.trim() || line.trim().startsWith('#')) { i++; continue; }\n const kv = line.match(/^([A-Za-z0-9_-]+):\\s*(.*)$/);\n if (!kv) { i++; continue; }\n const key = kv[1]!;\n const rest = (kv[2] ?? '').trim();\n if (rest === '') {\n // block array or block scalar\n const block: string[] = [];\n i++;\n while (i < lines.length && /^\\s+-\\s/.test(lines[i] ?? '')) {\n block.push((lines[i] ?? '').replace(/^\\s+-\\s/, '').trim());\n i++;\n }\n if (block.length > 0) fm[key] = block;\n else {\n // multi-line scalar (block style with `|`)\n // Not commonly used here; leave as empty.\n fm[key] = '';\n }\n continue;\n }\n if (rest.startsWith('[') && rest.endsWith(']')) {\n // inline array\n fm[key] = rest.slice(1, -1).split(',').map((s) => stripQuotes(s.trim())).filter(Boolean);\n } else {\n fm[key] = stripQuotes(rest);\n }\n i++;\n }\n return { frontmatter: fm, body };\n}\n\nfunction stripQuotes(value: string): string {\n if ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n return value.slice(1, -1);\n }\n return value;\n}\n\nfunction serializeWithFrontmatter(fm: Record<string, unknown>, body: string): string {\n const lines: string[] = ['---'];\n const FIELD_ORDER = ['name', 'description', 'when_to_use', 'allowed-tools', 'paths', 'model', 'disable-model-invocation', 'version'];\n const seen = new Set<string>();\n for (const key of FIELD_ORDER) {\n if (!(key in fm)) continue;\n emit(key, fm[key], lines);\n seen.add(key);\n }\n for (const [key, value] of Object.entries(fm)) {\n if (seen.has(key)) continue;\n emit(key, value, lines);\n }\n lines.push('---');\n return lines.join('\\n') + '\\n' + body;\n}\n\nfunction emit(key: string, value: unknown, out: string[]): void {\n if (value === undefined || value === null) return;\n if (Array.isArray(value)) {\n out.push(`${key}:`);\n for (const v of value) out.push(` - ${String(v)}`);\n return;\n }\n if (typeof value === 'boolean' || typeof value === 'number') {\n out.push(`${key}: ${value}`);\n return;\n }\n const s = String(value);\n if (s.includes('\\n')) {\n out.push(`${key}: |`);\n for (const line of s.split('\\n')) out.push(` ${line}`);\n return;\n }\n out.push(`${key}: ${s}`);\n}\n\nfunction coerceTools(value: unknown): string[] {\n if (Array.isArray(value)) return value.map((v) => String(v).trim()).filter(Boolean);\n if (typeof value === 'string') return value.split(',').map((s) => s.trim()).filter(Boolean);\n return [];\n}\n\nfunction scaffoldSkillMd(name: string, tools: string[], actionTitle?: string, actionDescription?: string): string {\n const lines = [\n '---',\n `name: ${name}`,\n `description: Use when ${actionTitle ?? name}. ${actionDescription ?? ''}`.trim(),\n 'allowed-tools:',\n ...tools.map((t) => ` - ${t}`),\n 'model: inherit',\n '---',\n '',\n `# ${name}`,\n '',\n 'Workflow:',\n '',\n '<!-- Adapter scaffold — skill-creator did not produce SKILL.md. Add body manually. -->',\n '',\n ];\n return lines.join('\\n');\n}\n","/**\n * Install — Phase 5 Chunk 4. Per docs/development/SKILL_CREATOR.md §10.\n *\n * cp -r workspace/ → .claude/skills/<name>/ (project scope, default)\n * cp -r workspace/ → ~/.claude/skills/<name>/ (--scope user)\n *\n * Conflict handling: overwrite (archives existing to .snapshots/skills/<name>-<ts>/),\n * rename (<name>-2, <name>-3, ...), abort. Sidecar `installed-at.json`\n * lives in the workspace (per T3.9 — NOT inside the installed skill dir to\n * avoid Claude Code loading it as a support file).\n */\nimport { cpSync, existsSync, mkdirSync, readdirSync, renameSync, rmSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { UserError } from '../errors.js';\nimport { askConfirm, askSelect } from '../../ui/prompts.js';\nimport type { EmittedFile } from './invoke-skill-creator.js';\n\nexport type ConflictMode = 'overwrite' | 'rename' | 'abort';\n\nexport interface InstallOptions {\n files: EmittedFile[];\n /** Final skill name (kebab-case) — used for both dir name and frontmatter validation. */\n skillName: string;\n /** Default 'project'. */\n scope?: 'project' | 'user';\n /** Project root (for project-scope installs). Defaults to process.cwd(). */\n projectRoot?: string;\n /** Auto-resolve conflicts (--yes mode). */\n yes?: boolean;\n /** Workspace root containing skill-runs/<runId>/installed-at.json sidecar. */\n workspaceRoot?: string;\n /** Run id (used in sidecar). */\n runId?: string;\n /** Action item id (used in sidecar). */\n actionItemId?: string;\n /** Cap on `.snapshots/skills/<name>-*` entries. */\n snapshotRetention?: number;\n}\n\nexport interface InstallResult {\n installPath: string;\n conflictAction?: ConflictMode;\n archivedTo?: string;\n filesWritten: number;\n}\n\nexport async function installSkillPackage(opts: InstallOptions): Promise<InstallResult> {\n const scope = opts.scope ?? 'project';\n const projectRoot = opts.projectRoot ?? process.cwd();\n let installPath = scope === 'user'\n ? join(homedir(), '.claude', 'skills', opts.skillName)\n : join(projectRoot, '.claude', 'skills', opts.skillName);\n\n let conflictAction: ConflictMode | undefined;\n let archivedTo: string | undefined;\n\n if (existsSync(installPath)) {\n conflictAction = opts.yes ? 'overwrite' : await askConflictMode(installPath);\n if (conflictAction === 'abort') {\n throw new UserError(`Install aborted — ${installPath} already exists.`);\n }\n if (conflictAction === 'rename') {\n installPath = uniqueRename(installPath);\n } else {\n // overwrite — archive first\n archivedTo = archiveExisting(installPath, opts.snapshotRetention ?? 5);\n rmSync(installPath, { recursive: true, force: true });\n }\n }\n\n // Write each file.\n mkdirSync(installPath, { recursive: true });\n let filesWritten = 0;\n for (const f of opts.files) {\n const target = join(installPath, ...f.path.split('/'));\n mkdirSync(dirname(target), { recursive: true });\n writeFileSync(target, f.content, 'utf8');\n filesWritten++;\n }\n\n // Sidecar — lives in the workspace, not in the installed skill dir.\n if (opts.workspaceRoot && opts.runId) {\n const sidecarDir = join(opts.workspaceRoot, 'skill-runs', opts.runId);\n mkdirSync(sidecarDir, { recursive: true });\n writeFileSync(\n join(sidecarDir, 'installed-at.json'),\n JSON.stringify(\n {\n runId: opts.runId,\n actionItemId: opts.actionItemId,\n skillName: opts.skillName,\n installPath,\n installedAt: new Date().toISOString(),\n generatedBy: 'aab actions solve',\n },\n null,\n 2,\n ),\n 'utf8',\n );\n }\n\n return { installPath, conflictAction, archivedTo, filesWritten };\n}\n\nasync function askConflictMode(path: string): Promise<ConflictMode> {\n const proceed = await askConfirm(`${path} already exists. Overwrite (archives existing)?`, false);\n if (proceed) return 'overwrite';\n const next = await askSelect<ConflictMode>(\n 'Choose alternative',\n [\n { name: 'rename', message: 'Install under a renamed slug (<name>-2)' },\n { name: 'abort', message: 'Abort the install' },\n ],\n { initial: 'rename' },\n );\n return next;\n}\n\nfunction uniqueRename(installPath: string): string {\n let n = 2;\n let candidate = `${installPath}-${n}`;\n while (existsSync(candidate)) {\n n++;\n candidate = `${installPath}-${n}`;\n }\n return candidate;\n}\n\nfunction archiveExisting(installPath: string, retention: number): string {\n const parentDir = dirname(installPath);\n const skillsDirName = installPath.split(/[\\\\/]/).pop()!;\n const snapshotsDir = join(parentDir, '.snapshots', 'skills');\n mkdirSync(snapshotsDir, { recursive: true });\n const ts = new Date().toISOString().replace(/[:.]/g, '-');\n const target = join(snapshotsDir, `${skillsDirName}-${ts}`);\n // Use rename if same volume; cp + rm as fallback.\n try {\n renameSync(installPath, target);\n } catch {\n cpSync(installPath, target, { recursive: true });\n rmSync(installPath, { recursive: true, force: true });\n }\n // Retention rotation — keep newest N.\n pruneSnapshots(snapshotsDir, skillsDirName, retention);\n return target;\n}\n\nfunction pruneSnapshots(snapshotsDir: string, namePrefix: string, retention: number): void {\n if (!existsSync(snapshotsDir)) return;\n try {\n const all = readdirSync(snapshotsDir).filter((n) => n.startsWith(namePrefix + '-')).sort();\n while (all.length > retention) {\n const oldest = all.shift()!;\n try {\n rmSync(join(snapshotsDir, oldest), { recursive: true, force: true });\n } catch {\n // ignore\n }\n }\n } catch {\n // ignore\n }\n}\n","/**\n * Persistence — Phase 5 Chunk 4. Per docs/development/SKILL_CREATOR.md §11.\n *\n * Writes a `SkillGenerationRun` JSON (with the full Planner proposal +\n * capability profile embedded in metadata) under\n * `~/.aabcli/<ws>/skill-runs/<actionItemId>/<runId>.json`, then updates\n * `ActionItem.linkedSkill` + `skillRunHistory[]`.\n *\n * The workspace tempdir (containing skill-creator's emitted SKILL.md\n * package) is preserved when `preserveWorkspaceOnSuccess: true` or always\n * on failure for post-mortem.\n */\nimport { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type {\n ActionItem,\n SkillGenerationRun,\n StorageService,\n} from '../../storage/types.js';\nimport { nowIso } from '../utils.js';\nimport { paths } from '../../storage/paths.js';\nimport type { ResolvedSkillCapabilityProfile } from './planner-review.js';\nimport type { EmittedFile } from './invoke-skill-creator.js';\n\nexport interface PersistRunOptions {\n storage: StorageService;\n workspaceRoot: string;\n action: ActionItem;\n runId: string;\n status: 'completed' | 'failed' | 'cancelled';\n startedAt: string;\n costUsd: number;\n cacheHitRate: number;\n durationMs: number;\n files: EmittedFile[];\n installPath?: string;\n capabilityProfile: ResolvedSkillCapabilityProfile;\n toolCallCount?: number;\n /** Default 5 (sage-council parity). */\n retainWorkspace?: boolean;\n workspaceDir?: string;\n /** Default: status === 'completed' ? 'in-progress' : action.status. */\n newActionStatus?: ActionItem['status'];\n}\n\nexport interface PersistRunResult {\n run: SkillGenerationRun;\n updatedAction: ActionItem;\n}\n\nexport async function persistSkillRun(opts: PersistRunOptions): Promise<PersistRunResult> {\n const cp = opts.capabilityProfile;\n const run: SkillGenerationRun = {\n id: opts.runId,\n actionItemId: opts.action.id,\n status: opts.status,\n startedAt: opts.startedAt,\n completedAt: nowIso(),\n costUsd: opts.costUsd,\n cacheHitRate: opts.cacheHitRate,\n durationMs: opts.durationMs,\n files: opts.files.map((f) => ({ path: f.path, content: f.content })),\n installPath: opts.installPath,\n metadata: {\n skillName: cp.proposal.skillName,\n // Embed the FULL Planner proposal + capability profile + recon\n // summary in `metadata.confirmedCapabilityProfile` so future\n // `aab actions runs show <run-id>` invocations can re-render\n // everything without losing fidelity.\n confirmedCapabilityProfile: {\n generatedAt: cp.generatedAt,\n microSteps: [],\n requiredCapabilities: [],\n confirmedAvailableCapabilityIds: cp.acceptedIntegrationIds,\n unavailableCapabilityIds: cp.rejectedIntegrationIds,\n fallbackPlans: [],\n notes: cp.userNarrativeEdits,\n },\n agentEnvironment: {\n targetPlatform: 'claude-code',\n mcpServers: cp.recon.pc.mcpServers.map((m) => m.name),\n cliTools: cp.recon.pc.cliTools.map((t) => t.name),\n envVariables: cp.recon.pc.envVars,\n },\n decompositionSubtaskCount: cp.proposal.integrations.length,\n researchSourceCount: cp.recon.web.bestPracticePatterns.reduce((acc, p) => acc + p.sources.length, 0),\n singleLoopTurnCount: opts.toolCallCount,\n // Surface the Planner proposal as a stringified attachment for\n // downstream re-render. The schema's `passthrough()` accepts it.\n ...({ plannerProposal: cp.proposal } as Record<string, unknown>),\n },\n };\n\n await opts.storage.saveSkillRun(run);\n\n // Update the ActionItem.\n const newAction: ActionItem = {\n ...opts.action,\n status: opts.newActionStatus ?? (opts.status === 'completed' ? 'in-progress' : opts.action.status),\n linkedSkill: opts.installPath && opts.status === 'completed'\n ? {\n name: cp.proposal.skillName,\n runId: opts.runId,\n installedAt: nowIso(),\n installPath: opts.installPath,\n }\n : opts.action.linkedSkill,\n skillRunHistory: [opts.runId, ...(opts.action.skillRunHistory ?? [])].slice(0, 50),\n updatedAt: nowIso(),\n };\n await opts.storage.updateActionItem(newAction);\n\n // Write the proposal as a side-by-side .md artifact for `aab actions runs\n // export` convenience. Filename ends in .md (NOT .json) so loadSkillRuns'\n // *.json glob doesn't pick it up as another SkillGenerationRun.\n const runDir = join(paths(opts.workspaceRoot).skillRuns, opts.action.id);\n if (!existsSync(runDir)) mkdirSync(runDir, { recursive: true });\n writeFileSync(\n join(runDir, `${opts.runId}.proposal.md`),\n JSON.stringify(cp.proposal, null, 2),\n 'utf8',\n );\n\n // Workspace cleanup (default: preserve on failure, archive on success).\n if (opts.workspaceDir && existsSync(opts.workspaceDir)) {\n const preserve = opts.retainWorkspace ?? opts.status !== 'completed';\n if (!preserve) {\n try {\n rmSync(opts.workspaceDir, { recursive: true, force: true });\n } catch {\n // ignore\n }\n }\n }\n\n return { run, updatedAction: newAction };\n}\n","/**\n * `aab skills` — Phase 5 Chunk 5.\n *\n * aab skills list enumerate installed skills (project + user)\n * aab skills show <name> pretty-print SKILL.md + sidecar metadata\n * aab skills test <name> \"<input>\" round-trip the skill via `claude -p`\n * aab skills uninstall <name> archive to .snapshots/skills/<name>-<ts>/\n * aab skills restore <name> [--snapshot <ts>]\n */\nimport { Command } from 'commander';\nimport { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { closeContext, openContext } from './_context.js';\nimport { askConfirm, askSelect } from '../ui/prompts.js';\nimport { c } from '../ui/colors.js';\nimport { spinner } from '../ui/spinner.js';\nimport { UserError } from '../core/errors.js';\nimport { runClaude } from '../llm/claude-code-runner.js';\nimport { resolveSkill } from '../core/skill/resolve-skill-creator.js';\nimport type { ResolvedSkill } from '../core/skill/resolve-skill-creator.js';\n\nexport function registerSkillsCommand(program: Command): void {\n const s = program.command('skills').description('list, show, test, uninstall installed Claude Code skills');\n\n // ----- list -----\n s.command('list')\n .description('enumerate installed skills (project + user + plugin)')\n .action(async () => {\n const ctx = await openContext(s, { lock: false });\n try {\n const installed = listInstalledSkills(process.cwd());\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ skills: installed }, null, 2) + '\\n');\n return;\n }\n if (installed.length === 0) {\n process.stdout.write(c.hint(' (no installed skills)\\n'));\n return;\n }\n for (const sk of installed) {\n process.stdout.write(\n ` ${c.bold(sk.name)} ${c.hint('(' + sk.scope + (sk.version ? '; v' + sk.version : '') + ') · ' + sk.dir)}\\n`,\n );\n }\n } finally {\n await closeContext(ctx);\n }\n });\n\n // ----- show -----\n s.command('show <name>')\n .description('pretty-print SKILL.md + sidecar metadata')\n .action(async (name: string) => {\n const ctx = await openContext(s, { lock: false });\n try {\n const sk = resolveSkill(name, { projectRoot: process.cwd() });\n if (!sk) throw new UserError(`Skill \"${name}\" not found in any scope.`);\n const body = readFileSync(sk.path, 'utf8');\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ skill: sk, body }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`\\n${c.bold(sk.name)} ${c.hint('(' + sk.scope + (sk.version ? '; v' + sk.version : '') + ')')}\\n`);\n process.stdout.write(c.hint(' ' + sk.dir + '\\n\\n'));\n process.stdout.write(body + '\\n');\n } finally {\n await closeContext(ctx);\n }\n });\n\n // ----- test -----\n s.command('test <name> [input...]')\n .description('round-trip the skill via `claude -p` with --append-system-prompt-file')\n .option('--timeout <ms>', 'wall-clock timeout', '300000')\n .action(async (name: string, input: string[], opts: { timeout?: string }) => {\n const ctx = await openContext(s, { lock: false });\n try {\n const sk = resolveSkill(name, { projectRoot: process.cwd() });\n if (!sk) throw new UserError(`Skill \"${name}\" not found.`);\n const prompt = input.join(' ').trim() || `Activate the ${name} skill and walk through its workflow.`;\n const sp = spinner(`Testing skill ${c.bold(name)} via claude -p…`);\n sp.start();\n try {\n const result = await runClaude({\n prompt,\n appendSystemPromptFile: sk.path,\n timeoutMs: Number(opts.timeout) || 5 * 60_000,\n });\n sp.succeed('skill test ran');\n process.stdout.write('\\n' + (result.json?.result ?? result.stdout) + '\\n');\n } catch (err) {\n sp.fail('skill test failed');\n throw err;\n }\n } finally {\n await closeContext(ctx);\n }\n });\n\n // ----- uninstall -----\n s.command('uninstall <name>')\n .description('archive a skill to .snapshots/skills/<name>-<timestamp>/')\n .option('--yes', 'skip confirmation')\n .option('--scope <scope>', 'project | user (default: auto)', undefined)\n .action(async (name: string, opts: { yes?: boolean; scope?: string }) => {\n const ctx = await openContext(s);\n try {\n const sk = resolveSkill(name, { projectRoot: process.cwd() });\n if (!sk) throw new UserError(`Skill \"${name}\" not found.`);\n if (opts.scope && opts.scope !== sk.scope) {\n throw new UserError(`Skill \"${name}\" is installed at ${sk.scope} scope, not ${opts.scope}.`);\n }\n if (!opts.yes) {\n const ok = await askConfirm(`Archive ${sk.dir} to .snapshots/?`, false);\n if (!ok) return;\n }\n const archived = archiveSkill(sk);\n process.stdout.write(`${c.ok('✓')} archived to ${archived}\\n`);\n } finally {\n await closeContext(ctx);\n }\n });\n\n // ----- restore -----\n s.command('restore <name>')\n .description('restore a skill from .snapshots/skills/')\n .option('--snapshot <ts>', 'specific snapshot timestamp to restore (default: latest)')\n .action(async (name: string, opts: { snapshot?: string }) => {\n const ctx = await openContext(s);\n try {\n const candidates = findArchivedSkills(name, process.cwd());\n if (candidates.length === 0) throw new UserError(`No archived snapshots found for \"${name}\".`);\n let chosen = candidates[candidates.length - 1]!;\n if (opts.snapshot) {\n const match = candidates.find((c) => c.includes(opts.snapshot!));\n if (!match) throw new UserError(`No snapshot matching \"${opts.snapshot}\".`);\n chosen = match;\n } else if (candidates.length > 1) {\n chosen = await askSelect('Pick a snapshot to restore', candidates.map((c) => ({ name: c, message: c })));\n }\n const targetParent = join(process.cwd(), '.claude', 'skills');\n mkdirSync(targetParent, { recursive: true });\n const target = join(targetParent, name);\n if (existsSync(target)) {\n throw new UserError(`Cannot restore: ${target} already exists. Uninstall first.`);\n }\n cpSync(chosen, target, { recursive: true });\n process.stdout.write(`${c.ok('✓')} restored ${name} from ${chosen}\\n`);\n } finally {\n await closeContext(ctx);\n }\n });\n}\n\n/**\n * List every installed skill across project + user + plugin scopes.\n */\nexport function listInstalledSkills(projectRoot: string): ResolvedSkill[] {\n const out: ResolvedSkill[] = [];\n const seen = new Set<string>();\n const sources: Array<{ root: string; scope: ResolvedSkill['scope'] }> = [\n { root: join(projectRoot, '.claude', 'skills'), scope: 'project' },\n { root: join(homedir(), '.claude', 'skills'), scope: 'user' },\n ];\n for (const { root } of sources) {\n if (!existsSync(root)) continue;\n let entries: string[] = [];\n try {\n entries = readdirSync(root);\n } catch {\n continue;\n }\n for (const e of entries) {\n if (seen.has(e)) continue;\n const sk = resolveSkill(e, { projectRoot });\n if (sk) {\n seen.add(e);\n out.push(sk);\n }\n }\n }\n // Plugin scope\n const pluginsRoot = join(homedir(), '.claude', 'plugins');\n if (existsSync(pluginsRoot)) {\n let plugins: string[] = [];\n try {\n plugins = readdirSync(pluginsRoot);\n } catch {\n plugins = [];\n }\n for (const p of plugins) {\n const inner = join(pluginsRoot, p, 'skills');\n if (!existsSync(inner)) continue;\n let names: string[] = [];\n try {\n names = readdirSync(inner);\n } catch {\n continue;\n }\n for (const n of names) {\n if (seen.has(n)) continue;\n const sk = resolveSkill(n, { projectRoot });\n if (sk) {\n seen.add(n);\n out.push(sk);\n }\n }\n }\n }\n return out;\n}\n\nfunction archiveSkill(sk: ResolvedSkill): string {\n const parent = sk.dir.replace(/[\\\\/][^\\\\/]+$/, '');\n const snapshotsDir = join(parent, '.snapshots', 'skills');\n mkdirSync(snapshotsDir, { recursive: true });\n const ts = new Date().toISOString().replace(/[:.]/g, '-');\n const target = join(snapshotsDir, `${sk.name}-${ts}`);\n cpSync(sk.dir, target, { recursive: true });\n rmSync(sk.dir, { recursive: true, force: true });\n return target;\n}\n\nfunction findArchivedSkills(name: string, projectRoot: string): string[] {\n const out: string[] = [];\n const candidates = [\n join(projectRoot, '.claude', '.snapshots', 'skills'),\n join(projectRoot, '.claude', 'skills', '.snapshots', 'skills'),\n join(homedir(), '.claude', '.snapshots', 'skills'),\n join(homedir(), '.claude', 'skills', '.snapshots', 'skills'),\n ];\n for (const dir of candidates) {\n if (!existsSync(dir)) continue;\n let entries: string[] = [];\n try {\n entries = readdirSync(dir);\n } catch {\n continue;\n }\n for (const e of entries) {\n if (e.startsWith(name + '-')) out.push(join(dir, e));\n }\n }\n return out.sort();\n}\n","/**\n * Aggregates token-usage JSONL logs (`<workspace>/token-usage/YYYY-MM-DD.jsonl`)\n * into the summary shape the Usage dashboard view consumes.\n *\n * Pure function — no I/O. The caller passes in the records loaded via\n * `storage.loadTokenUsageLogs(...)`.\n */\nimport type { TokenUsageLog } from '../../storage/types.js';\n\nexport interface UsageBucket {\n /** Key for the bucket: the date (YYYY-MM-DD), feature, or model name. */\n key: string;\n calls: number;\n promptTokens: number;\n completionTokens: number;\n cacheReadTokens: number;\n cacheCreationTokens: number;\n totalTokens: number;\n costUsd: number;\n}\n\nexport interface UsageSummary {\n totals: Omit<UsageBucket, 'key'>;\n byDay: UsageBucket[];\n byFeature: UsageBucket[];\n byModel: UsageBucket[];\n /** Earliest createdAt in the logs (ISO). undefined when logs is empty. */\n windowStart?: string;\n /** Latest createdAt in the logs (ISO). undefined when logs is empty. */\n windowEnd?: string;\n}\n\nfunction emptyBucket(key: string): UsageBucket {\n return {\n key,\n calls: 0,\n promptTokens: 0,\n completionTokens: 0,\n cacheReadTokens: 0,\n cacheCreationTokens: 0,\n totalTokens: 0,\n costUsd: 0,\n };\n}\n\nfunction addInto(bucket: UsageBucket, log: TokenUsageLog): void {\n bucket.calls += 1;\n bucket.promptTokens += log.tokens.promptTokenCount || 0;\n bucket.completionTokens += log.tokens.candidatesTokenCount || 0;\n bucket.cacheReadTokens += log.tokens.cacheReadTokens || 0;\n bucket.cacheCreationTokens += log.tokens.cacheCreationTokens || 0;\n bucket.totalTokens += log.tokens.totalTokenCount || 0;\n bucket.costUsd += log.costUsd || 0;\n}\n\n/**\n * Build the dashboard summary from a flat list of token-usage logs.\n *\n * Day buckets are sorted by date ascending so a sparkline can render\n * left-to-right. Feature and model buckets are sorted by cost descending\n * (most expensive first) — the dashboard surfaces \"where is the money going\".\n */\nexport function summariseUsage(logs: TokenUsageLog[]): UsageSummary {\n const totals = emptyBucket('totals');\n const byDay = new Map<string, UsageBucket>();\n const byFeature = new Map<string, UsageBucket>();\n const byModel = new Map<string, UsageBucket>();\n\n let windowStart: string | undefined;\n let windowEnd: string | undefined;\n\n for (const log of logs) {\n addInto(totals, log);\n\n const date = (log.createdAt || '').slice(0, 10) || 'unknown';\n if (!byDay.has(date)) byDay.set(date, emptyBucket(date));\n addInto(byDay.get(date)!, log);\n\n const feature = log.feature || 'unknown';\n if (!byFeature.has(feature)) byFeature.set(feature, emptyBucket(feature));\n addInto(byFeature.get(feature)!, log);\n\n const model = log.model || 'unknown';\n if (!byModel.has(model)) byModel.set(model, emptyBucket(model));\n addInto(byModel.get(model)!, log);\n\n if (log.createdAt) {\n if (!windowStart || log.createdAt < windowStart) windowStart = log.createdAt;\n if (!windowEnd || log.createdAt > windowEnd) windowEnd = log.createdAt;\n }\n }\n\n // Strip the \"totals\" key field — the consumer just wants the numbers.\n const { key: _k, ...totalsNoKey } = totals;\n\n return {\n totals: totalsNoKey,\n byDay: [...byDay.values()].sort((a, b) => a.key.localeCompare(b.key)),\n byFeature: [...byFeature.values()].sort((a, b) => b.costUsd - a.costUsd || b.totalTokens - a.totalTokens),\n byModel: [...byModel.values()].sort((a, b) => b.costUsd - a.costUsd || b.totalTokens - a.totalTokens),\n ...(windowStart ? { windowStart } : {}),\n ...(windowEnd ? { windowEnd } : {}),\n };\n}\n","/**\n * `aab knowledge` — wiki management.\n *\n * Phase 1.5 surface (per `docs/development/KNOWLEDGE_WIKI.md` §17):\n * - Chunk 1 (this file as of initial drop): rename, show, list, open, edit,\n * stats, related, unresolved\n * - Chunk 2/3: ingest <path|url> [--paste] [--force]\n * - Chunk 5: backfill <discussion-id>\n * - Chunk 6: query, lint, graph\n * - Chunk 7: migrate\n */\nimport { Command } from 'commander';\nimport {\n existsSync,\n readFileSync,\n writeFileSync,\n mkdirSync,\n} from 'node:fs';\nimport { spawnSync } from 'node:child_process';\nimport { dirname, join, relative, resolve, basename } from 'node:path';\nimport { closeContext, openContext } from './_context.js';\nimport { c, brand } from '../ui/colors.js';\nimport { UserError } from '../core/errors.js';\nimport { paths, ensureWikiDirs } from '../storage/paths.js';\nimport {\n walkWikiPages,\n parsePage,\n serializePage,\n extractWikiLinks,\n toPosix,\n type PageType,\n PAGE_TYPES,\n pathForPage,\n folderForType,\n type WikiPageEntry,\n} from '../core/knowledge/page.js';\nimport {\n buildSlugMap,\n resolveSlug,\n parseSlugMap,\n writeSlugMapToIndex,\n extractBacklinksSection,\n} from '../core/knowledge/slug-map.js';\nimport {\n renameSlug,\n reconcileManifest,\n suggestSlug,\n} from '../core/knowledge/rename.js';\nimport { loadManifest, markUserEdited } from '../core/knowledge/manifest.js';\nimport { ingestFile, ingestPaste, ingestUrl, ingestDiscussionRaw } from '../core/knowledge/ingest.js';\nimport { queryWiki } from '../core/knowledge/query.js';\nimport { lintWiki } from '../core/knowledge/lint.js';\nimport { migrateBusinessContext } from '../core/knowledge/migrate.js';\nimport { nowIso } from '../core/utils.js';\n\nexport function registerKnowledgeCommand(program: Command): void {\n const k = program.command('knowledge').description('manage the Knowledge Wiki (Phase 1.5)');\n\n registerShow(k);\n registerList(k);\n registerOpen(k);\n registerEdit(k);\n registerStats(k);\n registerRename(k);\n registerRelated(k);\n registerUnresolved(k);\n registerIngest(k);\n registerQuery(k);\n registerLint(k);\n registerBackfill(k);\n registerMigrate(k);\n registerGraph(k);\n}\n\n// ---------------------------------------------------------------------------\n// list\n// ---------------------------------------------------------------------------\n\nfunction registerList(parent: Command): void {\n parent\n .command('list')\n .description('list all wiki pages, grouped by type')\n .option('--type <type>', `filter by type (${PAGE_TYPES.join('|')})`)\n .option('--orphans', 'only pages with zero incoming links')\n .option('--user-edited', 'only pages marked userEdited: true')\n .action(async (opts: { type?: string; orphans?: boolean; userEdited?: boolean }) => {\n const ctx = await openContext(parent, { lock: false });\n try {\n const p = paths(ctx.workspace.root);\n const pages = walkWikiPages(p.wiki, ctx.workspace.root);\n\n // Compute incoming-link graph if needed for --orphans.\n let inDegree: Map<string, number> | undefined;\n if (opts.orphans) {\n inDegree = new Map();\n for (const page of pages) {\n for (const link of extractWikiLinks(page.body)) {\n inDegree.set(link.slug, (inDegree.get(link.slug) ?? 0) + 1);\n }\n }\n }\n\n const filtered = pages.filter((page) => {\n if (opts.type && page.frontmatter.type !== opts.type) return false;\n if (opts.userEdited && page.frontmatter.userEdited !== true) return false;\n if (opts.orphans) {\n const slug = (page.frontmatter.slug ?? '').toLowerCase();\n if ((inDegree?.get(slug) ?? 0) > 0) return false;\n }\n return true;\n });\n\n if (ctx.json) {\n process.stdout.write(\n JSON.stringify(\n {\n pages: filtered.map((p) => ({\n slug: p.frontmatter.slug,\n title: p.frontmatter.title,\n type: p.frontmatter.type,\n summary: p.frontmatter.summary,\n tags: p.frontmatter.tags ?? [],\n path: p.wikiRelPath,\n userEdited: p.frontmatter.userEdited ?? false,\n updated: p.frontmatter.updated,\n })),\n },\n null,\n 2,\n ) + '\\n',\n );\n return;\n }\n\n process.stdout.write(`\\n${brand()} ${c.hint('· wiki pages')}\\n\\n`);\n if (filtered.length === 0) {\n process.stdout.write(c.hint(' (no pages matched — try `aab knowledge ingest <path>`)\\n'));\n return;\n }\n const grouped = new Map<string, WikiPageEntry[]>();\n for (const page of filtered) {\n const type = String(page.frontmatter.type ?? 'unknown');\n if (!grouped.has(type)) grouped.set(type, []);\n grouped.get(type)!.push(page);\n }\n for (const [type, list] of Array.from(grouped.entries()).sort(([a], [b]) => a.localeCompare(b))) {\n process.stdout.write(`${c.bold(type)} ${c.hint(`(${list.length})`)}\\n`);\n for (const p of list.sort((a, b) => (a.frontmatter.slug ?? '').localeCompare(b.frontmatter.slug ?? ''))) {\n const tag = p.frontmatter.userEdited ? c.warn(' [user-edited]') : '';\n const summary = p.frontmatter.summary ? c.hint(` — ${truncate(String(p.frontmatter.summary), 80)}`) : '';\n process.stdout.write(` ${c.cyan(String(p.frontmatter.slug ?? '?'))}${tag}${summary}\\n`);\n }\n process.stdout.write('\\n');\n }\n } finally {\n await closeContext(ctx);\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// show <slug>\n// ---------------------------------------------------------------------------\n\nfunction registerShow(parent: Command): void {\n parent\n .command('show <slug>')\n .description('pretty-print one wiki page (frontmatter + body + backlinks)')\n .action(async (slug: string) => {\n const ctx = await openContext(parent, { lock: false });\n try {\n const p = paths(ctx.workspace.root);\n const map = buildSlugMap(p.wiki, ctx.workspace.root);\n const entry = resolveSlug(map, slug);\n if (!entry) {\n throw new UserError(\n `No wiki page found for slug \"${slug}\".`,\n 'Use `aab knowledge list` to see existing slugs.',\n );\n }\n const fullPath = join(p.wiki, entry.path);\n const raw = readFileSync(fullPath, 'utf8');\n const parsed = parsePage(raw);\n if (!parsed) {\n throw new UserError(`Page ${entry.path} has no parseable frontmatter.`);\n }\n\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ ...parsed, slugMap: serializeMap(map), path: fullPath }, null, 2) + '\\n');\n return;\n }\n\n // Header\n const title = String(parsed.frontmatter.title ?? entry.slug);\n process.stdout.write(`\\n${c.bold(title)} ${c.hint(`(${entry.type})`)}\\n`);\n process.stdout.write(c.hint(` ${toPosix(relative(ctx.workspace.root, fullPath))}\\n\\n`));\n\n // Frontmatter summary\n const fm = parsed.frontmatter;\n if (fm.summary) process.stdout.write(`${c.bold('Summary:')} ${fm.summary}\\n`);\n if (Array.isArray(fm.tags) && fm.tags.length > 0) {\n process.stdout.write(`${c.bold('Tags:')} ${fm.tags.join(', ')}\\n`);\n }\n if (Array.isArray(fm.aliases) && fm.aliases.length > 0) {\n process.stdout.write(`${c.bold('Aliases:')} ${fm.aliases.join(', ')}\\n`);\n }\n if (fm.confidence) process.stdout.write(`${c.bold('Confidence:')} ${fm.confidence}\\n`);\n if (fm.provenance) process.stdout.write(`${c.bold('Provenance:')} ${fm.provenance}\\n`);\n if (fm.updated) process.stdout.write(`${c.bold('Updated:')} ${fm.updated}\\n`);\n if (Array.isArray(fm.sources) && fm.sources.length > 0) {\n process.stdout.write(`${c.bold('Sources:')}\\n`);\n for (const s of fm.sources) process.stdout.write(` - ${s}\\n`);\n }\n process.stdout.write('\\n');\n\n // Body with `[[slug]]` resolution pretty-print\n const pretty = parsed.body.replace(/(!?)\\[\\[([^\\]\\n]+)\\]\\]/g, (whole, bang: string, inner: string) => {\n if (bang === '!') return c.warn(`[[!${inner}]]`); // transclusion — unsupported\n const pipe = inner.indexOf('|');\n const target = (pipe >= 0 ? inner.slice(0, pipe) : inner).trim();\n const display = pipe >= 0 ? inner.slice(pipe + 1).trim() : '';\n const hash = target.indexOf('#');\n const slugPart = (hash >= 0 ? target.slice(0, hash) : target).toLowerCase();\n const anchor = hash >= 0 ? target.slice(hash) : '';\n const resolved = resolveSlug(map, slugPart);\n if (!resolved) return c.err(`[[${inner}]] ⚠ unresolved`);\n const label = display || resolved.title || resolved.slug;\n return c.cyan(`${resolved.slug}${anchor}`) + c.hint(` (\"${label}\")`);\n });\n process.stdout.write(pretty);\n process.stdout.write('\\n');\n } finally {\n await closeContext(ctx);\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// open <slug>\n// ---------------------------------------------------------------------------\n\nfunction registerOpen(parent: Command): void {\n parent\n .command('open <slug>')\n .description('print absolute filesystem path of a wiki page (handy for piping into editors)')\n .action(async (slug: string) => {\n const ctx = await openContext(parent, { lock: false });\n try {\n const p = paths(ctx.workspace.root);\n const map = buildSlugMap(p.wiki, ctx.workspace.root);\n const entry = resolveSlug(map, slug);\n if (!entry) {\n throw new UserError(`No wiki page found for slug \"${slug}\".`);\n }\n process.stdout.write(join(p.wiki, entry.path) + '\\n');\n } finally {\n await closeContext(ctx);\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// edit <slug>\n// ---------------------------------------------------------------------------\n\nfunction registerEdit(parent: Command): void {\n parent\n .command('edit <slug>')\n .description('open a wiki page in $EDITOR and mark userEdited: true on save')\n .action(async (slug: string) => {\n const ctx = await openContext(parent);\n try {\n const p = paths(ctx.workspace.root);\n const map = buildSlugMap(p.wiki, ctx.workspace.root);\n const entry = resolveSlug(map, slug);\n if (!entry) throw new UserError(`No wiki page found for slug \"${slug}\".`);\n const fullPath = join(p.wiki, entry.path);\n\n const editor = process.env.EDITOR || process.env.VISUAL || (process.platform === 'win32' ? 'notepad' : 'vi');\n const before = readFileSync(fullPath, 'utf8');\n const result = spawnSync(editor, [fullPath], { stdio: 'inherit' });\n if (result.status !== 0) {\n throw new UserError(`Editor exited with code ${result.status}.`);\n }\n const after = readFileSync(fullPath, 'utf8');\n if (before === after) {\n process.stdout.write(c.hint(' (no changes)\\n'));\n return;\n }\n // Re-parse and stamp userEdited + updated date.\n const parsed = parsePage(after);\n if (!parsed) throw new UserError('After edit, page has no parseable frontmatter — restore and try again.');\n const next = { ...parsed.frontmatter, userEdited: true, updated: nowIso().slice(0, 10) };\n writeFileSync(fullPath, serializePage(next, parsed.body), 'utf8');\n markUserEdited(p.manifest, toPosix(`wiki/${entry.path}`), 'aab knowledge edit');\n process.stdout.write(`${c.ok('✓')} marked ${c.bold(entry.slug)} as user-edited.\\n`);\n } finally {\n await closeContext(ctx);\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// stats\n// ---------------------------------------------------------------------------\n\nfunction registerStats(parent: Command): void {\n parent\n .command('stats')\n .description('show wiki size, page counts by type, ingest history')\n .action(async () => {\n const ctx = await openContext(parent, { lock: false });\n try {\n const p = paths(ctx.workspace.root);\n const pages = walkWikiPages(p.wiki, ctx.workspace.root);\n const manifest = loadManifest(p.manifest);\n const byType: Record<string, number> = {};\n let aliasCount = 0;\n for (const page of pages) {\n const type = String(page.frontmatter.type ?? 'unknown');\n byType[type] = (byType[type] ?? 0) + 1;\n if (Array.isArray(page.frontmatter.aliases)) aliasCount += page.frontmatter.aliases.length;\n }\n const totalCost = manifest.entries.reduce((sum, e) => sum + (e.ingestCostUsd ?? 0), 0);\n const lastIngest = manifest.entries[manifest.entries.length - 1]?.ingestedAt;\n\n if (ctx.json) {\n process.stdout.write(\n JSON.stringify(\n {\n pageCount: pages.length,\n byType,\n aliasCount,\n ingestCount: manifest.entries.length,\n renameCount: manifest.renames.length,\n userEditedCount: manifest.userEditedPages.length,\n totalIngestCostUsd: totalCost,\n lastIngestAt: lastIngest,\n },\n null,\n 2,\n ) + '\\n',\n );\n return;\n }\n process.stdout.write(`\\n${brand()} ${c.hint('· wiki stats')}\\n\\n`);\n process.stdout.write(` ${c.bold('Pages:')} ${pages.length}\\n`);\n for (const [type, count] of Object.entries(byType).sort(([a], [b]) => a.localeCompare(b))) {\n process.stdout.write(` ${type.padEnd(16)} ${count}\\n`);\n }\n process.stdout.write(` ${c.bold('Aliases:')} ${aliasCount}\\n`);\n process.stdout.write(` ${c.bold('Ingests:')} ${manifest.entries.length}\\n`);\n process.stdout.write(` ${c.bold('Renames:')} ${manifest.renames.length}\\n`);\n process.stdout.write(` ${c.bold('User-edited:')} ${manifest.userEditedPages.length}\\n`);\n process.stdout.write(` ${c.bold('Cost (USD):')} ${totalCost.toFixed(4)}\\n`);\n if (lastIngest) process.stdout.write(` ${c.bold('Last ingest:')} ${lastIngest}\\n`);\n process.stdout.write('\\n');\n } finally {\n await closeContext(ctx);\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// rename <old> <new>\n// ---------------------------------------------------------------------------\n\nfunction registerRename(parent: Command): void {\n parent\n .command('rename <oldSlug> [newSlug]')\n .description('atomically rename a slug across the wiki (file + body + related + aliases + manifest)')\n .option('--dry-run', 'print the diff without writing')\n .option('--auto-fix', 'fuzzy-match a broken slug to its likely new location and prompt')\n .option('--reconcile', 'align the manifest with the current filesystem (after Foam-driven moves)')\n .action(\n async (\n oldSlug: string,\n newSlug: string | undefined,\n opts: { dryRun?: boolean; autoFix?: boolean; reconcile?: boolean },\n ) => {\n const ctx = await openContext(parent);\n try {\n const p = paths(ctx.workspace.root);\n ensureWikiDirs(ctx.workspace.root);\n\n if (opts.reconcile) {\n const result = reconcileManifest({\n wikiRoot: p.wiki,\n workspaceRoot: ctx.workspace.root,\n manifestPath: p.manifest,\n dryRun: opts.dryRun,\n });\n if (ctx.json) {\n process.stdout.write(JSON.stringify(result, null, 2) + '\\n');\n return;\n }\n if (result.rewrites.length === 0) {\n process.stdout.write(`${c.hint('—')} manifest is already aligned with the filesystem.\\n`);\n } else {\n process.stdout.write(`${opts.dryRun ? c.warn('(dry-run) ') : c.ok('✓ ')}reconciled ${result.rewrites.length} manifest entr${result.rewrites.length === 1 ? 'y' : 'ies'}:\\n`);\n for (const r of result.rewrites) {\n process.stdout.write(` ${r.kind}: ${c.hint(r.from)} → ${c.bold(r.to)}\\n`);\n }\n }\n return;\n }\n\n let resolvedTo = newSlug;\n if (opts.autoFix) {\n const map = buildSlugMap(p.wiki, ctx.workspace.root);\n const all = Array.from(map.canonical.keys());\n const suggestion = suggestSlug(oldSlug, all);\n if (!suggestion) {\n throw new UserError(\n `auto-fix: no plausible match for \"${oldSlug}\".`,\n 'Pass the target slug explicitly: `aab knowledge rename <old> <new>`.',\n );\n }\n resolvedTo = suggestion;\n process.stdout.write(`${c.warn('auto-fix:')} matched ${c.bold(oldSlug)} → ${c.bold(resolvedTo)}\\n`);\n }\n if (!resolvedTo) {\n throw new UserError('rename: <newSlug> is required (or pass --auto-fix or --reconcile).');\n }\n\n const result = await renameSlug({\n wikiRoot: p.wiki,\n manifestPath: p.manifest,\n indexPath: p.wikiIndex,\n workspaceRoot: ctx.workspace.root,\n fromSlug: oldSlug,\n toSlug: resolvedTo,\n dryRun: opts.dryRun,\n trigger: opts.autoFix ? 'lint-recommended' : 'manual',\n });\n\n if (ctx.json) {\n process.stdout.write(JSON.stringify(result, null, 2) + '\\n');\n return;\n }\n\n const tag = result.dryRun ? c.warn('(dry-run) ') : c.ok('✓ ');\n process.stdout.write(\n `${tag}rename ${c.bold(result.fromSlug)} → ${c.bold(result.toSlug)}\\n` +\n ` ${c.hint('file:')} ${result.fromPath} → ${result.toPath}\\n` +\n ` ${c.hint('refs:')} ${result.rewroteRefs} body link${result.rewroteRefs === 1 ? '' : 's'} rewritten\\n` +\n ` ${c.hint('related:')} ${result.rewroteRelated} frontmatter entr${result.rewroteRelated === 1 ? 'y' : 'ies'}\\n` +\n ` ${c.hint('aliases:')} ${result.rewroteAliases}\\n` +\n ` ${c.hint('manifest:')} ${result.rewroteManifestEntries} path${result.rewroteManifestEntries === 1 ? '' : 's'}\\n`,\n );\n if (result.changedFiles.length > 0) {\n process.stdout.write(` ${c.hint('files:')}\\n`);\n for (const f of result.changedFiles) {\n process.stdout.write(` ${c.cyan(f.path)} ${c.hint(`(refs:${f.refs} related:${f.related} aliases:${f.aliases})`)}\\n`);\n }\n }\n } finally {\n await closeContext(ctx);\n }\n },\n );\n}\n\n// ---------------------------------------------------------------------------\n// related <slug>\n// ---------------------------------------------------------------------------\n\nfunction registerRelated(parent: Command): void {\n parent\n .command('related <slug>')\n .description('walk the link neighborhood of a slug (outgoing + incoming)')\n .option('--depth <n>', 'how many hops to walk (1-5)', (v) => Number(v), 1)\n .option('--out <path>', 'save as a markdown report')\n .action(async (slug: string, opts: { depth: number; out?: string }) => {\n const ctx = await openContext(parent, { lock: false });\n try {\n const p = paths(ctx.workspace.root);\n const pages = walkWikiPages(p.wiki, ctx.workspace.root);\n const map = buildSlugMap(p.wiki, ctx.workspace.root);\n const startEntry = resolveSlug(map, slug);\n if (!startEntry) {\n throw new UserError(`No wiki page found for slug \"${slug}\".`);\n }\n const startSlug = startEntry.slug;\n const depth = Math.min(5, Math.max(1, Number.isFinite(opts.depth) ? opts.depth : 1));\n\n // Build graph\n const outgoing = new Map<string, Set<string>>();\n const incoming = new Map<string, Set<string>>();\n for (const page of pages) {\n const fromSlug = (page.frontmatter.slug ?? '').toLowerCase();\n if (!fromSlug) continue;\n for (const link of extractWikiLinks(page.body)) {\n const target = map.aliasToCanonical.get(link.slug);\n if (!target) continue;\n if (!outgoing.has(fromSlug)) outgoing.set(fromSlug, new Set());\n outgoing.get(fromSlug)!.add(target);\n if (!incoming.has(target)) incoming.set(target, new Set());\n incoming.get(target)!.add(fromSlug);\n }\n }\n\n // BFS to depth\n const visited = new Map<string, number>([[startSlug, 0]]);\n const queue: string[] = [startSlug];\n while (queue.length > 0) {\n const node = queue.shift()!;\n const d = visited.get(node)!;\n if (d >= depth) continue;\n const neighbors = new Set([...(outgoing.get(node) ?? []), ...(incoming.get(node) ?? [])]);\n for (const n of neighbors) {\n if (!visited.has(n)) {\n visited.set(n, d + 1);\n queue.push(n);\n }\n }\n }\n\n const report: string[] = [];\n report.push(`# Related: ${startSlug}`);\n report.push('');\n report.push(`_Depth ${depth} · ${visited.size - 1} neighbor${visited.size === 2 ? '' : 's'}_`);\n report.push('');\n const grouped = new Map<number, string[]>();\n for (const [s, d] of visited.entries()) {\n if (d === 0) continue;\n if (!grouped.has(d)) grouped.set(d, []);\n grouped.get(d)!.push(s);\n }\n for (const [d, list] of Array.from(grouped.entries()).sort(([a], [b]) => a - b)) {\n report.push(`## Hop ${d}`);\n for (const s of list.sort()) {\n const e = map.canonical.get(s);\n report.push(`- \\`[[${s}]]\\`${e?.title ? ` — ${e.title}` : ''}${e?.summary ? ` — ${truncate(e.summary, 80)}` : ''}`);\n }\n report.push('');\n }\n\n const rendered = report.join('\\n');\n if (opts.out) {\n mkdirSync(dirname(resolve(opts.out)), { recursive: true });\n writeFileSync(resolve(opts.out), rendered, 'utf8');\n process.stdout.write(`${c.ok('✓')} wrote ${c.bold(resolve(opts.out))}\\n`);\n } else if (ctx.json) {\n const neighbors = Array.from(visited.entries())\n .filter(([s]) => s !== startSlug)\n .map(([s, d]) => ({ slug: s, hop: d }));\n process.stdout.write(JSON.stringify({ start: startSlug, depth, neighbors }, null, 2) + '\\n');\n } else {\n process.stdout.write(rendered + '\\n');\n }\n } finally {\n await closeContext(ctx);\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// unresolved\n// ---------------------------------------------------------------------------\n\nfunction registerUnresolved(parent: Command): void {\n parent\n .command('unresolved')\n .description('list every [[wikilink]] whose target slug does not exist')\n .option('--suggest-fixes', 'fuzzy-match each unresolved slug against existing slugs')\n .action(async (opts: { suggestFixes?: boolean }) => {\n const ctx = await openContext(parent, { lock: false });\n try {\n const p = paths(ctx.workspace.root);\n const pages = walkWikiPages(p.wiki, ctx.workspace.root);\n const map = buildSlugMap(p.wiki, ctx.workspace.root);\n const knownSlugs = Array.from(new Set([\n ...Array.from(map.canonical.keys()),\n ...Array.from(map.aliasToCanonical.keys()),\n ]));\n\n interface UnresolvedRef {\n slug: string;\n refs: Array<{ file: string; line: number }>;\n suggestion?: string;\n }\n const unresolvedBySlug = new Map<string, UnresolvedRef>();\n\n for (const page of pages) {\n const lines = page.body.split(/\\r?\\n/);\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i] ?? '';\n const re = /(!?)\\[\\[([^\\]\\n]+)\\]\\]/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(line)) !== null) {\n if (m[1] === '!') continue; // transclusion — separate lint warning\n const inner = (m[2] ?? '').trim();\n const pipe = inner.indexOf('|');\n const target = (pipe >= 0 ? inner.slice(0, pipe) : inner).trim();\n const hash = target.indexOf('#');\n const slugOnly = (hash >= 0 ? target.slice(0, hash) : target).trim().toLowerCase();\n if (!slugOnly) continue;\n if (map.aliasToCanonical.has(slugOnly)) continue;\n const existing = unresolvedBySlug.get(slugOnly) ?? { slug: slugOnly, refs: [] };\n existing.refs.push({ file: page.wikiRelPath, line: i + 1 });\n unresolvedBySlug.set(slugOnly, existing);\n }\n }\n }\n\n if (opts.suggestFixes) {\n for (const u of unresolvedBySlug.values()) {\n u.suggestion = suggestSlug(u.slug, knownSlugs);\n }\n }\n\n const list = Array.from(unresolvedBySlug.values()).sort((a, b) => a.slug.localeCompare(b.slug));\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ unresolved: list }, null, 2) + '\\n');\n return;\n }\n if (list.length === 0) {\n process.stdout.write(`${c.ok('✓')} no unresolved [[wikilinks]].\\n`);\n return;\n }\n process.stdout.write(`\\n${brand()} ${c.hint('· unresolved wiki-links')}\\n\\n`);\n for (const u of list) {\n process.stdout.write(`${c.err('[[')}${c.bold(u.slug)}${c.err(']]')}\\n`);\n for (const r of u.refs) {\n process.stdout.write(` ${c.hint(`${r.file}:${r.line}`)}\\n`);\n }\n if (u.suggestion) {\n process.stdout.write(` ${c.warn('→ suggestion:')} ${c.cyan(u.suggestion)}\\n`);\n }\n }\n process.stdout.write('\\n');\n } finally {\n await closeContext(ctx);\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// ingest <path-or-url>\n// ---------------------------------------------------------------------------\n\nfunction registerIngest(parent: Command): void {\n parent\n .command('ingest [pathOrUrl]')\n .description('ingest a file, URL, or raw text into the wiki')\n .option('--paste', 'read raw markdown from stdin')\n .option('--discussion <id>', 're-ingest (or initial ingest if it skipped) a discussion')\n .option('--type <type>', `hint to the agent (${PAGE_TYPES.join('|')})`)\n .option('--model <alias>', 'override the ingest model (default: fastModel)')\n .option('--force', 're-ingest even if hash already in manifest')\n .action(\n async (\n pathOrUrl: string | undefined,\n opts: { paste?: boolean; discussion?: string; type?: string; model?: string; force?: boolean },\n ) => {\n const ctx = await openContext(parent);\n try {\n const settings = await ctx.storage.loadSettings();\n if (opts.paste) {\n const stdin = await readStdin();\n if (!stdin.trim()) throw new UserError('ingest --paste: stdin is empty.');\n const result = await ingestPaste({\n text: stdin,\n workspace: ctx.workspace,\n settings,\n force: opts.force,\n hintType: opts.type as PageType | undefined,\n modelOverride: opts.model,\n });\n renderIngestResult(ctx.json, result);\n return;\n }\n if (opts.discussion) {\n const disc = await ctx.storage.loadDiscussionById(opts.discussion);\n if (!disc) throw new UserError(`No discussion found with id \"${opts.discussion}\".`);\n const result = await ingestDiscussionRaw({\n discussion: disc,\n workspace: ctx.workspace,\n settings,\n force: opts.force,\n storage: ctx.storage,\n modelOverride: opts.model,\n });\n renderIngestResult(ctx.json, result);\n return;\n }\n if (!pathOrUrl) {\n throw new UserError('ingest: provide a path, URL, --paste, or --discussion <id>.');\n }\n if (/^https?:\\/\\//i.test(pathOrUrl)) {\n const result = await ingestUrl({\n url: pathOrUrl,\n workspace: ctx.workspace,\n settings,\n force: opts.force,\n hintType: opts.type as PageType | undefined,\n modelOverride: opts.model,\n });\n renderIngestResult(ctx.json, result);\n return;\n }\n const result = await ingestFile({\n path: resolve(pathOrUrl),\n workspace: ctx.workspace,\n settings,\n force: opts.force,\n hintType: opts.type as PageType | undefined,\n modelOverride: opts.model,\n });\n renderIngestResult(ctx.json, result);\n } finally {\n await closeContext(ctx);\n }\n },\n );\n}\n\n// ---------------------------------------------------------------------------\n// query \"<question>\"\n// ---------------------------------------------------------------------------\n\nfunction registerQuery(parent: Command): void {\n parent\n .command('query <question>')\n .description('ask the wiki a question (read-only, citing pages)')\n .option('--max-pages <n>', 'cap pages opened (default 10)', (v) => Number(v))\n .option('--model <alias>', 'override the query model (default: queryModel)')\n .option('--out <path>', 'save the answer to a markdown file')\n .option('--save-as <type>', 'file the answer back into the wiki as a new page')\n .action(\n async (\n question: string,\n opts: { maxPages?: number; model?: string; out?: string; saveAs?: string },\n ) => {\n const ctx = await openContext(parent);\n try {\n const settings = await ctx.storage.loadSettings();\n const result = await queryWiki({\n question,\n workspace: ctx.workspace,\n settings,\n maxPages: opts.maxPages,\n modelOverride: opts.model,\n saveAs: opts.saveAs as PageType | undefined,\n });\n if (opts.out) {\n mkdirSync(dirname(resolve(opts.out)), { recursive: true });\n writeFileSync(resolve(opts.out), result.answer, 'utf8');\n process.stdout.write(`${c.ok('✓')} wrote ${c.bold(resolve(opts.out))}\\n`);\n }\n if (ctx.json) {\n process.stdout.write(JSON.stringify(result, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`\\n${c.bold('Answer:')}\\n\\n${result.answer}\\n\\n`);\n if (result.citations.length > 0) {\n process.stdout.write(c.bold('Citations:\\n'));\n for (const slug of result.citations) {\n process.stdout.write(` - [[${slug}]]\\n`);\n }\n process.stdout.write('\\n');\n }\n process.stdout.write(c.hint(` cost: ${result.costUsd.toFixed(4)} USD\\n`));\n } finally {\n await closeContext(ctx);\n }\n },\n );\n}\n\n// ---------------------------------------------------------------------------\n// lint [--write]\n// ---------------------------------------------------------------------------\n\nfunction registerLint(parent: Command): void {\n parent\n .command('lint')\n .description('run health checks on the wiki; rebuild slug-map + per-page backlinks')\n .option('--no-write', 'skip writing outputs/lint-<date>.md')\n .option('--no-llm', 'skip the LLM passes (contradiction / stale / missing concept)')\n .option('--max-pages <n>', 'cap LLM-pass pages (cost control)', (v) => Number(v))\n .action(async (opts: { write?: boolean; llm?: boolean; maxPages?: number }) => {\n const ctx = await openContext(parent);\n try {\n const settings = await ctx.storage.loadSettings();\n const result = await lintWiki({\n workspace: ctx.workspace,\n settings,\n writeReport: opts.write !== false,\n runLlm: opts.llm !== false,\n maxPages: opts.maxPages,\n });\n if (ctx.json) {\n process.stdout.write(JSON.stringify(result, null, 2) + '\\n');\n return;\n }\n const errs = result.findings.filter((f) => f.severity === 'error').length;\n const warns = result.findings.filter((f) => f.severity === 'warn').length;\n const infos = result.findings.filter((f) => f.severity === 'info').length;\n process.stdout.write(`\\n${brand()} ${c.hint('· lint')}\\n\\n`);\n process.stdout.write(` ${c.err('errors:')} ${errs}\\n`);\n process.stdout.write(` ${c.warn('warns:')} ${warns}\\n`);\n process.stdout.write(` ${c.hint('infos:')} ${infos}\\n`);\n if (result.reportPath) {\n process.stdout.write(`\\n report: ${c.bold(result.reportPath)}\\n`);\n }\n if (errs > 0) process.exitCode = 1;\n } finally {\n await closeContext(ctx);\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// backfill <discussion-id>\n// ---------------------------------------------------------------------------\n\nfunction registerBackfill(parent: Command): void {\n parent\n .command('backfill <discussionId>')\n .description('manually run the auto-ingest hook for one past discussion')\n .option('--force', 're-ingest even if hash already in manifest')\n .option('--model <alias>', 'override the ingest model')\n .action(async (discussionId: string, opts: { force?: boolean; model?: string }) => {\n const ctx = await openContext(parent);\n try {\n const settings = await ctx.storage.loadSettings();\n const disc = await ctx.storage.loadDiscussionById(discussionId);\n if (!disc) {\n // Try short prefix\n const all = await ctx.storage.loadDiscussions();\n const matches = all.filter((d) => d.id.startsWith(discussionId));\n if (matches.length === 0) throw new UserError(`No discussion found with id starting \"${discussionId}\".`);\n if (matches.length > 1) throw new UserError(`Multiple discussions match \"${discussionId}\". Use a longer prefix.`);\n const result = await ingestDiscussionRaw({\n discussion: matches[0]!,\n workspace: ctx.workspace,\n settings,\n force: opts.force,\n storage: ctx.storage,\n modelOverride: opts.model,\n });\n renderIngestResult(ctx.json, result);\n return;\n }\n const result = await ingestDiscussionRaw({\n discussion: disc,\n workspace: ctx.workspace,\n settings,\n force: opts.force,\n storage: ctx.storage,\n modelOverride: opts.model,\n });\n renderIngestResult(ctx.json, result);\n } finally {\n await closeContext(ctx);\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// migrate\n// ---------------------------------------------------------------------------\n\nfunction registerMigrate(parent: Command): void {\n parent\n .command('migrate')\n .description('convert BusinessContext / BusinessProfile JSON into wiki pages')\n .option('--dry-run', 'show what would be written, do not write')\n .option('--force-schema', 'overwrite wiki/KNOWLEDGE.md')\n .action(async (opts: { dryRun?: boolean; forceSchema?: boolean }) => {\n const ctx = await openContext(parent);\n try {\n const result = await migrateBusinessContext({\n workspace: ctx.workspace,\n storage: ctx.storage,\n dryRun: !!opts.dryRun,\n forceSchema: !!opts.forceSchema,\n });\n if (ctx.json) {\n process.stdout.write(JSON.stringify(result, null, 2) + '\\n');\n return;\n }\n const tag = result.dryRun ? c.warn('(dry-run) ') : c.ok('✓ ');\n process.stdout.write(`${tag}migrate complete: ${result.producedPages.length} produced, ${result.skipped.length} skipped\\n`);\n for (const p of result.producedPages) process.stdout.write(` + ${c.cyan(p)}\\n`);\n for (const s of result.skipped) process.stdout.write(` ${c.hint('—')} ${s}\\n`);\n if (result.backupPath) process.stdout.write(` ${c.hint('backup:')} ${result.backupPath}\\n`);\n } finally {\n await closeContext(ctx);\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// graph\n// ---------------------------------------------------------------------------\n\nfunction registerGraph(parent: Command): void {\n parent\n .command('graph')\n .description('print the wiki link graph in DOT format')\n .option('--out <path>', 'save to file')\n .action(async (opts: { out?: string }) => {\n const ctx = await openContext(parent, { lock: false });\n try {\n const p = paths(ctx.workspace.root);\n const pages = walkWikiPages(p.wiki, ctx.workspace.root);\n const map = buildSlugMap(p.wiki, ctx.workspace.root);\n const lines: string[] = ['digraph wiki {', ' rankdir=LR;', ' node [shape=box, style=rounded];'];\n for (const page of pages) {\n const slug = (page.frontmatter.slug ?? '').toLowerCase();\n if (!slug) continue;\n const type = String(page.frontmatter.type ?? '');\n lines.push(` \"${slug}\" [label=\"${slug}\\\\n(${type})\"];`);\n for (const link of extractWikiLinks(page.body)) {\n const target = map.aliasToCanonical.get(link.slug);\n if (target && target !== slug) {\n lines.push(` \"${slug}\" -> \"${target}\";`);\n }\n }\n }\n lines.push('}');\n const dot = lines.join('\\n') + '\\n';\n if (opts.out) {\n mkdirSync(dirname(resolve(opts.out)), { recursive: true });\n writeFileSync(resolve(opts.out), dot, 'utf8');\n process.stdout.write(`${c.ok('✓')} wrote ${c.bold(resolve(opts.out))}\\n`);\n } else if (ctx.json) {\n const nodes = pages.map((p) => ({\n slug: p.frontmatter.slug,\n type: p.frontmatter.type,\n title: p.frontmatter.title,\n }));\n const edges: Array<{ from: string; to: string }> = [];\n for (const page of pages) {\n const fromSlug = (page.frontmatter.slug ?? '').toLowerCase();\n for (const link of extractWikiLinks(page.body)) {\n const target = map.aliasToCanonical.get(link.slug);\n if (target && target !== fromSlug) edges.push({ from: fromSlug, to: target });\n }\n }\n process.stdout.write(JSON.stringify({ nodes, edges }, null, 2) + '\\n');\n } else {\n process.stdout.write(dot);\n }\n } finally {\n await closeContext(ctx);\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// helpers\n// ---------------------------------------------------------------------------\n\nfunction truncate(s: string, n: number): string {\n if (s.length <= n) return s;\n return s.slice(0, n - 1) + '…';\n}\n\nfunction serializeMap(map: ReturnType<typeof buildSlugMap>) {\n return {\n canonical: Object.fromEntries(map.canonical),\n aliasToCanonical: Object.fromEntries(map.aliasToCanonical),\n };\n}\n\ninterface IngestRenderShape {\n producedPages: string[];\n updatedPages: string[];\n skipped: string[];\n rawPath?: string;\n costUsd?: number;\n notes?: string;\n alreadyIngested?: boolean;\n warning?: string;\n}\n\nfunction renderIngestResult(json: boolean, result: IngestRenderShape) {\n if (json) {\n process.stdout.write(JSON.stringify(result, null, 2) + '\\n');\n return;\n }\n if (result.alreadyIngested) {\n process.stdout.write(`${c.hint('—')} already ingested (hash hit in manifest). Re-run with --force.\\n`);\n if (result.rawPath) process.stdout.write(c.hint(` source: ${result.rawPath}\\n`));\n return;\n }\n process.stdout.write(`${c.ok('✓')} ingest complete\\n`);\n if (result.rawPath) process.stdout.write(c.hint(` source: ${result.rawPath}\\n`));\n for (const p of result.producedPages) process.stdout.write(` ${c.ok('+')} ${c.cyan(p)} ${c.hint('(created)')}\\n`);\n for (const p of result.updatedPages) process.stdout.write(` ${c.warn('~')} ${c.cyan(p)} ${c.hint('(updated)')}\\n`);\n for (const p of result.skipped) process.stdout.write(` ${c.hint('—')} ${p} ${c.hint('(skipped — userEdited)')}\\n`);\n if (result.notes) process.stdout.write(c.hint(` notes: ${result.notes}\\n`));\n if (result.costUsd != null) process.stdout.write(c.hint(` cost: ${result.costUsd.toFixed(4)} USD\\n`));\n if (result.warning) process.stdout.write(`${c.warn('!')} ${result.warning}\\n`);\n}\n\nfunction readStdin(): Promise<string> {\n return new Promise((resolveFn, reject) => {\n let data = '';\n process.stdin.setEncoding('utf8');\n process.stdin.on('data', (chunk: string) => (data += chunk));\n process.stdin.on('end', () => resolveFn(data));\n process.stdin.on('error', reject);\n });\n}\n\n// Reference unused imports to keep TS happy until later chunks land.\nvoid basename;\nvoid extractBacklinksSection;\nvoid parseSlugMap;\nvoid writeSlugMapToIndex;\nvoid folderForType;\nvoid pathForPage;\n","/**\n * Migrate `BusinessContext` + `BusinessProfile` JSON into wiki pages.\n * Reference: `docs/development/KNOWLEDGE_WIKI.md` §19. Idempotent. Backs up the old\n * JSON to `business-context.json.migrated.bak` after success.\n */\nimport { existsSync, renameSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { paths, type ResolvedWorkspace } from '../../storage/paths.js';\nimport { toSlug, pathForPage, type PageType, type PageFrontmatter, writePageAtomic, toPosix } from './page.js';\nimport { emitWikiSkeleton } from './schema-emitter.js';\nimport { buildSlugMap, writeSlugMapToIndex } from './slug-map.js';\nimport { nowIso } from '../utils.js';\nimport { relative } from 'node:path';\nimport type {\n BusinessContext,\n BusinessProfile,\n StorageService,\n} from '../../storage/types.js';\n\nexport interface MigrateOptions {\n workspace: ResolvedWorkspace;\n storage: StorageService;\n dryRun?: boolean;\n forceSchema?: boolean;\n}\n\nexport interface MigrateResult {\n producedPages: string[];\n skipped: string[];\n backupPath?: string;\n dryRun: boolean;\n}\n\nexport async function migrateBusinessContext(opts: MigrateOptions): Promise<MigrateResult> {\n const p = paths(opts.workspace.root);\n\n // Ensure wiki skeleton exists before we write pages.\n if (!opts.dryRun) {\n emitWikiSkeleton({ workspaceRoot: opts.workspace.root, forceSchema: opts.forceSchema });\n }\n\n const items = await safeLoad(opts.storage.loadBusinessContext.bind(opts.storage));\n const profile = await safeLoadOne(opts.storage.loadBusinessProfile.bind(opts.storage));\n\n const produced: string[] = [];\n const skipped: string[] = [];\n\n // ---- Company profile → wiki/entities/company.md ----\n if (profile) {\n const path = pathForPage(p.wiki, 'entity', 'company');\n if (!opts.dryRun) {\n writePageAtomic(path, profileFrontmatter(profile), profileBody(profile));\n }\n produced.push(toPosix(`wiki/entities/company.md`));\n }\n\n // ---- BusinessContext items ----\n for (const item of items ?? []) {\n const target = mapItem(item);\n if (!target) {\n skipped.push(`${item.category}/${item.title}`);\n continue;\n }\n const path = pathForPage(p.wiki, target.type, target.slug);\n if (!opts.dryRun) writePageAtomic(path, target.frontmatter, target.body);\n produced.push(toPosix(`wiki/${typeFolder(target.type)}/${target.slug}.md`));\n }\n\n // Slug-map refresh\n if (!opts.dryRun) {\n const map = buildSlugMap(p.wiki, opts.workspace.root);\n writeSlugMapToIndex(p.wikiIndex, map);\n }\n\n // Back up the old JSON.\n let backupPath: string | undefined;\n if (!opts.dryRun && existsSync(p.businessContext)) {\n const backup = `${p.businessContext}.migrated.bak`;\n if (!existsSync(backup)) renameSync(p.businessContext, backup);\n backupPath = toPosix(relative(opts.workspace.root, backup));\n }\n // Also back up profile JSON if present.\n if (!opts.dryRun && existsSync(p.businessProfile)) {\n const backup = `${p.businessProfile}.migrated.bak`;\n if (!existsSync(backup)) renameSync(p.businessProfile, backup);\n }\n\n return { producedPages: produced, skipped, backupPath, dryRun: !!opts.dryRun };\n}\n\nasync function safeLoad<T>(fn: () => Promise<T[]>): Promise<T[] | null> {\n try {\n return await fn();\n } catch {\n return null;\n }\n}\nasync function safeLoadOne<T>(fn: () => Promise<T | null>): Promise<T | null> {\n try {\n return await fn();\n } catch {\n return null;\n }\n}\n\nfunction typeFolder(t: PageType): string {\n return ({ concept: 'concepts', entity: 'entities', decision: 'decisions', 'source-summary': 'sources', comparison: 'comparisons' } as const)[t];\n}\n\nfunction profileFrontmatter(p: BusinessProfile): PageFrontmatter {\n const today = nowIso().slice(0, 10);\n return {\n title: p.companyName || 'Company',\n slug: 'company',\n type: 'entity',\n summary: [p.companyName, p.industry, p.stage].filter(Boolean).join(' · ').slice(0, 200),\n tags: ['company', 'profile', p.industry, p.stage, p.companySize].filter((t): t is string => !!t),\n sources: ['business-profile.json (migrated)'],\n confidence: 'high',\n provenance: 'extracted',\n created: today,\n updated: today,\n userEdited: false,\n };\n}\n\nfunction profileBody(p: BusinessProfile): string {\n const lines: string[] = [];\n lines.push(`# ${p.companyName || 'Company'}`);\n lines.push('');\n if (p.industry) lines.push(`- **Industry:** ${p.industry}`);\n if (p.companySize) lines.push(`- **Size:** ${p.companySize}`);\n if (p.stage) lines.push(`- **Stage:** ${p.stage}`);\n if (p.targetMarket) lines.push(`- **Target market:** ${p.targetMarket}`);\n lines.push('');\n if (p.products && p.products.length > 0) {\n lines.push('## Products');\n for (const x of p.products) lines.push(`- ${x}`);\n lines.push('');\n }\n if (p.topGoals && p.topGoals.length > 0) {\n lines.push('## Top goals');\n for (const x of p.topGoals) lines.push(`- ${x}`);\n lines.push('');\n }\n if (p.blockers && p.blockers.length > 0) {\n lines.push('## Blockers');\n for (const x of p.blockers) lines.push(`- ${x}`);\n lines.push('');\n }\n if (p.tools && p.tools.length > 0) {\n lines.push('## Tools');\n for (const x of p.tools) lines.push(`- ${x}`);\n lines.push('');\n }\n if (p.customTools) {\n lines.push('## Custom tools');\n lines.push(p.customTools);\n lines.push('');\n }\n lines.push('> Migrated from `business-profile.json` on ' + nowIso() + '.');\n return lines.join('\\n');\n}\n\nfunction mapItem(item: BusinessContext): { type: PageType; slug: string; frontmatter: PageFrontmatter; body: string } | null {\n const today = nowIso().slice(0, 10);\n const slug = toSlug(item.title);\n if (!slug) return null;\n let type: PageType = 'concept';\n switch (item.category) {\n case 'company':\n case 'team':\n case 'product':\n case 'tools':\n case 'industry':\n case 'market':\n type = 'entity';\n break;\n case 'goals':\n case 'challenges':\n case 'strategy':\n type = 'concept';\n break;\n }\n const confidence: 'high' | 'medium' | 'low' = item.confidence >= 0.8 ? 'high' : item.confidence >= 0.5 ? 'medium' : 'low';\n const provenance: 'extracted' | 'inferred' = item.extractedFrom && item.extractedFrom !== 'manual' ? 'extracted' : 'inferred';\n const fm: PageFrontmatter = {\n title: item.title,\n slug,\n type,\n summary: item.description.slice(0, 200),\n tags: [item.category, ...(item.relevantKeywords ?? [])].filter(Boolean) as string[],\n sources: item.extractedFrom ? [`discussion:${item.extractedFrom}`] : [],\n confidence,\n provenance,\n created: (item.createdAt ?? today).slice(0, 10),\n updated: (item.updatedAt ?? today).slice(0, 10),\n userEdited: false,\n };\n const body = [\n `# ${item.title}`,\n '',\n item.description,\n '',\n '> Migrated from `business-context.json` on ' + nowIso() + '.',\n ].join('\\n');\n return { type, slug, frontmatter: fm, body };\n}\n\n// Silence unused\nvoid writeFileSync;\nvoid mkdirSync;\nvoid dirname;\n","/**\n * `aab members` — full Phase 2 surface.\n *\n * aab members list flat or --json\n * aab members show <name|id> full persona / voice / tools\n * aab members add interactive (name/title/expertise/persona OR --enhance <type>)\n * aab members edit <id|name> interactive field-by-field edit\n * aab members enhance <id|name> AI-fill persona + voiceGuide via claude -p\n * aab members delete <id|name> also removes .claude/agents/<slug>.md\n * aab members sync-agents regenerate .claude/agents/*.md (preserves user-edited)\n * aab members tools <id|name> per-member tool allowlist editor\n * aab members regenerate-voice <id> voice-guide-only refresh\n */\nimport { Command } from 'commander';\nimport { existsSync, unlinkSync } from 'node:fs';\nimport { closeContext, openContext } from './_context.js';\nimport { c, memberColor } from '../ui/colors.js';\nimport { askConfirm, askMultiSelect, askSelect, askText } from '../ui/prompts.js';\nimport { spinner } from '../ui/spinner.js';\nimport {\n emitMemberAgentFile,\n memberAgentPath,\n memberAgentSlug,\n} from '../agents/emit-member-agent.js';\nimport { generateUUID, nowIso } from '../core/utils.js';\nimport { UserError } from '../core/errors.js';\nimport { enhancePersona, type EnhancementType } from '../core/members/ai-enhancer.js';\nimport { generateVoiceGuide } from '../core/members/voice-guide.js';\nimport type { AdvisoryBoardMember } from '../storage/types.js';\n\nconst DEFAULT_TOOL_PALETTE = ['WebSearch', 'WebFetch', 'Read', 'Grep', 'Glob'] as const;\n\nexport function registerMembersCommand(program: Command): void {\n const m = program.command('members').description('manage advisory-board members');\n\n // --------------------------------------------------------------\n // list\n // --------------------------------------------------------------\n m.command('list')\n .description('list all board members')\n .option('--active', 'only show active members')\n .option('--inactive', 'only show inactive members')\n .action(async (opts: { active?: boolean; inactive?: boolean }) => {\n const ctx = await openContext(m, { lock: false });\n try {\n let members = await ctx.storage.loadBoardMembers();\n if (opts.active) members = members.filter((mb) => mb.isActive);\n if (opts.inactive) members = members.filter((mb) => !mb.isActive);\n\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ members }, null, 2) + '\\n');\n return;\n }\n if (members.length === 0) {\n process.stdout.write(c.hint(' (no members — run `aab init` to seed starters)\\n'));\n return;\n }\n for (const member of members) {\n const status = member.isActive ? c.ok('active') : c.hint('inactive');\n const color = memberColor(member.name);\n process.stdout.write(\n ` ${color(member.name)} ${c.hint('· ' + member.title)} ${status}\\n`,\n );\n }\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // show\n // --------------------------------------------------------------\n m.command('show <idOrName>')\n .description('show full persona, voice guide, and tool overrides')\n .action(async (idOrName: string) => {\n const ctx = await openContext(m, { lock: false });\n try {\n const member = await resolveMember(ctx.storage.loadBoardMembers(), idOrName);\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ member }, null, 2) + '\\n');\n return;\n }\n const color = memberColor(member.name);\n process.stdout.write(`\\n${color(c.bold(member.name))} ${c.hint('· ' + member.title)}\\n`);\n process.stdout.write(` ${c.hint('id:')} ${member.id}\\n`);\n process.stdout.write(` ${c.hint('status:')} ${member.isActive ? c.ok('active') : c.hint('inactive')}\\n`);\n process.stdout.write(` ${c.hint('expertise:')} ${member.expertise.join(', ') || '(none)'}\\n`);\n if (member.allowedTools && member.allowedTools.length > 0) {\n process.stdout.write(` ${c.hint('tools (allow):')} ${member.allowedTools.join(', ')}\\n`);\n }\n if (member.disallowedTools && member.disallowedTools.length > 0) {\n process.stdout.write(` ${c.hint('tools (deny):')} ${member.disallowedTools.join(', ')}\\n`);\n }\n process.stdout.write(`\\n${c.bold('Persona')}\\n${member.persona}\\n`);\n if (member.voiceGuide) {\n process.stdout.write(`\\n${c.bold('Voice guide')}\\n${member.voiceGuide}\\n`);\n }\n process.stdout.write('\\n');\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // add\n // --------------------------------------------------------------\n m.command('add')\n .description('add a new board member (interactive; --enhance for AI persona)')\n .option('--name <name>', 'member name')\n .option('--title <title>', 'role / title')\n .option('--expertise <list>', 'comma-separated expertise areas')\n .option('--persona <text>', 'persona text (or omit and use --enhance)')\n .option('--voice-guide <text>', 'voice guide text')\n .option(\n '--enhance <type>',\n 'AI-fill persona + voiceGuide. type: famous | expert | non-famous',\n )\n .option('--inactive', 'create the member as inactive')\n .action(\n async (opts: {\n name?: string;\n title?: string;\n expertise?: string;\n persona?: string;\n voiceGuide?: string;\n enhance?: string;\n inactive?: boolean;\n }) => {\n const ctx = await openContext(m);\n try {\n const name = opts.name ?? (await askText('Name', { required: true }));\n const title = opts.title ?? (await askText('Title / role', { required: true }));\n const expertiseRaw =\n opts.expertise ?? (await askText('Expertise (comma-separated)'));\n const expertise = expertiseRaw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n\n let persona = opts.persona;\n let voiceGuide = opts.voiceGuide;\n if (opts.enhance) {\n const type = normalizeEnhanceType(opts.enhance);\n const settings = await ctx.storage.loadSettings();\n const sp = spinner(`Enhancing persona (${type})...`);\n sp.start();\n try {\n const result = await enhancePersona(\n { name, title, expertise, type },\n settings,\n { currentPersona: persona },\n );\n persona = result.persona;\n voiceGuide = voiceGuide ?? result.voiceGuide;\n sp.succeed(`Enhanced persona (${persona.length} chars).`);\n } catch (error) {\n sp.fail(`Enhancement failed: ${error instanceof Error ? error.message : String(error)}`);\n if (!persona) {\n throw new UserError(\n 'Persona could not be generated and none was supplied — pass --persona or fix the enhancement error.',\n );\n }\n }\n }\n\n if (!persona) {\n persona = await askText('Persona (multi-line OK; press enter when done)', {\n required: true,\n });\n }\n\n const now = nowIso();\n const member: AdvisoryBoardMember = {\n id: generateUUID(),\n name,\n title,\n expertise,\n persona,\n voiceGuide: voiceGuide || undefined,\n isActive: !opts.inactive,\n createdAt: now,\n updatedAt: now,\n };\n await ctx.storage.saveBoardMember(member);\n\n // Emit the .claude/agents/<slug>.md file.\n const result = emitMemberAgentFile(member, { projectRoot: process.cwd() });\n\n if (ctx.json) {\n process.stdout.write(\n JSON.stringify({ member, agentFile: result }, null, 2) + '\\n',\n );\n return;\n }\n process.stdout.write(\n `${c.ok('✓')} Added member ${memberColor(name)(name)} (id ${member.id.slice(0, 8)})\\n`,\n );\n if (result.written) {\n process.stdout.write(c.hint(` → wrote ${result.path}\\n`));\n } else {\n process.stdout.write(c.hint(` — agent file skipped: ${result.reason}\\n`));\n }\n } finally {\n await closeContext(ctx);\n }\n },\n );\n\n // --------------------------------------------------------------\n // edit\n // --------------------------------------------------------------\n m.command('edit <idOrName>')\n .description('interactively edit a member (field-by-field)')\n .option('--active <bool>', 'set active flag (true|false)')\n .option('--name <name>')\n .option('--title <title>')\n .option('--expertise <list>')\n .option('--persona <text>')\n .option('--voice-guide <text>')\n .action(\n async (\n idOrName: string,\n opts: {\n active?: string;\n name?: string;\n title?: string;\n expertise?: string;\n persona?: string;\n voiceGuide?: string;\n },\n ) => {\n const ctx = await openContext(m);\n try {\n const member = await resolveMember(ctx.storage.loadBoardMembers(), idOrName);\n\n // Apply flag-supplied edits first (non-interactive path), then prompt\n // interactively for anything that wasn't overridden when the user\n // didn't pass any flags at all.\n const flagsTouched =\n !!opts.name ||\n !!opts.title ||\n !!opts.expertise ||\n !!opts.persona ||\n !!opts.voiceGuide ||\n !!opts.active;\n\n let next: AdvisoryBoardMember = { ...member };\n if (opts.name) next.name = opts.name;\n if (opts.title) next.title = opts.title;\n if (opts.expertise) {\n next.expertise = opts.expertise.split(',').map((s) => s.trim()).filter(Boolean);\n }\n if (opts.persona) next.persona = opts.persona;\n if (opts.voiceGuide) next.voiceGuide = opts.voiceGuide;\n if (opts.active) next.isActive = opts.active === 'true' || opts.active === '1';\n\n if (!flagsTouched) {\n next.name = await askText('Name', { initial: next.name, required: true });\n next.title = await askText('Title', { initial: next.title, required: true });\n const expertiseRaw = await askText('Expertise (comma-separated)', {\n initial: next.expertise.join(', '),\n });\n next.expertise = expertiseRaw.split(',').map((s) => s.trim()).filter(Boolean);\n next.persona = await askText('Persona', { initial: next.persona, required: true });\n next.voiceGuide = await askText('Voice guide', { initial: next.voiceGuide ?? '' });\n next.isActive = await askConfirm('Active?', next.isActive);\n }\n next.updatedAt = nowIso();\n\n await ctx.storage.updateBoardMember(next);\n\n // Regenerate the .claude/agents/<slug>.md file (renames if name changed).\n if (next.name !== member.name) {\n const oldPath = memberAgentPath(memberAgentSlug(member.name), process.cwd());\n if (existsSync(oldPath)) unlinkSync(oldPath);\n }\n const agent = emitMemberAgentFile(next, { projectRoot: process.cwd() });\n\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ member: next, agentFile: agent }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`${c.ok('✓')} Updated ${memberColor(next.name)(next.name)}\\n`);\n if (agent.written) process.stdout.write(c.hint(` → wrote ${agent.path}\\n`));\n else process.stdout.write(c.hint(` — agent file skipped: ${agent.reason}\\n`));\n } finally {\n await closeContext(ctx);\n }\n },\n );\n\n // --------------------------------------------------------------\n // enhance\n // --------------------------------------------------------------\n m.command('enhance <idOrName>')\n .description('AI-fill persona + voiceGuide via claude -p')\n .option(\n '--type <type>',\n 'famous | expert | non-famous (default: non-famous)',\n 'non-famous',\n )\n .option('--keep-voice', 'do not overwrite existing voiceGuide')\n .action(async (idOrName: string, opts: { type?: string; keepVoice?: boolean }) => {\n const ctx = await openContext(m);\n try {\n const member = await resolveMember(ctx.storage.loadBoardMembers(), idOrName);\n const type = normalizeEnhanceType(opts.type ?? 'non-famous');\n const settings = await ctx.storage.loadSettings();\n const sp = spinner(`Enhancing ${member.name} (${type})...`);\n sp.start();\n try {\n const result = await enhancePersona(\n {\n name: member.name,\n title: member.title,\n expertise: member.expertise,\n type,\n },\n settings,\n { currentPersona: member.persona },\n );\n sp.succeed(`Enhanced (${result.persona.length} chars).`);\n\n const next: AdvisoryBoardMember = {\n ...member,\n persona: result.persona,\n voiceGuide: opts.keepVoice\n ? member.voiceGuide\n : result.voiceGuide || member.voiceGuide,\n updatedAt: nowIso(),\n };\n await ctx.storage.updateBoardMember(next);\n const agent = emitMemberAgentFile(next, { projectRoot: process.cwd() });\n\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ member: next, agentFile: agent }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`${c.ok('✓')} Persona refreshed for ${memberColor(next.name)(next.name)}\\n`);\n if (agent.written) process.stdout.write(c.hint(` → wrote ${agent.path}\\n`));\n } catch (error) {\n sp.fail(`Enhancement failed: ${error instanceof Error ? error.message : String(error)}`);\n throw error;\n }\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // delete\n // --------------------------------------------------------------\n m.command('delete <idOrName>')\n .description('delete a member and remove its .claude/agents/<slug>.md')\n .option('--yes', 'skip confirmation prompt')\n .action(async (idOrName: string, opts: { yes?: boolean }) => {\n const ctx = await openContext(m);\n try {\n const member = await resolveMember(ctx.storage.loadBoardMembers(), idOrName);\n if (!opts.yes) {\n const ok = await askConfirm(`Delete ${member.name}? This cannot be undone.`, false);\n if (!ok) {\n process.stdout.write(c.hint(' aborted.\\n'));\n return;\n }\n }\n await ctx.storage.deleteBoardMember(member.id);\n const path = memberAgentPath(memberAgentSlug(member.name), process.cwd());\n let removedAgent = false;\n if (existsSync(path)) {\n try {\n unlinkSync(path);\n removedAgent = true;\n } catch {\n /* ignore — show warning instead */\n }\n }\n if (ctx.json) {\n process.stdout.write(\n JSON.stringify({ deleted: { id: member.id, name: member.name }, removedAgent }, null, 2) + '\\n',\n );\n return;\n }\n process.stdout.write(`${c.ok('✓')} Deleted ${member.name}\\n`);\n if (removedAgent) process.stdout.write(c.hint(` → removed ${path}\\n`));\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // sync-agents (kept from Phase 1.5)\n // --------------------------------------------------------------\n m.command('sync-agents')\n .description('regenerate .claude/agents/<slug>.md for every active member (preserves user-edited files)')\n .option('--agents-dir <path>', 'where .claude/agents/ should live (default: cwd)')\n .option('--all', 'include inactive members too')\n .action(async (opts: { agentsDir?: string; all?: boolean }) => {\n const ctx = await openContext(m);\n try {\n const members = await ctx.storage.loadBoardMembers();\n const projectRoot = opts.agentsDir ?? process.cwd();\n let written = 0;\n let skipped = 0;\n const skippedDetail: string[] = [];\n for (const member of members) {\n if (!opts.all && !member.isActive) continue;\n const slug = memberAgentSlug(member.name);\n const path = memberAgentPath(slug, projectRoot);\n const result = emitMemberAgentFile(member, { projectRoot });\n if (result.written) {\n written++;\n } else {\n skipped++;\n skippedDetail.push(`${slug} (${result.reason ?? 'unknown'})`);\n }\n if (!ctx.json) {\n process.stdout.write(` ${result.written ? c.ok('✓') : c.warn('—')} ${slug} ${c.hint(path)}\\n`);\n }\n }\n if (ctx.json) {\n process.stdout.write(\n JSON.stringify({ written, skipped, skippedDetail, total: members.length }, null, 2) + '\\n',\n );\n return;\n }\n process.stdout.write(`\\n${c.ok('✓')} sync complete: ${written} written, ${skipped} skipped\\n`);\n if (skippedDetail.length > 0) {\n process.stdout.write(c.hint(` ${skippedDetail.join('; ')}\\n`));\n }\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // tools — per-member allowlist editor\n // --------------------------------------------------------------\n m.command('tools <idOrName>')\n .description('edit per-member tool allowlist (overrides workspace default)')\n .option('--allow <list>', 'comma-separated allowlist; empty string clears the override')\n .option('--deny <list>', 'comma-separated denylist; empty string clears the override')\n .option('--reset', 'clear both allow and deny overrides (use workspace default)')\n .action(\n async (\n idOrName: string,\n opts: { allow?: string; deny?: string; reset?: boolean },\n ) => {\n const ctx = await openContext(m);\n try {\n const member = await resolveMember(ctx.storage.loadBoardMembers(), idOrName);\n let allowed = member.allowedTools;\n let denied = member.disallowedTools;\n\n if (opts.reset) {\n allowed = undefined;\n denied = undefined;\n } else if (opts.allow !== undefined || opts.deny !== undefined) {\n if (opts.allow !== undefined) {\n const list = parseToolList(opts.allow);\n allowed = list.length === 0 ? undefined : list;\n }\n if (opts.deny !== undefined) {\n const list = parseToolList(opts.deny);\n denied = list.length === 0 ? undefined : list;\n }\n } else {\n const current = new Set(member.allowedTools ?? DEFAULT_TOOL_PALETTE);\n const choices = DEFAULT_TOOL_PALETTE.map((tool) => ({\n name: tool,\n message: tool,\n selected: current.has(tool),\n }));\n const picked = await askMultiSelect<string>('Allowed tools for this member', choices);\n allowed = picked.length === 0 ? undefined : picked;\n }\n\n const next: AdvisoryBoardMember = {\n ...member,\n allowedTools: allowed,\n disallowedTools: denied,\n updatedAt: nowIso(),\n };\n await ctx.storage.updateBoardMember(next);\n const agent = emitMemberAgentFile(next, { projectRoot: process.cwd() });\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ member: next, agentFile: agent }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(\n `${c.ok('✓')} Tools updated for ${memberColor(next.name)(next.name)} — allow: [${(allowed ?? DEFAULT_TOOL_PALETTE).join(', ')}]\\n`,\n );\n if (agent.written) process.stdout.write(c.hint(` → wrote ${agent.path}\\n`));\n } finally {\n await closeContext(ctx);\n }\n },\n );\n\n // --------------------------------------------------------------\n // regenerate-voice\n // --------------------------------------------------------------\n m.command('regenerate-voice <idOrName>')\n .description('voice-guide-only refresh via the fast model')\n .option('--keep-old', 'show a preview and ask before overwriting')\n .action(async (idOrName: string, opts: { keepOld?: boolean }) => {\n const ctx = await openContext(m);\n try {\n const member = await resolveMember(ctx.storage.loadBoardMembers(), idOrName);\n const settings = await ctx.storage.loadSettings();\n const sp = spinner(`Regenerating voice guide for ${member.name}...`);\n sp.start();\n const result = await generateVoiceGuide(member, settings);\n if (result.fellBack) {\n sp.warn(`Fell back to hardcoded voice guide: ${result.error ?? 'unknown'}`);\n } else {\n sp.succeed(`Voice guide refreshed (${result.voiceGuide.length} chars).`);\n }\n\n if (opts.keepOld && member.voiceGuide) {\n process.stdout.write(`\\n${c.hint('Old:')} ${member.voiceGuide}\\n`);\n process.stdout.write(`\\n${c.hint('New:')} ${result.voiceGuide}\\n`);\n const ok = await askConfirm('Overwrite?', true);\n if (!ok) {\n process.stdout.write(c.hint(' aborted.\\n'));\n return;\n }\n }\n\n const next: AdvisoryBoardMember = {\n ...member,\n voiceGuide: result.voiceGuide,\n updatedAt: nowIso(),\n };\n await ctx.storage.updateBoardMember(next);\n const agent = emitMemberAgentFile(next, { projectRoot: process.cwd() });\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ member: next, fellBack: result.fellBack, agentFile: agent }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`${c.ok('✓')} Voice guide saved for ${memberColor(next.name)(next.name)}\\n`);\n if (agent.written) process.stdout.write(c.hint(` → wrote ${agent.path}\\n`));\n } finally {\n await closeContext(ctx);\n }\n });\n}\n\n// ----------------------------------------------------------------\n// Helpers\n// ----------------------------------------------------------------\n\nasync function resolveMember(\n loader: Promise<AdvisoryBoardMember[]>,\n idOrName: string,\n): Promise<AdvisoryBoardMember> {\n const members = await loader;\n const lower = idOrName.toLowerCase();\n const byId = members.find((m) => m.id === idOrName);\n if (byId) return byId;\n const byShortId = members.find((m) => m.id.startsWith(idOrName) && idOrName.length >= 4);\n if (byShortId) return byShortId;\n const byName = members.find((m) => m.name.toLowerCase() === lower);\n if (byName) return byName;\n const byPartial = members.filter((m) => m.name.toLowerCase().includes(lower));\n if (byPartial.length === 1 && byPartial[0]) return byPartial[0];\n if (byPartial.length > 1) {\n throw new UserError(\n `Ambiguous member: \"${idOrName}\" matches ${byPartial.map((m) => m.name).join(', ')}`,\n 'Use the full name or member id.',\n );\n }\n throw new UserError(\n `No member matches \"${idOrName}\"`,\n 'Run `aab members list` to see available members.',\n );\n}\n\nfunction normalizeEnhanceType(input: string): EnhancementType {\n const v = input.toLowerCase().trim();\n if (v === 'famous' || v === 'famous_person' || v === 'famous-person') return 'famous';\n if (v === 'expert' || v === 'top-expert' || v === 'top_expert') return 'expert';\n if (v === 'non-famous' || v === 'non_famous' || v === 'practitioner') return 'non-famous';\n throw new UserError(\n `Unknown enhance type \"${input}\"`,\n 'Use one of: famous | expert | non-famous.',\n );\n}\n\nfunction parseToolList(raw: string): string[] {\n return raw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n}\n","/**\n * `aab principles` — Phase 2 principles surface.\n *\n * aab principles list flat or --json; filters\n * aab principles add interactive (title/desc/cat/priority/behavior/anti)\n * aab principles edit <id|name> field-by-field interactive\n * aab principles delete <id|name> with confirmation\n * aab principles seed-starters re-seed 8 starters (no-op if any exist unless --force)\n * aab principles explore [--principle <id|name>] 5-step Socratic wizard (behavior → anti → triggers → examples → priority)\n */\nimport { Command } from 'commander';\nimport { closeContext, openContext } from './_context.js';\nimport { c } from '../ui/colors.js';\nimport { askConfirm, askSelect, askText } from '../ui/prompts.js';\nimport { spinner } from '../ui/spinner.js';\nimport { generateUUID, nowIso } from '../core/utils.js';\nimport { UserError } from '../core/errors.js';\nimport { STARTER_PRINCIPLES } from '../starter/starter-principles.js';\nimport {\n EXPLORER_STEPS,\n applyStep,\n explorerReply,\n type ExplorerStep,\n type ExplorerTurn,\n} from '../core/coach/principle-explorer.js';\nimport type { Principle, PrincipleCategory } from '../storage/types.js';\n\nconst CATEGORIES: PrincipleCategory[] = ['life', 'work', 'relationships', 'health', 'finance', 'meta'];\n\nexport function registerPrinciplesCommand(program: Command): void {\n const p = program.command('principles').description('manage decision-making principles');\n\n // --------------------------------------------------------------\n // list\n // --------------------------------------------------------------\n p.command('list')\n .description('list all principles')\n .option('--category <cat>', 'filter by category: ' + CATEGORIES.join(' | '))\n .option('--active', 'only active principles')\n .option('--inactive', 'only inactive principles')\n .action(async (opts: { category?: string; active?: boolean; inactive?: boolean }) => {\n const ctx = await openContext(p, { lock: false });\n try {\n let principles = await ctx.storage.loadPrinciples();\n if (opts.category) {\n if (!CATEGORIES.includes(opts.category as PrincipleCategory)) {\n throw new UserError(\n `Unknown category \"${opts.category}\"`,\n `Pick one of: ${CATEGORIES.join(', ')}`,\n );\n }\n principles = principles.filter((pp) => pp.category === opts.category);\n }\n if (opts.active) principles = principles.filter((pp) => pp.isActive);\n if (opts.inactive) principles = principles.filter((pp) => !pp.isActive);\n\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ principles }, null, 2) + '\\n');\n return;\n }\n if (principles.length === 0) {\n process.stdout.write(c.hint(' (no principles match — run `aab principles seed-starters` to seed defaults)\\n'));\n return;\n }\n principles.sort((a, b) => b.priority - a.priority);\n for (const pp of principles) {\n const status = pp.isActive ? c.ok('active') : c.hint('inactive');\n process.stdout.write(\n ` [${c.cyan(String(pp.priority).padStart(2))}] ${c.bold(pp.title)} ` +\n c.hint(`· ${pp.category}`) +\n ` ${status}\\n`,\n );\n if (pp.description) process.stdout.write(c.hint(` ${truncate(pp.description, 110)}\\n`));\n }\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // show\n // --------------------------------------------------------------\n p.command('show <idOrTitle>')\n .description('show full principle detail')\n .action(async (idOrTitle: string) => {\n const ctx = await openContext(p, { lock: false });\n try {\n const principle = await resolvePrinciple(ctx.storage.loadPrinciples(), idOrTitle);\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ principle }, null, 2) + '\\n');\n return;\n }\n renderPrincipleDetail(principle);\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // add\n // --------------------------------------------------------------\n p.command('add')\n .description('add a new principle (interactive)')\n .option('--title <title>')\n .option('--description <text>')\n .option('--category <cat>')\n .option('--priority <n>')\n .option('--behavior <text>')\n .option('--anti-pattern <text>')\n .action(\n async (opts: {\n title?: string;\n description?: string;\n category?: string;\n priority?: string;\n behavior?: string;\n antiPattern?: string;\n }) => {\n const ctx = await openContext(p);\n try {\n const title = opts.title ?? (await askText('Title', { required: true }));\n const description = opts.description ?? (await askText('Description', { required: true }));\n const categoryRaw =\n opts.category ??\n (await askSelect<PrincipleCategory>(\n 'Category',\n CATEGORIES.map((cat) => ({ name: cat, message: cat })),\n ));\n const category = normalizeCategory(categoryRaw);\n const priorityRaw =\n opts.priority ??\n (await askText('Priority (1-10)', { initial: '5' }));\n const priority = clampPriority(priorityRaw);\n const behavior =\n opts.behavior ??\n (await askText('Behavior (when and how to apply this)', { required: true }));\n const antiPattern =\n opts.antiPattern ?? (await askText('Anti-pattern (what violating this looks like; optional)'));\n\n const now = nowIso();\n const principle: Principle = {\n id: generateUUID(),\n category,\n title,\n description,\n behavior,\n antiPattern: antiPattern || undefined,\n triggerQuestions: undefined,\n priority,\n examples: undefined,\n isActive: true,\n createdAt: now,\n updatedAt: now,\n };\n await ctx.storage.savePrinciple(principle);\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ principle }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`${c.ok('✓')} Added principle ${c.bold(title)} (id ${principle.id.slice(0, 8)})\\n`);\n } finally {\n await closeContext(ctx);\n }\n },\n );\n\n // --------------------------------------------------------------\n // edit\n // --------------------------------------------------------------\n p.command('edit <idOrTitle>')\n .description('interactively edit a principle')\n .option('--active <bool>')\n .option('--title <title>')\n .option('--description <text>')\n .option('--category <cat>')\n .option('--priority <n>')\n .option('--behavior <text>')\n .option('--anti-pattern <text>')\n .action(\n async (\n idOrTitle: string,\n opts: {\n active?: string;\n title?: string;\n description?: string;\n category?: string;\n priority?: string;\n behavior?: string;\n antiPattern?: string;\n },\n ) => {\n const ctx = await openContext(p);\n try {\n const principle = await resolvePrinciple(ctx.storage.loadPrinciples(), idOrTitle);\n const flagsTouched =\n !!opts.title ||\n !!opts.description ||\n !!opts.category ||\n !!opts.priority ||\n !!opts.behavior ||\n !!opts.antiPattern ||\n !!opts.active;\n\n let next: Principle = { ...principle };\n if (opts.title) next.title = opts.title;\n if (opts.description) next.description = opts.description;\n if (opts.category) next.category = normalizeCategory(opts.category);\n if (opts.priority) next.priority = clampPriority(opts.priority);\n if (opts.behavior) next.behavior = opts.behavior;\n if (opts.antiPattern) next.antiPattern = opts.antiPattern;\n if (opts.active) next.isActive = opts.active === 'true' || opts.active === '1';\n\n if (!flagsTouched) {\n next.title = await askText('Title', { initial: next.title, required: true });\n next.description = await askText('Description', { initial: next.description, required: true });\n const cat = await askSelect<PrincipleCategory>(\n 'Category',\n CATEGORIES.map((c) => ({ name: c, message: c })),\n { initial: next.category },\n );\n next.category = cat;\n const pr = await askText('Priority (1-10)', { initial: String(next.priority) });\n next.priority = clampPriority(pr);\n next.behavior = await askText('Behavior', { initial: next.behavior, required: true });\n next.antiPattern = await askText('Anti-pattern', { initial: next.antiPattern ?? '' });\n next.isActive = await askConfirm('Active?', next.isActive);\n }\n next.updatedAt = nowIso();\n await ctx.storage.updatePrinciple(next);\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ principle: next }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`${c.ok('✓')} Updated ${c.bold(next.title)}\\n`);\n } finally {\n await closeContext(ctx);\n }\n },\n );\n\n // --------------------------------------------------------------\n // delete\n // --------------------------------------------------------------\n p.command('delete <idOrTitle>')\n .description('delete a principle')\n .option('--yes', 'skip confirmation prompt')\n .action(async (idOrTitle: string, opts: { yes?: boolean }) => {\n const ctx = await openContext(p);\n try {\n const principle = await resolvePrinciple(ctx.storage.loadPrinciples(), idOrTitle);\n if (!opts.yes) {\n const ok = await askConfirm(`Delete principle \"${principle.title}\"?`, false);\n if (!ok) {\n process.stdout.write(c.hint(' aborted.\\n'));\n return;\n }\n }\n await ctx.storage.deletePrinciple(principle.id);\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ deleted: principle.id }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`${c.ok('✓')} Deleted ${principle.title}\\n`);\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // seed-starters\n // --------------------------------------------------------------\n p.command('seed-starters')\n .description('seed 8 Dalio-inspired starters (skips by default if any principle exists)')\n .option('--force', 'add starters even if there are already principles in the workspace')\n .action(async (opts: { force?: boolean }) => {\n const ctx = await openContext(p);\n try {\n const existing = await ctx.storage.loadPrinciples();\n if (existing.length > 0 && !opts.force) {\n process.stdout.write(\n c.warn(\n ` ${existing.length} principle${existing.length === 1 ? '' : 's'} already exist — pass --force to add starters on top.\\n`,\n ),\n );\n return;\n }\n const now = nowIso();\n let added = 0;\n for (const starter of STARTER_PRINCIPLES) {\n const principle: Principle = {\n id: generateUUID(),\n category: starter.category,\n title: starter.title,\n description: starter.description,\n behavior: starter.behavior,\n antiPattern: starter.antiPattern,\n triggerQuestions: starter.triggerQuestions,\n priority: starter.priority,\n examples: starter.examples,\n isActive: starter.isActive,\n createdAt: now,\n updatedAt: now,\n };\n await ctx.storage.savePrinciple(principle);\n added++;\n }\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ added }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`${c.ok('✓')} Seeded ${added} starter principle${added === 1 ? '' : 's'}.\\n`);\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // explore — 5-step Socratic wizard\n // --------------------------------------------------------------\n p.command('explore')\n .description('5-step Socratic wizard: behavior → anti-pattern → triggers → examples → priority')\n .option('--principle <idOrTitle>', 'principle to refine (default: pick interactively)')\n .option('--title <title>', 'start a new draft principle with this title')\n .option('--description <text>', 'description for a new draft')\n .option('--category <cat>', 'category for a new draft')\n .option('--auto-accept', 'accept synthesised answers without confirmation')\n .option('--save-as-new', 'save the explored draft as a new principle (default: overwrite if --principle given)')\n .action(\n async (opts: {\n principle?: string;\n title?: string;\n description?: string;\n category?: string;\n autoAccept?: boolean;\n saveAsNew?: boolean;\n }) => {\n const ctx = await openContext(p);\n try {\n const all = await ctx.storage.loadPrinciples();\n let working: Principle | (Omit<Principle, 'id' | 'createdAt' | 'updatedAt'> & { id?: string });\n let isExisting = false;\n if (opts.principle) {\n const target = await resolvePrinciple(Promise.resolve(all), opts.principle);\n working = { ...target };\n isExisting = true;\n } else if (opts.title) {\n working = {\n title: opts.title,\n description: opts.description ?? '',\n category: normalizeCategory(opts.category ?? 'work'),\n priority: 5,\n behavior: '',\n isActive: true,\n };\n } else if (all.length > 0) {\n const choice = await askSelect<string>(\n 'Refine which principle?',\n [\n { name: '__new__', message: '(new draft)' },\n ...all.map((pp) => ({ name: pp.id, message: pp.title })),\n ],\n );\n if (choice === '__new__') {\n working = {\n title: await askText('Draft title', { required: true }),\n description: await askText('Draft description', { required: true }),\n category: normalizeCategory(\n await askSelect<PrincipleCategory>(\n 'Category',\n CATEGORIES.map((c) => ({ name: c, message: c })),\n ),\n ),\n priority: 5,\n behavior: '',\n isActive: true,\n };\n } else {\n const found = all.find((pp) => pp.id === choice);\n if (!found) throw new UserError(`Principle ${choice} not found`);\n working = { ...found };\n isExisting = true;\n }\n } else {\n working = {\n title: await askText('Draft title', { required: true }),\n description: await askText('Draft description', { required: true }),\n category: normalizeCategory(\n await askSelect<PrincipleCategory>(\n 'Category',\n CATEGORIES.map((c) => ({ name: c, message: c })),\n ),\n ),\n priority: 5,\n behavior: '',\n isActive: true,\n };\n }\n\n const settings = await ctx.storage.loadSettings();\n const history: ExplorerTurn[] = [];\n for (const step of EXPLORER_STEPS) {\n process.stdout.write(`\\n${c.bold(c.cyan(`Step: ${step}`))}\\n`);\n let userInput = '';\n let synthesised = false;\n let suggested: string | undefined;\n let firstIteration = true;\n // Up to 4 turns per step.\n for (let turn = 0; turn < 4 && !synthesised; turn++) {\n const sp = spinner('Coach thinking...');\n sp.start();\n let result;\n try {\n result = await explorerReply(\n {\n principle: working,\n history,\n step,\n isFirstMessage: firstIteration,\n },\n userInput,\n settings,\n );\n sp.stop();\n } catch (error) {\n sp.fail(`Coach failed: ${error instanceof Error ? error.message : String(error)}`);\n throw error;\n }\n process.stdout.write(`${c.gray('coach:')}\\n${result.reply}\\n\\n`);\n if (userInput) {\n history.push({ step, role: 'user', content: userInput });\n }\n history.push({ step, role: 'assistant', content: result.reply });\n if (result.synthesised && result.suggested) {\n synthesised = true;\n suggested = result.suggested;\n break;\n }\n firstIteration = false;\n userInput = await askText('you', { required: true });\n }\n\n if (!suggested) {\n const finalInput = await askText(\n 'Provide your own answer for this step (or press Enter to skip)',\n );\n if (finalInput.trim()) suggested = finalInput.trim();\n }\n\n if (suggested) {\n if (!opts.autoAccept) {\n const ok = await askConfirm(`Apply this ${step}?`, true);\n if (!ok) {\n process.stdout.write(c.hint(' skipped.\\n'));\n continue;\n }\n }\n working = applyStep(working, step, suggested) as typeof working;\n }\n }\n\n if (!isExisting || opts.saveAsNew) {\n const now = nowIso();\n const principle: Principle = {\n id: generateUUID(),\n category: working.category,\n title: working.title,\n description: working.description,\n behavior: working.behavior ?? '',\n antiPattern: working.antiPattern,\n triggerQuestions: working.triggerQuestions,\n priority: working.priority ?? 5,\n examples: working.examples,\n isActive: working.isActive ?? true,\n createdAt: now,\n updatedAt: now,\n };\n await ctx.storage.savePrinciple(principle);\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ principle, mode: 'created' }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`\\n${c.ok('✓')} Created principle ${c.bold(principle.title)}\\n`);\n } else {\n const id = (working as Principle).id;\n const next: Principle = {\n ...(working as Principle),\n id,\n updatedAt: nowIso(),\n };\n await ctx.storage.updatePrinciple(next);\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ principle: next, mode: 'updated' }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`\\n${c.ok('✓')} Updated ${c.bold(next.title)}\\n`);\n }\n } finally {\n await closeContext(ctx);\n }\n },\n );\n}\n\n// ----------------------------------------------------------------\n// Helpers\n// ----------------------------------------------------------------\n\nfunction renderPrincipleDetail(p: Principle): void {\n process.stdout.write(\n `\\n${c.bold(p.title)} ${c.hint(`· ${p.category} · priority ${p.priority}/10 · ${p.isActive ? 'active' : 'inactive'}`)}\\n`,\n );\n process.stdout.write(` ${c.hint('id:')} ${p.id}\\n`);\n process.stdout.write(`\\n${c.bold('Description')}\\n${p.description}\\n`);\n process.stdout.write(`\\n${c.bold('Behavior')}\\n${p.behavior}\\n`);\n if (p.antiPattern) process.stdout.write(`\\n${c.bold('Anti-pattern')}\\n${p.antiPattern}\\n`);\n if (p.triggerQuestions && p.triggerQuestions.length > 0) {\n process.stdout.write(`\\n${c.bold('Trigger questions')}\\n`);\n for (const q of p.triggerQuestions) process.stdout.write(` - ${q}\\n`);\n }\n if (p.examples && p.examples.length > 0) {\n process.stdout.write(`\\n${c.bold('Examples')}\\n`);\n for (const e of p.examples) process.stdout.write(` - ${e}\\n`);\n }\n process.stdout.write('\\n');\n}\n\nasync function resolvePrinciple(\n loader: Promise<Principle[]>,\n idOrTitle: string,\n): Promise<Principle> {\n const principles = await loader;\n const lower = idOrTitle.toLowerCase();\n const byId = principles.find((pp) => pp.id === idOrTitle);\n if (byId) return byId;\n const byShortId = principles.find((pp) => pp.id.startsWith(idOrTitle) && idOrTitle.length >= 4);\n if (byShortId) return byShortId;\n const byTitle = principles.find((pp) => pp.title.toLowerCase() === lower);\n if (byTitle) return byTitle;\n const byPartial = principles.filter((pp) => pp.title.toLowerCase().includes(lower));\n if (byPartial.length === 1 && byPartial[0]) return byPartial[0];\n if (byPartial.length > 1) {\n throw new UserError(\n `Ambiguous principle: \"${idOrTitle}\" matches ${byPartial.map((pp) => pp.title).join(', ')}`,\n 'Use the full title or principle id.',\n );\n }\n throw new UserError(`No principle matches \"${idOrTitle}\"`, 'Run `aab principles list`.');\n}\n\nfunction normalizeCategory(raw: string): PrincipleCategory {\n const v = raw.toLowerCase().trim();\n if ((CATEGORIES as string[]).includes(v)) return v as PrincipleCategory;\n throw new UserError(`Unknown category \"${raw}\"`, `Pick one of: ${CATEGORIES.join(', ')}`);\n}\n\nfunction clampPriority(raw: string): number {\n const n = Number(raw);\n if (!Number.isFinite(n)) {\n throw new UserError(`Priority must be a number, got \"${raw}\"`);\n }\n return Math.max(1, Math.min(10, Math.round(n)));\n}\n\nfunction truncate(text: string, max: number): string {\n if (text.length <= max) return text;\n return text.slice(0, max - 1) + '…';\n}\n\n// Re-export so tsc's verbatim-module-syntax check is satisfied for the type import.\nexport type { ExplorerStep };\n","/**\n * `aab coach` — principle-based decision coach REPL.\n *\n * aab coach start a new session (interactive)\n * aab coach --resume <id> resume an existing session\n * aab coach send <id> \"<msg>\" send one message non-interactively\n * aab coach show [<id>] list sessions or print one\n * aab coach delete <id> remove a session\n */\nimport { Command } from 'commander';\nimport { closeContext, openContext } from './_context.js';\nimport { c } from '../ui/colors.js';\nimport { askConfirm, askText } from '../ui/prompts.js';\nimport { spinner } from '../ui/spinner.js';\nimport { UserError } from '../core/errors.js';\nimport { nowIso } from '../core/utils.js';\nimport { coachReply, newDecisionSession } from '../core/coach/decision-coach.js';\nimport type { DecisionSession } from '../storage/types.js';\n\nexport function registerCoachCommand(program: Command): void {\n const coach = program.command('coach').description('principle-based decision coach (Dalio-style)');\n\n // Default action (no subcommand) — interactive REPL, either new or resumed.\n coach\n .option('--resume <id>', 'resume an existing decision session')\n .option('--situation <text>', 'situation prompt (for a brand-new session)')\n .option('--title <text>', 'title for a brand-new session')\n .option('--no-stream', 'disable token streaming (useful for testing)')\n .action(async (opts: { resume?: string; situation?: string; title?: string; stream?: boolean }) => {\n // If the user invoked a subcommand, commander handles it. This action\n // only fires when there's no subcommand.\n const ctx = await openContext(coach);\n try {\n let session: DecisionSession;\n if (opts.resume) {\n const found = await ctx.storage.loadDecisionSessionById(opts.resume);\n if (!found) {\n const all = await ctx.storage.loadDecisionSessions();\n const byShort = all.find((s) => s.id.startsWith(opts.resume!));\n if (!byShort) throw new UserError(`No coach session matches \"${opts.resume}\"`);\n session = byShort;\n } else {\n session = found;\n }\n process.stdout.write(\n `${c.hint('Resuming session')} ${c.bold(session.id.slice(0, 8))} ${c.hint('(' + session.messages.length + ' messages)\\n')}`,\n );\n for (const m of session.messages) renderMessage(m.role, m.content);\n } else {\n const situation = opts.situation ?? (await askText('Describe the decision / situation', { required: true }));\n const title = opts.title ?? '';\n session = newDecisionSession(situation, title || undefined);\n await ctx.storage.saveDecisionSession(session);\n process.stdout.write(`${c.hint('Started new session')} ${c.bold(session.id.slice(0, 8))}\\n\\n`);\n }\n\n const settings = await ctx.storage.loadSettings();\n const principles = await ctx.storage.loadPrinciples();\n const activePrincipleCount = principles.filter((pp) => pp.isActive).length;\n process.stdout.write(\n c.hint(`Coach loaded with ${activePrincipleCount} active principle${activePrincipleCount === 1 ? '' : 's'}. Type 'exit' or press Ctrl+C to end.\\n\\n`),\n );\n\n // If brand-new session, ask the coach to open the conversation first.\n if (session.messages.length === 0) {\n const sp = spinner('Coach thinking...');\n sp.start();\n try {\n const { session: updated, reply } = await coachReply(session, principles, '', settings);\n sp.stop();\n session = updated;\n await ctx.storage.updateDecisionSession(session);\n renderMessage(reply.role, reply.content);\n } catch (error) {\n sp.fail(`Coach failed: ${error instanceof Error ? error.message : String(error)}`);\n throw error;\n }\n }\n\n // REPL loop.\n let keepGoing = true;\n while (keepGoing) {\n const userInput = await askText('you', {});\n const trimmed = userInput.trim();\n if (!trimmed) continue;\n if (/^(exit|quit|bye)$/i.test(trimmed)) {\n keepGoing = false;\n break;\n }\n const sp = spinner('Coach thinking...');\n sp.start();\n try {\n const { session: updated, reply } = await coachReply(session, principles, trimmed, settings);\n sp.stop();\n session = updated;\n await ctx.storage.updateDecisionSession(session);\n renderMessage(reply.role, reply.content);\n } catch (error) {\n sp.fail(`Coach failed: ${error instanceof Error ? error.message : String(error)}`);\n // Continue the REPL so the user can retry.\n }\n }\n process.stdout.write(c.hint(`Session ${session.id.slice(0, 8)} saved.\\n`));\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // send — one-shot non-interactive turn\n // --------------------------------------------------------------\n coach\n .command('send <sessionId> <message>')\n .description('send one message and print the coach reply (non-interactive)')\n .action(async (sessionId: string, message: string) => {\n const ctx = await openContext(coach);\n try {\n let session = await ctx.storage.loadDecisionSessionById(sessionId);\n if (!session) {\n const all = await ctx.storage.loadDecisionSessions();\n const byShort = all.find((s) => s.id.startsWith(sessionId));\n if (!byShort) throw new UserError(`No coach session matches \"${sessionId}\"`);\n session = byShort;\n }\n const settings = await ctx.storage.loadSettings();\n const principles = await ctx.storage.loadPrinciples();\n const { session: updated, reply } = await coachReply(session, principles, message, settings);\n await ctx.storage.updateDecisionSession(updated);\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ session: updated, reply }, null, 2) + '\\n');\n return;\n }\n renderMessage(reply.role, reply.content);\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // show — list or print one\n // --------------------------------------------------------------\n coach\n .command('show [sessionId]')\n .description('list past sessions; pass a session id (or short id) to print it')\n .action(async (sessionId?: string) => {\n const ctx = await openContext(coach, { lock: false });\n try {\n if (!sessionId) {\n const all = await ctx.storage.loadDecisionSessions();\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ sessions: all }, null, 2) + '\\n');\n return;\n }\n if (all.length === 0) {\n process.stdout.write(c.hint(' (no sessions yet — run `aab coach` to start one)\\n'));\n return;\n }\n for (const s of all) {\n const ts = new Date(s.updatedAt).toLocaleString();\n const title = s.title || s.situation.slice(0, 60);\n process.stdout.write(\n ` ${c.cyan(s.id.slice(0, 8))} ${c.hint(ts)} ${c.bold(title)} ${c.hint(`(${s.messages.length} msgs · ${s.status})`)}\\n`,\n );\n }\n return;\n }\n\n let session = await ctx.storage.loadDecisionSessionById(sessionId);\n if (!session) {\n const all = await ctx.storage.loadDecisionSessions();\n const byShort = all.find((s) => s.id.startsWith(sessionId));\n if (!byShort) throw new UserError(`No coach session matches \"${sessionId}\"`);\n session = byShort;\n }\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ session }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(\n `\\n${c.bold(session.title ?? 'Decision session')} ${c.hint('· ' + session.id.slice(0, 8))}\\n`,\n );\n process.stdout.write(` ${c.hint('situation:')} ${session.situation}\\n`);\n process.stdout.write(` ${c.hint('status:')} ${session.status}\\n`);\n process.stdout.write(` ${c.hint('messages:')} ${session.messages.length}\\n\\n`);\n for (const m of session.messages) renderMessage(m.role, m.content);\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // delete\n // --------------------------------------------------------------\n coach\n .command('delete <sessionId>')\n .description('delete a coach session')\n .option('--yes', 'skip confirmation prompt')\n .action(async (sessionId: string, opts: { yes?: boolean }) => {\n const ctx = await openContext(coach);\n try {\n let session = await ctx.storage.loadDecisionSessionById(sessionId);\n if (!session) {\n const all = await ctx.storage.loadDecisionSessions();\n const byShort = all.find((s) => s.id.startsWith(sessionId));\n if (!byShort) throw new UserError(`No coach session matches \"${sessionId}\"`);\n session = byShort;\n }\n if (!opts.yes) {\n const ok = await askConfirm(\n `Delete session \"${session.title ?? session.situation.slice(0, 40)}\"?`,\n false,\n );\n if (!ok) {\n process.stdout.write(c.hint(' aborted.\\n'));\n return;\n }\n }\n await ctx.storage.deleteDecisionSession(session.id);\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ deleted: session.id }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`${c.ok('✓')} Deleted session ${session.id.slice(0, 8)}\\n`);\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // reflect / decided — set status (light-touch session lifecycle)\n // --------------------------------------------------------------\n coach\n .command('decide <sessionId> <decision>')\n .description('record the decision the user made and flip status to \"decided\"')\n .action(async (sessionId: string, decision: string) => {\n const ctx = await openContext(coach);\n try {\n const session = await ctx.storage.loadDecisionSessionById(sessionId);\n if (!session) throw new UserError(`No coach session matches \"${sessionId}\"`);\n const updated: DecisionSession = {\n ...session,\n decision,\n status: 'decided',\n updatedAt: nowIso(),\n };\n await ctx.storage.updateDecisionSession(updated);\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ session: updated }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`${c.ok('✓')} Decision recorded for ${updated.id.slice(0, 8)}\\n`);\n } finally {\n await closeContext(ctx);\n }\n });\n}\n\nfunction renderMessage(role: 'user' | 'assistant', content: string): void {\n if (role === 'user') {\n process.stdout.write(`${c.cyan('you:')}\\n${content}\\n\\n`);\n } else {\n process.stdout.write(`${c.green('coach:')}\\n${content}\\n\\n`);\n }\n}\n","/**\n * `aab actions` — Phase 4 Action Board (kanban) surface.\n *\n * aab actions add \"<title>\" [--description] [--priority] [--due]\n * aab actions list [--status pending|in-progress|completed] [--priority high|medium|low]\n * aab actions board 3-column ANSI Kanban\n * aab actions show <id> full detail\n * aab actions edit <id> interactive\n * aab actions move <id> <status> pending | in-progress | completed\n * aab actions delete <id> [--yes]\n * aab actions extract <discussion-id> [--auto] [--max N] [--accept-all]\n *\n * Per Part 6 of PLAN.md: kanban tracking + skill-only solve. No multi-agent\n * pipeline. `aab actions solve` lives in Phase 5.\n */\nimport { Command } from 'commander';\nimport { closeContext, openContext } from './_context.js';\nimport { c } from '../ui/colors.js';\nimport { askConfirm, askSelect, askText } from '../ui/prompts.js';\nimport { spinner } from '../ui/spinner.js';\nimport { generateUUID, nowIso } from '../core/utils.js';\nimport { UserError } from '../core/errors.js';\nimport { shortId } from '../ui/render-discussion.js';\nimport { writeFileSync } from 'node:fs';\nimport {\n extractActionItems,\n toActionItem,\n type ExtractedActionItem,\n} from '../core/actions/conversation-analyzer.js';\nimport { runSolve } from '../core/skill/solve-orchestrator.js';\nimport { renderProposalMarkdown } from '../core/skill/planner-review.js';\nimport { formatDuration, formatUsd } from '../core/utils.js';\nimport type { ActionItem, Discussion, StorageService } from '../storage/types.js';\n\nconst PRIORITIES = ['low', 'medium', 'high'] as const;\ntype Priority = (typeof PRIORITIES)[number];\n\nconst STATUSES = ['pending', 'in-progress', 'completed'] as const;\ntype Status = (typeof STATUSES)[number];\n\nexport function registerActionsCommand(program: Command): void {\n const a = program.command('actions').description('manage action items on the kanban board');\n\n // --------------------------------------------------------------\n // add\n // --------------------------------------------------------------\n a.command('add [title]')\n .description('add a new action item (interactive if title omitted)')\n .option('--description <text>', 'long-form description')\n .option('--priority <p>', 'low | medium | high (default medium)')\n .option('--due <yyyy-mm-dd>', 'due date')\n .option('--assignee <name>', 'who owns this')\n .option('--discussion <id>', 'link to an existing discussion id or short id')\n .action(\n async (\n title: string | undefined,\n opts: {\n description?: string;\n priority?: string;\n due?: string;\n assignee?: string;\n discussion?: string;\n },\n ) => {\n const ctx = await openContext(a);\n try {\n // If a positional title is given, treat as non-interactive: leave\n // optional fields blank unless their flags were passed. Otherwise\n // run a full interactive wizard.\n const interactive = !title;\n const finalTitle = (title ?? (await askText('Title', { required: true }))).trim();\n if (!finalTitle) throw new UserError('Title cannot be empty.');\n const description =\n opts.description ?? (interactive ? await askText('Description (optional)', { initial: '' }) : '');\n const priority = normalizePriority(\n opts.priority ??\n (interactive\n ? await askSelect<Priority>(\n 'Priority',\n PRIORITIES.map((p) => ({ name: p, message: p })),\n { initial: 'medium' },\n )\n : 'medium'),\n );\n const dueDate = opts.due ?? '';\n const assignee = opts.assignee ?? '';\n let discussionId: string | undefined;\n if (opts.discussion) {\n const linked = await resolveDiscussion(ctx.storage, opts.discussion);\n discussionId = linked.id;\n }\n const now = nowIso();\n const item: ActionItem = {\n id: generateUUID(),\n discussionId,\n title: finalTitle,\n description: description || '',\n priority,\n status: 'pending',\n assignedTo: assignee || undefined,\n dueDate: dueDate || undefined,\n createdAt: now,\n updatedAt: now,\n };\n await ctx.storage.saveActionItem(item);\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ action: item }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(\n `${c.ok('✓')} added action ${c.bold(item.title)} ${c.hint(`(${shortActionId(item.id)} · ${item.priority})`)}\\n`,\n );\n } finally {\n await closeContext(ctx);\n }\n },\n );\n\n // --------------------------------------------------------------\n // list\n // --------------------------------------------------------------\n a.command('list')\n .description('flat list of action items (optionally filtered)')\n .option('--status <s>', 'pending | in-progress | completed')\n .option('--priority <p>', 'low | medium | high')\n .option('--discussion <id>', 'only items linked to this discussion')\n .action(\n async (opts: { status?: string; priority?: string; discussion?: string }) => {\n const ctx = await openContext(a, { lock: false });\n try {\n let items = await ctx.storage.loadActionItems();\n if (opts.status) items = items.filter((i) => i.status === normalizeStatus(opts.status!));\n if (opts.priority)\n items = items.filter((i) => i.priority === normalizePriority(opts.priority!));\n if (opts.discussion) {\n const d = await resolveDiscussion(ctx.storage, opts.discussion);\n items = items.filter((i) => i.discussionId === d.id);\n }\n items.sort(itemSortKey);\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ actions: items }, null, 2) + '\\n');\n return;\n }\n if (items.length === 0) {\n process.stdout.write(c.hint(' (no action items match)\\n'));\n return;\n }\n for (const item of items) {\n process.stdout.write(renderListRow(item) + '\\n');\n }\n } finally {\n await closeContext(ctx);\n }\n },\n );\n\n // --------------------------------------------------------------\n // board (ANSI kanban)\n // --------------------------------------------------------------\n a.command('board')\n .description('3-column ANSI kanban view')\n .option('--filter <q>', 'case-insensitive substring filter over title/description')\n .action(async (opts: { filter?: string }) => {\n const ctx = await openContext(a, { lock: false });\n try {\n let items = await ctx.storage.loadActionItems();\n if (opts.filter) {\n const q = opts.filter.toLowerCase();\n items = items.filter(\n (i) =>\n i.title.toLowerCase().includes(q) ||\n (i.description ?? '').toLowerCase().includes(q),\n );\n }\n if (ctx.json) {\n process.stdout.write(\n JSON.stringify(\n {\n pending: items.filter((i) => i.status === 'pending'),\n inProgress: items.filter((i) => i.status === 'in-progress'),\n completed: items.filter((i) => i.status === 'completed'),\n },\n null,\n 2,\n ) + '\\n',\n );\n return;\n }\n renderKanban(items);\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // show\n // --------------------------------------------------------------\n a.command('show <id>')\n .description('full detail for one action item')\n .action(async (id: string) => {\n const ctx = await openContext(a, { lock: false });\n try {\n const item = await resolveActionItem(ctx.storage, id);\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ action: item }, null, 2) + '\\n');\n return;\n }\n renderActionDetail(item);\n if (item.discussionId) {\n const d = await ctx.storage.loadDiscussionById(item.discussionId);\n if (d)\n process.stdout.write(\n c.hint(` linked discussion: ${shortId(d.id)} — \"${ellipsis(d.question, 70)}\"\\n`),\n );\n }\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // edit\n // --------------------------------------------------------------\n a.command('edit <id>')\n .description('interactively edit an action item')\n .option('--title <text>')\n .option('--description <text>')\n .option('--priority <p>')\n .option('--status <s>')\n .option('--due <yyyy-mm-dd>')\n .option('--assignee <name>')\n .action(\n async (\n id: string,\n opts: {\n title?: string;\n description?: string;\n priority?: string;\n status?: string;\n due?: string;\n assignee?: string;\n },\n ) => {\n const ctx = await openContext(a);\n try {\n const item = await resolveActionItem(ctx.storage, id);\n const flagsTouched =\n !!opts.title ||\n !!opts.description ||\n !!opts.priority ||\n !!opts.status ||\n !!opts.due ||\n !!opts.assignee;\n\n const next: ActionItem = { ...item };\n if (opts.title) next.title = opts.title;\n if (opts.description !== undefined) next.description = opts.description;\n if (opts.priority) next.priority = normalizePriority(opts.priority);\n if (opts.status) next.status = normalizeStatus(opts.status);\n if (opts.due !== undefined) next.dueDate = opts.due || undefined;\n if (opts.assignee !== undefined) next.assignedTo = opts.assignee || undefined;\n\n if (!flagsTouched) {\n next.title = await askText('Title', { initial: next.title, required: true });\n next.description = await askText('Description', { initial: next.description ?? '' });\n next.priority = normalizePriority(\n await askSelect<Priority>(\n 'Priority',\n PRIORITIES.map((p) => ({ name: p, message: p })),\n { initial: next.priority },\n ),\n );\n next.status = normalizeStatus(\n await askSelect<Status>(\n 'Status',\n STATUSES.map((s) => ({ name: s, message: s })),\n { initial: next.status },\n ),\n );\n const due = await askText('Due date (YYYY-MM-DD, optional)', {\n initial: next.dueDate ?? '',\n });\n next.dueDate = due || undefined;\n const assignee = await askText('Assignee (optional)', {\n initial: next.assignedTo ?? '',\n });\n next.assignedTo = assignee || undefined;\n }\n\n next.updatedAt = nowIso();\n await ctx.storage.updateActionItem(next);\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ action: next }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`${c.ok('✓')} updated ${c.bold(next.title)}\\n`);\n } finally {\n await closeContext(ctx);\n }\n },\n );\n\n // --------------------------------------------------------------\n // move\n // --------------------------------------------------------------\n a.command('move <id> <status>')\n .description('move an action to a new column: pending | in-progress | completed')\n .action(async (id: string, statusRaw: string) => {\n const ctx = await openContext(a);\n try {\n const item = await resolveActionItem(ctx.storage, id);\n const status = normalizeStatus(statusRaw);\n const prev = item.status;\n if (prev === status) {\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ action: item, changed: false }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(c.hint(` ${shortActionId(item.id)} already ${status}.\\n`));\n return;\n }\n const next: ActionItem = { ...item, status, updatedAt: nowIso() };\n await ctx.storage.updateActionItem(next);\n if (ctx.json) {\n process.stdout.write(\n JSON.stringify({ action: next, changed: true, from: prev, to: status }, null, 2) + '\\n',\n );\n return;\n }\n process.stdout.write(\n `${c.ok('✓')} ${c.bold(item.title)}: ${c.hint(prev)} → ${c.cyan(status)}\\n`,\n );\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // delete\n // --------------------------------------------------------------\n a.command('delete <id>')\n .description('delete an action item')\n .option('--yes', 'skip confirmation prompt')\n .action(async (id: string, opts: { yes?: boolean }) => {\n const ctx = await openContext(a);\n try {\n const item = await resolveActionItem(ctx.storage, id);\n if (!opts.yes) {\n const ok = await askConfirm(`Delete action \"${item.title}\"?`, false);\n if (!ok) {\n process.stdout.write(c.hint(' aborted.\\n'));\n return;\n }\n }\n await ctx.storage.deleteActionItem(item.id);\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ deleted: item.id }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`${c.ok('✓')} deleted ${item.title}\\n`);\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // extract\n // --------------------------------------------------------------\n a.command('extract <discussionIdOrShort>')\n .description('auto-extract action items from a concluded discussion')\n .option('--accept-all', 'persist every candidate without confirmation')\n .option('--max <n>', 'cap candidates accepted (top N by confidence)')\n .option('--dry-run', 'print candidates only — do not persist')\n .action(\n async (\n discussionIdOrShort: string,\n opts: { acceptAll?: boolean; max?: string; dryRun?: boolean },\n ) => {\n const ctx = await openContext(a);\n try {\n const discussion = await resolveDiscussion(ctx.storage, discussionIdOrShort);\n const settings = await ctx.storage.loadSettings();\n\n const sp = spinner('Extracting action items…');\n sp.start();\n let analysis;\n try {\n analysis = await extractActionItems({ discussion, settings });\n sp.succeed(\n `Extracted ${analysis.actionItems.length} candidate${analysis.actionItems.length === 1 ? '' : 's'} ` +\n `via ${analysis.method} path (confidence ${analysis.analysisConfidence}/100)`,\n );\n } catch (err) {\n sp.fail('extract failed');\n throw err;\n }\n\n let candidates = [...analysis.actionItems].sort((a, b) => b.confidence - a.confidence);\n if (opts.max) {\n const n = Number.parseInt(opts.max, 10);\n if (Number.isFinite(n) && n > 0) candidates = candidates.slice(0, n);\n }\n\n if (ctx.json) {\n process.stdout.write(\n JSON.stringify(\n {\n discussionId: discussion.id,\n method: analysis.method,\n candidates,\n keyInsights: analysis.keyInsights,\n recommendedNextSteps: analysis.recommendedNextSteps,\n analysisConfidence: analysis.analysisConfidence,\n },\n null,\n 2,\n ) + '\\n',\n );\n return;\n }\n\n if (candidates.length === 0) {\n process.stdout.write(c.hint(' (no candidates)\\n'));\n return;\n }\n\n for (const cand of candidates) {\n process.stdout.write(renderCandidate(cand) + '\\n');\n }\n\n if (opts.dryRun) {\n process.stdout.write(c.hint(' --dry-run: nothing persisted.\\n'));\n return;\n }\n\n const accepted: ActionItem[] = [];\n for (const cand of candidates) {\n const accept = opts.acceptAll\n ? true\n : await askConfirm(\n `Accept \"${cand.title}\" (${cand.priority}, ${cand.category}, conf ${cand.confidence})?`,\n true,\n );\n if (!accept) continue;\n const item = toActionItem(cand, discussion.id);\n await ctx.storage.saveActionItem(item);\n accepted.push(item);\n }\n process.stdout.write(\n `${c.ok('✓')} added ${accepted.length} action item${accepted.length === 1 ? '' : 's'} from ${shortId(discussion.id)}\\n`,\n );\n } finally {\n await closeContext(ctx);\n }\n },\n );\n\n // --------------------------------------------------------------\n // plan — Phase 5 Chunk 3 first-class command (Planner-only, no skill-creator)\n // --------------------------------------------------------------\n a.command('plan <id>')\n .description('run the Skill Planner only (no skill-creator); print/save proposal')\n .option('--planner-tier <tier>', 'cap ambition: minimal | standard | maximalist (default maximalist)')\n .option('--planner-no-web', 'skip the web research phase')\n .option('--planner-no-pc-scan', 'skip the PC scan phase')\n .option('--planner-no-wiki', 'skip the wiki recon phase')\n .option('--out <path>', 'save proposal markdown to <path>')\n .option('--yes', 'auto-accept the Planner proposal')\n .action(async (id: string, opts: {\n plannerTier?: string;\n plannerNoWeb?: boolean;\n plannerNoPcScan?: boolean;\n plannerNoWiki?: boolean;\n out?: string;\n yes?: boolean;\n }) => {\n const ctx = await openContext(a);\n try {\n const action = await resolveActionItem(ctx.storage, id);\n const settings = await ctx.storage.loadSettings();\n const discussion = action.discussionId ? await ctx.storage.loadDiscussionById(action.discussionId) : null;\n const sp = spinner('Running Skill Planner (recon + reasoning)…');\n sp.start();\n let solveResult;\n try {\n solveResult = await runSolve({\n workspace: ctx.workspace,\n settings,\n storage: ctx.storage,\n action,\n discussionSummary: discussion?.summary,\n plannerTierCap: normalizePlannerTier(opts.plannerTier),\n skipPcScan: opts.plannerNoPcScan,\n skipWiki: opts.plannerNoWiki,\n skipWeb: opts.plannerNoWeb,\n planOnly: true,\n yes: opts.yes,\n projectRoot: process.cwd(),\n onEvent: (evt) => {\n if (evt.type === 'planner_recon_progress') {\n const p = evt.payload as { phase: string; summary: string };\n sp.text = `recon · ${p.phase}: ${p.summary}`;\n } else if (evt.type === 'planner_reasoning_started') {\n sp.text = 'planner · reasoning (Opus)…';\n }\n },\n });\n sp.succeed(\n `Planner done · tier ${solveResult.proposal.recommendedTier} · ` +\n `${solveResult.proposal.integrations.length} integration(s) · ${formatUsd(solveResult.costUsd)} · ${formatDuration(solveResult.durationMs)}`,\n );\n } catch (err) {\n sp.fail('planner failed');\n throw err;\n }\n\n if (ctx.json) {\n process.stdout.write(JSON.stringify({\n proposal: solveResult.proposal,\n capabilityProfile: solveResult.capabilityProfile,\n costUsd: solveResult.costUsd,\n durationMs: solveResult.durationMs,\n }, null, 2) + '\\n');\n } else {\n process.stdout.write('\\n' + renderProposalMarkdown(solveResult.proposal) + '\\n');\n }\n\n if (opts.out) {\n writeFileSync(opts.out, renderProposalMarkdown(solveResult.proposal), 'utf8');\n process.stdout.write(`${c.ok('✓')} proposal saved → ${opts.out}\\n`);\n }\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // solve — Phase 5 Chunk 4 first-class command (full pipeline)\n // --------------------------------------------------------------\n a.command('solve <id>')\n .description('Plan → user-accept → skill-creator → install end-to-end (Phase 5)')\n .option('--no-planner', 'skip the Skill Planner (fall back to minimal-tier)')\n .option('--planner-tier <tier>', 'cap ambition: minimal | standard | maximalist')\n .option('--planner-no-web', 'skip the web research phase')\n .option('--planner-no-pc-scan', 'skip the PC scan phase')\n .option('--planner-no-wiki', 'skip the wiki recon phase')\n .option('--skill-name <name>', 'override auto-derived skill name')\n .option('--scope <scope>', 'project | user (default project)', 'project')\n .option('--no-install', 'build but do not install to .claude/skills/')\n .option('--budget-cap-usd <n>', 'abort if projected cost exceeds')\n .option('--stub', 'use a stub skill-creator emit (test mode — no real skill-creator call)')\n .option('--yes', '-y', 'auto-accept Planner proposal + dry-run preview + overwrite conflicts')\n .action(async (id: string, opts: {\n planner?: boolean;\n plannerTier?: string;\n plannerNoWeb?: boolean;\n plannerNoPcScan?: boolean;\n plannerNoWiki?: boolean;\n skillName?: string;\n scope?: string;\n install?: boolean;\n budgetCapUsd?: string;\n stub?: boolean;\n yes?: boolean;\n }) => {\n const ctx = await openContext(a);\n try {\n const action = await resolveActionItem(ctx.storage, id);\n const settings = await ctx.storage.loadSettings();\n const discussion = action.discussionId ? await ctx.storage.loadDiscussionById(action.discussionId) : null;\n const sp = spinner('Solving action — running Planner → skill-creator → install…');\n sp.start();\n let solveResult;\n try {\n solveResult = await runSolve({\n workspace: ctx.workspace,\n settings,\n storage: ctx.storage,\n action,\n discussionSummary: discussion?.summary,\n yes: opts.yes,\n noPlanner: opts.planner === false,\n plannerTierCap: normalizePlannerTier(opts.plannerTier),\n skipPcScan: opts.plannerNoPcScan,\n skipWiki: opts.plannerNoWiki,\n skipWeb: opts.plannerNoWeb,\n skillName: opts.skillName,\n scope: opts.scope === 'user' ? 'user' : 'project',\n noInstall: opts.install === false,\n budgetCapUsd: opts.budgetCapUsd ? Number(opts.budgetCapUsd) : undefined,\n stub: opts.stub,\n projectRoot: process.cwd(),\n onEvent: (evt) => {\n if (evt.type === 'planner_recon_progress') {\n const p = evt.payload as { phase: string; summary: string };\n sp.text = `recon · ${p.phase}: ${p.summary}`;\n } else if (evt.type === 'planner_reasoning_started') {\n sp.text = 'planner · reasoning (Opus)…';\n } else if (evt.type === 'skill_run_started') {\n sp.text = 'skill-creator · authoring…';\n } else if (evt.type === 'skill_run_tool_call') {\n const p = evt.payload as { tool?: string };\n sp.text = `skill-creator · tool: ${p.tool ?? '?'}`;\n } else if (evt.type === 'skill_run_installed') {\n sp.text = 'installing skill…';\n }\n },\n });\n } catch (err) {\n sp.fail('solve failed');\n throw err;\n }\n if (solveResult.status === 'rejected') {\n sp.fail('proposal rejected — solve cancelled');\n return;\n }\n if (solveResult.status === 'plan-only') {\n sp.succeed('plan-only complete — re-run without --no-install to ship the skill');\n return;\n }\n sp.succeed(\n `Solved · skill ${c.bold(solveResult.proposal.skillName)} ` +\n `installed at ${solveResult.installPath ?? '(no-install)'} ` +\n `· ${formatUsd(solveResult.costUsd)} · ${formatDuration(solveResult.durationMs)}`,\n );\n if (ctx.json) {\n process.stdout.write(JSON.stringify({\n runId: solveResult.runId,\n skillName: solveResult.proposal.skillName,\n installPath: solveResult.installPath,\n costUsd: solveResult.costUsd,\n durationMs: solveResult.durationMs,\n adapterDiff: solveResult.skillRun ? 'see telemetry' : undefined,\n }, null, 2) + '\\n');\n }\n } finally {\n await closeContext(ctx);\n }\n });\n\n // --------------------------------------------------------------\n // runs — Phase 5 Chunk 5 history surface\n // --------------------------------------------------------------\n const runs = a.command('runs').description('skill-generation run history');\n\n runs.command('list [actionId]')\n .description('list past skill-generation runs (filter by action when given)')\n .action(async (actionId?: string) => {\n const ctx = await openContext(a, { lock: false });\n try {\n const actions = await ctx.storage.loadActionItems();\n const filtered = actionId\n ? [await resolveActionItem(ctx.storage, actionId)]\n : actions;\n const allRuns: Array<{ run: import('../storage/types.js').SkillGenerationRun; action: ActionItem }> = [];\n for (const action of filtered) {\n const runs = await ctx.storage.loadSkillRuns(action.id);\n for (const run of runs) allRuns.push({ run, action });\n }\n allRuns.sort((a, b) => b.run.startedAt.localeCompare(a.run.startedAt));\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ runs: allRuns.map((r) => ({\n id: r.run.id, actionId: r.run.actionItemId, action: r.action.title,\n status: r.run.status, skillName: r.run.metadata.skillName,\n startedAt: r.run.startedAt, completedAt: r.run.completedAt,\n costUsd: r.run.costUsd, durationMs: r.run.durationMs,\n installPath: r.run.installPath,\n })) }, null, 2) + '\\n');\n return;\n }\n if (allRuns.length === 0) {\n process.stdout.write(c.hint(' (no skill runs yet)\\n'));\n return;\n }\n for (const { run, action } of allRuns) {\n process.stdout.write(\n ` ${shortActionId(run.id)} · ${run.status === 'completed' ? c.ok('✓') : run.status === 'failed' ? c.err('✗') : c.warn('…')} ` +\n `${c.bold(run.metadata.skillName)} ${c.hint('(' + shortActionId(action.id) + ': ' + action.title.slice(0, 40) + ')')} ` +\n `${c.hint('· ' + formatUsd(run.costUsd) + ' · ' + formatDuration(run.durationMs))}\\n`,\n );\n }\n } finally {\n await closeContext(ctx);\n }\n });\n\n runs.command('show <runId>')\n .description('view a run\\'s metadata + Planner proposal + emitted files + telemetry tail')\n .action(async (runId: string) => {\n const ctx = await openContext(a, { lock: false });\n try {\n const run = await ctx.storage.getSkillRun(runId);\n if (!run) {\n // try shortId resolution\n const all = await ctx.storage.loadActionItems();\n for (const a of all) {\n const list = await ctx.storage.loadSkillRuns(a.id);\n const match = list.find((r) => r.id.startsWith(runId));\n if (match) {\n renderRunDetail(match, ctx.json);\n return;\n }\n }\n throw new UserError(`No skill run found with id starting \"${runId}\".`);\n }\n renderRunDetail(run, ctx.json);\n } finally {\n await closeContext(ctx);\n }\n });\n\n runs.command('export <runId>')\n .description('export a run as a .zip — proposal.md + SKILL.md + supporting files')\n .option('--zip <path>', 'output path (default ./<skillName>-<runId>.zip)')\n .action(async (runId: string, opts: { zip?: string }) => {\n const ctx = await openContext(a, { lock: false });\n try {\n const run = await ctx.storage.getSkillRun(runId);\n if (!run) throw new UserError(`No skill run with id \"${runId}\".`);\n // Lightweight export: write a directory tree (no ZIP — jszip not installed; CLI consumer can `zip -r` if needed).\n const target = opts.zip\n ? opts.zip.replace(/\\.zip$/i, '')\n : `./${run.metadata.skillName}-${run.id.slice(0, 8)}`;\n const fs = await import('node:fs');\n const path = await import('node:path');\n fs.mkdirSync(target, { recursive: true });\n for (const f of run.files) {\n const p = path.join(target, ...f.path.split('/'));\n fs.mkdirSync(path.dirname(p), { recursive: true });\n fs.writeFileSync(p, f.content, 'utf8');\n }\n const proposal = (run.metadata as unknown as { plannerProposal?: import('../core/parsing/llm-response-schemas.js').SkillDesignProposal }).plannerProposal;\n if (proposal) {\n fs.writeFileSync(\n path.join(target, 'proposal.md'),\n renderProposalMarkdown(proposal),\n 'utf8',\n );\n }\n if (ctx.json) {\n process.stdout.write(JSON.stringify({ exported: target, files: run.files.length }, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`${c.ok('✓')} exported run → ${target} (${run.files.length} files${proposal ? ' + proposal.md' : ''})\\n`);\n } finally {\n await closeContext(ctx);\n }\n });\n\n runs.command('delete <runId>')\n .description('delete a skill run record')\n .option('--yes', 'skip confirmation')\n .action(async (runId: string, opts: { yes?: boolean }) => {\n const ctx = await openContext(a);\n try {\n const run = await ctx.storage.getSkillRun(runId);\n if (!run) throw new UserError(`No run with id \"${runId}\".`);\n if (!opts.yes) {\n const ok = await askConfirm(`Delete skill run ${runId}?`, false);\n if (!ok) return;\n }\n await ctx.storage.deleteSkillRun(run.id);\n process.stdout.write(`${c.ok('✓')} deleted run ${runId}\\n`);\n } finally {\n await closeContext(ctx);\n }\n });\n}\n\nfunction normalizePlannerTier(input?: string): 'minimal' | 'standard' | 'maximalist' | undefined {\n if (!input) return undefined;\n const v = input.trim().toLowerCase();\n if (v === 'minimal' || v === 'standard' || v === 'maximalist') return v;\n throw new UserError(`Unknown planner tier \"${input}\". Pick: minimal | standard | maximalist`);\n}\n\nfunction renderRunDetail(run: import('../storage/types.js').SkillGenerationRun, asJson: boolean): void {\n if (asJson) {\n process.stdout.write(JSON.stringify(run, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`\\n${c.bold('Skill run ' + run.id)}\\n`);\n process.stdout.write(` status: ${run.status === 'completed' ? c.ok(run.status) : c.warn(run.status)}\\n`);\n process.stdout.write(` skill: ${c.bold(run.metadata.skillName)}\\n`);\n process.stdout.write(` started: ${run.startedAt}\\n`);\n if (run.completedAt) process.stdout.write(` completed: ${run.completedAt}\\n`);\n process.stdout.write(` cost: ${formatUsd(run.costUsd)} · duration: ${formatDuration(run.durationMs)}\\n`);\n if (run.installPath) process.stdout.write(` installPath: ${run.installPath}\\n`);\n process.stdout.write(` files: ${run.files.length}\\n`);\n const proposal = (run.metadata as unknown as { plannerProposal?: import('../core/parsing/llm-response-schemas.js').SkillDesignProposal }).plannerProposal;\n if (proposal) {\n process.stdout.write('\\n' + renderProposalMarkdown(proposal) + '\\n');\n }\n}\n\n// ----------------------------------------------------------------------------\n// Helpers\n// ----------------------------------------------------------------------------\n\nexport function shortActionId(id: string): string {\n return id.slice(0, 8);\n}\n\nexport async function resolveActionItem(\n storage: StorageService,\n idOrShort: string,\n): Promise<ActionItem> {\n const all = await storage.loadActionItems();\n const direct = all.find((i) => i.id === idOrShort);\n if (direct) return direct;\n const matches = all.filter((i) => i.id.startsWith(idOrShort));\n if (matches.length === 0)\n throw new UserError(`No action item found with id starting \"${idOrShort}\".`);\n if (matches.length > 1)\n throw new UserError(`Multiple action items match \"${idOrShort}\". Use a longer prefix.`);\n return matches[0]!;\n}\n\nasync function resolveDiscussion(\n storage: StorageService,\n idOrShort: string,\n): Promise<Discussion> {\n const direct = await storage.loadDiscussionById(idOrShort);\n if (direct) return direct;\n const all = await storage.loadDiscussions();\n const matches = all.filter((d) => d.id.startsWith(idOrShort));\n if (matches.length === 0)\n throw new UserError(`No discussion found with id starting \"${idOrShort}\".`);\n if (matches.length > 1)\n throw new UserError(`Multiple discussions match \"${idOrShort}\". Use a longer prefix.`);\n return matches[0]!;\n}\n\nexport function normalizePriority(input: string): Priority {\n const v = input.trim().toLowerCase() as Priority;\n if (!(PRIORITIES as readonly string[]).includes(v))\n throw new UserError(`Unknown priority \"${input}\". Pick: ${PRIORITIES.join(' | ')}`);\n return v;\n}\n\nexport function normalizeStatus(input: string): Status {\n const raw = input.trim().toLowerCase();\n const aliases: Record<string, Status> = {\n 'in-progress': 'in-progress',\n inprogress: 'in-progress',\n 'in_progress': 'in-progress',\n doing: 'in-progress',\n pending: 'pending',\n todo: 'pending',\n completed: 'completed',\n done: 'completed',\n };\n const v = aliases[raw];\n if (!v) throw new UserError(`Unknown status \"${input}\". Pick: ${STATUSES.join(' | ')}`);\n return v;\n}\n\nconst STATUS_ORDER: Record<Status, number> = {\n 'in-progress': 0,\n pending: 1,\n completed: 2,\n};\nconst PRIORITY_ORDER: Record<Priority, number> = { high: 0, medium: 1, low: 2 };\n\nfunction itemSortKey(a: ActionItem, b: ActionItem): number {\n const s = STATUS_ORDER[a.status] - STATUS_ORDER[b.status];\n if (s !== 0) return s;\n const p = PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority];\n if (p !== 0) return p;\n return (a.dueDate ?? '9999').localeCompare(b.dueDate ?? '9999');\n}\n\n// ----------------------------------------------------------------------------\n// Rendering\n// ----------------------------------------------------------------------------\n\nfunction priorityBadge(p: Priority): string {\n if (p === 'high') return c.err('●');\n if (p === 'medium') return c.warn('●');\n return c.hint('●');\n}\n\nfunction statusBadge(s: Status): string {\n if (s === 'completed') return c.ok('✓');\n if (s === 'in-progress') return c.cyan('→');\n return c.hint('○');\n}\n\nfunction renderListRow(item: ActionItem): string {\n const parts = [\n ` ${priorityBadge(item.priority)} ${statusBadge(item.status)}`,\n c.bold(item.title),\n c.hint(`(${shortActionId(item.id)})`),\n ];\n if (item.dueDate) parts.push(c.hint(`· due ${item.dueDate}`));\n if (item.assignedTo) parts.push(c.hint(`· ${item.assignedTo}`));\n if (item.linkedSkill) parts.push(c.cyan(`· skill ${item.linkedSkill.name}`));\n return parts.join(' ');\n}\n\nfunction renderActionDetail(item: ActionItem): void {\n const out = process.stdout;\n out.write(`\\n${c.bold(item.title)} ${c.hint(`(${shortActionId(item.id)})`)}\\n`);\n out.write(\n ` ${statusBadge(item.status)} ${item.status} ${priorityBadge(item.priority)} ${item.priority}`,\n );\n if (item.dueDate) out.write(c.hint(` · due ${item.dueDate}`));\n if (item.assignedTo) out.write(c.hint(` · ${item.assignedTo}`));\n out.write('\\n');\n if (item.description) out.write(`\\n ${item.description}\\n`);\n if (item.linkedSkill) {\n out.write(`\\n ${c.cyan('skill:')} ${item.linkedSkill.name} ${c.hint(`(${item.linkedSkill.installPath})`)}\\n`);\n }\n out.write(c.hint(`\\n created ${item.createdAt.slice(0, 19)} · updated ${item.updatedAt.slice(0, 19)}\\n`));\n}\n\nfunction renderCandidate(it: ExtractedActionItem): string {\n const lines: string[] = [];\n lines.push(` ${priorityBadge(it.priority)} ${c.bold(it.title)} ${c.hint(`· ${it.category} · conf ${it.confidence}`)}`);\n if (it.description) lines.push(` ${c.hint(it.description)}`);\n if (it.sourceContext) lines.push(` ${c.hint('from: ' + it.sourceContext)}`);\n if (it.suggestedAssignee) lines.push(` ${c.hint('assignee: ' + it.suggestedAssignee)}`);\n if (it.suggestedDueDate) lines.push(` ${c.hint('due: ' + it.suggestedDueDate)}`);\n return lines.join('\\n');\n}\n\nfunction renderKanban(items: ActionItem[]): void {\n const cols: Record<Status, ActionItem[]> = {\n pending: items.filter((i) => i.status === 'pending').sort(itemSortKey),\n 'in-progress': items.filter((i) => i.status === 'in-progress').sort(itemSortKey),\n completed: items.filter((i) => i.status === 'completed').sort(itemSortKey),\n };\n const COL_W = 36;\n const header =\n `┌${'─'.repeat(COL_W)}┬${'─'.repeat(COL_W)}┬${'─'.repeat(COL_W)}┐\\n` +\n `│ ${pad(c.bold(`PENDING (${cols.pending.length})`), COL_W - 1)}│ ${pad(c.bold(`IN-PROGRESS (${cols['in-progress'].length})`), COL_W - 1)}│ ${pad(c.bold(`COMPLETED (${cols.completed.length})`), COL_W - 1)}│\\n` +\n `├${'─'.repeat(COL_W)}┼${'─'.repeat(COL_W)}┼${'─'.repeat(COL_W)}┤`;\n process.stdout.write('\\n' + header + '\\n');\n\n const rows = Math.max(cols.pending.length, cols['in-progress'].length, cols.completed.length);\n if (rows === 0) {\n const empty = `│ ${pad(c.hint('(empty)'), COL_W - 1)}│ ${pad(c.hint('(empty)'), COL_W - 1)}│ ${pad(c.hint('(empty)'), COL_W - 1)}│`;\n process.stdout.write(empty + '\\n');\n }\n for (let r = 0; r < rows; r++) {\n const cellLines: string[][] = (['pending', 'in-progress', 'completed'] as Status[]).map((s) => {\n const item = cols[s][r];\n if (!item) return [pad('', COL_W - 1)];\n return formatKanbanCard(item, COL_W - 1);\n });\n const maxLines = Math.max(...cellLines.map((l) => l.length));\n for (let line = 0; line < maxLines; line++) {\n const left = cellLines[0]![line] ?? pad('', COL_W - 1);\n const mid = cellLines[1]![line] ?? pad('', COL_W - 1);\n const right = cellLines[2]![line] ?? pad('', COL_W - 1);\n process.stdout.write(`│ ${left}│ ${mid}│ ${right}│\\n`);\n }\n }\n process.stdout.write(`└${'─'.repeat(COL_W)}┴${'─'.repeat(COL_W)}┴${'─'.repeat(COL_W)}┘\\n`);\n}\n\nfunction formatKanbanCard(item: ActionItem, width: number): string[] {\n const titleLine = `${priorityBadge(item.priority)} ${ellipsis(item.title, width - 12)} ${c.hint('(' + shortActionId(item.id) + ')')}`;\n const metaParts: string[] = [];\n if (item.dueDate) metaParts.push('due ' + item.dueDate);\n if (item.assignedTo) metaParts.push(item.assignedTo);\n const meta = metaParts.length ? c.hint(ellipsis(' ' + metaParts.join(' · '), width)) : '';\n return [pad(titleLine, width), pad(meta, width)];\n}\n\n// chalk wraps strings with escape codes; we still pad based on visible width.\nfunction pad(s: string, width: number): string {\n // eslint-disable-next-line no-control-regex\n const visible = s.replace(/\\x1B\\[[0-9;]*m/g, '');\n const fill = Math.max(0, width - visible.length);\n return s + ' '.repeat(fill);\n}\n\nfunction ellipsis(s: string, max: number): string {\n if (s.length <= max) return s;\n return s.slice(0, Math.max(0, max - 1)) + '…';\n}\n","import { runCli } from '../src/cli.js';\r\n\r\nrunCli(process.argv).catch((error: unknown) => {\r\n // Unhandled errors fall through to here. Normal command errors are caught\r\n // inside cli.ts and mapped to typed exit codes.\r\n // eslint-disable-next-line no-console\r\n console.error('[aabcli] fatal:', error instanceof Error ? error.message : error);\r\n process.exit(1);\r\n});\r\n"],"mappings":"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","names":["readFileSync","dirname","join","trimmed","resolve","prompt","existsSync","mkdirSync","writeFileSync","dirname","join","c","existsSync","readFileSync","dirname","join","id","existsSync","mkdirSync","readdirSync","unlinkSync","join","existsSync","mkdirSync","readdirSync","readFileSync","writeFileSync","dirname","join","existsSync","readdirSync","join","mkdirSync","unlinkSync","c","prompt","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","slugify","existsSync","mkdirSync","writeFileSync","dirname","existsSync","readFileSync","writeFileSync","dirname","mkdirSync","existsSync","readFileSync","writeFileSync","mkdirSync","readdirSync","statSync","dirname","join","slugify","emit","existsSync","dirname","readdirSync","join","mkdirSync","writeFileSync","mkdirSync","dirname","existsSync","readFileSync","writeFileSync","existsSync","existsSync","existsSync","mkdirSync","dirname","writeFileSync","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","existsSync","readdirSync","readFileSync","statSync","homedir","join","FRONTMATTER_RE","existsSync","writeFileSync","root","join","mkdirSync","dirname","existsSync","mkdirSync","writeFileSync","dirname","existsSync","readdirSync","readFileSync","statSync","homedir","join","existsSync","readdirSync","readFileSync","statSync","delimiter","join","homedir","resolve","existsSync","readFileSync","join","homedir","statSync","readdirSync","c","existsSync","mkdirSync","renameSync","join","join","existsSync","mkdirSync","renameSync","existsSync","writeFileSync","join","meta","slugify","existsSync","truncate","c","DEFAULT_TOOLS","emit","c","prompt","finalize","entry","copyFileSync","existsSync","mkdirSync","readFileSync","writeFileSync","appendFileSync","statSync","basename","dirname","join","relative","existsSync","readFileSync","prompt","asStringArray","appendFileSync","statSync","basename","join","mkdirSync","dirname","writeFileSync","relative","existsSync","c","DEFAULT_TOOLS","prompt","pickModel","makeActivityForwarder","emit","join","writeFileSync","existsSync","dirname","join","resolve","fileURLToPath","existsSync","statSync","unlinkSync","existsSync","mkdirSync","writeFileSync","dirname","join","toSlug","join","dirname","mkdirSync","writeFileSync","existsSync","rmSync","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","existsSync","readFileSync","prompt","c","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","existsSync","join","p","readFileSync","truncate","writeFileSync","mkdirSync","dirname","readFileSync","writeFileSync","prompt","z","stringArrayFromUnknown","prompt","prompt","prompt","mkdirSync","writeFileSync","homedir","join","existsSync","readFileSync","existsSync","prompt","emptyContext","pickModel","prompt","escapeForPrompt","asString","coerceArray","nonNull","mkdirSync","readdirSync","readFileSync","statSync","writeFileSync","join","relative","mkdirSync","readdirSync","join","statSync","readFileSync","relative","writeFileSync","parseFrontmatter","block","emit","existsSync","mkdirSync","readdirSync","renameSync","writeFileSync","homedir","dirname","join","join","homedir","existsSync","mkdirSync","dirname","writeFileSync","renameSync","pruneSnapshots","readdirSync","existsSync","mkdirSync","rmSync","writeFileSync","join","join","existsSync","mkdirSync","writeFileSync","rmSync","join","mkdirSync","homedir","writeFileSync","cpSync","existsSync","mkdirSync","readFileSync","readdirSync","rmSync","homedir","join","readFileSync","prompt","c","join","mkdirSync","existsSync","cpSync","homedir","readdirSync","rmSync","unlinkSync","pickMembers","existsSync","join","readFileSync","writeFileSync","runPlanner","dirname","fileURLToPath","resolve","c","statSync","resolve","readFileSync","writeFileSync","mkdirSync","dirname","join","relative","resolve","basename","existsSync","renameSync","writeFileSync","mkdirSync","dirname","relative","existsSync","renameSync","registerShow","registerList","p","truncate","join","readFileSync","relative","writeFileSync","result","mkdirSync","dirname","resolve","existsSync","unlinkSync","result","existsSync","unlinkSync","truncate","c","writeFileSync","resolveDiscussion","renderListRow","a","writeFileSync","runs","meta"]}
|