70. An intent is a typed record, and its stage and satisfaction are derived from the plan and the evidence
Context
The project model says what work exists: milestones are outcomes, issues are execution
contracts, and plan.rs derives every status from what happened to them. The evidence
fabric says what ran: docs/CLAIMS.yaml names a test, and the ledger holds the run. Neither
says what the work was for. The public site said so plainly — there was no intent object, no
intent registry and no intent id — and every question of the form "which outcome does this
change serve" or "did finishing these milestones achieve anything" was answered, if at all,
from a prompt that did not survive its session.
Two ways to add the missing layer were open. One gives an intent a lifecycle of its own: a status field, transitions, a stamp when a pull request merges. The other treats an intent as a statement whose standing is computed from records the repository already keeps.
Decision
An intent is a YAML record under .ai/repo/project/intents/, kind intent, schema
majordomus.intent/v1: an id, a title, the statement that must become true, the
invariants that must stay true, the milestones that realise it, and satisfaction
criteria, each {id, criterion, evidence, ref} with evidence one of test, claim,
command or deployment. Optional governance, non_goals, cancelled and
superseded_by. The kind is declared in the distribution's share/kinds.yaml and its class
in both this repository's and the skeleton's sources.yaml.
Intent is not a second task or lifecycle model. No stage is stored, no capability transitions an intent, nothing stamps one, and no intent capability writes the repository. The stage is a pure derivation over two things that already exist:
- the status
plan::Planderives for each named milestone —declaredwhile a milestone does not resolve,plannedonce all do,executingonce any is ACTIVE, VERIFY or DONE,verifyingonce every milestone that is not cancelled or superseded is DONE; - the proof state the evidence fabric already derives — a
testcriterion is met by a passing ledger run whose source digest still matches, aclaimcriterion by a claim that isprovenorinputs unchanged.satisfiedisverifyingwith every criterion met.
command and deployment criteria resolve, and are never counted as met: there is no
recorded execution to derive them from, and treating a declared command as proof would be the
anonymous green the ledger exists to refuse.
Four read-only capabilities project the derivation to the command line, HTTP and MCP:
intents.list, intents.record, intents.validate (exit 10 on a failure) and
intents.preflight (issue or paths, to milestone, to the intents it serves, or a refusal naming
the missing link). The intent-check gate runs intent validate on a change to the project
model or the engine, and project.work-serves-a-declared-intent states the rule.
Alternatives rejected
A stored intent status with transitions. It would be a second lifecycle beside the plan's, and the two would disagree the first time an issue was re-planned — the defect the plan was written without a status field to avoid.
Satisfaction stamped when the last pull request merges. A merged pull request whose intent is still false is unfinished work; the git server is not an oracle of the outcome.
A new evidence ledger for intents. The ledger and the claim join already say what ran and whether it is current. A second one would be a second truth about the same executions.
Consequences
- Satisfaction is decided by the intent engine over the ledger. Superseded by ADR 0107: this
consequence first planned that, once completion policy (pull request 292) landed, whether an
intent is satisfied would become a completion-policy question and this engine would answer
the stage only. ADR 0107 keeps the engine as the one authority for a criterion's verdict;
completion discharges obligations and never decides satisfaction. That is slice 2 of the
intent-lifecyclemilestone, restated to match. milestone_serves_no_intentis a warning, so existing milestones stay valid while intents are written for them.- The devcontext and session preflight join, the Cockpit intent view with enforced script coverage, and GitHub milestone reconciliation with a closure gate are later slices and are not decided here.