"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.toRepositoryLikePath = exports.parseScalar = void 0;
exports.applyPlanningFrontMatterFieldUpdates = applyPlanningFrontMatterFieldUpdates;
exports.applyStatusAndPlanningFieldTransition = applyStatusAndPlanningFieldTransition;
exports.applyNonArtifactFrontMatterFieldUpdates = applyNonArtifactFrontMatterFieldUpdates;
exports.applyManifestMetadataFieldUpdates = applyManifestMetadataFieldUpdates;
exports.toTitleCase = toTitleCase;
const paths_1 = require("../paths");
const planning_document_utils_1 = require("./planning-document-utils");
const workflow_provenance_1 = require("./workflow-provenance");
var planning_document_utils_2 = require("./planning-document-utils");
Object.defineProperty(exports, "parseScalar", { enumerable: true, get: function () { return planning_document_utils_2.parseScalar; } });
Object.defineProperty(exports, "toRepositoryLikePath", { enumerable: true, get: function () { return planning_document_utils_2.toRepositoryLikePath; } });
const STATUS_FIELD_KEYS = new Set([
    "status",
    "readiness",
    "implementation_status",
    "reconciliation_status"
]);
const PLANNING_FIELD_KEYS = new Set([
    "slice",
    "phase",
    "milestone",
    "task",
    "planning_depth"
]);
const PROMPT_FRONT_MATTER_KEYS = new Set([
    "prompt_version",
    "layer",
    "action"
]);
const ALLOWED_PROMPT_LAYER_VALUES = new Set([
    "specification",
    "slice",
    "phase",
    "milestone",
    "task",
    "implementation",
    "reconciliation"
]);
const ALLOWED_PROMPT_ACTION_VALUES = new Set([
    "build",
    "next",
    "review"
]);
const MANIFEST_ENTRY_KEYS = new Set([
    "path",
    "version",
    "layer",
    "action",
    "kind",
    "artifact_type",
    "template_ref",
    "template_refs",
    "destination",
    "usage",
    "notes"
]);
const ALLOWED_READINESS_VALUES = new Set([
    "needs more evidence",
    "ready",
    "ready to implement",
    "blocked",
    "completed"
]);
const ALLOWED_IMPLEMENTATION_STATUS_VALUES = new Set([
    "pending",
    "completed"
]);
const ALLOWED_RECONCILIATION_STATUS_VALUES = new Set([
    "pending",
    "ready_for_review",
    "blocked",
    "completed"
]);
const ALLOWED_SHARED_STATUS_VALUES = new Set([
    "draft",
    "active",
    "blocked",
    "completed"
]);
const ALLOWED_EXECUTION_MODE_VALUES = new Set([
    "contract",
    "runtime",
    "hybrid"
]);
const EXECUTION_MODE_ARTIFACT_TYPES = new Set([
    "task_definition",
    "implementation_summary"
]);
const COMMAND_SUPPORTED_PLANNING_ARTIFACT_TYPES = new Set([
    "slice_overview",
    "phase_overview",
    "milestone_overview",
    "task_definition",
    "implementation_summary",
    "reconciliation"
]);
const WORKFLOW_PROVENANCE_FIELD_KEYS = [
    "workflow_provenance",
    "workflow_cli_command",
    "workflow_manual_exception"
];
const ALLOWED_WORKFLOW_LEVEL_VALUES = new Set(["basic", "structured", "governed"]);
const ALLOWED_AGENT_MODE_VALUES = new Set(["autonomous", "guided", "interactive"]);
const IMMUTABLE_MANIFEST_ENTRY_IDENTITY_KEYS = new Set([
    "path",
    "kind",
    "artifact_type"
]);
const ALLOWED_PROMPT_MANIFEST_TOP_LEVEL_KEYS = new Set([
    "prompt_manifest_version",
    "generated_at",
    "prompt_version",
    "notes",
    "prompts"
]);
const ALLOWED_TEMPLATE_MANIFEST_TOP_LEVEL_KEYS = new Set([
    "template_manifest_version",
    "generated_at",
    "template_version",
    "prompt_version",
    "notes",
    "templates"
]);
const ALLOWED_PROMPT_MANIFEST_ENTRY_KEYS = new Set([
    "path",
    "version",
    "layer",
    "action",
    "template_ref",
    "template_refs",
    "usage",
    "notes"
]);
const ALLOWED_TEMPLATE_MANIFEST_ENTRY_KEYS = new Set([
    "path",
    "version",
    "kind",
    "artifact_type",
    "destination",
    "usage",
    "notes"
]);
const PLANNING_IDENTITY_KEYS_BY_ARTIFACT_TYPE = {
    specification: [],
    slice_overview: ["slice"],
    phase_overview: ["slice", "phase"],
    milestone_overview: ["slice", "phase", "milestone"],
    task_definition: ["slice", "phase", "milestone", "task"],
    implementation_summary: ["slice", "phase", "milestone", "task"],
    reconciliation: ["slice", "phase", "milestone"]
};
const PLANNING_DEPTH_APPLICABLE_ARTIFACT_TYPES = new Set([
    "slice_overview",
    "phase_overview",
    "milestone_overview",
    "task_definition",
    "implementation_summary",
    "reconciliation"
]);
const STATUS_FIELDS_BY_ARTIFACT_TYPE = {
    specification: ["status"],
    slice_overview: ["status"],
    phase_overview: ["status"],
    milestone_overview: ["status"],
    task_definition: ["status", "readiness"],
    implementation_summary: ["status", "implementation_status"],
    reconciliation: ["status", "reconciliation_status"]
};
function applyPlanningFrontMatterFieldUpdates(markdownText, updates, options = {}) {
    const lines = markdownText.split(/\r?\n/);
    if (lines[0] !== "---") {
        throw new TypeError("Planning artifact is missing YAML front matter.");
    }
    const closingIndex = lines.findIndex((line, index) => index > 0 && line === "---");
    if (closingIndex === -1) {
        throw new TypeError("Planning artifact front matter is malformed.");
    }
    const normalizedUpdates = normalizeRepositoryRelativePathUpdates(updates, options.repositoryRelativePathKeys ?? []);
    const identityKeys = new Set(options.identityKeys ?? ["slice", "phase", "milestone", "task"]);
    const presentKeys = new Set();
    const nextLines = [...lines];
    for (let index = 1; index < closingIndex; index += 1) {
        const line = lines[index];
        const topLevelMatch = line.match(/^([A-Za-z0-9_]+):\s*(.*)$/);
        if (topLevelMatch !== null) {
            const key = topLevelMatch[1];
            presentKeys.add(key);
            if (normalizedUpdates[key] !== undefined) {
                assertNoIdentityRewrite(topLevelMatch[2], normalizedUpdates[key], key, identityKeys);
                nextLines[index] = `${key}: ${formatScalarPreservingQuoteStyle(topLevelMatch[2], normalizedUpdates[key])}`;
            }
            continue;
        }
        const upstreamMatch = line.match(/^\s{2}([A-Za-z0-9_]+):\s*(.*)$/);
        if (upstreamMatch !== null) {
            const key = `upstream.${upstreamMatch[1]}`;
            presentKeys.add(key);
            if (normalizedUpdates[key] !== undefined) {
                nextLines[index] = `  ${upstreamMatch[1]}: ${formatScalarPreservingQuoteStyle(upstreamMatch[2], normalizedUpdates[key])}`;
            }
        }
    }
    assertRequiredKeysPresent(options.requiredKeys ?? [], presentKeys);
    const executionMode = normalizedUpdates.execution_mode;
    if (executionMode !== undefined) {
        const artifactType = (0, planning_document_utils_1.readTopLevelField)(lines.slice(1, closingIndex), "artifact_type")?.trim();
        if (artifactType === undefined || !EXECUTION_MODE_ARTIFACT_TYPES.has(artifactType)) {
            throw new TypeError(`Front matter field 'execution_mode' is not applicable to artifact_type '${artifactType ?? "(missing)"}'.`);
        }
        if (!ALLOWED_EXECUTION_MODE_VALUES.has(executionMode)) {
            throw new TypeError(`Unsupported execution_mode token '${executionMode}'.`);
        }
        if (!presentKeys.has("execution_mode")) {
            nextLines.splice(closingIndex, 0, `execution_mode: ${executionMode}`);
        }
    }
    const artifactType = (0, planning_document_utils_1.readTopLevelField)(lines.slice(1, closingIndex), "artifact_type")?.trim();
    const planningDepth = normalizedUpdates.planning_depth;
    if (planningDepth !== undefined && !presentKeys.has("planning_depth")) {
        if (artifactType === undefined || !PLANNING_DEPTH_APPLICABLE_ARTIFACT_TYPES.has(artifactType)) {
            throw new TypeError(`Front matter field 'planning_depth' is not applicable to artifact_type '${artifactType ?? "(missing)"}'.`);
        }
        nextLines.splice(closingIndex, 0, `planning_depth: ${planningDepth}`);
    }
    validateAndInsertPolicyField({
        key: "workflow_level",
        value: normalizedUpdates.workflow_level,
        allowedValues: ALLOWED_WORKFLOW_LEVEL_VALUES,
        artifactType,
        presentKeys,
        nextLines,
        insertionIndex: closingIndex
    });
    validateAndInsertPolicyField({
        key: "agent_mode",
        value: normalizedUpdates.agent_mode,
        allowedValues: ALLOWED_AGENT_MODE_VALUES,
        artifactType,
        presentKeys,
        nextLines,
        insertionIndex: closingIndex
    });
    validateAndInsertPolicyField({
        key: "evidence_profile",
        value: normalizedUpdates.evidence_profile,
        allowedValues: ALLOWED_EXECUTION_MODE_VALUES,
        artifactType,
        presentKeys,
        nextLines,
        insertionIndex: closingIndex
    });
    validateAndInsertWorkflowProvenanceFields({
        normalizedUpdates,
        artifactType,
        presentKeys,
        nextLines
    });
    return nextLines.join("\n");
}
function validateAndInsertWorkflowProvenanceFields(options) {
    const hasWorkflowProvenanceUpdate = WORKFLOW_PROVENANCE_FIELD_KEYS.some((key) => options.normalizedUpdates[key] !== undefined);
    if (!hasWorkflowProvenanceUpdate)
        return;
    if (options.artifactType === undefined
        || !COMMAND_SUPPORTED_PLANNING_ARTIFACT_TYPES.has(options.artifactType)) {
        throw new TypeError(`Workflow provenance metadata is not applicable to artifact_type '${options.artifactType ?? "(missing)"}'.`);
    }
    let insertionIndex = options.nextLines.findIndex((line, index) => index > 0 && line === "---");
    if (insertionIndex === -1) {
        throw new TypeError("Planning artifact front matter is malformed.");
    }
    for (const key of WORKFLOW_PROVENANCE_FIELD_KEYS) {
        const value = options.normalizedUpdates[key];
        if (value === undefined || options.presentKeys.has(key))
            continue;
        const renderedValue = key === "workflow_provenance"
            ? value
            : JSON.stringify(value);
        options.nextLines.splice(insertionIndex, 0, `${key}: ${renderedValue}`);
        insertionIndex += 1;
    }
    const nextFrontMatterLines = options.nextLines.slice(1, insertionIndex);
    const issues = (0, workflow_provenance_1.inspectPlanningWorkflowProvenance)({
        artifactType: options.artifactType,
        workflowProvenance: (0, planning_document_utils_1.readTopLevelField)(nextFrontMatterLines, "workflow_provenance") ?? "",
        workflowCliCommand: (0, planning_document_utils_1.readTopLevelField)(nextFrontMatterLines, "workflow_cli_command") ?? "",
        workflowManualException: (0, planning_document_utils_1.readTopLevelField)(nextFrontMatterLines, "workflow_manual_exception") ?? ""
    });
    if (issues.length > 0) {
        throw new TypeError(issues[0].message);
    }
}
function validateAndInsertPolicyField(options) {
    if (options.value === undefined)
        return;
    if (options.artifactType === undefined || !EXECUTION_MODE_ARTIFACT_TYPES.has(options.artifactType)) {
        throw new TypeError(`Front matter field '${options.key}' is not applicable to artifact_type '${options.artifactType ?? "(missing)"}'.`);
    }
    if (!options.allowedValues.has(options.value)) {
        throw new TypeError(`Unsupported ${options.key} token '${options.value}'.`);
    }
    if (!options.presentKeys.has(options.key)) {
        options.nextLines.splice(options.insertionIndex, 0, `${options.key}: ${options.value}`);
    }
}
function applyStatusAndPlanningFieldTransition(markdownText, updates) {
    const lines = markdownText.split(/\r?\n/);
    if (lines[0] !== "---") {
        throw new TypeError("Planning artifact is missing YAML front matter.");
    }
    const closingIndex = lines.findIndex((line, index) => index > 0 && line === "---");
    if (closingIndex === -1) {
        throw new TypeError("Planning artifact front matter is malformed.");
    }
    const frontMatterLines = lines.slice(1, closingIndex);
    const artifactType = (0, planning_document_utils_1.readTopLevelField)(frontMatterLines, "artifact_type");
    if (artifactType === undefined || artifactType.trim() === "") {
        throw new TypeError("Planning artifact is missing required front matter field 'artifact_type'.");
    }
    const normalizedArtifactType = artifactType.trim();
    const applicableStatusFields = STATUS_FIELDS_BY_ARTIFACT_TYPE[normalizedArtifactType];
    const applicableIdentityKeys = PLANNING_IDENTITY_KEYS_BY_ARTIFACT_TYPE[normalizedArtifactType];
    if (applicableStatusFields === undefined || applicableIdentityKeys === undefined) {
        throw new TypeError(`Unsupported planning artifact type '${normalizedArtifactType}' for status/planning transitions.`);
    }
    const applicableStatusSet = new Set(applicableStatusFields);
    const applicableIdentitySet = new Set(applicableIdentityKeys);
    const identityUpdates = new Set();
    for (const [key, nextValue] of Object.entries(updates)) {
        if (!STATUS_FIELD_KEYS.has(key) && !PLANNING_FIELD_KEYS.has(key)) {
            throw new TypeError(`Unsupported status/planning transition field '${key}'.`);
        }
        if (STATUS_FIELD_KEYS.has(key)) {
            if (!applicableStatusSet.has(key)) {
                throw new TypeError(`Invalid status-field transition for artifact_type '${normalizedArtifactType}': field '${key}' is not applicable.`);
            }
            assertAllowedStatusToken(key, nextValue);
            continue;
        }
        if (key === "planning_depth") {
            if (!PLANNING_DEPTH_APPLICABLE_ARTIFACT_TYPES.has(normalizedArtifactType)) {
                throw new TypeError(`Invalid planning-field transition for artifact_type '${normalizedArtifactType}': field 'planning_depth' is not applicable.`);
            }
            continue;
        }
        if (!applicableIdentitySet.has(key)) {
            throw new TypeError(`Invalid planning-field transition for artifact_type '${normalizedArtifactType}': field '${key}' is not applicable.`);
        }
        const currentValue = (0, planning_document_utils_1.readTopLevelField)(frontMatterLines, key);
        if (currentValue === undefined) {
            throw new TypeError(`Planning artifact is missing required front matter field '${key}'.`);
        }
        if (!isTemplatePlaceholder(currentValue) && currentValue !== nextValue) {
            identityUpdates.add(key);
        }
    }
    if (identityUpdates.size > 0) {
        for (const identityKey of applicableIdentitySet) {
            if (updates[identityKey] === undefined) {
                throw new TypeError(`Incoherent planning-coordinate transition: updates that rewrite identity fields must include '${identityKey}' for artifact_type '${normalizedArtifactType}'.`);
            }
        }
    }
    return applyPlanningFrontMatterFieldUpdates(markdownText, updates, {
        identityKeys: []
    });
}
function applyNonArtifactFrontMatterFieldUpdates(markdownText, updates, options) {
    const lines = markdownText.split(/\r?\n/);
    if (lines[0] !== "---") {
        throw new TypeError("Metadata surface is missing YAML front matter.");
    }
    const closingIndex = lines.findIndex((line, index) => index > 0 && line === "---");
    if (closingIndex === -1) {
        throw new TypeError("Metadata surface front matter is malformed.");
    }
    const presentKeys = new Set();
    const nextLines = [...lines];
    const appliedKeys = new Set();
    const allowedKeys = new Set(options.allowedKeys ?? []);
    for (const [key, value] of Object.entries(updates)) {
        assertNonArtifactUpdateKeyApplicable(key, options.family, allowedKeys);
        assertNonArtifactUpdateValueApplicable(key, value, options.family);
    }
    for (let index = 1; index < closingIndex; index += 1) {
        const topLevelMatch = lines[index].match(/^([A-Za-z0-9_]+):\s*(.*)$/);
        if (topLevelMatch === null) {
            continue;
        }
        const key = topLevelMatch[1];
        presentKeys.add(key);
        if (updates[key] === undefined) {
            continue;
        }
        nextLines[index] = `${key}: ${formatScalarPreservingQuoteStyle(topLevelMatch[2], updates[key])}`;
        appliedKeys.add(key);
    }
    for (const key of Object.keys(updates)) {
        if (!appliedKeys.has(key)) {
            throw new TypeError(`Metadata surface is missing required front matter field '${key}'.`);
        }
    }
    assertRequiredKeysPresent(options.requiredKeys ?? [], presentKeys);
    return nextLines.join("\n");
}
function applyManifestMetadataFieldUpdates(manifestText, options) {
    let parsedManifest;
    try {
        parsedManifest = JSON.parse(manifestText);
    }
    catch {
        throw new TypeError("Manifest metadata surface is malformed JSON.");
    }
    if (!isPlainObject(parsedManifest)) {
        throw new TypeError("Manifest metadata surface must be a JSON object.");
    }
    const manifest = parsedManifest;
    if (options.family === "prompt-manifest" && typeof manifest.prompt_manifest_version !== "number") {
        throw new TypeError("Manifest metadata surface is not a prompt manifest.");
    }
    if (options.family === "template-manifest" && typeof manifest.template_manifest_version !== "number") {
        throw new TypeError("Manifest metadata surface is not a template manifest.");
    }
    const collectionName = options.family === "prompt-manifest" ? "prompts" : "templates";
    const entries = manifest[collectionName];
    if (!Array.isArray(entries)) {
        throw new TypeError(`Manifest metadata surface is missing required '${collectionName}' array.`);
    }
    if (options.topLevelFields !== undefined) {
        for (const [key, value] of Object.entries(options.topLevelFields)) {
            assertManifestTopLevelFieldApplicable(key, options.family);
            assertManifestTopLevelFieldValueApplicable(key, value, options.family);
            manifest[key] = value;
        }
    }
    for (const patch of options.entryPatches ?? []) {
        const index = findManifestEntryIndex(entries, patch.path);
        const entry = entries[index];
        for (const [field, value] of Object.entries(patch.fields)) {
            assertManifestEntryFieldApplicable(field, options.family, entry);
            assertManifestEntryFieldValueApplicable(field, value, options.family);
            if (IMMUTABLE_MANIFEST_ENTRY_IDENTITY_KEYS.has(field)) {
                const currentPath = typeof entry.path === "string" ? entry.path : "";
                const currentValue = entry[field];
                if (currentValue !== undefined && currentValue !== value) {
                    throw new TypeError(`Manifest entry patch cannot rewrite identity field '${field}' in-place.`);
                }
                if (field === "path" && (typeof value !== "string" || currentPath !== value)) {
                    throw new TypeError("Manifest entry patch cannot rewrite identity field 'path' in-place.");
                }
            }
            entry[field] = value;
        }
    }
    for (const replacement of options.entryReplacements ?? []) {
        const index = findManifestEntryIndex(entries, replacement.path);
        const currentEntry = entries[index];
        const nextEntry = replacement.entry;
        if (!isPlainObject(currentEntry) || !isPlainObject(nextEntry)) {
            throw new TypeError("Manifest entry replacement requires object-shaped entries.");
        }
        const currentObject = currentEntry;
        const nextObject = nextEntry;
        if (nextObject.path !== currentObject.path) {
            throw new TypeError("Manifest entry replacement must preserve identity field 'path'.");
        }
        for (const identityKey of ["kind", "artifact_type"]) {
            if (currentObject[identityKey] !== undefined && nextObject[identityKey] === undefined) {
                throw new TypeError(`Lossy manifest rewrite rejected: missing required identity field '${identityKey}'.`);
            }
        }
        for (const key of Object.keys(currentObject)) {
            if (!(key in nextObject)) {
                throw new TypeError(`Lossy manifest rewrite rejected: missing existing field '${key}'.`);
            }
        }
        const hasCurrentTemplateRef = currentObject.template_ref !== undefined;
        const hasCurrentTemplateRefs = currentObject.template_refs !== undefined;
        const hasNextTemplateRef = nextObject.template_ref !== undefined;
        const hasNextTemplateRefs = nextObject.template_refs !== undefined;
        if ((hasCurrentTemplateRef && hasNextTemplateRefs) || (hasCurrentTemplateRefs && hasNextTemplateRef)) {
            throw new TypeError("Lossy manifest rewrite rejected: template_ref/template_refs shape cannot be collapsed.");
        }
        entries[index] = nextObject;
    }
    return `${JSON.stringify(manifest, null, 2)}\n`;
}
function normalizeRepositoryRelativePathUpdates(updates, repositoryRelativePathKeys) {
    if (repositoryRelativePathKeys.length === 0) {
        return { ...updates };
    }
    const keys = new Set(repositoryRelativePathKeys);
    const normalized = { ...updates };
    for (const [key, value] of Object.entries(updates)) {
        if (!keys.has(key)) {
            continue;
        }
        normalized[key] = (0, paths_1.parseRepositoryRelativePath)(value).normalizedPath;
    }
    return normalized;
}
function findManifestEntryIndex(entries, entryPath) {
    const normalizedPath = (0, paths_1.parseRepositoryRelativePath)(entryPath).normalizedPath;
    const index = entries.findIndex((entry) => {
        if (!isPlainObject(entry)) {
            return false;
        }
        const pathValue = entry.path;
        if (typeof pathValue !== "string") {
            return false;
        }
        return (0, paths_1.parseRepositoryRelativePath)(pathValue).normalizedPath === normalizedPath;
    });
    if (index === -1) {
        throw new TypeError(`Manifest metadata surface is missing entry '${normalizedPath}'.`);
    }
    return index;
}
function assertNonArtifactUpdateKeyApplicable(key, family, allowedKeys) {
    if (STATUS_FIELD_KEYS.has(key) || PLANNING_FIELD_KEYS.has(key)) {
        throw new TypeError(`Invalid cross-family field '${key}' for ${family} metadata updates.`);
    }
    if (family === "prompt" && !PROMPT_FRONT_MATTER_KEYS.has(key)) {
        throw new TypeError(`Invalid prompt metadata field '${key}'.`);
    }
    if (family === "template" && MANIFEST_ENTRY_KEYS.has(key)) {
        throw new TypeError(`Invalid cross-family manifest field '${key}' for template metadata updates.`);
    }
    if (family === "template" && allowedKeys.size > 0 && !allowedKeys.has(key)) {
        throw new TypeError(`Template metadata field '${key}' is outside this transition scope.`);
    }
}
function assertNonArtifactUpdateValueApplicable(key, value, family) {
    if (family !== "prompt") {
        return;
    }
    if (key === "prompt_version") {
        if (!/^[1-9][0-9]*$/.test(value)) {
            throw new TypeError("Prompt metadata field 'prompt_version' must be a positive integer.");
        }
        return;
    }
    if (key === "layer") {
        if (!ALLOWED_PROMPT_LAYER_VALUES.has(value)) {
            throw new TypeError(`Invalid prompt metadata field value for 'layer': '${value}'.`);
        }
        return;
    }
    if (key === "action" && !ALLOWED_PROMPT_ACTION_VALUES.has(value)) {
        throw new TypeError(`Invalid prompt metadata field value for 'action': '${value}'.`);
    }
}
function assertManifestEntryFieldApplicable(key, family, entry) {
    if (STATUS_FIELD_KEYS.has(key) || PLANNING_FIELD_KEYS.has(key)) {
        throw new TypeError(`Invalid cross-family field '${key}' for manifest entry updates.`);
    }
    if (family === "template-manifest" && PROMPT_FRONT_MATTER_KEYS.has(key)) {
        throw new TypeError(`Invalid prompt-only field '${key}' for template manifest entry updates.`);
    }
    if (family === "prompt-manifest" && !ALLOWED_PROMPT_MANIFEST_ENTRY_KEYS.has(key)) {
        throw new TypeError(`Invalid prompt manifest entry field '${key}'.`);
    }
    if (family === "template-manifest" && !ALLOWED_TEMPLATE_MANIFEST_ENTRY_KEYS.has(key)) {
        throw new TypeError(`Invalid template manifest entry field '${key}'.`);
    }
    if (key === "template_ref" && Array.isArray(entry.template_refs)) {
        throw new TypeError("Manifest entry update would collapse 'template_refs' into 'template_ref'.");
    }
    if (key === "template_refs" && entry.template_ref !== undefined) {
        throw new TypeError("Manifest entry update would collapse 'template_ref' into 'template_refs'.");
    }
}
function assertManifestTopLevelFieldApplicable(key, family) {
    if (STATUS_FIELD_KEYS.has(key) || PLANNING_FIELD_KEYS.has(key)) {
        throw new TypeError(`Invalid cross-family field '${key}' for manifest metadata updates.`);
    }
    if (family === "prompt-manifest" && !ALLOWED_PROMPT_MANIFEST_TOP_LEVEL_KEYS.has(key)) {
        throw new TypeError(`Invalid prompt manifest top-level field '${key}'.`);
    }
    if (family === "template-manifest" && !ALLOWED_TEMPLATE_MANIFEST_TOP_LEVEL_KEYS.has(key)) {
        throw new TypeError(`Invalid template manifest top-level field '${key}'.`);
    }
    if (key === "prompts" || key === "templates") {
        throw new TypeError(`Lossy manifest rewrite rejected: top-level collection field '${key}' cannot be replaced through field-patch syntax. Use entry:<path>:<field> patches or guarded replace:<path> entry replacement.`);
    }
}
function assertManifestTopLevelFieldValueApplicable(key, value, family) {
    if (key === "prompt_manifest_version" || key === "template_manifest_version" || key === "template_version" || key === "prompt_version") {
        assertPositiveIntegerManifestFieldValue(key, value);
        return;
    }
    if (family === "prompt-manifest" && key === "notes" && !isStringArray(value)) {
        throw new TypeError("Prompt manifest top-level field 'notes' must be an array of strings.");
    }
    if (family === "template-manifest" && key === "notes" && !isStringArray(value)) {
        throw new TypeError("Template manifest top-level field 'notes' must be an array of strings.");
    }
}
function assertManifestEntryFieldValueApplicable(key, value, family) {
    if (key === "version") {
        assertPositiveIntegerManifestFieldValue("version", value);
        return;
    }
    if (family === "prompt-manifest" && key === "layer") {
        if (typeof value !== "string" || !ALLOWED_PROMPT_LAYER_VALUES.has(value)) {
            throw new TypeError(`Invalid prompt manifest entry field value for 'layer': '${String(value)}'.`);
        }
        return;
    }
    if (family === "prompt-manifest" && key === "action") {
        if (typeof value !== "string" || !ALLOWED_PROMPT_ACTION_VALUES.has(value)) {
            throw new TypeError(`Invalid prompt manifest entry field value for 'action': '${String(value)}'.`);
        }
        return;
    }
    if (key === "template_ref" && typeof value !== "string") {
        throw new TypeError("Manifest entry field 'template_ref' must be a string.");
    }
    if (key === "template_refs" && !isStringArray(value)) {
        throw new TypeError("Manifest entry field 'template_refs' must be an array of strings.");
    }
    if ((key === "usage" || key === "destination") && typeof value !== "string") {
        throw new TypeError(`Manifest entry field '${key}' must be a string.`);
    }
    if (key === "notes") {
        if (family === "prompt-manifest") {
            if (!isStringArray(value)) {
                throw new TypeError("Prompt manifest entry field 'notes' must be an array of strings.");
            }
        }
        else if (typeof value !== "string") {
            throw new TypeError("Template manifest entry field 'notes' must be a string.");
        }
    }
}
function assertPositiveIntegerManifestFieldValue(key, value) {
    if (!Number.isInteger(value) || value <= 0) {
        throw new TypeError(`Manifest metadata field '${key}' must be a positive integer.`);
    }
}
function isPlainObject(value) {
    return typeof value === "object" && value !== null && !Array.isArray(value);
}
function isStringArray(value) {
    return Array.isArray(value) && value.every((entry) => typeof entry === "string");
}
function assertRequiredKeysPresent(requiredKeys, presentKeys) {
    for (const key of requiredKeys) {
        if (!presentKeys.has(key)) {
            throw new TypeError(`Planning artifact is missing required front matter field '${key}'.`);
        }
    }
}
function assertAllowedStatusToken(key, value) {
    if (key === "status") {
        if (!ALLOWED_SHARED_STATUS_VALUES.has(value)) {
            throw new TypeError(`Unsupported status token '${value}' for field 'status'.`);
        }
        return;
    }
    if (key === "readiness") {
        if (!ALLOWED_READINESS_VALUES.has(value)) {
            throw new TypeError(`Unsupported status token '${value}' for field 'readiness'.`);
        }
        return;
    }
    if (key === "implementation_status") {
        if (!ALLOWED_IMPLEMENTATION_STATUS_VALUES.has(value)) {
            throw new TypeError(`Unsupported status token '${value}' for field 'implementation_status'.`);
        }
        return;
    }
    if (key === "reconciliation_status" && !ALLOWED_RECONCILIATION_STATUS_VALUES.has(value)) {
        throw new TypeError(`Unsupported status token '${value}' for field 'reconciliation_status'.`);
    }
}
function assertNoIdentityRewrite(rawCurrentValue, nextValue, key, identityKeys) {
    if (!identityKeys.has(key)) {
        return;
    }
    const currentValue = (0, planning_document_utils_1.parseScalar)(rawCurrentValue);
    if (!isTemplatePlaceholder(currentValue) && currentValue !== nextValue) {
        throw new TypeError(`Unsafe planning front matter rewrite: field '${key}' cannot change from '${currentValue}' to '${nextValue}'.`);
    }
}
function isTemplatePlaceholder(value) {
    return /^\{\{[A-Za-z0-9_.-]+\}\}$/.test(value.trim());
}
function formatScalarPreservingQuoteStyle(rawCurrentValue, nextValue) {
    const trimmed = rawCurrentValue.trim();
    if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
        return JSON.stringify(nextValue);
    }
    if (trimmed.startsWith("'") && trimmed.endsWith("'")) {
        return `'${nextValue.replace(/'/g, "''")}'`;
    }
    return nextValue;
}
function toTitleCase(slug) {
    return slug
        .split("-")
        .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
        .join(" ");
}
