"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getValidationRollupEvidenceSourceInventory = getValidationRollupEvidenceSourceInventory;
exports.getValidationRollupSpecializedBoundaries = getValidationRollupSpecializedBoundaries;
exports.getValidationRollupAggregationContract = getValidationRollupAggregationContract;
exports.isDoctorBlockingFailure = isDoctorBlockingFailure;
exports.deriveDoctorReadinessStatus = deriveDoctorReadinessStatus;
exports.runCoreDoctorChecks = runCoreDoctorChecks;
exports.runScopedDoctorChecks = runScopedDoctorChecks;
exports.renderDoctorReportText = renderDoctorReportText;
exports.renderScopedDoctorReportText = renderScopedDoctorReportText;
exports.renderDoctorErrorDetails = renderDoctorErrorDetails;
exports.runPlanningValidationSmoke = runPlanningValidationSmoke;
exports.renderPlanningValidationSmokeReport = renderPlanningValidationSmokeReport;
exports.writePlanningValidationBaseline = writePlanningValidationBaseline;
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const output_1 = require("../output");
const config_contract_1 = require("../config/config-contract");
const runtime_contract_1 = require("../runtime/runtime-contract");
const planning_navigation_1 = require("../planning/planning-navigation");
const planning_document_utils_1 = require("../planning/planning-document-utils");
const paths_1 = require("../paths");
const validation_1 = require("../validation");
const validation_links_check_1 = require("../../cli/commands/validation-links-check");
const environment_checks_1 = require("./environment-checks");
const hygiene_checks_1 = require("./hygiene-checks");
const planning_checks_1 = require("./planning-checks");
const spec_registry_checks_1 = require("./spec-registry-checks");
const action_relevance_1 = require("./action-relevance");
const check_orchestration_1 = require("./check-orchestration");
const workspace_ignore_1 = require("../workspace-ignore");
const workspace_scan_surface_1 = require("../workspace-scan-surface");
const artifact_lifecycle_1 = require("../planning/artifact-lifecycle");
const paths_2 = require("../paths");
__exportStar(require("./action-relevance"), exports);
__exportStar(require("./check-orchestration"), exports);
const DOCTOR_TEXT_PATH_PREVIEW_LIMIT = 12;
const EXPECTED_TEMPLATE_H2_HEADINGS = new Map([
    [
        ".day-shift/templates/specification.md",
        [
            "## Purpose",
            "## Problem Statement",
            "## Desired Outcome",
            "## Non-Goals",
            "## Scope",
            "## Constraints",
            "## Success Criteria",
            "## Open Questions"
        ]
    ],
    [
        ".day-shift/templates/slice-overview.md",
        [
            "## Purpose",
            "## Source Specification",
            "## Desired Outcome",
            "## Scope",
            "## Non-Goals",
            "## Planning Depth",
            "## Phases",
            "## Decisions",
            "## Risks",
            "## Validation Strategy",
            "## Open Questions"
        ]
    ],
    [
        ".day-shift/templates/phase-overview.md",
        [
            "## Purpose",
            "## Scope",
            "## Navigation",
            "## Milestones",
            "## Acceptance Criteria",
            "## Dependencies",
            "## Risks",
            "## Validation Focus",
            "## Open Questions"
        ]
    ],
    [
        ".day-shift/templates/milestone-overview.md",
        [
            "## Purpose",
            "## Scope",
            "## Navigation",
            "## Tasks",
            "## Acceptance Criteria",
            "## Dependencies",
            "## Risks",
            "## Validation Focus",
            "## Open Questions"
        ]
    ],
    [
        ".day-shift/templates/task-definition.md",
        [
            "## Objective",
            "## Navigation",
            "## Upstream Context",
            "## Implementation Target Paths",
            "## Current Behavior",
            "## Desired Behavior",
            "## Runtime Delta",
            "## Acceptance Criteria",
            "## Validation Commands",
            "## Rollback / Recovery",
            "## Risks",
            "## Dependencies",
            "## Constraints",
            "## Assumptions",
            "## Lifecycle / Closure Expectations",
            "## Open Questions"
        ]
    ],
    [
        ".day-shift/templates/implementation-summary.md",
        [
            "## Summary",
            "## Changed Paths",
            "## Acceptance Criteria Results",
            "## Validation Performed",
            "## Validation Exceptions",
            "## Scope Classification",
            "## Runtime Evidence Boundary",
            "## Deviations",
            "## Risks and Follow-Ups",
            "## Open Questions"
        ]
    ],
    [
        ".day-shift/templates/reconciliation.md",
        [
            "## Review Status",
            "## Original Intent",
            "## Completed Work",
            "## Acceptance Criteria Review",
            "## Planned Work",
            "## Discovered Work",
            "## Backlog Work",
            "## Accepted Residual Work",
            "## Validation Review",
            "## Follow-Up Tasks",
            "## Review Concerns",
            "## Final Notes"
        ]
    ],
    [
        ".day-shift/templates/milestone-reconciliation.md",
        [
            "## Review Status",
            "## Milestone Intent",
            "## Completed Task Summaries",
            "## Acceptance Criteria Review",
            "## Planned Work",
            "## Discovered Work",
            "## Backlog Work",
            "## Accepted Residual Work",
            "## Validation Review",
            "## Follow-Up Tasks",
            "## Review Concerns",
            "## Final Notes"
        ]
    ]
]);
const PLANNING_VALIDATION_BASELINE_PATH = ".day-shift/state/planning-validation-baseline.json";
const VALIDATION_ROLLUP_EVIDENCE_SOURCE_INVENTORY = [
    {
        id: "planning-artifact-metadata",
        producer: {
            path: "src/lib/doctor/planning-checks.ts",
            functionName: "runPlanningArtifactMetadataCheck",
            command: "day-shift validation smoke --scope planning"
        },
        evidenceShapes: ["checks", "findings", "readiness-status"],
        emitsSharedValidationFindings: true,
        commandEvidenceCategory: "validation-rollup",
        conciseSmoke: true,
        futureRollupCandidate: true,
        readOnlyExecution: true,
        notes: "Contributes the planning-artifact-metadata smoke check and shared validation findings when metadata drift is detected."
    },
    {
        id: "planning-cli-provenance",
        producer: {
            path: "src/lib/doctor/planning-checks.ts",
            functionName: "runPlanningCliProvenanceCheck",
            command: "day-shift validation smoke --scope planning"
        },
        evidenceShapes: ["checks", "findings", "readiness-status"],
        emitsSharedValidationFindings: true,
        commandEvidenceCategory: "validation-rollup",
        conciseSmoke: true,
        futureRollupCandidate: true,
        readOnlyExecution: true,
        notes: "Contributes the planning-cli-provenance smoke check and shared validation findings for provenance drift."
    },
    {
        id: "lightweight-artifact-strictness",
        producer: {
            path: "src/lib/doctor/planning-checks.ts",
            functionName: "runLightweightArtifactStrictnessCheck",
            command: "day-shift validation smoke --scope planning"
        },
        evidenceShapes: ["checks", "findings", "readiness-status"],
        emitsSharedValidationFindings: true,
        commandEvidenceCategory: "validation-rollup",
        conciseSmoke: true,
        futureRollupCandidate: true,
        readOnlyExecution: true,
        notes: "Contributes the lightweight-artifact-strictness smoke check and shared validation findings for lightweight boundary drift."
    },
    {
        id: "planning-inventory",
        producer: {
            path: "src/lib/planning/planning-navigation.ts",
            functionName: "inventoryPlanning",
            command: "day-shift planning inventory"
        },
        evidenceShapes: ["checks", "findings", "inventory-findings", "readiness-status"],
        emitsSharedValidationFindings: true,
        commandEvidenceCategory: "validation-rollup",
        conciseSmoke: true,
        futureRollupCandidate: true,
        readOnlyExecution: true,
        notes: "Contributes paired-artifact and stale-state inventory findings; smoke maps them into shared validation findings with source planning-inventory."
    },
    {
        id: "planning-gap-report",
        producer: {
            path: "src/lib/planning/planning-navigation.ts",
            functionName: "gapReportPlanning",
            command: "day-shift planning gap-report"
        },
        evidenceShapes: ["checks", "findings", "gaps", "readiness-status"],
        emitsSharedValidationFindings: true,
        commandEvidenceCategory: "validation-rollup",
        conciseSmoke: true,
        futureRollupCandidate: true,
        readOnlyExecution: true,
        notes: "Contributes expected-versus-observed planning gaps; smoke maps gaps into shared validation findings with source planning-gap-report."
    },
    {
        id: "validation-links-check",
        producer: {
            path: "src/cli/commands/validation-links-check/index.ts",
            functionName: "runValidationLinksCheckReport",
            command: "day-shift validation links-check --scope planning --artifact <path>"
        },
        evidenceShapes: ["checks", "findings", "readiness-status"],
        emitsSharedValidationFindings: true,
        commandEvidenceCategory: "validation-rollup",
        conciseSmoke: "optional",
        futureRollupCandidate: true,
        readOnlyExecution: true,
        notes: "Contributes selected-artifact trace-link lifecycle findings to artifact-scoped smoke and rollup without broadening repository-wide smoke traversal."
    },
    {
        id: "cross-artifact-alignment",
        producer: {
            path: "src/lib/doctor/index.ts",
            functionName: "runCrossArtifactAlignmentSmoke",
            command: "day-shift validation smoke --scope planning"
        },
        evidenceShapes: ["checks", "findings", "cross-artifact-lanes", "readiness-status"],
        emitsSharedValidationFindings: true,
        commandEvidenceCategory: "validation-rollup",
        conciseSmoke: true,
        futureRollupCandidate: true,
        readOnlyExecution: true,
        notes: "Contributes cross-artifact lane evidence for headings, prompt lanes, routing, handoffs, placeholder contracts, and no-write boundaries."
    },
    {
        id: "planning-next-action",
        producer: {
            path: "src/lib/planning/planning-navigation.ts",
            functionName: "suggestPlanningNextAction",
            command: "day-shift planning next-action"
        },
        evidenceShapes: ["next-actions"],
        emitsSharedValidationFindings: false,
        commandEvidenceCategory: null,
        conciseSmoke: "optional",
        futureRollupCandidate: true,
        readOnlyExecution: true,
        notes: "Contributes optional artifact-specific guidance when validation smoke receives --artifact; it remains advisory and does not create findings."
    },
    {
        id: "existing-baseline-comparison",
        producer: {
            path: "src/lib/doctor/index.ts",
            functionName: "loadPlanningValidationBaseline",
            command: "day-shift validation smoke --scope planning"
        },
        evidenceShapes: ["baseline-suppression-counts", "findings", "inventory-findings", "gaps", "readiness-status"],
        emitsSharedValidationFindings: false,
        commandEvidenceCategory: null,
        conciseSmoke: true,
        futureRollupCandidate: true,
        readOnlyExecution: true,
        notes: "Reads an existing forward-only planning validation baseline and reports suppression counts. Checkpoint creation is excluded from read-only rollup execution and remains a separate write command."
    }
];
const VALIDATION_ROLLUP_SPECIALIZED_BOUNDARIES = [
    {
        id: "task-readiness-review",
        kind: "specialized-review",
        command: "day-shift task readiness-review --task-definition <path>",
        sourcePath: "src/cli/commands/task-readiness-review/index.ts",
        rollupExecution: "excluded",
        writeCapable: false,
        mayReferenceAs: ["recovery-guidance", "follow-up-command"],
        duplicatesDetailedFindings: false,
        preservesSharedNoWritePolicy: true,
        notes: "Readiness review owns task handoff evidence and remains a separate no-write review surface."
    },
    {
        id: "task-review",
        kind: "specialized-review",
        command: "day-shift task review --task-definition <path>",
        sourcePath: "src/cli/commands/task-review/index.ts",
        rollupExecution: "excluded",
        writeCapable: false,
        mayReferenceAs: ["recovery-guidance", "follow-up-command"],
        duplicatesDetailedFindings: false,
        preservesSharedNoWritePolicy: true,
        notes: "Task review owns detailed task readiness and paired-execution evidence; rollup may point to it without inlining its findings."
    },
    {
        id: "milestone-review",
        kind: "specialized-review",
        command: "day-shift milestone review --milestone-overview <path>",
        sourcePath: "src/cli/commands/milestone-review/index.ts",
        rollupExecution: "excluded",
        writeCapable: false,
        mayReferenceAs: ["recovery-guidance", "follow-up-command"],
        duplicatesDetailedFindings: false,
        preservesSharedNoWritePolicy: true,
        notes: "Milestone review owns milestone-level planning readiness and reconciliation evidence."
    },
    {
        id: "implementation-summary-review",
        kind: "specialized-review",
        command: "day-shift implementation-summary review --task-definition <path>",
        sourcePath: "src/cli/commands/implementation-summary-review/index.ts",
        rollupExecution: "excluded",
        writeCapable: false,
        mayReferenceAs: ["recovery-guidance", "follow-up-command"],
        duplicatesDetailedFindings: false,
        preservesSharedNoWritePolicy: true,
        notes: "Implementation-summary review owns task closeout evidence quality and lifecycle alignment checks."
    },
    {
        id: "reconciliation-review",
        kind: "specialized-review",
        command: "day-shift reconciliation review --milestone-overview <path>",
        sourcePath: "src/cli/commands/reconciliation-review/index.ts",
        rollupExecution: "excluded",
        writeCapable: false,
        mayReferenceAs: ["recovery-guidance", "follow-up-command"],
        duplicatesDetailedFindings: false,
        preservesSharedNoWritePolicy: true,
        notes: "Reconciliation review owns milestone reconciliation evidence and task-summary rollup quality."
    },
    {
        id: "metadata-validate-update",
        kind: "metadata-validation",
        command: "day-shift metadata validate-update --artifact <path> --field <key=value>",
        sourcePath: "src/cli/commands/metadata-validate-update/index.ts",
        rollupExecution: "excluded",
        writeCapable: false,
        mayReferenceAs: ["recovery-guidance", "follow-up-command"],
        duplicatesDetailedFindings: false,
        preservesSharedNoWritePolicy: true,
        notes: "Metadata validate-update remains a helper-backed no-write validation surface for proposed metadata mutations."
    },
    {
        id: "planning-guidance",
        kind: "planning-guidance",
        command: "day-shift planning inventory | day-shift planning gap-report | day-shift planning next-action",
        sourcePath: "src/lib/planning/planning-navigation.ts",
        rollupExecution: "excluded",
        writeCapable: false,
        mayReferenceAs: ["recovery-guidance", "follow-up-command"],
        duplicatesDetailedFindings: false,
        preservesSharedNoWritePolicy: true,
        notes: "Command-specific planning guidance remains advisory. Rollup may summarize already-supported planning evidence and recommend these commands without treating guidance as completed review evidence."
    },
    {
        id: "validation-checkpoint",
        kind: "write-capable-checkpoint",
        command: "day-shift validation checkpoint --scope planning",
        sourcePath: "src/cli/commands/validation-checkpoint/index.ts",
        rollupExecution: "excluded",
        writeCapable: true,
        mayReferenceAs: ["existing-baseline-evidence"],
        duplicatesDetailedFindings: false,
        preservesSharedNoWritePolicy: true,
        notes: "Checkpoint creation writes the forward-only baseline and is never part of read-only rollup execution; only an existing baseline may be read through the existing-baseline-comparison evidence source."
    }
];
const VALIDATION_ROLLUP_AGGREGATION_CONTRACT = {
    lanes: [
        {
            id: "checks",
            reportField: "checks",
            sourceEvidence: "PlanningValidationSmokeReport.checks",
            preservesSourceLane: true,
            authoritativeFor: ["check ids", "check status", "check messages"],
            notes: "Concise smoke checks remain a first-class lane and are not replaced by finding counts."
        },
        {
            id: "shared-findings",
            reportField: "findings",
            sourceEvidence: "PlanningValidationSmokeReport.findings",
            preservesSourceLane: true,
            authoritativeFor: ["ValidationFinding identity", "severity", "affected paths", "artifact references", "recovery guidance", "command evidence"],
            notes: "Shared findings preserve the common ValidationFinding envelope and validation-rollup command evidence when available."
        },
        {
            id: "inventory-findings",
            reportField: "inventoryFindings",
            sourceEvidence: "PlanningValidationSmokeReport.inventoryFindings",
            preservesSourceLane: true,
            authoritativeFor: ["paired artifact inventory findings"],
            notes: "Inventory findings stay visible as their own source lane even when corresponding shared findings are emitted."
        },
        {
            id: "planning-gaps",
            reportField: "gaps",
            sourceEvidence: "PlanningValidationSmokeReport.gaps",
            preservesSourceLane: true,
            authoritativeFor: ["planning gap code", "planning gap path", "planning gap message"],
            notes: "Planning gaps stay traceable to gap-report evidence instead of being flattened into anonymous text."
        },
        {
            id: "cross-artifact-alignment",
            reportField: "crossArtifactAlignment",
            sourceEvidence: "PlanningValidationSmokeReport.crossArtifactAlignment",
            preservesSourceLane: true,
            authoritativeFor: ["alignment family", "surface mode", "no-write flag", "lane findings"],
            notes: "Cross-artifact alignment preserves its nested lane evidence for headings, prompt lanes, routing, handoff, placeholders, and no-write boundaries."
        },
        {
            id: "baseline",
            reportField: "baseline",
            sourceEvidence: "PlanningValidationSmokeReport.baseline",
            preservesSourceLane: true,
            authoritativeFor: ["baseline metadata", "suppression counts"],
            notes: "Baseline aggregation reports existing baseline metadata and suppression counts without writing or refreshing the baseline."
        },
        {
            id: "next-actions",
            reportField: "nextActions",
            sourceEvidence: "PlanningValidationSmokeReport.nextActions",
            preservesSourceLane: true,
            authoritativeFor: ["advisory safe next actions"],
            notes: "Next actions remain advisory guidance and do not count as acceptance, repair, synchronization, metadata mutation, status transition, or artifact generation."
        },
        {
            id: "summary-counts",
            reportField: "summary",
            sourceEvidence: "PlanningValidationSmokeReport.summary",
            preservesSourceLane: true,
            authoritativeFor: ["total check count", "passed check count", "finding severity counts"],
            notes: "Summary counts are derived rollup metadata and do not replace the underlying check or finding lanes."
        },
        {
            id: "readiness-status",
            reportField: "readinessStatus",
            sourceEvidence: "PlanningValidationSmokeReport.readinessStatus",
            preservesSourceLane: true,
            authoritativeFor: ["derived readiness status"],
            notes: "Readiness status is derived from error and warning evidence while keeping the underlying checks, findings, inventory findings, and gaps visible."
        }
    ],
    sharedFindingFields: ["id", "code", "level", "severity", "affectedPaths", "artifacts", "recovery", "evidence"],
    sourceLaneFields: ["checks", "findings", "inventoryFindings", "gaps", "crossArtifactAlignment", "baseline", "nextActions", "summary", "readinessStatus"],
    readinessDerivation: "Readiness status is derived from blocking/error evidence and unresolved warning lanes; it must not hide the underlying checks, findings, inventory findings, or gaps.",
    baselinePolicy: "Existing baseline evidence may suppress already-recorded findings and report suppression counts, but aggregation never writes, refreshes, or creates a baseline.",
    nextActionPolicy: "Advisory next actions are guidance only and do not imply repair, synchronization, metadata mutation, status transition, artifact generation, or completed specialized review.",
    noWriteBoundary: "Validation rollup aggregation reports evidence only; it does not repair metadata, synchronize links, mutate manifests, update status, write checkpoints, or generate artifacts."
};
function hasDoctorErrorFinding(findings) {
    return findings.some((finding) => finding.severity === "error");
}
function getValidationRollupEvidenceSourceInventory() {
    return VALIDATION_ROLLUP_EVIDENCE_SOURCE_INVENTORY.map((source) => ({
        ...source,
        producer: { ...source.producer },
        evidenceShapes: [...source.evidenceShapes]
    }));
}
function getValidationRollupSpecializedBoundaries() {
    return VALIDATION_ROLLUP_SPECIALIZED_BOUNDARIES.map((boundary) => ({
        ...boundary,
        mayReferenceAs: [...boundary.mayReferenceAs]
    }));
}
function getValidationRollupAggregationContract() {
    return {
        ...VALIDATION_ROLLUP_AGGREGATION_CONTRACT,
        lanes: VALIDATION_ROLLUP_AGGREGATION_CONTRACT.lanes.map((lane) => ({
            ...lane,
            authoritativeFor: [...lane.authoritativeFor]
        })),
        sharedFindingFields: [...VALIDATION_ROLLUP_AGGREGATION_CONTRACT.sharedFindingFields],
        sourceLaneFields: [...VALIDATION_ROLLUP_AGGREGATION_CONTRACT.sourceLaneFields]
    };
}
function isDoctorBlockingFailure(report) {
    // Keep blocking behavior anchored to the shared severity model.
    return hasDoctorErrorFinding(report.findings) || report.summary.errors > 0;
}
function deriveDoctorReadinessStatus(report) {
    if (isDoctorBlockingFailure(report)) {
        return "blocked";
    }
    if (report.summary.warnings > 0) {
        return "ready_with_warnings";
    }
    return "ready";
}
function runCoreDoctorChecks(options = {}) {
    const detection = (0, runtime_contract_1.detectRepositoryRoot)(options.repositoryRoot === undefined
        ? undefined
        : { explicitRoot: options.repositoryRoot });
    const repositoryContext = (0, runtime_contract_1.createRepositoryContext)(detection, false);
    let resolvedConfig;
    const orchestration = (0, check_orchestration_1.executeDoctorCheckPlan)([
        { id: "environment", run: (findings) => {
                const result = (0, environment_checks_1.runDoctorEnvironmentChecks)({ repositoryRoot: repositoryContext.root, detectionSource: detection.detectionSource, findings });
                resolvedConfig = result.resolvedConfig;
                return result.checks;
            } },
        { id: "ignore", run: (findings) => (0, hygiene_checks_1.runIgnoreRecommendationCheck)(repositoryContext.root, findings) },
        { id: "markdownlint", run: (findings) => (0, hygiene_checks_1.runMarkdownlintRecommendationCheck)(repositoryContext.root, findings) }
    ]);
    const { checks, findings } = orchestration;
    const sandboxParentResult = (0, hygiene_checks_1.runSandboxParentPathIdentityCheck)(repositoryContext.root, findings);
    checks.push(sandboxParentResult.check);
    const sandboxParentPath = sandboxParentResult.sandboxParentPath;
    checks.push((0, hygiene_checks_1.runSandboxPathHygieneCheck)(sandboxParentPath, findings));
    checks.push((0, hygiene_checks_1.runSandboxCleanupReadinessCheck)(repositoryContext.root, sandboxParentPath, findings));
    checks.push((0, planning_checks_1.runPlanningArtifactMetadataCheck)(resolvedConfig, findings));
    checks.push((0, planning_checks_1.runPlanningCliProvenanceCheck)(resolvedConfig, findings));
    checks.push((0, planning_checks_1.runLightweightArtifactStrictnessCheck)(resolvedConfig, findings));
    checks.push((0, spec_registry_checks_1.runSpecRegistryDuplicateIdCheck)(repositoryContext.root, findings));
    checks.push((0, spec_registry_checks_1.runSpecRegistryStructureAndMetadataCheck)(repositoryContext.root, findings));
    checks.push((0, spec_registry_checks_1.runSpecRegistryDestinationSourceAndTraceabilityCheck)(repositoryContext.root, findings));
    const summary = {
        totalChecks: checks.length,
        passed: checks.filter((check) => check.status === "ok").length,
        informational: findings.filter((finding) => finding.severity === "informational").length,
        warnings: findings.filter((finding) => finding.severity === "warning").length,
        errors: findings.filter((finding) => finding.severity === "error").length
    };
    return {
        repositoryRoot: repositoryContext.root,
        detectionSource: repositoryContext.detectionSource,
        checks,
        findings,
        summary
    };
}
function runScopedDoctorChecks(selection) {
    if (selection.domain === "repository-audit") {
        const report = runCoreDoctorChecks({ repositoryRoot: selection.repositoryRoot });
        const actionRelevance = selection.actionId === undefined ? null : (0, action_relevance_1.classifyFindingsForAction)({
            actionId: selection.actionId,
            findings: report.findings,
            context: { healthDomain: selection.domain },
            fullDetailCommand: buildScopedDoctorFullDetailCommand(selection)
        });
        return {
            ...report,
            runtimeProvenance: (0, runtime_contract_1.getRuntimeProvenance)(),
            domain: selection.domain,
            scope: { kind: "repository", path: "." },
            readOnly: true,
            producerFamilies: {
                executed: ["runtime-setup", "workspace-hygiene", "planning-validation", "spec-registry"],
                excluded: []
            },
            completeness: { complete: true, recoveryCommand: null },
            actionRelevance
        };
    }
    const detection = (0, runtime_contract_1.detectRepositoryRoot)(selection.repositoryRoot === undefined
        ? undefined
        : { explicitRoot: selection.repositoryRoot });
    const repositoryContext = (0, runtime_contract_1.createRepositoryContext)(detection, false);
    const checks = [];
    const findings = [];
    if (selection.domain === "scan-surface") {
        const scanSurface = (0, workspace_scan_surface_1.scanWorkspaceSurfaces)({
            workspaceRoot: repositoryContext.root,
            scanPath: selection.scanPath,
            policy: (0, workspace_ignore_1.createIgnorePolicy)({ workspaceRoot: repositoryContext.root }),
            budgets: selection.repositoryAudit
                ? { files: 50_000, directories: 10_000, metadataBytes: 64_000_000, elapsedMs: 15_000, evidenceEntries: 5_000 }
                : undefined
        });
        findings.push(...scanSurface.findings.map((finding) => ({
            code: finding.id,
            message: finding.message,
            severity: finding.severity === "info" ? "informational" : "warning",
            ...(finding.path === undefined ? {} : { path: finding.path }),
            evidence: (0, output_1.createValidationCommandEvidence)({
                category: "validation-rollup",
                details: { source: "scan-surface", policyId: scanSurface.policy.id, complete: scanSurface.complete }
            })
        })));
        checks.push({
            id: "scan-surface",
            status: scanSurface.complete ? statusFromFindings(findings) : "warning",
            message: scanSurface.complete
                ? `Bounded scan observed ${scanSurface.observed.files} files and ${scanSurface.observed.directories} directories.`
                : `Bounded scan stopped before exceeding the ${scanSurface.exhaustedBudget} budget.`
        });
        const report = createScopedDoctorReport({
            repositoryRoot: repositoryContext.root,
            detectionSource: repositoryContext.detectionSource,
            domain: selection.domain,
            scope: { kind: "scan-surface", path: selection.scanPath ?? "." },
            checks,
            findings,
            executed: ["scan-surface"],
            excluded: ["runtime-setup", "workspace-hygiene", "planning-validation", "spec-registry"],
            actionId: selection.actionId
        });
        return {
            ...report,
            completeness: {
                complete: scanSurface.complete,
                recoveryCommand: scanSurface.complete ? null : scanSurface.recovery?.command ?? "day-shift doctor --scan-surface --repository-audit --format json"
            },
            scanSurface
        };
    }
    if (selection.domain === "runtime") {
        checks.push(...(0, environment_checks_1.runDoctorEnvironmentChecks)({
            repositoryRoot: repositoryContext.root,
            detectionSource: detection.detectionSource,
            findings
        }).checks);
        return createScopedDoctorReport({
            repositoryRoot: repositoryContext.root,
            detectionSource: repositoryContext.detectionSource,
            domain: selection.domain,
            scope: { kind: "runtime", path: null },
            checks,
            findings,
            executed: ["runtime-setup"],
            excluded: ["workspace-hygiene", "planning-validation", "spec-registry"],
            actionId: selection.actionId
        });
    }
    const selectedPath = (0, planning_document_utils_1.toRepositoryLikePath)(selection.path).replace(/^\.\//, "");
    if (selection.domain === "artifact") {
        const artifactText = node_fs_1.default.readFileSync((0, paths_2.resolveRepositoryRelativePath)(repositoryContext.root, (0, paths_2.parseRepositoryRelativePath)(selectedPath)), "utf8");
        const lifecycleFindings = (0, artifact_lifecycle_1.createArtifactLifecycleFindings)(selectedPath, (0, artifact_lifecycle_1.readArtifactLifecycleState)(artifactText));
        const linksCheck = (0, validation_links_check_1.runValidationLinksCheckReport)({
            repositoryRoot: repositoryContext.root,
            artifactPath: selectedPath
        });
        findings.push(...lifecycleFindings, ...linksCheck.findings);
        checks.push({
            id: "validation-links-check",
            status: statusFromFindings(linksCheck.findings),
            message: linksCheck.findings.length === 0
                ? "Selected-artifact links-check did not find trace-link lifecycle findings."
                : `Found ${linksCheck.findings.length} selected-artifact trace-link lifecycle finding${linksCheck.findings.length === 1 ? "" : "s"}.`
        });
        return createScopedDoctorReport({
            repositoryRoot: repositoryContext.root,
            detectionSource: repositoryContext.detectionSource,
            domain: selection.domain,
            scope: { kind: "artifact", path: selectedPath },
            checks,
            findings,
            executed: ["planning-validation"],
            excluded: ["runtime-setup", "workspace-hygiene", "spec-registry"],
            actionId: selection.actionId
        });
    }
    const inventory = (0, planning_navigation_1.inventoryPlanning)({
        repositoryRoot: repositoryContext.root,
        rootPath: selectedPath
    });
    const gaps = (0, planning_navigation_1.gapReportPlanning)({
        repositoryRoot: repositoryContext.root,
        scopePath: selectedPath
    }).gaps;
    checks.push({
        id: "planning-inventory",
        status: inventory.findings.length === 0 ? "ok" : "warning",
        message: inventory.findings.length === 0
            ? "Selected planning directory inventory did not find stale paired-artifact state."
            : `Found ${inventory.findings.length} planning inventory finding${inventory.findings.length === 1 ? "" : "s"} in the selected directory.`
    }, {
        id: "planning-gap-report",
        status: gaps.length === 0 ? "ok" : "warning",
        message: gaps.length === 0
            ? "Selected planning directory gap report did not find incomplete downstream artifacts."
            : `Found ${gaps.length} expected-versus-observed planning gap${gaps.length === 1 ? "" : "s"} in the selected directory.`
    });
    findings.push(...inventory.findings.map((message) => ({
        code: "PLANNING_INVENTORY_FINDING",
        message,
        severity: "warning",
        evidence: (0, output_1.createValidationCommandEvidence)({
            category: "validation-rollup",
            details: { source: "planning-inventory" }
        })
    })), ...gaps.map((gap) => ({
        code: gap.code,
        message: gap.message,
        severity: "warning",
        path: gap.path,
        evidence: (0, output_1.createValidationCommandEvidence)({
            category: "validation-rollup",
            details: { source: "planning-gap-report" }
        })
    })));
    return createScopedDoctorReport({
        repositoryRoot: repositoryContext.root,
        detectionSource: repositoryContext.detectionSource,
        domain: selection.domain,
        scope: { kind: "directory", path: selectedPath },
        checks,
        findings,
        executed: ["planning-validation"],
        excluded: ["runtime-setup", "workspace-hygiene", "spec-registry"],
        actionId: selection.actionId
    });
}
function createScopedDoctorReport(options) {
    const checks = [...options.checks];
    const findings = [...options.findings];
    const actionRelevance = options.actionId === undefined ? null : (0, action_relevance_1.classifyFindingsForAction)({
        actionId: options.actionId,
        findings,
        context: {
            selectedArtifactPath: options.scope.kind === "artifact" ? options.scope.path : null,
            healthDomain: options.domain
        },
        fullDetailCommand: buildScopedDoctorFullDetailCommand({
            domain: options.domain,
            ...(options.scope.path === null || options.domain === "repository-audit"
                ? {}
                : { path: options.scope.path }),
            actionId: options.actionId
        })
    });
    return {
        repositoryRoot: options.repositoryRoot,
        detectionSource: options.detectionSource,
        runtimeProvenance: (0, runtime_contract_1.getRuntimeProvenance)(),
        domain: options.domain,
        scope: options.scope,
        readOnly: true,
        producerFamilies: { executed: [...options.executed], excluded: [...options.excluded] },
        completeness: {
            complete: true,
            recoveryCommand: options.domain === "repository-audit"
                ? null
                : "day-shift doctor --repository-audit --format json"
        },
        actionRelevance,
        checks,
        findings,
        summary: {
            totalChecks: checks.length,
            passed: checks.filter((check) => check.status === "ok").length,
            informational: findings.filter((finding) => finding.severity === "informational").length,
            warnings: findings.filter((finding) => finding.severity === "warning").length,
            errors: findings.filter((finding) => finding.severity === "error").length
        }
    };
}
function renderDoctorReportText(report) {
    const lines = [
        (0, output_1.renderTerminalHeading)("Day Shift workspace doctor", "title").trimEnd(),
        "",
        (0, output_1.renderTerminalSection)({
            heading: "Summary",
            fields: [
                { label: "Repository root", value: report.repositoryRoot },
                { label: "Detection source", value: report.detectionSource },
                {
                    label: "Checks",
                    value: `${report.summary.totalChecks} total, ${report.summary.passed} passed, ${report.summary.informational} informational, ${report.summary.warnings} warnings, ${report.summary.errors} errors`
                }
            ],
            lines: [(0, output_1.renderTerminalBoundary)({ kind: "read-only" })]
        })
    ];
    if (report.findings.length > 0) {
        lines.push("", renderDoctorGroupedFindings(report.findings));
    }
    return lines.join("\n");
}
function renderScopedDoctorReportText(report) {
    const scopeIdentity = report.scope.path === null
        ? report.scope.kind
        : `${report.scope.kind}:${report.scope.path}`;
    const lines = [
        (0, output_1.renderTerminalHeading)("Day Shift workspace doctor", "title").trimEnd(),
        "",
        (0, output_1.renderTerminalSection)({
            heading: "Summary",
            fields: [
                { label: "Repository root", value: report.repositoryRoot },
                { label: "Detection source", value: report.detectionSource },
                { label: "Health domain", value: report.domain },
                { label: "Selected scope", value: scopeIdentity },
                { label: "Complete", value: report.completeness.complete ? "yes" : "no" },
                { label: "Selected action", value: report.actionRelevance?.selectedAction.command ?? "none" },
                { label: "Current-action blockers", value: report.actionRelevance?.currentActionBlockers.length ?? 0 },
                {
                    label: "Checks",
                    value: `${report.summary.totalChecks} total, ${report.summary.passed} passed, ${report.summary.informational} informational, ${report.summary.warnings} warnings, ${report.summary.errors} errors`
                }
            ],
            lines: [(0, output_1.renderTerminalBoundary)({ kind: "read-only" })]
        })
    ];
    if (report.completeness.recoveryCommand !== null) {
        lines.push("", `Broader audit: ${report.completeness.recoveryCommand}`);
    }
    if (report.actionRelevance !== null) {
        lines.push("", `Full action detail: ${report.actionRelevance.fullDetailCommand}`);
        lines.push("", (0, output_1.renderTerminalCompactList)({
            heading: "Current-action blockers by code:",
            entries: report.actionRelevance.blockerGroups.map((group) => ({
                label: group.code,
                fields: [
                    { label: "Count", value: group.count },
                    { label: "Rule", value: group.representative.ruleId },
                    { label: "Message", value: group.representative.originalFinding.message }
                ]
            })),
            emptyMessage: "No blockers apply to the selected action."
        }));
    }
    if (report.findings.length > 0) {
        lines.push("", renderDoctorGroupedFindings(report.findings));
    }
    return lines.join("\n");
}
function buildScopedDoctorFullDetailCommand(selection) {
    const args = ["day-shift", "doctor"];
    if (selection.domain === "runtime")
        args.push("--runtime-only");
    if (selection.domain === "artifact")
        args.push("--artifact", selection.path);
    if (selection.domain === "planning")
        args.push("--planning-directory", selection.path);
    if (selection.domain === "scan-surface") {
        args.push("--scan-surface");
        if (selection.scanPath !== undefined)
            args.push("--scan-path", JSON.stringify(selection.scanPath));
        if (selection.repositoryAudit)
            args.push("--repository-audit");
    }
    if (selection.domain === "repository-audit")
        args.push("--repository-audit");
    if (selection.actionId !== undefined)
        args.push("--action", JSON.stringify(selection.actionId));
    args.push("--format", "json", "--detail", "full");
    return args.join(" ");
}
function renderDoctorErrorDetails(report) {
    return [
        "",
        (0, output_1.renderTerminalSection)({
            heading: "Summary",
            fields: [
                { label: "Repository root", value: report.repositoryRoot },
                { label: "Detection source", value: report.detectionSource },
                {
                    label: "Checks",
                    value: `${report.summary.totalChecks} total, ${report.summary.passed} passed, ${report.summary.informational} informational, ${report.summary.warnings} warnings, ${report.summary.errors} errors`
                }
            ],
            lines: [(0, output_1.renderTerminalBoundary)({ kind: "read-only" })]
        }),
        "",
        renderDoctorCheckSummary(report.checks),
        "",
        renderDoctorGroupedFindings(report.findings)
    ];
}
function renderDoctorCheckSummary(checks) {
    const relevantChecks = checks.filter((check) => check.status !== "ok");
    return (0, output_1.renderTerminalCompactList)({
        heading: "Checks needing attention",
        entries: relevantChecks.map((check) => ({
            label: `${check.id} (${check.status})`,
            fields: [
                { label: "Message", value: check.message }
            ]
        })),
        emptyMessage: "No checks need attention."
    });
}
function renderDoctorGroupedFindings(findings) {
    const groups = groupDoctorFindings(findings);
    return (0, output_1.renderTerminalCompactList)({
        heading: "Findings by issue",
        entrySpacing: "loose",
        entries: groups.map((group) => ({
            label: `[${group.severity}] ${group.code}`,
            fields: [
                { label: "Count", value: group.findings.length },
                { label: "Message", value: group.message }
            ],
            lines: renderDoctorFindingPaths(group.findings)
        })),
        emptyMessage: "No findings."
    });
}
function groupDoctorFindings(findings) {
    const groups = new Map();
    for (const finding of findings) {
        const key = [
            finding.severity,
            finding.code,
            finding.message
        ].join("\u0000");
        const existingGroup = groups.get(key);
        if (existingGroup !== undefined) {
            existingGroup.findings.push(finding);
            continue;
        }
        groups.set(key, {
            severity: finding.severity,
            code: finding.code,
            message: finding.message,
            findings: [finding]
        });
    }
    return Array.from(groups.values()).sort((left, right) => (doctorSeveritySortValue(left.severity) - doctorSeveritySortValue(right.severity)
        || left.code.localeCompare(right.code)
        || left.message.localeCompare(right.message)));
}
function doctorSeveritySortValue(severity) {
    if (severity === "error") {
        return 0;
    }
    if (severity === "warning") {
        return 1;
    }
    return 2;
}
function renderDoctorFindingPaths(findings) {
    const paths = Array.from(new Set(findings
        .map((finding) => finding.path)
        .filter((findingPath) => (findingPath !== undefined && findingPath.trim() !== ""))));
    if (paths.length === 0) {
        return [];
    }
    const visiblePaths = paths.slice(0, DOCTOR_TEXT_PATH_PREVIEW_LIMIT);
    const hiddenPathCount = paths.length - visiblePaths.length;
    return [
        hiddenPathCount > 0 ? "Paths (first 12):" : "Paths:",
        ...visiblePaths.map((findingPath) => `- ${findingPath}`),
        ...(hiddenPathCount > 0
            ? [`Additional paths: ${hiddenPathCount} more; rerun with --format json for the full finding payload.`]
            : [])
    ];
}
function runPlanningValidationSmoke(options = {}) {
    const detection = (0, runtime_contract_1.detectRepositoryRoot)(options.repositoryRoot === undefined
        ? undefined
        : { explicitRoot: options.repositoryRoot });
    const repositoryContext = (0, runtime_contract_1.createRepositoryContext)(detection, false);
    const resolvedConfig = (0, config_contract_1.resolveDayShiftConfig)({ repositoryContext });
    const loadedBaseline = loadPlanningValidationBaseline(repositoryContext.root);
    const findings = [];
    const checks = [];
    checks.push((0, planning_checks_1.runPlanningArtifactMetadataCheck)(resolvedConfig, findings));
    checks.push((0, planning_checks_1.runPlanningCliProvenanceCheck)(resolvedConfig, findings));
    checks.push((0, planning_checks_1.runLightweightArtifactStrictnessCheck)(resolvedConfig, findings));
    const selectedArtifactPath = options.artifactPath === undefined
        ? null
        : (0, planning_document_utils_1.toRepositoryLikePath)(options.artifactPath).replace(/^\.\//, "");
    const planningNavigationArtifactPath = selectedArtifactPath !== null && isPlanningNavigationArtifact(repositoryContext.root, selectedArtifactPath)
        ? selectedArtifactPath
        : null;
    const validationEvidenceScopePath = planningNavigationArtifactPath
        ?? (0, paths_1.toRepositoryRelativePath)(repositoryContext.root, resolvedConfig.derived.planningRootPath);
    const inventory = (0, planning_navigation_1.inventoryPlanning)({
        repositoryRoot: repositoryContext.root,
        rootPath: validationEvidenceScopePath
    });
    const gaps = (0, planning_navigation_1.gapReportPlanning)({
        repositoryRoot: repositoryContext.root,
        scopePath: validationEvidenceScopePath
    }).gaps;
    checks.push({
        id: "planning-inventory",
        status: inventory.findings.length > 0 ? "warning" : "ok",
        message: inventory.findings.length > 0
            ? `Found ${inventory.findings.length} planning inventory finding${inventory.findings.length === 1 ? "" : "s"} across paired artifacts and metadata state.`
            : "Planning inventory did not find stale paired-artifact state."
    });
    checks.push({
        id: "planning-gap-report",
        status: gaps.length > 0 ? "warning" : "ok",
        message: gaps.length > 0
            ? `Found ${gaps.length} expected-versus-observed planning gap${gaps.length === 1 ? "" : "s"}.`
            : "Planning gap report did not find missing or incomplete downstream artifacts."
    });
    const linksCheckReport = planningNavigationArtifactPath === null
        ? null
        : (0, validation_links_check_1.runValidationLinksCheckReport)({
            repositoryRoot: repositoryContext.root,
            artifactPath: planningNavigationArtifactPath
        });
    if (linksCheckReport !== null) {
        checks.push({
            id: "validation-links-check",
            status: statusFromFindings(linksCheckReport.findings),
            message: linksCheckReport.findings.length > 0
                ? `Found ${linksCheckReport.findings.length} selected-artifact trace-link lifecycle finding${linksCheckReport.findings.length === 1 ? "" : "s"}.`
                : "Selected-artifact links-check did not find trace-link lifecycle findings."
        });
    }
    const crossArtifactAlignment = runCrossArtifactAlignmentSmoke(repositoryContext.root, options.artifactPath);
    const crossArtifactFindings = crossArtifactAlignment.lanes.flatMap((lane) => [...lane.findings]);
    const crossArtifactStatus = statusFromFindings(crossArtifactFindings);
    checks.push({
        id: "cross-artifact-alignment",
        status: crossArtifactStatus,
        message: crossArtifactFindings.length > 0
            ? `Found ${crossArtifactFindings.length} cross-artifact alignment finding${crossArtifactFindings.length === 1 ? "" : "s"} across headings, prompt lanes, routing, handoffs, placeholder contracts, artifact shape, and no-write boundaries.`
            : "Cross-artifact alignment checks did not find heading, declared-child-slug, prompt-lane, routing, handoff, placeholder, artifact-shape, or no-write drift."
    });
    findings.push(...inventory.findings.map((message) => ({
        code: "PLANNING_INVENTORY_FINDING",
        message,
        severity: "warning",
        evidence: (0, output_1.createValidationCommandEvidence)({
            category: "validation-rollup",
            details: {
                source: "planning-inventory"
            }
        })
    })), ...gaps.map((gap) => ({
        code: gap.code,
        message: gap.message,
        severity: "warning",
        path: gap.path,
        evidence: (0, output_1.createValidationCommandEvidence)({
            category: "validation-rollup",
            details: {
                source: "planning-gap-report"
            }
        })
    })), ...(linksCheckReport?.findings ?? []), ...crossArtifactFindings);
    const rawFindings = [...findings];
    const filteredFindings = filterBaselineFindings(rawFindings, loadedBaseline);
    const filteredInventoryFindings = filterBaselineInventoryFindings(inventory.findings, loadedBaseline);
    const filteredGaps = filterBaselineGaps(gaps, loadedBaseline);
    findings.length = 0;
    findings.push(...filteredFindings);
    const baselineEvidence = buildPlanningValidationBaselineEvidence({
        loadedBaseline,
        rawFindings,
        filteredFindings,
        rawInventoryFindings: inventory.findings,
        filteredInventoryFindings,
        rawGaps: gaps,
        filteredGaps
    });
    const effectiveChecks = applyPlanningValidationBaselineToChecks({
        checks,
        rawFindings,
        filteredFindings,
        rawInventoryFindings: inventory.findings,
        filteredInventoryFindings,
        rawGaps: gaps,
        filteredGaps,
        baselineEvidence
    });
    const nextAction = planningNavigationArtifactPath
        ? (0, planning_navigation_1.suggestPlanningNextAction)({
            repositoryRoot: repositoryContext.root,
            artifactPath: planningNavigationArtifactPath
        })
        : null;
    const nextActions = derivePlanningValidationSmokeNextActions({
        checks: effectiveChecks,
        inventoryFindings: filteredInventoryFindings,
        gaps: filteredGaps,
        nextAction
    });
    const summary = {
        totalChecks: effectiveChecks.length,
        passed: effectiveChecks.filter((check) => check.status === "ok").length,
        informational: findings.filter((finding) => finding.severity === "informational").length,
        warnings: findings.filter((finding) => finding.severity === "warning").length,
        errors: findings.filter((finding) => finding.severity === "error").length
    };
    const readinessStatus = derivePlanningValidationSmokeStatus({
        checks: effectiveChecks,
        inventoryFindings: filteredInventoryFindings,
        gaps: filteredGaps
    });
    const actionRelevance = options.actionId === undefined ? null : {
        ...(0, action_relevance_1.classifyFindingsForAction)({
            actionId: options.actionId,
            findings,
            context: {
                selectedArtifactPath,
                healthDomain: "artifact"
            },
            fullDetailCommand: `day-shift validation smoke --scope planning --artifact ${JSON.stringify(selectedArtifactPath)} --action ${JSON.stringify(options.actionId)} --format json --detail full`
        }),
        sourceFindingsUnchanged: true,
        repositoryWideGate: createPlanningValidationRepositoryWideGate(options.actionId)
    };
    return {
        repositoryRoot: repositoryContext.root,
        detectionSource: repositoryContext.detectionSource,
        scope: "planning",
        planningRootPath: resolvedConfig.derived.planningRootPath,
        evidenceSourceInventory: getValidationRollupEvidenceSourceInventory(),
        specializedReviewBoundaries: getValidationRollupSpecializedBoundaries(),
        aggregationContract: getValidationRollupAggregationContract(),
        checks: effectiveChecks,
        findings,
        inventoryFindings: filteredInventoryFindings,
        crossArtifactAlignment,
        baseline: baselineEvidence,
        gaps: filteredGaps,
        nextActions,
        nextAction,
        summary,
        readinessStatus,
        actionRelevance
    };
}
function createPlanningValidationRepositoryWideGate(actionId) {
    const descriptor = (0, output_1.getRegisteredCommandDescriptor)(actionId);
    if (descriptor === null || descriptor.availability !== "callable") {
        throw new TypeError(`Unknown callable action descriptor '${actionId}'.`);
    }
    const required = descriptor.artifactFamily === "release"
        || descriptor.capability === "migration"
        || descriptor.mutationPosture === "applies-migration";
    return {
        required,
        satisfiedByArtifactValidation: false,
        requiredCommand: required
            ? `day-shift doctor --repository-audit --action ${JSON.stringify(descriptor.command)} --format json --detail full`
            : null
    };
}
function isPlanningNavigationArtifact(repositoryRoot, selectedArtifactPath) {
    const content = readRepositoryFile(repositoryRoot, selectedArtifactPath);
    if (content === null) {
        return false;
    }
    const family = (0, validation_1.detectArtifactFamily)({
        path: selectedArtifactPath,
        content
    }).family;
    return family === "planning" || family === "implementation-summary" || family === "reconciliation";
}
function renderPlanningValidationSmokeReport(report) {
    const lines = [
        (0, output_1.renderTerminalHeading)("Day Shift validation smoke", "title").trimEnd(),
        "",
        (0, output_1.renderTerminalSection)({
            heading: "Summary",
            fields: [
                { label: "Repository root", value: report.repositoryRoot },
                { label: "Detection source", value: report.detectionSource },
                { label: "Scope", value: report.scope },
                { label: "No-write validation surface", value: "yes" },
                { label: "Planning root", value: report.planningRootPath },
                { label: "Readiness status", value: report.readinessStatus },
                { label: "Selected action", value: report.actionRelevance?.selectedAction.command ?? "none" },
                { label: "Forward-only baseline", value: report.baseline.present ? `${report.baseline.path} (${report.baseline.suppressedFindings + report.baseline.suppressedInventoryFindings + report.baseline.suppressedGaps} suppressed)` : "none" },
                {
                    label: "Checks",
                    value: `${report.summary.totalChecks} total, ${report.summary.passed} passed, ${report.summary.informational} informational, ${report.summary.warnings} warnings, ${report.summary.errors} errors`
                }
            ],
            lines: [(0, output_1.renderTerminalBoundary)({ kind: "read-only" })]
        }),
        "",
        (0, output_1.renderTerminalCompactList)({
            heading: "Check results:",
            entries: report.checks.map((check) => ({
                label: `[${check.status}] ${check.id}`,
                lines: [check.message]
            }))
        })
    ];
    if (report.actionRelevance !== null) {
        lines.push("", "Action relevance:", `- Current-action blockers: ${report.actionRelevance.currentActionBlockers.length}`, `- Source findings unchanged: ${report.actionRelevance.sourceFindingsUnchanged ? "yes" : "no"}`, `- Repository-wide gate required: ${report.actionRelevance.repositoryWideGate.required ? "yes" : "no"}`);
        if (report.actionRelevance.repositoryWideGate.requiredCommand !== null) {
            lines.push(`- Required repository audit: ${report.actionRelevance.repositoryWideGate.requiredCommand}`);
        }
    }
    if (report.inventoryFindings.length > 0) {
        lines.push("", "Inventory findings:");
        for (const finding of report.inventoryFindings) {
            lines.push(`- ${finding}`);
        }
    }
    if (report.gaps.length > 0) {
        lines.push("", "Planning gaps:");
        for (const gap of report.gaps) {
            lines.push(`- [${gap.code}] ${gap.message}`);
        }
    }
    lines.push("", "Cross-artifact alignment:");
    lines.push(`- selected family: ${report.crossArtifactAlignment.selectedArtifactFamily}`, `- surface mode: ${report.crossArtifactAlignment.surfaceMode}`, `- no-write: ${report.crossArtifactAlignment.noWrite ? "yes" : "no"}`, `- findings taxonomy: ${report.crossArtifactAlignment.findingsTaxonomy}`);
    for (const lane of report.crossArtifactAlignment.lanes) {
        lines.push(`- [${lane.status}] ${lane.id}: ${lane.findings.length} finding${lane.findings.length === 1 ? "" : "s"}`);
    }
    if (report.nextAction !== null) {
        lines.push("", "Artifact guidance:", `- Recommendation: ${report.nextAction.recommendation}`, `- Reason: ${report.nextAction.reason}`, `- Command: ${report.nextAction.command ?? "(workflow-guided step; no direct CLI command)"}`);
    }
    if (report.nextActions.length > 0) {
        lines.push("", "Safe next actions:");
        for (const action of report.nextActions) {
            lines.push(`- ${action}`);
        }
    }
    if (report.findings.length > 0) {
        lines.push("", (0, output_1.renderValidationFindingsText)(report.findings, "Structured findings"));
    }
    return lines.join("\n");
}
function writePlanningValidationBaseline(options) {
    const baselinePath = PLANNING_VALIDATION_BASELINE_PATH;
    const absoluteBaselinePath = node_path_1.default.join(options.repositoryRoot, baselinePath);
    const existingBaselinePath = node_path_1.default.join(options.repositoryRoot, `${baselinePath}.disabled-for-refresh`);
    if (node_fs_1.default.existsSync(absoluteBaselinePath)) {
        node_fs_1.default.renameSync(absoluteBaselinePath, existingBaselinePath);
    }
    try {
        const report = runPlanningValidationSmoke();
        const record = {
            schema_version: 1,
            created_at: options.createdAt ?? new Date().toISOString(),
            scope: "planning",
            mode: "forward-only",
            notes: [
                "Forward-only baseline for repo-wide planning validation smoke.",
                "Historical findings captured here are preserved as repository history and suppressed from future repo-wide smoke blocking status when they match exactly.",
                "New or changed findings remain visible in validation smoke output."
            ],
            findings: report.findings.map((finding) => ({
                fingerprint: fingerprintFinding(finding),
                code: finding.code,
                severity: finding.severity,
                path: finding.path ?? null,
                message: finding.message
            })),
            inventory_findings: report.inventoryFindings.map((message) => ({
                fingerprint: fingerprintInventoryFinding(message),
                message
            })),
            gaps: report.gaps.map((gap) => ({
                fingerprint: fingerprintGap(gap),
                code: gap.code,
                path: gap.path,
                message: gap.message
            }))
        };
        node_fs_1.default.mkdirSync(node_path_1.default.dirname(absoluteBaselinePath), { recursive: true });
        node_fs_1.default.writeFileSync(absoluteBaselinePath, `${JSON.stringify(record, null, 2)}\n`, "utf8");
        return { ...record, path: baselinePath };
    }
    finally {
        if (node_fs_1.default.existsSync(existingBaselinePath)) {
            node_fs_1.default.rmSync(existingBaselinePath, { force: true });
        }
    }
}
function runCrossArtifactAlignmentSmoke(repositoryRoot, selectedArtifactPath) {
    const lanes = [
        createCrossArtifactLane("heading-section-order", runHeadingSectionOrderChecks(repositoryRoot)),
        createCrossArtifactLane("declared-child-slugs", runDeclaredChildSlugChecks(repositoryRoot)),
        createCrossArtifactLane("prompt-rendering-lanes", runPromptRenderingLaneChecks(repositoryRoot)),
        createCrossArtifactLane("source-destination-routing", runSourceDestinationRoutingChecks(repositoryRoot)),
        createCrossArtifactLane("review-handoff", runReviewHandoffChecks(repositoryRoot)),
        createCrossArtifactLane("placeholder-scaffolding", runPlaceholderScaffoldingChecks(repositoryRoot)),
        createCrossArtifactLane("artifact-shape", runSelectedArtifactShapeChecks(repositoryRoot, selectedArtifactPath)),
        createCrossArtifactLane("no-write-surface", runNoWriteSurfaceChecks(repositoryRoot))
    ];
    return {
        selectedArtifactFamily: "planning",
        surfaceMode: "validation-smoke",
        noWrite: true,
        findingsTaxonomy: "shared-findings",
        lanes
    };
}
function runSelectedArtifactShapeChecks(repositoryRoot, selectedArtifactPath) {
    if (selectedArtifactPath === undefined) {
        return [];
    }
    const artifactPath = (0, planning_document_utils_1.toRepositoryLikePath)(selectedArtifactPath).replace(/^\.\//, "");
    const content = readRepositoryFile(repositoryRoot, artifactPath);
    if (content === null) {
        return [
            createCrossArtifactFinding({
                code: "ARTIFACT_SHAPE_INPUT_MISSING",
                message: `Cannot verify artifact shape because '${artifactPath}' is missing.`,
                severity: "error",
                path: artifactPath,
                evidence: (0, output_1.createValidationCommandEvidence)({
                    category: "validation-rollup",
                    details: {
                        source: "artifact-shape"
                    }
                })
            })
        ];
    }
    const result = (0, validation_1.validateArtifactShape)({
        path: artifactPath,
        content
    });
    return result.findings.map((finding) => createCrossArtifactFinding({
        code: finding.code,
        message: finding.message,
        severity: finding.severity,
        path: finding.path,
        evidence: (0, output_1.createValidationCommandEvidence)({
            category: "validation-rollup",
            details: {
                source: "artifact-shape",
                family: result.family.family
            }
        })
    }));
}
function createCrossArtifactLane(id, findings) {
    return {
        id,
        selectedArtifactFamily: "planning",
        surfaceMode: "validation-smoke",
        status: statusFromFindings(findings),
        findings
    };
}
function runHeadingSectionOrderChecks(repositoryRoot) {
    const findings = [];
    for (const [templatePath, expectedHeadings] of EXPECTED_TEMPLATE_H2_HEADINGS) {
        const content = readRepositoryFile(repositoryRoot, templatePath);
        if (content === null) {
            findings.push(createCrossArtifactFinding({
                code: "CROSS_ARTIFACT_ALIGNMENT_INPUT_MISSING",
                message: `Cannot verify heading order because '${templatePath}' is missing.`,
                severity: "warning",
                path: templatePath
            }));
            continue;
        }
        const observedHeadings = content
            .split(/\r?\n/u)
            .filter((line) => line.startsWith("## "));
        if (!arraysEqual(observedHeadings, expectedHeadings)) {
            findings.push(createCrossArtifactFinding({
                code: "CROSS_ARTIFACT_HEADING_ORDER_DRIFT",
                message: `Template '${templatePath}' does not preserve the canonical H2 heading order for its artifact family.`,
                severity: "error",
                path: templatePath
            }));
        }
    }
    return findings;
}
function runDeclaredChildSlugChecks(repositoryRoot) {
    const findings = [];
    const planningRoot = node_path_1.default.join(repositoryRoot, ".day-shift", "planning");
    if (!node_fs_1.default.existsSync(planningRoot)) {
        return findings;
    }
    for (const artifactPath of collectPlanningMarkdownArtifacts(planningRoot, ".day-shift/planning")) {
        if (!artifactPath.endsWith("/overview.md")) {
            continue;
        }
        const absolutePath = node_path_1.default.join(repositoryRoot, artifactPath);
        const content = readRepositoryFile(repositoryRoot, artifactPath);
        if (content === null) {
            continue;
        }
        const document = (0, planning_document_utils_1.parseMarkdownFrontMatter)(content);
        if (!document.hasFrontMatter) {
            continue;
        }
        const artifactType = (0, planning_document_utils_1.readTopLevelField)(document.frontMatterLines, "artifact_type")?.trim() ?? null;
        const declaredChildContract = declaredChildContractForArtifact(document.frontMatterLines, artifactType);
        if (declaredChildContract === null) {
            continue;
        }
        const validation = (0, planning_document_utils_1.validateDeclaredChildSlugSection)(content, declaredChildContract.sectionName);
        for (const issue of validation.issues) {
            findings.push(createCrossArtifactFinding({
                code: "CROSS_ARTIFACT_DECLARED_CHILD_SLUG_DRIFT",
                message: `${declaredChildContract.artifactLabel} '${artifactPath}' has invalid ${declaredChildContract.childLabel} declarations: ${issue.message}`,
                severity: "error",
                path: (0, planning_document_utils_1.toRepositoryLikePath)(node_path_1.default.relative(repositoryRoot, absolutePath))
            }));
        }
    }
    return findings;
}
function declaredChildContractForArtifact(frontMatterLines, artifactType) {
    if (artifactType === "slice_overview") {
        const planningDepth = (0, planning_document_utils_1.readTopLevelField)(frontMatterLines, "planning_depth")?.trim() ?? "standard";
        if (planningDepth === "lightweight") {
            return null;
        }
        return {
            artifactLabel: "Slice overview",
            childLabel: "phase",
            sectionName: "Phases"
        };
    }
    if (artifactType === "phase_overview") {
        return {
            artifactLabel: "Phase overview",
            childLabel: "milestone",
            sectionName: "Milestones"
        };
    }
    if (artifactType === "milestone_overview") {
        return {
            artifactLabel: "Milestone overview",
            childLabel: "task",
            sectionName: "Tasks"
        };
    }
    return null;
}
function runPromptRenderingLaneChecks(repositoryRoot) {
    const findings = [];
    const enforceSourceOnlyContracts = isDayShiftSourceRepository(repositoryRoot);
    requireTextSnippets(repositoryRoot, findings, ".day-shift/specs/06-templates-and-prompts/prompts.md", [
        "A rendered prompt must keep four visible lanes distinct: generated context, agent entrypoint guidance, warnings, and prompt instructions.",
        "fail by default when required agent entrypoint guidance is missing",
        "allow `--no-agent` only as an explicit degraded mode with a visible warning"
    ], "CROSS_ARTIFACT_PROMPT_LANE_DRIFT", {
        allowMissingInput: !enforceSourceOnlyContracts
    });
    requireTextSnippets(repositoryRoot, findings, ".day-shift/prompts/user/manifest.json", [
        "Rendered prompt surfaces keep four visible lanes in order: generated context, agent entrypoint guidance, warnings, and prompt instructions",
        "Read-only prompt show/reporting surfaces should keep generated context, agent entrypoint guidance, warnings, and prompt instructions in separate visible lanes"
    ], "CROSS_ARTIFACT_PROMPT_LANE_DRIFT");
    requireTextSnippets(repositoryRoot, findings, ".day-shift/workflows/02-plan-from-spec.md", [
        "keep four visible lanes distinct in this order: generated context, agent entrypoint guidance, warnings, then prompt instructions",
        "fail by default when that agent entrypoint is missing"
    ], "CROSS_ARTIFACT_PROMPT_LANE_DRIFT");
    return findings;
}
function runSourceDestinationRoutingChecks(repositoryRoot) {
    const findings = [];
    const templateManifestPath = ".day-shift/templates/manifest.json";
    const promptManifestPath = ".day-shift/prompts/user/manifest.json";
    const templateManifest = readJsonObject(repositoryRoot, templateManifestPath, findings);
    const promptManifest = readJsonObject(repositoryRoot, promptManifestPath, findings);
    const templatePaths = new Set();
    if (templateManifest !== null) {
        for (const entry of readObjectArray(templateManifest, "templates")) {
            const templatePath = readString(entry, "path");
            const kind = readString(entry, "kind");
            const destination = readString(entry, "destination");
            if (templatePath !== null) {
                templatePaths.add(templatePath);
            }
            if (destination !== null && kind !== "scaffold") {
                findings.push(createCrossArtifactFinding({
                    code: "CROSS_ARTIFACT_DESTINATION_ROUTING_DRIFT",
                    message: `Template manifest entry '${templatePath ?? "(unknown)"}' declares destination outside the scaffold/support destination lane.`,
                    severity: "error",
                    path: templateManifestPath
                }));
            }
        }
    }
    if (promptManifest !== null) {
        for (const entry of readObjectArray(promptManifest, "prompts")) {
            const promptPath = readString(entry, "path") ?? "(unknown)";
            if (readString(entry, "destination") !== null) {
                findings.push(createCrossArtifactFinding({
                    code: "CROSS_ARTIFACT_PROMPT_DESTINATION_DRIFT",
                    message: `Prompt manifest entry '${promptPath}' declares destination routing; prompt template_ref/template_refs must stay source-template metadata only.`,
                    severity: "error",
                    path: promptManifestPath
                }));
            }
            for (const templateRef of readTemplateReferences(entry)) {
                if (!templateRef.startsWith(".day-shift/templates/")) {
                    findings.push(createCrossArtifactFinding({
                        code: "CROSS_ARTIFACT_TEMPLATE_REF_DRIFT",
                        message: `Prompt manifest entry '${promptPath}' references '${templateRef}' outside the template source path lane.`,
                        severity: "error",
                        path: promptManifestPath
                    }));
                }
                else if (templateManifest !== null && !templatePaths.has(templateRef)) {
                    findings.push(createCrossArtifactFinding({
                        code: "CROSS_ARTIFACT_TEMPLATE_REF_DRIFT",
                        message: `Prompt manifest entry '${promptPath}' references '${templateRef}', which is absent from the template manifest source inventory.`,
                        severity: "error",
                        path: promptManifestPath
                    }));
                }
            }
        }
    }
    const specIndex = readJsonObject(repositoryRoot, ".day-shift/specs/index.json", findings);
    if (specIndex !== null) {
        const requiredSpecEntries = new Map([
            ["templates-and-prompts-templates", "templates-and-prompts/templates"],
            ["templates-and-prompts-prompts", "templates-and-prompts/prompts"]
        ]);
        const specEntries = readObjectArray(specIndex, "specs");
        const shouldEnforceTemplatesAndPromptsTraceability = specEntries.some((entry) => {
            return requiredSpecEntries.has(readString(entry, "id") ?? "");
        }) || node_fs_1.default.existsSync(node_path_1.default.join(repositoryRoot, ".day-shift/specs/06-templates-and-prompts"));
        if (shouldEnforceTemplatesAndPromptsTraceability) {
            for (const [specId, expectedDestination] of requiredSpecEntries) {
                const entry = specEntries
                    .find((candidate) => readString(candidate, "id") === specId);
                if (entry === undefined) {
                    findings.push(createCrossArtifactFinding({
                        code: "CROSS_ARTIFACT_TRACEABILITY_DRIFT",
                        message: `Spec index is missing required entry '${specId}'.`,
                        severity: "error",
                        path: ".day-shift/specs/index.json"
                    }));
                    continue;
                }
                if (readString(entry, "destination") !== expectedDestination || readNestedString(entry, ["source", "ref"]) !== "root-spec.md") {
                    findings.push(createCrossArtifactFinding({
                        code: "CROSS_ARTIFACT_TRACEABILITY_DRIFT",
                        message: `Spec index entry '${specId}' must preserve destination '${expectedDestination}' and source.ref 'root-spec.md'.`,
                        severity: "error",
                        path: ".day-shift/specs/index.json"
                    }));
                }
            }
        }
    }
    return findings;
}
function runReviewHandoffChecks(repositoryRoot) {
    const findings = [];
    const enforceSourceOnlyContracts = isDayShiftSourceRepository(repositoryRoot);
    const promptManifestPath = ".day-shift/prompts/user/manifest.json";
    const promptManifest = readJsonObject(repositoryRoot, promptManifestPath, findings);
    if (promptManifest !== null) {
        requirePromptTemplateRefs(promptManifest, promptManifestPath, findings, ".day-shift/prompts/user/phase.next.md", [
            ".day-shift/templates/milestone-overview.md",
            ".day-shift/templates/milestone-reconciliation.md"
        ]);
        requirePromptTemplateRefs(promptManifest, promptManifestPath, findings, ".day-shift/prompts/user/milestone.next.md", [
            ".day-shift/templates/task-definition.md",
            ".day-shift/templates/implementation-summary.md"
        ]);
        requirePromptTemplateRefs(promptManifest, promptManifestPath, findings, ".day-shift/prompts/user/implementation.next.md", [
            ".day-shift/templates/milestone-reconciliation.md"
        ]);
        requirePromptTemplateRefs(promptManifest, promptManifestPath, findings, ".day-shift/prompts/user/reconciliation.build.md", [
            ".day-shift/templates/reconciliation.md"
        ]);
    }
    requireTextSnippets(repositoryRoot, findings, ".day-shift/specs/06-templates-and-prompts/prompts.md", [
        "implementation-summary.md` artifacts as the execution-evidence source of truth",
        "milestone `reconciliation.md` as the default downstream review rollup",
        "task-level reconciliation as an explicit exception path only"
    ], "CROSS_ARTIFACT_REVIEW_HANDOFF_DRIFT", {
        allowMissingInput: !enforceSourceOnlyContracts
    });
    requireTextSnippets(repositoryRoot, findings, ".day-shift/specs/05-planning-artifacts/artifact-model.md", [
        "Default review path: milestone-level reconciliation is the default review rollup path.",
        "Task-level reconciliation is an explicit exception"
    ], "CROSS_ARTIFACT_REVIEW_HANDOFF_DRIFT", {
        allowMissingInput: !enforceSourceOnlyContracts
    });
    requireTextSnippets(repositoryRoot, findings, ".day-shift/workflows/02-plan-from-spec.md", [
        "Preserve milestone-level reconciliation as the default review rollup path",
        "task-level reconciliation as an explicit exception path only"
    ], "CROSS_ARTIFACT_REVIEW_HANDOFF_DRIFT");
    return findings;
}
function runPlaceholderScaffoldingChecks(repositoryRoot) {
    const findings = [];
    const enforceSourceOnlyContracts = isDayShiftSourceRepository(repositoryRoot);
    requireTextSnippets(repositoryRoot, findings, ".day-shift/specs/06-templates-and-prompts/templates.md", [
        "Validation should use the canonical unresolved-token pattern `{{[a-z_][a-z0-9_]*}}`",
        "Saved artifacts should fail validation when unresolved placeholders or leaked scaffolding prose remain."
    ], "CROSS_ARTIFACT_PLACEHOLDER_CONTRACT_DRIFT", {
        allowMissingInput: !enforceSourceOnlyContracts
    });
    requireTextSnippets(repositoryRoot, findings, ".day-shift/workflows/02-plan-from-spec.md", [
        "No unresolved placeholder tokens remain",
        "Parser-sensitive formatting rules are enforced from prompt/workflow contract text rather than stored as instructional prose in artifact sections."
    ], "CROSS_ARTIFACT_PLACEHOLDER_CONTRACT_DRIFT");
    requireTextSnippets(repositoryRoot, findings, "tests_v2/init/template-contract.test.js", [
        "EXPECTED_SCAFFOLDING_STRINGS",
        "leaked scaffolding prose"
    ], "CROSS_ARTIFACT_PLACEHOLDER_CONTRACT_DRIFT", {
        allowMissingInput: !enforceSourceOnlyContracts
    });
    return findings;
}
function runNoWriteSurfaceChecks(repositoryRoot) {
    const findings = [];
    const enforceSourceOnlyContracts = isDayShiftSourceRepository(repositoryRoot);
    requireTextSnippets(repositoryRoot, findings, ".day-shift/workflows/01-start-here.md", [
        "validation smoke` are read-only findings or evidence surfaces",
        "advisory only and do not authorize writes"
    ], "CROSS_ARTIFACT_NO_WRITE_DRIFT");
    requireTextSnippets(repositoryRoot, findings, ".day-shift/workflows/workflow-guide.md", [
        "no-write state",
        "shared findings taxonomy"
    ], "CROSS_ARTIFACT_NO_WRITE_DRIFT");
    requireTextSnippets(repositoryRoot, findings, ".day-shift/specs/05-planning-artifacts/artifact-model.md", [
        "Metadata update-attempt and validate-update output should expose the selected family, surface mode, shared findings taxonomy, no-write state"
    ], "CROSS_ARTIFACT_NO_WRITE_DRIFT", {
        allowMissingInput: !enforceSourceOnlyContracts
    });
    return findings;
}
function requirePromptTemplateRefs(promptManifest, promptManifestPath, findings, promptPath, expectedRefs) {
    const entry = readObjectArray(promptManifest, "prompts")
        .find((candidate) => readString(candidate, "path") === promptPath);
    if (entry === undefined) {
        findings.push(createCrossArtifactFinding({
            code: "CROSS_ARTIFACT_REVIEW_HANDOFF_DRIFT",
            message: `Prompt manifest is missing review handoff entry '${promptPath}'.`,
            severity: "error",
            path: promptManifestPath
        }));
        return;
    }
    const observedRefs = readTemplateReferences(entry);
    for (const expectedRef of expectedRefs) {
        if (!observedRefs.includes(expectedRef)) {
            findings.push(createCrossArtifactFinding({
                code: "CROSS_ARTIFACT_REVIEW_HANDOFF_DRIFT",
                message: `Prompt manifest entry '${promptPath}' must reference '${expectedRef}' to preserve the implementation-summary/reconciliation handoff contract.`,
                severity: "error",
                path: promptManifestPath
            }));
        }
    }
}
function requireTextSnippets(repositoryRoot, findings, relativePath, snippets, code, options = {}) {
    const content = readRepositoryFile(repositoryRoot, relativePath);
    if (content === null) {
        if (options.allowMissingInput) {
            return;
        }
        findings.push(createCrossArtifactFinding({
            code: "CROSS_ARTIFACT_ALIGNMENT_INPUT_MISSING",
            message: `Cannot verify cross-artifact alignment because '${relativePath}' is missing.`,
            severity: "warning",
            path: relativePath
        }));
        return;
    }
    for (const snippet of snippets) {
        if (!content.includes(snippet)) {
            findings.push(createCrossArtifactFinding({
                code,
                message: `Expected cross-artifact contract text is missing from '${relativePath}': ${snippet}`,
                severity: "error",
                path: relativePath
            }));
        }
    }
}
function isDayShiftSourceRepository(repositoryRoot) {
    return node_fs_1.default.existsSync(node_path_1.default.join(repositoryRoot, "src", "cli", "index.ts"))
        && node_fs_1.default.existsSync(node_path_1.default.join(repositoryRoot, "src", "lib", "doctor", "index.ts"));
}
function readRepositoryFile(repositoryRoot, relativePath) {
    const absolutePath = node_path_1.default.join(repositoryRoot, relativePath);
    if (!node_fs_1.default.existsSync(absolutePath)) {
        return null;
    }
    return node_fs_1.default.readFileSync(absolutePath, "utf8");
}
function collectPlanningMarkdownArtifacts(currentPath, relativePath) {
    const artifacts = [];
    const entries = node_fs_1.default.readdirSync(currentPath, { withFileTypes: true });
    for (const entry of entries) {
        const entryPath = node_path_1.default.join(currentPath, entry.name);
        const entryRelativePath = (0, planning_document_utils_1.toRepositoryLikePath)(node_path_1.default.join(relativePath, entry.name));
        if (entry.isDirectory() && !entry.name.startsWith(".")) {
            artifacts.push(...collectPlanningMarkdownArtifacts(entryPath, entryRelativePath));
            continue;
        }
        if (entry.isFile() && entry.name.endsWith(".md")) {
            artifacts.push(entryRelativePath);
        }
    }
    return artifacts.sort((left, right) => left.localeCompare(right));
}
function readJsonObject(repositoryRoot, relativePath, findings) {
    const content = readRepositoryFile(repositoryRoot, relativePath);
    if (content === null) {
        findings.push(createCrossArtifactFinding({
            code: "CROSS_ARTIFACT_ALIGNMENT_INPUT_MISSING",
            message: `Cannot verify cross-artifact alignment because '${relativePath}' is missing.`,
            severity: "warning",
            path: relativePath
        }));
        return null;
    }
    try {
        const parsed = JSON.parse(content);
        if (isRecord(parsed)) {
            return parsed;
        }
    }
    catch {
        // Report malformed JSON through the shared alignment finding below.
    }
    findings.push(createCrossArtifactFinding({
        code: "CROSS_ARTIFACT_ALIGNMENT_INPUT_INVALID",
        message: `Cannot verify cross-artifact alignment because '${relativePath}' is not a JSON object.`,
        severity: "error",
        path: relativePath
    }));
    return null;
}
function readObjectArray(record, key) {
    const value = record[key];
    if (!Array.isArray(value)) {
        return [];
    }
    return value.filter(isRecord);
}
function readTemplateReferences(record) {
    const refs = [];
    const templateRef = readString(record, "template_ref");
    if (templateRef !== null) {
        refs.push(templateRef);
    }
    const templateRefs = record.template_refs;
    if (Array.isArray(templateRefs)) {
        refs.push(...templateRefs.filter((value) => typeof value === "string"));
    }
    return refs;
}
function readString(record, key) {
    const value = record[key];
    return typeof value === "string" ? value : null;
}
function readNestedString(record, pathParts) {
    let current = record;
    for (const pathPart of pathParts) {
        if (!isRecord(current)) {
            return null;
        }
        current = current[pathPart];
    }
    return typeof current === "string" ? current : null;
}
function isRecord(value) {
    return typeof value === "object" && value !== null && !Array.isArray(value);
}
function arraysEqual(left, right) {
    return left.length === right.length && left.every((value, index) => value === right[index]);
}
function statusFromFindings(findings) {
    if (findings.some((finding) => finding.severity === "error")) {
        return "error";
    }
    if (findings.some((finding) => finding.severity === "warning")) {
        return "warning";
    }
    if (findings.some((finding) => finding.severity === "informational")) {
        return "informational";
    }
    return "ok";
}
function createCrossArtifactFinding(finding) {
    return finding;
}
function loadPlanningValidationBaseline(repositoryRoot) {
    const baselinePath = PLANNING_VALIDATION_BASELINE_PATH;
    const absolutePath = node_path_1.default.join(repositoryRoot, baselinePath);
    if (!node_fs_1.default.existsSync(absolutePath)) {
        return {
            path: baselinePath,
            record: null,
            findingFingerprints: new Set(),
            inventoryFindingFingerprints: new Set(),
            gapFingerprints: new Set()
        };
    }
    try {
        const parsed = JSON.parse(node_fs_1.default.readFileSync(absolutePath, "utf8"));
        if (!isPlanningValidationBaselineRecord(parsed)) {
            return {
                path: baselinePath,
                record: null,
                findingFingerprints: new Set(),
                inventoryFindingFingerprints: new Set(),
                gapFingerprints: new Set()
            };
        }
        return {
            path: baselinePath,
            record: parsed,
            findingFingerprints: new Set(parsed.findings.map((finding) => finding.fingerprint)),
            inventoryFindingFingerprints: new Set(parsed.inventory_findings.map((finding) => finding.fingerprint)),
            gapFingerprints: new Set(parsed.gaps.map((gap) => gap.fingerprint))
        };
    }
    catch {
        return {
            path: baselinePath,
            record: null,
            findingFingerprints: new Set(),
            inventoryFindingFingerprints: new Set(),
            gapFingerprints: new Set()
        };
    }
}
function isPlanningValidationBaselineRecord(value) {
    return isRecord(value)
        && value.schema_version === 1
        && value.scope === "planning"
        && value.mode === "forward-only"
        && typeof value.created_at === "string"
        && Array.isArray(value.findings)
        && Array.isArray(value.inventory_findings)
        && Array.isArray(value.gaps);
}
function filterBaselineFindings(findings, baseline) {
    if (baseline.record === null) {
        return findings;
    }
    return findings.filter((finding) => !baseline.findingFingerprints.has(fingerprintFinding(finding)));
}
function filterBaselineInventoryFindings(findings, baseline) {
    if (baseline.record === null) {
        return findings;
    }
    return findings.filter((finding) => !baseline.inventoryFindingFingerprints.has(fingerprintInventoryFinding(finding)));
}
function filterBaselineGaps(gaps, baseline) {
    if (baseline.record === null) {
        return gaps;
    }
    return gaps.filter((gap) => !baseline.gapFingerprints.has(fingerprintGap(gap)));
}
function buildPlanningValidationBaselineEvidence(input) {
    return {
        path: input.loadedBaseline.path,
        present: input.loadedBaseline.record !== null,
        schemaVersion: input.loadedBaseline.record?.schema_version ?? null,
        createdAt: input.loadedBaseline.record?.created_at ?? null,
        mode: input.loadedBaseline.record?.mode ?? null,
        suppressedFindings: input.rawFindings.length - input.filteredFindings.length,
        suppressedInventoryFindings: input.rawInventoryFindings.length - input.filteredInventoryFindings.length,
        suppressedGaps: input.rawGaps.length - input.filteredGaps.length
    };
}
function applyPlanningValidationBaselineToChecks(input) {
    if (!input.baselineEvidence.present) {
        return input.checks;
    }
    return input.checks.map((check) => {
        switch (check.id) {
            case "planning-artifact-metadata":
                return applyFindingBaselineToCheck(check, input.rawFindings, input.filteredFindings, (finding) => finding.code.startsWith("ARTIFACT_"));
            case "planning-cli-provenance":
                return applyFindingBaselineToCheck(check, input.rawFindings, input.filteredFindings, (finding) => finding.code.startsWith("PLANNING_WORKFLOW_PROVENANCE_"));
            case "lightweight-artifact-strictness":
                return applyFindingBaselineToCheck(check, input.rawFindings, input.filteredFindings, (finding) => finding.code.startsWith("LIGHTWEIGHT_"));
            case "planning-inventory":
                if (input.rawInventoryFindings.length > 0 && input.filteredInventoryFindings.length === 0) {
                    return {
                        ...check,
                        status: "ok",
                        message: `All ${input.rawInventoryFindings.length} planning inventory finding${input.rawInventoryFindings.length === 1 ? "" : "s"} are covered by the forward-only validation baseline.`
                    };
                }
                return input.filteredInventoryFindings.length > 0
                    ? {
                        ...check,
                        status: "warning",
                        message: `Found ${input.filteredInventoryFindings.length} new planning inventory finding${input.filteredInventoryFindings.length === 1 ? "" : "s"} beyond the forward-only validation baseline.`
                    }
                    : check;
            case "planning-gap-report":
                if (input.rawGaps.length > 0 && input.filteredGaps.length === 0) {
                    return {
                        ...check,
                        status: "ok",
                        message: `All ${input.rawGaps.length} planning gap${input.rawGaps.length === 1 ? "" : "s"} are covered by the forward-only validation baseline.`
                    };
                }
                return input.filteredGaps.length > 0
                    ? {
                        ...check,
                        status: "warning",
                        message: `Found ${input.filteredGaps.length} new planning gap${input.filteredGaps.length === 1 ? "" : "s"} beyond the forward-only validation baseline.`
                    }
                    : check;
            case "cross-artifact-alignment":
                return applyFindingBaselineToCheck(check, input.rawFindings, input.filteredFindings, (finding) => finding.code.startsWith("CROSS_ARTIFACT_"));
            default:
                return check;
        }
    });
}
function applyFindingBaselineToCheck(check, rawFindings, filteredFindings, predicate) {
    const rawCount = rawFindings.filter(predicate).length;
    const filtered = filteredFindings.filter(predicate);
    if (rawCount > 0 && filtered.length === 0) {
        return {
            ...check,
            status: "ok",
            message: `All ${rawCount} ${check.id} finding${rawCount === 1 ? "" : "s"} are covered by the forward-only validation baseline.`
        };
    }
    if (filtered.length > 0) {
        return {
            ...check,
            status: statusFromFindings(filtered),
            message: `Found ${filtered.length} new ${check.id} finding${filtered.length === 1 ? "" : "s"} beyond the forward-only validation baseline.`
        };
    }
    return check;
}
function fingerprintFinding(finding) {
    return stableFingerprint({
        kind: "finding",
        code: finding.code,
        severity: finding.severity,
        path: finding.path ?? null,
        message: finding.message
    });
}
function fingerprintInventoryFinding(message) {
    return stableFingerprint({
        kind: "inventory-finding",
        message
    });
}
function fingerprintGap(gap) {
    return stableFingerprint({
        kind: "planning-gap",
        code: gap.code,
        path: gap.path,
        message: gap.message
    });
}
function stableFingerprint(value) {
    return Buffer.from(JSON.stringify(value)).toString("base64url");
}
function derivePlanningValidationSmokeStatus(input) {
    if (input.checks.some((check) => check.status === "error")) {
        return "blocked";
    }
    if (input.checks.some((check) => check.status === "warning")
        || input.inventoryFindings.length > 0
        || input.gaps.length > 0) {
        return "ready_with_warnings";
    }
    return "ready";
}
function derivePlanningValidationSmokeNextActions(input) {
    const actions = [];
    if (input.checks.some((check) => check.status === "error")) {
        actions.push("Repair blocking planning metadata or provenance findings before write-capable workflow steps.");
    }
    else if (input.gaps.length > 0 || input.inventoryFindings.length > 0) {
        actions.push("Review missing or stale paired planning artifacts before closeout or sync commands.");
    }
    else {
        actions.push("Planning smoke found no blocking issues in the current repository scope.");
    }
    if (input.nextAction?.command) {
        actions.push(`Artifact-specific next command: ${input.nextAction.command}`);
    }
    else if (input.nextAction !== null) {
        actions.push(`Artifact-specific next step: ${input.nextAction.recommendation}`);
    }
    else {
        actions.push("Use `day-shift planning next-action --artifact <path>` when you need artifact-specific guidance.");
    }
    return actions;
}
