"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildWorkerWorkflowPlanReviewContract = buildWorkerWorkflowPlanReviewContract;
exports.validateWorkerWorkflowPlanReviewSemanticRules = validateWorkerWorkflowPlanReviewSemanticRules;
const zod_1 = require("zod");
const structured_contract_support_1 = require("./structured-contract-support");
const types_1 = require("./types");
const validation_issues_1 = require("./validation-issues");
const workerWorkflowPlanReviewFindingSchema = zod_1.z
    .object({
    severity: zod_1.z
        .enum(["minor", "major", "blocker"])
        .describe("Impact of the finding on successful execution."),
    target: zod_1.z
        .object({
        kind: zod_1.z
            .enum([
            "plan",
            "contract",
            "step",
            "workflow_ref",
            "child_issue",
            "execution_guidance",
            "predicted_touched_paths",
        ])
            .describe("Plan area that needs correction."),
        stepId: zod_1.z
            .string()
            .trim()
            .min(1)
            .optional()
            .describe("Existing step id when the finding targets a step."),
        field: zod_1.z
            .string()
            .trim()
            .min(1)
            .optional()
            .describe("Specific field name when useful."),
    })
        .strict(),
    problem: zod_1.z.string().trim().min(1).describe("Specific issue found."),
    requestedOutcome: zod_1.z
        .string()
        .trim()
        .min(1)
        .describe("Outcome the planner should produce when revising."),
    acceptanceCheck: zod_1.z
        .string()
        .trim()
        .min(1)
        .describe("Observable check that proves the fix is sufficient."),
    evidence: zod_1.z
        .array(zod_1.z.string().trim().min(1))
        .min(1)
        .describe("Concrete evidence from the request, plan, or workflow state."),
})
    .strict();
const workerWorkflowPlanReviewSchema = zod_1.z
    .object({
    action: zod_1.z
        .enum([
        types_1.WORKER_WORKFLOW_PLAN_REVIEW_ACTIONS.usePlan,
        types_1.WORKER_WORKFLOW_PLAN_REVIEW_ACTIONS.requestRevision,
        types_1.WORKER_WORKFLOW_PLAN_REVIEW_ACTIONS.blockExecution,
    ])
        .describe("Plan review action."),
    basePlanRevision: zod_1.z
        .number()
        .int()
        .safe()
        .nonnegative()
        .describe("Reviewed workflow state planRevision."),
    reason: zod_1.z.string().trim().min(1).describe("Concise review reason."),
    evidence: zod_1.z
        .array(zod_1.z.string().trim().min(1))
        .min(1)
        .describe("Concrete evidence supporting the review action."),
    findings: zod_1.z
        .array(workerWorkflowPlanReviewFindingSchema)
        .describe("Actionable findings for planner revision."),
})
    .strict()
    .describe("Workflow plan review result.");
function buildWorkerWorkflowPlanReviewContract(input) {
    return (0, structured_contract_support_1.buildWorkerStructuredContract)({
        schema: workerWorkflowPlanReviewSchema,
        example: buildWorkerWorkflowPlanReviewExample(input),
        rules: buildWorkerWorkflowPlanReviewRules(),
    });
}
function validateWorkerWorkflowPlanReviewSemanticRules(review, input) {
    const issues = [];
    if (review.basePlanRevision !== input.reviewedPlanRevision) {
        (0, validation_issues_1.addWorkerSemanticValidationIssue)(issues, {
            path: ["basePlanRevision"],
            message: `basePlanRevision must equal reviewedPlanRevision ${input.reviewedPlanRevision}.`,
        });
    }
    if (review.action === types_1.WORKER_WORKFLOW_PLAN_REVIEW_ACTIONS.usePlan &&
        review.findings.length > 0) {
        (0, validation_issues_1.addWorkerSemanticValidationIssue)(issues, {
            path: ["findings"],
            message: "findings must be empty when action is use_plan.",
        });
    }
    if (review.action === types_1.WORKER_WORKFLOW_PLAN_REVIEW_ACTIONS.requestRevision &&
        review.findings.length === 0) {
        (0, validation_issues_1.addWorkerSemanticValidationIssue)(issues, {
            path: ["findings"],
            message: "findings are required when action is request_revision.",
        });
    }
    if (review.action === types_1.WORKER_WORKFLOW_PLAN_REVIEW_ACTIONS.blockExecution &&
        !review.findings.some((finding) => finding.severity === "blocker")) {
        (0, validation_issues_1.addWorkerSemanticValidationIssue)(issues, {
            path: ["findings"],
            message: "block_execution requires at least one blocker finding.",
        });
    }
    const stepsById = new Map(input.plan.steps.map((step) => [step.id, step]));
    review.findings.forEach((finding, index) => {
        const needsStepId = finding.target.kind === "step" ||
            finding.target.kind === "workflow_ref" ||
            finding.target.kind === "child_issue";
        if (needsStepId && finding.target.stepId === undefined) {
            (0, validation_issues_1.addWorkerSemanticValidationIssue)(issues, {
                path: ["findings", index, "target", "stepId"],
                message: `target.stepId is required for ${finding.target.kind} findings.`,
            });
            return;
        }
        if (finding.target.stepId !== undefined &&
            !stepsById.has(finding.target.stepId)) {
            (0, validation_issues_1.addWorkerSemanticValidationIssue)(issues, {
                path: ["findings", index, "target", "stepId"],
                message: `target.stepId ${finding.target.stepId} is not in the reviewed plan.`,
            });
            return;
        }
        const targetStep = finding.target.stepId === undefined
            ? undefined
            : stepsById.get(finding.target.stepId);
        if (finding.target.kind === "workflow_ref" &&
            targetStep?.kind !== "workflow_ref") {
            (0, validation_issues_1.addWorkerSemanticValidationIssue)(issues, {
                path: ["findings", index, "target", "stepId"],
                message: `target.stepId ${finding.target.stepId} must reference a workflow_ref step.`,
            });
        }
        if (finding.target.kind === "child_issue" &&
            targetStep?.kind !== "child_issue") {
            (0, validation_issues_1.addWorkerSemanticValidationIssue)(issues, {
                path: ["findings", index, "target", "stepId"],
                message: `target.stepId ${finding.target.stepId} must reference a child_issue step.`,
            });
        }
    });
    return issues;
}
function buildWorkerWorkflowPlanReviewExample(input) {
    return {
        action: types_1.WORKER_WORKFLOW_PLAN_REVIEW_ACTIONS.usePlan,
        basePlanRevision: input.reviewedPlanRevision,
        reason: "The plan preserves the request outcome and has executable verification evidence.",
        evidence: [
            "The reviewed plan contains concrete steps and observable doneWhen checks.",
        ],
        findings: [],
    };
}
function buildWorkerWorkflowPlanReviewRules() {
    return [
        "Return exactly one JSON object in the decision block.",
        "Review the plan against the user's requested outcome, not against preferred style.",
        "Choose use_plan only when the plan can plausibly achieve the request without material missing work, contradictions, unsafe assumptions, or unverifiable doneWhen checks.",
        "Before choosing use_plan, ensure every capability-sensitive step uses fitting available skill/MCP support, depends on skill/MCP resolution before dependent work, or gives a concrete no-specialized-capability rationale.",
        "Choose request_revision when catalog evidence finds fitting capability candidates but the plan only uses generic capability labels instead of exact skill refs, usable installed MCP refs, MCP catalog ids, search result ids, resolution output, or a no-specialized-capability rationale.",
        "Do not accept catalog ids or search result ids as required skill/MCP refs unless list or verify evidence shows they are usable required refs.",
        "When command execution is available for the review run, use bounded capability catalog commands as evidence for capability-sensitive checks.",
        "Choose request_revision when a report or note deliverable is planned as a repo artifact even though a concise comment-only result would satisfy the request, when a long temporary issue-scoped report is planned outside the configured issue notes path or without `issue-<issue-number>-<slug>.md` naming, or when durable project documentation is planned without evidence that the path follows the repository's existing documentation structure.",
        "Choose request_revision when the planner can fix the issue with bounded plan, contract, executionGuidance, predictedTouchedPaths, or step changes.",
        "Choose block_execution when the plan should not be auto-revised because it needs human judgment, contradicts explicit instructions, or would require unsafe or ambiguous changes.",
        "Each finding must be actionable for a planner using revise_plan or replan with planPatch.",
        "Findings should target the smallest affected area and include the acceptance check the revised plan must satisfy.",
        "Do not return planPatch, full plan, implementation steps, file edits, or commands.",
    ];
}
