"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createValidationLinksCheckCommand = createValidationLinksCheckCommand;
exports.runValidationLinksCheckReport = runValidationLinksCheckReport;
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const errors_1 = require("../../../lib/errors");
const config_contract_1 = require("../../../lib/config/config-contract");
const output_1 = require("../../../lib/output");
const validation_links_discovery_1 = require("../../../lib/planning/validation-links-discovery");
const validation_links_resolution_1 = require("../../../lib/planning/validation-links-resolution");
const paths_1 = require("../../../lib/paths");
const trace_link_dispositions_1 = require("../../../lib/trace-link-dispositions");
const global_format_1 = require("../global-format");
const LINKS_CHECK_NO_WRITE_BOUNDARY = "Reports trace-link evidence only; must not repair links, rewrite parent references, synchronize metadata, write checkpoints, mutate status, or generate planning artifacts.";
async function createValidationLinksCheckCommand() {
    const { Command } = await import("commander");
    const command = new Command("links-check");
    command
        .description("Run a read-only, local-only validation links check over repository-relative planning trace links.")
        .option("--scope <scope>", "Validation links-check scope. Currently only 'planning' is supported.", "planning")
        .option("--format <format>", "Validation links-check output format. Accepted values: text, json.")
        .option("--artifact <path>", "Optional repository-relative planning artifact file or directory path to focus links-check input validation.")
        .addHelpText("after", [
        "",
        "Boundaries:",
        "  Read-only and local-only: no remote provider checks, metadata repair, checkpoint writes, status mutation, or artifact generation.",
        "  This command resolves local trace values, hierarchy evidence, paired-artifact evidence, disposition-backed lifecycle findings, and trace-link findings without writing files.",
        "  Disposition evidence may report retired, deleted, migrated, malformed-storage, or applied-migration state and may recommend preview/apply commands, but validation never repairs links or infers replacement targets."
    ].join("\n"))
        .action((_, commandInstance) => {
        const options = commandInstance.opts();
        const requestedFormat = options.format ?? (0, global_format_1.getGlobalFormat)(commandInstance);
        const format = (0, output_1.resolveOutputFormat)(requestedFormat);
        if (format === null) {
            throw (0, errors_1.createUnsupportedOutputFormatError)({
                received: requestedFormat,
                commandBoundary: "validation links-check command output format"
            });
        }
        if (options.scope !== "planning") {
            throw (0, errors_1.createUsageError)("Validation links-check currently supports only the 'planning' scope.", [`Received: ${String(options.scope)}`]);
        }
        const artifactPath = normalizeOptionalArtifactPath(options.artifact);
        const repositoryRoot = getRootCommand(commandInstance).configRepositoryContext?.root ?? process.cwd();
        const report = runValidationLinksCheckReport({
            repositoryRoot,
            artifactPath
        });
        const { discovery, resolution, findings } = report;
        if (findings.some((finding) => finding.severity === "error")) {
            getRootCommand(commandInstance).runtimeExitCode = errors_1.RuntimeExitCode.ERROR;
        }
        (0, output_1.emitSuccess)({
            command: "validation links-check",
            format,
            text: renderValidationLinksCheckReport(discovery, resolution, findings),
            data: {
                repositoryRoot,
                scope: "planning",
                artifact: artifactPath,
                artifactInputKind: artifactPath === null
                    ? "repository"
                    : node_fs_1.default.existsSync(node_path_1.default.join(repositoryRoot, artifactPath)) && node_fs_1.default.statSync(node_path_1.default.join(repositoryRoot, artifactPath)).isDirectory()
                        ? "directory"
                        : "file",
                readOnly: true,
                localOnly: true,
                writeCapable: false,
                implementationState: "finding-output-implemented",
                checksImplemented: true,
                checkedArtifactCount: discovery.summary.artifactCount,
                checkedRelationshipCount: resolution.summary.valueResolutionCount +
                    resolution.summary.hierarchyCheckCount +
                    resolution.summary.pairingCheckCount,
                traceLinkFindingCount: findings.length,
                blockingFindingCount: findings.filter((finding) => finding.severity === "error").length,
                advisoryFindingCount: findings.filter((finding) => finding.severity !== "error").length,
                outputContracts: (0, output_1.getValidationCommandOutputContracts)(),
                readOnlyFailureContract: (0, output_1.getValidationReadOnlyFailureContract)(),
                noWriteBoundary: LINKS_CHECK_NO_WRITE_BOUNDARY,
                discovery,
                resolution,
                dispositionStorage: report.dispositionStorage,
                summary: createValidationLinksCheckSummary(discovery, resolution, findings)
            },
            findings
        });
    });
    return command;
}
function runValidationLinksCheckReport(options) {
    const artifactPath = normalizeOptionalArtifactPath(options.artifactPath);
    const resolvedConfig = (0, config_contract_1.resolveDayShiftConfig)({
        repositoryContext: {
            root: options.repositoryRoot,
            detectionSource: "explicit",
            warnedAboutFallback: false
        }
    });
    const discovery = (0, validation_links_discovery_1.discoverValidationLinksArtifacts)({
        repositoryRoot: options.repositoryRoot,
        artifactPath,
        planningRootPath: (0, paths_1.toRepositoryRelativePath)(options.repositoryRoot, resolvedConfig.derived.planningRootPath),
        specIndexPath: (0, paths_1.toRepositoryRelativePath)(options.repositoryRoot, resolvedConfig.derived.specIndexPath)
    });
    const dispositionState = readTraceLinkDispositionState(options.repositoryRoot);
    const resolution = applyDispositionEvidenceToResolution({
        resolution: (0, validation_links_resolution_1.evaluateValidationLinksResolution)(discovery),
        dispositionState,
        artifactPath
    });
    const findings = createValidationLinksCheckFindings({
        discovery,
        resolution,
        repositoryRoot: options.repositoryRoot,
        dispositionState
    });
    return {
        repositoryRoot: options.repositoryRoot,
        artifact: artifactPath,
        discovery,
        resolution,
        dispositionStorage: dispositionStateToReport(dispositionState),
        findings
    };
}
function normalizeOptionalArtifactPath(input) {
    if (input === undefined || input === null || input === "") {
        return null;
    }
    if (typeof input !== "string") {
        throw (0, errors_1.createUsageError)("Validation links-check artifact path 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)("Validation links-check artifact path must be a repository-relative path.", [error.message]);
        }
        throw error;
    }
}
function createValidationLinksCheckFindings(options) {
    return [
        ...createDiscoveryFindings(options),
        ...createDispositionStorageFindings(options),
        ...createMissingRequiredFieldFindings(options),
        ...options.resolution.valueResolutions.flatMap((evidence) => createValueResolutionFinding(evidence, options.repositoryRoot)),
        ...options.resolution.valueResolutions.flatMap((evidence) => createLinkedSliceScaffoldFinding(evidence, options.repositoryRoot)),
        ...options.resolution.hierarchyChecks.flatMap((evidence) => createHierarchyFinding(evidence, options.repositoryRoot)),
        ...options.resolution.pairingChecks.flatMap((evidence) => createPairingFinding(evidence, options.repositoryRoot))
    ];
}
function readTraceLinkDispositionState(repositoryRoot) {
    const absoluteStoragePath = node_path_1.default.join(repositoryRoot, trace_link_dispositions_1.TRACE_LINK_DISPOSITION_STORAGE_PATH);
    if (!node_fs_1.default.existsSync(absoluteStoragePath)) {
        return {
            status: "absent",
            storagePath: trace_link_dispositions_1.TRACE_LINK_DISPOSITION_STORAGE_PATH,
            dispositions: []
        };
    }
    try {
        const document = (0, trace_link_dispositions_1.parseTraceLinkDispositionStorageDocument)(node_fs_1.default.readFileSync(absoluteStoragePath, "utf8"));
        return {
            status: "loaded",
            storagePath: trace_link_dispositions_1.TRACE_LINK_DISPOSITION_STORAGE_PATH,
            dispositions: document.dispositions
        };
    }
    catch (error) {
        return {
            status: "malformed",
            storagePath: trace_link_dispositions_1.TRACE_LINK_DISPOSITION_STORAGE_PATH,
            error: error instanceof Error ? error.message : "Trace-link disposition storage could not be parsed.",
            dispositions: []
        };
    }
}
function dispositionStateToReport(state) {
    return {
        status: state.status,
        storagePath: state.storagePath,
        dispositionCount: state.dispositions.length,
        ...(state.status === "malformed" ? { error: state.error } : {})
    };
}
function createDispositionStorageFindings(options) {
    if (options.dispositionState.status !== "malformed") {
        return [];
    }
    return [
        (0, output_1.createTraceLinkValidationFinding)({
            taxonomyId: "LINKS_MALFORMED_DISPOSITION_STORAGE",
            artifact: {
                family: "other",
                path: options.dispositionState.storagePath
            },
            affectedPath: {
                role: "trace-link",
                path: options.dispositionState.storagePath,
                description: "Trace-link disposition storage could not be parsed."
            },
            relationship: "trace-link-disposition-storage",
            field: trace_link_dispositions_1.TRACE_LINK_DISPOSITION_STORAGE_PATH,
            traceValue: options.dispositionState.storagePath,
            detail: options.dispositionState.error,
            repositoryRoot: options.repositoryRoot
        })
    ];
}
function applyDispositionEvidenceToResolution(options) {
    if (options.dispositionState.status !== "loaded") {
        return options.resolution;
    }
    const dispositionsByTarget = new Map(options.dispositionState.dispositions.map((disposition) => [
        disposition.target.normalizedPath,
        disposition
    ]));
    const valueResolutions = options.resolution.valueResolutions.map((evidence) => {
        if (evidence.resolution.status !== "missing-local-target" ||
            evidence.resolution.normalizedPath === undefined) {
            return evidence;
        }
        const disposition = dispositionsByTarget.get(evidence.resolution.normalizedPath);
        if (disposition === undefined) {
            return evidence;
        }
        const applyEvidenceStatus = classifyApplyEvidenceForArtifact(disposition, options.artifactPath);
        return {
            ...evidence,
            severity: applyEvidenceStatus === "changed" ? "none" : "advisory",
            disposition: {
                status: disposition.status,
                storagePath: trace_link_dispositions_1.TRACE_LINK_DISPOSITION_STORAGE_PATH,
                originalTarget: disposition.target.normalizedPath,
                ...("replacementTarget" in disposition
                    ? {
                        replacementTarget: disposition.replacementTarget.normalizedPath,
                        recommendedCommand: `day-shift link disposition preview --target ${disposition.target.normalizedPath}`
                    }
                    : {}),
                applyEvidenceStatus
            }
        };
    });
    return {
        ...options.resolution,
        valueResolutions,
        summary: summarizeResolution(valueResolutions, options.resolution.hierarchyChecks, options.resolution.pairingChecks)
    };
}
function classifyApplyEvidenceForArtifact(disposition, artifactPath) {
    if (artifactPath === null || disposition.applyEvidence === undefined) {
        return "absent";
    }
    if (disposition.applyEvidence.changedPaths.includes(artifactPath)) {
        return "changed";
    }
    if (disposition.applyEvidence.skippedPaths.includes(artifactPath)) {
        return "skipped";
    }
    if (disposition.applyEvidence.conflictPaths.includes(artifactPath)) {
        return "conflict";
    }
    if (disposition.applyEvidence.unresolvedPaths.includes(artifactPath)) {
        return "unresolved";
    }
    return "absent";
}
function summarizeResolution(valueResolutions, hierarchyChecks, pairingChecks) {
    const blockingEvidenceCount = [
        ...valueResolutions,
        ...hierarchyChecks,
        ...pairingChecks
    ].filter((entry) => entry.severity === "blocking").length;
    const advisoryEvidenceCount = [
        ...valueResolutions,
        ...hierarchyChecks,
        ...pairingChecks
    ].filter((entry) => entry.severity === "advisory").length;
    return {
        valueResolutionCount: valueResolutions.length,
        resolvedLocalTargetCount: valueResolutions.filter((entry) => entry.resolution.status === "resolved-local-target").length,
        missingLocalTargetCount: valueResolutions.filter((entry) => entry.resolution.status === "missing-local-target").length,
        malformedLocalLinkCount: valueResolutions.filter((entry) => entry.resolution.status === "malformed-local-link").length,
        outsideTraversalBoundaryCount: valueResolutions.filter((entry) => entry.resolution.status === "outside-traversal-boundary").length,
        unsupportedReferenceCount: valueResolutions.filter((entry) => entry.resolution.status === "unsupported-external-reference").length,
        hierarchyCheckCount: hierarchyChecks.length,
        hierarchyMismatchCount: hierarchyChecks.filter((entry) => entry.comparison.status === "hierarchy-mismatch").length,
        staleLinkCount: hierarchyChecks.filter((entry) => entry.comparison.status === "stale-link").length,
        pairingCheckCount: pairingChecks.length,
        pairingMismatchCount: pairingChecks.filter((entry) => entry.severity !== "none").length,
        blockingEvidenceCount,
        advisoryEvidenceCount
    };
}
function createLinkedSliceScaffoldFinding(evidence, repositoryRoot) {
    if (evidence.family !== "spec_index_entry" ||
        evidence.field !== "linked_slice.path" ||
        evidence.resolution.status !== "resolved-local-target" ||
        evidence.resolution.normalizedPath === undefined) {
        return [];
    }
    const sliceOverviewPath = node_path_1.default.join(repositoryRoot, evidence.resolution.normalizedPath);
    const missingCompanions = [
        node_path_1.default.join(node_path_1.default.dirname(sliceOverviewPath), "decisions", ".gitkeep"),
        node_path_1.default.join(node_path_1.default.dirname(sliceOverviewPath), "notes", ".gitkeep")
    ].filter((candidate) => !node_fs_1.default.existsSync(candidate));
    const provenance = readPlanningWorkflowProvenance(sliceOverviewPath);
    if (missingCompanions.length === 0 &&
        provenance.workflowProvenance === "cli" &&
        /^day-shift slice new|^node dist\/cli\/index\.js slice new/u.test(provenance.workflowCliCommand)) {
        return [];
    }
    const reasons = [
        ...(provenance.workflowProvenance !== "cli"
            ? [`workflow_provenance is '${provenance.workflowProvenance || "<missing>"}' instead of 'cli'`]
            : []),
        ...(!/^day-shift slice new|^node dist\/cli\/index\.js slice new/u.test(provenance.workflowCliCommand)
            ? [`workflow_cli_command is '${provenance.workflowCliCommand || "<missing>"}' instead of a slice scaffold command`]
            : []),
        ...missingCompanions.map((companion) => `missing ${(0, paths_1.toRepositoryRelativePath)(repositoryRoot, companion)}`)
    ];
    return [
        (0, output_1.createTraceLinkValidationFinding)({
            taxonomyId: "LINKS_STALE_EXPLICIT_LINK",
            artifact: {
                family: "other",
                path: evidence.sourceArtifactPath
            },
            affectedPath: {
                role: "trace-link",
                path: evidence.resolution.normalizedPath,
                description: "linked_slice.path target is missing valid CLI scaffold evidence."
            },
            relationship: evidence.relationship,
            field: evidence.field,
            traceValue: evidence.originalValue,
            expectedPath: "CLI-scaffolded slice overview with decisions/.gitkeep and notes/.gitkeep",
            hierarchyStatus: "stale-link",
            detail: `linked_slice.path must reference a CLI-scaffolded slice overview with required companion artifacts: ${reasons.join("; ")}.`,
            repositoryRoot
        })
    ];
}
function readPlanningWorkflowProvenance(sliceOverviewPath) {
    try {
        const content = node_fs_1.default.readFileSync(sliceOverviewPath, "utf8");
        const lines = content.split(/\r?\n/);
        const closingIndex = lines.findIndex((line, index) => index > 0 && line === "---");
        if (!content.startsWith("---") || closingIndex === -1) {
            return { workflowProvenance: "", workflowCliCommand: "" };
        }
        const frontMatterLines = lines.slice(1, closingIndex);
        return {
            workflowProvenance: readTopLevelScalar(frontMatterLines, "workflow_provenance"),
            workflowCliCommand: readTopLevelScalar(frontMatterLines, "workflow_cli_command")
        };
    }
    catch {
        return { workflowProvenance: "", workflowCliCommand: "" };
    }
}
function readTopLevelScalar(lines, key) {
    for (const line of lines) {
        if (/^\s/u.test(line)) {
            continue;
        }
        const match = line.match(/^([A-Za-z0-9_]+):\s*(.*)$/u);
        if (match === null || match[1] !== key) {
            continue;
        }
        return match[2].trim().replace(/^"|"$/gu, "");
    }
    return "";
}
function createDiscoveryFindings(options) {
    if (options.discovery.mode !== "artifact") {
        return [];
    }
    return options.discovery.evidence
        .filter((evidence) => evidence.status === "missing")
        .map((evidence) => (0, output_1.createTraceLinkValidationFinding)({
        taxonomyId: "LINKS_REQUIRED_TARGET_MISSING",
        artifact: {
            family: "other",
            artifactType: evidence.artifactType ?? undefined,
            path: evidence.path
        },
        affectedPath: {
            role: "trace-link",
            path: evidence.path,
            description: evidence.message
        },
        relationship: "focused-artifact-input",
        field: "--artifact",
        traceValue: evidence.path,
        resolutionStatus: "missing-local-target",
        detail: `Focused links-check artifact is missing: ${evidence.path}.`,
        repositoryRoot: options.repositoryRoot
    }));
}
function createMissingRequiredFieldFindings(options) {
    return options.discovery.artifacts.flatMap((artifact) => {
        if (artifact.parseStatus !== "parsed") {
            return [];
        }
        return artifact.traceFields
            .filter((field) => shouldEmitMissingRequiredFieldFinding(field))
            .map((field) => (0, output_1.createTraceLinkValidationFinding)({
            taxonomyId: "LINKS_REQUIRED_FIELD_MISSING",
            artifact: {
                family: toValidationFindingArtifactFamily(artifact.family),
                artifactType: artifact.artifactType ?? undefined,
                path: artifact.path
            },
            affectedPath: {
                role: "finding-location",
                path: artifact.path,
                description: `Required trace field '${field.field}' is missing.`
            },
            relationship: field.relationship,
            field: field.field,
            detail: `Required trace field '${field.field}' is missing from ${artifact.path}.`,
            repositoryRoot: options.repositoryRoot
        }));
    });
}
function shouldEmitMissingRequiredFieldFinding(field) {
    if (field.requirement !== "required" || field.present) {
        return false;
    }
    // The readiness/rollup metadata validators own missing spec provenance.
    // Links-check validates trace values that are present, plus structural parent links.
    return field.field !== "upstream.specs";
}
function createValueResolutionFinding(evidence, repositoryRoot) {
    if (evidence.severity === "none") {
        return [];
    }
    if (evidence.severity === "advisory" &&
        evidence.resolution.status !== "unsupported-external-reference" &&
        !isRetiredTargetEvidence(evidence) &&
        evidence.disposition === undefined) {
        return [];
    }
    const taxonomyId = traceFindingIdForValueResolution(evidence);
    if (taxonomyId === null) {
        return [];
    }
    const targetPath = evidence.resolution.normalizedPath ?? evidence.sourceArtifactPath;
    return [
        (0, output_1.createTraceLinkValidationFinding)({
            taxonomyId,
            artifact: {
                family: toValidationFindingArtifactFamily(evidence.family),
                path: evidence.sourceArtifactPath
            },
            affectedPath: {
                role: "trace-link",
                path: targetPath,
                description: evidence.resolution.message
            },
            relationship: evidence.relationship,
            field: evidence.field,
            traceValue: evidence.originalValue,
            resolutionStatus: evidence.resolution.status,
            evidenceDetails: dispositionEvidenceDetails(evidence.disposition),
            detail: valueResolutionDetail(evidence),
            repositoryRoot
        })
    ];
}
function traceFindingIdForValueResolution(evidence) {
    if (evidence.disposition !== undefined) {
        switch (evidence.disposition.status) {
            case "retired":
                return "LINKS_RETIRED_TARGET";
            case "deleted":
                return "LINKS_DELETED_TARGET";
            case "migrated":
                return "LINKS_MIGRATION_AVAILABLE";
        }
    }
    return isRetiredTargetEvidence(evidence)
        ? "LINKS_RETIRED_TARGET"
        : traceFindingIdForResolutionStatus(evidence.resolution.status);
}
function dispositionEvidenceDetails(disposition) {
    if (disposition === undefined) {
        return undefined;
    }
    return {
        dispositionStatus: disposition.status,
        dispositionStoragePath: disposition.storagePath,
        originalTarget: disposition.originalTarget,
        ...(disposition.replacementTarget !== undefined
            ? { replacementTarget: disposition.replacementTarget }
            : {}),
        ...(disposition.recommendedCommand !== undefined
            ? { recommendedCommand: disposition.recommendedCommand }
            : {}),
        ...(disposition.applyEvidenceStatus !== undefined
            ? { applyEvidenceStatus: disposition.applyEvidenceStatus }
            : {})
    };
}
function valueResolutionDetail(evidence) {
    const base = `${evidence.relationship} in ${evidence.sourceArtifactPath}: ${evidence.resolution.message}`;
    if (evidence.disposition === undefined) {
        return base;
    }
    if (evidence.disposition.status === "migrated" && evidence.disposition.replacementTarget !== undefined) {
        return `${base} Recorded migrated disposition points to ${evidence.disposition.replacementTarget}.`;
    }
    return `${base} Recorded ${evidence.disposition.status} disposition found in ${evidence.disposition.storagePath}.`;
}
function isRetiredTargetEvidence(evidence) {
    return evidence.severity === "advisory" && evidence.resolution.status === "missing-local-target";
}
function createHierarchyFinding(evidence, repositoryRoot) {
    if (evidence.severity === "none") {
        return [];
    }
    return [
        (0, output_1.createTraceLinkValidationFinding)({
            taxonomyId: evidence.comparison.status === "stale-link"
                ? "LINKS_STALE_EXPLICIT_LINK"
                : "LINKS_OUT_OF_HIERARCHY",
            artifact: {
                family: toValidationFindingArtifactFamily(evidence.family),
                path: evidence.sourceArtifactPath
            },
            affectedPath: {
                role: "trace-link",
                path: evidence.comparison.normalizedActualPath,
                description: evidence.comparison.message
            },
            relationship: evidence.relationship,
            field: evidence.field,
            traceValue: evidence.comparison.originalValue,
            expectedPath: evidence.expectedPath,
            hierarchyStatus: evidence.comparison.status,
            detail: `${evidence.relationship} expected ${evidence.expectedPath}, received ${evidence.comparison.normalizedActualPath}.`,
            repositoryRoot
        })
    ];
}
function createPairingFinding(evidence, repositoryRoot) {
    if (evidence.severity === "none") {
        return [];
    }
    return [
        (0, output_1.createTraceLinkValidationFinding)({
            taxonomyId: "LINKS_REQUIRED_TARGET_MISSING",
            artifact: {
                family: evidence.family,
                path: evidence.sourceArtifactPath
            },
            affectedPath: {
                role: "trace-link",
                path: evidence.expectedPath,
                description: evidence.message
            },
            relationship: evidence.relationship,
            field: "pairedArtifact",
            traceValue: evidence.expectedPath,
            resolutionStatus: "missing-local-target",
            detail: `${evidence.relationship} expected paired artifact ${evidence.expectedPath}: ${evidence.message}`,
            repositoryRoot
        })
    ];
}
function toValidationFindingArtifactFamily(family) {
    return family === "spec_index_entry" || family === "unsupported" ? "other" : family;
}
function traceFindingIdForResolutionStatus(status) {
    switch (status) {
        case "missing-local-target":
            return "LINKS_REQUIRED_TARGET_MISSING";
        case "malformed-local-link":
        case "outside-traversal-boundary":
            return "LINKS_MALFORMED_LOCAL_VALUE";
        case "unsupported-external-reference":
            return "LINKS_UNSUPPORTED_REFERENCE";
        case "resolved-local-target":
            return null;
    }
}
function createValidationLinksCheckSummary(discovery, resolution, findings) {
    return {
        checkedArtifactCount: discovery.summary.artifactCount,
        checkedRelationshipCount: resolution.summary.valueResolutionCount +
            resolution.summary.hierarchyCheckCount +
            resolution.summary.pairingCheckCount,
        traceLinkFindingCount: findings.length,
        blockingFindingCount: findings.filter((finding) => finding.severity === "error").length,
        advisoryFindingCount: findings.filter((finding) => finding.severity !== "error").length,
        discoveryEvidenceCount: discovery.summary.evidenceCount,
        valueResolutionCount: resolution.summary.valueResolutionCount,
        hierarchyCheckCount: resolution.summary.hierarchyCheckCount,
        pairingCheckCount: resolution.summary.pairingCheckCount
    };
}
function renderValidationLinksCheckReport(discovery, resolution, findings) {
    return [
        (0, output_1.renderTerminalHeading)("Day Shift validation links-check", "title").trimEnd(),
        "",
        (0, output_1.renderTerminalSection)({
            heading: "Summary",
            fields: [
                { label: "Command", value: "validation links-check" },
                { label: "Scope", value: "planning" },
                { label: "Artifact", value: discovery.artifact ?? "(none)" },
                { label: "Mode", value: "read-only, local-only" },
                { label: "Write capable", value: "no" },
                { label: "Checks implemented", value: "discovery, local resolution, hierarchy comparison, paired-artifact checks" },
                { label: "No-write boundary", value: LINKS_CHECK_NO_WRITE_BOUNDARY },
                { label: "Findings", value: findings.length },
                { label: "Blocking findings", value: findings.filter((finding) => finding.severity === "error").length },
                { label: "Advisory findings", value: findings.filter((finding) => finding.severity !== "error").length }
            ],
            lines: [(0, output_1.renderTerminalBoundary)({ kind: "read-only" })]
        }),
        "",
        "Discovery summary:",
        `- Mode: ${discovery.mode}`,
        `- Artifacts discovered: ${discovery.summary.artifactCount}`,
        `- Parsed artifacts: ${discovery.summary.parsedCount}`,
        `- Evidence records: ${discovery.summary.evidenceCount}`,
        `- Unsupported artifacts: ${discovery.summary.unsupportedCount}`,
        `- Malformed artifacts: ${discovery.summary.malformedCount}`,
        `- Missing artifacts: ${discovery.summary.missingCount}`,
        `- Outside coverage artifacts: ${discovery.summary.outsideCoverageCount}`,
        "",
        "Resolution summary:",
        `- Value resolutions: ${resolution.summary.valueResolutionCount}`,
        `- Resolved local targets: ${resolution.summary.resolvedLocalTargetCount}`,
        `- Missing local targets: ${resolution.summary.missingLocalTargetCount}`,
        `- Malformed local links: ${resolution.summary.malformedLocalLinkCount}`,
        `- Outside traversal boundary: ${resolution.summary.outsideTraversalBoundaryCount}`,
        `- Unsupported references: ${resolution.summary.unsupportedReferenceCount}`,
        `- Hierarchy checks: ${resolution.summary.hierarchyCheckCount}`,
        `- Hierarchy mismatches: ${resolution.summary.hierarchyMismatchCount}`,
        `- Stale explicit links: ${resolution.summary.staleLinkCount}`,
        `- Paired-artifact checks: ${resolution.summary.pairingCheckCount}`,
        `- Paired-artifact mismatches: ${resolution.summary.pairingMismatchCount}`,
        `- Blocking evidence: ${resolution.summary.blockingEvidenceCount}`,
        `- Advisory evidence: ${resolution.summary.advisoryEvidenceCount}`,
        "",
        "Report lanes:",
        "- discovery",
        "- resolution",
        "- relationship evidence",
        "- summary",
        "- findings",
        "",
        (0, output_1.renderValidationFindingsText)(findings, "Structured findings")
    ].join("\n");
}
function getRootCommand(commandInstance) {
    let current = commandInstance;
    while (current?.parent != null) {
        current = current.parent;
    }
    return current ?? commandInstance;
}
