///|
fn definition(
id : String,
category : RuleCategory,
severity : Severity,
title : String,
description : String,
remediation : String,
profiles : Array[String],
) -> RuleDefinition {
RuleDefinition::new(
id, category, severity, title, description, remediation, profiles,
)
}
///|
/// Return the complete stable v1 rule catalog.
pub fn rule_catalog() -> Array[RuleDefinition] {
[
definition(
"missing_moon_mod",
Manifest,
Error,
"moon.mod is required",
"A MoonBit module needs moon.mod at its root.",
"Create moon.mod with name, version, readme, repository and license metadata.",
["default", "github", "mooncakes", "release"],
),
definition(
"missing_root_moon_pkg",
Package,
Warn,
"root moon.pkg is recommended",
"A reusable root package should make its package boundary explicit.",
"Add an empty or imported moon.pkg at the module root.",
["github", "mooncakes", "release"],
),
definition(
"missing_readme",
Documentation,
Warn,
"README is recommended",
"Public repositories need a visible project overview.",
"Add README.md with usage, development and license sections.",
["default", "github", "mooncakes", "release"],
),
definition(
"missing_github_readme",
Documentation,
Info,
"GitHub README is missing",
"README.mbt.md is useful to MoonBit but GitHub normally shows README.md.",
"Add README.md or a repository-supported link.",
["github", "release"],
),
definition(
"missing_license",
Release,
Error,
"LICENSE is required",
"Open-source reuse needs an explicit license file.",
"Add the selected license text at repository root.",
["default", "github", "mooncakes", "release"],
),
definition(
"license_mismatch",
Release,
Warn,
"License metadata should match",
"moon.mod and LICENSE should describe the same license.",
"Align moon.mod license with the LICENSE text.",
["github", "mooncakes", "release"],
),
definition(
"missing_gitignore",
Release,
Info,
"Git ignore file is recommended",
"Generated artifacts should stay out of commits.",
"Add .gitignore with _build/ and .mooncakes/.",
["default", "github", "mooncakes", "release"],
),
definition(
"gitignore_missing_build",
Release,
Info,
"Ignore build artifacts",
"MoonBit build output should not be committed.",
"Add _build/ to .gitignore.",
["github", "release"],
),
definition(
"gitignore_missing_mooncakes",
Release,
Info,
"Ignore fetched dependencies",
"Mooncakes downloads are normally local state.",
"Add .mooncakes/ to .gitignore unless intentionally vendored.",
["github", "release"],
),
definition(
"missing_ci",
Ci,
Info,
"CI is recommended",
"Public packages benefit from repeatable quality gates.",
"Add GitHub Actions to run moon check and moon test.",
["github", "release"],
),
definition(
"ci_missing_moon_check",
Ci,
Warn,
"CI should run moon check",
"A workflow without type checking cannot catch basic regressions.",
"Add moon check to the workflow.",
["github", "release"],
),
definition(
"ci_missing_moon_test",
Ci,
Warn,
"CI should run moon test",
"A workflow should execute the package test suite.",
"Add moon test to the workflow.",
["github", "release"],
),
definition(
"missing_examples",
Documentation,
Info,
"Examples are recommended",
"Runnable examples reduce adoption cost.",
"Add an examples directory with source or documentation.",
["github", "mooncakes", "release"],
),
definition(
"examples_missing_content",
Documentation,
Info,
"Examples need useful content",
"An empty examples directory is not a user-facing example.",
"Add a .mbt example, moon.pkg, or README under examples.",
["github", "mooncakes", "release"],
),
definition(
"missing_tests",
Package,
Warn,
"Tests are recommended",
"Core behavior should be protected by MoonBit tests.",
"Add _test.mbt or _wbtest.mbt files.",
["default", "github", "mooncakes", "release"],
),
definition(
"missing_name",
Manifest,
Warn,
"Module name is missing",
"Packages need a stable module import name.",
"Set name in moon.mod.",
["default", "mooncakes", "release"],
),
definition(
"missing_version",
Manifest,
Warn,
"Version is missing",
"Published packages need a semantic version.",
"Set version in moon.mod.",
["mooncakes", "release"],
),
definition(
"missing_readme_metadata",
Manifest,
Warn,
"Readme metadata is missing",
"Package metadata should point to the readme file.",
"Set readme in moon.mod.",
["mooncakes", "release"],
),
definition(
"missing_repository",
Manifest,
Info,
"Repository metadata is missing",
"A package should link to its source.",
"Set repository in moon.mod.",
["github", "mooncakes", "release"],
),
definition(
"missing_description",
Manifest,
Info,
"Description metadata is missing",
"Search and discovery need a short description.",
"Set description in moon.mod.",
["mooncakes", "release"],
),
definition(
"missing_keywords",
Manifest,
Info,
"Keywords metadata is missing",
"Keywords improve package discovery.",
"Set keywords in moon.mod.",
["mooncakes", "release"],
),
definition(
"readme_target_missing",
Manifest,
Warn,
"Readme target is missing",
"moon.mod points to a file that does not exist.",
"Update readme or add the referenced file.",
["github", "mooncakes", "release"],
),
definition(
"repository_placeholder",
Manifest,
Warn,
"Repository is a placeholder",
"A release should point to its real source repository.",
"Replace the placeholder URL.",
["github", "mooncakes", "release"],
),
definition(
"repository_unusual",
Manifest,
Info,
"Repository host is unusual",
"Known hosts improve user confidence.",
"Use a stable GitHub or Gitlink URL when possible.",
["github", "mooncakes", "release"],
),
definition(
"description_placeholder",
Manifest,
Info,
"Description is a placeholder",
"Placeholder metadata harms discovery.",
"Write a concrete one-sentence summary.",
["mooncakes", "release"],
),
definition(
"keywords_placeholder",
Manifest,
Info,
"Keywords are placeholders",
"Placeholder keywords do not help search.",
"Use domain-specific searchable terms.",
["mooncakes", "release"],
),
definition(
"package_missing_source",
Package,
Warn,
"Package has no source",
"A package manifest without source files is usually accidental.",
"Add source files or remove the package manifest.",
["release"],
),
definition(
"package_missing_tests",
Package,
Info,
"Package has no tests",
"Multi-package modules should protect each package boundary.",
"Add package-level tests or document why none are needed.",
["release"],
),
definition(
"package_missing_local_import",
Package,
Error,
"Local import cannot be resolved",
"A local package import does not map to any moon.pkg.",
"Fix the import path or add the missing package.",
["default", "github", "mooncakes", "release"],
),
definition(
"package_cycle",
Package,
Error,
"Local package dependency cycle",
"MoonBit package imports must remain acyclic.",
"Extract shared code into a lower-level package.",
["default", "github", "mooncakes", "release"],
),
]
}
///|
pub fn find_rule_definition(rule_id : String) -> RuleDefinition? {
for rule in rule_catalog() {
if rule.id == rule_id {
return Some(rule)
}
}
None
}
///|
pub fn rules_for_profile(profile : DoctorProfile) -> Array[RuleDefinition] {
let expected = profile.label()
let rules : Array[RuleDefinition] = []
for rule in rule_catalog() {
if rule.profiles.contains(expected) || rule.profiles.contains("default") {
rules.push(rule)
}
}
rules
}
///|
pub fn render_rule_catalog() -> String {
let builder = StringBuilder()
for rule in rule_catalog() {
builder.write_string(
"[" +
rule.default_severity.label() +
"] " +
rule.id +
" - " +
rule.title +
"\n",
)
}
builder.to_string()
}