///|
pub(all) enum MaintenanceRecordKind {
IssueRecord
PullRequestRecord
TestRecord
ChangelogEntry
ReleaseRecord
DesignDecision
LicenseNote
CiRunRecord
} derive(Eq, Debug)
///|
pub(all) enum MaintenanceState {
Planned
InProgress
Done
Deferred
BlockedState
} derive(Eq, Debug)
///|
pub(all) struct MaintenanceRecord {
id : String
kind : MaintenanceRecordKind
title : String
state : MaintenanceState
evidence : String
link : String
owner : String
date : String
note : String
} derive(Eq, Debug)
///|
pub fn MaintenanceRecord::MaintenanceRecord(
id? : String = "",
kind? : MaintenanceRecordKind = IssueRecord,
title? : String = "",
state? : MaintenanceState = Done,
evidence? : String = "",
link? : String = "",
owner? : String = "",
date? : String = "",
note? : String = "",
) -> MaintenanceRecord {
{ id, kind, title, state, evidence, link, owner, date, note }
}
///|
pub(all) struct MaintenancePolicy {
min_issue_records : Int
min_test_records : Int
require_changelog : Bool
require_release : Bool
require_design_notes : Bool
require_license_note : Bool
require_ci_record : Bool
require_evidence_for_done : Bool
} derive(Eq, Debug)
///|
pub fn MaintenancePolicy::MaintenancePolicy(
min_issue_records? : Int = 1,
min_test_records? : Int = 1,
require_changelog? : Bool = true,
require_release? : Bool = true,
require_design_notes? : Bool = true,
require_license_note? : Bool = true,
require_ci_record? : Bool = true,
require_evidence_for_done? : Bool = true,
) -> MaintenancePolicy {
{
min_issue_records,
min_test_records,
require_changelog,
require_release,
require_design_notes,
require_license_note,
require_ci_record,
require_evidence_for_done,
}
}
///|
pub(all) struct MaintenanceFinding {
id : String
severity : Severity
title : String
detail : String
repair : String
evidence : String
penalty : Int
} derive(Eq, Debug)
///|
pub(all) struct MaintenanceReport {
score : Int
verdict : String
records : Array[MaintenanceRecord]
findings : Array[MaintenanceFinding]
record_count : Int
completed_count : Int
open_count : Int
evidence_count : Int
issue_count : Int
test_count : Int
release_count : Int
changelog_count : Int
design_count : Int
ci_count : Int
license_count : Int
} derive(Eq, Debug)
///|
pub fn maintenance_review(
records : Array[MaintenanceRecord],
policy? : MaintenancePolicy = MaintenancePolicy::MaintenancePolicy(),
) -> MaintenanceReport {
let findings = maintenance_findings(records, policy)
let score = maintenance_score(findings)
let completed_count = count_records_by_state(records, Done)
let open_count = records.length() - completed_count
let evidence_count = count_records_with_evidence(records)
{
score,
verdict: maintenance_verdict(findings, score),
records,
findings,
record_count: records.length(),
completed_count,
open_count,
evidence_count,
issue_count: count_records_by_kind(records, IssueRecord),
test_count: count_records_by_kind(records, TestRecord),
release_count: count_records_by_kind(records, ReleaseRecord),
changelog_count: count_records_by_kind(records, ChangelogEntry),
design_count: count_records_by_kind(records, DesignDecision),
ci_count: count_records_by_kind(records, CiRunRecord),
license_count: count_records_by_kind(records, LicenseNote),
}
}
///|
pub fn maintenance_markdown(
records : Array[MaintenanceRecord],
policy? : MaintenancePolicy = MaintenancePolicy::MaintenancePolicy(),
) -> String {
maintenance_review(records, policy~).to_markdown()
}
///|
pub fn maintenance_json(
records : Array[MaintenanceRecord],
policy? : MaintenancePolicy = MaintenancePolicy::MaintenancePolicy(),
) -> String {
maintenance_review(records, policy~).to_json()
}
///|
pub fn MaintenanceReport::has_blockers(self : MaintenanceReport) -> Bool {
for finding in self.findings {
if finding.severity == Fail {
return true
}
}
false
}
///|
pub fn MaintenanceReport::warning_count(self : MaintenanceReport) -> Int {
let mut total = 0
for finding in self.findings {
if finding.severity == Warn {
total += 1
}
}
total
}
///|
pub fn MaintenanceReport::repair_steps(
self : MaintenanceReport,
) -> Array[String] {
let steps = Array::new(capacity=self.findings.length())
for finding in self.findings {
if finding.severity != Pass && finding.repair != "" {
steps.push(finding.repair)
}
}
steps
}
///|
pub fn MaintenanceReport::records_for_kind(
self : MaintenanceReport,
kind : MaintenanceRecordKind,
) -> Array[MaintenanceRecord] {
let out = Array::new(capacity=self.records.length())
for record in self.records {
if record.kind == kind {
out.push(record)
}
}
out
}
///|
pub fn MaintenanceReport::to_markdown(self : MaintenanceReport) -> String {
let out = StringBuilder()
out.write_string("# HarborCheck Maintenance Evidence\n\n")
out.write_string("- Verdict: " + self.verdict + "\n")
out.write_string("- Score: " + self.score.to_string() + "/100\n")
out.write_string("- Records: " + self.record_count.to_string() + "\n")
out.write_string("- Completed: " + self.completed_count.to_string() + "\n")
out.write_string("- Open: " + self.open_count.to_string() + "\n")
out.write_string(
"- Evidence-backed: " + self.evidence_count.to_string() + "\n\n",
)
out.write_string("## Coverage\n\n")
out.write_string("- Issues: " + self.issue_count.to_string() + "\n")
out.write_string("- Tests: " + self.test_count.to_string() + "\n")
out.write_string("- Changelog: " + self.changelog_count.to_string() + "\n")
out.write_string("- Releases: " + self.release_count.to_string() + "\n")
out.write_string(
"- Design decisions: " + self.design_count.to_string() + "\n",
)
out.write_string("- CI runs: " + self.ci_count.to_string() + "\n")
out.write_string(
"- License notes: " + self.license_count.to_string() + "\n\n",
)
out.write_string("## Findings\n\n")
for finding in self.findings {
out.write_string("- [" + severity_text(finding.severity) + "] ")
out.write_string(finding.id + ": " + finding.title)
if finding.evidence != "" {
out.write_string(" -- " + finding.evidence)
}
if finding.repair != "" && finding.severity != Pass {
out.write_string(" Fix: " + finding.repair)
}
out.write_string("\n")
}
out.write_string("\n## Records\n\n")
for record in self.records {
out.write_string("- " + record.id + " ")
out.write_string("(" + maintenance_kind_text(record.kind) + ", ")
out.write_string(maintenance_state_text(record.state) + "): ")
out.write_string(record.title)
if record.evidence != "" {
out.write_string(" -- " + record.evidence)
} else if record.link != "" {
out.write_string(" -- " + record.link)
}
out.write_string("\n")
}
out.to_string()
}
///|
pub fn MaintenanceReport::to_json(self : MaintenanceReport) -> String {
let out = StringBuilder()
out.write_string("{")
out.write_string("\"verdict\":\"" + json_escape(self.verdict) + "\",")
out.write_string("\"score\":" + self.score.to_string() + ",")
out.write_string("\"record_count\":" + self.record_count.to_string() + ",")
out.write_string(
"\"completed_count\":" + self.completed_count.to_string() + ",",
)
out.write_string("\"open_count\":" + self.open_count.to_string() + ",")
out.write_string(
"\"evidence_count\":" + self.evidence_count.to_string() + ",",
)
out.write_string("\"coverage\":{")
out.write_string("\"issues\":" + self.issue_count.to_string() + ",")
out.write_string("\"tests\":" + self.test_count.to_string() + ",")
out.write_string("\"changelog\":" + self.changelog_count.to_string() + ",")
out.write_string("\"releases\":" + self.release_count.to_string() + ",")
out.write_string("\"design\":" + self.design_count.to_string() + ",")
out.write_string("\"ci\":" + self.ci_count.to_string() + ",")
out.write_string("\"license\":" + self.license_count.to_string())
out.write_string("},")
out.write_string("\"findings\":[")
for i in 0.. 0 {
out.write_string(",")
}
out.write_string("{")
out.write_string("\"id\":\"" + json_escape(finding.id) + "\",")
out.write_string(
"\"severity\":\"" + severity_text(finding.severity) + "\",",
)
out.write_string("\"title\":\"" + json_escape(finding.title) + "\",")
out.write_string("\"detail\":\"" + json_escape(finding.detail) + "\",")
out.write_string("\"repair\":\"" + json_escape(finding.repair) + "\",")
out.write_string("\"evidence\":\"" + json_escape(finding.evidence) + "\"")
out.write_string("}")
}
out.write_string("],")
out.write_string("\"records\":[")
for i in 0.. 0 {
out.write_string(",")
}
out.write_string("{")
out.write_string("\"id\":\"" + json_escape(record.id) + "\",")
out.write_string("\"kind\":\"" + maintenance_kind_text(record.kind) + "\",")
out.write_string(
"\"state\":\"" + maintenance_state_text(record.state) + "\",",
)
out.write_string("\"title\":\"" + json_escape(record.title) + "\",")
out.write_string("\"evidence\":\"" + json_escape(record.evidence) + "\",")
out.write_string("\"link\":\"" + json_escape(record.link) + "\",")
out.write_string("\"owner\":\"" + json_escape(record.owner) + "\",")
out.write_string("\"date\":\"" + json_escape(record.date) + "\"")
out.write_string("}")
}
out.write_string("]}")
out.to_string()
}
///|
pub fn example_maintenance_records() -> Array[MaintenanceRecord] {
[
MaintenanceRecord(
id="issue-001",
kind=IssueRecord,
title="Define README example and provenance proof boundary",
state=Done,
evidence="docs/design.md and docs/issues.md",
owner="EJJ-ai-nb",
date="2026-08-17",
note="Tracks the project scope expected by reviewers.",
),
MaintenanceRecord(
id="test-001",
kind=TestRecord,
title="Run check, build, test, fmt, docs and runnable examples",
state=Done,
evidence="docs/test-record.md",
owner="EJJ-ai-nb",
date="2026-08-20",
note="Local verification and CI evidence are both retained.",
),
MaintenanceRecord(
id="change-001",
kind=ChangelogEntry,
title="Record release changes for 0.1.x packages",
state=Done,
evidence="CHANGELOG.md",
owner="EJJ-ai-nb",
date="2026-08-20",
),
MaintenanceRecord(
id="release-001",
kind=ReleaseRecord,
title="Publish HarborCheck to Mooncakes",
state=Done,
evidence="EJJ-ai-nb/harborcheck 0.1.4",
link="https://mooncakes.io/docs/EJJ-ai-nb/harborcheck",
owner="EJJ-ai-nb",
date="2026-08-20",
),
MaintenanceRecord(
id="design-001",
kind=DesignDecision,
title="Keep HarborCheck pure MoonBit and snapshot-driven",
state=Done,
evidence="docs/design.md",
owner="EJJ-ai-nb",
date="2026-08-20",
),
MaintenanceRecord(
id="ci-001",
kind=CiRunRecord,
title="GitHub Actions verifies check, build, test and examples",
state=Done,
evidence="ci success on main",
link="https://github.com/EJJ-ai-nb/harborcheck/actions",
owner="EJJ-ai-nb",
date="2026-08-20",
),
MaintenanceRecord(
id="license-001",
kind=LicenseNote,
title="Document MIT license and absence of bundled third-party assets",
state=Done,
evidence="LICENSE and README license section",
owner="EJJ-ai-nb",
date="2026-08-20",
),
]
}
///|
fn maintenance_findings(
records : Array[MaintenanceRecord],
policy : MaintenancePolicy,
) -> Array[MaintenanceFinding] {
let findings = Array::new(capacity=12)
push_record_volume_finding(findings, records)
push_kind_minimum_finding(
findings,
records,
IssueRecord,
policy.min_issue_records,
"trace.issues",
"Issue or work-item records are retained",
"Add a concise issue/work-item record for the implemented scope.",
)
push_kind_minimum_finding(
findings,
records,
TestRecord,
policy.min_test_records,
"trace.tests",
"Test records are retained",
"Record the latest local and CI verification commands.",
)
push_required_kind_finding(
findings,
records,
ChangelogEntry,
policy.require_changelog,
"trace.changelog",
"Changelog evidence is retained",
"Add or update CHANGELOG.md for the published version.",
)
push_required_kind_finding(
findings,
records,
ReleaseRecord,
policy.require_release,
"trace.release",
"Version release evidence is retained",
"Record the Mooncakes package version and release link.",
)
push_required_kind_finding(
findings,
records,
DesignDecision,
policy.require_design_notes,
"trace.design",
"Design notes are retained",
"Add a short technical decision note or design document.",
)
push_required_kind_finding(
findings,
records,
CiRunRecord,
policy.require_ci_record,
"trace.ci",
"CI run evidence is retained",
"Record the latest green main-branch CI run.",
)
push_required_kind_finding(
findings,
records,
LicenseNote,
policy.require_license_note,
"trace.license",
"License and source notes are retained",
"Record the project license and any third-party source notes.",
)
if policy.require_evidence_for_done {
push_done_evidence_finding(findings, records)
}
push_open_work_finding(findings, records)
findings
}
///|
fn push_record_volume_finding(
findings : Array[MaintenanceFinding],
records : Array[MaintenanceRecord],
) -> Unit {
if records.length() >= 5 {
findings.push(
maintenance_pass(
"trace.volume",
"Development evidence has enough records",
records.length().to_string() + " records",
),
)
} else if records.length() > 0 {
findings.push(
maintenance_warn(
"trace.volume",
"Development evidence is thin",
records.length().to_string() + " records",
"Keep at least five concise records across issues, tests, releases and design notes.",
penalty=5,
),
)
} else {
findings.push(
maintenance_fail(
"trace.volume",
"No development evidence records were supplied",
"0 records",
"Add issue, test, changelog, release and design records before review.",
penalty=16,
),
)
}
}
///|
fn push_kind_minimum_finding(
findings : Array[MaintenanceFinding],
records : Array[MaintenanceRecord],
kind : MaintenanceRecordKind,
minimum : Int,
id : String,
title : String,
repair : String,
) -> Unit {
let count = count_records_by_kind(records, kind)
if count >= minimum {
findings.push(maintenance_pass(id, title, count.to_string() + " records"))
} else {
findings.push(
maintenance_fail(
id,
title + " are missing",
count.to_string() + "/" + minimum.to_string(),
repair,
penalty=12,
),
)
}
}
///|
fn push_required_kind_finding(
findings : Array[MaintenanceFinding],
records : Array[MaintenanceRecord],
kind : MaintenanceRecordKind,
required : Bool,
id : String,
title : String,
repair : String,
) -> Unit {
if !required {
findings.push(maintenance_pass(id, title, "not required by policy"))
return
}
let count = count_records_by_kind(records, kind)
if count > 0 {
findings.push(maintenance_pass(id, title, count.to_string() + " records"))
} else {
findings.push(
maintenance_fail(id, title + " missing", "0 records", repair, penalty=10),
)
}
}
///|
fn push_done_evidence_finding(
findings : Array[MaintenanceFinding],
records : Array[MaintenanceRecord],
) -> Unit {
let mut missing = 0
for record in records {
if record.state == Done && !record_has_evidence(record) {
missing += 1
}
}
if missing == 0 {
findings.push(
maintenance_pass(
"trace.done-evidence", "Completed records have evidence", "all completed records are backed by evidence",
),
)
} else {
findings.push(
maintenance_warn(
"trace.done-evidence",
"Some completed records lack evidence",
missing.to_string() + " completed records",
"Attach a file path, release link or concise evidence string to completed records.",
penalty=missing * 3,
),
)
}
}
///|
fn push_open_work_finding(
findings : Array[MaintenanceFinding],
records : Array[MaintenanceRecord],
) -> Unit {
let mut blocked = 0
let mut open = 0
for record in records {
if record.state == BlockedState {
blocked += 1
} else if record.state == Planned ||
record.state == InProgress ||
record.state == Deferred {
open += 1
}
}
if blocked > 0 {
findings.push(
maintenance_fail(
"trace.blocked-work",
"Blocked maintenance records remain",
blocked.to_string() + " blocked records",
"Resolve or explicitly defer blocked review work before final acceptance.",
penalty=14,
),
)
} else if open > 0 {
findings.push(
maintenance_warn(
"trace.open-work",
"Open maintenance records remain",
open.to_string() + " open records",
"Make sure open records describe follow-up work, not unfinished promised scope.",
penalty=4,
),
)
} else {
findings.push(
maintenance_pass(
"trace.closed-work", "No blocked maintenance records remain", "all records are completed",
),
)
}
}
///|
fn count_records_by_kind(
records : Array[MaintenanceRecord],
kind : MaintenanceRecordKind,
) -> Int {
let mut total = 0
for record in records {
if record.kind == kind {
total += 1
}
}
total
}
///|
fn count_records_by_state(
records : Array[MaintenanceRecord],
state : MaintenanceState,
) -> Int {
let mut total = 0
for record in records {
if record.state == state {
total += 1
}
}
total
}
///|
fn count_records_with_evidence(records : Array[MaintenanceRecord]) -> Int {
let mut total = 0
for record in records {
if record_has_evidence(record) {
total += 1
}
}
total
}
///|
fn record_has_evidence(record : MaintenanceRecord) -> Bool {
has_text(record.evidence) || has_text(record.link) || has_text(record.note)
}
///|
fn maintenance_score(findings : Array[MaintenanceFinding]) -> Int {
let mut score = 100
for finding in findings {
score -= finding.penalty
}
if score < 0 {
0
} else {
score
}
}
///|
fn maintenance_verdict(
findings : Array[MaintenanceFinding],
score : Int,
) -> String {
let mut fail_count = 0
let mut warn_count = 0
for finding in findings {
if finding.severity == Fail {
fail_count += 1
} else if finding.severity == Warn {
warn_count += 1
}
}
if fail_count > 0 {
"trace-blocked"
} else if score >= 95 && warn_count == 0 {
"trace-ready"
} else if score >= 80 {
"trace-ready-with-notes"
} else {
"trace-needs-work"
}
}
///|
fn maintenance_pass(
id : String,
title : String,
evidence : String,
) -> MaintenanceFinding {
{
id,
severity: Pass,
title,
detail: "Requirement satisfied.",
repair: "",
evidence,
penalty: 0,
}
}
///|
fn maintenance_warn(
id : String,
title : String,
detail : String,
repair : String,
penalty? : Int = 4,
) -> MaintenanceFinding {
{ id, severity: Warn, title, detail, repair, evidence: detail, penalty }
}
///|
fn maintenance_fail(
id : String,
title : String,
detail : String,
repair : String,
penalty? : Int = 10,
) -> MaintenanceFinding {
{ id, severity: Fail, title, detail, repair, evidence: detail, penalty }
}
///|
fn maintenance_kind_text(kind : MaintenanceRecordKind) -> String {
match kind {
IssueRecord => "issue"
PullRequestRecord => "pull-request"
TestRecord => "test"
ChangelogEntry => "changelog"
ReleaseRecord => "release"
DesignDecision => "design"
LicenseNote => "license"
CiRunRecord => "ci"
}
}
///|
fn maintenance_state_text(state : MaintenanceState) -> String {
match state {
Planned => "planned"
InProgress => "in-progress"
Done => "done"
Deferred => "deferred"
BlockedState => "blocked"
}
}