import { formatGoalBlockingPrerequisites, goalHasBlockingPrerequisites, } from "./goal-store.js";
export const DEFAULT_GOAL_TASK_ATTEMPT_LIMIT = 5;
export const DEFAULT_GOAL_VERIFIER_FIX_LIMIT = 5;
export const DEFAULT_GOAL_EVIDENCE_RECONCILIATION_LIMIT = 2;
const EVIDENCE_RECONCILIATION_TASK_TITLE = "Reconcile Goal evidence plan";
const FINAL_COMPLETION_AUDIT_TASK_TITLE = "Audit Goal completion evidence";
const DEFAULT_GOAL_COMPLETION_AUDIT_LIMIT = 3;
function needsHarnessInstrumentation(run) {
    return run.harness.some((item) => !item.command && !item.path);
}
function buildHarnessTaskPrompt(run) {
    const harnessItems = run.harness
        .filter((item) => !item.command && !item.path)
        .map((item) => `- ${item.label}: ${item.description ?? "Create local instrumentation."}`)
        .join("\n");
    return (`Goal: ${run.goal}\n\n` +
        `Build only the missing local/free harness instrumentation needed before verification. Start by restating the intended experience, the relevant failure modes, and the senses/signals this harness must observe; do not default to generic tests, scripts, screenshots, benchmarks, or simulations unless that signal is required for this specific goal.\n` +
        `${harnessItems}\n\n` +
        `Inventory available local capabilities just deeply enough to choose a proportional instrument, then build it. Update the Goal harness/verifier metadata with the goals tool and record durable evidence showing the instrument exists and works. Do not require paid services or signups; block only with exact user instructions if a true external prerequisite is missing.`);
}
function blockedEvidencePlanReason(run) {
    const blocked = run.evidencePlan.find((item) => item.status === "blocked");
    if (!blocked)
        return undefined;
    return `${blocked.label}: ${blocked.instructions?.trim() || "User must provide this evidence prerequisite."}`;
}
function needsEvidenceInstrumentation(run) {
    return unsatisfiedGoalEvidencePlanItems(run).some((item) => item.status === "planned");
}
function evidenceReconciliationTaskCount(run) {
    return run.tasks.filter((task) => task.title === EVIDENCE_RECONCILIATION_TASK_TITLE).length;
}
function shouldCreateEvidenceReconciliationTask(run, limit = DEFAULT_GOAL_EVIDENCE_RECONCILIATION_LIMIT) {
    return evidenceReconciliationTaskCount(run) < limit;
}
export function unsatisfiedGoalEvidencePlanItems(run) {
    return run.evidencePlan.filter((item) => !evidencePlanItemSatisfiedByDurableEvidence(run, item));
}
function exactTokenReferenced(content, token) {
    return !!content?.trim() && !!token?.trim() && content.includes(token);
}
function evidencePlanItemSatisfiedByDurableEvidence(run, item) {
    if (item.status === "ready" && item.evidence?.trim())
        return true;
    if (item.evidence?.trim())
        return true;
    const verifier = run.verifier?.lastResult;
    if (verifier?.status === "pass") {
        if (item.command && verifier.command === item.command)
            return true;
        if (item.path && verifier.outputPath === item.path)
            return true;
    }
    return run.evidence.some((evidence) => {
        if (item.path && evidence.path === item.path)
            return true;
        if (item.command && exactTokenReferenced(evidence.content, item.command))
            return true;
        if (item.path && exactTokenReferenced(evidence.content, item.path))
            return true;
        return false;
    });
}
function buildEvidenceReconciliationTaskPrompt(run) {
    const missingItems = unsatisfiedGoalEvidencePlanItems(run)
        .map((item) => `- ${item.id} / ${item.label} (${item.mechanism}): ${item.description}${item.command ? `; expected command: ${item.command}` : ""}${item.path ? `; expected artifact: ${item.path}` : ""}`)
        .join("\n");
    const verifier = run.verifier?.lastResult;
    const recentEvidence = run.evidence
        .slice(-10)
        .map((item) => `- ${item.label}${item.path ? ` (${item.path})` : ""}: ${(item.content ?? "").slice(0, 240)}`)
        .join("\n");
    return (`Goal: ${run.goal}\n\n` +
        `The verifier has already passed, but the durable evidence plan still has unmatched items. Reconcile bookkeeping only; do not implement project changes or rerun broad work unless a small targeted check is required to confirm existing evidence.\n\n` +
        `Unsatisfied evidence-plan items:\n${missingItems || "- none"}\n\n` +
        `Verifier result: ${verifier?.status ?? "unknown"}; command: ${verifier?.command ?? run.verifier?.command ?? "not recorded"}; output: ${verifier?.outputPath ?? "not recorded"}; summary: ${verifier?.summary ?? "not recorded"}\n\n` +
        `Recent durable evidence:\n${recentEvidence || "- none"}\n\n` +
        `For each unsatisfied item, either record matching durable evidence or update the evidence_plan item to status=ready with a concise evidence summary using the goals tool. If an item truly lacks proof, add the exact minimal worker/verifier task needed. Do not mark the Goal complete; the coordinator will complete it after reconciliation and verifier evidence satisfy the original criteria.`);
}
export function hasRequiredGoalEvidence(run) {
    const missing = unsatisfiedGoalEvidencePlanItems(run);
    if (missing.length > 0) {
        return {
            ok: false,
            reason: `Goal evidence plan is not satisfied: ${missing.map((item) => item.label).join(", ")}.`,
        };
    }
    return {
        ok: true,
        reason: "All required evidence-plan items are ready or proven by durable evidence.",
    };
}
function finalAuditTaskCount(run) {
    return run.tasks.filter((task) => task.title === FINAL_COMPLETION_AUDIT_TASK_TITLE).length;
}
function shouldCreateFinalAuditTask(run, limit = DEFAULT_GOAL_COMPLETION_AUDIT_LIMIT) {
    return finalAuditTaskCount(run) < limit;
}
function isFinalAuditWorkerEvidence(run, label) {
    const match = /^Worker\s+(\S+)\s+/.exec(label);
    const workerId = match?.[1];
    if (!workerId)
        return false;
    return run.tasks.some((task) => task.title === FINAL_COMPLETION_AUDIT_TASK_TITLE && task.workerId === workerId);
}
function isCompletionAuditDecision(label) {
    return label === "Goal decision: completion_audit";
}
function latestMatchingEvidence(evidence, predicate) {
    return evidence.filter(predicate).sort((a, b) => b.createdAt.localeCompare(a.createdAt))[0];
}
function latestNonAuditWorkerEvidenceAfterVerifier(run) {
    const verifierCheckedAt = run.verifier?.lastResult?.checkedAt;
    if (!verifierCheckedAt)
        return undefined;
    return latestMatchingEvidence(run.evidence, (item) => item.createdAt > verifierCheckedAt &&
        item.label.startsWith("Worker ") &&
        !isFinalAuditWorkerEvidence(run, item.label));
}
function latestCompletionRelevantEvidenceAfterVerifier(run) {
    const verifierCheckedAt = run.verifier?.lastResult?.checkedAt;
    if (!verifierCheckedAt)
        return undefined;
    return latestMatchingEvidence(run.evidence, (item) => {
        if (item.createdAt <= verifierCheckedAt)
            return false;
        if (isFinalAuditWorkerEvidence(run, item.label))
            return false;
        if (isCompletionAuditDecision(item.label))
            return false;
        if (item.label === "Verifier result" || item.label.startsWith("Verifier "))
            return false;
        return item.label.startsWith("Worker ") || item.label.startsWith("Goal decision:");
    });
}
export function hasFreshGoalCompletionAudit(run) {
    const verifierResult = run.verifier?.lastResult;
    if (!verifierResult || verifierResult.status !== "pass") {
        return { ok: false, reason: "Goal has no passing verifier result to audit." };
    }
    const postVerifierWorkerEvidence = latestNonAuditWorkerEvidenceAfterVerifier(run);
    if (postVerifierWorkerEvidence) {
        return {
            ok: false,
            reason: `Latest verifier result is stale after later Goal worker evidence: ${postVerifierWorkerEvidence.label}.`,
        };
    }
    const audit = run.completionAudit;
    if (!audit) {
        return { ok: false, reason: "Goal has no final completion audit." };
    }
    if (audit.status !== "pass") {
        return { ok: false, reason: `Final completion audit status is ${audit.status}.` };
    }
    if (!audit.summary.startsWith("FINAL_AUDIT_PASS")) {
        return {
            ok: false,
            reason: "Final completion audit pass summary must start with FINAL_AUDIT_PASS.",
        };
    }
    if (!audit.summary.includes(`verifier_checked_at=${verifierResult.checkedAt}`)) {
        return {
            ok: false,
            reason: "Final completion audit pass summary must include latest verifier_checked_at.",
        };
    }
    if (!audit.outputPath && !audit.summary.match(/(?:output|artifact|log|path)=\S+/)) {
        return {
            ok: false,
            reason: "Final completion audit pass must reference verifier output or artifacts.",
        };
    }
    if (audit.verifierCheckedAt !== verifierResult.checkedAt) {
        return {
            ok: false,
            reason: "Final completion audit does not match the latest verifier result.",
        };
    }
    if (audit.checkedAt < verifierResult.checkedAt) {
        return {
            ok: false,
            reason: "Final completion audit is older than the latest verifier result.",
        };
    }
    const newerEvidence = latestCompletionRelevantEvidenceAfterVerifier(run);
    if (newerEvidence && newerEvidence.createdAt > audit.checkedAt) {
        return {
            ok: false,
            reason: `Final completion audit is stale after later Goal evidence: ${newerEvidence.label}.`,
        };
    }
    return { ok: true, reason: "Final completion audit passed after latest verifier evidence." };
}
function buildEvidencePlanTaskPrompt(run) {
    const plannedItems = unsatisfiedGoalEvidencePlanItems(run)
        .map((item) => `- ${item.label} (${item.mechanism}): ${item.description}${item.command ? `; candidate command: ${item.command}` : ""}${item.path ? `; artifact: ${item.path}` : ""}`)
        .join("\n");
    return (`Goal: ${run.goal}\n\n` +
        `Turn the planned proof paths below into real local/free verification capability before the Goal verifier runs. For each path, preserve the orchestrator's goal-specific sensory intent: what experience is being observed, what failure it catches, and what signal proves it.\n` +
        `${plannedItems}\n\n` +
        `Inventory available local capabilities without anchoring on any fixed tool category. Build only the proportional instrument needed for this proof path, update the Goal evidence_plan/harness/verifier metadata with the goals tool, and persist concrete command/file/artifact/log evidence that the instrument works. Do not use narrative-only verification or human visual inspection as completion evidence. Only block with exact user instructions for inputs that cannot be generated or checked locally.`);
}
function buildVerifierTaskPrompt(run) {
    return (`Goal: ${run.goal}\n\n` +
        `Define and build a real end-to-end verifier for this Goal. Begin from the intended experience and required senses/signals already implied by the success criteria and evidence plan. Choose a proportional local/free verifier that observes those signals and catches the important goal-specific failures; do not add generic simulations, screenshots, benchmarks, or scripts unless they directly support that proof. Update the Goal with a verifier_command and verifier_description using the goals tool. The verifier must be runnable locally/free and produce durable command or file evidence, not narrative or human visual inspection. If an external prerequisite is missing, mark it missing with exact user instructions.`);
}
function incompleteTasks(run) {
    return run.tasks.filter((task) => task.status !== "done");
}
function activeTask(run) {
    return run.tasks.find((task) => task.status === "running" || task.status === "verifying");
}
function nextRunnableTask(run) {
    return run.tasks.find((task) => task.status === "pending" || task.status === "failed");
}
export function canCompleteGoalRun(run) {
    if (run.status === "draft") {
        return { ok: false, reason: "Goal setup is incomplete and remains draft." };
    }
    if (run.successCriteria.length === 0) {
        return { ok: false, reason: "Goal setup is incomplete: success criteria are required." };
    }
    if (run.evidencePlan.length === 0) {
        return { ok: false, reason: "Goal setup is incomplete: an evidence plan is required." };
    }
    if (!run.verifier?.command) {
        return { ok: false, reason: "Goal setup is incomplete: verifier command is required." };
    }
    if (goalHasBlockingPrerequisites(run)) {
        return { ok: false, reason: formatGoalBlockingPrerequisites(run) };
    }
    const remainingTasks = incompleteTasks(run);
    if (remainingTasks.length > 0) {
        return {
            ok: false,
            reason: `${remainingTasks.length} Goal task${remainingTasks.length === 1 ? " is" : "s are"} not done.`,
        };
    }
    const requiredEvidence = hasRequiredGoalEvidence(run);
    if (!requiredEvidence.ok)
        return requiredEvidence;
    const verifierResult = run.verifier?.lastResult;
    if (!verifierResult) {
        return { ok: false, reason: "Goal has no verifier evidence." };
    }
    if (verifierResult.status !== "pass") {
        return { ok: false, reason: `Verifier status is ${verifierResult.status}.` };
    }
    const completionAudit = hasFreshGoalCompletionAudit(run);
    if (!completionAudit.ok)
        return completionAudit;
    return {
        ok: true,
        reason: "All tasks are done, verifier evidence passed, and final completion audit passed.",
    };
}
export function shouldClearGoalContinuation(decision) {
    return decision.kind !== "wait";
}
export function shouldCreateVerifierFixTask(run, limit = DEFAULT_GOAL_VERIFIER_FIX_LIMIT) {
    return run.tasks.filter((task) => task.title === "Fix verifier failure").length < limit;
}
export function verifierFixTaskCount(run) {
    return run.tasks.filter((task) => task.title === "Fix verifier failure").length;
}
export function hasRepeatedVerifierFailure(run, repeatLimit = 2) {
    const failures = run.evidence
        .filter((item) => item.label === "Verifier fail" || item.label === "Verifier result")
        .map((item) => (item.content ?? "").trim())
        .filter(Boolean);
    if (failures.length < repeatLimit)
        return false;
    const last = failures[failures.length - 1];
    return failures.slice(-repeatLimit).every((item) => item === last);
}
function buildFinalCompletionAuditTaskPrompt(run) {
    const verifier = run.verifier?.lastResult;
    const evidencePlanItems = run.evidencePlan
        .map((item) => `- ${item.id} / ${item.label} (${item.status}, ${item.mechanism}): ${item.description}${item.command ? `; command=${item.command}` : ""}${item.path ? `; path=${item.path}` : ""}${item.evidence ? `; evidence=${item.evidence}` : ""}`)
        .join("\n");
    const recentEvidence = run.evidence
        .slice(-12)
        .map((item) => `- ${item.createdAt} ${item.label}${item.path ? ` (${item.path})` : ""}: ${(item.content ?? "").slice(0, 320)}`)
        .join("\n");
    return (`Goal: ${run.goal}\n\n` +
        `You are the final read-only Goal completion auditor. Do not edit files, do not run broad implementation work, do not mark the Goal complete, and do not trust worker summaries by themselves. Verify the original success criteria against actual durable artifacts after the latest verifier pass.\n\n` +
        `Success criteria:\n${run.successCriteria.map((item) => `- ${item}`).join("\n") || "- none recorded"}\n\n` +
        `Latest verifier: status=${verifier?.status ?? "unknown"}; checkedAt=${verifier?.checkedAt ?? "unknown"}; command=${verifier?.command ?? run.verifier?.command ?? "not recorded"}; output=${verifier?.outputPath ?? "not recorded"}; summary=${verifier?.summary ?? "not recorded"}\n\n` +
        `Evidence plan:\n${evidencePlanItems || "- none"}\n\n` +
        `Recent durable evidence:\n${recentEvidence || "- none"}\n\n` +
        `Read the referenced report/log/source artifacts and compare them with the latest verifier result. If everything matches, record a passing completion audit with the goals tool by using action=audit, verification_status=pass, output_path matching the verifier output when available, and a summary that starts with "FINAL_AUDIT_PASS" and includes "verifier_checked_at=${verifier?.checkedAt ?? "unknown"}". If anything is missing, stale, contradictory, or unverified, create a new pending Goal task with exact instructions to fix it, record evidence describing the mismatch, and leave the audit failing or absent so the coordinator resumes a worker until fixed.`);
}
function buildVerifierFailureTaskPrompt(run) {
    const result = run.verifier?.lastResult;
    const priorSummaries = run.evidence
        .filter((item) => item.label.startsWith("Verifier"))
        .slice(-3)
        .map((item) => `- ${item.label}${item.path ? ` (${item.path})` : ""}: ${(item.content ?? "").slice(0, 500)}`)
        .join("\n") || "- none";
    const attempt = verifierFixTaskCount(run) + 1;
    return (`Original objective: ${run.goal}\n\n` +
        `Success criteria:\n${run.successCriteria.map((item) => `- ${item}`).join("\n") || "- none recorded"}\n\n` +
        `Verifier command: ${run.verifier?.command ?? "(missing)"}\n` +
        `Exit code: ${result?.exitCode ?? "unknown"}\n` +
        `Output path: ${result?.outputPath ?? "not recorded"}\n` +
        `Fix attempt ${attempt}/${DEFAULT_GOAL_VERIFIER_FIX_LIMIT}.\n\n` +
        `Prior verifier summaries:\n${priorSummaries}\n\n` +
        `Run targeted diagnostics, fix the root cause, update durable Goal evidence with the goals tool, and rerun the exact verifier command. Do not mark the Goal complete.`);
}
export function formatGoalControllerDecision(decision) {
    const parts = [`kind=${decision.kind}`];
    if ("reason" in decision)
        parts.push(`reason=${decision.reason}`);
    if (decision.kind === "start_worker" || decision.kind === "pause") {
        parts.push(`task=${decision.task.id}`, `title=${decision.task.title}`, `attempts=${decision.attempts}`);
        if (decision.task.workerId)
            parts.push(`worker=${decision.task.workerId}`);
    }
    if (decision.kind === "wait" && decision.workerId)
        parts.push(`worker=${decision.workerId}`);
    if (decision.kind === "run_verifier")
        parts.push(`verifier=${decision.command}`);
    if (decision.kind === "terminal")
        parts.push(`status=${decision.status}`);
    if (decision.kind === "create_task")
        parts.push(`title=${decision.title}`);
    return { label: `Goal decision: ${decision.kind}`, content: parts.join("; ") };
}
export function decideGoalNextAction(run, options = {}) {
    const completion = canCompleteGoalRun(run);
    if (completion.ok) {
        return { kind: "complete", reason: completion.reason };
    }
    if (goalHasBlockingPrerequisites(run)) {
        return { kind: "blocked", reason: formatGoalBlockingPrerequisites(run) };
    }
    if ((run.status === "blocked" && run.verifier?.lastResult?.status !== "pass") ||
        run.status === "failed" ||
        (run.status === "passed" && run.verifier?.lastResult?.status !== "pass") ||
        (run.status === "paused" && !run.continueRequestedAt)) {
        return { kind: "terminal", status: run.status, reason: `Goal is ${run.status}.` };
    }
    if (run.activeWorkerId) {
        return {
            kind: "wait",
            reason: "Goal already has an active worker.",
            workerId: run.activeWorkerId,
        };
    }
    const runningTask = activeTask(run);
    if (runningTask) {
        return {
            kind: "wait",
            reason: `Goal task "${runningTask.title}" is already ${runningTask.status}.`,
            ...(runningTask.workerId ? { workerId: runningTask.workerId } : {}),
        };
    }
    const task = nextRunnableTask(run);
    if (task) {
        const attempts = task.attempts + 1;
        const limit = options.taskAttemptLimit ?? DEFAULT_GOAL_TASK_ATTEMPT_LIMIT;
        if (attempts > limit) {
            return {
                kind: "pause",
                task,
                attempts,
                reason: `Attempt limit reached for task ${task.title}.`,
            };
        }
        return {
            kind: "start_worker",
            task,
            attempts,
            reason: `Goal task "${task.title}" is ready for worker attempt ${attempts}.`,
        };
    }
    const blockedEvidence = blockedEvidencePlanReason(run);
    if (blockedEvidence) {
        return { kind: "blocked", reason: blockedEvidence };
    }
    if (needsEvidenceInstrumentation(run)) {
        if (run.verifier?.lastResult?.status === "pass") {
            const limit = options.evidenceReconciliationLimit ?? DEFAULT_GOAL_EVIDENCE_RECONCILIATION_LIMIT;
            if (shouldCreateEvidenceReconciliationTask(run, limit)) {
                return {
                    kind: "create_task",
                    title: EVIDENCE_RECONCILIATION_TASK_TITLE,
                    prompt: buildEvidenceReconciliationTaskPrompt(run),
                    reason: `Verifier passed but ${unsatisfiedGoalEvidencePlanItems(run).length} evidence-plan item(s) still need durable reconciliation (${evidenceReconciliationTaskCount(run) + 1}/${limit}).`,
                };
            }
            return {
                kind: "blocked",
                reason: "Verifier passed, but the Goal evidence plan is still not satisfied after bounded reconciliation attempts.",
            };
        }
        return {
            kind: "create_task",
            title: "Build Goal evidence path",
            prompt: buildEvidencePlanTaskPrompt(run),
            reason: "Goal evidence plan requires local instrumentation or exact prerequisite handling before verification.",
        };
    }
    if (needsHarnessInstrumentation(run)) {
        return {
            kind: "create_task",
            title: "Build Goal verification harness",
            prompt: buildHarnessTaskPrompt(run),
            reason: "Goal harness requires local instrumentation before verification.",
        };
    }
    if (run.verifier?.lastResult?.status === "fail") {
        if (hasRepeatedVerifierFailure(run)) {
            return {
                kind: "blocked",
                reason: "Verifier produced the same failure repeatedly; pause for diagnosis before creating more fix tasks.",
            };
        }
        const limit = options.verifierFixLimit ?? DEFAULT_GOAL_VERIFIER_FIX_LIMIT;
        if (shouldCreateVerifierFixTask(run, limit)) {
            return {
                kind: "create_task",
                title: "Fix verifier failure",
                prompt: buildVerifierFailureTaskPrompt(run),
                reason: `Verifier failed; creating bounded fix task ${verifierFixTaskCount(run) + 1}/${limit}.`,
            };
        }
        return {
            kind: "pause",
            task: {
                id: "verifier-fix-limit",
                title: "Fix verifier failure",
                prompt: "Verifier fix attempt limit reached.",
                status: "blocked",
                attempts: limit,
            },
            attempts: limit,
            reason: `Verifier fix task limit reached (${limit}).`,
        };
    }
    if (run.verifier?.lastResult?.status === "pass") {
        if (latestNonAuditWorkerEvidenceAfterVerifier(run) && run.verifier?.command) {
            return {
                kind: "run_verifier",
                command: run.verifier.command,
                reason: "Latest verifier result is stale after later Goal worker evidence; rerunning verifier before final completion audit.",
            };
        }
        if (shouldCreateFinalAuditTask(run)) {
            return {
                kind: "create_task",
                title: FINAL_COMPLETION_AUDIT_TASK_TITLE,
                prompt: buildFinalCompletionAuditTaskPrompt(run),
                reason: `Verifier passed; creating final read-only completion audit before the Goal can pass (${finalAuditTaskCount(run) + 1}/${DEFAULT_GOAL_COMPLETION_AUDIT_LIMIT}).`,
            };
        }
        return {
            kind: "blocked",
            reason: "Verifier passed, but final completion audit did not pass after bounded attempts.",
        };
    }
    if (run.verifier?.command) {
        return {
            kind: "run_verifier",
            command: run.verifier.command,
            reason: "All Goal tasks are done; running configured verifier for real completion evidence.",
        };
    }
    return {
        kind: "create_task",
        title: "Define Goal verifier",
        prompt: buildVerifierTaskPrompt(run),
        reason: "No pending Goal task or verifier command is configured.",
    };
}
//# sourceMappingURL=goal-controller.js.map