"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createTaskValidationRecordCommand = createTaskValidationRecordCommand;
const errors_1 = require("../../../lib/errors");
const output_1 = require("../../../lib/output");
const task_validation_1 = require("../../../lib/planning/task-validation");
const task_lifecycle_timestamps_1 = require("../../../lib/planning/task-lifecycle-timestamps");
const runtime_contract_1 = require("../../../lib/runtime/runtime-contract");
const global_format_1 = require("../global-format");
async function createTaskValidationRecordCommand() {
    const { Command } = await import("commander");
    const command = new Command("validation-record");
    command
        .description("Preview a non-executing validation plan or execute exact argv once and transactionally append one revision-bound result, including evidence-only and closed-attempt backfill modes.")
        .requiredOption("--task-definition <path>", "Repository-relative canonical task-definition.md path.")
        .requiredOption("--validation-id <identity>", "Stable append-only validation result identity.")
        .requiredOption("--attempt-id <identity>", "Owning current attempt identity.")
        .requiredOption("--name <text>", "Human-readable validation name.")
        .option("--command <text>", "Intended command text for non-execution or imported evidence; compatible inline JSON execution contracts remain supported.")
        .option("--execution-contract <path>", "Repository-relative schemaVersion 1 JSON execution-contract file.")
        .option("--timeout-ms <milliseconds>", "Optional command-owned execution timeout from 1 through 86400000 milliseconds.")
        .option("--expect-json <assertion>", "Repeatable <json-pointer>=<JSON-literal> equality assertion over one bounded JSON stdout document.", collect, [])
        .option("--supersedes-validation-id <identity>", "Optional validation identity replaced by this result.")
        .requiredOption("--required <boolean>", "Whether the validation is required: true or false.")
        .option("--status <value>", "passed, failed, not_run, waived, blocked, or not_applicable; omitted for command-owned execution.")
        .option("--exit-code <integer>", "Process exit code when the status supports one.")
        .requiredOption("--summary <text>", "Concise validation result summary.")
        .option("--output-reference <value>", "For CI/imported passed evidence, a repository-relative schemaVersion 1 verified-result JSON contract; otherwise a bounded output, log, or artifact reference.")
        .option("--source-reference <value>", "CI/import source reference; required for ci or imported evidence.")
        .option("--recorded-at <timestamp>", "ISO-8601 record time with explicit timezone; command-owned execution derives it.")
        .option("--source <value>", "manual, ci, or imported.", "manual")
        .requiredOption("--dependency-mode <value>", "repository, declared, or unknown.")
        .option("--scope-path <path>", "Explicit validated path. Repeat as needed.", collect, [])
        .option("--dependency <path>", "Explicit dependency path. Repeat as needed.", collect, [])
        .option("--waiver-id <identity>", "Optional explicit waiver identity reference.")
        .option("--closed-attempt-backfill", "Append preservation-only imported evidence to the named closed runtime-attribution opt-out attempt.")
        .option("--dry-run", "Preview exact argv and pair preconditions without launching command-owned validation or mutating files.")
        .argument("[argv...]", "Exact command argv after '--' for one command-owned process execution.")
        .action((argv, _, commandInstance) => {
        const format = (0, output_1.resolveOutputFormat)((0, global_format_1.getGlobalFormat)(commandInstance));
        if (format === null)
            throw (0, errors_1.createUsageError)("Output format must be one of: text, json.");
        const repository = (0, runtime_contract_1.createRepositoryContext)((0, runtime_contract_1.detectRepositoryRoot)(), false);
        const options = commandInstance.opts();
        let preview;
        try {
            preview = (0, task_validation_1.previewTaskValidationRecordSync)({
                repositoryRoot: repository.root,
                taskDefinitionPath: options.taskDefinition,
                validationId: options.validationId,
                attemptId: options.attemptId,
                name: options.name,
                command: options.command,
                executionArgv: argv.length === 0 ? undefined : argv,
                executionContractPath: options.executionContract,
                executionTimeoutMs: parseTimeout(options.timeoutMs),
                expectJson: options.expectJson,
                supersedesValidationId: options.supersedesValidationId,
                required: parseBoolean(options.required),
                status: options.status,
                exitCode: parseExitCode(options.exitCode),
                summary: options.summary,
                outputReference: options.outputReference,
                sourceReference: options.sourceReference,
                recordedAt: options.recordedAt,
                source: options.source,
                dependencyMode: options.dependencyMode,
                scopePaths: options.scopePath,
                dependencies: options.dependency,
                waiverId: options.waiverId,
                closedAttemptBackfill: options.closedAttemptBackfill === true
            });
        }
        catch (error) {
            if (error instanceof task_lifecycle_timestamps_1.TaskLifecycleTimestampValidationError)
                throw error;
            throw (0, errors_1.createUsageError)(error instanceof Error ? error.message : String(error), [
                "No validation evidence was inferred or written; refresh the task pair and current attempt before retrying."
            ]);
        }
        const result = options.dryRun === true ? preview : (0, task_validation_1.applyTaskValidationRecordSync)(preview);
        if (result.writeOutcome !== "previewed" && result.writeOutcome !== "committed") {
            if (result.environmentExecutionFailure != null) {
                throw (0, errors_1.createEnvironmentExecutionError)(result.environmentExecutionFailure);
            }
            throw (0, errors_1.createUsageError)(`Task validation record ended with '${result.writeOutcome}'.`, [
                ...(result.failure === null ? [] : [result.failure]),
                ...(result.recoveryPath === null ? [] : [`Recovery record: ${result.recoveryPath}`]),
                ...result.conflicts.map((conflict) => `${conflict.path}: ${conflict.guidance}`)
            ]);
        }
        const identity = result.validation ?? result.executionPlan;
        if (identity === null) {
            throw (0, errors_1.createUsageError)("Task validation record produced neither validation evidence nor an execution plan.");
        }
        (0, output_1.emitSuccess)({
            command: "task validation-record",
            format,
            text: [
                "Task validation record",
                "",
                `Task definition: ${result.taskDefinitionPath}`,
                `Attempt ID: ${identity.attemptId}`,
                `Validation ID: ${identity.validationId}`,
                `Supersedes validation ID: ${identity.supersedesValidationId ?? "(none)"}`,
                `Status: ${result.validation?.status ?? "pending-execution"}`,
                `Source: ${result.validation?.source ?? "manual"}`,
                `Verification mode: ${result.validation?.evidenceVerification?.mode ?? "not-executed"}`,
                `Semantic assertions: ${result.executionPlan?.semanticAssertions.length ?? result.validation?.evidenceVerification?.semanticAssertions?.assertions.length ?? 0}`,
                `Effective validation IDs: ${result.validationIdentityProjection.effectiveValidationIds.join(", ") || "(none)"}`,
                `Superseded validation IDs: ${result.validationIdentityProjection.supersededValidationIds.join(", ") || "(none)"}`,
                `Evidence binding: ${result.validation?.evidenceBinding ?? "pending-execution"}`,
                `Recording mode: ${result.validation?.recordingMode ?? "pending-execution"}`,
                `Dependency mode: ${result.validation?.validationScope.dependencyMode ?? options.dependencyMode}`,
                `Write outcome: ${result.writeOutcome}`,
                `Changed paths: ${result.changedPaths.length}`
            ].join("\n"),
            data: { ...result, repositoryRoot: repository.root, detectionSource: repository.detectionSource }
        });
    });
    return command;
}
function collect(value, previous) {
    previous.push(value);
    return previous;
}
function parseBoolean(value) {
    if (value === "true")
        return true;
    if (value === "false")
        return false;
    throw (0, errors_1.createUsageError)("--required must be true or false.");
}
function parseExitCode(value) {
    if (value === undefined)
        return null;
    if (!/^\d+$/.test(value))
        throw (0, errors_1.createUsageError)("--exit-code must be an integer.");
    return Number(value);
}
function parseTimeout(value) {
    if (value === undefined)
        return null;
    if (!/^\d+$/.test(value))
        throw (0, errors_1.createUsageError)("--timeout-ms must be an integer.");
    const timeout = Number(value);
    if (timeout < 1 || timeout > 86_400_000) {
        throw (0, errors_1.createUsageError)("--timeout-ms must be from 1 through 86400000.");
    }
    return timeout;
}
