Expand description
The two planning records an intent is held to before execution: the gap and the critique.
Majordomus does not reason about what is missing or what a plan overlooked. A worker does — a person, Claude, Codex, Gemini — and writes what it found into a typed record, so that planning starts from a recorded analysis rather than from a prompt, and so that the analysis can be refused (ADR 0073):
- a gap (
.ai/repo/project/gaps/<intent>.yaml,majordomus.gap/v1) states, at one commit, the observations made of the repository, the state of every criterion of the intent against them (satisfied,missing,conflictingorunknown), the risks, and the work it suggests; - a critique (
.ai/repo/project/critiques/<intent>.yaml,majordomus.critique/v1) records the adversarial pass over the plan: each finding has a class, a subject, whether it blocks execution, and a resolution —open,plannedinto an issue that serves the intent, orrejectedwith a reason.
What this module decides is only whether the records hold together and whether the plan
honours them. A gap must answer every criterion and cite an observation for every answer
that is not unknown. A criterion the gap observed satisfied needs no planned work; every
other criterion still does (that is the coverage’s question). A finding planned into an
issue must name an issue that exists and serves the intent. And no issue serving an intent
may have started while the intent has no critique, or while a blocking finding is open.
Every function here is pure over parsed records, the intent outlines and the plan.
use majordomus_cli::intent_plan::IntentOutline;
use majordomus_cli::intent_review::{review, GapRecord};
use majordomus_cli::plan::Plan;
let intent = IntentOutline {
id: "x".into(),
criteria: vec!["a".into(), "b".into()],
milestones: vec!["m".into()],
..Default::default()
};
// a gap that answers one criterion and leaves the other out is refused, by name
let gap = GapRecord::from_metadata(".ai/repo/project/gaps/x.yaml", &serde_json::json!({
"intent": "x", "observed_at": "c3f20da",
"observations": [{"id": "o1", "statement": "nothing there", "source": "file:src"}],
"conditions": [{"criterion": "a", "state": "missing", "observations": ["o1"]}],
}));
let findings = review(&[intent], &plan, &[gap], &[]);
assert!(findings.iter().any(|f| f.code == "gap_criterion_unanswered" && f.subject == "x#b"));Structs§
- Critique
Finding - One critique finding: what the review found, what it is about, whether it blocks execution,
and how it was resolved.
classandresolutionareNonewhen the record spells one this module does not know, and the_textfields keep what was written. - Critique
Record - A critique record: the adversarial pass over one intent’s plan, at the commit it was reviewed at, with every finding and its resolution. One per intent, named by it.
- GapCondition
- One criterion’s state against the observations, as the record spells it.
stateisNonewhen the file names a state this module does not know, andstate_textkeeps what was written so the finding can quote it. - GapObservation
- One observation of the current state, with the place it was observed in — a file, a command, a test or a URL — so a reader can go and look at the same thing.
- GapRecord
- A gap record: the observations a worker made of the repository at one commit, the state of every criterion of the intent against them, the risks, and the work it suggests. One per intent, named by it.
- GapWork
- One work item the gap suggests: what it would do, the criteria it would make true, and the issue it became once somebody planned it. Nothing turns this into an issue automatically; the link is recorded when a worker writes the issue.
Enums§
- Condition
State - The state of one criterion as the gap observed it. Four values, because “not determined”
has to be writable: an omitted criterion is refused, and
Unknownis never a pass. - Critique
Class - The class of a critique finding: the question the adversarial pass asked. Closed, so that a review’s findings can be counted by question rather than read as prose.
- Resolution
State - How a critique finding was resolved: not yet, by planning work that serves the intent, or
by rejecting it with a reason. A blocking finding left
Openrefuses execution.
Constants§
Functions§
- observed_
satisfied - The criteria a gap observed already satisfied, by intent: the ones coverage does not ask
work of. A condition counts only if it is
satisfiedand cites at least one observation the gap declares. - review
- The findings of the gap and critique records against the intents and the plan: whether each record holds together, and whether execution waited for the review.