import { createHash } from "node:crypto";
import {
  chmod,
  lstat,
  mkdir,
  open,
  readFile,
  realpath
} from "node:fs/promises";
import path from "node:path";
import { verifyRunrailCandidateAudit } from "./runrail-deepseek-advisory-core.mjs";
import { verifyRunrailHunkContinuity } from "./runrail-hunk-continuity-core.mjs";
import {
  verifyRunrailAuditV4,
  verifyRunrailReviewCoverage
} from "./runrail-review-session-core.mjs";

export const RUNRAIL_CANDIDATE_TOURNAMENT = Object.freeze({
  schemaVersion: 2,
  artifactType: "runrail-candidate-tournament",
  profile: "runrail-candidate-tournament-v2",
  legacySchemaVersion: 1,
  legacyProfile: "runrail-candidate-tournament-v1",
  comparisonBasisProfile: "runrail-tournament-equal-basis-v1",
  reviewOrderReceiptProfile:
    "runrail-tournament-review-order-receipt-v1",
  product: "Runrail Local v1",
  minimumCandidates: 2,
  maximumCandidates: 5
});

const SHA256_PATTERN = /^[a-f0-9]{64}$/;
const TOURNAMENT_ID_PATTERN = /^RCT-[A-F0-9]{24}$/;
const CANDIDATE_ID_PATTERN = /^RCC-[A-F0-9]{20}$/;
const riskRanks = Object.freeze({ low: 1, medium: 2, high: 3 });
const allowedPriorityReasons = new Set([
  "preflight-blocked",
  "contract-failed",
  "verifier-failed",
  "unsupported-source-types",
  "missing-companion-groups",
  "high-deterministic-risk",
  "medium-deterministic-risk",
  "low-deterministic-risk",
  "hunk-attention-required",
  "contract-evidence-required",
  "high-finding-present",
  "medium-finding-present",
  "larger-change-surface"
]);

export class RunrailCandidateTournamentError extends Error {
  constructor(code, message) {
    super(message);
    this.name = "RunrailCandidateTournamentError";
    this.code = code;
  }
}

function fail(code, message) {
  throw new RunrailCandidateTournamentError(code, message);
}

function isRecord(value) {
  return value !== null && typeof value === "object" && !Array.isArray(value);
}

function stableValue(value) {
  if (Array.isArray(value)) return value.map(stableValue);
  if (isRecord(value)) {
    return Object.fromEntries(
      Object.keys(value)
        .sort()
        .map((key) => [key, stableValue(value[key])])
    );
  }
  return value;
}

export function stableRunrailCandidateTournamentJson(value) {
  return `${JSON.stringify(stableValue(value), null, 2)}\n`;
}

function sha256(value) {
  return createHash("sha256").update(value).digest("hex");
}

export function computeRunrailCandidateTournamentChecksum(value) {
  return sha256(stableRunrailCandidateTournamentJson(value));
}

function exactKeys(value, expected, label) {
  if (!isRecord(value)) fail("candidate-tournament-invalid", `${label} must be an object.`);
  const actual = Object.keys(value).sort();
  const wanted = [...expected].sort();
  if (
    actual.length !== wanted.length ||
    actual.some((key, index) => key !== wanted[index])
  ) {
    fail("candidate-tournament-invalid", `${label} has an invalid field set.`);
  }
}

function expectInteger(value, label, minimum = 0, maximum = Number.MAX_SAFE_INTEGER) {
  if (!Number.isSafeInteger(value) || value < minimum || value > maximum) {
    fail("candidate-tournament-invalid", `${label} must be a bounded integer.`);
  }
}

function expectBoolean(value, label) {
  if (typeof value !== "boolean") {
    fail("candidate-tournament-invalid", `${label} must be a boolean.`);
  }
}

function compareText(left, right) {
  return left < right ? -1 : left > right ? 1 : 0;
}

function comparePriorityVectorsDescending(left, right) {
  for (let index = 0; index < left.length; index += 1) {
    if (left[index] !== right[index]) return right[index] - left[index];
  }
  return 0;
}

function priorityReasonsFor(metrics) {
  const reasons = [];
  if (!metrics.preflightPassed) reasons.push("preflight-blocked");
  if (!metrics.contractPassed) reasons.push("contract-failed");
  if (!metrics.verifierPassed) reasons.push("verifier-failed");
  if (metrics.unsupportedChangedSourceFileCount > 0) {
    reasons.push("unsupported-source-types");
  }
  if (metrics.missingCompanionGroupCount > 0) {
    reasons.push("missing-companion-groups");
  }
  reasons.push(`${metrics.riskLevel}-deterministic-risk`);
  if (metrics.hunkAttentionRequiredCount > 0) {
    reasons.push("hunk-attention-required");
  }
  if (metrics.requiredEvidenceCount > 0) {
    reasons.push("contract-evidence-required");
  }
  if (metrics.highFindingCount > 0) reasons.push("high-finding-present");
  if (metrics.mediumFindingCount > 0) reasons.push("medium-finding-present");
  if (metrics.changedFileCount > 1 || metrics.diffLineCount > 120) {
    reasons.push("larger-change-surface");
  }
  return reasons;
}

function candidateEntry({ audit, coverage }) {
  verifyRunrailAuditV4(audit);
  verifyRunrailCandidateAudit(audit);
  verifyRunrailReviewCoverage(coverage, audit);
  verifyRunrailHunkContinuity(coverage);
  const revisionBindingSha256 = sha256(
    `runrail-candidate-tournament-revision-v1\0${audit.source.baseCommit}\0${audit.source.candidateCommit}`
  );
  const summary = coverage.summary;
  const hunkAttentionRequiredCount =
    summary.unreviewedCount + summary.needsRevisionCount;
  const metrics = {
    preflightPassed: audit.preflightPassed,
    contractPassed: audit.reviewContract.passed,
    verifierPassed: audit.verifier.passed,
    riskLevel: audit.decision.riskLevel,
    riskRank: riskRanks[audit.decision.riskLevel],
    highFindingCount: audit.decision.findingCounts.high,
    mediumFindingCount: audit.decision.findingCounts.medium,
    infoFindingCount: audit.decision.findingCounts.info,
    missingCompanionGroupCount:
      audit.reviewContract.missingCompanionGroupCount,
    unsupportedChangedSourceFileCount:
      audit.verifier.unsupportedChangedSourceFileCount,
    requiredEvidenceCount: audit.reviewContract.requiredEvidence.length,
    requiredReviewLaneCount: audit.reviewContract.requiredReviewLanes.length,
    hunkCount: summary.hunkCount,
    reviewedHunkCount: summary.reviewedCount,
    needsRevisionHunkCount: summary.needsRevisionCount,
    unreviewedHunkCount: summary.unreviewedCount,
    hunkAttentionRequiredCount,
    changedFileCount: audit.policy.changedFileCount,
    diffLineCount: audit.policy.diffLineCount
  };
  const priorityVector = [
    metrics.preflightPassed ? 0 : 1,
    metrics.riskRank,
    metrics.highFindingCount,
    metrics.contractPassed ? 0 : 1,
    metrics.verifierPassed ? 0 : 1,
    metrics.unsupportedChangedSourceFileCount,
    metrics.missingCompanionGroupCount,
    metrics.hunkAttentionRequiredCount,
    metrics.requiredEvidenceCount,
    metrics.mediumFindingCount,
    metrics.requiredReviewLaneCount,
    metrics.changedFileCount,
    metrics.diffLineCount
  ];
  return {
    candidateId: `RCC-${sha256(
      `runrail-candidate-tournament-candidate-v1\0${revisionBindingSha256}`
    )
      .slice(0, 20)
      .toUpperCase()}`,
    revisionBindingSha256,
    auditChecksumSha256: audit.checksumSha256,
    coverageChecksumSha256: coverage.checksumSha256,
    metrics,
    priorityVector,
    priorityReasons: priorityReasonsFor(metrics),
    humanDecisionRequired: true,
    automaticSelectionPerformed: false,
    bestCodeClaimed: false,
    _baseCommit: audit.source.baseCommit,
    _candidateCommit: audit.source.candidateCommit,
    _contractChecksumSha256: audit.reviewContract.contractSha256,
    _verifierProfile: audit.verifier.profile
  };
}

export function buildRunrailCandidateTournament({ entries }) {
  if (
    !Array.isArray(entries) ||
    entries.length < RUNRAIL_CANDIDATE_TOURNAMENT.minimumCandidates ||
    entries.length > RUNRAIL_CANDIDATE_TOURNAMENT.maximumCandidates
  ) {
    fail(
      "candidate-tournament-count",
      `Candidate Tournament requires ${RUNRAIL_CANDIDATE_TOURNAMENT.minimumCandidates} to ${RUNRAIL_CANDIDATE_TOURNAMENT.maximumCandidates} candidates.`
    );
  }
  const candidates = entries.map(candidateEntry);
  const baseCommits = new Set(candidates.map((entry) => entry._baseCommit));
  const candidateCommits = candidates.map((entry) => entry._candidateCommit);
  const contractChecksums = new Set(
    candidates.map((entry) => entry._contractChecksumSha256)
  );
  const verifierProfiles = new Set(
    candidates.map((entry) => entry._verifierProfile)
  );
  const auditChecksums = candidates.map((entry) => entry.auditChecksumSha256);
  if (baseCommits.size !== 1) {
    fail(
      "candidate-tournament-base-mismatch",
      "Every tournament candidate must use the same confirmed base commit."
    );
  }
  if (
    new Set(candidateCommits).size !== candidateCommits.length ||
    new Set(auditChecksums).size !== auditChecksums.length
  ) {
    fail(
      "candidate-tournament-duplicate",
      "Candidate Tournament does not accept duplicate candidate revisions."
    );
  }
  if (
    contractChecksums.size !== 1 ||
    verifierProfiles.size !== 1 ||
    !verifierProfiles.has("safe-static")
  ) {
    fail(
      "candidate-tournament-basis-mismatch",
      "Every tournament candidate must use the same base-owned contract and safe-static verifier."
    );
  }

  const inputSetChecksumSha256 = sha256(
    stableRunrailCandidateTournamentJson(
      candidates
        .map((entry) => ({
          auditChecksumSha256: entry.auditChecksumSha256,
          coverageChecksumSha256: entry.coverageChecksumSha256
        }))
        .sort((left, right) =>
          compareText(left.auditChecksumSha256, right.auditChecksumSha256)
        )
    )
  );
  const ranked = candidates
    .sort((left, right) =>
      comparePriorityVectorsDescending(left.priorityVector, right.priorityVector) ||
      compareText(left.revisionBindingSha256, right.revisionBindingSha256)
    )
    .map((entry, index) => {
      const {
        _baseCommit,
        _candidateCommit,
        _contractChecksumSha256,
        _verifierProfile,
        ...pathFreeEntry
      } = entry;
      void _baseCommit;
      void _candidateCommit;
      void _contractChecksumSha256;
      void _verifierProfile;
      return { rank: index + 1, ...pathFreeEntry };
    });
  const tournamentId = `RCT-${sha256(
    `${RUNRAIL_CANDIDATE_TOURNAMENT.profile}\0${inputSetChecksumSha256}`
  )
    .slice(0, 24)
    .toUpperCase()}`;
  const body = {
    schemaVersion: RUNRAIL_CANDIDATE_TOURNAMENT.schemaVersion,
    artifactType: RUNRAIL_CANDIDATE_TOURNAMENT.artifactType,
    profile: RUNRAIL_CANDIDATE_TOURNAMENT.profile,
    product: RUNRAIL_CANDIDATE_TOURNAMENT.product,
    tournamentId,
    candidateCount: ranked.length,
    inputSetChecksumSha256,
    rankingBasis: {
      objective: "human-review-order",
      order: "lexicographic-descending",
      dimensions: [
        "blocked-preflight",
        "deterministic-risk",
        "high-findings",
        "contract-failure",
        "verifier-failure",
        "unsupported-source-types",
        "missing-companion-groups",
        "hunk-attention",
        "required-evidence",
        "medium-findings",
        "review-lanes",
        "changed-files",
        "diff-lines"
      ],
      tieBreak: "revision-binding-sha256-ascending",
      automaticBestCandidateSelection: false,
      bestCodeClaimed: false
    },
    comparisonBasis: {
      profile: RUNRAIL_CANDIDATE_TOURNAMENT.comparisonBasisProfile,
      sameConfirmedBase: true,
      sameBaseOwnedContract: true,
      equalContractBudget: true,
      sameVerifierProfile: "safe-static",
      equalVerifierBudget: true,
      candidateSpecificExecution: false,
      projectTestsExecuted: false
    },
    reviewOrderReceipt: {
      profile: RUNRAIL_CANDIDATE_TOURNAMENT.reviewOrderReceiptProfile,
      title: "Why review this candidate first",
      candidateId: ranked[0].candidateId,
      reasonIds: ranked[0].priorityReasons.slice(0, 3),
      sameConfirmedBase: true,
      equalContractBudget: true,
      equalVerifierBudget: true,
      reviewOrderOnly: true,
      codeQualityClaim: false,
      mergeRecommendation: false
    },
    candidates: ranked,
    boundaries: {
      localOnly: true,
      pathFree: true,
      repositoryIdentityIncluded: false,
      branchNamesIncluded: false,
      commitsIncluded: false,
      sourceContentIncluded: false,
      diffContentIncluded: false,
      rawVerifierOutputIncluded: false,
      projectTestsExecuted: false,
      sourceMutation: false,
      networkUsed: false,
      modelAuthority: "none",
      executionAuthority: "none",
      humanDecisionRequired: true
    }
  };
  return verifyRunrailCandidateTournament({
    ...body,
    checksumSha256: computeRunrailCandidateTournamentChecksum(body)
  });
}

function verifyMetrics(metrics) {
  exactKeys(
    metrics,
    [
      "preflightPassed",
      "contractPassed",
      "verifierPassed",
      "riskLevel",
      "riskRank",
      "highFindingCount",
      "mediumFindingCount",
      "infoFindingCount",
      "missingCompanionGroupCount",
      "unsupportedChangedSourceFileCount",
      "requiredEvidenceCount",
      "requiredReviewLaneCount",
      "hunkCount",
      "reviewedHunkCount",
      "needsRevisionHunkCount",
      "unreviewedHunkCount",
      "hunkAttentionRequiredCount",
      "changedFileCount",
      "diffLineCount"
    ],
    "Candidate Tournament metrics"
  );
  for (const key of ["preflightPassed", "contractPassed", "verifierPassed"]) {
    expectBoolean(metrics[key], `Candidate Tournament ${key}`);
  }
  if (!Object.hasOwn(riskRanks, metrics.riskLevel)) {
    fail("candidate-tournament-invalid", "Candidate Tournament risk level is invalid.");
  }
  if (metrics.riskRank !== riskRanks[metrics.riskLevel]) {
    fail("candidate-tournament-invalid", "Candidate Tournament risk rank is invalid.");
  }
  for (const key of [
    "highFindingCount",
    "mediumFindingCount",
    "infoFindingCount",
    "missingCompanionGroupCount",
    "unsupportedChangedSourceFileCount",
    "requiredEvidenceCount",
    "requiredReviewLaneCount",
    "hunkCount",
    "reviewedHunkCount",
    "needsRevisionHunkCount",
    "unreviewedHunkCount",
    "hunkAttentionRequiredCount",
    "changedFileCount",
    "diffLineCount"
  ]) {
    expectInteger(metrics[key], `Candidate Tournament ${key}`, 0, 100_000);
  }
  if (
    metrics.reviewedHunkCount +
      metrics.needsRevisionHunkCount +
      metrics.unreviewedHunkCount !==
      metrics.hunkCount ||
    metrics.needsRevisionHunkCount + metrics.unreviewedHunkCount !==
      metrics.hunkAttentionRequiredCount
  ) {
    fail("candidate-tournament-invalid", "Candidate Tournament hunk metrics are inconsistent.");
  }
}

export function verifyRunrailCandidateTournament(tournament) {
  const currentSchema =
    tournament?.schemaVersion === RUNRAIL_CANDIDATE_TOURNAMENT.schemaVersion &&
    tournament?.profile === RUNRAIL_CANDIDATE_TOURNAMENT.profile;
  const legacySchema =
    tournament?.schemaVersion ===
      RUNRAIL_CANDIDATE_TOURNAMENT.legacySchemaVersion &&
    tournament?.profile === RUNRAIL_CANDIDATE_TOURNAMENT.legacyProfile;
  exactKeys(
    tournament,
    currentSchema
      ? [
          "schemaVersion",
          "artifactType",
          "profile",
          "product",
          "tournamentId",
          "candidateCount",
          "inputSetChecksumSha256",
          "rankingBasis",
          "comparisonBasis",
          "reviewOrderReceipt",
          "candidates",
          "boundaries",
          "checksumSha256"
        ]
      : [
          "schemaVersion",
          "artifactType",
          "profile",
          "product",
          "tournamentId",
          "candidateCount",
          "inputSetChecksumSha256",
          "rankingBasis",
          "candidates",
          "boundaries",
          "checksumSha256"
        ],
    "Candidate Tournament"
  );
  if (
    (!currentSchema && !legacySchema) ||
    tournament.artifactType !== RUNRAIL_CANDIDATE_TOURNAMENT.artifactType ||
    tournament.product !== RUNRAIL_CANDIDATE_TOURNAMENT.product ||
    !TOURNAMENT_ID_PATTERN.test(String(tournament.tournamentId || "")) ||
    !SHA256_PATTERN.test(String(tournament.inputSetChecksumSha256 || "")) ||
    !SHA256_PATTERN.test(String(tournament.checksumSha256 || ""))
  ) {
    fail("candidate-tournament-invalid", "Candidate Tournament identity is invalid.");
  }
  exactKeys(
    tournament.rankingBasis,
    [
      "objective",
      "order",
      "dimensions",
      "tieBreak",
      "automaticBestCandidateSelection",
      "bestCodeClaimed"
    ],
    "Candidate Tournament ranking basis"
  );
  const expectedDimensions = [
    "blocked-preflight",
    "deterministic-risk",
    "high-findings",
    "contract-failure",
    "verifier-failure",
    "unsupported-source-types",
    "missing-companion-groups",
    "hunk-attention",
    "required-evidence",
    "medium-findings",
    "review-lanes",
    "changed-files",
    "diff-lines"
  ];
  if (
    tournament.rankingBasis.objective !== "human-review-order" ||
    tournament.rankingBasis.order !== "lexicographic-descending" ||
    tournament.rankingBasis.tieBreak !==
      "revision-binding-sha256-ascending" ||
    JSON.stringify(tournament.rankingBasis.dimensions) !==
      JSON.stringify(expectedDimensions) ||
    tournament.rankingBasis.automaticBestCandidateSelection !== false ||
    tournament.rankingBasis.bestCodeClaimed !== false
  ) {
    fail("candidate-tournament-invalid", "Candidate Tournament ranking contract is invalid.");
  }
  if (currentSchema) {
    exactKeys(
      tournament.comparisonBasis,
      [
        "profile",
        "sameConfirmedBase",
        "sameBaseOwnedContract",
        "equalContractBudget",
        "sameVerifierProfile",
        "equalVerifierBudget",
        "candidateSpecificExecution",
        "projectTestsExecuted"
      ],
      "Candidate Tournament comparison basis"
    );
    if (
      tournament.comparisonBasis.profile !==
        RUNRAIL_CANDIDATE_TOURNAMENT.comparisonBasisProfile ||
      tournament.comparisonBasis.sameConfirmedBase !== true ||
      tournament.comparisonBasis.sameBaseOwnedContract !== true ||
      tournament.comparisonBasis.equalContractBudget !== true ||
      tournament.comparisonBasis.sameVerifierProfile !== "safe-static" ||
      tournament.comparisonBasis.equalVerifierBudget !== true ||
      tournament.comparisonBasis.candidateSpecificExecution !== false ||
      tournament.comparisonBasis.projectTestsExecuted !== false
    ) {
      fail(
        "candidate-tournament-invalid",
        "Candidate Tournament comparison basis is invalid."
      );
    }
    exactKeys(
      tournament.reviewOrderReceipt,
      [
        "profile",
        "title",
        "candidateId",
        "reasonIds",
        "sameConfirmedBase",
        "equalContractBudget",
        "equalVerifierBudget",
        "reviewOrderOnly",
        "codeQualityClaim",
        "mergeRecommendation"
      ],
      "Candidate Tournament review-order receipt"
    );
    if (
      tournament.reviewOrderReceipt.profile !==
        RUNRAIL_CANDIDATE_TOURNAMENT.reviewOrderReceiptProfile ||
      tournament.reviewOrderReceipt.title !==
        "Why review this candidate first" ||
      !CANDIDATE_ID_PATTERN.test(
        String(tournament.reviewOrderReceipt.candidateId || "")
      ) ||
      !Array.isArray(tournament.reviewOrderReceipt.reasonIds) ||
      tournament.reviewOrderReceipt.reasonIds.length < 1 ||
      tournament.reviewOrderReceipt.reasonIds.length > 3 ||
      tournament.reviewOrderReceipt.reasonIds.some(
        (reason) => !allowedPriorityReasons.has(reason)
      ) ||
      tournament.reviewOrderReceipt.sameConfirmedBase !== true ||
      tournament.reviewOrderReceipt.equalContractBudget !== true ||
      tournament.reviewOrderReceipt.equalVerifierBudget !== true ||
      tournament.reviewOrderReceipt.reviewOrderOnly !== true ||
      tournament.reviewOrderReceipt.codeQualityClaim !== false ||
      tournament.reviewOrderReceipt.mergeRecommendation !== false
    ) {
      fail(
        "candidate-tournament-invalid",
        "Candidate Tournament review-order receipt is invalid."
      );
    }
  }
  if (
    !Array.isArray(tournament.candidates) ||
    tournament.candidates.length < RUNRAIL_CANDIDATE_TOURNAMENT.minimumCandidates ||
    tournament.candidates.length > RUNRAIL_CANDIDATE_TOURNAMENT.maximumCandidates ||
    tournament.candidateCount !== tournament.candidates.length
  ) {
    fail("candidate-tournament-invalid", "Candidate Tournament candidate count is invalid.");
  }
  const seenCandidates = new Set();
  const seenAudits = new Set();
  let previousVector = null;
  let previousId = "";
  for (let index = 0; index < tournament.candidates.length; index += 1) {
    const candidate = tournament.candidates[index];
    exactKeys(
      candidate,
      [
        "rank",
        "candidateId",
        "revisionBindingSha256",
        "auditChecksumSha256",
        "coverageChecksumSha256",
        "metrics",
        "priorityVector",
        "priorityReasons",
        "humanDecisionRequired",
        "automaticSelectionPerformed",
        "bestCodeClaimed"
      ],
      "Candidate Tournament candidate"
    );
    if (
      candidate.rank !== index + 1 ||
      !CANDIDATE_ID_PATTERN.test(String(candidate.candidateId || "")) ||
      !SHA256_PATTERN.test(String(candidate.revisionBindingSha256 || "")) ||
      !SHA256_PATTERN.test(String(candidate.auditChecksumSha256 || "")) ||
      !SHA256_PATTERN.test(String(candidate.coverageChecksumSha256 || "")) ||
      candidate.candidateId !==
        `RCC-${sha256(
          `runrail-candidate-tournament-candidate-v1\0${candidate.revisionBindingSha256}`
        )
          .slice(0, 20)
          .toUpperCase()}` ||
      seenCandidates.has(candidate.candidateId) ||
      seenAudits.has(candidate.auditChecksumSha256)
    ) {
      fail("candidate-tournament-invalid", "Candidate Tournament candidate identity is invalid.");
    }
    seenCandidates.add(candidate.candidateId);
    seenAudits.add(candidate.auditChecksumSha256);
    verifyMetrics(candidate.metrics);
    const expectedVector = [
      candidate.metrics.preflightPassed ? 0 : 1,
      candidate.metrics.riskRank,
      candidate.metrics.highFindingCount,
      candidate.metrics.contractPassed ? 0 : 1,
      candidate.metrics.verifierPassed ? 0 : 1,
      candidate.metrics.unsupportedChangedSourceFileCount,
      candidate.metrics.missingCompanionGroupCount,
      candidate.metrics.hunkAttentionRequiredCount,
      candidate.metrics.requiredEvidenceCount,
      candidate.metrics.mediumFindingCount,
      candidate.metrics.requiredReviewLaneCount,
      candidate.metrics.changedFileCount,
      candidate.metrics.diffLineCount
    ];
    if (
      JSON.stringify(candidate.priorityVector) !== JSON.stringify(expectedVector) ||
      !Array.isArray(candidate.priorityReasons) ||
      candidate.priorityReasons.some((reason) => !allowedPriorityReasons.has(reason)) ||
      new Set(candidate.priorityReasons).size !== candidate.priorityReasons.length ||
      JSON.stringify(candidate.priorityReasons) !==
        JSON.stringify(priorityReasonsFor(candidate.metrics)) ||
      candidate.humanDecisionRequired !== true ||
      candidate.automaticSelectionPerformed !== false ||
      candidate.bestCodeClaimed !== false
    ) {
      fail("candidate-tournament-invalid", "Candidate Tournament priority evidence is invalid.");
    }
    if (previousVector) {
      const vectorOrder = comparePriorityVectorsDescending(
        previousVector,
        candidate.priorityVector
      );
      if (
        vectorOrder > 0 ||
        (
          vectorOrder === 0 &&
          compareText(previousId, candidate.revisionBindingSha256) > 0
        )
      ) {
        fail("candidate-tournament-invalid", "Candidate Tournament ranking order is invalid.");
      }
    }
    previousVector = candidate.priorityVector;
    previousId = candidate.revisionBindingSha256;
  }
  if (
    currentSchema &&
    (
      tournament.reviewOrderReceipt.candidateId !==
        tournament.candidates[0].candidateId ||
      JSON.stringify(tournament.reviewOrderReceipt.reasonIds) !==
        JSON.stringify(tournament.candidates[0].priorityReasons.slice(0, 3))
    )
  ) {
    fail(
      "candidate-tournament-invalid",
      "Candidate Tournament review-order receipt does not match rank one."
    );
  }
  const expectedInputSetChecksum = sha256(
    stableRunrailCandidateTournamentJson(
      tournament.candidates
        .map((candidate) => ({
          auditChecksumSha256: candidate.auditChecksumSha256,
          coverageChecksumSha256: candidate.coverageChecksumSha256
        }))
        .sort((left, right) =>
          compareText(left.auditChecksumSha256, right.auditChecksumSha256)
        )
    )
  );
  if (
    tournament.inputSetChecksumSha256 !== expectedInputSetChecksum ||
    tournament.tournamentId !==
      `RCT-${sha256(
        `${tournament.profile}\0${expectedInputSetChecksum}`
      )
        .slice(0, 24)
        .toUpperCase()}`
  ) {
    fail("candidate-tournament-invalid", "Candidate Tournament input binding is invalid.");
  }
  exactKeys(
    tournament.boundaries,
    [
      "localOnly",
      "pathFree",
      "repositoryIdentityIncluded",
      "branchNamesIncluded",
      "commitsIncluded",
      "sourceContentIncluded",
      "diffContentIncluded",
      "rawVerifierOutputIncluded",
      "projectTestsExecuted",
      "sourceMutation",
      "networkUsed",
      "modelAuthority",
      "executionAuthority",
      "humanDecisionRequired"
    ],
    "Candidate Tournament boundaries"
  );
  if (
    tournament.boundaries.localOnly !== true ||
    tournament.boundaries.pathFree !== true ||
    tournament.boundaries.repositoryIdentityIncluded !== false ||
    tournament.boundaries.branchNamesIncluded !== false ||
    tournament.boundaries.commitsIncluded !== false ||
    tournament.boundaries.sourceContentIncluded !== false ||
    tournament.boundaries.diffContentIncluded !== false ||
    tournament.boundaries.rawVerifierOutputIncluded !== false ||
    tournament.boundaries.projectTestsExecuted !== false ||
    tournament.boundaries.sourceMutation !== false ||
    tournament.boundaries.networkUsed !== false ||
    tournament.boundaries.modelAuthority !== "none" ||
    tournament.boundaries.executionAuthority !== "none" ||
    tournament.boundaries.humanDecisionRequired !== true
  ) {
    fail("candidate-tournament-authority", "Candidate Tournament expanded its authority boundary.");
  }
  const { checksumSha256, ...body } = tournament;
  if (computeRunrailCandidateTournamentChecksum(body) !== checksumSha256) {
    fail("candidate-tournament-tampered", "Candidate Tournament checksum verification failed.");
  }
  return tournament;
}

async function ensureOrdinaryDirectory(directory, label) {
  const entry = await lstat(directory).catch(() => null);
  if (!entry || !entry.isDirectory() || entry.isSymbolicLink()) {
    fail("candidate-tournament-storage", `${label} must be an ordinary directory.`);
  }
  const canonical = await realpath(directory);
  if (canonical !== path.resolve(directory)) {
    fail("candidate-tournament-storage", `${label} must not traverse a symbolic link.`);
  }
  return canonical;
}

export async function writeRunrailCandidateTournament({
  tournament,
  historyRoot
}) {
  verifyRunrailCandidateTournament(tournament);
  const canonicalHistoryRoot = await ensureOrdinaryDirectory(
    historyRoot,
    "Runrail history root"
  );
  const outputRoot = path.join(canonicalHistoryRoot, "tournaments");
  await mkdir(outputRoot, { recursive: true, mode: 0o700 });
  const canonicalOutputRoot = await ensureOrdinaryDirectory(
    outputRoot,
    "Candidate Tournament output root"
  );
  if (process.platform !== "win32") await chmod(canonicalOutputRoot, 0o700);
  const tournamentPath = path.join(
    canonicalOutputRoot,
    `${tournament.tournamentId}.json`
  );
  const expected = stableRunrailCandidateTournamentJson(tournament);
  const existing = await lstat(tournamentPath).catch(() => null);
  if (existing) {
    if (!existing.isFile() || existing.isSymbolicLink() || existing.size > 1024 * 1024) {
      fail(
        "candidate-tournament-storage",
        "The existing Candidate Tournament artifact is not an ordinary bounded file."
      );
    }
    const stored = verifyRunrailCandidateTournament(
      JSON.parse(await readFile(tournamentPath, "utf8"))
    );
    if (stableRunrailCandidateTournamentJson(stored) !== expected) {
      fail(
        "candidate-tournament-conflict",
        "A different Candidate Tournament already exists for this input set."
      );
    }
    return { tournamentPath, tournament: stored };
  }
  const handle = await open(tournamentPath, "wx", 0o600);
  try {
    await handle.writeFile(expected, "utf8");
    await handle.sync();
  } finally {
    await handle.close();
  }
  if (process.platform !== "win32") await chmod(tournamentPath, 0o600);
  const stored = verifyRunrailCandidateTournament(
    JSON.parse(await readFile(tournamentPath, "utf8"))
  );
  return { tournamentPath, tournament: stored };
}
