capsuletrace-upload

MoonBit-native capability boundary and acceptance trace validator

moonbit
traceability
validation
acceptance
ci
mooncakes
moon add SHX-ai-nb/capsuletrace-upload@0.2.0
Download zip
Author
Version
0.2.0
License
MIT
Last updated
18 hours ago
Downloads
3
README

#CapsuleTrace

CapsuleTrace is a MoonBit-native capability boundary and acceptance trace validator. It helps package authors describe what a project does, what it does not do, which requirements must be proven, and which tests, examples, CI jobs, documents, or releases prove those requirements. It also provides policy gates, canonical manifest rendering, evidence matrices, and compatibility reviews for release workflows.

#What It Solves

Many small open-source packages have tests and examples, but reviewers still need to infer the functional boundary by reading scattered files. CapsuleTrace turns that boundary into a compact line manifest, validates references, normalizes snapshot text, and produces reviewer-friendly Markdown or JSON reports.

#Use Cases

  • MoonBit libraries that need a clear acceptance checklist.
  • CLI or Wasm examples that need deterministic offline validation.
  • Hackathon projects that must show README, tests, CI, examples, and release evidence.
  • Maintainers who want a small traceability layer without external services.

#Install

moon add SHX-ai-nb/capsuletrace-upload

Mooncakes package name:

SHX-ai-nb/capsuletrace-upload

The package owner is configured as SHX-ai-nb. If your Mooncakes owner is different, update moon.mod, cmd/main/moon.pkg, and this install command before publishing.

#Minimal Example

fn main {
let report = validate_manifest(sample_manifest())
println(report.to_markdown())
}

Run the included smoke example:

moon run cmd/main

#Manifest Format

CapsuleTrace uses line records:

project: CapsuleTrace purpose: Validate capability boundaries and acceptance evidence. scope: Parse compact line manifests. out-of-scope: Execute shell commands at runtime. capability: parse-manifest | Parse records | text manifest | BoundarySpec | deterministic, offline requirement: R1 | must | Parser accepts supported records. | parse-manifest evidence: T1 | test | capsuletrace_wbtest.mbt | verified | R1 | Unit tests cover parser behavior.

#Core API

  • parse_manifest(raw) parses a line manifest into BoundarySpec.
  • validate_spec(spec) validates a parsed boundary spec.
  • validate_manifest(raw) parses and validates in one step.
  • TraceReport::to_markdown() exports a human-readable report.
  • TraceReport::to_json_string() exports structured CI-friendly JSON.
  • manifest_template(project, purpose) creates a parseable starting template.
  • validate_manifest_with_policy(raw, policy) applies development, release, or strict policy gates.
  • normalize_manifest(raw) trims, deduplicates, and canonically orders valid manifest records.
  • build_trace_matrix(spec) links each requirement to its evidence and coverage state.
  • compare_manifests(before, after) identifies added, removed, and modified trace entities, including breaking changes.

#Release Review Example

Run the included policy and compatibility-review example:

moon run cmd/audit

The example runs a strict policy, renders an evidence matrix, normalizes a manifest, and demonstrates how removing a declared capability is reported as a breaking change. Its release evidence is a self-contained fixture for demonstrating the API; it does not claim that this repository has already been published to Mooncakes.

Use the APIs in your own release workflow:

let raw = strict_ready_manifest()
let report = validate_manifest_with_policy(raw, strict_policy())
let matrix = build_trace_matrix(report.spec)
let delta = compare_manifests(raw, next_release_manifest)

println(report.to_policy_markdown(strict_policy()))
println(matrix.to_markdown())
println(delta.to_markdown())

#Supported

  • Project purpose and supported/non-supported scope records.
  • Capability records with inputs, outputs, and constraints.
  • Requirement records with must, should, and may levels.
  • Evidence records for test, example, ci, doc, release, and design.
  • Duplicate ID checks, broken reference checks, missing evidence checks, scoring, Markdown export, and JSON export.
  • Development, release, and strict validation policies with configurable counts and required evidence kinds.
  • Stable normalization for snapshot review, including whitespace cleanup and list-value deduplication.
  • Requirement-to-evidence matrices with verified, pending, rejected, and missing coverage states.
  • Manifest-to-manifest change review with explicit breaking-change classification.

#Not Supported

  • Runtime filesystem scanning.
  • Shell command execution.
  • Network calls to Mooncakes or GitHub at runtime.
  • Full TOML, YAML, JSON Schema, or SPDX parsing.

#Local Verification

moon check moon fmt --check moon build moon test moon run cmd/main moon run cmd/audit moon publish --dry-run

Current local verification:

moon check: passed moon build: passed moon test: 23 passed, 0 failed moon run cmd/main: passed moon run cmd/audit: passed moon publish --dry-run: requires moon login with the publisher account

#Mooncakes Release

Recommended release flow:

moon login moon publish --dry-run moon publish

After publishing, verify:

https://mooncakes.io/docs/SHX-ai-nb/capsuletrace-upload https://mooncakes.io/api/v0/manifest/SHX-ai-nb/capsuletrace-upload

#License And Third-Party Notice

CapsuleTrace is licensed under MIT. The implementation is original MoonBit code and does not include third-party source code, private code, external datasets, images, fonts, or media assets.

#
BoundarySpec

pub(all) struct BoundarySpec {
project : String
purpose : String
scopes : Array[String]
out_of_scope : Array[String]
capabilities : Array[Capability]
requirements : Array[Requirement]
evidence : Array[Evidence]
issues : Array[TraceIssue]
} derive(Eq,
Debug
)

#
BoundarySpec::capability

fn BoundarySpec::capability(self : BoundarySpec, id : StringView) -> Capability?

#
BoundarySpec::evidence_for_requirement

fn BoundarySpec::evidence_for_requirement(self : BoundarySpec, requirement_id : StringView) -> Array[Evidence]

#
BoundarySpec::evidence_item

fn BoundarySpec::evidence_item(self : BoundarySpec, id : StringView) -> Evidence?

#
BoundarySpec::requirement

fn BoundarySpec::requirement(self : BoundarySpec, id : StringView) -> Requirement?

#
BoundarySpec::requirements_for_capability

fn BoundarySpec::requirements_for_capability(self : BoundarySpec, capability_id : StringView) -> Array[Requirement]

#
Capability

pub(all) struct Capability {
id : String
title : String
inputs : Array[String]
outputs : Array[String]
constraints : Array[String]
} derive(Eq,
Debug
)

#
ChangeImpact

pub(all) enum ChangeImpact {
Breaking
Review
Informational
} derive(Eq,
Debug
)

Impact is deliberately conservative. Removing a promised capability or a required behavior is treated as breaking even when source compilation still succeeds.

#
ChangeImpact::label

fn ChangeImpact::label(self : ChangeImpact) -> String

#
ChangeKind

pub(all) enum ChangeKind {
Added
Removed
Modified
} derive(Eq,
Debug
)

Change classification for a single trace entity between two snapshots.

#
ChangeKind::label

fn ChangeKind::label(self : ChangeKind) -> String

#
CoverageState

pub(all) enum CoverageState {
VerifiedCoverage
PendingCoverage
RejectedCoverage
MissingCoverage
} derive(Eq,
Debug
)

A coverage state is derived from all evidence linked to a requirement. Verified evidence wins, because a requirement may retain historical failed evidence alongside a newer passing test or release artifact.

#
CoverageState::is_satisfied

fn CoverageState::is_satisfied(self : CoverageState) -> Bool

#
CoverageState::label

fn CoverageState::label(self : CoverageState) -> String

#
EntityChange

pub(all) struct EntityChange {
category : String
id : String
kind : ChangeKind
impact : ChangeImpact
before : String
after : String
} derive(Eq,
Debug
)

#
Evidence

pub(all) struct Evidence {
id : String
kind : EvidenceKind
target : String
status : EvidenceStatus
requirements : Array[String]
note : String
} derive(Eq,
Debug
)

#
EvidenceKind

pub(all) enum EvidenceKind {
Test
Example
CI
Doc
Release
Design
} derive(Eq,
Debug
)

#
EvidenceKind::label

fn EvidenceKind::label(self : EvidenceKind) -> String

#
EvidenceStatus

pub(all) enum EvidenceStatus {
Verified
Pending
Rejected
} derive(Eq,
Debug
)

#
EvidenceStatus::label

fn EvidenceStatus::label(self : EvidenceStatus) -> String

#
EvidenceSummary

pub(all) struct EvidenceSummary {
kind : EvidenceKind
total : Int
verified : Int
pending : Int
rejected : Int
} derive(Eq,
Debug
)

#
EvidenceSummary::is_healthy

fn EvidenceSummary::is_healthy(self : EvidenceSummary) -> Bool

#
NormalizationChange

pub(all) struct NormalizationChange {
category : String
subject : String
before : String
after : String
} derive(Eq,
Debug
)

#
NormalizationOptions

pub(all) struct NormalizationOptions {
sort_records : Bool
sort_list_values : Bool
deduplicate_list_values : Bool
compact_whitespace : Bool
drop_empty_values : Bool
} derive(Eq,
Debug
)

Options for producing stable manifest text suitable for reviews and snapshots. Normalization is deliberately opt-in: it returns a new specification and never changes the caller's original data.

#
NormalizationResult

pub(all) struct NormalizationResult {
spec : BoundarySpec
changes : Array[NormalizationChange]
source_issues : Array[TraceIssue]
} derive(Eq,
Debug
)

#
NormalizationResult::changed

fn NormalizationResult::changed(self : NormalizationResult) -> Bool

#
NormalizationResult::is_lossless

fn NormalizationResult::is_lossless(self : NormalizationResult) -> Bool

#
NormalizationResult::to_manifest

fn NormalizationResult::to_manifest(self : NormalizationResult) -> String

#
NormalizationResult::to_markdown

fn NormalizationResult::to_markdown(self : NormalizationResult) -> String

#
PolicyProfile

pub(all) enum PolicyProfile {
Development
Release
Strict
} derive(Eq,
Debug
)

Named policy presets let the same manifest be reviewed for different stages of a project: local development, a release candidate, or a strict audit.

#
PolicyProfile::label

fn PolicyProfile::label(self : PolicyProfile) -> String

#
Requirement

pub(all) struct Requirement {
id : String
level : RequirementLevel
text : String
capabilities : Array[String]
} derive(Eq,
Debug
)

#
RequirementLevel

pub(all) enum RequirementLevel {
Must
Should
May
} derive(Eq,
Debug
)

CapsuleTrace parses and validates capability-boundary manifests.

A manifest is intentionally line-oriented so it can live in README files, design notes, CI fixtures, and small Wasm demos without external parsers.

#
RequirementLevel::label

fn RequirementLevel::label(self : RequirementLevel) -> String

#
Severity

pub(all) enum Severity {
Critical
High
Medium
Low
Info
} derive(Eq,
Debug
)

#
Severity::label

fn Severity::label(self : Severity) -> String

#
Severity::weight

fn Severity::weight(self : Severity) -> Int

#
SpecDelta

pub(all) struct SpecDelta {
before_project : String
after_project : String
summary_changes : Array[SummaryChange]
capability_changes : Array[EntityChange]
requirement_changes : Array[EntityChange]
evidence_changes : Array[EntityChange]
} derive(Eq,
Debug
)

#
SpecDelta::all_entity_changes

fn SpecDelta::all_entity_changes(self : SpecDelta) -> Array[EntityChange]

#
SpecDelta::breaking_changes

fn SpecDelta::breaking_changes(self : SpecDelta) -> Array[EntityChange]

#
SpecDelta::change_count

fn SpecDelta::change_count(self : SpecDelta) -> Int

#
SpecDelta::has_breaking_change

fn SpecDelta::has_breaking_change(self : SpecDelta) -> Bool

#
SpecDelta::is_empty

fn SpecDelta::is_empty(self : SpecDelta) -> Bool

#
SpecDelta::requires_review

fn SpecDelta::requires_review(self : SpecDelta) -> Bool

#
SpecDelta::to_json_string

fn SpecDelta::to_json_string(self : SpecDelta) -> String

#
SpecDelta::to_markdown

fn SpecDelta::to_markdown(self : SpecDelta) -> String

#
SummaryChange

pub(all) struct SummaryChange {
field : String
before : String
after : String
impact : ChangeImpact
} derive(Eq,
Debug
)

#
TraceFinding

pub(all) struct TraceFinding {
id : String
severity : Severity
subject : String
message : String
remediation : String
} derive(Eq,
Debug
)

#
TraceIssue

pub(all) struct TraceIssue {
kind : TraceIssueKind
line : Int
record : String
message : String
} derive(Eq,
Debug
)

#
TraceIssueKind

pub(all) enum TraceIssueKind {
MalformedLine
UnknownRecord
MissingField
InvalidLevel
InvalidEvidenceKind
InvalidEvidenceStatus
} derive(Eq,
Debug
)

#
TraceIssueKind::label

fn TraceIssueKind::label(self : TraceIssueKind) -> String

#
TraceMatrix

pub(all) struct TraceMatrix {
project : String
rows : Array[TraceRow]
evidence_summaries : Array[EvidenceSummary]
} derive(Eq,
Debug
)

#
TraceMatrix::coverage_percent

fn TraceMatrix::coverage_percent(self : TraceMatrix) -> Int

#
TraceMatrix::covered_requirements

fn TraceMatrix::covered_requirements(self : TraceMatrix) -> Int

#
TraceMatrix::must_requirements_ready

fn TraceMatrix::must_requirements_ready(self : TraceMatrix) -> Bool

#
TraceMatrix::outstanding_rows

fn TraceMatrix::outstanding_rows(self : TraceMatrix) -> Array[TraceRow]

#
TraceMatrix::row

fn TraceMatrix::row(self : TraceMatrix, requirement_id : StringView) -> TraceRow?

#
TraceMatrix::rows_for_capability

fn TraceMatrix::rows_for_capability(self : TraceMatrix, capability_id : StringView) -> Array[TraceRow]

#
TraceMatrix::rows_in_state

fn TraceMatrix::rows_in_state(self : TraceMatrix, state : CoverageState) -> Array[TraceRow]

#
TraceMatrix::summary

fn TraceMatrix::summary(self : TraceMatrix) -> String

#
TraceMatrix::summary_for_kind

fn TraceMatrix::summary_for_kind(self : TraceMatrix, kind : EvidenceKind) -> EvidenceSummary?

#
TraceMatrix::to_json_string

fn TraceMatrix::to_json_string(self : TraceMatrix) -> String

#
TraceMatrix::to_markdown

fn TraceMatrix::to_markdown(self : TraceMatrix) -> String

#
TraceReport

pub(all) struct TraceReport {
score : Int
grade : String
ready : Bool
findings : Array[TraceFinding]
spec : BoundarySpec
} derive(Eq,
Debug
)

#
TraceReport::count_by_severity

fn TraceReport::count_by_severity(self : TraceReport, severity : Severity) -> Int

#
TraceReport::coverage_percent

fn TraceReport::coverage_percent(self : TraceReport) -> Int

#
TraceReport::covered_requirements

fn TraceReport::covered_requirements(self : TraceReport) -> Int

#
TraceReport::has_finding

fn TraceReport::has_finding(self : TraceReport, id : StringView) -> Bool

#
TraceReport::policy_summary

fn TraceReport::policy_summary(self : TraceReport, policy : ValidationPolicy) -> String

#
TraceReport::to_json_string

fn TraceReport::to_json_string(self : TraceReport) -> String

#
TraceReport::to_markdown

fn TraceReport::to_markdown(self : TraceReport) -> String

#
TraceReport::to_policy_markdown

fn TraceReport::to_policy_markdown(self : TraceReport, policy : ValidationPolicy) -> String

#
TraceRow

pub(all) struct TraceRow {
requirement_id : String
level : RequirementLevel
text : String
capability_ids : Array[String]
evidence_ids : Array[String]
verified_evidence_ids : Array[String]
state : CoverageState
} derive(Eq,
Debug
)

#
ValidationPolicy

pub(all) struct ValidationPolicy {
name : String
minimum_capabilities : Int
minimum_requirements : Int
minimum_evidence : Int
require_out_of_scope : Bool
require_verified_test : Bool
require_verified_example : Bool
require_verified_ci : Bool
require_verified_doc : Bool
require_verified_release : Bool
reject_pending_evidence : Bool
require_should_evidence : Bool
require_unique_targets : Bool
require_lowercase_ids : Bool
require_capability_scope : Bool
require_capability_constraints : Bool
minimum_project_length : Int
minimum_purpose_length : Int
} derive(Eq,
Debug
)

#
build_trace_matrix

fn build_trace_matrix(spec : BoundarySpec) -> TraceMatrix

Build a requirement-to-evidence matrix that can be rendered independently of the full validator report. It is useful when a maintainer wants to see which promises lack evidence without scanning all findings.

#
capability_to_manifest_line

fn capability_to_manifest_line(capability : Capability) -> String

#
compare_manifests

fn compare_manifests(before : StringView, after : StringView) -> SpecDelta

#
compare_specs

fn compare_specs(before : BoundarySpec, after : BoundarySpec) -> SpecDelta

Compare two parsed specifications by stable entity identifier. The result contains only changes, so an empty delta is convenient for CI gates.

#
default_normalization_options

fn default_normalization_options() -> NormalizationOptions

#
development_policy

fn development_policy() -> ValidationPolicy

#
evidence_to_manifest_line

fn evidence_to_manifest_line(item : Evidence) -> String

#
incomplete_manifest

fn incomplete_manifest() -> String

#
manifest_template

fn manifest_template(project : String, purpose : String) -> String

#
normalize_manifest

fn normalize_manifest(raw : StringView) -> NormalizationResult

Parse, normalize, and describe the changes made to a manifest. Invalid source records are retained as source issues; callers should only overwrite files when result.is_lossless() is true.

#
normalize_manifest_with_options

fn normalize_manifest_with_options(raw : StringView, options : NormalizationOptions) -> NormalizationResult

#
normalize_spec

fn normalize_spec(source : BoundarySpec, options : NormalizationOptions) -> NormalizationResult

#
parse_evidence_kind

fn parse_evidence_kind(value : StringView) -> EvidenceKind?

#
parse_evidence_status

fn parse_evidence_status(value : StringView) -> EvidenceStatus?

#
parse_level

fn parse_level(value : StringView) -> RequirementLevel?

#
parse_manifest

fn parse_manifest(raw : StringView) -> BoundarySpec

#
policy_for

fn policy_for(profile : PolicyProfile) -> ValidationPolicy

#
preserve_order_normalization_options

fn preserve_order_normalization_options() -> NormalizationOptions

#
release_policy

fn release_policy() -> ValidationPolicy

#
requirement_to_manifest_line

fn requirement_to_manifest_line(requirement : Requirement) -> String

#
sample_manifest

fn sample_manifest() -> String

#
sort_strings_ascending

fn sort_strings_ascending(values : Array[String]) -> Array[String]

The manifests involved here are intentionally small. Insertion sorting avoids target-specific ordering surprises while keeping canonical output stable.

#
spec_to_manifest

fn spec_to_manifest(spec : BoundarySpec) -> String

Render valid manifest records in canonical record order. This is useful for snapshot tests and generated review artifacts, not as a replacement for a parser error message.

#
strict_policy

fn strict_policy() -> ValidationPolicy

#
strict_ready_manifest

fn strict_ready_manifest() -> String

A complete offline fixture for release-policy examples, integration tests, and documentation. It includes distinct artifacts for tests, CI, docs, and a package release, so it also satisfies the strict profile.

#
validate_manifest

fn validate_manifest(raw : StringView) -> TraceReport

#
validate_manifest_with_policy

fn validate_manifest_with_policy(raw : StringView, policy : ValidationPolicy) -> TraceReport

#
validate_spec

fn validate_spec(spec : BoundarySpec) -> TraceReport

#
validate_spec_with_policy

fn validate_spec_with_policy(spec : BoundarySpec, policy : ValidationPolicy) -> TraceReport

Apply the standard structural checks together with a caller-supplied policy. The policy never mutates the source specification, which makes it safe to run multiple policy profiles against one parsed manifest in CI.

Powered by MoonBit

Site sourceReport issuePackagesBuild queueSkillsStatistics

© 2026 mooncakes.io