Skip to content

docs: ADR-036 and ADR-037 — delivery architecture, and correct the register's counting - #152

Open
Polichinel wants to merge 3 commits into
developmentfrom
docs/adr-036-037-delivery-architecture
Open

docs: ADR-036 and ADR-037 — delivery architecture, and correct the register's counting#152
Polichinel wants to merge 3 commits into
developmentfrom
docs/adr-036-037-delivery-architecture

Conversation

@Polichinel

Copy link
Copy Markdown
Contributor

Two ADRs, six new register entries, and a correction to a correction. Both ADRs are Proposed and await your ratification — nothing is implemented.

ADR-036 — bulk delivery is a built artifact, not a rendered response

Precompute the 45-column schema at each level once per run; serve with FileResponse; verify byte-for-byte against the 461,991-byte characterization test that already exists; delete nothing until the new path has served a monthly cycle.

The key reasoning: the HDI-of-a-sum argument proves server-side aggregation, not a query API. The vocabulary is closed — 5 levels × 2 categories — so precomputing satisfies the statistics identically, at ~2.5 min per delivery against 3–70 s per request. This repo already does it for one route.

Deferred with named triggers, not dropped: publishing raw draws (nobody has asked, and publication is a contract), and deleting cache tiers (views-faoapi attempted this and found three of four targets load-bearing for security and the last-good fallback, not rendering).

ADR-037 — run identity and the live-run pointer

get_latest_manifest() takes no arguments and returns docs[0] sorted by upload time — a last-write-wins register deciding what a UN partner sees. Upload a second artifact today and it becomes production.

Artifacts become run-addressed; lead time goes in the path (four review seats reached this independently — a catalogue carrying identity the bytes do not is a second source of truth); one explicit pointer says which run is live, the only mutable thing in the delivery. The archive waits on three upstream blockers; only the shape is built now.

Register — C-303…C-308

ID Tier
C-303 2 no run address; newest upload wins — live hazard today
C-304 3 the 413 names provenance fields the endpoint does not return — my defect from Sunday
C-305 3 shard resolution scans every run in the bucket, forever
C-306 3 identity guards carry cache invalidation and the ADR-033 guarantee in one comparison
C-307 3 the 20-route grid was inherited, not chosen; ADR-026's informed party is FAO
C-308 2 the delivered run is pgm-only, reconciled: false on 108/108 shards

The correction, which is the part worth reading

C-298 is corrected a second time. The register's section headings are decorative. Entries have been appended to the file end for months: 39 concerns sit under "Register Conventions", 11 under "Disagreements" — including four I added last week.

Counted by content: 63 open / 14 resolved of 77. My 2026-08-24 "fix" to 22/43 trusted the headings and was further from the truth than the original 54/11.

test_register_counts.py now derives status from each entry's own text and never from its section. The previous version encoded the section rule and therefore enforced the wrong numbers — a guard that codifies an untested assumption makes it harder to question, not easier. Confirmed failing on the exact figure it used to enforce.

The 39 misplaced entries are deliberately left alone: moving them is a large diff that changes nothing now that counting is content-based.

Verification

1128 passed, ruff clean, docs/validate_docs.sh passes.

…over

Two decisions came out of the delivery-architecture review, so two ADRs.

ADR-036 — bulk delivery is a built artifact, not a rendered response.
Precompute the 45-column consumer schema at each level once per run, serve
with FileResponse, verify byte-for-byte against the existing 461,991-byte
characterization test, and delete nothing until the new path has served a
monthly cycle. The HDI-of-a-sum argument proves server-side AGGREGATION, not a
query API: the vocabulary is closed (5 levels x 2 categories), so precomputing
satisfies the statistics at ~2.5 min per delivery against 3-70 s per request.
Deferred with named triggers: publishing raw draws (nobody has asked), and
deleting cache tiers (faoapi attempted exactly this and found three of four
targets load-bearing for security and last-good fallback, not rendering).

ADR-037 — run identity and the live-run pointer. get_latest_manifest() takes
no arguments and returns docs[0] by upload time: a last-write-wins register
deciding what a UN partner sees. Upload a second artifact today and it becomes
production. Artifacts become run-addressed, lead time goes in the path (four
review seats reached this independently), and one explicit pointer says which
run is live — the only mutable thing in the delivery. The archive itself waits
on three upstream blockers; only the shape is built now.

Register: C-303..C-308 registered.
- C-303 (Tier 2) no run address; newest upload wins — live hazard today
- C-304 (Tier 3) the 413 names provenance fields the endpoint does not return
- C-305 (Tier 3) shard resolution scans every run in the bucket
- C-306 (Tier 3) identity guards carry cache invalidation AND the ADR-033
  guarantee in one comparison
- C-307 (Tier 3) the 20-route grid was inherited, not chosen; ADR-026's
  informed party is FAO
- C-308 (Tier 2) the delivered run is pgm-only, reconciled:false on 108/108
  shards, so the agreed spec cannot currently be met

C-298 corrected a second time, and the correction is the interesting part: the
register's section headings are decorative. Entries have been appended to the
file end for months, so 39 concerns sit under "Register Conventions" and 11
under "Disagreements" — including four I added last week. Counted by content,
which is the only reliable method, it is 63 open / 14 resolved of 77. My
2026-08-24 "fix" to 22/43 trusted the headings and was further from the truth
than the original 54/11.

test_register_counts.py rewritten to derive status from each entry's own text
and never from its section. The previous version encoded the section rule and
therefore ENFORCED the wrong numbers — a guard that codifies an untested
assumption makes it harder to question, not easier. Confirmed to fail on the
exact figure it used to enforce.

The 39 misplaced entries are deliberately left in place: moving them is a large
diff that changes nothing now that counting is content-based.
views-pipeline-core raised this in cross-session review; verified at source
before accepting.

C-302 reported crafd_bucket answering an anonymous file listing with HTTP 200
and total:0, and concluded the container grants anonymous read while
file_security=True hides the files. That conclusion is not supported by the
evidence, and the endpoint is documented as unable to support it.

views-models/tools/credentials/close_resource_permissions.py:118-136, measured
against Appwrite 1.9.5 on 2026-08-02: Appwrite answers a REJECTED key on the
file-listing endpoint with HTTP 200 and total:0 rather than 401 — "a shape that
renders a refusal as emptiness". Their probe therefore refuses to reduce the
result to a boolean and discriminates three ways: 4xx refused; total>0
"READABLE BY ANYONE"; total==0 "accepted the request but returned nothing",
explicitly not called readable.

Mine returned total:0. I reported it as the readable case.

What stands: the 401s, which are the half that mattered. crafd is closed on
both API shapes, #123's subject is clean, and create_bucket normalises
permissions=None to [] so this repo cannot have created that bucket.

What does not stand: that the container is world-readable. Unknown, and
unknowable by the method I used.

The transferable part is the method rather than the finding — I built a probe
to answer a yes/no question on an endpoint another repo had already measured as
unable to carry one, and its failure mode was returning the answer I was
looking for. The entry is now a question, not a finding.

Also corrected views-appwrite#160, where I had used the finding as an argument
for one of the options in their resource-permissions story. That argument
rested on the container being open and is withdrawn. The narrower point
survives and is worth their attention: their probe reads declared container
permissions and does not probe anonymously; mine probed anonymously and cannot
read the ACL. Neither instrument alone distinguishes a closed container from a
refusal rendered as emptiness.

ADR-037 gains one upstream fact from the same exchange, which changes a
downstream instruction: on the PredictionFrame path pgm_cm_point is not
honoured as point reconciliation at all — prediction_frame_ensemble.py:646
gates on truthiness rather than equality, so a sampled ensemble declaring
"point" receives aligned-draws regardless. If a reconciliation type is adopted
for this delivery, adopt pgm_cm. That is now a concrete instruction for
views-models#423 rather than a preference.
I wrote that pipeline-core #490 'step 1 has landed'. Verified against GitHub:
PR #492 is OPEN against development and not merged, so pgm_cm_point warns in
no released version. Raised by views-pipeline-core.

The instruction is unaffected and the ADR now says why: the truthiness gate at
prediction_frame_ensemble.py:646 is in shipped code today, so a sampled
ensemble declaring pgm_cm_point already receives aligned-draws regardless of
when the deprecation lands. 'Adopt pgm_cm' holds independently of #492.

Small, but it is the third time this week a status I reported as landed was
in fact in flight, and an ADR that overstates upstream readiness is exactly
how a downstream plan gets built on a branch.
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