Repository navigation
[EPIC] One delivery path, one partner boundary — make this repo cloneable for views-crafdapi + views-productionapi #148
Description
The problem
views-crafdapi and views-productionapi will be cut from this platform, with this repo as the basis for their delivery layer. Four investigations — repo-assimilation, expert-code-review, review-rr strategic and prioritize — converged on one diagnosis:
The architecture is sound and largely reusable. What blocks cloning is one un-executed deletion and one packaging boundary that was never drawn.
What is already good — do not touch it
views_pipeline_coreis imported by exactly one module (unfao/managers/unfao.py). The coupling C-40 describes is real but one file wide.delivery/is partner-agnostic by its own declaration (__init__.py:3) and imports neither pandas nor views_frames.unfao/wire/already takes its consumer name as a parameter (sink.py:162) — the machinery is parameterisable today.- ADR-013 is enforced by 40+ falsification guards and byte-parity fixtures.
What blocks it
The frame-native contract path replaced the pandas path and won — run-0 delivered global-land on 2026-07-27 and FAO has been served from it since. The replaced path was kept behind a config fork "until run 0 proves the contract path live" (register C-40) and never removed.
D-11 predicted exactly this: "If it lingers, three-way duplication becomes the permanent shape." It has.
Two independent config axes (wire_contract, data_format) give four delivery modes; production uses one; omitting either key silently selects the retired half — .get() returning None is indistinguishable from a deliberate False. That is the inference ADR-003 forbids, in the repo that authored it.
Meanwhile ~800 of unfao/'s 1,001 lines are partner-neutral machinery sitting under one partner's name (C-69).
Why the deletion leads
Seven open register entries collapse on it: C-63 (silent fork), C-65 (extraction 4/5 dead), C-66 (lookup read 3×), C-68 (private-name coupling), C-29 (disk side-channel — legacy-only), #145 (silent upload failures), C-25 (registered mitigation is legacy-only).
Nothing else available scores close. Everything else open is blocked upstream (C-13/C-26/C-27/C-28/C-58 = pipeline-core; C-44/C-62 = the 3.0.0 release signal; C-43 = views-datafactory#387; C-24 = faoapi) or already discharged. This epic is deliberately free of upstream blocks.
Desired end state
- One delivery path. An incomplete launch config raises, naming the missing key.
- Partner declarations physically separated from delivery machinery.
- ADR-012 describes what the code actually is.
- A mechanical proof that the machinery imports with zero reference to
unfao— so a clone takes the wire contract without taking FAO.
Scope boundaries — explicitly OUT
No Strategy hierarchy · no DeliveryProfile object (C-33/D-09 — wait for #97's real second-partner needs) · no shared client library · no pipeline-core de-inheritance (C-40's shell, blocked on their 3.0.0) · no repo rename (D-12/#96).
Each is a speculative abstraction for a consumer that does not exist yet. WET before DRY — build the abstraction when the second partner shows its real shape, and defer behind a named trigger.
Stories
| # | Story | Closes |
|---|---|---|
| S1 | Delete the retired delivery path; refuse an incomplete config | C-63, #145, C-29 |
| S2 | Retire delivery/identity.py; record why |
C-64, C-25 |
| S3 | Collapse the two extraction seams | C-65 |
| S4 | Lookup access hygiene | C-66, C-68 |
| S5 | Separate partner declarations from delivery machinery | C-69, C-70 |
| S6 | Correct ADR-012 and the CIC | C-67 |
| S7 | Prove clone-readiness mechanically | — |
| S8 | Closeout | Cluster L |
S1 ──┬──> S2
├──> S3 ──> S4 ──┐
└────────────────┴──> S5 ──┬──> S6
└──> S7 ──> S8
Epic acceptance criteria
- One delivery path; incomplete config raises naming the missing key.
unfao/managers/unfao.py< 450 lines (from 636); nowire_contractbranch outside the single refusal.- Partner-neutral machinery importable with zero reference to
unfao, proven by a subprocess import test. - Every row of ADR-012's ontology table verifiable by a command.
- All 40+ ADR-013 guards and byte-parity fixtures green throughout — the wire contract does not change in this epic.
- Register reflects the end state; Cluster L closed.
Verification, every story
ruff check . · pytest -q --deselect tests/test_datafactory_deploy_readiness.py (expect the 5 known local pyarrow byte-parity failures, no new ones; CI authoritative) · test_hop_b_sink_e2e.py green — proves the surviving path unchanged · test_register_integrity.py green.
Full ritual per story: /review-diff → /register-risk if findings → /ship-it → PR → CI → merge.
Investigation: repo-assimilation + expert-code-review + review-rr (2026-07-31). Register entries C-63–C-70 and Cluster L landed in #147.
Activity
Polichinel commentedon Jul 31, 2026
Stories created — execution tracked in #157.
delivery/identity.py, and record whyChecklist and invariants: #157. Starting S1.
feat(delivery): S1 — one delivery path; refuse an incomplete launch c…
refactor(delivery): S2 — retire delivery/identity.py; the rule moved,…
refactor(unfao): S3 — one representation seam; store metadata gets it…
refactor(unfao): S4 — the GAUL lookup is one artifact, read once, pub…
docs(adr): S6 — the ontology describes the code, and the claims are n…
test(clone): S7 — prove the machinery imports without the partner (#165)
docs: S8 — epic #148 closeout; Cluster L closed (#166)
Polichinel commentedon Aug 1, 2026
✅ Complete — all eight stories merged, tracker #157 closed
The diagnosis held. What blocked cloning was one un-executed deletion and one packaging boundary that was never drawn. Both are done.
views_postprocessing/now has three packages that answer three questions:delivery/(what makes a delivery valid) ·contract/(how it is built) ·unfao/(who it is for — 3 files).Every invariant held
The §10 golden fixture and byte-parity tests were untouched and green on CI at all eight merges.
contract_versionunchanged. This was a restructure, and it is provable rather than asserted.The finding I did not expect
S5's move exposed a coupling invisible while everything shared a package:
contract/wire/sink.pyimportedunfao.product— not in its logic, but as default argument values. DIP looked satisfied because the parameters existed. A clone would silently have inherited FAO's consumer name and collapse floor.That is the whole case for doing the packaging split rather than declaring the machinery reusable because it took parameters.
Left open on purpose
C-40 — the double inheritance stands, gated on views-pipeline-core 3.0.0 (a release signal, not engineering). C-60 — moved verbatim in S4 rather than fixed, because no behaviour change in a move is the discipline S5 depended on.
The lesson, recorded in Cluster L
Not that WET-before-DRY was wrong — the siblings were correct, and a premature Protocol would have outlived them. What failed is that the removal condition was written without a named trigger to act on. The box expired on 2026-07-27 and nobody opened it.
docs(accuracy): S11 #197 — living docs still described code #148 dele…
test(redaction): S10 #192 — repair the þing-01 guard; a declared root…
#268: download refuses instead of returning None — C-79's untreated s…