107. Completion discharges obligations and never decides whether an intent is satisfied
Context
ADR 0070 made an intent a typed record whose stage is derived from the plan and whose
satisfaction is derived from the evidence ledger. Its first consequence planned the opposite
direction for later: once completion policy landed (pull request 292, cited there as ADR 0057,
which exists only on an unmerged branch), whether an intent is satisfied would become a
completion-policy question over the same evidence, and the intent engine would answer the
stage only. Slice 2 of the intent-lifecycle milestone carries that plan.
Completion answers a different question. majordomus finish judges whether a task discharged
the obligations its profile and policy declare: scope, verification, the note, the regression
test, the gates. An intent asks whether something is observably true for the people it is for.
A task can be finished and its intent still false, and an intent can become true without any
task finishing — a test that starts passing, a claim whose inputs stop changing. If completion
policy decided satisfaction, a finished task would be one policy edit away from stamping an
intent satisfied, which is the merge-stamping ADR 0070 rejected under another name.
The engine couples two answers today: intent::stage returns satisfied only when every
counted milestone is DONE and every criterion is met, so a reader cannot ask whether the
evidence alone settles an intent while its milestones are still open.
Decision
- One authority. Whether a satisfaction criterion is met is decided by the intent engine
(
apps/majordomus-cli/src/intent.rs) over the evidence ledger and the claim join, and by nothing else. No other module, policy file, capability or gate computes, stores or overrides a criterion's verdict or an intent's satisfaction. - Completion reads, never decides. Completion policy decides whether work is done. It may
read an intent's derived standing as an input to a question (for example, to report which
criteria a task advanced), but it never declares a question whose answer is that an intent is
satisfied, never writes an intent record, and never stores a stage or a verdict. A finish
with outcome
completedleaves every intent's stage and criterion states exactly as the plan and the evidence derive them. - The stage stays plan-derived.
stagekeeps its meaning:satisfiedis the stage of an intent whose counted milestones are DONE and whose criteria are all met; no surface changes here. - Satisfaction gets its own verdict. A separate derived verdict answers the evidence
question alone:
satisfiedwhen every criterion is met,unsatisfiedwhen a criterion the ledger can settle is not met,unknownwhen the unmet criteria are only of kinds the ledger cannot yet settle (command,deployment). DONE neither implies it nor is required for it. The field is namedverdict, becausesatisfactionalready names the criteria array in the record and inIntentView. Slice S07 implements it, with drift findings where the verdict and the stage disagree. - ADR 0070's first consequence is superseded by this decision, and slice 2 of the
intent-lifecyclemilestone is restated to match.
Alternatives rejected
Satisfaction as a completion-policy question (ADR 0070's plan). It would put a policy file between the evidence and the answer, and a finished task would become a route to a satisfied intent. Completion is about the task; satisfaction is about the world the task was for.
Keeping satisfaction coupled to DONE. It is true of today's stage, but it hides an answer the evidence already has: an intent whose criteria all hold while a milestone is open is exactly the drift a reader needs to see, and a coupled answer cannot show it.
Renaming the existing satisfaction array to free the name. It is in the schema, the
distribution skeleton, the documentation examples and every surface's output; renaming it
breaks readers to save choosing a new word.
Consequences
project.completion-never-decides-satisfactionstates the boundary, andtest/cases/895_a_finished_task_does_not_satisfy_an_intent.shproves it through the built executable: a completed finish next to a DONE milestone with unmet criteria leaves the stageverifying, the criterionnot_runand the intent record unchanged.- The completion batch's policy (
share/completion.yaml) must never gain an intent-satisfaction question; a question that reads intent standing is an input, never a verdict. - S07 adds
verdicttoIntentViewon every surface; until it lands, the stage is the only derived answer and it stays coupled to DONE. - Evidence-first acceptance at the plan transition —
plan doneon an issue that serves a criterion requiring that criterion's evidence — is not decided here; it belongs to the plan, not to completion, and is left to a later slice.