ADR 0349: Top-level success follows completion policies
Status: accepted. Extends the one-result projection model from ADR 0028, canonical-set parity from ADR 0051, classified recovery from ADR 0266, structurally valid result states from ADR 0334, and typed advisories from ADR 0346.
Context
§DiscernResult<TData> made contradictory structural states impossible by type, but it did not give every producer the same meaning for ok. A verb could report ok: true after a required late operation failed, provided its own Boolean convention happened to treat an earlier effect as success. Setup and upgrade exposed this defect when required instruction compilation failed after other files had changed. Similar ambiguity existed around cancelled steps, incomplete landing cleanup, failed optional resources, Proof recording, and observational warnings.
Repairing only the known setup fields would leave the semantic rule distributed across verb implementations. A future verb could repeat the defect, while command-line interface (CLI), human, JSON, Markdown, and Model Context Protocol (MCP) adapters could disagree if each interpreted the payload independently. An empty list or warning sentence could not safely distinguish an idempotent success, a required failure, and an explicitly optional degradation.
The result contract therefore needs a total authority over the live result-verb set, typed evidence for every permitted degradation, and one evaluation seam before projection. It must preserve the truth of effects that already happened instead of implying rollback.
Decision
§Every public result verb has one entry in RESULT_COMPLETION_POLICIES. The policy declares its required typed outcomes, permitted advisory kinds, refusal meaning, cancellation meaning, partial-effect meaning, no-op meaning, and recovery owner. Compile-time parity ties the literal policy keys to the result-contract registry; an injected bidirectional coverage check rejects missing, stale, and duplicate members.
evaluateResultCompletion derives the top-level verdict from the result's typed plan/apply outcomes and the verb's policy. ok: true means every required outcome in that policy holds. A required failed or cancelled step is false. A refusal is false. A no-op is true only where the policy admits one. The evaluator does not parse messages or renderer prose.
A degradation may coexist with ok: true only as a policy-permitted ResultAdvisory. Each advisory has a closed kind, non-empty structured evidence, and a non-empty next_action. A failed executed step counts as optional only when it carries such an advisory and its verb policy permits that kind. Hints remain presentation and navigation records; they do not waive required completion.
Required failures after effects preserve those effects in typed data and steps. Acceptance uses its landing-effect record; setup and upgrade use a discriminated data.instruction_refresh outcome. status: "partial" carries completed artifacts, non-empty failures, effects_preserved: true, and the safe discern refresh recovery. The top-level result is false and the CLI exits nonzero. No result claims rollback unless a typed rollback operation actually occurred.
Result capture, quiet CLI emission, serialization, MCP adaptation, and the Logbook CLI completion wrapper all consume the evaluated result. Human, Markdown, JSON, generated schemas, and MCP project that verdict; they cannot upgrade or downgrade it. MCP isError is the inverse of the evaluated ok. Generated result-contract metadata publishes each verb's exact completion policy so a consumer can audit the declared contract without reconstructing it from prose.
Consequences
§- An agent or integration can branch on
okas the truth of the verb's documented completion contract before inspecting verb-specific data. - Adding a result-producing verb now requires choosing its semantic state table, not merely its schema and renderer. A missing policy fails compilation or the architectural guard.
- Optional failures are visible and actionable without turning every warning into failure. Adding a new permitted degradation requires a typed kind and explicit policy enrollment.
- Late required failures return false while retaining partial-state and safe-rerun evidence. Callers must not assume
ok: falsemeans no effects occurred. - Setup and upgrade consumers must migrate from ambiguous compilation Booleans and lists to
data.instruction_refresh. This intentionally breaks consumers that treated a required compilation failure as success. - Successful setup-acceptance no-ops carry a typed
data.completionstate and reason; absence of landing data cannot stand for idempotence. - Completion evaluation is a shared boundary with some defensive repetition. That cost prevents a surface adapter or manually returned exit code from publishing a verdict that differs from the core envelope.
Alternatives considered
§- Fix setup and upgrade locally. Rejected because it would cure two instances while leaving every current and future verb free to define
okdifferently. - Infer completion from error strings, warnings, or empty collections. Rejected because wording and absence are not typed state, and renderers would become semantic authorities.
- Treat every warning or failed step as failure. Rejected because optional resources, cleanup, and observations can degrade explicitly without invalidating the verb's required contract.
- Keep renderer-specific verdict rules for compatibility. Rejected because CLI, JSON, Markdown, human, and MCP consumers would observe different facts for one operation.
- Hide partial effects behind a generic failure. Rejected because safe recovery depends on knowing what changed and whether rerunning is valid.