"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.executeMetadataUpdateOperation = executeMetadataUpdateOperation;
exports.executeOverviewUpdateOperation = executeOverviewUpdateOperation;
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const config_contract_1 = require("../../lib/config/config-contract");
const errors_1 = require("../../lib/errors");
const command_write_summary_1 = require("../../lib/license/command-write-summary");
const output_1 = require("../../lib/output");
const paths_1 = require("../../lib/paths");
const prompt_version_evidence_1 = require("../../lib/prompts/prompt-version-evidence");
const front_matter_utils_1 = require("../../lib/planning/front-matter-utils");
const spec_registry_1 = require("../../lib/spec-registry");
const global_format_1 = require("./global-format");
const persisted_artifact_reminder_1 = require("./persisted-artifact-reminder");
const STATUS_AND_PLANNING_FIELDS = new Set([
    "status",
    "readiness",
    "implementation_status",
    "reconciliation_status",
    "slice",
    "phase",
    "milestone",
    "task",
    "planning_depth"
]);
const REPOSITORY_RELATIVE_PARENT_LINK_KEYS = [
    "upstream.slice_overview",
    "upstream.phase_overview",
    "upstream.milestone_overview",
    "upstream.task_definition"
];
function executeMetadataUpdateOperation(options) {
    const format = (0, output_1.resolveOutputFormat)((0, global_format_1.getGlobalFormat)(options.commandInstance));
    if (format === null) {
        throw (0, errors_1.createUsageError)("Output format must be one of: text, json.", [`Received: ${String((0, global_format_1.getGlobalFormat)(options.commandInstance))}`]);
    }
    const commandOptions = options.commandInstance.opts();
    const artifactPathOption = options.artifactPathOption ?? "artifact";
    const artifactPathOptionFlag = artifactPathOption.replace(/([A-Z])/g, "-$1").toLowerCase();
    const artifactPathInput = options.artifactPathOverride
        ?? readRequiredStringOption(commandOptions[artifactPathOption], `--${artifactPathOptionFlag}`);
    const assignments = parseFieldAssignments(options.fieldAssignmentsOverride !== undefined
        ? Array.from(options.fieldAssignmentsOverride)
        : commandOptions.field);
    const parsedArtifact = (0, paths_1.parseRepositoryRelativePath)(artifactPathInput);
    const artifactPath = parsedArtifact.normalizedPath;
    const activeArtifactPath = normalizeOptionalRepositoryRelativeOption(commandOptions.activeArtifact, "--active-artifact");
    const absolutePath = (0, paths_1.resolveRepositoryRelativePath)(options.repositoryRoot, parsedArtifact);
    if (!node_fs_1.default.existsSync(absolutePath)) {
        throw (0, errors_1.createUsageError)(`Artifact path '${artifactPath}' does not exist.`, ["Pass an existing repository-relative --artifact path."]);
    }
    const originalContent = node_fs_1.default.readFileSync(absolutePath, "utf8");
    let detectedFamily = detectMetadataFamilyForReporting(artifactPath, originalContent);
    try {
        assertActiveArtifactMatchesSelection({
            artifactPath,
            activeArtifactPath,
            commandName: options.commandName
        });
        const family = detectMetadataFamily(artifactPath, originalContent);
        detectedFamily = family;
        if (options.expectedFamilies !== undefined && !options.expectedFamilies.includes(family)) {
            throw (0, errors_1.createUsageError)(`Artifact '${artifactPath}' is not supported by ${options.commandName}.`, [
                `Expected metadata family: ${options.expectedFamilies.join(", ")}.`,
                `Detected metadata family: ${family}.`
            ]);
        }
        const nextContent = applyFamilyAwareUpdates({
            family,
            artifactPath,
            originalContent,
            repositoryRoot: options.repositoryRoot,
            assignments
        });
        const changed = nextContent !== originalContent;
        if (options.write && changed) {
            node_fs_1.default.writeFileSync(absolutePath, nextContent, "utf8");
        }
        const result = {
            artifactPath,
            activeArtifactPath,
            family,
            changed,
            writeApplied: options.write && changed,
            fieldChanges: toFieldChanges(assignments),
            reportingAlignment: createMetadataReportingAlignment({
                family,
                writeRequested: options.write
            }),
            commandWriteSummary: createMetadataCommandWriteSummary({
                artifactPath,
                changed,
                writeApplied: options.write && changed,
                writeRequested: options.write,
                jsonOnly: format === "json"
            }),
            promptVersionEvidence: family === "prompt"
                ? (0, prompt_version_evidence_1.collectPromptVersionEvidence)({
                    repositoryRoot: options.repositoryRoot,
                    promptPath: artifactPath,
                    promptContent: nextContent,
                    manifestPath: node_path_1.default.posix.join(config_contract_1.BUILT_IN_CONFIG_DEFAULTS.prompt_user_root, "manifest.json"),
                    canonicalPromptPath: artifactPath
                })
                : undefined
        };
        const persistedArtifactLicenseReminder = (0, persisted_artifact_reminder_1.applyPlanningCommandPersistedArtifactReminderWrites)({
            repositoryContext: {
                root: options.repositoryRoot,
                detectionSource: options.detectionSource
            },
            commandWriteSummary: result.commandWriteSummary,
            format
        });
        (0, output_1.emitSuccess)({
            command: options.commandName,
            format,
            text: renderMetadataOperationText(result, options.write),
            data: {
                repositoryRoot: options.repositoryRoot,
                detectionSource: options.detectionSource,
                artifactPath,
                activeArtifactPath,
                family,
                requestedFieldCount: assignments.length,
                fieldChanges: result.fieldChanges,
                changed,
                writeApplied: result.writeApplied,
                commandWriteSummary: persistedArtifactLicenseReminder.commandWriteSummary,
                persistedArtifactLicenseReminder,
                reportingAlignment: result.reportingAlignment,
                promptVersionEvidence: result.promptVersionEvidence
            }
        });
    }
    catch (error) {
        if (error instanceof TypeError || error instanceof RangeError || error instanceof SyntaxError) {
            throw (0, errors_1.createBlockingInvalidConfigError)({
                message: "Metadata updates were rejected.",
                detail: error.message,
                findingCode: "METADATA_UPDATE_BLOCKED",
                path: artifactPath,
                blockingReason: "invalid-command-input",
                recovery: "Correct the rejected metadata field request or artifact metadata, then rerun the command. No partial write was applied.",
                evidenceDetails: createMetadataRejectionEvidence({
                    commandName: options.commandName,
                    artifactPath,
                    family: detectedFamily,
                    assignments,
                    rejectionDetail: error.message
                })
            });
        }
        throw error;
    }
}
function executeOverviewUpdateOperation(options) {
    const format = (0, output_1.resolveOutputFormat)((0, global_format_1.getGlobalFormat)(options.commandInstance));
    if (format === null) {
        throw (0, errors_1.createUsageError)("Output format must be one of: text, json.", [`Received: ${String((0, global_format_1.getGlobalFormat)(options.commandInstance))}`]);
    }
    const commandOptions = options.commandInstance.opts();
    const dashOption = options.artifactPathOption.replace(/([A-Z])/g, "-$1").toLowerCase();
    const artifactPathInput = readRequiredStringOption(commandOptions[options.artifactPathOption], `--${dashOption}`);
    const assignments = parseFieldAssignments(commandOptions.field);
    const parsedArtifact = (0, paths_1.parseRepositoryRelativePath)(artifactPathInput);
    const artifactPath = parsedArtifact.normalizedPath;
    const activeArtifactPath = normalizeOptionalRepositoryRelativeOption(commandOptions.activeArtifact, "--active-artifact");
    const absolutePath = (0, paths_1.resolveRepositoryRelativePath)(options.repositoryRoot, parsedArtifact);
    if (!node_fs_1.default.existsSync(absolutePath)) {
        throw (0, errors_1.createUsageError)(`Artifact path '${artifactPath}' does not exist.`, [`Pass an existing repository-relative --${dashOption} path.`]);
    }
    const originalContent = node_fs_1.default.readFileSync(absolutePath, "utf8");
    let detectedFamily = "planning-artifact";
    try {
        assertActiveArtifactMatchesSelection({
            artifactPath,
            activeArtifactPath,
            commandName: options.commandName
        });
        const frontMatter = readFrontMatter(artifactPath, originalContent);
        if (frontMatter.artifactType?.trim() !== options.expectedArtifactType) {
            throw (0, errors_1.createUsageError)(`Artifact '${artifactPath}' is not a ${options.expectedArtifactType} artifact.`, [
                `Expected artifact_type '${options.expectedArtifactType}', found '${frontMatter.artifactType ?? "(none)"}'.`,
                `Pass a repository-relative path to an existing ${options.expectedArtifactType.replace(/_/g, " ")} file.`
            ]);
        }
        const updates = toStringUpdateMap(assignments);
        const transitionUpdates = {};
        const frontMatterUpdates = {};
        for (const [key, value] of Object.entries(updates)) {
            if (STATUS_AND_PLANNING_FIELDS.has(key)) {
                transitionUpdates[key] = value;
            }
            else {
                frontMatterUpdates[key] = value;
            }
        }
        let nextContent = originalContent;
        if (Object.keys(transitionUpdates).length > 0) {
            nextContent = (0, front_matter_utils_1.applyStatusAndPlanningFieldTransition)(nextContent, transitionUpdates);
        }
        if (Object.keys(frontMatterUpdates).length > 0) {
            nextContent = (0, front_matter_utils_1.applyPlanningFrontMatterFieldUpdates)(nextContent, frontMatterUpdates, {
                repositoryRelativePathKeys: REPOSITORY_RELATIVE_PARENT_LINK_KEYS
            });
        }
        assertPlanningArtifactSelectionIsConsistent({
            repositoryRoot: options.repositoryRoot,
            artifactPath,
            content: nextContent
        });
        const changed = nextContent !== originalContent;
        if (options.write && changed) {
            node_fs_1.default.writeFileSync(absolutePath, nextContent, "utf8");
        }
        const result = {
            artifactPath,
            activeArtifactPath,
            family: "planning-artifact",
            changed,
            writeApplied: options.write && changed,
            fieldChanges: toFieldChanges(assignments),
            reportingAlignment: createMetadataReportingAlignment({
                family: "planning-artifact",
                writeRequested: options.write
            }),
            commandWriteSummary: createMetadataCommandWriteSummary({
                artifactPath,
                changed,
                writeApplied: options.write && changed,
                writeRequested: options.write,
                jsonOnly: format === "json"
            })
        };
        const persistedArtifactLicenseReminder = (0, persisted_artifact_reminder_1.applyPlanningCommandPersistedArtifactReminderWrites)({
            repositoryContext: {
                root: options.repositoryRoot,
                detectionSource: options.detectionSource
            },
            commandWriteSummary: result.commandWriteSummary,
            format
        });
        (0, output_1.emitSuccess)({
            command: options.commandName,
            format,
            text: renderMetadataOperationText(result, options.write),
            data: {
                repositoryRoot: options.repositoryRoot,
                detectionSource: options.detectionSource,
                artifactPath,
                activeArtifactPath,
                family: "planning-artifact",
                requestedFieldCount: assignments.length,
                fieldChanges: result.fieldChanges,
                changed,
                writeApplied: result.writeApplied,
                commandWriteSummary: persistedArtifactLicenseReminder.commandWriteSummary,
                persistedArtifactLicenseReminder,
                reportingAlignment: result.reportingAlignment
            }
        });
    }
    catch (error) {
        if (error instanceof TypeError || error instanceof RangeError || error instanceof SyntaxError) {
            throw (0, errors_1.createBlockingInvalidConfigError)({
                message: "Metadata updates were rejected.",
                detail: error.message,
                findingCode: "METADATA_UPDATE_BLOCKED",
                path: artifactPath,
                blockingReason: "invalid-command-input",
                recovery: "Correct the rejected metadata field request or artifact metadata, then rerun the command. No partial write was applied.",
                evidenceDetails: createMetadataRejectionEvidence({
                    commandName: options.commandName,
                    artifactPath,
                    family: detectedFamily,
                    assignments,
                    rejectionDetail: error.message
                })
            });
        }
        throw error;
    }
}
function assertPlanningArtifactSelectionIsConsistent(options) {
    const metadata = readPlanningMetadata(options.artifactPath, options.content);
    const artifactType = metadata.get("artifact_type") ?? "";
    const planningDepth = metadata.get("planning_depth") ?? "";
    const expected = getExpectedPlanningArtifactEvidence(options.artifactPath, artifactType, planningDepth);
    if (expected === null) {
        return;
    }
    for (const [field, expectedValue] of Object.entries(expected.coordinates)) {
        assertMetadataEvidenceMatches({
            artifactPath: options.artifactPath,
            field,
            actualValue: metadata.get(field),
            expectedValue,
            evidenceSource: "selected artifact path and front matter"
        });
    }
    for (const [field, expectedValue] of Object.entries(expected.parents)) {
        assertParentOverviewEvidenceMatches({
            repositoryRoot: options.repositoryRoot,
            artifactPath: options.artifactPath,
            field,
            actualValue: metadata.get(field),
            expectedValue
        });
    }
}
function assertParentOverviewEvidenceMatches(options) {
    if (options.actualValue === options.expectedValue) {
        return;
    }
    const compatibleLayer = getParentOverviewLayerForField(options.field);
    if (compatibleLayer !== null && options.actualValue !== undefined) {
        const expectedDirectory = node_path_1.default.posix.dirname(options.expectedValue);
        const resolution = (0, paths_1.resolvePlanningOverviewPath)(options.repositoryRoot, {
            layer: compatibleLayer,
            directoryPath: expectedDirectory
        });
        if (resolution.selected?.path === options.actualValue) {
            return;
        }
    }
    assertMetadataEvidenceMatches({
        artifactPath: options.artifactPath,
        field: options.field,
        actualValue: options.actualValue,
        expectedValue: options.expectedValue,
        evidenceSource: "selected artifact path and explicit upstream parent link"
    });
}
function getParentOverviewLayerForField(field) {
    switch (field) {
        case "upstream.slice_overview":
            return "slice";
        case "upstream.phase_overview":
            return "phase";
        case "upstream.milestone_overview":
            return "milestone";
        default:
            return null;
    }
}
function getExpectedPlanningArtifactEvidence(artifactPath, artifactType, planningDepth) {
    const segments = (0, paths_1.parseRepositoryRelativePath)(artifactPath).segments;
    const planningIndex = segments.indexOf("planning");
    if (segments[0] !== ".day-shift" || planningIndex === -1 || segments.length < planningIndex + 3) {
        return null;
    }
    const phasesIndex = segments.indexOf("phases");
    const milestonesIndex = segments.indexOf("milestones");
    const tasksIndex = segments.indexOf("tasks");
    const sliceSegment = segments[planningIndex + 1];
    const sliceSlug = stripOrderedPrefix(sliceSegment);
    const coordinates = {};
    const parents = {};
    if (artifactType === "slice_overview") {
        coordinates.slice = sliceSlug;
        return { coordinates, parents };
    }
    if (phasesIndex >= 0) {
        coordinates.slice = sliceSlug;
        parents["upstream.slice_overview"] = (0, paths_1.composeCanonicalPlanningOverviewPath)("slice", segments.slice(0, phasesIndex).join("/"));
    }
    if (artifactType === "phase_overview" &&
        phasesIndex >= 0 &&
        (segments[phasesIndex + 2] === "phase-overview.md" || segments[phasesIndex + 2] === "overview.md")) {
        coordinates.phase = segments[phasesIndex + 1];
        return { coordinates, parents };
    }
    if (milestonesIndex >= 0) {
        coordinates.phase = segments[phasesIndex + 1];
        parents["upstream.phase_overview"] = (0, paths_1.composeCanonicalPlanningOverviewPath)("phase", segments.slice(0, phasesIndex + 2).join("/"));
    }
    if (artifactType === "milestone_overview" &&
        milestonesIndex >= 0 &&
        (segments[milestonesIndex + 2] === "milestone-overview.md" || segments[milestonesIndex + 2] === "overview.md")) {
        coordinates.milestone = segments[milestonesIndex + 1];
        return { coordinates, parents };
    }
    if (tasksIndex >= 0) {
        if (planningDepth !== "lightweight") {
            coordinates.milestone = segments[milestonesIndex + 1];
            parents["upstream.milestone_overview"] = (0, paths_1.composeCanonicalPlanningOverviewPath)("milestone", segments.slice(0, milestonesIndex + 2).join("/"));
        }
        else {
            parents["upstream.slice_overview"] = (0, paths_1.composeCanonicalPlanningOverviewPath)("slice", segments.slice(0, tasksIndex).join("/"));
        }
    }
    if (artifactType === "task_definition" &&
        tasksIndex >= 0 &&
        segments[tasksIndex + 2] === "task-definition.md") {
        coordinates.task = segments[tasksIndex + 1];
        return { coordinates, parents };
    }
    if (artifactType === "implementation_summary" &&
        tasksIndex >= 0 &&
        segments[tasksIndex + 2] === "implementation-summary.md") {
        coordinates.task = segments[tasksIndex + 1];
        parents["upstream.task_definition"] = segments.slice(0, tasksIndex + 2).concat("task-definition.md").join("/");
        return { coordinates, parents };
    }
    if (artifactType === "reconciliation" &&
        milestonesIndex >= 0 &&
        segments[milestonesIndex + 2] === "reconciliation.md") {
        coordinates.milestone = segments[milestonesIndex + 1];
        parents["upstream.milestone_overview"] = (0, paths_1.composeCanonicalPlanningOverviewPath)("milestone", segments.slice(0, milestonesIndex + 2).join("/"));
        return { coordinates, parents };
    }
    return null;
}
function assertMetadataEvidenceMatches(options) {
    if (options.actualValue === options.expectedValue) {
        return;
    }
    throw new TypeError([
        `Active artifact conflict for '${options.artifactPath}'.`,
        `Evidence source: ${options.evidenceSource}.`,
        `Field '${options.field}' is '${options.actualValue ?? "<missing>"}'; expected '${options.expectedValue}'.`,
        "Recovery: pass the artifact that matches the recorded metadata, or repair the selected artifact's metadata with a compatible planning workflow before rerunning this write command."
    ].join(" "));
}
function stripOrderedPrefix(value) {
    return value.replace(/^\d{2}-/u, "");
}
function normalizeOptionalRepositoryRelativeOption(input, optionName) {
    if (input === undefined || input === null || input === "") {
        return null;
    }
    if (typeof input !== "string") {
        throw (0, errors_1.createUsageError)(`${optionName} must be a repository-relative path.`, [`Received: ${String(input)}`]);
    }
    try {
        return (0, paths_1.parseRepositoryRelativePath)(input).normalizedPath;
    }
    catch (error) {
        if (error instanceof RangeError) {
            throw (0, errors_1.createUsageError)(`${optionName} must be a repository-relative path.`, [error.message]);
        }
        throw error;
    }
}
function assertActiveArtifactMatchesSelection(options) {
    if (options.activeArtifactPath === null || options.activeArtifactPath === options.artifactPath) {
        return;
    }
    throw new TypeError([
        `Active artifact conflict for ${options.commandName}.`,
        `Evidence source: --active-artifact and selected command artifact argument.`,
        `Field '--active-artifact' is '${options.activeArtifactPath}'; expected '${options.artifactPath}'.`,
        "Recovery: rerun the command with matching --active-artifact and selected artifact paths, or omit --active-artifact when no explicit handoff is being checked. No partial write was applied."
    ].join(" "));
}
function createMetadataCommandWriteSummary(options) {
    return (0, command_write_summary_1.normalizeCommandWriteSummary)({
        commandFamily: "metadata_update",
        jsonOnly: options.jsonOnly,
        primaryOutputArtifacts: [options.artifactPath],
        updatedArtifacts: [
            {
                path: options.artifactPath,
                action: options.writeApplied ? "changed" : options.writeRequested ? "kept" : "inspected",
                reason: options.writeApplied
                    ? undefined
                    : options.writeRequested
                        ? "no_write"
                        : "read_only_output",
                materialUpdate: options.writeApplied ? true : false
            }
        ]
    });
}
function createMetadataReportingAlignment(options) {
    return {
        surfaceMode: options.writeRequested ? "write-attempt" : "read-only",
        family: options.family,
        findingsTaxonomy: "shared-findings",
        noWrite: !options.writeRequested,
        evidenceLanes: getMetadataEvidenceLanes(options.family),
        adjacentEvidencePolicy: "visible-not-authority"
    };
}
function getMetadataEvidenceLanes(family) {
    switch (family) {
        case "prompt":
            return [
                "promptMarkdown.promptVersion",
                "promptMarkdown.layer",
                "promptMarkdown.action",
                "promptManifest.promptManifestVersion",
                "promptManifest.promptVersion",
                "promptManifest.entryVersion"
            ];
        case "prompt-manifest":
            return [
                "promptManifest.promptManifestVersion",
                "promptManifest.promptVersion",
                "promptManifest.entryVersion",
                "promptManifest.entryLayer",
                "promptManifest.entryAction"
            ];
        case "template":
            return [
                "templateMarkdown.frontMatter",
                "templateFamily.adjacentManifestEvidence"
            ];
        case "template-manifest":
            return [
                "templateManifest.templateManifestVersion",
                "templateManifest.templateVersion",
                "templateManifest.entryVersion",
                "templateManifest.entryDestinationEligibility"
            ];
        case "planning-artifact":
            return [
                "planningArtifact.lifecycleStatus",
                "planningArtifact.familySpecificStatus",
                "planningArtifact.traceability"
            ];
        case "spec-registry":
            return [
                "specRegistry.entryIdentity",
                "specRegistry.sourceMetadata",
                "specRegistry.destination"
            ];
        default:
            return assertUnreachable(family);
    }
}
function renderMetadataOperationText(result, writeRequested) {
    const lines = [
        (0, output_1.renderTerminalHeading)("Metadata Update", "title"),
        (0, output_1.renderTerminalSection)({
            heading: "Summary",
            fields: [
                {
                    label: "Result",
                    value: writeRequested
                        ? (result.writeApplied ? "metadata update applied" : "metadata update accepted with no file changes")
                        : "validation completed with no writes"
                },
                { label: "Changed", value: result.changed ? "yes" : "no" },
                { label: "Write requested", value: writeRequested ? "yes" : "no" }
            ]
        }),
        "",
        (0, output_1.renderTerminalSection)({
            heading: "Artifact",
            fields: [
                { label: "Path", value: result.artifactPath },
                { label: "Family", value: result.family },
                { label: "Reporting surface", value: result.reportingAlignment.surfaceMode },
                { label: "Findings taxonomy", value: result.reportingAlignment.findingsTaxonomy },
                { label: "Adjacent evidence policy", value: result.reportingAlignment.adjacentEvidencePolicy }
            ]
        }),
        "",
        (0, output_1.renderTerminalCompactList)({
            heading: "Field Changes",
            entries: result.fieldChanges.map((fieldChange) => ({
                label: fieldChange.key,
                fields: [{ label: "Intended value", value: fieldChange.value }]
            })),
            emptyMessage: "No field changes were requested."
        }),
        "",
        (0, output_1.renderTerminalCompactList)({
            heading: "Evidence Lanes",
            entries: result.reportingAlignment.evidenceLanes.map((lane) => ({ label: lane })),
            emptyMessage: "No evidence lanes are available for this family."
        }),
        "",
        (0, output_1.renderTerminalSection)({
            heading: "Write Boundary",
            lines: [
                writeRequested
                    ? result.writeApplied
                        ? (0, output_1.renderTerminalBoundary)({
                            kind: "write-applied",
                            target: result.artifactPath,
                            targetLabel: "Write target"
                        })
                        : (0, output_1.renderTerminalBoundary)({
                            kind: "mutating-no-op",
                            reason: "Artifact already matched the intended metadata state.",
                            target: result.artifactPath,
                            targetLabel: "Write target"
                        })
                    : (0, output_1.renderTerminalBoundary)({ kind: "read-only" })
            ]
        })
    ];
    if (result.promptVersionEvidence !== undefined) {
        lines.push("", (0, output_1.renderTerminalSection)({
            heading: "Prompt Version Evidence",
            fields: [
                { label: "Prompt Markdown version", value: renderEvidenceValue(result.promptVersionEvidence.promptMarkdown.promptVersion) },
                { label: "Prompt manifest version", value: renderEvidenceValue(result.promptVersionEvidence.promptManifest.promptManifestVersion) },
                { label: "Prompt manifest baseline prompt_version", value: renderEvidenceValue(result.promptVersionEvidence.promptManifest.promptVersion) },
                {
                    label: `Prompt manifest entry version (${result.promptVersionEvidence.promptManifest.entryPath})`,
                    value: renderEvidenceValue(result.promptVersionEvidence.promptManifest.entryVersion)
                }
            ]
        }));
        if (result.promptVersionEvidence.promptManifest.warning !== null) {
            lines.push("", (0, output_1.renderTerminalSection)({
                heading: "Warnings",
                lines: [result.promptVersionEvidence.promptManifest.warning]
            }));
        }
    }
    return lines.join("\n");
}
function renderEvidenceValue(value) {
    return value === null ? "(missing)" : String(value);
}
function createMetadataRejectionEvidence(options) {
    const requestedFields = options.assignments.map((assignment) => assignment.key);
    const rejectedField = requestedFields.find((field) => options.rejectionDetail.includes(`'${field}'`) ||
        options.rejectionDetail.includes(`field ${field}`));
    return {
        commandName: options.commandName,
        artifactPath: options.artifactPath,
        family: options.family,
        requestedFields,
        rejectedField: rejectedField ?? null,
        rejectionReason: options.rejectionDetail,
        writeApplied: false,
        noWriteRequired: true,
        recommendedCommand: buildMetadataRejectionRecoveryCommand({
            commandName: options.commandName,
            artifactPath: options.artifactPath,
            family: options.family,
            rejectedField: rejectedField ?? null
        })
    };
}
function buildMetadataRejectionRecoveryCommand(options) {
    if (options.family === "planning-artifact") {
        if (options.rejectedField === "readiness") {
            return `day-shift task update --task-definition ${options.artifactPath} --field readiness=<value>`;
        }
        if (options.rejectedField === "implementation_status") {
            return `day-shift implementation-summary update --summary ${options.artifactPath} --field implementation_status=<value>`;
        }
        if (options.rejectedField === "reconciliation_status") {
            return `day-shift reconciliation update --reconciliation ${options.artifactPath} --field reconciliation_status=<value>`;
        }
        if (options.rejectedField === "status") {
            return `${options.commandName} --artifact ${options.artifactPath} --field status=<draft|active|blocked|completed>`;
        }
    }
    return "Correct the field family and rerun the matching explicit update or validate-update command.";
}
function detectMetadataFamilyForReporting(artifactPath, content) {
    try {
        return detectMetadataFamily(artifactPath, content);
    }
    catch {
        return "unsupported";
    }
}
function readRequiredStringOption(value, optionName) {
    if (typeof value !== "string" || value.trim() === "") {
        throw (0, errors_1.createUsageError)(`${optionName} is required.`);
    }
    return value.trim();
}
function parseFieldAssignments(rawFields) {
    if (!Array.isArray(rawFields) || rawFields.length === 0) {
        throw (0, errors_1.createUsageError)("Provide one or more --field <key>=<value> assignments.", ["Example: --field status=completed --field readiness=completed"]);
    }
    return rawFields.map((token) => {
        const separatorIndex = token.indexOf("=");
        if (separatorIndex <= 0) {
            throw (0, errors_1.createUsageError)(`Invalid --field assignment '${token}'.`, ["Each assignment must use <key>=<value>."]);
        }
        const key = token.slice(0, separatorIndex).trim();
        const rawValue = token.slice(separatorIndex + 1);
        if (key === "") {
            throw (0, errors_1.createUsageError)(`Invalid --field assignment '${token}'.`, ["Field keys must be non-empty."]);
        }
        return { key, rawValue };
    });
}
function detectMetadataFamily(artifactPath, content) {
    if (artifactPath === ".day-shift/specs/index.json") {
        return "spec-registry";
    }
    if (artifactPath.endsWith(".json")) {
        const parsed = JSON.parse(content);
        if (!isPlainObject(parsed)) {
            throw new TypeError("JSON metadata surfaces must be object-shaped.");
        }
        if (typeof parsed.prompt_manifest_version === "number") {
            return "prompt-manifest";
        }
        if (typeof parsed.template_manifest_version === "number") {
            return "template-manifest";
        }
        throw new TypeError("Unsupported JSON metadata family for generic metadata update.");
    }
    if (!artifactPath.endsWith(".md")) {
        throw new TypeError("Unsupported artifact extension for metadata updates.");
    }
    const frontMatter = readFrontMatter(artifactPath, content);
    if (frontMatter.artifactType !== undefined && frontMatter.artifactType.trim() !== "") {
        return "planning-artifact";
    }
    if (artifactPath.startsWith(".day-shift/prompts/")) {
        return "prompt";
    }
    if (artifactPath.startsWith(".day-shift/templates/")) {
        return "template";
    }
    throw new TypeError("Unsupported Markdown metadata family for generic metadata update.");
}
function applyFamilyAwareUpdates(options) {
    switch (options.family) {
        case "planning-artifact": {
            const updates = toStringUpdateMap(options.assignments);
            const transitionUpdates = {};
            const frontMatterUpdates = {};
            for (const [key, value] of Object.entries(updates)) {
                if (STATUS_AND_PLANNING_FIELDS.has(key)) {
                    transitionUpdates[key] = value;
                }
                else {
                    frontMatterUpdates[key] = value;
                }
            }
            let nextContent = options.originalContent;
            if (Object.keys(transitionUpdates).length > 0) {
                nextContent = (0, front_matter_utils_1.applyStatusAndPlanningFieldTransition)(nextContent, transitionUpdates);
            }
            if (Object.keys(frontMatterUpdates).length > 0) {
                nextContent = (0, front_matter_utils_1.applyPlanningFrontMatterFieldUpdates)(nextContent, frontMatterUpdates, {
                    repositoryRelativePathKeys: REPOSITORY_RELATIVE_PARENT_LINK_KEYS
                });
            }
            return nextContent;
        }
        case "prompt": {
            assertWritablePromptLayerPath(options.artifactPath);
            return (0, front_matter_utils_1.applyNonArtifactFrontMatterFieldUpdates)(options.originalContent, toStringUpdateMap(options.assignments), {
                family: "prompt",
                requiredKeys: ["prompt_version", "layer", "action"]
            });
        }
        case "template": {
            return (0, front_matter_utils_1.applyNonArtifactFrontMatterFieldUpdates)(options.originalContent, toStringUpdateMap(options.assignments), { family: "template" });
        }
        case "prompt-manifest":
        case "template-manifest": {
            const manifestUpdates = toManifestUpdates(options.assignments);
            return (0, front_matter_utils_1.applyManifestMetadataFieldUpdates)(options.originalContent, {
                family: options.family,
                topLevelFields: Object.keys(manifestUpdates.topLevelFields).length > 0
                    ? manifestUpdates.topLevelFields
                    : undefined,
                entryPatches: manifestUpdates.entryPatches.length > 0
                    ? manifestUpdates.entryPatches
                    : undefined,
                entryReplacements: manifestUpdates.entryReplacements.length > 0
                    ? manifestUpdates.entryReplacements
                    : undefined
            });
        }
        case "spec-registry": {
            const specUpdates = toSpecFieldUpdates(options.assignments);
            const currentDocument = (0, spec_registry_1.parseSpecIndexDocumentText)(options.originalContent);
            const nextDocument = (0, spec_registry_1.applySpecIndexEntryFieldUpdates)({
                currentDocument,
                entryId: specUpdates.entryId,
                updates: specUpdates.updates
            });
            if (Object.keys(specUpdates.updates).some((key) => key.startsWith("linked_slice."))) {
                assertLinkedSliceTargetIsWritable({
                    repositoryRoot: options.repositoryRoot,
                    entryId: specUpdates.entryId,
                    document: nextDocument
                });
            }
            return (0, spec_registry_1.renderSpecIndexDocument)(nextDocument);
        }
        default:
            return assertUnreachable(options.family);
    }
}
function assertLinkedSliceTargetIsWritable(options) {
    const entry = options.document.entries.find((candidate) => candidate.id === options.entryId);
    const linkedSlice = entry?.optional.linked_slice;
    if (entry === undefined || linkedSlice === undefined) {
        throw new TypeError(`Spec index entry '${options.entryId}' must include linked_slice.slice and linked_slice.path after a linked_slice update.`);
    }
    const targetAbsolutePath = (0, paths_1.resolveRepositoryRelativePath)(options.repositoryRoot, (0, paths_1.parseRepositoryRelativePath)(linkedSlice.path));
    if (!node_fs_1.default.existsSync(targetAbsolutePath)) {
        throw new TypeError(`Spec index entry '${options.entryId}' linked_slice.path '${linkedSlice.path}' must reference an existing slice overview before the registry update can be written.`);
    }
    const targetContent = node_fs_1.default.readFileSync(targetAbsolutePath, "utf8");
    const frontMatter = readPlanningFrontMatter(linkedSlice.path, targetContent);
    assertFrontMatterValue(frontMatter, "artifact_type", "slice_overview", linkedSlice.path);
    assertFrontMatterValue(frontMatter, "slice", linkedSlice.slice, linkedSlice.path);
    const missingCompanions = [
        node_path_1.default.posix.join(node_path_1.default.posix.dirname(linkedSlice.path), "decisions", ".gitkeep"),
        node_path_1.default.posix.join(node_path_1.default.posix.dirname(linkedSlice.path), "notes", ".gitkeep")
    ].filter((companionPath) => !node_fs_1.default.existsSync((0, paths_1.resolveRepositoryRelativePath)(options.repositoryRoot, (0, paths_1.parseRepositoryRelativePath)(companionPath))));
    if (missingCompanions.length > 0) {
        throw new TypeError(`Spec index entry '${options.entryId}' linked_slice.path '${linkedSlice.path}' is missing required slice companion artifacts: ${missingCompanions.join(", ")}.`);
    }
    const workflowProvenance = frontMatter.get("workflow_provenance") ?? "";
    const workflowCliCommand = frontMatter.get("workflow_cli_command") ?? "";
    const workflowManualException = frontMatter.get("workflow_manual_exception") ?? "";
    const isCliScaffolded = workflowProvenance === "cli" &&
        /^day-shift slice new\b|^node dist\/cli\/index\.js slice new\b/u.test(workflowCliCommand);
    const isManualException = workflowProvenance === "manual-exception" &&
        isAllowedManualException(workflowManualException) &&
        workflowCliCommand.trim() !== "";
    if (!isCliScaffolded && !isManualException) {
        throw new TypeError([
            `Spec index entry '${options.entryId}' linked_slice.path '${linkedSlice.path}' must reference a CLI-scaffolded slice overview or an allowed manual-exception artifact.`,
            `Found workflow_provenance '${workflowProvenance || "<missing>"}', workflow_cli_command '${workflowCliCommand || "<missing>"}', workflow_manual_exception '${workflowManualException || "<missing>"}'.`
        ].join(" "));
    }
}
function assertFrontMatterValue(frontMatter, field, expected, artifactPath) {
    const actual = frontMatter.get(field);
    if (actual !== expected) {
        throw new TypeError(`Linked slice target '${artifactPath}' has ${field} '${actual ?? "<missing>"}'; expected '${expected}'.`);
    }
}
function isAllowedManualException(value) {
    return value === "unsupported by CLI" ||
        value === "CLI failed" ||
        value === "manual recovery after scaffold verification";
}
function readPlanningFrontMatter(filePath, content) {
    return readPlanningMetadata(filePath, content, false);
}
function readPlanningMetadata(filePath, content, includeNested = true) {
    const lines = content.split(/\r?\n/);
    if (lines[0] !== "---") {
        throw new TypeError(`Planning artifact '${filePath}' is missing YAML front matter.`);
    }
    const closingIndex = lines.findIndex((line, index) => index > 0 && line === "---");
    if (closingIndex === -1) {
        throw new TypeError(`Planning artifact '${filePath}' has malformed YAML front matter.`);
    }
    const values = new Map();
    let parentKey = null;
    for (let index = 1; index < closingIndex; index += 1) {
        const line = lines[index];
        const topLevelMatch = line.match(/^([A-Za-z0-9_]+):\s*(.*)$/);
        if (topLevelMatch !== null) {
            parentKey = topLevelMatch[2].trim() === "" ? topLevelMatch[1] : null;
            values.set(topLevelMatch[1], (0, front_matter_utils_1.parseScalar)(topLevelMatch[2]));
            continue;
        }
        if (!includeNested || parentKey === null) {
            continue;
        }
        const nestedMatch = line.match(/^\s{2}([A-Za-z0-9_]+):\s*(.*)$/);
        if (nestedMatch !== null) {
            values.set(`${parentKey}.${nestedMatch[1]}`, (0, front_matter_utils_1.parseScalar)(nestedMatch[2]));
        }
    }
    return values;
}
function assertWritablePromptLayerPath(artifactPath) {
    const layer = (0, config_contract_1.classifyPromptWorkspaceLayer)(artifactPath, config_contract_1.BUILT_IN_CONFIG_DEFAULTS);
    if (layer === "user") {
        return;
    }
    if (layer === "latest") {
        throw new TypeError(`Prompt metadata updates may not write directly to latest-layer prompt '${artifactPath}'. Copy the active prompt into '${config_contract_1.BUILT_IN_CONFIG_DEFAULTS.prompt_user_root}/' before mutation; latest and packaged-default layers remain read-only sources.`);
    }
    if (layer === "shared-root") {
        throw new TypeError(`Prompt metadata updates may target only user-layer prompt files under '${config_contract_1.BUILT_IN_CONFIG_DEFAULTS.prompt_user_root}/'.`);
    }
    throw new TypeError(`Prompt metadata updates may target only repository prompt files under '${config_contract_1.BUILT_IN_CONFIG_DEFAULTS.prompt_user_root}/'.`);
}
function toStringUpdateMap(assignments) {
    const updates = {};
    for (const assignment of assignments) {
        updates[assignment.key] = (0, front_matter_utils_1.parseScalar)(assignment.rawValue);
    }
    return updates;
}
function toFieldChanges(assignments) {
    return assignments.map((assignment) => ({
        key: assignment.key,
        value: (0, front_matter_utils_1.parseScalar)(assignment.rawValue)
    }));
}
function toManifestUpdates(assignments) {
    const topLevelFields = {};
    const entryPatchMap = new Map();
    const entryReplacements = [];
    for (const assignment of assignments) {
        if (assignment.key.startsWith("entry:")) {
            const [entryPath, field] = parseManifestEntryKey(assignment.key);
            const updatesForPath = entryPatchMap.get(entryPath) ?? {};
            updatesForPath[field] = parseLooseValue(assignment.rawValue);
            entryPatchMap.set(entryPath, updatesForPath);
            continue;
        }
        if (assignment.key.startsWith("replace:")) {
            const entryPath = parseManifestReplacementKey(assignment.key);
            const replacementValue = parseLooseValue(assignment.rawValue);
            if (!isPlainObject(replacementValue)) {
                throw new TypeError(`Manifest replacement '${assignment.key}' requires an object-shaped JSON value.`);
            }
            entryReplacements.push({
                path: entryPath,
                entry: replacementValue
            });
            continue;
        }
        const topLevelKey = assignment.key.startsWith("top:")
            ? assignment.key.slice("top:".length)
            : assignment.key;
        if (topLevelKey.trim() === "") {
            throw new TypeError("Manifest top-level field keys must be non-empty.");
        }
        topLevelFields[topLevelKey] = parseLooseValue(assignment.rawValue);
    }
    const entryPatches = Array.from(entryPatchMap.entries()).map(([entryPath, fields]) => ({
        path: entryPath,
        fields
    }));
    return {
        topLevelFields,
        entryPatches,
        entryReplacements
    };
}
function parseManifestReplacementKey(key) {
    const entryPath = key.slice("replace:".length).trim();
    if (entryPath === "") {
        throw new TypeError(`Invalid manifest replacement key '${key}'. Use 'replace:<path>'.`);
    }
    return entryPath;
}
function parseManifestEntryKey(key) {
    const firstSeparator = key.indexOf(":");
    const secondSeparator = key.indexOf(":", firstSeparator + 1);
    if (secondSeparator === -1) {
        throw new TypeError(`Invalid manifest entry update key '${key}'. Use 'entry:<path>:<field>'.`);
    }
    const entryPath = key.slice(firstSeparator + 1, secondSeparator).trim();
    const field = key.slice(secondSeparator + 1).trim();
    if (entryPath === "" || field === "") {
        throw new TypeError(`Invalid manifest entry update key '${key}'. Use 'entry:<path>:<field>'.`);
    }
    return [entryPath, field];
}
function toSpecFieldUpdates(assignments) {
    let entryId = null;
    const updates = {};
    for (const assignment of assignments) {
        const [parsedEntryId, fieldPath] = parseSpecEntryKey(assignment.key);
        if (entryId === null) {
            entryId = parsedEntryId;
        }
        else if (entryId !== parsedEntryId) {
            throw new TypeError("Spec-registry updates must target exactly one entry id per command invocation.");
        }
        updates[fieldPath] = parseLooseValue(assignment.rawValue);
    }
    if (entryId === null) {
        throw new TypeError("Spec-registry updates require at least one entry field update.");
    }
    return {
        entryId,
        updates
    };
}
function parseSpecEntryKey(key) {
    if (!key.startsWith("entry:")) {
        throw new TypeError(`Invalid spec-registry update key '${key}'. Use 'entry:<id>:<field-path>'.`);
    }
    const firstSeparator = key.indexOf(":");
    const secondSeparator = key.indexOf(":", firstSeparator + 1);
    if (secondSeparator === -1) {
        throw new TypeError(`Invalid spec-registry update key '${key}'. Use 'entry:<id>:<field-path>'.`);
    }
    const entryId = key.slice(firstSeparator + 1, secondSeparator).trim();
    const fieldPath = key.slice(secondSeparator + 1).trim();
    if (entryId === "" || fieldPath === "") {
        throw new TypeError(`Invalid spec-registry update key '${key}'. Use 'entry:<id>:<field-path>'.`);
    }
    return [entryId, fieldPath];
}
function parseLooseValue(rawValue) {
    const trimmed = rawValue.trim();
    if (trimmed === "") {
        return "";
    }
    if ((trimmed.startsWith("\"") && trimmed.endsWith("\"")) || (trimmed.startsWith("'") && trimmed.endsWith("'"))) {
        return (0, front_matter_utils_1.parseScalar)(trimmed);
    }
    if (trimmed === "true") {
        return true;
    }
    if (trimmed === "false") {
        return false;
    }
    if (trimmed === "null") {
        return null;
    }
    if (/^-?\d+(\.\d+)?$/.test(trimmed)) {
        const parsedNumber = Number(trimmed);
        if (!Number.isNaN(parsedNumber)) {
            return parsedNumber;
        }
    }
    if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
        return JSON.parse(trimmed);
    }
    return (0, front_matter_utils_1.parseScalar)(rawValue);
}
function readFrontMatter(filePath, content) {
    const lines = content.split(/\r?\n/);
    if (lines[0] !== "---") {
        throw new TypeError(`Markdown metadata surface '${filePath}' is missing YAML front matter.`);
    }
    const closingIndex = lines.findIndex((line, index) => index > 0 && line === "---");
    if (closingIndex === -1) {
        throw new TypeError(`Markdown metadata surface '${filePath}' has malformed YAML front matter.`);
    }
    let artifactType;
    for (let index = 1; index < closingIndex; index += 1) {
        const match = lines[index].match(/^([A-Za-z0-9_]+):\s*(.*)$/);
        if (match === null) {
            continue;
        }
        if (match[1] === "artifact_type") {
            artifactType = (0, front_matter_utils_1.parseScalar)(match[2]);
        }
    }
    return { artifactType };
}
function isPlainObject(value) {
    return typeof value === "object" && value !== null && !Array.isArray(value);
}
function assertUnreachable(value) {
    throw new TypeError(`Unsupported metadata family '${String(value)}'.`);
}
