Skip to content

[EPIC] One delivery path, one partner boundary — make this repo cloneable for views-crafdapi + views-productionapi #148

Closed

Description

@Polichinel

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_core is 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

  1. One delivery path. An incomplete launch config raises, naming the missing key.
  2. Partner declarations physically separated from delivery machinery.
  3. ADR-012 describes what the code actually is.
  4. 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

  1. One delivery path; incomplete config raises naming the missing key.
  2. unfao/managers/unfao.py < 450 lines (from 636); no wire_contract branch outside the single refusal.
  3. Partner-neutral machinery importable with zero reference to unfao, proven by a subprocess import test.
  4. Every row of ADR-012's ontology table verifiable by a command.
  5. All 40+ ADR-013 guards and byte-parity fixtures green throughout — the wire contract does not change in this epic.
  6. 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

  1. added
    epicA large capability spanning multiple stories
    planningInvestigation/spike/decision work
    on Jul 31, 2026
  2. Polichinel commented on Jul 31, 2026

    @Polichinel
    CollaboratorAuthor

    Stories created — execution tracked in #157.

    Story Closes
    #149 S1 · Delete the retired delivery path; refuse an incomplete config C-63, #145, C-29
    #150 S2 · Retire delivery/identity.py, and record why C-64, C-25
    #151 S3 · Collapse the two extraction seams C-65
    #152 S4 · Lookup access hygiene C-66, C-68
    #153 S5 · Separate partner declarations from delivery machinery C-69, C-70
    #154 S6 · Correct ADR-012 and the manager CIC C-67
    #155 S7 · Prove clone-readiness mechanically —
    #156 S8 · Closeout Cluster L

    Checklist and invariants: #157. Starting S1.

  3. Polichinel commented on Aug 1, 2026

    @Polichinel
    CollaboratorAuthor

    ✅ 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.

    before after
    Manager 636 lines 406
    Config forks 14 0 + one refusal
    pandas importers 3 1
    Lookup reads per delivery 3 1
    Open register concerns 34 25

    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_version unchanged. 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.py imported unfao.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.

    A deferral needs an owner and a trigger, not just a reason.

  4. added 2 commits that reference this issue on Aug 2, 2026
  5. added a commit that references this issue on Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    epicA large capability spanning multiple storiesplanningInvestigation/spike/decision work

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions