/**
 * 验证契约 — 问题十二 (Verification Contract)。
 *
 * 核心规则:
 * - VerificationPlan 只是计划，不是结果
 * - VerificationResult 必须来自真实执行或明确 not_executed
 * - 未验证不得 delivered
 * - delivery_readiness 不得触发 delivery_execution
 */
/**
 * 创建验证计划（不执行）。
 */
export function createVerificationPlan(taskId, commands, acceptanceCriteria) {
    return {
        plan_id: `vp-${taskId}-${Date.now()}`,
        task_id: taskId,
        commands,
        acceptance_criteria: acceptanceCriteria,
        created_at: new Date().toISOString(),
        status: "plan_only",
    };
}
/**
 * 检查是否为 plan_only（无真实执行）。
 * VerificationPlan.status === "plan_only" 时不得视为 VerificationResult。
 */
export function isPlanOnly(plan) {
    return plan.status === "plan_only";
}
/**
 * 创建验证结果（内部使用，provenance = "direct"）。
 * delivery_readiness 必须拒绝 provenance="direct" 的 passed 结果。
 * 唯一合法 passed 入口是 recordVerificationExecution。
 */
export function createVerificationResult(taskId, planId, evidenceIds, commandResults) {
    // 不允许空 evidenceIds + 空 commandResults 时返回 passed
    const hasEvidence = evidenceIds.length > 0;
    const hasCommands = commandResults.length > 0;
    // 无 evidence 或无 commands → 强制 failed
    if (!hasEvidence || !hasCommands) {
        return {
            result_id: `vr-${taskId}-${Date.now()}`,
            task_id: taskId,
            plan_id: planId,
            status: "failed",
            total_commands: commandResults.length,
            passed_commands: 0,
            failed_commands: 0,
            evidence_ids: evidenceIds,
            findings: [{
                    rule: "evidence_required",
                    severity: "hard_fail",
                    message_zh: `验证结果缺少${!hasEvidence ? " evidence" : ""}${!hasEvidence && !hasCommands ? " 和" : ""}${!hasCommands ? " commands" : ""}，不得 passed`,
                    diagnostic_code: "SF-VERIFY-0003",
                }],
            completed_at: new Date().toISOString(),
            provenance: "direct",
        };
    }
    const passedCount = commandResults.filter((r) => r.passed).length;
    const failedCount = commandResults.filter((r) => !r.passed).length;
    const findings = commandResults
        .filter((r) => !r.passed && r.diagnostic_code)
        .map((r) => ({
        rule: "command_failed",
        severity: "hard_fail",
        message_zh: `验证命令失败: ${r.diagnostic_code}`,
        diagnostic_code: r.diagnostic_code,
    }));
    return {
        result_id: `vr-${taskId}-${Date.now()}`,
        task_id: taskId,
        plan_id: planId,
        status: failedCount === 0 ? "passed" : "failed",
        total_commands: commandResults.length,
        passed_commands: passedCount,
        failed_commands: failedCount,
        evidence_ids: evidenceIds,
        findings,
        completed_at: new Date().toISOString(),
        provenance: "direct",
    };
}
/**
 * 创建未执行的验证结果。
 */
export function createNotExecutedResult(taskId, planId, reason) {
    return {
        result_id: `vr-${taskId}-${Date.now()}`,
        task_id: taskId,
        plan_id: planId,
        status: "not_executed",
        total_commands: 0,
        passed_commands: 0,
        failed_commands: 0,
        evidence_ids: [],
        findings: [{
                rule: "not_executed",
                severity: "warning",
                message_zh: `验证未执行: ${reason}`,
                diagnostic_code: "SF-VERIFY-0001",
            }],
        completed_at: new Date().toISOString(),
        provenance: "direct",
    };
}
/** SHA256 hex 格式 */
const SHA256_RE = /^[a-f0-9]{64}$/i;
/** ISO 8601 日期格式 */
const ISO8601_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/;
/**
 * 校验执行记录: 证据格式、命令合法性、evidence_id 唯一性、时间合法性。
 * 返回校验失败的记录索引及对应的 diagnostic_code。
 */
export function validateExecutionRecords(plan, records) {
    const errors = [];
    const seenEvidenceIds = new Set();
    const planCommands = new Set(plan.commands);
    for (let i = 0; i < records.length; i++) {
        const r = records[i];
        if (!r.command) {
            errors.push({ index: i, diagnostic_code: "SF-VERIFY-5001", message_zh: `记录 ${i}: command 为空` });
            continue;
        }
        if (!planCommands.has(r.command)) {
            errors.push({ index: i, diagnostic_code: "SF-VERIFY-5006", message_zh: `记录 ${i}: 命令 "${r.command}" 不在 plan.commands 中` });
        }
        if (!r.stdout_hash || !SHA256_RE.test(r.stdout_hash)) {
            errors.push({ index: i, diagnostic_code: "SF-VERIFY-5007", message_zh: `记录 ${i}: stdout_hash 为空或格式非法` });
        }
        if (!r.stderr_hash || !SHA256_RE.test(r.stderr_hash)) {
            errors.push({ index: i, diagnostic_code: "SF-VERIFY-5008", message_zh: `记录 ${i}: stderr_hash 为空或格式非法` });
        }
        if (!r.evidence_id) {
            errors.push({ index: i, diagnostic_code: "SF-VERIFY-5009", message_zh: `记录 ${i}: evidence_id 为空` });
        }
        else if (seenEvidenceIds.has(r.evidence_id)) {
            errors.push({ index: i, diagnostic_code: "SF-VERIFY-5010", message_zh: `记录 ${i}: evidence_id "${r.evidence_id}" 重复` });
        }
        else {
            seenEvidenceIds.add(r.evidence_id);
        }
        if (!r.started_at || !ISO8601_RE.test(r.started_at)) {
            errors.push({ index: i, diagnostic_code: "SF-VERIFY-5011", message_zh: `记录 ${i}: started_at 格式非法` });
        }
        if (!r.finished_at || !ISO8601_RE.test(r.finished_at)) {
            errors.push({ index: i, diagnostic_code: "SF-VERIFY-5012", message_zh: `记录 ${i}: finished_at 格式非法` });
        }
        if (r.started_at && r.finished_at && ISO8601_RE.test(r.started_at) && ISO8601_RE.test(r.finished_at)) {
            if (new Date(r.finished_at).getTime() < new Date(r.started_at).getTime()) {
                errors.push({ index: i, diagnostic_code: "SF-VERIFY-5013", message_zh: `记录 ${i}: finished_at 早于 started_at` });
            }
        }
    }
    return errors;
}
/**
 * 计算命令覆盖率: plan.commands 中被 records 覆盖的比例。
 */
export function computeCommandCoverage(plan, records) {
    const covered = new Set(records.map((r) => r.command));
    const coveredCommands = [];
    const missingCommands = [];
    for (const cmd of plan.commands) {
        if (covered.has(cmd)) {
            coveredCommands.push(cmd);
        }
        else {
            missingCommands.push(cmd);
        }
    }
    return { covered_commands: coveredCommands, missing_commands: missingCommands };
}
/** 构造带 diagnostic_code 的 failed 结果 */
function createFailedResult(taskId, planId, diagnosticCode, message) {
    return {
        result_id: `vr-${taskId}-${Date.now()}`,
        task_id: taskId,
        plan_id: planId,
        status: "failed",
        total_commands: 0,
        passed_commands: 0,
        failed_commands: 0,
        evidence_ids: [],
        findings: [{
                rule: "plan_binding_required",
                severity: "hard_fail",
                message_zh: message,
                diagnostic_code: diagnosticCode,
            }],
        completed_at: new Date().toISOString(),
        provenance: "direct",
        covered_commands: [],
        missing_commands: [],
        evidence_integrity_passed: false,
    };
}
/**
 * 录入真实执行结果 — VerificationResult.status = "passed" 的唯一合法入口。
 *
 * 规则:
 * - plan 为 null → hard fail (SF-VERIFY-5002)
 * - records 为空 → not_executed
 * - 非计划命令 → 该条 failed (SF-VERIFY-5006)
 * - stdout/stderr hash 格式非法 → 该条 failed
 * - evidence_id 重复 → 该条 failed
 * - 时间倒挂 → 该条 failed
 * - plan.commands 未全覆盖 → failed (SF-VERIFY-5003)
 * - 所有 exit_code === 0 且全覆盖且无格式错误 → passed
 */
export function recordVerificationExecution(taskId, planId, records, plan) {
    if (!plan) {
        return createFailedResult(taskId, planId, "SF-VERIFY-5002", "无关联 VerificationPlan，不得录入执行结果");
    }
    if (planId !== plan.plan_id) {
        return createFailedResult(taskId, planId, "SF-VERIFY-5014", `plan_id 不匹配: 传入 "${planId}"，plan 中 "${plan.plan_id}"`);
    }
    if (taskId !== plan.task_id) {
        return createFailedResult(taskId, planId, "SF-VERIFY-5015", `task_id 不匹配: 传入 "${taskId}"，plan 中 "${plan.task_id}"`);
    }
    if (records.length === 0) {
        return createNotExecutedResult(taskId, planId, "无执行记录");
    }
    // 校验证据格式和命令合法性
    const validationErrors = validateExecutionRecords(plan, records);
    const errorIndices = new Set(validationErrors.map((e) => e.index));
    // 校验命令覆盖
    const { covered_commands, missing_commands } = computeCommandCoverage(plan, records);
    const hasMissing = missing_commands.length > 0;
    // 逐条判定: 合法记录按 exit_code 判，非法记录直接 failed
    const commandResults = records.map((r, i) => {
        if (errorIndices.has(i)) {
            return { passed: false, diagnostic_code: "SF-VERIFY-5001" };
        }
        return {
            passed: r.exit_code === 0,
            diagnostic_code: r.exit_code !== 0 ? "SF-VERIFY-0004" : undefined,
        };
    });
    // 所有校验错误转为 findings（每条记录可能有多个错误）
    const validationFindings = validationErrors.map((e) => ({
        rule: "evidence_validation",
        severity: "hard_fail",
        message_zh: e.message_zh,
        diagnostic_code: e.diagnostic_code,
    }));
    const evidenceIds = records.map((r) => r.evidence_id);
    const base = createVerificationResult(taskId, planId, evidenceIds, commandResults);
    // 合并所有 findings
    const allFindings = [...base.findings, ...validationFindings];
    // 命令未全覆盖 → 强制 failed 并追加 finding
    if (hasMissing) {
        return {
            ...base,
            status: "failed",
            provenance: "record_verification_execution",
            findings: [...allFindings, {
                    rule: "plan_coverage_incomplete",
                    severity: "hard_fail",
                    message_zh: `plan 命令未全覆盖，缺少: ${missing_commands.join(", ")}`,
                    diagnostic_code: "SF-VERIFY-5003",
                }],
            covered_commands,
            missing_commands,
            evidence_integrity_passed: errorIndices.size === 0,
        };
    }
    return {
        ...base,
        provenance: "record_verification_execution",
        findings: allFindings,
        covered_commands,
        missing_commands,
        evidence_integrity_passed: errorIndices.size === 0,
    };
}
/**
 * 验证: VerificationPlan 不得当作 VerificationEvidence。
 */
export function validateVerificationSeparation(plan, result) {
    const errors = [];
    if (!result) {
        errors.push({
            error: `验证计划 ${plan.plan_id} 存在但无 VerificationResult`,
            severity: "hard_fail",
        });
    }
    else if (result.status === "not_executed") {
        errors.push({
            error: `验证结果状态为 not_executed，不得视为通过`,
            severity: "hard_fail",
        });
    }
    return errors;
}
//# sourceMappingURL=verification_contract.js.map