"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BasicTaskCreationError = void 0;
exports.previewBasicTaskPairCreationSync = previewBasicTaskPairCreationSync;
exports.applyBasicTaskPairCreationSync = applyBasicTaskPairCreationSync;
const node_path_1 = __importDefault(require("node:path"));
const mutation_preconditions_1 = require("../filesystem/mutation-preconditions");
const repository_transaction_1 = require("../filesystem/repository-transaction");
const canonical_write_target_1 = require("../paths/canonical-write-target");
const ordered_root_identity_1 = require("../planning/ordered-root-identity");
const policy_resolution_1 = require("../planning/policy-resolution");
class BasicTaskCreationError extends Error {
    code;
    constructor(code, message) {
        super(message);
        this.name = "BasicTaskCreationError";
        this.code = code;
    }
}
exports.BasicTaskCreationError = BasicTaskCreationError;
const TASK_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
const plans = new WeakMap();
function previewBasicTaskPairCreationSync(request) {
    const repositoryRoot = requireText(request.repositoryRoot, "Repository root");
    const task = normalizeTask(request.task);
    const createdAt = normalizeTimestamp(request.createdAt ?? new Date().toISOString());
    const inventoryCollectionPath = ".day-shift/planning/basic/tasks";
    let inventory;
    let allocation;
    try {
        inventory = (0, ordered_root_identity_1.inspectOrderedRootCollectionSync)({
            repositoryRoot,
            collectionPath: inventoryCollectionPath,
            context: "basic-root"
        });
        allocation = (0, ordered_root_identity_1.allocateOrderedRoot)({
            context: "basic-root",
            stableId: task.taskId,
            requestedOrder: request.implementationOrder,
            inventory
        });
    }
    catch (error) {
        throw normalizeOrderedRootError(error);
    }
    const taskRoot = node_path_1.default.posix.join(inventoryCollectionPath, allocation.orderedRootName);
    const taskTarget = (0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, node_path_1.default.posix.join(taskRoot, "task-definition.md"));
    const summaryTarget = (0, canonical_write_target_1.resolveCanonicalWriteTargetSync)(repositoryRoot, node_path_1.default.posix.join(taskRoot, "implementation-summary.md"));
    if (taskTarget.exists || summaryTarget.exists) {
        throw new BasicTaskCreationError("destination-conflict", `Basic task '${task.taskId}' already has a canonical pair destination.`);
    }
    const policy = (0, policy_resolution_1.resolveIndependentTaskPolicy)({
        agentMode: {
            ...request.agentModeResolution,
            task: task.agentMode
        },
        evidenceProfile: {
            ...request.evidenceProfileResolution,
            task: task.evidenceProfile
        }
    });
    const preconditions = [
        (0, mutation_preconditions_1.captureDestinationPresencePreconditionSync)(taskTarget),
        (0, mutation_preconditions_1.captureDestinationPresencePreconditionSync)(summaryTarget)
    ];
    const writes = [
        {
            path: taskTarget.repositoryRelativePath,
            contents: renderBasicTaskDefinition({
                task,
                createdAt,
                implementationOrder: allocation.implementationOrder,
                agentMode: policy.agentMode.value,
                evidenceProfile: policy.evidenceProfile.value
            })
        },
        {
            path: summaryTarget.repositoryRelativePath,
            contents: renderBasicImplementationSummary({
                task,
                taskDefinitionPath: taskTarget.repositoryRelativePath,
                implementationOrder: allocation.implementationOrder,
                agentMode: policy.agentMode.value,
                evidenceProfile: policy.evidenceProfile.value
            })
        }
    ];
    const result = {
        workflowLevel: "basic",
        taskId: task.taskId,
        title: task.title,
        implementationOrder: allocation.implementationOrder,
        implementationOrderSource: allocation.implementationOrderSource,
        orderedRootName: allocation.orderedRootName,
        rootInventoryFingerprint: inventory.fingerprint,
        agentMode: policy.agentMode.value,
        agentModeSource: policy.agentMode.source,
        evidenceProfile: policy.evidenceProfile.value,
        evidenceProfileSource: policy.evidenceProfile.source,
        taskDefinitionPath: taskTarget.repositoryRelativePath,
        implementationSummaryPath: summaryTarget.repositoryRelativePath,
        expected: preconditions.map((precondition) => ({
            path: precondition.repositoryRelativePath,
            kind: "destination-presence",
            expectedState: "absent"
        })),
        intendedPaths: writes.map((write) => write.path),
        changedPaths: [],
        writeOutcome: "previewed",
        transactionId: null,
        conflicts: [],
        recoveryPath: null,
        failure: null,
        nextAction: "Apply this preview to create the parentless Basic task pair."
    };
    plans.set(result, {
        repositoryRoot: node_path_1.default.resolve(repositoryRoot),
        writes,
        preconditions,
        inventoryCollectionPath,
        inventoryFingerprint: inventory.fingerprint
    });
    return result;
}
function applyBasicTaskPairCreationSync(preview, options = {}) {
    const plan = plans.get(preview);
    if (plan === undefined || preview.writeOutcome !== "previewed") {
        throw new BasicTaskCreationError("stale-preview", "Basic task-pair apply requires the original unused in-process preview. Refresh the preview.");
    }
    plans.delete(preview);
    let currentFingerprint;
    try {
        currentFingerprint = (0, ordered_root_identity_1.inspectOrderedRootCollectionSync)({
            repositoryRoot: plan.repositoryRoot,
            collectionPath: plan.inventoryCollectionPath,
            context: "basic-root"
        }).fingerprint;
    }
    catch {
        currentFingerprint = "invalid-inventory";
    }
    if (currentFingerprint !== plan.inventoryFingerprint) {
        return {
            ...preview,
            writeOutcome: "conflict",
            conflicts: [inventoryConflict(plan.inventoryCollectionPath, plan.inventoryFingerprint, currentFingerprint)],
            nextAction: "Refresh the Basic creation preview after the root allocation inventory changed."
        };
    }
    const transaction = (0, repository_transaction_1.executeRepositoryTransactionSync)(plan.repositoryRoot, { writes: plan.writes, preconditions: plan.preconditions }, options.transaction);
    return {
        ...preview,
        changedPaths: transaction.entries
            .slice(0, transaction.canonicalWrites)
            .map((entry) => entry.path),
        writeOutcome: transaction.outcome,
        transactionId: transaction.transactionId,
        conflicts: transaction.conflicts,
        recoveryPath: transaction.outcome === "incomplete" ? transaction.transactionPath : null,
        failure: transaction.failure,
        nextAction: transaction.outcome === "committed"
            ? "Run the read-only readiness review, then explicitly authorize readiness before implementation."
            : transaction.outcome === "conflict"
                ? "Refresh the Basic creation preview after inspecting current destination evidence."
                : transaction.outcome === "incomplete"
                    ? "Inspect retained transaction evidence before retrying or recovering."
                    : "Refresh the Basic creation preview; no canonical write was required."
    };
}
function normalizeTask(input) {
    if (input === null || typeof input !== "object" || Array.isArray(input)) {
        throw new BasicTaskCreationError("invalid-request", "Basic task input must be an object.");
    }
    const taskId = requireText(input.taskId, "Basic task id");
    if (!TASK_ID_PATTERN.test(taskId)) {
        throw new BasicTaskCreationError("invalid-request", `Basic task id '${taskId}' must be lowercase kebab-case.`);
    }
    return {
        ...input,
        taskId,
        title: optionalText(input.title) ?? titleFromSlug(taskId),
        objective: requireText(input.objective, "Basic task objective"),
        targetPaths: requirePathList(input.targetPaths, "Basic task targetPaths", true),
        currentBehavior: optionalText(input.currentBehavior)
            ?? "The requested Basic task outcome is not implemented yet.",
        desiredBehavior: requireText(input.desiredBehavior, "Basic task desiredBehavior"),
        acceptanceCriteria: requireStringList(input.acceptanceCriteria, "Basic task acceptanceCriteria", true),
        validationCommands: requireStringList(input.validationCommands, "Basic task validationCommands", true),
        rollbackRecovery: requireText(input.rollbackRecovery, "Basic task rollbackRecovery"),
        dependencies: requirePathList(input.dependencies ?? [], "Basic task dependencies", false),
        constraints: requireStringList(input.constraints ?? [], "Basic task constraints", false)
    };
}
function renderBasicTaskDefinition(input) {
    const task = input.task;
    const runtimeRequired = input.evidenceProfile === "runtime" || input.evidenceProfile === "hybrid";
    const criterionIds = task.acceptanceCriteria.map((_, index) => criterionId(task.taskId, index));
    const runtimeDelta = [
        `- Runtime target files: ${task.targetPaths.map((value) => `\`${value}\``).join(", ")}.`,
        `- Expected behavior change: ${task.desiredBehavior}`,
        `- Verification commands with expected evidence: ${task.validationCommands.map((value) => `\`${value}\``).join(", ")}.`,
        `- Rollback path: ${task.rollbackRecovery}`
    ];
    return [
        "---",
        "artifact_schema_version: 1",
        "artifact_type: task_definition",
        `id: ${yamlString(task.taskId)}`,
        `task: ${yamlString(task.taskId)}`,
        `implementation_order: ${yamlString(input.implementationOrder)}`,
        "workflow_level: basic",
        "planning_depth: standard",
        `agent_mode: ${yamlString(input.agentMode)}`,
        `evidence_profile: ${yamlString(input.evidenceProfile)}`,
        `runtime_attribution_required: ${runtimeRequired}`,
        `created_at: ${yamlString(input.createdAt)}`,
        `updated_at: ${yamlString(input.createdAt)}`,
        "readiness: needs_more_evidence",
        "status: draft",
        "workflow_provenance: cli",
        `workflow_cli_command: ${yamlString(`day-shift work create --level basic --implementation-order ${input.implementationOrder} --task-id ${task.taskId}`)}`,
        "runtime_acceptance:",
        `  required: ${runtimeRequired}`,
        ...(runtimeRequired
            ? ["  criterion_ids:", ...criterionIds.map((id) => `    - ${id}`)]
            : ["  criterion_ids: []"]),
        "---",
        "",
        `# ${task.title}`,
        "",
        "## Upstream Context",
        "",
        "- None. Basic work is an independent task pair with no upstream planning parent.",
        "",
        "## Objective",
        "",
        task.objective,
        "",
        "## Implementation Target Paths",
        "",
        ...bulletList(task.targetPaths),
        "",
        "## Current Behavior",
        "",
        task.currentBehavior,
        "",
        "## Desired Behavior",
        "",
        task.desiredBehavior,
        "",
        "## Runtime Delta",
        "",
        ...runtimeDelta,
        "",
        "## Acceptance Criteria",
        "",
        ...task.acceptanceCriteria.map((criterion, index) => `- [${criterionIds[index]}] ${criterion}`),
        "",
        "## Validation Commands",
        "",
        "```sh",
        ...task.validationCommands,
        "```",
        "",
        "## Rollback / Recovery",
        "",
        task.rollbackRecovery,
        "",
        "## Risks",
        "",
        "- The independent Basic boundary must remain valid throughout implementation.",
        "",
        "## Dependencies",
        "",
        ...(task.dependencies.length === 0 ? ["- None."] : bulletList(task.dependencies)),
        "",
        "## Constraints",
        "",
        ...(task.constraints.length === 0 ? ["- None."] : bulletList(task.constraints)),
        "",
        "## Assumptions",
        "",
        "- Target paths, sequencing, and dependencies are resolved for one independent task.",
        "",
        "## Lifecycle / Closure Expectations",
        "",
        "Use the shared readiness, attempt, baseline, validation, review, disposition, and close commands; no Basic-specific lifecycle shortcut is authorized.",
        "",
        "## Open Questions",
        "",
        "- None currently.",
        ""
    ].join("\n");
}
function renderBasicImplementationSummary(input) {
    const runtimeRequired = input.evidenceProfile === "runtime" || input.evidenceProfile === "hybrid";
    const criterionIds = input.task.acceptanceCriteria.map((_, index) => criterionId(input.task.taskId, index));
    return [
        "---",
        "artifact_schema_version: 1",
        "artifact_type: implementation_summary",
        `id: ${yamlString(input.task.taskId)}`,
        `task: ${yamlString(input.task.taskId)}`,
        `implementation_order: ${yamlString(input.implementationOrder)}`,
        "workflow_level: basic",
        "planning_depth: standard",
        `agent_mode: ${yamlString(input.agentMode)}`,
        `evidence_profile: ${yamlString(input.evidenceProfile)}`,
        `runtime_attribution_required: ${runtimeRequired}`,
        "current_attempt_id: null",
        "attempts: []",
        "workflow_provenance: cli",
        `workflow_cli_command: ${yamlString(`day-shift work create --level basic --implementation-order ${input.implementationOrder} --task-id ${input.task.taskId}`)}`,
        "runtime_acceptance:",
        `  required: ${runtimeRequired}`,
        ...(runtimeRequired
            ? ["  criterion_ids:", ...criterionIds.map((id) => `    - ${id}`)]
            : ["  criterion_ids: []"]),
        "upstream:",
        `  task_definition: ${yamlString(input.taskDefinitionPath)}`,
        "---",
        "",
        `# ${input.task.title} Implementation Summary`,
        "",
        "## Summary",
        "",
        "Pending. Record implementation outcomes after the Basic task is executed.",
        "",
        "## Changed Paths",
        "",
        "None yet.",
        "",
        "## Acceptance Criteria Results",
        "",
        "Pending review after implementation.",
        "",
        "## Validation Performed",
        "",
        "None yet.",
        "",
        "## Validation Exceptions",
        "",
        "None.",
        "",
        "## Scope Classification",
        "",
        "Not started. Expected scope is limited to the task definition.",
        "",
        "## Runtime Evidence Boundary",
        "",
        `Pending ${input.evidenceProfile} evidence for the current implementation attempt.`,
        "",
        "## Deviations",
        "",
        "None yet.",
        "",
        "## Risks and Follow-Ups",
        "",
        "Pending implementation review.",
        "",
        "## Open Questions",
        "",
        "- None currently.",
        ""
    ].join("\n");
}
function requireText(value, label) {
    if (typeof value !== "string" || value.trim() === "") {
        throw new BasicTaskCreationError("invalid-request", `${label} is required.`);
    }
    return value.trim();
}
function optionalText(value) {
    return typeof value === "string" && value.trim() !== "" ? value.trim() : null;
}
function requireStringList(value, label, required) {
    if (!Array.isArray(value)) {
        throw new BasicTaskCreationError("invalid-request", `${label} must be a list.`);
    }
    const result = value.map((entry, index) => requireText(entry, `${label}[${index}]`));
    if (required && result.length === 0) {
        throw new BasicTaskCreationError("invalid-request", `${label} requires at least one value.`);
    }
    return result;
}
function requirePathList(value, label, required) {
    return requireStringList(value, label, required).map((entry) => {
        const normalized = entry.replace(/\\/g, "/").replace(/^\.\//, "");
        if (node_path_1.default.posix.isAbsolute(normalized) || normalized.split("/").includes("..")) {
            throw new BasicTaskCreationError("invalid-request", `${label} values must be repository-relative and contained.`);
        }
        return normalized;
    });
}
function normalizeTimestamp(value) {
    if (!Number.isFinite(Date.parse(value)) || !/(?:Z|[+-]\d{2}:\d{2})$/.test(value)) {
        throw new BasicTaskCreationError("invalid-request", "Basic task creation time must be an ISO-8601 timestamp with an explicit timezone.");
    }
    return value;
}
function titleFromSlug(value) {
    return value.split("-").map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`).join(" ");
}
function bulletList(values) {
    return values.map((value) => `- ${value}`);
}
function yamlString(value) {
    return JSON.stringify(value);
}
function criterionId(taskId, index) {
    return `BASIC-${taskId.toUpperCase().replace(/-/g, "_")}-AC-${String(index + 1).padStart(2, "0")}`;
}
function normalizeOrderedRootError(error) {
    if (error instanceof BasicTaskCreationError)
        return error;
    if (error instanceof ordered_root_identity_1.OrderedRootIdentityError) {
        const conflictCodes = new Set([
            "duplicate-stable-identity",
            "duplicate-implementation-order",
            "identity-mismatch",
            "order-mismatch",
            "inventory-incomplete"
        ]);
        return new BasicTaskCreationError(conflictCodes.has(error.code) ? "destination-conflict" : "invalid-request", error.message);
    }
    return new BasicTaskCreationError("invalid-request", error instanceof Error ? error.message : "Basic ordered-root allocation failed.");
}
function inventoryConflict(pathValue, expected, observed) {
    return {
        path: pathValue,
        expectationKind: "content-revision",
        expectedState: expected,
        observedState: observed,
        refreshPreviewRequired: true,
        guidance: "Refresh the preview before retrying this mutation."
    };
}
