"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildImplementationSummaryArtifact = buildImplementationSummaryArtifact;
exports.readImplementationSummaryTaskDefinitionSync = readImplementationSummaryTaskDefinitionSync;
// Responsibility-focused implementation extracted from the public compatibility facade.
const node_crypto_1 = require("node:crypto");
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const errors_1 = require("../../errors");
const mutation_preconditions_1 = require("../../filesystem/mutation-preconditions");
const repository_transaction_1 = require("../../filesystem/repository-transaction");
const declared_target_paths_1 = require("../../validation/declared-target-paths");
const task_scoped_change_report_1 = require("../../validation/task-scoped-change-report");
const artifact_policy_projection_1 = require("../artifact-policy-projection");
const front_matter_utils_1 = require("../front-matter-utils");
const build_1 = require("../reconciliation/build");
const task_cycle_runtime_attribution_1 = require("../task-cycle-runtime-attribution");
const context_1 = require("./context");
const document_paths_1 = require("./document-paths");
const document_rendering_1 = require("./document-rendering");
const renderers_1 = require("./renderers");
const DEFAULT_TASK_READ_ATTEMPTS = 3;
const TASK_READ_RETRY_DELAYS_MS = [5, 15];
function buildImplementationSummaryArtifact(repositoryRoot, options) {
    const taskDefinitionPath = (0, document_paths_1.resolveRepositoryPath)(repositoryRoot, options.taskDefinitionPath, "task-definition");
    const expectedTaskRevision = selectExpectedTaskRevision(taskDefinitionPath.relative, options.expectedTaskRevisions ?? []);
    let taskSnapshot;
    try {
        taskSnapshot = readImplementationSummaryTaskDefinitionSync(taskDefinitionPath.absolute, options.taskRead);
    }
    catch (error) {
        throw classifyTaskDefinitionReadFailure(taskDefinitionPath.relative, error, expectedTaskRevision, options.taskRead?.maxAttempts ?? DEFAULT_TASK_READ_ATTEMPTS);
    }
    assertExpectedTaskRevision(taskDefinitionPath.relative, taskSnapshot.revision, expectedTaskRevision);
    const taskDefinitionText = taskSnapshot.text;
    const taskDocument = (0, document_paths_1.parseMarkdownDocument)(taskDefinitionPath.relative, taskDefinitionText);
    (0, context_1.assertArtifactType)(taskDocument.frontMatterLines, taskDefinitionPath.relative, "task_definition");
    const taskPolicy = (0, artifact_policy_projection_1.projectArtifactPolicy)(taskDefinitionText);
    const topology = (0, renderers_1.requireImplementationSummaryWorkflowTopology)(taskDefinitionPath.relative, taskPolicy);
    const context = (0, context_1.parseTaskDefinitionContext)(taskDefinitionPath.relative, taskDocument);
    const implementationSummaryPath = (0, front_matter_utils_1.toRepositoryLikePath)(node_path_1.default.join(node_path_1.default.dirname(taskDefinitionPath.relative), "implementation-summary.md"));
    const implementationSummaryAbsolute = node_path_1.default.join(repositoryRoot, implementationSummaryPath);
    const existingSnapshot = readOptionalTextArtifactSnapshotSync(implementationSummaryAbsolute);
    const existingText = existingSnapshot?.text ?? null;
    const existingDocument = existingText === null
        ? null
        : (0, document_paths_1.parseMarkdownDocument)(implementationSummaryPath, existingText);
    if (existingDocument !== null) {
        (0, context_1.assertArtifactType)(existingDocument.frontMatterLines, implementationSummaryPath, "implementation_summary");
    }
    const metadata = (0, context_1.resolveSummaryMetadataState)(existingDocument, taskDefinitionPath.relative);
    const sections = (0, context_1.resolveImplementationSummarySectionValues)(existingDocument, metadata);
    const changedPathAuthoring = (0, document_paths_1.buildImplementationSummaryChangedPathAuthoring)(repositoryRoot, {
        taskDefinitionPath: taskDefinitionPath.relative,
        taskMarkdownText: taskDefinitionText,
        summaryMarkdownText: existingText
    });
    sections["Changed Paths"] = (0, document_paths_1.normalizeImplementationSummaryChangedPathsForBuild)(sections["Changed Paths"], changedPathAuthoring);
    let rendered = (0, document_rendering_1.renderImplementationSummaryDocument)(repositoryRoot, context, {
        metadata,
        sections,
        lifecycleLines: (0, document_rendering_1.resolveSummaryLifecycleLines)(existingDocument)
    });
    if ((0, context_1.hasConcreteImplementationSummaryCoreEvidence)(sections)) {
        rendered = (0, context_1.stripKnownImplementationSummaryAuthoringGuidance)(rendered);
    }
    rendered = (0, task_cycle_runtime_attribution_1.injectRuntimeAttributionSummaryFrontMatter)(rendered, (0, task_cycle_runtime_attribution_1.deriveTaskCycleRuntimeAttribution)(repositoryRoot, {
        taskDefinitionPath: taskDefinitionPath.relative,
        taskMarkdownText: taskDefinitionText,
        summaryMarkdownText: rendered
    }));
    const declaredTargetPathEvidence = (0, declared_target_paths_1.readTaskDeclaredTargetPathEvidence)(taskDefinitionPath.relative, taskDefinitionText);
    const completeTaskScopedChangeReport = (0, task_scoped_change_report_1.buildTaskScopedChangeReport)({
        statusLines: (0, renderers_1.collectGitStatusPorcelainLines)(repositoryRoot),
        declaredTargetEvidence: declaredTargetPathEvidence.evidence
    });
    const deviationsText = (0, document_paths_1.parseMarkdownDocument)(implementationSummaryPath, rendered)
        .sections.get("Deviations");
    const taskScopedChangeReport = (0, task_scoped_change_report_1.projectTaskScopedChangeReport)(completeTaskScopedChangeReport, completeTaskScopedChangeReport.unrelatedChangedPaths.filter((changedPath) => (0, document_paths_1.hasConcreteDeviationJustification)(deviationsText)
        && (0, document_paths_1.normalizePathEvidenceText)(deviationsText ?? "").includes(changedPath)));
    const changed = existingText !== rendered;
    const mutationPreconditions = buildImplementationSummaryMutationPreconditions({
        taskDefinitionPath,
        taskRevision: taskSnapshot.revision,
        implementationSummaryPath,
        implementationSummaryAbsolute,
        existingSummaryRevision: existingSnapshot?.revision ?? null
    });
    if (changed) {
        const transaction = (0, repository_transaction_1.executeRepositoryTransactionSync)(repositoryRoot, {
            writes: [{ path: implementationSummaryPath, contents: rendered }],
            preconditions: mutationPreconditions
        }, options.transaction);
        assertImplementationSummaryTransactionCommitted(transaction);
    }
    else {
        const validation = (0, mutation_preconditions_1.revalidateMutationPreconditionsSync)(mutationPreconditions);
        if (!validation.ok) {
            throw createImplementationSummaryConcurrencyError(validation.conflicts);
        }
    }
    return {
        repositoryRoot,
        taskDefinitionPath: taskDefinitionPath.relative,
        implementationSummaryPath,
        action: existingText === null ? "created" : "refreshed",
        changed,
        writeApplied: changed,
        commandWriteSummary: (0, build_1.normalizeCanonicalBuildCommandWriteSummary)({
            commandFamily: "implementation_summary",
            artifactPath: implementationSummaryPath,
            action: existingText === null ? "created" : "refreshed",
            changed,
            materialWhenChanged: true
        }),
        canonicalDestination: {
            sourcePath: taskDefinitionPath.relative,
            destinationPath: implementationSummaryPath,
            destinationKind: "task-implementation-summary",
            writeMode: "canonical-paired-artifact",
            writeApplied: changed,
            readOnly: false
        },
        reviewHandoff: {
            sourcePath: taskDefinitionPath.relative,
            destinationPath: implementationSummaryPath,
            handoffKind: "task-to-implementation-summary",
            defaultReviewRollup: topology.taskSummaryReviewBoundary,
            taskLevelReconciliation: "explicit-exception-only",
            workflowTopology: topology,
            taskSummaryReviewBoundary: topology.taskSummaryReviewBoundary,
            reconciliationArtifactKind: topology.reconciliationArtifactKind,
            reconciliationRequired: topology.reconciliationRequired,
            organizationParents: topology.organizationParents,
            projectReviewCapability: topology.projectReviewCapability
        },
        taskScopedChangeReport,
        changedPathAuthoring
    };
}
function readImplementationSummaryTaskDefinitionSync(absolutePath, options = {}) {
    const maxAttempts = options.maxAttempts ?? DEFAULT_TASK_READ_ATTEMPTS;
    if (!Number.isInteger(maxAttempts) || maxAttempts < 1 || maxAttempts > 8) {
        throw new TypeError("Implementation-summary task reads require 1-8 attempts.");
    }
    const operations = options.operations ?? node_fs_1.default;
    const waitSync = options.waitSync ?? waitForRetrySync;
    for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
        try {
            return readTextArtifactSnapshotFromDescriptorSync(absolutePath, operations);
        }
        catch (error) {
            if (!isTransientArtifactReadError(error) || attempt === maxAttempts)
                throw error;
            waitSync(TASK_READ_RETRY_DELAYS_MS[Math.min(attempt - 1, TASK_READ_RETRY_DELAYS_MS.length - 1)]);
        }
    }
    throw new Error("Implementation-summary task read exhausted without a terminal result.");
}
function readOptionalTextArtifactSnapshotSync(absolutePath) {
    try {
        return readTextArtifactSnapshotFromDescriptorSync(absolutePath, node_fs_1.default);
    }
    catch (error) {
        if (isNodeError(error) && error.code === "ENOENT")
            return null;
        throw error;
    }
}
function readTextArtifactSnapshotFromDescriptorSync(absolutePath, operations) {
    const descriptor = operations.openSync(absolutePath, "r");
    let snapshot = null;
    let failure = null;
    try {
        const stats = operations.fstatSync(descriptor);
        if (!stats.isFile()) {
            throw Object.assign(new Error(`Artifact '${absolutePath}' is not a regular file.`), {
                code: "EISDIR"
            });
        }
        const text = operations.readFileSync(descriptor, "utf8");
        snapshot = {
            text,
            revision: (0, node_crypto_1.createHash)("sha256").update(text).digest("hex")
        };
    }
    catch (error) {
        failure = error;
    }
    try {
        operations.closeSync(descriptor);
    }
    catch (error) {
        if (failure === null)
            failure = error;
    }
    if (failure !== null)
        throw failure;
    return snapshot;
}
function selectExpectedTaskRevision(taskDefinitionPath, bindings) {
    const matches = bindings.filter((binding) => binding.path === taskDefinitionPath);
    if (matches.length === 0)
        return null;
    const revisions = new Set(matches.map((binding) => normalizeTaskRevision(binding.revision)));
    if (revisions.size !== 1) {
        throw new errors_1.RuntimeError({
            message: `Lifecycle bindings disagree about the expected revision of '${taskDefinitionPath}'.`,
            code: "IMPLEMENTATION_SUMMARY_TASK_REVISION_BINDING_CONFLICT",
            exitCode: errors_1.RuntimeExitCode.STALE_EVIDENCE,
            details: matches.map((binding) => `${binding.source}: ${binding.revision}`),
            recoveryActions: [staleTaskRecoveryAction()]
        });
    }
    return {
        ...matches[0],
        revision: [...revisions][0]
    };
}
function normalizeTaskRevision(revision) {
    const normalized = revision.replace(/^sha256:/u, "");
    if (!/^[a-f0-9]{64}$/u.test(normalized)) {
        throw new TypeError("Expected task revisions must be lowercase SHA-256 identities.");
    }
    return normalized;
}
function assertExpectedTaskRevision(taskDefinitionPath, observedRevision, expected) {
    if (expected === null || observedRevision === expected.revision)
        return;
    throw new errors_1.RuntimeError({
        message: `Task definition '${taskDefinitionPath}' changed after lifecycle binding.`,
        code: "IMPLEMENTATION_SUMMARY_TASK_REVISION_STALE",
        exitCode: errors_1.RuntimeExitCode.STALE_EVIDENCE,
        details: [
            `bindingSource: ${expected.source}`,
            `expectedRevision: sha256:${expected.revision}`,
            `observedRevision: sha256:${observedRevision}`,
            "The implementation summary was not constructed or written."
        ],
        recoveryActions: [staleTaskRecoveryAction()]
    });
}
function buildImplementationSummaryMutationPreconditions(options) {
    const preconditions = [{
            kind: "content-revision",
            repositoryRelativePath: options.taskDefinitionPath.relative,
            runtimePath: options.taskDefinitionPath.absolute,
            expectedRevision: options.taskRevision
        }, {
            kind: "destination-presence",
            repositoryRelativePath: options.implementationSummaryPath,
            runtimePath: options.implementationSummaryAbsolute,
            expectedPresence: options.existingSummaryRevision === null ? "absent" : "present"
        }];
    if (options.existingSummaryRevision !== null) {
        preconditions.push({
            kind: "content-revision",
            repositoryRelativePath: options.implementationSummaryPath,
            runtimePath: options.implementationSummaryAbsolute,
            expectedRevision: options.existingSummaryRevision
        });
    }
    return preconditions;
}
function assertImplementationSummaryTransactionCommitted(transaction) {
    const cleanupFailure = transaction.cleanupErrors.length > 0
        ? transaction.cleanupErrors.join(" ")
        : null;
    if (transaction.outcome === "committed" && cleanupFailure === null)
        return;
    if (transaction.outcome === "conflict") {
        throw createImplementationSummaryConcurrencyError(transaction.conflicts);
    }
    const partial = transaction.outcome === "incomplete" || transaction.outcome === "committed";
    throw new errors_1.RuntimeError({
        message: partial
            ? "Implementation-summary publication left repository transaction state requiring recovery."
            : "Implementation-summary publication could not start its atomic repository transaction.",
        code: partial
            ? "IMPLEMENTATION_SUMMARY_TRANSACTION_INCOMPLETE"
            : "IMPLEMENTATION_SUMMARY_TRANSACTION_UNAVAILABLE",
        exitCode: partial ? errors_1.RuntimeExitCode.PARTIAL_MUTATION : errors_1.RuntimeExitCode.UNAVAILABLE_DEPENDENCY,
        details: [
            `transactionId: ${transaction.transactionId}`,
            `transactionOutcome: ${transaction.outcome}`,
            `recoveryPath: ${transaction.transactionPath}`,
            ...(transaction.failure === null ? [] : [`failure: ${transaction.failure}`]),
            ...(cleanupFailure === null ? [] : [`cleanupFailure: ${cleanupFailure}`])
        ],
        recoveryActions: [(0, errors_1.createNonCallableRecoveryAction)({
                id: "recovery.implementation-summary.inspect-repository-transaction",
                explanation: partial
                    ? `Inspect and recover repository transaction '${transaction.transactionId}' before another summary build.`
                    : "Resolve the repository transaction failure, verify the task revision, and retry the exact build once.",
                reason: "Recovery requires inspecting the retained transaction evidence and current canonical artifact revisions."
            })]
    });
}
function createImplementationSummaryConcurrencyError(conflicts) {
    return new errors_1.RuntimeError({
        message: "The task pair changed while the implementation summary was being constructed.",
        code: "IMPLEMENTATION_SUMMARY_ARTIFACT_CONCURRENCY_CONFLICT",
        exitCode: errors_1.RuntimeExitCode.CONCURRENCY_CONFLICT,
        details: [
            ...conflicts.map((conflict) => `${conflict.path}: expected ${conflict.expectedState}; observed ${conflict.observedState}`),
            "No stale implementation-summary bytes were published."
        ],
        recoveryActions: [staleTaskRecoveryAction()]
    });
}
function classifyTaskDefinitionReadFailure(taskDefinitionPath, error, expectedRevision, attempts) {
    const filesystemCode = isNodeError(error) && typeof error.code === "string"
        ? error.code
        : "UNKNOWN";
    if (filesystemCode === "ENOENT" && expectedRevision === null) {
        return (0, errors_1.createUsageError)(`Task definition is not present at '${taskDefinitionPath}'.`, [
            `filesystemCode: ${filesystemCode}`,
            `readAttempts: ${attempts}`,
            "Pass an existing repository-relative --task-definition path."
        ]);
    }
    const permissionFailure = filesystemCode === "EACCES" || filesystemCode === "EPERM";
    const transientOrStale = filesystemCode === "ENOENT" || filesystemCode === "EIO";
    return new errors_1.RuntimeError({
        message: transientOrStale
            ? `Task definition '${taskDefinitionPath}' was transiently unavailable or stale during summary construction.`
            : `Task definition '${taskDefinitionPath}' could not be read for summary construction.`,
        code: transientOrStale
            ? "IMPLEMENTATION_SUMMARY_TASK_ARTIFACT_TRANSIENT"
            : permissionFailure
                ? "IMPLEMENTATION_SUMMARY_TASK_ARTIFACT_PERMISSION_DENIED"
                : "IMPLEMENTATION_SUMMARY_TASK_ARTIFACT_UNAVAILABLE",
        exitCode: transientOrStale
            ? errors_1.RuntimeExitCode.STALE_EVIDENCE
            : permissionFailure
                ? errors_1.RuntimeExitCode.PERMISSION_FAILURE
                : errors_1.RuntimeExitCode.UNAVAILABLE_DEPENDENCY,
        details: [
            `filesystemCode: ${filesystemCode}`,
            `readAttempts: ${attempts}`,
            ...(expectedRevision === null
                ? []
                : [`expectedRevision: sha256:${expectedRevision.revision}`, `bindingSource: ${expectedRevision.source}`]),
            error instanceof Error ? error.message : String(error),
            "No implementation-summary bytes were written."
        ],
        recoveryActions: transientOrStale ? [staleTaskRecoveryAction()] : [],
        cause: error
    });
}
function staleTaskRecoveryAction() {
    return (0, errors_1.createNonCallableRecoveryAction)({
        id: "recovery.implementation-summary.refresh-task-revision",
        command: "implementation-summary build",
        explanation: "Verify the canonical task bytes and lifecycle-bound revision, serialize planning writers, then retry the exact build once.",
        reason: "The shared error boundary cannot prove filesystem stability or reconstruct the caller's exact lifecycle binding."
    });
}
function isTransientArtifactReadError(error) {
    return isNodeError(error) && (error.code === "ENOENT" || error.code === "EIO");
}
function isNodeError(error) {
    return error instanceof Error && "code" in error;
}
function waitForRetrySync(delayMs) {
    Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, delayMs);
}
