{"version":3,"sources":["../src/cli.ts","../src/version.ts","../src/commands/init.ts","../src/commands/serve.ts","../src/commands/status.ts","../src/commands/config.ts","../src/commands/setup.ts","../src/utils/orchestrator.ts","../src/commands/bridge.ts","../src/commands/bridge/connect.ts","../src/commands/bridge/dispatch-handler.ts","../src/commands/bridge/conductor-handler.ts","../src/commands/bridge/conductor-watcher.ts","../src/commands/bridge/command-applier.ts","../src/commands/bridge/adoption-watcher.ts","../src/commands/bridge/transcript-tail.ts","../src/commands/bridge/observer.ts","../src/commands/sessions/scan-pipeline.ts","../src/commands/bridge/resume-applier.ts","../src/commands/bridge/introspect.ts","../src/commands/bridge/disconnect.ts","../src/commands/bridge/status.ts","../src/commands/session.ts","../src/commands/session/new.ts","../src/commands/session/join.ts","../src/commands/session/tail.ts","../src/commands/sessions/index.ts","../src/commands/session-runner/index.ts","../src/commands/session-runner/server.ts","../src/commands/session-runner/claude-runner.ts","../src/commands/session-runner/stream-events.ts","../src/commands/session-runner/callbacks.ts","../src/commands/update.ts","../src/commands/wiki.ts"],"sourcesContent":["import { Command } from 'commander';\nimport updateNotifier from 'update-notifier';\nimport { VERSION } from './version';\n\n// Import commands\nimport { initCommand } from './commands/init';\nimport { serveCommand } from './commands/serve';\nimport { statusCommand } from './commands/status';\nimport { configCommand } from './commands/config';\nimport { setupCommand } from './commands/setup';\nimport { bridgeCommand } from './commands/bridge';\nimport { sessionCommand } from './commands/session';\nimport { sessionsCommand } from './commands/sessions';\nimport { sessionRunnerCommand } from './commands/session-runner';\nimport { updateCommand } from './commands/update';\nimport { wikiCommand } from './commands/wiki';\nimport { benchCommand } from '@devpilot.sh/benchmarks/cli';\n\n// Package info for update-notifier\nconst pkg = {\n  name: '@devpilot.sh/cli',\n  version: VERSION,\n};\n\nexport const cli = new Command();\n\ncli\n  .name('devpilot')\n  .description('DevPilot CLI - Manage your AI coding agent fleet')\n  .version(VERSION);\n\n// Register commands\ncli.addCommand(initCommand);\ncli.addCommand(setupCommand);\ncli.addCommand(serveCommand);\ncli.addCommand(statusCommand);\ncli.addCommand(configCommand);\ncli.addCommand(bridgeCommand);\ncli.addCommand(sessionCommand);\ncli.addCommand(sessionsCommand);\ncli.addCommand(sessionRunnerCommand);\ncli.addCommand(updateCommand);\ncli.addCommand(wikiCommand);\ncli.addCommand(benchCommand);\n\nexport function runCli(args: string[] = process.argv): void {\n  // Check for updates in background (non-blocking)\n  // Notifies user if update is available (checks once per day by default)\n  const notifier = updateNotifier({\n    pkg,\n    updateCheckInterval: 1000 * 60 * 60 * 24, // 24 hours\n  });\n\n  // Show update notification if available\n  // This displays after CLI execution completes\n  notifier.notify({\n    message: `Update available: {currentVersion} → {latestVersion}\nRun {updateCommand} to update`,\n    boxenOptions: {\n      padding: 1,\n      margin: 1,\n      borderColor: 'cyan',\n      borderStyle: 'round',\n    },\n  });\n\n  cli.parse(args);\n}\n","// GENERATED by scripts/sync-version.mjs from package.json. Do not edit.\nexport const VERSION = '0.5.14';\n","import { Command } from 'commander';\nimport { existsSync, mkdirSync, writeFileSync } from 'fs';\nimport { join } from 'path';\nimport chalk from 'chalk';\n\nexport const initCommand = new Command('init')\n  .description('Initialize DevPilot in the current repository')\n  .option('-f, --force', 'Overwrite existing configuration')\n  .action(async (options) => {\n    const cwd = process.cwd();\n    const devpilotDir = join(cwd, '.devpilot');\n    const configPath = join(devpilotDir, 'config.yaml');\n\n    // Check if already initialized\n    if (existsSync(configPath) && !options.force) {\n      console.log(\n        chalk.yellow('⚠️  DevPilot is already initialized in this directory.')\n      );\n      console.log(chalk.gray('   Use --force to reinitialize.'));\n      return;\n    }\n\n    // Create .devpilot directory\n    if (!existsSync(devpilotDir)) {\n      mkdirSync(devpilotDir, { recursive: true });\n    }\n\n    // Create default config\n    const defaultConfig = `# DevPilot Configuration\nversion: 1\n\nmode: local  # 'local' | 'cloud' | 'hybrid'\n\ndatabase:\n  type: sqlite\n  path: .devpilot/data.db\n\nsync:\n  enabled: false\n  endpoint: https://api.devpilot.sh\n  org_id: null\n  project_id: null\n\nwatchers:\n  enabled: true\n  patterns:\n    - \"src/**/*.ts\"\n    - \"src/**/*.tsx\"\n    - \"tests/**/*.ts\"\n  ignore:\n    - \"**/node_modules/**\"\n    - \"**/.git/**\"\n\nui:\n  port: 3847\n  open_browser: true\n`;\n\n    writeFileSync(configPath, defaultConfig);\n\n    // Add to .gitignore if it exists\n    const gitignorePath = join(cwd, '.gitignore');\n    if (existsSync(gitignorePath)) {\n      const gitignore = require('fs').readFileSync(gitignorePath, 'utf-8');\n      if (!gitignore.includes('.devpilot/data.db')) {\n        const addition = '\\n# DevPilot\\n.devpilot/data.db\\n';\n        require('fs').appendFileSync(gitignorePath, addition);\n        console.log(chalk.gray('   Added .devpilot/data.db to .gitignore'));\n      }\n    }\n\n    console.log(chalk.green('✅ DevPilot initialized successfully!'));\n    console.log('');\n    console.log(chalk.white('Next steps:'));\n    console.log(chalk.gray('  1. Run ') + chalk.cyan('devpilot setup') + chalk.gray(' to configure Linear and agent-orchestrator'));\n    console.log(chalk.gray('  2. Run ') + chalk.cyan('devpilot serve') + chalk.gray(' to start the local UI'));\n    console.log(chalk.gray('  3. Run ') + chalk.cyan('devpilot status') + chalk.gray(' to see fleet status'));\n  });\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport open from 'open';\nimport { spawn } from 'child_process';\nimport { existsSync, mkdirSync } from 'fs';\nimport { join, resolve } from 'path';\n\n/**\n * Where the bundled cockpit lives inside the published package.\n *\n * Assembled by scripts/bundle-cockpit.mjs at publish time and listed in\n * package.json `files`. From a repo checkout it will be absent until someone\n * runs `pnpm --filter @devpilot.sh/cli bundle:cockpit`, which is why the\n * missing case below explains itself rather than just failing.\n */\nfunction cockpitEntry(): string | null {\n  /**\n   * Candidates, not one path. tsup bundles every command into dist/cli.js, so\n   * __dirname is <pkg>/dist — but that is a property of the bundler config, not\n   * a fact. The first version hard-coded '../../ui/server.js' on the assumption\n   * of dist/commands/serve.js and resolved to packages/ui, which does not exist;\n   * the CLI then reported the bundle as missing when it was sitting right there.\n   */\n  for (const rel of ['../ui/server.js', '../../ui/server.js', './ui/server.js']) {\n    const entry = resolve(__dirname, rel);\n    if (existsSync(entry)) return entry;\n  }\n  return null;\n}\n\nexport const serveCommand = new Command('serve')\n  .description('Start the local DevPilot Conductor API server')\n  .option('-p, --port <port>', 'Port to run the server on', '3847')\n  .option('--no-open', 'Do not open browser automatically')\n  .option('--sync', 'Enable cloud sync')\n  .option('--db <path>', 'Path to SQLite database', '.devpilot/data.db')\n  .option(\n    '--orchestrator-mode <mode>',\n    'Orchestrator mode: claude-session | ao-cli | http | disabled'\n  )\n  .option('--session-api-url <url>', 'claude-session dispatcher base URL')\n  .option('--session-api-key <key>', 'claude-session dispatcher bearer token')\n  .option('--ao-project <name>', 'ao-cli project name')\n  .option('--ao-path <path>', 'Path to the ao binary')\n  .option('--orchestrator-url <url>', 'Remote orchestrator base URL (http mode)')\n  .action(async (options) => {\n    const port = parseInt(options.port, 10);\n\n    // Assemble orchestrator config from flags, falling back to env (§8.1).\n    const orchestratorMode = options.orchestratorMode || process.env.DEVPILOT_ORCHESTRATOR_MODE;\n    const orchestrator = orchestratorMode\n      ? {\n          mode: orchestratorMode as 'claude-session' | 'ao-cli' | 'http' | 'disabled',\n          sessionApiUrl: options.sessionApiUrl || process.env.DEVPILOT_SESSION_API_URL,\n          sessionApiKey: options.sessionApiKey || process.env.DEVPILOT_SESSION_API_KEY,\n          sessionEnvironmentId: process.env.DEVPILOT_SESSION_ENVIRONMENT_ID,\n          callbackToken: process.env.DEVPILOT_CALLBACK_TOKEN,\n          aoProjectName: options.aoProject || process.env.DEVPILOT_AO_PROJECT,\n          aoPath: options.aoPath || process.env.DEVPILOT_AO_PATH,\n          httpUrl: options.orchestratorUrl || process.env.DEVPILOT_ORCHESTRATOR_URL,\n          apiKey: process.env.DEVPILOT_ORCHESTRATOR_API_KEY,\n        }\n      : undefined;\n\n    const dbPath = options.db.startsWith('/') ? options.db : join(process.cwd(), options.db);\n\n    console.log(chalk.cyan('🚀 Starting DevPilot Conductor...'));\n    console.log('');\n    console.log(chalk.gray(`   Port: ${port}`));\n    console.log(chalk.gray(`   Database: ${dbPath}`));\n    console.log('');\n\n    const dbDir = join(process.cwd(), '.devpilot');\n    if (!existsSync(dbDir)) {\n      mkdirSync(dbDir, { recursive: true });\n      console.log(chalk.gray(`   Created: ${dbDir}`));\n    }\n\n    const entry = cockpitEntry();\n    if (!entry) {\n      console.error(chalk.red('✗ The cockpit bundle is missing from this install.'));\n      console.error('');\n      console.error(chalk.gray('  Expected: <package>/ui/server.js'));\n      console.error(chalk.gray('  From a repo checkout, build it with:'));\n      console.error(chalk.cyan('    pnpm --filter @devpilot.sh/cli bundle:cockpit'));\n      console.error('');\n      console.error(chalk.gray('  If you installed from npm, this is a packaging bug — please file'));\n      console.error(chalk.gray('  an issue at https://github.com/geastham/devpilot/issues'));\n      process.exit(1);\n      return;\n    }\n\n    /**\n     * The cockpit IS the server now.\n     *\n     * `serve` used to start a separate Fastify app that reimplemented the same\n     * API over the same tables, and never served a UI at all. Running the\n     * cockpit's own Next server means one API, one UI, one command — and the\n     * wave-planner routes that Fastify never had come along for free.\n     *\n     * Config crosses the boundary as environment variables because that is what\n     * a Next server reads; there is no argv to thread through.\n     */\n    const child = spawn(process.execPath, [entry], {\n      stdio: ['ignore', 'pipe', 'inherit'],\n      env: {\n        ...process.env,\n        PORT: String(port),\n        HOSTNAME: '127.0.0.1',\n        DEVPILOT_SQLITE_PATH: dbPath,\n        ...(orchestrator?.mode ? { DEVPILOT_ORCHESTRATOR_MODE: orchestrator.mode } : {}),\n        ...(orchestrator?.sessionApiUrl ? { DEVPILOT_SESSION_API_URL: orchestrator.sessionApiUrl } : {}),\n        ...(orchestrator?.sessionApiKey ? { DEVPILOT_SESSION_API_KEY: orchestrator.sessionApiKey } : {}),\n        ...(orchestrator?.aoProjectName ? { DEVPILOT_AO_PROJECT: orchestrator.aoProjectName } : {}),\n        ...(orchestrator?.aoPath ? { DEVPILOT_AO_PATH: orchestrator.aoPath } : {}),\n        ...(orchestrator?.httpUrl ? { DEVPILOT_ORCHESTRATOR_URL: orchestrator.httpUrl } : {}),\n      },\n    });\n\n    const url = `http://127.0.0.1:${port}`;\n    let opened = false;\n\n    // Next prints its own ready line; wait for it rather than guessing with a\n    // timer, so `--open` never races a server that is not listening yet.\n    child.stdout?.on('data', (chunk: Buffer) => {\n      const text = chunk.toString();\n      process.stdout.write(chalk.gray(text.replace(/^/gm, '   ')));\n\n      if (!opened && /Ready in|started server|Local:/i.test(text)) {\n        opened = true;\n        console.log('');\n        console.log(chalk.green('✓ Cockpit ready'));\n        console.log('');\n        console.log(chalk.cyan(`   ${url}`));\n        console.log('');\n        console.log(chalk.gray('   Press Ctrl+C to stop'));\n        console.log('');\n        if (options.open) void open(url);\n      }\n    });\n\n    child.on('exit', (code) => {\n      if (code && code !== 0) {\n        console.error(chalk.red(`\\n✗ Cockpit exited with code ${code}`));\n      }\n      process.exit(code ?? 0);\n    });\n\n    const stop = () => {\n      child.kill('SIGTERM');\n    };\n    process.on('SIGINT', stop);\n    process.on('SIGTERM', stop);\n  });\n","import { Command } from 'commander';\nimport chalk from 'chalk';\n\nexport const statusCommand = new Command('status')\n  .description('Show current fleet and runway status')\n  .option('-v, --verbose', 'Show detailed information')\n  .action(async (options) => {\n    console.log(chalk.cyan('📊 DevPilot Status'));\n    console.log('');\n\n    // TODO: Read from actual database\n    // For now, show placeholder data\n    console.log(chalk.white('Fleet Status:'));\n    console.log(chalk.gray('  Active Sessions: ') + chalk.green('3'));\n    console.log(chalk.gray('  Needs Spec: ') + chalk.yellow('1'));\n    console.log(chalk.gray('  Fleet Utilization: ') + chalk.cyan('75%'));\n    console.log('');\n\n    console.log(chalk.white('Runway:'));\n    console.log(chalk.gray('  Ready Items: ') + chalk.green('2'));\n    console.log(chalk.gray('  Refining: ') + chalk.blue('1'));\n    console.log(chalk.gray('  Shaping: ') + chalk.magenta('2'));\n    console.log(chalk.gray('  Directional: ') + chalk.gray('3'));\n    console.log(chalk.gray('  Runway Hours: ') + chalk.green('4.2h'));\n    console.log('');\n\n    console.log(chalk.white('Conductor Score:'));\n    console.log(chalk.gray('  Total: ') + chalk.magenta('742') + chalk.gray('/1000'));\n    console.log(chalk.gray('  Rank: ') + chalk.cyan('#23'));\n\n    if (options.verbose) {\n      console.log('');\n      console.log(chalk.white('Score Breakdown:'));\n      console.log(chalk.gray('  Fleet Utilization: ') + chalk.white('156/200'));\n      console.log(chalk.gray('  Runway Health: ') + chalk.white('148/200'));\n      console.log(chalk.gray('  Plan Accuracy: ') + chalk.white('162/200'));\n      console.log(chalk.gray('  Cost Efficiency: ') + chalk.white('138/200'));\n      console.log(chalk.gray('  Velocity Trend: ') + chalk.white('138/200'));\n    }\n  });\n","import { Command } from 'commander';\nimport { existsSync, readFileSync, writeFileSync } from 'fs';\nimport { join } from 'path';\nimport chalk from 'chalk';\nimport YAML from 'yaml';\nimport { linear } from '@devpilot.sh/core';\n\n// Linear setup subcommand\nconst linearCommand = new Command('linear')\n  .description('Configure Linear integration')\n  .option('--api-key <key>', 'Linear API key')\n  .option('--team-id <id>', 'Linear team ID')\n  .option('--test', 'Test the connection')\n  .action(async (options) => {\n    const configPath = join(process.cwd(), '.devpilot', 'config.yaml');\n\n    if (!existsSync(configPath)) {\n      console.log(chalk.red('DevPilot not initialized. Run \"devpilot init\" first.'));\n      return;\n    }\n\n    const configContent = readFileSync(configPath, 'utf-8');\n    const config = YAML.parse(configContent);\n\n    // Initialize integrations section if needed\n    if (!config.integrations) config.integrations = {};\n    if (!config.integrations.linear) config.integrations.linear = {};\n\n    // Update API key if provided\n    if (options.apiKey) {\n      config.integrations.linear.apiKey = options.apiKey;\n      writeFileSync(configPath, YAML.stringify(config));\n      console.log(chalk.green('Linear API key saved.'));\n    }\n\n    // Update team ID if provided\n    if (options.teamId) {\n      config.integrations.linear.teamId = options.teamId;\n      writeFileSync(configPath, YAML.stringify(config));\n      console.log(chalk.green('Linear team ID saved.'));\n    }\n\n    // Test the connection\n    if (options.test || (options.apiKey && options.teamId)) {\n      const apiKey = config.integrations.linear.apiKey;\n      const teamId = config.integrations.linear.teamId;\n\n      if (!apiKey || !teamId) {\n        console.log(chalk.yellow('Missing API key or team ID. Set both to test connection.'));\n        return;\n      }\n\n      console.log(chalk.cyan('Testing Linear connection...'));\n\n      try {\n        const client = linear.initLinearClient({ apiKey, teamId });\n        const team = await client.getTeam();\n        console.log(chalk.green(`Connected to Linear team: ${team.name} (${team.key})`));\n      } catch (error) {\n        const message = error instanceof Error ? error.message : 'Unknown error';\n        console.log(chalk.red(`Connection failed: ${message}`));\n      }\n    }\n\n    // Show current config if no options\n    if (!options.apiKey && !options.teamId && !options.test) {\n      const apiKey = config.integrations.linear.apiKey;\n      const teamId = config.integrations.linear.teamId;\n\n      console.log(chalk.cyan('Linear Configuration:'));\n      console.log(`  API Key: ${apiKey ? chalk.green('configured') : chalk.yellow('not set')}`);\n      console.log(`  Team ID: ${teamId || chalk.yellow('not set')}`);\n    }\n  });\n\nexport const configCommand = new Command('config')\n  .description('Manage DevPilot configuration')\n  .argument('[key]', 'Configuration key (e.g., ui.port)')\n  .argument('[value]', 'Value to set')\n  .option('-l, --list', 'List all configuration')\n  .action(async (key, value, options) => {\n    const configPath = join(process.cwd(), '.devpilot', 'config.yaml');\n\n    if (!existsSync(configPath)) {\n      console.log(chalk.red('❌ DevPilot not initialized. Run \"devpilot init\" first.'));\n      return;\n    }\n\n    const configContent = readFileSync(configPath, 'utf-8');\n    const config = YAML.parse(configContent);\n\n    if (options.list || (!key && !value)) {\n      // List all config\n      console.log(chalk.cyan('DevPilot Configuration:'));\n      console.log('');\n      console.log(YAML.stringify(config));\n      return;\n    }\n\n    if (key && !value) {\n      // Get a specific key\n      const keys = key.split('.');\n      let current = config;\n      for (const k of keys) {\n        if (current && typeof current === 'object' && k in current) {\n          current = current[k];\n        } else {\n          console.log(chalk.red(`❌ Key \"${key}\" not found.`));\n          return;\n        }\n      }\n      console.log(current);\n      return;\n    }\n\n    if (key && value) {\n      // Set a value\n      const keys = key.split('.');\n      let current = config;\n      for (let i = 0; i < keys.length - 1; i++) {\n        const k = keys[i];\n        if (!(k in current)) {\n          current[k] = {};\n        }\n        current = current[k];\n      }\n\n      // Parse value (try JSON, then boolean, then number, then string)\n      let parsedValue: unknown = value;\n      try {\n        parsedValue = JSON.parse(value);\n      } catch {\n        if (value === 'true') parsedValue = true;\n        else if (value === 'false') parsedValue = false;\n        else if (!isNaN(Number(value))) parsedValue = Number(value);\n      }\n\n      current[keys[keys.length - 1]] = parsedValue;\n\n      writeFileSync(configPath, YAML.stringify(config));\n      console.log(chalk.green(`✅ Set ${key} = ${JSON.stringify(parsedValue)}`));\n    }\n  })\n  .addCommand(linearCommand);\n","import { Command } from 'commander';\nimport { existsSync, readFileSync, writeFileSync } from 'fs';\nimport { join } from 'path';\nimport chalk from 'chalk';\nimport YAML from 'yaml';\nimport * as readline from 'readline';\nimport { linear } from '@devpilot.sh/core';\nimport {\n  checkSystemRequirements,\n  printRequirementsStatus,\n  getInstallInstructions,\n  isOrchestratorInstalled,\n  installOrchestrator,\n  generateOrchestratorConfig,\n  writeOrchestratorConfig,\n  orchestratorConfigExists,\n  isRtkInstalled,\n  installRtk,\n  initRtkHook,\n  isCavemanInstalled,\n  installCaveman,\n} from '../utils/orchestrator';\n\n/**\n * Prompt user for input\n */\nfunction prompt(question: string): Promise<string> {\n  const rl = readline.createInterface({\n    input: process.stdin,\n    output: process.stdout,\n  });\n\n  return new Promise((resolve) => {\n    rl.question(question, (answer) => {\n      rl.close();\n      resolve(answer.trim());\n    });\n  });\n}\n\n/**\n * Prompt for yes/no confirmation\n */\nasync function confirm(question: string, defaultYes = true): Promise<boolean> {\n  const hint = defaultYes ? '[Y/n]' : '[y/N]';\n  const answer = await prompt(`${question} ${hint}: `);\n  if (!answer) return defaultYes;\n  return answer.toLowerCase().startsWith('y');\n}\n\nexport const setupCommand = new Command('setup')\n  .description('Interactive setup wizard for DevPilot and agent-orchestrator')\n  .option('--linear-only', 'Only configure Linear integration')\n  .option('--orchestrator-only', 'Only configure agent-orchestrator')\n  .option('--check', 'Only check system requirements')\n  .option('-y, --yes', 'Accept all defaults (non-interactive mode)')\n  .action(async (options) => {\n    const nonInteractive = options.yes;\n    const cwd = process.cwd();\n    const configPath = join(cwd, '.devpilot', 'config.yaml');\n\n    // Check if DevPilot is initialized\n    if (!existsSync(configPath)) {\n      console.log(chalk.red('DevPilot not initialized. Run \"devpilot init\" first.'));\n      return;\n    }\n\n    console.log(chalk.bold.cyan('\\n DevPilot Setup Wizard\\n'));\n    console.log(chalk.gray('This wizard will help you configure DevPilot and agent-orchestrator.\\n'));\n\n    // Step 1: Check system requirements\n    console.log(chalk.bold('Step 1: Checking System Requirements'));\n    const reqs = checkSystemRequirements();\n    printRequirementsStatus(reqs);\n\n    // Check for critical missing requirements\n    if (!reqs.node.meetsMinimum) {\n      console.log(chalk.red('\\nNode.js 20+ is required. Please upgrade and try again.'));\n      return;\n    }\n\n    if (!reqs.git.meetsMinimum) {\n      console.log(chalk.red('\\nGit 2.25+ is required. Please upgrade and try again.'));\n      return;\n    }\n\n    // Show optional installation instructions\n    const instructions = getInstallInstructions(reqs);\n    if (instructions.length > 0) {\n      console.log(chalk.yellow('\\nOptional installations:'));\n      instructions.forEach((inst) => console.log(chalk.gray(`  - ${inst}`)));\n    }\n\n    if (options.check) {\n      return; // Only checking requirements\n    }\n\n    console.log('');\n\n    // Step 2: Linear Integration\n    if (!options.orchestratorOnly) {\n      console.log(chalk.bold('Step 2: Linear Integration'));\n      console.log(chalk.gray('Linear integration enables ticket tracking and auto-status updates.\\n'));\n\n      const configContent = readFileSync(configPath, 'utf-8');\n      const config = YAML.parse(configContent);\n\n      const existingApiKey = config.integrations?.linear?.apiKey;\n      const existingTeamId = config.integrations?.linear?.teamId;\n\n      if (existingApiKey && existingTeamId) {\n        console.log(chalk.green('  Linear is already configured.'));\n        if (!nonInteractive) {\n          const reconfigure = await confirm('  Reconfigure Linear?', false);\n          if (reconfigure) {\n            await configureLinear(configPath, config);\n          }\n        }\n        console.log('');\n      } else if (nonInteractive) {\n        console.log(chalk.gray('  Skipping Linear setup (non-interactive mode).\\n'));\n      } else {\n        const setupLinear = await confirm('  Would you like to set up Linear integration?');\n        if (setupLinear) {\n          await configureLinear(configPath, config);\n        } else {\n          console.log(chalk.gray('  Skipping Linear setup.\\n'));\n        }\n      }\n    }\n\n    // Step 3: Agent Orchestrator\n    if (!options.linearOnly) {\n      console.log(chalk.bold('Step 3: Agent Orchestrator'));\n      console.log(chalk.gray('Agent orchestrator manages parallel AI coding agents.\\n'));\n\n      // Check if installed\n      const installed = isOrchestratorInstalled();\n      if (!installed) {\n        console.log(chalk.yellow('  @composio/ao-cli is not installed.'));\n        if (nonInteractive) {\n          console.log(chalk.gray('  Skipping installation (non-interactive mode).'));\n          console.log(chalk.gray('  Install later with: npm install -g @composio/ao-cli\\n'));\n        } else {\n          const install = await confirm('  Install @composio/ao-cli globally?');\n          if (install) {\n            const success = installOrchestrator();\n            if (!success) {\n              console.log(chalk.yellow('  Continuing without agent-orchestrator CLI...\\n'));\n            }\n          } else {\n            console.log(chalk.gray('  Skipping installation. You can install later with:'));\n            console.log(chalk.cyan('    npm install -g @composio/ao-cli\\n'));\n          }\n        }\n      } else {\n        console.log(chalk.green('  @composio/ao-cli is installed.'));\n      }\n\n      // Generate config\n      if (orchestratorConfigExists(cwd)) {\n        console.log(chalk.green('  agent-orchestrator.yaml already exists.'));\n        if (!nonInteractive) {\n          const regenerate = await confirm('  Regenerate configuration?', false);\n          if (regenerate) {\n            await configureOrchestrator(cwd, configPath, nonInteractive);\n          }\n        }\n      } else {\n        if (nonInteractive) {\n          // Auto-generate in non-interactive mode\n          await configureOrchestrator(cwd, configPath, nonInteractive);\n        } else {\n          const generate = await confirm('  Generate agent-orchestrator.yaml?');\n          if (generate) {\n            await configureOrchestrator(cwd, configPath, nonInteractive);\n          } else {\n            console.log(chalk.gray('  Skipping config generation.\\n'));\n          }\n        }\n      }\n    }\n\n    // Step 4: RTK Token Optimization\n    if (!options.linearOnly && !options.orchestratorOnly) {\n      console.log(chalk.bold('Step 4: RTK Token Optimization'));\n      console.log(chalk.gray('RTK reduces LLM token consumption by 60-90% across fleet agents.\\n'));\n\n      const rtkInstalled = isRtkInstalled();\n      if (rtkInstalled) {\n        console.log(chalk.green('  RTK is already installed.'));\n        console.log(chalk.gray('  Ensuring Claude Code hook is configured...'));\n        initRtkHook();\n      } else if (nonInteractive) {\n        console.log(chalk.gray('  Installing RTK (non-interactive mode)...'));\n        const success = installRtk();\n        if (success) {\n          initRtkHook();\n        }\n      } else {\n        const install = await confirm('  Install RTK for token-optimized agent sessions?');\n        if (install) {\n          const success = installRtk();\n          if (success) {\n            initRtkHook();\n          }\n        } else {\n          console.log(chalk.gray('  Skipping RTK installation. Install later with:'));\n          console.log(chalk.cyan('    cargo install --git https://github.com/rtk-ai/rtk'));\n          console.log(chalk.cyan('    rtk init -g\\n'));\n        }\n      }\n      console.log('');\n    }\n\n    // Step 5: Caveman Plugin\n    if (!options.linearOnly && !options.orchestratorOnly) {\n      console.log(chalk.bold('Step 5: Caveman Output Compression'));\n      console.log(chalk.gray('Caveman reduces output token usage by ~65-75% across fleet agents.\\n'));\n\n      const cavemanInstalled = isCavemanInstalled();\n      if (cavemanInstalled) {\n        console.log(chalk.green('  Caveman plugin is already installed.'));\n        console.log(chalk.gray('  Activate in any session with /caveman (modes: lite, full, ultra)'));\n      } else if (nonInteractive) {\n        console.log(chalk.gray('  Installing Caveman plugin (non-interactive mode)...'));\n        installCaveman();\n      } else {\n        const install = await confirm('  Install Caveman plugin for compressed agent output?');\n        if (install) {\n          installCaveman();\n        } else {\n          console.log(chalk.gray('  Skipping Caveman installation. Install later with:'));\n          console.log(chalk.cyan('    npx skills add JuliusBrussee/caveman\\n'));\n        }\n      }\n      console.log('');\n    }\n\n    // Summary\n    console.log(chalk.bold.green('\\nSetup Complete!\\n'));\n    console.log(chalk.white('Next steps:'));\n    console.log(chalk.gray('  1. Run ') + chalk.cyan('devpilot serve') + chalk.gray(' to start the UI'));\n    console.log(chalk.gray('  2. Run ') + chalk.cyan('ao start') + chalk.gray(' to start agent orchestrator'));\n    console.log(chalk.gray('  3. Use the UI to create items and dispatch to the fleet'));\n    console.log(chalk.gray('  4. Run ') + chalk.cyan('rtk gain') + chalk.gray(' to monitor token savings'));\n    console.log(chalk.gray('  5. Use ') + chalk.cyan('/caveman') + chalk.gray(' in sessions for compressed output\\n'));\n  });\n\n/**\n * Configure Linear integration\n */\nasync function configureLinear(configPath: string, config: Record<string, unknown>): Promise<void> {\n  console.log('');\n  console.log(chalk.gray('  Get your API key from: https://linear.app/settings/api\\n'));\n\n  const apiKey = await prompt('  Linear API key: ');\n  if (!apiKey) {\n    console.log(chalk.yellow('  No API key provided. Skipping Linear setup.\\n'));\n    return;\n  }\n\n  // Initialize Linear client to fetch teams\n  console.log(chalk.cyan('\\n  Connecting to Linear...'));\n  try {\n    const tempClient = linear.initLinearClient({ apiKey, teamId: '' });\n    const teams = await tempClient.getTeams();\n\n    if (teams.length === 0) {\n      console.log(chalk.yellow('  No teams found. Make sure you have access to at least one team.'));\n      return;\n    }\n\n    console.log(chalk.green(`  Found ${teams.length} team(s):\\n`));\n    teams.forEach((team, i) => {\n      console.log(chalk.white(`    ${i + 1}. ${team.name} (${team.key})`));\n    });\n\n    const teamChoice = await prompt('\\n  Select team number: ');\n    const teamIndex = parseInt(teamChoice, 10) - 1;\n\n    if (isNaN(teamIndex) || teamIndex < 0 || teamIndex >= teams.length) {\n      console.log(chalk.yellow('  Invalid selection. Skipping Linear setup.'));\n      return;\n    }\n\n    const selectedTeam = teams[teamIndex];\n\n    // Save to config\n    if (!config.integrations) config.integrations = {};\n    (config.integrations as Record<string, unknown>).linear = {\n      apiKey,\n      teamId: selectedTeam.id,\n      teamName: selectedTeam.name,\n      teamKey: selectedTeam.key,\n    };\n\n    writeFileSync(configPath, YAML.stringify(config));\n    console.log(chalk.green(`\\n  Linear configured for team: ${selectedTeam.name}\\n`));\n\n    // Set environment variable hint\n    console.log(chalk.gray('  For agent-orchestrator, also set the LINEAR_API_KEY environment variable:'));\n    console.log(chalk.cyan(`    export LINEAR_API_KEY=\"${apiKey}\"\\n`));\n  } catch (error) {\n    const message = error instanceof Error ? error.message : 'Unknown error';\n    console.log(chalk.red(`  Failed to connect: ${message}`));\n    console.log(chalk.gray('  You can configure Linear later with: devpilot config linear\\n'));\n  }\n}\n\n/**\n * Configure agent orchestrator\n */\nasync function configureOrchestrator(cwd: string, configPath: string, nonInteractive = false): Promise<void> {\n  const config = YAML.parse(readFileSync(configPath, 'utf-8'));\n  const linearTeamId = config.integrations?.linear?.teamId;\n\n  // Generate config\n  const aoConfig = generateOrchestratorConfig({\n    cwd,\n    linearTeamId,\n  });\n\n  // Ask about custom agent rules (skip in non-interactive mode)\n  if (!nonInteractive) {\n    const customRules = await confirm('\\n  Would you like to customize agent rules?', false);\n    if (customRules) {\n      console.log(chalk.gray('  Enter rules (one per line, empty line to finish):'));\n      const rules: string[] = [];\n      let line = '';\n      do {\n        line = await prompt('    > ');\n        if (line) rules.push(line);\n      } while (line);\n\n      if (rules.length > 0) {\n        const projectName = Object.keys(aoConfig.projects)[0];\n        aoConfig.projects[projectName].agentRules = rules.join('\\n');\n      }\n    }\n  }\n\n  // Write config\n  writeOrchestratorConfig(cwd, aoConfig);\n  console.log(chalk.green('\\n  Created agent-orchestrator.yaml'));\n\n  // Show sample YAML\n  console.log(chalk.gray('\\n  Configuration preview:'));\n  console.log(chalk.gray('  ' + '-'.repeat(40)));\n  const preview = YAML.stringify(aoConfig).split('\\n').slice(0, 15).join('\\n');\n  preview.split('\\n').forEach((line) => console.log(chalk.gray(`  ${line}`)));\n  console.log(chalk.gray('  ...\\n'));\n}\n","import { execSync, spawnSync } from 'child_process';\nimport { existsSync, readFileSync, writeFileSync } from 'fs';\nimport { join, basename } from 'path';\nimport { homedir } from 'os';\nimport chalk from 'chalk';\n\nexport interface SystemRequirements {\n  node: { installed: boolean; version: string | null; meetsMinimum: boolean };\n  git: { installed: boolean; version: string | null; meetsMinimum: boolean };\n  tmux: { installed: boolean };\n  gh: { installed: boolean; authenticated: boolean };\n  rtk: { installed: boolean; version: string | null };\n  caveman: { installed: boolean };\n}\n\nexport interface OrchestratorConfig {\n  dataDir: string;\n  worktreeDir: string;\n  projects: {\n    [key: string]: {\n      repo: string;\n      path: string;\n      defaultBranch: string;\n      tracker?: {\n        plugin: string;\n        teamId: string;\n      };\n      agentRules?: string;\n    };\n  };\n}\n\n/**\n * Check if a command exists and get its version\n */\nfunction checkCommand(cmd: string, versionArg = '--version'): { installed: boolean; version: string | null } {\n  try {\n    const result = spawnSync(cmd, [versionArg], { encoding: 'utf-8', stdio: 'pipe' });\n    if (result.status === 0) {\n      const versionMatch = result.stdout.match(/(\\d+\\.\\d+(\\.\\d+)?)/);\n      return {\n        installed: true,\n        version: versionMatch ? versionMatch[1] : null,\n      };\n    }\n    return { installed: false, version: null };\n  } catch {\n    return { installed: false, version: null };\n  }\n}\n\n/**\n * Parse version string and compare\n */\nfunction versionMeetsMinimum(version: string | null, minimum: string): boolean {\n  if (!version) return false;\n  const vParts = version.split('.').map(Number);\n  const mParts = minimum.split('.').map(Number);\n  for (let i = 0; i < mParts.length; i++) {\n    if ((vParts[i] || 0) > mParts[i]) return true;\n    if ((vParts[i] || 0) < mParts[i]) return false;\n  }\n  return true;\n}\n\n/**\n * Check all system requirements for agent-orchestrator\n */\nexport function checkSystemRequirements(): SystemRequirements {\n  // Check Node.js (minimum 20.0.0)\n  const node = checkCommand('node');\n  const nodeMeetsMin = versionMeetsMinimum(node.version, '20.0.0');\n\n  // Check Git (minimum 2.25.0)\n  const git = checkCommand('git');\n  const gitMeetsMin = versionMeetsMinimum(git.version, '2.25.0');\n\n  // Check tmux\n  const tmux = checkCommand('tmux', '-V');\n\n  // Check GitHub CLI and authentication\n  const gh = checkCommand('gh');\n  let ghAuthenticated = false;\n  if (gh.installed) {\n    try {\n      const result = spawnSync('gh', ['auth', 'status'], { encoding: 'utf-8', stdio: 'pipe' });\n      ghAuthenticated = result.status === 0;\n    } catch {\n      ghAuthenticated = false;\n    }\n  }\n\n  // Check RTK\n  const rtk = checkCommand('rtk');\n\n  // Check Caveman plugin\n  const cavemanInstalled = isCavemanInstalled();\n\n  return {\n    node: { ...node, meetsMinimum: nodeMeetsMin },\n    git: { ...git, meetsMinimum: gitMeetsMin },\n    tmux: { installed: tmux.installed },\n    gh: { installed: gh.installed, authenticated: ghAuthenticated },\n    rtk: { installed: rtk.installed, version: rtk.version },\n    caveman: { installed: cavemanInstalled },\n  };\n}\n\n/**\n * Print system requirements status\n */\nexport function printRequirementsStatus(reqs: SystemRequirements): void {\n  console.log(chalk.cyan('\\nSystem Requirements:'));\n  console.log('');\n\n  // Node.js\n  if (reqs.node.installed && reqs.node.meetsMinimum) {\n    console.log(chalk.green(`  ✓ Node.js ${reqs.node.version}`));\n  } else if (reqs.node.installed) {\n    console.log(chalk.yellow(`  ⚠ Node.js ${reqs.node.version} (requires 20.0.0+)`));\n  } else {\n    console.log(chalk.red('  ✗ Node.js not found'));\n  }\n\n  // Git\n  if (reqs.git.installed && reqs.git.meetsMinimum) {\n    console.log(chalk.green(`  ✓ Git ${reqs.git.version}`));\n  } else if (reqs.git.installed) {\n    console.log(chalk.yellow(`  ⚠ Git ${reqs.git.version} (requires 2.25.0+)`));\n  } else {\n    console.log(chalk.red('  ✗ Git not found'));\n  }\n\n  // tmux\n  if (reqs.tmux.installed) {\n    console.log(chalk.green('  ✓ tmux'));\n  } else {\n    console.log(chalk.yellow('  ⚠ tmux not found (optional, for session management)'));\n  }\n\n  // GitHub CLI\n  if (reqs.gh.installed && reqs.gh.authenticated) {\n    console.log(chalk.green('  ✓ GitHub CLI (authenticated)'));\n  } else if (reqs.gh.installed) {\n    console.log(chalk.yellow('  ⚠ GitHub CLI (not authenticated - run: gh auth login)'));\n  } else {\n    console.log(chalk.yellow('  ⚠ GitHub CLI not found (optional, for PR creation)'));\n  }\n\n  // RTK\n  if (reqs.rtk.installed) {\n    console.log(chalk.green(`  ✓ RTK ${reqs.rtk.version || ''} (token optimization)`));\n  } else {\n    console.log(chalk.yellow('  ⚠ RTK not found (recommended, for 60-90% token savings)'));\n  }\n\n  // Caveman\n  if (reqs.caveman.installed) {\n    console.log(chalk.green('  ✓ Caveman plugin (output token compression)'));\n  } else {\n    console.log(chalk.yellow('  ⚠ Caveman not found (optional, for ~65-75% output token savings)'));\n  }\n}\n\n/**\n * Check if agent-orchestrator CLI is installed\n */\nexport function isOrchestratorInstalled(): boolean {\n  try {\n    const result = spawnSync('npx', ['@composio/ao-cli', '--version'], {\n      encoding: 'utf-8',\n      stdio: 'pipe',\n    });\n    return result.status === 0;\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Install agent-orchestrator CLI globally\n */\nexport function installOrchestrator(): boolean {\n  console.log(chalk.cyan('\\nInstalling @composio/ao-cli...'));\n  try {\n    execSync('npm install -g @composio/ao-cli', { stdio: 'inherit' });\n    console.log(chalk.green('✓ @composio/ao-cli installed successfully'));\n    return true;\n  } catch {\n    console.log(chalk.red('✗ Failed to install @composio/ao-cli'));\n    console.log(chalk.gray('  Try manually: npm install -g @composio/ao-cli'));\n    return false;\n  }\n}\n\n/**\n * Check if RTK (Rust Token Killer) is installed\n */\nexport function isRtkInstalled(): boolean {\n  try {\n    const result = spawnSync('rtk', ['--version'], { encoding: 'utf-8', stdio: 'pipe' });\n    return result.status === 0;\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Install RTK via cargo (requires Rust toolchain)\n */\nexport function installRtk(): boolean {\n  // Try cargo install first (most reliable)\n  const hasCargo = spawnSync('cargo', ['--version'], { encoding: 'utf-8', stdio: 'pipe' }).status === 0;\n\n  if (hasCargo) {\n    console.log(chalk.cyan('\\n  Installing RTK via cargo (this may take a few minutes)...'));\n    try {\n      execSync('cargo install --git https://github.com/rtk-ai/rtk', { stdio: 'inherit' });\n      console.log(chalk.green('  ✓ RTK installed successfully'));\n      return true;\n    } catch {\n      console.log(chalk.red('  ✗ Failed to install RTK via cargo'));\n    }\n  }\n\n  // Try curl install script as fallback\n  console.log(chalk.cyan('\\n  Installing RTK via install script...'));\n  try {\n    execSync('curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh', {\n      stdio: 'inherit',\n    });\n    console.log(chalk.green('  ✓ RTK installed successfully'));\n    return true;\n  } catch {\n    console.log(chalk.red('  ✗ Failed to install RTK'));\n    console.log(chalk.gray('  Install manually: cargo install --git https://github.com/rtk-ai/rtk'));\n    console.log(chalk.gray('  Or: brew install rtk'));\n    return false;\n  }\n}\n\n/**\n * Initialize RTK Claude Code hook for automatic command rewriting\n */\nexport function initRtkHook(): boolean {\n  console.log(chalk.cyan('\\n  Initializing RTK hook for Claude Code...'));\n  try {\n    execSync('rtk init -g', { encoding: 'utf-8', stdio: 'pipe' });\n    console.log(chalk.green('  ✓ RTK hook initialized'));\n    return true;\n  } catch {\n    console.log(chalk.yellow('  ⚠ RTK hook init requires manual step: rtk init -g'));\n    return false;\n  }\n}\n\n/**\n * Check if the Caveman Claude Code plugin is installed.\n * Detects by checking for the caveman hook scripts in ~/.claude/hooks/\n * or for caveman entries in ~/.claude/settings.json.\n */\nexport function isCavemanInstalled(): boolean {\n  const claudeDir = join(homedir(), '.claude');\n\n  // Check for hook script (installed via hooks/install.sh or npx skills add)\n  if (existsSync(join(claudeDir, 'hooks', 'caveman-activate.js'))) {\n    return true;\n  }\n\n  // Check settings.json for caveman hook entries\n  const settingsPath = join(claudeDir, 'settings.json');\n  if (existsSync(settingsPath)) {\n    try {\n      const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));\n      const settingsStr = JSON.stringify(settings);\n      if (settingsStr.includes('caveman')) {\n        return true;\n      }\n    } catch {\n      // Ignore parse errors\n    }\n  }\n\n  return false;\n}\n\n/**\n * Install the Caveman plugin for Claude Code using npx skills add.\n * This installs the plugin hooks and skill definitions automatically.\n */\nexport function installCaveman(): boolean {\n  console.log(chalk.cyan('\\n  Installing Caveman plugin for Claude Code...'));\n  try {\n    execSync('npx -y skills add JuliusBrussee/caveman', {\n      stdio: 'inherit',\n      timeout: 120000,\n    });\n    console.log(chalk.green('  ✓ Caveman plugin installed successfully'));\n    return true;\n  } catch {\n    // Fallback: try the hook install script directly\n    console.log(chalk.yellow('  npx skills add failed, trying hook install script...'));\n    try {\n      execSync(\n        'bash <(curl -fsSL https://raw.githubusercontent.com/JuliusBrussee/caveman/main/hooks/install.sh)',\n        { stdio: 'inherit', shell: '/bin/bash', timeout: 60000 }\n      );\n      console.log(chalk.green('  ✓ Caveman hooks installed successfully'));\n      return true;\n    } catch {\n      console.log(chalk.red('  ✗ Failed to install Caveman plugin'));\n      console.log(chalk.gray('  Install manually: npx skills add JuliusBrussee/caveman'));\n      return false;\n    }\n  }\n}\n\n/**\n * Detect git repository information\n */\nexport function detectRepoInfo(cwd: string): { repo: string; branch: string } | null {\n  try {\n    // Get remote origin URL\n    const remoteResult = spawnSync('git', ['remote', 'get-url', 'origin'], {\n      cwd,\n      encoding: 'utf-8',\n      stdio: 'pipe',\n    });\n\n    if (remoteResult.status !== 0) return null;\n\n    const remoteUrl = remoteResult.stdout.trim();\n    let repo = '';\n\n    // Parse GitHub URL (HTTPS or SSH)\n    const httpsMatch = remoteUrl.match(/github\\.com\\/([^/]+\\/[^/]+?)(?:\\.git)?$/);\n    const sshMatch = remoteUrl.match(/git@github\\.com:([^/]+\\/[^/]+?)(?:\\.git)?$/);\n\n    if (httpsMatch) {\n      repo = httpsMatch[1];\n    } else if (sshMatch) {\n      repo = sshMatch[1];\n    } else {\n      return null;\n    }\n\n    // Get default branch\n    const branchResult = spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {\n      cwd,\n      encoding: 'utf-8',\n      stdio: 'pipe',\n    });\n\n    const branch = branchResult.status === 0 ? branchResult.stdout.trim() : 'main';\n\n    return { repo, branch };\n  } catch {\n    return null;\n  }\n}\n\n/**\n * Generate agent-orchestrator.yaml configuration\n */\nexport function generateOrchestratorConfig(options: {\n  cwd: string;\n  linearTeamId?: string;\n  agentRules?: string;\n}): OrchestratorConfig {\n  const { cwd, linearTeamId, agentRules } = options;\n  const projectName = basename(cwd);\n  const repoInfo = detectRepoInfo(cwd);\n\n  const config: OrchestratorConfig = {\n    dataDir: '~/.agent-orchestrator',\n    worktreeDir: '~/.worktrees',\n    projects: {\n      [projectName]: {\n        repo: repoInfo?.repo || `owner/${projectName}`,\n        path: cwd,\n        defaultBranch: repoInfo?.branch || 'main',\n      },\n    },\n  };\n\n  // Add Linear tracker if team ID provided\n  if (linearTeamId) {\n    config.projects[projectName].tracker = {\n      plugin: 'linear',\n      teamId: linearTeamId,\n    };\n  }\n\n  // Add agent rules if provided\n  if (agentRules) {\n    config.projects[projectName].agentRules = agentRules;\n  } else {\n    // Default agent rules\n    config.projects[projectName].agentRules = `Always link Linear tickets in commit messages.\nRun tests before pushing.\nUse conventional commits (feat:, fix:, chore:).\nCreate small, focused PRs.`;\n  }\n\n  return config;\n}\n\n/**\n * Write agent-orchestrator.yaml to disk\n */\nexport function writeOrchestratorConfig(cwd: string, config: OrchestratorConfig): void {\n  const YAML = require('yaml');\n  const configPath = join(cwd, 'agent-orchestrator.yaml');\n  const yamlContent = YAML.stringify(config);\n  writeFileSync(configPath, yamlContent);\n}\n\n/**\n * Check if agent-orchestrator.yaml exists\n */\nexport function orchestratorConfigExists(cwd: string): boolean {\n  return existsSync(join(cwd, 'agent-orchestrator.yaml'));\n}\n\n/**\n * Get installation instructions for missing requirements\n */\nexport function getInstallInstructions(reqs: SystemRequirements): string[] {\n  const instructions: string[] = [];\n\n  if (!reqs.node.installed || !reqs.node.meetsMinimum) {\n    instructions.push('Node.js 20+: https://nodejs.org or use nvm: nvm install 20');\n  }\n\n  if (!reqs.git.installed || !reqs.git.meetsMinimum) {\n    instructions.push('Git 2.25+: https://git-scm.com/downloads');\n  }\n\n  if (!reqs.tmux.installed) {\n    instructions.push('tmux: brew install tmux (macOS) or apt install tmux (Linux)');\n  }\n\n  if (!reqs.gh.installed) {\n    instructions.push('GitHub CLI: brew install gh (macOS) or https://cli.github.com');\n  } else if (!reqs.gh.authenticated) {\n    instructions.push('GitHub CLI auth: gh auth login');\n  }\n\n  if (!reqs.rtk.installed) {\n    instructions.push('RTK (token savings): cargo install --git https://github.com/rtk-ai/rtk');\n  }\n\n  if (!reqs.caveman.installed) {\n    instructions.push('Caveman (output compression): npx skills add JuliusBrussee/caveman');\n  }\n\n  return instructions;\n}\n","import { Command } from 'commander';\nimport { connectCommand, disconnectCommand, statusCommand } from './bridge/index';\n\nexport const bridgeCommand = new Command('bridge')\n  .description('Manage connection to DevPilot cloud bridge')\n  .addCommand(connectCommand)\n  .addCommand(disconnectCommand)\n  .addCommand(statusCommand);\n","import os from 'os';\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport { BridgeClient, DispatchLoop, HeartbeatService } from '@devpilot.sh/bridge-client';\nimport { createBridgeDispatchHandler } from './dispatch-handler';\nimport { createConductorDispatchHandler } from './conductor-handler';\nimport { homedir } from 'node:os';\nimport { join, dirname } from 'node:path';\nimport { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';\n\n/**\n * A machine name that does not change between runs.\n *\n * The hosted side upserts orchestrators on (orgId, name), so a stable name\n * means one orchestrator per machine. `os.hostname()` is not stable on macOS:\n * it returns the mDNS name or the DHCP-assigned one depending on the network,\n * and this machine alternated between `Mac.lan` and\n * `Garretts-MacBook-Pro-2.local` across restarts on the same day.\n *\n * Every flip minted a NEW orchestrator. That littered the org with duplicate\n * machines, and worse: sessions belong to the orchestrator that claimed them,\n * so a rename orphaned every run in flight — `requireOwnedSession` correctly\n * answered 404 and the bridge could never report how those runs ended.\n *\n * So the first name this machine ever used is written down and reused. An\n * explicit `--name` still wins, and is what a user should reach for if they\n * genuinely want to re-identify a machine.\n */\nfunction stableMachineName(): string {\n  const path = join(homedir(), '.devpilot', 'machine.json');\n  try {\n    if (existsSync(path)) {\n      const saved = JSON.parse(readFileSync(path, 'utf8')) as { name?: string };\n      if (saved.name) return saved.name;\n    }\n  } catch {\n    // A corrupt file must not stop the bridge from connecting; fall through and\n    // rewrite it below.\n  }\n\n  const name = os.hostname();\n  try {\n    mkdirSync(dirname(path), { recursive: true });\n    writeFileSync(path, JSON.stringify({ name }, null, 2), 'utf8');\n  } catch {\n    // Unwritable home directory: the name is still correct for this run, it\n    // just will not be remembered.\n  }\n  return name;\n}\nimport { ConductorWatcher } from './conductor-watcher';\nimport { CommandApplier } from './command-applier';\nimport { AdoptionWatcher } from './adoption-watcher';\nimport { SessionObserver } from './observer';\nimport { ResumeApplier } from './resume-applier';\nimport { runIntrospection } from './introspect';\n\ninterface ConnectOptions {\n  url?: string;\n  token?: string;\n  name: string;\n  repos?: string;\n  mode: 'ao-cli' | 'http' | 'claude-session';\n  transport: 'realtime' | 'poll';\n  sessionApiUrl?: string;\n  sessionApiKey?: string;\n  plan?: boolean;\n  cockpitUrl?: string;\n  maxJobs: string;\n  httpUrl?: string;\n  aoProject?: string;\n  aoPath?: string;\n  discover?: boolean;\n  observe?: boolean;\n  adopt?: boolean;\n  adoptAllRepos?: boolean;\n}\n\nexport const connectCommand = new Command('connect')\n  .description('Connect this machine to a DevPilot bridge and run dispatched work locally')\n  .option('-u, --url <url>', 'Bridge URL', process.env.DEVPILOT_BRIDGE_URL)\n  .option('-t, --token <token>', 'Orchestrator token (dp_orch_…)', process.env.DEVPILOT_BRIDGE_TOKEN)\n  .option('-n, --name <name>', 'Name for this machine (defaults to a stable name for this machine)')\n  .option('-r, --repos <repos>', 'Comma-separated repos this machine handles')\n  // Default is `http`: ao-cli is deprecated and throws (see ao-cli-adapter.ts),\n  // and http is the mode that points at the current ao daemon on :3001.\n  .option('-m, --mode <mode>', 'Local orchestrator mode (http|claude-session)', 'http')\n  .option(\n    '--transport <transport>',\n    'realtime | poll — polling is fully correct, just higher latency',\n    process.env.DEVPILOT_BRIDGE_TRANSPORT || 'realtime',\n  )\n  .option('-j, --max-jobs <n>', 'Max concurrent local jobs', '4')\n  .option('--http-url <url>', 'Orchestrator URL (required for --mode http)')\n  .option('--ao-project <name>', 'ao project name (for --mode ao-cli)')\n  .option('--ao-path <path>', 'Path to the ao binary (default: ao on PATH)')\n  .option(\n    '--session-api-url <url>',\n    'Session runner URL (required for --mode claude-session)',\n    process.env.DEVPILOT_SESSION_API_URL,\n  )\n  .option(\n    '--session-api-key <token>',\n    'Bearer token the session runner expects',\n    process.env.DEVPILOT_SESSION_API_KEY,\n  )\n  // Off by default: planning a ticket costs a model call and stops at a human\n  // review gate, which is a different contract from \"run this ticket now\".\n  // Opt in per machine until the planned path is the one you want by default.\n  .option(\n    '--plan',\n    'Route dispatches through the conductor (plan → waves) instead of one session',\n    process.env.DEVPILOT_BRIDGE_PLAN === 'true',\n  )\n  .option(\n    '--cockpit-url <url>',\n    'Local cockpit base URL for --plan',\n    process.env.DEVPILOT_COCKPIT_URL || 'http://127.0.0.1:3000',\n  )\n  /**\n   * Introspection — TRD 21.\n   *\n   * Discovery is ON by default because it is inert: a filesystem walk and\n   * `git remote`, producing rows a member must accept before anything routes.\n   * Adoption is OFF by default because it creates issues on a shared board,\n   * and a flag someone set once should not keep writing to their team's Linear\n   * every time a laptop reconnects.\n   */\n  .option('--no-discover', 'Do not report which repos this machine has agent history for')\n  .option(\n    '--no-observe',\n    'Do not report the agent sessions running on this machine to the cockpit',\n  )\n  .option(\n    '--adopt',\n    'Also put agent sessions already running on this machine onto the board',\n    process.env.DEVPILOT_BRIDGE_ADOPT === 'true',\n  )\n  .option(\n    '--adopt-all-repos',\n    'With --adopt, include repos this machine does not route (names them first)',\n    false,\n  )\n  .action(async (options: ConnectOptions) => {\n    if (!options.url) {\n      console.error(chalk.red('✗ Bridge URL required (--url or DEVPILOT_BRIDGE_URL)'));\n      process.exit(1);\n    }\n    if (!options.token) {\n      console.error(chalk.red('✗ Token required (--token or DEVPILOT_BRIDGE_TOKEN)'));\n      console.error(chalk.gray('  Mint one in the dashboard under Settings → Tokens.'));\n      process.exit(1);\n    }\n\n    const repos = options.repos?.split(',').map((r) => r.trim()).filter(Boolean) ?? [];\n    const maxConcurrentJobs = Math.max(1, parseInt(options.maxJobs, 10) || 4);\n\n    console.log(chalk.cyan('🌉 DevPilot bridge'));\n    console.log(chalk.gray(`   ${options.url}`));\n    console.log(chalk.gray(`   machine: ${options.name}`));\n    console.log('');\n\n    // --plan routes dispatches to the local cockpit, which builds its own\n    // orchestrator config from env. The local orchestrator mode is therefore\n    // unused on that path, and demanding --http-url for it blocks the planned\n    // flow with a message about a daemon it will never contact.\n    const usesLocalOrchestrator = !options.plan;\n\n    if (usesLocalOrchestrator && options.mode === 'ao-cli') {\n      console.error(chalk.red('✗ --mode ao-cli is deprecated and non-functional.'));\n      console.error(chalk.gray('  `ao` is now a daemon on 127.0.0.1:3001; point http mode at it:'));\n      console.error(chalk.gray('    devpilot bridge connect --mode http --http-url http://127.0.0.1:3001'));\n      process.exit(1);\n    }\n    if (usesLocalOrchestrator && options.mode === 'http' && !options.httpUrl) {\n      console.error(chalk.red('✗ --mode http requires --http-url'));\n      console.error(chalk.gray('  For the ao daemon: --http-url http://127.0.0.1:3001'));\n      process.exit(1);\n    }\n    if (usesLocalOrchestrator && options.mode === 'claude-session' && !options.sessionApiUrl) {\n      console.error(chalk.red('✗ --mode claude-session requires --session-api-url'));\n      console.error(chalk.gray('  Start the runner, then point at it:'));\n      console.error(chalk.gray('    devpilot session-runner --port 3900 --token <t>'));\n      console.error(chalk.gray('    … --session-api-url http://127.0.0.1:3900 --session-api-key <t>'));\n      process.exit(1);\n    }\n\n    const client = new BridgeClient({ bridgeUrl: options.url, token: options.token });\n\n    let registration;\n    try {\n      const machineName = options.name ?? stableMachineName();\n      registration = await client.register({ name: machineName, repos, maxConcurrentJobs });\n    } catch (err) {\n      console.error(chalk.red('✗ Registration failed'));\n      console.error(chalk.red(`   ${err instanceof Error ? err.message : err}`));\n      process.exit(1);\n    }\n\n    console.log(chalk.green('✓ Registered'));\n    console.log(chalk.gray(`   orchestrator: ${registration.orchestratorId}`));\n    console.log(chalk.gray(`   repos: ${repos.join(', ') || '(none)'}`));\n    if (repos.length === 0) {\n      console.log(chalk.yellow('   ⚠ No repos specified — nothing can route to this machine.'));\n      console.log(chalk.gray('     Re-run with --repos owner/name to receive dispatches.'));\n    }\n    console.log('');\n\n    // The bridge returns realtime credentials only when it can mint a scoped\n    // JWT. If it could not, or the user asked for polling, we poll — which is\n    // fully correct, because the delivery guarantee is in the queue table.\n    const useRealtime = options.transport !== 'poll' && registration.realtime !== null;\n    if (options.transport !== 'poll' && !registration.realtime) {\n      console.log(chalk.yellow('   Realtime unavailable from this bridge — polling instead.'));\n    }\n\n    // Reports a finished conductor run to the bridge, which is what makes the\n    // hosted side write back to Linear. Only the planned path needs it: the\n    // single-session path reports through the orchestrator's status poller.\n    const conductorWatcher = options.plan\n      ? new ConductorWatcher({\n          client,\n          cockpitUrl: options.cockpitUrl!,\n          // Survives a restart. Without this, upgrading the CLI or closing a\n          // laptop lid orphaned every in-flight run: the cockpit kept working\n          // and Linear was never told how any of it ended.\n          statePath: join(homedir(), '.devpilot', 'conductor-watch.json'),\n          onLog: (line) => console.log(chalk.blue(`   ${line}`)),\n          onLost: (run) =>\n            console.log(\n              chalk.yellow(\n                `   ${run.linearIdentifier} still running at shutdown — it will be picked up on the next start`,\n              ),\n            ),\n        })\n      : null;\n\n    /**\n     * Decisions taken in the hosted cockpit, applied here.\n     *\n     * Polled on the same cadence as everything else rather than pushed: the\n     * machine holding the credentials stays the only thing that can act, and\n     * nothing needs to reach into it.\n     */\n    const commandApplier =\n      options.plan && conductorWatcher\n        ? new CommandApplier({\n            client,\n            cockpitUrl: options.cockpitUrl!,\n            resolveItemId: (sessionId) => conductorWatcher.itemFor(sessionId),\n            onLog: (line) => console.log(chalk.blue(`   ${line}`)),\n          })\n        : null;\n\n\n    const readopted = conductorWatcher?.restore() ?? 0;\n    if (readopted > 0) {\n      console.log(\n        chalk.blue(\n          `   Resumed watching ${readopted} run${readopted === 1 ? '' : 's'} from a previous session`,\n        ),\n      );\n    }\n\n    /**\n     * Look around this machine — TRD 21 §8.1.\n     *\n     * Runs on every connect, unless switched off. It is cheap by construction:\n     * no model call, no board write, no Linear API call, just a filesystem walk\n     * and `git remote`. Adoption, which creates issues, stays behind `--adopt`.\n     *\n     * This is also the answer to the warning printed a few lines above. A first\n     * connect used to say \"no repos, nothing can route here\" and stop; now it\n     * follows that with the repos it can see.\n     */\n    const adoptionWatcher = new AdoptionWatcher({\n      client,\n      statePath: join(homedir(), '.devpilot', 'adoption-watch.json'),\n      onLog: (line) => console.log(chalk.blue(`   ${line}`)),\n    });\n\n    const resumedAdoptions = adoptionWatcher.restore();\n    if (resumedAdoptions > 0) {\n      console.log(\n        chalk.blue(\n          `   Watching ${resumedAdoptions} adopted session${resumedAdoptions === 1 ? '' : 's'} from a previous run`,\n        ),\n      );\n    }\n\n    /**\n     * Observe continuously — TRD 22 §8.\n     *\n     * On by default and needing no configuration at all: no Linear workspace,\n     * no team, no route. This is what makes \"turn the bridge on and your\n     * sessions are there\" true rather than aspirational.\n     */\n    const observer =\n      options.observe !== false\n        ? new SessionObserver({\n            client,\n            machineName: options.name ?? stableMachineName(),\n            repos,\n            onLog: (line) => console.log(chalk.gray(`   ${line}`)),\n          })\n        : null;\n\n    if (observer) {\n      const first = await observer.sweep();\n      if (first && first.observed > 0) {\n        console.log(\n          chalk.green(\n            `   ✓ Observing ${first.observed} agent session${first.observed === 1 ? '' : 's'} on this machine`,\n          ),\n        );\n        console.log(chalk.gray(`     ${client.hostedUrl()}/cockpit`));\n        console.log('');\n      }\n      observer.start();\n    }\n\n    /**\n     * The command return path — TRD 23 §7.1.\n     *\n     * This used to run only under `--plan`, because the only commands were\n     * conductor decisions. `resume` is not one: it is how a person picks up a\n     * session DevPilot never dispatched, and a bridge in single-session mode\n     * must be able to apply it. So the poll moved out from behind the flag.\n     *\n     * ONE poll, then routed. Two pollers would race to claim the same rows and\n     * each would see half of them.\n     */\n    /**\n     * Constructed when EITHER mode is possible, not only when both are.\n     *\n     * This required `--session-api-url`, which meant a bridge started with\n     * `--plan --cockpit-url` — a perfectly good planning bridge, and the shape\n     * the reference machine actually runs — could take the wheel in neither\n     * mode. Planning never touches the session runner; it is an HTTP call to\n     * the cockpit. Gating both on the runner was simply wrong.\n     *\n     * Each mode refuses individually when its own dependency is missing, and\n     * says which one to start.\n     */\n    const resumeApplier =\n      observer && (options.sessionApiUrl || options.cockpitUrl)\n        ? new ResumeApplier({\n            client,\n            sessionApiUrl: options.sessionApiUrl,\n            sessionApiKey: options.sessionApiKey,\n            // Deliberately none: an adopted session is reported by the\n            // observation sweep, which is already watching its transcript.\n            callbackUrl: '',\n            // Planning is an HTTP call to the local cockpit; without one the\n            // applier refuses `plan` and says so rather than silently\n            // continuing the conversation instead.\n            cockpitUrl: options.cockpitUrl,\n            resolveTarget: (key) => {\n              const at = observer.targetFor(key);\n              return at ? { ...at, cwd: '' } : undefined;\n            },\n            onLog: (line) => console.log(chalk.blue(`   ${line}`)),\n          })\n        : null;\n\n    if (commandApplier || resumeApplier) {\n      const pump = async () => {\n        let commands;\n        try {\n          commands = await client.pollSessionCommands();\n        } catch {\n          // Briefly unreachable is not worth stopping a bridge for.\n          return;\n        }\n        for (const command of commands) {\n          if (ResumeApplier.handles(command)) {\n            if (resumeApplier) {\n              await resumeApplier.apply(command);\n            } else {\n              /**\n               * Told, not left pending. A bridge with no session runner cannot\n               * take the wheel, and a cockpit button that spins forever is\n               * worse than one that says why it cannot.\n               */\n              await client.acknowledgeCommands(\n                [command.id],\n                'failed',\n                'This machine has no session runner, so it cannot take the wheel. ' +\n                  'Start one with `devpilot session-runner` and reconnect.',\n              );\n            }\n          } else if (commandApplier) {\n            await commandApplier.applyOne(command);\n          } else {\n            await client.acknowledgeCommands(\n              [command.id],\n              'failed',\n              'This bridge is not running a conductor, so it cannot apply that decision.',\n            );\n          }\n        }\n      };\n      const tick = () => void pump();\n      setInterval(tick, 15_000).unref?.();\n      tick();\n    }\n\n    if (options.discover !== false) {\n      await runIntrospection({\n        client,\n        machineName: options.name ?? stableMachineName(),\n        repos,\n        adopt: Boolean(options.adopt),\n        allRepos: Boolean(options.adoptAllRepos),\n        watcher: adoptionWatcher,\n      });\n    }\n\n    const loop = new DispatchLoop({\n      client,\n      orchestratorId: registration.orchestratorId,\n      realtime: useRealtime && registration.realtime\n        ? {\n            supabaseUrl: registration.realtime.supabaseUrl,\n            anonKey: registration.realtime.anonKey,\n            jwt: registration.realtime.jwt,\n          }\n        : null,\n      maxConcurrent: maxConcurrentJobs,\n      handler: options.plan\n        ? createConductorDispatchHandler({\n            client,\n            cockpitUrl: options.cockpitUrl!,\n            watcher: conductorWatcher!,\n            onLog: (line) => console.log(chalk.blue(`   ${line}`)),\n          })\n        : createBridgeDispatchHandler({\n            client,\n            orchestratorMode: options.mode,\n            httpUrl: options.httpUrl,\n            sessionApiUrl: options.sessionApiUrl,\n            sessionApiKey: options.sessionApiKey,\n            aoProjectName: options.aoProject,\n            aoPath: options.aoPath,\n            onLog: (line) => console.log(chalk.blue(`   ${line}`)),\n          }),\n      onLog: (line) => console.log(chalk.gray(`   ${line}`)),\n      onError: (e) => console.log(chalk.yellow(`   ${e.message}`)),\n    });\n\n    const heartbeat = new HeartbeatService({\n      client,\n      activeJobs: () => loop.activeJobs,\n      onError: (e) => console.log(chalk.gray(`   heartbeat: ${e.message}`)),\n    });\n\n    await loop.start();\n    heartbeat.start();\n\n    console.log(chalk.green(`✓ Listening (${useRealtime ? 'realtime' : 'poll'})`));\n    console.log(chalk.gray('   Agents run on THIS machine. Ctrl+C to disconnect.'));\n    console.log('');\n\n    let shuttingDown = false;\n    const shutdown = async () => {\n      if (shuttingDown) return;\n      shuttingDown = true;\n      console.log('');\n      console.log(chalk.yellow('Disconnecting…'));\n      heartbeat.stop();\n      observer?.stop();\n      // Before the loop: stopping surfaces any run still in flight via onLost,\n      // and that warning is the only signal that a ticket's completion will\n      // never reach Linear.\n      conductorWatcher?.stop();\n      await loop.stop();\n      console.log(chalk.green('✓ Disconnected'));\n      process.exit(0);\n    };\n\n    process.on('SIGINT', () => void shutdown());\n    process.on('SIGTERM', () => void shutdown());\n\n    await new Promise<never>(() => {});\n  });\n","import type { BridgeClient, TaskDispatchMessage } from '@devpilot.sh/bridge-client';\nimport { orchestrator } from '@devpilot.sh/core';\n\n/**\n * Derived structurally rather than imported by name: core's dts rollup does not\n * re-export this through its public surface, and this file should not depend on\n * that being fixed.\n */\ntype OrchestratorService = ReturnType<typeof orchestrator.getOrchestratorService>;\n// initStatusPoller(service, config) — the service is arg 0, config is arg 1.\ntype PollerConfig = NonNullable<Parameters<typeof orchestrator.initStatusPoller>[1]>;\ntype JobStatus = Parameters<NonNullable<PollerConfig['onStatusUpdate']>>[1];\ntype CompletionReport = Parameters<NonNullable<PollerConfig['onComplete']>>[1];\n\nexport interface DispatchHandlerOptions {\n  client: BridgeClient;\n  orchestratorMode: 'ao-cli' | 'http' | 'claude-session';\n  aoProjectName?: string;\n  aoPath?: string;\n  httpUrl?: string;\n  apiKey?: string;\n  /**\n   * Where the local session runner listens, for `claude-session` mode.\n   *\n   * Without these the adapter is constructed with no endpoint and every\n   * dispatch goes nowhere — the mode was selectable from `--mode` and could\n   * never have worked.\n   */\n  sessionApiUrl?: string;\n  sessionApiKey?: string;\n  callbackUrl?: string;\n  /** Status poll cadence. Core defaults to 5s. */\n  pollIntervalMs?: number;\n  onLog?: (line: string) => void;\n}\n\n/** Resolvers for sessions currently in flight, keyed by sessionId. */\ntype Outcome = { ok: boolean; error?: string; reported?: boolean };\ntype Settler = (outcome: Outcome) => void;\nconst inFlight = new Map<string, Settler>();\n\nfunction service(opts: DispatchHandlerOptions): OrchestratorService {\n  const existing = orchestrator.getOrchestratorServiceOrNull();\n  if (existing) return existing;\n\n  // NOTE: the config field is `url`, not `httpUrl`. This previously passed\n  // `httpUrl` behind an `as` cast, which silenced the mismatch entirely — http\n  // mode could never have reached an orchestrator. No cast now, so the compiler\n  // checks it.\n  return orchestrator.initOrchestratorService({\n    mode: opts.orchestratorMode,\n    url: opts.httpUrl,\n    apiKey: opts.apiKey,\n    callbackUrl: opts.callbackUrl,\n    aoProjectName: opts.aoProjectName,\n    aoPath: opts.aoPath,\n    sessionApiUrl: opts.sessionApiUrl,\n    sessionApiKey: opts.sessionApiKey,\n    pollIntervalMs: opts.pollIntervalMs,\n  });\n}\n\n/**\n * Wire the status poller ONCE, with callbacks that report to the bridge.\n *\n * This corrects TRD 05 §6.6, which said to subscribe to `service.onEvent`. That\n * does not work: OrchestratorService.dispatch simply forwards to the adapter and\n * emits nothing itself. Status feedback comes from StatusPoller, which the HOST\n * must wire — the Next app does exactly this via orchestrator/host-wiring.ts,\n * and the CLI had no equivalent. Observed before this fix: the stub agent ran to\n * completion and the session stayed `pending` forever, because nobody was\n * polling.\n */\nfunction ensurePoller(opts: DispatchHandlerOptions, svc: OrchestratorService): void {\n  if (orchestrator.isStatusPollerInitialized()) return;\n  const log = opts.onLog ?? (() => {});\n\n  const poller = orchestrator.initStatusPoller(svc, {\n    pollIntervalMs: opts.pollIntervalMs ?? 2000,\n    maxRetries: 3,\n\n    onStatusUpdate: async (sessionId: string, status: JobStatus) => {\n      if (!inFlight.has(sessionId)) return;\n\n      // StatusPoller fires onStatusUpdate for EVERY status change, including\n      // the terminal one, and only then calls handleCompletion. Reporting a\n      // terminal status here would post `running` for a job that just finished\n      // — observed as a `progress` event landing AFTER `complete` in the event\n      // trail, which makes a finished session flicker back to running in the\n      // dashboard. Terminal states belong to onComplete/onError alone.\n      if (status.status === 'complete' || status.status === 'error' || status.status === 'cancelled') {\n        return;\n      }\n\n      try {\n        await opts.client.reportSessionStatus(sessionId, {\n          status: status.status === 'queued' ? 'dispatched' : 'running',\n          progressPercent: Math.max(0, Math.min(100, status.progressPercent ?? 0)),\n          message: status.message ?? status.currentStep,\n        });\n      } catch (e) {\n        log(`status report failed: ${e instanceof Error ? e.message : e}`);\n      }\n    },\n\n    onComplete: async (sessionId: string, report: CompletionReport) => {\n      const settle = inFlight.get(sessionId);\n      try {\n        await opts.client.reportSessionComplete(sessionId, {\n          success: report.success,\n          ...(report.prUrl ? { prUrl: report.prUrl } : {}),\n          ...(report.summary ? { summary: report.summary } : {}),\n          ...(report.tokensUsed !== undefined ? { tokensUsed: report.tokensUsed } : {}),\n          ...(report.costUsd !== undefined ? { costUsd: report.costUsd } : {}),\n          ...(report.success ? {} : { errorMessage: report.error?.message ?? 'Agent failed' }),\n        });\n        // Reported successfully — including a reported FAILURE. Either way the\n        // bridge now knows the terminal state, so the catch block below must\n        // not report it a second time.\n        settle?.({ ok: report.success, error: report.error?.message, reported: true });\n      } catch (e) {\n        const msg = e instanceof Error ? e.message : String(e);\n        log(`completion report failed: ${msg}`);\n        settle?.({ ok: false, error: msg });\n      }\n    },\n\n    onError: async (sessionId: string, error: Error) => {\n      const settle = inFlight.get(sessionId);\n      try {\n        await opts.client.reportSessionComplete(sessionId, {\n          success: false,\n          errorMessage: error.message,\n        });\n      } catch {\n        /* the settle below still releases the claim */\n      }\n      settle?.({ ok: false, error: error.message, reported: true });\n    },\n  });\n\n  poller.start();\n}\n\n/**\n * Bridge dispatch → local execution — TRD 05 §6.6.\n *\n * Failure protocol, corrected from the TRD: it said the handler must never\n * throw, reasoning from Pub/Sub where a throw meant nack-and-redeliver. Here\n * DispatchLoop catches a throw and calls release(queueId), re-arming the row\n * with backoff. So the contract is: report to the bridge, THEN throw, so the\n * claim is released rather than stranded until the stale sweep.\n *\n * The agent runs HERE, on this machine, against this checkout. The bridge sent\n * a title and a repo name; it never sees the code.\n */\nexport function createBridgeDispatchHandler(\n  opts: DispatchHandlerOptions,\n): (message: TaskDispatchMessage) => Promise<void> {\n  const log = opts.onLog ?? (() => {});\n\n  return async function handle(message: TaskDispatchMessage): Promise<void> {\n    const { sessionId, linearIdentifier, title, repo } = message;\n    log(`${linearIdentifier} → ${repo}: ${title}`);\n\n    try {\n      const svc = service(opts);\n      ensurePoller(opts, svc);\n\n      const request = orchestrator.buildDispatchRequest({\n        sessionId,\n        repo,\n        title,\n        filePaths: [],\n        linearTicketId: linearIdentifier,\n        callbackUrl: opts.callbackUrl ?? '',\n      });\n\n      const settled = new Promise<Outcome>((resolve) => {\n        inFlight.set(sessionId, resolve);\n      });\n\n      const response = await svc.dispatch(request);\n      if (!response.accepted) {\n        inFlight.delete(sessionId);\n        throw new Error(response.error ?? 'Orchestrator rejected the dispatch');\n      }\n\n      await opts.client.reportSessionStatus(sessionId, {\n        status: 'dispatched',\n        progressPercent: 0,\n        message: `Dispatched to local orchestrator (${opts.orchestratorMode})`,\n      });\n\n      // The poller reports progress and resolves `settled` on a terminal state.\n      orchestrator\n        .getStatusPoller()\n        .trackSession(sessionId, response.orchestratorJobId ?? sessionId);\n\n      const outcome = await settled;\n      inFlight.delete(sessionId);\n\n      if (!outcome.ok) {\n        const e = new Error(outcome.error ?? 'Session failed');\n        // Mark it so the catch block does not re-report a state the bridge\n        // already has. Without this the failure is posted twice.\n        (e as Error & { alreadyReported?: boolean }).alreadyReported = outcome.reported;\n        throw e;\n      }\n      // The dispatch completed and was reported. Whether the AGENT succeeded is\n      // recorded in the session, not here — an agent that ran and failed is a\n      // finished dispatch, not one to retry.\n      log(`${linearIdentifier} reported`);\n    } catch (err) {\n      inFlight.delete(sessionId);\n      const reason = err instanceof Error ? err.message : String(err);\n      log(`${linearIdentifier} failed: ${reason}`);\n\n      // Best-effort. If the bridge is unreachable too, the throw below still\n      // makes DispatchLoop release the claim, and the server-side stale sweep\n      // is the final backstop.\n      if (!(err as Error & { alreadyReported?: boolean })?.alreadyReported) {\n        try {\n          await opts.client.reportSessionStatus(sessionId, {\n            status: 'error',\n            progressPercent: 0,\n            message: reason,\n          });\n        } catch {\n          /* nothing further we can do from here */\n        }\n      }\n\n      throw new Error(reason);\n    }\n  };\n}\n","import type { BridgeClient, MirroredPlan, TaskDispatchMessage } from '@devpilot.sh/bridge-client';\nimport type { ConductorWatcher } from './conductor-watcher';\n\n/**\n * Bridge dispatch → the CONDUCTOR, rather than a single agent session.\n *\n * `createBridgeDispatchHandler` turns a Linear ticket into exactly one Claude\n * Code session. That works, but it routes the paid path around the entire\n * product thesis: DESIGN.md §1 argues the bottleneck is planning throughput, and\n * a ticket that becomes one agent is never planned, never decomposed into waves,\n * and never parallelised. This handler is the other option — the ticket lands on\n * the conductor's desk and comes back as a wave plan.\n *\n * ## Why this talks HTTP to the local cockpit\n *\n * The conductor graph lives in the Next app, not in `@devpilot.sh/core`, because\n * the langchain dependency is deliberately kept out of the package every CLI\n * install pulls down (`src/lib/conductor.ts` says so explicitly). The CLI\n * therefore cannot import it. Rather than duplicate the graph or drag langchain\n * into core, this calls the cockpit's own API — the same endpoints the Review\n * Plan button uses. The boundary stays where it was drawn.\n *\n * ## Why it does not wait for the run to finish\n *\n * The conductor stops at a human review interrupt by default, which is the point\n * of it (DESIGN.md §6 calls that \"the highest-stakes interaction in DevPilot\").\n * A handler that awaited approval would hold its queue claim for however long a\n * person takes to look — hours, overnight — and a held claim is invisible work\n * that the stale sweep eventually reclaims and re-runs.\n *\n * So the unit of work here is \"get the ticket onto the conductor's desk and say\n * so\". Wave execution and completion reporting continue under the cockpit's own\n * machinery after this returns.\n */\n\nexport interface ConductorHandlerOptions {\n  client: BridgeClient;\n  /** Base URL of the local cockpit (`devpilot serve`). */\n  cockpitUrl: string;\n  /** Bound on each cockpit call. Plan generation is a model call and is slow. */\n  requestTimeoutMs?: number;\n  /**\n   * Watches handed-off runs and reports completion to the bridge, which is what\n   * triggers the Linear write-back. Optional: without it a planned ticket runs\n   * to completion and Linear is never told.\n   */\n  watcher?: ConductorWatcher;\n  onLog?: (line: string) => void;\n}\n\ninterface HorizonItem {\n  id: string;\n  title?: string;\n  linearTicketId?: string | null;\n}\n\ninterface ConductorState {\n  status?: string;\n  awaiting?: 'review' | 'wave' | null;\n  review?: {\n    score?: { parallelizationScore?: number };\n    /** Carried so the review message can say how big the plan is, not just that\n        one exists — \"2 waves, 9 tasks, 89% parallel\" is a decision; \"plan\n        ready\" is a notification. It is also what gets mirrored to the hosted\n        cockpit. */\n    plan?: PlanShape;\n  } | null;\n  errors?: string[];\n}\n\n/** The planner's output, as the cockpit returns it. */\ninterface PlanShape {\n  waves?: {\n    label?: string;\n    tasks?: {\n      taskCode?: string;\n      description?: string;\n      filePaths?: string[];\n      complexity?: string;\n      recommendedModel?: string;\n      canRunInParallel?: boolean;\n    }[];\n  }[];\n  dependencyEdges?: { from: string; to: string; type?: string }[];\n  criticalPath?: string[];\n}\n\n/**\n * The planner writes file paths as markdown code spans — `` `src/lib/x.ts` `` —\n * because its output is a markdown table. Storing the backticks would push them\n * into every hosted surface that renders a path.\n */\nfunction cleanPath(value: string): string {\n  return value.replace(/`/g, '').trim();\n}\n\n/**\n * Reshape a plan for the hosted cockpit.\n *\n * Structure only. Task descriptions and file paths cross the boundary; nothing\n * that could carry file contents does, and the hosted schema has no column for\n * it either.\n */\nfunction toMirroredPlan(\n  plan: PlanShape,\n  itemId: string,\n  parallelization?: number\n): MirroredPlan {\n  return {\n    cockpitItemId: itemId,\n    parallelization,\n    waves: (plan.waves ?? []).map((w) => ({\n      label: w.label,\n      tasks: (w.tasks ?? []).map((t) => ({\n        taskCode: t.taskCode ?? '',\n        description: t.description ?? '',\n        filePaths: (t.filePaths ?? []).map(cleanPath),\n        complexity: t.complexity,\n        recommendedModel: t.recommendedModel,\n        canRunInParallel: t.canRunInParallel,\n      })),\n    })),\n    dependencyEdges: plan.dependencyEdges ?? [],\n    criticalPath: plan.criticalPath ?? [],\n  };\n}\n\nconst DEFAULT_TIMEOUT_MS = 15 * 60_000;\n\nasync function call<T>(\n  url: string,\n  init: RequestInit,\n  timeoutMs: number,\n  fetchImpl: typeof fetch = fetch\n): Promise<T> {\n  const controller = new AbortController();\n  const timer = setTimeout(() => controller.abort(), timeoutMs);\n  try {\n    const res = await fetchImpl(url, {\n      ...init,\n      signal: controller.signal,\n      headers: { 'Content-Type': 'application/json', ...(init.headers ?? {}) },\n    });\n\n    const text = await res.text();\n    if (!res.ok) {\n      // Carry the body: the cockpit reports PLAN_AI_UNAVAILABLE and\n      // CONDUCTOR_FAILED with detail, and losing that turns a fixable\n      // configuration problem into \"the bridge failed\".\n      throw new Error(`${init.method ?? 'GET'} ${url} → ${res.status}: ${text.slice(0, 300)}`);\n    }\n    return (text ? JSON.parse(text) : {}) as T;\n  } finally {\n    clearTimeout(timer);\n  }\n}\n\n/**\n * Find the item this ticket already created, if any.\n *\n * The hosted side dedupes Linear's own redelivery, but a claim that is released\n * and re-taken (handler threw, process died mid-run, stale sweep) arrives here\n * again with the same ticket. Without this, each retry creates another board\n * item and starts another paid planning run.\n */\nasync function existingItem(\n  cockpitUrl: string,\n  linearTicketId: string,\n  timeoutMs: number\n): Promise<HorizonItem | null> {\n  const items = await call<HorizonItem[]>(\n    `${cockpitUrl}/api/items?linearTicketId=${encodeURIComponent(linearTicketId)}`,\n    { method: 'GET' },\n    timeoutMs\n  );\n  return Array.isArray(items) && items.length > 0 ? items[0] : null;\n}\n\n/** Describe where the run got to, for the status line a human reads in Linear. */\n/**\n * Deep links back into the cockpit.\n *\n * These messages become agent activities on the Linear issue, and they used to\n * name the board item as a bare id — \"On the board as ds21hni0xpviz…\" — which\n * is a fact you cannot act on. The whole point of the review gate is that a\n * human goes and looks; telling them where without letting them go there is the\n * wrong half of the sentence.\n *\n * Linear renders activity bodies as markdown, so these are real links. They\n * point at the cockpit, which is the machine the bridge runs on: the hosted\n * plane never sees a plan, so there is nothing to link to there.\n */\n/**\n * Where a link in a Linear activity should send someone.\n *\n * The first version pointed at the local cockpit — `127.0.0.1:3100/?item=…` —\n * which is a dead link for anyone not sitting at the machine the bridge runs\n * on. Most people on the hosted product never run that app at all, so the link\n * has to go to the hosted session page, which renders the mirrored plan with\n * the same cockpit components.\n */\nfunction sessionLink(hosted: string, sessionId: string): string {\n  return `${hosted}/sessions/${sessionId}`;\n}\n\n/**\n * The hosted base URL, or empty if this client cannot say.\n *\n * `hostedUrl` arrived in a later bridge-client, and calling it unconditionally\n * threw on an older one — propagating out, releasing the queue claim and\n * failing the ticket. That is the second time a *link* nearly cost a dispatch;\n * a message that cannot be decorated is still a message worth sending.\n */\nfunction hostedBase(client: BridgeClient): string {\n  return typeof client.hostedUrl === 'function' ? client.hostedUrl() : '';\n}\n\n/** A markdown link, or bare text when we have nowhere to point. */\nfunction linkOrText(hosted: string, sessionId: string, text: string): string {\n  return hosted ? `[${text}](${sessionLink(hosted, sessionId)})` : text;\n}\n\nfunction describe(state: ConductorState, hosted: string, sessionId: string): string {\n  if (state.awaiting === 'review') {\n    const score = state.review?.score?.parallelizationScore;\n    const waves = state.review?.plan?.waves?.length;\n    const tasks = state.review?.plan?.waves?.reduce(\n      (n, w) => n + (w.tasks?.length ?? 0),\n      0\n    );\n    // Assembled from the parts that exist. The shape is absent on a run whose\n    // plan we have not read back, and stitching in a placeholder produced\n    // \"Plan ready — Plan ready, 88% parallel\".\n    const parts = [\n      waves && tasks ? `${waves} wave${waves === 1 ? '' : 's'}, ${tasks} tasks` : null,\n      typeof score === 'number' ? `${Math.round(score * 100)}% parallel` : null,\n    ].filter(Boolean);\n    const shape = parts.length ? ` — ${parts.join(', ')}` : '';\n    return `Plan ready${shape}. ${linkOrText(hosted, sessionId, 'Review it in the cockpit')} to dispatch, or reply here with constraints to re-plan. Awaiting review.`;\n  }\n  if (state.awaiting === 'wave') {\n    return `Plan approved — dispatching waves. ${linkOrText(hosted, sessionId, 'Watch the waves')}.`;\n  }\n  if (state.status === 'complete') return 'All waves complete.';\n  if (state.status === 'failed') {\n    return `Conductor run failed: ${state.errors?.[state.errors.length - 1] ?? 'unknown error'}`;\n  }\n  return `Conductor run ${state.status ?? 'started'}.`;\n}\n\nexport function createConductorDispatchHandler(\n  opts: ConductorHandlerOptions\n): (message: TaskDispatchMessage) => Promise<void> {\n  const log = opts.onLog ?? (() => {});\n  const timeout = opts.requestTimeoutMs ?? DEFAULT_TIMEOUT_MS;\n  const base = opts.cockpitUrl.replace(/\\/$/, '');\n\n  return async function handle(message: TaskDispatchMessage): Promise<void> {\n    const { sessionId, linearIdentifier, title, repo, description } = message;\n    log(`${linearIdentifier} → conductor (${repo}): ${title}`);\n\n    try {\n      let item = await existingItem(base, linearIdentifier, timeout);\n\n      if (item) {\n        log(`${linearIdentifier} already on the board as ${item.id} — reusing`);\n\n        // Reusing the item is not enough. Posting to /conductor again starts a\n        // *fresh* planning run — observed live at 236s and a full model call for\n        // a ticket that was already sitting at its review gate. A redelivery\n        // must not re-spend that. Only an item with no live run gets one.\n        const current = await call<ConductorState>(\n          `${base}/api/items/${item.id}/conductor`,\n          { method: 'GET' },\n          timeout\n        ).catch(() => ({}) as ConductorState);\n\n        const live =\n          current.awaiting === 'review' ||\n          current.awaiting === 'wave' ||\n          current.status === 'planning' ||\n          current.status === 'executing';\n\n        if (live) {\n          const summary = describe(current, hostedBase(opts.client), sessionId);\n          log(`${linearIdentifier}: ${summary} (no new run started)`);\n          await opts.client.reportSessionStatus(sessionId, {\n            status: 'running',\n            progressPercent: current.awaiting === 'review' ? 40 : 60,\n            message: summary,\n          });\n          // Still hand it to the watcher: this claim is a *new* bridge session\n          // for a run that was already in flight, and its completion has to be\n          // reported against this session id or Linear never hears back. The\n          // state was just reported above, so seed the dedup signature or the\n          // watcher's first sweep repeats it on the ticket.\n          opts.watcher?.watch(\n            { sessionId, itemId: item.id, linearIdentifier },\n            current.awaiting === 'review' ? 'review' : undefined\n          );\n          return;\n        }\n      } else {\n        item = await call<HorizonItem>(\n          `${base}/api/items`,\n          {\n            method: 'POST',\n            body: JSON.stringify({\n              title,\n              repo,\n              // REFINING is where an item that is about to be planned belongs;\n              // DIRECTIONAL (the API default) would leave it parked as an idea.\n              zone: 'REFINING',\n              linearTicketId: linearIdentifier,\n              description,\n            }),\n          },\n          timeout\n        );\n        if (!item?.id) throw new Error('Cockpit did not return a created item id');\n        log(`${linearIdentifier} → item ${item.id}`);\n      }\n\n      await opts.client.reportSessionStatus(sessionId, {\n        status: 'running',\n        progressPercent: 5,\n        message: `Planning — ${linkOrText(hostedBase(opts.client), sessionId, 'open it in the cockpit')}.`,\n      });\n\n      // The planning call itself. Minutes, and it costs tokens.\n      const state = await call<ConductorState>(\n        `${base}/api/items/${item.id}/conductor`,\n        { method: 'POST', body: JSON.stringify({}) },\n        timeout\n      );\n\n      const summary = describe(state, hostedBase(opts.client), sessionId);\n      log(`${linearIdentifier}: ${summary}`);\n\n      /**\n       * Mirror the plan so it is visible on devpilot.sh, not only on this\n       * machine. Best-effort: the run is real work already underway, and losing\n       * it because a display copy failed to upload would be an absurd trade.\n       */\n      // The capability check is not defensive noise. `mirrorSessionPlan` arrived\n      // in a later bridge-client, and a client without it threw a TypeError\n      // here — which propagates, releases the queue claim, and fails the ticket.\n      // Losing real work because a *display copy* could not be uploaded is\n      // exactly the trade this must never make.\n      if (state.review?.plan?.waves?.length && typeof opts.client.mirrorSessionPlan === 'function') {\n        const mirrored = await opts.client.mirrorSessionPlan(\n          sessionId,\n          toMirroredPlan(\n            state.review.plan,\n            item.id,\n            state.review.score?.parallelizationScore\n          )\n        );\n        log(\n          `${linearIdentifier}: plan ${mirrored ? 'mirrored to the hosted cockpit' : 'not mirrored (hosted unreachable)'}`\n        );\n      }\n\n      if (state.status === 'failed') {\n        throw new Error(summary);\n      }\n\n      // `running`, not a new status: SESSION_STATUSES is mirrored by a CHECK\n      // constraint on dispatch_sessions.status, and its own comment requires a\n      // matching migration for any new value. An \"awaiting review\" state is not\n      // worth a schema change — the message carries it.\n      await opts.client.reportSessionStatus(sessionId, {\n        status: 'running',\n        progressPercent: state.awaiting === 'review' ? 40 : 60,\n        message: summary,\n      });\n\n      // The run continues under the cockpit after this returns, so completion\n      // is the watcher's job — it is what eventually calls\n      // reportSessionComplete and makes the hosted side write back to Linear.\n      // The review gate was just reported; seed it so the ticket does not carry\n      // the same \"Plan ready\" activity twice, seconds apart.\n      opts.watcher?.watch(\n        { sessionId, itemId: item.id, linearIdentifier },\n        state.awaiting === 'review' ? 'review' : undefined\n      );\n\n      // Deliberately returns here. See the header: waiting for a human to\n      // approve would strand the queue claim.\n    } catch (err) {\n      const reason = err instanceof Error ? err.message : String(err);\n      log(`${linearIdentifier} failed: ${reason}`);\n\n      try {\n        await opts.client.reportSessionStatus(sessionId, {\n          status: 'error',\n          progressPercent: 0,\n          message: reason,\n        });\n      } catch {\n        /* bridge unreachable too — the throw below still releases the claim */\n      }\n\n      // Throwing is what makes DispatchLoop release the claim for a retry.\n      throw new Error(reason);\n    }\n  };\n}\n\n\n/**\n * Hand an observed session's work to the planner — TRD 23 §3.5.\n *\n * The other half of \"take the wheel\". Resuming carries the conversation on;\n * this asks what the work should BE, which is the thing the cockpit can do and\n * `claude.ai/code` cannot: it has the fleet, the repo, and a planning agent.\n *\n * ## Why this plans from the session rather than resuming it\n *\n * A resumed turn produces an answer. A planned one produces a decomposition you\n * approve before anything runs, which is the interaction DESIGN.md §6 calls the\n * highest-stakes one in the product. Those are different requests and the UI\n * offers both; this is the second.\n *\n * The planner's input is everything the session already told us — its title,\n * what it opened with, the branch, the files it touched — plus whatever the\n * person typed on pickup. That last part matters most: \"finish the migration\n * and run the tests\" is a far better planning brief than any amount of derived\n * metadata.\n *\n * ## Why it does not wait for approval\n *\n * Same reason `createConductorDispatchHandler` does not: the conductor stops at\n * a human review interrupt, and holding a command open across that would hold\n * it for however long a person takes to look. The unit of work is \"get it onto\n * the conductor's desk and say so\".\n */\nexport interface PlanFromSessionOptions {\n  client: BridgeClient;\n  cockpitUrl: string;\n  sessionId: string;\n  repo: string;\n  title: string;\n  /** What the person typed on pickup, if anything. */\n  message?: string;\n  /** What the session opened with, as the observer recorded it. */\n  summary?: string;\n  branch?: string;\n  touchedPaths?: string[];\n  requestTimeoutMs?: number;\n  /** Injected in tests; the cockpit is a real HTTP call in production. */\n  fetchImpl?: typeof fetch;\n  onLog?: (line: string) => void;\n}\n\n/** The brief the planner reads. Evidence, then the instruction. */\nexport function buildSessionBrief(o: PlanFromSessionOptions): string {\n  const lines: string[] = [];\n\n  if (o.message?.trim()) {\n    // First, and labelled: everything below is context, this is the request.\n    lines.push(`## What to do\\n\\n${o.message.trim()}`, '');\n  }\n\n  lines.push('## Where this came from', '');\n  lines.push(\n    `An agent session already running in \\`${o.repo}\\`${o.branch ? ` on \\`${o.branch}\\`` : ''}, ` +\n      'picked up from the DevPilot cockpit.',\n    ''\n  );\n  if (o.summary?.trim()) lines.push(o.summary.trim(), '');\n\n  if (o.touchedPaths?.length) {\n    lines.push('## Files it had already touched', '');\n    for (const f of o.touchedPaths.slice(0, 30)) lines.push(`- \\`${f}\\``);\n    if (o.touchedPaths.length > 30) lines.push(`- …and ${o.touchedPaths.length - 30} more`);\n    lines.push('');\n  }\n\n  if (!o.message?.trim()) {\n    // Without an instruction the planner needs to be told what question to\n    // answer, or it will invent one.\n    lines.push(\n      '## What to do',\n      '',\n      'Work out what remains to finish this piece of work, and plan it.'\n    );\n  }\n\n  return lines.join('\\n');\n}\n\nexport async function planFromSession(o: PlanFromSessionOptions): Promise<string> {\n  const log = o.onLog ?? (() => {});\n  const timeout = o.requestTimeoutMs ?? DEFAULT_TIMEOUT_MS;\n  const base = o.cockpitUrl.replace(/\\/$/, '');\n\n  const item = await call<HorizonItem>(\n    `${base}/api/items`,\n    {\n      method: 'POST',\n      body: JSON.stringify({\n        title: o.title,\n        repo: o.repo,\n        zone: 'REFINING',\n        description: buildSessionBrief(o),\n      }),\n    },\n    timeout,\n    o.fetchImpl\n  );\n  if (!item?.id) throw new Error('Cockpit did not return a created item id');\n\n  /**\n   * Narration is best-effort, here and below.\n   *\n   * The planning call is minutes of real work that costs tokens. Failing it\n   * because a progress message could not be delivered would throw that away for\n   * a display update — the same trade `mirrorSessionPlan` already refuses to\n   * make.\n   */\n  await say(o, 5, 'Planning what remains — this takes a minute and costs tokens.');\n\n  const state = await call<ConductorState>(\n    `${base}/api/items/${item.id}/conductor`,\n    { method: 'POST', body: JSON.stringify({}) },\n    timeout,\n    o.fetchImpl\n  );\n\n  const summary = describe(state, hostedBase(o.client), o.sessionId);\n\n  // Best-effort, exactly as in the dispatch path: losing real work because a\n  // display copy failed to upload would be an absurd trade.\n  if (state.review?.plan?.waves?.length && typeof o.client.mirrorSessionPlan === 'function') {\n    const mirrored = await o.client.mirrorSessionPlan(\n      o.sessionId,\n      toMirroredPlan(state.review.plan, item.id, state.review.score?.parallelizationScore)\n    );\n    log(`plan ${mirrored ? 'mirrored to the hosted cockpit' : 'not mirrored (hosted unreachable)'}`);\n  }\n\n  if (state.status === 'failed') throw new Error(summary);\n\n  await say(o, state.awaiting === 'review' ? 40 : 60, summary);\n\n  return summary;\n}\n\n/** Report progress, and never let a failed report cost a real planning run. */\nasync function say(\n  o: PlanFromSessionOptions,\n  progressPercent: number,\n  message: string\n): Promise<void> {\n  try {\n    await o.client.reportSessionStatus(o.sessionId, {\n      status: 'running',\n      progressPercent,\n      message,\n    });\n  } catch (err) {\n    o.onLog?.(`could not report progress: ${err instanceof Error ? err.message : String(err)}`);\n  }\n}\n","import { readFileSync, writeFileSync, mkdirSync, unlinkSync, existsSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { BridgeClient } from '@devpilot.sh/bridge-client';\n\n/**\n * Closes the loop: a conductor run that finishes reports completion to the\n * bridge, which is what makes the hosted side write back to Linear.\n *\n * ## Why this exists separately from the handler\n *\n * The single-session path reports completion through the orchestrator's status\n * poller, which lives in the bridge process for exactly as long as the session\n * does. The planned path has no equivalent: the handler must RETURN at the\n * review gate (holding a queue claim while a human deliberates is invisible work\n * that the stale sweep re-runs), and the run then continues under the cockpit\n * for minutes or hours afterwards. So without something watching, a planned\n * ticket runs to completion and Linear is never told — the loop the user sees\n * simply stops.\n *\n * `POST /api/sessions/:id/complete` already calls `syncSessionCompletionToLinear`\n * hosted-side. This is the missing caller, not a new mechanism.\n *\n * ## Surviving a restart\n *\n * It used to hold runs in memory only, so a restarted bridge orphaned anything\n * in flight: the run kept going in the cockpit, and Linear was never told how it\n * ended. Observed on AVA-10 — the bridge was restarted to pick up a new CLI, the\n * session was never re-claimed, and the ticket was left showing an error for a\n * run that had not actually failed.\n *\n * The tracked set is now mirrored to disk. The bridge is the only party that\n * can do this: the hosted plane records the session but never learns the cockpit\n * item id, so it cannot reconstruct what to poll.\n *\n * Restored entries are treated as claims to verify, not as truth. A run whose\n * item the cockpit no longer knows about is dropped rather than polled forever,\n * because stale local state must not outlive the thing it describes.\n */\n\nexport interface ConductorState {\n  status?: string;\n  awaiting?: 'review' | 'wave' | null;\n  completedWaves?: number[];\n  errors?: string[];\n  review?: {\n    score?: { parallelizationScore?: number };\n    plan?: {\n      waves?: {\n        label?: string;\n        tasks?: {\n          taskCode?: string;\n          description?: string;\n          filePaths?: string[];\n          complexity?: string;\n          recommendedModel?: string;\n          canRunInParallel?: boolean;\n        }[];\n      }[];\n      dependencyEdges?: { from: string; to: string; type?: string }[];\n      criticalPath?: string[];\n    };\n  } | null;\n  currentWaveIndex?: number;\n  score?: { parallelizationScore?: number } | null;\n  lastDispatch?: { dispatched?: number; queued?: number } | null;\n  /** What the run has produced. See `outcomeFor` in the cockpit's conductor route. */\n  outcome?: {\n    tasksTotal?: number;\n    tasksComplete?: number;\n    tasksFailed?: number;\n    wavesTotal?: number;\n    filesChanged?: string[];\n    costUsd?: number;\n    failures?: { taskCode: string; error: string }[];\n  } | null;\n}\n\n/**\n * A one-line description of where a run currently is, plus a signature used to\n * suppress repeats. Returns null when there is nothing worth saying.\n */\nfunction progressReport(\n  state: ConductorState,\n  /** Cockpit base URL and item, so the message can be somewhere you can go. */\n  links: { hosted: string; sessionId: string }\n): { signature: string; message: string; percent: number } | null {\n  if (state.awaiting === 'review') {\n    const waves = state.review?.plan?.waves?.length ?? 0;\n    const tasks =\n      state.review?.plan?.waves?.reduce((n, w) => n + (w.tasks?.length ?? 0), 0) ?? 0;\n    const pct = Math.round((state.score?.parallelizationScore ?? 0) * 100);\n    return {\n      signature: 'review',\n      message:\n        `Plan ready — ${waves} wave${waves === 1 ? '' : 's'}, ${tasks} task${tasks === 1 ? '' : 's'}, ` +\n        `${pct}% parallel. ` +\n        (links.hosted\n          ? `[Review it in the cockpit](${links.hosted}/sessions/${links.sessionId}) to dispatch`\n          : 'Review it in the cockpit to dispatch') +\n        `, or reply here with constraints to re-plan. Awaiting review.`,\n      percent: 40,\n    };\n  }\n\n  if (state.status === 'executing') {\n    const wave = state.currentWaveIndex ?? 0;\n    const done = state.completedWaves?.length ?? 0;\n    const d = state.lastDispatch?.dispatched ?? 0;\n    const q = state.lastDispatch?.queued ?? 0;\n    const o = state.outcome ?? {};\n\n    /**\n     * Progress that survives being read weeks later.\n     *\n     * \"Dispatching wave 2\" says the machinery moved. Adding tasks done, files\n     * touched so far and spend says what it *cost* and what it *changed* — the\n     * two questions anyone actually brings to a ticket. The signature includes\n     * the task count so a wave that is quietly making progress still updates,\n     * rather than going silent between dispatch boundaries.\n     */\n    const complete = o.tasksComplete ?? 0;\n    const total = o.tasksTotal ?? 0;\n    const files = o.filesChanged?.length ?? 0;\n    const cost =\n      typeof o.costUsd === 'number' && o.costUsd > 0 ? `, $${o.costUsd.toFixed(2)} so far` : '';\n\n    const detail = total\n      ? ` — ${complete}/${total} tasks done, ${files} file${files === 1 ? '' : 's'} touched${cost}`\n      : d || q\n        ? ` — ${d} agent${d === 1 ? '' : 's'} running, ${q} queued`\n        : '';\n\n    return {\n      signature: `wave:${wave}:${done}:${complete}:${files}`,\n      message:\n        `Wave ${wave + 1}${total ? ` of ${o.wavesTotal ?? '?'}` : ''}${detail}` +\n        (links.hosted\n          ? `. [Watch the waves](${links.hosted}/sessions/${links.sessionId}).`\n          : '.'),\n      percent: Math.min(60 + done * 15, 95),\n    };\n  }\n\n  return null;\n}\n\nexport interface WatchedRun {\n  /** Bridge session id — what completion is reported against. */\n  sessionId: string;\n  /** Cockpit horizon item whose conductor run this is. */\n  itemId: string;\n  linearIdentifier: string;\n}\n\nexport interface ConductorWatcherOptions {\n  client: BridgeClient;\n  cockpitUrl: string;\n  /**\n   * File the tracked set is mirrored to. Omit to keep the old in-memory-only\n   * behaviour, which is what the tests use unless they are testing persistence.\n   */\n  statePath?: string;\n  /** How often to ask the cockpit for run state. Default 30s. */\n  pollIntervalMs?: number;\n  onLog?: (line: string) => void;\n  /** Called for runs still unfinished when the watcher stops. */\n  onLost?: (run: WatchedRun) => void;\n  /** Injectable for tests. */\n  fetchImpl?: typeof fetch;\n}\n\nconst TERMINAL = new Set(['complete', 'failed']);\n\n/** Files are listed, not just counted — the count is the least useful part. */\nconst MAX_LISTED_FILES = 12;\n\nfunction successSummary(state: ConductorState): string {\n  const o = state.outcome ?? {};\n  const waves = o.wavesTotal ?? state.completedWaves?.length ?? 0;\n\n  /**\n   * Fall back to the plan's own task count when no outcome is available.\n   *\n   * An older cockpit does not return `outcome`, and reading a missing value as\n   * zero made the summary say \"finished 0 tasks\" for a run that had just\n   * completed successfully — asserting nothing was done when the truth is that\n   * we do not know how much was.\n   */\n  const planned =\n    state.review?.plan?.waves?.reduce((n, w) => n + (w.tasks?.length ?? 0), 0) ?? 0;\n  const tasks = o.tasksComplete ?? planned;\n  const files = o.filesChanged ?? [];\n\n  const head =\n    `DevPilot finished ${tasks} task${tasks === 1 ? '' : 's'} across ` +\n    `${waves} wave${waves === 1 ? '' : 's'}` +\n    (typeof o.costUsd === 'number' && o.costUsd > 0 ? ` for $${o.costUsd.toFixed(2)}` : '') +\n    '.';\n\n  if (files.length === 0) {\n    // Only claim \"nothing changed\" when the cockpit actually told us. Absent\n    // data and an empty result are different facts, and reporting the first as\n    // the second would send a reviewer hunting a problem that may not exist.\n    return o.filesChanged\n      ? `${head}\\n\\n**No files were changed.** Worth checking whether the plan matched the intent.`\n      : head;\n  }\n\n  const shown = files.slice(0, MAX_LISTED_FILES).map((f) => `- \\`${f}\\``);\n  const more =\n    files.length > MAX_LISTED_FILES\n      ? `\\n- …and ${files.length - MAX_LISTED_FILES} more`\n      : '';\n\n  return `${head}\\n\\n**${files.length} file${files.length === 1 ? '' : 's'} changed**\\n${shown.join('\\n')}${more}`;\n}\n\nfunction failureSummary(state: ConductorState): string {\n  const o = state.outcome ?? {};\n  const failures = o.failures ?? [];\n  const last = state.errors?.[state.errors.length - 1];\n\n  const head =\n    `DevPilot run failed after ${o.tasksComplete ?? 0} of ${o.tasksTotal ?? 0} tasks` +\n    (typeof o.costUsd === 'number' && o.costUsd > 0 ? ` ($${o.costUsd.toFixed(2)} spent)` : '') +\n    '.';\n\n  // Name the tasks that failed. \"Run failed\" sends someone to a log; a task\n  // code and its error sends them to the problem.\n  if (failures.length > 0) {\n    const lines = failures.slice(0, 5).map((f) => `- **${f.taskCode}** — ${f.error}`);\n    return `${head}\\n\\n**Failed tasks**\\n${lines.join('\\n')}`;\n  }\n  return last ? `${head}\\n\\n${last}` : head;\n}\n\nexport class ConductorWatcher {\n  private readonly runs = new Map<string, WatchedRun>();\n  /** Last progress signature reported per session, so we do not repeat ourselves. */\n  private readonly reported = new Map<string, string>();\n  /** Sessions whose plan has already been mirrored, so we upload it once. */\n  private readonly mirroredPlans = new Set<string>();\n  private timer: NodeJS.Timeout | null = null;\n  private readonly base: string;\n  private readonly interval: number;\n  private readonly log: (line: string) => void;\n  private readonly doFetch: typeof fetch;\n\n  constructor(private readonly opts: ConductorWatcherOptions) {\n    this.base = opts.cockpitUrl.replace(/\\/$/, '');\n    this.interval = opts.pollIntervalMs ?? 30_000;\n    this.log = opts.onLog ?? (() => {});\n    this.doFetch = opts.fetchImpl ?? fetch;\n  }\n\n  /**\n   * Begin watching a run. Idempotent per bridge session.\n   *\n   * `alreadyReported` seeds the dedup signature with something the caller has\n   * just said. The dispatch handler announces the review gate itself, and\n   * without this the watcher's first sweep announced it again — AVA-13 carried\n   * two identical \"Plan ready — 5 waves, 17 tasks, 71% parallel\" activities\n   * seconds apart, which reads as the agent stuttering rather than working.\n   */\n  watch(run: WatchedRun, alreadyReported?: 'review'): void {\n    if (this.runs.has(run.sessionId)) return;\n    this.runs.set(run.sessionId, run);\n    if (alreadyReported) this.reported.set(run.sessionId, alreadyReported);\n    this.persist();\n    this.log(`watching ${run.linearIdentifier} (${this.runs.size} tracked)`);\n    this.start();\n  }\n\n  /**\n   * Re-adopt runs left behind by a previous process.\n   *\n   * Restored runs are claims, not facts — `check` verifies each against the\n   * cockpit on the next sweep and drops any whose item has gone. Returns how\n   * many were adopted so the caller can say so.\n   */\n  restore(): number {\n    const path = this.opts.statePath;\n    if (!path || !existsSync(path)) return 0;\n\n    let entries: WatchedRun[] = [];\n    try {\n      const parsed: unknown = JSON.parse(readFileSync(path, 'utf8'));\n      // A corrupt or hand-edited file must not stop the bridge from starting;\n      // losing the watch list degrades write-back, refusing to boot loses\n      // everything.\n      if (Array.isArray(parsed)) {\n        entries = parsed.filter(\n          (e): e is WatchedRun =>\n            Boolean(e) &&\n            typeof (e as WatchedRun).sessionId === 'string' &&\n            typeof (e as WatchedRun).itemId === 'string'\n        );\n      }\n    } catch {\n      return 0;\n    }\n\n    let adopted = 0;\n    for (const run of entries) {\n      if (this.runs.has(run.sessionId)) continue;\n      this.runs.set(run.sessionId, run);\n      adopted++;\n    }\n    if (adopted > 0) this.start();\n    return adopted;\n  }\n\n  /**\n   * Read this run's live telemetry from the cockpit and send it up.\n   *\n   * The cockpit knows what each agent is doing because the session runner\n   * streams it there; the hosted plane knew none of it, so a session page could\n   * only ever show a title and a percentage. Adopted sessions — Claude Code\n   * sessions discovered already running — have no plan at all, which is why\n   * twenty-eight of them displayed 0%: no denominator, and no activity either.\n   */\n  private async mirrorTelemetry(run: WatchedRun): Promise<void> {\n    if (typeof this.opts.client.reportTelemetry !== 'function') return;\n\n    try {\n      const res = await this.doFetch(`${this.base}/api/fleet/state`);\n      if (!res.ok) return;\n\n      const state = (await res.json()) as {\n        sessions?: {\n          id: string;\n          currentWorkstream?: string;\n          telemetry?: {\n            toolCalls?: number;\n            filesTouched?: string[];\n            lastAction?: { tool: string; path?: string };\n            commands?: string[];\n            costUsd?: number;\n            costIsEstimate?: boolean;\n            tokensIn?: number;\n            tokensOut?: number;\n            turns?: number;\n            elapsedMs?: number;\n            idleMs?: number;\n          } | null;\n        }[];\n      };\n\n      // The cockpit keys sessions by its own id; this run's tasks may span\n      // several. Aggregate them: the hosted view is per RUN, not per agent.\n      const sessions = state.sessions ?? [];\n      if (sessions.length === 0) return;\n\n      const files = new Set<string>();\n      let toolCalls = 0;\n      let costUsd = 0;\n      let estimated = false;\n      let elapsedMs = 0;\n      let idleMs = Number.MAX_SAFE_INTEGER;\n      let action: string | undefined;\n\n      for (const s of sessions) {\n        const t = s.telemetry;\n        if (!t) continue;\n        toolCalls += t.toolCalls ?? 0;\n        costUsd += t.costUsd ?? 0;\n        estimated = estimated || Boolean(t.costIsEstimate);\n        elapsedMs = Math.max(elapsedMs, t.elapsedMs ?? 0);\n        // The LEAST idle agent decides: one busy agent means the run is not\n        // stalled, however quiet the others are.\n        idleMs = Math.min(idleMs, t.idleMs ?? Number.MAX_SAFE_INTEGER);\n        for (const f of t.filesTouched ?? []) files.add(f);\n        if (!action && t.lastAction) {\n          const file = t.lastAction.path?.split('/').slice(-1)[0];\n          action =\n            t.lastAction.tool === 'Bash'\n              ? (t.commands?.at(-1) ?? 'shell').split(/\\s+/).slice(0, 3).join(' ')\n              : `${t.lastAction.tool.toLowerCase()}${file ? ` ${file}` : ''}`;\n        }\n      }\n\n      if (toolCalls === 0 && files.size === 0) return;\n\n      await this.opts.client.reportTelemetry(run.sessionId, {\n        toolCalls,\n        filesTouched: [...files],\n        currentAction: action,\n        costUsd: costUsd > 0 ? costUsd : undefined,\n        costEstimated: estimated,\n        elapsedMs: elapsedMs || undefined,\n        idleMs: idleMs === Number.MAX_SAFE_INTEGER ? undefined : idleMs,\n      });\n    } catch {\n      // Never let an instrument frame disturb the run it describes.\n    }\n  }\n\n  /** Mirror the tracked set to disk. Never throws — this is bookkeeping. */\n  private persist(): void {\n    const path = this.opts.statePath;\n    if (!path) return;\n    try {\n      if (this.runs.size === 0) {\n        if (existsSync(path)) unlinkSync(path);\n        return;\n      }\n      mkdirSync(dirname(path), { recursive: true });\n      writeFileSync(path, JSON.stringify([...this.runs.values()], null, 2), 'utf8');\n    } catch {\n      // A bridge that cannot write its watch list still works for this process.\n    }\n  }\n\n  private start(): void {\n    if (this.timer) return;\n    this.timer = setInterval(() => void this.sweep(), this.interval);\n    // Never hold the process open on this timer alone.\n    this.timer.unref?.();\n  }\n\n  stop(): void {\n    if (this.timer) {\n      clearInterval(this.timer);\n      this.timer = null;\n    }\n    for (const run of this.runs.values()) this.opts.onLost?.(run);\n    this.runs.clear();\n  }\n\n  /** Exposed for tests and for an immediate check after handing off a run. */\n  async sweep(): Promise<void> {\n    for (const run of [...this.runs.values()]) {\n      try {\n        await this.check(run);\n      } catch (err) {\n        // A cockpit that is down or restarting must not kill the watcher; the\n        // next sweep retries. Losing the loop is worse than a noisy log.\n        this.log(\n          `${run.linearIdentifier}: state check failed (${\n            err instanceof Error ? err.message : String(err)\n          })`\n        );\n      }\n    }\n    if (this.runs.size === 0 && this.timer) {\n      clearInterval(this.timer);\n      this.timer = null;\n    }\n  }\n\n  private async check(run: WatchedRun): Promise<void> {\n    const res = await this.doFetch(`${this.base}/api/items/${run.itemId}/conductor`);\n\n    if (res.status === 404) {\n      /**\n       * The cockpit has no run for this item. For a restored entry that means\n       * the item is gone — the database was reset, or the run was cleaned up\n       * while this bridge was down. Polling it forever would keep a dead\n       * session on the books and re-log the same failure every sweep.\n       *\n       * Drop it and say so. Reporting completion would be worse: we do not\n       * know how it ended, and inventing an outcome for a Linear ticket is\n       * exactly the kind of confident wrongness this write-back must not do.\n       */\n      this.runs.delete(run.sessionId);\n      this.reported.delete(run.sessionId);\n      this.persist();\n      this.log(\n        `${run.linearIdentifier}: no conductor run on the cockpit — dropped (was it reset?)`\n      );\n      return;\n    }\n\n    if (!res.ok) throw new Error(`conductor state → ${res.status}`);\n\n    const state = (await res.json()) as ConductorState;\n\n    if (!state.status || !TERMINAL.has(state.status)) {\n      /**\n       * Report progress while the run is still going.\n       *\n       * This used to return here, saying nothing until the run reached a\n       * terminal state. A conductor run takes minutes to hours, so the Linear\n       * agent session sat silent from the moment it was claimed — and Linear\n       * marks an agent that stops emitting activities as unresponsive.\n       * Observed on AVA-10: one \"picking this up\" thought, then thirty minutes\n       * of nothing, then \"Stopped responding\" on the ticket while the planner\n       * was working normally the whole time.\n       *\n       * The review gate matters most. The run is blocked on a human, and the\n       * person who delegated the issue is reading the issue, not watching a\n       * cockpit they may not know exists. Saying so there turns a dead-looking\n       * session into a question they can answer.\n       */\n      /**\n       * Mirror the plan from here as well as from the dispatch handler.\n       *\n       * The handler mirrors once, at claim time. If that call fails — the\n       * hosted plane is unreachable, the cockpit restarts mid-plan, the bridge\n       * is upgraded — nothing ever tried again, and the hosted cockpit stayed\n       * empty for a run that has a perfectly good plan. Observed on AVA-12: the\n       * cockpit was restarted during planning, the handler's call died with it,\n       * and the plan existed everywhere except the place a hosted customer\n       * would look.\n       *\n       * The watcher is already polling this exact state, so it is the natural\n       * place to catch up. Once per session; best-effort, like the handler's.\n       */\n      if (\n        state.review?.plan?.waves?.length &&\n        !this.mirroredPlans.has(run.sessionId) &&\n        typeof this.opts.client.mirrorSessionPlan === 'function'\n      ) {\n        const ok = await this.opts.client.mirrorSessionPlan(run.sessionId, {\n          cockpitItemId: run.itemId,\n          parallelization: state.review.score?.parallelizationScore,\n          waves: state.review.plan.waves.map((w) => ({\n            label: w.label,\n            tasks: (w.tasks ?? []).map((t) => ({\n              taskCode: t.taskCode ?? '',\n              description: t.description ?? '',\n              // The planner writes paths as markdown code spans.\n              filePaths: (t.filePaths ?? []).map((f) => f.replace(/`/g, '').trim()),\n              complexity: t.complexity,\n              recommendedModel: t.recommendedModel,\n              canRunInParallel: t.canRunInParallel,\n            })),\n          })),\n          dependencyEdges: state.review.plan.dependencyEdges ?? [],\n          criticalPath: state.review.plan.criticalPath ?? [],\n        });\n        if (ok) {\n          this.mirroredPlans.add(run.sessionId);\n          this.log(`${run.linearIdentifier}: plan mirrored to the hosted cockpit`);\n        }\n      }\n\n      /**\n       * Mirror the instruments, so the hosted cockpit shows work and not just\n       * a title and a zero.\n       *\n       * Derived facts only — the assistant's prose and raw tool inputs are not\n       * read here and have no column on the other side. Best-effort: an\n       * instrument frame is never worth failing a run over.\n       */\n      void this.mirrorTelemetry(run);\n\n      const progress = progressReport(state, {\n        // Same guard as the handler: an older client has no `hostedUrl`, and a\n        // missing link must never cost the progress report itself.\n        hosted:\n          typeof this.opts.client.hostedUrl === 'function' ? this.opts.client.hostedUrl() : '',\n        sessionId: run.sessionId,\n      });\n      if (progress && this.reported.get(run.sessionId) !== progress.signature) {\n        this.reported.set(run.sessionId, progress.signature);\n        try {\n          await this.opts.client.reportSessionStatus(run.sessionId, {\n            status: 'running',\n            progressPercent: progress.percent,\n            message: progress.message,\n          });\n          this.log(`${run.linearIdentifier}: ${progress.message}`);\n        } catch (err) {\n          const reason = err instanceof Error ? err.message : String(err);\n\n          /**\n           * A missing session is permanent, not transient.\n           *\n           * Every `bridge connect` registers a NEW orchestrator, so a restart\n           * leaves restored runs pointing at sessions the hosted plane now\n           * considers owned by the previous identity — `requireOwnedSession`\n           * correctly answers 404. Retrying that on every sweep never succeeds\n           * and logs the same failure forever; observed on AVA-11 after several\n           * restarts, once per poll indefinitely.\n           *\n           * Drop it, and say why. We deliberately do NOT report completion: we\n           * do not know how the run ended, and inventing an outcome for a\n           * Linear ticket is worse than admitting we lost track of it.\n           */\n          if (/not_found|not found/i.test(reason)) {\n            this.runs.delete(run.sessionId);\n            this.reported.delete(run.sessionId);\n            this.persist();\n            this.log(\n              `${run.linearIdentifier}: session no longer reachable from this bridge — stopped watching`\n            );\n            return;\n          }\n\n          // Anything else may be transient. Never let a failed narration drop a\n          // run whose completion is still owed.\n          this.reported.delete(run.sessionId);\n          this.log(`${run.linearIdentifier}: progress report failed (${reason})`);\n        }\n      }\n      return;\n    }\n\n    const success = state.status === 'complete';\n    const waves = state.completedWaves?.length ?? 0;\n    const tasks =\n      state.review?.plan?.waves?.reduce((n, w) => n + (w.tasks?.length ?? 0), 0) ?? 0;\n\n    /**\n     * A summary someone can act on.\n     *\n     * This used to say \"DevPilot completed 2 waves\" and nothing else. Linear is\n     * the source of record, and the record was that something happened — no\n     * files, no cost, no way to tell a run that wrote nine files from one that\n     * wrote none. Everything below already existed; it was simply never joined\n     * and never sent.\n     */\n    const summary = success ? successSummary(state) : failureSummary(state);\n\n    // Remove BEFORE reporting: if the report throws, the run is not re-reported\n    // on the next sweep. Linear comments are not idempotent, and a flapping\n    // cockpit would otherwise post the same comment repeatedly.\n    this.runs.delete(run.sessionId);\n    this.reported.delete(run.sessionId);\n    this.mirroredPlans.delete(run.sessionId);\n    this.persist();\n\n    await this.opts.client.reportSessionComplete(run.sessionId, {\n      success,\n      summary,\n      ...(success ? {} : { errorMessage: summary }),\n    });\n\n    this.log(`${run.linearIdentifier}: reported ${success ? 'complete' : 'failed'} to the bridge`);\n  }\n\n  /**\n   * The cockpit item a session's run belongs to, if this bridge is tracking it.\n   *\n   * The command applier needs this: a decision arrives addressed to a bridge\n   * session, and the conductor is addressed by horizon item.\n   */\n  itemFor(sessionId: string): string | undefined {\n    return this.runs.get(sessionId)?.itemId;\n  }\n\n  /** Test/introspection helper. */\n  get tracked(): number {\n    return this.runs.size;\n  }\n}\n","import type { BridgeClient, SessionCommandMessage } from '@devpilot.sh/bridge-client';\n\n/**\n * Applies decisions taken in the hosted cockpit to the local conductor.\n *\n * Everything else in the bridge runs one way: work comes down, status goes up.\n * This is the return path for the one thing a person has to decide — whether a\n * plan is good enough to spend money on. Without it, a hosted customer could\n * watch a run reach its review gate and had no way to answer it, which made the\n * mirrored plan a picture rather than a cockpit.\n *\n * ## Why the bridge is still the only thing that acts\n *\n * The hosted plane queues a row; this polls for it and applies it locally. No\n * inbound connection to anyone's laptop, and the machine that holds the\n * credentials remains the only thing that can start work. That property is the\n * whole reason DevPilot is safe to install, and a command channel that reached\n * the other way would quietly give it up.\n *\n * ## Acknowledgement is deliberate about ordering\n *\n * A command is acknowledged only AFTER the conductor has accepted it. If the\n * cockpit is unreachable the row stays pending and the next poll tries again —\n * a decision a human made must not be silently dropped because a laptop was\n * asleep. The cost is that a command applied but not acknowledged is retried,\n * so `approve` has to be safe to repeat: the conductor answers a resume on a\n * graph with no pending interrupt by continuing from where it is, not by\n * re-running the wave.\n */\n\nexport interface CommandApplierOptions {\n  client: BridgeClient;\n  /** Local cockpit base URL. */\n  cockpitUrl: string;\n  /** Maps a bridge session to the cockpit item its conductor run belongs to. */\n  resolveItemId: (sessionId: string) => string | undefined;\n  onLog?: (line: string) => void;\n  fetchImpl?: typeof fetch;\n  requestTimeoutMs?: number;\n}\n\nexport class CommandApplier {\n  private readonly base: string;\n  private readonly log: (line: string) => void;\n  private readonly doFetch: typeof fetch;\n  private readonly timeout: number;\n\n  constructor(private readonly opts: CommandApplierOptions) {\n    this.base = opts.cockpitUrl.replace(/\\/$/, '');\n    this.log = opts.onLog ?? (() => {});\n    this.doFetch = opts.fetchImpl ?? fetch;\n    this.timeout = opts.requestTimeoutMs ?? 15 * 60_000;\n  }\n\n  /** One pass: fetch pending commands and apply them in order. */\n  async sweep(): Promise<void> {\n    let commands: SessionCommandMessage[];\n    try {\n      commands = await this.opts.client.pollSessionCommands();\n    } catch (err) {\n      // A hosted plane that is briefly unreachable is not an error worth\n      // stopping the bridge for; the next sweep will pick these up.\n      this.log(`command poll failed (${err instanceof Error ? err.message : String(err)})`);\n      return;\n    }\n\n    for (const command of commands) {\n      await this.applyOne(command);\n    }\n  }\n\n  /**\n   * Apply one command that has already been polled.\n   *\n   * Public since TRD 23: the bridge now polls ONCE and routes, because\n   * `resume` is applied by a different applier and two pollers would race to\n   * claim the same rows.\n   */\n  async applyOne(command: SessionCommandMessage): Promise<void> {\n    const itemId = this.opts.resolveItemId(command.sessionId);\n\n    if (!itemId) {\n      /**\n       * The bridge does not know which cockpit item this session is. That\n       * happens when the run was claimed by a previous process and this one has\n       * not restored it, and it is permanent from here — there is nothing to\n       * apply the decision to.\n       *\n       * Failing it is kinder than leaving it pending forever: the hosted\n       * cockpit can show that the decision did not land, instead of a spinner\n       * that never resolves.\n       */\n      await this.opts.client.acknowledgeCommands(\n        [command.id],\n        'failed',\n        'This bridge is not tracking that run, so the decision could not be applied.'\n      );\n      this.log(`command ${command.command} for an untracked session — reported as failed`);\n      return;\n    }\n\n    const decision =\n      command.command === 'approve'\n        ? { action: 'approve' as const }\n        : command.command === 'replan'\n          ? { action: 'refine' as const, constraints: command.payload?.constraints ?? [] }\n          : { action: 'abort' as const, reason: 'Aborted from the hosted cockpit' };\n\n    const controller = new AbortController();\n    const timer = setTimeout(() => controller.abort(), this.timeout);\n\n    try {\n      const res = await this.doFetch(`${this.base}/api/items/${itemId}/conductor`, {\n        method: 'POST',\n        signal: controller.signal,\n        headers: { 'content-type': 'application/json' },\n        body: JSON.stringify({ decision }),\n      });\n\n      if (!res.ok) {\n        const detail = await res.text().catch(() => '');\n        throw new Error(`conductor → ${res.status} ${detail.slice(0, 200)}`);\n      }\n\n      // Only now. See the header: acknowledging first would let a decision\n      // vanish if the conductor rejected it.\n      await this.opts.client.acknowledgeCommands([command.id], 'applied');\n      this.log(`applied ${command.command} from the hosted cockpit`);\n    } catch (err) {\n      const reason = err instanceof Error ? err.message : String(err);\n\n      /**\n       * Distinguish \"the cockpit is not running\" from \"the conductor refused\".\n       * The first is transient and the command should be retried on the next\n       * sweep; the second will fail identically forever, and leaving it pending\n       * would retry a paid planning call every 30 seconds.\n       */\n      const transient = /fetch failed|ECONNREFUSED|abort|timeout/i.test(reason);\n      if (transient) {\n        this.log(`command ${command.command} deferred — cockpit unreachable (${reason})`);\n        return;\n      }\n\n      await this.opts.client.acknowledgeCommands([command.id], 'failed', reason);\n      this.log(`command ${command.command} failed: ${reason}`);\n    } finally {\n      clearTimeout(timer);\n    }\n  }\n}\n","import { statSync, existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { BridgeClient } from '@devpilot.sh/bridge-client';\nimport { tailTranscript, initialTailState, type TailState } from './transcript-tail.js';\n\n/**\n * Keeping an adopted session's status honest — TRD 21 §6.6.\n *\n * The counterpart to `ConductorWatcher`, and deliberately the same shape: a\n * disk-backed set of things to check, restored on start, where a restored entry\n * is a CLAIM TO VERIFY rather than truth. That posture exists because the\n * alternative was observed in production — a restarted bridge orphaned every\n * in-flight run and Linear was never told how any of it ended.\n *\n * ## What this watcher can and cannot know\n *\n * It has no session handle. It cannot ask the agent anything. All it observes is\n * a file's mtime, so it reports exactly two things:\n *\n *   - the transcript grew → the session is still going\n *   - the transcript has been still for a while → the session stopped\n *\n * \"Stopped\" is not \"finished\", and §3.4 turns that distinction into behaviour:\n * the completion this posts carries `moveToDone: false` at the hosted end, so\n * a settling session comments on the ticket and leaves its state alone.\n *\n * ## Why progress is always zero\n *\n * A dispatched session has a plan, so a percentage has a denominator. An adopted\n * session has none. Reporting a made-up fraction would put a number on the board\n * that looks measured and is not, so elapsed time goes in the message and\n * `progressPercent` stays 0.\n */\n\nexport interface AdoptionLedgerEntry {\n  adoptionKey: string;\n  /** `dispatch_sessions.id` on the hosted plane. */\n  sessionId: string;\n  identifier: string;\n  transcriptPath: string;\n  repo: string;\n  startedAt: string;\n  lastMtimeMs: number;\n  lastReportedAt: string;\n  settled: boolean;\n  /** Working directory the session runs in, for repo-relative paths. */\n  cwd?: string | null;\n  /**\n   * Incremental read position into the transcript. Persisted so a restarted\n   * bridge resumes the stream where it left off instead of re-sending\n   * everything — the hosted side would dedupe by seq, but re-deriving a\n   * 10-hour transcript on every restart is work for nothing.\n   */\n  tail?: TailState;\n}\n\ninterface Ledger {\n  version: 1;\n  entries: Record<string, AdoptionLedgerEntry>;\n}\n\nexport interface AdoptionWatcherConfig {\n  client: BridgeClient;\n  statePath: string;\n  /** How long a transcript must be still before the session is called stopped. */\n  settleAfterMs?: number;\n  tickMs?: number;\n  onLog?: (line: string) => void;\n}\n\nconst DEFAULT_SETTLE_MS = 30 * 60 * 1000;\nconst DEFAULT_TICK_MS = 60_000;\n\nexport class AdoptionWatcher {\n  private entries = new Map<string, AdoptionLedgerEntry>();\n  private timer: NodeJS.Timeout | null = null;\n  private readonly settleAfterMs: number;\n  private readonly tickMs: number;\n\n  constructor(private readonly config: AdoptionWatcherConfig) {\n    this.settleAfterMs = config.settleAfterMs ?? DEFAULT_SETTLE_MS;\n    this.tickMs = config.tickMs ?? DEFAULT_TICK_MS;\n  }\n\n  /** Begin watching a freshly adopted session. */\n  track(entry: AdoptionLedgerEntry): void {\n    this.entries.set(entry.adoptionKey, entry);\n    this.persist();\n    this.start();\n  }\n\n  /**\n   * Re-adopt entries left behind by a previous process.\n   *\n   * Entries whose transcript no longer exists are dropped rather than polled\n   * forever: stale local state must not outlive the thing it describes.\n   */\n  restore(): number {\n    try {\n      if (!existsSync(this.config.statePath)) return 0;\n      const parsed = JSON.parse(readFileSync(this.config.statePath, 'utf8')) as Ledger;\n      if (parsed?.version !== 1 || !parsed.entries) return 0;\n\n      let restored = 0;\n      for (const entry of Object.values(parsed.entries)) {\n        if (entry.settled) continue;\n        if (!existsSync(entry.transcriptPath)) continue;\n        this.entries.set(entry.adoptionKey, entry);\n        restored++;\n      }\n      if (restored > 0) this.start();\n      return restored;\n    } catch {\n      // A corrupt ledger must not stop a bridge from connecting.\n      return 0;\n    }\n  }\n\n  size(): number {\n    return [...this.entries.values()].filter((e) => !e.settled).length;\n  }\n\n  start(): void {\n    if (this.timer) return;\n    this.timer = setInterval(() => void this.sweep(), this.tickMs);\n    this.timer.unref?.();\n  }\n\n  stop(): void {\n    if (this.timer) clearInterval(this.timer);\n    this.timer = null;\n    this.persist();\n  }\n\n  /** One pass. Never throws: a reporting failure is retried on the next tick. */\n  async sweep(now = Date.now()): Promise<void> {\n    for (const entry of [...this.entries.values()]) {\n      if (entry.settled) continue;\n\n      let mtimeMs: number;\n      try {\n        mtimeMs = statSync(entry.transcriptPath).mtimeMs;\n      } catch {\n        // The transcript is gone — the session's history was deleted. There is\n        // nothing left to observe and nothing truthful left to say about it.\n        this.entries.delete(entry.adoptionKey);\n        this.persist();\n        continue;\n      }\n\n      /**\n       * First sight of a session streams its backlog even without growth.\n       * The tailer used to run only when the transcript grew, so a session\n       * that went quiet before the bridge started never streamed at all —\n       * its watch view sat empty while 1,800 events sat on disk.\n       */\n      const neverDerived = entry.tail === undefined;\n      if (mtimeMs > entry.lastMtimeMs || neverDerived) {\n        const grew = mtimeMs > entry.lastMtimeMs;\n        entry.lastMtimeMs = mtimeMs;\n        entry.lastReportedAt = new Date(now).toISOString();\n\n        /**\n         * The transcript grew — derive what was appended and stream it up.\n         * This is the sender that never existed: telemetry and the live watch\n         * both read from what lands here. Failure is tolerated per tick; the\n         * byte offset only advances after derivation, so nothing is skipped.\n         */\n        // Capability-guarded like the conductor watcher: an older installed\n        // bridge-client simply has no streaming, and that degrades to the\n        // status line below rather than a crash.\n        const canStream = typeof this.config.client.streamEvents === 'function';\n        entry.tail ??= initialTailState();\n        const derived = canStream\n          ? tailTranscript(entry.transcriptPath, entry.tail, entry.cwd)\n          : [];\n        this.persist();\n\n        if (derived.length > 0) {\n          const sent = await this.config.client.streamEvents(entry.sessionId, derived);\n          if (!sent) {\n            this.config.onLog?.(`stream for ${entry.identifier} did not land; will catch up next tick`);\n          }\n\n          const latest = derived[derived.length - 1];\n          const files = new Set<string>();\n          for (const e of derived) if (e.path) files.add(e.path);\n          if (typeof this.config.client.reportTelemetry === 'function')\n          await this.config.client.reportTelemetry(entry.sessionId, {\n            toolCalls: entry.tail.seq,\n            filesTouched: [...files].slice(0, 500),\n            currentAction: latest.path\n              ? `${latest.tool} · ${latest.path.split('/').slice(-2).join('/')}`\n              : latest.tool,\n            elapsedMs: Math.round(entry.tail.activeMs),\n            // mtimeMs is fractional on macOS; the schema's int() refuses a\n            // float and the client swallows the 400 — a silently empty table.\n            idleMs: Math.round(Math.max(0, now - mtimeMs)),\n          });\n        }\n\n        if (grew) {\n        try {\n          await this.config.client.reportSessionStatus(entry.sessionId, {\n            status: 'running',\n            progressPercent: 0,\n            message: `Still running on this machine — ${elapsed(entry.startedAt, now)} so far`,\n          });\n        } catch (err) {\n          this.config.onLog?.(\n            `could not report ${entry.identifier}: ${err instanceof Error ? err.message : err}`,\n          );\n        }\n        continue;\n        }\n      }\n\n      if (now - mtimeMs < this.settleAfterMs) continue;\n\n      try {\n        await this.config.client.reportSessionComplete(entry.sessionId, {\n          success: true,\n          summary:\n            `The session stopped writing after ${elapsed(entry.startedAt, mtimeMs)}. ` +\n            'DevPilot observed it rather than running it, so whether the work is finished ' +\n            'is not something it can say.',\n        });\n        entry.settled = true;\n        this.persist();\n        this.config.onLog?.(`${entry.identifier} went quiet — reported, ticket left as it was`);\n      } catch (err) {\n        this.config.onLog?.(\n          `could not settle ${entry.identifier}: ${err instanceof Error ? err.message : err}`,\n        );\n      }\n    }\n\n    if (this.size() === 0) this.stop();\n  }\n\n  private persist(): void {\n    try {\n      mkdirSync(dirname(this.config.statePath), { recursive: true });\n      const ledger: Ledger = { version: 1, entries: Object.fromEntries(this.entries) };\n      writeFileSync(this.config.statePath, JSON.stringify(ledger, null, 2), 'utf8');\n    } catch {\n      // Unwritable state means a restart loses track, which the hosted stale\n      // view already tolerates. It must never break a live run.\n    }\n  }\n}\n\nfunction elapsed(startedAt: string, endMs: number): string {\n  const ms = endMs - Date.parse(startedAt);\n  if (!Number.isFinite(ms) || ms < 0) return 'an unknown time';\n  const minutes = Math.round(ms / 60_000);\n  if (minutes < 1) return 'under a minute';\n  if (minutes < 60) return `${minutes} minute${minutes === 1 ? '' : 's'}`;\n  const hours = Math.floor(minutes / 60);\n  const rest = minutes % 60;\n  return rest === 0 ? `${hours} hour${hours === 1 ? '' : 's'}` : `${hours}h ${rest}m`;\n}\n","import { openSync, readSync, fstatSync, closeSync } from 'node:fs';\n\n/**\n * Derive stream events from a Claude Code transcript, incrementally.\n *\n * The transcript is the machine's full record and never leaves the machine.\n * What leaves is what this extracts: tool name, repo-relative path, and a time\n * offset — the derived-facts line the telemetry schema draws, applied at event\n * granularity. Tool INPUTS are deliberately never read beyond the two path\n * fields, because a Write tool's input IS the file contents.\n *\n * Incremental by byte offset: the adoption watcher already ticks on transcript\n * growth, so each tick reads only the appended region. A partial trailing line\n * (the writer mid-append) is carried to the next tick rather than parsed.\n *\n * Idle collapse mirrors the hosted view's contract: `t` is active seconds, not\n * wall clock. A session left overnight resumes seconds after it paused, so the\n * strip reads as work instead of as one long silence.\n */\n\nconst IDLE_MS = 5 * 60 * 1000;\n/** A long pause is shown as one beat, not erased entirely. */\nconst PAUSE_BEAT_MS = 30 * 1000;\n\nexport interface DerivedEvent {\n  seq: number;\n  /** Active seconds since the first observed event. */\n  t: number;\n  tool: string;\n  path: string | null;\n}\n\nexport interface TailState {\n  byteOffset: number;\n  /** Carried partial line from the previous read. */\n  remainder: string;\n  seq: number;\n  lastEventMs: number | null;\n  activeMs: number;\n}\n\nexport function initialTailState(): TailState {\n  return { byteOffset: 0, remainder: '', seq: 0, lastEventMs: null, activeMs: 0 };\n}\n\n/** Recover a path from a Bash command without keeping the command. */\nfunction pathFromCommand(command: unknown): string | null {\n  if (typeof command !== 'string') return null;\n  const m = command.match(/[\\w./-]+\\.(?:ts|tsx|js|jsx|py|sql|md|json|css|sh|mjs|go|rs)\\b/);\n  return m ? m[0] : null;\n}\n\nexport function tailTranscript(\n  transcriptPath: string,\n  state: TailState,\n  cwd?: string | null,\n): DerivedEvent[] {\n  let fd: number;\n  try {\n    fd = openSync(transcriptPath, 'r');\n  } catch {\n    return [];\n  }\n\n  let chunk: string;\n  try {\n    const size = fstatSync(fd).size;\n    // Truncated or rotated: start over rather than reading garbage offsets.\n    if (size < state.byteOffset) {\n      state.byteOffset = 0;\n      state.remainder = '';\n    }\n    if (size === state.byteOffset) {\n      return []; // the finally below owns the close\n    }\n    const buf = Buffer.alloc(size - state.byteOffset);\n    readSync(fd, buf, 0, buf.length, state.byteOffset);\n    state.byteOffset = size;\n    chunk = state.remainder + buf.toString('utf8');\n  } finally {\n    closeSync(fd);\n  }\n\n  const lines = chunk.split('\\n');\n  // The last element is either '' (chunk ended on a newline) or a partial\n  // line still being written; both belong to the next tick.\n  state.remainder = lines.pop() ?? '';\n\n  const events: DerivedEvent[] = [];\n  for (const line of lines) {\n    if (!line) continue;\n    let o: {\n      type?: string;\n      timestamp?: string;\n      message?: { content?: Array<{ type?: string; name?: string; input?: Record<string, unknown> }> };\n    };\n    try {\n      o = JSON.parse(line);\n    } catch {\n      continue; // a torn line mid-file; nothing recoverable\n    }\n    if (o.type !== 'assistant') continue;\n    const ms = o.timestamp ? Date.parse(o.timestamp) : NaN;\n    if (!Number.isFinite(ms)) continue;\n\n    for (const block of o.message?.content ?? []) {\n      if (block.type !== 'tool_use' || !block.name) continue;\n      const input = block.input ?? {};\n\n      let path =\n        (typeof input.file_path === 'string' && input.file_path) ||\n        (typeof input.path === 'string' && input.path) ||\n        (typeof input.notebook_path === 'string' && input.notebook_path) ||\n        null;\n      if (!path && block.name === 'Bash') path = pathFromCommand(input.command);\n\n      // Repo-relative or nothing. An absolute path outside the repo is\n      // someone else's filesystem detail, not this session's work.\n      if (path && cwd && path.startsWith(cwd)) path = path.slice(cwd.length + 1);\n      if (path && path.startsWith('/')) path = null;\n\n      if (state.lastEventMs !== null) {\n        const gap = ms - state.lastEventMs;\n        // Zero gap is real: several tool calls in one assistant turn share a\n        // timestamp. Only a LONG gap becomes the pause beat.\n        state.activeMs += gap >= IDLE_MS ? PAUSE_BEAT_MS : Math.max(gap, 0);\n      }\n      state.lastEventMs = ms;\n\n      events.push({\n        seq: state.seq++,\n        t: Math.round(state.activeMs / 1000),\n        tool: block.name,\n        path,\n      });\n    }\n  }\n  return events;\n}\n","import chalk from 'chalk';\nimport type { BridgeClient } from '@devpilot.sh/bridge-client';\nimport { runScanPipeline } from '../sessions/scan-pipeline';\n\n/**\n * Keeping the cockpit live — TRD 22 §8.\n *\n * The bridge re-scans this machine on a cadence and reports what it sees. That\n * is the whole of what makes \"turn it on and your sessions are there\" true:\n * without a sweep, observation is a snapshot taken at connect time that decays\n * into a list of agents that finished hours ago.\n *\n * ## Why this is safe to run by default, and adoption is not\n *\n * An observation writes to the caller's own organization and creates nothing\n * outside it: no Linear issue, no queue row, no routing decision, no capability.\n * Adoption creates issues on a board a whole team reads, which is why it stays\n * behind a flag and a confirmation.\n *\n * ## Why it reports endings explicitly\n *\n * A session that stops between two sweeps would otherwise stay `running` in the\n * cockpit forever. Each sweep sends the keys it no longer sees live, so the\n * board reflects the machine rather than the high-water mark of the machine. A\n * confidently wrong \"11 agents running\" is worse than an empty page.\n */\n\nexport interface ObserverConfig {\n  client: BridgeClient;\n  machineName: string;\n  repos: string[];\n  /** Observe every repo, not only routed ones. Default true — see below. */\n  allRepos?: boolean;\n  intervalMs?: number;\n  /** Model-written summaries per sweep. Sessions beyond it wait for the next. */\n  summariseBudget?: number;\n  /** How far back a session counts as worth reporting. */\n  sinceMs?: number;\n  onLog?: (line: string) => void;\n}\n\nconst DEFAULT_INTERVAL_MS = 60_000;\nconst DEFAULT_SINCE_MS = 24 * 60 * 60 * 1000;\n/** Model-written summaries per sweep. Bounded so a big fleet does not spike. */\nconst DEFAULT_SUMMARISE_BUDGET = 10;\n\nexport class SessionObserver {\n  private timer: NodeJS.Timeout | null = null;\n  private running = false;\n  /** Adoption keys reported live on the previous sweep. */\n  private lastLive = new Set<string>();\n  /**\n   * Adoption keys this process has already reported once.\n   *\n   * A summary is worth paying for exactly once per session: it is what\n   * `/api/sessions/:id/promote` uses as the body of the Linear issue it drafts,\n   * and a sweep with no summary produced tickets describing nothing. Paying for\n   * it every 60 seconds would be absurd; paying for it never left every ticket\n   * thin. First sight is the right moment.\n   */\n  private seen = new Set<string>();\n  /**\n   * `adoptionKey → where that conversation lives on this machine`.\n   *\n   * The resolution table for \"take the wheel\" (TRD 23 §3.3). The hosted plane\n   * can only point at a row; this is the state that says what that means here,\n   * and it never leaves the process.\n   */\n  private targets = new Map<\n    string,\n    {\n      transcriptPath: string;\n      sessionUuid: string;\n      repo: string;\n      title?: string;\n      summary?: string;\n      branch?: string;\n      touchedPaths?: string[];\n    }\n  >();\n  private readonly intervalMs: number;\n  private readonly sinceMs: number;\n  private readonly summariseBudget: number;\n\n  constructor(private readonly config: ObserverConfig) {\n    this.intervalMs = config.intervalMs ?? DEFAULT_INTERVAL_MS;\n    this.sinceMs = config.sinceMs ?? DEFAULT_SINCE_MS;\n    this.summariseBudget = config.summariseBudget ?? DEFAULT_SUMMARISE_BUDGET;\n  }\n\n  /**\n   * Where a conversation lives on this machine, by adoption key.\n   *\n   * Undefined for anything this process has not observed — which is the honest\n   * answer, and the reason a resume for another machine's session refuses\n   * rather than guessing.\n   */\n  targetFor(adoptionKey: string):\n    | {\n        transcriptPath: string;\n        sessionUuid: string;\n        repo: string;\n        title?: string;\n        summary?: string;\n        branch?: string;\n        touchedPaths?: string[];\n      }\n    | undefined {\n    return this.targets.get(adoptionKey);\n  }\n\n  start(): void {\n    if (this.timer) return;\n    this.timer = setInterval(() => void this.sweep(), this.intervalMs);\n    this.timer.unref?.();\n  }\n\n  stop(): void {\n    if (this.timer) clearInterval(this.timer);\n    this.timer = null;\n  }\n\n  /**\n   * One pass. Never throws, and never overlaps itself.\n   *\n   * A scan on a large machine takes most of a second and `git status` can take\n   * longer; without the guard a slow sweep would stack behind the interval and\n   * the machine would spend its life scanning itself.\n   */\n  async sweep(): Promise<{ observed: number; ended: number } | null> {\n    if (this.running) return null;\n    this.running = true;\n\n    try {\n      const result = await runScanPipeline({\n        machineName: this.config.machineName,\n        repos: this.config.repos,\n        /**\n         * Observation defaults to EVERY repo, unlike placement.\n         *\n         * TRD 21 §3.5 narrowed adoption to routed repos because it pushes repo\n         * names onto a shared Linear board, and one client's names must not\n         * reach another client's workspace. Observation has no such reach: it\n         * writes only into the org that already receives the full repo\n         * inventory from discovery, so restricting it here would buy no privacy\n         * and would leave the cockpit empty for anyone who has not routed\n         * anything yet — which is everyone, on day one.\n         */\n        allRepos: this.config.allRepos !== false,\n        sinceMs: this.sinceMs,\n        includePaths: true,\n        /**\n         * Summarise only what this process has not seen before, and only a\n         * handful per sweep.\n         *\n         * The first sweep after a connect is the expensive one — everything is\n         * new — so it is capped, and the remainder pick up their summary on\n         * later passes rather than all at once.\n         */\n        maxSummaries: this.summariseBudget,\n        summarize: true,\n        skipSummaryFor: this.seen,\n      });\n\n      /**\n       * Nothing is stripped from already-seen candidates here: they simply\n       * never got a summary this pass, and the server's COALESCE upsert treats\n       * an absent summary as \"leave what you have\" rather than an erasure.\n       */\n      result.candidates.forEach((c) => {\n        this.seen.add(c.adoptionKey);\n        const at = result.transcriptPaths.get(c.adoptionKey);\n        if (at) {\n          this.targets.set(c.adoptionKey, {\n            transcriptPath: at.transcriptPath,\n            sessionUuid: at.sessionUuid,\n            repo: c.repo,\n            // Carried so a planning handoff has a brief to work from without\n            // going back to the hosted plane for what this machine just read.\n            title: c.title,\n            summary: c.summary,\n            branch: c.branch,\n            touchedPaths: c.touchedPaths,\n          });\n        }\n      });\n\n      const live = new Set(result.candidates.filter((c) => c.live).map((c) => c.adoptionKey));\n      const ended = [...this.lastLive].filter((key) => !live.has(key));\n\n      const response = await this.config.client.reportObservations({\n        machineName: this.config.machineName,\n        sessions: result.candidates,\n        endedKeys: ended,\n      });\n\n      this.lastLive = live;\n\n      if (response) {\n        return { observed: response.observed, ended: response.ended };\n      }\n      return null;\n    } catch (err) {\n      this.config.onLog?.(\n        chalk.gray(`observation sweep failed: ${err instanceof Error ? err.message : err}`),\n      );\n      return null;\n    } finally {\n      this.running = false;\n    }\n  }\n}\n","import { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport chalk from 'chalk';\nimport { adoption } from '@devpilot.sh/core';\nimport type { AdoptionCandidate, DiscoveredRepo } from '@devpilot.sh/bridge-protocol';\n\n/**\n * The shared scan → summarize step behind `sessions scan`, `sessions adopt`\n * and `bridge connect --adopt` — TRD 21 §6.5.\n *\n * One implementation because the three surfaces must agree exactly: a preview\n * that scanned differently from the adopt that follows it would show a user one\n * list and act on another.\n */\n\nexport interface PipelineOptions {\n  machineName: string;\n  /** Repos this machine routes. Empty plus `allRepos: false` adopts nothing. */\n  repos: string[];\n  allRepos: boolean;\n  onlyRepo?: string;\n  sinceMs: number;\n  includePaths: boolean;\n  maxSummaries: number;\n  /** Skip the model entirely. Discovery-only paths do not need titles. */\n  summarize: boolean;\n  /**\n   * Adoption keys that already have a summary somewhere else, so paying for\n   * one again is waste. The observer passes everything it has reported before.\n   */\n  skipSummaryFor?: Set<string>;\n  onWarn?: (message: string) => void;\n}\n\nexport interface PipelineResult {\n  candidates: AdoptionCandidate[];\n  discovered: DiscoveredRepo[];\n  unmappedProjectCount: number;\n  skipped: adoption.SkippedSession[];\n  projectDirCount: number;\n  withheldOwners: string[];\n  /** How many titles came from a model rather than the heuristic. */\n  modelTitles: number;\n  /**\n   * `adoptionKey → where that session lives on disk`. LOCAL ONLY — this is what\n   * lets the watcher stat the right file after adoption, and it must never be\n   * serialized into a request.\n   */\n  transcriptPaths: Map<string, { transcriptPath: string; sessionUuid: string; cwd: string | null }>;\n}\n\n/** `24h`, `90m`, `7d`, or a bare number of hours. */\nexport function parseDuration(input: string, fallbackMs: number): number {\n  const match = /^(\\d+)\\s*([smhdw])?$/i.exec(input.trim());\n  if (!match) return fallbackMs;\n  const value = Number(match[1]);\n  const unit = (match[2] ?? 'h').toLowerCase();\n  const scale: Record<string, number> = {\n    s: 1000,\n    m: 60_000,\n    h: 3_600_000,\n    d: 86_400_000,\n    w: 604_800_000,\n  };\n  return value * (scale[unit] ?? scale.h);\n}\n\nexport async function runScanPipeline(options: PipelineOptions): Promise<PipelineResult> {\n  const repos = options.onlyRepo ? [options.onlyRepo] : options.repos;\n\n  const scan = adoption.scanSessions({\n    machineName: options.machineName,\n    repos,\n    // `--repo x` is an explicit narrowing, so it must not be widened by\n    // `--all-repos` arriving from a config file or an alias.\n    allRepos: options.onlyRepo ? false : options.allRepos,\n    sinceMs: options.sinceMs,\n    includePaths: options.includePaths,\n    excludeSessionUuids: adoption.loadOwnedSessionIds(\n      join(homedir(), '.devpilot', 'owned-sessions.json'),\n    ),\n  });\n\n  let modelTitles = 0;\n\n  /**\n   * Titles come from the scan already (the client's own session title, or the\n   * first prompt). The model call only improves them, so everything below is\n   * optional and any failure leaves the heuristic in place.\n   */\n  /**\n   * Runs with or without an API key.\n   *\n   * This used to require `ANTHROPIC_API_KEY`, which skipped the HEURISTIC tier\n   * as well as the model one — so a machine with no key produced no summary at\n   * all, and `promote` drafted every Linear issue from bare evidence. All 102\n   * adopted sessions on the live fleet had a null summary because of this line.\n   *\n   * `summarizeSessions` already decides per session which tier it can afford;\n   * gating the call on the key second-guessed it and lost the free tier.\n   */\n  if (options.summarize && scan.candidates.length > 0) {\n    const jobs = scan.candidates\n      .filter((c) => !options.skipSummaryFor?.has(c.adoptionKey))\n      .map((candidate) => {\n        // Re-probe rather than threading observations through the scan's return\n        // type: the scanner's contract is wire values, and widening it to carry\n        // transcript samples would put them one careless `JSON.stringify` from\n        // the network.\n        const observation = observationFor(candidate, scan);\n        return observation ? { candidate, observation } : null;\n      })\n      .filter((j): j is NonNullable<typeof j> => j !== null);\n\n    const summaries = await adoption.summarizeSessions(\n      jobs.map((j) => ({\n        observation: j.observation,\n        touchedPaths: j.candidate.touchedPaths ?? [],\n      })),\n      { maxSummaries: options.maxSummaries, onWarn: options.onWarn },\n    );\n\n    summaries.forEach((summary, i) => {\n      const candidate = jobs[i].candidate;\n      candidate.title = summary.title;\n      if (summary.summary) candidate.summary = summary.summary;\n      if (summary.source === 'model') modelTitles++;\n    });\n  }\n\n  return {\n    candidates: scan.candidates,\n    discovered: scan.discovered,\n    unmappedProjectCount: scan.unmappedProjectCount,\n    skipped: scan.skipped,\n    projectDirCount: scan.projectDirCount,\n    withheldOwners: adoption.withheldOwners(scan.skipped),\n    modelTitles,\n    transcriptPaths: scan.transcriptPaths,\n  };\n}\n\n/**\n * Recover the observation behind a candidate.\n *\n * The scan discards observations deliberately — they hold `headSample`, which\n * is transcript text — so the summarizer re-reads the one file it needs. That\n * is one bounded probe per candidate, not per session, and it keeps the type\n * that crosses the network free of anything that could leak.\n */\nfunction observationFor(\n  candidate: AdoptionCandidate,\n  scan: adoption.ScanResult,\n): adoption.SessionObservation | null {\n  const path = scan.transcriptPaths?.get(candidate.adoptionKey);\n  if (!path) return null;\n  return adoption.probeTranscript(path.transcriptPath, path.sessionUuid);\n}\n\n/** The `● 2m` recency column. */\nexport function relativeAge(iso: string, now = Date.now()): string {\n  const ms = now - Date.parse(iso);\n  if (!Number.isFinite(ms) || ms < 0) return '—';\n  const minutes = Math.round(ms / 60_000);\n  if (minutes < 1) return 'now';\n  if (minutes < 60) return `${minutes}m`;\n  const hours = Math.round(minutes / 60);\n  if (hours < 48) return `${hours}h`;\n  return `${Math.round(hours / 24)}d`;\n}\n\nfunction pad(value: string, width: number): string {\n  return value.length > width ? `${value.slice(0, width - 1)}…` : value.padEnd(width);\n}\n\nexport interface PreviewRow {\n  repo: string;\n  title: string;\n  lastActivityAt: string;\n  live: boolean;\n  /** What the server said this would do. */\n  destination: string;\n}\n\n/**\n * The table both `scan` and `adopt` print.\n *\n * The skip line names the owners it is withholding — TRD 21 §3.5. That is the\n * consent moment made concrete: a user who sees `arthaus` and `neurograph`\n * named can decide whether they belong on this board, and a user who sees only\n * \"3 skipped\" cannot.\n */\nexport function renderPreview(rows: PreviewRow[], result: PipelineResult): string {\n  const lines: string[] = [];\n\n  lines.push(\n    chalk.gray(\n      `  Scanned ${result.projectDirCount} project director${\n        result.projectDirCount === 1 ? 'y' : 'ies'\n      } · ${result.candidates.length} session${result.candidates.length === 1 ? '' : 's'} in scope`,\n    ),\n  );\n  lines.push('');\n\n  if (rows.length > 0) {\n    lines.push(\n      chalk.gray(`  ${pad('REPO', 30)} ${pad('SESSION', 44)} ${pad('LAST', 6)} → BOARD`),\n    );\n    for (const row of rows) {\n      lines.push(\n        `  ${chalk.cyan(pad(row.repo, 30))} ${pad(row.title, 44)} ${\n          row.live ? chalk.green(pad(relativeAge(row.lastActivityAt), 5)) + '●'\n                   : chalk.gray(pad(relativeAge(row.lastActivityAt), 6))\n        } → ${row.destination}`,\n      );\n    }\n    lines.push('');\n  }\n\n  const reasons = new Map<string, number>();\n  for (const skip of result.skipped) {\n    reasons.set(skip.reason, (reasons.get(skip.reason) ?? 0) + 1);\n  }\n\n  const parts: string[] = [];\n  const label: Record<string, string> = {\n    'not-routed': 'not routed',\n    'devpilot-owned': 'DevPilot-owned',\n    'too-old': 'outside the window',\n    'no-repo': 'no git remote',\n    sidechain: 'subagent transcripts',\n    empty: 'empty',\n    unreadable: 'unreadable',\n  };\n  for (const [reason, count] of reasons) {\n    if (reason === 'not-routed' && result.withheldOwners.length > 0) {\n      parts.push(`${count} not routed (${result.withheldOwners.join(', ')})`);\n    } else {\n      parts.push(`${count} ${label[reason] ?? reason}`);\n    }\n  }\n\n  if (parts.length > 0) {\n    lines.push(chalk.gray(`  Skipped: ${parts.join(', ')}`));\n    if (reasons.has('not-routed')) {\n      lines.push(chalk.gray('           Run with --all-repos to include the others.'));\n    }\n  }\n\n  return lines.join('\\n');\n}\n","import { adoption } from '@devpilot.sh/core';\nimport type { BridgeClient, SessionCommandMessage } from '@devpilot.sh/bridge-client';\nimport { planFromSession } from './conductor-handler';\n\n/**\n * Picking up the wheel on a session DevPilot did not start — TRD 23 §7.2.\n *\n * The hosted plane queues a `resume` against a DevPilot session id. This\n * resolves that, locally, to a Claude Code conversation on this machine and\n * continues it under the session-runner — at which point the run is\n * DevPilot-spawned and every callback, stream event and plan gate already built\n * applies to it.\n *\n * ## The hosted plane cannot name a local session, and this is why that holds\n *\n * `adoptionKey` is `sha256(machineName + ':' + sessionUuid)` and the uuid has\n * never crossed the wire (TRD 21 §4.1). So a command can only point at a row\n * the hosted plane already had; what that means on this machine is decided\n * here, from state only this machine holds.\n *\n * A compromised control plane therefore cannot ask a laptop to resume an\n * arbitrary conversation, because it does not know what any conversation is\n * called. That property is worth more than the convenience of sending a uuid.\n *\n * ## Why liveness is re-checked immediately before spawning\n *\n * Two processes appending to one transcript corrupts it. The cockpit's idea of\n * \"held\" can be a minute old — a person may have gone back to the terminal in\n * the meantime — so the decision is made here, against the file, at the moment\n * of acting. Refusing is cheap; a corrupted transcript is not recoverable.\n */\n\nexport interface ResumeTarget {\n  transcriptPath: string;\n  sessionUuid: string;\n  repo: string;\n  /** Absolute working directory the session ran in. */\n  cwd: string;\n  /** What the cockpit calls this session; the planner's item title. */\n  title?: string;\n  summary?: string;\n  branch?: string;\n  touchedPaths?: string[];\n}\n\nexport interface ResumeApplierOptions {\n  client: BridgeClient;\n  /**\n   * Session-runner base URL, e.g. http://127.0.0.1:3900.\n   *\n   * Required only for `continue`. A planning bridge does not run one, and\n   * demanding it would refuse the mode that does not need it.\n   */\n  sessionApiUrl?: string;\n  sessionApiKey?: string;\n  /**\n   * Where the runner should report back to — usually nowhere.\n   *\n   * An adopted session's status comes from the OBSERVATION SWEEP, not from\n   * callbacks: the resumed run appends to the same transcript, so the next\n   * sweep sees it live and reports it, and sees it quiet and settles it. That\n   * is already the mechanism keeping every adopted row current.\n   *\n   * The first version pointed this at `/api/orchestrator`, which does not\n   * exist — the hosted routes are `/api/sessions/:id/status` — so every\n   * callback 404'd. Pointing it at the real route would not have worked either:\n   * the runner authenticates callbacks with `X-DevPilot-Callback-Token`, and\n   * the hosted routes read `Authorization: Bearer`. Two reporting paths where\n   * one already works is not worth reconciling.\n   */\n  callbackUrl?: string;\n  /** `adoptionKey → where that conversation lives on this machine`. */\n  resolveTarget: (adoptionKey: string) => ResumeTarget | undefined;\n  /**\n   * Local cockpit base URL (`devpilot serve`).\n   *\n   * Required only for `plan`. The conductor graph lives in the Next app rather\n   * than in core — langchain is deliberately kept out of the package every CLI\n   * install pulls down — so planning is an HTTP call to the cockpit, exactly as\n   * the dispatch path does it.\n   */\n  cockpitUrl?: string;\n  /** Treated as still running within this window. Default 5 minutes. */\n  liveWithinMs?: number;\n  onLog?: (line: string) => void;\n  fetchImpl?: typeof fetch;\n}\n\nconst DEFAULT_LIVE_WITHIN_MS = 5 * 60_000;\n\nexport class ResumeApplier {\n  private readonly log: (line: string) => void;\n  private readonly doFetch: typeof fetch;\n  private readonly liveWithinMs: number;\n\n  constructor(private readonly opts: ResumeApplierOptions) {\n    this.log = opts.onLog ?? (() => {});\n    this.doFetch = opts.fetchImpl ?? fetch;\n    this.liveWithinMs = opts.liveWithinMs ?? DEFAULT_LIVE_WITHIN_MS;\n  }\n\n  /** Whether this applier handles a given command. */\n  static handles(command: SessionCommandMessage): boolean {\n    return command.command === 'resume';\n  }\n\n  /**\n   * Apply one resume.\n   *\n   * Acknowledges only AFTER the runner accepts, matching the ordering rule in\n   * `command-applier.ts`: a decision a person made must not be silently dropped\n   * because a laptop was asleep. The cost is that an accepted-but-unacknowledged\n   * resume is retried, which the runner's own idempotency on `sessionId`\n   * absorbs rather than starting a second agent on the same repo.\n   */\n  async apply(command: SessionCommandMessage): Promise<void> {\n    const adoptionKey = command.payload?.adoptionKey;\n    if (!adoptionKey) {\n      await this.fail(\n        command,\n        'That resume carried no session key, so this machine cannot tell which conversation it means.',\n      );\n      return;\n    }\n\n    const target = this.opts.resolveTarget(adoptionKey);\n\n    if (!target) {\n      /**\n       * This machine does not know that session.\n       *\n       * Legitimate and common: the ledger is per-machine, so a session observed\n       * by a laptop that is now offline cannot be resumed by a different one.\n       * Failing it says so; leaving it pending would spin forever on a cockpit\n       * button that can never resolve.\n       */\n      await this.fail(\n        command,\n        'This machine is not tracking that session, so there is nothing to resume. ' +\n          'It may belong to a different machine in the fleet.',\n      );\n      return;\n    }\n\n    // Re-probe against the file, not against a status that may be a minute old.\n    const observation = adoption.probeTranscript(target.transcriptPath, target.sessionUuid);\n    if (!observation) {\n      await this.fail(command, 'That session’s transcript is no longer on this machine.');\n      return;\n    }\n\n    /**\n     * Liveness blocks CONTINUING, not planning.\n     *\n     * The rule was never \"leave live sessions alone\", it was \"do not put a\n     * second process on one transcript\". Planning does not touch the transcript\n     * at all — it reads what the observer already recorded and asks the\n     * conductor — so refusing it on a live session withheld the safe mode along\n     * with the unsafe one.\n     *\n     * That matters in practice: a session you are watching run and want to\n     * redirect is exactly when a plan is most useful, and it is the state a\n     * busy fleet is mostly in.\n     */\n    if (\n      command.payload?.mode !== 'plan' &&\n      Date.now() - observation.lastActivityMs < this.liveWithinMs\n    ) {\n      await this.fail(\n        command,\n        'That session is still running, so continuing it would put two agents on one ' +\n          'transcript. Open it in Claude Code, or plan the work instead.',\n      );\n      return;\n    }\n\n    const message = command.payload?.message?.trim();\n\n    if (command.payload?.mode !== 'plan' && !this.opts.sessionApiUrl) {\n      await this.fail(\n        command,\n        'Continuing a session needs the local session runner. Start one with ' +\n          '`devpilot session-runner` and reconnect with --session-api-url, or use Plan it.',\n      );\n      return;\n    }\n\n    /**\n     * Plan, rather than continue — TRD 23 §3.5.\n     *\n     * Handled before the runner call because it is a different request, not a\n     * variation on one: the person asked what the work SHOULD be, and the\n     * answer is a decomposition they approve before anything runs.\n     */\n    if (command.payload?.mode === 'plan') {\n      if (!this.opts.cockpitUrl) {\n        await this.fail(\n          command,\n          'Planning needs the local cockpit. Start it with `devpilot serve`, reconnect the ' +\n            'bridge with --cockpit-url, or take the wheel without planning.',\n        );\n        return;\n      }\n      try {\n        const summary = await planFromSession({\n          client: this.opts.client,\n          cockpitUrl: this.opts.cockpitUrl,\n          sessionId: command.sessionId,\n          repo: target.repo,\n          title: target.title || `Continue work in ${target.repo}`,\n          message,\n          summary: target.summary,\n          branch: target.branch,\n          touchedPaths: target.touchedPaths,\n          fetchImpl: this.doFetch,\n          onLog: this.log,\n        });\n        await this.opts.client.acknowledgeCommands([command.id], 'applied');\n        this.log(`planned ${target.repo}: ${summary}`);\n      } catch (err) {\n        /**\n         * FAILED, not left pending, unlike an unreachable runner. A planning\n         * call that got as far as the cockpit and came back with an error —\n         * no API key, a refused model, a graph failure — will fail the same way\n         * on every retry, and a command that retries forever is worse than one\n         * that says why it stopped.\n         */\n        await this.fail(\n          command,\n          `Planning failed: ${err instanceof Error ? err.message : String(err)}`,\n        );\n      }\n      return;\n    }\n\n    try {\n      const res = await this.doFetch(`${this.opts.sessionApiUrl!.replace(/\\/$/, '')}/v1/sessions`, {\n        method: 'POST',\n        headers: {\n          'content-type': 'application/json',\n          ...(this.opts.sessionApiKey\n            ? { authorization: `Bearer ${this.opts.sessionApiKey}` }\n            : {}),\n        },\n        body: JSON.stringify({\n          sessionId: command.sessionId,\n          repo: target.repo,\n          /**\n           * `--resume` continues the conversation, so a prompt is optional in a\n           * way it never is for a fresh dispatch. With nothing to say, ask the\n           * agent to take stock rather than sending an empty string — an empty\n           * turn produces an empty answer, and the point of picking this up is\n           * to find out where it got to.\n           */\n          prompt:\n            message ||\n            'Summarise where this session got to and what remains, then stop and wait.',\n          resumeSessionId: target.sessionUuid,\n          // Empty is the established \"no callbacks\" value; the dispatch path\n          // passes the same and relies on polling instead.\n          callbackUrl: this.opts.callbackUrl ?? '',\n        }),\n      });\n\n      // 409 is the runner saying it already has this sessionId — idempotent,\n      // and exactly what a retried acknowledgement should produce.\n      if (!res.ok && res.status !== 409) {\n        const body = await res.text().catch(() => '');\n        await this.fail(\n          command,\n          `The local session runner refused: ${res.status} ${body.slice(0, 200)}`,\n        );\n        return;\n      }\n\n      await this.opts.client.acknowledgeCommands([command.id], 'applied');\n      this.log(\n        `took the wheel on ${target.repo}${message ? ' with an instruction' : ''} — ` +\n          'it now reports as a DevPilot run',\n      );\n    } catch (err) {\n      /**\n       * Left PENDING deliberately, unlike the refusals above.\n       *\n       * Those are permanent facts about this machine; this is a runner that may\n       * simply not be up yet. Failing it would throw away a decision a person\n       * made because a daemon was starting.\n       */\n      this.log(\n        `could not reach the session runner (${err instanceof Error ? err.message : String(err)}) — ` +\n          'the resume stays queued',\n      );\n    }\n  }\n\n  private async fail(command: SessionCommandMessage, reason: string): Promise<void> {\n    await this.opts.client.acknowledgeCommands([command.id], 'failed', reason);\n    this.log(`resume refused — ${reason}`);\n  }\n}\n","import chalk from 'chalk';\nimport type { BridgeClient } from '@devpilot.sh/bridge-client';\nimport { adoption } from '@devpilot.sh/core';\nimport { runScanPipeline } from '../sessions/scan-pipeline';\nimport type { AdoptionWatcher } from './adoption-watcher';\n\n/**\n * What `devpilot bridge connect` does the moment it registers — TRD 21 §8.1.\n *\n * ## The product argument, in one function\n *\n * A first connect used to print `repos: (none)`, warn that nothing could route\n * to this machine, and start listening at an empty board. Everything the user\n * had already been doing with agents was on the other side of a wall.\n *\n * This walks the machine and says what it found, grouped by owner. The\n * warning about having no repos is immediately followed by the answer to it.\n *\n * ## Discovery always; adoption only when asked\n *\n * Discovery is an inventory: no model call, no Linear call, no board write, and\n * every row is inert until a member accepts it. Adoption creates issues on a\n * board a whole team reads, so it needs `--adopt`, and even then it prints what\n * it did.\n *\n * Nothing here may prevent a connect. A machine that cannot introspect is still\n * a machine that can run dispatched work, and trading that for an inventory\n * would be an absurd bargain — so every failure below is a printed line.\n */\n\nexport interface IntrospectionOptions {\n  client: BridgeClient;\n  machineName: string;\n  repos: string[];\n  adopt: boolean;\n  allRepos: boolean;\n  watcher: AdoptionWatcher;\n}\n\nexport async function runIntrospection(options: IntrospectionOptions): Promise<void> {\n  let result;\n  try {\n    result = await runScanPipeline({\n      machineName: options.machineName,\n      repos: options.repos,\n      allRepos: options.allRepos,\n      sinceMs: 24 * 60 * 60 * 1000,\n      includePaths: true,\n      maxSummaries: 25,\n      // Only pay for titles when they are about to be written somewhere.\n      summarize: options.adopt,\n      onWarn: (line) => console.log(chalk.gray(`   ${line}`)),\n    });\n  } catch (err) {\n    console.log(chalk.gray(`   Could not look around this machine: ${describe(err)}`));\n    return;\n  }\n\n  if (result.projectDirCount === 0) {\n    // No transcript store at all: a machine that has never run an agent. Not a\n    // problem, and not worth a line about it.\n    return;\n  }\n\n  const live = result.discovered.reduce((n, r) => n + r.liveSessionCount, 0);\n  const owners = adoption.groupByOwner(result.discovered);\n\n  console.log(\n    chalk.cyan(\n      `   Looked around this machine: ${result.projectDirCount} projects, ` +\n        `${owners.size} owner${owners.size === 1 ? '' : 's'}, ` +\n        `${result.discovered.reduce((n, r) => n + r.sessionCount, 0)} sessions`,\n    ),\n  );\n  console.log('');\n\n  const sorted = [...owners.entries()].sort(\n    (a, b) =>\n      b[1].reduce((n, r) => n + r.sessionCount, 0) - a[1].reduce((n, r) => n + r.sessionCount, 0),\n  );\n\n  for (const [owner, repos] of sorted.slice(0, 8)) {\n    const sessions = repos.reduce((n, r) => n + r.sessionCount, 0);\n    const liveHere = repos.reduce((n, r) => n + r.liveSessionCount, 0);\n    console.log(\n      `     ${chalk.bold(owner.padEnd(18))} ${String(repos.length).padStart(2)} repo${\n        repos.length === 1 ? ' ' : 's'\n      }   ${String(sessions).padStart(4)} session${sessions === 1 ? ' ' : 's'}` +\n        (liveHere > 0 ? chalk.green(`   ● ${liveHere} live`) : ''),\n    );\n  }\n  if (sorted.length > 8) {\n    console.log(chalk.gray(`     … and ${sorted.length - 8} more`));\n  }\n  console.log('');\n\n  const discovery = await options.client.reportDiscovery({\n    machineName: options.machineName,\n    repos: result.discovered,\n    unmappedProjectCount: result.unmappedProjectCount,\n  });\n\n  if (discovery && discovery.proposed > 0) {\n    console.log(\n      chalk.gray(\n        `     ${discovery.proposed} repo${discovery.proposed === 1 ? '' : 's'} not yet routed — review at ` +\n          `${options.client.hostedUrl()}/fleet/discovered`,\n      ),\n    );\n    console.log('');\n  } else if (!discovery) {\n    console.log(chalk.gray('     (could not report the inventory — the bridge is still fine)'));\n    console.log('');\n  }\n\n  if (live > 0 && !options.adopt) {\n    console.log(\n      chalk.gray(\n        `     ${live} of these are running right now. \\`devpilot sessions scan\\` shows what ` +\n          'putting them on the board would do.',\n      ),\n    );\n    console.log('');\n  }\n\n  if (!options.adopt || result.candidates.length === 0) return;\n\n  try {\n    const response = await options.client.adoptSessions({\n      machineName: options.machineName,\n      candidates: result.candidates,\n      dryRun: false,\n    });\n\n    console.log(\n      chalk.green(\n        `   ✓ Adopted ${response.adopted}, attached ${response.attached}, ` +\n          `${response.duplicates} already tracked, ${response.skipped} skipped`,\n      ),\n    );\n\n    /**\n     * Watch what was adopted, so a session going quiet reaches the ticket.\n     *\n     * Only live sessions are tracked: one already recorded as complete has\n     * nothing left to observe, and polling its mtime forever would be work in\n     * service of an event that cannot happen.\n     */\n    const byKey = new Map(result.candidates.map((c) => [c.adoptionKey, c]));\n    for (const outcome of response.outcomes) {\n      /**\n       * 'duplicate' is tracked too — deliberately. It means the session is\n       * already on the board, and the hosted side returns the existing row's\n       * id precisely so a machine can resume watching it. Without this, a\n       * bridge that lost its ledger (reinstall, new machine, deleted state)\n       * would never stream for any session adopted before the loss — which\n       * was this machine's exact condition when streaming first shipped.\n       */\n      if (outcome.status !== 'adopted' && outcome.status !== 'attached' && outcome.status !== 'duplicate')\n        continue;\n      if (!outcome.sessionId) continue;\n\n      const candidate = byKey.get(outcome.adoptionKey);\n      const location = result.transcriptPaths?.get(outcome.adoptionKey);\n      if (!candidate?.live || !location) continue;\n\n      options.watcher.track({\n        adoptionKey: outcome.adoptionKey,\n        sessionId: outcome.sessionId,\n        identifier: outcome.linearIdentifier ?? candidate.repo,\n        transcriptPath: location.transcriptPath,\n        repo: candidate.repo,\n        startedAt: candidate.startedAt,\n        lastMtimeMs: Date.parse(candidate.lastActivityAt),\n        lastReportedAt: new Date().toISOString(),\n        settled: false,\n        // Repo-relative paths in the stream need the absolute prefix to strip.\n        cwd: location.cwd,\n      });\n    }\n\n    if (options.watcher.size() > 0) {\n      console.log(\n        chalk.gray(\n          `     Watching ${options.watcher.size()} of them. They are observed, not dispatched — ` +\n            'no ticket will be moved.',\n        ),\n      );\n    }\n    console.log('');\n  } catch (err) {\n    console.log(chalk.yellow(`   Could not adopt: ${describe(err)}`));\n    console.log('');\n  }\n}\n\nfunction describe(err: unknown): string {\n  return err instanceof Error ? err.message : String(err);\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\n\nexport const disconnectCommand = new Command('disconnect')\n  .description('Disconnect from DevPilot cloud bridge')\n  .option('-u, --bridge-url <url>', 'Bridge service URL', process.env.DEVPILOT_BRIDGE_URL)\n  .option('-k, --api-key <key>', 'API key', process.env.DEVPILOT_BRIDGE_API_KEY)\n  .option('-i, --orchestrator-id <id>', 'Orchestrator ID to disconnect')\n  .action(async (options) => {\n    if (!options.bridgeUrl || !options.orchestratorId) {\n      console.error(chalk.red('✗ Error: Bridge URL and orchestrator ID required'));\n      console.error(chalk.gray('   Use: devpilot bridge disconnect -u <url> -i <orchestrator-id>'));\n      process.exit(1);\n    }\n\n    console.log(chalk.cyan('🌉 Disconnecting from DevPilot Bridge'));\n    console.log('');\n    console.log(chalk.gray(`   Bridge URL: ${options.bridgeUrl}`));\n    console.log(chalk.gray(`   Orchestrator ID: ${options.orchestratorId}`));\n    console.log('');\n\n    try {\n      const response = await fetch(\n        `${options.bridgeUrl}/api/orchestrators/${options.orchestratorId}`,\n        {\n          method: 'DELETE',\n          headers: {\n            'Authorization': `Bearer ${options.apiKey}`,\n          },\n        }\n      );\n\n      if (response.ok) {\n        console.log(chalk.green('✓ Successfully disconnected from bridge'));\n      } else {\n        const errorText = await response.text();\n        console.error(chalk.red('✗ Failed to disconnect:'));\n        console.error(chalk.red(`   ${errorText}`));\n        process.exit(1);\n      }\n    } catch (error) {\n      console.error(chalk.red('✗ Error disconnecting:'));\n      console.error(chalk.red(`   ${error instanceof Error ? error.message : error}`));\n      process.exit(1);\n    }\n  });\n","import { Command } from 'commander';\nimport chalk from 'chalk';\n\nexport const statusCommand = new Command('status')\n  .description('Check bridge connection status')\n  .option('-u, --bridge-url <url>', 'Bridge service URL', process.env.DEVPILOT_BRIDGE_URL)\n  .option('-i, --orchestrator-id <id>', 'Orchestrator ID')\n  .option('-k, --api-key <key>', 'API key', process.env.DEVPILOT_BRIDGE_API_KEY)\n  .action(async (options) => {\n    if (!options.bridgeUrl) {\n      console.error(chalk.red('✗ Error: Bridge URL required'));\n      console.error(chalk.gray('   Use: devpilot bridge status -u <url>'));\n      process.exit(1);\n    }\n\n    console.log(chalk.cyan('🌉 DevPilot Bridge Status'));\n    console.log('');\n\n    try {\n      // Check bridge health\n      const healthRes = await fetch(`${options.bridgeUrl}/health`);\n      const health = (await healthRes.json()) as { status?: string };\n\n      console.log(chalk.white('Bridge Status:'));\n      if (health.status === 'ok') {\n        console.log(chalk.gray('  Status: ') + chalk.green('✓ Online'));\n      } else {\n        console.log(chalk.gray('  Status: ') + chalk.red('✗ Offline'));\n      }\n      console.log('');\n\n      // Check orchestrator status if ID provided\n      if (options.orchestratorId) {\n        const orchRes = await fetch(\n          `${options.bridgeUrl}/api/orchestrators/${options.orchestratorId}`,\n          {\n            headers: {\n              'Authorization': `Bearer ${options.apiKey}`,\n            },\n          }\n        );\n\n        if (orchRes.ok) {\n          const orch = (await orchRes.json()) as {\n            id?: string;\n            name?: string;\n            isOnline?: boolean;\n            activeJobs?: number;\n            lastHeartbeat?: string;\n            repos?: string[];\n          };\n          console.log(chalk.white('Orchestrator Status:'));\n          console.log(chalk.gray('  ID: ') + chalk.cyan(orch.id));\n          console.log(chalk.gray('  Name: ') + chalk.white(orch.name));\n\n          if (orch.isOnline) {\n            console.log(chalk.gray('  Online: ') + chalk.green('✓'));\n          } else {\n            console.log(chalk.gray('  Online: ') + chalk.red('✗'));\n          }\n\n          console.log(chalk.gray('  Active Jobs: ') + chalk.yellow(orch.activeJobs));\n          console.log(chalk.gray('  Last Heartbeat: ') + chalk.white(orch.lastHeartbeat || 'Never'));\n          console.log(chalk.gray('  Repos: ') + chalk.cyan(orch.repos?.join(', ') || 'None'));\n        } else {\n          console.log(chalk.white('Orchestrator Status:'));\n          console.log(chalk.gray('  ') + chalk.red('Not found or unauthorized'));\n        }\n      }\n    } catch (error) {\n      console.error(chalk.red('✗ Error checking status:'));\n      console.error(chalk.red(`   ${error instanceof Error ? error.message : error}`));\n      process.exit(1);\n    }\n  });\n","import { Command } from 'commander';\nimport { newCommand, joinCommand, tailCommand } from './session/index';\n\n/**\n * Shared agent sessions — TRD 06.\n *\n * A shared, ordered, end-to-end encrypted transcript that several people and\n * their local agents read and write. The hosted plane relays ciphertext and\n * cannot read it: the key lives in the link fragment and never leaves the\n * machines holding it.\n */\nexport const sessionCommand = new Command('session')\n  .description('Shared, end-to-end encrypted sessions across machines')\n  .addCommand(newCommand)\n  .addCommand(joinCommand)\n  .addCommand(tailCommand);\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { sessionCrypto, buildJoinLink, formatApiError } from '@devpilot.sh/bridge-protocol';\n\ninterface NewOptions {\n  url?: string;\n  token?: string;\n  org?: string;\n  issue?: string;\n}\n\n/**\n * `devpilot session new \"…\"` — TRD 06 §6.3.\n *\n * The key is generated HERE and never sent. What goes to the bridge is\n * sha256(verifier), where the verifier is a separate HKDF branch that cannot\n * decrypt anything. The bridge stores that hash and nothing else, which is why\n * it can host the transcript without being able to read it.\n */\nexport const newCommand = new Command('new')\n  .description('Create a shared session and print its join link')\n  .argument('<title>', 'What this session is about (stored in plaintext — no secrets)')\n  .option('-u, --url <url>', 'Bridge URL', process.env.DEVPILOT_BRIDGE_URL)\n  .option('-t, --token <token>', 'Orchestrator token (dp_orch_…)', process.env.DEVPILOT_BRIDGE_TOKEN)\n  .option('-o, --org <orgId>', 'Organization id that will own the session')\n  .option('--issue <identifier>', 'Linear issue identifier to attach, e.g. ENG-394')\n  .action(async (title: string, options: NewOptions) => {\n    if (!options.url || !options.token) {\n      console.error(chalk.red('✗ Bridge URL and token required'));\n      console.error(chalk.gray('  --url / DEVPILOT_BRIDGE_URL, --token / DEVPILOT_BRIDGE_TOKEN'));\n      process.exit(1);\n    }\n    if (!options.org) {\n      console.error(chalk.red('✗ --org <orgId> is required'));\n      console.error(chalk.gray('  The token is bound to one org; this must be that org.'));\n      process.exit(1);\n    }\n\n    const key = sessionCrypto.generateKey();\n    const { joinKeyHash } = await sessionCrypto.deriveJoinCredentials(key);\n\n    const base = options.url.replace(/\\/+$/, '');\n    const res = await fetch(`${base}/api/sessions/shared`, {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${options.token}` },\n      body: JSON.stringify({\n        orgId: options.org,\n        title,\n        joinKeyHash,\n        ...(options.issue ? { linearIdentifier: options.issue } : {}),\n      }),\n    });\n\n    if (!res.ok) {\n      const body = await res.json().catch(() => null);\n      console.error(chalk.red(`✗ Could not create session (${res.status})`));\n      // formatApiError renders the §5.4 envelope, so the user sees the server's\n      // actual reason rather than a bare \"Bad Request\".\n      console.error(chalk.gray(`  ${formatApiError(body, res.statusText)}`));\n      process.exit(1);\n    }\n\n    const { session } = (await res.json()) as { session: { id: string; title: string } };\n    const link = buildJoinLink(base, session.id, key);\n\n    console.log('');\n    console.log(chalk.cyan(`  ${session.title}`));\n    console.log(chalk.bold(`  ${link}`));\n    console.log('');\n    // §3.4 requires this AT COPY TIME, not in a footnote. The link is the\n    // credential: there is no second factor and no per-person access list.\n    console.log(chalk.yellow('  Anyone with this link can read the whole transcript.'));\n    console.log(chalk.gray('  It carries the encryption key after the #, which never reaches'));\n    console.log(chalk.gray('  devpilot.sh. Send it the way you would send a password — not to'));\n    console.log(chalk.gray('  a public channel. To revoke it, re-key the session; that ends'));\n    console.log(chalk.gray('  access for this link but cannot un-send what was already read.'));\n    console.log('');\n    console.log(chalk.gray(`  Others join with:  devpilot session join \"${chalk.italic('<link>')}\"`));\n    console.log('');\n  });\n","import os from 'os';\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport { SharedSessionClient } from '@devpilot.sh/bridge-client';\n\n/**\n * `devpilot session join <url>` — TRD 06 §6.3.\n *\n * Joins, posts an optional opening message, and prints the roster. For a live\n * view use `devpilot session tail`.\n */\nexport const joinCommand = new Command('join')\n  .description('Join a shared session by link and post a message')\n  .argument('<url>', 'Join link, including the #k=… fragment')\n  .option('-n, --name <name>', 'Display name in the transcript', os.hostname())\n  .option('-m, --message <text>', 'Post this message after joining')\n  .action(async (url: string, options: { name: string; message?: string }) => {\n    try {\n      const client = await SharedSessionClient.join({ link: url, displayName: options.name });\n      const s = client.session;\n\n      console.log(chalk.cyan(`\\n  ${s.title}`));\n      console.log(chalk.gray(`  mode: ${s.mode}  ·  messages: ${s.lastSeq ?? 0}\\n`));\n\n      if (options.message) {\n        const posted = await client.post(options.message);\n        console.log(chalk.green(`  posted #${posted.seq}\\n`));\n      }\n\n      const participants = await client.who();\n      for (const p of participants) {\n        const agent = p.agentKind ? chalk.gray(` [${p.agentKind}]`) : '';\n        console.log(`  · ${p.displayName}${agent}${p.leftAt ? chalk.gray(' (left)') : ''}`);\n      }\n      console.log('');\n    } catch (err) {\n      // Never echo the link back: it contains the key, and shell history and\n      // terminal recordings both outlive the session.\n      console.error(chalk.red(`✗ ${err instanceof Error ? err.message : String(err)}`));\n      process.exit(1);\n    }\n  });\n","import os from 'os';\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport { SharedSessionClient, type TranscriptEntry } from '@devpilot.sh/bridge-client';\n\n/**\n * `devpilot session tail <url>` — TRD 06 §6.3.\n *\n * Polls for new messages by `seq` and decrypts locally.\n *\n * POLLING, not Realtime, and that is not a stopgap: TRD 05 established that the\n * durable table is the delivery guarantee and Realtime is a latency\n * optimisation. `?since=<seq>` cannot miss a message or deliver one twice,\n * which a dropped websocket can. Realtime for session_messages was\n * deliberately not wired in Wave 2 and has never connected in this project.\n */\nexport const tailCommand = new Command('tail')\n  .description('Follow a shared session transcript in the terminal')\n  .argument('<url>', 'Join link, including the #k=… fragment')\n  .option('-n, --name <name>', 'Display name in the transcript', os.hostname())\n  .option('-i, --interval <seconds>', 'Poll interval', '3')\n  .action(async (url: string, options: { name: string; interval: string }) => {\n    const intervalMs = Math.max(1, parseInt(options.interval, 10) || 3) * 1000;\n\n    let client: SharedSessionClient;\n    try {\n      client = await SharedSessionClient.join({ link: url, displayName: options.name });\n    } catch (err) {\n      console.error(chalk.red(`✗ ${err instanceof Error ? err.message : String(err)}`));\n      process.exit(1);\n      return;\n    }\n\n    const names = new Map<string, string>();\n    for (const p of await client.who()) names.set(p.id, p.displayName);\n\n    console.log(chalk.cyan(`\\n  ${client.session.title}`));\n    console.log(chalk.gray(`  following · ctrl-c to stop\\n`));\n\n    let cursor = 0;\n    let stopped = false;\n    process.on('SIGINT', () => {\n      stopped = true;\n      console.log(chalk.gray('\\n  stopped\\n'));\n      process.exit(0);\n    });\n\n    while (!stopped) {\n      try {\n        const { entries, latestSeq } = await client.read(cursor);\n\n        if (entries.length > 0) {\n          // Refresh names only when someone unknown appears, rather than every\n          // tick: the roster is a second request and this loop runs forever.\n          if (entries.some((e) => e.participantId && !names.has(e.participantId))) {\n            for (const p of await client.who()) names.set(p.id, p.displayName);\n          }\n          for (const e of entries) console.log(format(e, names));\n          cursor = latestSeq;\n        }\n      } catch (err) {\n        // Keep following. A transient network failure must not end a tail the\n        // user left running — the seq cursor means nothing is missed on resume.\n        console.error(chalk.gray(`  … ${err instanceof Error ? err.message : String(err)}`));\n      }\n\n      await new Promise((r) => setTimeout(r, intervalMs));\n    }\n  });\n\nfunction format(e: TranscriptEntry, names: Map<string, string>): string {\n  const who = e.participantId ? (names.get(e.participantId) ?? e.participantId) : 'system';\n  const seq = chalk.gray(`#${String(e.seq).padStart(3)}`);\n\n  if (e.status === 'system') {\n    const reason = e.systemNotice?.reason ? ` (${e.systemNotice.reason})` : '';\n    return `  ${seq} ${chalk.yellow(`⚙ ${e.systemNotice?.type ?? e.text}${reason}`)}`;\n  }\n  if (e.status === 'undecryptable') {\n    // Shown, not skipped. A transcript with silent holes is worse than one with\n    // visible ones — the reader would not know to go looking.\n    return `  ${seq} ${chalk.gray(`${who}: <sealed under an earlier key — not readable with this link>`)}`;\n  }\n  return `  ${seq} ${chalk.bold(who)}: ${e.text}`;\n}\n","import os from 'os';\nimport { homedir } from 'node:os';\nimport { join, dirname } from 'node:path';\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport inquirer from 'inquirer';\nimport { BridgeClient } from '@devpilot.sh/bridge-client';\nimport type { AdoptionOutcome } from '@devpilot.sh/bridge-protocol';\nimport {\n  parseDuration,\n  renderPreview,\n  runScanPipeline,\n  type PipelineResult,\n  type PreviewRow,\n} from './scan-pipeline';\n\n/**\n * `devpilot sessions scan` / `devpilot sessions adopt` — TRD 21 §6.5.\n *\n * The user-facing half of adoption. `scan` is read-only; `adopt` writes, after\n * showing the same table and asking.\n *\n * ## Why `scan` still reaches the network\n *\n * It calls the adoption route with `dryRun: true` rather than guessing locally\n * what would happen. Duplicate detection, routing, and issue matching are all\n * server-side facts; a local approximation of them would eventually disagree\n * with the real thing, and a preview that disagrees with what follows it is\n * worse than no preview.\n *\n * With no credentials, `scan` degrades to a purely local listing and says so.\n */\n\ninterface CommonOptions {\n  url?: string;\n  token?: string;\n  name?: string;\n  repos?: string;\n  allRepos?: boolean;\n  repo?: string;\n  since: string;\n  paths: boolean;\n  maxSummaries: string;\n  json?: boolean;\n}\n\ninterface AdoptOptions extends CommonOptions {\n  yes?: boolean;\n}\n\n/** Mirrors `bridge connect`'s stable name so both agree on the adoption key. */\nfunction stableMachineName(): string {\n  const path = join(homedir(), '.devpilot', 'machine.json');\n  try {\n    if (existsSync(path)) {\n      const saved = JSON.parse(readFileSync(path, 'utf8')) as { name?: string };\n      if (saved.name) return saved.name;\n    }\n  } catch {\n    // A corrupt file must not stop a scan; fall through and rewrite it.\n  }\n  const name = os.hostname();\n  try {\n    mkdirSync(dirname(path), { recursive: true });\n    writeFileSync(path, JSON.stringify({ name }, null, 2), 'utf8');\n  } catch {\n    // Unwritable home: correct for this run, just not remembered.\n  }\n  return name;\n}\n\nfunction withCommonOptions(command: Command): Command {\n  return command\n    .option('-u, --url <url>', 'Bridge URL', process.env.DEVPILOT_BRIDGE_URL)\n    .option('-t, --token <token>', 'Orchestrator token (dp_orch_…)', process.env.DEVPILOT_BRIDGE_TOKEN)\n    .option('-n, --name <name>', 'Machine name (defaults to this machine’s stable name)')\n    .option('-r, --repos <repos>', 'Comma-separated repos this machine handles')\n    .option(\n      '--all-repos',\n      'Include every repo found on this machine, not only the ones it routes',\n      false,\n    )\n    .option('--repo <owner/name>', 'Restrict to a single repo')\n    .option('--since <duration>', 'How far back to look (e.g. 24h, 3d)', '24h')\n    .option('--no-paths', 'Do not send the paths of changed files')\n    .option('--max-summaries <n>', 'Cap on model-written titles', '25')\n    .option('--json', 'Machine-readable output');\n}\n\nasync function pipeline(options: CommonOptions): Promise<{\n  machineName: string;\n  result: PipelineResult;\n}> {\n  const machineName = options.name ?? stableMachineName();\n  const result = await runScanPipeline({\n    machineName,\n    repos: options.repos?.split(',').map((r) => r.trim()).filter(Boolean) ?? [],\n    allRepos: Boolean(options.allRepos),\n    onlyRepo: options.repo,\n    sinceMs: parseDuration(options.since, 24 * 60 * 60 * 1000),\n    includePaths: options.paths !== false,\n    maxSummaries: Math.max(0, parseInt(options.maxSummaries, 10) || 25),\n    summarize: true,\n    onWarn: (message) => {\n      if (!options.json) console.log(chalk.gray(`   ${message}`));\n    },\n  });\n  return { machineName, result };\n}\n\n/** The `→ BOARD` column, from the server's own answer. */\nfunction destinationFor(outcome: AdoptionOutcome | undefined): string {\n  if (!outcome) return chalk.gray('—');\n  switch (outcome.status) {\n    case 'duplicate':\n      return chalk.gray(`${outcome.linearIdentifier ?? 'already adopted'} (tracked)`);\n    case 'attached':\n      return chalk.green(`${outcome.linearIdentifier} (${outcome.matchedBy})`);\n    case 'adopted':\n      return outcome.linearIdentifier\n        ? chalk.green(outcome.linearIdentifier)\n        : chalk.yellow('create');\n    case 'skipped':\n      return chalk.yellow(outcome.reason ? `skip — ${outcome.reason.slice(0, 60)}` : 'skip');\n  }\n}\n\nfunction rowsFrom(result: PipelineResult, outcomes: AdoptionOutcome[]): PreviewRow[] {\n  const byKey = new Map(outcomes.map((o) => [o.adoptionKey, o]));\n  return result.candidates.map((candidate) => ({\n    repo: candidate.repo,\n    title: candidate.title,\n    lastActivityAt: candidate.lastActivityAt,\n    live: candidate.live,\n    destination: destinationFor(byKey.get(candidate.adoptionKey)),\n  }));\n}\n\nfunction client(options: CommonOptions): BridgeClient | null {\n  if (!options.url || !options.token) return null;\n  return new BridgeClient({ bridgeUrl: options.url, token: options.token });\n}\n\n// ---------------------------------------------------------------------------\n\nexport const scanCommand = withCommonOptions(\n  new Command('scan').description(\n    'List agent sessions on this machine and what adopting them would do. Writes nothing.',\n  ),\n).action(async (options: CommonOptions) => {\n  const { machineName, result } = await pipeline(options);\n\n  let outcomes: AdoptionOutcome[] = [];\n  const bridge = client(options);\n\n  if (bridge && result.candidates.length > 0) {\n    try {\n      const response = await bridge.adoptSessions({\n        machineName,\n        candidates: result.candidates,\n        dryRun: true,\n      });\n      outcomes = response.outcomes;\n    } catch (err) {\n      if (!options.json) {\n        console.log(chalk.yellow(`   Could not preview against the bridge: ${describe(err)}`));\n        console.log(chalk.gray('   Showing the local scan only.'));\n      }\n    }\n  }\n\n  if (options.json) {\n    console.log(\n      JSON.stringify(\n        {\n          machineName,\n          candidates: result.candidates,\n          discovered: result.discovered,\n          outcomes,\n          skipped: result.skipped,\n          unmappedProjectCount: result.unmappedProjectCount,\n        },\n        null,\n        2,\n      ),\n    );\n    return;\n  }\n\n  console.log('');\n  console.log(renderPreview(rowsFrom(result, outcomes), result));\n  console.log('');\n\n  if (!bridge) {\n    console.log(\n      chalk.gray(\n        '  No bridge credentials, so this is a local listing only. Pass --url and --token',\n      ),\n    );\n    console.log(chalk.gray('  to see which Linear issues these would attach to.'));\n  } else if (result.candidates.length > 0) {\n    console.log(chalk.gray('  Nothing was written. Run `devpilot sessions adopt` to act on this.'));\n  }\n  console.log('');\n});\n\nexport const adoptCommand = withCommonOptions(\n  new Command('adopt').description('Put agent sessions running on this machine onto the board'),\n)\n  .option('-y, --yes', 'Skip the confirmation')\n  .action(async (options: AdoptOptions) => {\n    const bridge = client(options);\n    if (!bridge) {\n      console.error(chalk.red('✗ Bridge URL and token required (--url / --token)'));\n      console.error(chalk.gray('  Mint a token in the dashboard under Settings → Tokens.'));\n      process.exit(1);\n    }\n\n    const { machineName, result } = await pipeline(options);\n\n    if (result.candidates.length === 0) {\n      console.log('');\n      console.log(renderPreview([], result));\n      console.log('');\n      console.log(chalk.gray('  No sessions to adopt.'));\n      console.log('');\n      return;\n    }\n\n    /**\n     * Preview first, always — TRD 21 §6.5.\n     *\n     * This is a real request, not a local guess, so the identifiers printed\n     * below are the ones adoption will use. `--yes` skips the QUESTION; it does\n     * not skip the preview, because a log of what happened is worth as much\n     * afterwards as the confirmation was beforehand.\n     */\n    let preview;\n    try {\n      preview = await bridge.adoptSessions({\n        machineName,\n        candidates: result.candidates,\n        dryRun: true,\n      });\n    } catch (err) {\n      console.error(chalk.red(`✗ ${describe(err)}`));\n      process.exit(1);\n    }\n\n    console.log('');\n    console.log(renderPreview(rowsFrom(result, preview.outcomes), result));\n    console.log('');\n\n    const willCreate = preview.outcomes.filter((o) => o.status === 'adopted').length;\n    const willAttach = preview.outcomes.filter((o) => o.status === 'attached').length;\n\n    if (willCreate === 0 && willAttach === 0) {\n      console.log(chalk.gray('  Nothing new to adopt — everything here is already tracked.'));\n      console.log('');\n      return;\n    }\n\n    console.log(\n      `  This creates ${chalk.bold(String(willCreate))} Linear issue${\n        willCreate === 1 ? '' : 's'\n      } and attaches ${chalk.bold(String(willAttach))} existing.`,\n    );\n    console.log('');\n\n    if (!options.yes) {\n      const { proceed } = await inquirer.prompt<{ proceed: boolean }>([\n        { type: 'confirm', name: 'proceed', message: 'Continue?', default: false },\n      ]);\n      if (!proceed) {\n        console.log(chalk.gray('  Nothing was written.'));\n        return;\n      }\n    }\n\n    let response;\n    try {\n      response = await bridge.adoptSessions({\n        machineName,\n        candidates: result.candidates,\n        dryRun: false,\n      });\n    } catch (err) {\n      console.error(chalk.red(`✗ ${describe(err)}`));\n      process.exit(1);\n    }\n\n    console.log('');\n    for (const outcome of response.outcomes) {\n      if (outcome.status === 'skipped') {\n        console.log(chalk.yellow(`   ○ skipped — ${outcome.reason ?? 'no reason given'}`));\n      } else if (outcome.status === 'duplicate') {\n        console.log(chalk.gray(`   · ${outcome.linearIdentifier ?? '?'} already tracked`));\n      } else {\n        console.log(\n          chalk.green(\n            `   ✓ ${outcome.linearIdentifier}${\n              outcome.status === 'attached' ? ` (attached, ${outcome.matchedBy})` : ''\n            }`,\n          ),\n        );\n      }\n    }\n\n    console.log('');\n    console.log(\n      chalk.green(\n        `✓ ${response.adopted} adopted, ${response.attached} attached, ` +\n          `${response.duplicates} already tracked, ${response.skipped} skipped`,\n      ),\n    );\n    console.log(\n      chalk.gray(\n        '  These are observed, not dispatched: DevPilot is watching them and will not move a ticket.',\n      ),\n    );\n    console.log('');\n  });\n\nfunction describe(err: unknown): string {\n  return err instanceof Error ? err.message : String(err);\n}\n\nexport const sessionsCommand = new Command('sessions')\n  .description('Agent sessions running on this machine')\n  .addCommand(scanCommand)\n  .addCommand(adoptCommand);\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { resolve } from 'path';\nimport { SessionRunner } from './server';\nimport type { RunnerConfig } from './types';\n\nexport { SessionRunner } from './server';\nexport type { RunnerConfig } from './types';\n\n/**\n * `devpilot session-runner` — the local execution engine for `claude-session`\n * orchestrator mode (TRD-01 §7.1).\n *\n * Run it beside `devpilot serve`:\n *\n *   devpilot session-runner --workspace ~/dev --token dp_local_dev\n *   DEVPILOT_ORCHESTRATOR_MODE=claude-session \\\n *   DEVPILOT_SESSION_API_URL=http://127.0.0.1:3900 \\\n *   DEVPILOT_SESSION_API_KEY=dp_local_dev \\\n *   devpilot serve\n */\nfunction parseRepoMap(values: string[]): Map<string, string> {\n  const map = new Map<string, string>();\n  for (const entry of values) {\n    const idx = entry.indexOf('=');\n    if (idx === -1) {\n      throw new Error(`--repo expects <repo>=<path>, got '${entry}'`);\n    }\n    map.set(entry.slice(0, idx).trim(), resolve(entry.slice(idx + 1).trim()));\n  }\n  return map;\n}\n\nexport const sessionRunnerCommand = new Command('session-runner')\n  .description('Run Claude Code sessions dispatched by DevPilot (claude-session mode)')\n  .option('-p, --port <port>', 'Port to listen on', '3900')\n  .option('--host <host>', 'Interface to bind', '127.0.0.1')\n  .option('--token <token>', 'Bearer token the dispatcher must present')\n  .option('-w, --workspace <dir>', 'Directory containing repo checkouts', process.cwd())\n  .option(\n    '--repo <mapping>',\n    'Explicit repo mapping, <owner/name>=<path> (repeatable)',\n    (value: string, previous: string[]) => [...previous, value],\n    [] as string[]\n  )\n  .option('--claude-path <path>', 'Path to the claude executable', 'claude')\n  .option(\n    '--permission-mode <mode>',\n    'claude --permission-mode (acceptEdits | bypassPermissions | plan)',\n    'acceptEdits'\n  )\n  .option('--max-concurrent <n>', 'Max simultaneous sessions before answering 429', '3')\n  .option('--timeout <minutes>', 'Wall-clock cap per session', '30')\n  .action(async (options) => {\n    let repoMap: Map<string, string>;\n    try {\n      repoMap = parseRepoMap(options.repo ?? []);\n    } catch (error) {\n      console.error(chalk.red(error instanceof Error ? error.message : String(error)));\n      process.exitCode = 1;\n      return;\n    }\n\n    const config: RunnerConfig = {\n      port: parseInt(options.port, 10),\n      host: options.host,\n      apiKey: options.token ?? process.env.DEVPILOT_SESSION_API_KEY,\n      workspace: resolve(options.workspace),\n      repoMap,\n      claudePath: options.claudePath,\n      permissionMode: options.permissionMode,\n      maxConcurrent: parseInt(options.maxConcurrent, 10),\n      timeoutMs: parseInt(options.timeout, 10) * 60_000,\n      log: (line) => console.log(chalk.dim(`[runner] ${line}`)),\n    };\n\n    const runner = new SessionRunner(config);\n\n    try {\n      await runner.start();\n    } catch (error) {\n      const message = error instanceof Error ? error.message : String(error);\n      console.error(chalk.red(`Failed to start session runner: ${message}`));\n      process.exitCode = 1;\n      return;\n    }\n\n    const base = `http://${config.host}:${config.port}`;\n    console.log(chalk.bold('\\n  DevPilot session runner\\n'));\n    console.log(`  ${chalk.dim('listening')}   ${base}`);\n    console.log(`  ${chalk.dim('workspace')}   ${config.workspace}`);\n    console.log(`  ${chalk.dim('claude')}      ${config.claudePath} (${config.permissionMode})`);\n    console.log(`  ${chalk.dim('concurrency')} ${config.maxConcurrent}`);\n    if (repoMap.size > 0) {\n      for (const [repo, path] of repoMap) console.log(`  ${chalk.dim('repo')}        ${repo} → ${path}`);\n    }\n    if (!config.apiKey) {\n      console.log(chalk.yellow('\\n  No --token set: the dispatcher API is unauthenticated.'));\n    }\n    console.log(chalk.dim('\\n  Point DevPilot at it:'));\n    console.log(\n      chalk.dim(\n        `    DEVPILOT_ORCHESTRATOR_MODE=claude-session DEVPILOT_SESSION_API_URL=${base} devpilot serve\\n`\n      )\n    );\n\n    const shutdown = async () => {\n      console.log(chalk.dim('\\n[runner] shutting down…'));\n      await runner.stop();\n      process.exit(0);\n    };\n    process.on('SIGINT', shutdown);\n    process.on('SIGTERM', shutdown);\n  });\n","import { createServer, type IncomingMessage, type Server, type ServerResponse } from 'http';\nimport { randomUUID } from 'crypto';\nimport { existsSync } from 'fs';\nimport { basename, isAbsolute, resolve } from 'path';\nimport { runClaudeSession } from './claude-runner';\nimport { sendCompletion, sendStatus } from './callbacks';\nimport { describeActivity, estimateProgress, type SessionTelemetry } from './stream-events';\nimport type {\n  CreateSessionRequest,\n  RunnerConfig,\n  RunnerSession,\n  StatusUpdate,\n} from './types';\n\n/**\n * The local session runner — the dispatcher API from\n * `spec/trd/01-TIER1-EXECUTION-LOOP.md` §7.1.\n *\n * This is the piece that was missing. `ClaudeSessionAdapter` and its\n * `HttpSessionTransport` were built, and so were DevPilot's `/api/orchestrator/*`\n * callback routes — but nothing implemented the service in between, so\n * `claude-session` mode had no runner to point `DEVPILOT_SESSION_API_URL` at and\n * could never dispatch. Every other orchestrator mode is either deprecated\n * (`ao-cli`), speaks a contract nothing local implements (`http` against the ao\n * daemon), or is `disabled`.\n *\n * Deliberately `node:http` and no framework: it runs on a conductor's laptop\n * next to `devpilot serve`, and a dependency-free daemon is one less thing to\n * break at install time.\n */\n\nconst VERSION = '1.0.0';\n\nfunction json(res: ServerResponse, status: number, body: unknown): void {\n  const payload = JSON.stringify(body);\n  res.writeHead(status, {\n    'Content-Type': 'application/json',\n    'Content-Length': Buffer.byteLength(payload),\n  });\n  res.end(payload);\n}\n\nasync function readBody(req: IncomingMessage): Promise<unknown> {\n  const chunks: Buffer[] = [];\n  let bytes = 0;\n  for await (const chunk of req) {\n    bytes += (chunk as Buffer).length;\n    // A composed prompt is large but bounded. Refuse rather than buffer forever.\n    if (bytes > 8 * 1024 * 1024) throw new Error('PAYLOAD_TOO_LARGE');\n    chunks.push(chunk as Buffer);\n  }\n  if (chunks.length === 0) return {};\n  return JSON.parse(Buffer.concat(chunks).toString('utf8'));\n}\n\nexport class SessionRunner {\n  /** Keyed by runner-side externalSessionId. */\n  private readonly sessions = new Map<string, RunnerSession>();\n  /** DevPilot sessionId -> externalSessionId. The §7.1 idempotency index. */\n  private readonly byDevpilotId = new Map<string, string>();\n  private server: Server | null = null;\n\n  constructor(private readonly config: RunnerConfig) {}\n\n  private get activeCount(): number {\n    let n = 0;\n    for (const session of this.sessions.values()) {\n      if (session.status === 'queued' || session.status === 'running') n++;\n    }\n    return n;\n  }\n\n  /**\n   * Resolve `owner/name` to a checkout on this machine.\n   *\n   * Explicit `--repo` mappings win; otherwise the repo's basename is looked up\n   * under `--workspace`. A repo that resolves nowhere is rejected at create\n   * time with a message naming the path it tried, because the alternative —\n   * spawning the agent in the wrong directory — produces a session that edits\n   * unrelated files and reports success.\n   */\n  private resolveWorkdir(repo: string): { workdir?: string; error?: string } {\n    const mapped = this.config.repoMap.get(repo);\n    if (mapped) {\n      return existsSync(mapped)\n        ? { workdir: mapped }\n        : { error: `Mapped path for '${repo}' does not exist: ${mapped}` };\n    }\n\n    const candidate = isAbsolute(repo)\n      ? repo\n      : resolve(this.config.workspace, basename(repo));\n\n    if (!existsSync(candidate)) {\n      return {\n        error:\n          `No checkout for '${repo}'. Tried ${candidate}. ` +\n          `Pass --repo ${repo}=/path/to/checkout, or set --workspace.`,\n      };\n    }\n    return { workdir: candidate };\n  }\n\n  private authorized(req: IncomingMessage): boolean {\n    if (!this.config.apiKey) return true;\n    return req.headers.authorization === `Bearer ${this.config.apiKey}`;\n  }\n\n  /** Fire-and-forget status callback; delivery failures are logged, not thrown. */\n  private reportStatus(\n    session: RunnerSession,\n    callbackUrl: string,\n    callbackToken: string | undefined,\n    patch: Partial<StatusUpdate>\n  ): void {\n    const update: StatusUpdate = {\n      sessionId: session.devpilotSessionId,\n      status: session.status,\n      progressPercent: session.progressPercent,\n      filesModified: session.filesModified,\n      tokensUsed: session.tokensUsed,\n      timestamp: new Date().toISOString(),\n      ...patch,\n    };\n    void sendStatus(callbackUrl, update, callbackToken, this.config.log);\n  }\n\n  /**\n   * Run a session to completion and report. Never rejects: a throw here would be\n   * an unhandled rejection in a detached promise, and — worse — would leave the\n   * wave task stuck on `dispatched` with no completion callback ever sent.\n   */\n  private async execute(session: RunnerSession, request: CreateSessionRequest): Promise<void> {\n    const { callbackUrl, callbackToken } = request;\n\n    try {\n      session.status = 'running';\n      session.progressPercent = 5;\n      session.currentStep = 'session started';\n      this.reportStatus(session, callbackUrl, callbackToken, {\n        currentStep: 'session started',\n        message: `Claude Code session running in ${session.workdir}`,\n      });\n\n      /**\n       * The heartbeat is now a floor, not the signal.\n       *\n       * It used to BE the progress: five percent every ninety seconds, capped\n       * at ninety, because `claude -p` said nothing until it exited. Agents sat\n       * at 0% for ten minutes and then snapped to 100%, and elapsed read 0m\n       * against a real 5.76m. With `stream-json` the telemetry below carries\n       * the actual picture; this only guarantees §7.2's two-minute liveness\n       * requirement when an agent is genuinely quiet (a long Bash step, say).\n       */\n      const heartbeat = setInterval(() => {\n        if (session.terminal) return;\n        this.reportStatus(session, callbackUrl, callbackToken, {\n          currentStep: session.currentStep ?? 'working',\n          message: session.message ?? 'Session in progress',\n        });\n      }, 90_000);\n      heartbeat.unref();\n\n      /**\n       * Throttled so the instrument does not become the load. A busy agent\n       * emits tool calls faster than anyone can read them, and every report is\n       * an HTTP round trip plus a database write on the other end.\n       */\n      let lastReportAt = 0;\n      const REPORT_INTERVAL_MS = 3_000;\n\n      const outcome = await runClaudeSession({\n        workdir: session.workdir,\n        prompt: request.prompt,\n        sessionLink: request.sessionLink,\n        model: request.model,\n        claudePath: this.config.claudePath,\n        /**\n         * Permission mode is the OPERATOR's, never the caller's — TRD 23 S-04.\n         *\n         * A request that could raise it would let someone in the cockpit\n         * escalate what an agent may do on another person's laptop. It stays\n         * with whoever started the bridge.\n         */\n        permissionMode: this.config.permissionMode,\n        resumeSessionId: request.resumeSessionId,\n        timeoutMs: this.config.timeoutMs,\n        onLog: (line) => this.config.log(`[${session.externalSessionId}] ${line}`),\n        onSpawn: (kill) => {\n          session.kill = kill;\n        },\n        onTelemetry: (telemetry) => {\n          session.telemetry = telemetry;\n          session.currentStep = describeActivity(telemetry);\n          session.progressPercent = estimateProgress(telemetry, request.filePaths ?? []);\n\n          const now = Date.now();\n          if (now - lastReportAt < REPORT_INTERVAL_MS) return;\n          lastReportAt = now;\n\n          this.reportStatus(session, callbackUrl, callbackToken, {\n            currentStep: session.currentStep,\n            message: telemetry.lastText ?? `${telemetry.toolCalls} tool calls`,\n            filesModified: telemetry.filesTouched,\n            tokensUsed: telemetry.tokensIn + telemetry.tokensOut,\n            telemetry,\n          });\n        },\n      });\n\n      clearInterval(heartbeat);\n\n      session.terminal = true;\n      session.status = outcome.success ? 'complete' : 'error';\n      session.progressPercent = outcome.success ? 100 : session.progressPercent;\n      session.currentStep = outcome.success ? 'complete' : 'failed';\n      session.filesModified = outcome.filesModified;\n      session.tokensUsed = outcome.tokensUsed;\n      session.message = outcome.summary;\n\n      this.config.log(\n        `[${session.externalSessionId}] ${outcome.success ? 'complete' : 'FAILED'} — ` +\n          `${outcome.filesModified.length} modified, ${outcome.filesCreated.length} created, ` +\n          `$${outcome.costUsd.toFixed(4)}, ${outcome.durationMinutes}m`\n      );\n\n      await sendCompletion(\n        callbackUrl,\n        {\n          sessionId: session.devpilotSessionId,\n          success: outcome.success,\n          commitSha: outcome.commitSha,\n          filesModified: outcome.filesModified,\n          filesCreated: outcome.filesCreated,\n          filesDeleted: outcome.filesDeleted,\n          summary: outcome.summary,\n          tokensUsed: outcome.tokensUsed,\n          costUsd: outcome.costUsd,\n          durationMinutes: outcome.durationMinutes,\n          error: outcome.error,\n          metadata: request.metadata,\n        },\n        callbackToken,\n        this.config.log\n      );\n    } catch (error) {\n      const message = error instanceof Error ? error.message : String(error);\n      this.config.log(`[${session.externalSessionId}] runner error: ${message}`);\n\n      session.terminal = true;\n      session.status = 'error';\n\n      // Still report. A wave task with no completion callback is stuck forever.\n      await sendCompletion(\n        callbackUrl,\n        {\n          sessionId: session.devpilotSessionId,\n          success: false,\n          filesModified: [],\n          filesCreated: [],\n          filesDeleted: [],\n          summary: 'The session runner failed before the agent could report.',\n          tokensUsed: 0,\n          costUsd: 0,\n          durationMinutes: (Date.now() - session.startedAt) / 60_000,\n          error: message,\n          metadata: request.metadata,\n        },\n        callbackToken,\n        this.config.log\n      ).catch(() => undefined);\n    }\n  }\n\n  private async handleCreate(req: IncomingMessage, res: ServerResponse): Promise<void> {\n    let body: CreateSessionRequest;\n    try {\n      body = (await readBody(req)) as CreateSessionRequest;\n    } catch (error) {\n      const message = error instanceof Error ? error.message : 'invalid JSON';\n      return json(res, 400, { error: 'INVALID_PAYLOAD', message });\n    }\n\n    if (!body?.sessionId || !body?.repo || !body?.prompt || !body?.callbackUrl) {\n      return json(res, 400, {\n        error: 'INVALID_PAYLOAD',\n        message: 'sessionId, repo, prompt and callbackUrl are required',\n      });\n    }\n\n    // §7.1 idempotency: re-POSTing a sessionId must not start a second agent.\n    // Returns 200 with the existing id — a duplicate dispatch after a DevPilot\n    // restart is normal, not an error.\n    const existing = this.byDevpilotId.get(body.sessionId);\n    if (existing) {\n      const session = this.sessions.get(existing);\n      return json(res, 200, {\n        externalSessionId: existing,\n        status: session?.status ?? 'running',\n        createdAt: session?.createdAt,\n        idempotent: true,\n      });\n    }\n\n    if (this.activeCount >= this.config.maxConcurrent) {\n      return json(res, 429, { error: 'CAPACITY', retryAfterSeconds: 60 });\n    }\n\n    const { workdir, error } = this.resolveWorkdir(body.repo);\n    if (!workdir) {\n      this.config.log(`create rejected: ${error}`);\n      return json(res, 400, { error: 'REPO_NOT_FOUND', message: error });\n    }\n\n    const externalSessionId = `run_${randomUUID()}`;\n    const session: RunnerSession = {\n      externalSessionId,\n      devpilotSessionId: body.sessionId,\n      repo: body.repo,\n      workdir,\n      status: 'queued',\n      progressPercent: 0,\n      filesModified: [],\n      tokensUsed: 0,\n      startedAt: Date.now(),\n      createdAt: new Date().toISOString(),\n      terminal: false,\n    };\n\n    this.sessions.set(externalSessionId, session);\n    this.byDevpilotId.set(body.sessionId, externalSessionId);\n\n    // Logs that a shared session is attached, NEVER the link — it carries the\n    // session key and runner logs are routinely pasted into bug reports.\n    this.config.log(\n      `dispatch ${body.sessionId} -> ${externalSessionId} (${body.repo} @ ${workdir}, ` +\n        `model=${body.model ?? 'default'}${body.sessionLink ? ', shared-session' : ''})`\n    );\n\n    // Respond before the agent runs. §7.1 is create-and-return; the adapter\n    // treats 201 as accepted and waits for callbacks.\n    json(res, 201, { externalSessionId, status: 'queued', createdAt: session.createdAt });\n\n    void this.execute(session, body);\n  }\n\n  private handleGet(res: ServerResponse, externalSessionId: string): void {\n    const session = this.sessions.get(externalSessionId);\n    if (!session) return json(res, 404, { error: 'NOT_FOUND' });\n\n    json(res, 200, {\n      status: session.status,\n      progressPercent: session.progressPercent,\n      currentStep: session.currentStep,\n      message: session.message,\n      filesModified: session.filesModified,\n      tokensUsed: session.tokensUsed,\n    });\n  }\n\n  private async handleMessages(\n    req: IncomingMessage,\n    res: ServerResponse,\n    externalSessionId: string\n  ): Promise<void> {\n    const session = this.sessions.get(externalSessionId);\n    if (!session) return json(res, 404, { error: 'NOT_FOUND' });\n    if (session.terminal) return json(res, 410, { error: 'TERMINAL' });\n\n    // `claude -p` is one-shot: it reads a prompt on stdin and exits. There is no\n    // channel to steer a run already in flight, so this reports honestly rather\n    // than accepting the message and dropping it. Steering needs the streaming\n    // input mode (`--input-format stream-json`), which is a separate change.\n    await readBody(req).catch(() => ({}));\n    json(res, 501, {\n      error: 'NOT_IMPLEMENTED',\n      message: 'Mid-session steering requires streaming input mode; not supported by this runner.',\n    });\n  }\n\n  private handleStop(res: ServerResponse, externalSessionId: string): void {\n    const session = this.sessions.get(externalSessionId);\n    if (!session) return json(res, 404, { error: 'NOT_FOUND' });\n    if (session.terminal) return json(res, 410, { success: true, message: 'already stopped' });\n\n    session.kill?.();\n    this.config.log(`stop requested for ${externalSessionId}`);\n    json(res, 202, { success: true, message: 'stopping' });\n  }\n\n  private async route(req: IncomingMessage, res: ServerResponse): Promise<void> {\n    const url = new URL(req.url ?? '/', `http://${req.headers.host ?? 'localhost'}`);\n    const path = url.pathname;\n\n    if (path === '/v1/health' && req.method === 'GET') {\n      return json(res, 200, {\n        status: 'healthy',\n        version: VERSION,\n        activeSessions: this.activeCount,\n      });\n    }\n\n    if (!this.authorized(req)) return json(res, 401, { error: 'UNAUTHORIZED' });\n\n    if (path === '/v1/sessions' && req.method === 'POST') {\n      return this.handleCreate(req, res);\n    }\n\n    const match = path.match(/^\\/v1\\/sessions\\/([^/]+)(\\/messages|\\/stop)?$/);\n    if (match) {\n      const [, id, suffix] = match;\n      if (!suffix && req.method === 'GET') return this.handleGet(res, id);\n      if (suffix === '/messages' && req.method === 'POST') return this.handleMessages(req, res, id);\n      if (suffix === '/stop' && req.method === 'POST') return this.handleStop(res, id);\n      return json(res, 405, { error: 'METHOD_NOT_ALLOWED' });\n    }\n\n    json(res, 404, { error: 'NOT_FOUND' });\n  }\n\n  start(): Promise<void> {\n    return new Promise((resolvePromise, reject) => {\n      this.server = createServer((req, res) => {\n        this.route(req, res).catch((error) => {\n          const message = error instanceof Error ? error.message : String(error);\n          this.config.log(`unhandled: ${message}`);\n          if (!res.headersSent) json(res, 500, { error: 'INTERNAL', message });\n        });\n      });\n\n      this.server.on('error', reject);\n      this.server.listen(this.config.port, this.config.host, () => resolvePromise());\n    });\n  }\n\n  async stop(): Promise<void> {\n    for (const session of this.sessions.values()) {\n      if (!session.terminal) session.kill?.();\n    }\n    await new Promise<void>((resolvePromise) => {\n      if (!this.server) return resolvePromise();\n      this.server.close(() => resolvePromise());\n    });\n  }\n}\n","import { spawn, execFile } from 'child_process';\nimport { promisify } from 'util';\nimport { mkdtempSync, rmSync, writeFileSync, existsSync, readFileSync, mkdirSync } from 'fs';\nimport { tmpdir, homedir } from 'os';\nimport { join } from 'path';\nimport { TelemetryCollector, type SessionTelemetry } from './stream-events';\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Runs one Claude Code session and turns it into ground truth.\n *\n * The prompt DevPilot composes (`session-prompt.ts` §7.3) asks the *session* to\n * curl its own status and completion callbacks. This runner does not rely on\n * that, and TRD-01 §7.2 explicitly permits the alternative: \"the session (or\n * runner on its behalf) POSTs\".\n *\n * Reporting on its behalf is the honest option. A model may forget the final\n * callback, may send it twice, and — worst — will happily invent `tokensUsed`\n * and `costUsd`, because it has no way to know them. Every number in the report\n * this module produces comes from something observable: the process exit code,\n * `claude`'s own `--output-format json` envelope, and the repo's git state.\n */\n\n/** The fields of `claude -p --output-format json` this runner depends on. */\ninterface ClaudeResultEnvelope {\n  is_error?: boolean;\n  subtype?: string;\n  result?: string;\n  total_cost_usd?: number;\n  duration_ms?: number;\n  session_id?: string;\n  usage?: {\n    input_tokens?: number;\n    output_tokens?: number;\n    cache_read_input_tokens?: number;\n    cache_creation_input_tokens?: number;\n  };\n}\n\nexport interface ClaudeRunOutcome {\n  success: boolean;\n  summary: string;\n  error?: string;\n  tokensUsed: number;\n  costUsd: number;\n  durationMinutes: number;\n  filesModified: string[];\n  filesCreated: string[];\n  filesDeleted: string[];\n  commitSha?: string;\n}\n\n/** `path -> two-letter porcelain code`, e.g. `src/a.ts -> ' M'`. */\ntype GitState = Map<string, string>;\n\n/** How many owned session ids to keep. Older ones fall outside any scan window. */\nconst OWNED_SESSION_LIMIT = 5_000;\n\n/**\n * Append a session id to `~/.devpilot/owned-sessions.json`.\n *\n * Best-effort and never throwing: failing to record one means the adoption\n * scanner falls back to the prompt-marker check for it, which is a slightly\n * weaker exclusion — not a reason to fail a completed agent run.\n *\n * Read-modify-write is safe enough here. Concurrent runners can lose an id in a\n * race, and losing one costs a duplicate offer in a preview a human confirms.\n * Locking for that would be a mechanism the failure does not justify.\n */\nfunction recordOwnedSession(sessionId: string): void {\n  try {\n    const dir = join(homedir(), '.devpilot');\n    const path = join(dir, 'owned-sessions.json');\n\n    let ids: string[] = [];\n    if (existsSync(path)) {\n      const parsed = JSON.parse(readFileSync(path, 'utf8')) as { sessionIds?: unknown };\n      if (Array.isArray(parsed.sessionIds)) {\n        ids = parsed.sessionIds.filter((v): v is string => typeof v === 'string');\n      }\n    }\n    if (ids.includes(sessionId)) return;\n\n    ids.push(sessionId);\n    if (ids.length > OWNED_SESSION_LIMIT) ids = ids.slice(-OWNED_SESSION_LIMIT);\n\n    mkdirSync(dir, { recursive: true });\n    writeFileSync(path, JSON.stringify({ version: 1, sessionIds: ids }, null, 2), 'utf8');\n  } catch {\n    // See above.\n  }\n}\n\nasync function git(workdir: string, args: string[]): Promise<string> {\n  const { stdout } = await execFileAsync('git', args, {\n    cwd: workdir,\n    maxBuffer: 32 * 1024 * 1024,\n  });\n  return stdout;\n}\n\n/**\n * Snapshot the working tree. `-uall` lists untracked files individually rather\n * than collapsing them into a directory entry, without which a session that\n * creates `src/new/a.ts` and `src/new/b.ts` reports the single path `src/new/`.\n */\nasync function snapshot(workdir: string): Promise<GitState> {\n  const state: GitState = new Map();\n  try {\n    const out = await git(workdir, ['status', '--porcelain', '-uall']);\n    for (const line of out.split('\\n')) {\n      if (line.length < 4) continue;\n      state.set(line.slice(3).trim(), line.slice(0, 2));\n    }\n  } catch {\n    // Not a git repo, or git missing. File attribution degrades to empty rather\n    // than failing the session — the work still happened.\n  }\n  return state;\n}\n\nasync function headSha(workdir: string): Promise<string | undefined> {\n  try {\n    return (await git(workdir, ['rev-parse', 'HEAD'])).trim();\n  } catch {\n    return undefined;\n  }\n}\n\n/**\n * Classify what the session did to the tree by diffing two snapshots.\n *\n * KNOWN LIMITATION: a file that was already dirty in the same way before the\n * session and edited further during it has an unchanged porcelain code, so it\n * is not attributed. Dispatch onto a clean tree and this is exact; dispatch onto\n * a dirty one and it under-reports rather than inventing. Under-reporting is the\n * right direction — DevPilot releases in-flight file locks from this list.\n */\nfunction classify(before: GitState, after: GitState) {\n  const filesModified: string[] = [];\n  const filesCreated: string[] = [];\n  const filesDeleted: string[] = [];\n\n  for (const [path, code] of after) {\n    if (before.get(path) === code) continue;\n    if (code.includes('?')) filesCreated.push(path);\n    else if (code.includes('D')) filesDeleted.push(path);\n    else if (code.includes('A')) filesCreated.push(path);\n    else filesModified.push(path);\n  }\n\n  // Present before, gone after: staged-and-committed, or reverted. Either way it\n  // is no longer pending, so it is not a change the session leaves behind.\n  return { filesModified, filesCreated, filesDeleted };\n}\n\n/**\n * Pull the last JSON object out of claude's stdout.\n *\n * With `--output-format stream-json` stdout is newline-delimited events and the\n * envelope is the final `result` object — which carries the same fields the old\n * single-object format did (`total_cost_usd`, `num_turns`, `usage`, `result`,\n * `is_error`), so everything downstream reads unchanged.\n *\n * Scanning backwards for the last balanced object handles both shapes, and also\n * the case this was originally written for: MCP servers and plugins that print\n * to stdout before the envelope. `JSON.parse(stdout)` handles neither.\n */\nfunction parseEnvelope(stdout: string): ClaudeResultEnvelope | null {\n  const trimmed = stdout.trim();\n  if (!trimmed) return null;\n\n  try {\n    return JSON.parse(trimmed) as ClaudeResultEnvelope;\n  } catch {\n    // Fall through to the scan.\n  }\n\n  const start = trimmed.lastIndexOf('\\n{');\n  if (start !== -1) {\n    try {\n      return JSON.parse(trimmed.slice(start + 1)) as ClaudeResultEnvelope;\n    } catch {\n      // Fall through.\n    }\n  }\n  return null;\n}\n\n/**\n * Wire the spawned agent into a DevPilot shared session (TRD-15 §3.1/§3.2).\n *\n * The join link carries the session key, so it must not be observable. It is\n * written into a `0600` MCP config file and passed BY PATH — never as an argv\n * element, because `ps` on a shared machine shows argv to every user on it, and\n * never through the environment, which `/proc/<pid>/environ` exposes on Linux.\n *\n * The caller deletes the directory when the process exits; `finally` in\n * `runClaudeSession` guarantees it even on a throw.\n */\nfunction writeSessionMcpConfig(sessionLink: string): { dir: string; file: string } {\n  const dir = mkdtempSync(join(tmpdir(), 'devpilot-mcp-'));\n  const file = join(dir, 'mcp.json');\n\n  writeFileSync(\n    file,\n    JSON.stringify(\n      {\n        mcpServers: {\n          'devpilot-session': {\n            command: 'npx',\n            args: ['-y', '@devpilot.sh/mcp-session'],\n            env: { DEVPILOT_SESSION_LINK: sessionLink },\n          },\n        },\n      },\n      null,\n      2\n    ),\n    { mode: 0o600 }\n  );\n\n  return { dir, file };\n}\n\n/**\n * Instructions prepended when the dispatch belongs to a shared session.\n *\n * The link is NOT interpolated here. The MCP server reads it from its own env;\n * putting it in the prompt would place the key in the transcript, which is the\n * one place guaranteed to be replayed.\n */\nfunction sessionPreamble(): string {\n  return [\n    '# Shared session',\n    '',\n    'You are working inside a DevPilot shared session. Your collaborators can',\n    'watch this session and join it while you work.',\n    '',\n    '1. Call `devpilot_session_join` FIRST, with no `url` argument — the runner',\n    '   has already supplied the link out of band.',\n    '2. Post a short plan before you change anything.',\n    '3. Post a summary of what you did and why when you finish.',\n    '',\n    'Never print the join link or any key material into the transcript.',\n    '',\n    '---',\n    '',\n  ].join('\\n');\n}\n\nexport interface RunClaudeOptions {\n  workdir: string;\n  prompt: string;\n  /** Join link for the shared session, if this dispatch belongs to one. */\n  sessionLink?: string;\n  model?: string;\n  claudePath: string;\n  /** Continue this Claude Code conversation rather than starting a new one. */\n  resumeSessionId?: string;\n  permissionMode: string;\n  timeoutMs: number;\n  /** Called with each chunk of stderr, for operator visibility. */\n  onLog?: (line: string) => void;\n  /** Receives the kill handle so the HTTP `stop` route can cancel the run. */\n  onSpawn?: (kill: () => void) => void;\n  /**\n   * Called as the agent works, with the running picture of what it is doing.\n   *\n   * This is the difference between a status board and an instrument. Without it\n   * a dispatched agent is opaque until it exits, and the only honest thing the\n   * cockpit can show is a timer pretending to be a progress bar.\n   */\n  onTelemetry?: (telemetry: SessionTelemetry) => void;\n}\n\nexport async function runClaudeSession(\n  options: RunClaudeOptions\n): Promise<ClaudeRunOutcome> {\n  const { workdir, prompt, sessionLink, model, claudePath, permissionMode, timeoutMs, resumeSessionId, onLog, onSpawn } =\n    options;\n\n  const before = await snapshot(workdir);\n  const startedAt = Date.now();\n\n  /**\n   * `stream-json`, not `json`.\n   *\n   * `json` buffers everything and returns one object when the run ends, which\n   * is why an agent was a black box for its entire life. `stream-json` emits\n   * newline-delimited events as the work happens — every tool call, its result,\n   * and a final `result` carrying real cost and turns. `--verbose` is required\n   * for it to include the assistant turns at all.\n   *\n   * The final `result` event is still a superset of what `json` returned, so\n   * everything downstream that parsed the old envelope keeps working.\n   */\n  const args = [\n    '-p',\n    '--output-format',\n    'stream-json',\n    '--verbose',\n    '--permission-mode',\n    permissionMode,\n  ];\n  if (model) args.push('--model', model);\n\n  /**\n   * Continue the conversation rather than opening a new one — TRD 23.\n   *\n   * Deliberately WITHOUT `--fork-session`: resuming in place keeps the same\n   * session id, so the transcript the cockpit is already watching simply grows\n   * and the row stays continuous. Forking would mint a new id, hence a new\n   * adoption key, hence a second row for what a person thinks of as one piece\n   * of work.\n   *\n   * The caller is responsible for only ever passing a HELD session. Two\n   * processes appending to one transcript corrupts it, which is why the bridge\n   * re-probes liveness immediately before spawning rather than trusting a\n   * status that may be a minute old.\n   */\n  if (resumeSessionId) args.push('--resume', resumeSessionId);\n\n  // Shared-session wiring. `--strict-mcp-config` keeps the agent to exactly this\n  // server: a dispatched agent should not inherit whatever MCP servers happen to\n  // be configured on the machine, which would vary per operator and could reach\n  // systems the dispatch never intended to touch.\n  let mcpDir: string | undefined;\n  let effectivePrompt = prompt;\n  if (sessionLink) {\n    const cfg = writeSessionMcpConfig(sessionLink);\n    mcpDir = cfg.dir;\n    args.push('--mcp-config', cfg.file, '--strict-mcp-config');\n    effectivePrompt = sessionPreamble() + prompt;\n  }\n\n  const outcome = await new Promise<{\n    code: number | null;\n    stdout: string;\n    stderr: string;\n    timedOut: boolean;\n    killed: boolean;\n  }>((resolve) => {\n    const child = spawn(claudePath, args, {\n      cwd: workdir,\n      // The prompt goes in on stdin, not argv. A composed prompt carries\n      // newlines, backticks and quotes, and is easily tens of kilobytes — well\n      // past ARG_MAX on a long file scope.\n      stdio: ['pipe', 'pipe', 'pipe'],\n    });\n\n    let stdout = '';\n    let stderr = '';\n    /** Partial trailing line between chunks; NDJSON does not respect chunk boundaries. */\n    let pending = '';\n    // Paths come back relative to the repo, not to whoever's laptop this is.\n    const collector = new TelemetryCollector(Date.now, workdir);\n    let timedOut = false;\n    let killed = false;\n\n    const timer = setTimeout(() => {\n      timedOut = true;\n      child.kill('SIGTERM');\n      // SIGKILL if it ignores the polite request.\n      setTimeout(() => child.kill('SIGKILL'), 5_000).unref();\n    }, timeoutMs);\n\n    onSpawn?.(() => {\n      killed = true;\n      child.kill('SIGTERM');\n    });\n\n    child.stdout.on('data', (chunk: Buffer) => {\n      const text = chunk.toString();\n      stdout += text;\n\n      /**\n       * Split on newlines and keep the remainder. A chunk boundary lands in the\n       * middle of a JSON object often enough that parsing per-chunk silently\n       * drops events — and dropped events are exactly the tool calls the\n       * instrument exists to show.\n       */\n      pending += text;\n      const lines = pending.split('\\n');\n      pending = lines.pop() ?? '';\n      for (const line of lines) collector.ingestLine(line);\n      if (lines.length > 0) options.onTelemetry?.(collector.snapshot());\n    });\n    child.stderr.on('data', (chunk: Buffer) => {\n      const text = chunk.toString();\n      stderr += text;\n      onLog?.(text.trimEnd());\n    });\n\n    child.on('error', (error) => {\n      clearTimeout(timer);\n      resolve({ code: null, stdout, stderr: `${stderr}\\n${error.message}`, timedOut, killed });\n    });\n\n    child.on('close', (code) => {\n      clearTimeout(timer);\n      resolve({ code, stdout, stderr, timedOut, killed });\n    });\n\n    child.stdin.write(effectivePrompt);\n    child.stdin.end();\n  }).finally(() => {\n    // The config holds the session key. Remove it as soon as the process is\n    // gone, whether it exited, timed out, was killed, or threw.\n    if (mcpDir) rmSync(mcpDir, { recursive: true, force: true });\n  });\n\n  const after = await snapshot(workdir);\n  const files = classify(before, after);\n  const envelope = parseEnvelope(outcome.stdout);\n\n  const usage = envelope?.usage ?? {};\n  const tokensUsed =\n    (usage.input_tokens ?? 0) +\n    (usage.output_tokens ?? 0) +\n    (usage.cache_read_input_tokens ?? 0) +\n    (usage.cache_creation_input_tokens ?? 0);\n\n  const durationMs = envelope?.duration_ms ?? Date.now() - startedAt;\n\n  /**\n   * Write this session down as DevPilot's own — TRD 21 §4.4, mechanism 1.\n   *\n   * Sessions the runner starts leave a transcript in `~/.claude/projects` like\n   * any other, so without this the adoption scanner would offer to put work\n   * already on the board back onto the board a second time.\n   *\n   * `session_id` comes from `claude`'s own JSON envelope, which is the exact\n   * value the scanner reads off the transcript filename — so this is an exact\n   * match, not a heuristic. The prompt-marker check in `transcript.ts` is the\n   * fallback for sessions that predate this ledger.\n   */\n  if (envelope?.session_id) recordOwnedSession(envelope.session_id);\n\n  // Success needs BOTH the process and the envelope to agree. `claude` exits 0\n  // on an in-band error (`is_error: true`), so exit code alone would report a\n  // refused or errored turn as a completed task.\n  const processOk = outcome.code === 0 && !outcome.timedOut && !outcome.killed;\n  const envelopeOk = envelope ? envelope.is_error !== true : false;\n  const success = processOk && envelopeOk;\n\n  let error: string | undefined;\n  if (outcome.timedOut) error = `Session exceeded ${Math.round(timeoutMs / 1000)}s timeout`;\n  else if (outcome.killed) error = 'Session stopped by operator';\n  else if (!envelope) error = `No JSON result from claude. stderr: ${outcome.stderr.slice(-2000)}`;\n  else if (envelope.is_error) error = envelope.result ?? `claude reported ${envelope.subtype}`;\n  else if (outcome.code !== 0) error = `claude exited ${outcome.code}. stderr: ${outcome.stderr.slice(-2000)}`;\n\n  return {\n    success,\n    summary: envelope?.result?.trim() || (success ? 'Session completed.' : error || 'Session failed.'),\n    error,\n    tokensUsed,\n    costUsd: envelope?.total_cost_usd ?? 0,\n    durationMinutes: Math.round((durationMs / 60_000) * 100) / 100,\n    ...files,\n    commitSha: await headSha(workdir),\n  };\n}\n","/**\n * What an agent is doing, while it is doing it.\n *\n * `claude -p --output-format json` returns a single blob when the run ends, so\n * a dispatched agent was opaque for its entire life. The cockpit compensated\n * with a fake progress bar — five percent every ninety seconds, capped at\n * ninety — which is why three agents sat at 0% for ten minutes and then snapped\n * to 100%. The conductor was reading painted dials.\n *\n * `--output-format stream-json --verbose` emits newline-delimited JSON as the\n * work happens: every tool call, its result, the assistant's text, and a final\n * `result` carrying real cost, turns and duration. This module turns that\n * firehose into something a person can be shown.\n *\n * ## Why this aggregates rather than forwards\n *\n * A long task emits hundreds of events. Forwarding each one to SQLite and out\n * through SSE would make the instrument itself the load. What a conductor needs\n * is not every keystroke but the shape of the work: which files are being\n * touched, how many tool calls have completed, what it has cost so far, and —\n * the question no wall-clock timer can answer — whether anything has happened\n * recently at all.\n */\n\n/** One decoded line from the stream. Shapes are Claude Code's, not ours. */\ninterface StreamEvent {\n  type?: string;\n  subtype?: string;\n  message?: {\n    content?: {\n      type?: string;\n      name?: string;\n      text?: string;\n      input?: Record<string, unknown>;\n    }[];\n  };\n  total_cost_usd?: number;\n  num_turns?: number;\n  duration_ms?: number;\n  usage?: TokenUsage;\n}\n\ninterface TokenUsage {\n  input_tokens?: number;\n  output_tokens?: number;\n  cache_creation_input_tokens?: number;\n  cache_read_input_tokens?: number;\n}\n\n/**\n * Per-million token prices, to put a number on the dial while work is running.\n *\n * `total_cost_usd` only arrives in the final `result` event, so the money\n * reading was $0.0000 for the entire life of a run — dark at exactly the moment\n * a conductor could still act on it. Each assistant turn carries its own usage,\n * including cache tokens, so the spend can be accumulated as it happens.\n *\n * These are Opus rates and this is an ESTIMATE. The authoritative number\n * replaces it the moment `result` lands, and `costIsEstimate` says which one\n * you are looking at — a made-up figure presented as fact is worse than a blank\n * dial, which is the whole reason the old progress bar had to go.\n */\nconst PRICE_PER_MTOK = {\n  input: 5,\n  output: 25,\n  cacheWrite: 6.25,\n  cacheRead: 0.5,\n} as const;\n\nfunction priceUsage(usage: TokenUsage): number {\n  const m = 1_000_000;\n  return (\n    ((usage.input_tokens ?? 0) * PRICE_PER_MTOK.input) / m +\n    ((usage.output_tokens ?? 0) * PRICE_PER_MTOK.output) / m +\n    ((usage.cache_creation_input_tokens ?? 0) * PRICE_PER_MTOK.cacheWrite) / m +\n    ((usage.cache_read_input_tokens ?? 0) * PRICE_PER_MTOK.cacheRead) / m\n  );\n}\n\n/** A single observed action, kept for the session timeline. */\nexport interface AgentAction {\n  /** Tool name as Claude reports it: Write, Edit, Bash, Read, Grep… */\n  tool: string;\n  /** The file it acted on, when the tool names one. */\n  path?: string;\n  /** Milliseconds since the session started, so the UI can lay out a timeline. */\n  atMs: number;\n}\n\n/** The live picture of one agent, rebuilt on every event. */\nexport interface SessionTelemetry {\n  /** Tool calls the agent has issued. The honest denominator for progress. */\n  toolCalls: number;\n  /** Distinct files it has written to or edited, in the order first touched. */\n  filesTouched: string[];\n  /** Files it only read. Useful for seeing an agent orienting vs. producing. */\n  filesRead: string[];\n  /** Shell commands run, most recent last. */\n  commands: string[];\n  /** The most recent thing it said, which is usually what it is about to do. */\n  lastText?: string;\n  /** The most recent tool, for a \"currently: Editing scheduler.ts\" readout. */\n  lastAction?: AgentAction;\n  /** Timeline of actions, bounded — see MAX_ACTIONS. */\n  actions: AgentAction[];\n  /**\n   * Spend so far. Estimated from per-turn usage while running, then replaced by\n   * the authoritative figure when the run ends.\n   */\n  costUsd: number;\n  /** True while `costUsd` is our arithmetic rather than Claude's own number. */\n  costIsEstimate: boolean;\n  tokensIn: number;\n  tokensOut: number;\n  turns: number;\n  /** Wall-clock ms since the first event; the fake \"elapsed 0m\" is gone. */\n  elapsedMs: number;\n  /** Ms since anything last happened. The stall signal. */\n  idleMs: number;\n}\n\n/**\n * The timeline is for showing shape, not for forensics. A runaway agent can\n * emit thousands of actions, and an unbounded array in a long-lived process is\n * how a session runner starts leaking.\n */\nconst MAX_ACTIONS = 200;\n\n/** Tools whose `input.file_path` means \"this file changed\". */\nconst WRITE_TOOLS = new Set(['Write', 'Edit', 'MultiEdit', 'NotebookEdit']);\nconst READ_TOOLS = new Set(['Read', 'Glob', 'Grep']);\n\n/**\n * Make a path readable to a human who knows the repository.\n *\n * Claude reports `file_path` as an absolute path, so every surface that showed\n * a file showed\n * `/private/tmp/claude-501/-Users-…/scratchpad/fleet-a/src/lru.ts`. On a Linear\n * ticket that is unreadable, and it publishes the directory layout of whoever\n * happened to run the agent to everyone who can see the issue.\n *\n * Stripped here rather than at each display site: the cockpit HUD, the graph\n * node labels and the Linear summary all read the same field, and three\n * independent trimmings would drift.\n */\nfunction relativize(path: string, workdir?: string): string {\n  if (!workdir) return path;\n  const root = workdir.endsWith('/') ? workdir : `${workdir}/`;\n  if (path.startsWith(root)) return path.slice(root.length);\n\n  // Symlinked temp dirs mean the agent may report /private/var/… for a workdir\n  // given as /var/…, and vice versa. Compare both ways before giving up.\n  const alt = root.startsWith('/private/') ? root.slice('/private'.length) : `/private${root}`;\n  if (path.startsWith(alt)) return path.slice(alt.length);\n\n  return path;\n}\n\nexport class TelemetryCollector {\n  private readonly startedAt: number;\n  private lastEventAt: number;\n  private readonly touched: string[] = [];\n  private readonly read: string[] = [];\n  private readonly commands: string[] = [];\n  private readonly actions: AgentAction[] = [];\n  private toolCalls = 0;\n  private costUsd = 0;\n  private costIsEstimate = true;\n  private tokensIn = 0;\n  private tokensOut = 0;\n  private turns = 0;\n  private lastText?: string;\n  private lastAction?: AgentAction;\n\n  constructor(now: () => number = Date.now, workdir?: string) {\n    this.now = now;\n    this.workdir = workdir;\n    this.startedAt = now();\n    this.lastEventAt = this.startedAt;\n  }\n\n  private readonly now: () => number;\n  /** The repo root, so reported paths are relative to it. */\n  private readonly workdir?: string;\n\n  /**\n   * Feed one raw line. Malformed lines are ignored rather than thrown:\n   * telemetry must never be able to kill the session it is describing.\n   */\n  ingestLine(line: string): void {\n    const trimmed = line.trim();\n    if (!trimmed) return;\n\n    let event: StreamEvent;\n    try {\n      event = JSON.parse(trimmed) as StreamEvent;\n    } catch {\n      return;\n    }\n    this.ingest(event);\n  }\n\n  ingest(event: StreamEvent): void {\n    this.lastEventAt = this.now();\n\n    if (event.type === 'assistant') {\n      // Each turn prices itself, so the dial moves during the run instead of\n      // staying dark until it ends.\n      const usage = (event.message as { usage?: TokenUsage } | undefined)?.usage;\n      if (usage && this.costIsEstimate) {\n        this.costUsd += priceUsage(usage);\n        this.tokensIn += usage.input_tokens ?? 0;\n        this.tokensOut += usage.output_tokens ?? 0;\n      }\n\n      for (const block of event.message?.content ?? []) {\n        if (block.type === 'tool_use' && block.name) {\n          this.recordTool(block.name, block.input ?? {});\n        } else if (block.type === 'text' && block.text?.trim()) {\n          // Kept short: this is a status line, not a transcript.\n          this.lastText = block.text.trim().slice(0, 240);\n        }\n      }\n    }\n\n    if (event.type === 'result') {\n      // Authoritative from here: stop estimating and stop accumulating, or the\n      // real figure would be added to the guess.\n      if (typeof event.total_cost_usd === 'number') this.costIsEstimate = false;\n      this.costUsd = event.total_cost_usd ?? this.costUsd;\n      this.turns = event.num_turns ?? this.turns;\n      this.tokensIn = event.usage?.input_tokens ?? this.tokensIn;\n      this.tokensOut = event.usage?.output_tokens ?? this.tokensOut;\n    }\n  }\n\n  private recordTool(tool: string, input: Record<string, unknown>): void {\n    this.toolCalls++;\n\n    const raw =\n      typeof input.file_path === 'string'\n        ? input.file_path\n        : typeof input.path === 'string'\n          ? input.path\n          : undefined;\n    const path = raw ? relativize(raw, this.workdir) : undefined;\n\n    if (path) {\n      const list = WRITE_TOOLS.has(tool) ? this.touched : READ_TOOLS.has(tool) ? this.read : null;\n      // First-touch order, not frequency: a conductor reads this as \"what has\n      // this agent been into\", and re-listing a file it edited eight times\n      // would drown out the other seven files.\n      if (list && !list.includes(path)) list.push(path);\n    }\n\n    if (tool === 'Bash' && typeof input.command === 'string') {\n      this.commands.push(input.command.slice(0, 200));\n    }\n\n    const action: AgentAction = { tool, path, atMs: this.now() - this.startedAt };\n    this.lastAction = action;\n    this.actions.push(action);\n    if (this.actions.length > MAX_ACTIONS) this.actions.shift();\n  }\n\n  snapshot(): SessionTelemetry {\n    const now = this.now();\n    return {\n      toolCalls: this.toolCalls,\n      filesTouched: [...this.touched],\n      filesRead: [...this.read],\n      commands: [...this.commands],\n      lastText: this.lastText,\n      lastAction: this.lastAction,\n      actions: [...this.actions],\n      costUsd: this.costUsd,\n      costIsEstimate: this.costIsEstimate,\n      tokensIn: this.tokensIn,\n      tokensOut: this.tokensOut,\n      turns: this.turns,\n      elapsedMs: now - this.startedAt,\n      idleMs: now - this.lastEventAt,\n    };\n  }\n}\n\n/**\n * Progress from evidence rather than from a timer.\n *\n * The plan states which files a task will touch. Once an agent has written to\n * all of them it is, by its own contract, essentially done — so the ratio is a\n * real measurement instead of a countdown. Both bounds matter: it never claims\n * completion (the agent decides that), and it never claims zero once work has\n * started, because an agent five tool calls in is visibly not at nothing.\n *\n * With no declared files there is nothing to measure against, so this falls\n * back to a coarse tool-call curve — still evidence, just weaker evidence, and\n * it is capped low enough that nobody mistakes it for a real reading.\n */\nexport function estimateProgress(\n  telemetry: SessionTelemetry,\n  declaredFiles: string[] = []\n): number {\n  if (declaredFiles.length > 0) {\n    const declared = declaredFiles.map(normalize);\n    const done = declared.filter((f) =>\n      telemetry.filesTouched.some((t) => normalize(t).endsWith(f) || f.endsWith(normalize(t)))\n    ).length;\n    const ratio = done / declared.length;\n    // 10 as a floor once anything has happened, 90 as a ceiling because the\n    // agent is the only thing that can declare itself finished.\n    return Math.max(telemetry.toolCalls > 0 ? 10 : 0, Math.min(90, Math.round(ratio * 90)));\n  }\n\n  if (telemetry.toolCalls === 0) return 0;\n  // Diminishing curve: 1 call ≈ 12%, 5 ≈ 40%, 20 ≈ 65%, never past 70 without\n  // file evidence to back it.\n  return Math.min(70, Math.round(70 * (1 - Math.exp(-telemetry.toolCalls / 8))));\n}\n\nfunction normalize(p: string): string {\n  return p.replace(/^\\.\\//, '').replace(/\\\\/g, '/');\n}\n\n/** A short human phrase for what the agent is doing right now. */\nexport function describeActivity(telemetry: SessionTelemetry): string {\n  const a = telemetry.lastAction;\n  if (!a) return 'starting up';\n\n  const file = a.path ? a.path.split('/').slice(-1)[0] : undefined;\n  switch (a.tool) {\n    case 'Write':\n      return file ? `writing ${file}` : 'writing';\n    case 'Edit':\n    case 'MultiEdit':\n      return file ? `editing ${file}` : 'editing';\n    case 'Read':\n      return file ? `reading ${file}` : 'reading';\n    case 'Bash':\n      return `running ${(telemetry.commands.at(-1) ?? '').split(/\\s+/)[0] || 'a command'}`;\n    case 'Grep':\n    case 'Glob':\n      return 'searching';\n    default:\n      return a.tool.toLowerCase();\n  }\n}\n\n/**\n * Has this agent stopped making progress?\n *\n * The one question a wall-clock timer cannot answer, and the reason a conductor\n * would look at this screen at all. Silence is not the same as slowness: a long\n * Bash step is quiet and healthy, so the threshold is generous by default and\n * the caller decides what to do about it.\n */\nexport function isStalled(telemetry: SessionTelemetry, thresholdMs = 180_000): boolean {\n  return telemetry.toolCalls > 0 && telemetry.idleMs > thresholdMs;\n}\n","import type { CompletionReport, StatusUpdate } from './types';\n\n/**\n * Callback delivery to DevPilot (§7.2).\n *\n * \"At-least-once with exponential backoff for 10 minutes; DevPilot handlers are\n * idempotent.\" Both halves matter: the completion POST is the only thing that\n * moves a wave task off `dispatched`, so dropping it silently strands the whole\n * wave — which looks exactly like an agent that never finished.\n */\n\n/** 1s, 2s, 4s … capped, summing to a little over 10 minutes. */\nconst BACKOFF_MS = [1_000, 2_000, 4_000, 8_000, 16_000, 32_000, 60_000, 120_000, 240_000, 240_000];\n\nfunction sleep(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function post(\n  url: string,\n  body: unknown,\n  token: string | undefined,\n  log: (line: string) => void\n): Promise<boolean> {\n  const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n  if (token) headers['X-DevPilot-Callback-Token'] = token;\n\n  for (let attempt = 0; attempt <= BACKOFF_MS.length; attempt++) {\n    try {\n      const res = await fetch(url, {\n        method: 'POST',\n        headers,\n        body: JSON.stringify(body),\n        signal: AbortSignal.timeout(30_000),\n      });\n\n      if (res.ok) return true;\n\n      // 4xx other than 408/429 is a contract problem, not a transient one.\n      // Retrying a 401 for ten minutes just delays the error by ten minutes.\n      if (res.status >= 400 && res.status < 500 && res.status !== 408 && res.status !== 429) {\n        log(`callback ${url} rejected: ${res.status} ${await res.text().catch(() => '')}`);\n        return false;\n      }\n\n      log(`callback ${url} failed: ${res.status} (attempt ${attempt + 1})`);\n    } catch (error) {\n      const message = error instanceof Error ? error.message : String(error);\n      log(`callback ${url} error: ${message} (attempt ${attempt + 1})`);\n    }\n\n    if (attempt < BACKOFF_MS.length) await sleep(BACKOFF_MS[attempt]);\n  }\n\n  log(`callback ${url} GAVE UP after ${BACKOFF_MS.length + 1} attempts`);\n  return false;\n}\n\nexport function sendStatus(\n  callbackUrl: string,\n  update: StatusUpdate,\n  token: string | undefined,\n  log: (line: string) => void\n): Promise<boolean> {\n  return post(`${callbackUrl.replace(/\\/$/, '')}/status`, update, token, log);\n}\n\nexport function sendCompletion(\n  callbackUrl: string,\n  report: CompletionReport,\n  token: string | undefined,\n  log: (line: string) => void\n): Promise<boolean> {\n  return post(`${callbackUrl.replace(/\\/$/, '')}/complete`, report, token, log);\n}\n","import { Command } from 'commander';\nimport { execSync, spawn } from 'child_process';\nimport chalk from 'chalk';\nimport { VERSION } from '../version';\n\n/**\n * Get the latest version from npm registry\n */\nasync function getLatestVersion(): Promise<string | null> {\n  try {\n    const result = execSync('npm view @devpilot.sh/cli version', {\n      encoding: 'utf-8',\n      stdio: ['pipe', 'pipe', 'pipe'],\n    });\n    return result.trim();\n  } catch {\n    return null;\n  }\n}\n\n/**\n * Compare semantic versions\n * Returns: 1 if a > b, -1 if a < b, 0 if equal\n */\nfunction compareVersions(a: string, b: string): number {\n  const partsA = a.split('.').map(Number);\n  const partsB = b.split('.').map(Number);\n\n  for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {\n    const numA = partsA[i] || 0;\n    const numB = partsB[i] || 0;\n    if (numA > numB) return 1;\n    if (numA < numB) return -1;\n  }\n  return 0;\n}\n\n/**\n * Detect package manager used for global install\n */\nfunction detectPackageManager(): 'npm' | 'pnpm' | 'yarn' | 'bun' {\n  try {\n    // Check if installed via pnpm\n    const pnpmList = execSync('pnpm list -g @devpilot.sh/cli 2>/dev/null', {\n      encoding: 'utf-8',\n      stdio: ['pipe', 'pipe', 'pipe'],\n    });\n    if (pnpmList.includes('@devpilot.sh/cli')) return 'pnpm';\n  } catch {\n    // Not installed via pnpm\n  }\n\n  try {\n    // Check if installed via yarn\n    const yarnList = execSync('yarn global list 2>/dev/null', {\n      encoding: 'utf-8',\n      stdio: ['pipe', 'pipe', 'pipe'],\n    });\n    if (yarnList.includes('@devpilot.sh/cli')) return 'yarn';\n  } catch {\n    // Not installed via yarn\n  }\n\n  try {\n    // Check if bun is available\n    execSync('bun --version', { stdio: ['pipe', 'pipe', 'pipe'] });\n    return 'bun';\n  } catch {\n    // Bun not available\n  }\n\n  // Default to npm\n  return 'npm';\n}\n\n/**\n * Get update command for package manager\n */\nfunction getUpdateCommand(pm: 'npm' | 'pnpm' | 'yarn' | 'bun'): string {\n  switch (pm) {\n    case 'pnpm':\n      return 'pnpm add -g @devpilot.sh/cli@latest';\n    case 'yarn':\n      return 'yarn global add @devpilot.sh/cli@latest';\n    case 'bun':\n      return 'bun add -g @devpilot.sh/cli@latest';\n    default:\n      return 'npm install -g @devpilot.sh/cli@latest';\n  }\n}\n\nexport const updateCommand = new Command('update')\n  .description('Update DevPilot CLI to the latest version')\n  .option('-c, --check', 'Only check for updates without installing')\n  .option('--force', 'Force update even if already on latest version')\n  .action(async (options) => {\n    console.log(chalk.cyan('Checking for updates...'));\n\n    const latestVersion = await getLatestVersion();\n\n    if (!latestVersion) {\n      console.log(chalk.yellow('Could not check for updates. Please check your network connection.'));\n      console.log(chalk.gray('You can manually update with: npm install -g @devpilot.sh/cli@latest'));\n      return;\n    }\n\n    const comparison = compareVersions(latestVersion, VERSION);\n\n    if (comparison === 0 && !options.force) {\n      console.log(chalk.green(`You're already on the latest version (${VERSION})`));\n      return;\n    }\n\n    if (comparison === -1 && !options.force) {\n      console.log(chalk.yellow(`You're on a newer version (${VERSION}) than the latest release (${latestVersion})`));\n      console.log(chalk.gray('This might be a pre-release or development version.'));\n      return;\n    }\n\n    if (options.check) {\n      if (comparison === 1) {\n        console.log(chalk.yellow(`Update available: ${VERSION} → ${latestVersion}`));\n        console.log(chalk.gray('Run \"devpilot update\" to install the latest version.'));\n      }\n      return;\n    }\n\n    // Perform the update\n    const pm = detectPackageManager();\n    const updateCmd = getUpdateCommand(pm);\n\n    console.log(chalk.cyan(`Updating from ${VERSION} to ${latestVersion}...`));\n    console.log(chalk.gray(`Using: ${updateCmd}`));\n    console.log('');\n\n    try {\n      // Run update command with inherited stdio for real-time output\n      const [cmd, ...args] = updateCmd.split(' ');\n      const child = spawn(cmd, args, {\n        stdio: 'inherit',\n        shell: true,\n      });\n\n      child.on('close', (code) => {\n        if (code === 0) {\n          console.log('');\n          console.log(chalk.green(`Successfully updated to ${latestVersion}`));\n          console.log(chalk.gray('Run \"devpilot --version\" to verify.'));\n        } else {\n          console.log('');\n          console.log(chalk.red('Update failed. Please try manually:'));\n          console.log(chalk.cyan(`  ${updateCmd}`));\n        }\n      });\n\n      child.on('error', (err) => {\n        console.log(chalk.red(`Update failed: ${err.message}`));\n        console.log(chalk.gray('Please try manually:'));\n        console.log(chalk.cyan(`  ${updateCmd}`));\n      });\n    } catch (error) {\n      const message = error instanceof Error ? error.message : 'Unknown error';\n      console.log(chalk.red(`Update failed: ${message}`));\n      console.log(chalk.gray('Please try manually:'));\n      console.log(chalk.cyan(`  ${updateCmd}`));\n    }\n  });\n","import { Command } from 'commander';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { join } from 'path';\nimport chalk from 'chalk';\nimport { resolveWikiModel } from '@devpilot.sh/core/wave-planner';\n\n// ============================================================================\n// Wiki CLI Command\n// ============================================================================\n// devpilot wiki — LLM-compiled knowledge base for your codebase\n//\n// Subcommands:\n//   init     Initialize the wiki system\n//   ingest   Ingest a source into the wiki\n//   query    Ask a question against the wiki\n//   lint     Check wiki health\n//   status   Show wiki stats\n//   flush    Export wiki to disk as markdown\n//   index    Show the wiki table of contents\n\nexport const wikiCommand = new Command('wiki')\n  .description('LLM-compiled knowledge base — institutional memory for your codebase');\n\n// --------------------------------------------------------------------------\n// wiki init\n// --------------------------------------------------------------------------\n\nwikiCommand\n  .command('init')\n  .description('Initialize the wiki system in the current repository')\n  .option('--wiki-dir <path>', 'Wiki output directory', '.devpilot/wiki')\n  .action(async (options) => {\n    const cwd = process.cwd();\n    const devpilotDir = join(cwd, '.devpilot');\n    const wikiDir = join(cwd, options.wikiDir);\n\n    // Ensure .devpilot exists\n    if (!existsSync(devpilotDir)) {\n      console.log(\n        chalk.yellow('⚠️  DevPilot not initialized. Run `devpilot init` first.')\n      );\n      return;\n    }\n\n    // Create wiki directory structure\n    if (!existsSync(wikiDir)) {\n      mkdirSync(wikiDir, { recursive: true });\n    }\n\n    // Create initial index.md\n    const indexPath = join(wikiDir, 'index.md');\n    if (!existsSync(indexPath)) {\n      const initialIndex = `# Wiki Index\n\n> Auto-generated wiki — compiled from session logs, commits, specs, and decisions.\n> This wiki is maintained by DevPilot's wiki compiler following the LLM Knowledge Base pattern.\n\n## Getting Started\n\nThis wiki will grow automatically as you work with DevPilot:\n- **Session logs** are compiled into architecture and decision articles\n- **Commits** are analyzed for patterns and architectural changes\n- **Specs** are indexed for requirements and design rationale\n\nRun \\`devpilot wiki ingest\\` to manually add sources, or let the session hook capture knowledge automatically.\n`;\n      writeFileSync(indexPath, initialIndex);\n    }\n\n    // Create log.md\n    const logPath = join(wikiDir, 'log.md');\n    if (!existsSync(logPath)) {\n      writeFileSync(\n        logPath,\n        `# Wiki Activity Log\\n\\n> Append-only chronicle of wiki operations.\\n\\n- **${new Date().toISOString().split('T')[0]}** [init] Wiki initialized\\n`\n      );\n    }\n\n    // Update .gitignore — wiki content should be committed\n    const gitignorePath = join(cwd, '.gitignore');\n    if (existsSync(gitignorePath)) {\n      const gitignore = readFileSync(gitignorePath, 'utf-8');\n      if (!gitignore.includes('.devpilot/wiki')) {\n        // Don't ignore the wiki — it should be version controlled\n        // But ensure the DB is still ignored\n      }\n    }\n\n    console.log(chalk.green('✅ Wiki initialized!'));\n    console.log('');\n    console.log(chalk.white('Wiki directory: ') + chalk.cyan(wikiDir));\n    console.log('');\n    console.log(chalk.white('Next steps:'));\n    console.log(\n      chalk.gray('  1. ') +\n        chalk.cyan('devpilot wiki ingest --file <path>') +\n        chalk.gray(' to add source material')\n    );\n    console.log(\n      chalk.gray('  2. ') +\n        chalk.cyan('devpilot wiki query \"How does auth work?\"') +\n        chalk.gray(' to ask questions')\n    );\n    console.log(\n      chalk.gray('  3. ') +\n        chalk.cyan('devpilot wiki status') +\n        chalk.gray(' to check wiki health')\n    );\n    console.log('');\n    console.log(\n      chalk.gray(\n        'The wiki will grow automatically as agents work — each session compounds the knowledge base.'\n      )\n    );\n  });\n\n// --------------------------------------------------------------------------\n// wiki ingest\n// --------------------------------------------------------------------------\n\nwikiCommand\n  .command('ingest')\n  .description('Ingest a source document into the wiki')\n  .requiredOption('--type <type>', 'Source type: session_log, commit, spec, decision, manual')\n  .requiredOption('--title <title>', 'Human-readable title for the source')\n  .option('--file <path>', 'Path to source file')\n  .option('--stdin', 'Read source from stdin')\n  .option('--origin <origin>', 'Origin identifier (e.g. session ID, commit SHA)')\n  .action(async (options) => {\n    let content: string;\n\n    if (options.file) {\n      if (!existsSync(options.file)) {\n        console.log(chalk.red(`❌ File not found: ${options.file}`));\n        return;\n      }\n      content = readFileSync(options.file, 'utf-8');\n    } else if (options.stdin) {\n      content = readFileSync(0, 'utf-8'); // Read from stdin\n    } else {\n      console.log(\n        chalk.red('❌ Provide either --file <path> or --stdin')\n      );\n      return;\n    }\n\n    const validTypes = ['session_log', 'commit', 'spec', 'decision', 'manual'];\n    if (!validTypes.includes(options.type)) {\n      console.log(\n        chalk.red(\n          `❌ Invalid type \"${options.type}\". Must be one of: ${validTypes.join(', ')}`\n        )\n      );\n      return;\n    }\n\n    console.log(chalk.gray(`Ingesting ${options.type}: \"${options.title}\"...`));\n\n    try {\n      const { createWikiCompiler } = await import('@devpilot.sh/core/wiki');\n      const config = getWikiConfig();\n      const compiler = createWikiCompiler(config);\n      const result = await compiler.ingest(\n        content,\n        options.type,\n        options.title,\n        options.origin\n      );\n\n      console.log(chalk.green('✅ Ingested successfully!'));\n      console.log(\n        chalk.gray(`   Source ID: ${result.sourceId}`)\n      );\n      if (result.articlesCreated.length > 0) {\n        console.log(\n          chalk.white(`   Articles created: `) +\n            chalk.cyan(result.articlesCreated.join(', '))\n        );\n      }\n      if (result.articlesUpdated.length > 0) {\n        console.log(\n          chalk.white(`   Articles updated: `) +\n            chalk.yellow(result.articlesUpdated.join(', '))\n        );\n      }\n      console.log(\n        chalk.gray(`   Tokens used: ${result.tokensUsed}`)\n      );\n    } catch (error) {\n      console.log(\n        chalk.red(\n          `❌ Ingest failed: ${error instanceof Error ? error.message : String(error)}`\n        )\n      );\n    }\n  });\n\n// --------------------------------------------------------------------------\n// wiki query\n// --------------------------------------------------------------------------\n\nwikiCommand\n  .command('query <question>')\n  .description('Ask a question against the wiki')\n  .action(async (question: string) => {\n    console.log(chalk.gray(`Searching wiki for: \"${question}\"...`));\n\n    try {\n      const { createWikiCompiler } = await import('@devpilot.sh/core/wiki');\n      const config = getWikiConfig();\n      const compiler = createWikiCompiler(config);\n      const result = await compiler.query(question);\n\n      console.log('');\n      console.log(chalk.white(result.answer));\n      console.log('');\n\n      if (result.citedArticles.length > 0) {\n        console.log(\n          chalk.gray('Cited: ') +\n            chalk.cyan(result.citedArticles.map((s) => `[[${s}]]`).join(', '))\n        );\n      }\n\n      if (result.newArticleSlug) {\n        console.log(\n          chalk.green(\n            `📝 New article created from this query: [[${result.newArticleSlug}]]`\n          )\n        );\n      }\n\n      console.log(chalk.gray(`Tokens used: ${result.tokensUsed}`));\n    } catch (error) {\n      console.log(\n        chalk.red(\n          `❌ Query failed: ${error instanceof Error ? error.message : String(error)}`\n        )\n      );\n    }\n  });\n\n// --------------------------------------------------------------------------\n// wiki lint\n// --------------------------------------------------------------------------\n\nwikiCommand\n  .command('lint')\n  .description('Check wiki health — find stale content, orphans, and gaps')\n  .action(async () => {\n    console.log(chalk.gray('Linting wiki...'));\n\n    try {\n      const { createWikiCompiler } = await import('@devpilot.sh/core/wiki');\n      const config = getWikiConfig();\n      const compiler = createWikiCompiler(config);\n      const result = await compiler.lint();\n\n      if (result.findings.length === 0) {\n        console.log(chalk.green('✅ Wiki is healthy — no issues found!'));\n        return;\n      }\n\n      console.log(\n        chalk.yellow(`⚠️  Found ${result.findings.length} issue(s):\\n`)\n      );\n\n      for (const finding of result.findings) {\n        const icon = {\n          stale: '🕐',\n          orphaned: '🔗',\n          contradiction: '⚡',\n          gap: '📭',\n          broken_link: '💔',\n        }[finding.type];\n\n        console.log(\n          `  ${icon} ${chalk.white(`[${finding.type}]`)} ${chalk.cyan(`[[${finding.articleSlug}]]`)}`\n        );\n        console.log(chalk.gray(`     ${finding.description}`));\n        console.log(chalk.gray(`     → ${finding.suggestion}`));\n        console.log('');\n      }\n\n      if (result.articlesMarkedStale.length > 0) {\n        console.log(\n          chalk.yellow(\n            `Marked ${result.articlesMarkedStale.length} article(s) as stale.`\n          )\n        );\n      }\n\n      console.log(chalk.gray(`Tokens used: ${result.tokensUsed}`));\n    } catch (error) {\n      console.log(\n        chalk.red(\n          `❌ Lint failed: ${error instanceof Error ? error.message : String(error)}`\n        )\n      );\n    }\n  });\n\n// --------------------------------------------------------------------------\n// wiki status\n// --------------------------------------------------------------------------\n\nwikiCommand\n  .command('status')\n  .description('Show wiki statistics')\n  .action(async () => {\n    try {\n      const { createWikiCompiler } = await import('@devpilot.sh/core/wiki');\n      const config = getWikiConfig();\n      const compiler = createWikiCompiler(config);\n      const status = await compiler.getStatus();\n\n      console.log(chalk.white.bold('\\n📚 Wiki Status\\n'));\n      console.log(\n        chalk.gray('  Sources:    ') + chalk.white(String(status.totalSources))\n      );\n      console.log(\n        chalk.gray('  Articles:   ') +\n          chalk.white(String(status.totalArticles)) +\n          chalk.gray(' (') +\n          chalk.green(`${status.activeArticles} active`) +\n          (status.staleArticles > 0\n            ? chalk.yellow(`, ${status.staleArticles} stale`)\n            : '') +\n          (status.archivedArticles > 0\n            ? chalk.gray(`, ${status.archivedArticles} archived`)\n            : '') +\n          chalk.gray(')')\n      );\n\n      if (Object.keys(status.categories).length > 0) {\n        console.log(chalk.gray('\\n  Categories:'));\n        for (const [category, count] of Object.entries(status.categories).sort()) {\n          console.log(\n            chalk.gray('    ') +\n              chalk.cyan(category) +\n              chalk.gray(': ') +\n              chalk.white(String(count))\n          );\n        }\n      }\n\n      if (status.lastActivity) {\n        console.log(\n          chalk.gray('\\n  Last activity: ') +\n            chalk.white(status.lastActivity.toISOString().split('T')[0])\n        );\n      }\n\n      console.log('');\n    } catch (error) {\n      console.log(\n        chalk.red(\n          `❌ Status failed: ${error instanceof Error ? error.message : String(error)}`\n        )\n      );\n    }\n  });\n\n// --------------------------------------------------------------------------\n// wiki flush\n// --------------------------------------------------------------------------\n\nwikiCommand\n  .command('flush')\n  .description('Export wiki to disk as markdown files')\n  .action(async () => {\n    console.log(chalk.gray('Flushing wiki to disk...'));\n\n    try {\n      const { createWikiCompiler } = await import('@devpilot.sh/core/wiki');\n      const config = getWikiConfig();\n      const compiler = createWikiCompiler(config);\n      const result = await compiler.flushToDisk();\n\n      console.log(chalk.green(`✅ Wrote ${result.filesWritten} files to ${result.wikiDir}`));\n    } catch (error) {\n      console.log(\n        chalk.red(\n          `❌ Flush failed: ${error instanceof Error ? error.message : String(error)}`\n        )\n      );\n    }\n  });\n\n// --------------------------------------------------------------------------\n// wiki index\n// --------------------------------------------------------------------------\n\nwikiCommand\n  .command('index')\n  .description('Show the wiki table of contents')\n  .option('--category <category>', 'Filter by category')\n  .action(async (options) => {\n    try {\n      const { createWikiCompiler } = await import('@devpilot.sh/core/wiki');\n      const config = getWikiConfig();\n      const compiler = createWikiCompiler(config);\n      let index = await compiler.getIndex();\n\n      if (options.category) {\n        index = index.filter((e) => e.category === options.category);\n      }\n\n      if (index.length === 0) {\n        console.log(chalk.gray('Wiki is empty. Run `devpilot wiki ingest` to add sources.'));\n        return;\n      }\n\n      // Group by category\n      const byCategory: Record<string, typeof index> = {};\n      for (const entry of index) {\n        if (!byCategory[entry.category]) {\n          byCategory[entry.category] = [];\n        }\n        byCategory[entry.category].push(entry);\n      }\n\n      console.log(chalk.white.bold('\\n📖 Wiki Index\\n'));\n\n      for (const [category, entries] of Object.entries(byCategory).sort()) {\n        console.log(\n          chalk.cyan.bold(\n            `  ${category.charAt(0).toUpperCase() + category.slice(1)}`\n          )\n        );\n\n        for (const entry of entries) {\n          const statusColor =\n            entry.status === 'active'\n              ? chalk.green\n              : entry.status === 'stale'\n                ? chalk.yellow\n                : chalk.gray;\n          const badge = statusColor(`[${entry.status}]`);\n\n          console.log(\n            `    ${badge} ${chalk.white(entry.title)} ${chalk.gray(`[[${entry.slug}]]`)}`\n          );\n        }\n        console.log('');\n      }\n    } catch (error) {\n      console.log(\n        chalk.red(\n          `❌ Index failed: ${error instanceof Error ? error.message : String(error)}`\n        )\n      );\n    }\n  });\n\n// --------------------------------------------------------------------------\n// wiki read\n// --------------------------------------------------------------------------\n\nwikiCommand\n  .command('read <slug>')\n  .description('Read a specific wiki article')\n  .action(async (slug: string) => {\n    try {\n      const { createWikiCompiler } = await import('@devpilot.sh/core/wiki');\n      const config = getWikiConfig();\n      const compiler = createWikiCompiler(config);\n      const article = await compiler.getArticle(slug);\n\n      if (!article) {\n        console.log(chalk.red(`❌ Article not found: [[${slug}]]`));\n        return;\n      }\n\n      console.log(chalk.white.bold(`\\n# ${article.title}\\n`));\n      console.log(\n        chalk.gray(\n          `Category: ${article.category} | Status: ${article.status} | v${article.version}`\n        )\n      );\n\n      if (article.backlinks.length > 0) {\n        console.log(\n          chalk.gray(\n            `Related: ${article.backlinks.map((b) => `[[${b}]]`).join(', ')}`\n          )\n        );\n      }\n\n      console.log(chalk.gray('─'.repeat(60)));\n      console.log(article.content);\n      console.log('');\n    } catch (error) {\n      console.log(\n        chalk.red(\n          `❌ Read failed: ${error instanceof Error ? error.message : String(error)}`\n        )\n      );\n    }\n  });\n\n// --------------------------------------------------------------------------\n// Helpers\n// --------------------------------------------------------------------------\n\nfunction getWikiConfig() {\n  const cwd = process.cwd();\n  return {\n    apiKey: process.env.ANTHROPIC_API_KEY || '',\n    model: resolveWikiModel(),\n    maxTokens: parseInt(process.env.WIKI_MAX_TOKENS || '8192', 10),\n    repo: getRepoName(cwd),\n    wikiDir: join(cwd, '.devpilot', 'wiki'),\n  };\n}\n\nfunction getRepoName(cwd: string): string {\n  try {\n    const { execSync } = require('child_process');\n    const remote = execSync('git remote get-url origin', {\n      cwd,\n      encoding: 'utf-8',\n    }).trim();\n    // Extract owner/repo from git URL\n    const match = remote.match(/[/:]([\\w.-]+\\/[\\w.-]+?)(?:\\.git)?$/);\n    return match ? match[1] : cwd.split('/').pop() || 'unknown';\n  } catch {\n    return cwd.split('/').pop() || 'unknown';\n  }\n}\n"],"mappings":"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","names":["Command","Command","chalk","existsSync","mkdirSync","join","orchestrator","Command","chalk","Command","existsSync","writeFileSync","join","chalk","client","Command","existsSync","readFileSync","writeFileSync","join","chalk","YAML","linear","existsSync","readFileSync","writeFileSync","join","chalk","git","YAML","resolve","Command","join","existsSync","chalk","readFileSync","YAML","linear","writeFileSync","Command","Command","chalk","resolve","client","summary","homedir","join","dirname","readFileSync","writeFileSync","mkdirSync","existsSync","readFileSync","writeFileSync","mkdirSync","existsSync","existsSync","readFileSync","writeFileSync","mkdirSync","dirname","existsSync","readFileSync","mkdirSync","dirname","writeFileSync","chalk","homedir","join","chalk","chalk","adoption","adoption","chalk","adoption","chalk","describe","adoption","join","homedir","existsSync","readFileSync","mkdirSync","dirname","writeFileSync","Command","chalk","client","Command","chalk","Command","chalk","statusCommand","Command","statusCommand","Command","Command","chalk","os","Command","chalk","client","os","Command","chalk","SharedSessionClient","client","Command","os","homedir","join","dirname","existsSync","readFileSync","writeFileSync","mkdirSync","Command","chalk","BridgeClient","stableMachineName","join","homedir","existsSync","readFileSync","os","mkdirSync","dirname","writeFileSync","chalk","BridgeClient","Command","describe","Command","chalk","resolve","existsSync","basename","resolve","spawn","writeFileSync","existsSync","readFileSync","mkdirSync","homedir","join","join","homedir","existsSync","readFileSync","mkdirSync","writeFileSync","sessionLink","prompt","resolve","spawn","error","resolve","VERSION","existsSync","resolve","basename","error","session","resolve","Command","chalk","Command","execSync","spawn","chalk","execSync","Command","chalk","spawn","Command","existsSync","mkdirSync","readFileSync","writeFileSync","join","chalk","execSync","Command"]}