/**
 * Per-action LLM micro-call orchestrator. Phase B of the
 * 2026-05-04-ANALYSE-VIA-FAITHFUL-SKELETON-AND-MICROCALLS plan.
 *
 * Architecture:
 *   - Skeleton emitter (Phase A) produced skeleton + actionStubs[]
 *   - This orchestrator walks actionStubs[], firing a focused LLM call
 *     per stub in parallel (with a concurrency cap)
 *   - Plus a single manifest call running alongside
 *   - Each call's prompt + response + parsed output + latency is
 *     forward-logged to MicrocallProvenance
 *   - Final assembly merges skeleton + filled action bodies + manifest
 *
 * Forward-logging discipline: every LLM call records WHICH stub it
 * filled, the assembled prompt, the raw response, the parsed body, and
 * timing metadata. The report assembler reads provenance directly. No
 * heuristic matching of LLM output to spec sections.
 */
import { runPrompt } from './prompt-runner.js';
import type { LanguageModel } from 'ai';
import type { SkeletonProvenance } from './skeleton-emitter.js';
export interface MicrocallProvenance {
    schemaVersion: '1.0';
    /** ISO timestamp when the orchestrator started. */
    startedAt: string;
    /** ISO timestamp when the last call completed. */
    endedAt: string;
    /** Total wall time across all calls (parallel — max not sum). */
    wallTimeMs: number;
    /** Concurrency cap that was applied. */
    concurrencyCap: number;
    /** Per-action call records. */
    actionCalls: ActionCallRecord[];
    /** Manifest call record (when fired). */
    manifestCall: ManifestCallRecord | null;
    /** Aggregate counters for reporting. */
    totals: {
        actionCallsAttempted: number;
        actionCallsSucceeded: number;
        actionCallsFailed: number;
        totalTokensIn?: number;
        totalTokensOut?: number;
        avgLatencyMsPerCall: number;
    };
}
export interface ActionCallRecord {
    /** Sequence in dispatch order — useful for deterministic-replay debugging. */
    ordinal: number;
    /** Resolves the stub via the skeleton-provenance actionStubs[] entry. */
    stubRef: {
        componentName: string;
        ownerKind: 'controller' | 'service';
        ownerName: string;
        actionName: string;
        yamlPath: string;
    };
    /** SHA256 of the assembled prompt (system + user) for reproducibility checks. */
    promptHash: string;
    /** Bytes-in / bytes-out for token-cost monitoring. */
    promptBytes: number;
    responseBytes: number;
    latencyMs: number;
    /** The parsed action body (steps / requires / ensures / emits) when parse OK. */
    parsedBody: ActionBody | null;
    /** Failure reason when parsedBody is null. */
    failure: string | null;
    /** Raw LLM response text. Capped at 4KB to keep the sidecar bounded.
     *  Captured for every call so failures are debuggable from the sidecar
     *  alone without re-running the LLM. */
    responseTextSnippet: string;
    /** Rate-limit retry count (engines 6.27.8+). Number of times this call
     *  was re-fired with backoff before either succeeding or hitting the
     *  retry budget. Zero on the happy path; up to `RATE_LIMIT_MAX_RETRIES`
     *  on rate-limited calls. */
    rateLimitRetries?: number;
}
export interface ManifestCallRecord {
    promptHash: string;
    promptBytes: number;
    responseBytes: number;
    latencyMs: number;
    /** The raw manifest yaml when extraction succeeded. */
    manifestYaml: string | null;
    failure: string | null;
}
export interface ActionBody {
    steps?: string[];
    requires?: string[];
    ensures?: string[];
    publishes?: string[];
}
export interface RunActionMicrocallsOptions {
    skeleton: string;
    skeletonProvenance: SkeletonProvenance;
    /** Indexed candidate-step content keyed by `${className}::${methodIndex}`.
     *  Caller pre-formats each method's timeline as markdown. */
    candidateStepsByMethodKey: Map<string, string>;
    /** TODO #22 (engines 6.88.0). Raw method source keyed by the same
     *  `${className}::${methodIndex}` shape. Fed to the per-action microcall
     *  as `sourceBody` so the LLM abstracts to business intent instead of
     *  parroting the `[kind]` candidate-step timeline (sonnet 42% → 93%
     *  business steps across JobHunter's controllers). */
    sourceByMethodKey?: Map<string, string>;
    /** Engines 6.32.0+ (TODO #51 phase 2C). Optional cross-method process
     *  context keyed by the same `${className}::${methodIndex}` shape. When
     *  present, augments the per-action prompt with pre-grouped Process
     *  step sequences extracted from `facts.processes`. Empty/absent maps
     *  cleanly degrade — orchestrator falls back to "(no related processes)". */
    processContextByMethodKey?: Map<string, string>;
    model?: LanguageModel;
    sessionId?: string;
    /** Max parallel runPrompt calls. Default 10. */
    concurrencyCap?: number;
    /** Per-call timeout. Default 5 minutes. */
    timeoutMsPerCall?: number;
    /** When provided, also fire a manifest call with this overview as input. */
    manifestInputs?: {
        skeletonOverview: string;
        importsList: string;
        language: string;
        frameworks: string;
    };
    /** Optional callback for streaming progress (one call per completion). */
    onProgress?: (record: ActionCallRecord) => void;
    /** Hook for tests — replace runPrompt with a stub. */
    runPromptOverride?: typeof runPrompt;
    /** When true, the rate-limit retry loop is skipped — transient 429s
     *  return as terminal failures with rateLimitRetries=0. Used by
     *  surgical retry to avoid compounding the retry amplifier (rate-limit
     *  retry × surgical retry = up to 16 invocations per stub otherwise). */
    disableRateLimitRetry?: boolean;
    /** Analyse post-emit verify (analyse-verify framework, TODO #92). Per-stub
     *  correction text injected into the `analyse-action` prompt's `{{correction}}`
     *  slot on a re-fire. Keyed by stub `yamlPath`. Absent / no entry → the normal
     *  first-pass call (correction renders as a blank line). This is the
     *  "error-feedback prompting v2" the surgical-retry note anticipated. */
    correctionByYamlPath?: Map<string, string>;
}
/**
 * Run the per-action micro-call pass + manifest call.
 * Returns the filled action bodies indexed by yamlPath plus the
 * manifest yaml string (when fired) plus full provenance.
 */
export declare function runActionMicrocalls(opts: RunActionMicrocallsOptions): Promise<{
    actionBodies: Map<string, ActionBody>;
    manifestYaml: string | null;
    provenance: MicrocallProvenance;
}>;
/** Parse an action body yaml — expects steps/requires/ensures/publishes keys.
 *  Tolerates LLMs that wrap the body inside the action name (e.g.
 *  `applyEffect: { steps: [...] }`) — we unwrap a single-key parent
 *  whose child has the expected body shape. */
export declare function parseActionBodyYaml(text: string): Promise<ActionBody | null>;
export interface SurgicalRetryClassification {
    /** Action-stub-level errors — yamlPath of stub → array of error lines that fall under it. */
    actionPathErrors: Map<string, string[]>;
    /** Errors that don't match any action stub — typically skeleton bugs. */
    structuralErrors: string[];
}
/** Parse an `spv validate` error output and classify each error by
 *  whether it falls under one of the skeleton's action stubs. */
export declare function classifyValidationErrors(errorText: string, skeletonProvenance: SkeletonProvenance): SurgicalRetryClassification;
/** Re-fire microcalls for action stubs whose previous body produced
 *  validation errors. Builds a focused prompt-input set that includes
 *  the prior failed body + the specific error, asking the LLM to fix it.
 *
 *  Skeleton-structural errors in `classification.structuralErrors` are
 *  NOT retried — they're skeleton-emitter bugs. The caller (analyse-
 *  runner) records them as humanReviewItems via the verify recorder. */
export declare function runSurgicalRetry(opts: {
    skeleton: string;
    skeletonProvenance: SkeletonProvenance;
    candidateStepsByMethodKey: Map<string, string>;
    /** TODO #22. Same shape + semantics as runActionMicrocalls. */
    sourceByMethodKey?: Map<string, string>;
    /** Engines 6.32.0+. Same shape + semantics as runActionMicrocalls. */
    processContextByMethodKey?: Map<string, string>;
    prior: {
        actionBodies: Map<string, ActionBody>;
        classification: SurgicalRetryClassification;
    };
    model?: LanguageModel;
    concurrencyCap?: number;
    timeoutMsPerCall?: number;
    runPromptOverride?: typeof runPrompt;
    onProgress?: (record: ActionCallRecord) => void;
    /** analyse-verify: per-stub correction injected into the re-fire prompt. */
    correctionByYamlPath?: Map<string, string>;
}): Promise<{
    actionBodies: Map<string, ActionBody>;
    retriedStubs: number;
    retryProvenance: ActionCallRecord[];
}>;
/**
 * Extract just the named component's slice from the full skeleton.
 * Preserves the file preamble (leading `#` comments + the `components:`
 * header line) and adds a one-line listing of sibling component names
 * so the LLM still has landscape awareness without paying the full
 * skeleton cost.
 *
 * Cuts the per-call user prompt by ~80% on idle-meta-class codebases
 * (24 entities across 8 components → ~17.8KB skeleton → ~1KB slice).
 *
 * Falls back to the full skeleton when the component header isn't found
 * (defensive — shouldn't happen since stubs are produced from the same
 * skeleton, but a fallback keeps the path safe under future refactors).
 */
export declare function extractComponentSlice(skeleton: string, componentName: string): string;
/**
 * Merge the skeleton with the filled action bodies. Returns the final
 * spec yaml. Uses simple line-based replacement: for each yamlPath in
 * actionBodies, find the action's stub in the skeleton and inject the
 * body fields immediately after the stub line.
 *
 * The skeleton's stub format is:
 *   <indent>actionName:
 *   <indent>  # body filled by per-action LLM micro-call (skeleton-emitter stub)
 *
 * We replace the comment line with the action body fields at body-indent.
 *
 * `opts.behavioursSkipped` distinguishes the two empty-body situations so the
 * placeholder description tells the truth: when the behaviours pass was never
 * run (skeleton-only analyse), no microcall was attempted and no
 * `microcall-decisions.json` is written — emitting "microcall failed" there is
 * misleading. The genuine per-stub failure wording is reserved for the path
 * where a microcall ran and returned nothing.
 */
export declare function assembleFinalSpec(skeleton: string, skeletonProvenance: SkeletonProvenance, actionBodies: Map<string, ActionBody>, opts?: {
    behavioursSkipped?: boolean;
}): string;
/**
 * Normalise an LLM-emitted manifest body so the realize manifest-loader
 * accepts it. The loader (manifest-loader.ts) accepts either
 * `manifests:` container or `specVersion:` at top-level — the prompt
 * deliberately produces neither (it asks for a bare manifest body), so
 * we prepend `specVersion: "1.0"` here. Idempotent: if the LLM already
 * emitted `specVersion:` (or wrapped in `manifests:`), pass through.
 */
export declare function ensureManifestSpecVersion(yaml: string): string;
//# sourceMappingURL=microcall-orchestrator.d.ts.map