"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.runReviewOnlyPhase = runReviewOnlyPhase;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const reviewer_driver_js_1 = require("./reviewer-driver.js");
/**
 * Run a review-only phase. The artifact (supplied at chat-create time) is
 * written to a synthetic doer answer slot; reviewers then critique it
 * just like a real doer's answer. Single pass — no iterate, no retry.
 * Reviewer agreement/disagreement is reported via outcome.allReviewersFailed;
 * the verdict itself doesn't gate further phases (review-only is the whole
 * point of the chat).
 *
 * Synthetic doer events make the cockpit + replay code paths Just Work
 * without special-casing the missing doer card.
 */
async function runReviewOnlyPhase(args) {
    const { chatDir, chatId, phase, phaseIdx, artifact, work, filesBlock, tmuxMgr, errorDetector, onEvent, abortSignal, } = args;
    if (abortSignal.aborted) {
        return { completed: false, allReviewersFailed: false, agreed: false, summary: 'aborted' };
    }
    const round = 1; // review-only is always single-pass
    const roundDir = path_1.default.join(chatDir, `round-${round}`);
    if (!fs_1.default.existsSync(roundDir)) {
        fs_1.default.mkdirSync(roundDir, { recursive: true });
    }
    // Synthetic doer dir holds the artifact as answer.md so the cockpit's
    // existing replay code finds it under the same path shape it expects.
    const syntheticDoerDir = path_1.default.join(roundDir, 'doer-artifact');
    if (!fs_1.default.existsSync(syntheticDoerDir)) {
        fs_1.default.mkdirSync(syntheticDoerDir, { recursive: true });
    }
    const answerFile = path_1.default.join(syntheticDoerDir, 'answer.md');
    // Strip trailing whitespace before the sentinel check so an artifact
    // ending with "## DONE\n" or "## DONE  " doesn't produce a duplicate
    // sentinel after we append. Idempotent: artifacts without the sentinel
    // get a clean "\n\n## DONE\n" tail.
    const trimmed = artifact.replace(/\s+$/, '');
    const artifactWithSentinel = /##\s*DONE$/i.test(trimmed)
        ? `${trimmed}\n`
        : `${trimmed}\n\n## DONE\n`;
    fs_1.default.writeFileSync(answerFile, artifactWithSentinel);
    // Synthetic doer phase events. agent='artifact' is a sentinel value the
    // cockpit can render as "user-supplied" rather than as a real CLI run.
    onEvent({
        chatId,
        type: 'phase_start',
        payload: {
            phaseId: phase.id,
            phaseIdx,
            kind: phase.kind,
            round,
            role: 'doer',
            agent: 'artifact',
            synthetic: true,
        },
        ts: Date.now(),
    });
    onEvent({
        chatId,
        type: 'phase_progress',
        payload: {
            phaseId: phase.id,
            round,
            role: 'doer',
            agent: 'artifact',
            output: artifact.slice(0, 500),
            synthetic: true,
        },
        ts: Date.now(),
    });
    // The synthetic StandardPhase shape carries the same reviewer block
    // plus a no-op iterate config so runReviewers can consume it. Local
    // to this call — never escapes back into the template.
    const syntheticStandardPhase = {
        id: phase.id,
        kind: 'review',
        title: phase.title,
        description: phase.description,
        doer: { lineage: 'any' },
        reviewer: phase.reviewer,
        inputs: phase.inputs,
        iterate: {
            maxRounds: 1,
            onDisagreement: 'continue',
            shareSessionAcrossRounds: false,
            shareSessionAcrossPhases: false,
        },
        timeoutMs: phase.timeoutMs,
    };
    const consensus = await (0, reviewer_driver_js_1.runReviewers)(chatDir, chatId, syntheticStandardPhase, phaseIdx, round, artifact, work, filesBlock, tmuxMgr, errorDetector, onEvent, abortSignal, args.templateFallbackReviewer);
    return {
        completed: !abortSignal.aborted,
        allReviewersFailed: consensus.allFailed,
        agreed: consensus.agreed,
        summary: consensus.summary,
    };
}
//# sourceMappingURL=review-only-phase.js.map