"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createTaskAttemptChronologyRecoverCommand = createTaskAttemptChronologyRecoverCommand;
const errors_1 = require("../../../lib/errors");
const output_1 = require("../../../lib/output");
const task_chronology_recovery_1 = require("../../../lib/planning/task-chronology-recovery");
const runtime_contract_1 = require("../../../lib/runtime/runtime-contract");
const global_format_1 = require("../global-format");
async function createTaskAttemptChronologyRecoverCommand() {
    const { Command } = await import('commander');
    const command = new Command('attempt-chronology-recover');
    command
        .description('Preview or atomically preserve one evidence-bearing attempt whose opening, baseline, or latest closed-predecessor timestamp conflicts with immutable run evidence.')
        .requiredOption('--chronology-run-directory <path>', 'Full-cycle-strict source run containing immutable chronology evidence. This is distinct from the global lifecycle-capture --run-directory.')
        .requiredOption('--task-definition <path>', 'Repository-relative canonical task-definition.md path.')
        .requiredOption('--attempt-id <identity>', 'Exact invalid open current attempt or latest closed poisoned predecessor identity.')
        .requiredOption('--task-revision <revision>', 'Exact current 64-character task revision.')
        .requiredOption('--recorded-by <actor>', 'Non-empty recovery actor.')
        .requiredOption('--recorded-at <timestamp>', 'ISO-8601 recovery time with explicit timezone.')
        .requiredOption('--reason <text>', 'Non-empty audit reason for invalid chronology recovery.')
        .option('--dry-run', 'Preview exact source evidence, pair preconditions, and append-only recovery writes without mutation; omit to apply.')
        .action((_, 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();
        const request = {
            repositoryRoot: repository.root,
            runDirectory: options.chronologyRunDirectory,
            taskDefinitionPath: options.taskDefinition,
            attemptId: options.attemptId,
            taskRevision: options.taskRevision,
            recordedBy: options.recordedBy,
            recordedAt: options.recordedAt,
            reason: options.reason,
        };
        let result;
        try {
            const preview = (0, task_chronology_recovery_1.previewTaskChronologyRecoverySync)(request);
            result = options.dryRun === true || preview.writeOutcome === 'no-write'
                ? preview
                : (0, task_chronology_recovery_1.applyTaskChronologyRecoverySync)(preview);
        }
        catch (error) {
            throw normalizeError(error, request);
        }
        if (!['previewed', 'committed', 'no-write'].includes(result.writeOutcome)) {
            throw outcomeError(result);
        }
        (0, output_1.emitSuccess)({
            command: 'task attempt-chronology-recover',
            format,
            text: renderText(result),
            data: {
                ...result,
                repositoryRoot: repository.root,
                detectionSource: repository.detectionSource,
                nextAction: result.writeOutcome === 'previewed'
                    ? applyAction(request)
                    : freshReadinessAction(result),
                historicalValidationPosture: 'Unrecordable predecessor executions remain non-advancing historical evidence. The chronology_repair successor receives new validation identities for the corrected repository state.',
            },
        });
    });
    command.addHelpText('after', [
        '',
        'Boundaries:',
        '  Eligibility requires hash-verified source-run evidence proving invalid opening, baseline, or future close chronology.',
        '  No-evidence future attempts remain task attempt-abort territory.',
        '  Apply appends chronology audit fields, preserves original close timestamps and all baseline/run evidence, resets readiness, and creates no successor or authorization.',
        '  A later attempt-open links the fresh successor with successor_kind chronology_repair.',
    ].join('\n'));
    return command;
}
function applyAction(request) {
    return {
        reasonCode: 'apply-chronology-recovery',
        command: 'task attempt-chronology-recover',
        argv: [
            'day-shift', 'task', 'attempt-chronology-recover',
            '--chronology-run-directory', request.runDirectory,
            '--task-definition', request.taskDefinitionPath,
            '--attempt-id', request.attemptId,
            '--task-revision', request.taskRevision,
            '--recorded-by', request.recordedBy,
            '--recorded-at', request.recordedAt,
            '--reason', request.reason,
        ],
        callable: true,
        writeCapable: true,
    };
}
function freshReadinessAction(result) {
    return (0, errors_1.createDescriptorBackedRecoveryAction)({
        command: 'task readiness-review',
        argv: [
            'day-shift', 'task', 'readiness-review',
            '--task-definition', result.taskDefinitionPath,
            '--reviewed-by', result.recordedBy,
            '--reviewed-at', result.recordedAt,
            '--format', 'json',
        ],
        explanation: 'Run the exact fresh readiness review outside the now-immutable source run. Its complete result supplies authorization inputs for a new chronology_repair successor attempt.',
        selectedArtifactPath: result.taskDefinitionPath,
    });
}
function normalizeError(error, request) {
    if (error instanceof errors_1.RuntimeError)
        return error;
    if (!(error instanceof task_chronology_recovery_1.TaskChronologyRecoveryError))
        throw error;
    const code = `TASK_ATTEMPT_CHRONOLOGY_RECOVER_${error.code.replace(/-/g, '_').toUpperCase()}`;
    const exitCode = error.code === 'stale-task-revision' || error.code === 'stale-preview'
        ? errors_1.RuntimeExitCode.STALE_EVIDENCE
        : error.code === 'invalid-input'
            ? errors_1.RuntimeExitCode.USAGE
            : errors_1.RuntimeExitCode.INVALID_CONFIG;
    return new errors_1.RuntimeError({
        message: 'Task attempt chronology recovery was rejected.',
        code,
        exitCode,
        writeOutcome: 'no-writes',
        details: [
            error.message,
            'No task, summary, attempt, baseline, validation execution, run entry, or source evidence was rewritten or deleted.',
        ],
        findings: [{
                code,
                severity: 'error',
                message: error.message,
                path: request.taskDefinitionPath,
                noWriteBoundary: 'Rejected chronology recovery does not mutate the selected task pair or lifecycle run.',
            }],
        recoveryActions: [(0, errors_1.createNonCallableRecoveryAction)({
                id: 'recovery.task-attempt-chronology-recover.refresh-exact-preview',
                command: 'task attempt-chronology-recover',
                explanation: 'Refresh the exact source run, current pair revision, attempt, actor, time, and reason before retrying.',
                reason: 'The failure boundary cannot safely reconstruct stale or conflicting caller inputs.',
            })],
    });
}
function outcomeError(result) {
    const details = [
        `writeOutcome: ${result.writeOutcome}`,
        `intendedPaths: ${JSON.stringify(result.intendedPaths)}`,
        `changedPaths: ${JSON.stringify(result.changedPaths)}`,
        `conflicts: ${JSON.stringify(result.conflicts)}`,
        `recoveryPath: ${result.recoveryPath ?? 'null'}`,
        `failure: ${result.failure ?? 'null'}`,
    ];
    if (result.writeOutcome === 'conflict') {
        return new errors_1.RuntimeError({
            message: 'Task attempt chronology recovery preview is stale or conflicted.',
            code: 'TASK_ATTEMPT_CHRONOLOGY_RECOVER_CONFLICT',
            exitCode: errors_1.RuntimeExitCode.CONCURRENCY_CONFLICT,
            writeOutcome: 'no-writes',
            details,
        });
    }
    if (result.writeOutcome === 'incomplete') {
        return new errors_1.RuntimeError({
            message: 'Task attempt chronology recovery stopped with incomplete repository state.',
            code: 'TASK_ATTEMPT_CHRONOLOGY_RECOVER_INCOMPLETE',
            exitCode: errors_1.RuntimeExitCode.PARTIAL_MUTATION,
            writeOutcome: 'partial',
            details,
            recoveryActions: [(0, errors_1.createNonCallableRecoveryAction)({
                    id: 'recovery.inspect-task-attempt-chronology-recover-transaction',
                    explanation: 'Inspect retained transaction evidence before retrying or repairing the task pair.',
                    reason: result.recoveryPath ?? 'The retained transaction path was unavailable.',
                })],
        });
    }
    return new errors_1.RuntimeError({
        message: 'Task attempt chronology recovery produced no canonical result.',
        code: 'TASK_ATTEMPT_CHRONOLOGY_RECOVER_NO_WRITE',
        exitCode: errors_1.RuntimeExitCode.ERROR,
        details,
    });
}
function renderText(result) {
    return [
        'Task attempt chronology recovery',
        '',
        `Task definition: ${result.taskDefinitionPath}`,
        `Implementation summary: ${result.implementationSummaryPath}`,
        `Source run: ${result.runDirectory}`,
        `Prior attempt: ${result.priorAttemptId}`,
        `Recovery ID: ${result.recoveryId}`,
        `Recovery state: ${result.recoveryState}`,
        `Observed opening: ${result.observedOpenedAt}`,
        `Observed baseline capture: ${result.observedBaselineAt ?? 'none'}`,
        `Original close: ${result.originalClosedAt ?? 'none'}`,
        `Effective close: ${result.effectiveClosedAt ?? 'none'}`,
        `Source entry: ${result.sourceEntryId ?? 'none'}`,
        `Immutable evidence entries: ${result.evidenceEntryIds.length}`,
        `Unrecordable validations: ${result.unrecordableValidationIds.length}`,
        `Idempotent replay: ${result.idempotent ? 'yes' : 'no'}`,
        `Write outcome: ${result.writeOutcome}`,
    ].join('\n');
}
