feat(#333): the un_crafd launcher, disarmed — and the delivery protocol gets one home (ADR-022) - #380
Merged
Merged
Conversation
… home CRAF'd's bucket is empty because nothing in views-models runs its producer. This adds the launcher. views-crafdapi's epic #40 calls it the single true blocker. DISARMED ON PURPOSE. deliveries/un_crafd.py declares intent = paused(...), so wire_upload_enabled derives to False and the manager never constructs a partner store: a run stages artifacts locally and makes zero store calls. #333 asked for "wire_upload_enabled: False"; since #348 that key is derived from intent, and paused is how you say it while keeping the reason and the date. Arming is views-crafdapi's D5 (#45), after their D4 dry run. #333's file spec is stale and was NOT followed literally. It predates ADR-019, #348 and ADR-021: it says to type region="land_gaul" and ensemble="rusty_bucket" into config_meta, and never mentions deliveries/ at all. ADR-021 §1 forbids a coverage literal under postprocessors/. crafdapi #43 is the current spec and is what this follows. Nothing under postprocessors/un_crafd/ types a coverage or a source; both derive. THE RUN.SH EXTRACTION (ADR-022, on the maintainer's explicit decision). run.sh changes for two unrelated reasons -- because a partner differs (conda env, pin) and because the delivery protocol differs (registry before conda, environment after it, capability by import not grep). The second must not be copied: a protocol fix would need hand-applying per partner, and the first one missed fails silently. views-postprocessing already has that scar from cloning unfao/ into crafd/ -- their #211's follow-up is titled "every partner-scoped guard was scoped to ONE partner". tools/launcher/postprocessor.sh the body, sourced and non-executable, the same shape as platform_env.sh un_fao/run.sh 136 lines -> 21 un_crafd/run.sh 21 lines Every scar the body carries is preserved with its issue number: #308 registry fatal and early, #293 no set -a, #294 capability by import, C-57, C-112. THE PIN. un_crafd pins the immutable commit 3286eab. NOT a tag, because no tag carries the crafd package -- the only tag is 1.0.0 and `git ls-tree -r 1.0.0 | grep -c crafd` is 0, with no GitHub releases at all. crafdapi #43 asked for a released tag; a commit is the closest thing that exists and it has the property the request is for. un_fao keeps @main: changing a live delivery's installer is #364's, not this extraction's side effect. Parameterising it makes #364 a one-variable edit. deliveries/status.py gains declared_source() and upload_armed() beside declared_coverage(), so the second config derives rather than copying three helper functions. THREE TEST GAPS CLOSED, each found by building the second consumer: Nothing checked that a delivery declaration is coherent -- all 20 check() call sites hardcoded consumer="un_fao", so a flatly incoherent un_crafd would have shipped green. Now every file delivery_files() finds is checked. test_the_fao_source_is_no_longer_a_buried_literal was un_fao-hardcoded, so a cloned config with a literal ensemble would have passed it. Generalised. Nothing asserted that a postprocessor config IMPORTS. get_queryset() swallows the exception (model_path.py:783-785) and declared_data_format(None) defaults to dataframe, so a failed import is indistinguishable from a wrong declaration (views-postprocessing C-83) -- and at global-land scale the pandas path OOM-kills. ADR-021 gave config_queryset an import, which is what made this worth asserting. Imports are exercised from an unrelated working directory. The two launcher test files are parametrised over EVERY launcher and read each one's effective text (wrapper + sourced body). Reading run.sh alone would have made all of them pass vacuously the moment the body moved. Renamed from test_unfao_* to test_postprocessor_* because they no longer describe one partner. Also corrected while here, all verified stale rather than assumed: ADR-017 §357 "exactly one coherence violation" -> two edges, same cause deliveries/un_fao.py "nothing reads this file yet" -- it has since #347 registry_to_env.py + bootstrap.yml -- both described CRAFD coordinates as planned; they graduated to valued [target] entries 2026-08-02 forecast_delivery_map.md -- singular-FAO prose. The re-traced date is NOT bumped: I re-checked the code, not the buckets. Register: C-134 (the launcher clone, Mitigated) with the extraction trigger crafdapi named -- a third partner, or the first bug hand-patched in both. Full suite: 7794 passed, 219 skipped, 0 failed.
This was referenced Aug 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #333. Executes views-crafdapi D3 (#43). Introduces ADR-022.
CRAF'd's bucket is empty because nothing here runs its producer — crafdapi's epic #40 calls this the single true blocker.
Disarmed on purpose
deliveries/un_crafd.pydeclaresintent = paused(...), sowire_upload_enabledderives toFalseand the manager never constructs a partner store: a run stages artifacts locally and makes zero store calls.#333 asked for
wire_upload_enabled: False; since #348 that key derives fromintent, andpausedis how you say it while keeping the reason and the date. Arming is crafdapi's D5 (#45), after their D4 dry run.#333's file spec is stale and was not followed literally
It predates ADR-019, #348 and ADR-021: it says to type
region="land_gaul"andensemble="rusty_bucket"intoconfig_meta, and never mentionsdeliveries/at all. ADR-021 §1 forbids a coverage literal underpostprocessors/. crafdapi #43 is the current spec and is what this follows — nothing underpostprocessors/un_crafd/types a coverage or a source.The run.sh extraction — ADR-022
run.shchanges for two unrelated reasons: because a partner differs (conda env, pin), and because the delivery protocol differs (registry before conda, environment after it, capability by import not grep). The second must not be copied — a protocol fix would need hand-applying per partner, and the first one missed fails silently. views-postprocessing already has that scar from cloningunfao/intocrafd/: their #211's follow-up is titled "every partner-scoped guard was scoped to ONE partner".tools/launcher/postprocessor.shplatform_env.shun_fao/run.shun_crafd/run.shEvery scar the body carries keeps its issue number: #308, #293, #294, C-57, C-112.
The pin — and a #43 criterion I could not meet as written
un_crafdpins the immutable commit3286eab. Not a tag, because no tag carries the crafd package: the only tag is1.0.0,git ls-tree -r 1.0.0 | grep -c crafd→0, and there are no GitHub releases at all. #43 asked for a released tag; a commit is the closest thing that exists and has the property the request is for. Say the word upstream and it becomes a one-line change.un_faokeeps@main— changing a live delivery's installer is #364's, not this extraction's side effect. Parameterising it makes #364 a one-variable edit.Three test gaps closed, each found by building the second consumer
check()call sites hardcodedconsumer="un_fao", so a flatly incoherentun_crafdwould have shipped green. Now every filedelivery_files()finds is checked. Verified it bites.test_the_fao_source_is_no_longer_a_buried_literalwas un_fao-hardcoded, so a cloned config with a literalensemblewould have passed it. Generalised.get_queryset()swallows the exception (model_path.py:783-785) anddeclared_data_format(None)defaults todataframe, so a failed import is indistinguishable from a wrong declaration (views-postprocessing C-83) — and at global-land scale the pandas path OOM-kills. ADR-021 gaveconfig_querysetan import, which is what made this worth asserting. Exercised from an unrelated working directory. Verified it bites.Both launcher test files are now parametrised over every launcher and read each one's effective text (wrapper + sourced body). Reading
run.shalone would have made all of them pass vacuously the moment the body moved. Renamedtest_unfao_*→test_postprocessor_*, because they no longer describe one partner.Corrected while here — all verified stale, not assumed
deliveries/un_fao.py— "nothing reads this file yet"; it has since S5 — Make the FAO launcher read deliveries/un_fao.py and retire the buried "ensemble" line #347registry_to_env.py+bootstrap.yml— both described CRAFD coordinates asplanned; they graduated to valued[target]entries on 2026-08-02, so no credential work was neededforecast_delivery_map.md— singular-FAO prose. The re-traced date is not bumped: I re-checked the code, not the bucketsRegister
C-134 (Mitigated) — the launcher clone, with the extraction trigger #43 named: a third partner, or the first bug hand-patched in both.
Verification
ruff check .cleana0b5e015viatools/audit/verify_committed.sh— 7607 passed, 0 failed. That matters more than usual here: the point of a launcher is that a clean clone can run itun_fao→ armed,un_crafd→ disarmedland_gaulorrusty_bucketliteral anywhere underpostprocessors/un_crafd/models/violet_visitor/untouchedA real
bash postprocessors/un_crafd/run.shis not run here — that is crafdapi's D4 dry run, on a machine with credentials.