"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WorkspaceMigrationApplicationError = exports.WORKSPACE_STRUCTURE_MIGRATION_APPLY_PROTOCOL_VERSION = void 0;
exports.applyWorkspaceStructureMigrationSync = applyWorkspaceStructureMigrationSync;
const node_crypto_1 = require("node:crypto");
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const operational_state_1 = require("../filesystem/operational-state");
const repository_transaction_1 = require("../filesystem/repository-transaction");
const canonical_write_target_1 = require("../paths/canonical-write-target");
const planning_document_utils_1 = require("./planning-document-utils");
const task_lifecycle_1 = require("./task-lifecycle");
const workspace_migration_planning_1 = require("./workspace-migration-planning");
exports.WORKSPACE_STRUCTURE_MIGRATION_APPLY_PROTOCOL_VERSION = 1;
class WorkspaceMigrationApplicationError extends Error {
    code;
    noWrite;
    constructor(code, message) {
        super(message);
        this.name = "WorkspaceMigrationApplicationError";
        this.code = code;
        this.noWrite = true;
    }
}
exports.WorkspaceMigrationApplicationError = WorkspaceMigrationApplicationError;
function applyWorkspaceStructureMigrationSync(options) {
    const expectedPlanDigest = requireDigest(options.expectedPlanDigest);
    const actor = requireText(options.actor ?? "workspace-migration-operator", "Migration actor");
    const reason = requireText(options.reason ?? "Apply the explicitly previewed structural workspace migration.", "Migration reason");
    const appliedAt = normalizeTimestamp(options.appliedAt ?? new Date().toISOString());
    const plan = (0, workspace_migration_planning_1.planWorkspaceStructureMigrationSync)({
        repositoryRoot: options.repositoryRoot,
        selections: options.selections ?? []
    });
    if (plan.planDigest !== expectedPlanDigest) {
        throw new WorkspaceMigrationApplicationError("plan-mismatch", `Workspace migration apply expected exact plan digest '${expectedPlanDigest}', but current repository evidence produced '${plan.planDigest}'. No write was attempted.`);
    }
    if (plan.status !== "ready" || plan.findings.length > 0) {
        throw new WorkspaceMigrationApplicationError("blocked-plan", `Workspace migration plan is '${plan.status}' with ${plan.findings.length} blocking finding(s). No write was attempted.`);
    }
    const repositoryRoot = node_fs_1.default.realpathSync(node_path_1.default.resolve(options.repositoryRoot));
    const transactionId = `migration-${(0, node_crypto_1.randomBytes)(18).toString("hex")}`;
    const application = buildApplication(repositoryRoot, plan, {
        transactionId,
        actor,
        reason,
        appliedAt
    });
    const transaction = (0, repository_transaction_1.executeRepositoryTransactionSync)(repositoryRoot, {
        transactionId,
        transactionKind: "migration",
        durableRecordPath: plan.migrationRecordPath,
        writes: application.writes,
        retirements: application.retirements,
        preconditions: application.preconditions
    }, withFreshPlanGuard(repositoryRoot, plan, options.selections ?? [], options.transaction));
    const changedEntries = transaction.entries.slice(0, transaction.canonicalWrites);
    const recoveryPath = transaction.outcome === "incomplete"
        || transaction.cleanupErrors.length > 0
        ? transaction.transactionPath
        : null;
    return {
        protocolVersion: exports.WORKSPACE_STRUCTURE_MIGRATION_APPLY_PROTOCOL_VERSION,
        plan,
        planDigest: plan.planDigest,
        expectedPlanDigest,
        outcome: transaction.outcome,
        committed: transaction.outcome === "committed",
        writeApplied: transaction.outcome === "committed",
        transactionId: transaction.transactionId,
        transactionPath: transaction.transactionPath,
        migrationRecordPath: plan.migrationRecordPath,
        sourcePaths: application.sourcePaths,
        destinationPaths: application.destinationPaths,
        changedPaths: changedEntries.map((entry) => entry.path),
        retiredPaths: changedEntries
            .filter((entry) => entry.operation === "retire")
            .map((entry) => entry.path),
        conflicts: transaction.conflicts,
        recoveryPath,
        recoveryFingerprint: recoveryFingerprintFor(repositoryRoot, transaction.transactionId, recoveryPath),
        cleanupErrors: transaction.cleanupErrors,
        failure: transaction.failure,
        actor,
        reason,
        appliedAt,
        nextAction: nextActionFor(transaction.outcome, transaction.cleanupErrors.length > 0)
    };
}
function buildApplication(repositoryRoot, plan, record) {
    const writesByPath = new Map();
    for (const evidence of plan.sharedEvidenceArchives) {
        const source = (0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, evidence.sourcePath);
        if (!source.exists || !node_fs_1.default.statSync(source.runtimePath).isFile()) {
            throw new WorkspaceMigrationApplicationError("invalid-request", `Shared migration evidence '${evidence.sourcePath}' is missing.`);
        }
        writesByPath.set(evidence.archivePath, {
            path: evidence.archivePath,
            contents: node_fs_1.default.readFileSync(source.runtimePath)
        });
    }
    for (const unit of plan.workUnits) {
        if (!unit.actionable || unit.selectedWorkflowLevel === null)
            continue;
        for (const mapping of unit.artifactMappings) {
            const write = {
                path: mapping.destinationPath,
                contents: renderMapping(repositoryRoot, plan, unit, mapping)
            };
            const existing = writesByPath.get(write.path);
            if (existing === undefined) {
                writesByPath.set(write.path, write);
            }
            else if (existing.contents !== write.contents) {
                throw new WorkspaceMigrationApplicationError("invalid-request", `Migration mappings produced conflicting content for destination '${write.path}'. No write was attempted.`);
            }
        }
    }
    for (const update of plan.repositoryUpdates) {
        const source = (0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, update.path);
        if (!source.exists || !node_fs_1.default.statSync(source.runtimePath).isFile()) {
            throw new WorkspaceMigrationApplicationError("invalid-request", `Repository relationship source '${update.path}' is missing.`);
        }
        const before = node_fs_1.default.readFileSync(source.runtimePath, "utf8");
        const rewritten = (0, workspace_migration_planning_1.rewriteKnownRepositoryPaths)(before, plan.pathReplacements, {
            sourceArtifactPath: update.path,
            destinationArtifactPath: update.path
        });
        if (rewritten.replacementCount !== update.replacementCount) {
            throw new WorkspaceMigrationApplicationError("invalid-request", `Repository relationship source '${update.path}' changed after planning.`);
        }
        const rebound = update.readinessRevisionRebound
            ? (0, task_lifecycle_1.rebindTaskReadinessAuthorizationRevision)(rewritten.text)
            : { text: rewritten.text, changed: false };
        if (rebound.changed !== update.readinessRevisionRebound) {
            throw new WorkspaceMigrationApplicationError("invalid-request", `Repository relationship source '${update.path}' readiness authorization changed after planning.`);
        }
        const existing = writesByPath.get(update.path);
        if (existing !== undefined) {
            throw new WorkspaceMigrationApplicationError("invalid-request", `Repository relationship update '${update.path}' conflicts with a migration write.`);
        }
        writesByPath.set(update.path, { path: update.path, contents: rebound.text });
    }
    const recordWrite = {
        path: plan.migrationRecordPath,
        contents: renderMigrationRecord(plan, record)
    };
    const existingRecord = writesByPath.get(recordWrite.path);
    if (existingRecord !== undefined) {
        throw new WorkspaceMigrationApplicationError("invalid-request", `Migration record destination '${recordWrite.path}' conflicts with an artifact mapping. No write was attempted.`);
    }
    writesByPath.set(recordWrite.path, recordWrite);
    const writes = [...writesByPath.values()];
    const sourcePaths = uniqueSorted(plan.retirementPaths);
    const destinationPaths = uniqueSorted(writes.map((write) => write.path));
    return {
        writes,
        retirements: sourcePaths.map((sourcePath) => ({ path: sourcePath })),
        preconditions: plan.expected.map((condition) => {
            const target = (0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, condition.path);
            return condition.kind === "content-revision"
                ? {
                    kind: "content-revision",
                    repositoryRelativePath: target.repositoryRelativePath,
                    runtimePath: target.runtimePath,
                    expectedRevision: condition.expectedState
                }
                : {
                    kind: "destination-presence",
                    repositoryRelativePath: target.repositoryRelativePath,
                    runtimePath: target.runtimePath,
                    expectedPresence: condition.expectedState === "present" ? "present" : "absent"
                };
        }),
        sourcePaths,
        destinationPaths
    };
}
function renderMapping(repositoryRoot, plan, unit, mapping) {
    if (mapping.sourcePath === null) {
        if (mapping.role !== "work-overview") {
            throw new WorkspaceMigrationApplicationError("invalid-request", `Generated migration mapping '${mapping.destinationPath}' has unsupported role '${mapping.role}'.`);
        }
        return renderWorkOverview(plan, unit);
    }
    const source = (0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, mapping.sourcePath);
    if (!source.exists || !node_fs_1.default.statSync(source.runtimePath).isFile()) {
        throw new WorkspaceMigrationApplicationError("invalid-request", `Migration source '${mapping.sourcePath}' is missing.`);
    }
    let result = node_fs_1.default.readFileSync(source.runtimePath, "utf8");
    result = (0, workspace_migration_planning_1.rewriteKnownRepositoryPaths)(result, plan.pathReplacements, {
        sourceArtifactPath: mapping.sourcePath,
        destinationArtifactPath: mapping.destinationPath
    }).text;
    if (!(0, planning_document_utils_1.parseMarkdownFrontMatter)(result).hasFrontMatter) {
        return result;
    }
    result = rewriteMappedFrontMatterPaths(result, plan);
    result = rewriteSpecificationReferences(result, unit);
    result = upsertTopLevelScalar(result, "workflow_level", unit.selectedWorkflowLevel);
    if (unit.implementationOrder !== null
        && ((unit.selectedWorkflowLevel === "structured" && mapping.role === "work-overview")
            || (unit.selectedWorkflowLevel === "basic"
                && (mapping.role === "task-definition" || mapping.role === "implementation-summary")))) {
        result = upsertTopLevelScalar(result, "implementation_order", unit.implementationOrder);
    }
    if (mapping.role === "work-overview") {
        result = upsertTopLevelScalar(result, "artifact_type", "work_overview");
        result = upsertTopLevelScalar(result, "id", unit.workId);
        for (const field of ["slice", "phase", "milestone", "task"]) {
            result = removeTopLevelScalar(result, field);
        }
    }
    if (mapping.role === "task-definition" || mapping.role === "implementation-summary") {
        result = rewriteTaskRelationshipMetadata(result, plan, unit, mapping);
    }
    else if (unit.selectedWorkflowLevel === "governed" && mapping.role === "planning-artifact") {
        result = rewriteGovernedParentMetadata(result, unit, mapping.destinationPath);
        if (mapping.destinationPath === unit.destinationRootPath + "/slice-overview.md") {
            result = appendFormerContainerProvenance(result, unit);
        }
    }
    if (mapping.role === "task-definition") {
        const taskMapping = unit.taskMappings.find((entry) => entry.destinationTaskDefinitionPath === mapping.destinationPath);
        if (taskMapping?.sequence !== null && taskMapping?.sequence !== undefined) {
            result = upsertTopLevelScalar(result, "sequence", String(taskMapping.sequence));
        }
        result = (0, task_lifecycle_1.rebindTaskReadinessAuthorizationRevision)(result).text;
    }
    return result;
}
function rewriteTaskRelationshipMetadata(markdownText, plan, unit, mapping) {
    let result = markdownText;
    const level = unit.selectedWorkflowLevel;
    if (level === "basic" || level === "structured") {
        for (const field of ["slice", "phase", "milestone"]) {
            result = removeTopLevelScalar(result, field);
        }
        for (const field of ["slice_overview", "phase_overview", "milestone_overview"]) {
            result = removeUpstreamScalar(result, field);
        }
    }
    if (level === "basic") {
        result = removeUpstreamScalar(result, "work_overview");
    }
    if (level === "structured") {
        const structuredRoot = mapping.destinationPath.split("/tasks/")[0];
        result = upsertUpstreamScalar(result, "work_overview", `${structuredRoot}/overview.md`);
    }
    if (level === "governed") {
        const coordinates = governedCoordinates(mapping.destinationPath);
        if (coordinates !== null) {
            result = upsertTopLevelScalar(result, "slice", coordinates.slice);
            result = upsertTopLevelScalar(result, "phase", coordinates.phase);
            result = upsertTopLevelScalar(result, "milestone", coordinates.milestone);
            result = removeUpstreamScalar(result, "work_overview");
            result = upsertUpstreamScalar(result, "slice_overview", coordinates.sliceOverview);
            result = upsertUpstreamScalar(result, "phase_overview", coordinates.phaseOverview);
            result = upsertUpstreamScalar(result, "milestone_overview", coordinates.milestoneOverview);
        }
    }
    if (mapping.role === "implementation-summary") {
        const taskMapping = unit.taskMappings.find((candidate) => candidate.destinationImplementationSummaryPath === mapping.destinationPath);
        if (taskMapping !== undefined) {
            result = upsertUpstreamScalar(result, "task_definition", taskMapping.destinationTaskDefinitionPath);
        }
    }
    return result;
}
function rewriteGovernedParentMetadata(markdownText, unit, destinationPath) {
    let result = markdownText;
    const sliceMatch = destinationPath.match(/^(.+\/governed\/([^/]+))\/slice-overview\.md$/);
    if (sliceMatch !== null) {
        result = upsertTopLevelScalar(result, "artifact_type", "slice_overview");
        result = upsertTopLevelScalar(result, "slice", sliceMatch[2]);
        result = removeUpstreamScalar(result, "work_overview");
        return result;
    }
    const phaseMatch = destinationPath.match(/^(.+\/governed\/([^/]+)\/phases\/([^/]+))\/phase-overview\.md$/);
    if (phaseMatch !== null) {
        result = upsertTopLevelScalar(result, "artifact_type", "phase_overview");
        result = upsertTopLevelScalar(result, "slice", phaseMatch[2]);
        result = upsertTopLevelScalar(result, "phase", phaseMatch[3]);
        result = upsertUpstreamScalar(result, "slice_overview", `${phaseMatch[1].split("/phases/")[0]}/slice-overview.md`);
        return result;
    }
    const milestoneMatch = destinationPath.match(/^(.+\/governed\/([^/]+)\/phases\/([^/]+)\/milestones\/([^/]+))\/(milestone-overview|reconciliation)\.md$/);
    if (milestoneMatch !== null) {
        const artifactType = destinationPath.endsWith("/reconciliation.md")
            ? "reconciliation"
            : "milestone_overview";
        result = upsertTopLevelScalar(result, "artifact_type", artifactType);
        result = upsertTopLevelScalar(result, "slice", milestoneMatch[2]);
        result = upsertTopLevelScalar(result, "phase", milestoneMatch[3]);
        result = upsertTopLevelScalar(result, "milestone", milestoneMatch[4]);
        const phaseRoot = milestoneMatch[1].split("/milestones/")[0];
        result = upsertUpstreamScalar(result, "slice_overview", `${phaseRoot.split("/phases/")[0]}/slice-overview.md`);
        result = upsertUpstreamScalar(result, "phase_overview", `${phaseRoot}/phase-overview.md`);
        if (artifactType === "reconciliation") {
            result = upsertUpstreamScalar(result, "milestone_overview", `${milestoneMatch[1]}/milestone-overview.md`);
        }
    }
    return result;
}
function appendFormerContainerProvenance(markdownText, unit) {
    if (unit.sharedEvidence === null || unit.formerContainerIdentity === null) {
        return markdownText;
    }
    if (markdownText.includes("## Former Governed Container Provenance")) {
        return markdownText;
    }
    const trailingNewline = markdownText.endsWith("\n");
    const body = markdownText.replace(/\s*$/, "");
    const appended = [
        body,
        "",
        "## Former Governed Container Provenance",
        "",
        `- Former container: \`${unit.formerContainerIdentity}\`.`,
        `- Shared generated migration evidence: \`${unit.sharedEvidence.archivePath}\`.`,
        "- Disposition: archived once and referenced by every applicable migrated slice."
    ].join("\n");
    return trailingNewline ? `${appended}\n` : appended;
}
function rewriteMappedFrontMatterPaths(markdownText, plan) {
    const replacements = new Map(plan.workUnits.flatMap((candidate) => candidate.artifactMappings.flatMap((entry) => entry.sourcePath === null ? [] : [[entry.sourcePath, entry.destinationPath]])));
    return rewriteFrontMatterScalarValues(markdownText, (value) => replacements.get(value) ?? value);
}
function rewriteSpecificationReferences(markdownText, unit) {
    const replacements = new Map(unit.specifications
        .filter((specification) => specification.sourceRef !== specification.ref)
        .map((specification) => [
        `${specification.id}\0${specification.sourceRef}`,
        specification.ref
    ]));
    if (replacements.size === 0)
        return markdownText;
    const document = splitFrontMatter(markdownText);
    let currentSpecificationId = null;
    document.frontMatter = document.frontMatter.map((line) => {
        const id = line.match(/^\s{4}-\s+id:\s*(.+?)\s*$/);
        if (id !== null) {
            currentSpecificationId = unquoteScalar(id[1]);
            return line;
        }
        const ref = line.match(/^(\s{6}ref:\s*)(.+?)\s*$/);
        if (ref === null || currentSpecificationId === null)
            return line;
        const sourceRef = unquoteScalar(ref[2]);
        const replacement = replacements.get(`${currentSpecificationId}\0${sourceRef}`);
        return replacement === undefined ? line : `${ref[1]}${JSON.stringify(replacement)}`;
    });
    return joinFrontMatter(document);
}
function rewriteFrontMatterScalarValues(markdownText, rewrite) {
    const document = splitFrontMatter(markdownText);
    let inUpstream = false;
    document.frontMatter = document.frontMatter.map((line) => {
        if (/^upstream:\s*$/.test(line)) {
            inUpstream = true;
            return line;
        }
        if (inUpstream && /^[^\s]/.test(line)) {
            inUpstream = false;
        }
        if (!inUpstream)
            return line;
        const scalar = line.match(/^(\s*(?:-\s+)?[A-Za-z0-9_]+:\s*)(.+?)\s*$/);
        if (scalar === null)
            return line;
        const value = unquoteScalar(scalar[2]);
        const replacement = rewrite(value);
        return replacement === value ? line : `${scalar[1]}${JSON.stringify(replacement)}`;
    });
    return joinFrontMatter(document);
}
function unquoteScalar(value) {
    const trimmed = value.trim();
    return ((trimmed.startsWith("\"") && trimmed.endsWith("\""))
        || (trimmed.startsWith("'") && trimmed.endsWith("'"))) ? trimmed.slice(1, -1) : trimmed;
}
function renderWorkOverview(plan, unit) {
    const matchingUnits = plan.workUnits
        .filter((candidate) => candidate.actionable
        && candidate.workId === unit.workId
        && candidate.selectedWorkflowLevel === unit.selectedWorkflowLevel)
        .sort((left, right) => left.workUnitId.localeCompare(right.workUnitId));
    const specificationsByKey = new Map();
    for (const candidate of matchingUnits) {
        for (const specification of candidate.specifications) {
            specificationsByKey.set(`${specification.id}\0${specification.ref}\0${specification.revision ?? ""}`, specification);
        }
    }
    const specifications = [...specificationsByKey.values()]
        .sort((left, right) => `${left.id}\0${left.ref}\0${left.revision ?? ""}`
        .localeCompare(`${right.id}\0${right.ref}\0${right.revision ?? ""}`))
        .flatMap((specification) => [
        `    - id: ${JSON.stringify(specification.id)}`,
        `      ref: ${JSON.stringify(specification.ref)}`,
        ...(specification.revision === null
            ? []
            : [`      revision: ${JSON.stringify(specification.revision)}`])
    ]);
    const legacyWorkUnits = matchingUnits.map((candidate) => `- Legacy work unit: \`${candidate.workUnitId}\`.`);
    return [
        "---",
        "artifact_schema_version: 1",
        "artifact_type: work_overview",
        `id: ${JSON.stringify(unit.workId)}`,
        `workflow_level: ${unit.selectedWorkflowLevel}`,
        "status: draft",
        "upstream:",
        "  specs:",
        ...specifications,
        "---",
        "",
        `# Migrated ${title(unit.selectedWorkflowLevel)} Work: ${unit.workId}`,
        "",
        "## Purpose",
        "",
        "Preserve the explicitly previewed legacy planning hierarchy under its canonical workflow-level root.",
        "",
        "## Migration Evidence",
        "",
        `- Plan id: \`${plan.planId}\`.`,
        `- Plan digest: \`${plan.planDigest}\`.`,
        ...legacyWorkUnits,
        "",
        "## Open Questions",
        "",
        "- None currently.",
        ""
    ].join("\n");
}
function renderMigrationRecord(plan, record) {
    return `${JSON.stringify({
        schemaVersion: 1,
        protocolVersion: exports.WORKSPACE_STRUCTURE_MIGRATION_APPLY_PROTOCOL_VERSION,
        migrationKind: "workspace-structure",
        transactionState: "authorized",
        transactionId: record.transactionId,
        planId: plan.planId,
        planDigest: plan.planDigest,
        actor: record.actor,
        reason: record.reason,
        appliedAt: record.appliedAt,
        sourcePaths: plan.retirementPaths,
        destinationPaths: uniqueSorted(plan.workUnits.flatMap((unit) => unit.destinationPaths)),
        historicalCompatibilityDisposition: plan.historicalCompatibilityDisposition,
        sharedEvidenceArchives: plan.sharedEvidenceArchives,
        pathReplacements: plan.pathReplacements,
        repositoryUpdates: plan.repositoryUpdates,
        metadataInsertions: plan.metadataInsertions,
        revisionRebindings: plan.revisionRebindings,
        recoveryActions: plan.recoveryActions,
        retirementPaths: plan.retirementPaths,
        pathMappings: plan.workUnits.flatMap((unit) => unit.artifactMappings.flatMap((mapping) => mapping.sourcePath === null ? [] : [{
                workUnitId: unit.workUnitId,
                role: mapping.role,
                sourcePath: mapping.sourcePath,
                destinationPath: mapping.destinationPath
            }])).sort((left, right) => left.sourcePath.localeCompare(right.sourcePath)
            || left.destinationPath.localeCompare(right.destinationPath)),
        workUnits: plan.workUnits.map((unit) => ({
            workUnitId: unit.workUnitId,
            workId: unit.workId,
            selectedWorkflowLevel: unit.selectedWorkflowLevel,
            taskIds: unit.taskMappings.map((mapping) => mapping.taskId)
        })),
        preservation: {
            authoredBodies: "preserved",
            safeUnknownFrontMatter: "preserved",
            evidenceHistory: "preserved",
            specifications: "referenced-in-place",
            missingAuthorityOrEvidence: "not-fabricated",
            recoverableSourceState: "transaction-retired-staging"
        }
    }, null, 2)}\n`;
}
function withFreshPlanGuard(repositoryRoot, plan, selections, transactionOptions) {
    const callerHook = transactionOptions?.hook;
    return {
        ...transactionOptions,
        hook(context) {
            callerHook?.(context);
            if (context.phase === "after-preconditions") {
                const refreshed = (0, workspace_migration_planning_1.planWorkspaceStructureMigrationSync)({
                    repositoryRoot,
                    selections
                });
                if (refreshed.planDigest !== plan.planDigest || refreshed.status !== "ready") {
                    throw new Error("Workspace migration evidence changed after lock acquisition; refresh the no-write plan.");
                }
            }
        }
    };
}
function buildCoordinates(destinationPath) {
    const match = destinationPath.match(/\/governed\/([^/]+)\/phases\/([^/]+)\/milestones\/([^/]+)\/tasks\//);
    return match === null ? null : {
        slice: match[1],
        phase: match[2],
        milestone: match[3]
    };
}
function governedCoordinates(destinationPath) {
    const coordinates = buildCoordinates(destinationPath);
    if (coordinates === null)
        return null;
    const taskPrefix = destinationPath.split("/tasks/")[0];
    const phaseRoot = taskPrefix.split("/milestones/")[0];
    const sliceRoot = phaseRoot.split("/phases/")[0];
    return {
        ...coordinates,
        sliceOverview: `${sliceRoot}/slice-overview.md`,
        phaseOverview: `${phaseRoot}/phase-overview.md`,
        milestoneOverview: `${taskPrefix}/milestone-overview.md`
    };
}
function splitFrontMatter(markdownText) {
    const document = (0, planning_document_utils_1.parseMarkdownFrontMatter)(markdownText);
    if (!document.hasFrontMatter) {
        throw new WorkspaceMigrationApplicationError("invalid-request", "Migration planning artifacts require YAML front matter.");
    }
    return {
        frontMatter: [...document.frontMatterLines],
        bodyText: document.bodyText,
        trailingNewline: markdownText.endsWith("\n")
    };
}
function joinFrontMatter(input) {
    const text = ["---", ...input.frontMatter, "---", input.bodyText].join("\n");
    return input.trailingNewline && !text.endsWith("\n") ? `${text}\n` : text;
}
function upsertTopLevelScalar(markdownText, field, value) {
    const document = splitFrontMatter(markdownText);
    const pattern = new RegExp(`^${escapeRegExp(field)}:\\s*`);
    const index = document.frontMatter.findIndex((line) => pattern.test(line));
    const rendered = `${field}: ${JSON.stringify(value)}`;
    if (index >= 0) {
        document.frontMatter[index] = rendered;
    }
    else {
        document.frontMatter.push(rendered);
    }
    return joinFrontMatter(document);
}
function removeTopLevelScalar(markdownText, field) {
    const document = splitFrontMatter(markdownText);
    const pattern = new RegExp(`^${escapeRegExp(field)}:\\s*`);
    document.frontMatter = document.frontMatter.filter((line) => !pattern.test(line));
    return joinFrontMatter(document);
}
function ensureUpstreamBlock(lines) {
    let start = lines.findIndex((line) => /^upstream:\s*$/.test(line));
    if (start < 0) {
        lines.push("upstream:");
        start = lines.length - 1;
    }
    let end = start + 1;
    while (end < lines.length && /^\s/.test(lines[end]))
        end += 1;
    return { start, end };
}
function upsertUpstreamScalar(markdownText, field, value) {
    const document = splitFrontMatter(markdownText);
    const range = ensureUpstreamBlock(document.frontMatter);
    const pattern = new RegExp(`^  ${escapeRegExp(field)}:\\s*`);
    const index = document.frontMatter.findIndex((line, lineIndex) => lineIndex > range.start && lineIndex < range.end && pattern.test(line));
    const rendered = `  ${field}: ${JSON.stringify(value)}`;
    if (index >= 0) {
        document.frontMatter[index] = rendered;
    }
    else {
        document.frontMatter.splice(range.end, 0, rendered);
    }
    return joinFrontMatter(document);
}
function removeUpstreamScalar(markdownText, field) {
    const document = splitFrontMatter(markdownText);
    const range = ensureUpstreamBlock(document.frontMatter);
    const pattern = new RegExp(`^  ${escapeRegExp(field)}:\\s*`);
    document.frontMatter = document.frontMatter.filter((line, lineIndex) => !(lineIndex > range.start && lineIndex < range.end && pattern.test(line)));
    return joinFrontMatter(document);
}
function recoveryFingerprintFor(repositoryRoot, transactionId, recoveryPath) {
    if (recoveryPath === null)
        return null;
    try {
        return (0, operational_state_1.inspectOperationalStateSync)(repositoryRoot).transactions.find((transaction) => transaction.transactionId === transactionId)?.evidenceFingerprint ?? null;
    }
    catch {
        return null;
    }
}
function nextActionFor(outcome, cleanupIncomplete) {
    if (cleanupIncomplete) {
        return "Inspect the reported transaction and cleanup errors before retrying or cleaning operational state.";
    }
    if (outcome === "committed") {
        return "Review the canonical workflow-level destinations and durable migration record.";
    }
    if (outcome === "conflict") {
        return "Discard this authorization, inspect changed evidence, and generate a refreshed no-write plan.";
    }
    if (outcome === "incomplete") {
        return "Inspect the retained transaction before any retry, roll-forward, restoration, or cleanup.";
    }
    return "No canonical write completed; inspect recovery evidence and generate a refreshed no-write plan.";
}
function requireDigest(value) {
    if (typeof value !== "string" || !/^sha256:[a-f0-9]{64}$/.test(value)) {
        throw new WorkspaceMigrationApplicationError("invalid-request", "Workspace migration apply requires an expected plan digest in sha256:<hex> form.");
    }
    return value;
}
function requireText(value, label) {
    if (typeof value !== "string" || value.trim() === "") {
        throw new WorkspaceMigrationApplicationError("invalid-request", `${label} must be non-empty.`);
    }
    return value.trim();
}
function normalizeTimestamp(value) {
    const parsed = Date.parse(value);
    if (!Number.isFinite(parsed)) {
        throw new WorkspaceMigrationApplicationError("invalid-request", "Migration applied-at timestamp must be an ISO-8601 timestamp.");
    }
    return new Date(parsed).toISOString();
}
function uniqueSorted(values) {
    return [...new Set(values)].sort((left, right) => left.localeCompare(right));
}
function escapeRegExp(value) {
    return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function title(value) {
    return value.charAt(0).toUpperCase() + value.slice(1);
}
