"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.assertCanonicalGovernedParentSync = assertCanonicalGovernedParentSync;
exports.assertExistingGovernedArtifactSync = assertExistingGovernedArtifactSync;
exports.readGovernedSliceOverviewSync = readGovernedSliceOverviewSync;
exports.readGovernedHierarchyPolicy = readGovernedHierarchyPolicy;
exports.renderGovernedHierarchyPolicyLines = renderGovernedHierarchyPolicyLines;
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const errors_1 = require("../errors");
const paths_1 = require("../paths");
const canonical_write_target_1 = require("../paths/canonical-write-target");
const work_routing_1 = require("../work-routing");
const planning_document_utils_1 = require("./planning-document-utils");
const policy_resolution_1 = require("./policy-resolution");
const SLICE_ID_PATTERN = /^(?:0\d|[1-9]\d+)-[a-z0-9]+(?:-[a-z0-9]+)*$/;
const IMPLEMENTATION_ORDER_PATTERN = /^(?:0\d|[1-9]\d+)$/;
function assertCanonicalGovernedParentSync(repositoryRoot, input) {
    if (input.policy === null) {
        throw (0, errors_1.createUsageError)(`New ${nextLayerName(input.layer)} scaffolds require a Governed parent; '${input.parentPath}' is a supported legacy input but not a write destination.`, ["Promote or migrate the parent into .day-shift/planning/governed/ before creating child artifacts."]);
    }
    const normalized = (0, paths_1.parseRepositoryRelativePath)(input.parentPath).normalizedPath;
    const expected = input.layer === "slice"
        ? `.day-shift/planning/governed/${input.slice}/slice-overview.md`
        : input.layer === "phase"
            ? `.day-shift/planning/governed/${input.slice}/phases/${input.phase ?? ""}/phase-overview.md`
            : `.day-shift/planning/governed/${input.slice}/phases/${input.phase ?? ""}/milestones/${input.milestone ?? ""}/milestone-overview.md`;
    if (!SLICE_ID_PATTERN.test(input.slice) || normalized !== expected) {
        throw (0, errors_1.createUsageError)(`Governed ${input.layer} overview '${normalized}' does not match canonical path '${expected}'.`);
    }
    const target = (0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, normalized);
    if (!target.exists || !node_fs_1.default.statSync(target.runtimePath).isFile()) {
        throw (0, errors_1.createUsageError)(`Governed parent overview not found at '${normalized}'.`);
    }
    const document = (0, planning_document_utils_1.parseMarkdownFrontMatter)(node_fs_1.default.readFileSync(target.runtimePath, "utf8"));
    const expectedArtifactType = `${input.layer}_overview`;
    const coordinateIssues = [];
    if ((0, planning_document_utils_1.readTopLevelField)(document.frontMatterLines, "artifact_type")?.trim() !== expectedArtifactType) {
        coordinateIssues.push(`artifact_type must be '${expectedArtifactType}'`);
    }
    if ((0, planning_document_utils_1.readTopLevelField)(document.frontMatterLines, "slice")?.trim() !== input.slice) {
        coordinateIssues.push(`slice must be '${input.slice}'`);
    }
    if (input.phase !== undefined
        && (0, planning_document_utils_1.readTopLevelField)(document.frontMatterLines, "phase")?.trim() !== input.phase) {
        coordinateIssues.push(`phase must be '${input.phase}'`);
    }
    if (input.milestone !== undefined
        && (0, planning_document_utils_1.readTopLevelField)(document.frontMatterLines, "milestone")?.trim() !== input.milestone) {
        coordinateIssues.push(`milestone must be '${input.milestone}'`);
    }
    if (input.layer !== "slice") {
        const expectedSliceOverview = `.day-shift/planning/governed/${input.slice}/slice-overview.md`;
        if (readNestedUpstreamField(document.frontMatterLines, "slice_overview")
            !== expectedSliceOverview) {
            coordinateIssues.push(`upstream.slice_overview must be '${expectedSliceOverview}'`);
        }
    }
    if (input.layer === "milestone") {
        const expectedPhaseOverview = `.day-shift/planning/governed/${input.slice}/phases/${input.phase ?? ""}/phase-overview.md`;
        if (readNestedUpstreamField(document.frontMatterLines, "phase_overview")
            !== expectedPhaseOverview) {
            coordinateIssues.push(`upstream.phase_overview must be '${expectedPhaseOverview}'`);
        }
    }
    if (coordinateIssues.length > 0) {
        throw (0, errors_1.createUsageError)(`Governed ${input.layer} overview '${normalized}' has conflicting hierarchy coordinates.`, coordinateIssues);
    }
}
function assertExistingGovernedArtifactSync(artifactPath, expectation) {
    const text = node_fs_1.default.readFileSync(artifactPath, "utf8");
    const document = (0, planning_document_utils_1.parseMarkdownFrontMatter)(text);
    const expectedFields = {
        artifact_type: expectation.artifactType,
        slice: expectation.slice,
        planning_depth: expectation.planningDepth,
        workflow_level: "governed",
        ...(expectation.phase === undefined ? {} : { phase: expectation.phase }),
        ...(expectation.milestone === undefined ? {} : { milestone: expectation.milestone }),
        ...(expectation.task === undefined ? {} : { task: expectation.task })
    };
    const issues = [];
    const workflowProvenance = (0, planning_document_utils_1.readTopLevelField)(document.frontMatterLines, "workflow_provenance")?.trim();
    if (!document.hasFrontMatter) {
        issues.push("missing YAML front matter");
    }
    for (const [field, expected] of Object.entries(expectedFields)) {
        const observed = (0, planning_document_utils_1.readTopLevelField)(document.frontMatterLines, field)?.trim();
        const isCompatibleLegacyReconciliation = field === "workflow_level"
            && observed === undefined
            && expectation.artifactType === "reconciliation"
            && workflowProvenance === "cli";
        if (observed !== expected && !isCompatibleLegacyReconciliation) {
            issues.push(`${field}: expected '${expected}', observed '${observed ?? "(missing)"}'`);
        }
    }
    for (const [field, expected] of Object.entries(expectation.upstream ?? {})) {
        const observed = readNestedUpstreamField(document.frontMatterLines, field);
        if (observed !== expected) {
            issues.push(`upstream.${field}: expected '${expected}', observed '${observed ?? "(missing)"}'`);
        }
    }
    if (issues.length > 0) {
        throw (0, errors_1.createUsageError)(`Existing scaffold artifact '${artifactPath}' conflicts with the requested Governed hierarchy.`, issues);
    }
}
function readGovernedSliceOverviewSync(repositoryRoot, sliceOverviewInput, requiredSources) {
    let normalizedInput;
    try {
        normalizedInput = (0, paths_1.parseRepositoryRelativePath)(sliceOverviewInput).normalizedPath;
    }
    catch (error) {
        throw (0, errors_1.createUsageError)(`Invalid Governed slice-overview path '${sliceOverviewInput}'.`, [error instanceof Error ? error.message : String(error)]);
    }
    const target = (0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, normalizedInput);
    if (!target.exists) {
        throw (0, errors_1.createUsageError)(`Governed slice overview not found at '${target.repositoryRelativePath}'.`);
    }
    const stats = node_fs_1.default.statSync(target.runtimePath);
    if (!stats.isFile()) {
        throw (0, errors_1.createUsageError)(`Governed slice overview '${target.repositoryRelativePath}' must be a regular file.`);
    }
    const text = node_fs_1.default.readFileSync(target.runtimePath, "utf8");
    const document = (0, planning_document_utils_1.parseMarkdownFrontMatter)(text);
    const artifactType = (0, planning_document_utils_1.readTopLevelField)(document.frontMatterLines, "artifact_type");
    const workflowLevel = (0, planning_document_utils_1.readTopLevelField)(document.frontMatterLines, "workflow_level");
    const sliceId = (0, planning_document_utils_1.readTopLevelField)(document.frontMatterLines, "slice")?.trim() ?? "";
    const implementationOrder = (0, planning_document_utils_1.readTopLevelField)(document.frontMatterLines, "implementation_order")?.trim() ?? "";
    if (!document.hasFrontMatter || artifactType !== "slice_overview" || workflowLevel !== "governed") {
        throw (0, errors_1.createUsageError)(`Overview '${target.repositoryRelativePath}' must be a Governed slice_overview artifact.`);
    }
    if (!SLICE_ID_PATTERN.test(sliceId)) {
        throw (0, errors_1.createUsageError)(`Governed slice overview '${target.repositoryRelativePath}' has invalid slice identity '${sliceId}'.`);
    }
    if (!IMPLEMENTATION_ORDER_PATTERN.test(implementationOrder)
        || !sliceId.startsWith(`${implementationOrder}-`)) {
        throw (0, errors_1.createUsageError)(`Governed slice overview '${target.repositoryRelativePath}' has conflicting implementation-order evidence.`);
    }
    const expectedRoot = (0, work_routing_1.resolvePlanningDestinationSync)(repositoryRoot, {
        planningRoot: ".day-shift/planning",
        level: "governed",
        sliceId
    });
    const expectedPath = node_path_1.default.posix.join(expectedRoot.repositoryRelativePath, "slice-overview.md");
    if (target.repositoryRelativePath !== expectedPath) {
        throw (0, errors_1.createUsageError)(`Governed slice overview '${target.repositoryRelativePath}' does not match canonical path '${expectedPath}'.`);
    }
    const defaultAgentMode = (0, planning_document_utils_1.readTopLevelField)(document.frontMatterLines, "default_agent_mode")?.trim() ?? "";
    const defaultEvidenceProfile = (0, planning_document_utils_1.readTopLevelField)(document.frontMatterLines, "default_evidence_profile")?.trim() ?? "";
    (0, policy_resolution_1.resolveAgentMode)({ parent: defaultAgentMode });
    (0, policy_resolution_1.resolveEvidenceProfile)({ parent: defaultEvidenceProfile });
    const availableSources = parseGovernedSources(document.frontMatterLines);
    const missingSources = requiredSources.filter((source) => {
        const normalizedPath = (0, paths_1.parseRepositoryRelativePath)(source.path).normalizedPath;
        return !availableSources.some((candidate) => candidate.id === source.id && candidate.path === normalizedPath);
    });
    if (missingSources.length > 0) {
        throw (0, errors_1.createUsageError)(`Governed slice overview '${target.repositoryRelativePath}' does not include every selected source.`, missingSources.map((source) => `${source.id}: ${source.path}`));
    }
    return {
        workflowLevel: "governed",
        sliceId,
        implementationOrder,
        initiativeId: (0, planning_document_utils_1.readTopLevelField)(document.frontMatterLines, "initiative_id")?.trim() ?? null,
        sliceOverviewPath: target.repositoryRelativePath,
        defaultAgentMode,
        defaultEvidenceProfile
    };
}
function nextLayerName(parentLayer) {
    if (parentLayer === "slice")
        return "phase";
    if (parentLayer === "phase")
        return "milestone";
    return "task";
}
function readNestedUpstreamField(lines, key) {
    let inUpstream = false;
    for (const line of lines) {
        if (line === "upstream:") {
            inUpstream = true;
            continue;
        }
        if (!inUpstream)
            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, planning_document_utils_1.parseScalar)(match[2]).trim();
    }
    return undefined;
}
function readGovernedHierarchyPolicy(frontMatterLines) {
    const workflowLevel = (0, planning_document_utils_1.readTopLevelField)(frontMatterLines, "workflow_level")?.trim();
    if (workflowLevel === undefined || workflowLevel === "") {
        return null;
    }
    if (workflowLevel !== "governed") {
        throw (0, errors_1.createUsageError)(`Hierarchy parent declares unsupported workflow_level '${workflowLevel}'.`);
    }
    const defaultAgentMode = (0, planning_document_utils_1.readTopLevelField)(frontMatterLines, "default_agent_mode")?.trim() ?? "";
    const defaultEvidenceProfile = (0, planning_document_utils_1.readTopLevelField)(frontMatterLines, "default_evidence_profile")?.trim() ?? "";
    (0, policy_resolution_1.resolveAgentMode)({ parent: defaultAgentMode });
    (0, policy_resolution_1.resolveEvidenceProfile)({ parent: defaultEvidenceProfile });
    return {
        workflowLevel: "governed",
        defaultAgentMode,
        defaultEvidenceProfile
    };
}
function renderGovernedHierarchyPolicyLines(policy) {
    if (policy === null) {
        return [];
    }
    return [
        "workflow_level: governed",
        `default_agent_mode: ${JSON.stringify(policy.defaultAgentMode)}`,
        `default_evidence_profile: ${JSON.stringify(policy.defaultEvidenceProfile)}`
    ];
}
function parseGovernedSources(lines) {
    const sources = [];
    let inUpstream = false;
    let inSpecs = false;
    let current = null;
    const finish = () => {
        if (current === null)
            return;
        if (current.id === undefined || current.path === undefined) {
            throw (0, errors_1.createUsageError)("Governed slice overview contains incomplete upstream.specs metadata.");
        }
        sources.push({
            id: current.id,
            path: (0, paths_1.parseRepositoryRelativePath)(current.path).normalizedPath
        });
        current = null;
    };
    for (const line of lines) {
        if (line === "upstream:") {
            inUpstream = true;
            continue;
        }
        if (!inUpstream)
            continue;
        if (/^[^\s]/.test(line))
            break;
        if (line === "  specs:") {
            inSpecs = true;
            continue;
        }
        if (!inSpecs)
            continue;
        const idMatch = line.match(/^\s{4}-\s+id:\s*(.*)$/);
        if (idMatch !== null) {
            finish();
            current = { id: (0, planning_document_utils_1.parseScalar)(idMatch[1]) };
            continue;
        }
        const refMatch = line.match(/^\s{6}ref:\s*(.*)$/);
        if (refMatch !== null && current !== null) {
            current.path = (0, planning_document_utils_1.parseScalar)(refMatch[1]);
        }
    }
    finish();
    return sources;
}
