/**
 * Analyse-verify feedback runner — the analyse-side analog of realize's
 * `feedback-runner.ts`. Runs the verifiers, groups findings by action stub,
 * surgically re-fires each offending body ONCE with a targeted correction, and
 * recomputes the residual. Mirrors realize's default single-pass policy.
 *
 * Decoupled from the orchestrator: the caller supplies a `refire` callback that
 * wraps `runSurgicalRetry` (with the new `correctionByYamlPath`) and the
 * skeleton / model / source context. This module owns only the rule loop, the
 * correction assembly, and the residual recompute. It NEVER drops a body — a
 * residual finding is surfaced in the sidecar, not deleted.
 */
import { runAllAnalyseVerifiers } from './verifier-manifest.js';
/** A finding's identity for residual matching — same code + same stub. */
function findingKey(f) {
    return `${f.code}::${f.stubPath}`;
}
/** Assemble the `{{correction}}` block for one stub from its findings. */
function buildCorrection(findings) {
    const lines = findings.map((f) => `- ${f.correction}`);
    return (`CORRECTION — your previous body for this action had quality issue(s). ` +
        `Re-emit the FULL body, fixing only the following and leaving everything else intact:\n` +
        lines.join('\n'));
}
/** Run the verify + single surgical re-fire pass. */
export async function runAnalyseVerifyFeedback(ctx, refire, enabledOverrides) {
    const { findings: initialFindings, notes } = runAllAnalyseVerifiers(ctx, enabledOverrides);
    if (initialFindings.length === 0) {
        return {
            initialFindings: [],
            residualFindings: [],
            finalBodies: ctx.actionBodies,
            refiredStubs: 0,
            notes,
        };
    }
    // Group findings by stub; merge each stub's corrections into one block.
    const byStub = new Map();
    for (const f of initialFindings) {
        if (!byStub.has(f.stubPath))
            byStub.set(f.stubPath, []);
        byStub.get(f.stubPath).push(f);
    }
    const correctionByYamlPath = new Map();
    for (const [stubPath, fs] of byStub) {
        correctionByYamlPath.set(stubPath, buildCorrection(fs));
    }
    const affectedStubPaths = [...byStub.keys()];
    // Single surgical re-fire pass.
    const finalBodies = await refire({ affectedStubPaths, correctionByYamlPath });
    // Recompute residual on the re-fired bodies.
    const { findings: afterFindings } = runAllAnalyseVerifiers({ ...ctx, actionBodies: finalBodies }, enabledOverrides);
    const afterKeys = new Set(afterFindings.map(findingKey));
    const residualFindings = afterFindings;
    // (residual is the post-pass finding set; afterKeys retained for callers that
    //  want to know which initial findings persisted.)
    void afterKeys;
    return {
        initialFindings,
        residualFindings,
        finalBodies,
        refiredStubs: affectedStubPaths.length,
        notes,
    };
}
//# sourceMappingURL=feedback-runner.js.map