From 4e3239914c303ca0a5825de3834706823b73d87a Mon Sep 17 00:00:00 2001 From: Mark Beacom Date: Wed, 5 Aug 2026 18:45:31 -0400 Subject: [PATCH] docs(data-model): say what provenance means when there is no annotation Phase E found a genuine gap in the two-value provenance domain decided on 2026-08-05. Both table rows describe an annotation that EXISTS - upstream-authored and maintainer-overlay - but annotation-absent is the dominant real-corpus case: zero of 156 community-plugins descriptor files carry the annotation. Neither row was literally true of such an entity, and this section did not say what provenance meant for one. The fix is not a third value. provenance is a declaration about the SOURCE, made as part of the generation request and carried onto every entity derived from it. For an annotation-absent entity it is carried but vacuous: there is no annotation for it to describe, and the entity makes no adoption claim in either direction. Only the pair (ownershipState, provenance) is unambiguous. Code branching on provenance alone is reading a claim that may not have been made. An entity asserts third-party adoption only when its ownership state is explicit-paths or explicit-empty AND its provenance is upstream-authored. The declaration is required and exhaustive, with no default in either direction. Defaulting to upstream-authored would silently convert an omission into a third-party adoption claim, which is exactly what ADR-0020 clause 5 and ADR-0014's honesty rules exist to prevent. Defaulting to maintainer-overlay would be safer but would still fabricate a declaration nobody made. Phase E reached the same shape independently and did not invent a third value, adding isAdoptionClaim(ownershipState, provenance) instead. This records the reasoning in the contract so the next reader does not have to re-derive it. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- specs/010-catalog-backstage/data-model.md | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/specs/010-catalog-backstage/data-model.md b/specs/010-catalog-backstage/data-model.md index bbdb09ef..6cc327c2 100644 --- a/specs/010-catalog-backstage/data-model.md +++ b/specs/010-catalog-backstage/data-model.md @@ -449,6 +449,31 @@ upstream" would be true always and would distinguish nothing. | `upstream-authored` | The `adrkit.io/owned-paths` annotation was already present in the real upstream descriptor as found. | | `maintainer-overlay` | The annotation was authored by us and overlaid onto an otherwise-unmodified upstream descriptor. | +**It is a declaration about the SOURCE, not a per-entity derivation — and this is what +makes `annotation-absent` entities representable.** Both rows above describe an annotation +that *exists*, yet `annotation-absent` is the overwhelmingly common real-corpus case: of +156 `community-plugins` descriptor files, **zero** carry the annotation. Neither row is +literally true of such an entity, and an earlier revision of this section did not say what +`provenance` meant for one. + +It is not a third value. `provenance` is **declared for the source** as part of the +generation request and carried onto every entity derived from it. For an entity whose +ownership state is `annotation-absent`, the declaration is carried but **vacuous**: there +is no annotation for it to describe, and the entity makes **no adoption claim** in either +direction. + +**Only the pair `(ownershipState, provenance)` is unambiguous.** `provenance` alone is +not, and code that branches on it without the ownership state is reading a claim that may +not have been made. An entity asserts third-party adoption of the annotation **only** when +its ownership state is `explicit-paths` or `explicit-empty` *and* its provenance is +`upstream-authored`. + +**The declaration is required and exhaustive; there is no default.** Defaulting to +`upstream-authored` would silently convert an omission into a third-party adoption claim — +exactly the claim ADR-0020 clause 5 and ADR-0014's honesty rules exist to keep honest. +Defaulting to `maintainer-overlay` would be safer but would still fabricate a declaration +nobody made. An absent declaration is invalid input. + That is what makes **FR-043** satisfiable: clause 5's "only the corpus data is third-party, never the validation" boundary becomes legible from the artifact itself.