/**
 * Per-owner LLM emit hook — Phase 1 of the 2026-05-11-PER-OWNER-VS-PER-ACTION
 * proposal.
 *
 * Sibling of `per-action-llm-emit.ts`. SAME structural-validator and
 * parse-check infrastructure, DIFFERENT granularity: one LLM call per
 * controller / service instead of one per action. Restores the
 * class-level context (constructor injection, shared helpers, sibling
 * methods) that per-action emission engineered out and that surfaced
 * empirically as the 31% LLM-decline rate on idle-meta sonnet (the
 * LLM correctly refused to invent imports it couldn't see were
 * available).
 *
 * Three quality gates run on the emitted file:
 *   1. Markdown extraction — pull the ```typescript fenced block out
 *      of the LLM response. Empty / missing block → null (caller
 *      falls through to per-action emit OR engine γ-stub).
 *   2. Structural preservation (DR3) — every pre-baked snippet from
 *      every action's per-step matches must appear verbatim somewhere
 *      in the emitted file. A rewritten snippet is a loud failure;
 *      we throw with a diff.
 *   3. esbuild parse check — the file must be syntactically valid TS.
 *      Surgical retry once on parse failure; if it fails again we
 *      return null (caller falls through).
 *
 * The realize-owner.prompt.yaml asset ships at:
 * `@specverse/assets/prompts/core/standard/default/realize-owner.prompt.yaml`.
 * Until assets is republished with it, a filesystem fallback under
 * `specverse-self/assets/` is searched.
 */
import { runPrompt as runPromptFn, type PromptYaml } from '../ai/prompt-runner.js';
import { type ActionSpec, type MatchResult } from './owner-emit-shared.js';
/** One action collected for the owner. Includes step-match results
 *  so the structural validator and the prompt's per-action scaffolding
 *  can both reference them. */
export interface CollectedOwnerAction {
    /** Action / operation name as it appears in the spec. */
    actionName: string;
    /** Full ActionSpec for the action. */
    spec: ActionSpec;
    /** Per-step matcher results; matched ones contribute to the
     *  pre-baked snippet set that the structural validator enforces. */
    perStepMatches: Array<MatchResult | null>;
}
/** Request shape for the per-owner emit hook. One per owner. */
export interface PerOwnerEmitRequest {
    /** Owner identifier — controller / service / model name. */
    ownerName: string;
    ownerKind: 'controller' | 'service' | 'model';
    /** Full owner spec block (the controller/service yaml object). */
    ownerSpec: any;
    /** All actions / operations on this owner, with step matches. */
    actions: CollectedOwnerAction[];
    /** V2 import clients string (from component's import: block). */
    availableClients?: string;
    /** Manifest capability mappings text (NEW vs per-action).
     *  Format: lines like `  - orm.client → PrismaClient (orm/prisma)`.
     *  The LLM uses these to decide what to import at top-of-file. */
    availableCapabilities?: string;
    /** Cross-service / cross-controller operation signatures (TODO #60).
     *  Format: lines per service/controller with declared operations,
     *  excluding the current owner (which has its own spec block).
     *  The LLM uses this as the source of truth for which methods can
     *  be called on imported service classes. */
    availableSpecSurface?: string;
    /** Target runtime declaration. The realize-owner prompt opens with
     *  this so the LLM knows up-front which APIs are available. The
     *  runtime-API validator (post-emit) enforces the forbidden-API set
     *  for each runtime. Examples: `'Node.js (backend)'`,
     *  `'Browser (DOM)'`, `'Edge runtime (no Node builtins)'`. */
    targetRuntime?: string;
    /** Cross-method process context string. Same shape as per-action. */
    processContext?: string;
}
/** Per-owner emit function signature — returns the full file contents
 *  (a TypeScript module with `export async function ...` per action)
 *  or null when emission failed. */
export type PerOwnerEmitFn = (request: PerOwnerEmitRequest) => Promise<string | null>;
/**
 * Per-owner emission telemetry record. One per call to the emit
 * function. Always-on (no env gate) — captures the journey through
 * the retry chain so downstream observers can answer "did Lever 1
 * fire" / "did surgical retry recover" / "how long did emit take"
 * without parsing log lines.
 *
 * Filed 2026-05-15 against the engines 6.64.0 Lever 1 validation
 * that surfaced the "I have no idea whether the retry actually fired"
 * blind spot. Phase 5c of `2026-05-14-PER-ACTION-RECOVERY-TIER.md`
 * (Tier 1 portion); future work extends with Tier 2 + Tier 3 records.
 */
export interface PerOwnerEmitTelemetry {
    ownerName: string;
    /** Number of LLM calls actually made (1 or 2 typically). */
    attempts: number;
    /** Terminal outcome of this owner's Tier 1 emission. */
    outcome: 'success' | 'structural-retry-recovered' | 'parse-retry-recovered' | 'rule-retry-recovered' | 'structural-exhausted' | 'structural-immediate' | 'parse-exhausted' | 'rule-exhausted' | 'empty-block' | 'threw-from-llm';
    structuralRetryFired: boolean;
    parseRetryFired: boolean;
    ruleRetryFired: boolean;
    /** Step numbers of dropped [PRE-BAKED] snippets when structural
     *  retry fired (or null if structural never failed). */
    structuralMissingSteps?: number[];
    /** Total wall time (ms) for this owner's emit, including all
     *  attempts. */
    durationMs: number;
}
/**
 * Always-on telemetry collector. The runner builds one per
 * realize cycle and passes it to {@link createRealizeOwnerLlmEmit}.
 * Each owner's emit pushes one record. The collector is then
 * serialized to `realize-emission.json` next to `realize-quality.json`.
 */
export interface EmissionTelemetryCollector {
    record(entry: PerOwnerEmitTelemetry): void;
}
/** Options for {@link createRealizeOwnerLlmEmit}. */
export interface CreateRealizeOwnerLlmEmitOptions {
    /** Override `runPrompt` for tests. */
    runPromptOverride?: typeof runPromptFn;
    /** Override `loadPrompt` for tests; default loads `realize-owner`. */
    loadPromptOverride?: () => PromptYaml;
    /** Override the parse-check for tests. Returns null on success, an
     *  error message string on failure. */
    parseCheckOverride?: (code: string) => Promise<string | null>;
    /** Override the model passed to runPrompt (rare). */
    model?: any;
    /** Per-call timeout. Default 5min — same as microcall-orchestrator. */
    timeoutMs?: number;
    /** Disable the surgical retry (tests). */
    disableSurgicalRetry?: boolean;
    /** Always-on emission telemetry. Each owner's emit pushes one
     *  {@link PerOwnerEmitTelemetry} record into the collector. */
    telemetry?: EmissionTelemetryCollector;
}
/**
 * Build a {@link PerOwnerEmitFn} for use in per-owner realize emission.
 *
 * Returned function:
 *   1. Builds the prompt input from the per-owner request.
 *   2. Calls runPrompt({ operation: 'realize-owner', ... }).
 *   3. Extracts the ```typescript block from the response.
 *   4. Runs the structural validator (DR3); throws on rewrite.
 *   5. Runs an esbuild parse check; surgical-retries once on failure.
 *   6. Returns the file contents string, or null when all attempts
 *      fail (caller falls through).
 */
export declare function createRealizeOwnerLlmEmit(opts?: CreateRealizeOwnerLlmEmitOptions): PerOwnerEmitFn;
/** Filesystem fallback search for the realize-owner prompt. Mirrors
 *  per-action-llm-emit.ts:loadRealizeActionPromptFromFallback's three-
 *  tier search: @specverse/assets package path, engine-bundled assets,
 *  worktree-sibling specverse-self/assets. */
export declare function loadRealizeOwnerPromptFromFallback(): PromptYaml | null;
/** Build the per-action scaffolding block. One section per action,
 *  listing its steps with [PRE-BAKED] / [WRITE] markers. Exported for
 *  reuse by the realize-context-snapshot module (Phase 3 of
 *  2026-05-13-VERIFIER-DIAGNOSTIC-TREATMENT-SPLIT) — the reemit prompt
 *  embeds the same scaffolding the original per-owner prompt used. */
export declare function buildPerActionScaffolding(actions: CollectedOwnerAction[]): string;
//# sourceMappingURL=per-owner-emit.d.ts.map