"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.previewLifecycleRunContractRevisionSync = previewLifecycleRunContractRevisionSync;
exports.applyLifecycleRunContractRevisionSync = applyLifecycleRunContractRevisionSync;
exports.parseContractRevisionRollbackGate = parseContractRevisionRollbackGate;
exports.assertPlanningContractArtifact = assertPlanningContractArtifact;
exports.readCurrentContractRevisionReview = readCurrentContractRevisionReview;
exports.captureContractRevisionPreconditions = captureContractRevisionPreconditions;
exports.cloneContractRevisionCheckpoint = cloneContractRevisionCheckpoint;
exports.cloneManifestEntry = cloneManifestEntry;
exports.cloneContractRevisionResult = cloneContractRevisionResult;
exports.defaultContractRevisionImpactBudget = defaultContractRevisionImpactBudget;
// Lifecycle run-context contracts, capture, inspection, and persistence orchestration.
const node_crypto_1 = require("node:crypto");
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const config_1 = require("../config");
const mutation_preconditions_1 = require("../filesystem/mutation-preconditions");
const repository_transaction_1 = require("../filesystem/repository-transaction");
const paths_1 = require("../paths");
const canonical_write_target_1 = require("../paths/canonical-write-target");
const milestone_generation_1 = require("../planning/milestone-generation");
const artifact_policy_projection_1 = require("../planning/artifact-policy-projection");
const task_readiness_review_1 = require("../planning/task-readiness-review");
const task_lifecycle_1 = require("../planning/task-lifecycle");
const task_lifecycle_timestamps_1 = require("../planning/task-lifecycle-timestamps");
const contract_impact_1 = require("./contract-impact");
const context_capture_1 = require("./context-capture");
const context_inspection_1 = require("./context-inspection");
const evidence_store_1 = require("./evidence-store");
const context_storage_1 = require("./context-storage");
function previewLifecycleRunContractRevisionSync(request) {
    const repositoryRoot = (0, context_storage_1.canonicalRoot)(request.repositoryRoot);
    const loaded = (0, context_inspection_1.readManifest)(repositoryRoot, request.runDirectory);
    const manifest = loaded.manifest;
    const recordedBy = (0, context_storage_1.requireBoundedText)(request.recordedBy, 'Contract revision actor');
    const recordedAt = (0, context_storage_1.requireTimestamp)(request.recordedAt, 'Contract revision time');
    const reason = (0, context_storage_1.requireBoundedText)(request.reason, 'Contract revision reason');
    const rollbackGate = parseContractRevisionRollbackGate(request.rollbackGate);
    const selectedArtifactPath = (0, paths_1.parseRepositoryRelativePath)(request.activeArtifactPath).normalizedPath;
    const inspection = (0, context_inspection_1.inspectLifecycleRunContext)({
        repositoryRoot,
        runDirectory: request.runDirectory,
        selectedArtifactPath,
    });
    if (manifest.lifecycleProfile !== 'full-cycle-strict') {
        throw new context_capture_1.LifecycleRunContractRevisionError('unsupported-profile', 'Contract revision is reserved for the full-cycle-strict lifecycle profile.');
    }
    if (inspection.conflict !== null || selectedArtifactPath !== manifest.activeArtifactPath) {
        throw new context_capture_1.LifecycleRunContractRevisionError('artifact-conflict', `Selected active artifact '${selectedArtifactPath}' does not match the run binding '${manifest.activeArtifactPath}'.`);
    }
    const phase = (0, context_storage_1.readBoundedRepositoryFile)(repositoryRoot, manifest.phasePath, 'Current selected phase');
    const activeArtifact = (0, context_storage_1.readBoundedRepositoryFile)(repositoryRoot, selectedArtifactPath, 'Current active planning artifact');
    const phaseText = node_fs_1.default.readFileSync(phase.absolutePath, 'utf8');
    const activeArtifactText = phase.absolutePath === activeArtifact.absolutePath
        ? phaseText
        : node_fs_1.default.readFileSync(activeArtifact.absolutePath, 'utf8');
    const phasePolicy = (0, artifact_policy_projection_1.projectArtifactPolicy)(phaseText);
    const activeArtifactPolicy = (0, artifact_policy_projection_1.projectArtifactPolicy)(activeArtifactText);
    const directTaskAnchor = phase.relativePath === activeArtifact.relativePath &&
        phasePolicy.artifactType === 'task_definition' &&
        phasePolicy.topology?.variant === 'direct' &&
        (phasePolicy.topology.workflowLevel === 'basic' || phasePolicy.topology.workflowLevel === 'structured');
    assertPlanningContractArtifact(repositoryRoot, phase.relativePath, directTaskAnchor ? 'task_definition' : 'phase_overview');
    assertPlanningContractArtifact(repositoryRoot, activeArtifact.relativePath);
    const review = readCurrentContractRevisionReview({
        repositoryRoot,
        reviewResultPath: request.reviewResultPath,
        phasePath: phase.relativePath,
        phaseHash: phase.hash,
        metadataPosture: manifest.metadataPosture,
        authority: directTaskAnchor ? 'direct-task' : 'phase',
    });
    const impactBudget = request.impactBudget ?? defaultContractRevisionImpactBudget();
    const historicalTaskHash = manifest.activeArtifactHash === activeArtifact.hash &&
        activeArtifactPolicy.artifactType === 'task_definition' &&
        rollbackGate === 'task-readiness'
        ? resolveAttemptBoundTaskPredecessorHash({
            repositoryRoot,
            manifest,
            taskPath: activeArtifact.relativePath,
            taskText: activeArtifactText,
        })
        : null;
    const latestCheckpoint = manifest.contractRevisions.at(-1) ?? null;
    const latestCheckpointAlreadyBindsTask = historicalTaskHash !== null &&
        latestCheckpoint !== null &&
        latestCheckpoint.rollbackGate === 'task-readiness' &&
        latestCheckpoint.oldActiveArtifactPath === activeArtifact.relativePath &&
        latestCheckpoint.oldActiveArtifactHash === historicalTaskHash &&
        latestCheckpoint.newActiveArtifactPath === activeArtifact.relativePath &&
        latestCheckpoint.newActiveArtifactHash === activeArtifact.hash;
    const oldActiveArtifactHash = manifest.activeArtifactHash !== activeArtifact.hash ||
        historicalTaskHash === null ||
        latestCheckpointAlreadyBindsTask
        ? manifest.activeArtifactHash
        : historicalTaskHash;
    const replayCheckpoint = [...manifest.contractRevisions]
        .reverse()
        .find((checkpoint) => checkpoint.recordedBy === recordedBy &&
        checkpoint.recordedAt === recordedAt &&
        checkpoint.reason === reason &&
        checkpoint.rollbackGate === rollbackGate &&
        checkpoint.reviewReceiptId === review.receiptId &&
        checkpoint.reviewSourcePath === review.source.relativePath &&
        checkpoint.reviewSourceHash === review.source.hash &&
        checkpoint.newPhaseHash === phase.hash &&
        (historicalTaskHash === null || checkpoint.oldActiveArtifactHash === historicalTaskHash) &&
        checkpoint.newActiveArtifactPath === activeArtifact.relativePath &&
        checkpoint.newActiveArtifactHash === activeArtifact.hash);
    if (replayCheckpoint !== undefined &&
        manifest.phaseHash === phase.hash &&
        manifest.activeArtifactPath === activeArtifact.relativePath &&
        manifest.activeArtifactHash === activeArtifact.hash &&
        manifest.activeGate === rollbackGate) {
        const replayEntry = manifest.entries.find((entry) => entry.entryId === replayCheckpoint.reviewEntryId);
        if (replayEntry === undefined) {
            throw new context_capture_1.LifecycleRunContractRevisionError('replay-invalid', 'The matching contract revision checkpoint does not reference an indexed review entry.');
        }
        const replayImpact = (0, contract_impact_1.computeLifecycleContractRevisionImpact)({
            repositoryRoot,
            manifest,
            invalidatedEntryIds: replayCheckpoint.invalidatedEntryIds,
        });
        if (replayCheckpoint.impactDigest !== undefined && replayCheckpoint.impactDigest !== replayImpact.impactDigest) {
            throw new context_capture_1.LifecycleRunContractRevisionError('impact-input-stale', 'The current contract-impact inputs no longer match the recorded checkpoint impact digest.');
        }
        const replayImpactBudget = (0, contract_impact_1.assessLifecycleContractRevisionImpactBudget)({
            impact: replayImpact,
            budget: impactBudget,
        });
        const replayImpactAuthorization = (0, contract_impact_1.createLifecycleContractRevisionImpactAcknowledgement)({
            runId: manifest.runId,
            oldPhaseHash: replayCheckpoint.oldPhaseHash,
            newPhaseHash: replayCheckpoint.newPhaseHash,
            oldActiveArtifactHash: replayCheckpoint.oldActiveArtifactHash,
            newActiveArtifactHash: replayCheckpoint.newActiveArtifactHash,
            reviewReceiptId: replayCheckpoint.reviewReceiptId,
            impactDigest: replayImpact.impactDigest,
            impactBudget,
            actor: recordedBy,
            recordedAt,
            required: replayImpactBudget.overBudget,
            providedAcknowledgement: request.impactAcknowledgement,
        });
        if (replayCheckpoint.impactAcknowledgementId !== undefined &&
            replayCheckpoint.impactAcknowledgementId !==
                (replayImpactAuthorization.required ? replayImpactAuthorization.acknowledgementId : null)) {
            throw new context_capture_1.LifecycleRunContractRevisionError('impact-input-stale', 'The current impact authorization inputs no longer match the recorded checkpoint.');
        }
        return {
            runId: manifest.runId,
            runDirectory: manifest.runDirectory,
            manifestPath: loaded.manifestPath,
            checkpoint: cloneContractRevisionCheckpoint(replayCheckpoint),
            reviewEntry: cloneManifestEntry(replayEntry),
            impact: replayImpact,
            impactBudget: replayImpactBudget,
            impactAuthorization: replayImpactAuthorization,
            manifestRevision: loaded.manifestHash,
            nextManifestRevision: loaded.manifestHash,
            idempotent: true,
            intendedPaths: [replayCheckpoint.reviewEvidencePath, loaded.manifestPath].sort(),
            changedPaths: [],
            expected: [],
            writeOutcome: 'no-write',
            transactionId: null,
            conflicts: [],
            recoveryPath: null,
            failure: null,
        };
    }
    if (manifest.entries.length >= context_capture_1.MAX_ENTRIES) {
        throw new context_capture_1.LifecycleRunContractRevisionError('entry-bound', `Lifecycle run contexts may contain at most ${context_capture_1.MAX_ENTRIES} entries.`);
    }
    if (manifest.contractRevisions.length >= context_capture_1.MAX_CONTRACT_REVISIONS) {
        throw new context_capture_1.LifecycleRunContractRevisionError('checkpoint-bound', `Lifecycle runs may contain at most ${context_capture_1.MAX_CONTRACT_REVISIONS} contract revision checkpoints.`);
    }
    const allowedUnexpected = new Set(inspection.structuredFiles.unexpected.filter((candidate) => candidate === review.source.relativePath));
    const unrelatedUnexpected = inspection.structuredFiles.unexpected.filter((candidate) => !allowedUnexpected.has(candidate));
    if (unrelatedUnexpected.length > 0) {
        throw new context_capture_1.LifecycleRunContractRevisionError('manifest-incomplete', `Contract revision found unrelated unindexed structured evidence: ${unrelatedUnexpected.join(', ')}.`);
    }
    const allowedStaleReasons = new Set([
        `phase-changed:${manifest.phasePath}`,
        `active artifact-changed:${manifest.activeArtifactPath}`,
    ]);
    const unrelatedStaleReasons = inspection.staleReasons.filter((candidate) => !allowedStaleReasons.has(candidate));
    if (unrelatedStaleReasons.length > 0) {
        throw new context_capture_1.LifecycleRunContractRevisionError('unbounded-stale-state', `Contract revision may not repair unrelated stale state: ${unrelatedStaleReasons.join(', ')}.`);
    }
    const phaseChanged = phase.hash !== manifest.phaseHash;
    const activeArtifactChanged = activeArtifact.hash !== oldActiveArtifactHash;
    if (!phaseChanged && !activeArtifactChanged) {
        throw new context_capture_1.LifecycleRunContractRevisionError('revision-not-required', 'The selected phase and active artifact already match the current run bindings.');
    }
    const lastRollbackSequence = [...manifest.entries].reverse().find((entry) => entry.gate === rollbackGate)?.sequence ?? null;
    const invalidatedEntryIds = manifest.entries
        .filter((entry) => {
        const revisionChanged = phaseChanged ||
            (entry.artifactPath === manifest.phasePath && entry.artifactHash !== phase.hash) ||
            (entry.artifactPath === manifest.activeArtifactPath && entry.artifactHash !== activeArtifact.hash);
        const afterRollbackBoundary = lastRollbackSequence === null ? true : entry.sequence > lastRollbackSequence;
        return revisionChanged || afterRollbackBoundary;
    })
        .map((entry) => entry.entryId)
        .sort();
    const impact = (0, contract_impact_1.computeLifecycleContractRevisionImpact)({
        repositoryRoot,
        manifest,
        invalidatedEntryIds,
    });
    const budgetAssessment = (0, contract_impact_1.assessLifecycleContractRevisionImpactBudget)({
        impact,
        budget: impactBudget,
    });
    const impactAuthorization = (0, contract_impact_1.createLifecycleContractRevisionImpactAcknowledgement)({
        runId: manifest.runId,
        oldPhaseHash: manifest.phaseHash,
        newPhaseHash: phase.hash,
        oldActiveArtifactHash,
        newActiveArtifactHash: activeArtifact.hash,
        reviewReceiptId: review.receiptId,
        impactDigest: impact.impactDigest,
        impactBudget,
        actor: recordedBy,
        recordedAt,
        required: budgetAssessment.overBudget,
        providedAcknowledgement: request.impactAcknowledgement,
    });
    const sequence = manifest.nextSequence;
    const sequenceLabel = String(sequence).padStart(4, '0');
    const evidencePath = node_path_1.default.posix.join(manifest.runDirectory, 'evidence', `${sequenceLabel}-${(0, context_storage_1.slug)(rollbackGate)}-${(0, context_storage_1.slug)(review.commandIdentity)}-ok.json`);
    const reviewEntryId = `lifecycle-entry-${sequenceLabel}-${(0, context_storage_1.sha256)(Buffer.from([
        manifest.runId,
        String(sequence),
        review.commandIdentity,
        review.artifactPath,
        rollbackGate,
        'ok',
    ].join('\u0000'))).slice(7, 23)}`;
    const reviewEntry = {
        schemaVersion: 1,
        entryId: reviewEntryId,
        sequence,
        commandIdentity: review.commandIdentity,
        artifactPath: review.artifactPath,
        artifactHash: review.artifactHash,
        gate: rollbackGate,
        status: 'ok',
        writeOutcome: 'complete',
        receiptIds: (0, context_storage_1.normalizeReceiptIds)([review.receiptId, ...(0, context_storage_1.collectReceiptIds)(review.envelope)]),
        supersedesEntryId: null,
        evidencePath,
        evidenceHash: (0, context_storage_1.sha256)(review.bytes),
        evidenceBytes: review.bytes.byteLength,
        evidenceKind: 'structured-success',
        errorCode: null,
        recordedAt,
        ...(review.source.relativePath === evidencePath ? {} : { sourceResultPath: review.source.relativePath }),
    };
    const checkpointWithoutId = {
        schemaVersion: 1,
        recordedBy,
        recordedAt,
        reason,
        rollbackGate,
        reviewReceiptId: review.receiptId,
        reviewSourcePath: review.source.relativePath,
        reviewSourceHash: review.source.hash,
        reviewEvidencePath: evidencePath,
        reviewEntryId,
        oldPhaseHash: manifest.phaseHash,
        newPhaseHash: phase.hash,
        oldActiveArtifactPath: manifest.activeArtifactPath,
        oldActiveArtifactHash,
        newActiveArtifactPath: activeArtifact.relativePath,
        newActiveArtifactHash: activeArtifact.hash,
        invalidatedEntryIds,
        impactDigest: impact.impactDigest,
        impactAcknowledgementId: impactAuthorization.required ? impactAuthorization.acknowledgementId : null,
    };
    const checkpoint = {
        ...checkpointWithoutId,
        checkpointId: `lifecycle-contract-revision-${(0, context_storage_1.sha256)(Buffer.from(JSON.stringify(checkpointWithoutId))).slice(7, 31)}`,
    };
    const nextManifest = {
        ...manifest,
        phaseHash: phase.hash,
        activeArtifactPath: activeArtifact.relativePath,
        activeArtifactHash: activeArtifact.hash,
        activeGate: rollbackGate,
        updatedAt: recordedAt,
        nextSequence: sequence + 1,
        entries: [...manifest.entries, reviewEntry],
        contractRevisions: [...manifest.contractRevisions, checkpoint],
    };
    const manifestBytes = (0, context_storage_1.jsonBytes)(nextManifest, context_capture_1.MAX_LIFECYCLE_RUN_MANIFEST_BYTES);
    const preconditions = captureContractRevisionPreconditions({
        repositoryRoot,
        manifestPath: loaded.manifestPath,
        evidencePath,
        sourcePath: review.source.relativePath,
        phasePath: phase.relativePath,
        activeArtifactPath: activeArtifact.relativePath,
        indexedEvidencePaths: manifest.entries.map((entry) => entry.evidencePath),
    });
    const writes = [
        { path: evidencePath, contents: review.bytes },
        { path: loaded.manifestPath, contents: manifestBytes },
    ].sort((left, right) => left.path.localeCompare(right.path));
    const snapshot = {
        runId: manifest.runId,
        runDirectory: manifest.runDirectory,
        manifestPath: loaded.manifestPath,
        checkpoint: cloneContractRevisionCheckpoint(checkpoint),
        reviewEntry: cloneManifestEntry(reviewEntry),
        impact,
        impactBudget: budgetAssessment,
        impactAuthorization,
        manifestRevision: loaded.manifestHash,
        nextManifestRevision: (0, context_storage_1.sha256)(manifestBytes),
        idempotent: false,
        intendedPaths: writes.map((write) => write.path),
        changedPaths: [],
        expected: preconditions.map(mutation_preconditions_1.serializeMutationPrecondition),
        writeOutcome: 'previewed',
        transactionId: null,
        conflicts: [],
        recoveryPath: null,
        failure: null,
    };
    if (!impactAuthorization.satisfied) {
        return {
            ...snapshot,
            intendedPaths: [],
            expected: [],
            writeOutcome: 'no-write',
        };
    }
    context_capture_1.contractRevisionPlans.set(snapshot, {
        repositoryRoot,
        writes,
        preconditions,
        snapshot: cloneContractRevisionResult(snapshot),
    });
    return snapshot;
}
function applyLifecycleRunContractRevisionSync(preview, options = {}) {
    if (preview.writeOutcome === 'no-write' && (preview.idempotent || !preview.impactAuthorization.satisfied)) {
        return cloneContractRevisionResult(preview);
    }
    const plan = context_capture_1.contractRevisionPlans.get(preview);
    if (plan === undefined) {
        throw new context_capture_1.LifecycleRunContractRevisionError('stale-preview', 'Contract revision apply requires the original in-process preview. Refresh the preview.');
    }
    (0, task_lifecycle_timestamps_1.revalidateObservedLifecycleTimestamp)(plan.snapshot.checkpoint.recordedAt, 'recorded_at', 'Contract revision time');
    const transaction = (0, repository_transaction_1.executeRepositoryTransactionSync)(plan.repositoryRoot, { writes: plan.writes, preconditions: plan.preconditions }, options.transaction);
    return {
        ...cloneContractRevisionResult(plan.snapshot),
        changedPaths: transaction.entries.slice(0, transaction.canonicalWrites).map((entry) => entry.path),
        writeOutcome: transaction.outcome,
        transactionId: transaction.transactionId,
        conflicts: transaction.conflicts,
        recoveryPath: transaction.outcome === 'incomplete' ? transaction.transactionPath : null,
        failure: transaction.failure ?? (transaction.cleanupErrors.length > 0 ? transaction.cleanupErrors.join(' ') : null),
    };
}
function parseContractRevisionRollbackGate(value) {
    const normalized = value.trim();
    if (!context_capture_1.LIFECYCLE_CONTRACT_REVISION_ROLLBACK_GATES.includes(normalized)) {
        throw new context_capture_1.LifecycleRunContractRevisionError('unsupported-rollback-gate', `Contract revision rollback gate must be one of: ${context_capture_1.LIFECYCLE_CONTRACT_REVISION_ROLLBACK_GATES.join(', ')}.`);
    }
    return normalized;
}
function assertPlanningContractArtifact(repositoryRoot, artifactPath, expectedType) {
    if (!artifactPath.startsWith('.day-shift/planning/')) {
        throw new context_capture_1.LifecycleRunContractRevisionError('unbounded-artifact', `Contract revision artifact '${artifactPath}' is outside the canonical planning tree.`);
    }
    const artifact = (0, context_storage_1.readBoundedRepositoryFile)(repositoryRoot, artifactPath, 'Planning contract artifact');
    const artifactType = (0, context_storage_1.readFrontMatterScalar)(node_fs_1.default.readFileSync(artifact.absolutePath, 'utf8'), 'artifact_type');
    const allowedTypes = new Set([
        'phase_overview',
        'milestone_overview',
        'task_definition',
        'implementation_summary',
        'reconciliation',
    ]);
    if (artifactType === null ||
        !allowedTypes.has(artifactType) ||
        (expectedType !== undefined && artifactType !== expectedType)) {
        throw new context_capture_1.LifecycleRunContractRevisionError('unbounded-artifact', expectedType === undefined
            ? `Contract revision requires a canonical planning lifecycle artifact; '${artifactPath}' declares '${artifactType ?? 'no artifact type'}'.`
            : `Contract revision phase '${artifactPath}' must declare artifact_type: ${expectedType}.`);
    }
}
function resolveAttemptBoundTaskPredecessorHash(options) {
    const taskSegments = (0, paths_1.parseRepositoryRelativePath)(options.taskPath).segments;
    if (taskSegments.at(-1) !== 'task-definition.md')
        return null;
    const summaryPath = [...taskSegments.slice(0, -1), 'implementation-summary.md'].join('/');
    let summary;
    try {
        summary = (0, context_storage_1.readBoundedRepositoryFile)(options.repositoryRoot, summaryPath, 'Current implementation summary');
    }
    catch {
        return null;
    }
    const projection = (0, task_lifecycle_1.projectTaskLifecyclePair)({
        taskDefinition: options.taskText,
        implementationSummary: node_fs_1.default.readFileSync(summary.absolutePath, 'utf8'),
    });
    const authorization = projection.task.readinessAuthorization;
    const currentAttempt = projection.summary?.currentAttempt ?? null;
    if (!authorization.complete ||
        !authorization.valid ||
        authorization.applicable ||
        currentAttempt === null ||
        currentAttempt.attemptId === null ||
        currentAttempt.closedAt !== null ||
        currentAttempt.reviewDisposition !== 'pending' ||
        currentAttempt.readinessReviewId === null ||
        currentAttempt.readinessReviewId !== authorization.id)
        return null;
    const candidates = [...options.manifest.entries]
        .filter((entry) => entry.status === 'ok' &&
        entry.artifactPath === options.taskPath &&
        entry.artifactHash !== options.manifest.activeArtifactHash)
        .sort((left, right) => right.sequence - left.sequence)
        .filter((entry) => lifecycleEntryBindsAttempt(options, entry, {
        attemptId: currentAttempt.attemptId,
        readinessReviewId: currentAttempt.readinessReviewId,
    }));
    const predecessor = candidates.at(0) ?? null;
    if (predecessor === null) {
        throw new context_capture_1.LifecycleRunContractRevisionError('task-checkpoint-ineligible', `The selected task has a stale open attempt, but indexed lifecycle evidence does not prove its predecessor task revision for '${currentAttempt.attemptId}'.`);
    }
    return predecessor.artifactHash;
}
function lifecycleEntryBindsAttempt(options, entry, lineage) {
    try {
        const evidence = (0, evidence_store_1.readLifecycleEvidenceBytesSync)({
            repositoryRoot: options.repositoryRoot,
            runDirectory: options.manifest.runDirectory,
            entry,
            maximumBytes: context_capture_1.MAX_LIFECYCLE_RUN_RESULT_BYTES,
        });
        const document = (0, context_storage_1.parseObjectJson)(evidence.bytes, `Lifecycle entry '${entry.entryId}'`);
        const envelope = (0, context_storage_1.asRecord)(document.result) ?? document;
        const data = (0, context_storage_1.asRecord)(envelope.data);
        if (data === null)
            return false;
        const records = [
            data,
            (0, context_storage_1.asRecord)(data.attempt),
            (0, context_storage_1.asRecord)(data.baseline),
            (0, context_storage_1.asRecord)(data.validation),
            (0, context_storage_1.asRecord)(data.result),
        ].filter((value) => value !== null);
        const attemptMatches = records.some((record) => record.attemptId === lineage.attemptId ||
            record.taskCycleId === lineage.attemptId ||
            record.priorAttemptId === lineage.attemptId);
        if (!attemptMatches)
            return false;
        if (entry.commandIdentity !== 'task attempt-open')
            return true;
        return records.some((record) => record.readinessReviewId === lineage.readinessReviewId ||
            record.checkpointId === lineage.readinessReviewId);
    }
    catch {
        return false;
    }
}
function readCurrentContractRevisionReview(options) {
    try {
        const source = (0, context_storage_1.readBoundedRepositoryFile)(options.repositoryRoot, options.reviewResultPath, options.authority === 'phase' ? 'Current phase review result' : 'Current task readiness review result', context_capture_1.MAX_LIFECYCLE_RUN_RESULT_BYTES);
        const bytes = node_fs_1.default.readFileSync(source.absolutePath);
        const document = (0, context_storage_1.parseObjectJson)(bytes, options.authority === 'phase' ? 'Current phase review result' : 'Current task readiness review result');
        const envelope = (0, context_storage_1.asRecord)(document.result) ?? (document.status === 'ok' || document.status === 'error' ? document : null);
        const data = (0, context_storage_1.asRecord)(envelope?.data);
        if (options.authority === 'direct-task') {
            return readCurrentDirectTaskReview({ ...options, source, bytes, envelope, data });
        }
        if (envelope?.status !== 'ok' ||
            envelope.command !== 'phase review' ||
            data === null ||
            data.readOnly !== true ||
            data.writeCapable !== false ||
            data.phaseOverviewPath !== options.phasePath) {
            throw new context_capture_1.LifecycleRunContractRevisionError('review-invalid', 'Contract revision requires one successful read-only phase review for the exact current phase.');
        }
        if (data.reviewMode === 'readiness') {
            const receipt = (0, milestone_generation_1.assertCurrentPhaseAuthoringReviewResult)(options.repositoryRoot, {
                phaseOverviewPath: options.phasePath,
                phaseReviewResult: envelope,
            });
            if (receipt.phaseRevision !== options.phaseHash) {
                throw new context_capture_1.LifecycleRunContractRevisionError('review-stale', 'The supplied phase authoring receipt does not bind the current phase revision.');
            }
            return {
                source,
                bytes,
                envelope,
                receiptId: receipt.receiptId,
                commandIdentity: 'phase review',
                artifactPath: options.phasePath,
                artifactHash: options.phaseHash,
            };
        }
        const receipt = (0, context_storage_1.asRecord)(data.phaseReviewReceipt);
        const blockingIssues = Array.isArray(data.blockingIssues) ? data.blockingIssues : null;
        if (data.reviewMode !== 'evidence' ||
            data.metadataPosture !== options.metadataPosture ||
            blockingIssues === null ||
            blockingIssues.length !== 0 ||
            receipt === null ||
            receipt.reviewMode !== 'evidence' ||
            receipt.metadataPosture !== options.metadataPosture ||
            receipt.phaseOverviewPath !== options.phasePath ||
            receipt.complete !== true ||
            receipt.blockerCount !== 0 ||
            typeof receipt.reviewId !== 'string') {
            throw new context_capture_1.LifecycleRunContractRevisionError('review-invalid', 'Contract revision requires one complete zero-blocker current phase review with the run metadata posture.');
        }
        const receiptWithoutId = { ...receipt };
        delete receiptWithoutId.reviewId;
        const expectedReviewId = `phase-review-${(0, node_crypto_1.createHash)('sha256')
            .update(JSON.stringify(receiptWithoutId))
            .digest('hex')
            .slice(0, 24)}`;
        if (expectedReviewId !== receipt.reviewId) {
            throw new context_capture_1.LifecycleRunContractRevisionError('review-invalid', 'The supplied phase review receipt identity does not match its canonical contents.');
        }
        const transitions = Array.isArray(receipt.metadataStatusTransitions) ? receipt.metadataStatusTransitions : [];
        const transitionPaths = new Set();
        let currentPhaseTransition = false;
        for (const value of transitions) {
            const transition = (0, context_storage_1.asRecord)(value);
            const artifactPath = typeof transition?.artifactPath === 'string' ? transition.artifactPath : null;
            const artifactRevision = typeof transition?.artifactRevision === 'string' ? transition.artifactRevision : null;
            if (artifactPath === null ||
                artifactRevision === null ||
                transition?.eligible !== true ||
                transitionPaths.has(artifactPath) ||
                !(0, context_storage_1.currentRevisionMatches)(options.repositoryRoot, artifactPath, artifactRevision)) {
                throw new context_capture_1.LifecycleRunContractRevisionError('review-stale', 'The supplied phase review contains a missing, duplicate, ineligible, or stale artifact transition.');
            }
            transitionPaths.add(artifactPath);
            if (artifactPath === options.phasePath && artifactRevision === options.phaseHash) {
                currentPhaseTransition = true;
            }
        }
        if (!currentPhaseTransition) {
            throw new context_capture_1.LifecycleRunContractRevisionError('review-stale', 'The supplied phase review does not bind the exact current phase revision.');
        }
        const reconciliations = Array.isArray(receipt.reconciliationEvidence) ? receipt.reconciliationEvidence : [];
        const reconciledMilestones = new Set();
        for (const value of reconciliations) {
            const reconciliation = (0, context_storage_1.asRecord)(value);
            const milestonePath = typeof reconciliation?.milestoneOverviewPath === 'string' ? reconciliation.milestoneOverviewPath : null;
            const reconciliationPath = typeof reconciliation?.reconciliationPath === 'string' ? reconciliation.reconciliationPath : null;
            const reconciliationRevision = typeof reconciliation?.reconciliationRevision === 'string' ? reconciliation.reconciliationRevision : null;
            if (milestonePath === null ||
                reconciliationPath === null ||
                reconciliationRevision === null ||
                reconciliation?.completedNonPlaceholder !== true ||
                reconciledMilestones.has(milestonePath) ||
                !transitionPaths.has(milestonePath) ||
                !(0, context_storage_1.currentRevisionMatches)(options.repositoryRoot, reconciliationPath, reconciliationRevision)) {
                throw new context_capture_1.LifecycleRunContractRevisionError('review-stale', 'The supplied phase review contains incomplete or stale reconciliation evidence.');
            }
            reconciledMilestones.add(milestonePath);
        }
        if ([...transitionPaths].some((artifactPath) => artifactPath !== options.phasePath && !reconciledMilestones.has(artifactPath))) {
            throw new context_capture_1.LifecycleRunContractRevisionError('review-invalid', 'The supplied phase review does not reconcile every reviewed milestone.');
        }
        return {
            source,
            bytes,
            envelope,
            receiptId: receipt.reviewId,
            commandIdentity: 'phase review',
            artifactPath: options.phasePath,
            artifactHash: options.phaseHash,
        };
    }
    catch (error) {
        if (error instanceof context_capture_1.LifecycleRunContractRevisionError)
            throw error;
        throw new context_capture_1.LifecycleRunContractRevisionError('review-invalid', error instanceof Error
            ? `The supplied contract-revision review is invalid: ${error.message}`
            : 'The supplied contract-revision review is invalid.');
    }
}
function readCurrentDirectTaskReview(options) {
    const review = (0, context_storage_1.asRecord)(options.data?.reviewResult);
    const blockingIssues = Array.isArray(review?.blockingIssues) ? review.blockingIssues : null;
    const findings = Array.isArray(review?.findings) ? review.findings : null;
    const topology = (0, context_storage_1.asRecord)(review?.workflowTopology);
    const contractImpact = (0, context_storage_1.asRecord)(review?.contractImpact);
    const currentAttemptState = (0, context_storage_1.asRecord)(review?.currentAttemptState);
    const nextAction = (0, context_storage_1.asRecord)(review?.nextAction);
    const errorFindings = findings?.filter((value) => (0, context_storage_1.asRecord)(value)?.severity === 'error') ?? null;
    const currentTaskRevision = options.phaseHash.replace(/^sha256:/, '');
    const cleanReadiness = review?.readinessStatus === 'ready to implement' &&
        review.handoffStatus === 'ready for implementation handoff' &&
        blockingIssues?.length === 0 &&
        errorFindings?.length === 0;
    const recoveryBlocker = 'Stored readiness authorization is stale and the current attempt contains lifecycle evidence that cannot be superseded automatically.';
    const supersessionBlocker = 'Stored readiness authorization is stale after a task contract revision; the open baseline-only attempt must be superseded before fresh authorization.';
    const evidenceRecoveryReadiness = review?.readinessStatus === 'blocked' &&
        review.handoffStatus === 'blocked' &&
        currentAttemptState?.state === 'open-evidence-bearing' &&
        (nextAction?.reasonCode === 'stale_readiness_authorization' ||
            nextAction?.reasonCode === 'contract_revision_requires_checkpoint_adoption' ||
            nextAction?.reasonCode === 'contract_revision_requires_evidence_recovery') &&
        blockingIssues?.length === 1 &&
        blockingIssues[0] === recoveryBlocker &&
        Array.isArray(review.missingEvidence) &&
        review.missingEvidence.length === 1 &&
        review.missingEvidence[0] === recoveryBlocker &&
        errorFindings?.length === 1 &&
        (0, context_storage_1.asRecord)(errorFindings[0])?.code === 'TASK_READINESS_MISSING_EVIDENCE' &&
        (0, context_storage_1.asRecord)(errorFindings[0])?.message === recoveryBlocker;
    const baselineSupersessionReadiness = review?.readinessStatus === 'blocked' &&
        review.handoffStatus === 'blocked' &&
        currentAttemptState?.state === 'open-baseline-only' &&
        nextAction?.reasonCode === 'contract_revision_requires_attempt_supersession' &&
        blockingIssues?.length === 1 &&
        blockingIssues[0] === supersessionBlocker &&
        Array.isArray(review.missingEvidence) &&
        review.missingEvidence.length === 1 &&
        review.missingEvidence[0] === supersessionBlocker &&
        errorFindings?.length === 1 &&
        (0, context_storage_1.asRecord)(errorFindings[0])?.code === 'TASK_READINESS_MISSING_EVIDENCE' &&
        (0, context_storage_1.asRecord)(errorFindings[0])?.message === supersessionBlocker;
    const directTaskTopology = topology?.variant === 'direct' &&
        ((topology.workflowLevel === 'basic' &&
            Array.isArray(topology.organizationParents) &&
            topology.organizationParents.length === 0) ||
            (topology.workflowLevel === 'structured' &&
                Array.isArray(topology.organizationParents) &&
                topology.organizationParents.length === 1 &&
                topology.organizationParents[0] === 'work_overview'));
    if (options.envelope?.status !== 'ok' ||
        options.envelope.command !== 'task readiness-review' ||
        options.data === null ||
        options.data.readOnly !== true ||
        options.data.writeCapable !== false ||
        review === null ||
        review.protocolVersion !== 1 ||
        review.readOnly !== true ||
        review.taskDefinitionPath !== options.phasePath ||
        review.taskRevision !== currentTaskRevision ||
        blockingIssues === null ||
        findings === null ||
        (!cleanReadiness && !evidenceRecoveryReadiness && !baselineSupersessionReadiness) ||
        !directTaskTopology ||
        contractImpact?.requiredComplete !== true ||
        typeof review.readinessReviewId !== 'string' ||
        typeof review.reviewedBy !== 'string' ||
        typeof review.reviewedAt !== 'string' ||
        options.data.readinessReviewId !== review.readinessReviewId ||
        options.data.taskRevision !== review.taskRevision) {
        throw new context_capture_1.LifecycleRunContractRevisionError('review-invalid', 'A direct Basic or Structured contract revision requires one complete current task readiness review with no unrelated blocker; only the exact stale-attempt supersession or evidence-recovery blocker is admissible.');
    }
    const { readinessReviewId: _readinessReviewId, ...reviewWithoutIdentity } = review;
    const expectedReviewId = (0, task_readiness_review_1.computeTaskReadinessReviewId)(reviewWithoutIdentity);
    if (expectedReviewId !== review.readinessReviewId) {
        throw new context_capture_1.LifecycleRunContractRevisionError('review-invalid', 'The supplied task readiness review identity does not match its complete evidence.');
    }
    const currentReview = (0, task_readiness_review_1.reviewTaskReadiness)(options.repositoryRoot, {
        taskDefinitionPath: options.phasePath,
        reviewedBy: review.reviewedBy,
        reviewedAt: review.reviewedAt,
    });
    if (currentReview.readinessReviewId !== review.readinessReviewId) {
        throw new context_capture_1.LifecycleRunContractRevisionError('review-stale', 'The supplied task readiness review does not match the current task pair, dependencies, or readiness evidence.');
    }
    return {
        source: options.source,
        bytes: options.bytes,
        envelope: options.envelope,
        receiptId: review.readinessReviewId,
        commandIdentity: 'task readiness-review',
        artifactPath: options.phasePath,
        artifactHash: options.phaseHash,
    };
}
function captureContractRevisionPreconditions(options) {
    const contentPaths = [
        ...new Set([
            options.manifestPath,
            options.sourcePath,
            options.phasePath,
            options.activeArtifactPath,
            ...options.indexedEvidencePaths,
        ]),
    ].sort((left, right) => left.localeCompare(right));
    if (contentPaths.includes(options.evidencePath)) {
        throw new context_capture_1.LifecycleRunContractRevisionError('review-destination-conflict', 'The supplied review result may not occupy the deterministic indexed evidence destination.');
    }
    const preconditions = contentPaths.map((repositoryPath) => {
        const target = (0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(options.repositoryRoot, repositoryPath);
        return (0, mutation_preconditions_1.captureContentRevisionPreconditionSync)(target);
    });
    const manifestPresence = (0, mutation_preconditions_1.captureDestinationPresencePreconditionSync)((0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(options.repositoryRoot, options.manifestPath));
    if (manifestPresence.expectedPresence !== 'present') {
        throw new context_capture_1.LifecycleRunContractRevisionError('manifest-conflict', `Lifecycle run manifest '${options.manifestPath}' is no longer present.`);
    }
    const evidenceTarget = (0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(options.repositoryRoot, options.evidencePath);
    const evidencePresence = (0, mutation_preconditions_1.captureDestinationPresencePreconditionSync)(evidenceTarget);
    if (evidencePresence.expectedPresence !== 'absent') {
        throw new context_capture_1.LifecycleRunContractRevisionError('evidence-conflict', `Deterministic contract revision evidence path '${options.evidencePath}' already exists.`);
    }
    return [...preconditions, manifestPresence, evidencePresence];
}
function cloneContractRevisionCheckpoint(checkpoint) {
    return {
        ...checkpoint,
        invalidatedEntryIds: [...checkpoint.invalidatedEntryIds],
    };
}
function cloneManifestEntry(entry) {
    return {
        ...entry,
        receiptIds: [...entry.receiptIds],
    };
}
function cloneContractRevisionResult(result) {
    return {
        ...result,
        checkpoint: cloneContractRevisionCheckpoint(result.checkpoint),
        reviewEntry: cloneManifestEntry(result.reviewEntry),
        impact: {
            ...result.impact,
            invalidatedEntryIds: [...result.impact.invalidatedEntryIds],
            counts: { ...result.impact.counts },
            downstreamArtifacts: {
                ...result.impact.downstreamArtifacts,
                relationshipIds: [...result.impact.downstreamArtifacts.relationshipIds],
                paths: [...result.impact.downstreamArtifacts.paths],
                unknownProducerPaths: [...result.impact.downstreamArtifacts.unknownProducerPaths],
                issues: [...result.impact.downstreamArtifacts.issues],
            },
        },
        impactBudget: {
            ...result.impactBudget,
            budget: {
                ...result.impactBudget.budget,
                thresholds: {
                    maxInvalidatedEntries: {
                        ...result.impactBudget.budget.thresholds.maxInvalidatedEntries,
                    },
                    maxEvidenceBytes: {
                        ...result.impactBudget.budget.thresholds.maxEvidenceBytes,
                    },
                },
                precedence: [...result.impactBudget.budget.precedence],
            },
            exceededThresholds: result.impactBudget.exceededThresholds.map((entry) => ({ ...entry })),
        },
        impactAuthorization: {
            ...result.impactAuthorization,
            binding: { ...result.impactAuthorization.binding },
        },
        intendedPaths: [...result.intendedPaths],
        changedPaths: [...result.changedPaths],
        expected: result.expected.map((entry) => ({ ...entry })),
        conflicts: result.conflicts.map((entry) => ({ ...entry })),
    };
}
function defaultContractRevisionImpactBudget() {
    return {
        schemaVersion: 1,
        thresholds: {
            maxInvalidatedEntries: {
                key: 'max_invalidated_entries',
                value: config_1.CONTRACT_REVISION_IMPACT_BUDGET_DEFAULTS.max_invalidated_entries,
                sourceKind: 'defaults',
                sourceDescription: 'Resolved from built-in contract-revision impact-budget defaults.',
            },
            maxEvidenceBytes: {
                key: 'max_evidence_bytes',
                value: config_1.CONTRACT_REVISION_IMPACT_BUDGET_DEFAULTS.max_evidence_bytes,
                sourceKind: 'defaults',
                sourceDescription: 'Resolved from built-in contract-revision impact-budget defaults.',
            },
        },
        precedence: ['defaults', 'repository', 'project', 'explicit'],
    };
}
