DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path phases/stele-extraction-contract/loomworks-stele-contract-phase-opening-handoff-v0_2.md

Loomworks — Stele Extraction Contract Phase Opening Handoff — v0.2

Version. 0.2 Date. 2026-06-16 Author. Marvin Percival (DUNIN7 Operator) with Claude.ai (scoping) on DUNIN7-M4. Status. Opening handoff for a fresh chat to scope and run the Stele contract phase — the physical teardown that 6b's view split deliberately deferred. Phase 6b is closed (merged 129d124, recorded CR-2026-110 v0.7, branch retired). Markdown primary (technical consumer / next-session orientation). v0.2 folds in two carry-forwards from CR v0.7 omitted in v0.1 (the delivery-cost reassurance and the profiling option) after a cross-check against the canonical record; no corrections, additions only.


Plain-language summary

What the contract phase is. 6a split the tables and 6b re-homed every read off the fused Person view. Now nothing reads the host columns on persons through a view — so the contract phase physically tears down the transitional structure: drop the duplicate host columns from persons, re-target the 12 host foreign keys from persons to host_account, retire the two mirror triggers, and rename/relocate PersonRow host-side. After this, persons is principal-only (or gone), host_account is the sole host home, and the transitional mirroring is removed.

Why it is its own CR, and why it is different from 6a/6b. 6a and 6b were structured so the dangerous physical change came last, after the reads were safely moved. The contract phase is that last step. Critically: unlike 6b, this phase is all migrations. 6b was application-layer — alembic stayed at 0086 throughout, and that was a guarded invariant; its safety net was "the suite breaks loudly, revert pure Python." The contract phase is the opposite: every task is a schema migration. The safety model changes completely — migration up/down correctness, trigger-retirement ordering, and FK re-targeting against live data. This is genuinely more dangerous work and wants fresh, full-attention scoping with a real Step 0 inspect, not a continuation.


Read first (the new chat's orientation)

In order, from loomworks-record (record.dunin7.com, behind Cloudflare Access — if a file can't be reached directly, ask CC to fetch it):

  1. The seed — highest loomworks-candidate-seed-vN_M in candidate-seeds/loomworks/ (canonical v0.12). The foundation document.
  2. The manifest — highest current-status-manifest-vN_M in current-status/ (v0.61 just filed; confirm it is still highest). It marks 6b complete and names the contract phase as the next slice.
  3. CR-2026-110 v0.7change-requests/cr-2026-110-stele-extraction-phase-6b-v0_7.md. The 6b close-out; its "Contract phase — handoff" section is this phase's starting inventory.
  4. The 6a completion recordphases/stele-extraction-phase-6a/loomworks-stele-phase-6a-completion-record-v0_1.md. The mirror triggers (§5) and their ordered-pair retirement requirement; the column homes and the 12 host FKs.
  5. The Stele body-of-work briefstanding-notes/loomworks-stele-body-of-work-brief-v0_4.md (confirm highest). Where the contract phase sits (Phase 6 physical split: 6a + 6b + contract; Phase 7 = de-engine packaging).

Current build state (as of 6b close, 2026-06-16)

| Ref | State | |---|---| | engine main | 129d124 (6b merged, --no-ff) | | alembic | 0086 (will advance in the contract phase — this phase has migrations) | | suite | 2933 / 46 / 0 | | branches | no open Stele branch (6b retired) | | views | one Principal (Stele) + HostAccount (host-side); Person view + get_current_person retired |

The new chat starts clean from main at 129d124.

The contract-phase scope (what to scope — do NOT pre-decide; these are Step 0 work)

The four teardown tasks, from CR v0.7's handoff:

  1. Drop the persons host columns. Now that 6b re-homed every reader, the host columns on persons are duplicates of host_account. Drop them. Includes the mint host-column cleanup — mint stops writing email/mobile/onboarding_complete to persons. (Scope: which columns exactly, in what order relative to FK re-targeting and trigger retirement.)
  2. Re-target the 12 host FKs from persons to host_account. (Scope: the real FK inventory, the re-target order, whether any FK is hot-path-sensitive, and the deferred/shared-id mechanics from 6a.)
  3. Retire the two mirror triggers AS AN ORDERED PAIR. 0085 (personsprincipals) and 0086 (personshost_account) fire in name-sort order. They must be retired so one never fires without the other (6a completion record §5). This is the single most ordering-sensitive task in the phase. (Scope: the exact retirement sequence; what depends on each trigger still firing during the column drop / FK re-target; whether retirement is one migration or an ordered sequence.)
  4. Rename/relocate PersonRow host-side. The ORM row kept its name through 6b. Relocating it resolves the standing inversion: persons/host_account_view.py currently imports HostAccountRow from stele/models.py (the row still physically in Stele) — fine during expand, resolved at relocation. Use the token-level rename pattern proven in 6b 3.7 — a NAME-token sweep, NOT a blanket \bPerson\b regex, which would corrupt title="Person" (OpenAPI), "Test Person" string literals, and docstrings.

The ordering question is the heart of Step 0. These four tasks interact: the triggers keep host_account in sync with persons writes; dropping persons columns removes what the triggers mirror; re-targeting FKs changes what points where. The order — drop columns vs retire triggers vs re-target FKs — is not obvious and must be grounded against the real schema, not assumed. Expect this to be the central scoping work.

Reassurance for the scoper (not a teardown task — from CR v0.7 item 5). The deps.py two-load delivery needs no change when persons drops its host columns. get_host_account_by_id already reads from host_account (chosen in 3.0 for exactly this durability), so when persons loses its host columns the two-load shape is simply the natural principals + host_account read — the contract reality 6b's delivery was already built for. No 6b delivery rework falls out of the column drop. This is a reassurance, not a task; it tells the scoper one thing they might otherwise inspect-to-confirm is already handled.

Non-blocking cleanups to fold in (carry, do not let them gate the CR)

Standing disciplines to carry in (hardened across Phases 0–6b)

The method 6b proved (reusable here)

What comes after the contract phase

Phase 7 — de-engine completion + packaging: cut the remaining config/database/persons/shared-Base threads; Stele's own dependency manifest + migration set; the SDK surface; docs-with-runnable-examples; the reference UI template (closes the Phase 0 WebAuthn-ceremony gap). The clone-and-run standalone repo for the Claude Code Miami milestone. The contract phase is the last step before Stele is physically free of the host's schema.


DUNIN7 — Done In Seven LLC — Miami, Florida Loomworks — Stele Extraction Contract Phase Opening Handoff — v0.2 — 2026-06-16