"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.runPlanningValidationSmoke = runPlanningValidationSmoke;
exports.createPlanningValidationRepositoryWideGate = createPlanningValidationRepositoryWideGate;
exports.isPlanningNavigationArtifact = isPlanningNavigationArtifact;
exports.renderPlanningValidationSmokeReport = renderPlanningValidationSmokeReport;
exports.writePlanningValidationBaseline = writePlanningValidationBaseline;
// Doctor report contracts, scoped execution, rendering, and validation rollup orchestration.
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 cli_invocation_1 = require("../runtime/cli-invocation");
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_report_1 = require("../validation/validation-links-report");
const planning_checks_1 = require("./planning-checks");
const action_relevance_1 = require("./action-relevance");
const contracts_1 = require("./contracts");
const runtime_reporting_1 = require("./runtime-reporting");
const validation_checks_1 = require("./validation-checks");
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 = (0, validation_checks_1.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 discoveredGaps = (0, planning_navigation_1.gapReportPlanning)({
        repositoryRoot: repositoryContext.root,
        scopePath: validationEvidenceScopePath,
    }).gaps;
    const { gaps, expectedChildGaps } = classifyFocusedParentOnlyCreationGaps({
        repositoryRoot: repositoryContext.root,
        selectedArtifactPath: planningNavigationArtifactPath,
        gaps: discoveredGaps,
    });
    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 && expectedChildGaps.length > 0 ? 'informational' : (0, validation_checks_1.statusFromPlanningGaps)(gaps),
        message: gaps.length > 0
            ? `Found ${gaps.length} expected-versus-observed planning gap${gaps.length === 1 ? '' : 's'}.`
            : expectedChildGaps.length > 0
                ? `Deferred ${expectedChildGaps.length} direct missing-child gap${expectedChildGaps.length === 1 ? '' : 's'} for the completed layer-local parent scaffold.`
                : 'Planning gap report did not find missing or incomplete downstream artifacts.',
    });
    const linksCheckReport = planningNavigationArtifactPath === null
        ? null
        : (0, validation_links_report_1.runValidationLinksCheckReport)({
            repositoryRoot: repositoryContext.root,
            artifactPath: planningNavigationArtifactPath,
        });
    if (linksCheckReport !== null) {
        checks.push({
            id: 'validation-links-check',
            status: (0, validation_checks_1.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 = (0, validation_checks_1.runCrossArtifactAlignmentSmoke)(repositoryContext.root, options.artifactPath);
    const crossArtifactFindings = crossArtifactAlignment.lanes.flatMap((lane) => [...lane.findings]);
    const crossArtifactStatus = (0, validation_checks_1.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(validation_checks_1.validationFindingFromPlanningGap), ...(linksCheckReport?.findings ?? []), ...crossArtifactFindings);
    const rawFindings = [...findings];
    const filteredFindings = (0, validation_checks_1.filterBaselineFindings)(rawFindings, loadedBaseline);
    const filteredInventoryFindings = (0, validation_checks_1.filterBaselineInventoryFindings)(inventory.findings, loadedBaseline);
    const filteredGaps = (0, validation_checks_1.filterBaselineGaps)(gaps, loadedBaseline);
    findings.length = 0;
    findings.push(...filteredFindings);
    const baselineEvidence = (0, validation_checks_1.buildPlanningValidationBaselineEvidence)({
        loadedBaseline,
        rawFindings,
        filteredFindings,
        rawInventoryFindings: inventory.findings,
        filteredInventoryFindings,
        rawGaps: gaps,
        filteredGaps,
    });
    const effectiveChecks = (0, validation_checks_1.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 = (0, validation_checks_1.derivePlanningValidationSmokeNextActions)({
        checks: effectiveChecks,
        inventoryFindings: filteredInventoryFindings,
        gaps: filteredGaps,
        nextAction,
    });
    const summary = (0, runtime_reporting_1.summarizeDoctorEvidence)(effectiveChecks, findings);
    const readinessStatus = (0, validation_checks_1.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: (0, cli_invocation_1.renderDayShiftCliCommand)(`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: (0, runtime_reporting_1.getValidationRollupEvidenceSourceInventory)(),
        specializedReviewBoundaries: (0, runtime_reporting_1.getValidationRollupSpecializedBoundaries)(),
        aggregationContract: (0, runtime_reporting_1.getValidationRollupAggregationContract)(),
        checks: effectiveChecks,
        findings,
        inventoryFindings: filteredInventoryFindings,
        crossArtifactAlignment,
        baseline: baselineEvidence,
        gaps: filteredGaps,
        expectedChildGaps,
        nextActions,
        nextAction,
        summary,
        readinessStatus,
        actionRelevance,
    };
}
function classifyFocusedParentOnlyCreationGaps(options) {
    if (options.selectedArtifactPath === null) {
        return { gaps: options.gaps, expectedChildGaps: [] };
    }
    const content = (0, validation_checks_1.readRepositoryFile)(options.repositoryRoot, options.selectedArtifactPath);
    if (content === null) {
        return { gaps: options.gaps, expectedChildGaps: [] };
    }
    const artifactType = readFrontMatterScalar(content, 'artifact_type');
    const status = readFrontMatterScalar(content, 'status');
    const workflowLevel = readFrontMatterScalar(content, 'workflow_level');
    const workflowCommand = readFrontMatterScalar(content, 'workflow_cli_command')?.replace(/^['"]|['"]$/g, '') ?? null;
    const parentCommand = artifactType === 'slice_overview'
        ? 'slice'
        : artifactType === 'phase_overview'
            ? 'phase'
            : artifactType === 'milestone_overview'
                ? 'milestone'
                : null;
    const isStructuredWorkOverview = artifactType === 'work_overview' && workflowLevel === 'structured';
    if (status !== 'draft' ||
        !(isStructuredWorkOverview ||
            (parentCommand !== null &&
                workflowCommand !== null &&
                new RegExp(`^(?:day-shift|node dist/cli/index\\.js) ${parentCommand} new(?:\\s|$)`).test(workflowCommand)))) {
        return { gaps: options.gaps, expectedChildGaps: [] };
    }
    const parentDirectory = node_path_1.default.posix.dirname(options.selectedArtifactPath);
    const isDirectMissingChild = (gap) => {
        if (gap.code !== 'MISSING_ARTIFACT')
            return false;
        if (node_fs_1.default.existsSync(node_path_1.default.join(options.repositoryRoot, node_path_1.default.posix.dirname(gap.path))))
            return false;
        const relativePath = node_path_1.default.posix.relative(parentDirectory, gap.path);
        if (artifactType === 'slice_overview') {
            return /^phases\/[^/]+\/(?:phase-overview|overview)\.md$/.test(relativePath);
        }
        if (artifactType === 'phase_overview') {
            return /^milestones\/[^/]+\/(?:milestone-overview|overview)\.md$/.test(relativePath);
        }
        return (artifactType === 'milestone_overview' || isStructuredWorkOverview) &&
            /^tasks\/[^/]+\/task-definition\.md$/.test(relativePath);
    };
    return {
        gaps: options.gaps.filter((gap) => !isDirectMissingChild(gap)),
        expectedChildGaps: options.gaps.filter(isDirectMissingChild),
    };
}
function readFrontMatterScalar(markdown, key) {
    const frontMatter = markdown.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/)?.[1] ?? '';
    const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    const value = frontMatter.match(new RegExp(`^${escapedKey}:\\s*(.+?)\\s*$`, 'm'))?.[1].trim();
    return value === undefined || value === '' ? null : value.replace(/^['"]|['"]$/g, '');
}
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
            ? (0, cli_invocation_1.renderDayShiftCliCommand)(`doctor --repository-audit --action ${JSON.stringify(descriptor.command)} --format json --detail full`)
            : null,
    };
}
function isPlanningNavigationArtifact(repositoryRoot, selectedArtifactPath) {
    const content = (0, validation_checks_1.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 = contracts_1.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: (0, validation_checks_1.fingerprintFinding)(finding),
                code: finding.code,
                severity: finding.severity,
                path: finding.path ?? null,
                message: finding.message,
            })),
            inventory_findings: report.inventoryFindings.map((message) => ({
                fingerprint: (0, validation_checks_1.fingerprintInventoryFinding)(message),
                message,
            })),
            gaps: report.gaps.map((gap) => ({
                fingerprint: (0, validation_checks_1.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 });
        }
    }
}
