/** * SplitDiagnosticianRunner — orchestrates the 3-stage split pipeline (PRI-372). * * Implements the same `run(taskId)` interface as DiagnosticianRunner, * so the PainSignalBridge can use it as a drop-in replacement when * the `diagnostician_split_pipeline` feature flag is enabled. * * Internally creates sub-tasks for each stage and runs them sequentially: * Stage A (diag_rootcause) → Stage B (diag_distiller) → Stage C (diag_router) * * After Stage C succeeds, onDiagnosisComplete is invoked by the bridge * (PainSignalBridge.onPainDetected), not by this router or the router. * * Key constraints: * - Each stage gets its own task with the correct taskKind * - Stage B depends on Stage A (dependencyTaskIds) * - Stage C depends on both A and B (dependencyTaskIds) * - If any stage fails, the pipeline stops and returns the failure * - The parent diagnostician task is NOT created — the bridge already * creates it; this runner only creates the 3 sub-tasks * - If a sub-runner returns `retried`, this orchestrator waits for the * backoff period and re-runs the stage until it succeeds or fails * (ERR-067 fix: previously `retried` was treated as failure) * * @see PRI-372 * @see ERR-067 */ import type { DiagRootCauseRunner } from './diag-rootcause-runner.js'; import type { DiagDistillerRunner } from './diag-distiller-runner.js'; import type { DiagRouterRunner } from './diag-router-runner.js'; import type { RuntimeStateManager } from '../store/runtime-state-manager.js'; import type { RunnerResult } from '../runner/runner-result.js'; import type { DiagnosticianCommitter } from '../store/commit/diagnostician-committer.js'; import type { RetryPolicy } from '../store/lifecycle/retry-policy.js'; export interface SplitDiagnosticianRunnerDeps { readonly rootCauseRunner: DiagRootCauseRunner; readonly distillerRunner: DiagDistillerRunner; readonly routerRunner: DiagRouterRunner; readonly stateManager: RuntimeStateManager; readonly committer: DiagnosticianCommitter; /** Per-stage timeout in ms. Default: 600_000 (10 min). Split pipeline total = 3 × this value. */ readonly perStageTimeoutMs?: number; /** Retry policy for backoff calculation. Defaults to stateManager.getRetryPolicy(). */ readonly retryPolicy?: RetryPolicy; } /** * Orchestrates the 3-stage split diagnostician pipeline. * * This class is a thin orchestrator — it does NOT extend BasePeerRunner. * It creates sub-tasks, runs each stage's runner, and returns a RunnerResult * compatible with the monolithic DiagnosticianRunner's output. * * ERR-067 fix: when a sub-runner returns `retried`, this orchestrator * waits for the backoff period and re-runs the stage, up to maxAttempts. * Previously, `retried` was treated as failure, breaking the retry chain. */ export declare class SplitDiagnosticianRunner { private readonly rootCauseRunner; private readonly distillerRunner; private readonly routerRunner; private readonly stateManager; private readonly perStageTimeoutMs; private readonly retryPolicy; /** * PRI-818 (R-04): same authority the live Stage C path uses for semantic * validation (diag-router-runner.ts). A cached succeeded run must pass the * identical gate before it is allowed to skip the router stage. */ private readonly cacheOutputValidator; constructor(deps: SplitDiagnosticianRunnerDeps); /** * Execute the full split pipeline A→B→C for a parent diagnostician task. * * The `taskId` parameter is the parent diagnostician task ID (e.g. `diagnosis_pain-001`). * Sub-tasks are derived from it: * - Stage A: `diag_rootcause-{parentTaskId}` * - Stage B: `diag_distiller-{parentTaskId}` * - Stage C: `diag_router-{parentTaskId}` * * Returns a RunnerResult compatible with DiagnosticianRunner.run(). */ run(parentTaskId: string): Promise; /** * Ensure a sub-task exists. If it already exists in `retry_wait` status, * transition it to `pending` WITHOUT resetting attemptCount (ERR-067 fix: * previously attemptCount was reset to 0, losing retry progress). * * If it exists in `failed` status, also transition to `pending` without * resetting attemptCount — the retry policy will check shouldRetry(). */ private ensureSubTask; /** * Run a stage's runner with retry support (ERR-067 fix). * * When the sub-runner returns `retried`, this method: * 1. Waits for the backoff period calculated by the retry policy * 2. Re-runs the sub-runner * 3. Repeats until the result is `succeeded` or `failed` * * This ensures that transient LLM failures (e.g., schema non-compliance) * are actually retried instead of being treated as terminal failures. */ private runStageWithRetry; /** * Mark the parent task as failed and return a failure result. */ private failParent; } //# sourceMappingURL=split-diagnostician-runner.d.ts.map