rules.report
The whole rule corpus joined to the tree and the ledger: per rule, its class, its enforcement mode, the validator and the cases it names, whether each is in the tree, the execution behind each, the CI gates that run them, and the sentence explaining how the state was derived. The tallies count the whole corpus even when the answer is filtered, and the findings name every rule whose declared class the proof does not support. Kept per checkout state, never longer: the ledger is a file that changes outside this process, and an edit of it, of a validator or of any tracked file, a new untracked file, a commit or a new ref is a new answer.
The whole rule corpus joined to the tree and the ledger: per rule, its class, its enforcement mode, the validator and the cases it names, whether each is in the tree, the execution behind each, the CI gates that run them, and the sentence explaining how the state was derived. The tallies count the whole corpus even when the answer is filtered, and the findings name every rule whose declared class the proof does not support. Kept per checkout state, never longer: the ledger is a file that changes outside this process, and an edit of it, of a validator or of any tracked file, a new untracked file, a commit or a new ref is a new answer.
- query
- behaviorally_verified
- module rules
- #rules
- #governance
- #verification
- #evidence
- #gates
Exposure
Where this one definition is reachable. Absence is explicit: a surface not listed does not carry it.
| surface | as |
|---|---|
| MCP | tool majordomus_rules resource majordomus://rules |
| HTTP | GET /api/v1/rules operationId rules.report |
| command line | majordomus rules report |
Schemas
The canonical input and output, from the Rust types; the MCP tool schema and the OpenAPI parameters and responses are derived from these.
input · RulesReportInput
Example
Every field narrows the answer; the tallies still count the whole corpus, so a filtered report never misreports how much of it was examined.
use majordomus_cli::capability::builtin::rules::RulesReportInput;
use majordomus_cli::rules::Class;
let i = RulesReportInput { class: Some(Class::Blocking), ..Default::default() };
assert_eq!(i.class, Some(Class::Blocking));
assert!(!i.findings_only);| property | type | required | description |
|---|---|---|---|
| class | one of 2 | no | Only rules of this class (blocking, advisory). Absent: every rule. |
| findings_only | boolean | no | Only the rules whose declared class the proof does not support, with the findings. The tallies still count the whole corpus, so a filtered answer never misreports how much of it was examined. |
| namespace | string | null | no | Only rules of this namespace — project for this repository's own, majordomus for
the vendored package. Absent: both. |
| state | one of 2 | no | Only rules in this proof state (proven, inputs_unchanged, stale, failing,
not_run, unrunnable, dangling, unproven). Absent: every rule. |
JSON Schema
{
"$defs": {
"RuleClass": {
"description": "What a rule declares about how strongly it binds.\n\nThe repository has exactly two, and they are not severities on a scale: `blocking` means\na gate refuses the work, `advisory` means a reader is expected to have read it. A rule\nwhose front matter says neither is reported as `Class::Unknown` rather than defaulted,\nbecause guessing here is how a blocking rule quietly becomes advice.\n# Example\n\n```\nuse majordomus_cli::rules::Class;\nassert_eq!(Class::Blocking.label(), \"blocking\");\nassert_eq!(Class::parse(\"advisory\"), Class::Advisory);\n```",
"oneOf": [
{
"const": "blocking",
"description": "A gate refuses work that violates it.",
"type": "string"
},
{
"const": "advisory",
"description": "Normative for whoever reads it; nothing refuses a violation.",
"type": "string"
},
{
"const": "unknown",
"description": "The front matter declared no class, or one this repository does not know.",
"type": "string"
}
]
},
"RuleState": {
"description": "What the repository can say about one rule's proof, as a whole.\n\nOrdered strongest to weakest so that a summary sorted by this reads as a ranking. A rule's\nstate is made from its parts' by `crate::evidence::freshness::aggregate`: a failing part\nmakes it failing, and otherwise the weakest part that can carry proof decides.\n# Example\n\n```\nuse majordomus_cli::rules::RuleState;\nassert!(RuleState::Proven < RuleState::Stale);\nassert!(RuleState::Stale.passing());\nassert!(!RuleState::Dangling.passing());\n```",
"oneOf": [
{
"const": "proven",
"description": "Every artifact it names is present, and every test it names has a passing run that\nnothing has invalidated.",
"type": "string"
},
{
"const": "inputs_unchanged",
"description": "Every artifact is present and every test passed, but at least one run is only\nun-invalidated rather than measured against this tree.",
"type": "string"
},
{
"const": "stale",
"description": "A passing run exists, but something it is about has changed since.",
"type": "string"
},
{
"const": "gated",
"description": "An executable gate runs what this rule names, on every CI run that selects it. The\nmechanism is in the tree and wired; no verdict for it is recorded here.",
"type": "string"
},
{
"const": "failing",
"description": "The latest run of a test this rule names did not pass.",
"type": "string"
},
{
"const": "not_run",
"description": "Every artifact is present, and no run of at least one named test was ever recorded.",
"type": "string"
},
{
"const": "reviewed",
"description": "The rule declares, with a stated reason, that nothing executable can express it. An\nhonest exemption: counted apart from every proven rule, never counted as one.",
"type": "string"
},
{
"const": "unrunnable",
"description": "The rule names a path no runner in this repository drives.",
"type": "string"
},
{
"const": "dangling",
"description": "The rule names a path that is not in the tree. A proof that does not exist is worse\nthan no proof, because the rule reads as proven.",
"type": "string"
},
{
"const": "unproven",
"description": "The rule names neither a validator nor a test. Correct for a rule nothing executable\ncan express; a defect for a blocking one.",
"type": "string"
}
]
}
},
"additionalProperties": false,
"description": "Which part of the corpus to answer for.\n# Example\n\nEvery field narrows the answer; the tallies still count the whole corpus, so a filtered\nreport never misreports how much of it was examined.\n\n```\nuse majordomus_cli::capability::builtin::rules::RulesReportInput;\nuse majordomus_cli::rules::Class;\nlet i = RulesReportInput { class: Some(Class::Blocking), ..Default::default() };\nassert_eq!(i.class, Some(Class::Blocking));\nassert!(!i.findings_only);\n```",
"properties": {
"class": {
"anyOf": [
{
"$ref": "#/$defs/RuleClass"
},
{
"type": "null"
}
],
"description": "Only rules of this class (`blocking`, `advisory`). Absent: every rule."
},
"findings_only": {
"description": "Only the rules whose declared class the proof does not support, with the findings.\nThe tallies still count the whole corpus, so a filtered answer never misreports how\nmuch of it was examined.",
"type": "boolean"
},
"namespace": {
"description": "Only rules of this namespace — `project` for this repository's own, `majordomus` for\nthe vendored package. Absent: both.",
"type": [
"string",
"null"
]
},
"state": {
"anyOf": [
{
"$ref": "#/$defs/RuleState"
},
{
"type": "null"
}
],
"description": "Only rules in this proof state (`proven`, `inputs_unchanged`, `stale`, `failing`,\n`not_run`, `unrunnable`, `dangling`, `unproven`). Absent: every rule."
}
},
"title": "RulesReportInput",
"type": "object"
}output · RulesReport
Example
The whole corpus joined to the tree and the ledger. verdict is what the corpus can be
said to prove; satisfied is only that there are no findings, and the two differ
whenever a blocking rule has never been run.
use majordomus_cli::rules::{RulesReport, RulesVerdict};
let r = RulesReport {
head: None,
working_tree: "clean".into(),
verdict: RulesVerdict::Unproven,
rules: vec![],
states: Default::default(),
coverage: Default::default(),
findings: vec![],
satisfied: true,
};
assert!(r.satisfied());
assert_ne!(r.verdict, RulesVerdict::Proven, "no findings is not proof");| property | type | required | description |
|---|---|---|---|
| coverage | reference | yes | The parts of a proof, counted. |
| findings | array | yes | Every rule whose declared class the proof does not support. |
| head | string | null | no | The commit the report was derived against, when git could say. |
| rules | array | yes | Every rule, in canonical id order. |
| satisfied | boolean | yes | Whether there are no findings — and nothing more. A corpus none of whose blocking
rules was ever run is satisfied; verdict is the field that says whether anything
was proven. |
| states | object | yes | How many rules are in each state, by the state's printed word. |
| verdict | reference | yes | What the whole corpus proves: proven, unproven or failing. Derived over the
whole corpus before any filter, like the tallies. |
| working_tree | string | yes | clean, dirty or unknown at the time of derivation. |
JSON Schema
{
"$defs": {
"EvidenceExecution": {
"description": "One recorded run of one test: the whole of what this repository durably remembers about\nit.\n\nEvery field is provenance. A result with no commit is an anonymous green, which is the\nthing a badge must never be derived from.\n\n```\nuse majordomus_cli::evidence::{digest_of, Execution, Origin, Outcome, Runner, TestId};\n\nlet id = TestId::of(\"apps/majordomus-cli/tests/why.rs\").unwrap();\nlet run = Execution {\n test: id.as_string(),\n runner: Runner::Crate,\n source: id.source(),\n outcome: Outcome::Pass,\n seconds: 12,\n commit: \"0\".repeat(40),\n working_tree: \"clean\".into(),\n digest: digest_of(b\"fn main() {}\"),\n at: \"2026-09-11T00:00:00Z\".into(),\n origin: Origin::Ci,\n command: id.reproduce(),\n run: None,\n};\n\n// it is a value in a tracked JSON file, so it has to survive the file unchanged\nlet back: Execution = serde_json::from_str(&serde_json::to_string(&run).unwrap()).unwrap();\nassert_eq!(back, run);\nassert_eq!(back.test, \"crate:why\");\nassert_eq!(back.command, \"cargo test --test why\");\n```\n# Example\n\nOne recorded run, with the provenance the runner did not carry: which commit, which\ntree state, the digest of the test's own source, when, and how to run it again.\n\n```\nuse majordomus_cli::evidence::{Execution, Origin, Outcome, Runner};\nlet e = Execution {\n test: \"suite:07_scope\".into(),\n runner: Runner::Suite,\n source: \"test/cases/07_scope.sh\".into(),\n outcome: Outcome::Pass,\n seconds: 3,\n commit: \"a04b65c9\".into(),\n working_tree: \"clean\".into(),\n digest: \"sha256:00\".into(),\n at: \"2026-09-11T00:00:00Z\".into(),\n origin: Origin::Local,\n command: \"bash test/run.sh 07_scope\".into(),\n run: None,\n};\nassert!(e.outcome.proves());\n```",
"properties": {
"at": {
"description": "When it was recorded, RFC 3339, UTC.",
"type": "string"
},
"command": {
"description": "The exact command that runs this one test again.",
"type": "string"
},
"commit": {
"description": "The full commit id the run was made against.",
"type": "string"
},
"digest": {
"description": "`sha256:<hex>` of the test's own source as it was when the run was recorded. An\nexecution whose test no longer hashes to this did not run the test that is there now.",
"type": "string"
},
"origin": {
"$ref": "#/$defs/EvidenceOrigin",
"description": "Where the run happened."
},
"outcome": {
"$ref": "#/$defs/EvidenceOutcome",
"description": "What it said."
},
"run": {
"anyOf": [
{
"$ref": "#/$defs/EvidenceRun"
},
{
"type": "null"
}
],
"description": "The continuous-integration run the execution was recorded in, when it was recorded in\none that could name itself. Absent for a local run, and absent from every row recorded\nbefore runs were named, which is why the ledger's version did not change."
},
"runner": {
"$ref": "#/$defs/EvidenceRunner",
"description": "Which runner produced it."
},
"seconds": {
"description": "How long it took, in whole seconds.",
"format": "uint64",
"minimum": 0,
"type": "integer"
},
"source": {
"description": "The test's own source, repository-relative.",
"type": "string"
},
"test": {
"description": "The test, in `TestId::as_string` form.",
"type": "string"
},
"working_tree": {
"description": "`clean`, `dirty` or `unknown`: whether the tree the run measured was the commit.",
"type": "string"
}
},
"required": [
"test",
"runner",
"source",
"outcome",
"seconds",
"commit",
"working_tree",
"digest",
"at",
"origin",
"command"
],
"type": "object"
},
"EvidenceOrigin": {
"description": "Where a run happened. The canonical model is provider-neutral: a CI adapter records\n`Ci`, and nothing here knows or cares which CI it was.\n\n```\nuse majordomus_cli::evidence::Origin;\n\nassert_eq!(Origin::parse(\"CI\"), Some(Origin::Ci));\nassert_eq!(Origin::parse(\"local\"), Some(Origin::Local));\n// naming the provider is the adapter's business; the ledger records the kind of run,\n// so a repository that changes CI does not change what its old evidence says\nassert!(Origin::parse(\"github-actions\").is_none());\n```\n# Example\n\n```\nuse majordomus_cli::evidence::Origin;\nassert_eq!(Origin::parse(\"ci\"), Some(Origin::Ci));\nassert_eq!(Origin::parse(\"nowhere\"), None);\n```",
"oneOf": [
{
"const": "local",
"description": "Someone ran it on their own machine.",
"type": "string"
},
{
"const": "ci",
"description": "A continuous-integration run.",
"type": "string"
},
{
"const": "release",
"description": "A release run.",
"type": "string"
}
]
},
"EvidenceOutcome": {
"description": "What a run said about one test.\n\n`NotRun` is deliberately absent: it is the absence of an execution, not an outcome one\nhad. Encoding it here would let a recorder write \"this did not run\" and have it counted\namong the things that did.\n\n```\nuse majordomus_cli::evidence::Outcome;\n\nassert!(Outcome::parse(\"ok\").proves());\nassert!(!Outcome::parse(\"timeout\").proves());\n// exactly one of the five is evidence of anything; the other four are reasons there\n// is none, kept apart because \"it declined\" and \"the harness broke\" are different bugs\nassert_eq!(Outcome::parse(\"skipped\"), Outcome::Skip);\nassert_eq!(Outcome::parse(\"nonsense\"), Outcome::Error);\n```\n# Example\n\n```\nuse majordomus_cli::evidence::Outcome;\nassert!(Outcome::parse(\"ok\").proves());\nassert_eq!(Outcome::parse(\"wat\"), Outcome::Error);\n```",
"oneOf": [
{
"const": "pass",
"description": "It passed.",
"type": "string"
},
{
"const": "fail",
"description": "It failed.",
"type": "string"
},
{
"const": "skip",
"description": "It declined to run and said so (an unmet precondition the case reports itself).",
"type": "string"
},
{
"const": "timeout",
"description": "The bound fired before it finished.",
"type": "string"
},
{
"const": "error",
"description": "The harness could not run it at all.",
"type": "string"
}
]
},
"EvidenceRun": {
"description": "The continuous-integration run an execution was recorded in: enough to navigate back to\nthe run that produced it.\n\n`Origin` says what kind of run it was and deliberately names no provider. This names the\none run, in the words the provider addressed it with when it happened — its identifier,\nits attempt, the workflow and job, and the address a reader follows — because a link built\nlater from a template would point wherever the template's idea of the provider had drifted\nto. Only an adapter constructs it; nothing in the model reads the provider's name.\n\n```\nuse majordomus_cli::evidence::RunRef;\n\nlet actions = |k: &str| {\n let v = match k {\n \"GITHUB_ACTIONS\" => \"true\",\n \"GITHUB_SERVER_URL\" => \"https://github.com\",\n \"GITHUB_REPOSITORY\" => \"owner/repo\",\n \"GITHUB_RUN_ID\" => \"42\",\n \"GITHUB_RUN_ATTEMPT\" => \"2\",\n \"GITHUB_WORKFLOW\" => \"validate\",\n \"GITHUB_JOB\" => \"evidence\",\n _ => return None,\n };\n Some(v.to_string())\n};\nlet run = RunRef::from_env(actions).unwrap();\nassert_eq!(run.id, \"42\");\nassert_eq!(run.attempt, 2);\nassert_eq!(run.url, \"https://github.com/owner/repo/actions/runs/42/attempts/2\");\n// a run that names neither its pull request's head nor its event still names itself\nassert_eq!((run.head_sha, run.event), (None, None));\n\nlet head = \"0123456789abcdef0123456789abcdef01234567\";\nlet pull = |k: &str| match k {\n \"MJ_RUN_HEAD_SHA\" => Some(head.to_string()),\n \"GITHUB_EVENT_NAME\" => Some(\"pull_request\".to_string()),\n _ => actions(k),\n};\nlet run = RunRef::from_env(pull).unwrap();\nassert_eq!(run.head_sha.as_deref(), Some(head));\nassert_eq!(run.event.as_deref(), Some(\"pull_request\"));\n\n// outside a run there is nothing to name, and a half-described run is not a run\nassert!(RunRef::from_env(|_| None).is_none());\nassert!(RunRef::from_env(|k| (k == \"GITHUB_ACTIONS\").then(|| \"true\".to_string())).is_none());\n```",
"properties": {
"attempt": {
"description": "Which attempt of the run, counted from 1.",
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"event": {
"description": "The event that started the run: `push`, `pull_request`, `schedule`,\n`workflow_dispatch`.",
"type": [
"string",
"null"
]
},
"head_sha": {
"description": "The pull request's head commit when the run was a pull-request run (its `commit` is\nGitHub's merge commit, the tree that ran). Carried beside the commit, never\nsubstituted for it.",
"type": [
"string",
"null"
]
},
"id": {
"description": "The provider's identifier of the run.",
"type": "string"
},
"job": {
"description": "The job within the run that recorded the execution.",
"type": "string"
},
"provider": {
"description": "The provider that ran it, as the adapter that recorded it names it.",
"type": "string"
},
"url": {
"description": "Where a reader finds the run, as the provider addressed it at the time.",
"type": "string"
},
"workflow": {
"description": "The workflow the run belongs to.",
"type": "string"
}
},
"required": [
"provider",
"id",
"attempt",
"workflow",
"job",
"url"
],
"type": "object"
},
"EvidenceRunner": {
"description": "Which runner produced a result, and therefore how the test is named and re-run.\n\nThe repository has exactly two that a claim may name today. A third would be a variant\nhere and a branch in `TestId::of`; a claim naming something neither runner produces is\nreported as `ProofState::Unrunnable` rather than silently counted as covered.\n\n```\nuse majordomus_cli::evidence::{Runner, TestId};\n\n// which runner owns a test is read off where the test lives, never declared\nassert_eq!(TestId::of(\"test/cases/07_scope.sh\").unwrap().runner, Runner::Suite);\nassert_eq!(\n TestId::of(\"apps/majordomus-cli/tests/why.rs\").unwrap().runner,\n Runner::Crate\n);\n// and a path under neither directory belongs to no runner at all\nassert!(TestId::of(\"test/lib.sh\").is_none());\n```\n# Example\n\n```\nuse majordomus_cli::evidence::Runner;\nassert_eq!(Runner::Suite.prefix(), \"suite\");\nassert_eq!(Runner::Crate.prefix(), \"crate\");\n```",
"oneOf": [
{
"const": "suite",
"description": "A behavioural case under `test/cases/`, run by `test/run.sh`.",
"type": "string"
},
{
"const": "crate",
"description": "An integration test binary under `apps/majordomus-cli/tests/`, run by `cargo test`.",
"type": "string"
}
]
},
"ProofState": {
"description": "What the repository can say about one claim's proof, right now.\n\nOrdered from strongest to weakest, so a summary that sorts by this reads as a ranking.\n\n```\nuse majordomus_cli::evidence::ProofState;\n\nlet mut states = vec![ProofState::NotRun, ProofState::Stale, ProofState::Proven];\nstates.sort();\nassert_eq!(\n states,\n vec![ProofState::Proven, ProofState::Stale, ProofState::NotRun]\n);\n\n// the two strongest are deliberately not one state: `inputs unchanged` is the absence\n// of a known invalidation, and collapsing it into `proven` is the unaccountable badge\nassert_ne!(ProofState::Proven, ProofState::InputsUnchanged);\nassert!(ProofState::Proven < ProofState::InputsUnchanged);\nassert!(ProofState::InputsUnchanged.passing());\n```\n# Example\n\n```\nuse majordomus_cli::evidence::ProofState;\nassert!(ProofState::Proven.passing());\nassert!(!ProofState::NotRun.passing());\nassert!(!ProofState::InputsUnchanged.meaning().is_empty());\n```",
"oneOf": [
{
"const": "proven",
"description": "A passing run, and nothing has changed since it — the diff against the execution's\nown commit is empty but for the ledger. Proof of the tree in front of you.",
"type": "string"
},
{
"const": "inputs_unchanged",
"description": "A passing run, and nothing this claim names has changed since. Not proof at HEAD:\nsomething the claim does not name may have broken it.",
"type": "string"
},
{
"const": "stale",
"description": "A passing run, but something this claim names has changed since. The proof is older\nthan its subject.",
"type": "string"
},
{
"const": "failing",
"description": "The latest run of this claim's test did not pass.",
"type": "string"
},
{
"const": "not_run",
"description": "The claim names a test a runner owns, and no run of it has ever been recorded.",
"type": "string"
},
{
"const": "unrunnable",
"description": "The claim names a path no runner in this repository drives. Nothing can record it,\nso nothing can prove it this way.",
"type": "string"
},
{
"const": "no_test",
"description": "The claim names no test at all. Correct for a `planned` or `rejected` claim, and a\ndefect for any other.",
"type": "string"
}
]
},
"RuleArtifactKind": {
"description": "What a path a rule names actually is, decided by what drives it rather than by where it\nsits.\n\nThe corpus names two kinds and this distinction is the difference between a verdict and\na mechanism. A **case** is driven by a runner, so an execution of it can be recorded and\nthe repository can show that it passed. A **gate** is an executable check a CI gate runs\nas its own command, or a unit-test module (`src/<module>/tests.rs`) the gate running the\ncrate's `cargo test` compiles: it refuses violations on every run, and this repository\nrecords no verdict for it, so what can be shown is the mechanism and not the result.\nAnything else a rule names is proof only in prose.\n# Example\n\n```\nuse majordomus_cli::rules::ArtifactKind;\nassert_eq!(ArtifactKind::Case.label(), \"case\");\nassert_eq!(ArtifactKind::Gate.label(), \"gate\");\n```",
"oneOf": [
{
"const": "case",
"description": "A behavioural case a runner drives; executions of it are recorded.",
"type": "string"
},
{
"const": "gate",
"description": "An executable check a CI gate runs as its own command, or a unit-test module the\ngate running the crate's `cargo test` compiles.",
"type": "string"
},
{
"const": "unknown",
"description": "Neither. Nothing can run it, so nothing can ever record it.",
"type": "string"
}
]
},
"RuleClass": {
"description": "What a rule declares about how strongly it binds.\n\nThe repository has exactly two, and they are not severities on a scale: `blocking` means\na gate refuses the work, `advisory` means a reader is expected to have read it. A rule\nwhose front matter says neither is reported as `Class::Unknown` rather than defaulted,\nbecause guessing here is how a blocking rule quietly becomes advice.\n# Example\n\n```\nuse majordomus_cli::rules::Class;\nassert_eq!(Class::Blocking.label(), \"blocking\");\nassert_eq!(Class::parse(\"advisory\"), Class::Advisory);\n```",
"oneOf": [
{
"const": "blocking",
"description": "A gate refuses work that violates it.",
"type": "string"
},
{
"const": "advisory",
"description": "Normative for whoever reads it; nothing refuses a violation.",
"type": "string"
},
{
"const": "unknown",
"description": "The front matter declared no class, or one this repository does not know.",
"type": "string"
}
]
},
"RuleCoverage": {
"description": "How much of the rule corpus carries each part of a proof.\n\nEvery number here is counted from the tree. Nothing in this struct may be written down\nanywhere else: a hardcoded rule count is the defect this repository keeps rediscovering.\n# Example\n\nEvery number is counted from the tree; an empty corpus counts zero rather than\nreading as complete, which is what `Coverage::default` is for.\n\n```\nuse majordomus_cli::rules::Coverage;\nlet c = Coverage::default();\nassert_eq!(c.rules, 0);\nassert_eq!(c.review_only, 0);\n```",
"properties": {
"advisory": {
"description": "Of those, advisory.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"artifacts_present": {
"description": "Rules every one of whose named paths is in the tree.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"blocking": {
"description": "Of those, blocking.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"gated": {
"description": "Rules some CI gate runs.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"mechanism_only": {
"description": "Rules whose only executable proof is a gate: a mechanism that refuses violations,\nwith no recorded verdict behind it. Counted apart from `passing` so that the two\nare never read as one number.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"named_proof": {
"description": "Rules naming a validator or at least one test.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"passing": {
"description": "Rules whose recorded runs all passed.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"recorded": {
"description": "Rules every one of whose tests has a recorded run.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"review_only": {
"description": "Rules that declare, with a reason, that a reader enforces them. Counted apart from\nevery executable mode: this number going up is governance getting weaker, and a\nsummary that folded it into a total would hide exactly that.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"rules": {
"description": "Rules discovered.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"runnable": {
"description": "Rules at least one of whose tests a runner owns.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"satisfied": {
"description": "Rules whose state their class can live with.",
"format": "uint",
"minimum": 0,
"type": "integer"
}
},
"required": [
"rules",
"blocking",
"advisory",
"named_proof",
"artifacts_present",
"runnable",
"recorded",
"passing",
"gated",
"mechanism_only",
"review_only",
"satisfied"
],
"type": "object"
},
"RuleDefinition": {
"description": "One rule, as the repository canonically declares it.\n# Example\n\nBuilt by `definitions` from the index rather than by hand. Its ordering is the one\nthe crate has, so a report over the same tree reads the same twice.\n\n```\nuse majordomus_cli::rules::{Class, RuleDefinition};\n# use majordomus_cli::rules::{Enforcement, Mode};\nlet d = RuleDefinition {\n id: \"project.scope-is-declared\".into(),\n identity: \"project.scope-is-declared@1\".into(),\n uri: \"majordomus://rule/project.scope-is-declared@1\".into(),\n version: 1,\n title: \"Scope is declared\".into(),\n description: None,\n statement: None,\n status: \"active\".into(),\n class: Class::Blocking,\n namespace: \"project\".into(),\n depends_on: vec![],\n tags: vec![],\n path: \".ai/repo/rules/project/scope-is-declared.v1.md\".into(),\n enforcement: Enforcement {\n mode: Mode::Declarative, validator: None, category: None, exit_code: None,\n enforced_by: None, tests: vec![], reviewed_because: None,\n },\n};\nassert_eq!(d.class, Class::Blocking);\n```",
"properties": {
"class": {
"$ref": "#/$defs/RuleClass",
"description": "How strongly it binds."
},
"depends_on": {
"description": "The rules it depends on, by id.",
"items": {
"type": "string"
},
"type": "array"
},
"description": {
"description": "The one-line description.",
"type": [
"string",
"null"
]
},
"enforcement": {
"$ref": "#/$defs/RuleEnforcement",
"description": "How it is enforced, as declared."
},
"id": {
"description": "The rule id, `<namespace>.<stem>`, without the version.",
"type": "string"
},
"identity": {
"description": "The identity the index holds, with the version.",
"type": "string"
},
"namespace": {
"description": "Whether it came with the vendored package or belongs to this project.",
"type": "string"
},
"path": {
"description": "Repository-relative path of the rule object.",
"type": "string"
},
"statement": {
"description": "The normative sentence.",
"type": [
"string",
"null"
]
},
"status": {
"description": "`active`, or whatever else the front matter declares.",
"type": "string"
},
"tags": {
"description": "The declared tags.",
"items": {
"type": "string"
},
"type": "array"
},
"title": {
"description": "The title.",
"type": "string"
},
"uri": {
"description": "`majordomus://rule/<identity>`.",
"type": "string"
},
"version": {
"description": "The declared version.",
"format": "uint64",
"minimum": 0,
"type": "integer"
}
},
"required": [
"id",
"identity",
"uri",
"version",
"title",
"status",
"class",
"namespace",
"path",
"enforcement"
],
"type": "object"
},
"RuleEnforcement": {
"description": "The enforcement block of a rule, read from `x-majordomus`.\n# Example\n\nRead from front matter rather than built by hand; this is the shape a gated rule\nproduces, and the mode is decided by what the block actually names.\n\n```\nuse majordomus_cli::rules::{Enforcement, Mode};\nlet e = Enforcement {\n mode: Mode::Gated,\n validator: None,\n category: None,\n exit_code: None,\n enforced_by: None,\n tests: vec![\"test/cases/07_scope.sh\".into()],\n reviewed_because: None,\n};\nassert_eq!(e.mode, Mode::Gated);\n```",
"properties": {
"category": {
"description": "The diagnostic category the validator reports under.",
"type": [
"string",
"null"
]
},
"enforced_by": {
"description": "Which boundary enforces it: the word the rule's own block uses.",
"type": [
"string",
"null"
]
},
"exit_code": {
"description": "The exit code the validator uses to refuse.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"mode": {
"$ref": "#/$defs/RuleMode",
"description": "Which of the two canonical modes, or neither."
},
"reviewed_because": {
"description": "Why nothing executable can express this rule, when the mode is reviewed. Required\nthere: a declared exemption with no reason is the debt it exists to replace.",
"type": [
"string",
"null"
]
},
"tests": {
"description": "Every test the block names, in the order it names them.",
"items": {
"type": "string"
},
"type": "array"
},
"validator": {
"description": "The validator the dispatcher calls, when the mode is dispatched.",
"type": [
"string",
"null"
]
}
},
"required": [
"mode"
],
"type": "object"
},
"RuleFinding": {
"description": "One rule whose declared class the proof does not support.\n# Example\n\n```\nuse majordomus_cli::rules::{Class, Finding, RuleState};\nlet f = Finding {\n rule: \"project.x\".into(),\n class: Class::Blocking,\n state: RuleState::Dangling,\n reason: \"it names a path that is not in the tree\".into(),\n reproduce: \"scripts/ci/rule-proof-check\".into(),\n};\nassert_eq!(f.state, RuleState::Dangling);\n```",
"properties": {
"class": {
"$ref": "#/$defs/RuleClass",
"description": "The class it declares."
},
"reason": {
"description": "Why that combination is a finding.",
"type": "string"
},
"reproduce": {
"description": "The command that shows it again.",
"type": "string"
},
"rule": {
"description": "The rule id.",
"type": "string"
},
"state": {
"$ref": "#/$defs/RuleState",
"description": "The state its proof is in."
}
},
"required": [
"rule",
"class",
"state",
"reason",
"reproduce"
],
"type": "object"
},
"RuleMode": {
"description": "How a rule is enforced, as its own front matter declares it.\n# Example\n\n```\nuse majordomus_cli::rules::Mode;\nassert_eq!(Mode::Dispatched.label(), \"dispatched\");\nassert_eq!(Mode::Declarative.label(), \"declarative\");\n```",
"oneOf": [
{
"const": "dispatched",
"description": "Names a validator the doctrine dispatcher calls at run time.",
"type": "string"
},
{
"const": "gated",
"description": "Names behavioural cases and no validator; a gate runs them.",
"type": "string"
},
{
"const": "reviewed",
"description": "Carries a reason why nothing executable can express it, and so declares that a\nreader enforces it. An honest declaration, not an absence: the reason *is* the\ndeclaration — there is no flag beside it, because a flag can be set and a reason\ncannot be set without writing one — it is counted apart from every executable mode,\nand it separates a rule nobody could automate from a rule nobody got round to.",
"type": "string"
},
{
"const": "declarative",
"description": "Names neither. Correct for a rule nothing executable can express; a defect for a\nblocking one.",
"type": "string"
}
]
},
"RuleProof": {
"description": "One rule, joined to everything the repository can show about it.\n# Example\n\nA `RuleProof` is what `report` produces per rule; `satisfied` is whether the state\nsupports the class the rule declares, which is the whole question.\n\n```\nuse majordomus_cli::rules::{report, RuleProof, RuleState};\nuse majordomus_cli::evidence::Ledger;\nuse majordomus_cli::synthetic::SyntheticRepository;\nlet repo = SyntheticRepository::small().unwrap();\nlet ledger = Ledger::load(repo.root()).unwrap();\nlet r = report(&repo.index().unwrap(), &ledger);\nlet first: &RuleProof = &r.rules[0];\nassert_eq!(first.state, RuleState::Unproven);\nassert!(first.satisfied, \"an advisory rule owes no executable proof\");\n```",
"properties": {
"gates": {
"description": "Every CI gate that runs something this rule names, deduplicated.",
"items": {
"type": "string"
},
"type": "array"
},
"meaning": {
"description": "That state, in one sentence.",
"type": "string"
},
"required_by": {
"description": "The rules that depend on this one, by id — the converse of `depends_on`, which no\nrule declares and which a reader always wants.",
"items": {
"type": "string"
},
"type": "array"
},
"rule": {
"$ref": "#/$defs/RuleDefinition",
"description": "The canonical definition."
},
"satisfied": {
"description": "Whether the state is one this rule's class can live with.",
"type": "boolean"
},
"state": {
"$ref": "#/$defs/RuleState",
"description": "What the repository can say, as a whole."
},
"tests": {
"description": "Every test the rule names, joined to the ledger.",
"items": {
"$ref": "#/$defs/RuleTestProof"
},
"type": "array"
},
"validator": {
"anyOf": [
{
"$ref": "#/$defs/RuleValidator"
},
{
"type": "null"
}
],
"description": "The validator, when the mode is dispatched."
}
},
"required": [
"rule",
"state",
"meaning",
"satisfied"
],
"type": "object"
},
"RuleState": {
"description": "What the repository can say about one rule's proof, as a whole.\n\nOrdered strongest to weakest so that a summary sorted by this reads as a ranking. A rule's\nstate is made from its parts' by `crate::evidence::freshness::aggregate`: a failing part\nmakes it failing, and otherwise the weakest part that can carry proof decides.\n# Example\n\n```\nuse majordomus_cli::rules::RuleState;\nassert!(RuleState::Proven < RuleState::Stale);\nassert!(RuleState::Stale.passing());\nassert!(!RuleState::Dangling.passing());\n```",
"oneOf": [
{
"const": "proven",
"description": "Every artifact it names is present, and every test it names has a passing run that\nnothing has invalidated.",
"type": "string"
},
{
"const": "inputs_unchanged",
"description": "Every artifact is present and every test passed, but at least one run is only\nun-invalidated rather than measured against this tree.",
"type": "string"
},
{
"const": "stale",
"description": "A passing run exists, but something it is about has changed since.",
"type": "string"
},
{
"const": "gated",
"description": "An executable gate runs what this rule names, on every CI run that selects it. The\nmechanism is in the tree and wired; no verdict for it is recorded here.",
"type": "string"
},
{
"const": "failing",
"description": "The latest run of a test this rule names did not pass.",
"type": "string"
},
{
"const": "not_run",
"description": "Every artifact is present, and no run of at least one named test was ever recorded.",
"type": "string"
},
{
"const": "reviewed",
"description": "The rule declares, with a stated reason, that nothing executable can express it. An\nhonest exemption: counted apart from every proven rule, never counted as one.",
"type": "string"
},
{
"const": "unrunnable",
"description": "The rule names a path no runner in this repository drives.",
"type": "string"
},
{
"const": "dangling",
"description": "The rule names a path that is not in the tree. A proof that does not exist is worse\nthan no proof, because the rule reads as proven.",
"type": "string"
},
{
"const": "unproven",
"description": "The rule names neither a validator nor a test. Correct for a rule nothing executable\ncan express; a defect for a blocking one.",
"type": "string"
}
]
},
"RuleTestProof": {
"description": "One test a rule names, joined to what was recorded against it.\n# Example\n\n```\nuse majordomus_cli::rules::{ArtifactKind, TestProof};\nuse majordomus_cli::evidence::ProofState;\nlet t = TestProof {\n path: \"test/cases/07_scope.sh\".into(),\n kind: ArtifactKind::Case,\n present: true,\n test: Some(\"suite:07_scope\".into()),\n state: ProofState::NotRun,\n meaning: ProofState::NotRun.meaning().into(),\n execution: None,\n reproduce: Some(\"bash test/run.sh 07_scope\".into()),\n gates: vec![\"shell-suite\".into()],\n};\nassert_eq!(t.kind, ArtifactKind::Case);\n```",
"properties": {
"execution": {
"anyOf": [
{
"$ref": "#/$defs/EvidenceExecution"
},
{
"type": "null"
}
],
"description": "The execution behind the state, when there is one."
},
"gates": {
"description": "The CI gates that run this test, derived from the repository's own CI model.",
"items": {
"type": "string"
},
"type": "array"
},
"kind": {
"$ref": "#/$defs/RuleArtifactKind",
"description": "What drives it: a runner, a CI gate, or nothing."
},
"meaning": {
"description": "That state, in one sentence, from the one place it is worded.",
"type": "string"
},
"path": {
"description": "The path the rule names.",
"type": "string"
},
"present": {
"description": "Whether that path is in the tree.",
"type": "boolean"
},
"reproduce": {
"description": "The command that runs this test again.",
"type": [
"string",
"null"
]
},
"state": {
"$ref": "#/$defs/ProofState",
"description": "What the repository can say about this test's latest run."
},
"test": {
"description": "The canonical test identity (`suite:<case>`, `crate:<binary>`), when a runner owns\nthe path. Absent means no runner drives it, so no run of it can ever be recorded.",
"type": [
"string",
"null"
]
}
},
"required": [
"path",
"kind",
"present",
"state",
"meaning"
],
"type": "object"
},
"RuleValidator": {
"description": "The validator a dispatched rule names, and whether anything defines it.\n\nA validator is **not a path**. `validator: adr` names the shell function\n`mj_validate_adr`, which the doctrine dispatcher calls; the tool finds it by scanning\n`lib/`, exactly as `majordomus doctor` does. Reading it as a path is a mistake worth\nrecording here, because it is the one this type was introduced to fix: it makes every\ndispatched rule in the vendored package report as naming something that is not in the\ntree, which is the opposite of true — those are the best-enforced rules there are.\n# Example\n\n```\nuse majordomus_cli::rules::ValidatorRef;\nlet v = ValidatorRef {\n name: \"adr\".into(),\n function: \"mj_validate_adr\".into(),\n defined_in: Some(\"lib/adr.sh\".into()),\n present: true,\n};\nassert_eq!(v.function, \"mj_validate_adr\");\n```",
"properties": {
"defined_in": {
"description": "The file that defines it, when one does.",
"type": [
"string",
"null"
]
},
"function": {
"description": "The function the dispatcher calls.",
"type": "string"
},
"name": {
"description": "The name the rule declares, without the `mj_validate_` prefix.",
"type": "string"
},
"present": {
"description": "Whether anything in `lib/` defines it.",
"type": "boolean"
}
},
"required": [
"name",
"function",
"present"
],
"type": "object"
},
"RulesVerdict": {
"description": "What the whole corpus can be said to prove, in one word, before any number is read.\n\n`satisfied` answers a narrower question — are there findings — and a corpus in which no\nblocking rule was ever run has none, because `not run`, `gated` and `reviewed` are weaker\nstates rather than defects (docs/DOCTRINE.md). Read alone, `satisfied: true` over such a\ncorpus says \"every rule is enforced\" about a repository that has shown nothing. The\nverdict is the answer that cannot be read that way: it is `proven` only when every\nblocking rule is `proven` — a passing run recorded on a clean tree, at a commit that\nnothing but the evidence ledger has changed since. A rule whose inputs are merely\nunchanged is not that (ADR 0041), and leaves the corpus `unproven`.\n# Example\n\n```\nuse majordomus_cli::rules::{RuleState, RulesVerdict};\n// a corpus with a finding is failing, whatever else is true of it\nassert_eq!(RulesVerdict::of([RuleState::Proven], true), RulesVerdict::Failing);\n// one blocking rule never run is enough to leave the corpus unproven\nassert_eq!(\n RulesVerdict::of([RuleState::Proven, RuleState::NotRun], false),\n RulesVerdict::Unproven\n);\nassert_eq!(RulesVerdict::of([RuleState::Proven], false), RulesVerdict::Proven);\n// a pass whose inputs are merely unchanged is not proven\nassert_eq!(\n RulesVerdict::of([RuleState::Proven, RuleState::InputsUnchanged], false),\n RulesVerdict::Unproven\n);\n```",
"oneOf": [
{
"const": "proven",
"description": "Every blocking rule is proven: a passing run recorded on a clean tree, at a commit\nthat nothing but the evidence ledger has changed since.",
"type": "string"
},
{
"const": "unproven",
"description": "No rule is a finding, and at least one blocking rule is not proven — never run,\ngated, reviewed, stale, or passing with only its inputs unchanged — or there is no\nblocking rule at all.",
"type": "string"
},
{
"const": "failing",
"description": "At least one rule declares a class its proof does not support.",
"type": "string"
}
]
}
},
"description": "The whole rule corpus, verified.\n# Example\n\nThe whole corpus joined to the tree and the ledger. `verdict` is what the corpus can be\nsaid to prove; `satisfied` is only that there are no findings, and the two differ\nwhenever a blocking rule has never been run.\n\n```\nuse majordomus_cli::rules::{RulesReport, RulesVerdict};\nlet r = RulesReport {\n head: None,\n working_tree: \"clean\".into(),\n verdict: RulesVerdict::Unproven,\n rules: vec![],\n states: Default::default(),\n coverage: Default::default(),\n findings: vec![],\n satisfied: true,\n};\nassert!(r.satisfied());\nassert_ne!(r.verdict, RulesVerdict::Proven, \"no findings is not proof\");\n```",
"properties": {
"coverage": {
"$ref": "#/$defs/RuleCoverage",
"description": "The parts of a proof, counted."
},
"findings": {
"description": "Every rule whose declared class the proof does not support.",
"items": {
"$ref": "#/$defs/RuleFinding"
},
"type": "array"
},
"head": {
"description": "The commit the report was derived against, when git could say.",
"type": [
"string",
"null"
]
},
"rules": {
"description": "Every rule, in canonical id order.",
"items": {
"$ref": "#/$defs/RuleProof"
},
"type": "array"
},
"satisfied": {
"description": "Whether there are no findings — and nothing more. A corpus none of whose blocking\nrules was ever run is `satisfied`; `verdict` is the field that says whether anything\nwas proven.",
"type": "boolean"
},
"states": {
"additionalProperties": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"description": "How many rules are in each state, by the state's printed word.",
"type": "object"
},
"verdict": {
"$ref": "#/$defs/RulesVerdict",
"description": "What the whole corpus proves: `proven`, `unproven` or `failing`. Derived over the\nwhole corpus before any filter, like the tallies."
},
"working_tree": {
"description": "`clean`, `dirty` or `unknown` at the time of derivation.",
"type": "string"
}
},
"required": [
"working_tree",
"verdict",
"rules",
"states",
"coverage",
"findings",
"satisfied"
],
"title": "RulesReport",
"type": "object"
}Policies
- benchmark
- required — a target on every transport the exposure declares; the cases are the input type's
- cache
- checkout — up to 8 entries in the process, scoped by the registry fingerprint, the context's reading of the repository and the checkout's state (HEAD, the index, the refs, every changed path)
Benchmark targets
Derived from the registry for this repository: one requirement per transport, and the cases the input type provides. The whole matrix is on the benchmarks page.