"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.LifecycleFlightPlanCompileError = exports.FULL_CYCLE_STRICT_WORKFLOW_PATH = exports.FULL_CYCLE_STRICT_PROFILE = exports.LIFECYCLE_FLIGHT_PLAN_SCHEMA_VERSION = void 0;
exports.compileLifecycleFlightPlan = compileLifecycleFlightPlan;
exports.projectCompactLifecycleFlightPlan = projectCompactLifecycleFlightPlan;
exports.renderLifecycleFlightPlan = renderLifecycleFlightPlan;
const node_crypto_1 = require("node:crypto");
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const command_capabilities_1 = require("../output/command-capabilities");
const sandbox_contract_1 = require("../paths/sandbox-contract");
const planning_artifact_document_1 = require("./planning-artifact-document");
exports.LIFECYCLE_FLIGHT_PLAN_SCHEMA_VERSION = 1;
exports.FULL_CYCLE_STRICT_PROFILE = "full-cycle-strict";
exports.FULL_CYCLE_STRICT_WORKFLOW_PATH = ".day-shift/workflows/phase.agent-lifecycle-guide.md";
class LifecycleFlightPlanCompileError extends Error {
    code;
    findings;
    constructor(code, message, findings) {
        super(message);
        this.name = "LifecycleFlightPlanCompileError";
        this.code = code;
        this.findings = findings;
    }
}
exports.LifecycleFlightPlanCompileError = LifecycleFlightPlanCompileError;
const PROFILE_GATE_DEFINITIONS = Object.freeze([
    gate("artifact-selection", 1, "workflow explain", "Canonical selected-artifact identity and profile applicability.", "The selected canonical phase overview is present and classified.", ["selected artifact"], { intrinsic: "selected-artifact" }),
    gate("run-open", 1, "resume run open", "A bounded run-context manifest bound to the selected phase revision.", "One fresh run manifest exists without granting lifecycle authority.", ["selected phase overview", "sandbox/run-<run-id>"], {
        intrinsic: "open-run",
        conditionalInputs: [
            condition("runDirectory", "A lifecycle run is required before gate evidence can be indexed.", "operator-selected repository-local run directory", "runDirectory"),
            condition("actor", "Run creation records the responsible actor.", "current operator identity", "actor"),
            condition("metadataPosture", "The run must freeze either read-only or sync-on-clean-review posture.", "explicit workflow invocation", "metadataPosture"),
            condition("openedAt", "A reusable run may record an explicit opening time.", "current trusted clock", "observedAt"),
            condition("authorization", "Opening a repository-local run manifest is a write and requires separate authority.", "current user authorization", "authorization", "authorized")
        ]
    }),
    gate("phase-authoring-readiness", 2, "phase review", "A current zero-blocker phase authoring receipt covering declared milestone order.", "The current phase revision is handoff-ready before scaffolding.", ["selected phase overview"], {
        manifestGates: ["phase-authoring-review", "phase-readiness"],
        suppliedInputs: { reviewMode: "readiness" },
        conditionalInputs: [
            condition("metadataPosture", "Phase readiness review requires an explicit metadata posture.", "explicit workflow invocation", "metadataPosture"),
            condition("reviewedAt", "Reusable readiness evidence records its observation time.", "current trusted clock", "observedAt")
        ]
    }),
    gate("declared-milestone-scaffold", 3, "milestone new", "A full-set scaffold result covering only declared milestones.", "Every declared milestone pair exists and no undeclared child was created.", ["phase authoring review receipt", "declared milestone set"], {
        manifestGates: ["milestone-scaffold"],
        suppliedInputs: { fullSet: true },
        conditionalInputs: [
            condition("phaseReviewResult", "A material full-set scaffold requires the exact current phase authoring receipt.", "preceding phase-authoring-readiness evidence path", "runDirectory"),
            condition("authorization", "Milestone scaffolding creates canonical artifacts.", "current user authorization", "authorization", "authorized")
        ]
    }),
    gate("phase-link-materialization", 4, "link materialize", "Revision-bound zero-candidate link evidence or an authorized write plus post-write proof.", "Every required overview relationship is local, canonical, and current.", ["selected phase overview"], {
        manifestGates: ["phase-link", "link-materialize", "phase-final-validation"],
        suppliedInputs: { scope: "planning", dryRun: true }
    }),
    gate("ordered-milestone-selection", 5, "planning next-action", "The first declared milestone without completed reconciliation evidence.", "Selection follows declared order and names at most one active milestone.", ["declared milestone order", "current reconciliation state"]),
    gate("prior-reconciliation-input", 6, "planning next-action", "Completed earlier reconciliations projected as active-contract inputs.", "Earlier decisions are reviewed before the active milestone contract changes.", ["earlier completed reconciliations"]),
    gate("active-milestone-contract", 7, "workflow explain", "Current workflow and prompt boundary for the active milestone.", "Only the active milestone contract is eligible for implementation.", ["active milestone overview"]),
    gate("declared-task-scaffold", 8, "task new", "A full-set task scaffold bounded to the active milestone's declarations.", "Only declared task pairs exist under the active milestone.", ["active milestone overview"], {
        suppliedInputs: { fullSet: true },
        conditionalInputs: [
            condition("milestoneOverview", "Task scaffolding requires the selected active milestone.", "ordered-milestone-selection evidence", "runDirectory"),
            condition("authorization", "Task scaffolding creates canonical artifacts.", "current user authorization", "authorization", "authorized")
        ]
    }),
    gate("task-closeout", 8, "task close", "Current completed-and-accepted task pair plus receipt-bound close result.", "Every active-milestone task closes in declared dependency order.", ["selected task definition", "current implementation-summary review receipt"], {
        manifestGates: ["task-closeout"],
        conditionalInputs: [
            condition("taskDefinition", "Close targets the one current declared task.", "active milestone task order", "runDirectory"),
            condition("reviewResult", "Close requires the fresh review receipt that authorizes close.", "current task implementation-summary review evidence", "runDirectory"),
            condition("authorization", "Task close mutates the canonical task pair.", "current user authorization", "authorization", "authorized")
        ]
    }),
    gate("reconciliation-build", 8, "reconciliation build", "A reconciliation body generated from completed task summaries.", "The active milestone reconciliation is concrete and non-placeholder.", ["active milestone overview", "completed task summaries"], {
        manifestGates: ["reconciliation-build"],
        conditionalInputs: [
            condition("milestoneOverview", "Milestone reconciliation requires the active milestone selection.", "ordered-milestone-selection evidence", "runDirectory"),
            condition("authorization", "Reconciliation build writes the canonical reconciliation artifact.", "current user authorization", "authorization", "authorized")
        ]
    }),
    gate("reconciliation-review", 8, "reconciliation review", "A current zero-blocker milestone reconciliation review receipt.", "Acceptance, validation, deviations, and discovered work are reviewed together.", ["active milestone reconciliation"], {
        manifestGates: ["reconciliation-review"],
        conditionalInputs: [
            condition("milestoneOverview", "Review requires the active milestone selection.", "ordered-milestone-selection evidence", "runDirectory")
        ]
    }),
    gate("milestone-terminal-check", 9, "reconciliation review", "Re-opened non-placeholder completed reconciliation evidence.", "The active milestone is terminal before selection advances.", ["active milestone reconciliation"], { manifestGates: ["reconciliation-review"] }),
    gate("advance-declared-milestone", 10, "planning next-action", "Next unreconciled milestone selection or proof that none remains.", "The milestone loop advances only after the prior reconciliation is complete.", ["phase overview", "completed reconciliations"]),
    gate("first-blocker-stop", 11, "resume run status", "Fresh run evidence identifying any first failed, stale, or blocked dependency.", "Execution stops at the first blocker unless a different read-only sweep was explicitly requested.", ["lifecycle run manifest"], {
        conditionalInputs: [condition("runDirectory", "Strict status inspection requires the selected lifecycle run.", "run-open output", "runDirectory")]
    }),
    gate("phase-final-inventory", 12, "planning inventory", "Final planning inventory for the selected phase.", "The final artifact set is complete before phase review.", ["selected phase overview"], { manifestGates: ["phase-final-validation"] }),
    gate("phase-final-gap-report", 12, "planning gap-report", "Final local gap report for the selected phase.", "No unresolved implementation gap is hidden by closeout metadata.", ["selected phase overview"], { manifestGates: ["phase-final-validation"] }),
    gate("phase-final-link", 12, "link materialize", "Final revision-bound link gate.", "The final phase relationship graph is current and clean.", ["selected phase overview"], {
        manifestGates: ["phase-final-validation"],
        suppliedInputs: { scope: "planning", dryRun: true }
    }),
    gate("phase-final-smoke", 12, "validation smoke", "Final planning smoke evidence.", "The selected phase and current descendants pass declared planning checks.", ["selected phase overview"], {
        manifestGates: ["phase-final-validation"],
        suppliedInputs: { scope: "planning" }
    }),
    gate("phase-read-only-review", 13, "phase review", "Final current zero-blocker phase review receipt.", "All milestone reconciliations are complete and the review remains read-only evidence.", ["selected phase overview", "completed milestone reconciliations"], {
        manifestGates: ["phase-review"],
        conditionalInputs: [
            condition("metadataPosture", "Final phase review requires an explicit metadata posture.", "explicit workflow invocation", "metadataPosture"),
            condition("reviewedAt", "Reusable phase review evidence records its observation time.", "current trusted clock", "observedAt")
        ]
    }),
    gate("read-only-review-boundary", 14, "phase review", "The final receipt's explicit no-write boundary and administrative follow-ups.", "Review evidence performs no status synchronization.", ["final phase review receipt"], { manifestGates: ["phase-review"] }),
    gate("optional-metadata-sync", 15, "metadata sync-status-from-review", "An exact dry-run transaction plan and separately authorized apply, when requested.", "Read-only posture skips synchronization; sync posture applies only an exact authorized batch.", ["final phase review receipt"], {
        optionalSync: true,
        suppliedInputs: { dryRun: true },
        conditionalInputs: [
            condition("metadataPosture", "Metadata sync is applicable only under sync-on-clean-review.", "explicit workflow invocation", "metadataPosture", "sync-on-clean-review"),
            condition("reviewResult", "Sync requires the exact current phase review receipt.", "phase-read-only-review evidence", "runDirectory"),
            condition("authorization", "Review never grants phase metadata write authority.", "current user authorization", "authorization", "authorized")
        ]
    }),
    gate("terminal-report", 16, "resume run status", "Final phase status, milestone outcomes, validation, blockers, and discovered-work evidence.", "Reporting occurs after terminal reconciliation evidence or identifies the first blocker.", ["lifecycle run manifest", "phase review evidence"], {
        conditionalInputs: [condition("runDirectory", "Terminal strict-run reporting requires the selected lifecycle run.", "run-open output", "runDirectory")]
    })
]);
function compileLifecycleFlightPlan(options) {
    const repositoryRoot = node_path_1.default.resolve(options.repositoryRoot);
    const profile = normalizeProfile(options.profile);
    const artifactPath = normalizeRepositoryPath(options.artifactPath, "artifact");
    const absoluteArtifactPath = resolveInside(repositoryRoot, artifactPath, "artifact");
    const artifactText = readRequiredFile(absoluteArtifactPath, artifactPath);
    const artifactDocument = (0, planning_artifact_document_1.parsePlanningArtifactDocument)(artifactText);
    const artifactType = artifactDocument.frontMatterFields.artifact_type;
    if (artifactType !== "phase_overview") {
        throw compileError("LIFECYCLE_PROFILE_ARTIFACT_MISMATCH", `Profile '${profile}' requires a canonical phase_overview artifact.`, artifactPath, lineOf(artifactText, "artifact_type:"), `Observed artifact_type '${artifactType ?? "missing"}'.`);
    }
    const workflowPath = exports.FULL_CYCLE_STRICT_WORKFLOW_PATH;
    const workflowText = readRequiredFile(resolveInside(repositoryRoot, workflowPath, "workflow"), workflowPath);
    const stepClauses = validateProfileSource(workflowText, workflowPath, profile);
    const descriptors = resolveGateDescriptors(workflowPath, stepClauses);
    const artifactRevision = digestText(artifactText);
    const run = readRunManifest(options.runDirectory, repositoryRoot, artifactPath, artifactRevision);
    const revisions = {
        profile: digestValue({ profile, clauses: [...stepClauses.entries()] }),
        artifact: artifactRevision,
        workflow: digestText(workflowText),
        registry: digestValue(descriptors.map((descriptor) => ({ command: descriptor.command, descriptor }))),
        canonicalContent: [
            { path: workflowPath, revision: digestText(workflowText) },
            { path: artifactPath, revision: artifactRevision }
        ]
    };
    const optionValues = normalizeObservedOptions(options, artifactPath);
    const completedEntries = classifyRunEntries(run?.entries ?? []);
    const gates = [];
    let dependencyOpen = true;
    for (let index = 0; index < PROFILE_GATE_DEFINITIONS.length; index += 1) {
        const definition = PROFILE_GATE_DEFINITIONS[index];
        const descriptor = descriptors[index];
        const clause = stepClauses.get(definition.profileStep);
        const conditionalInputs = resolveConditionalInputs(definition, optionValues);
        const commandSkeleton = buildCommandSkeleton(definition, descriptor, artifactPath, profile, conditionalInputs, optionValues);
        const entryState = resolveEntryState(definition, completedEntries, run !== null);
        let state;
        if (entryState === "completed" || definition.intrinsic === "selected-artifact") {
            state = "completed";
        }
        else if (entryState === "superseded") {
            state = "superseded";
        }
        else if (definition.optionalSync && optionValues.metadataPosture !== "sync-on-clean-review") {
            state = "not_yet_applicable";
        }
        else if (dependencyOpen) {
            state = entryState === "blocked" ? "blocked" : "executable";
            dependencyOpen = false;
        }
        else {
            state = "not_yet_applicable";
        }
        gates.push({
            id: definition.id,
            sequence: index + 1,
            profileStep: definition.profileStep,
            dependsOn: index === 0 ? [] : [PROFILE_GATE_DEFINITIONS[index - 1].id],
            state,
            posture: descriptor.writeCapable ? "mutation" : "read-only",
            requiredArtifacts: definition.requiredArtifacts.map((value) => value === "selected artifact" ? artifactPath : value),
            commandDescriptor: {
                command: descriptor.command,
                availability: descriptor.availability,
                revision: digestValue(descriptor),
                writeCapable: descriptor.writeCapable,
                authorization: descriptor.authorization,
                mutationPosture: descriptor.mutationPosture
            },
            commandSkeleton,
            conditionalInputs,
            expectedEvidence: definition.expectedEvidence,
            terminalCondition: definition.terminalCondition,
            source: { path: workflowPath, line: clause.line, clause: clause.text }
        });
    }
    const planIdentity = {
        schemaVersion: exports.LIFECYCLE_FLIGHT_PLAN_SCHEMA_VERSION,
        profile,
        artifactPath,
        revisions,
        gates: gates.map((gate) => ({
            id: gate.id,
            sequence: gate.sequence,
            profileStep: gate.profileStep,
            dependsOn: gate.dependsOn,
            commandDescriptor: gate.commandDescriptor,
            source: gate.source
        }))
    };
    const planRevision = digestValue(planIdentity);
    const expectedRevision = options.expectedPlanRevision?.trim() || null;
    if (expectedRevision !== null && expectedRevision !== planRevision) {
        throw compileError("LIFECYCLE_FLIGHT_PLAN_STALE", "The supplied lifecycle flight-plan revision does not match current canonical inputs.", artifactPath, 1, `Expected ${expectedRevision}; current ${planRevision}. Recompile instead of reusing stale gate guidance.`);
    }
    const nextExecutableGateId = gates.find((gate) => gate.state === "executable")?.id ?? null;
    const blockedGateCount = gates.filter((gate) => gate.state === "blocked").length;
    return {
        schemaVersion: 1,
        profile,
        artifactPath,
        artifactType: "phase_overview",
        workflowPath,
        planRevision,
        reusable: true,
        staleInputs: [],
        revisions,
        currentState: {
            nextExecutableGateId,
            terminal: nextExecutableGateId === null && blockedGateCount === 0,
            completedGateCount: gates.filter((gate) => gate.state === "completed").length,
            blockedGateCount,
            totalGateCount: gates.length
        },
        gates,
        findings: [],
        readOnly: true,
        writeApplied: false,
        authorizationGranted: false,
        noWriteBoundary: "Workflow compilation reads canonical workflow, artifact, registry, and optional run evidence only; it performs no gate, write, selection, or authorization."
    };
}
function projectCompactLifecycleFlightPlan(plan) {
    const decisionGates = plan.gates.filter((gate) => (gate.state === "executable" || gate.state === "blocked")).slice(0, 1).map((gate) => ({
        id: gate.id,
        sequence: gate.sequence,
        state: gate.state,
        posture: gate.posture,
        command: gate.commandDescriptor.command,
        commandRevision: gate.commandDescriptor.revision,
        callable: gate.commandSkeleton.callable,
        argv: gate.commandSkeleton.argv,
        unresolvedInputs: gate.commandSkeleton.unresolvedInputs,
        expectedEvidence: gate.expectedEvidence,
        source: gate.source
    }));
    return {
        schemaVersion: plan.schemaVersion,
        profile: plan.profile,
        artifactPath: plan.artifactPath,
        workflowPath: plan.workflowPath,
        planRevision: plan.planRevision,
        reusable: plan.reusable,
        staleInputs: plan.staleInputs,
        revisions: plan.revisions,
        currentState: plan.currentState,
        gates: decisionGates,
        graphRecovery: {
            routine: `day-shift workflow compile --profile ${plan.profile} --artifact ${plan.artifactPath} --format json`,
            audit: {
                full: `day-shift workflow compile --profile ${plan.profile} --artifact ${plan.artifactPath} --format json --detail full`,
                paged: `day-shift workflow compile --profile ${plan.profile} --artifact ${plan.artifactPath} --format json --detail full --page-lane gates --page-size 10`
            }
        },
        findings: plan.findings,
        readOnly: plan.readOnly,
        writeApplied: plan.writeApplied,
        authorizationGranted: plan.authorizationGranted,
        noWriteBoundary: plan.noWriteBoundary
    };
}
function renderLifecycleFlightPlan(plan) {
    const next = plan.gates.find((gate) => gate.id === plan.currentState.nextExecutableGateId) ?? null;
    const lines = [
        `Lifecycle flight plan: ${plan.profile}`,
        `Artifact: ${plan.artifactPath}`,
        `Revision: ${plan.planRevision}`,
        `Gates: ${plan.currentState.completedGateCount}/${plan.currentState.totalGateCount} completed`
    ];
    if (next === null) {
        lines.push(plan.currentState.terminal ? "Next gate: terminal" : "Next gate: blocked");
    }
    else {
        lines.push(`Next gate: ${next.id} (${next.commandDescriptor.command})`);
        lines.push(`Callable: ${next.commandSkeleton.callable}`);
        if (!next.commandSkeleton.callable)
            lines.push(`Unresolved: ${next.commandSkeleton.unresolvedInputs.join(", ")}`);
    }
    lines.push(plan.noWriteBoundary);
    return lines.join("\n");
}
function gate(id, profileStep, command, expectedEvidence, terminalCondition, requiredArtifacts, options = {}) {
    return { id, profileStep, command, expectedEvidence, terminalCondition, requiredArtifacts, ...options };
}
function condition(name, rule, source, option, acceptedValue) {
    return { name, rule, source, option, ...(acceptedValue === undefined ? {} : { acceptedValue }) };
}
function normalizeProfile(value) {
    const profile = value.trim();
    if (profile !== exports.FULL_CYCLE_STRICT_PROFILE) {
        throw compileError("LIFECYCLE_PROFILE_UNKNOWN", `Unknown lifecycle profile '${profile || "<empty>"}'.`, exports.FULL_CYCLE_STRICT_WORKFLOW_PATH, 1, `Registered profile: ${exports.FULL_CYCLE_STRICT_PROFILE}.`);
    }
    return profile;
}
function validateProfileSource(workflowText, workflowPath, profile) {
    const lines = workflowText.split(/\r?\n/u);
    const profileLine = lines.findIndex((line) => line.includes(`Profile: ${profile}`));
    if (profileLine < 0) {
        throw compileError("LIFECYCLE_PROFILE_SOURCE_MISSING", `Profile '${profile}' is absent from its authoritative lifecycle guide.`, workflowPath, 1, "The profile identity must be explicit in canonical prose.");
    }
    const headingIndex = lines.findIndex((line) => line === "## Full-Cycle Algorithm");
    const nextHeading = headingIndex < 0 ? -1 : lines.findIndex((line, index) => index > headingIndex && /^##\s/u.test(line));
    if (headingIndex < 0) {
        throw compileError("LIFECYCLE_PROFILE_SOURCE_MISSING", "The authoritative Full-Cycle Algorithm section is missing.", workflowPath, profileLine + 1, "Compilation cannot infer a lifecycle graph from unrelated prose.");
    }
    const end = nextHeading < 0 ? lines.length : nextHeading;
    const clauses = new Map();
    for (let index = headingIndex + 1; index < end; index += 1) {
        const match = lines[index].match(/^(\d+)\.\s+(.+)$/u);
        if (match === null)
            continue;
        const step = Number(match[1]);
        if (step < 1 || step > 16 || clauses.has(step)) {
            throw compileError("LIFECYCLE_PROFILE_UNKNOWN_CLAUSE", `Unknown or duplicate numbered lifecycle clause '${match[1]}'.`, workflowPath, index + 1, lines[index]);
        }
        clauses.set(step, { line: index + 1, text: lines[index] });
    }
    const missing = Array.from({ length: 16 }, (_, index) => index + 1).filter((step) => !clauses.has(step));
    if (missing.length > 0) {
        throw compileError("LIFECYCLE_PROFILE_UNKNOWN_CLAUSE", `Lifecycle profile is missing numbered clause(s): ${missing.join(", ")}.`, workflowPath, headingIndex + 1, "Compilation fails closed instead of dropping gates.");
    }
    return clauses;
}
function resolveGateDescriptors(workflowPath, clauses) {
    return PROFILE_GATE_DEFINITIONS.map((definition) => {
        const descriptor = (0, command_capabilities_1.getRegisteredCommandDescriptor)(definition.command);
        if (descriptor === null || descriptor.availability !== "callable") {
            const clause = clauses.get(definition.profileStep);
            throw compileError("LIFECYCLE_PROFILE_COMMAND_DRIFT", `Lifecycle gate '${definition.id}' does not resolve to a callable authoritative descriptor '${definition.command}'.`, workflowPath, clause.line, clause.text);
        }
        return descriptor;
    });
}
function resolveConditionalInputs(definition, options) {
    return (definition.conditionalInputs ?? []).map((input) => {
        let value = options[input.option] ?? null;
        if (input.name === "phaseReviewResult" || input.name === "reviewResult" || input.name === "taskDefinition" || input.name === "milestoneOverview") {
            value = null;
        }
        const resolved = value !== null && (input.acceptedValue === undefined || value === input.acceptedValue);
        return {
            name: input.name,
            triggeringRule: input.rule,
            authoritativeSource: input.source,
            resolved,
            value
        };
    });
}
function buildCommandSkeleton(definition, descriptor, artifactPath, profile, conditionalInputs, options) {
    const argv = ["day-shift", ...descriptor.command.split(/\s+/u)];
    const unresolved = new Set(conditionalInputs.filter((input) => !input.resolved).map((input) => input.name));
    const supplied = new Map(Object.entries(definition.suppliedInputs ?? {}));
    const standard = {
        artifact: artifactPath,
        phase: artifactPath,
        phaseOverview: artifactPath,
        activeArtifact: artifactPath,
        profile,
        activeGate: definition.id,
        runDirectory: options.runDirectory,
        actor: options.actor,
        openedAt: options.observedAt,
        reviewedAt: options.observedAt,
        reviewedBy: options.actor,
        metadataPosture: options.metadataPosture,
        taskDefinition: null,
        milestoneOverview: null,
        reviewResult: null,
        phaseReviewResult: null
    };
    for (const input of descriptor.inputs) {
        const value = supplied.has(input.name) ? supplied.get(input.name) : standard[input.name];
        if (value === undefined || value === null || value === "") {
            if (input.required)
                unresolved.add(input.name);
            if (input.required || unresolved.has(input.name)) {
                if (input.kind === "argument") {
                    argv.push(`<${input.name}>`);
                }
                else {
                    const flag = `--${input.name.replace(/[A-Z]/gu, (letter) => `-${letter.toLowerCase()}`)}`;
                    argv.push(flag);
                    if (input.valueType !== "boolean")
                        argv.push(`<${input.name}>`);
                }
            }
            continue;
        }
        if (input.kind === "argument") {
            argv.push(String(value));
            continue;
        }
        const flag = `--${input.name.replace(/[A-Z]/gu, (letter) => `-${letter.toLowerCase()}`)}`;
        if (input.valueType === "boolean") {
            if (value === true)
                argv.push(flag);
        }
        else {
            argv.push(flag, String(value));
        }
    }
    return {
        argv,
        callable: unresolved.size === 0,
        unresolvedInputs: [...unresolved].sort(),
        nonCallableReason: unresolved.size === 0 ? null : `Unresolved authoritative input(s): ${[...unresolved].sort().join(", ")}.`
    };
}
function readRunManifest(requested, repositoryRoot, artifactPath, artifactRevision) {
    const token = requested?.trim();
    if (!token)
        return null;
    const runDirectory = normalizeRepositoryPath(token, "run directory");
    if (!sandbox_contract_1.LIFECYCLE_RUN_DIRECTORY_PATH_PATTERN.test(runDirectory)) {
        throw compileError("LIFECYCLE_RUN_INVALID", "Run directory must use canonical .day-shift/runs/run-<run-id> form (legacy sandbox/run-<run-id> remains readable).", runDirectory, 1, "No run evidence was read.");
    }
    const manifestPath = `${runDirectory}/run-context.json`;
    const raw = readRequiredFile(resolveInside(repositoryRoot, manifestPath, "run manifest"), manifestPath);
    let manifest;
    try {
        manifest = JSON.parse(raw);
    }
    catch {
        throw compileError("LIFECYCLE_RUN_INVALID", "Lifecycle run manifest is not valid JSON.", manifestPath, 1, "Compilation performs no repair.");
    }
    if (manifest.phasePath !== artifactPath || manifest.phaseHash !== artifactRevision) {
        throw compileError("LIFECYCLE_FLIGHT_PLAN_STALE", "Lifecycle run manifest is not bound to the current selected artifact revision.", manifestPath, 1, `Expected ${artifactPath} at ${artifactRevision}.`);
    }
    return manifest;
}
function classifyRunEntries(entries) {
    const superseded = new Set(entries.map((entry) => entry.supersedesEntryId).filter((value) => typeof value === "string"));
    return { current: entries.filter((entry) => !superseded.has(entry.entryId ?? "")), superseded };
}
function resolveEntryState(definition, entries, hasRun) {
    if (definition.intrinsic === "open-run")
        return hasRun ? "completed" : "absent";
    const matches = (entry) => entry.commandIdentity === definition.command
        && (definition.manifestGates === undefined || definition.manifestGates.includes(entry.gate ?? ""));
    const current = entries.current.filter(matches);
    if (current.some((entry) => entry.status === "ok"))
        return "completed";
    if (current.some((entry) => entry.status === "error"))
        return "blocked";
    return "absent";
}
function normalizeObservedOptions(options, artifactPath) {
    const metadataPosture = options.metadataPosture?.trim() || null;
    if (metadataPosture !== null && !["read-only", "sync-on-clean-review"].includes(metadataPosture)) {
        throw compileError("LIFECYCLE_INPUT_INVALID", "Metadata posture must be read-only or sync-on-clean-review.", artifactPath, 1, `Observed '${metadataPosture}'.`);
    }
    const authorization = options.authorization?.trim() || null;
    if (authorization !== null && !["authorized", "not-authorized"].includes(authorization)) {
        throw compileError("LIFECYCLE_INPUT_INVALID", "Authorization observation must be authorized or not-authorized.", artifactPath, 1, `Observed '${authorization}'.`);
    }
    return {
        runDirectory: options.runDirectory?.trim() || null,
        actor: options.actor?.trim() || null,
        observedAt: options.observedAt?.trim() || null,
        metadataPosture,
        authorization,
        artifact: artifactPath
    };
}
function normalizeRepositoryPath(value, label) {
    const normalized = value.trim().replace(/\\/gu, "/").replace(/^\.\//u, "");
    if (!normalized || node_path_1.default.posix.isAbsolute(normalized) || normalized.split("/").includes("..")) {
        throw compileError("LIFECYCLE_INPUT_INVALID", `${label} must be a repository-relative path.`, normalized || "<empty>", 1, "Absolute and parent-traversal paths are rejected.");
    }
    return node_path_1.default.posix.normalize(normalized);
}
function resolveInside(repositoryRoot, repositoryPath, label) {
    const absolute = node_path_1.default.resolve(repositoryRoot, repositoryPath);
    const relative = node_path_1.default.relative(repositoryRoot, absolute);
    if (relative.startsWith("..") || node_path_1.default.isAbsolute(relative)) {
        throw compileError("LIFECYCLE_INPUT_INVALID", `${label} resolves outside the repository.`, repositoryPath, 1, "No outside-repository content was read.");
    }
    return absolute;
}
function readRequiredFile(absolutePath, repositoryPath) {
    let stats;
    try {
        stats = node_fs_1.default.statSync(absolutePath);
    }
    catch {
        throw compileError("LIFECYCLE_INPUT_MISSING", `Required canonical file '${repositoryPath}' does not exist.`, repositoryPath, 1, "Compilation is read-only and does not create it.");
    }
    if (!stats.isFile()) {
        throw compileError("LIFECYCLE_INPUT_INVALID", `Required canonical path '${repositoryPath}' is not a regular file.`, repositoryPath, 1, "Compilation accepts regular files only.");
    }
    return node_fs_1.default.readFileSync(absolutePath, "utf8");
}
function compileError(code, message, sourcePath, line, detail) {
    return new LifecycleFlightPlanCompileError(code, message, [{ code, severity: "error", path: sourcePath, line, message: detail }]);
}
function lineOf(text, needle) {
    const index = text.split(/\r?\n/u).findIndex((line) => line.includes(needle));
    return index < 0 ? 1 : index + 1;
}
function digestText(value) {
    return `sha256:${(0, node_crypto_1.createHash)("sha256").update(value).digest("hex")}`;
}
function digestValue(value) {
    return digestText(JSON.stringify(value));
}
