Problem
The impairment.coherence invariant landed in #4601 (adcp#2859) with three rules:
- Forward — every
impairments[] entry references a currently-offline resource.
- Inverse — any offline resource referenced by a non-terminal buy MUST appear in
impairments[].
- Health-iff —
health == "impaired" whenever impairments[] is non-empty (and ok when empty).
The Out-of-scope block in lifecycle.mdx § Compliance reads:
Buys in terminal status (completed, canceled, rejected) MAY remain unreported even when a referenced resource is offline; the buy is no longer serving and the synchronisation cost is wasted.
The runner implementation in adcp-client#1801 extends this carve-out to all three rules including the health-iff biconditional — i.e., a completed buy with health: "impaired" and empty impairments[] is graded not_applicable rather than failing the biconditional. The runner's reasoning: once a buy is terminal, the seller may stop syncing impairments altogether, so the biconditional can break in either direction without operational consequence.
That's a reasonable pragma but it's not what the spec text says. Read strictly, the biconditional binds every buy regardless of status. The current carve-out only addresses "MAY remain unreported" — it doesn't say the health field is allowed to drift from impairments[] cardinality.
Proposal
Make the carve-out explicit. One-line edit to lifecycle.mdx § Compliance § Out of scope:
Out of scope. Buys in terminal status (`completed`, `canceled`, `rejected`)
MAY remain unreported even when a referenced resource is offline; the buy
is no longer serving and the synchronisation cost is wasted. The
`impairments[]` ↔ `health` biconditional likewise relaxes on terminal
buys — sellers MAY leave stale `health: "impaired"` with an empty
`impairments[]` (or vice versa) once a buy reaches a terminal state.
Materiality (the requirement that `package_ids` be non-empty) is enforced
at the schema layer by `package_ids: minItems: 1` on `impairment.json`
(#2855) and is not re-checked here.
Plus a one-line addition to compliance-catalog.mdx's Cross-resource invariants table to mirror the relaxation.
Why this matters
- Sellers building against the strict reading would over-engineer terminal-state impairment cleanup that adds no operational value.
- Runner authors implementing the spec strictly would surface false-positive failures on completed buys with stale health values.
- The relaxation matches what real sellers will do (and what adcp-client#1801 already grades).
Acceptance
Related
- #4601 — spec PR that landed the invariant
- #2859 — original invariant issue
- adcp-client#1801 — runner implementation that prompted this clarification
Problem
The
impairment.coherenceinvariant landed in #4601 (adcp#2859) with three rules:impairments[]entry references a currently-offline resource.impairments[].health == "impaired"wheneverimpairments[]is non-empty (andokwhen empty).The Out-of-scope block in
lifecycle.mdx § Compliancereads:The runner implementation in adcp-client#1801 extends this carve-out to all three rules including the health-iff biconditional — i.e., a
completedbuy withhealth: "impaired"and emptyimpairments[]is gradednot_applicablerather than failing the biconditional. The runner's reasoning: once a buy is terminal, the seller may stop syncing impairments altogether, so the biconditional can break in either direction without operational consequence.That's a reasonable pragma but it's not what the spec text says. Read strictly, the biconditional binds every buy regardless of status. The current carve-out only addresses "MAY remain unreported" — it doesn't say the health field is allowed to drift from
impairments[]cardinality.Proposal
Make the carve-out explicit. One-line edit to
lifecycle.mdx § Compliance § Out of scope:Plus a one-line addition to
compliance-catalog.mdx's Cross-resource invariants table to mirror the relaxation.Why this matters
Acceptance
lifecycle.mdx § Compliance § Out of scopeextended with the terminal-buy biconditional relaxationcompliance-catalog.mdxCross-resource invariants row updated to mirrorRelated