"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.deriveTaskCycleRuntimeAttribution = deriveTaskCycleRuntimeAttribution;
exports.deriveTaskAttemptPathAttribution = deriveTaskAttemptPathAttribution;
exports.parsePorcelainStatus = parsePorcelainStatus;
exports.isProtectedAttributionPath = isProtectedAttributionPath;
exports.injectRuntimeAttributionSummaryFrontMatter = injectRuntimeAttributionSummaryFrontMatter;
exports.reviewTaskCycleRuntimeAttribution = reviewTaskCycleRuntimeAttribution;
exports.readSiblingOwnedRuntimeCriterionClaims = readSiblingOwnedRuntimeCriterionClaims;
exports.readRuntimeAttributionEvidence = readRuntimeAttributionEvidence;
const node_crypto_1 = require("node:crypto");
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const paths_1 = require("../../paths");
const declared_target_paths_1 = require("../../validation/declared-target-paths");
const documentation_path_classifier_1 = require("../../validation/documentation-path-classifier");
const artifact_policy_projection_1 = require("../artifact-policy-projection");
const planning_document_utils_1 = require("../planning-document-utils");
const runtime_acceptance_1 = require("../runtime-acceptance");
const semantic_evidence_1 = require("../semantic-evidence");
const task_lifecycle_1 = require("../task-lifecycle");
const baseline_planning_1 = require("./baseline-planning");
const contracts_1 = require("./contracts");
const predecessor_evidence_1 = require("./predecessor-evidence");
const repository_support_1 = require("./repository-support");
const serialization_1 = require("./serialization");
function deriveTaskCycleRuntimeAttribution(repositoryRoot, options) {
    const baseline = (0, baseline_planning_1.readPreferredRuntimeBaseline)(options.taskDefinitionPath, options.taskMarkdownText, options.summaryMarkdownText);
    if (baseline === null)
        return null;
    const sections = (0, planning_document_utils_1.parseMarkdownSections)(options.summaryMarkdownText);
    const changedPaths = (0, semantic_evidence_1.readChangedPaths)(sections.get("Changed Paths") ?? "");
    const executableValidation = (0, repository_support_1.readExecutableCommands)(sections.get("Validation Performed") ?? "");
    const acceptance = (0, runtime_acceptance_1.inspectRuntimeAcceptance)({
        artifactPath: options.taskDefinitionPath,
        artifactKind: "task",
        frontMatterLines: (0, planning_document_utils_1.parseMarkdownFrontMatter)(options.taskMarkdownText).frontMatterLines,
        markdownText: options.taskMarkdownText,
        requireExplicitForExecutableEvidence: true
    });
    const inheritedIds = acceptance.metadata?.criterionIds ?? [];
    const acceptanceResults = sections.get("Acceptance Criteria Results") ?? "";
    const satisfiedCriterionIds = inheritedIds.filter((criterionId) => acceptanceResults.includes(criterionId));
    const eligibleTargets = (0, baseline_planning_1.readEligibleRuntimeTargets)({
        taskDefinitionPath: options.taskDefinitionPath,
        taskMarkdownText: options.taskMarkdownText,
        summaryMarkdownText: options.summaryMarkdownText,
        baseline
    });
    const currentTargets = new Map(eligibleTargets.map((target) => [target.path, (0, predecessor_evidence_1.inspectTarget)(repositoryRoot, target.path, null)]));
    const declaredTargetEvidence = (0, declared_target_paths_1.readTaskDeclaredTargetPathEvidence)(options.taskDefinitionPath, options.taskMarkdownText).evidence;
    const freshRuntimePaths = [];
    const ineligiblePaths = [];
    for (const changedPath of changedPaths) {
        if (!(0, documentation_path_classifier_1.classifyDocumentationPath)(changedPath, {
            declaredTargetRole: (0, declared_target_paths_1.resolveDeclaredTargetPathRole)(declaredTargetEvidence, changedPath)
        }).runtimeEligible) {
            continue;
        }
        const baselineTarget = eligibleTargets.find((target) => (0, paths_1.pathsOverlap)(changedPath, target.path));
        if (baselineTarget === undefined) {
            ineligiblePaths.push(changedPath);
            continue;
        }
        const currentTarget = currentTargets.get(baselineTarget.path);
        const changedSinceBaseline = currentTarget !== undefined
            && (currentTarget.exists !== baselineTarget.exists
                || currentTarget.kind !== baselineTarget.kind
                || currentTarget.contentSha256 !== baselineTarget.contentSha256);
        if (changedSinceBaseline || baselineTarget.preExistingClassification === "adopted-pre-staged") {
            freshRuntimePaths.push(changedPath);
        }
        else {
            ineligiblePaths.push(changedPath);
        }
    }
    const currentRevision = (0, repository_support_1.runGit)(repositoryRoot, ["rev-parse", "--verify", "HEAD"]) ?? "unknown";
    return {
        schemaVersion: 1,
        baselineId: baseline.baselineId,
        taskCycleId: baseline.taskCycleId,
        checkpointId: baseline.checkpointId,
        sourceRevision: baseline.sourceRevision,
        currentRevision,
        freshRuntimePaths: (0, repository_support_1.unique)(freshRuntimePaths),
        executableValidation: (0, repository_support_1.unique)(executableValidation),
        satisfiedCriterionIds,
        adoptedPaths: baseline.declaredTargets
            .filter((target) => target.preExistingClassification === "adopted-pre-staged")
            .map((target) => ({ path: target.path, rationale: target.adoptionRationale })),
        acceptedPredecessorPaths: baseline.declaredTargets.flatMap((target) => target.preExistingClassification === "accepted-predecessor"
            && target.acceptedPredecessor !== null
            ? [{ path: target.path, ...target.acceptedPredecessor }]
            : []),
        ineligiblePaths: (0, repository_support_1.unique)(ineligiblePaths)
    };
}
function deriveTaskAttemptPathAttribution(repositoryRoot, options) {
    const projection = (0, task_lifecycle_1.projectTaskLifecyclePair)({
        taskDefinition: (0, serialization_1.removeFrontMatterBlock)(options.taskMarkdownText, contracts_1.BASELINE_BLOCK),
        implementationSummary: options.summaryMarkdownText
    });
    const currentAttempt = projection.summary?.currentAttempt ?? null;
    if (currentAttempt?.attemptId === null || currentAttempt?.attemptId === undefined
        || currentAttempt.readinessReviewId === null)
        return null;
    const baseline = (0, baseline_planning_1.readPreferredRuntimeBaseline)(options.taskDefinitionPath, options.taskMarkdownText, options.summaryMarkdownText);
    if (baseline === null)
        return null;
    const eligibleTargets = (0, baseline_planning_1.readEligibleRuntimeTargets)({
        taskDefinitionPath: options.taskDefinitionPath,
        taskMarkdownText: options.taskMarkdownText,
        summaryMarkdownText: options.summaryMarkdownText,
        baseline
    });
    let statusBytes;
    let observationsComplete = baseline.observationsComplete;
    try {
        statusBytes = (0, repository_support_1.readBoundedGitStatus)(repositoryRoot);
    }
    catch {
        statusBytes = Buffer.alloc(0);
        observationsComplete = false;
    }
    const currentRevision = (0, repository_support_1.runGit)(repositoryRoot, ["rev-parse", "--verify", "HEAD"]) ?? "unknown";
    if (!contracts_1.SOURCE_REVISION_PATTERN.test(currentRevision))
        observationsComplete = false;
    const statuses = parsePorcelainStatus(statusBytes);
    const classifications = [];
    const observedBaselinePaths = new Set();
    for (const status of statuses) {
        const baselineTarget = eligibleTargets.find((target) => (0, paths_1.pathsOverlap)(status.path, target.path)
            || (status.previousPath !== null && (0, paths_1.pathsOverlap)(status.previousPath, target.path)));
        if (baselineTarget !== undefined)
            observedBaselinePaths.add(baselineTarget.path);
        const declared = baselineTarget !== undefined;
        const protectedPath = isProtectedAttributionPath(status.path)
            || (status.previousPath !== null && isProtectedAttributionPath(status.previousPath));
        let classification;
        if (!observationsComplete) {
            classification = "uncertain_ownership";
        }
        else if (status.previousPath !== null) {
            classification = "renamed";
        }
        else if (!declared) {
            classification = "post_baseline_out_of_scope";
        }
        else if (status.code === "??") {
            classification = "new_untracked";
        }
        else {
            let current = null;
            try {
                current = (0, predecessor_evidence_1.inspectTarget)(repositoryRoot, baselineTarget.path, null);
            }
            catch {
                observationsComplete = false;
            }
            const unchangedFromBaseline = current !== null
                && current.exists === baselineTarget.exists
                && current.kind === baselineTarget.kind
                && current.contentSha256 === baselineTarget.contentSha256;
            const hasAttributedDirtyBaseline = baselineTarget.preExistingClassification === "accepted-predecessor"
                || baselineTarget.preExistingClassification === "adopted-pre-staged";
            if (current === null) {
                classification = "uncertain_ownership";
            }
            else if (unchangedFromBaseline) {
                classification = baselineTarget.preExistingClassification === "accepted-predecessor"
                    ? "accepted_predecessor"
                    : baselineTarget.preExistingClassification === "adopted-pre-staged"
                        ? "adopted_pre_staged"
                        : baselineTarget.dirty
                            ? "pre_existing"
                            : "task_associated";
            }
            else {
                classification = !baselineTarget.dirty || hasAttributedDirtyBaseline
                    ? "task_associated"
                    : "uncertain_ownership";
            }
        }
        classifications.push({
            path: status.path,
            previousPath: status.previousPath,
            classification,
            declared,
            protectedPath,
            deleted: status.code.includes("D"),
            repositoryStatus: status.code
        });
    }
    for (const target of eligibleTargets) {
        if (target.dirty && !observedBaselinePaths.has(target.path)) {
            classifications.push({
                path: target.path,
                previousPath: null,
                classification: "uncertain_ownership",
                declared: true,
                protectedPath: isProtectedAttributionPath(target.path),
                deleted: false,
                repositoryStatus: "baseline-dirty-now-unobserved"
            });
            observationsComplete = false;
        }
    }
    const currentTargets = eligibleTargets.map((target) => {
        try {
            return (0, predecessor_evidence_1.inspectTarget)(repositoryRoot, target.path, null);
        }
        catch {
            observationsComplete = false;
            return null;
        }
    });
    const currentWorkingTreeDigest = (0, repository_support_1.hashCanonical)({ currentRevision, targets: currentTargets });
    const currentStatusDigest = `sha256:${(0, node_crypto_1.createHash)("sha256").update(statusBytes).digest("hex")}`;
    const uncertain = classifications.some((entry) => entry.classification === "uncertain_ownership");
    const failed = classifications.some((entry) => entry.protectedPath || entry.classification === "post_baseline_out_of_scope");
    return {
        baselineId: baseline.baselineId,
        attemptId: currentAttempt.attemptId,
        readinessReviewId: currentAttempt.readinessReviewId,
        currentRevision,
        currentWorkingTreeDigest,
        currentStatusDigest,
        observationsComplete,
        classifications,
        scopeVerdict: !observationsComplete || uncertain ? "unknown" : failed ? "fail" : "pass"
    };
}
function parsePorcelainStatus(bytes) {
    const tokens = bytes.toString("utf8").split("\0").filter((entry) => entry !== "");
    const entries = [];
    for (let index = 0; index < tokens.length; index += 1) {
        const token = tokens[index];
        if (token.length < 4)
            continue;
        const code = token.slice(0, 2);
        const currentPath = token.slice(3);
        const renamed = code.includes("R") || code.includes("C");
        const previousPath = renamed ? tokens[index + 1] ?? null : null;
        if (renamed)
            index += 1;
        entries.push({ code, path: (0, planning_document_utils_1.toRepositoryLikePath)(currentPath), previousPath: previousPath === null ? null : (0, planning_document_utils_1.toRepositoryLikePath)(previousPath) });
    }
    return entries;
}
function isProtectedAttributionPath(candidate) {
    return candidate === ".git"
        || candidate.startsWith(".git/")
        || candidate === ".day-shift/state"
        || candidate.startsWith(".day-shift/state/")
        || candidate === ".day-shift/local"
        || candidate.startsWith(".day-shift/local/");
}
function injectRuntimeAttributionSummaryFrontMatter(summaryMarkdownText, evidence) {
    if (evidence === null)
        return (0, serialization_1.removeFrontMatterBlock)(summaryMarkdownText, contracts_1.SUMMARY_BLOCK);
    return (0, serialization_1.replaceFrontMatterBlock)(summaryMarkdownText, contracts_1.SUMMARY_BLOCK, (0, serialization_1.renderSummaryBlock)(evidence));
}
function reviewTaskCycleRuntimeAttribution(repositoryRoot, options) {
    const taskFrontMatter = (0, planning_document_utils_1.parseMarkdownFrontMatter)(options.taskMarkdownText).frontMatterLines;
    const executionMode = (0, artifact_policy_projection_1.projectArtifactPolicy)(options.taskMarkdownText).evidenceProfile;
    if (executionMode !== "runtime" && executionMode !== "hybrid")
        return [];
    if ((0, planning_document_utils_1.readTopLevelField)(taskFrontMatter, "runtime_attribution_required")?.trim() !== "true")
        return [];
    const issues = [];
    let baseline = null;
    try {
        baseline = (0, baseline_planning_1.readPreferredRuntimeBaseline)(options.taskDefinitionPath, options.taskMarkdownText, options.summaryMarkdownText);
    }
    catch (error) {
        return [error instanceof Error ? error.message : String(error)];
    }
    if (baseline === null) {
        return ["Runtime or hybrid closeout requires a structured post-readiness, pre-write baseline on the current attempt."];
    }
    const stored = readRuntimeAttributionEvidence(options.summaryMarkdownText);
    if (stored === null) {
        return ["Runtime or hybrid closeout requires structured runtime_attribution evidence on the paired implementation summary."];
    }
    const expected = deriveTaskCycleRuntimeAttribution(repositoryRoot, options);
    if (expected === null)
        return ["Unable to derive current-cycle runtime attribution from the stored baseline."];
    const declaredTargetEvidence = (0, declared_target_paths_1.readTaskDeclaredTargetPathEvidence)(options.taskDefinitionPath, options.taskMarkdownText).evidence;
    for (const key of ["baselineId", "taskCycleId", "checkpointId", "sourceRevision"]) {
        if (stored[key] !== expected[key]) {
            issues.push(`Implementation-summary runtime_attribution.${(0, repository_support_1.toSnakeCase)(key)} does not match the task baseline.`);
        }
    }
    if (!(0, repository_support_1.sameValues)(stored.freshRuntimePaths, expected.freshRuntimePaths)) {
        issues.push("Implementation-summary fresh_runtime_paths is stale or contradicts the current declared-target comparison.");
    }
    if (stored.freshRuntimePaths.length === 0) {
        issues.push("Runtime or hybrid closeout requires at least one freshly attributable runtime-eligible path.");
    }
    if (stored.freshRuntimePaths.some((entry) => !(0, documentation_path_classifier_1.classifyDocumentationPath)(entry, {
        declaredTargetRole: (0, declared_target_paths_1.resolveDeclaredTargetPathRole)(declaredTargetEvidence, entry)
    }).runtimeEligible)) {
        issues.push("Documentation-only paths cannot satisfy fresh_runtime_paths.");
    }
    if (!(0, repository_support_1.sameValues)(stored.executableValidation, expected.executableValidation)
        || stored.executableValidation.length === 0) {
        issues.push("Implementation-summary executable_validation must preserve concrete executed commands from Validation Performed.");
    }
    const acceptance = (0, runtime_acceptance_1.inspectRuntimeAcceptance)({
        artifactPath: options.taskDefinitionPath,
        artifactKind: "task",
        frontMatterLines: taskFrontMatter,
        markdownText: options.taskMarkdownText,
        requireExplicitForExecutableEvidence: true
    });
    const inheritedIds = acceptance.metadata?.criterionIds ?? [];
    const siblingOwnedClaims = readSiblingOwnedRuntimeCriterionClaims({
        repositoryRoot,
        taskFrontMatter,
        inheritedCriterionIds: inheritedIds,
        summaryMarkdownText: options.summaryMarkdownText
    });
    if (siblingOwnedClaims.length > 0) {
        issues.push(`Implementation-summary Acceptance Criteria Results claims parent runtime-acceptance IDs not assigned to this child: ${siblingOwnedClaims.join(", ")}.`);
    }
    if (!(0, repository_support_1.sameValues)(stored.satisfiedCriterionIds, inheritedIds)
        || !(0, repository_support_1.sameValues)(expected.satisfiedCriterionIds, inheritedIds)) {
        issues.push(`Implementation-summary satisfied_criterion_ids must exactly preserve every inherited runtime-acceptance ID: ${inheritedIds.join(", ") || "(none)"}.`);
    }
    if (!(0, repository_support_1.sameAdoptions)(stored.adoptedPaths, expected.adoptedPaths)) {
        issues.push("Implementation-summary adopted_paths does not preserve the baseline's per-path adoption evidence.");
    }
    if (!(0, repository_support_1.sameAcceptedPredecessorPaths)(stored.acceptedPredecessorPaths, expected.acceptedPredecessorPaths)) {
        issues.push("Implementation-summary accepted_predecessor_paths does not preserve the baseline's exact predecessor provenance.");
    }
    if (stored.ineligiblePaths.length > 0 || expected.ineligiblePaths.length > 0) {
        issues.push(`Changed Paths includes current-cycle-ineligible evidence: ${(0, repository_support_1.unique)([...stored.ineligiblePaths, ...expected.ineligiblePaths]).join(", ")}.`);
    }
    return (0, repository_support_1.unique)(issues);
}
function readSiblingOwnedRuntimeCriterionClaims(options) {
    const milestoneOverviewPath = (0, planning_document_utils_1.readUpstreamField)(options.taskFrontMatter, "milestone_overview")?.trim();
    if (milestoneOverviewPath === undefined || milestoneOverviewPath === "")
        return [];
    const parentAbsolutePath = node_path_1.default.join(options.repositoryRoot, milestoneOverviewPath);
    if (!node_fs_1.default.existsSync(parentAbsolutePath))
        return [];
    const parentText = node_fs_1.default.readFileSync(parentAbsolutePath, "utf8");
    const parentAcceptance = (0, runtime_acceptance_1.inspectRuntimeAcceptance)({
        artifactPath: milestoneOverviewPath,
        artifactKind: "milestone",
        frontMatterLines: (0, planning_document_utils_1.parseMarkdownFrontMatter)(parentText).frontMatterLines,
        markdownText: parentText,
        requireExplicitForExecutableEvidence: false
    });
    if (parentAcceptance.metadata === null)
        return [];
    const inherited = new Set(options.inheritedCriterionIds);
    const parentIds = new Set(parentAcceptance.metadata.criterionIds);
    const acceptanceResults = (0, planning_document_utils_1.parseMarkdownSections)(options.summaryMarkdownText)
        .get("Acceptance Criteria Results") ?? "";
    const claimedIds = [...acceptanceResults.matchAll(/\[([A-Za-z0-9]+(?:[._-][A-Za-z0-9]+)+)\]/gu)]
        .map((match) => match[1]);
    return (0, repository_support_1.unique)(claimedIds.filter((criterionId) => parentIds.has(criterionId) && !inherited.has(criterionId)));
}
function readRuntimeAttributionEvidence(markdownText) {
    const lines = (0, serialization_1.readFrontMatterBlock)((0, planning_document_utils_1.parseMarkdownFrontMatter)(markdownText).frontMatterLines, contracts_1.SUMMARY_BLOCK);
    if (lines === null)
        return null;
    const adoptedPaths = (0, serialization_1.readAdoptionList)(lines);
    return {
        schemaVersion: Number((0, serialization_1.readScalar)(lines, "schema_version") ?? "0"),
        baselineId: (0, serialization_1.readScalar)(lines, "baseline_id") ?? "",
        taskCycleId: (0, serialization_1.readScalar)(lines, "task_cycle_id") ?? "",
        checkpointId: (0, serialization_1.readScalar)(lines, "checkpoint_id") ?? "",
        sourceRevision: (0, serialization_1.readScalar)(lines, "source_revision") ?? "",
        currentRevision: (0, serialization_1.readScalar)(lines, "current_revision") ?? "",
        freshRuntimePaths: (0, serialization_1.readScalarList)(lines, "fresh_runtime_paths"),
        executableValidation: (0, serialization_1.readScalarList)(lines, "executable_validation"),
        satisfiedCriterionIds: (0, serialization_1.readScalarList)(lines, "satisfied_criterion_ids"),
        adoptedPaths,
        acceptedPredecessorPaths: (0, serialization_1.readAcceptedPredecessorList)(lines),
        ineligiblePaths: (0, serialization_1.readScalarList)(lines, "ineligible_paths")
    };
}
