{"version":3,"file":"planMode-CtsDYMUp.mjs","names":["PRIVATE_DIRECTORY_MODE","PRIVATE_FILE_MODE","isRecord","loadDoomConfig","snapshot","custom"],"sources":["../src/services/optionalTeamServices/index.ts","../src/services/planPointer/index.ts","../src/types/planApi.ts","../src/services/planMode/index.ts"],"sourcesContent":["import type { Context } from '@deepseek-ai/cordis';\n\nimport { FABLE_PLAN_REQUESTER, type FablePlanRequest, type FablePlanResult } from '../fableFlow';\n\nexport const DOOM_FABLE_PLAN_SERVICE = 'doom/fable-plan';\nexport const DOOM_SUBAGENT_POLICY_SERVICE = 'doom/subagent-policy';\n\nexport interface DoomFablePlanService {\n  start(request: FablePlanRequest, signal: AbortSignal): Promise<FablePlanResult>;\n  cancel(request: { requester: typeof FABLE_PLAN_REQUESTER; operationId: string; reason: string }): void;\n}\n\nexport interface SubagentPolicy {\n  owner: string;\n  allowedTools?: string[];\n  requiredTools?: string[];\n  allowMcpTools?: boolean;\n  allowedExternalProfiles?: string[];\n  denyExtensions?: boolean;\n}\n\nexport interface SubagentPolicyHandle {\n  update(policy: SubagentPolicy): void;\n  dispose(): void;\n}\n\nexport interface DoomSubagentPolicyService {\n  register(policy: SubagentPolicy): SubagentPolicyHandle;\n}\n\ntype StructuralServiceContext = {\n  get(name: string): unknown;\n};\n\nexport function readDoomFablePlanService(ctx: Context): DoomFablePlanService | undefined {\n  return (ctx as unknown as StructuralServiceContext).get(DOOM_FABLE_PLAN_SERVICE) as DoomFablePlanService | undefined;\n}\n\nexport function readDoomSubagentPolicyService(ctx: Context): DoomSubagentPolicyService | undefined {\n  return (ctx as unknown as StructuralServiceContext).get(DOOM_SUBAGENT_POLICY_SERVICE) as\n    | DoomSubagentPolicyService\n    | undefined;\n}\n","import { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport type { PlanPointerRecord } from '../../types/planApi';\nimport type { PlanPointerPort } from '../../types/planPointer';\n\n/**\n * Record and read where write_plan left this session's plan file.\n *\n * Pi already gives every session an agent directory, so the records live under\n * it rather than in a second place a reader would have to know about. The\n * posture matches the plan file itself, 0700 on the directory and 0600 on the\n * record: a plan is a private working document, not something to leave\n * world-readable in a shared home.\n */\n\nconst POINTER_DIRECTORY = 'doom-plan';\nconst AGENT_DIRECTORY = ['.pi', 'agent'];\nconst PRIVATE_DIRECTORY_MODE = 0o700;\nconst PRIVATE_FILE_MODE = 0o600;\n\nexport interface NodePlanPointerOptions {\n  env?: NodeJS.ProcessEnv;\n  homeDirectory?: string;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nexport class PlanPointerService implements PlanPointerPort {\n  private readonly env: NodeJS.ProcessEnv;\n  private readonly homeDirectory: string;\n\n  constructor(options: NodePlanPointerOptions = {}) {\n    this.env = options.env ?? {};\n    this.homeDirectory = options.homeDirectory ?? os.homedir();\n  }\n\n  /** Where the records live; exposed so a test can look without guessing. */\n  directory(): string {\n    const agentDirectory = this.env.PI_CODING_AGENT_DIR || path.join(this.homeDirectory, ...AGENT_DIRECTORY);\n    return path.join(agentDirectory, POINTER_DIRECTORY);\n  }\n\n  /**\n   * The record for one session. The id is hashed rather than used as written:\n   * it reaches here from a host that may word it however it likes, and a\n   * filename is not the place to find that out.\n   */\n  pathFor(sessionId: string): string {\n    return path.join(this.directory(), `${this.hash(sessionId)}.json`);\n  }\n\n  read(sessionId: string): PlanPointerRecord | undefined {\n    let raw: string;\n    try {\n      raw = fs.readFileSync(this.pathFor(sessionId), 'utf8');\n    } catch {\n      return undefined;\n    }\n    let parsed: unknown;\n    try {\n      parsed = JSON.parse(raw);\n    } catch {\n      return undefined;\n    }\n    if (!isRecord(parsed)) return undefined;\n    const { path: planPath, title, writtenAt, planId } = parsed;\n    // A record half-written by an interrupted run reads as no plan at all,\n    // which is a state the cockpit already handles.\n    if (typeof planPath !== 'string' || !path.isAbsolute(planPath)) return undefined;\n    if (typeof title !== 'string' || typeof writtenAt !== 'string') return undefined;\n    return { path: planPath, title, writtenAt, ...(typeof planId === 'string' ? { planId } : {}) };\n  }\n\n  write(sessionId: string, record: PlanPointerRecord): void {\n    fs.mkdirSync(this.directory(), { recursive: true, mode: PRIVATE_DIRECTORY_MODE });\n    fs.writeFileSync(this.pathFor(sessionId), JSON.stringify(record), { mode: PRIVATE_FILE_MODE });\n  }\n\n  clear(sessionId: string): void {\n    fs.rmSync(this.pathFor(sessionId), { force: true });\n  }\n\n  private hash(value: string): string {\n    return createHash('sha256').update(value).digest('hex').slice(0, 16);\n  }\n}\n","/**\n * The wire vocabulary this package's API shares with whatever calls it.\n *\n * It lives under src/types because that is the one server root a browser\n * bundle may read: the routes answer with these shapes and the cockpit plugin\n * reads them, so neither half can drift from the other. The paths themselves\n * are not here; they are declared once in `./apiRoutes`, which the Hono app\n * and the generated client both read.\n *\n * Two routes, and neither takes a path. A session has one current plan, so\n * `current` answers it and `content` takes the manual save back; the file they\n * act on is the one write_plan recorded, never one the page named. That is\n * also why there is nothing to escape here: a reader cannot address a second\n * file through these URLs.\n */\n\n/** Where a host mounts this package's API; the segment after /api/plugins/. */\nexport const API_BASE_PATH = 'plans';\n\n/**\n * Footer status key the session publishes once a plan exists, which is what\n * makes the cockpit's activity group appear at all. It outlives plan mode: the\n * plan is most worth reading while the agent implements it.\n */\nexport const PLAN_STATUS_KEY = 'doom-plan-document';\n\n/** The selector contract shared by complete_plan and its cockpit composer prompt. */\nexport const PLAN_REVIEW_TITLE = 'Plan complete. What would you like to do?';\nexport const EXIT_PLAN_MODE_CHOICE = 'Exit plan mode and start implementation';\nexport const CONTINUE_PLANNING_CHOICE = 'Continue planning';\nexport const EXIT_PLAN_DECISION = 'exit';\nexport const CONTINUE_PLAN_DECISION = 'continue';\n\n/**\n * The label the reader sees paired with the decision the tool acts on. A headless\n * client answers with `value`, so a facet never has to recognise the wording; Pi's\n * own `ui.select` carries labels only, so its half maps the label back itself.\n */\nexport const PLAN_REVIEW_CHOICES = [\n  { label: EXIT_PLAN_MODE_CHOICE, value: EXIT_PLAN_DECISION },\n  { label: CONTINUE_PLANNING_CHOICE, value: CONTINUE_PLAN_DECISION },\n] as const;\n\n/** The same options as bare labels, which is all Pi's select and the composer prompt need. */\nexport const PLAN_REVIEW_OPTIONS = PLAN_REVIEW_CHOICES.map((choice) => choice.label);\n\n/** Between the plan's title and the stamp that marks a rewrite. */\nconst STATUS_SEPARATOR = ' · ';\n\n/** Strips the colour a session may have themed a status with. */\nconst ANSI = /\u001b\\[[0-9;]*m/gu;\n\n/** The status line the session publishes; the stamp changes on every write. */\nexport function formatPlanStatus(title: string, stamp: string): string {\n  return `${title}${STATUS_SEPARATOR}${stamp}`;\n}\n\n/** What a reader gets out of the status line. */\nexport interface PlanStatusView {\n  title: string;\n  /** When the plan was last written, as the session worded it; empty when it said nothing. */\n  stamp: string;\n}\n\n/**\n * Reading the status line back. Statuses reach a plugin raw, so the colour a\n * session may have added comes off here. A title can itself contain the\n * separator, so the stamp is taken from the last one rather than the first.\n */\nexport function parsePlanStatus(raw: string | undefined): PlanStatusView | undefined {\n  if (raw === undefined) return undefined;\n  const text = raw.replace(ANSI, '').trim();\n  if (text === '') return undefined;\n  const cut = text.lastIndexOf(STATUS_SEPARATOR);\n  if (cut === -1) return { title: text, stamp: '' };\n  return { title: text.slice(0, cut).trim(), stamp: text.slice(cut + STATUS_SEPARATOR.length).trim() };\n}\n\n/**\n * What write_plan recorded about this session's plan.\n *\n * The absolute path is the point of it: the extension resolves the plans\n * directory against the harness root, which no other process knows, so it\n * writes down where the plan landed rather than leaving the API to derive a\n * location it would sometimes get wrong.\n */\nexport interface PlanPointerRecord {\n  path: string;\n  title: string;\n  writtenAt: string;\n  planId?: string;\n}\n\n/** The plan as it stands on disk right now, which is what the source view edits. */\nexport interface PlanDetailView {\n  path: string;\n  title: string;\n  writtenAt: string;\n  planId?: string;\n  content: string;\n  /** sha256 of the content; the token a save hands back to prove it is not stale. */\n  hash: string;\n  /** True when the plan is missing or past the size cap, so `content` is empty. */\n  unavailable: boolean;\n  reason?: string;\n}\n\n/** What the save route takes. */\nexport interface PlanSaveRequest {\n  /** The hash the reader loaded; a mismatch means the plan moved underneath them. */\n  expectedHash: string;\n  content: string;\n}\n\n/** What the save route answers with. */\nexport interface PlanSaveView {\n  hash: string;\n}\n\n/** What a route reports when it refuses; the page shows `error` verbatim. */\nexport interface PlanErrorView {\n  error: string;\n  /** On a stale save, the hash the plan actually has now. */\n  hash?: string;\n}\n","import { Buffer } from 'node:buffer';\nimport { createHash, randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { globalDoomConfigPath } from '@agimon-ai/doompi-config';\nimport { setDoomConfigValue, unsetDoomConfigValue } from '@agimon-ai/doompi-config/configWriter';\nimport { CONFIG_ACTION, type DoomConfigContributionHandle } from '@agimon-ai/doompi-core/config';\nimport type { LeaderBinding, DoomLeaderContributionHandle } from '@agimon-ai/doompi-core/leader';\nimport {\n  createNarrationRequest,\n  DOOM_NARRATION_SERVICE,\n  type DoomNarrationService,\n  requireDoomNarrationService,\n} from '@agimon-ai/doompi-core/narration';\nimport type { PiPluginContributions } from '@agimon-ai/doompi-core/piExtension';\nimport {\n  DOOM_TOOL_SURFACE_SERVICE,\n  type DoomToolRestriction,\n  type DoomToolRestrictionHandle,\n  readDoomToolSurface,\n} from '@agimon-ai/doompi-core/toolSurface';\nimport { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from '@agimon-ai/doompi-core/uiHub';\nimport {\n  DOOM_VOICE_AUTO_MODE_ID,\n  DOOM_VOICE_SOURCE,\n  DOOM_VOICE_TOOLS_SERVICE,\n  requireDoomVoiceToolsService,\n  type VoiceToolDefinition,\n} from '@agimon-ai/doompi-core/voiceTools';\nimport {\n  DOOM_MINOR_MODE_CATALOG_SERVICE,\n  type MinorModeCatalogService,\n  type MinorModeOwnerHandle,\n  type MinorModeState,\n  registerMinorModeOwner,\n  requireMinorModeCatalog,\n} from '@agimon-ai/doompi-minor-mode';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI, ExtensionContext, ToolCallEvent } from '@earendil-works/pi-coding-agent';\n\nimport {\n  getHarnessState,\n  loadDoomConfig,\n  loadHarnessState,\n  type PlanningAgentConfig,\n  type PlanningModeConfig,\n  type PlanningThinkingLevel,\n  resolvePlanningPlansDirectory,\n} from '../../schemas/plan/config';\nimport { type PlanModelChoice, planConfigSections, planSettingByFieldId } from '../../schemas/plan/planConfig';\nimport {\n  createFablePlanFlow,\n  FABLE_PLAN_PROFILE,\n  FABLE_PLAN_REQUESTER,\n  type FablePlanBroker,\n  type FablePlanResult,\n  type FableStage,\n} from '../../services/fableFlow';\nimport { createPlanTelemetry, PLAN_EVENT, type PlanTelemetry } from '../../services/logSinkTelemetry';\nimport {\n  DOOM_FABLE_PLAN_SERVICE,\n  DOOM_SUBAGENT_POLICY_SERVICE,\n  type DoomFablePlanService,\n  type DoomSubagentPolicyService,\n  readDoomFablePlanService,\n  readDoomSubagentPolicyService,\n  type SubagentPolicyHandle,\n} from '../../services/optionalTeamServices';\nimport { PlanPointerService } from '../../services/planPointer';\nimport {\n  buildFlavorPlanningPrompt,\n  buildPlanModeBasePrompt,\n  type DebugEvidencePacket,\n  type PlanHostCapabilities,\n  type PlanningFlavor,\n} from '../../services/prompts';\nimport {\n  CONTINUE_PLAN_DECISION,\n  CONTINUE_PLANNING_CHOICE,\n  EXIT_PLAN_DECISION,\n  EXIT_PLAN_MODE_CHOICE,\n  formatPlanStatus,\n  PLAN_REVIEW_OPTIONS,\n  PLAN_REVIEW_TITLE,\n  PLAN_STATUS_KEY,\n} from '../../types/planApi';\nimport type { PlanPointerPort } from '../../types/planPointer';\n\n/**\n * What this facet's tools accept: complete_plan declares a `decision` enum, the voice path\n * narrates the review, and a Fable broker is resolved for run_fable_plan.\n */\nexport const PLAN_CLI_CAPABILITIES: PlanHostCapabilities = {\n  completePlanTakesDecision: true,\n  narratesReview: true,\n  fableAvailable: true,\n};\n\nconst PLAN_MODE_ENTRY = 'agent-harness-plan-mode';\nconst PLAN_MODE_CONTEXT = 'agent-harness-plan-mode-context';\nconst PLAN_DOCUMENT_ENTRY = 'agent-harness-plan-document';\nconst COMPLETE_PLAN_TOOL = 'complete_plan';\nconst WRITE_PLAN_TOOL = 'write_plan';\nconst BASH_TOOL = 'bash';\nconst FIND_TOOL = 'find';\nconst GREP_TOOL = 'grep';\nconst LIST_TOOL = 'ls';\nconst MCP_TOOL = 'mcp';\nconst READ_TOOL = 'read';\nconst SUBAGENT_TOOL = 'subagent';\nconst TASK_TOOL = 'task';\nconst RECORD_DEBUG_EVIDENCE_TOOL = 'record_debug_evidence';\nconst RUN_FABLE_PLAN_TOOL = 'run_fable_plan';\nconst DEFAULT_PLAN_TITLE = 'implementation-plan';\nconst PLAN_TITLE_MAX_LENGTH = 64;\nconst SESSION_ID_MAX_LENGTH = 48;\nconst PLAN_MODE_STATUS_KEY = 'plan-mode';\nconst PLAN_LEADER_SOURCE = '@agimon-ai/doompi-plan';\nconst PLAN_LEADER_GROUP_ORDER = 60;\nconst MODE_ID = 'plan';\nconst MODE_LABEL = 'Plan';\nconst READ_ONLY_DETAIL = 'read only';\nconst MODE_ORDER = 40;\nconst MODE_ACTIVATE_ACTION = 'activate';\nconst MODE_DEACTIVATE_ACTION = 'deactivate';\nconst WARNING_STYLE = 'warning';\nconst INFO_STYLE = 'info';\nconst PRIVATE_FILE_MODE = 0o600;\nconst PRIVATE_DIRECTORY_MODE = 0o700;\nconst PLAN_ALLOCATION_ATTEMPTS = 3;\nconst INVALID_PLAN_DESTINATION = 'Refused to write the plan because its destination is not a regular file.';\nconst PLAN_TRIGGER_ATTRIBUTE = 'plan.trigger';\nconst PLAN_MODEL_ATTRIBUTE = 'plan.model';\nconst PLAN_FLAVOR_ATTRIBUTE = 'plan.flavor';\nconst MODEL_NOT_FOUND_REASON = 'not_found';\nconst MODEL_UNAUTHENTICATED_REASON = 'unauthenticated';\nconst MODEL_RESTORE_FAILED_REASON = 'restore_failed';\nconst DEBUG_EVIDENCE_MAX_BYTES = 32 * 1024;\nconst DEBUG_EVIDENCE_MAX_TEXT_BYTES = 4 * 1024;\nconst DEBUG_EVIDENCE_MAX_ITEMS = 32;\nconst DEBUG_DIAGNOSTIC_TOOLS = new Set<string>();\nexport const WRITE_PLAN_TIMEOUT_MS = 5_000;\n\n/**\n * What complete_plan tells the model once the reader has answered. Exported because the\n * server facet runs its own copy of this tool and must not word the outcome differently.\n */\nexport const PLAN_EXIT_APPROVED_TEXT =\n  'The user approved exiting plan mode. Full tool access is restored. Begin implementing the approved plan.';\nexport const PLAN_CONTINUE_TEXT = 'The user chose to continue planning. Remain read-only and refine the plan.';\nconst PLAN_REVIEW_PROMPT = [\n  PLAN_REVIEW_TITLE,\n  `  1. ${EXIT_PLAN_MODE_CHOICE}`,\n  `  2. ${CONTINUE_PLANNING_CHOICE}`,\n  '  Type something.',\n].join('\\n');\nconst PLAN_REVIEW_NARRATION = `${PLAN_REVIEW_TITLE} Options: 1, ${EXIT_PLAN_MODE_CHOICE}; 2, ${CONTINUE_PLANNING_CHOICE}. Please choose one option. You may also answer in your own words.`;\nconst PLAN_REVIEW_NARRATION_REQUEST = createNarrationRequest(PLAN_REVIEW_NARRATION)!;\nconst PLAN_REVIEW_WAIT_MESSAGE =\n  \"The choices were spoken through autonomous voice. Stop now and wait for the user's next message; it will arrive as an ordinary user message.\";\nconst PLAN_MODE_EXPLORATION_TOOLS = [READ_TOOL, BASH_TOOL, GREP_TOOL, FIND_TOOL, LIST_TOOL] as const;\nconst CHILD_EXPLORATION_TOOLS = [...PLAN_MODE_EXPLORATION_TOOLS, MCP_TOOL] as const;\n/** Withheld while any plan flavor is active. Restored by the surface arbiter on exit. */\nconst PLAN_MODE_EXCLUDED_TOOLS = new Set(['edit', 'write']);\nconst PLAN_MODE_TRIGGER_LEADER = 'leader' as const;\nconst PLAN_MODE_TRIGGER_SESSION_RESTORE = 'session_restore' as const;\nconst PLAN_MODE_TRIGGER_PLAN_APPROVED = 'plan_approved' as const;\nconst PLAN_MODE_TRIGGER_SESSION_SHUTDOWN = 'session_shutdown' as const;\nconst PLAN_MODE_TRIGGER_VOICE_TOOL = 'voice_tool' as const;\nconst PLAN_STATE_VERSION = 2 as const;\nconst VALID_THINKING_LEVELS: readonly PlanningThinkingLevel[] = [\n  'off',\n  'minimal',\n  'low',\n  'medium',\n  'high',\n  'xhigh',\n  'max',\n];\nconst VALID_FABLE_STAGES: readonly FableStage[] = [\n  'idle',\n  'draft',\n  'review',\n  'completed',\n  'failed',\n  'cancelled',\n  'interrupted',\n];\nconst PLAN_VOICE_SOURCE = '@agimon-ai/doompi-plan';\nconst PLAN_VOICE_ACTIVATE_ID = 'plan-activate';\nconst PLAN_VOICE_EXIT_ID = 'plan-exit';\nconst PLAN_VOICE_ACTIVATE_NAME = 'activate_plan';\nconst PLAN_VOICE_EXIT_NAME = 'exit_plan';\nconst PLAN_VOICE_FLAVORS = ['normal', 'debug', 'fable'] as const;\nconst PLAN_VOICE_FLAVOR_SCHEMA = { type: 'string', enum: [...PLAN_VOICE_FLAVORS] } as const;\nconst PLAN_VOICE_ACTIVATE_INPUT_SCHEMA = {\n  type: 'object',\n  properties: { flavor: PLAN_VOICE_FLAVOR_SCHEMA },\n  required: ['flavor'],\n  additionalProperties: false,\n} as const;\nconst PLAN_VOICE_EXIT_INPUT_SCHEMA = {\n  type: 'object',\n  properties: {},\n  additionalProperties: false,\n} as const;\nconst PLAN_VOICE_RESULT_SCHEMA = {\n  type: 'object',\n  properties: {\n    active: { type: 'boolean' },\n    flavor: { anyOf: [{ ...PLAN_VOICE_FLAVOR_SCHEMA }, { type: 'null' }] },\n    changed: { type: 'boolean' },\n  },\n  required: ['active', 'flavor', 'changed'],\n  additionalProperties: false,\n} as const;\nexport type { PlanningFlavor } from '../../services/prompts';\n\nexport interface ModelIdentity {\n  provider: string;\n  id: string;\n}\n\nexport interface PlanSnapshot {\n  tools: string[];\n  model?: ModelIdentity;\n  thinking: PlanningThinkingLevel;\n}\n\ninterface PersistedPlanModeState {\n  version: typeof PLAN_STATE_VERSION;\n  activeFlavor?: PlanningFlavor;\n  originalSnapshot?: PlanSnapshot;\n  planId?: string;\n  interruptedFableStage?: FableStage;\n}\n\ninterface PlanDocument {\n  content: string;\n  path: string;\n  sessionId: string;\n  planId?: string;\n  title: string;\n  writtenAt: string;\n}\n\ntype PlanWritePhase = 'checking' | 'writing';\n\n/** Why plan mode changed state, so the sink can tell a user toggle from a session restore. */\ntype PlanModeTrigger =\n  | typeof PLAN_MODE_TRIGGER_LEADER\n  | typeof PLAN_MODE_TRIGGER_SESSION_RESTORE\n  | typeof PLAN_MODE_TRIGGER_PLAN_APPROVED\n  | typeof PLAN_MODE_TRIGGER_SESSION_SHUTDOWN\n  | typeof PLAN_MODE_TRIGGER_VOICE_TOOL;\n\nexport interface PlanModeExtensionOptions {\n  fableBroker?: FablePlanBroker;\n  debugDiagnosticTools?: readonly string[];\n  doomIntegrations?: boolean;\n  /** Where the written plan is recorded for the session's API server to find. */\n  planPointers?: PlanPointerPort;\n}\n\ninterface PlanVoiceReviewServices {\n  readonly modes: Pick<MinorModeCatalogService, 'list'>;\n  readonly narration: Pick<DoomNarrationService, 'request'>;\n}\n\n/** The plan's own heading, as the status line and the pointer record word it. */\nexport function planTitleOf(markdown: string): string {\n  return markdown.match(/^#\\s+(.+?)\\s*$/m)?.[1] ?? DEFAULT_PLAN_TITLE;\n}\n\nexport function planTitleSlug(markdown: string): string {\n  const heading = planTitleOf(markdown);\n  return (\n    heading\n      .normalize('NFKD')\n      .replace(/[\\u0300-\\u036f]/g, '')\n      .toLowerCase()\n      .replace(/[^a-z0-9]+/g, '-')\n      .replace(/^-+|-+$/g, '')\n      .slice(0, PLAN_TITLE_MAX_LENGTH) || DEFAULT_PLAN_TITLE\n  );\n}\n\n/**\n * How the status line words when a plan was written. A malformed timestamp is\n * shown as it came rather than as an invalid date: the stamp's other job is to\n * change on a rewrite, and it can still do that.\n */\nexport function planStampOf(writtenAt: string): string {\n  const at = new Date(writtenAt);\n  return Number.isNaN(at.getTime()) ? writtenAt : at.toLocaleTimeString();\n}\n\nexport function planSessionIdentifier(sessionId: string): string {\n  const readable = encodeURIComponent(sessionId).slice(0, SESSION_ID_MAX_LENGTH) || 'session';\n  const digest = createHash('sha256').update(sessionId).digest('hex');\n  return `${readable}--${digest}`;\n}\n\nexport function createPlanIdentifier(now = new Date(), id = randomUUID()): string {\n  const timestamp = now\n    .toISOString()\n    .replace(/[-:]/g, '')\n    .replace(/\\.\\d{3}Z$/, 'Z');\n  return `${timestamp}--${id}`;\n}\n\nexport function visiblePlanForToolCall(entries: readonly unknown[], toolCallId: string): string | undefined {\n  for (let index = entries.length - 1; index >= 0; index -= 1) {\n    const entry = entries[index];\n    if (!entry || typeof entry !== 'object') continue;\n    const candidate = entry as {\n      type?: string;\n      message?: { role?: string; content?: unknown };\n    };\n    if (candidate.type !== 'message' || candidate.message?.role !== 'assistant') continue;\n    if (!Array.isArray(candidate.message.content)) continue;\n\n    const toolIndex = candidate.message.content.findIndex((block) => {\n      if (!block || typeof block !== 'object') return false;\n      const content = block as { type?: string; id?: string; name?: string };\n      return content.type === 'toolCall' && content.id === toolCallId && content.name === WRITE_PLAN_TOOL;\n    });\n    if (toolIndex < 0) continue;\n\n    const plan = candidate.message.content\n      .slice(0, toolIndex)\n      .flatMap((block) => {\n        if (!block || typeof block !== 'object') return [];\n        const content = block as { type?: string; text?: unknown };\n        return content.type === 'text' && typeof content.text === 'string' ? [content.text] : [];\n      })\n      .join('\\n\\n')\n      .trim();\n    return plan || undefined;\n  }\n  return undefined;\n}\n\nfunction abortReason(signal: AbortSignal): Error {\n  return signal.reason instanceof Error ? signal.reason : new Error('Plan write cancelled.');\n}\n\nasync function waitForAbortable<T>(operation: () => Promise<T>, signal: AbortSignal): Promise<T> {\n  if (signal.aborted) throw abortReason(signal);\n  let onAbort: (() => void) | undefined;\n  const aborted = new Promise<never>((_resolve, reject) => {\n    onAbort = () => reject(abortReason(signal));\n    signal.addEventListener('abort', onAbort, { once: true });\n  });\n  try {\n    return await Promise.race([operation(), aborted]);\n  } finally {\n    if (onAbort) signal.removeEventListener('abort', onAbort);\n  }\n}\n\ntype MutableSubagentStep = {\n  model?: string;\n  output?: string | boolean;\n  progress?: boolean;\n  worktree?: boolean;\n  parallel?: MutableSubagentStep | MutableSubagentStep[];\n};\n\ntype MutableSubagentRunRequest = {\n  [key: string]: unknown;\n  model?: string;\n};\n\ntype MutableSubagentInput = MutableSubagentStep & {\n  action?: string;\n  artifacts?: boolean;\n  outputSchema?: Record<string, unknown>;\n  share?: boolean;\n  tasks?: MutableSubagentStep[];\n  chain?: MutableSubagentStep[];\n  chainDir?: string;\n  sessionDir?: string;\n  requests?: MutableSubagentRunRequest[];\n};\n\ntype MutableTaskAssignment = {\n  [key: string]: unknown;\n  model?: string;\n};\n\ntype MutableTaskInput = {\n  action?: string;\n  assignments?: MutableTaskAssignment[];\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isString(value: unknown): value is string {\n  return typeof value === 'string';\n}\n\nfunction parseModelIdentity(value: unknown): ModelIdentity | undefined {\n  if (!isRecord(value) || !isString(value.provider) || !isString(value.id)) return undefined;\n  if (!value.provider || !value.id || value.provider.length > 128 || value.id.length > 128) return undefined;\n  return { provider: value.provider, id: value.id };\n}\n\nfunction parseThinkingLevel(value: unknown): PlanningThinkingLevel | undefined {\n  return isString(value) && VALID_THINKING_LEVELS.includes(value as PlanningThinkingLevel)\n    ? (value as PlanningThinkingLevel)\n    : undefined;\n}\n\nfunction parseFableStage(value: unknown): FableStage | undefined {\n  return isString(value) && VALID_FABLE_STAGES.includes(value as FableStage) ? (value as FableStage) : undefined;\n}\n\nfunction parseStringArray(value: unknown): string[] | undefined {\n  if (!Array.isArray(value) || value.some((item) => !isString(item))) return undefined;\n  return value.map((item) => item);\n}\n\nfunction parsePlanSnapshot(value: unknown): PlanSnapshot | undefined {\n  if (!isRecord(value)) return undefined;\n  const tools = parseStringArray(value.tools);\n  const thinking = parseThinkingLevel(value.thinking);\n  if (!tools || thinking === undefined) return undefined;\n  const model = value.model === undefined ? undefined : parseModelIdentity(value.model);\n  if (value.model !== undefined && !model) return undefined;\n  return { tools, ...(model ? { model } : {}), thinking };\n}\n\nfunction parsePlanningFlavor(value: unknown): PlanningFlavor | undefined {\n  return value === 'normal' || value === 'debug' || value === 'fable' ? value : undefined;\n}\n\nfunction parseVersionedPlanState(value: Record<string, unknown>): PersistedPlanModeState | undefined {\n  if (value.version !== PLAN_STATE_VERSION) return undefined;\n  const activeFlavor = value.activeFlavor === undefined ? undefined : parsePlanningFlavor(value.activeFlavor);\n  if (value.activeFlavor !== undefined && !activeFlavor) return undefined;\n  const originalSnapshot = value.originalSnapshot === undefined ? undefined : parsePlanSnapshot(value.originalSnapshot);\n  if (value.originalSnapshot !== undefined && !originalSnapshot) return undefined;\n  const planId = value.planId === undefined ? undefined : isString(value.planId) ? value.planId : undefined;\n  if (value.planId !== undefined && planId === undefined) return undefined;\n  const interruptedFableStage =\n    value.interruptedFableStage === undefined ? undefined : parseFableStage(value.interruptedFableStage);\n  if (value.interruptedFableStage !== undefined && !interruptedFableStage) return undefined;\n  return {\n    version: PLAN_STATE_VERSION,\n    ...(activeFlavor ? { activeFlavor } : {}),\n    ...(originalSnapshot ? { originalSnapshot } : {}),\n    ...(planId ? { planId } : {}),\n    ...(interruptedFableStage ? { interruptedFableStage } : {}),\n  };\n}\n\nfunction parseLegacyPlanState(value: Record<string, unknown>): PersistedPlanModeState | undefined {\n  if (value.enabled !== true && value.enabled !== false) return undefined;\n  const tools = value.toolsBeforePlanMode === undefined ? undefined : parseStringArray(value.toolsBeforePlanMode);\n  if (value.toolsBeforePlanMode !== undefined && !tools) return undefined;\n  const model = value.modelBeforePlanMode === undefined ? undefined : parseModelIdentity(value.modelBeforePlanMode);\n  if (value.modelBeforePlanMode !== undefined && !model) return undefined;\n  const thinking =\n    value.thinkingBeforePlanMode === undefined ? undefined : parseThinkingLevel(value.thinkingBeforePlanMode);\n  if (value.thinkingBeforePlanMode !== undefined && thinking === undefined) return undefined;\n  const planId = value.planId === undefined ? undefined : isString(value.planId) ? value.planId : undefined;\n  if (value.planId !== undefined && planId === undefined) return undefined;\n  const originalSnapshot =\n    tools && thinking !== undefined ? { tools, ...(model ? { model } : {}), thinking } : undefined;\n  return {\n    version: PLAN_STATE_VERSION,\n    ...(value.enabled ? { activeFlavor: 'normal' as const } : {}),\n    ...(originalSnapshot ? { originalSnapshot } : {}),\n    ...(planId ? { planId } : {}),\n  };\n}\n\nexport function parsePersistedPlanState(value: unknown): PersistedPlanModeState | undefined {\n  if (!isRecord(value)) return undefined;\n  return parseVersionedPlanState(value) ?? parseLegacyPlanState(value);\n}\n\nfunction parsePlanDocument(value: unknown): PlanDocument | undefined {\n  if (!isRecord(value)) return undefined;\n  if (!isString(value.content) || !isString(value.path) || !isString(value.sessionId) || !isString(value.title)) {\n    return undefined;\n  }\n  if (!isString(value.writtenAt)) return undefined;\n  const planId = value.planId === undefined ? undefined : isString(value.planId) ? value.planId : undefined;\n  if (value.planId !== undefined && planId === undefined) return undefined;\n  return {\n    content: value.content,\n    path: value.path,\n    sessionId: value.sessionId,\n    ...(planId ? { planId } : {}),\n    title: value.title,\n    writtenAt: value.writtenAt,\n  };\n}\n\nfunction boundedDebugText(value: unknown, field: string, required: boolean): string {\n  if (!isString(value)) throw new Error(`${field} must be a string.`);\n  const text = value.trim();\n  if (required && !text) throw new Error(`${field} must not be empty.`);\n  if (Buffer.byteLength(text, 'utf8') > DEBUG_EVIDENCE_MAX_TEXT_BYTES) {\n    throw new Error(`${field} exceeds the bounded debug evidence limit.`);\n  }\n  return text;\n}\n\nfunction boundedDebugList(value: unknown, field: string): string[] {\n  if (!Array.isArray(value) || value.length > DEBUG_EVIDENCE_MAX_ITEMS) {\n    throw new Error(`${field} must be a bounded string array.`);\n  }\n  return value.map((item, index) => boundedDebugText(item, `${field}[${index}]`, false));\n}\n\nfunction optionalDebugText(value: unknown, field: string): string {\n  return value === undefined ? '' : boundedDebugText(value, field, false);\n}\n\nfunction optionalDebugList(value: unknown, field: string): string[] {\n  return value === undefined ? [] : boundedDebugList(value, field);\n}\n\nfunction assertExactObjectKeys(value: Record<string, unknown>, keys: readonly string[], field: string): void {\n  const allowed = new Set(keys);\n  const unexpected = Object.keys(value).find((key) => !allowed.has(key));\n  if (unexpected) throw new Error(`${field} contains unsupported field '${unexpected}'.`);\n}\n\nexport function parseDebugEvidencePacket(value: unknown): DebugEvidencePacket {\n  if (!isRecord(value)) throw new Error('Debug evidence must be an object.');\n  assertExactObjectKeys(\n    value,\n    [\n      'issue',\n      'expectedBehavior',\n      'reproductionAttempt',\n      'actualBehavior',\n      'logs',\n      'correlatedTraceEvidence',\n      'processOutput',\n      'browserConsoleEvidence',\n      'correlationIds',\n      'timestamps',\n      'verifiedFacts',\n      'hypotheses',\n      'unavailableEvidence',\n    ],\n    'Debug evidence',\n  );\n  const packet: DebugEvidencePacket = {\n    issue: boundedDebugText(value.issue, 'issue', true),\n    expectedBehavior: optionalDebugText(value.expectedBehavior, 'expectedBehavior'),\n    reproductionAttempt: optionalDebugText(value.reproductionAttempt, 'reproductionAttempt'),\n    actualBehavior: optionalDebugText(value.actualBehavior, 'actualBehavior'),\n    logs: optionalDebugList(value.logs, 'logs'),\n    correlatedTraceEvidence: optionalDebugList(value.correlatedTraceEvidence, 'correlatedTraceEvidence'),\n    processOutput: optionalDebugList(value.processOutput, 'processOutput'),\n    browserConsoleEvidence: optionalDebugList(value.browserConsoleEvidence, 'browserConsoleEvidence'),\n    correlationIds: optionalDebugList(value.correlationIds, 'correlationIds'),\n    timestamps: optionalDebugList(value.timestamps, 'timestamps'),\n    verifiedFacts: optionalDebugList(value.verifiedFacts, 'verifiedFacts'),\n    hypotheses: optionalDebugList(value.hypotheses, 'hypotheses'),\n    unavailableEvidence: optionalDebugList(value.unavailableEvidence, 'unavailableEvidence'),\n  };\n  if (Buffer.byteLength(JSON.stringify(packet), 'utf8') > DEBUG_EVIDENCE_MAX_BYTES) {\n    throw new Error('Debug evidence exceeds the bounded packet size.');\n  }\n  return packet;\n}\n\n/**\n * Gate Plan-owned tools by flavor, and withhold the two file-writing tools.\n *\n * `flavor` undefined means plan mode is off, which hides plan's own tools\n * because they are registered for the whole session, and restores edit and write.\n */\nexport function planToolRestriction(\n  flavor: PlanningFlavor | undefined,\n  _diagnosticTools: ReadonlySet<string>,\n): DoomToolRestriction {\n  return (incoming) =>\n    incoming.filter((name) => {\n      if (name === COMPLETE_PLAN_TOOL || name === WRITE_PLAN_TOOL) return flavor !== undefined;\n      if (name === RUN_FABLE_PLAN_TOOL) return flavor === 'fable';\n      if (name === RECORD_DEBUG_EVIDENCE_TOOL) return flavor === 'debug';\n      if (flavor === undefined) return true;\n      return !PLAN_MODE_EXCLUDED_TOOLS.has(name);\n    });\n}\n\nfunction disableStepOutput(step: MutableSubagentStep): void {\n  step.output = false;\n  step.progress = false;\n  step.worktree = false;\n  if (Array.isArray(step.parallel)) {\n    for (const child of step.parallel) disableStepOutput(child);\n  } else if (step.parallel) {\n    disableStepOutput(step.parallel);\n  }\n}\n\nexport function constrainSubagentInput(input: MutableSubagentInput): void {\n  if (input.action !== undefined) {\n    if (input.action === 'run') input.artifacts = false;\n    return;\n  }\n\n  input.artifacts = false;\n  input.output = false;\n  input.share = false;\n  input.progress = false;\n  input.worktree = false;\n  delete input.chainDir;\n  delete input.outputSchema;\n  delete input.sessionDir;\n  for (const task of input.tasks ?? []) disableStepOutput(task);\n  for (const step of input.chain ?? []) disableStepOutput(step);\n}\n\nexport function planningSubagentModel(\n  config: PlanningAgentConfig | undefined,\n  currentModel: ModelIdentity | undefined,\n): string | undefined {\n  if (!config?.model && !config?.thinking) return undefined;\n  const baseModel = config.model ?? (currentModel ? `${currentModel.provider}/${currentModel.id}` : undefined);\n  if (!baseModel) return undefined;\n  if (!config.thinking) return baseModel;\n  return `${baseModel.replace(/:(?:off|minimal|low|medium|high|xhigh|max)$/, '')}:${config.thinking}`;\n}\n\nexport function configurePlanningSubagentInput(input: MutableSubagentInput, model: string): void {\n  if (input.action !== 'run') return;\n  for (const request of input.requests ?? []) request.model = model;\n}\n\nexport function configurePlanningTaskInput(input: MutableTaskInput, model: string): void {\n  if (input.action !== 'assign') return;\n  for (const assignment of input.assignments ?? []) assignment.model = model;\n}\n\nexport function isBlockedSubagentManagementAction(action: string | undefined): boolean {\n  return new Set([\n    'append-step',\n    'create',\n    'delete',\n    'disable',\n    'eject',\n    'enable',\n    'grant-spawn-budget',\n    'reset',\n    'schedule',\n    'schedule-cancel',\n    'update',\n    'watchdog.configure',\n  ]).has(action ?? '');\n}\n\nfunction resolvePlanningModel(\n  modelSpec: string,\n  ctx: ExtensionContext,\n): NonNullable<ExtensionContext['model']> | undefined {\n  const separator = modelSpec.indexOf('/');\n  if (separator > 0) {\n    return ctx.modelRegistry.find(modelSpec.slice(0, separator), modelSpec.slice(separator + 1));\n  }\n\n  const matches = ctx.modelRegistry.getAvailable().filter((model) => model.id === modelSpec);\n  return (\n    matches.find((model) => model.provider === ctx.model?.provider) ?? (matches.length === 1 ? matches[0] : undefined)\n  );\n}\n\nexport type PlanningConfigProvider = () => PlanningModeConfig | undefined;\n\n/** Reads Doom settings from disk so each plan-mode activation sees current configuration. */\nexport function loadPlanningModeConfig(\n  environment: NodeJS.ProcessEnv = process.env,\n  currentDirectory = process.cwd(),\n): PlanningModeConfig | undefined {\n  return loadDoomConfig(loadHarnessState(environment).state.root ?? currentDirectory).modes?.planning;\n}\n\n/**\n * The plan menu as it stands with the mode on or off.\n *\n * One entry on `e` rather than an enter row beside an exit row: only one of the\n * two ever does anything, and a menu that prints both makes the reader check the\n * mode line to find out which. `d` and `f` stay on their own keys because they\n * are flavors of the same mode, reachable whether or not it is already on.\n */\nfunction planLeaderBindings(active: boolean): LeaderBinding[] {\n  const group = {\n    key: 'p',\n    label: 'plan',\n    detail: 'read-only planning modes',\n    order: PLAN_LEADER_GROUP_ORDER,\n  } as const;\n  return [\n    active\n      ? {\n          id: 'plan.exit',\n          path: [group, { key: 'e', label: 'exit', detail: 'restore and exit', tone: 'exit' }],\n          action: { name: 'plan.exit' },\n        }\n      : {\n          id: 'plan.normal',\n          path: [group, { key: 'e', label: 'enter', detail: 'read-only planning' }],\n          action: { name: 'plan.normal' },\n        },\n    {\n      id: 'plan.debug',\n      path: [group, { key: 'd', label: 'debug', detail: 'adaptive debug planning' }],\n      action: { name: 'plan.debug' },\n    },\n    {\n      id: 'plan.fable',\n      path: [group, { key: 'f', label: 'fable', detail: 'repository-aware draft' }],\n      action: { name: 'plan.fable' },\n    },\n  ];\n}\n\nexport function createPlanModeRuntime(\n  pi: ExtensionAPI,\n  planningConfigProvider: PlanningConfigProvider = loadPlanningModeConfig,\n  telemetry: PlanTelemetry = createPlanTelemetry(),\n  options: PlanModeExtensionOptions = {},\n): Omit<PiPluginContributions, 'tools'> & { tools: Parameters<ExtensionAPI['registerTool']>[0][] } {\n  let active = true;\n  let sessionGeneration = 0;\n  let shutdownPromise: Promise<void> | undefined;\n  let modeOwner: Pick<MinorModeOwnerHandle, 'publish' | 'dispose'> | undefined;\n  let leaderContribution: DoomLeaderContributionHandle | undefined;\n  let planConfigContribution: DoomConfigContributionHandle | undefined;\n  let disposeLeaderActions: (() => void) | undefined;\n  let planConfigNotice: string | undefined;\n  /** The session context, kept only to read its model registry for the config panel. */\n  let configSessionCtx: ExtensionContext | undefined;\n  const sessionModels = (): PlanModelChoice[] => {\n    const registry = configSessionCtx?.modelRegistry;\n    if (!registry) return [];\n    return registry\n      .getAvailable()\n      .filter((model) => registry.hasConfiguredAuth(model))\n      .map((model) => ({ provider: model.provider, id: model.id }));\n  };\n\n  let enabled = false;\n  let activeFlavor: PlanningFlavor | undefined;\n  let planSnapshot: PlanSnapshot | undefined;\n  let activePlanningConfig: PlanningModeConfig | undefined;\n  let capabilityCeiling: SubagentPolicyHandle | undefined;\n  let subagentPolicyService: DoomSubagentPolicyService | undefined;\n  let fablePlanService: DoomFablePlanService | undefined;\n  let currentPlan: PlanDocument | undefined;\n  let activePlanId: string | undefined;\n  let planReadyForReview = false;\n  /** Whether this runtime has published the plan status a cockpit keys its group off. */\n  let planAnnounced = false;\n  let awaitingVoicePlanDecision = false;\n  let voiceReviewServices: PlanVoiceReviewServices | undefined;\n  let debugEvidence: DebugEvidencePacket | undefined;\n  let fableStage: FableStage = 'idle';\n  let interruptedFableStage: FableStage | undefined;\n  let activeContext: ExtensionContext | undefined;\n  let activeFableRun: Promise<FablePlanResult> | undefined;\n  let fableFlow: ReturnType<typeof createFablePlanFlow> | undefined;\n  let transitionQueue: Promise<void> = Promise.resolve();\n  const doomIntegrations = options.doomIntegrations ?? true;\n  const planPointers: PlanPointerPort = options.planPointers ?? new PlanPointerService({ env: process.env });\n  const diagnosticTools = new Set(options.debugDiagnosticTools ?? DEBUG_DIAGNOSTIC_TOOLS);\n  let toolRestriction: DoomToolRestrictionHandle | undefined;\n  const currentToolRestriction = (): DoomToolRestriction =>\n    planToolRestriction(enabled ? activeFlavor : undefined, diagnosticTools);\n  const applyToolRestriction = (): void => {\n    toolRestriction?.update(currentToolRestriction());\n  };\n\n  const runtimeAbortController = new AbortController();\n\n  const fableBroker: FablePlanBroker = options.fableBroker ?? {\n    start: (request, signal) => {\n      const service = fablePlanService;\n      if (!service) throw new Error('The session-bound Fable broker is unavailable.');\n      return service.start(request, signal);\n    },\n    cancel: (operationId, reason) => {\n      fablePlanService?.cancel({ requester: FABLE_PLAN_REQUESTER, operationId, reason });\n    },\n  };\n  const isFableBrokerAvailable = (): boolean => options.fableBroker !== undefined || fablePlanService !== undefined;\n\n  function assertRuntimeActive(generation = sessionGeneration): void {\n    if (!active || generation !== sessionGeneration) throw new Error('Plan runtime is disposed or stale.');\n  }\n\n  async function requestVoicePlanReview(): Promise<boolean> {\n    const services = voiceReviewServices;\n    if (\n      !services ||\n      !services.modes\n        .list()\n        .some(\n          (record) =>\n            record.descriptor.source === DOOM_VOICE_SOURCE &&\n            record.descriptor.id === DOOM_VOICE_AUTO_MODE_ID &&\n            record.state.activation === 'active',\n        )\n    ) {\n      return false;\n    }\n    try {\n      await services.narration.request(PLAN_REVIEW_NARRATION_REQUEST);\n      return true;\n    } catch (error) {\n      void telemetry.recordWarning(PLAN_EVENT.planReviewCompleted, error, {\n        'plan.outcome': 'narration_failed',\n      });\n      return false;\n    }\n  }\n\n  function voicePlanReviewResult(): {\n    readonly content: Array<{ readonly type: 'text'; readonly text: string }>;\n    readonly details: {\n      readonly answers: readonly [];\n      readonly awaitingResponse: true;\n      readonly cancelled: false;\n      readonly delivery: 'voice';\n      readonly voicePrompt: string;\n    };\n    readonly terminate: true;\n  } {\n    return {\n      content: [{ type: 'text', text: `${PLAN_REVIEW_PROMPT}\\n\\n${PLAN_REVIEW_WAIT_MESSAGE}` }],\n      details: {\n        answers: [],\n        awaitingResponse: true,\n        cancelled: false,\n        delivery: 'voice',\n        voicePrompt: PLAN_REVIEW_PROMPT,\n      },\n      terminate: true,\n    };\n  }\n\n  function shutdownPlanRuntime(): Promise<void> {\n    shutdownPromise ??= (async () => {\n      active = false;\n      sessionGeneration += 1;\n      runtimeAbortController.abort(new Error('Plan runtime is shutting down.'));\n      const cleanupContext = activeContext;\n      const cleanupSnapshot = planSnapshot;\n      const cleanupErrors: unknown[] = [];\n      fableFlow?.cancel('Plan runtime is shutting down.');\n      const pendingWork = [transitionQueue, ...(activeFableRun ? [activeFableRun] : [])];\n      const settledWork = await Promise.allSettled(pendingWork);\n      for (const result of settledWork) {\n        if (result.status === 'rejected') cleanupErrors.push(result.reason);\n      }\n\n      if (enabled && cleanupSnapshot && cleanupContext) {\n        try {\n          const restored = await restoreMainAgent(cleanupContext, cleanupSnapshot, true);\n          if (restored) {\n            toolRestriction?.update(planToolRestriction(undefined, diagnosticTools));\n          }\n        } catch (error) {\n          cleanupErrors.push(error);\n        }\n      }\n\n      const disposers = [\n        () => retirePlanDocument(cleanupContext),\n        () => capabilityCeiling?.dispose(),\n        () => disposeLeaderActions?.(),\n        () => planConfigContribution?.dispose(),\n        () => leaderContribution?.dispose(),\n        () => modeOwner?.dispose(),\n      ];\n      for (const disposeResource of disposers) {\n        try {\n          disposeResource();\n        } catch (error) {\n          cleanupErrors.push(error);\n        }\n      }\n\n      capabilityCeiling = undefined;\n      voiceReviewServices = undefined;\n      disposeLeaderActions = undefined;\n      planConfigContribution = undefined;\n      leaderContribution = undefined;\n      modeOwner = undefined;\n      activeFableRun = undefined;\n      activeContext = undefined;\n      awaitingVoicePlanDecision = false;\n      enabled = false;\n      activeFlavor = undefined;\n      planSnapshot = undefined;\n      activePlanningConfig = undefined;\n      try {\n        await telemetry.shutdown();\n      } catch (error) {\n        cleanupErrors.push(error);\n      }\n      if (cleanupErrors.length > 0) throw new AggregateError(cleanupErrors, 'Plan runtime cleanup failed.');\n    })();\n    return shutdownPromise;\n  }\n\n  /** Identical bindings are dropped by the handle, so this can ride along with every state change. */\n  function updateLeader(): void {\n    if (!active) return;\n    leaderContribution?.update(planLeaderBindings(enabled));\n  }\n\n  function currentPlanModeState(): MinorModeState {\n    const flavor = activeFlavor;\n    const stage = flavor === 'fable' && fableStage !== 'idle' ? ` · ${fableStage}` : '';\n    return {\n      activation: enabled ? 'active' : 'inactive',\n      condition: fableStage === 'failed' ? 'failed' : fableStage === 'interrupted' ? 'degraded' : 'ready',\n      ...(enabled && flavor\n        ? { detail: `${flavor}${stage} - ${READ_ONLY_DETAIL}`, color: WARNING_STYLE, modelContextVariant: flavor }\n        : {}),\n      actions: [\n        { id: MODE_ACTIVATE_ACTION, enabled: true },\n        ...(enabled\n          ? [{ id: MODE_DEACTIVATE_ACTION, enabled: true } as const]\n          : [{ id: MODE_DEACTIVATE_ACTION, enabled: false, disabledReason: 'Plan mode is inactive.' } as const]),\n      ],\n    };\n  }\n\n  /**\n   * Pi exposes `ui.theme` as a proxy over a global the TUI installs, so every\n   * property access throws `Theme not initialized` in a headless runtime (an\n   * SDK child, a web-hosted session). Colour on a status label is not worth\n   * failing the hook that calls this, so styling is best effort and the plain\n   * label is the fallback.\n   */\n  function styleStatus(ctx: ExtensionContext, status: string): string {\n    try {\n      return ctx.ui.theme.fg(WARNING_STYLE, status);\n    } catch {\n      return status;\n    }\n  }\n\n  function updateStatus(ctx: ExtensionContext): void {\n    if (!active) return;\n    updateLeader();\n    const flavor = activeFlavor;\n    const status = enabled && flavor ? `plan:${flavor}` : undefined;\n    ctx.ui.setStatus(PLAN_MODE_STATUS_KEY, status ? styleStatus(ctx, status) : undefined);\n    modeOwner?.publish(currentPlanModeState());\n  }\n\n  /**\n   * Announces the written plan: the pointer for the session's API server, and\n   * the status the cockpit's activity group appears on.\n   *\n   * This deliberately outlives plan mode. Exiting is when the agent starts\n   * implementing, which is exactly when the plan is most worth having open, so\n   * the announcement is retired with the session rather than with the mode.\n   * The stamp is what makes the line change on a rewrite, which is how an open\n   * tab learns to re-read.\n   *\n   * A failure here is reported and dropped: the plan is on disk either way,\n   * and losing a cockpit view is not worth failing the write that produced it.\n   */\n  function announcePlanDocument(ctx: ExtensionContext, plan: PlanDocument): void {\n    try {\n      planPointers.write(ctx.sessionManager.getSessionId(), {\n        path: plan.path,\n        title: plan.title,\n        writtenAt: plan.writtenAt,\n        ...(plan.planId === undefined ? {} : { planId: plan.planId }),\n      });\n    } catch (error) {\n      void telemetry.recordWarning(PLAN_EVENT.planPointerFailed, 'The plan pointer was not recorded.', {\n        'plan.reason': error instanceof Error ? error.name : 'unknown',\n      });\n    }\n    if (!ctx.hasUI) return;\n    ctx.ui.setStatus(PLAN_STATUS_KEY, formatPlanStatus(plan.title, planStampOf(plan.writtenAt)));\n    planAnnounced = true;\n  }\n\n  /**\n   * Retires the announcement; a session that wrote no plan has nothing to\n   * retire.\n   *\n   * The status is only cleared when this runtime published one. A cockpit\n   * records a status key the first time it hears of it and never drops it\n   * again, so clearing a key it has not seen is not a no-op there: it puts the\n   * key on the session as an empty string, which is enough to show the plan\n   * group on a session that has written nothing.\n   */\n  function retirePlanDocument(ctx: ExtensionContext | undefined): void {\n    if (!ctx) return;\n    try {\n      planPointers.clear(ctx.sessionManager.getSessionId());\n    } catch {\n      // A pointer that cannot be removed is stale data for a session id that\n      // will not come back, not a reason to fail a shutdown.\n    }\n    if (!planAnnounced) return;\n    planAnnounced = false;\n    if (ctx.hasUI) ctx.ui.setStatus(PLAN_STATUS_KEY, undefined);\n  }\n\n  function updateCapabilityCeiling(): void {\n    if (!active || !doomIntegrations || !enabled || !activeFlavor || !activeContext) return;\n    const allowedTools = [...CHILD_EXPLORATION_TOOLS];\n    const allowedExternalProfiles = activeFlavor === 'fable' ? [FABLE_PLAN_PROFILE] : [];\n    const policy = {\n      owner: PLAN_LEADER_SOURCE,\n      allowedTools,\n      requiredTools: [BASH_TOOL],\n      allowMcpTools: true,\n      allowedExternalProfiles,\n      denyExtensions: false,\n    };\n    if (capabilityCeiling) capabilityCeiling.update(policy);\n    else capabilityCeiling = subagentPolicyService?.register(policy);\n  }\n\n  function persistState(): void {\n    if (!active) return;\n    pi.appendEntry(PLAN_MODE_ENTRY, {\n      version: PLAN_STATE_VERSION,\n      ...(enabled && activeFlavor ? { activeFlavor } : {}),\n      ...(planSnapshot\n        ? {\n            originalSnapshot: {\n              tools: [...planSnapshot.tools],\n              ...(planSnapshot.model ? { model: { ...planSnapshot.model } } : {}),\n              thinking: planSnapshot.thinking,\n            },\n          }\n        : {}),\n      ...(activePlanId ? { planId: activePlanId } : {}),\n      ...(interruptedFableStage ? { interruptedFableStage } : {}),\n    } satisfies PersistedPlanModeState);\n  }\n\n  function reportModelFailure(\n    phase: 'apply' | 'restore',\n    model: string,\n    reason: typeof MODEL_NOT_FOUND_REASON | typeof MODEL_UNAUTHENTICATED_REASON | typeof MODEL_RESTORE_FAILED_REASON,\n  ): void {\n    void telemetry.recordWarning(PLAN_EVENT.modelResolveFailed, `Planning model ${reason}: ${model}`, {\n      [PLAN_MODEL_ATTRIBUTE]: model,\n      'plan.model.phase': phase,\n      'plan.model.reason': reason,\n    });\n  }\n\n  async function applyMainPlanningConfig(ctx: ExtensionContext): Promise<void> {\n    const generation = sessionGeneration;\n    assertRuntimeActive(generation);\n    const config = activePlanningConfig?.main;\n    if (!config) return;\n    if (config.model) {\n      const model = resolvePlanningModel(config.model, ctx);\n      if (!model) {\n        ctx.ui.notify(`Planning model not found: ${config.model}`, WARNING_STYLE);\n        reportModelFailure('apply', config.model, MODEL_NOT_FOUND_REASON);\n      } else {\n        const authenticated = await pi.setModel(model);\n        assertRuntimeActive(generation);\n        if (!authenticated) {\n          ctx.ui.notify(`Planning model is unavailable without authentication: ${config.model}`, WARNING_STYLE);\n          reportModelFailure('apply', config.model, MODEL_UNAUTHENTICATED_REASON);\n        }\n      }\n    }\n    assertRuntimeActive(generation);\n    if (config.thinking) pi.setThinkingLevel(config.thinking);\n  }\n\n  async function restoreMainAgent(\n    ctx: ExtensionContext,\n    snapshot: PlanSnapshot | undefined,\n    allowInactive = false,\n  ): Promise<boolean> {\n    const generation = sessionGeneration;\n    if (!allowInactive) assertRuntimeActive(generation);\n    if (!snapshot) return false;\n    if (snapshot.model) {\n      const identity = `${snapshot.model.provider}/${snapshot.model.id}`;\n      const model = ctx.modelRegistry.find(snapshot.model.provider, snapshot.model.id);\n      if (!model) {\n        ctx.ui.notify(`Previous model not found: ${identity}`, WARNING_STYLE);\n        reportModelFailure('restore', identity, MODEL_NOT_FOUND_REASON);\n        return false;\n      }\n      try {\n        const authenticated = await pi.setModel(model);\n        if (!allowInactive) assertRuntimeActive(generation);\n        if (!authenticated) {\n          ctx.ui.notify(`Previous model is unavailable without authentication: ${identity}`, WARNING_STYLE);\n          reportModelFailure('restore', identity, MODEL_UNAUTHENTICATED_REASON);\n          return false;\n        }\n      } catch (error) {\n        if (!allowInactive) assertRuntimeActive(generation);\n        ctx.ui.notify(`Previous model could not be restored: ${identity}`, WARNING_STYLE);\n        reportModelFailure('restore', identity, MODEL_RESTORE_FAILED_REASON);\n        void telemetry.recordError(PLAN_EVENT.modelResolveFailed, error, {\n          [PLAN_MODEL_ATTRIBUTE]: identity,\n          'plan.model.phase': 'restore',\n          'plan.model.reason': MODEL_RESTORE_FAILED_REASON,\n        });\n        return false;\n      }\n    }\n    if (!allowInactive) assertRuntimeActive(generation);\n    pi.setThinkingLevel(snapshot.thinking);\n    return true;\n  }\n\n  function reportCurrentFlavor(ctx: ExtensionContext): void {\n    if (enabled && activeFlavor) ctx.ui.notify(`Already in plan:${activeFlavor}.`, INFO_STYLE);\n    else ctx.ui.notify('Plan mode is inactive.', INFO_STYLE);\n  }\n\n  function queueTransition<T>(transition: () => Promise<T>): Promise<T> {\n    const generation = sessionGeneration;\n    const run = async (): Promise<T> => {\n      assertRuntimeActive(generation);\n      const result = await transition();\n      assertRuntimeActive(generation);\n      return result;\n    };\n    const queued = transitionQueue.then(run, run);\n    transitionQueue = queued.then(\n      () => undefined,\n      () => undefined,\n    );\n    return queued;\n  }\n\n  async function cancelFableOperation(reason: string): Promise<void> {\n    const generation = sessionGeneration;\n    assertRuntimeActive(generation);\n    if (!activeFableRun && !fableStage.match(/^(draft|review)$/u)) return;\n    if (fableStage === 'draft' || fableStage === 'review') interruptedFableStage = fableStage;\n    fableFlow?.cancel(reason);\n    const pending = activeFableRun;\n    if (pending) {\n      try {\n        await pending;\n        assertRuntimeActive(generation);\n      } catch (error) {\n        assertRuntimeActive(generation);\n        void telemetry.recordError(PLAN_EVENT.modeDisabled, error, {\n          [PLAN_FLAVOR_ATTRIBUTE]: 'fable',\n          'plan.fable.reason': 'cancel_failed',\n        });\n      }\n    }\n    assertRuntimeActive(generation);\n    activeFableRun = undefined;\n    if (interruptedFableStage) fableStage = 'interrupted';\n    if (activeContext) updateStatus(activeContext);\n    persistState();\n  }\n\n  async function activateFlavor(\n    ctx: ExtensionContext,\n    flavor: PlanningFlavor,\n    trigger: PlanModeTrigger,\n    restoring: boolean,\n  ): Promise<void> {\n    const generation = sessionGeneration;\n    assertRuntimeActive(generation);\n    activeContext = ctx;\n    if (enabled) {\n      if (activeFlavor === flavor) {\n        reportCurrentFlavor(ctx);\n        return;\n      }\n      if (activeFlavor === 'fable') await cancelFableOperation(`Leaving Fable for plan:${flavor}.`);\n      assertRuntimeActive(generation);\n      activeFlavor = flavor;\n      updateCapabilityCeiling();\n      applyToolRestriction();\n      updateStatus(ctx);\n      persistState();\n      void telemetry.recordEvent(PLAN_EVENT.modeEnabled, {\n        [PLAN_TRIGGER_ATTRIBUTE]: trigger,\n        [PLAN_FLAVOR_ATTRIBUTE]: flavor,\n        'plan.tool.count': pi.getActiveTools().length,\n      });\n      return;\n    }\n\n    let nextPlanningConfig: PlanningModeConfig | undefined;\n    try {\n      nextPlanningConfig = planningConfigProvider();\n    } catch (error) {\n      void telemetry.recordError(PLAN_EVENT.configLoadFailed, error, { [PLAN_TRIGGER_ATTRIBUTE]: trigger });\n      throw error;\n    }\n\n    if (!restoring) {\n      currentPlan = undefined;\n      planReadyForReview = false;\n      awaitingVoicePlanDecision = false;\n      activePlanId = createPlanIdentifier();\n      interruptedFableStage = undefined;\n      fableStage = 'idle';\n    } else {\n      activePlanId ??= createPlanIdentifier();\n    }\n    activePlanningConfig = nextPlanningConfig;\n    planSnapshot ??= {\n      tools: [...pi.getActiveTools()],\n      ...(ctx.model ? { model: { provider: ctx.model.provider, id: ctx.model.id } } : {}),\n      thinking: pi.getThinkingLevel(),\n    };\n    enabled = true;\n    activeFlavor = flavor;\n    applyToolRestriction();\n    updateCapabilityCeiling();\n    await applyMainPlanningConfig(ctx);\n    assertRuntimeActive(generation);\n    updateStatus(ctx);\n    persistState();\n    void telemetry.recordEvent(PLAN_EVENT.modeEnabled, {\n      [PLAN_TRIGGER_ATTRIBUTE]: trigger,\n      [PLAN_FLAVOR_ATTRIBUTE]: flavor,\n      'plan.tool.count': pi.getActiveTools().length,\n      ...(activePlanningConfig?.main?.model ? { [PLAN_MODEL_ATTRIBUTE]: activePlanningConfig.main.model } : {}),\n      ...(activePlanningConfig?.main?.thinking ? { 'plan.thinking': activePlanningConfig.main.thinking } : {}),\n    });\n  }\n\n  async function exitPlanMode(ctx: ExtensionContext, trigger: PlanModeTrigger): Promise<boolean> {\n    const generation = sessionGeneration;\n    assertRuntimeActive(generation);\n    if (!enabled) {\n      reportCurrentFlavor(ctx);\n      return false;\n    }\n    await cancelFableOperation('Plan mode is exiting.');\n    assertRuntimeActive(generation);\n    const snapshot = planSnapshot;\n    const restored = await restoreMainAgent(ctx, snapshot);\n    assertRuntimeActive(generation);\n    if (!restored) {\n      ctx.ui.notify('Previous model was not restored. Plan mode remains read-only.', WARNING_STYLE);\n      updateStatus(ctx);\n      persistState();\n      void telemetry.recordWarning(PLAN_EVENT.modeDisabled, 'Plan mode restoration failed.', {\n        [PLAN_TRIGGER_ATTRIBUTE]: trigger,\n        [PLAN_FLAVOR_ATTRIBUTE]: activeFlavor ?? 'unknown',\n        'plan.restored': false,\n      });\n      return false;\n    }\n\n    const hadPlan = Boolean(currentPlan);\n    toolRestriction?.update(planToolRestriction(undefined, diagnosticTools));\n    capabilityCeiling?.dispose();\n    capabilityCeiling = undefined;\n    enabled = false;\n    activeFlavor = undefined;\n    activePlanningConfig = undefined;\n    awaitingVoicePlanDecision = false;\n    planSnapshot = undefined;\n    debugEvidence = undefined;\n    fableStage = 'idle';\n    interruptedFableStage = undefined;\n    updateStatus(ctx);\n    persistState();\n    void telemetry.recordEvent(PLAN_EVENT.modeDisabled, {\n      [PLAN_TRIGGER_ATTRIBUTE]: trigger,\n      [PLAN_FLAVOR_ATTRIBUTE]: 'normal',\n      'plan.written': hadPlan,\n      'plan.restored': true,\n    });\n    return true;\n  }\n\n  fableFlow = createFablePlanFlow({\n    broker: fableBroker,\n    isAuthorized: () => active && enabled && activeFlavor === 'fable' && isFableBrokerAvailable(),\n    onStage: (stage) => {\n      if (!active) return;\n      fableStage = stage;\n      if (stage === 'completed' || stage === 'failed' || stage === 'cancelled') interruptedFableStage = undefined;\n      if (activeContext) updateStatus(activeContext);\n      if (enabled) persistState();\n    },\n    onError: (error) => {\n      if (!active) return;\n      void telemetry.recordError(PLAN_EVENT.modeEnabled, error, {\n        [PLAN_FLAVOR_ATTRIBUTE]: 'fable',\n        'plan.fable.reason': 'flow_error',\n      });\n    },\n  });\n\n  async function applyPlanReviewDecision(\n    decision: typeof EXIT_PLAN_DECISION | typeof CONTINUE_PLAN_DECISION,\n    ctx: ExtensionContext,\n  ) {\n    assertRuntimeActive();\n    void telemetry.recordEvent(PLAN_EVENT.planReviewCompleted, {\n      'plan.outcome': decision === EXIT_PLAN_DECISION ? 'exited' : 'continued',\n    });\n    if (decision === EXIT_PLAN_DECISION) {\n      const exited = await queueTransition(() => exitPlanMode(ctx, PLAN_MODE_TRIGGER_PLAN_APPROVED));\n      return {\n        content: [\n          {\n            type: 'text' as const,\n            text: exited\n              ? PLAN_EXIT_APPROVED_TEXT\n              : 'The previous model could not be restored. Plan mode remains read-only.',\n          },\n        ],\n        details: { exited },\n      };\n    }\n\n    planReadyForReview = false;\n    return {\n      content: [{ type: 'text' as const, text: PLAN_CONTINUE_TEXT }],\n      details: { exited: false },\n    };\n  }\n\n  return {\n    services: [\n      (cordis: Context) => {\n        cordis.inject([DOOM_TOOL_SURFACE_SERVICE], (surfaceContext) => {\n          const surface = readDoomToolSurface(surfaceContext);\n          if (!surface) return undefined;\n          const handle = surface.register({ source: PLAN_LEADER_SOURCE, restrict: currentToolRestriction() });\n          toolRestriction = handle;\n          return () => {\n            if (toolRestriction !== handle) return;\n            toolRestriction = undefined;\n            handle.dispose();\n          };\n        });\n        cordis.inject([DOOM_FABLE_PLAN_SERVICE], (serviceContext) => {\n          const service = readDoomFablePlanService(serviceContext);\n          if (!service) return undefined;\n          fablePlanService = service;\n          return () => {\n            if (fablePlanService !== service) return;\n            fablePlanService = undefined;\n            if (activeFableRun) fableFlow?.cancel('The Team Fable service was unloaded.');\n          };\n        });\n        cordis.inject([DOOM_SUBAGENT_POLICY_SERVICE], (serviceContext) => {\n          const service = readDoomSubagentPolicyService(serviceContext);\n          if (!service) return undefined;\n          subagentPolicyService = service;\n          updateCapabilityCeiling();\n          return () => {\n            if (subagentPolicyService !== service) return;\n            capabilityCeiling?.dispose();\n            capabilityCeiling = undefined;\n            subagentPolicyService = undefined;\n          };\n        });\n        if (doomIntegrations) {\n          cordis.inject([DOOM_MINOR_MODE_CATALOG_SERVICE, DOOM_NARRATION_SERVICE], (voiceContext) => {\n            const services: PlanVoiceReviewServices = {\n              modes: requireMinorModeCatalog(voiceContext),\n              narration: requireDoomNarrationService(voiceContext),\n            };\n            voiceReviewServices = services;\n            return () => {\n              if (voiceReviewServices === services) voiceReviewServices = undefined;\n            };\n          });\n          cordis.inject([DOOM_MINOR_MODE_CATALOG_SERVICE], (modeContext) => {\n            const owner = registerMinorModeOwner<ExtensionContext>(requireMinorModeCatalog(modeContext), {\n              descriptor: {\n                source: PLAN_LEADER_SOURCE,\n                id: MODE_ID,\n                label: MODE_LABEL,\n                description: 'Read-only planning with normal, debug, and Fable flavors.',\n                order: MODE_ORDER,\n                actions: [\n                  {\n                    id: MODE_ACTIVATE_ACTION,\n                    label: 'Activate',\n                    description: 'Activate plan mode or switch its planning flavor.',\n                    contexts: ['tui', 'headless'],\n                    parameters: [\n                      {\n                        name: 'flavor',\n                        label: 'Flavor',\n                        kind: 'enum',\n                        required: true,\n                        choices: [\n                          { value: 'normal', label: 'Normal' },\n                          { value: 'debug', label: 'Debug' },\n                          { value: 'fable', label: 'Fable' },\n                        ],\n                      },\n                    ],\n                  },\n                  {\n                    id: MODE_DEACTIVATE_ACTION,\n                    label: 'Deactivate',\n                    description: 'Exit plan mode and restore the previous agent configuration.',\n                    contexts: ['tui', 'headless'],\n                    parameters: [],\n                  },\n                ],\n              },\n              initialState: currentPlanModeState(),\n              async handleAction(actionId, argumentsValue, execution) {\n                if (!active) throw new Error('Plan runtime is disposed.');\n                if (actionId === MODE_ACTIVATE_ACTION) {\n                  const flavor = argumentsValue.flavor;\n                  if (flavor !== 'normal' && flavor !== 'debug' && flavor !== 'fable') {\n                    throw new Error('A valid plan flavor is required.');\n                  }\n                  await queueTransition(() =>\n                    activateFlavor(execution.context, flavor, PLAN_MODE_TRIGGER_LEADER, false),\n                  );\n                  return { message: `Plan mode is active with the ${flavor} flavor.` };\n                }\n                if (actionId === MODE_DEACTIVATE_ACTION) {\n                  const exited = await queueTransition(() => exitPlanMode(execution.context, PLAN_MODE_TRIGGER_LEADER));\n                  return { message: exited ? 'Plan mode deactivated.' : 'Plan mode remains active.' };\n                }\n                throw new Error(`Unknown plan mode action: ${actionId}`);\n              },\n              onError: (error) => void telemetry.recordError(PLAN_EVENT.configLoadFailed, error),\n            });\n            modeOwner = owner;\n            return () => {\n              owner.dispose();\n              if (modeOwner === owner) modeOwner = undefined;\n            };\n          });\n          cordis.inject([DOOM_UI_HUB_SERVICE], (uiContext) => {\n            const hub = requireDoomUiHub(uiContext);\n            const leader = hub.registerLeader({\n              source: PLAN_LEADER_SOURCE,\n              bindings: planLeaderBindings(enabled),\n            });\n            const config = hub.registerConfig<ExtensionContext>({\n              source: PLAN_LEADER_SOURCE,\n              // Read at publish time, not cached: plan mode re-reads this file on every\n              // activation anyway, so the panel should show whatever is on disk now.\n              listSections: () => {\n                // Read from the live session so the list is the models this session\n                // can actually switch to, not a table compiled into the package.\n                const models = sessionModels();\n                try {\n                  return planConfigSections(planningConfigProvider(), planConfigNotice, models);\n                } catch (error) {\n                  // A malformed config file must not take session start down with it. The\n                  // panel is where someone would go to repair it, so it has to still draw.\n                  return planConfigSections(undefined, error instanceof Error ? error.message : String(error), models);\n                }\n              },\n              handlers: {\n                [CONFIG_ACTION.set]: async ({ fieldId, value }) => {\n                  const setting = planSettingByFieldId(fieldId);\n                  if (!setting || !value) return;\n                  planConfigNotice = undefined;\n                  await setDoomConfigValue(globalDoomConfigPath(), [...setting.keyPath], value);\n                },\n                [CONFIG_ACTION.clear]: async ({ fieldId }) => {\n                  const setting = planSettingByFieldId(fieldId);\n                  if (!setting) return;\n                  planConfigNotice = undefined;\n                  await unsetDoomConfigValue(globalDoomConfigPath(), [...setting.keyPath]);\n                },\n              },\n              onError: (error) => {\n                if (active) planConfigNotice = error instanceof Error ? error.message : String(error);\n              },\n            });\n            leaderContribution = leader;\n            planConfigContribution = config;\n            return () => {\n              config.dispose();\n              leader.dispose();\n              if (planConfigContribution === config) planConfigContribution = undefined;\n              if (leaderContribution === leader) leaderContribution = undefined;\n            };\n          });\n        }\n        if (doomIntegrations) {\n          const assertVoiceTransitionNotCancelled = (signal: AbortSignal): void => {\n            assertRuntimeActive();\n            if (signal.aborted) {\n              throw signal.reason instanceof Error ? signal.reason : new Error('Plan voice transition was cancelled.');\n            }\n          };\n          const activatePlanVoiceTool: VoiceToolDefinition<ExtensionContext> = {\n            descriptor: {\n              source: PLAN_VOICE_SOURCE,\n              id: PLAN_VOICE_ACTIVATE_ID,\n              name: PLAN_VOICE_ACTIVATE_NAME,\n              label: 'Activate Plan',\n              description: 'Activate or switch the serialized read-only planning mode flavor.',\n              order: 10,\n              inputSchema: PLAN_VOICE_ACTIVATE_INPUT_SCHEMA,\n              resultSchema: PLAN_VOICE_RESULT_SCHEMA,\n            },\n            execute(input, execution) {\n              const flavor = parsePlanningFlavor(isRecord(input) ? input.flavor : undefined);\n              if (!flavor) throw new Error('A valid plan flavor is required.');\n              assertVoiceTransitionNotCancelled(execution.signal);\n              return queueTransition(async () => {\n                assertVoiceTransitionNotCancelled(execution.signal);\n                const previousEnabled = enabled;\n                const previousFlavor = activeFlavor;\n                await activateFlavor(execution.context, flavor, PLAN_MODE_TRIGGER_VOICE_TOOL, false);\n                return {\n                  active: enabled,\n                  flavor: activeFlavor ?? flavor,\n                  changed: previousEnabled !== enabled || previousFlavor !== activeFlavor,\n                };\n              });\n            },\n          };\n          const exitPlanVoiceTool: VoiceToolDefinition<ExtensionContext> = {\n            descriptor: {\n              source: PLAN_VOICE_SOURCE,\n              id: PLAN_VOICE_EXIT_ID,\n              name: PLAN_VOICE_EXIT_NAME,\n              label: 'Exit Plan',\n              description: 'Exit read-only planning mode and restore the previous agent configuration.',\n              order: 20,\n              inputSchema: PLAN_VOICE_EXIT_INPUT_SCHEMA,\n              resultSchema: PLAN_VOICE_RESULT_SCHEMA,\n            },\n            execute(_input, execution) {\n              assertVoiceTransitionNotCancelled(execution.signal);\n              return queueTransition(async () => {\n                assertVoiceTransitionNotCancelled(execution.signal);\n                const previousEnabled = enabled;\n                const exited = await exitPlanMode(execution.context, PLAN_MODE_TRIGGER_VOICE_TOOL);\n                return {\n                  active: enabled,\n                  flavor: activeFlavor ?? null,\n                  changed: previousEnabled !== enabled || exited,\n                };\n              });\n            },\n          };\n          cordis.inject([DOOM_VOICE_TOOLS_SERVICE], (voiceContext) => {\n            const service = requireDoomVoiceToolsService(voiceContext);\n            const activate = service.register(activatePlanVoiceTool);\n            const exit = service.register(exitPlanVoiceTool);\n            return () => {\n              exit.dispose();\n              activate.dispose();\n            };\n          });\n        }\n        if (doomIntegrations) {\n          cordis.inject([DOOM_UI_HUB_SERVICE], (uiContext) => {\n            const dispose = requireDoomUiHub(uiContext).registerLeaderActions<ExtensionContext>({\n              source: PLAN_LEADER_SOURCE,\n              handlers: {\n                'plan.normal': () => {\n                  const ctx = active ? activeContext : undefined;\n                  return ctx\n                    ? queueTransition(() => activateFlavor(ctx, 'normal', PLAN_MODE_TRIGGER_LEADER, false))\n                    : undefined;\n                },\n                'plan.exit': () => {\n                  const ctx = active ? activeContext : undefined;\n                  return ctx\n                    ? queueTransition(async () => {\n                        await exitPlanMode(ctx, PLAN_MODE_TRIGGER_LEADER);\n                      })\n                    : undefined;\n                },\n                'plan.debug': () => {\n                  const ctx = active ? activeContext : undefined;\n                  return ctx\n                    ? queueTransition(() => activateFlavor(ctx, 'debug', PLAN_MODE_TRIGGER_LEADER, false))\n                    : undefined;\n                },\n                'plan.fable': () => {\n                  const ctx = active ? activeContext : undefined;\n                  return ctx\n                    ? queueTransition(() => activateFlavor(ctx, 'fable', PLAN_MODE_TRIGGER_LEADER, false))\n                    : undefined;\n                },\n              },\n              onError: (error, actionName) => {\n                if (!active) return;\n                if (activeContext?.hasUI) {\n                  activeContext.ui.notify(\n                    `Leader action ${actionName} failed. Plan mode remains read-only.`,\n                    WARNING_STYLE,\n                  );\n                }\n                void telemetry.recordError(PLAN_EVENT.modeEnabled, error, {\n                  [PLAN_TRIGGER_ATTRIBUTE]: PLAN_MODE_TRIGGER_LEADER,\n                  'plan.action': actionName,\n                });\n              },\n            });\n            disposeLeaderActions = dispose;\n            return () => {\n              dispose();\n              if (disposeLeaderActions === dispose) disposeLeaderActions = undefined;\n            };\n          });\n        }\n      },\n    ],\n    onStop: shutdownPlanRuntime,\n    onDispose: shutdownPlanRuntime,\n    tools: [\n      {\n        name: RECORD_DEBUG_EVIDENCE_TOOL,\n        label: 'Record Debug Evidence',\n        description: 'Record optional bounded debug evidence while planning a repository fix.',\n        promptSnippet:\n          'Record the issue and any relevant reproduction, logs, traces, process output, or browser evidence',\n        parameters: {\n          type: 'object',\n          properties: {\n            issue: { type: 'string' },\n            expectedBehavior: { type: 'string' },\n            reproductionAttempt: { type: 'string' },\n            actualBehavior: { type: 'string' },\n            logs: { type: 'array', items: { type: 'string' } },\n            correlatedTraceEvidence: { type: 'array', items: { type: 'string' } },\n            processOutput: { type: 'array', items: { type: 'string' } },\n            browserConsoleEvidence: { type: 'array', items: { type: 'string' } },\n            correlationIds: { type: 'array', items: { type: 'string' } },\n            timestamps: { type: 'array', items: { type: 'string' } },\n            verifiedFacts: { type: 'array', items: { type: 'string' } },\n            hypotheses: { type: 'array', items: { type: 'string' } },\n            unavailableEvidence: { type: 'array', items: { type: 'string' } },\n          },\n          required: ['issue'],\n          additionalProperties: false,\n        },\n        async execute(_toolCallId, params) {\n          assertRuntimeActive();\n          if (!enabled || activeFlavor !== 'debug') {\n            return { content: [{ type: 'text', text: 'Debug planning is not active.' }], details: { recorded: false } };\n          }\n          try {\n            debugEvidence = parseDebugEvidencePacket(params);\n          } catch (error) {\n            void telemetry.recordWarning(PLAN_EVENT.modeEnabled, error, {\n              [PLAN_FLAVOR_ATTRIBUTE]: 'debug',\n              'plan.debug.reason': 'invalid_evidence',\n            });\n            throw error;\n          }\n          if (activeContext) updateStatus(activeContext);\n          return {\n            content: [{ type: 'text', text: 'Debug evidence recorded as optional planning context.' }],\n            details: { recorded: true },\n          };\n        },\n      },\n      {\n        name: RUN_FABLE_PLAN_TOOL,\n        label: 'Run Fable Plan',\n        description:\n          'Send a bounded, sanitized planning packet to the local Fable broker for one repository-aware draft.',\n        promptSnippet: 'Run the local Fable draft with the bounded planning packet',\n        parameters: {\n          type: 'object',\n          properties: {\n            goal: { type: 'array', items: { type: 'string' } },\n            constraints: { type: 'array', items: { type: 'string' } },\n            decisions: { type: 'array', items: { type: 'string' } },\n            verifiedFindings: { type: 'array', items: { type: 'object' } },\n            inferredFindings: { type: 'array', items: { type: 'string' } },\n            unresolvedQuestions: { type: 'array', items: { type: 'string' } },\n            currentPlan: { type: 'string' },\n          },\n          additionalProperties: false,\n        },\n        async execute(_toolCallId, params, signal) {\n          const generation = sessionGeneration;\n          assertRuntimeActive(generation);\n          if (!enabled || activeFlavor !== 'fable') {\n            return {\n              content: [{ type: 'text', text: 'Fable planning is not active.' }],\n              details: { started: false } as Record<string, unknown>,\n            };\n          }\n          if (!isFableBrokerAvailable()) {\n            return {\n              content: [\n                { type: 'text', text: 'The local Fable broker is unavailable. Fable planning remains disabled.' },\n              ],\n              details: { started: false, errorCode: 'broker_unavailable' } as Record<string, unknown>,\n            };\n          }\n          const flow = fableFlow;\n          if (!flow) throw new Error('Fable planning flow is unavailable.');\n          const operation = flow.run(params, signal);\n          activeFableRun = operation;\n          try {\n            const result = await operation;\n            assertRuntimeActive(generation);\n            const text = result.draft\n              ? `Fable draft:\\n${result.draft}`\n              : `Fable planning ${result.status}: ${result.errorCode ?? 'no output'}.`;\n            return {\n              content: [{ type: 'text', text }],\n              details: { ...result, started: true } as Record<string, unknown>,\n            };\n          } finally {\n            if (active && generation === sessionGeneration && activeFableRun === operation) activeFableRun = undefined;\n          }\n        },\n      },\n      {\n        name: WRITE_PLAN_TOOL,\n        label: 'Write Plan',\n        description:\n          'After presenting the complete implementation plan as Markdown in chat, save that visible plan to a unique Markdown file in the configured plans directory.',\n        promptSnippet: 'Save the implementation plan already presented in chat to the configured plans directory',\n        parameters: { type: 'object', properties: {}, additionalProperties: false },\n        async execute(toolCallId, _params, signal, onUpdate, ctx) {\n          const generation = sessionGeneration;\n          assertRuntimeActive(generation);\n          if (!enabled) {\n            return {\n              content: [{ type: 'text', text: 'Plan mode is disabled. Use normal file tools instead.' }],\n              details: { written: false },\n            };\n          }\n          const content = visiblePlanForToolCall(ctx.sessionManager.getBranch(), toolCallId);\n          if (!content) {\n            const error = new Error(\n              'Present the complete implementation plan as visible Markdown in chat before calling write_plan.',\n            );\n            void telemetry.recordError(PLAN_EVENT.writePlanFailed, error, { 'plan.reason': 'missing_visible_plan' });\n            throw error;\n          }\n\n          const startedAt = Date.now();\n          const repoRoot = getHarnessState().root ?? ctx.cwd;\n          const plansDirectory = resolvePlanningPlansDirectory(\n            activePlanningConfig?.plansDirectory,\n            repoRoot,\n            os.homedir(),\n          );\n          const sessionId = planSessionIdentifier(ctx.sessionManager.getSessionId());\n          activePlanId ??= createPlanIdentifier();\n          const storedPlanPath =\n            currentPlan?.planId === activePlanId && path.dirname(currentPlan.path) === plansDirectory\n              ? currentPlan.path\n              : undefined;\n          const title = planTitleSlug(content);\n          let planId = activePlanId;\n          let planPath = storedPlanPath ?? path.join(plansDirectory, `${title}--${planId}.md`);\n          const timeoutController = new AbortController();\n          const timeoutError = new Error(`Writing ${planPath} timed out after ${WRITE_PLAN_TIMEOUT_MS}ms.`);\n          const timeout = setTimeout(() => timeoutController.abort(timeoutError), WRITE_PLAN_TIMEOUT_MS);\n          const writeSignal = AbortSignal.any([\n            timeoutController.signal,\n            runtimeAbortController.signal,\n            ...(signal ? [signal] : []),\n          ]);\n          let phase: PlanWritePhase = 'checking';\n          const reportPhase = (): void => {\n            onUpdate?.({\n              content: [{ type: 'text', text: `${phase === 'checking' ? 'Checking' : 'Writing'} ${planPath}...` }],\n              details: { phase, path: planPath, startedAt },\n            });\n          };\n          const recordRefusal = (refusal: string, message: string): void => {\n            void telemetry.recordWarning(PLAN_EVENT.writePlanUnsafePath, message, {\n              'plan.phase': phase,\n              'plan.refusal': refusal,\n            });\n          };\n\n          try {\n            reportPhase();\n            try {\n              await waitForAbortable(\n                () => fs.promises.mkdir(plansDirectory, { recursive: true, mode: PRIVATE_DIRECTORY_MODE }),\n                writeSignal,\n              );\n            } catch (error) {\n              if (writeSignal.aborted) throw abortReason(writeSignal);\n              throw new Error(`Could not create the configured plans directory ${plansDirectory}.`, { cause: error });\n            }\n            const directoryStats = await waitForAbortable(() => fs.promises.lstat(plansDirectory), writeSignal);\n            const resolvedPlansDirectory = await waitForAbortable(\n              () => fs.promises.realpath(plansDirectory),\n              writeSignal,\n            );\n            if (directoryStats.isSymbolicLink() || !directoryStats.isDirectory()) {\n              recordRefusal(\n                'unsafe_plans_directory',\n                'Refused to write the plan because the configured path is unsafe.',\n              );\n              return {\n                content: [{ type: 'text', text: 'Refused to write the plan because the configured path is unsafe.' }],\n                details: { written: false, path: planPath, phase, durationMs: Date.now() - startedAt },\n              };\n            }\n\n            assertRuntimeActive(generation);\n            phase = 'writing';\n            reportPhase();\n            let planFile: Awaited<ReturnType<typeof fs.promises.open>> | undefined;\n            try {\n              for (let attempt = 0; attempt < PLAN_ALLOCATION_ATTEMPTS; attempt += 1) {\n                try {\n                  const createFlags = storedPlanPath ? 0 : fs.constants.O_EXCL;\n                  planFile = await waitForAbortable(\n                    () =>\n                      fs.promises.open(\n                        planPath,\n                        fs.constants.O_CREAT |\n                          fs.constants.O_WRONLY |\n                          fs.constants.O_NONBLOCK |\n                          fs.constants.O_NOFOLLOW |\n                          createFlags,\n                        PRIVATE_FILE_MODE,\n                      ),\n                    writeSignal,\n                  );\n                  break;\n                } catch (error) {\n                  const collision =\n                    !storedPlanPath && error instanceof Error && 'code' in error && String(error.code) === 'EEXIST';\n                  if (!collision || attempt === PLAN_ALLOCATION_ATTEMPTS - 1) throw error;\n                  planId = createPlanIdentifier();\n                  activePlanId = planId;\n                  planPath = path.join(plansDirectory, `${title}--${planId}.md`);\n                  persistState();\n                }\n              }\n              if (!planFile) throw new Error(`Could not allocate a unique plan filename in ${plansDirectory}.`);\n              const resolvedAfterOpen = await waitForAbortable(() => fs.promises.realpath(plansDirectory), writeSignal);\n              const stats = await waitForAbortable(() => planFile!.stat(), writeSignal);\n              if (resolvedAfterOpen !== resolvedPlansDirectory || !stats.isFile() || stats.nlink !== 1) {\n                recordRefusal('invalid_destination', INVALID_PLAN_DESTINATION);\n                return {\n                  content: [{ type: 'text', text: INVALID_PLAN_DESTINATION }],\n                  details: { written: false, path: planPath, phase, durationMs: Date.now() - startedAt },\n                };\n              }\n              await waitForAbortable(() => planFile!.truncate(0), writeSignal);\n              await waitForAbortable(\n                () => planFile!.writeFile(content, { encoding: 'utf8', signal: writeSignal }),\n                writeSignal,\n              );\n            } catch (error) {\n              if (\n                error instanceof Error &&\n                'code' in error &&\n                ['EISDIR', 'ELOOP', 'ENXIO'].includes(String(error.code))\n              ) {\n                recordRefusal('invalid_destination', INVALID_PLAN_DESTINATION);\n                return {\n                  content: [{ type: 'text', text: INVALID_PLAN_DESTINATION }],\n                  details: { written: false, path: planPath, phase, durationMs: Date.now() - startedAt },\n                };\n              }\n              throw error;\n            } finally {\n              await planFile?.close();\n            }\n            assertRuntimeActive(generation);\n            currentPlan = { content, path: planPath, sessionId, planId, title, writtenAt: new Date().toISOString() };\n            pi.appendEntry(PLAN_DOCUMENT_ENTRY, currentPlan);\n            announcePlanDocument(ctx, currentPlan);\n            planReadyForReview = true;\n            awaitingVoicePlanDecision = false;\n            void telemetry.recordEvent(PLAN_EVENT.planWritten, {\n              'plan.written': true,\n              'plan.bytes': Buffer.byteLength(content, 'utf8'),\n              'plan.duration_ms': Date.now() - startedAt,\n              'plan.revised': Boolean(storedPlanPath),\n            });\n            return {\n              content: [{ type: 'text', text: `Wrote implementation plan to ${planPath}.` }],\n              details: { written: true, path: planPath, phase, durationMs: Date.now() - startedAt },\n            };\n          } catch (error) {\n            if (!active || generation !== sessionGeneration) throw abortReason(runtimeAbortController.signal);\n            const attributes = {\n              'plan.phase': phase,\n              'plan.duration_ms': Date.now() - startedAt,\n            };\n            if (timeoutController.signal.aborted && !signal?.aborted) {\n              const timedOut = new Error(`write_plan timed out during ${phase} for ${planPath}.`, { cause: error });\n              void telemetry.recordError(PLAN_EVENT.writePlanTimedOut, timedOut, {\n                ...attributes,\n                'plan.timeout_ms': WRITE_PLAN_TIMEOUT_MS,\n              });\n              throw timedOut;\n            }\n            void telemetry.recordError(PLAN_EVENT.writePlanFailed, error, {\n              ...attributes,\n              'plan.cancelled': signal?.aborted ?? false,\n            });\n            throw error;\n          } finally {\n            clearTimeout(timeout);\n          }\n        },\n      },\n      {\n        name: COMPLETE_PLAN_TOOL,\n        label: 'Complete Plan',\n        description:\n          'Present the saved implementation plan for exit-or-continue approval. Interactive sessions use the normal selector; autonomous voice narrates a plain-text handoff and waits for the next user message.',\n        promptSnippet: 'Request explicit exit-or-continue approval after the saved plan has been presented',\n        promptGuidelines: [\n          'After write_plan succeeds, call complete_plan without a decision so it can present the review question.',\n          'When autonomous voice returns an awaiting-response result, stop. Interpret the next ordinary user message, then call complete_plan again with decision \"exit\" or \"continue\".',\n          `Never pass decision \"${EXIT_PLAN_DECISION}\" without the user explicitly choosing \"${EXIT_PLAN_MODE_CHOICE}\".`,\n        ],\n        parameters: {\n          type: 'object',\n          properties: {\n            decision: { type: 'string', enum: [EXIT_PLAN_DECISION, CONTINUE_PLAN_DECISION] },\n          },\n          additionalProperties: false,\n        },\n        async execute(_toolCallId, params, _signal, _onUpdate, ctx) {\n          const generation = sessionGeneration;\n          assertRuntimeActive(generation);\n          if (!enabled) {\n            return {\n              content: [{ type: 'text', text: 'Plan mode is already disabled.' }],\n              details: { exited: false },\n            };\n          }\n          if (!planReadyForReview) {\n            return {\n              content: [\n                {\n                  type: 'text',\n                  text: 'Present the complete plan in chat and save it with write_plan before requesting approval.',\n                },\n              ],\n              details: { exited: false },\n            };\n          }\n          if (!ctx.hasUI) {\n            void telemetry.recordEvent(PLAN_EVENT.planReviewCompleted, { 'plan.outcome': 'no_ui' });\n            return {\n              content: [\n                {\n                  type: 'text',\n                  text: 'The plan is complete, but this run cannot ask the user interactively. Remain in plan mode until the user uses SPC p e.',\n                },\n              ],\n              details: { exited: false },\n            };\n          }\n\n          const decision = isRecord(params) ? params.decision : undefined;\n          const hasDecision = decision === EXIT_PLAN_DECISION || decision === CONTINUE_PLAN_DECISION;\n          if (awaitingVoicePlanDecision) {\n            if (!hasDecision) {\n              throw new Error('The narrated plan review is waiting for an explicit exit or continue decision.');\n            }\n            awaitingVoicePlanDecision = false;\n            return applyPlanReviewDecision(decision, ctx);\n          }\n          if (decision !== undefined) {\n            throw new Error('Call complete_plan without a decision before submitting a narrated plan-review answer.');\n          }\n\n          if (await requestVoicePlanReview()) {\n            assertRuntimeActive(generation);\n            awaitingVoicePlanDecision = true;\n            return voicePlanReviewResult();\n          }\n\n          const choice = await ctx.ui.select(PLAN_REVIEW_TITLE, [...PLAN_REVIEW_OPTIONS]);\n          assertRuntimeActive(generation);\n          return applyPlanReviewDecision(\n            choice === EXIT_PLAN_MODE_CHOICE ? EXIT_PLAN_DECISION : CONTINUE_PLAN_DECISION,\n            ctx,\n          );\n        },\n      },\n    ],\n    events: {\n      tool_call: async (event: ToolCallEvent, ctx) => {\n        if (!active || !enabled) return undefined;\n        if (currentToolRestriction()([event.toolName], [event.toolName]).length === 0) {\n          return { block: true, reason: `Plan mode blocks the ${event.toolName} tool. Use SPC p e to restore access.` };\n        }\n        const model = planningSubagentModel(activePlanningConfig?.subagents, ctx.model);\n        if (event.toolName === TASK_TOOL) {\n          if (model) configurePlanningTaskInput(event.input as MutableTaskInput, model);\n          return undefined;\n        }\n        if (event.toolName !== SUBAGENT_TOOL) return undefined;\n\n        const input = event.input as MutableSubagentInput;\n        if (isBlockedSubagentManagementAction(input.action)) {\n          return {\n            block: true,\n            reason: `Plan mode blocks subagent management action '${input.action}'. Use SPC p e first.`,\n          };\n        }\n        constrainSubagentInput(input);\n        if (model) configurePlanningSubagentInput(input, model);\n        return undefined;\n      },\n      before_agent_start: async (event, ctx) => {\n        if (!active) return undefined;\n        const sections: string[] = [];\n        if (enabled) {\n          const repoRoot = getHarnessState().root ?? ctx.cwd;\n          const plansDirectory = resolvePlanningPlansDirectory(\n            activePlanningConfig?.plansDirectory,\n            repoRoot,\n            os.homedir(),\n          );\n          sections.push(\n            buildPlanModeBasePrompt(plansDirectory, PLAN_CLI_CAPABILITIES),\n            buildFlavorPlanningPrompt(activeFlavor!, plansDirectory, debugEvidence, fableStage, PLAN_CLI_CAPABILITIES),\n          );\n        }\n        if (currentPlan) {\n          // Read from disk rather than from what write_plan remembered. The plan is\n          // editable in the cockpit, and a reader who corrected it expects the\n          // agent to implement the correction, not the draft it wrote. A file that\n          // has since been moved or removed falls back to the remembered text, so\n          // the plan never silently disappears from the prompt.\n          let content = currentPlan.content;\n          try {\n            content = await fs.promises.readFile(currentPlan.path, 'utf8');\n          } catch {\n            content = currentPlan.content;\n          }\n          sections.push(`[CURRENT PLAN]\\nSource: ${currentPlan.path}\\n\\n${content}`);\n        }\n        if (sections.length === 0) return undefined;\n        return { systemPrompt: `${event.systemPrompt}\\n\\n${sections.join('\\n\\n')}` };\n      },\n      context: async (event) => {\n        if (!active) return undefined;\n        return {\n          messages: event.messages.filter((message) => {\n            const custom = message as { customType?: string };\n            return custom.customType !== PLAN_MODE_CONTEXT;\n          }),\n        };\n      },\n      session_start: async (_event, ctx) => {\n        if (!active) return;\n        configSessionCtx = ctx;\n        const generation = ++sessionGeneration;\n        const entries = ctx.sessionManager.getEntries();\n        const state = entries\n          .flatMap((entry) =>\n            entry.type === 'custom' && entry.customType === PLAN_MODE_ENTRY\n              ? [parsePersistedPlanState(entry.data)]\n              : [],\n          )\n          .filter((value): value is PersistedPlanModeState => value !== undefined)\n          .at(-1);\n        const piSessionId = ctx.sessionManager.getSessionId();\n        const sessionId = planSessionIdentifier(piSessionId);\n        const storedPlan = entries\n          .flatMap((entry) =>\n            entry.type === 'custom' && entry.customType === PLAN_DOCUMENT_ENTRY ? [parsePlanDocument(entry.data)] : [],\n          )\n          .filter((value): value is PlanDocument => value !== undefined)\n          .at(-1);\n\n        const snapshotFromPreviousSession = planSnapshot;\n        capabilityCeiling?.dispose();\n        capabilityCeiling = undefined;\n        currentPlan = storedPlan?.sessionId === sessionId ? storedPlan : undefined;\n        // A resumed session keeps its plan, so it keeps the announcement too; one\n        // that restored none clears whatever a previous run left behind under this\n        // session id.\n        if (currentPlan) announcePlanDocument(ctx, currentPlan);\n        else retirePlanDocument(ctx);\n        activePlanId = state?.planId ?? currentPlan?.planId;\n        planReadyForReview = false;\n        awaitingVoicePlanDecision = false;\n        activePlanningConfig = undefined;\n        debugEvidence = undefined;\n        enabled = false;\n        activeFlavor = undefined;\n        // A session that restores nothing never reaches updateStatus, and the menu\n        // would otherwise still offer the exit the previous session left on it.\n        updateLeader();\n        planSnapshot = state?.originalSnapshot;\n        interruptedFableStage = state?.interruptedFableStage;\n        fableStage = interruptedFableStage ? 'interrupted' : 'idle';\n        activeContext = ctx;\n        if (state?.activeFlavor) {\n          await activateFlavor(ctx, state.activeFlavor, PLAN_MODE_TRIGGER_SESSION_RESTORE, true);\n          assertRuntimeActive(generation);\n        } else {\n          const snapshotToRestore = state?.originalSnapshot ?? snapshotFromPreviousSession;\n          if (snapshotToRestore) {\n            await restoreMainAgent(ctx, snapshotToRestore);\n            assertRuntimeActive(generation);\n          }\n          applyToolRestriction();\n          assertRuntimeActive(generation);\n          planSnapshot = undefined;\n          updateStatus(ctx);\n        }\n      },\n    },\n  };\n}\n"],"mappings":"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"}