From 8ca39db96d1fe6633bc24d58690fe849fb2c6b5c Mon Sep 17 00:00:00 2001 From: Polichinl Date: Wed, 12 Aug 2026 18:18:22 +0200 Subject: [PATCH 1/3] =?UTF-8?q?fix(tests):=20#248=20=E2=80=94=20delete=20b?= =?UTF-8?q?oth=20consumer=20source-reads;=20the=20category=20is=20wrong?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit THE SUITE IS FULLY GREEN AGAIN. 413 passed, zero failures. The failure that has been red on `development` since 2026-08-12 is gone, and it is gone by deleting the check rather than repairing it. TWO BREAKAGES IN TWENTY-FOUR HOURS, BOTH BECAUSE THEIR CODE GOT BETTER. views-faoapi on 11 August, views-crafdapi on the 12th, each refactoring `APIPathManager("literal")` into `APIPathManager(CONSUMER_DOCUMENT_NAME)` — an improvement in both repositories, and a red build here both times. The regex was measuring their code quality and reporting it as our failure. ADR-017 §7 said we were never entitled to depend on another repository's file layout; repairing it a third time would have been repairing the wrong thing. WHAT WENT: `_CONSUMER_PATH_MANAGER`, `_CONSUMER_FILTER`, `_CONSUMER_SELF_CHECK_PENDING`, `_consumer_package`, both tests that used them, and the views-crafdapi checkout from CI — measured first, that fetch had exactly zero remaining consumers. The SIBLINGS entry stays with `ci_checkout=False` and a note naming the record, because CONSUMER_REPO still names that repository; only the fetch is gone. THE SEQUENCING CONSTRAINT DISSOLVED RATHER THAN BEING SATISFIED, and that is the part worth writing down. ADR-017 §5 said a partner's source read is removed only once that partner's consumer-side check lands. views-crafdapi#53 has not landed. The read went anyway, because the constraint was guarding a window in a mechanism that turned out to be the wrong mechanism. §5 now carries an erratum saying so, and a plainer rule: a check that reads another repository's source is not a check this repository builds. THE GAP IS NOW PERMANENT AND UNGUARDED HERE, BY CHOICE. Nothing verifies that a consumer's query uses the name it declares. C-92 states the chain link by link and says plainly that a delivery is verified by two values this platform authored agreeing with each other, plus the consumer's own word. Filed where the fact lives: views-faoapi#390 (under their seam-verification epic #383, whose flagship this is) and views-crafdapi#55 — both with file:line evidence, both noting that `manager.py:117` applies the filter conditionally so a falsy name broadens the query rather than failing, both explicitly not prescribing their internals. Also, while in the file: the module docstring and a comment block each carried a real coordinate value, and pytest prints a module docstring whenever anything in the file fails. Now named, not quoted (C-97). tests/test_product.py 348 -> 253. Suite 413 passed / 1 skipped / 40 xfailed, ruff clean. Closes #248. Unblocks PR #240. Epic #241. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/run_pytest.yml | 9 -- .../017_facts_across_a_private_boundary.md | 16 +++ reports/technical_risk_register.md | 21 ++- tests/conftest.py | 14 +- tests/test_ci_sibling_coverage.py | 5 +- tests/test_product.py | 129 +++--------------- 6 files changed, 65 insertions(+), 129 deletions(-) diff --git a/.github/workflows/run_pytest.yml b/.github/workflows/run_pytest.yml index 94773d6..7e7b354 100644 --- a/.github/workflows/run_pytest.yml +++ b/.github/workflows/run_pytest.yml @@ -67,14 +67,6 @@ jobs: path: _siblings/views-appwrite fetch-depth: 0 - - name: Checkout views-crafdapi (sibling) - uses: actions/checkout@v3 - with: - repository: views-platform/views-crafdapi - ref: main - path: _siblings/views-crafdapi - fetch-depth: 0 - - name: Set up Python uses: actions/setup-python@v4 with: @@ -97,7 +89,6 @@ jobs: - name: Run tests env: VIEWS_APPWRITE: ${{ github.workspace }}/_siblings/views-appwrite - VIEWS_CRAFDAPI: ${{ github.workspace }}/_siblings/views-crafdapi run: | set -e poetry run pytest tests/ diff --git a/docs/ADRs/017_facts_across_a_private_boundary.md b/docs/ADRs/017_facts_across_a_private_boundary.md index d327e68..72d3ec6 100644 --- a/docs/ADRs/017_facts_across_a_private_boundary.md +++ b/docs/ADRs/017_facts_across_a_private_boundary.md @@ -161,6 +161,22 @@ machine for the private one. Slightly redundant for a while, and redundancy is t price for not having a window where the only thing verifying a delivery label is our own typing. +**Erratum, 2026-08-12: this constraint did not survive contact, and it dissolved rather +than being satisfied.** Both source reads are gone, and neither partner's step 3 is what +removed them. The reads broke twice in twenty-four hours — views-faoapi on 11 August, +views-crafdapi on the 12th — each time because that repository refactored a literal +argument into a named constant, which is an improvement. §7 of this document says we were +never entitled to depend on another repository's file layout; two breakages in a day is +the evidence, and repairing the regex a third time would have been repairing the wrong +thing. + +So the ordering above is superseded by a plainer rule: **a check that reads another +repository's source is not a check this repository builds.** The window the constraint +guarded against is now permanent rather than temporary, and it is registered as **C-92** +rather than sequenced away. What closes it is each consumer proving that its query uses +the name it declares — asked for in views-faoapi#390 and views-crafdapi#55, because that +is a fact only the consumer can hold. + **One assumption worth stating rather than relying on.** The registry is versioned, so the two sides could in principle read it at different editions and both pass while disagreeing. That is not a live risk here because the label is contract-immutable — changing it is an diff --git a/reports/technical_risk_register.md b/reports/technical_risk_register.md index 504a11c..767edb8 100644 --- a/reports/technical_risk_register.md +++ b/reports/technical_risk_register.md @@ -409,7 +409,26 @@ views-faoapi#379 binds their *served-name constant* to the registry row. The ass **A second, structural half.** `_CONSUMER_SELF_CHECK_PENDING` is asserted non-empty and asserted to name only real partners — never asserted to *cover* them. Every other partner map here is two-sided against `PARTNER_PACKAGES`; this one is not, so a third partner is silently exempt from the source read the day it lands. And `SIBLINGS["views-crafdapi"].note` says the fetch "buys nothing and should be removed" once the registry read exists — which PR #239 landed — while ADR-017 §5 forbids retiring that partner's source read until views-crafdapi#53 lands. A maintainer following the note does the thing the ADR forbids, and `test_the_pending_list_is_not_empty` does not object because the map stays non-empty. -Cross-refs: **C-87** (the broader residual this sharpens, not duplicates), ADR-017 §5/§8/Appendix B, views-faoapi#379, views-crafdapi#53. +**Resolved as far as it can be here, 2026-08-12 (#248) — the check is gone, the gap is permanent, and the ask is filed.** + +Both source reads are deleted. Not because the sequencing constraint was satisfied — it **dissolved**: the reads broke twice in twenty-four hours, views-faoapi on 11 August and views-crafdapi on the 12th, each time because that repository refactored a literal argument into a named constant. Their code got better and our test went red. ADR-017 §7 said we were never entitled to depend on another repository's file layout; two breakages in a day is the evidence, and repairing the regex a third time would have been repairing the wrong thing. ADR-017 §5 carries the erratum. + +**The gap is now permanent and unguarded here, by choice.** Nothing in this repository verifies that a consumer's query uses the name it declares. The chain reads: + +| link | owner | held by | +|---|---|---| +| we upload with name N | us | construction | +| N == the registry row | us | `test_product.py::test_the_declared_consumer_name_matches_the_registry` | +| their constant == the registry row | them | views-faoapi's `tests/test_seam_contract_binding.py`; views-crafdapi's equivalent | +| **their query == their constant** | **them** | **nothing** | + +**Filed where the fact lives:** views-faoapi#390 (under their seam-verification epic #383, whose flagship this is) and views-crafdapi#55. Both carry `file:line` evidence, both note that `manager.py:117` applies the name filter *conditionally* so a falsy name broadens the query rather than failing, and both say plainly that we are not prescribing their internals. + +**Verified intact at the time of writing** — the constant reaches the path manager and the manager still filters on it, in both consumers. This is a risk, not an incident. + +**Trigger** is now theirs to clear and ours to notice: when either issue lands, this entry closes for that partner. Until then the honest statement is that a delivery is verified by two values this platform authored agreeing with each other, plus the consumer's own word. + +Cross-refs: **C-87** (the broader residual this sharpens, not duplicates), **C-94** (the producer-side preflight that would close it without asking anyone), ADR-017 §5/§7/§8/Appendix B, views-faoapi#390, views-crafdapi#55. --- diff --git a/tests/conftest.py b/tests/conftest.py index 839acaa..9a093b6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -158,12 +158,16 @@ class Sibling: ), "views-crafdapi": Sibling( env="VIEWS_CRAFDAPI", - ci_checkout=True, + ci_checkout=False, note=( - "PUBLIC, and fetched **temporarily**. Measured: this fetch serves exactly one " - "test, the consumer-name pin. ADR-017 §7 replaces that test with a read of " - "the public registry, at which point this fetch buys nothing and should be " - "removed along with it. Until then it is real coverage, not decoration." + "PUBLIC, and no longer fetched. It served exactly one test — the check that " + "read this consumer's source for its query filter — and #248 deleted that " + "check rather than repairing it: the same read broke twice in 24 hours " + "because both consumers refactored a literal into a named constant, which " + "ADR-017 §7 predicted. The declaration stays because CONSUMER_REPO still " + "names this repository; only the fetch is gone. What the source read used to " + "cover is register C-92, and views-crafdapi#55 is the ask that would close it " + "where the fact lives." ), ), } diff --git a/tests/test_ci_sibling_coverage.py b/tests/test_ci_sibling_coverage.py index 0572e2e..ee0238a 100644 --- a/tests/test_ci_sibling_coverage.py +++ b/tests/test_ci_sibling_coverage.py @@ -181,8 +181,9 @@ def _g4_every_note_names_a_record( **Widened 2026-08-10 after external review.** The rule used to look only at siblings with ``ci_checkout=False``, which left a hole in exactly the place ADR-016 calls out: - `views-crafdapi` is fetched *temporarily*, until the check it serves moves to a - registry read, and that fact lived in a note **no rule examined**. A claim about + `views-crafdapi` was fetched *temporarily*, until the check it served moved to a + registry read, and that fact lived in a note **no rule examined**. (That fetch is gone + as of #248; the rule this incident produced is not.) A claim about another repository, in prose, that nothing can check — which is the failure ADR-016 §3 diagnoses, reintroduced for the one download the document itself calls temporary. diff --git a/tests/test_product.py b/tests/test_product.py index 633f0e1..9fbd848 100644 --- a/tests/test_product.py +++ b/tests/test_product.py @@ -8,9 +8,11 @@ The consumer-name pin is the one that matters most and the one a partner-scoped test could never catch: a document written under a name the consumer does not filter for is -delivered, stored, billed, and invisible. That is not hypothetical here — six -`orange_ensemble` forecast documents sat in `unfao_bucket` for months while FAO's -forecast serving read empty (ADR-013 §11.4 post-adoption record, register C-01). +delivered, stored, billed, and invisible. That is not hypothetical here — six forecast +documents sat in the UNFAO bucket for months, under a name nothing was looking for, while +FAO's forecast serving read empty (ADR-013 §11.4 post-adoption record, register C-01). +*(Named, not quoted: the bucket's declared value is a coordinate, and this docstring is +printed by pytest whenever anything in this file fails — register C-97.)* Parametrised over `tests/conftest.PARTNER_PACKAGES`, so a third partner is caught by `test_clone_readiness.py::test_the_declared_partner_list_is_the_real_one` rather than @@ -35,48 +37,32 @@ #: passes for every possible value, which is the shape of the replica defect epic #181 #: spent a story retiring. So the expected value is written out. #: -#: **But a literal transcribed from another repository is a guarantee, and ADR-014 §1 -#: says a guarantee needs a check.** On its own this pin catches drift authored *here* — -#: which was never the danger. If views-crafdapi changed its filter tomorrow, this file -#: would stay green, the delivery would upload, and the document would be invisible: -#: ADR-013 §4.1a, the defect that stranded six `orange_ensemble` documents in -#: `unfao_bucket` while FAO's forecast serving read empty for months. +#: **A literal transcribed from another repository is a guarantee, and ADR-014 §1 says a +#: guarantee needs a check.** On its own this pin catches drift authored *here*, which was +#: never the danger: if a consumer changed its filter tomorrow this file would stay green, +#: the delivery would upload, and the document would be invisible (ADR-013 §4.1a). #: #: ``test_the_declared_consumer_name_matches_the_registry`` closes that half against the #: **public coordinate registry** rather than the consumer's source (ADR-017 §5). It runs #: for every partner and needs no credential, because the registry is public even when the #: consumer is not — which is why it reaches the FAO partner and its predecessor could not. #: -#: One partner is still ALSO read at the source, and only one: -#: ``_CONSUMER_SELF_CHECK_PENDING`` below names it and the issue that retires it. +#: What it does **not** close is whether the consumer's query uses the name it declares. +#: This repository used to read their source for that; the check broke twice in 24 hours +#: because both consumers refactored a literal into a named constant, and #248 deleted it +#: rather than repairing it. Register **C-92** carries the gap; views-faoapi#390 and +#: views-crafdapi#55 are the asks that would close it where the fact lives. _CONSUMER_DOCUMENT_NAME = { "unfao": "un_fao", "crafd": "un_crafd", } -#: Where the consumer's name lives, and the mechanism that consumes it. Both are -#: pinned: a consumer that kept the string but started filtering on a different field -#: would strand a delivery just as thoroughly as one that renamed it. _PKG = Path(__file__).resolve().parent.parent / "views_postprocessing" -_CONSUMER_PATH_MANAGER = re.compile(r'APIPathManager\(\s*"([a-z0-9_]+)"') -_CONSUMER_FILTER = 'filters["name"] = self.model_path.model_name' - - def _product(partner: str): return importlib.import_module(f"views_postprocessing.{partner}.product") -def _consumer_package(repo: Path) -> Path: - """``src/views_api`` inside a consumer checkout.""" - candidates = sorted((repo / "src").glob("views_*api")) - assert len(candidates) == 1, ( - f"expected exactly one package under {repo}/src, found {candidates}. The " - "consumer's layout changed; this test's assumption about where to look is " - "part of what it asserts." - ) - return candidates[0] - def test_every_partner_has_its_consumer_name_pinned(): """Assert this file's declared scope is the real one (ADR-014 §2).""" @@ -233,8 +219,9 @@ def test_the_declared_consumer_name_matches_the_registry(partner): which is public, so this needs no credential even for the private partner — that is the whole of ADR-017 §5 in one assertion. - *"Neither reads the other" is the end state, not yet the present one:* CRAF'd's source - is still read by the check below, until views-crafdapi#53 lands. + *"Neither reads the other" is now the present state, not just the end state* — #248 + deleted the last source read. What that costs is register C-92: nothing here verifies + that a consumer's query uses the name it declares. The value it guards is the one whose failure is silent: a delivery filed under a name the consumer does not ask for is uploaded, stored, billed, and invisible — no error @@ -264,85 +251,3 @@ def test_the_declared_consumer_name_matches_the_registry(partner): f"[{partner}] the pin in this file disagrees with the registry — the local " "always-on test above should have caught a mismatch with the module first." ) - - -#: Partners whose consumer-side self-check has NOT landed yet, so this repository still -#: reads their source as well as the registry (ADR-017 §5's sequencing constraint). -#: -#: Declared rather than inferred, and deliberately a *shrinking* list: an entry leaves it -#: when that partner's own check lands, and the day it empties this whole mechanism goes. -_CONSUMER_SELF_CHECK_PENDING = { - "crafd": "views-crafdapi#53", -} - - -def test_the_pending_list_is_not_empty_and_names_only_real_partners(): - """An empty map must be a prompt to delete code, not a silent skip. - - ``parametrize`` over an empty collection is a **skip** under pytest's default - ``empty_parameter_set_mark``, and this repository declares no pytest configuration at - all. So emptying this map — by a premature cleanup, or an edit made before - views-crafdapi#53 lands — would retire the only check that reads what a consumer - actually does, and report ``1 skipped`` on a green build. The registry check would - then be comparing two values this platform authored to each other, which is the exact - failure the retained test's docstring warns about. - - So the map is asserted non-empty. When it legitimately empties, this assertion is - what tells you to delete the test, its regexes, and the sibling fetch that serves it. - """ - unknown = sorted(set(_CONSUMER_SELF_CHECK_PENDING) - set(PARTNER_PACKAGES)) - assert not unknown, f"not partners: {unknown}" - assert _CONSUMER_SELF_CHECK_PENDING, ( - "_CONSUMER_SELF_CHECK_PENDING is empty, which means every consumer now checks " - "itself against the registry. That is the end state ADR-017 §5 describes — so " - "finish it: delete test_the_consumer_still_filters_on_the_name_until_it_checks_" - "itself, the _CONSUMER_PATH_MANAGER and _CONSUMER_FILTER patterns, and the " - "views-crafdapi entry in tests/conftest.py::SIBLINGS whose note says that fetch " - "serves exactly this one test. Leaving them costs a clone on every pull request " - "and asserts nothing." - ) - - -@pytest.mark.parametrize("partner", sorted(_CONSUMER_SELF_CHECK_PENDING)) -def test_the_consumer_still_filters_on_the_name_until_it_checks_itself(partner): - """The source-read, kept ONLY for partners whose own check does not exist yet. - - ADR-017 §5 constrains the order: this repository stops reading a consumer's source - when *that consumer* starts checking itself against the registry. Otherwise there is - a window where the registry row is a string a human typed, our check compares our - copy to it, and nothing anywhere consults what the consumer actually does — a green - build proving only that two values this platform authored agree. - - views-faoapi#379 landed on 2026-08-11, so the FAO half of this check is gone. - views-crafdapi#53 has not, so CRAF'd's stays — and with it the crafd sibling fetch, - whose ``note`` in ``tests/conftest.py`` records that it lives or dies with this one - check. - - **This test is meant to be deleted.** When #53 lands, remove that partner from - ``_CONSUMER_SELF_CHECK_PENDING``; when the map empties, remove this test, the regexes - it uses, and the fetch. - """ - repo = require_sibling(CONSUMER_REPO[partner]) - pkg = _consumer_package(repo) - - api = (pkg / "managers" / "api.py").read_text() - found = _CONSUMER_PATH_MANAGER.findall(api) - assert len(found) == 1, ( - f"expected exactly one APIPathManager(...) construction in " - f"{CONSUMER_REPO[partner]}'s managers/api.py, found {found}. This is the fragile " - "half ADR-017 retires — a layout change there breaks a check here, which is what " - "happened to the FAO half on 2026-08-11. It survives only until " - f"{_CONSUMER_SELF_CHECK_PENDING[partner]} lands." - ) - assert found[0] == _CONSUMER_DOCUMENT_NAME[partner], ( - f"{CONSUMER_REPO[partner]} filters on {found[0]!r}; this repository declares " - f"{_CONSUMER_DOCUMENT_NAME[partner]!r}. A delivery under a name the consumer does " - "not ask for is uploaded, stored, and invisible (ADR-013 §4.1a)." - ) - - manager = (pkg / "managers" / "prediction" / "manager.py").read_text() - assert _CONSUMER_FILTER in manager, ( - f"{CONSUMER_REPO[partner]} no longer selects by {_CONSUMER_FILTER!r}. The name " - "may still match while the consumer filters on something else entirely — same " - "invisibility, different cause." - ) From b82fca0204738d294fe091bc0320f0c1b791b8ec Mon Sep 17 00:00:00 2001 From: Polichinl Date: Wed, 12 Aug 2026 18:31:41 +0200 Subject: [PATCH 2/3] =?UTF-8?q?fix(docs):=20#248=20review=20=E2=80=94=20I?= =?UTF-8?q?=20repealed=20a=20rule=20on=20a=20false=20claim=20about=20anoth?= =?UTF-8?q?er=20repository?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The deletion is right and the review confirmed it: nothing stranded in code, the workflow edit is clean, all six CI rules still bite. The defect is in the prose, and it is the worst kind — permanent governance text resting on something untrue. VIEWS-CRAFDAPI#53 CLOSED AT 12:15. MY COMMIT WAS 18:18 THE SAME DAY. My ADR-017 §5 erratum says "neither partner's step 3 is what removed them" and my commit message says "views-crafdapi#53 has not landed". Both false, by six hours. Both partners' consumer-side checks HAD landed — the constraint was satisfied, not dissolved. Worse, and more interesting: the crafd commit that satisfied step 3 is THE SAME COMMIT that broke our regex. While binding its served name to the registry, it tidied `APIPathManager("literal")` into `APIPathManager(CONSUMER_DOCUMENT_NAME)`. The improvement and the breakage were one edit, in both repositories, a day apart. The event I narrated as "their code got better and our test went red" IS the sequencing constraint being met. So the erratum is rewritten on honest ground. The outcome stands — the source read had to go — but on §7's argument (we were never entitled to depend on another repository's file layout), not on a false claim that the ordering was bypassed. The constraint is DISCHARGED, not repealed. Writing a repeal into ADR-017 on an untrue claim about another repository is §3's failure inside §5's text, and it is corrected visibly rather than quietly. NINE MORE STALE CLAIMS, all named by the same review, none caught by any test: ADR-017 — §5's body still said "today the check still reads the consumer's source and still skips in CI", seven lines below the erratum saying otherwise. Appendix B still said views-crafdapi#53 was open, that step 4 was "not yet filed", and closed the document with "so no window exists in which the label is verified only against our own typing" — which this change makes permanently false, deliberately. ADR-016 — the §4 table row said the crafdapi fetch "retires when views-crafdapi#53 lands, not before"; §5 explained which download was temporary; the 2026-08-11 update said that partner's source-read and fetch stay until #53 lands. All three now false. Register — C-92's own Location cited three symbols this change deleted and two line numbers past the end of a file that is now 253 lines; its title and Trigger scoped to FAO while its body covers both partners; its "second structural half" is entirely about deleted code. C-87's trigger named #53 as live. C-81 said crafdapi is "now checked out in CI". C-97's headline number was measured at 33 and is now 25 across 8 files — recounted, with a note to re-measure rather than cite it. AND CONSUMER_REPO WAS GUARDING A PRECONDITION OF NOTHING. Its test's docstring said "the gated check below iterates this map"; there is no gated check below. Its failure message described a `require_sibling()` call site that no longer exists. Reframed to what the map is actually for now: addressing — it records who receives each delivery, and it is who C-92's cross-repo asks are sent to. Suite 413 passed / 1 skipped / 40 xfailed, ruff clean. Epic #241. Co-Authored-By: Claude Opus 5 (1M context) --- .../016_ci_read_access_to_private_siblings.md | 24 +++-- .../017_facts_across_a_private_boundary.md | 87 ++++++++++++------- reports/technical_risk_register.md | 20 ++--- tests/conftest.py | 10 ++- tests/test_product.py | 25 +++--- 5 files changed, 101 insertions(+), 65 deletions(-) diff --git a/docs/ADRs/016_ci_read_access_to_private_siblings.md b/docs/ADRs/016_ci_read_access_to_private_siblings.md index ee77a84..bb0cba9 100644 --- a/docs/ADRs/016_ci_read_access_to_private_siblings.md +++ b/docs/ADRs/016_ci_read_access_to_private_siblings.md @@ -115,7 +115,7 @@ Who is who, once and in one table: | repository | public? | fetched by CI? | why not, if not | |---|---|---|---| | **views-appwrite** | yes | **yes** | — carries the registry drift checks | -| **views-crafdapi** | yes | **yes**, temporarily | — retires when views-crafdapi#53 lands, not before (ADR-017 §5 is per partner) | +| **views-crafdapi** | yes | **no**, since 2026-08-12 | it was fetched for one test; that check read the consumer's source, broke twice in a day when both consumers improved theirs, and was deleted rather than repaired (ADR-017 §7 and its §5 erratum) | | **views-datafactory** | yes | no | its checks need raw data that is not in its git repository; fetching it turns an honest skip into a crash | | **views-faoapi** | **no** | no | private — no amount of workflow configuration reaches it. That case is [ADR-017](017_facts_across_a_private_boundary.md) | @@ -148,12 +148,14 @@ Each rule is a plain function, so each is also run against a deliberately broken to prove it objects. A rule only ever tried against a correct file is a rule nobody has watched fail. -**One of these downloads is temporary, and it is worth knowing which.** `views-crafdapi` is -fetched for exactly one test. [ADR-017](017_facts_across_a_private_boundary.md) §7 replaces -that test with one that reads a public declaration instead — at which point this download -buys nothing and goes. That has been decided and is not yet done; it waits on the -declaration landing in the registry. That is a decision this document cannot make on its own, which -is why it is recorded there and cross-referenced here. +**One of these downloads was temporary, and it is worth knowing what became of it.** +`views-crafdapi` was fetched for exactly one test — a check that read the consumer's own +source. [ADR-017](017_facts_across_a_private_boundary.md) §7 said this repository was never +entitled to depend on another's file layout, and on 11 and 12 August 2026 both consumers +proved it by refactoring a literal into a named constant and reddening this repository +twice in a day. The check was deleted rather than repaired, and the download went with it. +What that costs is register C-92: nothing here verifies that a consumer's query uses the +name it declares. ### §6 A repository CI expects but cannot find turns the build red @@ -311,8 +313,12 @@ the record that owns it. **Update 2026-08-11.** The declaration now exists (views-appwrite#75), views-faoapi checks itself against it (their #379), and this repository's check reads the registry rather than that repository's source. So the FAO half is no longer laptop-only, and no -credential was issued. What remains is CRAF'd's consumer-side check (views-crafdapi#53); -until it lands, that partner's source-read stays, and with it that partner's fetch. +credential was issued. CRAF'd's consumer-side check landed the next day (views-crafdapi#53, closed 2026-08-12). + +**Amended 2026-08-12.** Both source-reads are now gone, and the crafd fetch with them — +but not because those gates opened. The reads broke twice in twenty-four hours, each time +because a consumer improved its own code, so the mechanism was abandoned rather than +sequenced out. ADR-017 §5 carries the erratum; the residual is C-92. --- diff --git a/docs/ADRs/017_facts_across_a_private_boundary.md b/docs/ADRs/017_facts_across_a_private_boundary.md index 72d3ec6..dcff34a 100644 --- a/docs/ADRs/017_facts_across_a_private_boundary.md +++ b/docs/ADRs/017_facts_across_a_private_boundary.md @@ -161,29 +161,42 @@ machine for the private one. Slightly redundant for a while, and redundancy is t price for not having a window where the only thing verifying a delivery label is our own typing. -**Erratum, 2026-08-12: this constraint did not survive contact, and it dissolved rather -than being satisfied.** Both source reads are gone, and neither partner's step 3 is what -removed them. The reads broke twice in twenty-four hours — views-faoapi on 11 August, -views-crafdapi on the 12th — each time because that repository refactored a literal -argument into a named constant, which is an improvement. §7 of this document says we were -never entitled to depend on another repository's file layout; two breakages in a day is -the evidence, and repairing the regex a third time would have been repairing the wrong -thing. - -So the ordering above is superseded by a plainer rule: **a check that reads another -repository's source is not a check this repository builds.** The window the constraint -guarded against is now permanent rather than temporary, and it is registered as **C-92** -rather than sequenced away. What closes it is each consumer proving that its query uses -the name it declares — asked for in views-faoapi#390 and views-crafdapi#55, because that -is a fact only the consumer can hold. +**Erratum, 2026-08-12. The sequence above was followed, and the check was still the wrong +mechanism. Both facts belong here, and an earlier draft of this erratum got the first one +backwards.** + +Both partners' step 3 landed. views-faoapi#379 merged on 11 August; views-crafdapi#53 +closed at 12:15 on the 12th. So the constraint stated above was **satisfied**, not +bypassed — and the first version of this erratum claimed the opposite, that "neither +partner's step 3 is what removed them". That was false when written, six hours after the +second one landed. It is corrected here rather than quietly, because an ADR that repeals +its own rule on a false claim about another repository is §3's failure inside §5's text. + +**What actually happened is more useful than what that draft said.** In both repositories +the commit that satisfied step 3 was *the same commit* that broke our source-reading +check: each consumer, while binding its served name to the registry, tidied +`APIPathManager("literal")` into `APIPathManager(CONSUMER_DOCUMENT_NAME)`. The improvement +and the breakage were one edit. Twice, a day apart. + +That is the argument for removing the check, and it is **§7's argument, not §5's**: we were +never entitled to depend on another repository's file layout, and a mechanism that a +consumer breaks by improving itself will keep breaking. The ordering rule above did its +job; the thing it was ordering was not worth having. + +So the ordering constraint is not repealed — it is **discharged**, and superseded for this +class by a plainer rule: **a check that reads another repository's source is not a check +this repository builds.** The residual window is now permanent rather than temporary, +registered as **C-92**, and what closes it is each consumer proving its query uses the name +it declares — asked for in views-faoapi#390 and views-crafdapi#55, because that is a fact +only the consumer can hold. **One assumption worth stating rather than relying on.** The registry is versioned, so the two sides could in principle read it at different editions and both pass while disagreeing. That is not a live risk here because the label is contract-immutable — changing it is an amendment, which produces a new edition both sides re-pin to, and our pin's reachability is already checked. Recorded because an unstated assumption carrying a silent-failure mode is -what §1 is about. Today the check still reads the consumer's source -and still skips in CI. The order the three land in, and what is blocked on what, is +what §1 is about. *(Until 2026-08-12 the check also read the consumer's source and +skipped in CI; see the erratum above — that half is gone and its residual is C-92.)* The order the three land in, and what is blocked on what, is Appendix B. Said here because a decision record that reads as a description of the code is how this repository has repeatedly ended up believing work was done. @@ -393,21 +406,31 @@ visibility can be inferred for future APIs. Corrected: **retirement is per partner, and follows that partner's step 3.** For FAO that is now met (views-faoapi#379 merged 2026-08-11), so the FAO source-read goes. For - CRAF'd it is not (views-crafdapi#53 open), so the crafd source-read stays — and with - it the crafd fetch, whose `note` in `tests/conftest.py` already records that it lives - or dies with that one check. + CRAF'd it was not yet, so the crafd source-read stayed — and with it the crafd fetch. + + *(Superseded 2026-08-12. views-crafdapi#53 closed at 12:15 that day, and the crafd + source-read was deleted anyway — not because the gate opened, but because the mechanism + was wrong. Both fetch and check are gone; `tests/conftest.py`'s note records it. See the + §5 erratum.)* 3. **views-faoapi** — verify its own served label against the declaration; §8's other half. Filed as views-faoapi#379, and the consumer-side maintainer has accepted it. -4. **views-crafdapi** — the same self-check for the other partner. **Not yet filed at the - time of writing, and that gap matters**: §7 retires the crafdapi fetch, so without this - leg the CRAF'd label would end up checked against a registry row that nobody checks - against CRAF'd's actual code — no verification against reality at all, which is worse - than the status quo. §7 argues the rule must apply uniformly; uniform application means - uniformly filing the third leg. Sequenced after that partner's data contract settles, - per step 1. - -**Step 3 is a precondition for removing the old check**, though not for adding the new one -— see the sequencing note in §5. The order is safe to interrupt at any point: until step 3 -lands for a partner, that partner's source-reading check stays, so no window exists in which -the label is verified only against our own typing. +4. **views-crafdapi** — the same self-check for the other partner. Landed as + views-crafdapi#53 (closed 2026-08-12), with the *query*-side ask filed the same day as + views-crafdapi#55 alongside views-faoapi#390. + + The reasoning that made this leg necessary still stands: §7 retires the crafdapi fetch, + so without it the CRAF'd label would be checked against a registry row that nobody + checks against CRAF'd's actual code — no verification against reality at all, which is + worse than the status quo. §7 argues the rule must apply uniformly; uniform application + means uniformly filing the third leg. + +**Step 3 was a precondition for removing the old check**, though never for adding the new +one — see the sequencing note in §5. The order was safe to interrupt at any point: until +step 3 landed for a partner, that partner's source-reading check stayed, so no window +existed in which the label was verified only against our own typing. + +**That last sentence stopped being true on 2026-08-12, deliberately.** Both source reads +were deleted once the mechanism — not the ordering — was found wanting, so the window is +now permanent and carried as **C-92**. See the §5 erratum for why the constraint was +discharged rather than repealed. diff --git a/reports/technical_risk_register.md b/reports/technical_risk_register.md index 767edb8..8071d55 100644 --- a/reports/technical_risk_register.md +++ b/reports/technical_risk_register.md @@ -161,7 +161,7 @@ that indexes only deleted code is noise. ## Open Concerns -### C-97: Thirty-three coordinate values sit in docstrings and comments, where the scan deliberately does not look +### C-97: Coordinate values sit in docstrings and comments, where the scan deliberately does not look | Field | Value | |-------|-------| @@ -170,7 +170,7 @@ that indexes only deleted code is noise. | Source | `/code-review max` on #242, 2026-08-12; count reproduced here | | Trigger | **Either.** (a) A check whose failing function contains one of these values starts firing in CI. (b) Someone proposes widening the no-copy scan to docstrings — at which point this entry is the measurement that says what that would cost. | | Owner | This repository. | -| Location | Measured across `git ls-files '*.py'`: 33 standalone occurrences in 9 files, including `views_postprocessing/{unfao,crafd}/managers/`, `contract/store_metadata.py`, `contract/wire/sink.py`. | +| Location | Measured across `git ls-files '*.py'`, **25 standalone occurrences in 8 files** (2026-08-12, down from 33 in 9 when filed — #242 cleared the no-copy scan's own docstring and #248 cleared `tests/test_product.py`). Includes `views_postprocessing/{unfao,crafd}/managers/`, `contract/store_metadata.py`, `contract/wire/sink.py`. **The count moves whenever prose is edited; re-measure rather than cite it.** | The no-copy scan compares string **constants** and excludes docstrings outright. That exclusion is C-57's recorded lesson: an early draft fired on refusal labels and on docstrings naming which store a function serves, and *"a guard that fails on `def file_metadata(record)` gets deleted — after which the real rule is unguarded"* (ADR-014 §3). @@ -388,16 +388,16 @@ Cross-refs: **C-90** (the same module's untested core), **C-88** (why the module --- -### C-92: This repository lost its only check that the FAO consumer still SELECTS by the delivery label +### C-92: Nothing here checks that a consumer SELECTS by the delivery label — for either partner | Field | Value | |-------|-------| | ID | C-92 | | Tier | 2 — the failure mode is invisible by construction and is on the live FAO path. Upload succeeds, storage is billed, the consumer's endpoint returns empty, nothing raises anywhere. | | Source | `/code-review max` on PR #239 post-merge, 2026-08-11 | -| Trigger | views-faoapi changes how `managers/prediction/manager.py` selects — to a category, a metadata field, a query builder — without touching its served-name constant. | +| Trigger | **Either consumer** changes how it selects — to a category, a metadata field, a query builder — without touching its served-name constant. Also live: `manager.py:117` in both drops the name filter entirely when `model_name` is falsy. | | Owner | Shared: views-faoapi owns the check; this repository owns noticing it does not exist. | -| Location | `tests/test_product.py:63` (`_CONSUMER_FILTER`), `:274` (`_CONSUMER_SELF_CHECK_PENDING`), `:344`; `tests/conftest.py:159-167`; ADR-017 §5. | +| Location | `views_postprocessing//product.py::CONSUMER_DOCUMENT_NAME`; `tests/test_product.py::test_the_declared_consumer_name_matches_the_registry` (what remains); ADR-017 §5/§7. Function names, not line numbers. | PR #239 retired the FAO half of the source-reading check on the strength of views-faoapi#379. That was the right sequencing — §5 requires the consumer-side check to land first, and it had. **But the two checks are not the same check.** @@ -407,7 +407,7 @@ views-faoapi#379 binds their *served-name constant* to the registry row. The ass **C-87 is not this.** C-87 records that we verify our copy against the declaration rather than the consumer's code against it. This is narrower and worse: for one partner we briefly had the second check and gave it up for something that does not cover the same failure. -**A second, structural half.** `_CONSUMER_SELF_CHECK_PENDING` is asserted non-empty and asserted to name only real partners — never asserted to *cover* them. Every other partner map here is two-sided against `PARTNER_PACKAGES`; this one is not, so a third partner is silently exempt from the source read the day it lands. And `SIBLINGS["views-crafdapi"].note` says the fetch "buys nothing and should be removed" once the registry read exists — which PR #239 landed — while ADR-017 §5 forbids retiring that partner's source read until views-crafdapi#53 lands. A maintainer following the note does the thing the ADR forbids, and `test_the_pending_list_is_not_empty` does not object because the map stays non-empty. +**~~A second, structural half.~~ MOOT 2026-08-12 (#248)** — `_CONSUMER_SELF_CHECK_PENDING`, `test_the_pending_list_is_not_empty` and the `SIBLINGS` note it describes were all deleted with the mechanism. Left visible because the reasoning still applies to any future map of this shape: `_CONSUMER_SELF_CHECK_PENDING` is asserted non-empty and asserted to name only real partners — never asserted to *cover* them. Every other partner map here is two-sided against `PARTNER_PACKAGES`; this one is not, so a third partner is silently exempt from the source read the day it lands. And `SIBLINGS["views-crafdapi"].note` says the fetch "buys nothing and should be removed" once the registry read exists — which PR #239 landed — while ADR-017 §5 forbids retiring that partner's source read until views-crafdapi#53 lands. A maintainer following the note does the thing the ADR forbids, and `test_the_pending_list_is_not_empty` does not object because the map stays non-empty. **Resolved as far as it can be here, 2026-08-12 (#248) — the check is gone, the gap is permanent, and the ask is filed.** @@ -605,7 +605,7 @@ would fix it, and its trigger is below. | ID | C-87 | | Tier | 2 — the failure mode is invisible by construction. The upload succeeds, the storage is paid for, the consumer's endpoint returns empty, and nothing anywhere raises. That is the shape ADR-013 §4.1a calls *"invisible to the consumer, not merely degraded"*. | | Source | ADR-017 §8, sharpened by external review (#232, #234), 2026-08-10 | -| Trigger | **Either half going missing.** (a) `views-faoapi#379` or `views-crafdapi#53` is closed without the check being written. (b) A private API operated by a **third party** becomes a consumer — at which point the second half cannot be required at all and this becomes permanent. | +| Trigger | **Either half going missing.** (a) ~~`views-faoapi#379` or `views-crafdapi#53` is closed without the check being written.~~ **Both closed WITH the check written** (2026-08-11, 2026-08-12). The live trigger is now (a') either consumer's *query* stops using its declared constant — see **C-92**, and views-faoapi#390 / views-crafdapi#55. (b) A private API operated by a **third party** becomes a consumer — at which point the second half cannot be required at all and this becomes permanent. | | Owner | The consumer-side seats own the check; this repository owns noticing that it exists. | | Location | `views_postprocessing//product.py::CONSUMER_DOCUMENT_NAME`; the check in `tests/test_product.py`; ADR-017 §5, §8, Appendix B. | @@ -613,9 +613,9 @@ ADR-017 decides that the delivery label is declared in the public coordinate reg Its residual is stated plainly in §8 and belongs here rather than only in a document: **we will verify our copy against the declaration, not the consumer's code against it.** If a consumer quietly starts filtering on something else, our check passes and the delivery is invisible exactly as before. -**Why this is a risk and not merely a note.** The second half is real work in repositories this project does not control. `views-faoapi#379` has a willing owner. `views-crafdapi#53` is blocked on that partner's data contract and could sit for a long time. Until both land, the label's agreement with reality rests on the source-reading check — which ADR-017's sequencing deliberately keeps alive for exactly this reason, and which someone could remove believing the registry check replaced it. +**Why this is a risk and not merely a note.** The second half is real work in repositories this project does not control. `views-faoapi#379` has a willing owner. `views-crafdapi#53` is blocked on that partner's data contract and could sit for a long time. Both have now landed. The label's agreement with reality **no longer rests on any source-reading check**: both were deleted on 2026-08-12, not because those gates opened but because a consumer improving its own code broke the mechanism twice in a day (ADR-017 §5 erratum). What remains is C-92 — a consumer's word that its query uses the name it declares. -**What was already prevented.** A reviewer caught that the obvious sequence created a window where the source-reading check was deleted before the consumer-side check existed, leaving a green build proving only that two values this platform authored agreed with each other. ADR-017 now forbids that ordering. This entry exists so the ordering constraint has a home outside the document that states it. +**What was already prevented, and then accepted.** A reviewer caught that the obvious sequence created a window where the source-reading check was deleted before the consumer-side check existed, leaving a green build proving only that two values this platform authored agreed with each other. ADR-017 forbade that ordering, and the ordering was in fact honoured — both partners' consumer-side checks landed before their source-read was removed. The window exists anyway, permanently, because the source-reads were then deleted on their own demerits. This entry exists so that history has a home outside the document that states it. Cross-refs: **C-77** (the same field's producer-side half, resolved), ADR-013 §4.1a, ADR-017 §5/§8/Appendix B, views-appwrite#75, views-faoapi#379, views-crafdapi#53. @@ -979,7 +979,7 @@ Cross-refs: **C-62** (the transitive dependency drag; the other 31 alerts), **C- Nine of the seventeen are **new in this arc**, including both registry-drift detectors (pinned edition, commit-reachable-from-`main`) for both partners. Those detectors have a demonstrated drift rate: they fired **twice on 2026-08-03**, hours apart. A detector for a fault that recurs twice in a day, running only on one machine, is most of the way to not existing. Where each sibling stands, after trying them: -- **views-crafdapi** — public, its check reads source text. **Now checked out in CI**, recovering **one** test: the cross-seam consumer-document-name pin for CRAF'd. +- **views-crafdapi** — public; its check read source text. Checked out in CI from 2026-08-10, recovering **one** test; **that checkout was removed on 2026-08-12** when the check it served was deleted (ADR-017 §5 erratum, C-92): the cross-seam consumer-document-name pin for CRAF'd. - **views-datafactory** — public, but its eight tests need the producer's raw GAUL parquets, which are **not in its git repository**. Checking it out converts an honest skip into a `FileNotFoundError`; tried and reverted. - **views-appwrite** — was private when this was written; **made public 2026-08-08** (`views-appwrite@9d80b75`) and **now checked out in CI**, recovering **seven** tests including both registry-drift detectors. No credential was needed for any of them, and none was ever the obstacle after 2026-08-08 — the obstacle was that this line went on saying "private" for two days after it stopped being true. - **views-faoapi** — **private**, and the only one. Its single check is dark. Closing it needs either a credential or FAO's consent to make that repository public; the second is being pursued, and ADR-016 §8 carries the trigger for falling back to the first. diff --git a/tests/conftest.py b/tests/conftest.py index 9a093b6..1943321 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -179,10 +179,12 @@ class Sibling: #: the second one ``un-crafdapi`` while the repository on disk is ``views-crafdapi`` — #: exactly the kind of near-miss that makes guessing expensive. #: -#: This exists so the consumer-document-name pin can be checked **across the seam** -#: rather than asserted locally. A name this repo declares and the consumer filters on -#: is a fact this repo does not own; declaring it here is right, but only the sibling -#: checkout can confirm it still matches (ADR-014 §1 — the guarantee needs a check). +#: It exists so this repository records **who receives each delivery**. It used to also +#: locate a sibling checkout so the consumer-document-name pin could be read from that +#: consumer's source; #248 deleted that read (ADR-017 §7 — we were never entitled to +#: depend on another repository's file layout, and two consumers proved it in a day by +#: improving theirs). What the map is for now is addressing: it is who register C-92's +#: cross-repo asks are sent to. CONSUMER_REPO = { "unfao": "views-faoapi", "crafd": "views-crafdapi", diff --git a/tests/test_product.py b/tests/test_product.py index 9fbd848..e4b461d 100644 --- a/tests/test_product.py +++ b/tests/test_product.py @@ -63,7 +63,6 @@ def _product(partner: str): return importlib.import_module(f"views_postprocessing.{partner}.product") - def test_every_partner_has_its_consumer_name_pinned(): """Assert this file's declared scope is the real one (ADR-014 §2).""" assert set(_CONSUMER_DOCUMENT_NAME) == set(PARTNER_PACKAGES), ( @@ -100,7 +99,6 @@ def test_upload_interlock_defaults_off(partner): assert _product(partner).UPLOAD_ENABLED is False - @pytest.mark.parametrize("partner", PARTNER_PACKAGES) def test_both_delivery_legs_name_the_document_from_the_declaration(partner): """Register C-77 — the forecast and historical legs must agree, by construction. @@ -150,21 +148,28 @@ def test_both_delivery_legs_name_the_document_from_the_declaration(partner): "checked against the consumer's filter." ) -# ── across the seam: the pin above, checked against the repo that owns the fact ── +# ── across the seam: the pin above, checked against the registry that owns the fact ── -def test_every_partner_has_a_declared_consumer_repository(): - """The gated check below iterates this map; assert it is real (ADR-014 §2).""" +def test_every_partner_names_the_repository_that_consumes_its_delivery(): + """Every partner must name its consumer, and that name must be a declared sibling. + + **No test reads a consumer's checkout any more** (#248), so this no longer guards a + call site. It guards the *addressing*: `CONSUMER_REPO` is how this repository says who + receives each delivery, and it is what the cross-repo asks in register C-92 are + addressed to. A partner with no consumer named is a delivery with no recorded + recipient; a consumer named but absent from `SIBLINGS` is a name nothing else in this + repository can resolve. + """ assert set(CONSUMER_REPO) == set(PARTNER_PACKAGES), ( f"partners with no declared consumer repository: " - f"{sorted(set(PARTNER_PACKAGES) - set(CONSUMER_REPO))}. Without one, that " - "partner's consumer-name pin is never checked against the consumer." + f"{sorted(set(PARTNER_PACKAGES) - set(CONSUMER_REPO))}. Without one, nothing " + "records who receives that partner's delivery." ) undeclared = sorted(r for r in CONSUMER_REPO.values() if r not in SIBLINGS) assert not undeclared, ( - f"consumer repositories with no SIBLINGS entry: {undeclared}. " - "require_sibling() raises KeyError rather than skipping for those, so the " - "check would fail confusingly instead of skipping cleanly." + f"consumer repositories with no SIBLINGS entry: {undeclared}. Every repository " + "this one names must be resolvable from one declaration, or the two lists drift." ) From e806dfefc26694d8d7a24a4099980d2a760b1933 Mon Sep 17 00:00:00 2001 From: Polichinl Date: Wed, 12 Aug 2026 21:53:24 +0200 Subject: [PATCH 3/3] docs(adr-017): check the "same commit" claim instead of asserting it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /review-diff on the remediation. The erratum asserted that in BOTH repositories the commit satisfying step 3 was the same commit that broke our source read. I had verified that for views-crafdapi and asserted it for views-faoapi — the exact overstatement this arc keeps producing, in the paragraph correcting an overstatement. Verified now, and it holds: `8615574` (faoapi, #379, closed 11 August) and `0c493ae` (crafd, #53, closed 12:15 on the 12th) each introduce the named constant AND add that repository's registry-binding test. One edit, both effects, both repositories. Both shas are now in the ADR so the next reader can check it in one command rather than trusting the sentence. Also: #379 is an issue and issues close, they do not merge. Cross-document scan for residual contradictions across ADR-016 and ADR-017 — "source-read stays", "fetch stays", "#53 open", "#53 lands", "temporarily", "no window exists" — all zero. Suite 413 passed / 1 skipped / 40 xfailed, ruff clean. Epic #241. Co-Authored-By: Claude Opus 5 (1M context) --- docs/ADRs/017_facts_across_a_private_boundary.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/ADRs/017_facts_across_a_private_boundary.md b/docs/ADRs/017_facts_across_a_private_boundary.md index dcff34a..2710c15 100644 --- a/docs/ADRs/017_facts_across_a_private_boundary.md +++ b/docs/ADRs/017_facts_across_a_private_boundary.md @@ -165,16 +165,17 @@ typing. mechanism. Both facts belong here, and an earlier draft of this erratum got the first one backwards.** -Both partners' step 3 landed. views-faoapi#379 merged on 11 August; views-crafdapi#53 -closed at 12:15 on the 12th. So the constraint stated above was **satisfied**, not +Both partners' step 3 landed. views-faoapi#379 closed on 11 August (commit `8615574`); +views-crafdapi#53 at 12:15 on the 12th (commit `0c493ae`). So the constraint stated above was **satisfied**, not bypassed — and the first version of this erratum claimed the opposite, that "neither partner's step 3 is what removed them". That was false when written, six hours after the second one landed. It is corrected here rather than quietly, because an ADR that repeals its own rule on a false claim about another repository is §3's failure inside §5's text. -**What actually happened is more useful than what that draft said.** In both repositories -the commit that satisfied step 3 was *the same commit* that broke our source-reading -check: each consumer, while binding its served name to the registry, tidied +**What actually happened is more useful than what that draft said, and it is checked +rather than asserted.** In both repositories the commit that satisfied step 3 was *the +same commit* that broke our source-reading check — verified: `8615574` and `0c493ae` each +introduce the named constant and add that repository's registry-binding test: each consumer, while binding its served name to the registry, tidied `APIPathManager("literal")` into `APIPathManager(CONSUMER_DOCUMENT_NAME)`. The improvement and the breakage were one edit. Twice, a day apart.