"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createTaskBaselineCommand = createTaskBaselineCommand;
const errors_1 = require("../../../lib/errors");
const output_1 = require("../../../lib/output");
const task_cycle_runtime_attribution_1 = require("../../../lib/planning/task-cycle-runtime-attribution");
const task_attempts_1 = require("../../../lib/planning/task-attempts");
const cli_constants_1 = require("../../../lib/config/cli-constants");
const runtime_contract_1 = require("../../../lib/runtime/runtime-contract");
const global_format_1 = require("../global-format");
const persisted_artifact_reminder_1 = require("../persisted-artifact-reminder");
async function createTaskBaselineCommand() {
    const { Command } = await import('commander');
    const command = new Command('baseline');
    command
        .description('Plan, capture, or validate one post-readiness, pre-write runtime-attribution baseline on a task definition.')
        .requiredOption('--task-definition <path>', 'Repository-relative task-definition.md path.')
        .requiredOption('--task-cycle-id <attempt-id>', cli_constants_1.CLI_TASK_BASELINE_TASK_CYCLE_IDENTITY_CONTRACT)
        .requiredOption('--checkpoint-id <readiness-review-id>', cli_constants_1.CLI_TASK_BASELINE_CHECKPOINT_IDENTITY_CONTRACT)
        .option('--captured-by <actor>', 'Required actor for a new schema-2 attempt-owned baseline.')
        .option('--captured-at <timestamp>', 'Required ISO-8601 capture time for a new schema-2 attempt-owned baseline.')
        .option('--contract-impact-fingerprint <sha256>', 'Exact current fingerprint emitted by task readiness-review when the repository contract-impact contract is present.')
        .option('--resume', 'Reuse only an existing baseline with the exact task-cycle and checkpoint identities.')
        .option('--plan', 'Report deterministic target and accepted-predecessor eligibility without writing files.')
        .option('--dry-run', 'Preview exact pair preconditions and attempt-owned baseline writes without mutation.')
        .option('--adopt <path::rationale>', 'Explicitly adopt a dirty declared target with a concrete rationale, select accepted-predecessor:<task-definition.md>, or use an emitted chronology-repair-predecessor:<attempt>:<recovery> attribution. Repeat per path.', collectValue, [])
        .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 repositoryContext = (0, runtime_contract_1.createRepositoryContext)((0, runtime_contract_1.detectRepositoryRoot)(), false);
        const options = commandInstance.opts();
        if (options.plan === true) {
            if (options.resume === true || options.dryRun === true) {
                throw (0, errors_1.createUsageError)('--plan cannot be combined with --resume or --dry-run.');
            }
            let plan;
            try {
                plan = (0, task_cycle_runtime_attribution_1.planTaskCycleRuntimeBaseline)(repositoryContext.root, {
                    taskDefinitionPath: options.taskDefinition,
                    taskCycleId: options.taskCycleId,
                    checkpointId: options.checkpointId,
                    capturedBy: options.capturedBy,
                    capturedAt: options.capturedAt,
                    contractImpactFingerprint: options.contractImpactFingerprint,
                    adoptions: options.adopt,
                });
            }
            catch (error) {
                throw normalizeTaskBaselineError(error, options, repositoryContext.root);
            }
            (0, output_1.emitSuccess)({
                command: 'task baseline',
                format,
                text: [
                    'Task runtime-attribution baseline plan',
                    '',
                    `Task definition: ${plan.taskDefinitionPath}`,
                    `Task-cycle ID: ${plan.taskCycleId}`,
                    `Checkpoint ID: ${plan.checkpointId}`,
                    `Read-only: ${plan.readOnly ? 'yes' : 'no'}`,
                    `Bounded: ${plan.bounded ? 'yes' : 'no'}`,
                    `Callable: ${plan.callable ? 'yes' : 'no'}`,
                    `Declared targets: ${plan.targets.length}`,
                    ...plan.targets.map((target) => `- ${target.path}: ${target.status}; content ${target.contentSha256 ?? 'unavailable'}; status ${target.statusSha256 ?? 'unavailable'}`),
                    `Blockers: ${plan.blockers.length}`,
                    ...plan.blockers.map((blocker) => `- ${blocker}`),
                    ...(plan.baselineArgv === null
                        ? []
                        : [`Baseline argv: ${plan.baselineArgv.map((entry) => JSON.stringify(entry)).join(' ')}`]),
                ].join('\n'),
                data: {
                    repositoryRoot: repositoryContext.root,
                    detectionSource: repositoryContext.detectionSource,
                    mode: 'plan',
                    ...plan,
                    recovery: {
                        callable: plan.callable,
                        argv: plan.baselineArgv,
                        previewArgv: plan.previewArgv,
                        nonCallableReasons: plan.blockers,
                    },
                },
            });
            return;
        }
        let preview;
        try {
            preview = (0, task_cycle_runtime_attribution_1.previewTaskCycleRuntimeBaseline)(repositoryContext.root, {
                taskDefinitionPath: options.taskDefinition,
                taskCycleId: options.taskCycleId,
                checkpointId: options.checkpointId,
                capturedBy: options.capturedBy,
                capturedAt: options.capturedAt,
                contractImpactFingerprint: options.contractImpactFingerprint,
                resume: options.resume === true,
                adoptions: options.adopt,
            });
        }
        catch (error) {
            throw normalizeTaskBaselineError(error, options, repositoryContext.root);
        }
        const result = options.dryRun === true || preview.writeOutcome === 'no-write'
            ? preview
            : (0, task_cycle_runtime_attribution_1.applyTaskCycleRuntimeBaseline)(preview);
        const persistedArtifactLicenseReminder = result.writeApplied
            ? (0, persisted_artifact_reminder_1.applyPlanningCommandPersistedArtifactReminderWrites)({
                repositoryContext,
                commandWriteSummary: result.commandWriteSummary,
                format,
            })
            : null;
        (0, output_1.emitSuccess)({
            command: 'task baseline',
            format,
            text: [
                'Task runtime-attribution baseline',
                '',
                `Task definition: ${result.taskDefinitionPath}`,
                `Action: ${result.action}`,
                `Baseline ID: ${result.baseline.baselineId}`,
                `Task-cycle ID: ${result.baseline.taskCycleId}`,
                `Checkpoint ID: ${result.baseline.checkpointId}`,
                `Declared targets: ${result.baseline.declaredTargets.length}`,
                `Accepted predecessor targets: ${result.baseline.declaredTargets.filter((entry) => entry.preExistingClassification === 'accepted-predecessor').length}`,
                `Write outcome: ${result.writeOutcome}`,
                `Write applied: ${result.writeApplied ? 'yes' : 'no'}`,
                `Changed paths: ${result.changedPaths.length}`,
                ...(result.evidenceGaps.length === 0
                    ? []
                    : ['Evidence gaps:', ...result.evidenceGaps.map((entry) => `- ${entry}`)]),
            ].join('\n'),
            data: {
                repositoryRoot: repositoryContext.root,
                detectionSource: repositoryContext.detectionSource,
                taskDefinitionPath: result.taskDefinitionPath,
                action: result.action,
                changed: result.changed,
                writeApplied: result.writeApplied,
                writeOutcome: result.writeOutcome,
                intendedPaths: result.intendedPaths,
                changedPaths: result.changedPaths,
                transactionId: result.transactionId,
                evidenceGaps: result.evidenceGaps,
                identityContract: {
                    taskCycleId: cli_constants_1.CLI_TASK_BASELINE_TASK_CYCLE_IDENTITY_CONTRACT,
                    checkpointId: cli_constants_1.CLI_TASK_BASELINE_CHECKPOINT_IDENTITY_CONTRACT,
                },
                baseline: result.baseline,
                commandWriteSummary: persistedArtifactLicenseReminder?.commandWriteSummary ?? result.commandWriteSummary,
                persistedArtifactLicenseReminder,
            },
        });
    });
    return command;
}
function collectValue(value, previous) {
    previous.push(value);
    return previous;
}
function normalizeTaskBaselineError(error, options, repositoryRoot) {
    const conditionalInputs = normalizeTaskBaselineConditionalInputs(error, options);
    if (conditionalInputs !== null)
        return conditionalInputs;
    const identityMismatch = normalizeTaskBaselineIdentityMismatch(error, options);
    if (identityMismatch !== null)
        return identityMismatch;
    const contractImpact = normalizeTaskBaselineContractImpactError(error, options);
    if (contractImpact !== null)
        return contractImpact;
    if (!(error instanceof task_cycle_runtime_attribution_1.TaskBaselineRuntimeAcceptanceContractError))
        return error;
    const reviewedBy = nonEmptyString(options.capturedBy) ?? 'operator';
    const reviewedAt = validIsoTimestamp(options.capturedAt) ?? new Date().toISOString();
    const reviewArgv = [
        'day-shift',
        'task',
        'readiness-review',
        '--task-definition',
        error.taskDefinitionPath,
        '--reviewed-by',
        reviewedBy,
        '--reviewed-at',
        reviewedAt,
        '--format',
        'json',
    ];
    const reviewCommand = reviewArgv.join(' ');
    let abortInspection = null;
    try {
        abortInspection = (0, task_attempts_1.inspectTaskAttemptAbortRecoverySync)(repositoryRoot, error.taskDefinitionPath, options.taskCycleId);
    }
    catch {
        abortInspection = null;
    }
    const abortReason = 'Baseline preconditions rejected this open attempt before runtime attribution or implementation evidence could be recorded.';
    const abortArgv = abortInspection?.eligible === true && abortInspection.currentAttemptId !== null
        ? [
            'day-shift',
            'task',
            'attempt-abort',
            '--task-definition',
            abortInspection.taskDefinitionPath,
            '--attempt-id',
            abortInspection.currentAttemptId,
            '--task-revision',
            abortInspection.taskRevision,
            '--recorded-by',
            reviewedBy,
            '--recorded-at',
            reviewedAt,
            '--reason',
            abortReason,
            '--dry-run',
            '--format',
            'json',
        ]
        : null;
    const abortCommand = abortArgv?.join(' ') ?? null;
    const refinement = "Refine the selected task through .day-shift/prompts/user/task.build.md so runtime_acceptance.required is true and criterion_ids is a non-empty stable set aligned with the task's executable acceptance criteria.";
    const recovery = 'If attempt-abort is offered, preview and apply that exact pair reset before refinement. Then run the emitted task readiness-review command, apply task readiness-authorize from its complete JSON result, open a clean successor with a new task attempt-open identity, and capture baseline against the successor identities.';
    return new errors_1.RuntimeError({
        message: 'Task baseline capture is blocked by an invalid runtime acceptance planning contract.',
        code: task_cycle_runtime_attribution_1.TASK_BASELINE_RUNTIME_ACCEPTANCE_CONTRACT_INVALID,
        exitCode: errors_1.RuntimeExitCode.INVALID_CONFIG,
        writeOutcome: 'no-writes',
        details: [
            ...error.issues,
            ...(abortCommand === null ? [] : [`Invalid no-evidence attempt recovery preview: ${abortCommand}`]),
            refinement,
            recovery,
            'No task-definition or implementation-summary bytes were written.',
        ],
        findings: [
            {
                id: task_cycle_runtime_attribution_1.TASK_BASELINE_RUNTIME_ACCEPTANCE_CONTRACT_INVALID,
                code: task_cycle_runtime_attribution_1.TASK_BASELINE_RUNTIME_ACCEPTANCE_CONTRACT_INVALID,
                summary: error.message,
                message: error.message,
                level: 'error',
                severity: 'error',
                path: error.taskDefinitionPath,
                artifactPath: error.taskDefinitionPath,
                ruleFamily: 'task-baseline-runtime-acceptance',
                evidenceSource: 'planning-contract',
                reason: error.classification,
                noWriteBoundary: 'Rejected baseline capture does not mutate the selected task pair.',
                recommendedCommand: reviewCommand,
                recovery: [...(abortCommand === null ? [] : [abortCommand]), refinement, reviewCommand, recovery],
                evidence: {
                    category: 'planning-review',
                    details: {
                        classification: error.classification,
                        contract: 'runtime_acceptance',
                        issues: [...error.issues],
                        noWriteRequired: true,
                    },
                },
            },
        ],
        recoveryActions: [
            (0, errors_1.createDescriptorBackedRecoveryAction)({
                command: 'task readiness-review',
                argv: reviewArgv,
                explanation: 'Generate fresh revision-bound readiness evidence after refining the runtime acceptance contract.',
                selectedArtifactPath: error.taskDefinitionPath,
            }),
        ],
    });
}
function normalizeTaskBaselineConditionalInputs(error, options) {
    if (!(error instanceof errors_1.RuntimeError) ||
        error.code !== 'USAGE_ERROR' ||
        options.resume === true ||
        !/New attempt-owned baseline capture requires/u.test(error.message)) {
        return null;
    }
    const missingInputs = [
        ...(nonEmptyString(options.capturedBy) === null ? ['captured-by'] : []),
        ...(validIsoTimestamp(options.capturedAt) === null ? ['captured-at'] : []),
    ];
    if (missingInputs.length === 0)
        return null;
    const skeleton = [
        'day-shift',
        'task',
        'baseline',
        '--task-definition',
        options.taskDefinition,
        '--task-cycle-id',
        options.taskCycleId,
        '--checkpoint-id',
        options.checkpointId,
        ...(nonEmptyString(options.capturedBy) === null
            ? ['--captured-by', '<actor>']
            : ['--captured-by', nonEmptyString(options.capturedBy)]),
        ...(validIsoTimestamp(options.capturedAt) === null
            ? ['--captured-at', '<ISO-8601 timestamp>']
            : ['--captured-at', validIsoTimestamp(options.capturedAt)]),
        ...(options.plan === true ? ['--plan'] : []),
        ...(options.adopt ?? []).flatMap((adoption) => ['--adopt', adoption]),
        ...(options.dryRun === true ? ['--dry-run'] : []),
        '--format',
        'json',
    ].join(' ');
    return new errors_1.RuntimeError({
        message: 'Task baseline capture is missing conditional new-baseline inputs.',
        code: 'TASK_BASELINE_CONDITIONAL_INPUTS_MISSING',
        exitCode: errors_1.RuntimeExitCode.USAGE,
        writeOutcome: 'no-writes',
        details: [
            `missingInputs: ${missingInputs.join(', ')}`,
            '--captured-by and --captured-at are required only when creating or planning a new baseline; --resume reuses exact stored identities without them.',
            `authoritativeCommandSkeleton: ${skeleton}`,
            'The angle-bracket values are bounded input requests, not callable argv.',
            'No task-definition or implementation-summary bytes were written.',
        ],
        recoveryActions: [
            (0, errors_1.createNonCallableRecoveryAction)({
                id: 'recovery.task-baseline.supply-conditional-inputs',
                command: 'task baseline',
                explanation: 'Supply the explicitly listed actor and/or ISO-8601 time, then invoke the authoritative command skeleton.',
                reason: `Required conditional input${missingInputs.length === 1 ? '' : 's'} ${missingInputs.join(', ')} cannot be inferred.`,
                expectedPostcondition: 'A descriptor-valid exact baseline command is assembled without placeholder argv.',
            }),
        ],
    });
}
function normalizeTaskBaselineContractImpactError(error, options) {
    if (!(error instanceof task_cycle_runtime_attribution_1.TaskBaselineContractImpactError))
        return null;
    const reviewedBy = nonEmptyString(options.capturedBy) ?? 'operator';
    const reviewedAt = validIsoTimestamp(options.capturedAt) ?? new Date().toISOString();
    const reviewArgv = [
        'day-shift',
        'task',
        'readiness-review',
        '--task-definition',
        error.taskDefinitionPath,
        '--reviewed-by',
        reviewedBy,
        '--reviewed-at',
        reviewedAt,
        '--format',
        'json',
    ];
    const issueDetails = error.contractImpact.blockingIssues.length > 0 ? [...error.contractImpact.blockingIssues] : [error.message];
    return new errors_1.RuntimeError({
        message: error.message,
        code: task_cycle_runtime_attribution_1.TASK_CONTRACT_IMPACT_BASELINE_BLOCKED,
        exitCode: errors_1.RuntimeExitCode.INVALID_CONFIG,
        writeOutcome: 'no-writes',
        details: [
            ...issueDetails,
            `Current contract-impact fingerprint: ${error.contractImpact.fingerprint}`,
            `Supplied contract-impact fingerprint: ${error.suppliedFingerprint ?? '(missing)'}`,
            'No task-definition or implementation-summary bytes were written.',
        ],
        findings: [
            {
                id: task_cycle_runtime_attribution_1.TASK_CONTRACT_IMPACT_BASELINE_BLOCKED,
                code: task_cycle_runtime_attribution_1.TASK_CONTRACT_IMPACT_BASELINE_BLOCKED,
                summary: error.message,
                message: error.message,
                level: 'error',
                severity: 'error',
                path: error.taskDefinitionPath,
                artifactPath: error.taskDefinitionPath,
                ruleFamily: 'task-contract-impact',
                evidenceSource: 'planning-contract',
                reason: error.contractImpact.requiredComplete ? 'stale-fingerprint' : 'required-impact-incomplete',
                noWriteBoundary: 'Rejected impact preflight and baseline capture do not mutate the selected task pair.',
                recommendedCommand: reviewArgv.join(' '),
                recovery: [
                    'Revise only the task contract or repository impact contract needed to resolve the reported obligation.',
                    reviewArgv.join(' '),
                    `Reuse fingerprint '${error.contractImpact.fingerprint}' only from current clean readiness evidence.`,
                ],
                evidence: {
                    category: 'planning-review',
                    details: {
                        contractPath: error.contractImpact.contractPath,
                        contractState: error.contractImpact.contractState,
                        unknownPolicy: error.contractImpact.unknownPolicy,
                        fingerprint: error.contractImpact.fingerprint,
                        missingRequiredCount: error.contractImpact.missingRequired.length,
                        missingWritableCount: error.contractImpact.missingWritable.length,
                        missingGeneratedCount: error.contractImpact.missingGenerated.length,
                        immutableTargetCount: error.contractImpact.immutableTargets.length,
                        unknownCount: error.contractImpact.unknown.length,
                        suppliedFingerprint: error.suppliedFingerprint,
                        noWriteRequired: true,
                    },
                },
            },
        ],
        recoveryActions: [
            (0, errors_1.createDescriptorBackedRecoveryAction)({
                command: 'task readiness-review',
                argv: reviewArgv,
                explanation: 'Generate a fresh read-only impact preflight and readiness result before retrying baseline.',
                selectedArtifactPath: error.taskDefinitionPath,
            }),
        ],
    });
}
function normalizeTaskBaselineIdentityMismatch(error, options) {
    if (!(error instanceof errors_1.RuntimeError) ||
        error.code !== 'USAGE_ERROR' ||
        error.message !== 'Baseline compatibility identities must exactly match current attempt_id and readiness_review_id.') {
        return null;
    }
    const expectedTaskCycleId = readDetailValue(error.details, 'Current attempt_id:');
    const expectedCheckpointId = readDetailValue(error.details, 'Current readiness_review_id:');
    if (expectedTaskCycleId === null || expectedCheckpointId === null)
        return null;
    const retryArgv = [
        'day-shift',
        'task',
        'baseline',
        '--task-definition',
        options.taskDefinition,
        '--task-cycle-id',
        expectedTaskCycleId,
        '--checkpoint-id',
        expectedCheckpointId,
    ];
    if (options.resume === true) {
        retryArgv.push('--resume');
    }
    else {
        const capturedBy = nonEmptyString(options.capturedBy);
        const capturedAt = validIsoTimestamp(options.capturedAt);
        if (capturedBy !== null)
            retryArgv.push('--captured-by', capturedBy);
        if (capturedAt !== null)
            retryArgv.push('--captured-at', capturedAt);
    }
    if (options.plan === true)
        retryArgv.push('--plan');
    for (const adoption of options.adopt ?? []) {
        retryArgv.push('--adopt', adoption);
    }
    if (options.dryRun === true)
        retryArgv.push('--dry-run');
    retryArgv.push('--format', 'json');
    const contractDetails = [
        cli_constants_1.CLI_TASK_BASELINE_TASK_CYCLE_IDENTITY_CONTRACT,
        cli_constants_1.CLI_TASK_BASELINE_CHECKPOINT_IDENTITY_CONTRACT,
        `Expected task-cycle-id (current attempt_id): ${expectedTaskCycleId}`,
        `Received task-cycle-id: ${options.taskCycleId}`,
        `Expected checkpoint-id (attempt readiness_review_id): ${expectedCheckpointId}`,
        `Received checkpoint-id: ${options.checkpointId}`,
        'No task-definition or implementation-summary bytes were written.',
    ];
    const missingConditionalInputs = options.resume === true
        ? []
        : [
            ...(nonEmptyString(options.capturedBy) === null ? ['captured-by'] : []),
            ...(validIsoTimestamp(options.capturedAt) === null ? ['captured-at'] : []),
        ];
    const recoveryAction = missingConditionalInputs.length === 0
        ? (0, errors_1.createDescriptorBackedRecoveryAction)({
            command: 'task baseline',
            argv: retryArgv,
            explanation: 'Retry with task-cycle-id equal to the current attempt_id and checkpoint-id equal to that attempt readiness_review_id.',
            selectedArtifactPath: options.taskDefinition,
        })
        : (0, errors_1.createNonCallableRecoveryAction)({
            id: 'recovery.task-baseline.correct-identities-and-supply-inputs',
            command: 'task baseline',
            explanation: 'Use the reported exact lifecycle identities and supply the missing new-baseline actor/time inputs.',
            reason: `Required conditional input${missingConditionalInputs.length === 1 ? '' : 's'} ${missingConditionalInputs.join(', ')} cannot be inferred; no placeholder argv is callable.`,
        });
    return new errors_1.RuntimeError({
        message: 'Task baseline identity inputs do not match the current lifecycle attempt.',
        code: cli_constants_1.CLI_TASK_BASELINE_IDENTITY_MISMATCH,
        exitCode: errors_1.RuntimeExitCode.USAGE,
        writeOutcome: 'no-writes',
        details: contractDetails,
        findings: [
            {
                id: cli_constants_1.CLI_TASK_BASELINE_IDENTITY_MISMATCH,
                code: cli_constants_1.CLI_TASK_BASELINE_IDENTITY_MISMATCH,
                summary: 'Task baseline identity inputs do not match the current lifecycle attempt.',
                message: 'Task baseline identity inputs do not match the current lifecycle attempt.',
                level: 'error',
                severity: 'error',
                path: options.taskDefinition,
                artifactPath: options.taskDefinition,
                ruleFamily: 'task-baseline-identity',
                evidenceSource: 'current-attempt',
                reason: 'identity-mismatch',
                noWriteBoundary: 'Rejected baseline identity inputs do not mutate the selected task pair.',
                recommendedCommand: missingConditionalInputs.length === 0
                    ? retryArgv.join(' ')
                    : `${retryArgv.join(' ')} ${missingConditionalInputs.map((input) => `--${input} <value>`).join(' ')}`,
                recovery: [
                    missingConditionalInputs.length === 0
                        ? retryArgv.join(' ')
                        : `Supply ${missingConditionalInputs.join(' and ')} before invoking the emitted command skeleton.`,
                ],
                evidence: {
                    category: 'command-specific',
                    details: {
                        identityContract: {
                            taskCycleId: cli_constants_1.CLI_TASK_BASELINE_TASK_CYCLE_IDENTITY_CONTRACT,
                            checkpointId: cli_constants_1.CLI_TASK_BASELINE_CHECKPOINT_IDENTITY_CONTRACT,
                        },
                        expected: {
                            taskCycleId: expectedTaskCycleId,
                            checkpointId: expectedCheckpointId,
                        },
                        received: {
                            taskCycleId: options.taskCycleId,
                            checkpointId: options.checkpointId,
                        },
                    },
                },
            },
        ],
        recoveryActions: [recoveryAction],
    });
}
function readDetailValue(details, prefix) {
    const detail = details.find((entry) => entry.startsWith(prefix));
    return detail === undefined ? null : nonEmptyString(detail.slice(prefix.length));
}
function nonEmptyString(value) {
    return typeof value === 'string' && value.trim() !== '' ? value.trim() : null;
}
function validIsoTimestamp(value) {
    const normalized = nonEmptyString(value);
    return normalized !== null && Number.isFinite(Date.parse(normalized)) ? normalized : null;
}
