///|
/// High-level acceptance state for release and contest submission reviews.
pub(all) enum TapReadinessLevel {
  ReadinessReady
  ReadinessNeedsWork
  ReadinessBlocked
} derive(Debug, Eq)

///|
/// Risk level attached to one readiness check.
pub(all) enum TapReadinessRisk {
  RiskPass
  RiskNotice
  RiskWarning
  RiskBlock
} derive(Debug, Eq)

///|
/// Evidence supplied by a project, script, or human review.
pub(all) struct TapProjectEvidence {
  package_name : String
  version : String
  repository : String
  license : String
  readme_present : Bool
  readme_has_usage : Bool
  readme_has_features : Bool
  ci_configured : Bool
  examples : Int
  test_cases : Int
  build_ok : Bool
  mooncakes_published : Bool
  mooncakes_version : String
  mooncakes_build_ok : Bool
  commit_count : Int
  total_moonbit_lines : Int
  effective_moonbit_lines : Int
  has_changelog : Bool
  has_design_doc : Bool
  has_provenance_doc : Bool
  has_acceptance_checklist : Bool
  clean_tree : Bool
} derive(Debug, Eq)

///|
/// One scored acceptance or release readiness check.
pub(all) struct TapReadinessCheck {
  id : String
  category : String
  title : String
  required : Bool
  passed : Bool
  score : Int
  max_score : Int
  risk : TapReadinessRisk
  evidence : String
  remediation : String
} derive(Debug, Eq)

///|
/// Complete readiness report composed from TAP data and repository evidence.
pub(all) struct TapReadinessReport {
  project : String
  suite : TapSuiteReport
  policy : TapPolicyResult
  evidence : TapProjectEvidence
  checks : Array[TapReadinessCheck]
  score : Int
  level : TapReadinessLevel
  ok : Bool
} derive(Debug, Eq)

///|
/// Construct an empty evidence object for tests or incremental tools.
pub fn empty_project_evidence(package_name : String) -> TapProjectEvidence {
  TapProjectEvidence::{
    package_name,
    version: "",
    repository: "",
    license: "",
    readme_present: false,
    readme_has_usage: false,
    readme_has_features: false,
    ci_configured: false,
    examples: 0,
    test_cases: 0,
    build_ok: false,
    mooncakes_published: false,
    mooncakes_version: "",
    mooncakes_build_ok: false,
    commit_count: 0,
    total_moonbit_lines: 0,
    effective_moonbit_lines: 0,
    has_changelog: false,
    has_design_doc: false,
    has_provenance_doc: false,
    has_acceptance_checklist: false,
    clean_tree: false,
  }
}

///|
/// Construct evidence for a repository that already passed local verification.
pub fn verified_project_evidence(
  package_name : String,
  version : String,
  repository : String,
  license : String,
  examples : Int,
  test_cases : Int,
  total_moonbit_lines : Int,
  effective_moonbit_lines : Int,
  commit_count : Int,
) -> TapProjectEvidence {
  TapProjectEvidence::{
    package_name,
    version,
    repository,
    license,
    readme_present: true,
    readme_has_usage: true,
    readme_has_features: true,
    ci_configured: true,
    examples,
    test_cases,
    build_ok: true,
    mooncakes_published: true,
    mooncakes_version: version,
    mooncakes_build_ok: true,
    commit_count,
    total_moonbit_lines,
    effective_moonbit_lines,
    has_changelog: true,
    has_design_doc: true,
    has_provenance_doc: true,
    has_acceptance_checklist: true,
    clean_tree: true,
  }
}

///|
/// Evaluate one TAP report by wrapping it as a single-member suite.
pub fn readiness_from_report(
  project : String,
  report_name : String,
  report : TapReport,
  evidence : TapProjectEvidence,
) -> TapReadinessReport {
  readiness_from_suite(
    project,
    build_suite_report(report_name, [named_report(report_name, report)]),
    evidence,
  )
}

///|
/// Evaluate a full suite and repository evidence for release readiness.
pub fn readiness_from_suite(
  project : String,
  suite : TapSuiteReport,
  evidence : TapProjectEvidence,
) -> TapReadinessReport {
  let policy = evaluate_suite_policy(suite, release_policy())
  let checks = build_readiness_checks(suite, policy, evidence)
  let score = readiness_score(checks)
  let level = classify_readiness(checks, score)
  TapReadinessReport::{
    project,
    suite,
    policy,
    evidence,
    checks,
    score,
    level,
    ok: level == ReadinessReady,
  }
}

///|
/// Return true when the readiness report is suitable for submission.
pub fn readiness_passes(report : TapReadinessReport) -> Bool {
  report.ok
}

///|
/// Return a stable label for the readiness level.
pub fn readiness_level_label(level : TapReadinessLevel) -> String {
  match level {
    ReadinessReady => "ready"
    ReadinessNeedsWork => "needs-work"
    ReadinessBlocked => "blocked"
  }
}

///|
/// Return a stable label for one readiness risk.
pub fn readiness_risk_label(risk : TapReadinessRisk) -> String {
  match risk {
    RiskPass => "pass"
    RiskNotice => "notice"
    RiskWarning => "warning"
    RiskBlock => "block"
  }
}

///|
/// Numeric risk order for dashboards and automation.
pub fn readiness_risk_rank(risk : TapReadinessRisk) -> Int {
  match risk {
    RiskPass => 0
    RiskNotice => 1
    RiskWarning => 2
    RiskBlock => 3
  }
}

///|
/// Return a compact grade for a readiness score.
pub fn readiness_grade(score : Int) -> String {
  if score >= 95 {
    "excellent"
  } else if score >= 90 {
    "ready"
  } else if score >= 75 {
    "solid"
  } else if score >= 60 {
    "needs-work"
  } else {
    "high-risk"
  }
}

///|
/// Sum earned points across checks.
pub fn readiness_earned_score(checks : Array[TapReadinessCheck]) -> Int {
  let mut total = 0
  for item in checks {
    total += item.score
  }
  total
}

///|
/// Sum maximum points across checks.
pub fn readiness_max_score(checks : Array[TapReadinessCheck]) -> Int {
  let mut total = 0
  for item in checks {
    total += item.max_score
  }
  total
}

///|
/// Calculate normalized 0-100 readiness score.
pub fn readiness_score(checks : Array[TapReadinessCheck]) -> Int {
  let max_score = readiness_max_score(checks)
  if max_score == 0 {
    0
  } else {
    readiness_earned_score(checks) * 100 / max_score
  }
}

///|
/// Return checks that passed.
pub fn passed_readiness_checks(
  report : TapReadinessReport,
) -> Array[TapReadinessCheck] {
  let items : Array[TapReadinessCheck] = []
  for item in report.checks {
    if item.passed {
      items.push(item)
    }
  }
  items
}

///|
/// Return failed checks, including optional recommendations.
pub fn failed_readiness_checks(
  report : TapReadinessReport,
) -> Array[TapReadinessCheck] {
  let items : Array[TapReadinessCheck] = []
  for item in report.checks {
    if !item.passed {
      items.push(item)
    }
  }
  items
}

///|
/// Return failed required checks.
pub fn blocking_readiness_checks(
  report : TapReadinessReport,
) -> Array[TapReadinessCheck] {
  let items : Array[TapReadinessCheck] = []
  for item in report.checks {
    if !item.passed && item.required {
      items.push(item)
    }
  }
  items
}

///|
/// Return failed optional checks.
pub fn optional_readiness_gaps(
  report : TapReadinessReport,
) -> Array[TapReadinessCheck] {
  let items : Array[TapReadinessCheck] = []
  for item in report.checks {
    if !item.passed && !item.required {
      items.push(item)
    }
  }
  items
}

///|
/// Count checks with a given risk level.
pub fn readiness_risk_count(
  report : TapReadinessReport,
  risk : TapReadinessRisk,
) -> Int {
  let mut count = 0
  for item in report.checks {
    if item.risk == risk {
      count += 1
    }
  }
  count
}

///|
/// Return the highest risk present in a report.
pub fn highest_readiness_risk(report : TapReadinessReport) -> TapReadinessRisk {
  let mut risk = RiskPass
  for item in report.checks {
    if readiness_risk_rank(item.risk) > readiness_risk_rank(risk) {
      risk = item.risk
    }
  }
  risk
}

///|
/// Return a one-line summary for terminals and release notes.
pub fn readiness_summary_line(report : TapReadinessReport) -> String {
  "\{report.project}: \{readiness_level_label(report.level)} score=\{report.score} grade=\{readiness_grade(report.score)} blockers=\{blocking_readiness_checks(report).length()} warnings=\{readiness_risk_count(report, RiskWarning)}"
}

///|
/// Render a Markdown report suitable for GitHub job summaries.
pub fn readiness_to_markdown(report : TapReadinessReport) -> String {
  let sb = StringBuilder()
  sb.write_string("# TAPTrail Release Readiness\n\n")
  sb.write_string("- project: ")
  sb.write_string(report.project)
  sb.write_string("\n")
  sb.write_string("- level: ")
  sb.write_string(readiness_level_label(report.level))
  sb.write_string("\n")
  sb.write_string("- score: \{report.score}\n")
  sb.write_string("- grade: ")
  sb.write_string(readiness_grade(report.score))
  sb.write_string("\n")
  sb.write_string("- suite_status: ")
  sb.write_string(suite_status_label(report.suite))
  sb.write_string("\n")
  sb.write_string("- policy_status: ")
  sb.write_string(if report.policy.ok { "ok" } else { "failed" })
  sb.write_string("\n")
  sb.write_string("- highest_risk: ")
  sb.write_string(readiness_risk_label(highest_readiness_risk(report)))
  sb.write_string("\n")
  sb.write_string("\n## Evidence\n\n")
  sb.write_string(readiness_evidence_markdown(report.evidence))
  sb.write_string("\n## Checks\n\n")
  sb.write_string(readiness_checks_to_markdown(report.checks))
  let blockers = blocking_readiness_checks(report)
  if blockers.length() > 0 {
    sb.write_string("\n## Blocking Fixes\n\n")
    sb.write_string(readiness_actions_markdown(blockers))
  }
  let gaps = optional_readiness_gaps(report)
  if gaps.length() > 0 {
    sb.write_string("\n## Optional Improvements\n\n")
    sb.write_string(readiness_actions_markdown(gaps))
  }
  sb.to_string()
}

///|
/// Render only the evidence section as Markdown.
pub fn readiness_evidence_markdown(evidence : TapProjectEvidence) -> String {
  let sb = StringBuilder()
  sb.write_string("| Field | Value |\n")
  sb.write_string("| --- | --- |\n")
  sb.write_string("| package | ")
  sb.write_string(readiness_cell(evidence.package_name))
  sb.write_string(" |\n")
  sb.write_string("| version | ")
  sb.write_string(readiness_cell(evidence.version))
  sb.write_string(" |\n")
  sb.write_string("| repository | ")
  sb.write_string(readiness_cell(evidence.repository))
  sb.write_string(" |\n")
  sb.write_string("| license | ")
  sb.write_string(readiness_cell(evidence.license))
  sb.write_string(" |\n")
  sb.write_string("| examples | \{evidence.examples} |\n")
  sb.write_string("| test_cases | \{evidence.test_cases} |\n")
  sb.write_string("| total_moonbit_lines | \{evidence.total_moonbit_lines} |\n")
  sb.write_string(
    "| effective_moonbit_lines | \{evidence.effective_moonbit_lines} |\n",
  )
  sb.write_string("| commits | \{evidence.commit_count} |\n")
  sb.write_string("| mooncakes | ")
  sb.write_string(
    if evidence.mooncakes_published {
      "published"
    } else {
      "missing"
    },
  )
  sb.write_string(" |\n")
  sb.to_string()
}

///|
/// Render checks as a Markdown table.
pub fn readiness_checks_to_markdown(
  checks : Array[TapReadinessCheck],
) -> String {
  let sb = StringBuilder()
  sb.write_string("| Check | Required | Status | Risk | Score | Evidence |\n")
  sb.write_string("| --- | --- | --- | --- | ---: | --- |\n")
  for item in checks {
    sb.write_string("| `")
    sb.write_string(item.id)
    sb.write_string("` ")
    sb.write_string(readiness_cell(item.title))
    sb.write_string(" | ")
    sb.write_string(if item.required { "yes" } else { "no" })
    sb.write_string(" | ")
    sb.write_string(if item.passed { "pass" } else { "fail" })
    sb.write_string(" | ")
    sb.write_string(readiness_risk_label(item.risk))
    sb.write_string(" | \{item.score}/\{item.max_score} | ")
    sb.write_string(readiness_cell(item.evidence))
    sb.write_string(" |\n")
  }
  sb.to_string()
}

///|
/// Render remediation actions as Markdown bullets.
pub fn readiness_actions_markdown(checks : Array[TapReadinessCheck]) -> String {
  let sb = StringBuilder()
  for item in checks {
    sb.write_string("- `")
    sb.write_string(item.id)
    sb.write_string("`: ")
    sb.write_string(item.remediation)
    sb.write_string("\n")
  }
  sb.to_string()
}

///|
/// Render a compact JSON object for dashboards.
pub fn readiness_to_json(report : TapReadinessReport) -> String {
  let sb = StringBuilder()
  sb.write_string("{")
  sb.write_string("\"project\":\"")
  sb.write_string(json_escape(report.project))
  sb.write_string("\",\"level\":\"")
  sb.write_string(readiness_level_label(report.level))
  sb.write_string("\",\"ok\":")
  sb.write_string(if report.ok { "true" } else { "false" })
  sb.write_string(",\"score\":\{report.score}")
  sb.write_string(",\"grade\":\"")
  sb.write_string(readiness_grade(report.score))
  sb.write_string("\",\"highest_risk\":\"")
  sb.write_string(readiness_risk_label(highest_readiness_risk(report)))
  sb.write_string(
    "\",\"blockers\":\{blocking_readiness_checks(report).length()}",
  )
  sb.write_string(",\"warnings\":\{readiness_risk_count(report, RiskWarning)}")
  sb.write_string(",\"suite_ok\":")
  sb.write_string(if report.suite.ok { "true" } else { "false" })
  sb.write_string(",\"policy_ok\":")
  sb.write_string(if report.policy.ok { "true" } else { "false" })
  sb.write_string(",\"effective_moonbit_lines\":")
  sb.write_string("\{report.evidence.effective_moonbit_lines}")
  sb.write_string(",\"checks\":[")
  for item in report.checks; first = true {
    if first {
      ()
    } else {
      sb.write_string(",")
    }
    sb.write_string("{\"id\":\"")
    sb.write_string(json_escape(item.id))
    sb.write_string("\",\"category\":\"")
    sb.write_string(json_escape(item.category))
    sb.write_string("\",\"required\":")
    sb.write_string(if item.required { "true" } else { "false" })
    sb.write_string(",\"passed\":")
    sb.write_string(if item.passed { "true" } else { "false" })
    sb.write_string(",\"risk\":\"")
    sb.write_string(readiness_risk_label(item.risk))
    sb.write_string(
      "\",\"score\":\{item.score},\"max_score\":\{item.max_score}",
    )
    sb.write_string(",\"title\":\"")
    sb.write_string(json_escape(item.title))
    sb.write_string("\"}")
    continue false
  }
  sb.write_string("]}")
  sb.to_string()
}

///|
/// Render readiness fields as .properties content.
pub fn readiness_to_properties(
  report : TapReadinessReport,
  prefix : String,
) -> String {
  let key = if prefix.length() == 0 { "taptrail" } else { prefix }
  let sb = StringBuilder()
  sb.write_string("\{key}.ready=\{report.ok}\n")
  sb.write_string("\{key}.level=\{readiness_level_label(report.level)}\n")
  sb.write_string("\{key}.score=\{report.score}\n")
  sb.write_string("\{key}.grade=\{readiness_grade(report.score)}\n")
  sb.write_string(
    "\{key}.blockers=\{blocking_readiness_checks(report).length()}\n",
  )
  sb.write_string(
    "\{key}.warnings=\{readiness_risk_count(report, RiskWarning)}\n",
  )
  sb.write_string("\{key}.checks=\{report.checks.length()}\n")
  sb.write_string(
    "\{key}.effective_moonbit_lines=\{report.evidence.effective_moonbit_lines}\n",
  )
  sb.write_string(
    "\{key}.mooncakes_published=\{report.evidence.mooncakes_published}\n",
  )
  sb.write_string("\{key}.ci_configured=\{report.evidence.ci_configured}\n")
  sb.to_string()
}

///|
/// Render readiness values as GitHub environment lines.
pub fn readiness_to_env_lines(
  report : TapReadinessReport,
  prefix : String,
) -> String {
  let key = readiness_env_prefix(prefix)
  let sb = StringBuilder()
  sb.write_string("\{key}_READY=\{report.ok}\n")
  sb.write_string("\{key}_LEVEL=\{readiness_level_label(report.level)}\n")
  sb.write_string("\{key}_SCORE=\{report.score}\n")
  sb.write_string("\{key}_GRADE=\{readiness_grade(report.score)}\n")
  sb.write_string(
    "\{key}_BLOCKERS=\{blocking_readiness_checks(report).length()}\n",
  )
  sb.write_string(
    "\{key}_WARNINGS=\{readiness_risk_count(report, RiskWarning)}\n",
  )
  sb.write_string(
    "\{key}_EFFECTIVE_MOONBIT_LINES=\{report.evidence.effective_moonbit_lines}\n",
  )
  sb.to_string()
}

///|
/// Render one CSV row for spreadsheet-style tracking.
pub fn readiness_to_csv(report : TapReadinessReport) -> String {
  let sb = StringBuilder()
  sb.write_string(
    "project,level,ok,score,grade,blockers,warnings,checks,effective_moonbit_lines\n",
  )
  sb.write_string(csv_escape(report.project))
  sb.write_string(",")
  sb.write_string(readiness_level_label(report.level))
  sb.write_string(",\{report.ok}")
  sb.write_string(",\{report.score}")
  sb.write_string(",")
  sb.write_string(readiness_grade(report.score))
  sb.write_string(",\{blocking_readiness_checks(report).length()}")
  sb.write_string(",\{readiness_risk_count(report, RiskWarning)}")
  sb.write_string(",\{report.checks.length()}")
  sb.write_string(",\{report.evidence.effective_moonbit_lines}\n")
  sb.to_string()
}

///|
/// Render a checkbox list for manual release review.
pub fn readiness_to_checklist(report : TapReadinessReport) -> String {
  let sb = StringBuilder()
  sb.write_string("# Acceptance Checklist\n\n")
  for item in report.checks {
    sb.write_string("- [")
    sb.write_string(if item.passed { "x" } else { " " })
    sb.write_string("] ")
    sb.write_string(item.title)
    sb.write_string(" (`")
    sb.write_string(item.id)
    sb.write_string("`, ")
    sb.write_string(readiness_risk_label(item.risk))
    sb.write_string(")\n")
  }
  sb.to_string()
}

///|
/// Render a short release note sentence.
pub fn readiness_release_note(report : TapReadinessReport) -> String {
  let blockers = blocking_readiness_checks(report).length()
  let warnings = readiness_risk_count(report, RiskWarning)
  let sb = StringBuilder()
  sb.write_string("TapTrail readiness is ")
  sb.write_string(readiness_level_label(report.level))
  sb.write_string(" with score \{report.score}/100")
  sb.write_string(
    " and \{report.evidence.effective_moonbit_lines} effective MoonBit lines.",
  )
  if blockers > 0 {
    sb.write_string(" Blocking checks: \{blockers}.")
  }
  if warnings > 0 {
    sb.write_string(" Optional warnings: \{warnings}.")
  }
  sb.to_string()
}

///|
/// Render a Markdown badge for README or release dashboards.
pub fn readiness_badge_markdown(
  report : TapReadinessReport,
  target_url : String,
) -> String {
  let message = readiness_level_label(report.level)
  let color = if report.level == ReadinessReady {
    "brightgreen"
  } else if report.level == ReadinessNeedsWork {
    "yellow"
  } else {
    "red"
  }
  let url = "https://img.shields.io/badge/taptrail%20readiness-\{url_component(message)}-\{color}"
  if target_url.length() == 0 {
    "![taptrail readiness](\{url})"
  } else {
    "[![taptrail readiness](\{url})](\{target_url})"
  }
}

///|
/// Return concise human-readable recommendations.
pub fn readiness_recommendations(report : TapReadinessReport) -> Array[String] {
  let items : Array[String] = []
  if report.ok {
    items.push(
      "Keep CI, mooncakes.io publication, examples, and test evidence synchronized with the submitted commit.",
    )
  } else {
    for check in failed_readiness_checks(report) {
      items.push("\{check.title}: \{check.remediation}")
    }
  }
  items
}

///|
/// Return true when a package name looks publishable to mooncakes.io.
pub fn package_name_has_namespace(package_name : String) -> Bool {
  match package_name.find("/") {
    Some(index) => index > 0 && index + 1 < package_name.length()
    None => false
  }
}

///|
/// Return true when a repository URL is present and public-looking.
pub fn repository_link_present(repository : String) -> Bool {
  repository.has_prefix("https://github.com/") ||
  repository.has_prefix("http://github.com/") ||
  repository.has_prefix("https://gitlink.org.cn/") ||
  repository.has_prefix("http://gitlink.org.cn/")
}

///|
/// Return true when supplied evidence has a recognized open-source license.
pub fn license_is_recognized(license : String) -> Bool {
  license == "MIT" ||
  license == "Apache-2.0" ||
  license == "BSD-2-Clause" ||
  license == "BSD-3-Clause" ||
  license == "MPL-2.0" ||
  license == "ISC" ||
  license == "LGPL-2.1-or-later" ||
  license == "LGPL-3.0-or-later"
}

///|
/// Return true when the code scale is close to the contest reference range.
pub fn code_scale_matches_reference(evidence : TapProjectEvidence) -> Bool {
  evidence.effective_moonbit_lines >= 4000 &&
  evidence.effective_moonbit_lines <= 10000
}

///|
/// Return true when source scale is meaningful even if still below reference.
pub fn code_scale_is_meaningful(evidence : TapProjectEvidence) -> Bool {
  evidence.effective_moonbit_lines >= 2000 &&
  evidence.total_moonbit_lines >= evidence.effective_moonbit_lines
}

///|
fn build_readiness_checks(
  suite : TapSuiteReport,
  policy : TapPolicyResult,
  evidence : TapProjectEvidence,
) -> Array[TapReadinessCheck] {
  let checks : Array[TapReadinessCheck] = []
  checks.push(
    readiness_check(
      "moonbit-project",
      "project",
      "MoonBit package metadata",
      true,
      package_name_has_namespace(evidence.package_name) &&
      evidence.version.length() > 0,
      8,
      "package=\{evidence.package_name}, version=\{evidence.version}",
      "Set `moon.mod` name to `owner/package` and keep a non-empty version.",
    ),
  )
  checks.push(
    readiness_check(
      "public-repository",
      "submission",
      "Public repository link",
      true,
      repository_link_present(evidence.repository),
      7,
      evidence.repository,
      "Use a public GitHub or Gitlink URL in repository metadata and submission form.",
    ),
  )
  checks.push(
    readiness_check(
      "readme-complete",
      "documentation",
      "README explains purpose, features, and usage",
      true,
      evidence.readme_present &&
      evidence.readme_has_usage &&
      evidence.readme_has_features,
      9,
      "present=\{evidence.readme_present}, usage=\{evidence.readme_has_usage}, features=\{evidence.readme_has_features}",
      "Keep README purpose, feature list, install/run commands, examples, and status links complete.",
    ),
  )
  checks.push(
    readiness_check(
      "ci-configured",
      "automation",
      "Continuous integration configured",
      true,
      evidence.ci_configured,
      8,
      "ci_configured=\{evidence.ci_configured}",
      "Add a CI workflow that runs format, check, build, info, tests, and examples.",
    ),
  )
  checks.push(
    readiness_check(
      "local-build",
      "verification",
      "Local build and standard checks pass",
      true,
      evidence.build_ok,
      8,
      "build_ok=\{evidence.build_ok}",
      "Run `moon check`, `moon build`, and `moon test` before submitting.",
    ),
  )
  checks.push(
    readiness_check(
      "tap-suite-release-policy",
      "verification",
      "TAP suite passes release policy",
      true,
      suite.ok && policy.ok,
      11,
      "suite_ok=\{suite.ok}, policy_ok=\{policy.ok}, reports=\{suite.summary.suites}",
      "Fix failing TAP reports or release-policy errors before tagging the release.",
    ),
  )
  checks.push(
    readiness_check(
      "runnable-examples",
      "usability",
      "Runnable examples are present",
      true,
      evidence.examples >= 1,
      7,
      "examples=\{evidence.examples}",
      "Provide at least one `moon run` example and document the command.",
    ),
  )
  checks.push(
    readiness_check(
      "tests-present",
      "verification",
      "Tests are present and runnable",
      true,
      evidence.test_cases >= 1,
      7,
      "test_cases=\{evidence.test_cases}",
      "Add unit or white-box tests for parser, policy, renderers, and edge cases.",
    ),
  )
  checks.push(
    readiness_check(
      "mooncakes-published",
      "release",
      "Package published to mooncakes.io",
      true,
      evidence.mooncakes_published &&
      evidence.mooncakes_build_ok &&
      evidence.mooncakes_version == evidence.version,
      10,
      "published=\{evidence.mooncakes_published}, version=\{evidence.mooncakes_version}, build=\{evidence.mooncakes_build_ok}",
      "Publish the current version to mooncakes.io and wait for successful package build.",
    ),
  )
  checks.push(
    readiness_check(
      "license-clear",
      "license",
      "Open-source license is clear",
      true,
      license_is_recognized(evidence.license),
      6,
      "license=\{evidence.license}",
      "Keep a root LICENSE file and matching SPDX-like license value in `moon.mod`.",
    ),
  )
  checks.push(
    readiness_check(
      "meaningful-code-scale",
      "implementation",
      "MoonBit implementation is substantial",
      true,
      code_scale_is_meaningful(evidence),
      7,
      "effective=\{evidence.effective_moonbit_lines}, total=\{evidence.total_moonbit_lines}",
      "Keep the main implementation in MoonBit and avoid template-only or demo-only scope.",
    ),
  )
  checks.push(
    readiness_check(
      "contest-scale-reference",
      "implementation",
      "Effective MoonBit lines meet contest scale reference",
      false,
      code_scale_matches_reference(evidence),
      5,
      "effective=\{evidence.effective_moonbit_lines}",
      "Aim for 4k-10k effective MoonBit lines through real features, tests, and examples.",
    ),
  )
  checks.push(
    readiness_check(
      "history-trackable",
      "process",
      "Development history is trackable",
      true,
      evidence.commit_count >= 5,
      5,
      "commits=\{evidence.commit_count}",
      "Keep meaningful commits that show development progress during the contest period.",
    ),
  )
  checks.push(
    readiness_check(
      "maintenance-docs",
      "maintenance",
      "Maintenance documents are present",
      false,
      evidence.has_changelog &&
      evidence.has_design_doc &&
      evidence.has_acceptance_checklist,
      4,
      "changelog=\{evidence.has_changelog}, design=\{evidence.has_design_doc}, checklist=\{evidence.has_acceptance_checklist}",
      "Maintain CHANGELOG, design notes, and acceptance checklist for future maintainers.",
    ),
  )
  checks.push(
    readiness_check(
      "provenance-documented",
      "license",
      "Third-party provenance is documented",
      false,
      evidence.has_provenance_doc,
      4,
      "provenance_doc=\{evidence.has_provenance_doc}",
      "Document dependencies, generated material, fixtures, and license provenance.",
    ),
  )
  checks.push(
    readiness_check(
      "clean-working-tree",
      "release",
      "Repository is clean before push",
      false,
      evidence.clean_tree,
      4,
      "clean_tree=\{evidence.clean_tree}",
      "Remove generated artifacts and commit intended files before publishing.",
    ),
  )
  checks
}

///|
fn readiness_check(
  id : String,
  category : String,
  title : String,
  required : Bool,
  passed : Bool,
  max_score : Int,
  evidence : String,
  remediation : String,
) -> TapReadinessCheck {
  let risk = if passed {
    RiskPass
  } else if required {
    RiskBlock
  } else if max_score >= 5 {
    RiskWarning
  } else {
    RiskNotice
  }
  TapReadinessCheck::{
    id,
    category,
    title,
    required,
    passed,
    score: if passed {
      max_score
    } else {
      0
    },
    max_score,
    risk,
    evidence,
    remediation,
  }
}

///|
fn classify_readiness(
  checks : Array[TapReadinessCheck],
  score : Int,
) -> TapReadinessLevel {
  for item in checks {
    if item.required && !item.passed {
      return ReadinessBlocked
    }
  }
  if score >= 90 {
    ReadinessReady
  } else {
    ReadinessNeedsWork
  }
}

///|
fn readiness_env_prefix(prefix : String) -> String {
  let raw = if prefix.length() == 0 { "TAPTRAIL" } else { prefix }
  let sb = StringBuilder()
  for ch in raw {
    let code = ch.to_int()
    if code >= 97 && code <= 122 {
      sb.write_char(Int::unsafe_to_char(code - 32))
    } else if code >= 65 && code <= 90 {
      sb.write_char(ch)
    } else if code >= 48 && code <= 57 {
      sb.write_char(ch)
    } else {
      sb.write_string("_")
    }
  }
  sb.to_string()
}

///|
fn readiness_cell(text : String) -> String {
  let sb = StringBuilder()
  for ch in text {
    match ch {
      '|' => sb.write_string("\\|")
      '\n' => sb.write_string("
") '\r' => () _ => sb.write_char(ch) } } sb.to_string() }