{"version":3,"file":"planner-run.mjs","names":[],"sources":["../../../../../../../ai/src/planner/planner-run.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { log } from \"@warlock.js/logger\";\nimport type { AgentContract } from \"../contracts/agent/agent.contract\";\nimport type { PlannerCapability } from \"../contracts/planner/planner-capability.type\";\nimport type { PlannerConfig } from \"../contracts/planner/planner-config.type\";\nimport type {\n  PlannerExecuteOptions,\n  PlannerStepDirective,\n} from \"../contracts/planner/planner-execute-options.type\";\nimport type { PlannerPlan, PlannerStep } from \"../contracts/planner/planner-plan.type\";\nimport type {\n  PlannerReport,\n  PlannerResult,\n  PlannerStepSnapshot,\n} from \"../contracts/planner/planner-result.type\";\nimport type {\n  PlannerSnapshot,\n  PlannerSnapshotStatus,\n} from \"../contracts/planner/planner-snapshot.type\";\nimport type { BaseReport } from \"../contracts/result/base-report.type\";\nimport { REPORT_SCHEMA_VERSION } from \"../contracts/result/base-report.type\";\nimport type { BaseResult } from \"../contracts/result/base-result.type\";\nimport type { Usage } from \"../contracts/result/usage.type\";\nimport { AIError } from \"../errors/ai-error\";\nimport { PlannerCancelledError } from \"../errors/planner-cancelled-error\";\nimport { PlannerFailedError } from \"../errors/planner-failed-error\";\nimport { PlannerPlanInvalidError } from \"../errors/planner-plan-invalid-error\";\nimport { SchemaValidationError } from \"../errors/schema-validation-error\";\nimport { notifyObservers } from \"../observe/resolve-observers\";\nimport { accumulateCost } from \"../utils/compute-cost\";\nimport { generateRunId } from \"../utils/generate-run-id\";\nimport { captureChildReport, withoutRunFrame } from \"../utils/run-context\";\nimport { stampReportLineage } from \"../utils/stamp-report-lineage\";\nimport type { DagNode, PlannerDag } from \"./dag-scheduler\";\nimport { buildDag, readyNodes, sinkNodes } from \"./dag-scheduler\";\nimport { planSchema } from \"./plan-schema\";\nimport {\n  deletePlannerSnapshot,\n  persistPlannerSnapshot,\n} from \"./snapshot\";\n\n/**\n * Construction args for one {@link PlannerRun}. Carries everything the\n * factory resolved once (config, capability map, signature, planning\n * agent) plus the per-call goal and options.\n */\nexport type PlannerRunArgs<TOutput> = {\n  config: PlannerConfig<TOutput>;\n  capabilities: Map<string, PlannerCapability>;\n  maxSteps: number;\n  signature: string;\n  planningAgent: AgentContract<unknown>;\n  goal: string;\n  options?: PlannerExecuteOptions<TOutput>;\n  /**\n   * Durable resume seed. When present the run re-hydrates the frozen plan\n   * + executed-node ledger + usage + child reports + replan budget from a\n   * prior crash, skips plan generation, and continues scheduling only the\n   * unfinished frontier. Absent ⇒ a normal cold run.\n   */\n  resumeFrom?: PlannerSnapshot;\n};\n\n/**\n * Per-call orchestration state for one `planner.execute()` invocation.\n *\n * **Role.** Owns the full bounded-v1 planning lifecycle across four\n * phases that share mutable accumulators: (1) ask the LLM to GENERATE a\n * plan, (2) execute each plan step through its capability's `execute()`,\n * (3) optionally validate the final output, (4) assemble the unified\n * {@link PlannerResult}. Instantiated fresh per call inside the factory\n * so the accumulators (`usage`, `children`, `executedSteps`) are never\n * shared across runs. Unexported — callers only ever see the plain\n * {@link PlannerResult}.\n *\n * **Composition, not a fork.** Plan generation runs through a normal\n * `agent.execute()`; each step runs through the capability's own\n * `executable.execute()`. The planner adds the plan-generation brain and\n * the ordered-dispatch loop on top of the existing executable machinery —\n * it does not reimplement agent or step internals.\n */\nexport class PlannerRun<TOutput> {\n  private readonly runId: string;\n  /**\n   * Run start timestamp. A resumed run restores it from the snapshot (in\n   * the constructor) so the rebuilt report spans the whole run, not just\n   * the resumed tail — hence not `readonly`.\n   */\n  private startedAt = new Date().toISOString();\n  private readonly startPerf = performance.now();\n\n  private readonly usage: Usage = { input: 0, output: 0, total: 0 };\n  private readonly children: BaseReport[] = [];\n  private readonly executedSteps: PlannerStepSnapshot[] = [];\n\n  private plan?: PlannerPlan;\n  private data?: TOutput;\n  private error?: AIError;\n  private cancelledAt?: string;\n\n  /** Set when `mode: \"plan-only\"` short-circuited before execution. */\n  private awaitingApproval = false;\n\n  /** How many times the plan has been regenerated mid-run (≤ maxReplans). */\n  private replanCount = 0;\n\n  /**\n   * One-shot guard so the DAG resume re-seed runs only on the first\n   * `executeDag` pass — a later replan recursion gets a fresh plan with\n   * different node ids and must NOT re-seed against the stale ledger.\n   */\n  private dagResumeConsumed = false;\n\n  public constructor(private readonly args: PlannerRunArgs<TOutput>) {\n    // A resumed run reuses the snapshot's key so it writes back to the\n    // same record; otherwise a caller-supplied `options.runId` wins, else\n    // a fresh id is generated.\n    this.runId = args.resumeFrom?.runId ?? args.options?.runId ?? generateRunId(\"planner\");\n\n    // Seed the accumulators from the snapshot on resume — re-hydrate the\n    // frozen plan, the per-node ledger, the rolled-up usage, the child\n    // reports, and the replan budget. `startedAt` restores too so the\n    // resumed report spans the whole run. Pushing into the ledger rather\n    // than re-running nodes is what keeps completed capabilities from\n    // re-dispatching — the sequential guard / DAG re-seed read \"what ran\"\n    // straight off `executedSteps`. Absent ⇒ accumulators stay empty and\n    // the cold path is byte-for-byte unchanged.\n    if (args.resumeFrom) {\n      this.plan = args.resumeFrom.plan;\n      this.executedSteps.push(...args.resumeFrom.executedSteps);\n      this.children.push(...args.resumeFrom.children);\n      this.mergeUsage(this.usage, args.resumeFrom.usage);\n      this.replanCount = args.resumeFrom.replanCount;\n      this.startedAt = args.resumeFrom.startedAt;\n    }\n  }\n\n  /**\n   * Run the planner end-to-end. Never throws on runtime failure —\n   * generation errors, plan-validity errors, step failures, and\n   * cancellation all surface on `result.error` with a narrowing\n   * `report.status`.\n   */\n  public async run(): Promise<PlannerResult<TOutput>> {\n    const result = await this.runPlan();\n\n    // Route the planner's OWN report — the planning trip plus every\n    // capability step already nest under it via `absorb`, so this single\n    // call surfaces the whole tree as one trace. Mirrors agent/workflow:\n    // `notifyObservers` self-routes a root run under observe-all (skipped\n    // when nested, via the run-frame gate), then `captureChildReport`\n    // auto-nests the planner under any enclosing orchestration run. Without\n    // this, observe-all would only ever see the sub-agents as standalone\n    // fragments — the planner itself never appeared.\n    await notifyObservers(this.args.config.observe, result.report);\n    captureChildReport(result.report);\n\n    return result;\n  }\n\n  /**\n   * Drive the planner lifecycle and return the built result WITHOUT\n   * routing it — `run()` owns observer routing + auto-nesting so the\n   * unified tree is emitted exactly once.\n   */\n  private async runPlan(): Promise<PlannerResult<TOutput>> {\n    // Completed-run short-circuit. A resume of a snapshot whose run\n    // already COMPLETED re-runs nothing — the stored ledger IS the\n    // result. A `failed` / `cancelled` snapshot is NOT short-circuited:\n    // those are the runs a caller resumes to retry the unfinished\n    // frontier after fixing the cause, so they re-enter execution below.\n    if (this.args.resumeFrom && this.args.resumeFrom.status === \"completed\") {\n      this.rebuildResumedTerminal(\"completed\");\n      return this.buildResult();\n    }\n\n    try {\n      if (this.isAborted()) {\n        this.markCancelled();\n        await this.checkpoint(this.resolveSnapshotStatus());\n        return this.buildResult();\n      }\n\n      // Resume fork — the plan is frozen (re-asking the LLM would burn\n      // tokens and risk a different plan that no longer matches the\n      // executed-node ledger). Skip generation entirely and execute the\n      // re-hydrated plan; the sequential guard / DAG re-seed skip the\n      // nodes already terminal in `executedSteps`.\n      const plan = this.args.resumeFrom\n        ? (this.plan as PlannerPlan)\n        : (this.args.options?.approvedPlan ?? (await this.generatePlan()));\n\n      if (this.error || !plan) {\n        await this.checkpoint(this.resolveSnapshotStatus());\n        return this.buildResult();\n      }\n\n      // On a fresh run, validate the plan (a generated / approved plan\n      // could name an unknown capability). A resumed plan was already\n      // valid when persisted, so skip re-validation unless drift `force`\n      // is implied — re-validating a frozen plan against the same live\n      // capabilities is redundant.\n      if (!this.args.resumeFrom) {\n        this.assertPlanValid(plan);\n\n        if (this.error) {\n          await this.checkpoint(this.resolveSnapshotStatus());\n          return this.buildResult();\n        }\n      }\n\n      this.plan = plan;\n\n      // Plan-only mode — surface the validated plan for sign-off and execute\n      // NOTHING. `approvedPlan` overrides this (execute the supplied plan),\n      // mirroring the documented \"approvedPlan wins\" precedence. A resume is\n      // always an execution, never a plan-only short-circuit.\n      if (\n        !this.args.resumeFrom &&\n        this.args.options?.mode === \"plan-only\" &&\n        !this.args.options?.approvedPlan\n      ) {\n        this.awaitingApproval = true;\n        return this.buildResult();\n      }\n\n      await this.executePlan(plan);\n\n      await this.finalizeOutput();\n    } catch (caught) {\n      this.error = this.toAIError(caught);\n    }\n\n    // Terminal checkpoint — persist the final state so a completed-run\n    // resume short-circuits, then optionally drop the snapshot when\n    // `deleteOnComplete` is set and the run succeeded. No-op when\n    // `durable` is absent.\n    await this.checkpoint(this.resolveSnapshotStatus());\n\n    if (!this.error && this.args.config.durable?.deleteOnComplete) {\n      const outcome = await deletePlannerSnapshot({\n        durable: this.args.config.durable,\n        runId: this.runId,\n      });\n\n      if (!outcome.ok) {\n        this.logDurableFailure(\"snapshot.delete.failed\", outcome.error);\n      }\n    }\n\n    return this.buildResult();\n  }\n\n  /**\n   * Phase 1 — ask the planning agent for a structured plan. The plan\n   * schema (built from the live capability names) is supplied as the\n   * agent's per-call `output`, so the model is steered to reference only\n   * real capabilities. The planning trip's usage + report roll into the\n   * planner's totals regardless of outcome.\n   *\n   * `feedback` is set only on a RE-plan: the regenerated request is\n   * seeded with the executed-step digest plus the caller's feedback so\n   * the planner revises the remaining work rather than starting cold.\n   */\n  private async generatePlan(feedback?: string): Promise<PlannerPlan | undefined> {\n    const schema = planSchema([...this.args.capabilities.keys()], this.args.maxSteps);\n\n    // `withoutRunFrame` suppresses the planning trip's own self-routing:\n    // `absorb` already folds its report into `this.children`, so without\n    // this the trip would ALSO route as a standalone top-level trace under\n    // observe-all. The planner routes the unified tree once, in `run()`.\n    const result = await withoutRunFrame(() =>\n      this.args.planningAgent.execute(this.buildPlanPrompt(feedback), {\n        output: schema as StandardSchemaV1<unknown>,\n        placeholders: this.args.options?.placeholders,\n        signal: this.args.options?.signal,\n        sessionId: this.args.options?.sessionId,\n      }),\n    );\n\n    this.absorb(result.usage, result.report);\n\n    if (result.error) {\n      // A schema rejection from the planning trip (e.g. an empty\n      // `steps` array tripping the plan schema) is really an invalid\n      // plan — re-wrap it into the typed planner contract so callers\n      // branch on `PlannerPlanInvalidError` rather than the agent's raw\n      // `SchemaValidationError`. Any other child error flows through\n      // unchanged.\n      this.error =\n        result.error instanceof SchemaValidationError\n          ? new PlannerPlanInvalidError(\n              `ai.planner(\"${this.args.config.name}\"): the planner produced no usable plan`,\n              { cause: result.error, context: { runId: this.runId } },\n            )\n          : result.error;\n      return undefined;\n    }\n\n    const plan = result.data as PlannerPlan | undefined;\n\n    if (!plan || !Array.isArray(plan.steps) || plan.steps.length === 0) {\n      this.error = new PlannerPlanInvalidError(\n        `ai.planner(\"${this.args.config.name}\"): the planner produced no usable plan`,\n        { context: { runId: this.runId } },\n      );\n      return undefined;\n    }\n\n    this.assertPlanValid(plan);\n\n    if (this.error) {\n      return undefined;\n    }\n\n    return plan;\n  }\n\n  /**\n   * Shared plan-validity guard — used both for a freshly generated plan\n   * and for a caller-supplied `approvedPlan`. Sets `this.error` to a\n   * typed {@link PlannerPlanInvalidError} when the plan is empty or names\n   * an unknown capability; a stale `approvedPlan` thus fails the same way\n   * a hallucinated capability does, never silently mis-dispatching.\n   */\n  private assertPlanValid(plan: PlannerPlan): void {\n    if (!Array.isArray(plan.steps) || plan.steps.length === 0) {\n      this.error = new PlannerPlanInvalidError(\n        `ai.planner(\"${this.args.config.name}\"): the planner produced no usable plan`,\n        { context: { runId: this.runId } },\n      );\n      return;\n    }\n\n    const unknownStep = plan.steps.find((step) => !this.args.capabilities.has(step.capability));\n\n    if (unknownStep) {\n      this.error = new PlannerPlanInvalidError(\n        `ai.planner(\"${this.args.config.name}\"): plan references unknown capability \"${unknownStep.capability}\"`,\n        { context: { runId: this.runId, capability: unknownStep.capability } },\n      );\n    }\n  }\n\n  /**\n   * Phase 2 — execute the plan. Branches on `config.dag`: the default is\n   * the strict array-order sequential loop (byte-for-byte today's\n   * behavior when neither `onStep` nor `replan` is configured); `dag:\n   * true` schedules independent `dependsOn` branches in parallel.\n   */\n  private async executePlan(plan: PlannerPlan): Promise<void> {\n    if (this.args.config.dag) {\n      return this.executeDag(plan);\n    }\n\n    return this.executeSequential(plan);\n  }\n\n  /**\n   * Sequential executor — the original strict array-order loop, threading\n   * each completed step's output into the next step's input context.\n   * Stops at the first step failure or when the abort signal fires\n   * between steps; steps beyond `maxSteps` are recorded `skipped`.\n   *\n   * **Additive hooks (inert by default).** After each step settles it\n   * fires the `onStep` directive hook; an `abort` directive stops the run\n   * like a failure, and a `replan` directive (or, when `config.replan` is\n   * set, an unhandled failure) regenerates the REMAINING plan instead of\n   * aborting. With no `onStep` and no `replan`, the behavior is identical\n   * to before.\n   */\n  private async executeSequential(plan: PlannerPlan): Promise<void> {\n    const previousOutputs: string[] = [];\n    let steps = plan.steps;\n    let index = 0;\n\n    // Resume re-seed (sequential). The frozen plan's already-completed\n    // prefix lives in the persisted ledger; thread its outputs forward and\n    // jump the cursor past it so completed nodes are never re-dispatched.\n    // Stale non-completed entries (the failed node that crashed the run,\n    // and any `skipped` tail) are pruned so the re-run repopulates them\n    // cleanly instead of duplicating. No-op on a cold run (empty ledger).\n    if (this.args.resumeFrom) {\n      index = this.rehydrateSequentialState(steps, previousOutputs);\n    }\n\n    while (index < steps.length) {\n      const step = steps[index] as PlannerStep;\n\n      if (index >= this.args.maxSteps) {\n        this.recordSkipped(index, step);\n        index++;\n        continue;\n      }\n\n      if (this.isAborted()) {\n        this.markCancelled();\n        this.recordSkipped(index, step);\n        index++;\n        continue;\n      }\n\n      const completed = await this.executeStep(index, step, previousOutputs);\n\n      const snapshot = this.snapshotFor(index);\n      const directive = snapshot\n        ? await this.resolveDirective(snapshot, plan, completed)\n        : undefined;\n\n      if (directive?.type === \"replan\") {\n        const remaining = await this.regeneratePlan(directive.feedback);\n\n        if (this.error || !remaining) {\n          this.skipRest(steps, index + 1);\n          return;\n        }\n\n        // Replace the remaining tail with the regenerated plan and restart\n        // the cursor against it (executed steps already recorded stay put).\n        // Each new step gets the executed-so-far digest as its context.\n        steps = remaining.steps;\n        index = 0;\n        previousOutputs.length = 0;\n        previousOutputs.push(...this.executedDigest());\n        continue;\n      }\n\n      if (directive?.type === \"abort\") {\n        // The hook (or an unhandled failure) asked to stop — record the\n        // remaining steps as skipped so the report still describes the\n        // whole intended plan, then stop.\n        this.skipRest(steps, index + 1);\n        return;\n      }\n\n      index++;\n    }\n  }\n\n  /**\n   * DAG executor — schedule independent `dependsOn` branches in parallel.\n   *\n   * Builds the DAG (cycle / unknown-id → `PlannerPlanInvalidError`),\n   * then repeatedly computes the ready set (steps whose deps all\n   * completed), dispatches up to `maxConcurrency` of them with\n   * `Promise.all`, and feeds each step ONLY its dependencies' outputs. A\n   * failed step blocks just its descendants (recorded `skipped`);\n   * independent branches still settle. With an `output` schema set, the\n   * final `data` is the topological SINK's output (multiple sinks → a\n   * convergence error).\n   */\n  private async executeDag(plan: PlannerPlan): Promise<void> {\n    const dag = buildDag(plan.steps, this.args.config.name);\n    const maxConcurrency = Math.max(1, this.args.config.maxConcurrency ?? 4);\n\n    const completed = new Set<string>();\n    const done = new Set<string>();\n    const outputs = new Map<string, string>();\n    const rawOutputs = new Map<string, unknown>();\n    let executedCount = 0;\n\n    // Resume re-seed (DAG). Re-derive the scheduler's working sets from\n    // the persisted ledger so `readyNodes` schedules only the unfinished\n    // frontier — completed nodes go straight into `completed` + `done`\n    // with their outputs restored; stale non-completed entries are pruned\n    // so the re-run repopulates them. One-shot: consumed on the first DAG\n    // pass so a later replan recursion (fresh plan, different node ids)\n    // doesn't re-seed against a stale ledger. No-op on a cold run.\n    if (this.args.resumeFrom && !this.dagResumeConsumed) {\n      this.dagResumeConsumed = true;\n      executedCount = this.rehydrateDagState(dag, completed, done, outputs, rawOutputs);\n    }\n\n    while (done.size < dag.nodes.length) {\n      if (this.isAborted()) {\n        this.markCancelled();\n        this.skipDagRest(dag, done);\n        return;\n      }\n\n      const ready = readyNodes(dag, completed, done);\n\n      if (ready.length === 0) {\n        // No node can advance — every remaining node transitively depends\n        // on a failed/skipped ancestor. Record them skipped and stop.\n        this.skipDagRest(dag, done);\n        return;\n      }\n\n      const batch = ready.slice(0, maxConcurrency);\n\n      const settled = await Promise.all(\n        batch.map(async (node) => {\n          // `maxSteps` truncation applies to the count of DISPATCHED steps.\n          if (executedCount >= this.args.maxSteps) {\n            this.recordSkipped(node.index, node.step);\n            return { node, ran: false, completed: false };\n          }\n\n          executedCount++;\n          // Feed this step ONLY its dependencies' output digests — the DAG\n          // fix for the sequential loop's \"all prior outputs into every\n          // step\" behavior. `executeStep` pushes into the array it is\n          // given, so a fresh array per node keeps branches isolated.\n          const previousOutputs = node.dependencies.map(\n            (dependency) => outputs.get(dependency) as string,\n          );\n          const stepCompleted = await this.executeStep(\n            node.index,\n            node.step,\n            previousOutputs,\n          );\n\n          if (stepCompleted) {\n            // Read the raw output off the snapshot (NOT shared `this.data`,\n            // which races under Promise.all) for both the dependent digest\n            // and the eventual sink output.\n            const rawOutput = this.snapshotFor(node.index)?.output;\n            rawOutputs.set(node.id, rawOutput);\n            outputs.set(node.id, this.stringifyOutput(node.step.capability, rawOutput));\n          }\n\n          return { node, ran: true, completed: stepCompleted };\n        }),\n      );\n\n      for (const entry of settled) {\n        done.add(entry.node.id);\n\n        if (entry.completed) {\n          completed.add(entry.node.id);\n        }\n      }\n\n      // Fire the per-step hook for each settled step (in dispatch order).\n      let replanFeedback: string | undefined;\n      let shouldAbort = false;\n\n      for (const entry of settled) {\n        if (!entry.ran) {\n          continue;\n        }\n\n        const snapshot = this.snapshotFor(entry.node.index);\n        const directive = snapshot\n          ? await this.resolveDirective(snapshot, plan, entry.completed)\n          : undefined;\n\n        if (directive?.type === \"replan\") {\n          replanFeedback = directive.feedback;\n        } else if (directive?.type === \"abort\") {\n          shouldAbort = true;\n        }\n      }\n\n      if (shouldAbort) {\n        this.skipDagRest(dag, done);\n        return;\n      }\n\n      if (replanFeedback !== undefined) {\n        const remaining = await this.regeneratePlan(replanFeedback);\n\n        if (this.error || !remaining) {\n          this.skipDagRest(dag, done);\n          return;\n        }\n\n        // Re-plan in DAG mode regenerates the remaining work as a fresh\n        // (sequential) plan and runs it through the DAG scheduler again.\n        return this.executeDag(remaining);\n      }\n    }\n\n    this.finalizeDagOutput(dag, completed, rawOutputs);\n  }\n\n  /**\n   * Dispatch one plan step through its capability's `executable.execute()`\n   * and fold the outcome into the accumulators. Returns `true` when the\n   * step completed, `false` when it failed (setting the run error).\n   */\n  private async executeStep(\n    index: number,\n    step: PlannerStep,\n    previousOutputs: string[],\n  ): Promise<boolean> {\n    const capability = this.args.capabilities.get(step.capability) as PlannerCapability;\n    const stepStart = performance.now();\n    const startedAt = new Date().toISOString();\n    const input = this.composeStepInput(step, previousOutputs);\n\n    // `withoutRunFrame` keeps each capability step nested under the planner\n    // only — `absorb` folds its report into `this.children`, so suppressing\n    // its self-route prevents a duplicate standalone trace under observe-all.\n    const result = await withoutRunFrame(() =>\n      capability.executable.execute(input, {\n        signal: this.args.options?.signal,\n        sessionId: this.args.options?.sessionId,\n      }),\n    );\n\n    const childReport = \"report\" in result ? (result.report as BaseReport) : undefined;\n    this.absorb(result.usage, childReport);\n\n    const output = this.extractOutput(result);\n    const failed = result.error !== undefined;\n\n    this.executedSteps.push({\n      index,\n      step,\n      status: failed ? \"failed\" : \"completed\",\n      output: failed ? undefined : output,\n      error: result.error,\n      startedAt,\n      endedAt: new Date().toISOString(),\n      duration: performance.now() - stepStart,\n      usage: result.usage,\n      childReport,\n    });\n\n    // Per-node durable checkpoint. Sits AFTER the node's snapshot is\n    // pushed and `absorb` has folded its usage + child report — the only\n    // point where the ledger + usage + children are mutually consistent.\n    // A completed node is never re-dispatched on resume (the sequential\n    // guard / DAG re-seed skip it). Swallow-and-log; no-op when `durable`\n    // is absent.\n    await this.checkpoint(\"running\");\n\n    if (failed) {\n      this.error = result.error;\n      return false;\n    }\n\n    previousOutputs.push(this.stringifyOutput(step.capability, output));\n    this.data = output as TOutput;\n\n    return true;\n  }\n\n  /**\n   * Resolve the steering directive for a just-settled step, shared by the\n   * sequential and DAG executors. Fires the user's `onStep` hook, then\n   * normalizes the result against the `replan` budget:\n   *\n   * - explicit `replan` directive — honored only when `config.replan` is\n   *   set and the budget remains; otherwise downgraded to `continue`.\n   * - explicit `abort` — honored.\n   * - failed step with no overriding directive — auto-`replan` when\n   *   `config.replan` is set and the budget remains (feedback = the step\n   *   error message), else `abort` (today's abort-on-first-failure).\n   *\n   * Returns `undefined` when the run should simply continue. A returned\n   * `replan` directive has ALREADY consumed one unit of the replan budget.\n   */\n  private async resolveDirective(\n    snapshot: PlannerStepSnapshot,\n    plan: PlannerPlan,\n    completed: boolean,\n  ): Promise<PlannerStepDirective | undefined> {\n    const hook = this.args.options?.onStep;\n    const userDirective = hook ? await hook(snapshot, plan) : undefined;\n\n    if (userDirective?.type === \"replan\") {\n      if (this.canReplan()) {\n        this.replanCount++;\n        return userDirective;\n      }\n\n      // Replan requested but unavailable (no config or budget spent) — fall\n      // through to the failure/continue defaults below.\n    } else if (userDirective?.type === \"abort\") {\n      return { type: \"abort\" };\n    } else if (userDirective?.type === \"continue\") {\n      return undefined;\n    }\n\n    if (!completed) {\n      if (this.canReplan()) {\n        this.replanCount++;\n        return { type: \"replan\", feedback: snapshot.error?.message ?? \"step failed\" };\n      }\n\n      return { type: \"abort\" };\n    }\n\n    return undefined;\n  }\n\n  /** Whether a re-plan is configured and the budget has room. */\n  private canReplan(): boolean {\n    const replan = this.args.config.replan;\n\n    return replan !== undefined && this.replanCount < replan.maxReplans;\n  }\n\n  /**\n   * Re-ask the planning agent for a plan over the REMAINING work — a\n   * second `generatePlan()` seeded with the executed-step digest plus the\n   * caller's feedback. Reuses the exact `generatePlan` plumbing (same\n   * schema, same `PlannerPlanInvalidError` handling), so a regenerated\n   * plan that is empty or names an unknown capability fails identically.\n   * The failed step's error is cleared so the regenerated plan runs\n   * cleanly; a fresh failure (or exhausted budget) re-sets it.\n   */\n  private async regeneratePlan(feedback: string): Promise<PlannerPlan | undefined> {\n    this.error = undefined;\n    return this.generatePlan(feedback);\n  }\n\n  /**\n   * The executed-so-far digest — one context line per completed step, in\n   * execution order. Seeds the regenerated plan's first step so it builds\n   * on what already ran.\n   */\n  private executedDigest(): string[] {\n    return this.executedSteps\n      .filter((snapshot) => snapshot.status === \"completed\")\n      .map((snapshot) => this.stringifyOutput(snapshot.step.capability, snapshot.output));\n  }\n\n  /** The last-pushed snapshot for a given step index, if any. */\n  private snapshotFor(index: number): PlannerStepSnapshot | undefined {\n    for (let position = this.executedSteps.length - 1; position >= 0; position--) {\n      const snapshot = this.executedSteps[position] as PlannerStepSnapshot;\n\n      if (snapshot.index === index) {\n        return snapshot;\n      }\n    }\n\n    return undefined;\n  }\n\n  /** Record every step from `from` onward (in a flat array plan) as skipped. */\n  private skipRest(steps: PlannerStep[], from: number): void {\n    for (let rest = from; rest < steps.length; rest++) {\n      this.recordSkipped(rest, steps[rest] as PlannerStep);\n    }\n  }\n\n  /** Record every not-yet-`done` DAG node as skipped, in plan order. */\n  private skipDagRest(dag: PlannerDag, done: ReadonlySet<string>): void {\n    for (const node of dag.nodes) {\n      if (!done.has(node.id)) {\n        this.recordSkipped(node.index, node.step);\n      }\n    }\n  }\n\n  /**\n   * Set `this.data` from the DAG's topological sink for a configured\n   * `output` schema. \"Last completed step\" is meaningless under\n   * parallelism, so the sink (the step nothing depends on) is the\n   * unambiguous final output. Multiple sinks while an `output` schema is\n   * set is a convergence error — a typed `PlannerPlanInvalidError`.\n   */\n  private finalizeDagOutput(\n    dag: PlannerDag,\n    completed: ReadonlySet<string>,\n    rawOutputs: Map<string, unknown>,\n  ): void {\n    const schema = this.args.options?.output ?? this.args.config.output;\n\n    if (!schema || this.error) {\n      return;\n    }\n\n    const sinks = sinkNodes(dag).filter((node) => completed.has(node.id));\n\n    if (sinks.length > 1) {\n      this.error = new PlannerPlanInvalidError(\n        `ai.planner(\"${this.args.config.name}\"): DAG has multiple sinks but an \\`output\\` schema is set — the plan must converge to a single final step`,\n        { context: { runId: this.runId, sinks: sinks.map((node) => node.id) } },\n      );\n      this.data = undefined;\n      return;\n    }\n\n    const sink = sinks[0] as DagNode | undefined;\n    this.data = (sink ? rawOutputs.get(sink.id) : undefined) as TOutput | undefined;\n  }\n\n  /**\n   * Phase 3 — when an `output` schema is configured (factory or per-call\n   * override), validate the final completed step's output into typed\n   * `result.data`. A validation failure replaces the run error and flips\n   * the status to failed.\n   */\n  private async finalizeOutput(): Promise<void> {\n    const schema = this.args.options?.output ?? this.args.config.output;\n\n    if (!schema || this.error) {\n      return;\n    }\n\n    if (this.data === undefined) {\n      // An `output` schema is configured but the final completed step\n      // produced nothing to validate — returning `{ data: undefined,\n      // error: undefined, status: \"completed\" }` would be a silent\n      // contract violation. Surface it as an invalid plan instead.\n      this.error = new PlannerPlanInvalidError(\n        `ai.planner(\"${this.args.config.name}\"): plan completed without producing output for the configured \\`output\\` schema`,\n        { context: { runId: this.runId } },\n      );\n      return;\n    }\n\n    const validation = await schema[\"~standard\"].validate(this.data);\n\n    if (validation.issues) {\n      this.error = new PlannerPlanInvalidError(\n        `ai.planner(\"${this.args.config.name}\"): final output failed validation`,\n        {\n          context: {\n            runId: this.runId,\n            issues: validation.issues.map((issue) => issue.message),\n          },\n        },\n      );\n      this.data = undefined;\n      return;\n    }\n\n    this.data = validation.value as TOutput;\n  }\n\n  /**\n   * Phase 4 — fold the accumulators into the planner's own\n   * {@link PlannerReport} node and the final {@link PlannerResult}, then\n   * stamp lineage across the whole subtree so every child shares this\n   * run's root id.\n   */\n  private buildResult(): PlannerResult<TOutput> {\n    const status = this.resolveStatus();\n\n    const report: PlannerReport = {\n      runId: this.runId,\n      rootRunId: this.runId,\n      name: this.args.config.name,\n      version: this.args.config.version,\n      type: \"planner\",\n      status,\n      // Stamp the terminal error so the observe path surfaces it on the\n      // planner span (no result envelope reaches an observer). Absent on\n      // a completed run.\n      ...(this.error ? { error: this.error } : {}),\n      startedAt: this.startedAt,\n      endedAt: new Date().toISOString(),\n      duration: performance.now() - this.startPerf,\n      usage: this.usage,\n      children: this.children,\n      signature: this.args.signature,\n      plan: this.plan,\n      executedSteps: this.executedSteps,\n      cancelledAt: this.cancelledAt,\n      reportSchemaVersion: REPORT_SCHEMA_VERSION,\n    };\n\n    stampReportLineage(report, {\n      rootRunId: this.runId,\n      sessionId: this.args.options?.sessionId,\n    });\n\n    const result: PlannerResult<TOutput> = {\n      type: \"planner\",\n      data: this.error ? undefined : this.data,\n      error: this.error,\n      usage: this.usage,\n      report,\n    };\n\n    // Plan-only mode surfaces the validated plan WITHOUT execution so the\n    // caller can sign off and re-run with `approvedPlan`.\n    if (this.awaitingApproval) {\n      result.plan = this.plan;\n    }\n\n    return result;\n  }\n\n  /**\n   * Resolve the terminal status from the accumulated outcome.\n   * `awaiting-approval` (plan-only short-circuit) wins over everything —\n   * nothing executed, so neither cancellation nor error applies.\n   * Otherwise cancelled wins over failed (an abort that also produced a\n   * step error still reads as cancelled); failed wins over completed.\n   */\n  private resolveStatus(): PlannerReport[\"status\"] {\n    if (this.awaitingApproval) {\n      return \"awaiting-approval\";\n    }\n\n    if (this.cancelledAt !== undefined) {\n      return \"cancelled\";\n    }\n\n    if (this.error) {\n      return \"failed\";\n    }\n\n    return \"completed\";\n  }\n\n  /**\n   * Build the prompt handed to the planning agent. On the first pass this\n   * is just the user's goal (byte-for-byte unchanged). On a RE-plan it\n   * prepends the executed-step digest and the steering feedback so the\n   * planner revises the remaining work.\n   */\n  private buildPlanPrompt(feedback?: string): string {\n    if (feedback === undefined) {\n      return this.args.goal;\n    }\n\n    const digest = this.executedDigest();\n    const sections: string[] = [`Goal: ${this.args.goal}`, \"\"];\n\n    if (digest.length > 0) {\n      sections.push(\"Steps already completed:\", ...digest, \"\");\n    }\n\n    sections.push(\n      `Feedback requiring a revised plan: ${feedback}`,\n      \"\",\n      \"Produce a plan for the REMAINING work only.\",\n    );\n\n    return sections.join(\"\\n\");\n  }\n\n  /**\n   * Compose a step's effective input: the step's own `input`, prefixed\n   * with a compact digest of every prior step's output so a downstream\n   * capability can build on what ran before it. No prior output → the\n   * step's raw input.\n   */\n  private composeStepInput(step: PlannerStep, previousOutputs: string[]): string {\n    if (previousOutputs.length === 0) {\n      return step.input;\n    }\n\n    return [\n      \"Context from earlier steps:\",\n      ...previousOutputs,\n      \"\",\n      `Task: ${step.input}`,\n    ].join(\"\\n\");\n  }\n\n  /**\n   * Pull the usable output off a capability's result. Prefers structured\n   * `data` (agents/workflows with an `output` schema, tools), and falls\n   * back to an agent's raw `text` when no structured data was produced —\n   * the common case for a plain text-producing capability agent.\n   */\n  private extractOutput(result: BaseResult): unknown {\n    const shaped = result as { data?: unknown; text?: unknown };\n\n    if (shaped.data !== undefined) {\n      return shaped.data;\n    }\n\n    if (typeof shaped.text === \"string\") {\n      return shaped.text;\n    }\n\n    return undefined;\n  }\n\n  /** Serialize a capability output into a single context line for the next step. */\n  private stringifyOutput(capability: string, output: unknown): string {\n    if (output === undefined) {\n      return `- ${capability}: (no output)`;\n    }\n\n    if (typeof output === \"string\") {\n      return `- ${capability}: ${output}`;\n    }\n\n    return `- ${capability}: ${JSON.stringify(output)}`;\n  }\n\n  /** Push a `skipped` snapshot for a step the planner never dispatched. */\n  private recordSkipped(index: number, step: PlannerStep): void {\n    const now = new Date().toISOString();\n\n    this.executedSteps.push({\n      index,\n      step,\n      status: \"skipped\",\n      startedAt: now,\n      endedAt: now,\n      duration: 0,\n      usage: { input: 0, output: 0, total: 0 },\n    });\n  }\n\n  /** Fold a child's usage + report node into the planner's accumulators. */\n  private absorb(usage: Usage, report: BaseReport | undefined): void {\n    this.mergeUsage(this.usage, usage);\n\n    if (report) {\n      this.children.push(report);\n    }\n  }\n\n  /**\n   * Add a child's usage into the running total. Mirrors the batch\n   * primitive's rollup: scalar token channels sum directly, optional\n   * sub-channels accumulate only when reported, and the cost breakdown\n   * merges via {@link accumulateCost} so one unpriced child can't erase\n   * priced siblings.\n   */\n  private mergeUsage(target: Usage, child: Usage): void {\n    target.input += child.input;\n    target.output += child.output;\n    target.total += child.total;\n\n    if (child.cachedTokens !== undefined) {\n      target.cachedTokens = (target.cachedTokens ?? 0) + child.cachedTokens;\n    }\n\n    if (child.reasoningTokens !== undefined) {\n      target.reasoningTokens = (target.reasoningTokens ?? 0) + child.reasoningTokens;\n    }\n\n    if (child.cacheWriteTokens !== undefined) {\n      target.cacheWriteTokens = (target.cacheWriteTokens ?? 0) + child.cacheWriteTokens;\n    }\n\n    const mergedCost = accumulateCost(target.cost, child.cost);\n\n    if (mergedCost !== undefined) {\n      target.cost = mergedCost;\n    }\n  }\n\n  /**\n   * Re-derive the sequential cursor + prior-output context from the\n   * persisted ledger on resume. Threads every already-`completed` node's\n   * output into `previousOutputs`, returns the first index NOT completed\n   * as the resume cursor, and prunes stale non-completed ledger entries\n   * (the failed node + any skipped tail) at-or-after that cursor so the\n   * re-run repopulates them without duplicating.\n   */\n  private rehydrateSequentialState(\n    steps: PlannerStep[],\n    previousOutputs: string[],\n  ): number {\n    let cursor = 0;\n\n    for (let index = 0; index < steps.length; index++) {\n      const snapshot = this.snapshotFor(index);\n\n      if (snapshot?.status === \"completed\") {\n        const step = steps[index] as PlannerStep;\n        previousOutputs.push(this.stringifyOutput(step.capability, snapshot.output));\n        cursor = index + 1;\n        continue;\n      }\n\n      // First non-completed index — this is where the re-run resumes.\n      break;\n    }\n\n    // Drop any ledger entries at-or-after the cursor (failed / skipped\n    // from the crashed run) so the resumed loop's pushes don't duplicate.\n    this.pruneLedgerFrom(cursor);\n\n    return cursor;\n  }\n\n  /**\n   * Re-derive the DAG scheduler's working sets from the persisted ledger\n   * on resume. Completed nodes go into `completed` + `done` with their\n   * string + raw outputs restored (so dependents read the right context);\n   * stale non-completed entries are pruned so the re-run repopulates them.\n   * Returns the count of nodes already dispatched (for the `maxSteps`\n   * truncation budget).\n   */\n  private rehydrateDagState(\n    dag: PlannerDag,\n    completed: Set<string>,\n    done: Set<string>,\n    outputs: Map<string, string>,\n    rawOutputs: Map<string, unknown>,\n  ): number {\n    const completedIndices = new Set<number>();\n\n    for (const node of dag.nodes) {\n      const snapshot = this.snapshotFor(node.index);\n\n      if (snapshot?.status !== \"completed\") {\n        continue;\n      }\n\n      completed.add(node.id);\n      done.add(node.id);\n      completedIndices.add(node.index);\n      rawOutputs.set(node.id, snapshot.output);\n      outputs.set(node.id, this.stringifyOutput(node.step.capability, snapshot.output));\n    }\n\n    // Prune every non-completed ledger entry so the re-run's pushes don't\n    // duplicate the failed / skipped frontier from the crashed run.\n    const retained = this.executedSteps.filter((snapshot) =>\n      completedIndices.has(snapshot.index),\n    );\n    this.executedSteps.length = 0;\n    this.executedSteps.push(...retained);\n\n    return completedIndices.size;\n  }\n\n  /**\n   * Drop every ledger entry whose index is at or after `from`. Used by\n   * the sequential resume re-seed to clear the crashed run's failed /\n   * skipped frontier before the re-run repopulates it.\n   */\n  private pruneLedgerFrom(from: number): void {\n    const retained = this.executedSteps.filter((snapshot) => snapshot.index < from);\n    this.executedSteps.length = 0;\n    this.executedSteps.push(...retained);\n  }\n\n  /**\n   * Map the run's terminal outcome to the persisted snapshot status.\n   * `awaiting-approval` (plan-only) never persists a durable snapshot\n   * (resume is always an execution), so it folds to `running` here —\n   * but the durable + plan-only combination is disallowed at the call\n   * site, so this path is effectively unreachable.\n   */\n  private resolveSnapshotStatus(): PlannerSnapshotStatus {\n    if (this.cancelledAt !== undefined) {\n      return \"cancelled\";\n    }\n\n    if (this.error) {\n      return \"failed\";\n    }\n\n    if (this.awaitingApproval) {\n      return \"running\";\n    }\n\n    return \"completed\";\n  }\n\n  /**\n   * Build and persist a {@link PlannerSnapshot} from the current\n   * accumulators. The per-node and terminal checkpoints both route\n   * through here. No-op when `durable` is absent. A failed persist is\n   * logged and swallowed (never aborts the run), matching the supervisor\n   * / workflow checkpoint policy.\n   */\n  private async checkpoint(status: PlannerSnapshotStatus): Promise<void> {\n    if (!this.args.config.durable || !this.plan) {\n      return;\n    }\n\n    const outcome = await persistPlannerSnapshot({\n      durable: this.args.config.durable,\n      runId: this.runId,\n      plannerName: this.args.config.name,\n      signature: this.args.signature,\n      version: this.args.config.version,\n      goal: this.args.goal,\n      plan: this.plan,\n      executedSteps: this.executedSteps,\n      usage: this.usage,\n      children: this.children,\n      replanCount: this.replanCount,\n      status,\n      startedAt: this.startedAt,\n    });\n\n    if (!outcome.ok) {\n      this.logDurableFailure(\"snapshot.persist.failed\", outcome.error);\n    }\n  }\n\n  /**\n   * Re-derive the terminal state when a resume short-circuits a snapshot\n   * whose run already COMPLETED. The persisted ledger is the\n   * authoritative outcome — `this.data` is restored from the last\n   * completed node so the rebuilt result carries the final output.\n   *\n   * Only reached for a `completed` snapshot — `failed` / `cancelled`\n   * snapshots re-enter execution to retry the unfinished frontier instead.\n   */\n  private rebuildResumedTerminal(_status: PlannerSnapshotStatus): void {\n    const lastCompleted = [...this.executedSteps]\n      .reverse()\n      .find((snapshot) => snapshot.status === \"completed\");\n\n    if (lastCompleted) {\n      this.data = lastCompleted.output as TOutput;\n    }\n  }\n\n  /** Structured-log a durable persist/delete failure. */\n  private logDurableFailure(action: string, error: unknown): void {\n    log.warn(\"ai.planner\", action, \"durable snapshot operation failed\", {\n      runId: this.runId,\n      planner: this.args.config.name,\n      error: error instanceof Error ? error.message : String(error),\n    });\n  }\n\n  /** Whether the caller's abort signal has fired. */\n  private isAborted(): boolean {\n    return this.args.options?.signal?.aborted === true;\n  }\n\n  /** Record a cancellation observation, setting the run error once. */\n  private markCancelled(): void {\n    if (this.cancelledAt !== undefined) {\n      return;\n    }\n\n    this.cancelledAt = new Date().toISOString();\n\n    const reason = this.args.options?.signal?.reason;\n\n    this.error = new PlannerCancelledError(\n      `ai.planner(\"${this.args.config.name}\"): run cancelled`,\n      {\n        cancelledAt: this.cancelledAt,\n        reason: typeof reason === \"string\" ? reason : undefined,\n        context: { runId: this.runId },\n      },\n    );\n  }\n\n  /** Normalize any thrown value into a typed {@link AIError}. */\n  private toAIError(caught: unknown): AIError {\n    if (caught instanceof AIError) {\n      return caught;\n    }\n\n    const message = caught instanceof Error ? caught.message : String(caught);\n\n    return new PlannerFailedError(`ai.planner(\"${this.args.config.name}\"): ${message}`, {\n      cause: caught,\n      context: { runId: this.runId },\n    });\n  }\n}\n"],"mappings":"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"}