{"version":3,"file":"workflowRuntime.cjs","names":["truncateToWidth","visibleWidth","SUBAGENT_ROOT_SESSION_ENV","basename","extname","createRequire","spawn","createEmbeddedWorkflowFeature","randomUUID","readDoomReadinessCoordinator","createDoomReadinessCoordinator","registerRunProvider","defineMinorMode","PACKAGE_SOURCE","WorkflowProgressOverlay","createDoomTelemetry","createNarrationRequest","DOOM_NARRATION_SERVICE","requireDoomNarrationService","resolveRootSessionId","createWorkflowLaunchExecutor","isSessionRun","launchNotice","workflowProgressRow","runsForSession","finishedRunSummary","readWorkflowProgress","summarizeWorkflowProgress","WORKFLOW_FINISHED_MESSAGE","WorkflowTerminalService","createWorkflowTerminalService","TerminalInputBatcher","WorkflowRunPanelComponent","runPanelUiOptions","WorkflowInspectorComponent","withOptions","resolve","readFile","openWorkflowChoice","toolResultText","openWorkflowInput","loadWorkflowCatalog","openWorkflowCatalogOverlay","summarizeWorkflowFile","launchWorkflowEntry","parseWorkflowLaunchCommand","isLaunchParseFailure","resolveWorkflowEntry","validateWorkflowLaunch","openWorkflowPickerOverlay","workflowSkillDirectory","existsSync","createWorkflowFinishedRenderer","isWorkflowStepMessageDetails","renderWorkflowStepMessage","DOOM_UI_HUB_SERVICE","requireDoomUiHub","LEADER_ENABLE_ACTION","LEADER_DISABLE_ACTION","LEADER_MANAGE_ACTION","LEADER_CATALOG_ACTION","LEADER_RECOVER_ACTION","piMinorModes","workflowToolRestriction"],"sources":["../../../src/tui/workflowRuntime.ts"],"sourcesContent":["import { spawn } from 'node:child_process';\nimport { randomUUID } from 'node:crypto';\nimport { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { basename, extname, resolve } from 'node:path';\n\nimport { resolveRootSessionId, SUBAGENT_ROOT_SESSION_ENV } from '@agimon-ai/doompi-core/child-process';\nimport {\n  createNarrationRequest,\n  DOOM_NARRATION_SERVICE,\n  type DoomNarrationService,\n  requireDoomNarrationService,\n} from '@agimon-ai/doompi-core/narration';\nimport type { PiPluginContributions, PiEventHandlers } from '@agimon-ai/doompi-core/pi-extension';\nimport {\n  createDoomReadinessCoordinator,\n  type DoomReadinessCoordinator,\n  type DoomReadinessHandle,\n  type DoomReadinessNotification,\n  readDoomReadinessCoordinator,\n} from '@agimon-ai/doompi-core/readiness';\nimport { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from '@agimon-ai/doompi-core/ui-hub';\nimport { piMinorModes } from '@agimon-ai/doompi-minor-mode';\nimport {\n  defineMinorMode,\n  type MinorModeOwner,\n  type MinorModeOwnerActionContext,\n  type MinorModeState,\n} from '@agimon-ai/doompi-minor-mode';\nimport { createDoomTelemetry, type DoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport {\n  createEmbeddedWorkflowFeature,\n  type EmbeddedWorkflowFeature,\n  readWorkflowProgress,\n  summarizeWorkflowProgress,\n  type Workflow,\n  type WorkflowProgressEvent,\n  type WorkflowProgressJob,\n  type WorkflowRunControl,\n  type WorkflowRunRecord,\n  type WorkflowStage,\n  WorkflowTerminalService,\n} from '@agimon-ai/workflow-mcp';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI, ExtensionContext, Theme } from '@earendil-works/pi-coding-agent';\nimport { type OverlayHandle, truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';\n\nimport {\n  LEADER_DISABLE_ACTION,\n  LEADER_ENABLE_ACTION,\n  LEADER_CATALOG_ACTION,\n  LEADER_MANAGE_ACTION,\n  LEADER_RECOVER_ACTION,\n  PACKAGE_SOURCE,\n} from '../constants/workflow';\nimport { type RunProviderHandle, registerRunProvider } from '../services/backgroundWork';\nimport {\n  finishedRunSummary,\n  isSessionRun,\n  launchNotice,\n  runsForSession,\n  toolResultText,\n  withOptions,\n} from '../services/piToolBridge';\nimport {\n  createWorkflowLaunchExecutor,\n  type WorkflowPiToolDependencies,\n  workflowToolRestriction,\n  type WorkflowLaunchExecutor,\n  type WorkflowLaunchInput,\n} from '../services/workflowExecution';\nimport {\n  isLaunchParseFailure,\n  parseWorkflowLaunchCommand,\n  resolveWorkflowEntry,\n  validateWorkflowLaunch,\n} from '../services/workflowLaunchCommand';\nimport {\n  launchWorkflowEntry,\n  loadWorkflowCatalog,\n  summarizeWorkflowFile,\n  type WorkflowLauncherUi,\n} from '../services/workflowLauncher';\nimport { narrateWorkflowTransition, type WorkflowNarrationSink } from '../services/workflowNarration';\nimport { workflowSkillDirectory } from '../services/workflowResource';\nimport { createWorkflowTerminalService } from '../services/workflowTerminal';\nimport { openWorkflowCatalogOverlay } from './workflow/workflowCatalog';\nimport {\n  createWorkflowFinishedRenderer,\n  type WorkflowFinishedRun,\n  WORKFLOW_FINISHED_MESSAGE,\n} from './workflow/workflowFinishedMessage';\nimport { WorkflowInspectorComponent, type WorkflowInspectorSelection } from './workflow/workflowInspector';\nimport { TerminalInputBatcher } from './workflow/workflowOverlay';\nimport { openWorkflowPickerOverlay } from './workflow/workflowPicker';\nimport { WorkflowProgressOverlay, workflowProgressRow } from './workflow/workflowProgressOverlay';\nimport { openWorkflowChoice, openWorkflowInput } from './workflow/workflowPrompt';\nimport { runPanelUiOptions, WorkflowRunPanelComponent } from './workflow/workflowRunPanel';\nimport { isWorkflowStepMessageDetails, renderWorkflowStepMessage } from './workflow/workflowStepMessage';\n\nconst DOOM_FULLSCREEN_UI_OPTIONS = {\n  overlay: true,\n  overlayOptions: {\n    anchor: 'top-left',\n    width: '100%',\n    maxHeight: '100%',\n    margin: 0,\n  },\n} as const;\n\n/** A run panel currently on screen, and how to take it down. */\ninterface ActiveOverlay {\n  handle?: OverlayHandle;\n  /**\n   * Whether keys typed at this panel can reach the run.\n   *\n   * False for a natively hosted run, which has no multiplexer to address. Such\n   * a panel is opened without focus and must never be given it: typing into it\n   * would go nowhere at all.\n   */\n  interactive: boolean;\n  runKey: string;\n  teardown: () => void;\n}\n\n/** Renderer retained for step cards already persisted by older package versions. */\nconst LEGACY_WORKFLOW_STEP_MESSAGE = 'workflow-step';\nconst FOLLOW_WIDGET_KEY = 'workflow-mcp-follow';\nconst MODE_ID = 'workflow';\nconst MODE_LABEL = 'Workflow';\nconst MODE_LABEL_STYLE = 'accent';\nconst MODE_ORDER = 20;\nconst MODE_ACTION_ACTIVATE = 'activate';\nconst MODE_ACTION_DEACTIVATE = 'deactivate';\n\nfunction workflowModeState(active: boolean, runCount: number): MinorModeState {\n  return {\n    activation: active ? 'active' : 'inactive',\n    condition: 'ready',\n    ...(active ? { detail: runCount > 0 ? `${runCount} active runs` : 'tools enabled', color: MODE_LABEL_STYLE } : {}),\n    actions: [\n      ...(active\n        ? [{ id: MODE_ACTION_ACTIVATE, enabled: false, disabledReason: 'Workflow mode is active.' } as const]\n        : [{ id: MODE_ACTION_ACTIVATE, enabled: true } as const]),\n      ...(active\n        ? [{ id: MODE_ACTION_DEACTIVATE, enabled: true } as const]\n        : [{ id: MODE_ACTION_DEACTIVATE, enabled: false, disabledReason: 'Workflow mode is inactive.' } as const]),\n    ],\n  };\n}\n\nconst LEADER_MODE_BREADCRUMB = 'SPC w e';\nconst CATALOG_BREADCRUMB = 'SPC › w / workflows › l / list';\nconst MANAGE_BREADCRUMB = 'SPC › w / workflows › r / runs';\nconst RECOVER_BREADCRUMB = 'SPC › w / workflows › c / recover';\nconst RUN_PANEL_BREADCRUMB = 'SPC › w / workflows › run';\nconst PAUSED_EXECUTION_STATE = 'paused';\n\nconst UNFOLLOW_SHORTCUT = 'ctrl+alt+w';\n/**\n * Dismisses the run panel.\n *\n * Separate from the focus toggle because a focused panel hands every key to the\n * run, Escape included, so a plain \"Escape closes an overlay\" is unavailable:\n * interrupting the agent inside a step is worth more than a close key. Folding\n * closing into the focus toggle instead would leave an unfocused panel with no\n * way back to typing into the run.\n *\n * Not the only way out. This chord relies on a modifier some terminals do not\n * transmit, so `DoubleEscapeDetector` backs it with a plain double-Escape that\n * every terminal can send.\n */\nconst CLOSE_OVERLAY_SHORTCUT = 'ctrl+alt+q';\n\n/** Modifier glyphs macOS users read on their own keyboards and in every menu. */\nconst MAC_MODIFIER_GLYPHS: Record<string, string> = {\n  alt: '⌥',\n  cmd: '⌘',\n  ctrl: '⌃',\n  meta: '⌘',\n  shift: '⇧',\n};\n\n/**\n * Render a binding the way the user's own platform writes it.\n *\n * The binding string Pi registers stays canonical (`ctrl+alt+w`) on every\n * platform; only the label changes. A macOS user reading \"alt\" has to translate\n * it to the Option key they actually press, and the modifier is not even\n * labelled \"alt\" on most Apple keyboards.\n *\n * Pi branches on `process.platform` for its own keybindings, so this follows a\n * convention already in the host rather than inventing one.\n */\nexport function shortcutLabel(binding: string, platform: NodeJS.Platform = process.platform): string {\n  const parts = binding.split('+');\n  if (platform === 'darwin') {\n    // Glyphs join without separators, as they do in a macOS menu: ⌃⌥W.\n    return parts.map((part) => MAC_MODIFIER_GLYPHS[part] ?? part.toUpperCase()).join('');\n  }\n  return parts.map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join('+');\n}\nconst DEFAULT_PAGE_SIZE = 100;\n/**\n * The reconcile sweep, which is a fallback rather than the mechanism.\n *\n * The observer reports a change as it happens, so this only bounds how long a\n * change nothing notified us about stays invisible. It was 5s when it was the\n * only way anything was noticed.\n */\nconst MONITOR_INTERVAL_MS = 30_000;\n/**\n * Coalescing window for event-driven status refreshes.\n *\n * A run emits several transitions at once, and each one would otherwise page\n * the registry for the authoritative lifecycle snapshot. One page per burst.\n */\nconst STATUS_REFRESH_DEBOUNCE_MS = 120;\nconst PI_EXEC_TIMEOUT_MS = 10_000;\nconst RECOVERY_EVIDENCE_MAX_BYTES = 64 * 1024;\nconst RUNNING_STATUS = 'running';\nconst COMPLETED_STATUS = 'completed';\nconst FAILED_STATUS = 'failed';\nconst ERROR_STAGE = 'error';\nconst ERROR_COLOUR = 'error';\n/**\n * How long shutdown waits for an interrupted inline run to finalize its record.\n *\n * Long enough for a step that honours SIGTERM to unwind and for the registry\n * write that follows, short enough that a step ignoring it does not strand the\n * user in a session that will not close.\n */\nconst SHUTDOWN_FINALIZE_TIMEOUT_MS = 10_000;\nconst FOLLOW_INTERVAL_MS = 2_000;\nconst TAIL_LINES = 24;\n/** Below these a resized run has no room left to draw, so it keeps its own size and the panel clips. */\n/**\n * Overlay refresh cadence and size.\n *\n * Faster than the background widget's 2s: a foregrounded terminal that lags\n * behind your own typing reads as broken, and only the one run being watched\n * pays for it.\n */\nconst OVERLAY_REFRESH_MS = 200;\n/**\n * Slowest part of a refresh, given its own cadence.\n *\n * Reading a run's screen means forking `tmux capture-pane` or `cmux read-screen`,\n * measured at ~75ms. Repainting at 200ms is right for a panel; forking at 200ms\n * is not, so the two are decoupled and only the render keeps the fast tick. A\n * terminal tail is a rolling window of the last few seconds either way, so the\n * slower read costs the reader nothing they can perceive.\n */\nconst SCREEN_REFRESH_MS = 750;\n/**\n * How many recent run announcements the launch handshake can look back through.\n *\n * Only ever searched for a run that registered within the acknowledgement\n * window, so this needs to cover concurrent launches, not session history. The\n * per-session concurrency ceiling is five.\n */\nconst ANNOUNCED_RUN_HISTORY = 32;\n/**\n * Telemetry name for a launch being asked for.\n *\n * Named once because both launch paths, the wizard and the tool, report it and\n * a query that spans them only works while the two agree.\n */\nconst LAUNCH_REQUESTED_EVENT = 'doom_workflow.launch_requested';\n/**\n * Recovery skill shipped by this package, offered to Pi at resource discovery.\n *\n * Recovery is the one path here complex enough to deserve a real skill rather\n * than a few tool guidelines, and this package owns that domain: it cannot\n * assume the host repository provides one. Discovery is cheap, since Pi puts\n * only the name, description, and location in the system prompt and reads the\n * body on demand.\n *\n * Resolved from the module directory, not the module file: `resolve` treats a\n * trailing filename as a path segment. Both `src/extensions` and\n * `dist/extensions` sit two levels below the package root.\n */\n\n/**\n * Glyphs for widgets, panels, and notices.\n *\n * Deliberately restricted to characters that render in a default terminal font.\n * A box-drawing or emoji glyph that falls back to tofu is worse than no glyph.\n */\nconst GLYPH = {\n  running: '▸',\n  repair: '⚠',\n  completed: '✔',\n  failed: '✖',\n  separator: '·',\n} as const;\n\n/**\n * The panel's footer: how to leave, in the order a stuck user needs it.\n *\n * Escape leads on an interactive panel because it is the key every terminal\n * transmits, and the one someone reaches for first when a view will not let go.\n * A view-only panel says so instead: a user who does not know the run is\n * unreachable reads the silence as the panel being broken.\n */\nexport function panelHint(interactive: boolean, platform: NodeJS.Platform = process.platform): string {\n  const close = shortcutLabel(CLOSE_OVERLAY_SHORTCUT, platform);\n  if (!interactive) return `view only ${GLYPH.separator} ${close} closes this view`;\n  return [\n    'Esc Esc closes this view',\n    `${shortcutLabel(UNFOLLOW_SHORTCUT, platform)} switches typing`,\n    `${close} closes`,\n  ].join(` ${GLYPH.separator} `);\n}\n\n/** The same hints as key caps, for the doom footer legend. */\nexport function panelHints(\n  interactive: boolean,\n  platform: NodeJS.Platform = process.platform,\n): readonly (readonly [string, string])[] {\n  const close: readonly [string, string] = [shortcutLabel(CLOSE_OVERLAY_SHORTCUT, platform), 'close'];\n  if (!interactive) return [close];\n  // Leads the legend, and spelled as the copy says it: this cap is the escape\n  // hatch, and the chords beside it ride on a modifier some terminals never send.\n  return [['Esc Esc', 'close'], [shortcutLabel(UNFOLLOW_SHORTCUT, platform), 'switch typing'], close];\n}\n\n/**\n * Header and output lines for the follow widget, fitted to the terminal.\n *\n * Every line a component renders must fit the given width, so the header sheds\n * detail right to left as the terminal narrows: the dismissal hint goes first,\n * then the workspace/stage context, and the run key survives longest because it\n * is the identifier the user needs to name the run.\n *\n * Colour is applied after fitting. Measuring plain text and styling afterwards\n * keeps the arithmetic honest, since escape codes occupy no visible columns.\n */\nfunction renderFollowLines(record: WorkflowRunRecord, output: string[], theme: Theme, width: number): string[] {\n  const key = `${GLYPH.running} ${record.runKey}`;\n  const meta = [record.workspace, stageLabel(record), record.runner].filter(Boolean).join(` ${GLYPH.separator} `);\n  const hint = `${shortcutLabel(UNFOLLOW_SHORTCUT)} to background`;\n  const gap = '   ';\n\n  let header = theme.fg('accent', truncateToWidth(key, width));\n  if (visibleWidth(key) + gap.length + visibleWidth(meta) <= width) {\n    header += gap + theme.fg('muted', meta);\n    const used = visibleWidth(key) + gap.length + visibleWidth(meta);\n    if (used + gap.length + visibleWidth(hint) <= width) header += gap + theme.fg('dim', hint);\n  }\n\n  return [header, ...output.map((line) => truncateToWidth(line, width))];\n}\n\n/**\n * Job tree for the follow widget, in the shape a CI run reads best.\n *\n * Finished jobs collapse to a single line so the eye lands on the one still\n * running, whose steps are listed. That is the whole reason this exists: a\n * scraped terminal shows whatever the runner last printed, which is not the\n * same as knowing which job of how many is in flight.\n */\nfunction renderProgressLines(jobs: WorkflowProgressJob[], theme: Theme, width: number): string[] {\n  const lines: string[] = [];\n  for (const job of jobs) {\n    const glyph =\n      job.status === COMPLETED_STATUS ? GLYPH.completed : job.status === FAILED_STATUS ? GLYPH.failed : GLYPH.running;\n    const colour = job.status === COMPLETED_STATUS ? 'success' : job.status === FAILED_STATUS ? ERROR_COLOUR : 'accent';\n    const position = job.total ? ` ${GLYPH.separator} ${(job.index ?? 0) + 1}/${job.total}` : '';\n    lines.push(truncateToWidth(theme.fg(colour, `${glyph} ${job.name}`) + theme.fg('dim', position), width));\n\n    // Only the job in flight expands. A finished job's steps are noise.\n    if (job.status !== RUNNING_STATUS) continue;\n    for (const step of job.steps) {\n      const stepGlyph =\n        step.status === COMPLETED_STATUS\n          ? GLYPH.completed\n          : step.status === FAILED_STATUS\n            ? GLYPH.failed\n            : GLYPH.running;\n      const stepColour =\n        step.status === RUNNING_STATUS ? 'muted' : step.status === FAILED_STATUS ? ERROR_COLOUR : 'dim';\n      lines.push(truncateToWidth(theme.fg(stepColour, `    ${stepGlyph} ${step.name}`), width));\n    }\n  }\n  return lines;\n}\n\nfunction progressEventsForRun(record: WorkflowRunRecord, events: WorkflowProgressEvent[]): WorkflowProgressEvent[] {\n  const startedAt = Date.parse(record.startedAt);\n  if (!Number.isFinite(startedAt)) return events;\n  return events.filter((event) => {\n    const eventAt = Date.parse(event.at);\n    return !Number.isFinite(eventAt) || eventAt >= startedAt;\n  });\n}\n\n/** Human-readable stage, rather than leaking the raw registry enum. */\nfunction stageLabel(record: WorkflowRunRecord): string {\n  if (record.stale) return 'stale';\n  if (record.stage === ERROR_STAGE) return FAILED_STATUS;\n  return record.stage;\n}\n\ninterface ParsedArguments {\n  invalidLauncher?: string;\n  launcher?: MultiplexerLauncher;\n  name?: string;\n  positionals: string[];\n  runner?: string;\n  workspace?: string;\n}\n\n/** Spawn a launcher and forget it, which is all a delegated run needs from us. */\nexport type DetachedSpawn = (\n  command: string,\n  args: readonly string[],\n  options: { cwd: string; env: NodeJS.ProcessEnv },\n) => Promise<void>;\n\nexport interface WorkflowPiExtensionOptions {\n  /** Captured environment used for session lineage and external child processes. */\n  readonly environment: Readonly<Record<string, string | undefined>>;\n  /** Package plugin context used to resolve session-scoped Cordis services. */\n  cordis?: Context;\n  followIntervalMs?: number;\n  monitorIntervalMs?: number;\n  /** Initial session mode, used by the non-interactive dispatcher composition. */\n  initialMode?: boolean;\n  /** Told about every mode change, so the leader menu can offer the way out rather than the way in. */\n  onModeChange?: (enabled: boolean) => void;\n  featureFactory?: () => EmbeddedWorkflowFeature;\n  /** Reject work inherited from a stale session or disposed package root. */\n  isActive?: () => boolean;\n  runCleanup?: <T>(operation: () => T) => T;\n  /** Injected so a test can read the delegated command without running it. */\n  spawnDetached?: DetachedSpawn;\n  launchAckPollMs?: number;\n  launchAckTimeoutMs?: number;\n}\n\nexport interface WorkflowPiRuntime extends Pick<\n  PiPluginContributions,\n  'events' | 'shortcuts' | 'messageRenderers' | 'services' | 'toolRestrictions'\n> {\n  readonly commands: readonly (readonly [...Parameters<ExtensionAPI['registerCommand']>])[];\n  readonly toolDependencies: WorkflowPiToolDependencies;\n  waitForReadiness(signal?: AbortSignal): Promise<void>;\n  dispose(context?: ExtensionContext): Promise<void>;\n}\n\n/**\n * Multiplexer identity of THIS process, which a launcher spawn must not carry.\n *\n * A child that inherits it records Pi's own workspace as the run's launcher, so\n * every later `open` or `tail` would foreground or scrape this session's screen\n * instead of the run's. The status file is per-step and equally non-inheritable.\n */\nconst CMUX_WORKSPACE_ID_ENV = 'CMUX_WORKSPACE_ID';\nconst TMUX_PANE_ENV = 'TMUX_PANE';\nconst WORKFLOW_TMUX_SESSION_NAME_ENV = 'WORKFLOW_TMUX_SESSION_NAME';\nconst LAUNCHER_ENVIRONMENT_STRIPPED = [\n  'CMUX_SURFACE_ID',\n  SUBAGENT_ROOT_SESSION_ENV,\n  CMUX_WORKSPACE_ID_ENV,\n  TMUX_PANE_ENV,\n  'WORKFLOW_LAUNCHER_TYPE',\n  WORKFLOW_TMUX_SESSION_NAME_ENV,\n  'WORKFLOW_STATUS_FILE',\n] as const;\n\n/**\n * Slack between this process's clock and the run record's timestamp.\n *\n * The record is written by another process, and a launch acknowledged a\n * fraction of a second \"before\" it began is a clock difference, not somebody\n * else's run.\n */\nconst LAUNCH_ACK_CLOCK_SKEW_MS = 2_000;\n\nconst LAUNCHER_ENV = 'WORKFLOW_LAUNCHER';\nconst RECOVER_COMMAND = 'recover-workflow';\nconst LAUNCH_PROCESS_COMMAND = 'launch-process';\n\n/**\n * How a run is hosted, which is also the name of the binary that addresses it.\n *\n * One token per launcher rather than two, because they are the same token: a\n * record's `launcher.type` is `tmux` precisely because tmux is what hosts it and\n * `tmux` is what reads it back. `native` has no binary, which is exactly why\n * every surface has to branch on it.\n */\nconst LAUNCHER_TMUX = 'tmux';\nconst LAUNCHER_CMUX = 'cmux';\nconst LAUNCHER_NATIVE = 'native';\n/** The cmux socket method that answers with a styled render grid rather than plain text. */\n/** The verb the cockpit's launch dialog sends; the leader board does the same work. */\nconst WORKFLOW_LAUNCH_COMMAND = 'workflow-launch';\ntype MultiplexerLauncher = typeof LAUNCHER_TMUX | typeof LAUNCHER_CMUX;\n\nconst HOST_TERMINAL_OUTPUT_BLOCKED =\n  \"This run points at Pi's own terminal, so its launcher screen is hidden. Use workflow status instead.\";\n\n/**\n * Whether stale or inherited launcher metadata addresses this Pi process.\n *\n * Reading such a target recursively captures the chat into its own widget;\n * opening or sending to it can foreground or type into Pi itself. New embedded\n * runs record `native`, but this guard also makes older records safe.\n */\n/**\n * A run with no recorded launcher, which reading and foregrounding both hit.\n *\n * Older records predate launcher identity being persisted, so this is a real\n * state rather than a corrupt one, and both surfaces owe the user the same\n * explanation for it.\n */\nconst NO_LAUNCHER_RECORDED = 'No durable launcher identity is recorded for this run.';\n\n/**\n * The identifier a run record carries for its definition.\n *\n * Derived the same way `RunWorkflowService` derives it, so the two agree: the\n * file name without its final extension, which keeps the `.workflow` part.\n */\nfunction workflowIdFor(workflowPath: string): string {\n  return basename(workflowPath, extname(workflowPath));\n}\n\nfunction launcherEnvironment(environment: Readonly<Record<string, string | undefined>>): NodeJS.ProcessEnv {\n  const env = { ...environment };\n  for (const key of LAUNCHER_ENVIRONMENT_STRIPPED) delete env[key];\n  return env;\n}\n\n/** The launcher the workflow templates default to, when it is a known one. */\nfunction preferredLauncher(environment: Readonly<Record<string, string | undefined>>): MultiplexerLauncher | undefined {\n  const value = environment[LAUNCHER_ENV];\n  return value === LAUNCHER_TMUX || value === LAUNCHER_CMUX ? value : undefined;\n}\n\n/**\n * One shell word per argument.\n *\n * `launch-process` hands `--command` to the launcher as a shell string, so a\n * run key or a path with a space in it has to survive one more round of shell\n * parsing than the argv we spawn with.\n */\nfunction shellCommand(argv: readonly string[]): string {\n  return argv.map((word) => `'${word.replaceAll(\"'\", `'\\\\''`)}'`).join(' ');\n}\n\n/**\n * The workflow-mcp CLI this extension is built against.\n *\n * Resolved from the dependency rather than PATH: `pnpm exec workflow-mcp` finds\n * whatever the workspace root happens to install, which is not necessarily this\n * version, and it pays for a package-manager resolution on the launch path.\n */\nfunction resolveWorkflowCli(): string | undefined {\n  try {\n    return createRequire(import.meta.url).resolve('@agimon-ai/workflow-mcp/cli');\n  } catch {\n    return undefined;\n  }\n}\n\nconst detachedSpawn: DetachedSpawn = async (command, args, options) => {\n  // Detached with no stdio: the run owns a launcher terminal of its own, and\n  // anything inherited from here would be written onto Pi's screen. Wait only\n  // for spawn/error so an immediate exec failure releases the recovery claim.\n  await new Promise<void>((resolveSpawn, rejectSpawn) => {\n    const child = spawn(command, [...args], { ...options, detached: true, stdio: 'ignore' });\n    child.once('error', rejectSpawn);\n    child.once('spawn', () => {\n      child.off('error', rejectSpawn);\n      child.unref();\n      resolveSpawn();\n    });\n  });\n};\n\nfunction tokenize(value: string): string[] {\n  return (\n    value.match(/\"[^\"]*\"|'[^']*'|\\S+/g)?.map((token) => {\n      if ((token.startsWith('\"') && token.endsWith('\"')) || (token.startsWith(\"'\") && token.endsWith(\"'\"))) {\n        return token.slice(1, -1);\n      }\n      return token;\n    }) ?? []\n  );\n}\n\nexport function parseWorkflowCommandArguments(value: string): ParsedArguments {\n  const tokens = tokenize(value);\n  const parsed: ParsedArguments = { positionals: [] };\n  for (let index = 0; index < tokens.length; index += 1) {\n    const token = tokens[index];\n    const next = tokens[index + 1];\n    if (token === '--launcher' && next) {\n      if (next === LAUNCHER_CMUX || next === LAUNCHER_TMUX) parsed.launcher = next;\n      else parsed.invalidLauncher = next;\n      index += 1;\n    } else if (token === '--runner' && next) {\n      parsed.runner = next;\n      index += 1;\n    } else if (token === '--workspace' && next) {\n      parsed.workspace = next;\n      index += 1;\n    } else if (token === '--name' && next) {\n      parsed.name = next;\n      index += 1;\n    } else {\n      parsed.positionals.push(token);\n    }\n  }\n  return parsed;\n}\n\nfunction collectRunnerMaps(value: unknown, maps: string[][]): void {\n  if (Array.isArray(value)) {\n    for (const item of value) collectRunnerMaps(item, maps);\n    return;\n  }\n  if (!value || typeof value !== 'object') return;\n  for (const [key, nested] of Object.entries(value)) {\n    if ((key === 'interactiveRun' || key === 'run') && nested && typeof nested === 'object' && !Array.isArray(nested)) {\n      maps.push(Object.keys(nested));\n    } else {\n      collectRunnerMaps(nested, maps);\n    }\n  }\n}\n\nexport function compatibleRunners(workflow: Workflow): string[] | undefined {\n  const maps: string[][] = [];\n  collectRunnerMaps(workflow, maps);\n  if (maps.length === 0) return undefined;\n  return maps[0].filter((runner) => maps.every((available) => available.includes(runner))).sort();\n}\n\nasync function listAllRuns(\n  registry: EmbeddedWorkflowFeature['registry'],\n  workspace?: string,\n): Promise<WorkflowRunRecord[]> {\n  const records: WorkflowRunRecord[] = [];\n  let page = 1;\n  let hasNextPage = true;\n  while (hasNextPage) {\n    const result = await registry.listRunsPage({ page, pageSize: DEFAULT_PAGE_SIZE, workspace });\n    records.push(...result.items);\n    hasNextPage = result.hasNextPage;\n    page += 1;\n  }\n  return records;\n}\n\n/**\n * One run, as a person reads it.\n *\n * Middle dots rather than pipes: pipes read as table borders in a terminal and\n * collide visually with the launcher output the widget sits above.\n */\nfunction runLabel(record: WorkflowRunRecord): string {\n  return [record.runKey, record.workspace, stageLabel(record), record.runner]\n    .filter(Boolean)\n    .join(` ${GLYPH.separator} `);\n}\n\nexport function createWorkflowPiRuntime(pi: ExtensionAPI, options: WorkflowPiExtensionOptions): WorkflowPiRuntime {\n  const services: NonNullable<PiPluginContributions['services']>[number][] = [];\n  const feature = options.featureFactory?.() ?? createEmbeddedWorkflowFeature();\n  const runtimeGeneration = randomUUID();\n  let runtimeActive = true;\n  let sessionGeneration = 0;\n  let readinessAbort: AbortController | undefined;\n  let readinessHandle: Promise<DoomReadinessHandle<void>> | undefined;\n  let standaloneReadiness: DoomReadinessCoordinator | undefined;\n  const invocationActive = options.isActive ?? (() => true);\n  const isRuntimeActive = (): boolean => runtimeActive && invocationActive();\n  const notifyStandaloneReadiness = (notification: DoomReadinessNotification): void => {\n    const diagnostics = notification.diagnostics.join('; ');\n    const detail = (notification.error?.message ?? diagnostics) || 'Initialization did not complete.';\n    const message = `${notification.packageId} initialization ${notification.state}: ${detail}`;\n    if (sessionCtx?.hasUI) sessionCtx.ui.notify(message, 'warning');\n    else process.emitWarning(message);\n  };\n  const readinessCoordinator = (_ctx: ExtensionContext): DoomReadinessCoordinator => {\n    const shared = options.cordis ? readDoomReadinessCoordinator(options.cordis) : undefined;\n    if (shared) return shared;\n    standaloneReadiness ??= createDoomReadinessCoordinator({ notify: notifyStandaloneReadiness });\n    return standaloneReadiness;\n  };\n  const waitForReadiness = async (signal?: AbortSignal): Promise<void> => {\n    signal?.throwIfAborted();\n    const pending = readinessHandle;\n    if (!pending) throw new Error('Workflow session initialization has not started.');\n    const handle = await pending;\n    signal?.throwIfAborted();\n    await handle.wait(signal ? { signal } : undefined);\n    if (!isRuntimeActive() || pending !== readinessHandle) {\n      throw new Error('Workflow readiness belongs to a stale extension generation.');\n    }\n  };\n  const { parser, recoverService, registry, runService, runTool } = feature;\n  const spawnDetached = options.spawnDetached ?? detachedSpawn;\n  const monitorIntervalMs = options.monitorIntervalMs ?? MONITOR_INTERVAL_MS;\n  const followIntervalMs = options.followIntervalMs ?? FOLLOW_INTERVAL_MS;\n  let monitorTimer: NodeJS.Timeout | undefined;\n  let monitorRefreshGeneration: number | undefined;\n  let followTimer: NodeJS.Timeout | undefined;\n  let followRefreshActive = false;\n  let followedRun: WorkflowRunRecord | undefined;\n  let previousStages = new Map<string, WorkflowStage>();\n  const pendingTerminalRuns = new Map<string, WorkflowRunRecord>();\n  const deliveredTerminalRuns = new Set<string>();\n  let sessionStartedAt = 0;\n  let runProvider: RunProviderHandle | undefined;\n  services.push((context: Context) => {\n    runProvider = registerRunProvider(context);\n  });\n  let lifecycleNarrationReady = false;\n  let sessionRunCount = 0;\n  let workflowMode = false;\n  let publishedWorkflowState: string | undefined;\n  const restrictionListeners = new Set<() => void>();\n  const modeContribution: MinorModeOwner<MinorModeOwnerActionContext<ExtensionContext>> = defineMinorMode<\n    undefined,\n    MinorModeOwnerActionContext<ExtensionContext>\n  >({\n    descriptor: {\n      source: PACKAGE_SOURCE,\n      id: MODE_ID,\n      label: MODE_LABEL,\n      description: 'Workflow discovery, launch, inspection, control, and recovery tools.',\n      order: MODE_ORDER,\n      actions: [\n        {\n          id: MODE_ACTION_ACTIVATE,\n          label: 'Activate',\n          description: 'Enable workflow tools for this session.',\n          contexts: ['tui', 'headless'],\n          parameters: [],\n        },\n        {\n          id: MODE_ACTION_DEACTIVATE,\n          label: 'Deactivate',\n          description: 'Disable workflow tools without stopping active runs.',\n          contexts: ['tui', 'headless'],\n          parameters: [],\n        },\n      ],\n    },\n    state: () => workflowModeState(workflowMode, sessionRunCount),\n    async handleAction(_runtime, actionId, _argumentsValue, execution) {\n      await waitForReadiness();\n      if (actionId === MODE_ACTION_ACTIVATE) {\n        await applyWorkflowMode(true, execution.context);\n        return { message: 'Workflow mode activated.' };\n      }\n      if (actionId === MODE_ACTION_DEACTIVATE) {\n        await applyWorkflowMode(false, execution.context);\n        return { message: 'Workflow mode deactivated.' };\n      }\n      throw new Error(`Unknown workflow mode action: ${actionId}`);\n    },\n  }).createOwner(undefined);\n  /** Kept so callers outside a handler can still resolve the session id. */\n  let sessionCtx: ExtensionContext | undefined;\n  let activeOverlay: ActiveOverlay | undefined;\n  let inspectorHandle: OverlayHandle | undefined;\n  let inspectorOpen = false;\n  /** The runs the inspector last listed, keyed the way its items are. */\n  let inspectorRecords = new Map<string, WorkflowRunRecord>();\n  /**\n   * The pushed view of runs this session owns.\n   *\n   * A delegated run executes in a launcher's process, so nothing in here ever\n   * observes it directly. What it observes is the registry the run writes to,\n   * which is why this replaces polling rather than instrumenting anything.\n   */\n  let runControl: WorkflowRunControl | undefined;\n  const disposeRunControl = new Set<() => void>();\n  /**\n   * Job and step transitions per run, accumulated from pushed events.\n   *\n   * The live list derives its current position from this stream and a failed\n   * run reuses the same events for its terminal summary. Released after that\n   * summary is delivered.\n   */\n  const runEvents = new Map<string, WorkflowProgressEvent[]>();\n  /**\n   * Runs the observer has announced, newest first, for the launch handshake.\n   *\n   * A launch needs the run key of the run it just started, and the launcher\n   * process never learns it. Bounded, because a session that launches all day\n   * must not accumulate a record per launch for the sake of a lookup that\n   * only ever cares about the last few seconds.\n   */\n  const announcedRuns: WorkflowRunRecord[] = [];\n  /** Active records are the authoritative membership of the task-like progress widget. */\n  const activeRunRecords = new Map<string, WorkflowRunRecord>();\n  /** Invalidates a registry snapshot when a newer pushed lifecycle event lands mid-read. */\n  let activeRunRevision = 0;\n  const progressOverlay = new WorkflowProgressOverlay();\n\n  /**\n   * The session that owns this extension's runs.\n   *\n   * Taken from whatever context Pi hands us, and deliberately the SAME value\n   * `launch_workflow` stamps onto a run: reading the stamp from one place and\n   * the filter from another is how a run goes invisible to the session that\n   * just started it. `session_start` fills this in for a session that has\n   * launched nothing yet; before either, it is undefined and every ownership\n   * check fails closed, which is correct because such a session owns no runs.\n   */\n  let knownSessionId: string | undefined;\n  let telemetry: DoomTelemetry | undefined;\n  const getTelemetry = (ctx?: ExtensionContext): DoomTelemetry => {\n    telemetry ??= createDoomTelemetry({\n      serviceName: 'doom-workflow',\n      packageName: '@agimon-ai/doompi-workflow',\n      cwd: ctx?.cwd,\n      env: options.environment,\n      enableLogs: true,\n      enableTraces: true,\n    });\n    return telemetry;\n  };\n  let narrationService: DoomNarrationService | undefined;\n  const reportNarrationFailure = (error: unknown): void => {\n    void getTelemetry(sessionCtx)\n      .recordWarning('doom_workflow.narration_failed', error)\n      .catch((telemetryError: unknown) => {\n        process.emitWarning(`Doom-workflow could not record a narration failure: ${String(telemetryError)}`);\n      });\n  };\n  const narrationSink: WorkflowNarrationSink = {\n    narrate(text) {\n      const service = narrationService;\n      const request = createNarrationRequest(text);\n      if (!service || !request) return;\n      try {\n        void Promise.resolve(service.request(request)).catch(reportNarrationFailure);\n      } catch (error) {\n        reportNarrationFailure(error);\n      }\n    },\n  };\n  services.push((cordis: Context) => {\n    cordis.inject([DOOM_NARRATION_SERVICE], (serviceContext) => {\n      const service = requireDoomNarrationService(serviceContext);\n      narrationService = service;\n      return () => {\n        if (narrationService === service) narrationService = undefined;\n      };\n    });\n  });\n  const observeSession = (sessionId: string | undefined): void => {\n    if (sessionId && isRuntimeActive()) knownSessionId = resolveRootSessionId(sessionId, options.environment);\n  };\n  const currentSessionId = (): string | undefined => {\n    const sessionId = knownSessionId ?? sessionCtx?.sessionManager.getSessionId();\n    return sessionId ? resolveRootSessionId(sessionId, options.environment) : undefined;\n  };\n  const isRootProcess = (ctx: ExtensionContext, rootSessionId: string): boolean =>\n    ctx.sessionManager.getSessionId().trim() === rootSessionId;\n\n  /**\n   * The registry is one directory under $HOME shared by every repository and\n   * every Pi session on the machine, so an unscoped tool would let any session\n   * list, foreground, stop, or recover any other session's runs. Scoping is a\n   * host-level filter on the tool instance, not a caller input: the agent\n   * cannot opt out of it, and the CLI (which is how orphaned runs are managed)\n   * keeps the global view.\n   */\n  const recoverTool = feature.createRecoverTool({\n    // Ownership follows the recovering session. The host supplies identity\n    // out of band; the tool schema cannot choose or override it.\n    ownerSessionId: currentSessionId,\n  });\n  const controlTool = feature.createControlTool();\n\n  /**\n   * Inline executions still in flight, so shutdown can finalize them.\n   *\n   * A workflow declaring `launch-command` hands off to tmux or cmux and its\n   * promise settles almost immediately; one without runs its whole engine in\n   * this process. Only the latter lingers here, so the set needs no launcher\n   * check of its own.\n   */\n  const pendingInlineRuns = new Set<Promise<unknown>>();\n  const trackPendingRun = <T>(run: Promise<T>): Promise<T> => {\n    const startedAt = Date.now();\n    const runTelemetry = getTelemetry();\n    pendingInlineRuns.add(run);\n    void runTelemetry.recordEvent('doom_workflow.run_started', { outcome: 'started' });\n    // Bookkeeping and telemetry share one handler pair on purpose. A separate\n    // `finally` derives a promise that rejects with nobody watching, and an\n    // unhandled rejection ends the process, TUI included. Since a launch is\n    // answered from the registry, nothing else is necessarily awaiting this\n    // run by the time it fails, so this pair is the only thing standing\n    // between a failed launcher and a dead session.\n    void run.then(\n      () => {\n        pendingInlineRuns.delete(run);\n        return runTelemetry.recordEvent('doom_workflow.run_finished', {\n          duration_ms: Date.now() - startedAt,\n          outcome: 'completed',\n        });\n      },\n      (error: unknown) => {\n        pendingInlineRuns.delete(run);\n        return runTelemetry.recordError('doom_workflow.run_failed', error, {\n          duration_ms: Date.now() - startedAt,\n        });\n      },\n    );\n    return run;\n  };\n\n  const rejectRunner = (workflowPath: string, runner: string): string | undefined => {\n    const compatible = compatibleRunners(parser.parseWorkflowFile(workflowPath));\n    if (!compatible || compatible.includes(runner)) return undefined;\n    return `Runner ${JSON.stringify(runner)} is not available across this workflow. Compatible runners: ${compatible.join(', ') || 'none'}.`;\n  };\n\n  const launchExecutor: WorkflowLaunchExecutor = createWorkflowLaunchExecutor({\n    environment: options.environment,\n    activeRunCount: async () => sessionRunCount,\n    observeSession,\n    rejectRunner,\n    runTool,\n    trackPendingRun,\n    ...(options.launchAckPollMs === undefined ? {} : { launchAckPollMs: options.launchAckPollMs }),\n    ...(options.launchAckTimeoutMs === undefined ? {} : { launchAckTimeoutMs: options.launchAckTimeoutMs }),\n    // A run registering is the earliest honest answer to \"did it start?\": the\n    // launcher's own process chain can stay open long after the run is\n    // working, and a launch that waits for it holds the caller's turn open\n    // for as long as that takes.\n    //\n    // Answered from what the observer has announced, with the poll driving a\n    // sweep rather than waiting for one. Reading `announcedRuns` alone would\n    // make the handshake hostage to a filesystem notification, and a dropped\n    // one would cost the caller the whole acknowledgement budget for a run\n    // that had already registered. A sweep costs the registry read this used\n    // to do on its own, and every other surface gets its events from it.\n    findLaunchedRun: async ({ sessionId, since, workflowPath }) => {\n      const expectedId = workflowIdFor(workflowPath);\n      const matches = (record: WorkflowRunRecord): boolean => {\n        if (!isSessionRun(record, sessionId) || record.stale) return false;\n        // Matched on identity as well as time so two launches in flight from\n        // one session cannot report each other's run key.\n        if (record.workflowId && record.workflowId !== expectedId) return false;\n        const startedAt = Date.parse(record.startedAt);\n        return Number.isFinite(startedAt) && startedAt >= since - LAUNCH_ACK_CLOCK_SKEW_MS;\n      };\n      // No observer here: the dispatcher bridge runs the launch tool without\n      // a session of its own, so it still has to look for itself.\n      if (!runControl) return (await listAllRuns(registry)).find(matches);\n      await runControl.refresh();\n      return announcedRuns.find(matches);\n    },\n    // A launch answered early still owes the user its failure.\n    onLateFailure: (error, ctx) => {\n      const detail = error instanceof Error ? error.message : String(error);\n      ctx.ui.notify(launchNotice(`Workflow launch failed after it was reported started.\\n${detail}`), 'warning');\n    },\n    onLaunch: async (ctx) => {\n      await getTelemetry(ctx).recordEvent(LAUNCH_REQUESTED_EVENT, { outcome: 'requested' });\n      return refreshStatus(ctx, false);\n    },\n  });\n\n  /** Repaint the live list from pushed state without writing progress into chat. */\n  const publishProgressOverlay = (): void => {\n    const records = [...activeRunRecords.values()].sort(\n      (left, right) =>\n        Date.parse(left.startedAt) - Date.parse(right.startedAt) || runIdentity(left).localeCompare(runIdentity(right)),\n    );\n    progressOverlay.update(\n      records.map((record) => workflowProgressRow(record, runEvents.get(runIdentity(record)) ?? [])),\n    );\n  };\n\n  /** Add, refresh, or remove one run from the live list. */\n  const noteActiveRecord = (record: WorkflowRunRecord): void => {\n    activeRunRevision += 1;\n    const identity = runIdentity(record);\n    if (record.stage === RUNNING_STATUS && !record.stale) activeRunRecords.set(identity, record);\n    else activeRunRecords.delete(identity);\n    publishProgressOverlay();\n  };\n\n  /** Replace widget membership from an authoritative registry snapshot. */\n  const replaceActiveRecords = (records: readonly WorkflowRunRecord[]): void => {\n    activeRunRecords.clear();\n    for (const record of records) activeRunRecords.set(runIdentity(record), record);\n    publishProgressOverlay();\n  };\n\n  /** Keep every pushed progress event for both the live row and terminal summary. */\n  const noteProgressEvent = (identity: string, event: WorkflowProgressEvent): void => {\n    const events = runEvents.get(identity) ?? [];\n    events.push(event);\n    runEvents.set(identity, events);\n  };\n\n  /**\n   * Ask for a status refresh, collapsing a burst of events into one.\n   *\n   * The live list updates from the event itself, but terminal detection still\n   * needs the session's authoritative record set, and that costs a registry\n   * page. A run emitting six transitions at once must not buy six.\n   */\n  let statusRefreshTimer: NodeJS.Timeout | undefined;\n  const scheduleStatusRefresh = (ctx: ExtensionContext): void => {\n    if (!isRuntimeActive() || ctx !== sessionCtx || statusRefreshTimer) return;\n    statusRefreshTimer = setTimeout(() => {\n      statusRefreshTimer = undefined;\n      if (isRuntimeActive() && ctx === sessionCtx) void refreshStatus(ctx, true);\n    }, STATUS_REFRESH_DEBOUNCE_MS);\n    statusRefreshTimer.unref?.();\n  };\n\n  /** Everything remembered about a run, released once it can produce no more. */\n  const forgetRun = (identity: string): void => {\n    runEvents.delete(identity);\n  };\n\n  /**\n   * Subscribe to the registry instead of asking it what changed.\n   *\n   * A run this session launched executes in a launcher's own process, so the\n   * only thing connecting it to this one is the session stamp on its record.\n   * The filter is that stamp, and it is applied inside the observer so a\n   * shared registry never leaks another session's runs into this UI.\n   */\n  const startRunControl = async (ctx: ExtensionContext): Promise<void> => {\n    const sessionId = resolveRootSessionId(ctx.sessionManager.getSessionId(), options.environment);\n    const control = feature.createRunControl({\n      recordFilter: (candidate) => isSessionRun(candidate, sessionId),\n    });\n    runControl = control;\n    const controlIsCurrent = (): boolean => isRuntimeActive() && ctx === sessionCtx && runControl === control;\n\n    const controlDisposers = [\n      control.on('step', (event) => {\n        if (!controlIsCurrent()) return;\n        const identity = runIdentity(event.record);\n        noteProgressEvent(identity, {\n          at: event.at,\n          job: event.job,\n          status: event.status,\n          step: event.step,\n          type: 'step',\n          ...(event.reason === undefined ? {} : { reason: event.reason }),\n        });\n        noteActiveRecord(event.record);\n        scheduleStatusRefresh(ctx);\n      }),\n      control.on('job', (event) => {\n        if (!controlIsCurrent()) return;\n        const identity = runIdentity(event.record);\n        noteProgressEvent(identity, {\n          at: event.at,\n          job: event.job,\n          status: event.status,\n          type: 'job',\n          ...(event.index === undefined ? {} : { index: event.index }),\n          ...(event.reason === undefined ? {} : { reason: event.reason }),\n          ...(event.total === undefined ? {} : { total: event.total }),\n        });\n        noteActiveRecord(event.record);\n        scheduleStatusRefresh(ctx);\n      }),\n      control.on('runStarted', (event) => {\n        if (!controlIsCurrent()) return;\n        announcedRuns.unshift(event.record);\n        if (announcedRuns.length > ANNOUNCED_RUN_HISTORY) announcedRuns.length = ANNOUNCED_RUN_HISTORY;\n        noteActiveRecord(event.record);\n        scheduleStatusRefresh(ctx);\n      }),\n      control.on('runUpdated', (event) => {\n        if (!controlIsCurrent()) return;\n        noteActiveRecord(event.record);\n        void refreshStatus(ctx, true);\n      }),\n      control.on('runFinished', (event) => {\n        if (!controlIsCurrent()) return;\n        noteActiveRecord(event.record);\n        void refreshStatus(ctx, true);\n      }),\n    ];\n    for (const dispose of controlDisposers) disposeRunControl.add(dispose);\n\n    try {\n      await control.start();\n    } catch (error) {\n      for (const dispose of controlDisposers) {\n        disposeRunControl.delete(dispose);\n        dispose();\n      }\n      control.dispose();\n      if (runControl === control) runControl = undefined;\n      throw error;\n    }\n    if (!isRuntimeActive() || ctx !== sessionCtx || runControl !== control) {\n      for (const dispose of controlDisposers) {\n        disposeRunControl.delete(dispose);\n        dispose();\n      }\n      control.dispose();\n      if (runControl === control) runControl = undefined;\n    }\n  };\n\n  const stopRunControl = (): void => {\n    if (statusRefreshTimer) clearTimeout(statusRefreshTimer);\n    statusRefreshTimer = undefined;\n    for (const dispose of disposeRunControl) dispose();\n    disposeRunControl.clear();\n    runControl?.dispose();\n    runControl = undefined;\n    runEvents.clear();\n    activeRunRevision += 1;\n    activeRunRecords.clear();\n    publishProgressOverlay();\n  };\n\n  /** Dismiss the run panel entirely, leaving the run itself alone. */\n  const closeOverlay = (): void => {\n    activeOverlay?.teardown();\n    activeOverlay?.handle?.hide();\n    activeOverlay = undefined;\n  };\n\n  const runIdentity = (record: WorkflowRunRecord): string => record.runId ?? `${record.workspace}/${record.runKey}`;\n\n  const publishModeWidget = (): void => {\n    const contribution = modeContribution;\n    if (!contribution) return;\n    const next = workflowModeState(workflowMode, sessionRunCount);\n    const serialized = JSON.stringify(next);\n    if (serialized === publishedWorkflowState) return;\n    publishedWorkflowState = serialized;\n    contribution.publish();\n  };\n\n  const refreshStatus = async (ctx: ExtensionContext, notifyChanges: boolean): Promise<void> => {\n    const refreshGeneration = sessionGeneration;\n    const refreshIsCurrent = (): boolean =>\n      isRuntimeActive() && refreshGeneration === sessionGeneration && ctx === sessionCtx;\n    if (!refreshIsCurrent()) return;\n    // Resolved before the guard is latched. Anything that can throw between\n    // setting the flag and entering the try would strand it set, and a\n    // stranded flag turns every later refresh into the early return above:\n    // the run snapshot freezes, so the loop's launch budget never recovers.\n    const activeTelemetry = getTelemetry(ctx);\n    if (monitorRefreshGeneration === refreshGeneration) {\n      void activeTelemetry.recordEvent('doom_workflow.monitor_skipped', { outcome: 'already_running' });\n      return;\n    }\n    const startedAt = Date.now();\n    const activeRevisionAtRead = activeRunRevision;\n    monitorRefreshGeneration = refreshGeneration;\n    try {\n      const records = await listAllRuns(registry);\n      if (!refreshIsCurrent()) return;\n      const sessionId = resolveRootSessionId(ctx.sessionManager.getSessionId(), options.environment);\n      const rootProcess = isRootProcess(ctx, sessionId);\n      const sessionRecords = records.filter((record) => isSessionRun(record, sessionId));\n      const running = sessionRecords.filter((record) => record.stage === RUNNING_STATUS && !record.stale);\n      const failed = sessionRecords.filter((record) => record.stage === ERROR_STAGE);\n      // Never let a snapshot taken before a pushed terminal event resurrect\n      // the row that event just removed. The next refresh can reconcile from\n      // a fresh snapshot if any lifecycle event landed during this read.\n      if (activeRevisionAtRead === activeRunRevision) replaceActiveRecords(running);\n      void activeTelemetry.recordEvent('doom_workflow.monitor_counts', {\n        'workflow.run_count': sessionRecords.length,\n        'workflow.running_count': running.length,\n        'workflow.failed_count': failed.length,\n        mode: workflowMode ? 'on' : 'off',\n      });\n\n      // Runs this Pi session launched, identified by the session stamp the\n      // launch tool puts in the run environment. Publishing them lets other\n      // extensions size their own work without reaching into this one.\n      const mine = runsForSession(records, sessionId).filter((record) => !record.stale);\n      sessionRunCount = mine.length;\n      publishModeWidget();\n\n      // A run that has left the session's set can never produce output again,\n      // so its cached screen is dead weight.\n      forgetLauncherScreens(new Set(sessionRecords.map((record) => runIdentity(record))));\n\n      const nextStages = new Map(sessionRecords.map((record) => [runIdentity(record), record.stage]));\n      for (const record of sessionRecords) {\n        const identity = runIdentity(record);\n        const previous = previousStages.get(identity);\n        const startedAt = Date.parse(record.startedAt);\n        const startedDuringSession =\n          previous === undefined &&\n          (sessionStartedAt === 0 || !Number.isFinite(startedAt) || startedAt >= sessionStartedAt);\n        if (lifecycleNarrationReady) {\n          const narratedPrevious =\n            previous === RUNNING_STATUS || previous === COMPLETED_STATUS || previous === ERROR_STAGE\n              ? previous\n              : undefined;\n          narrateWorkflowTransition(narrationSink, record, narratedPrevious, startedDuringSession);\n        }\n        if (!notifyChanges || !rootProcess || record.stage === RUNNING_STATUS) continue;\n        if (!deliveredTerminalRuns.has(identity) && (previous === RUNNING_STATUS || startedDuringSession)) {\n          pendingTerminalRuns.set(identity, record);\n        }\n      }\n\n      // A terminal run remains background work until Pi accepts the completion\n      // turn. Otherwise another producer can observe an empty snapshot and\n      // continue the agent before the workflow result has been queued.\n      const retainedWork = new Map(mine.map((record) => [runIdentity(record), record]));\n      for (const [identity, record] of pendingTerminalRuns) retainedWork.set(identity, record);\n      if (!refreshIsCurrent()) return;\n      runProvider?.update(\n        [...retainedWork.values()].map((record) => ({ id: record.runId ?? record.runKey, sessionId })),\n      );\n      // Accumulated transitions belong to runs still going or still owed a\n      // summary. Detect terminal deliveries before pruning so a failed run's\n      // in-memory events remain available to its terminal message.\n      const retainedEventIdentities = new Set([\n        ...sessionRecords\n          .filter((record) => record.stage === RUNNING_STATUS && !record.stale)\n          .map((record) => runIdentity(record)),\n        ...pendingTerminalRuns.keys(),\n      ]);\n      for (const identity of runEvents.keys()) {\n        if (!retainedEventIdentities.has(identity)) forgetRun(identity);\n      }\n\n      if (notifyChanges) {\n        for (const record of sessionRecords) {\n          const previous = previousStages.get(runIdentity(record));\n          if (previous !== RUNNING_STATUS || record.stage === RUNNING_STATUS) continue;\n          const completed = record.stage === COMPLETED_STATUS;\n          const detail = record.failedJob ? ` at ${record.failedJob}` : '';\n          ctx.ui.notify(\n            completed\n              ? `${GLYPH.completed} ${record.runKey} completed`\n              : `${GLYPH.failed} ${record.runKey} ${stageLabel(record)}${detail}`,\n            completed ? 'info' : 'warning',\n          );\n          void activeTelemetry.recordEvent('doom_workflow.run_transition', {\n            outcome: completed ? 'completed' : stageLabel(record),\n          });\n        }\n      }\n\n      if (rootProcess && pendingTerminalRuns.size > 0) {\n        try {\n          const terminalRecords = [...pendingTerminalRuns.values()];\n          const summaries = await Promise.all(\n            terminalRecords.map(async (record) => {\n              if (record.stage === COMPLETED_STATUS) return finishedRunSummary(record, []);\n              // A failure needs the job tree to say which job died. The\n              // transitions pushed while the run was going are already in\n              // hand; only a run that finished before this session began\n              // watching has nothing accumulated and has to be read.\n              const identity = runIdentity(record);\n              const events =\n                runEvents.get(identity) ??\n                progressEventsForRun(record, await readWorkflowProgress(registry.runDirectoryFor(record)));\n              return finishedRunSummary(record, summarizeWorkflowProgress(events));\n            }),\n          );\n          if (!refreshIsCurrent()) return;\n          pi.sendMessage(\n            {\n              customType: WORKFLOW_FINISHED_MESSAGE,\n              content: summaries.join('\\n\\n'),\n              display: true,\n              details: {\n                runIds: terminalRecords.map((record) => record.runId ?? runIdentity(record)),\n                runs: terminalRecords.map((record): WorkflowFinishedRun => ({\n                  runKey: record.runKey,\n                  workspace: record.workspace,\n                  stage: record.stage,\n                  ...(record.workflowId ? { workflowId: record.workflowId } : {}),\n                  ...(record.failedJob ? { failedJob: record.failedJob } : {}),\n                  ...(record.errorMessage ? { error: record.errorMessage } : {}),\n                })),\n              },\n            },\n            { triggerTurn: true, deliverAs: 'steer' },\n          );\n          if (!refreshIsCurrent()) return;\n          for (const record of terminalRecords) {\n            const identity = runIdentity(record);\n            deliveredTerminalRuns.add(identity);\n            pendingTerminalRuns.delete(identity);\n            // Its summary has been delivered, so the accumulated transitions\n            // can never be needed again.\n            forgetRun(identity);\n          }\n          runProvider?.update(mine.map((record) => ({ id: record.runId ?? record.runKey, sessionId })));\n        } catch (error) {\n          await activeTelemetry.recordError('doom_workflow.terminal_delivery_failed', error, {\n            'workflow.pending_terminal_count': pendingTerminalRuns.size,\n          });\n        }\n      }\n\n      if (!refreshIsCurrent()) return;\n      previousStages = nextStages;\n      void activeTelemetry.recordEvent('doom_workflow.monitor_finished', {\n        duration_ms: Date.now() - startedAt,\n        outcome: 'completed',\n      });\n    } catch (error) {\n      await activeTelemetry.recordError('doom_workflow.monitor_failed', error, {\n        duration_ms: Date.now() - startedAt,\n      });\n      if (refreshIsCurrent()) {\n        ctx.ui.notify(\n          `Workflow status refresh failed: ${error instanceof Error ? error.message : String(error)}`,\n          'warning',\n        );\n      }\n    } finally {\n      if (monitorRefreshGeneration === refreshGeneration) monitorRefreshGeneration = undefined;\n    }\n  };\n\n  const clearFollow = (ctx: ExtensionContext): void => {\n    if (followTimer) clearInterval(followTimer);\n    followTimer = undefined;\n    followedRun = undefined;\n    ctx.ui.setWidget(FOLLOW_WIDGET_KEY, undefined);\n  };\n\n  /**\n   * This session's view of the terminals its runs were launched into.\n   *\n   * The engine owns how a launcher is read and driven; this owns how often,\n   * which is a property of the surface rather than of the run. Every panel\n   * here repaints five times a second and a scrape forks a CLI, so the two\n   * concerns stayed separate when the reads moved down into the engine.\n   */\n  const terminalFacade = new WorkflowTerminalService({\n    run: async (command, args, options) => {\n      const result = await pi.exec(command, [...args], { timeout: options.timeoutMs });\n      return { code: result.code, stdout: result.stdout, stderr: result.stderr };\n    },\n    lines: TAIL_LINES,\n    timeoutMs: PI_EXEC_TIMEOUT_MS,\n  });\n  const terminals = createWorkflowTerminalService<WorkflowRunRecord>({\n    terminal: terminalFacade,\n    now: () => Date.now(),\n    refreshMs: SCREEN_REFRESH_MS,\n  });\n\n  /**\n   * Geometry last asked of each run, so a repaint that changes nothing costs\n   * no exec. Keyed by run identity, like every other per-run cache here.\n   */\n  const launcherGeometry = new Map<string, string>();\n\n  /**\n   * Match the run's own terminal to the panel showing it.\n   *\n   * A run draws at whatever geometry its launcher gave it, so a panel\n   * narrower than that shows a clipped window onto a wider screen rather than\n   * a smaller rendering of it. Which launchers can be told a size is the\n   * engine's business; not asking twice for the same size is this one's.\n   *\n   * The size is NOT restored when the panel closes: the window belongs to this\n   * run, and a run that is watched at panel size should stay readable at panel\n   * size for whoever attaches to it next.\n   */\n  const resizeLauncherViewport = (record: WorkflowRunRecord, columns: number, rows: number): void => {\n    const identity = runIdentity(record);\n    const geometry = `${columns}x${rows}`;\n    if (launcherGeometry.get(identity) === geometry) return;\n    launcherGeometry.set(identity, geometry);\n    void terminalFacade.resize(record, columns, rows);\n  };\n\n  /**\n   * A run's recent output, reusing a recent read rather than forking again.\n   *\n   * Rendering stays as fast as it ever was: the caller gets the cached lines\n   * immediately and the next repaint picks up whatever the refresh found.\n   */\n  const cachedLauncherScreen = (record: WorkflowRunRecord): Promise<string[]> => {\n    // Answered here rather than by the engine: the engine cannot know that\n    // the caller's own terminal is a Pi session with a status surface to\n    // send the reader to instead.\n    if (terminalFacade.targetsCurrentTerminal(record)) return Promise.resolve([HOST_TERMINAL_OUTPUT_BLOCKED]);\n    return terminals.screen(runIdentity(record), record, TAIL_LINES);\n  };\n\n  /** Runs whose screens can never change again cannot earn their memory back. */\n  const forgetLauncherScreens = (live: Set<string>): void => {\n    terminals.forget(live);\n    // The geometry cache is per run for the same reason the screens are: a\n    // run that is gone can never be resized again.\n    for (const identity of launcherGeometry.keys()) {\n      if (!live.has(identity)) launcherGeometry.delete(identity);\n    }\n  };\n\n  /**\n   * Bring a run's launcher to the foreground.\n   *\n   * Returns a status line rather than notifying, because its only caller is now\n   * the `workflow_run` tool's `open` action and the agent needs to read the outcome.\n   */\n  const openLauncher = async (record: WorkflowRunRecord): Promise<string> => {\n    const launcher = record.launcher;\n    if (!launcher) return NO_LAUNCHER_RECORDED;\n    if (terminalFacade.targetsCurrentTerminal(record)) return HOST_TERMINAL_OUTPUT_BLOCKED;\n    if (launcher.type === LAUNCHER_NATIVE) {\n      return 'This run is hosted natively rather than in a multiplexer, so there is no separate window to bring forward.';\n    }\n    if (launcher.type === LAUNCHER_CMUX) {\n      await pi.exec(LAUNCHER_CMUX, ['select-workspace', '--workspace', launcher.workspaceId], {\n        timeout: PI_EXEC_TIMEOUT_MS,\n      });\n      return `Opened ${record.runKey} in cmux.`;\n    }\n    if (!options.environment.TMUX) {\n      return 'Pi is not attached to tmux. Follow the output instead, or attach to the recorded tmux session manually.';\n    }\n    const target = launcher.sessionId ?? launcher.sessionName;\n    const result = await pi.exec(LAUNCHER_TMUX, ['switch-client', '-t', target], { timeout: PI_EXEC_TIMEOUT_MS });\n    if (result.code !== 0) return result.stderr.trim() || `Unable to open tmux session ${target}.`;\n    if (launcher.paneId) {\n      await pi.exec(LAUNCHER_TMUX, ['select-pane', '-t', launcher.paneId], { timeout: PI_EXEC_TIMEOUT_MS });\n    }\n    return `Opened ${record.runKey} in tmux.`;\n  };\n\n  const renderFollow = async (record: WorkflowRunRecord, ctx: ExtensionContext): Promise<void> => {\n    if (followRefreshActive) return;\n    followRefreshActive = true;\n    try {\n      // Prefer the run's own progress log: it says which job and step are in\n      // flight, which a scraped screen cannot. Runs started before progress\n      // recording existed, and any run whose log is not readable, still get\n      // the terminal tail.\n      const jobs = summarizeWorkflowProgress(\n        progressEventsForRun(record, await readWorkflowProgress(registry.runDirectoryFor(record))),\n      );\n      const lines = jobs.length > 0 ? undefined : await cachedLauncherScreen(record);\n      // Component factory rather than a string array, for two reasons the\n      // string form cannot give us: render() receives the terminal width, so\n      // launcher output can be fitted instead of overflowing, and the theme is\n      // applied fresh on every render, so a theme switch repaints correctly\n      // without any cached colours to invalidate.\n      ctx.ui.setWidget(\n        FOLLOW_WIDGET_KEY,\n        (_tui, theme) => ({\n          render: (width: number) =>\n            renderFollowLines(record, lines ?? renderProgressLines(jobs, theme, width), theme, width),\n          invalidate: () => {\n            // Nothing cached: render() rebuilds from the current theme.\n          },\n        }),\n        { placement: 'aboveEditor' },\n      );\n    } finally {\n      followRefreshActive = false;\n    }\n  };\n\n  const followRun = async (record: WorkflowRunRecord, ctx: ExtensionContext): Promise<void> => {\n    clearFollow(ctx);\n    followedRun = record;\n    await renderFollow(record, ctx);\n    followTimer = setInterval(() => {\n      if (followedRun) void renderFollow(followedRun, ctx);\n    }, followIntervalMs);\n    followTimer.unref?.();\n  };\n\n  /**\n   * Forward literal text to a run's terminal.\n   *\n   * `tmux send-keys -l` and `cmux send` both take text verbatim, which keeps\n   * escape sequences intact: an arrow key must arrive as one sequence, not as\n   * a bracket and a letter. A natively hosted run has no multiplexer to\n   * address, so it reports rather than silently dropping the keystrokes.\n   */\n  const sendToRun = async (record: WorkflowRunRecord, text: string): Promise<void> => {\n    // Silently, because a panel only builds a keyboard for a run whose\n    // capabilities already said yes: reaching here with an unwritable run\n    // means the run changed under the panel, which is not the typist's problem.\n    if (!terminalFacade.capabilities(record).writable) return;\n    await terminalFacade.write(record, text);\n  };\n\n  /**\n   * Show a run over Pi: job tree, live output, and a keyboard that reaches it.\n   *\n   * Blocks until the user closes it, which is what makes it feel like the run\n   * rather than a report about the run. The refresh runs faster than the\n   * background widget because a foregrounded terminal that lags behind your\n   * own typing reads as broken.\n   */\n  /**\n   * Show a run over Pi as a persistent panel, not a modal.\n   *\n   * Returns as soon as the panel is up rather than awaiting its close. An\n   * awaited overlay would hold the tool call open, which freezes the agent\n   * mid-turn and makes \"switch back to the main agent\" impossible: there is\n   * nothing to switch back to while it is still waiting for a tool result.\n   *\n   * Focus, not lifetime, is what the user toggles. The panel stays on screen\n   * while typing goes back to Pi, so Escape stays free for the run's own\n   * agent, which uses it to interrupt.\n   */\n  const openOverlay = async (record: WorkflowRunRecord, ctx: ExtensionContext): Promise<string> => {\n    closeOverlay();\n    // Exactly what the engine says this run's terminal will take. A run with\n    // no reachable terminal gets a panel that is a view rather than a\n    // keyboard, and saying so up front beats letting the user type into nothing.\n    const interactive = terminalFacade.capabilities(record).writable;\n    const input = new TerminalInputBatcher((text) => sendToRun(record, text));\n    let jobs: WorkflowProgressJob[] = [];\n    let output: string[] = [];\n    let refresh: NodeJS.Timeout | undefined;\n\n    let polling = false;\n    const poll = async (): Promise<void> => {\n      jobs = summarizeWorkflowProgress(\n        progressEventsForRun(record, await readWorkflowProgress(registry.runDirectoryFor(record))),\n      );\n      output = await cachedLauncherScreen(record);\n    };\n    await poll();\n\n    const teardown = (): void => {\n      if (refresh) clearInterval(refresh);\n      refresh = undefined;\n      input.dispose();\n    };\n\n    const entry: ActiveOverlay = { interactive, runKey: record.runKey, teardown };\n    activeOverlay = entry;\n\n    /** Shared by the panel footer, the close chord, and the double-Escape failsafe. */\n    const closeWithNotice = (): void => {\n      closeOverlay();\n      ctx.ui.notify(`Closed the ${record.runKey} view. The run keeps going.`, 'info');\n    };\n\n    // Deliberately not awaited: the panel outlives this tool call.\n    void ctx.ui.custom<void>(\n      (tui, theme, _keybindings, done) => {\n        // Guarded, because a tick that outlives its interval would otherwise\n        // start another read on top of the last one and keep doing so. The\n        // progress log is a local file and the screen read is coalesced, so a\n        // skipped tick costs nothing: the next one repaints from the same state.\n        refresh = setInterval(() => {\n          if (polling) return;\n          polling = true;\n          void poll().finally(() => {\n            polling = false;\n            tui.requestRender();\n          });\n        }, OVERLAY_REFRESH_MS);\n        refresh.unref?.();\n\n        return new WorkflowRunPanelComponent(tui, theme, {\n          runKey: record.runKey,\n          label: `${GLYPH.running} ${runLabel(record)}`,\n          breadcrumb: RUN_PANEL_BREADCRUMB,\n          interactive,\n          footer: panelHint(interactive),\n          hints: panelHints(interactive),\n          snapshot: (width) => ({ progress: renderProgressLines(jobs, theme, width), output }),\n          onViewport: (columns, rows) => resizeLauncherViewport(record, columns, rows),\n          onUnfollow: () => {\n            entry.handle?.unfocus();\n            ctx.ui.notify('Typing goes to this session. The run keeps going.', 'info');\n          },\n          onClose: closeWithNotice,\n          sendInput: (data) => input.write(data),\n          // `flush` takes the pending bytes synchronously and sends them in the\n          // background, so the panel still closes on the same keystroke.\n          // Without it the run would be interrupted or not depending on whether\n          // the user out-typed a 16ms timer, which is not a behaviour anyone can\n          // predict or rely on.\n          flushInput: () => void input.flush(),\n          unfollowShortcut: UNFOLLOW_SHORTCUT,\n          closeShortcut: CLOSE_OVERLAY_SHORTCUT,\n          onDispose: () => {\n            teardown();\n            if (activeOverlay === entry) activeOverlay = undefined;\n            done();\n          },\n        });\n      },\n      {\n        ...runPanelUiOptions(interactive),\n        onHandle: (handle) => {\n          entry.handle = handle;\n        },\n      },\n    );\n\n    // Told to the user directly, not only through the tool result. The result\n    // is addressed to the agent, and the panel's own footer is one dim line\n    // that a user watching a run scroll past can easily miss. A view you\n    // cannot work out how to leave is the thing to avoid here.\n    ctx.ui.notify(\n      interactive\n        ? `${record.runKey}: typing goes to the run. Press Esc twice to close, ${shortcutLabel(UNFOLLOW_SHORTCUT)} to type here instead.`\n        : `${record.runKey}: view only, because this run is hosted natively. ${shortcutLabel(CLOSE_OVERLAY_SHORTCUT)} closes it.`,\n      'info',\n    );\n\n    if (!interactive) {\n      return [\n        `Showing ${record.runKey} over Pi, as a view only:`,\n        'the run is hosted natively rather than in a multiplexer, so there is no terminal to type into.',\n        `Typing stays with this session, and ${shortcutLabel(CLOSE_OVERLAY_SHORTCUT)} closes the view.`,\n      ].join(' ');\n    }\n\n    return [\n      `Showing ${record.runKey} over Pi. Typing goes to the run.`,\n      'Pressing Escape twice quickly closes the view, and a single Escape still reaches the run.',\n      `${shortcutLabel(UNFOLLOW_SHORTCUT)} moves typing between the run and this session,`,\n      `and ${shortcutLabel(CLOSE_OVERLAY_SHORTCUT)} closes the view. The run keeps going either way.`,\n    ].join(' ');\n  };\n\n  const openInspector = async (ctx: ExtensionContext, manage = false): Promise<void> => {\n    if (inspectorOpen || activeOverlay || followedRun) return;\n    inspectorOpen = true;\n    try {\n      const selection = await ctx.ui.custom<WorkflowInspectorSelection | undefined>(\n        (tui, theme, _keybindings, done) =>\n          new WorkflowInspectorComponent(\n            tui,\n            theme,\n            {\n              list: async () => {\n                const sessionId = currentSessionId();\n                const records = (await listAllRuns(registry)).filter(\n                  (record) => record.stage === RUNNING_STATUS && !record.stale && isSessionRun(record, sessionId),\n                );\n                // Kept so `output` can address the run under the cursor without\n                // paging the whole registry a second time on every refresh.\n                inspectorRecords = new Map(records.map((record) => [runIdentity(record), record]));\n                return Promise.all(\n                  records.map(async (record) => ({\n                    displayName: record.displayName,\n                    executionState: record.executionState,\n                    jobs: summarizeWorkflowProgress(\n                      progressEventsForRun(record, await readWorkflowProgress(registry.runDirectoryFor(record))),\n                    ),\n                    key: runIdentity(record),\n                    output: [],\n                    runKey: record.runKey,\n                    startedAt: record.startedAt,\n                    workspace: record.workspace,\n                  })),\n                );\n              },\n              output: async (item) => {\n                const record = inspectorRecords.get(item.key);\n                return record ? cachedLauncherScreen(record) : ['Workflow is no longer active.'];\n              },\n            },\n            done,\n          ),\n        {\n          ...DOOM_FULLSCREEN_UI_OPTIONS,\n          onHandle: (handle) => {\n            inspectorHandle = handle;\n          },\n        },\n      );\n      if (selection) {\n        const record = await requireRun(selection);\n        if (manage) await manageWorkflow(record, ctx);\n        else await openOverlay(record, ctx);\n      }\n    } finally {\n      inspectorHandle = undefined;\n      inspectorOpen = false;\n      inspectorRecords.clear();\n    }\n  };\n\n  /**\n   * Resolve a run this session owns, erroring rather than picking blindly.\n   *\n   * A run another session launched is reported exactly like one that does not\n   * exist. Distinguishing them would leak the shared registry's contents into\n   * a session that has no way to act on them anyway, and would invite the\n   * agent to keep trying keys it can never use.\n   */\n  const requireRun = async (\n    input: { runKey: string; workspace?: string },\n    sessionId: string | undefined = currentSessionId(),\n  ): Promise<WorkflowRunRecord> => {\n    observeSession(sessionId);\n    const records = await listAllRuns(registry, input.workspace);\n    const matches = records.filter(\n      (candidate) => candidate.runKey === input.runKey && isSessionRun(candidate, sessionId),\n    );\n    if (matches.length > 1) {\n      throw new Error(\n        withOptions(\n          `Workflow run key ${JSON.stringify(input.runKey)} exists in more than one workspace in this session.`,\n          ['Retry with the workspace from the run identity.'],\n        ),\n      );\n    }\n    const record = matches[0];\n    if (!record) {\n      throw new Error(\n        withOptions(`No workflow run matches ${JSON.stringify(input.runKey)} in this session.`, [\n          'workflow_run with action status: use a run key from this session before retrying.',\n          'Tell the user this session did not launch that run rather than guessing a similar key. A run launched by another Pi session, or from the command line, is managed there or with the workflow-mcp CLI.',\n        ]),\n      );\n    }\n    return record;\n  };\n\n  /**\n   * Resolve a failed run that this session may adopt through recovery.\n   *\n   * Failed runs are terminal and have no live owner to conflict with. This is\n   * intentionally the only cross-session lookup. Recovery-specific status\n   * and durable evidence reads may use it; live output, lifecycle controls,\n   * and running-run UI stay scoped to the launching session.\n   */\n  const requireRecoverableRun = async (input: { runKey: string; workspace?: string }): Promise<WorkflowRunRecord> => {\n    const matches = (await listAllRuns(registry, input.workspace)).filter(\n      (candidate) => candidate.runKey === input.runKey && candidate.stage === ERROR_STAGE,\n    );\n    if (matches.length > 1) {\n      throw new Error(\n        withOptions(`Failed workflow run key ${JSON.stringify(input.runKey)} exists in more than one workspace.`, [\n          'Retry with the workspace from the recovery picker or run identity.',\n        ]),\n      );\n    }\n    const record = matches[0];\n    if (!record) {\n      throw new Error(\n        withOptions(`No failed workflow run matches ${JSON.stringify(input.runKey)}.`, [\n          'Use the recovery picker to select an interrupted or failed run, or retry with its workspace.',\n          'Do not recover a running or completed workflow.',\n        ]),\n      );\n    }\n    return record;\n  };\n\n  const readRecoveryEvidenceTail = async (record: WorkflowRunRecord): Promise<string[]> => {\n    const runDir = registry.runDirectoryFor(record);\n    const paths = [resolve(runDir, 'changelog.md'), resolve(runDir, 'context.md'), resolve(runDir, 'progress.ndjson')];\n    const sections: string[] = [];\n    for (const path of paths) {\n      try {\n        const content = await readFile(path, 'utf-8');\n        sections.push(`--- ${basename(path)} ---`, content.slice(-RECOVERY_EVIDENCE_MAX_BYTES).trimEnd());\n      } catch (error) {\n        if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n      }\n    }\n    return sections.length > 0 ? sections : ['No durable recovery evidence files are recorded for this run.'];\n  };\n\n  /** Read-only evidence access for the one globally adoptable record class. */\n  const readRecoverableRunEvidence = async (\n    input: { runKey: string; workspace?: string },\n    ctx: ExtensionContext,\n  ): Promise<string> => {\n    const record = await requireRecoverableRun(input);\n    await getTelemetry(ctx).recordEvent('doom_workflow.recovery_evidence_requested', { outcome: 'requested' });\n    return [\n      `Workflow: ${runLabel(record)}`,\n      '--- run.json ---',\n      JSON.stringify(record, null, 2),\n      ...(await readRecoveryEvidenceTail(record)),\n    ].join('\\n');\n  };\n\n  /**\n   * Recover a run in a launcher of its own instead of replaying it here.\n   *\n   * `RecoverWorkflowService` replays with the launch step skipped, so an\n   * in-process recovery runs every job inside this process. A workflow whose\n   * steps are `interactiveRun` then has its agent spawned with inherited\n   * stdio, because that agent needs a real TTY to draw. Inside Pi that TTY is\n   * the TUI: the agent draws over it, and the reset sequence written when the\n   * step ends is one Pi never issued and cannot repaint from. Delegating\n   * costs a process and keeps the screen.\n   *\n   * Undefined leaves the caller on the in-process path: a workflow that\n   * declares no `launch-command` has no launcher to delegate to, and a\n   * definition that cannot be read is better diagnosed by the replay itself.\n   */\n  const delegateRecovery = async (\n    input: { runKey: string; workspace?: string; runner?: string },\n    ctx: ExtensionContext,\n  ): Promise<string | undefined> => {\n    const cli = resolveWorkflowCli();\n    if (!cli) return undefined;\n    const record = await requireRecoverableRun(input);\n    let workflow: Workflow;\n    try {\n      workflow = parser.parseWorkflowFile(record.workflowPath);\n    } catch {\n      return undefined;\n    }\n    if (!workflow['launch-command']) return undefined;\n\n    // Mint the transfer capability in the shared registry before spawning.\n    // The delegated CLI can only adopt this exact terminal record and gets\n    // the owner identity from the claim rather than caller-controlled argv.\n    const sessionId = resolveRootSessionId(ctx.sessionManager.getSessionId(), options.environment);\n    const claim = await registry.claimRunRecovery(record.workspace, record.runKey, sessionId);\n    const cwd = record.originalRepoPath ?? ctx.cwd;\n    const recoverCommand = shellCommand([\n      process.execPath,\n      cli,\n      RECOVER_COMMAND,\n      record.runKey,\n      '--workspace',\n      record.workspace,\n      '--recovery-claim',\n      claim.claimId,\n      ...(input.runner ? ['--runner', input.runner] : []),\n    ]);\n    const launcher = preferredLauncher(options.environment);\n    try {\n      await spawnDetached(\n        process.execPath,\n        [\n          cli,\n          LAUNCH_PROCESS_COMMAND,\n          ...(launcher ? ['--launcher', launcher] : []),\n          '--name',\n          `${record.displayName} recover`,\n          '--cwd',\n          cwd,\n          '--command',\n          recoverCommand,\n        ],\n        { cwd, env: launcherEnvironment(options.environment) },\n      );\n    } catch (error) {\n      await registry.releaseRunRecoveryClaim(record.workspace, record.runKey, claim.claimId);\n      throw error;\n    }\n    await getTelemetry(ctx).recordEvent('doom_workflow.recover_delegated', {\n      launcher: launcher ?? 'auto',\n      outcome: 'delegated',\n    });\n    return `Recovering ${record.runKey} in a launcher of its own, so this session keeps its terminal. It reports back here when it ends.`;\n  };\n\n  const manageWorkflow = async (selected: WorkflowRunRecord, ctx: ExtensionContext): Promise<void> => {\n    let record = selected;\n    while (true) {\n      const actions = ['Open output'];\n      const state = record.executionState ?? RUNNING_STATUS;\n      if (state === RUNNING_STATUS) actions.push('Pause');\n      if (state === PAUSED_EXECUTION_STATE) actions.push('Resume');\n      if (record.stage === RUNNING_STATUS) actions.push('Stop');\n      actions.push('Back');\n      const action = await openWorkflowChoice(ctx, {\n        title: `Manage ${record.runKey}`,\n        breadcrumb: MANAGE_BREADCRUMB,\n        choices: actions,\n      });\n      if (!action || action === 'Back') return;\n\n      record = await requireRun(record);\n      if (record.stage !== RUNNING_STATUS) {\n        ctx.ui.notify(`${record.runKey} is no longer running.`, 'warning');\n        return;\n      }\n      if (action === 'Open output') {\n        await openOverlay(record, ctx);\n        return;\n      }\n      if (action === 'Stop') {\n        const confirmed = await ctx.ui.confirm(\n          `Stop ${record.runKey}?`,\n          'The workflow will be interrupted and will not be restarted automatically.',\n        );\n        if (!confirmed) continue;\n        record = await requireRun(record);\n        if (record.stage !== RUNNING_STATUS) {\n          ctx.ui.notify(`${record.runKey} is no longer running.`, 'warning');\n          return;\n        }\n      }\n      if (action !== 'Pause' && action !== 'Resume' && action !== 'Stop') continue;\n      if (!record.runId) throw new Error(`${record.runKey} has no controllable run generation.`);\n      const result = await controlTool.execute({\n        action: action.toLowerCase() as 'pause' | 'resume' | 'stop',\n        expectedRunId: record.runId,\n        ...(action === 'Stop' ? { reason: 'Stopped from the workflow manager.' } : {}),\n        runKey: record.runKey,\n        workspace: record.workspace,\n      });\n      if (result.isError) throw new Error(toolResultText(result) || `Unable to ${action.toLowerCase()} workflow.`);\n      ctx.ui.notify(toolResultText(result) || `${action} requested for ${record.runKey}.`, 'info');\n      await refreshStatus(ctx, false);\n      record = await requireRun(record);\n    }\n  };\n\n  /**\n   * The wizard's prompts, backed by doom overlays instead of Pi's native\n   * widgets, so a launch reads as one framed sequence rather than three styles.\n   *\n   * `editor` stays with Pi: the workflow prompt is multi-line authoring, and\n   * reimplementing a text editor to match a frame would be a poor trade.\n   */\n  const doomLauncherUi = (ctx: ExtensionContext, breadcrumb: string): WorkflowLauncherUi => ({\n    editor: (title, prefill) => ctx.ui.editor(title, prefill),\n    input: (title, placeholder) =>\n      openWorkflowInput(ctx, { title, breadcrumb, ...(placeholder ? { fallback: placeholder } : {}) }),\n    notify: (message, type) => ctx.ui.notify(message, type),\n    select: (title, options) => openWorkflowChoice(ctx, { title, breadcrumb, choices: options }),\n  });\n\n  /**\n   * `SPC w l`: the repository's workflows, the cursor workflow's parsed\n   * detail beside it, and `r` to launch that one. Launching closes the board\n   * first - the launch prompts are host dialogs, and a fullscreen overlay\n   * would sit over them.\n   */\n  const openWorkflowCatalog = async (ctx: ExtensionContext): Promise<void> => {\n    if (!ctx.hasUI) {\n      ctx.ui.notify('The workflow list needs an interactive Pi session.', 'warning');\n      return;\n    }\n    const entries = await loadWorkflowCatalog(feature.listWorkflowsTool, ctx.cwd);\n    const byPath = new Map(entries.map((entry) => [entry.path, entry]));\n    const launchOptions = {\n      compatibleRunners,\n      launch: (input: WorkflowLaunchInput, launchContext: ExtensionContext) =>\n        launchExecutor.execute(input, launchContext),\n      parseWorkflow: (workflowPath: string) => parser.parseWorkflowFile(workflowPath),\n      ui: doomLauncherUi(ctx, CATALOG_BREADCRUMB),\n    };\n    await openWorkflowCatalogOverlay(\n      ctx,\n      entries.map((entry) => ({\n        key: entry.path,\n        name: entry.name,\n        relativePath: entry.relativePath,\n        description: entry.description,\n        tags: entry.tags,\n      })),\n      {\n        loadDetail: (row) => summarizeWorkflowFile(row.key, launchOptions),\n        launchWorkflow: (row) => {\n          const entry = byPath.get(row.key);\n          if (!entry) return;\n          void launchWorkflowEntry(launchOptions, entry, ctx).then(\n            (result) => {\n              // Trimmed, because a launch that ran in this process answers\n              // with the engine's whole console log, and notifying that\n              // verbatim paints tens of lines of banner and job tree over\n              // the transcript.\n              if (result) ctx.ui.notify(launchNotice(toolResultText(result)), 'info');\n            },\n            (error: unknown) => {\n              ctx.ui.notify(error instanceof Error ? error.message : String(error), 'error');\n            },\n          );\n        },\n      },\n    );\n  };\n\n  /**\n   * `/workflow-launch`: the same launch the catalog board performs, as a line.\n   *\n   * The cockpit can only send a session a prompt frame, so this is how a\n   * browser starts a workflow; typing it by hand does the same thing. Every\n   * value the board would have asked for in a dialog arrives on the line, and\n   * what the workflow requires is checked before anything is started, because\n   * a run missing its prompt starts and then waits for terminal input that is\n   * never coming.\n   */\n  const launchFromCommand = async (args: string, ctx: ExtensionContext): Promise<void> => {\n    const parsed = parseWorkflowLaunchCommand(args);\n    if (isLaunchParseFailure(parsed)) {\n      ctx.ui.notify(parsed.error, 'error');\n      return;\n    }\n    const entries = await loadWorkflowCatalog(feature.listWorkflowsTool, ctx.cwd);\n    const entry = resolveWorkflowEntry(entries, parsed.workflow);\n    if (!entry) {\n      ctx.ui.notify(`No workflow matches '${parsed.workflow}' under ${ctx.cwd}.`, 'error');\n      return;\n    }\n    const detail = summarizeWorkflowFile(entry.path, {\n      compatibleRunners,\n      parseWorkflow: (workflowPath: string) => parser.parseWorkflowFile(workflowPath),\n    });\n    if (detail.error !== undefined) {\n      ctx.ui.notify(`${entry.name} could not be read: ${detail.error}`, 'error');\n      return;\n    }\n    const problems = validateWorkflowLaunch(detail, parsed);\n    if (problems.length > 0) {\n      ctx.ui.notify(problems.join(' '), 'error');\n      return;\n    }\n    const workflow = parser.parseWorkflowFile(entry.path);\n    const input: WorkflowLaunchInput = {\n      workflowPath: entry.path,\n      ...(parsed.runner === undefined ? {} : { runner: parsed.runner }),\n      ...(typeof workflow.workspace === 'string' ? { workspace: workflow.workspace } : {}),\n      ...(parsed.prompt === undefined ? {} : { prompt: parsed.prompt }),\n      ...(Object.keys(parsed.inputs).length === 0 ? {} : { inputs: parsed.inputs }),\n    };\n    const result = await launchExecutor.execute(input, ctx);\n    // Trimmed for the same reason the board trims it: a launch that ran in\n    // this process answers with the engine's whole console log.\n    ctx.ui.notify(launchNotice(toolResultText(result)), 'info');\n  };\n\n  const commands: WorkflowPiRuntime['commands'] = [\n    [\n      WORKFLOW_LAUNCH_COMMAND,\n      {\n        description: 'Launch a workflow: /workflow-launch <workflow> [runner=x] [key=value …] [prompt]',\n        handler: async (args, ctx) => {\n          await waitForReadiness();\n          try {\n            await launchFromCommand(args, ctx);\n          } catch (error) {\n            ctx.ui.notify(error instanceof Error ? error.message : String(error), 'error');\n          }\n        },\n      },\n    ],\n  ];\n\n  const openRecoveryHandoff = async (ctx: ExtensionContext): Promise<void> => {\n    // Recovery adopts terminal work. Include failed runs from dead or other\n    // sessions here; passive UI and all controls over live runs stay scoped.\n    const records = (await listAllRuns(registry)).filter((record) => record.stage === ERROR_STAGE);\n    if (records.length === 0) {\n      ctx.ui.notify('No failed workflows are available to recover.', 'info');\n      return;\n    }\n    const chosen = await openWorkflowPickerOverlay(\n      ctx,\n      {\n        title: 'WORKFLOW RECOVERY',\n        breadcrumb: RECOVER_BREADCRUMB,\n        unit: 'failed runs',\n        action: 'recover',\n        filterPlaceholder: 'type to filter by name, run key or failed job',\n        emptyMessage: 'No failed workflows are available to recover.',\n      },\n      records.map((record) => ({\n        key: `${record.workspace}/${record.runKey}`,\n        name: record.displayName,\n        detail: `${record.workspace}/${record.runKey}${record.failedJob ? ` · ${record.failedJob}` : ''}`,\n        ...(record.failedJob ? { search: record.failedJob } : {}),\n        value: record,\n      })),\n    );\n    if (!chosen) return;\n    const record = await requireRecoverableRun(chosen);\n    if (record.stage !== ERROR_STAGE) throw new Error(`${record.runKey} is no longer failed.`);\n    const skillFile = resolve(workflowSkillDirectory(), 'workflow-recovery', 'SKILL.md');\n    if (!existsSync(skillFile)) throw new Error(`Workflow recovery skill is unavailable at ${skillFile}.`);\n    setWorkflowMode(true);\n    ctx.ui.notify(\n      'Workflow tools enabled. The agent will investigate this failure and choose the safe next step.',\n      'info',\n    );\n    pi.sendUserMessage(\n      [\n        'Investigate recovery for this failed workflow run. This selection is permission to investigate, not permission to recover blindly.',\n        `Run identity: ${JSON.stringify({ runKey: record.runKey, workspace: record.workspace })}`,\n        `Read the package-owned recovery skill with the read tool at ${JSON.stringify(skillFile)} before acting.`,\n        'Inspect status, every relevant log source, process state, the staged run.json, and only the repair referenced by activeRepairId.',\n        'Choose exactly one outcome: recover, launch fresh, or defer. Never edit issue.md or repair.json, never scan historical repairs, and never pass recovery dryRun or a job override.',\n        'Do not recover terminal, approval-pending, blocked, or otherwise unsafe work. If evidence is incomplete, defer and explain what is missing.',\n        'If recovery is justified, preserve the recorded worktree and repair metadata, then verify real process and registry progress before reporting success.',\n      ].join('\\n'),\n      { deliverAs: 'followUp' },\n    );\n  };\n\n  /**\n   * Turn workflow mode on or off.\n   *\n   * The tools are registered for the whole session, so the mode is a tool\n   * surface restriction rather than a registration: dropping it is what makes\n   * them visible again, and no other owner's tools are touched either way.\n   *\n   * Activating also injects each tool's `promptSnippet` and `promptGuidelines`\n   * into the system prompt, and deactivating strips them: in Pi, tool gating\n   * and instruction injection are the same lever.\n   */\n  const setWorkflowMode = (enabled: boolean): void => {\n    if (!isRuntimeActive()) return;\n    workflowMode = enabled;\n    restrictionListeners.forEach((listener) => listener());\n    // Published here rather than in refreshStatus so the label lands with the\n    // toggle: the status refresh is an async registry read, and a label that\n    // waits for it looks like the command did nothing.\n    publishModeWidget();\n    options.onModeChange?.(enabled);\n  };\n\n  /**\n   * What the user sees on every mode change.\n   *\n   * Leads with the state, then the one thing they can do next. Turning the\n   * mode on is useless without knowing that you now just ask in plain\n   * language, so that sentence earns its place; the tool count does not, and\n   * is left to the README.\n   */\n  const modeSummary = (): string =>\n    workflowMode\n      ? [\n          `${GLYPH.completed} Workflow mode on`,\n          'Ask for workflows in plain language: the agent can list, launch, inspect, pause, resume, stop, and recover runs.',\n          `${shortcutLabel(UNFOLLOW_SHORTCUT)} stops following a run without stopping it.`,\n        ].join('\\n')\n      : [\n          'Workflow mode off',\n          `Press ${LEADER_MODE_BREADCRUMB} to give the agent its workflow tools. Runs already going are unaffected.`,\n        ].join('\\n');\n\n  /**\n   * Toggle the mode from the leader menu.\n   *\n   * Replaces the `/workflow [on|off|status]` command: the mode line already\n   * answers `status` at a glance, and the other two arguments were a keyboard\n   * path to a switch the leader menu spells out. Plan mode is reached the same\n   * way, so the two modes are no longer toggled through different surfaces.\n   */\n  const applyWorkflowMode = async (enabled: boolean, ctx: ExtensionContext): Promise<void> => {\n    setWorkflowMode(enabled);\n    if (!workflowMode) clearFollow(ctx);\n    ctx.ui.notify(modeSummary(), 'info');\n    // Both directions: turning off has to clear the indicator, not just leave\n    // the last one on screen until the monitor next fires.\n    await refreshStatus(ctx, false);\n  };\n\n  // Zero palette cost, unlike a command. Guarded on an active follow so it\n  // does not swallow the key when there is nothing to dismiss.\n\n  // Dismissing is its own key because the panel cannot use Escape: a focused\n  // panel forwards every key to the run so its agent stays interruptible.\n\n  // A battery-included mode must not add model-visible skills while dormant.\n  // Discovery follows session_start, so environment-driven dispatcher\n  // activation is visible at startup while the normal parent remains neutral.\n  // The existence guard also fails closed if packaging ever drops the skill.\n  const onResourcesDiscover: NonNullable<PiEventHandlers['resources_discover']> = () => {\n    if (!workflowMode) return { skillPaths: [] };\n    const skillPath = workflowSkillDirectory();\n    return { skillPaths: existsSync(skillPath) ? [skillPath] : [] };\n  };\n\n  const messageRenderers: PiPluginContributions['messageRenderers'] = [\n    createWorkflowFinishedRenderer(),\n    [\n      LEGACY_WORKFLOW_STEP_MESSAGE,\n      (message, { outputPad }, theme) => {\n        const details = isWorkflowStepMessageDetails(message.details) ? message.details : undefined;\n        const content = typeof message.content === 'string' ? message.content : JSON.stringify(message.content);\n        return renderWorkflowStepMessage(details, content, outputPad, theme);\n      },\n    ],\n  ];\n\n  const toolDependencies: WorkflowPiToolDependencies = {\n    environment: options.environment,\n    runTool,\n    recoverTool,\n    launchExecutor,\n    controlTool,\n    requireSessionRun: requireRun,\n    requireRecoverableRun,\n    readRecoveryEvidence: readRecoverableRunEvidence,\n    delegateRecovery,\n    trackPendingRun,\n    observeSession,\n    activeRunCount: async () => sessionRunCount,\n    onLaunch: async (ctx) => {\n      await getTelemetry(ctx).recordEvent(LAUNCH_REQUESTED_EVENT, { outcome: 'requested' });\n      return refreshStatus(ctx, false);\n    },\n    followRun: async (input, ctx) => {\n      const record = await requireRun(input, ctx.sessionManager.getSessionId());\n      await getTelemetry(ctx).recordEvent('doom_workflow.follow_started', { outcome: 'started' });\n      await followRun(record, ctx);\n      return `Following ${runLabel(record)}. Press ${shortcutLabel(UNFOLLOW_SHORTCUT)} to stop following; the run keeps going.`;\n    },\n    tailRun: async (input, ctx) => {\n      const record = await requireRun(input, ctx.sessionManager.getSessionId());\n      await getTelemetry(ctx).recordEvent('doom_workflow.tail_requested', { outcome: 'requested' });\n      return [\n        `Workflow: ${runLabel(record)}`,\n        `Stage: ${stageLabel(record)}`,\n        'Raw launcher output is hidden from chat. Use action follow or open to view it.',\n      ].join('\\n');\n    },\n    openRun: async (input, ctx) => {\n      const record = await requireRun(input, ctx.sessionManager.getSessionId());\n      await getTelemetry(ctx).recordEvent('doom_workflow.open_requested', { outcome: 'requested' });\n      // Without a UI there is nothing to foreground, so fall back to handing\n      // the user's own terminal to the launcher.\n      if (!ctx.hasUI) return openLauncher(record);\n      return openOverlay(record, ctx);\n    },\n    rejectRunner,\n  };\n\n  let disposeLeaderActions: (() => void) | undefined;\n  services.push((cordis: Context) => {\n    cordis.inject([DOOM_UI_HUB_SERVICE], (uiContext) => {\n      const dispose = requireDoomUiHub(uiContext).registerLeaderActions<ExtensionContext>({\n        source: PACKAGE_SOURCE,\n        handlers: {\n          [LEADER_ENABLE_ACTION]: async (ctx) => {\n            await waitForReadiness();\n            return applyWorkflowMode(true, ctx);\n          },\n          [LEADER_DISABLE_ACTION]: async (ctx) => {\n            await waitForReadiness();\n            return applyWorkflowMode(false, ctx);\n          },\n          [LEADER_MANAGE_ACTION]: async (ctx) => {\n            await waitForReadiness();\n            return openInspector(ctx, true);\n          },\n          [LEADER_CATALOG_ACTION]: async (ctx) => {\n            await waitForReadiness();\n            return openWorkflowCatalog(ctx);\n          },\n          [LEADER_RECOVER_ACTION]: async (ctx) => {\n            await waitForReadiness();\n            return openRecoveryHandoff(ctx);\n          },\n        },\n        onError: (error, _actionName, ctx) => {\n          ctx.ui.notify(error instanceof Error ? error.message : String(error), 'error');\n        },\n      });\n      disposeLeaderActions = dispose;\n      return () => {\n        dispose();\n        if (disposeLeaderActions === dispose) disposeLeaderActions = undefined;\n      };\n    });\n  });\n\n  const onSessionStart: NonNullable<PiEventHandlers['session_start']> = (_event, ctx) => {\n    if (!runtimeActive || !invocationActive()) return;\n    const generation = ++sessionGeneration;\n    const previousReadiness = readinessHandle;\n    readinessAbort?.abort();\n    const ownReadinessAbort = new AbortController();\n    readinessAbort = ownReadinessAbort;\n    sessionCtx = ctx;\n    const ownsSession = (): boolean =>\n      runtimeActive && generation === sessionGeneration && sessionCtx === ctx && invocationActive();\n\n    // A second start retires every resource tied to the previous context\n    // before this context can publish its own state.\n    const retireSessionResources = (): void => {\n      stopRunControl();\n      if (monitorTimer) clearInterval(monitorTimer);\n      monitorTimer = undefined;\n      runProvider?.update([]);\n      clearFollow(ctx);\n      inspectorHandle?.hide();\n      inspectorHandle = undefined;\n      inspectorOpen = false;\n      inspectorRecords.clear();\n      closeOverlay();\n      terminals.forget(new Set());\n      progressOverlay.setUICtx(ctx.ui);\n    };\n    if (options.runCleanup) options.runCleanup(retireSessionResources);\n    else retireSessionResources();\n\n    const activeTelemetry = getTelemetry(ctx);\n    void activeTelemetry.recordEvent('doom_workflow.session_started', {\n      mode: options.environment.WORKFLOW_MCP_MODE === 'on' ? 'on' : 'off',\n      outcome: 'started',\n    });\n\n    // Tools registered during extension init are auto-activated by Pi, so the\n    // default-off state has to be applied here rather than by not registering.\n    // WORKFLOW_MCP_MODE=on is the non-interactive dispatcher path.\n    const sessionId = ctx.sessionManager.getSessionId();\n    const rootSessionId = resolveRootSessionId(sessionId, options.environment);\n    observeSession(rootSessionId);\n    sessionStartedAt = Date.now();\n    lifecycleNarrationReady = false;\n    previousStages = new Map<string, WorkflowStage>();\n    pendingTerminalRuns.clear();\n    deliveredTerminalRuns.clear();\n    setWorkflowMode(options.initialMode ?? options.environment.WORKFLOW_MCP_MODE === 'on');\n\n    const coordinator = readinessCoordinator(ctx);\n    readinessHandle = (async (): Promise<DoomReadinessHandle<void>> => {\n      if (previousReadiness) {\n        await Promise.allSettled([previousReadiness.then((handle) => handle.wait())]);\n      }\n      if (!ownsSession()) throw new Error('Workflow session initialization was superseded.');\n      return coordinator.start(PACKAGE_SOURCE, `${runtimeGeneration}:${generation}`, async (signal) => {\n        const retired = (): boolean => ownReadinessAbort.signal.aborted || !ownsSession();\n        signal.throwIfAborted();\n        if (retired()) return { value: undefined };\n\n        // Subscribed before the first status read, so a transition landing\n        // during startup is delivered rather than raced past.\n        await startRunControl(ctx);\n        signal.throwIfAborted();\n        if (retired()) return { value: undefined };\n        await refreshStatus(ctx, false);\n        signal.throwIfAborted();\n        if (retired()) return { value: undefined };\n        lifecycleNarrationReady = true;\n        // A fallback now, not the mechanism: the observer reports a change\n        // within its own debounce, and this only bounds how long a change\n        // nothing notified us about stays invisible.\n        monitorTimer = setInterval(() => {\n          if (ownsSession()) void refreshStatus(ctx, true);\n        }, monitorIntervalMs);\n        monitorTimer.unref?.();\n        return { value: undefined };\n      });\n    })();\n    // The coordinator host owns the single user-facing failure notification;\n    // this observer only ensures an idle failed task is still handled.\n    void Promise.allSettled([readinessHandle.then((handle) => handle.wait())]);\n  };\n\n  const runCleanup = async (label: string, cleanup: () => void | Promise<void>): Promise<void> => {\n    try {\n      await cleanup();\n    } catch (error) {\n      process.emitWarning(`Doom-workflow cleanup could not ${label}: ${String(error)}`);\n    }\n  };\n\n  let disposal: Promise<void> | undefined;\n  const dispose = (context: ExtensionContext | undefined = sessionCtx): Promise<void> => {\n    disposal ??= (async () => {\n      if (!runtimeActive) return;\n      runtimeActive = false;\n      sessionGeneration += 1;\n      const pendingReadiness = readinessHandle;\n      readinessHandle = undefined;\n      readinessAbort?.abort();\n      readinessAbort = undefined;\n      await runCleanup('stop the workflow observer', stopRunControl);\n      const ownedReadiness = standaloneReadiness;\n      standaloneReadiness = undefined;\n      if (ownedReadiness) {\n        await runCleanup('dispose standalone workflow readiness', () => ownedReadiness.dispose());\n      } else if (pendingReadiness) {\n        await Promise.allSettled([pendingReadiness.then((handle) => handle.wait())]);\n      }\n\n      // A workflow without a `launch-command` runs its engine inside this\n      // process. Interrupt it and wait only for the bounded finalization path.\n      if (pendingInlineRuns.size > 0) {\n        for (const service of [runService, recoverService]) {\n          await runCleanup('interrupt an inline workflow', () =>\n            service.interrupt('SIGTERM', { phase: 'workflow', source: 'pi-session-shutdown' }),\n          );\n        }\n        await Promise.race([\n          Promise.allSettled(pendingInlineRuns),\n          new Promise((settle) => setTimeout(settle, SHUTDOWN_FINALIZE_TIMEOUT_MS).unref?.()),\n        ]);\n      }\n      if (monitorTimer) clearInterval(monitorTimer);\n      monitorTimer = undefined;\n      if (statusRefreshTimer) clearTimeout(statusRefreshTimer);\n      statusRefreshTimer = undefined;\n      const provider = runProvider;\n      runProvider = undefined;\n      if (provider) await runCleanup('unregister the background-work provider', () => provider.dispose());\n      lifecycleNarrationReady = false;\n      inspectorHandle?.hide();\n      inspectorHandle = undefined;\n      inspectorOpen = false;\n      inspectorRecords.clear();\n      terminals.forget(new Set());\n      closeOverlay();\n      sessionRunCount = 0;\n      if (context) clearFollow(context);\n      else if (followTimer) clearInterval(followTimer);\n      followTimer = undefined;\n      followedRun = undefined;\n      progressOverlay.dispose();\n      workflowMode = false;\n      publishedWorkflowState = undefined;\n      const mode = modeContribution;\n\n      if (mode) {\n        await runCleanup('publish the inactive workflow mode', () => mode.publish());\n        await runCleanup('dispose the workflow mode owner', () => mode.detach());\n      }\n      const leaderActions = disposeLeaderActions;\n      disposeLeaderActions = undefined;\n      if (leaderActions) await runCleanup('dispose workflow leader actions', leaderActions);\n      const pendingCount = pendingInlineRuns.size;\n      const activeTelemetry = telemetry;\n      telemetry = undefined;\n      if (activeTelemetry) {\n        await runCleanup('record the workflow session finish', () =>\n          activeTelemetry.recordEvent('doom_workflow.session_finished', {\n            'workflow.pending_count': pendingCount,\n            outcome: pendingCount === 0 ? 'completed' : 'interrupted',\n          }),\n        );\n        await runCleanup('stop workflow telemetry', () => activeTelemetry.shutdown());\n      }\n      pendingInlineRuns.clear();\n      pendingTerminalRuns.clear();\n      deliveredTerminalRuns.clear();\n      announcedRuns.length = 0;\n      knownSessionId = undefined;\n      sessionCtx = undefined;\n    })();\n    return disposal;\n  };\n\n  return {\n    dispose,\n    commands,\n    messageRenderers,\n    toolDependencies,\n    waitForReadiness,\n    services: [...(services ?? []), piMinorModes([modeContribution])],\n    shortcuts: [\n      [\n        UNFOLLOW_SHORTCUT,\n        {\n          description: 'Open workflows or move typing between a workflow run and this session',\n          handler: async (ctx) => {\n            await waitForReadiness();\n            // With a panel up this is a focus toggle, not a dismissal: the run stays\n            // visible either way, and the user is only choosing who receives keys.\n            const handle = activeOverlay?.handle;\n            if (handle) {\n              // pi-tui's `focus()` does not honour `nonCapturing`, so a view-only\n              // panel would take the keyboard if this were left to fall through,\n              // and every key after it would vanish into a run that cannot hear it.\n              if (!activeOverlay?.interactive) {\n                ctx.ui.notify('This run is hosted natively, so the view takes no typing. Your keys stay here.', 'info');\n                return;\n              }\n              if (handle.isFocused()) {\n                handle.unfocus();\n                ctx.ui.notify('Typing goes to this session. The run keeps going.', 'info');\n              } else {\n                handle.focus();\n                ctx.ui.notify(`Typing goes to ${activeOverlay?.runKey}.`, 'info');\n              }\n              return;\n            }\n            if (followedRun) {\n              clearFollow(ctx);\n              ctx.ui.notify('Workflow continues in the background.', 'info');\n              return;\n            }\n            await openInspector(ctx);\n          },\n        },\n      ],\n      [\n        CLOSE_OVERLAY_SHORTCUT,\n        {\n          description: 'Close the workflow run view',\n          handler: async (ctx) => {\n            await waitForReadiness();\n            // Guarded so the key falls through to Pi when no panel is up.\n            if (!activeOverlay) return;\n            const runKey = activeOverlay.runKey;\n            closeOverlay();\n            ctx.ui.notify(`Closed the ${runKey} view. The run keeps going.`, 'info');\n          },\n        },\n      ],\n    ],\n    events: { session_start: onSessionStart, resources_discover: onResourcesDiscover },\n\n    toolRestrictions: [\n      {\n        source: PACKAGE_SOURCE,\n        get restrict() {\n          return workflowToolRestriction(workflowMode);\n        },\n        subscribe(listener) {\n          restrictionListeners.add(listener);\n          return () => {\n            restrictionListeners.delete(listener);\n          };\n        },\n      },\n    ],\n  };\n}\n"],"mappings":"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"}