Skip to content

docs(adr-013): #133 — Amendment A2 for run maturity, drafted and not in force - #226

Merged
Polichinel merged 1 commit into
developmentfrom
docs/adr013-provenance-maturity-133
Aug 5, 2026
Merged

docs(adr-013): #133 — Amendment A2 for run maturity, drafted and not in force#226
Polichinel merged 1 commit into
developmentfrom
docs/adr013-provenance-maturity-133

Conversation

@Polichinel

Copy link
Copy Markdown
Collaborator

Addresses #133. Registers C-85. No delivered byte changescontract_version stays 1.5.

Why this PR is mostly measurement

#133 asked for three declared fields on the run manifest and stated that the global historical artifact is not co-delivered. Implementing it as written meant bumping contract_version — which is written inside the header bytes that §10 pins — and therefore rebuilding the golden fixture and re-vendoring it across all three implementing repos.

That cost justified measuring the ask first. Two of the three fields already ship, and the fourth claim is false.

the ask measured 2026-08-05
stamp source; "source="unknown" is live today" already delivered as provenance.ensemble — and dataset_service.py:793 reads exactly that key
declare a required schema version already delivered as contract_version, on the run manifest and in every shard header
stamp maturity on the run manifest real, but belongs in the shard header (where the consumer reads it) and is not ours to stamp
"the global historical is not uploaded" → decide whether FAO stops receiving it false_save_contract uploads it, category="historical", under the same interlock as the forecast

Also worth knowing: faoapi treats maturity as informational and explicitly never a serving gate (dataset_service.py:788), and epic #244 is closed. The consumer side is built. The urgency implied by the issue body is not there.

What is actually owed, and by whom

Maturity belongs in provenance, which §2.1 clause 1 closes — so admitting a key is an amendment, not a free addition.

And it is not this repository's to stamp. Hop-B shard headers are the Hop-A headers re-embedded untouched (contract/wire/sink.py:110). This repo forwards provenance; it does not compose it and does not know a run's maturity. Synthesising one here would be a producer guessing at a fact nobody told it — the inference declare-don't-infer exists to forbid. The stamp belongs to views-models. Our part is to forward it, which needs no code once the key is admitted.

ADR-013 §2.2a — Amendment A2

Records the field, why it is an amendment, what adoption costs, who can stamp it, and a named trigger (ADR-014 §4): adopt when the next §10 re-vendor happens for another reason — C-72/#174 (pyarrow) being the one expected, since it also changes delivered bytes and also needs three repos to move together. Riding along costs nothing extra; going alone costs a full coordination for one optional field.

Numbered A2 because A1 was already taken (§7a, 2026-07-19). Caught after writing; renaming rather than colliding.

The guard is bidirectional, and that is the point

test_s2_2a_is_not_secretly_in_force. The obvious risk is that A2 ships without the ADR noticing. The worse one is the reverse — A2 ships, contract_version goes to 1.6, and §2.2a still says "NOT YET IN FORCE", leaving three repos believing a re-vendor is still owed. So the test asserts the code agrees with the prose, and skips with an instruction to rewrite it (not delete it) if the section is ever rewritten on adoption.

Mutation-proven both directions: adding status to _PROVENANCE_KEYS fails it; bumping CONTRACT_VERSION to 1.6 fails it.

C-85 (new, Tier 3)

A cross-repo ask adopted on its stated terms without anyone measuring current state.

It was not careless. It was written against the run manifest — the artifact whose name suggests it carries run-level facts — while the consumer reads them from the shard header's provenance, because that is where the producing pipeline's identity travels. Both seats described a real need; neither described the same object. A cross-repo ask names an artifact in the other repo's vocabulary, and vocabulary is what does not survive the trip.

No guard proposed, deliberately: there is no mechanical check for "is this request still true", and a template or checklist field would decay into an unread heading. What worked was reading the consumer's source before writing any.

Verification

ruff check .        # clean
pytest -q           # 361 passed, 40 xfailed

Register 84/11/73 → 85/12/73.

🤖 Generated with Claude Code

…in force

#133 asked for three declared fields and said the historical artifact is not
co-delivered. Measured before implementing, because implementing it as written meant
a contract_version bump — which lives inside the header bytes §10 pins — and so a
golden-fixture rebuild and a three-repo re-vendor.

Two of the three already ship:

- `source` is `provenance.ensemble`, and views-faoapi reads exactly that key.
- the schema version is `contract_version`, on the run manifest and every shard header.

The third is real but is not ours to stamp. Maturity belongs in `provenance`, which
§2.1 closes, so admitting it is an amendment. And Hop-B shard headers are the Hop-A
headers re-embedded untouched (contract/wire/sink.py) — this repo forwards provenance,
does not compose it, and does not know a run's maturity. Synthesising one here would be
a producer guessing at a fact nobody told it. The stamp belongs to views-models; our
part is to forward it, which needs no code once the key is admitted.

ADR-013 §2.2a records that as Amendment A2: the field, why it is an amendment and not
a free addition, what adoption costs, who can stamp it, and a named trigger — adopt when
the next fixture re-vendor happens for another reason, C-72/#174 being the one expected.
Numbered A2 because A1 was taken (§7a, 2026-07-19).

The issue's fourth claim is false: `_save_contract` DOES upload the historical artifact,
category="historical", under the same interlock as the forecast. faoapi's C-169 decision
has no premise, so there is nothing for the maintainer to decide.

test_s2_2a_is_not_secretly_in_force guards the amendment bidirectionally — the risk is
not only that A2 ships unrecorded but that it ships while §2.2a still says it has not,
leaving three repos believing a re-vendor is still owed. Mutation-proven both ways.

New C-85 (Tier 3): a cross-repo ask adopted on its stated terms without measuring
current state. Filed in good faith, wrong because it named the run manifest while the
consumer reads the shard header — vocabulary is what does not survive the trip between
repos. No guard proposed; a checklist would be theatre.

Register 84/11/73 -> 85/12/73. Suite 361 passed / 40 xfailed; ruff clean.
No delivered byte changes; contract_version stays 1.5.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Polichinel
Polichinel merged commit 8db5602 into development Aug 5, 2026
4 checks passed
@Polichinel
Polichinel deleted the docs/adr013-provenance-maturity-133 branch August 5, 2026 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant