"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WORKSPACE_COMPATIBILITY_DIAGNOSTIC_CATEGORIES = void 0;
exports.discoverWorkspaceCompatibilityVersions = discoverWorkspaceCompatibilityVersions;
exports.planWorkspaceSchemaMigration = planWorkspaceSchemaMigration;
exports.applyWorkspaceSchemaMigration = applyWorkspaceSchemaMigration;
exports.checkWorkspaceCompatibility = checkWorkspaceCompatibility;
exports.createWorkspaceCompatibilityDiagnostics = createWorkspaceCompatibilityDiagnostics;
exports.createWorkspaceCompatibilityFindings = createWorkspaceCompatibilityFindings;
exports.readCompatibilityVersionRangeShape = readCompatibilityVersionRangeShape;
exports.readMarkdownTraceabilityCompatibility = readMarkdownTraceabilityCompatibility;
exports.readWorkspaceAssetMetadataCompatibility = readWorkspaceAssetMetadataCompatibility;
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const planning_document_utils_1 = require("./planning/planning-document-utils");
const output_1 = require("./output");
exports.WORKSPACE_COMPATIBILITY_DIAGNOSTIC_CATEGORIES = [
    "missing-schema-evidence",
    "malformed-metadata",
    "unsupported-old-version",
    "unsupported-future-version",
    "partial-upgrade"
];
const DEFAULT_METADATA_TARGETS = [
    {
        family: "workspaceMetadata",
        relativePath: ".day-shift/config.toml",
        field: "config_schema_version",
        kind: "toml"
    },
    {
        family: "specification",
        relativePath: ".day-shift/specs",
        field: "artifact_schema_version",
        kind: "markdown-front-matter"
    },
    {
        family: "planning",
        relativePath: ".day-shift/planning",
        field: "artifact_schema_version",
        kind: "markdown-front-matter"
    },
    {
        family: "prompt",
        relativePath: ".day-shift/prompts/user",
        field: "prompt_version",
        kind: "markdown-front-matter"
    },
    {
        family: "template",
        relativePath: ".day-shift/templates/manifest.json",
        field: "template_version",
        kind: "json"
    },
    {
        family: "promptManifest",
        relativePath: ".day-shift/prompts/user/manifest.json",
        field: "prompt_manifest_version",
        kind: "json"
    },
    {
        family: "templateManifest",
        relativePath: ".day-shift/templates/manifest.json",
        field: "template_manifest_version",
        kind: "json"
    }
];
function discoverWorkspaceCompatibilityVersions(options) {
    const repositoryRoot = node_path_1.default.resolve(options.repositoryRoot);
    const targets = [...DEFAULT_METADATA_TARGETS];
    if (options.releaseManifestPath !== undefined && options.releaseManifestPath !== null) {
        targets.push({
            family: "releaseManifest",
            relativePath: options.releaseManifestPath,
            field: "schemaVersion",
            kind: "json"
        });
    }
    if (options.releaseRuntimeMetadataPath !== undefined && options.releaseRuntimeMetadataPath !== null) {
        targets.push({
            family: "releaseRuntimeMetadata",
            relativePath: options.releaseRuntimeMetadataPath,
            field: "schemaVersion",
            kind: "json"
        });
    }
    return targets.map((target) => readMetadataTarget(repositoryRoot, target));
}
function planWorkspaceSchemaMigration(options) {
    const targetSchemaVersion = options.targetSchemaVersion;
    const backupRoot = normalizeBackupRoot(options.backupRoot);
    const evidence = discoverWorkspaceCompatibilityVersions({
        repositoryRoot: options.repositoryRoot,
        releaseManifestPath: options.releaseManifestPath,
        releaseRuntimeMetadataPath: options.releaseRuntimeMetadataPath
    });
    const changes = [];
    const skippedArtifacts = [];
    const blockedArtifacts = [];
    if (!Number.isSafeInteger(targetSchemaVersion) || targetSchemaVersion < 1) {
        for (const item of evidence) {
            blockedArtifacts.push({
                family: item.family,
                path: item.path,
                field: item.field,
                detectedVersion: item.version,
                reason: "unsupported-target",
                message: `Target schema version ${String(targetSchemaVersion)} is not supported for workspace migration.`
            });
        }
        return createMigrationPlan({
            targetSchemaVersion,
            changes,
            skippedArtifacts,
            blockedArtifacts
        });
    }
    for (const item of evidence) {
        if (item.status === "missing") {
            skippedArtifacts.push({
                family: item.family,
                path: item.path,
                field: item.field,
                reason: "Schema metadata was not present in this workspace."
            });
            continue;
        }
        if (item.status === "malformed" || item.version === null) {
            blockedArtifacts.push({
                family: item.family,
                path: item.path,
                field: item.field,
                detectedVersion: item.version,
                reason: "malformed",
                message: `${item.field} is malformed and cannot be migrated safely.`
            });
            continue;
        }
        if (item.version === targetSchemaVersion) {
            skippedArtifacts.push({
                family: item.family,
                path: item.path,
                field: item.field,
                reason: "Artifact already uses the target schema version."
            });
            continue;
        }
        if (item.version > targetSchemaVersion) {
            blockedArtifacts.push({
                family: item.family,
                path: item.path,
                field: item.field,
                detectedVersion: item.version,
                reason: "lossy-downgrade",
                message: `Refusing to downgrade ${item.field} from ${item.version} to ${targetSchemaVersion}.`
            });
            continue;
        }
        changes.push({
            family: item.family,
            path: item.path,
            field: item.field,
            fromVersion: item.version,
            toVersion: targetSchemaVersion,
            backupPath: node_path_1.default.posix.join(backupRoot, item.path),
            coordinatedFields: getCoordinatedMigrationFields(item.family, item.field)
        });
    }
    return createMigrationPlan({
        targetSchemaVersion,
        changes,
        skippedArtifacts,
        blockedArtifacts
    });
}
function applyWorkspaceSchemaMigration(options) {
    const repositoryRoot = node_path_1.default.resolve(options.repositoryRoot);
    const plan = planWorkspaceSchemaMigration({
        repositoryRoot,
        targetSchemaVersion: options.targetSchemaVersion,
        backupRoot: options.backupRoot,
        releaseManifestPath: options.releaseManifestPath,
        releaseRuntimeMetadataPath: options.releaseRuntimeMetadataPath
    });
    if (plan.status === "blocked") {
        return {
            ...plan,
            dryRun: false,
            noWriteRequired: false,
            writeApplied: false,
            updatedArtifacts: [],
            backupArtifacts: []
        };
    }
    const updatedArtifacts = [];
    const backupArtifacts = [];
    for (const change of plan.changes) {
        const artifactPath = node_path_1.default.resolve(repositoryRoot, change.path);
        const backupPath = node_path_1.default.resolve(repositoryRoot, change.backupPath);
        node_fs_1.default.mkdirSync(node_path_1.default.dirname(backupPath), { recursive: true });
        node_fs_1.default.copyFileSync(artifactPath, backupPath);
        backupArtifacts.push(change.backupPath);
        const originalContent = node_fs_1.default.readFileSync(artifactPath, "utf8");
        const nextContent = updateSchemaVersionField(originalContent, change.field, change.toVersion, artifactPath);
        node_fs_1.default.writeFileSync(artifactPath, nextContent, "utf8");
        updatedArtifacts.push(change.path);
    }
    return {
        ...plan,
        dryRun: false,
        noWriteRequired: false,
        writeApplied: updatedArtifacts.length > 0,
        updatedArtifacts,
        backupArtifacts
    };
}
function checkWorkspaceCompatibility(options) {
    return options.evidence.map((evidence) => {
        const supportedRange = getRangeForFamily(options.compatibility, evidence.family);
        if (evidence.status === "absent") {
            return {
                family: evidence.family,
                status: "compatible",
                path: evidence.path,
                version: null,
                supportedRange,
                message: `${evidence.family} metadata is not yet present.`
            };
        }
        if (evidence.status === "missing") {
            return {
                family: evidence.family,
                status: "missing",
                path: evidence.path,
                version: null,
                supportedRange,
                message: `${evidence.family} metadata is missing.`
            };
        }
        if (evidence.status === "malformed" || evidence.version === null) {
            return {
                family: evidence.family,
                status: "malformed",
                path: evidence.path,
                version: evidence.version,
                supportedRange,
                message: `${evidence.family} metadata is malformed.`
            };
        }
        if (evidence.version < supportedRange.minimum) {
            return {
                family: evidence.family,
                status: "unsupported-old",
                path: evidence.path,
                version: evidence.version,
                supportedRange,
                message: `${evidence.family} schema version ${evidence.version} is older than supported minimum ${supportedRange.minimum}.`
            };
        }
        if (evidence.version > supportedRange.maximum) {
            return {
                family: evidence.family,
                status: "unsupported-future",
                path: evidence.path,
                version: evidence.version,
                supportedRange,
                message: `${evidence.family} schema version ${evidence.version} is newer than supported maximum ${supportedRange.maximum}.`
            };
        }
        return {
            family: evidence.family,
            status: "compatible",
            path: evidence.path,
            version: evidence.version,
            supportedRange,
            message: `${evidence.family} schema version ${evidence.version} is compatible.`
        };
    });
}
function createWorkspaceCompatibilityDiagnostics(options) {
    const evidenceByFamily = new Map();
    for (const evidence of options.evidence ?? []) {
        evidenceByFamily.set(evidence.family, evidence);
    }
    const diagnostics = options.checks.flatMap((check) => {
        if (!isIncompatibleCompatibilityCheck(check)) {
            return [];
        }
        const evidence = evidenceByFamily.get(check.family);
        return [
            createWorkspaceCompatibilityDiagnostic({
                check,
                field: evidence?.field ?? null
            })
        ];
    });
    const incompatibleVersionDiagnostics = diagnostics.filter((diagnostic) => diagnostic.category === "unsupported-old-version" ||
        diagnostic.category === "unsupported-future-version");
    const compatibleVersions = options.checks.filter((check) => check.status === "compatible");
    if (incompatibleVersionDiagnostics.length > 0 && compatibleVersions.length > 0) {
        const firstIncompatible = incompatibleVersionDiagnostics[0];
        diagnostics.push({
            category: "partial-upgrade",
            family: firstIncompatible.family,
            path: firstIncompatible.path,
            field: firstIncompatible.field,
            detectedVersion: firstIncompatible.detectedVersion,
            supportedRange: firstIncompatible.supportedRange,
            noWriteRequired: true,
            message: "Workspace metadata versions are partially upgraded across supported and unsupported families.",
            recovery: "Use a CLI release that supports every detected metadata family, or run an explicit migration with a compatible CLI before retrying this command."
        });
    }
    return diagnostics;
}
function isIncompatibleCompatibilityCheck(check) {
    return check.status !== "compatible";
}
function createWorkspaceCompatibilityFindings(diagnostics) {
    return diagnostics.map((diagnostic) => (0, output_1.createBlockingValidationFinding)({
        code: `workspace-compatibility-${diagnostic.category}`,
        message: diagnostic.message,
        path: diagnostic.path,
        blockingReason: "invalid-command-input",
        recovery: diagnostic.recovery,
        evidence: {
            category: "command-specific",
            details: {
                category: diagnostic.category,
                family: diagnostic.family,
                path: diagnostic.path,
                field: diagnostic.field,
                detectedVersion: diagnostic.detectedVersion,
                supportedRange: diagnostic.supportedRange,
                noWriteBoundary: "No workspace files were changed."
            }
        }
    }));
}
function readCompatibilityVersionRangeShape(value) {
    if (typeof value !== "object" || value === null || Array.isArray(value)) {
        return { ok: false, reason: "missing" };
    }
    const record = value;
    if (typeof record.minimum !== "number" ||
        typeof record.maximum !== "number" ||
        !Number.isSafeInteger(record.minimum) ||
        !Number.isSafeInteger(record.maximum) ||
        record.minimum < 1 ||
        record.maximum < 1) {
        return { ok: false, reason: "malformed" };
    }
    if (record.minimum > record.maximum) {
        return { ok: false, reason: "contradictory" };
    }
    return {
        ok: true,
        range: {
            minimum: record.minimum,
            maximum: record.maximum
        }
    };
}
function readMarkdownTraceabilityCompatibility(options) {
    const repositoryRoot = node_path_1.default.resolve(options.repositoryRoot);
    const absolutePath = node_path_1.default.resolve(repositoryRoot, options.artifactPath);
    const relativePath = toRepositoryRelativePath(repositoryRoot, absolutePath);
    if (!node_fs_1.default.existsSync(absolutePath) || !node_fs_1.default.statSync(absolutePath).isFile()) {
        return traceabilityIssue("missing", relativePath, null, null, "Markdown artifact does not exist.");
    }
    try {
        const parsed = (0, planning_document_utils_1.parseMarkdownFrontMatter)(node_fs_1.default.readFileSync(absolutePath, "utf8"));
        const artifactType = parsed.hasFrontMatter
            ? (0, planning_document_utils_1.readTopLevelField)(parsed.frontMatterLines, "artifact_type") ?? null
            : null;
        if (!parsed.hasFrontMatter) {
            return traceabilityIssue("malformed", relativePath, artifactType, null, "Markdown artifact has no parseable front matter.");
        }
        const sourceEvidence = readSourceTraceability(parsed.frontMatterLines);
        if (sourceEvidence !== null) {
            return traceabilitySuccess(relativePath, artifactType, "source", [sourceEvidence]);
        }
        const upstreamSpecsEvidence = readUpstreamSpecsTraceability(parsed.frontMatterLines);
        if (upstreamSpecsEvidence !== null) {
            return upstreamSpecsEvidence.length > 0
                ? traceabilitySuccess(relativePath, artifactType, "upstream.specs", upstreamSpecsEvidence)
                : traceabilityIssue("malformed", relativePath, artifactType, "upstream.specs", "upstream.specs is present but contains no readable spec references.");
        }
        const upstreamSpecEvidence = readUpstreamSpecTraceability(parsed.frontMatterLines);
        if (upstreamSpecEvidence !== null) {
            return upstreamSpecEvidence.ref.trim() !== ""
                ? traceabilitySuccess(relativePath, artifactType, "upstream.spec", [upstreamSpecEvidence])
                : traceabilityIssue("malformed", relativePath, artifactType, "upstream.spec", "upstream.spec is present but does not contain a readable spec reference.");
        }
        return traceabilityIssue("missing", relativePath, artifactType, null, "No supported source or upstream spec traceability shape was found.");
    }
    catch (error) {
        const message = error instanceof Error ? error.message : "Markdown traceability could not be read.";
        return traceabilityIssue("malformed", relativePath, null, null, message);
    }
}
function readWorkspaceAssetMetadataCompatibility(options) {
    const repositoryRoot = node_path_1.default.resolve(options.repositoryRoot);
    const absolutePath = node_path_1.default.resolve(repositoryRoot, options.artifactPath);
    const relativePath = toRepositoryRelativePath(repositoryRoot, absolutePath);
    if (!node_fs_1.default.existsSync(absolutePath) || !node_fs_1.default.statSync(absolutePath).isFile()) {
        return assetMetadataIssue("missing", relativePath, null, "Metadata asset does not exist.");
    }
    try {
        if (absolutePath.endsWith(".json")) {
            const parsed = JSON.parse(node_fs_1.default.readFileSync(absolutePath, "utf8"));
            if (typeof parsed.prompt_manifest_version === "number") {
                return readPromptManifestCompatibility(relativePath, parsed);
            }
            if (typeof parsed.template_manifest_version === "number") {
                return readTemplateManifestCompatibility(relativePath, parsed);
            }
            return assetMetadataIssue("malformed", relativePath, null, "JSON metadata is not a supported prompt or template manifest.");
        }
        if (absolutePath.endsWith(".md")) {
            return readMarkdownAssetCompatibility(relativePath, node_fs_1.default.readFileSync(absolutePath, "utf8"));
        }
        return assetMetadataIssue("malformed", relativePath, null, "Metadata asset extension is not supported.");
    }
    catch (error) {
        const message = error instanceof Error ? error.message : "Metadata asset could not be read.";
        return assetMetadataIssue("malformed", relativePath, null, message);
    }
}
function readMetadataTarget(repositoryRoot, target) {
    const absolutePath = node_path_1.default.resolve(repositoryRoot, target.relativePath);
    if (target.kind === "markdown-front-matter") {
        const markdownPath = node_fs_1.default.existsSync(absolutePath) && node_fs_1.default.statSync(absolutePath).isFile()
            ? findFirstMarkdownFile(absolutePath)
            : findFirstMarkdownFileWithField(absolutePath, target.field);
        if (markdownPath === null) {
            if (target.family === "planning" && planningRootHasNoMarkdownArtifacts(absolutePath)) {
                return absentEvidence(target);
            }
            return missingEvidence(target);
        }
        return readMarkdownVersion(repositoryRoot, markdownPath, target);
    }
    if (!node_fs_1.default.existsSync(absolutePath) || !node_fs_1.default.statSync(absolutePath).isFile()) {
        return missingEvidence(target);
    }
    if (target.kind === "json") {
        return readJsonVersion(repositoryRoot, absolutePath, target);
    }
    return readTomlVersion(repositoryRoot, absolutePath, target);
}
function readMarkdownVersion(repositoryRoot, absolutePath, target) {
    const relativePath = toRepositoryRelativePath(repositoryRoot, absolutePath);
    try {
        const parsed = (0, planning_document_utils_1.parseMarkdownFrontMatter)(node_fs_1.default.readFileSync(absolutePath, "utf8"));
        const rawVersion = parsed.hasFrontMatter
            ? (0, planning_document_utils_1.readTopLevelField)(parsed.frontMatterLines, target.field)
            : undefined;
        return versionEvidence({
            target,
            relativePath,
            rawVersion
        });
    }
    catch {
        return malformedEvidence(target, relativePath);
    }
}
function readJsonVersion(repositoryRoot, absolutePath, target) {
    const relativePath = toRepositoryRelativePath(repositoryRoot, absolutePath);
    try {
        const parsed = JSON.parse(node_fs_1.default.readFileSync(absolutePath, "utf8"));
        return versionEvidence({
            target,
            relativePath,
            rawVersion: parsed[target.field]
        });
    }
    catch {
        return malformedEvidence(target, relativePath);
    }
}
function readTomlVersion(repositoryRoot, absolutePath, target) {
    const relativePath = toRepositoryRelativePath(repositoryRoot, absolutePath);
    try {
        const rawVersion = readTopLevelTomlField(node_fs_1.default.readFileSync(absolutePath, "utf8"), target.field);
        return versionEvidence({
            target,
            relativePath,
            rawVersion
        });
    }
    catch {
        return malformedEvidence(target, relativePath);
    }
}
function versionEvidence(options) {
    const version = parseSchemaVersion(options.rawVersion);
    if (version === null) {
        return malformedEvidence(options.target, options.relativePath);
    }
    return {
        family: options.target.family,
        status: "discovered",
        path: options.relativePath,
        version,
        field: options.target.field,
        message: `${options.target.field}=${version}`
    };
}
function missingEvidence(target) {
    return {
        family: target.family,
        status: "missing",
        path: target.relativePath,
        version: null,
        field: target.field,
        message: `${target.field} was not found.`
    };
}
function absentEvidence(target) {
    return {
        family: target.family,
        status: "absent",
        path: target.relativePath,
        version: null,
        field: target.field,
        message: `${target.family} metadata is not yet present.`
    };
}
function malformedEvidence(target, relativePath) {
    return {
        family: target.family,
        status: "malformed",
        path: relativePath,
        version: null,
        field: target.field,
        message: `${target.field} is missing or malformed.`
    };
}
function normalizeBackupRoot(backupRoot) {
    const normalized = (backupRoot ?? ".day-shift/backups/workspace-migrations").replace(/\\/g, "/").replace(/\/+$/g, "");
    return normalized.length === 0 ? ".day-shift/backups/workspace-migrations" : normalized;
}
function updateSchemaVersionField(content, field, value, artifactPath) {
    if (artifactPath.endsWith(".json")) {
        const parsed = JSON.parse(content);
        parsed[field] = value;
        return `${JSON.stringify(parsed, null, 2)}\n`;
    }
    if (artifactPath.endsWith(".toml")) {
        return replaceScalarLine(content, field, `${value}`);
    }
    if (artifactPath.endsWith(".md")) {
        return replaceMarkdownFrontMatterScalar(content, field, `${value}`);
    }
    throw new TypeError(`Unsupported migration artifact extension for '${artifactPath}'.`);
}
function replaceScalarLine(content, field, value) {
    const lines = content.split(/\n/);
    const fieldPattern = new RegExp(`^(\\s*${escapeRegExp(field)}\\s*=\\s*).*$`);
    let replaced = false;
    const nextLines = lines.map((line) => {
        if (!replaced && fieldPattern.test(line)) {
            replaced = true;
            return line.replace(fieldPattern, `$1${value}`);
        }
        return line;
    });
    if (!replaced) {
        throw new TypeError(`Cannot migrate missing field '${field}'.`);
    }
    return nextLines.join("\n");
}
function replaceMarkdownFrontMatterScalar(content, field, value) {
    const lines = content.split(/\n/);
    if (lines[0]?.trim() !== "---") {
        throw new TypeError(`Cannot migrate '${field}' because Markdown front matter is missing.`);
    }
    const fieldPattern = new RegExp(`^(\\s*${escapeRegExp(field)}\\s*:\\s*).*$`);
    for (let index = 1; index < lines.length; index += 1) {
        if (lines[index].trim() === "---") {
            break;
        }
        if (fieldPattern.test(lines[index])) {
            lines[index] = lines[index].replace(fieldPattern, `$1${value}`);
            return lines.join("\n");
        }
    }
    throw new TypeError(`Cannot migrate missing field '${field}'.`);
}
function escapeRegExp(value) {
    return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function createMigrationPlan(options) {
    const status = options.blockedArtifacts.length > 0
        ? "blocked"
        : options.changes.length > 0
            ? "ready"
            : "no-op";
    return {
        status,
        dryRun: true,
        targetSchemaVersion: options.targetSchemaVersion,
        changes: options.changes,
        skippedArtifacts: options.skippedArtifacts,
        blockedArtifacts: options.blockedArtifacts,
        noWriteRequired: true
    };
}
function getCoordinatedMigrationFields(family, field) {
    if (family === "planning") {
        return [
            field,
            "upstream.specs",
            "upstream.slice_overview",
            "upstream.phase_overview",
            "upstream.milestone_overview",
            "upstream.task_definition",
            "status",
            "readiness",
            "implementation_status",
            "reconciliation_status"
        ];
    }
    if (family === "specification") {
        return [field, "source.ref", "source.type", "status"];
    }
    if (family === "prompt") {
        return [field, "layer", "action"];
    }
    if (family === "template") {
        return [field, "template_version", "artifact_type"];
    }
    if (family === "promptManifest") {
        return [field, "prompt_version", "prompts[].path", "prompts[].version"];
    }
    if (family === "templateManifest") {
        return [field, "template_version", "templates[].path", "templates[].version"];
    }
    return [field];
}
function getRangeForFamily(compatibility, family) {
    if (family === "workspaceMetadata") {
        return compatibility.workspaceMetadata;
    }
    return compatibility.artifactSchemas[family];
}
function createWorkspaceCompatibilityDiagnostic(options) {
    const { check } = options;
    const category = getCompatibilityDiagnosticCategory(check.status);
    const recovery = getCompatibilityRecovery(category);
    return {
        category,
        family: check.family,
        path: check.path,
        field: options.field,
        detectedVersion: check.version,
        supportedRange: check.supportedRange,
        noWriteRequired: true,
        message: check.message,
        recovery
    };
}
function getCompatibilityDiagnosticCategory(status) {
    switch (status) {
        case "missing":
            return "missing-schema-evidence";
        case "malformed":
            return "malformed-metadata";
        case "unsupported-old":
            return "unsupported-old-version";
        case "unsupported-future":
            return "unsupported-future-version";
    }
}
function getCompatibilityRecovery(category) {
    switch (category) {
        case "missing-schema-evidence":
            return "Restore the missing schema metadata or inspect the workspace with a CLI release that supports this artifact shape before retrying.";
        case "malformed-metadata":
            return "Repair malformed metadata with a compatible CLI or from source control before retrying; this command did not rewrite the artifact.";
        case "unsupported-old-version":
            return "Run an explicit migration with a CLI release that still supports this older schema version, then retry with the current CLI.";
        case "unsupported-future-version":
            return "Use a newer CLI release that supports the detected schema version; the current CLI will not parse it as current metadata.";
        case "partial-upgrade":
            return "Use one compatible CLI release for the whole workspace or complete an explicit migration before retrying.";
    }
}
function findFirstMarkdownFile(rootPath) {
    if (!node_fs_1.default.existsSync(rootPath)) {
        return null;
    }
    if (node_fs_1.default.statSync(rootPath).isFile()) {
        return rootPath.endsWith(".md") ? rootPath : null;
    }
    for (const entry of node_fs_1.default.readdirSync(rootPath, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name))) {
        const childPath = node_path_1.default.join(rootPath, entry.name);
        if (entry.isDirectory()) {
            const nested = findFirstMarkdownFile(childPath);
            if (nested !== null) {
                return nested;
            }
        }
        else if (entry.isFile() && entry.name.endsWith(".md")) {
            return childPath;
        }
    }
    return null;
}
function findFirstMarkdownFileWithField(rootPath, field) {
    if (!node_fs_1.default.existsSync(rootPath)) {
        return null;
    }
    const markdownFiles = collectMarkdownFiles(rootPath);
    for (const markdownFile of markdownFiles) {
        try {
            const parsed = (0, planning_document_utils_1.parseMarkdownFrontMatter)(node_fs_1.default.readFileSync(markdownFile, "utf8"));
            if (parsed.hasFrontMatter && (0, planning_document_utils_1.readTopLevelField)(parsed.frontMatterLines, field) !== undefined) {
                return markdownFile;
            }
        }
        catch {
            continue;
        }
    }
    return null;
}
function collectMarkdownFiles(rootPath) {
    if (!node_fs_1.default.existsSync(rootPath)) {
        return [];
    }
    if (node_fs_1.default.statSync(rootPath).isFile()) {
        return rootPath.endsWith(".md") ? [rootPath] : [];
    }
    const files = [];
    for (const entry of node_fs_1.default.readdirSync(rootPath, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name))) {
        const childPath = node_path_1.default.join(rootPath, entry.name);
        if (entry.isDirectory()) {
            files.push(...collectMarkdownFiles(childPath));
        }
        else if (entry.isFile() && entry.name.endsWith(".md")) {
            files.push(childPath);
        }
    }
    return files;
}
function planningRootHasNoMarkdownArtifacts(rootPath) {
    return node_fs_1.default.existsSync(rootPath)
        && node_fs_1.default.statSync(rootPath).isDirectory()
        && collectMarkdownFiles(rootPath).length === 0;
}
function readTopLevelTomlField(content, field) {
    for (const line of content.split(/\r?\n/)) {
        if (/^\s*\[/.test(line)) {
            return undefined;
        }
        const match = line.match(/^([A-Za-z0-9_]+)\s*=\s*(.+)$/);
        if (match !== null && match[1] === field) {
            return match[2].trim().replace(/^"|"$/g, "");
        }
    }
    return undefined;
}
function readSourceTraceability(lines) {
    const sourceBlock = readIndentedObject(lines, "source");
    if (sourceBlock === null) {
        return null;
    }
    const ref = sourceBlock.ref;
    if (typeof ref !== "string" || ref.trim() === "") {
        return null;
    }
    return {
        id: readOptionalString((0, planning_document_utils_1.readTopLevelField)(lines, "spec_id")),
        depth: readOptionalString((0, planning_document_utils_1.readTopLevelField)(lines, "depth")),
        ref,
        sourceType: readOptionalString(sourceBlock.type)
    };
}
function readMarkdownAssetCompatibility(relativePath, content) {
    const parsed = (0, planning_document_utils_1.parseMarkdownFrontMatter)(content);
    if (!parsed.hasFrontMatter) {
        return assetMetadataIssue("malformed", relativePath, null, "Markdown metadata asset has no parseable front matter.");
    }
    const promptVersion = parseSchemaVersion((0, planning_document_utils_1.readTopLevelField)(parsed.frontMatterLines, "prompt_version"));
    if (promptVersion !== null) {
        const layer = readOptionalString((0, planning_document_utils_1.readTopLevelField)(parsed.frontMatterLines, "layer"));
        const action = readOptionalString((0, planning_document_utils_1.readTopLevelField)(parsed.frontMatterLines, "action"));
        if (layer === null || action === null) {
            return assetMetadataIssue("malformed", relativePath, "prompt", "Prompt metadata is missing layer or action.");
        }
        return {
            status: "normalized",
            path: relativePath,
            family: "prompt",
            documentVersion: promptVersion,
            familyVersion: promptVersion,
            entries: [
                {
                    path: relativePath,
                    version: promptVersion,
                    layer,
                    action,
                    kind: null,
                    artifactType: null,
                    destination: null,
                    templateRefShape: "none",
                    templateRefs: []
                }
            ],
            message: "Prompt Markdown metadata was read without rewriting the artifact."
        };
    }
    const templateVersion = parseSchemaVersion((0, planning_document_utils_1.readTopLevelField)(parsed.frontMatterLines, "template_version"))
        ?? parseSchemaVersion((0, planning_document_utils_1.readTopLevelField)(parsed.frontMatterLines, "artifact_schema_version"));
    const artifactType = readOptionalString((0, planning_document_utils_1.readTopLevelField)(parsed.frontMatterLines, "artifact_type"));
    if (templateVersion === null || artifactType === null) {
        return assetMetadataIssue("malformed", relativePath, "template", "Template metadata is missing a readable version or artifact_type.");
    }
    return {
        status: "normalized",
        path: relativePath,
        family: "template",
        documentVersion: templateVersion,
        familyVersion: templateVersion,
        entries: [
            {
                path: relativePath,
                version: templateVersion,
                layer: null,
                action: null,
                kind: "artifact",
                artifactType,
                destination: null,
                templateRefShape: "none",
                templateRefs: []
            }
        ],
        message: "Template Markdown metadata was read without rewriting the artifact."
    };
}
function readPromptManifestCompatibility(relativePath, document) {
    const prompts = document.prompts;
    if (!Array.isArray(prompts)) {
        return assetMetadataIssue("malformed", relativePath, "promptManifest", "Prompt manifest is missing prompts[].");
    }
    return {
        status: "normalized",
        path: relativePath,
        family: "promptManifest",
        documentVersion: parseSchemaVersion(document.prompt_manifest_version),
        familyVersion: parseSchemaVersion(document.prompt_version),
        entries: prompts.map((entry) => normalizePromptManifestEntry(entry)).filter(isAssetEntry),
        message: "Prompt manifest metadata was read without rewriting the artifact."
    };
}
function readTemplateManifestCompatibility(relativePath, document) {
    const templates = document.templates;
    if (!Array.isArray(templates)) {
        return assetMetadataIssue("malformed", relativePath, "templateManifest", "Template manifest is missing templates[].");
    }
    return {
        status: "normalized",
        path: relativePath,
        family: "templateManifest",
        documentVersion: parseSchemaVersion(document.template_manifest_version),
        familyVersion: parseSchemaVersion(document.template_version),
        entries: templates.map((entry) => normalizeTemplateManifestEntry(entry)).filter(isAssetEntry),
        message: "Template manifest metadata was read without rewriting the artifact."
    };
}
function normalizePromptManifestEntry(entry) {
    if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
        return null;
    }
    const record = entry;
    const entryPath = readOptionalString(record.path);
    const layer = readOptionalString(record.layer);
    const action = readOptionalString(record.action);
    if (entryPath === null || layer === null || action === null) {
        return null;
    }
    const templateRefs = normalizeTemplateRefs(record);
    return {
        path: entryPath,
        version: parseSchemaVersion(record.version),
        layer,
        action,
        kind: null,
        artifactType: null,
        destination: null,
        templateRefShape: templateRefs.shape,
        templateRefs: templateRefs.refs
    };
}
function normalizeTemplateManifestEntry(entry) {
    if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
        return null;
    }
    const record = entry;
    const entryPath = readOptionalString(record.path);
    if (entryPath === null) {
        return null;
    }
    return {
        path: entryPath,
        version: parseSchemaVersion(record.version),
        layer: null,
        action: null,
        kind: readOptionalString(record.kind),
        artifactType: readOptionalString(record.artifact_type),
        destination: readOptionalString(record.destination),
        templateRefShape: "none",
        templateRefs: []
    };
}
function normalizeTemplateRefs(record) {
    if (typeof record.template_ref === "string" && record.template_ref.trim() !== "") {
        return {
            shape: "template_ref",
            refs: [record.template_ref]
        };
    }
    if (Array.isArray(record.template_refs)) {
        return {
            shape: "template_refs",
            refs: record.template_refs.filter((value) => typeof value === "string" && value.trim() !== "")
        };
    }
    return {
        shape: "none",
        refs: []
    };
}
function isAssetEntry(entry) {
    return entry !== null;
}
function assetMetadataIssue(status, relativePath, family, message) {
    return {
        status,
        path: relativePath,
        family,
        documentVersion: null,
        familyVersion: null,
        entries: [],
        message
    };
}
function readUpstreamSpecTraceability(lines) {
    const scalarSpec = (0, planning_document_utils_1.readUpstreamField)(lines, "spec");
    if (scalarSpec !== undefined && scalarSpec.trim() !== "") {
        return {
            id: null,
            depth: null,
            ref: scalarSpec,
            sourceType: null
        };
    }
    const upstreamBlock = readIndentedObject(lines, "upstream");
    if (upstreamBlock === null || upstreamBlock.spec !== "") {
        return null;
    }
    const specBlock = readNestedObject(lines, ["upstream", "spec"]);
    const ref = specBlock?.ref;
    if (specBlock === null || typeof ref !== "string" || ref.trim() === "") {
        return null;
    }
    return {
        id: readOptionalString(specBlock.id),
        depth: readOptionalString(specBlock.depth),
        ref,
        sourceType: readOptionalString(specBlock.source_type)
    };
}
function readUpstreamSpecsTraceability(lines) {
    if (!hasNestedSequence(lines, ["upstream", "specs"])) {
        return null;
    }
    return readNestedObjectSequence(lines, ["upstream", "specs"])
        .map((entry) => {
        const ref = entry.ref;
        if (typeof ref !== "string" || ref.trim() === "") {
            return null;
        }
        return {
            id: readOptionalString(entry.id),
            depth: readOptionalString(entry.depth),
            ref,
            sourceType: readOptionalString(entry.source_type)
        };
    })
        .filter((entry) => entry !== null);
}
function traceabilitySuccess(relativePath, artifactType, shape, specs) {
    return {
        status: "normalized",
        path: relativePath,
        artifactType,
        shape,
        specs,
        message: `${shape} traceability was read without rewriting the artifact.`
    };
}
function traceabilityIssue(status, relativePath, artifactType, shape, message) {
    return {
        status,
        path: relativePath,
        artifactType,
        shape,
        specs: [],
        message
    };
}
function readOptionalString(value) {
    return typeof value === "string" && value.trim() !== "" ? value : null;
}
function readIndentedObject(lines, key) {
    const startIndex = lines.findIndex((line) => line === `${key}:`);
    if (startIndex < 0) {
        return null;
    }
    const object = {};
    for (let index = startIndex + 1; index < lines.length; index += 1) {
        const line = lines[index];
        if (/^[^\s]/.test(line)) {
            break;
        }
        const match = line.match(/^\s{2}([A-Za-z0-9_]+):\s*(.*)$/);
        if (match !== null) {
            object[match[1]] = (0, planning_document_utils_1.parseScalar)(match[2]);
        }
    }
    return object;
}
function readNestedObject(lines, pathSegments) {
    const startIndex = findNestedKeyIndex(lines, pathSegments);
    if (startIndex < 0) {
        return null;
    }
    const indent = (pathSegments.length + 1) * 2;
    const childPattern = new RegExp(`^\\s{${indent}}([A-Za-z0-9_]+):\\s*(.*)$`);
    const object = {};
    for (let index = startIndex + 1; index < lines.length; index += 1) {
        const line = lines[index];
        const leadingSpaces = line.match(/^ */)?.[0].length ?? 0;
        if (line.trim() !== "" && leadingSpaces <= indent - 2) {
            break;
        }
        const match = line.match(childPattern);
        if (match !== null) {
            object[match[1]] = (0, planning_document_utils_1.parseScalar)(match[2]);
        }
    }
    return object;
}
function hasNestedSequence(lines, pathSegments) {
    return findNestedKeyIndex(lines, pathSegments) >= 0;
}
function readNestedObjectSequence(lines, pathSegments) {
    const startIndex = findNestedKeyIndex(lines, pathSegments);
    if (startIndex < 0) {
        return [];
    }
    const itemIndent = pathSegments.length * 2;
    const itemPattern = new RegExp(`^\\s{${itemIndent}}-\\s+([A-Za-z0-9_]+):\\s*(.*)$`);
    const propertyPattern = new RegExp(`^\\s{${itemIndent + 2}}([A-Za-z0-9_]+):\\s*(.*)$`);
    const items = [];
    let current = null;
    for (let index = startIndex + 1; index < lines.length; index += 1) {
        const line = lines[index];
        const leadingSpaces = line.match(/^ */)?.[0].length ?? 0;
        if (line.trim() !== "" && leadingSpaces < itemIndent) {
            break;
        }
        const itemMatch = line.match(itemPattern);
        if (itemMatch !== null) {
            current = { [itemMatch[1]]: (0, planning_document_utils_1.parseScalar)(itemMatch[2]) };
            items.push(current);
            continue;
        }
        const propertyMatch = line.match(propertyPattern);
        if (propertyMatch !== null && current !== null) {
            current[propertyMatch[1]] = (0, planning_document_utils_1.parseScalar)(propertyMatch[2]);
        }
    }
    return items;
}
function findNestedKeyIndex(lines, pathSegments) {
    let searchStart = 0;
    for (let segmentIndex = 0; segmentIndex < pathSegments.length; segmentIndex += 1) {
        const segment = pathSegments[segmentIndex];
        const indent = segmentIndex * 2;
        const pattern = new RegExp(`^\\s{${indent}}${segment}:\\s*$`);
        const matchIndex = lines.findIndex((line, index) => index >= searchStart && pattern.test(line));
        if (matchIndex < 0) {
            return -1;
        }
        searchStart = matchIndex + 1;
    }
    return searchStart - 1;
}
function parseSchemaVersion(value) {
    if (typeof value === "number" && Number.isSafeInteger(value) && value > 0) {
        return value;
    }
    if (typeof value === "string" && /^\d+$/.test(value.trim())) {
        const version = Number(value.trim());
        return Number.isSafeInteger(version) && version > 0 ? version : null;
    }
    return null;
}
function toRepositoryRelativePath(repositoryRoot, absolutePath) {
    return node_path_1.default.relative(repositoryRoot, absolutePath).split(node_path_1.default.sep).join("/");
}
