"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createMilestoneWorkspace = createMilestoneWorkspace;
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const errors_1 = require("../errors");
const authoring_policy_1 = require("./authoring-policy");
const command_write_summary_1 = require("../license/command-write-summary");
const paths_1 = require("../paths");
const front_matter_utils_1 = require("./front-matter-utils");
const upstream_specs_1 = require("./upstream-specs");
const path_resolution_1 = require("../templates/path-resolution");
const workflow_provenance_1 = require("./workflow-provenance");
const runtime_acceptance_1 = require("./runtime-acceptance");
function createMilestoneWorkspace(repositoryRoot, options) {
    const phaseOverviewPath = resolvePhaseOverviewPath(repositoryRoot, options.phaseOverviewPath);
    if (!node_fs_1.default.existsSync(phaseOverviewPath.absolute)) {
        throw (0, errors_1.createUsageError)(`Parent phase overview not found at '${phaseOverviewPath.relative}'.`, ["Run day-shift phase new first or pass the correct --phase-overview path."]);
    }
    const parsedPhaseOverview = parsePhaseOverview(phaseOverviewPath.absolute);
    const phaseOverviewText = node_fs_1.default.readFileSync(phaseOverviewPath.absolute, "utf8");
    const declaredMilestoneSlugs = (0, authoring_policy_1.declaredPlanningChildSlugs)(phaseOverviewText, "Milestones");
    const decompositionIssues = (0, authoring_policy_1.auditParentDecomposition)({
        artifactPath: phaseOverviewPath.relative,
        markdownText: phaseOverviewText,
        childKind: "milestone",
        declaredChildSlugs: declaredMilestoneSlugs
    });
    if (decompositionIssues.length > 0) {
        throw (0, errors_1.createUsageError)(`Planning decomposition contract rejected '${phaseOverviewPath.relative}' before milestone writes.`, (0, authoring_policy_1.formatParentDecompositionIssues)(decompositionIssues));
    }
    const upstreamSpecs = (0, upstream_specs_1.normalizeUpstreamSpecsToLocalSpecPaths)(repositoryRoot, parsedPhaseOverview.upstreamSpecs);
    const milestoneSlug = resolveMilestoneSlug(options.milestoneSlug);
    if (!declaredMilestoneSlugs.includes(milestoneSlug)) {
        throw (0, errors_1.createUsageError)(`Milestone '${milestoneSlug}' is not declared by '${phaseOverviewPath.relative}'.`, ["Declare the milestone and update the authored target count and decomposition rationale before scaffolding."]);
    }
    const milestoneTitle = resolveMilestoneTitle(milestoneSlug, options.milestoneTitle);
    const milestoneDescription = resolveMilestoneDescription(milestoneSlug, options.milestoneDescription, parsedPhaseOverview.milestoneDescriptions);
    const phaseDirectoryPath = node_path_1.default.dirname(phaseOverviewPath.absolute);
    const milestonesDirectoryPath = node_path_1.default.join(phaseDirectoryPath, "milestones");
    const milestoneDirectoryPath = node_path_1.default.join(milestonesDirectoryPath, milestoneSlug);
    const milestoneDirectoryRelative = (0, front_matter_utils_1.toRepositoryLikePath)(node_path_1.default.relative(repositoryRoot, milestoneDirectoryPath));
    const overviewRelativePath = node_path_1.default.basename(phaseOverviewPath.relative) === "overview.md"
        ? (0, paths_1.composeLegacyPlanningOverviewPath)(milestoneDirectoryRelative)
        : (0, paths_1.composeCanonicalPlanningOverviewPath)("milestone", milestoneDirectoryRelative);
    const overviewPath = node_path_1.default.join(repositoryRoot, overviewRelativePath);
    const reconciliationPath = node_path_1.default.join(milestoneDirectoryPath, "reconciliation.md");
    if (node_fs_1.default.existsSync(overviewPath) && parsedPhaseOverview.runtimeAcceptance !== null) {
        const existingText = node_fs_1.default.readFileSync(overviewPath, "utf8");
        const existingFrontMatter = extractFrontMatter(overviewPath, existingText);
        const existingInspection = (0, runtime_acceptance_1.inspectRuntimeAcceptance)({
            artifactPath: overviewPath,
            artifactKind: "milestone",
            frontMatterLines: existingFrontMatter.lines,
            markdownText: existingText,
            requireExplicitForExecutableEvidence: true
        });
        const inheritanceIssues = [
            ...existingInspection.issues,
            ...(0, runtime_acceptance_1.validateInheritedRuntimeAcceptance)(parsedPhaseOverview.runtimeAcceptance, existingInspection.metadata)
        ];
        if (inheritanceIssues.length > 0) {
            throw (0, errors_1.createUsageError)(`Runtime acceptance contract rejected '${(0, front_matter_utils_1.toRepositoryLikePath)(overviewPath)}'.`, inheritanceIssues);
        }
    }
    const taskCandidateSlugs = resolveMilestoneTaskCandidateSlugs(milestoneSlug);
    const runtimeAcceptance = parsedPhaseOverview.runtimeAcceptance === null
        ? null
        : (0, runtime_acceptance_1.childRuntimeAcceptanceMetadata)(parsedPhaseOverview.runtimeAcceptance, {
            breakoutTask: parsedPhaseOverview.runtimeAcceptance.required ? taskCandidateSlugs[0] : null
        });
    const overviewExistsBeforeWrite = node_fs_1.default.existsSync(overviewPath);
    const reconciliationExistsBeforeWrite = node_fs_1.default.existsSync(reconciliationPath);
    const renderedOverview = overviewExistsBeforeWrite
        ? null
        : renderMilestoneOverviewMarkdown({
            milestoneTitle,
            slice: parsedPhaseOverview.slice,
            phase: parsedPhaseOverview.phase,
            milestoneSlug,
            milestoneDescription,
            planningDepth: parsedPhaseOverview.planningDepth,
            sliceOverviewPath: parsedPhaseOverview.sliceOverviewPath,
            phaseOverviewPath: phaseOverviewPath.relative,
            upstreamSpecs,
            phasePurpose: parsedPhaseOverview.purpose,
            phaseScope: parsedPhaseOverview.scope,
            phaseAcceptanceCriteria: parsedPhaseOverview.acceptanceCriteria,
            phaseDependencies: parsedPhaseOverview.dependencies,
            phaseRisks: parsedPhaseOverview.risks,
            phaseValidationFocus: parsedPhaseOverview.validationFocus,
            runtimeAcceptance,
            workflowCliCommand: options.workflowCliCommand
        });
    const renderedReconciliation = reconciliationExistsBeforeWrite
        ? null
        : renderMilestoneReconciliationMarkdown({
            repositoryRoot,
            milestoneTitle,
            slice: parsedPhaseOverview.slice,
            phase: parsedPhaseOverview.phase,
            milestoneSlug,
            planningDepth: parsedPhaseOverview.planningDepth,
            sliceOverviewPath: parsedPhaseOverview.sliceOverviewPath,
            phaseOverviewPath: phaseOverviewPath.relative,
            milestoneOverviewPath: (0, front_matter_utils_1.toRepositoryLikePath)(node_path_1.default.relative(repositoryRoot, overviewPath)),
            upstreamSpecs,
            workflowCliCommand: options.workflowCliCommand
        });
    const overviewExists = node_fs_1.default.existsSync(overviewPath);
    const reconciliationExists = node_fs_1.default.existsSync(reconciliationPath);
    const milestonesDirectoryAction = node_fs_1.default.existsSync(milestonesDirectoryPath) ? "kept" : "created";
    if (options.validateOnly !== true) {
        ensureDirectory(milestonesDirectoryPath);
        node_fs_1.default.mkdirSync(milestoneDirectoryPath, { recursive: true });
        if (!overviewExists && renderedOverview !== null) {
            node_fs_1.default.writeFileSync(overviewPath, renderedOverview, "utf8");
        }
        if (!reconciliationExists && renderedReconciliation !== null) {
            node_fs_1.default.writeFileSync(reconciliationPath, renderedReconciliation, "utf8");
        }
    }
    const reconciliationRelativePath = (0, front_matter_utils_1.toRepositoryLikePath)(node_path_1.default.relative(repositoryRoot, reconciliationPath));
    return {
        repositoryRoot,
        slice: parsedPhaseOverview.slice,
        phase: parsedPhaseOverview.phase,
        planningDepth: parsedPhaseOverview.planningDepth,
        phaseOverviewPath: phaseOverviewPath.relative,
        milestonesDirectoryPath,
        milestoneDirectoryPath,
        overviewPath,
        reconciliationPath,
        milestoneSlug,
        milestoneTitle,
        milestonesDirectoryAction,
        overviewAction: overviewExists ? "kept" : "created",
        reconciliationAction: reconciliationExists ? "kept" : "created",
        contributingSpecIds: upstreamSpecs.map((entry) => entry.id),
        commandWriteSummary: (0, command_write_summary_1.normalizeCommandWriteSummary)({
            commandFamily: "milestone_generation",
            primaryOutputArtifacts: [overviewRelativePath, reconciliationRelativePath],
            updatedArtifacts: [
                {
                    path: overviewRelativePath,
                    action: overviewExists ? "kept" : "created",
                    reason: overviewExists ? "no_write" : "accepted_create"
                },
                {
                    path: reconciliationRelativePath,
                    action: reconciliationExists ? "kept" : "created",
                    reason: reconciliationExists ? "no_write" : "accepted_create"
                }
            ]
        })
    };
}
function resolvePhaseOverviewPath(repositoryRoot, inputPath) {
    try {
        return (0, paths_1.resolvePlanningOverviewInputPath)(repositoryRoot, {
            layer: "phase",
            inputPath
        });
    }
    catch (error) {
        throw (0, errors_1.createUsageError)(`Invalid --phase-overview path '${inputPath}'.`, [error instanceof Error ? error.message : String(error)]);
    }
}
function resolveMilestoneSlug(rawMilestoneSlug) {
    if ((0, paths_1.isCanonicalSlug)(rawMilestoneSlug)) {
        return rawMilestoneSlug;
    }
    const normalized = (0, paths_1.normalizeCanonicalSlug)(rawMilestoneSlug);
    if (normalized.kind === "canonical-slug") {
        return normalized.normalizedSlug;
    }
    throw (0, errors_1.createUsageError)(`Invalid milestone slug '${rawMilestoneSlug}'.`, [normalized.reason.message]);
}
function resolveMilestoneTitle(milestoneSlug, requestedTitle) {
    const trimmed = requestedTitle?.trim();
    if (trimmed !== undefined && trimmed !== "") {
        return trimmed;
    }
    return (0, front_matter_utils_1.toTitleCase)(milestoneSlug);
}
function ensureDirectory(directoryPath) {
    if (node_fs_1.default.existsSync(directoryPath)) {
        return "kept";
    }
    node_fs_1.default.mkdirSync(directoryPath, { recursive: true });
    return "created";
}
function parsePhaseOverview(phaseOverviewPath) {
    const fileText = node_fs_1.default.readFileSync(phaseOverviewPath, "utf8");
    const sections = extractMarkdownSections(fileText);
    const frontMatter = extractFrontMatter(phaseOverviewPath, fileText);
    const artifactType = readTopLevelField(frontMatter.lines, "artifact_type");
    if (artifactType !== "phase_overview") {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(phaseOverviewPath)}' must use artifact_type: phase_overview.`);
    }
    const slice = readTopLevelField(frontMatter.lines, "slice");
    if (slice === undefined || slice.trim() === "") {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(phaseOverviewPath)}' is missing required top-level field 'slice'.`);
    }
    const phase = readTopLevelField(frontMatter.lines, "phase");
    if (phase === undefined || phase.trim() === "") {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(phaseOverviewPath)}' is missing required top-level field 'phase'.`);
    }
    const planningDepth = readTopLevelField(frontMatter.lines, "planning_depth")?.trim() || "standard";
    const sliceOverviewPath = readUpstreamField(frontMatter.lines, "slice_overview");
    if (sliceOverviewPath === undefined || sliceOverviewPath.trim() === "") {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(phaseOverviewPath)}' is missing required upstream field 'slice_overview'.`);
    }
    const upstreamSpecs = parseUpstreamSpecs(frontMatter.lines, phaseOverviewPath);
    const runtimeAcceptance = (0, runtime_acceptance_1.assertRuntimeAcceptanceInspection)((0, runtime_acceptance_1.inspectRuntimeAcceptance)({
        artifactPath: phaseOverviewPath,
        artifactKind: "phase",
        frontMatterLines: frontMatter.lines,
        markdownText: fileText
    }));
    if (upstreamSpecs.length === 0) {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(phaseOverviewPath)}' must include at least one upstream spec entry under upstream.specs.`);
    }
    return {
        slice: slice.trim(),
        phase: phase.trim(),
        planningDepth,
        sliceOverviewPath: sliceOverviewPath.trim(),
        upstreamSpecs,
        purpose: normalizeSectionText(sections.get("Purpose")),
        scope: sectionBullets(sections.get("Scope")),
        acceptanceCriteria: sectionBullets(sections.get("Acceptance Criteria")),
        dependencies: sectionBullets(sections.get("Dependencies")),
        risks: sectionBullets(sections.get("Risks")),
        validationFocus: sectionBullets(sections.get("Validation Focus")),
        milestoneDescriptions: parseDeclaredMilestoneDescriptions(sections.get("Milestones") ?? []),
        runtimeAcceptance
    };
}
function extractFrontMatter(filePath, text) {
    const lines = text.split(/\r?\n/);
    if (lines[0] !== "---") {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(filePath)}' is missing YAML front matter.`);
    }
    let closingIndex = -1;
    for (let index = 1; index < lines.length; index += 1) {
        if (lines[index] === "---") {
            closingIndex = index;
            break;
        }
    }
    if (closingIndex === -1) {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(filePath)}' has malformed YAML front matter.`);
    }
    return {
        lines: lines.slice(1, closingIndex)
    };
}
function readTopLevelField(lines, key) {
    for (const line of lines) {
        if (/^\s/.test(line)) {
            continue;
        }
        const match = line.match(/^([A-Za-z0-9_]+):\s*(.*)$/);
        if (match === null) {
            continue;
        }
        if (match[1] === key) {
            return (0, front_matter_utils_1.parseScalar)(match[2]);
        }
    }
    return undefined;
}
function readUpstreamField(lines, key) {
    let inUpstream = false;
    for (const line of lines) {
        if (!inUpstream) {
            if (line.trim() === "upstream:") {
                inUpstream = true;
            }
            continue;
        }
        if (!/^\s/.test(line)) {
            break;
        }
        const match = line.match(/^\s{2}([A-Za-z0-9_]+):\s*(.*)$/);
        if (match !== null && match[1] === key) {
            return (0, front_matter_utils_1.parseScalar)(match[2]);
        }
    }
    return undefined;
}
function parseUpstreamSpecs(lines, filePath) {
    const entries = [];
    for (let index = 0; index < lines.length; index += 1) {
        const idMatch = lines[index].match(/^\s*-\s+id:\s*(.+)$/);
        if (idMatch === null) {
            continue;
        }
        const depthLine = lines[index + 1];
        const refLine = lines[index + 2];
        const sourceTypeLine = lines[index + 3];
        const depthMatch = depthLine?.match(/^\s+depth:\s*(.+)$/);
        const refMatch = refLine?.match(/^\s+ref:\s*(.+)$/);
        const sourceTypeMatch = sourceTypeLine?.match(/^\s+source_type:\s*(.+)$/);
        if (depthMatch === null || refMatch === null || sourceTypeMatch === null) {
            throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(filePath)}' has malformed upstream.specs metadata near '${lines[index].trim()}'.`);
        }
        entries.push({
            id: (0, front_matter_utils_1.parseScalar)(idMatch[1]),
            depth: (0, front_matter_utils_1.parseScalar)(depthMatch[1]),
            ref: (0, front_matter_utils_1.parseScalar)(refMatch[1]),
            sourceType: (0, front_matter_utils_1.parseScalar)(sourceTypeMatch[1])
        });
        index += 3;
    }
    return entries;
}
function extractMarkdownSections(text) {
    const lines = text.split(/\r?\n/);
    const sections = new Map();
    let currentSection;
    for (const line of lines) {
        const headingMatch = line.match(/^##\s+(.+?)\s*$/);
        if (headingMatch !== null) {
            currentSection = headingMatch[1];
            sections.set(currentSection, []);
            continue;
        }
        if (line.startsWith("# ")) {
            currentSection = undefined;
            continue;
        }
        if (currentSection !== undefined) {
            sections.get(currentSection)?.push(line);
        }
    }
    return sections;
}
function normalizeSectionText(lines) {
    return (lines ?? [])
        .map((line) => line.trim())
        .filter((line) => line !== "")
        .join(" ");
}
function sectionBullets(lines) {
    return (lines ?? [])
        .map((line) => line.trim())
        .filter((line) => line.startsWith("- "))
        .map((line) => line.slice(2).trim())
        .filter((line) => line !== "");
}
function parseDeclaredMilestoneDescriptions(lines) {
    const descriptions = new Map();
    for (const line of lines) {
        const match = line.trim().match(/^-\s+`([^`]+)`:\s*(.+)$/);
        if (match !== null) {
            descriptions.set(match[1].trim(), match[2].trim());
        }
    }
    return descriptions;
}
function resolveMilestoneDescription(milestoneSlug, requestedDescription, milestoneDescriptions) {
    const trimmed = requestedDescription?.trim();
    if (trimmed !== undefined && trimmed !== "") {
        return trimmed;
    }
    return milestoneDescriptions.get(milestoneSlug) ?? "";
}
function renderMilestoneOverviewMarkdown(options) {
    const workflowProvenance = (0, workflow_provenance_1.buildCliWorkflowProvenance)(options.workflowCliCommand
        ?? `day-shift milestone new --phase-overview ${options.phaseOverviewPath} --milestone-slug ${options.milestoneSlug}`);
    const upstreamSpecs = options.upstreamSpecs
        .map((entry) => {
        return [
            `    - id: ${entry.id}`,
            `      depth: ${entry.depth}`,
            `      ref: ${JSON.stringify(entry.ref)}`,
            `      source_type: ${JSON.stringify(entry.sourceType)}`
        ].join("\n");
    })
        .join("\n");
    const text = (0, runtime_acceptance_1.injectRuntimeAcceptanceFrontMatter)([
        "---",
        "artifact_schema_version: 1",
        "artifact_type: milestone_overview",
        `slice: ${options.slice}`,
        `phase: ${options.phase}`,
        `milestone: ${options.milestoneSlug}`,
        `planning_depth: ${options.planningDepth}`,
        `workflow_provenance: ${workflowProvenance.workflowProvenance}`,
        `workflow_cli_command: ${JSON.stringify(workflowProvenance.workflowCliCommand)}`,
        "status: draft",
        "upstream:",
        "  specs:",
        upstreamSpecs,
        `  slice_overview: ${options.sliceOverviewPath}`,
        `  phase_overview: ${options.phaseOverviewPath}`,
        "---",
        "",
        `# ${options.milestoneTitle}`,
        "",
        "## Purpose",
        "",
        renderMilestonePurpose(options),
        "",
        "## Scope",
        "",
        ...renderMilestoneScope(options),
        "",
        "## Navigation",
        "",
        `- ${options.phaseOverviewPath}`,
        `- ${options.sliceOverviewPath}`,
        "",
        "## Tasks",
        "",
        ...renderMilestoneTaskCandidates(options),
        "",
        "## Acceptance Criteria",
        "",
        ...renderMilestoneAcceptanceCriteria(options),
        "",
        "## Dependencies",
        "",
        ...renderMilestoneDependencies(options),
        "",
        "## Risks",
        "",
        ...renderMilestoneRisks(options),
        "",
        "## Validation Focus",
        "",
        ...renderMilestoneValidationFocus(options),
        "",
        "## Open Questions",
        "",
        "- None currently.",
        ""
    ].join("\n"), options.runtimeAcceptance, { includeBreakoutPolicy: true });
    assertPlanningAuthoringCompliance("milestone_overview", text);
    return text;
}
function renderMilestonePurpose(options) {
    if (options.milestoneDescription !== "") {
        return `Implement the \`${options.milestoneSlug}\` milestone: ${sentenceCase(verbPolicySafeProse(options.milestoneDescription))}`;
    }
    if (options.phasePurpose !== "") {
        return `Advance phase \`${options.phase}\` by completing the \`${options.milestoneSlug}\` milestone within the parent phase purpose: ${verbPolicySafeProse(options.phasePurpose)}`;
    }
    return `Complete the \`${options.milestoneSlug}\` milestone with explicit scope, validation evidence, and traceability to the parent phase.`;
}
function renderMilestoneScope(options) {
    const scoped = [
        options.milestoneDescription === "" ? undefined : `Deliver the declared milestone outcome: ${verbPolicySafeProse(options.milestoneDescription)}`,
        ...options.phaseScope.slice(0, 4).map((item) => `Apply parent phase scope: ${verbPolicySafeProse(item)}`)
    ].filter((item) => item !== undefined);
    return listOrFallback(scoped, [
        "Keep milestone work bounded to the parent phase declaration and directly related implementation surfaces.",
        "Preserve parent and source traceability in generated planning artifacts."
    ]);
}
function renderMilestoneTaskCandidates(options) {
    const [contractSlug, coverageSlug] = resolveMilestoneTaskCandidateSlugs(options.milestoneSlug);
    const behaviorNoun = options.milestoneDescription === ""
        ? "declared milestone behavior"
        : trimTerminalPunctuation(verbPolicySafeProse(options.milestoneDescription));
    return [
        `- \`${contractSlug}\`: implement parent-derived scaffold behavior for ${behaviorNoun}.`,
        `- \`${coverageSlug}\`: add focused regression coverage for ${behaviorNoun}.`
    ];
}
function resolveMilestoneTaskCandidateSlugs(milestoneSlug) {
    const baseSlug = milestoneSlug.replace(/^\d{2}-/, "");
    return [
        truncateSlug(`01-derive-${baseSlug}-contract`),
        truncateSlug(`02-cover-${baseSlug}-behavior`)
    ];
}
function renderMilestoneAcceptanceCriteria(options) {
    const criteria = [
        options.milestoneDescription === "" ? undefined : `The generated work satisfies the declared milestone outcome: ${verbPolicySafeProse(options.milestoneDescription)}`,
        ...options.phaseAcceptanceCriteria.slice(0, 4).map((item) => `Parent phase criterion addressed where in scope: ${verbPolicySafeProse(item)}`)
    ].filter((item) => item !== undefined);
    return listOrFallback(criteria, [
        "Milestone task outcomes are traceable to the parent phase declaration.",
        "Validation evidence covers the milestone behavior without broadening the phase scope."
    ]);
}
function renderMilestoneDependencies(options) {
    return listOrFallback([
        options.phaseOverviewPath,
        options.sliceOverviewPath,
        ...options.upstreamSpecs.map((entry) => entry.ref),
        ...options.phaseDependencies.slice(0, 3)
    ], [options.phaseOverviewPath]);
}
function renderMilestoneRisks(options) {
    return listOrFallback(options.phaseRisks.slice(0, 4).map((item) => `Parent phase risk to manage: ${item}`), ["Implementation may reveal additional contract gaps that should be recorded as discovered work instead of silently broadening scope."]);
}
function renderMilestoneValidationFocus(options) {
    return listOrFallback(options.phaseValidationFocus.slice(0, 4).map((item) => `Use parent phase validation focus: ${item}`), ["Run focused validation for generated planning artifacts and changed implementation surfaces."]);
}
function listOrFallback(items, fallback) {
    const normalized = items
        .map((item) => item.trim())
        .filter((item, index, allItems) => item !== "" && allItems.indexOf(item) === index);
    return (normalized.length === 0 ? fallback : normalized).map((item) => `- ${item}`);
}
function sentenceCase(value) {
    if (value === "") {
        return value;
    }
    return `${value[0].toLowerCase()}${value.slice(1)}`;
}
function verbPolicySafeProse(value) {
    return value.replace(/\bdefine\b/gi, (match) => {
        return match[0] === match[0].toUpperCase() ? "Specify" : "specify";
    });
}
function trimTerminalPunctuation(value) {
    return value.replace(/[.!?]+\s*$/, "");
}
function truncateSlug(value) {
    const parts = value.split("-");
    while (parts.join("-").length > 72 && parts.length > 4) {
        parts.splice(parts.length - 2, 1);
    }
    return parts.join("-");
}
function renderMilestoneReconciliationMarkdown(options) {
    const templatePath = (0, path_resolution_1.resolveWorkspaceTemplateAbsolutePath)({
        repositoryRoot: options.repositoryRoot,
        templatePath: ".day-shift/templates/milestone-reconciliation.md"
    });
    if (!node_fs_1.default.existsSync(templatePath)) {
        throw (0, errors_1.createUsageError)("Milestone reconciliation template is missing.", ["Expected template at .day-shift/templates/milestone-reconciliation.md"]);
    }
    const upstreamSpecsBlock = options.upstreamSpecs
        .map((entry) => {
        return [
            `    - id: ${entry.id}`,
            `      depth: ${entry.depth}`,
            `      ref: ${JSON.stringify(entry.ref)}`,
            `      source_type: ${JSON.stringify(entry.sourceType)}`
        ].join("\n");
    })
        .join("\n");
    let text = node_fs_1.default.readFileSync(templatePath, "utf8");
    text = text.replace([
        "  specs:",
        "    - id: \"{{spec_id}}\"",
        "      depth: \"{{spec_depth}}\"",
        "      ref: \"{{spec_ref}}\"",
        "      source_type: \"{{source_type}}\""
    ].join("\n"), ["  specs:", upstreamSpecsBlock].join("\n"));
    const replacementMap = {
        "{{slice}}": options.slice,
        "{{phase}}": options.phase,
        "{{milestone}}": options.milestoneSlug,
        "{{planning_depth}}": options.planningDepth,
        "{{workflow_provenance}}": "cli",
        "{{workflow_cli_command}}": options.workflowCliCommand
            ?? `day-shift milestone new --phase-overview ${options.phaseOverviewPath} --milestone-slug ${options.milestoneSlug}`,
        "{{workflow_manual_exception}}": "",
        "{{slice_overview}}": options.sliceOverviewPath,
        "{{phase_overview}}": options.phaseOverviewPath,
        "{{milestone_overview}}": options.milestoneOverviewPath,
        "{{milestone_title}}": options.milestoneTitle,
        "{{review_status}}": "Pending. This reconciliation artifact is initialized as the default milestone review rollup path for completed task summaries.",
        "{{milestone_intent}}": "Review whether milestone outcomes and child task planning remain aligned with deterministic path and traceability contracts.",
        "{{completed_task_summaries}}": "- Pending. Add completed task implementation summaries as milestone execution work finishes.",
        "{{acceptance_criteria_review}}": "Pending review after task implementation summaries are available.",
        "{{planned_work}}": "- Execute and validate milestone tasks against the settled phase and milestone generation contracts.",
        "{{discovered_work}}": "None yet.",
        "{{backlog_work}}": "None yet. Record out-of-scope follow-up work here if implementation or review surfaces it.",
        "{{validation_review}}": "Pending. Summarize targeted CLI validation evidence once milestone tasks complete.",
        "{{follow_up_tasks}}": "Pending. Add concrete next tasks here only if reconciliation identifies remaining work after review.",
        "{{review_concerns}}": "Residual review risk remains until all milestone task summaries confirm executable behavior and validation evidence.",
        "{{final_notes}}": "Pending milestone review."
    };
    for (const [token, replacement] of Object.entries(replacementMap)) {
        text = text.split(token).join(replacement);
    }
    assertPlanningAuthoringCompliance("reconciliation", text);
    return text;
}
function assertPlanningAuthoringCompliance(artifactType, markdownText) {
    const issues = (0, authoring_policy_1.auditPlanningArtifactAuthoring)({
        artifactPath: `generated ${artifactType}`,
        artifactType,
        markdownText
    });
    if (issues.length > 0) {
        throw (0, errors_1.createUsageError)(`Planning authoring policy rejected generated ${artifactType} scaffold text.`, (0, authoring_policy_1.formatPlanningAuthoringIssues)(issues));
    }
}
