DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path current-status/current-status-manifest-v0_59.md

Loomworks Current-Status Manifest — v0.59

Version: 0.59 Date: 2026-06-15 Status: Working draft. Marks Stele extraction Phase 5 (credential lifecycle) complete and merged to engine origin/main 8f2665a (fast-forward 9be25fd..8f2665a, 7 files / 918 insertions, no merge commit; branch cr-2026-108-stele-extraction-phase-5 held, not yet deleted — deletion is the Operator's separate step after the completion record files). Phase 5 added no schema change — alembic stays at 0084 (the streak Phase 4 broke is restored; the locked hard-delete decision avoided a migration). Phase 5 built the two genuinely-missing credential-lifecycle operations and closed one gap on the already-built enrollment path: passkey-revoke (DELETE /me/security/passkeys/{id} + a new Stele remove_credential primitive — the first delete idiom in stele/, hard-delete — with a last-passkey guard at the primitive layer); person-scoped TOTP-rotate (a new Stele twin stele/person_totp.pybegin_totp_rotation + confirm_totp_rotation, verify-in-primitive, re-encrypt onto PersonRow.totp_secret; no import of contributors/, layering preserved); and the display_name plumbing threaded through the passkey-complete route (substrate already accepted it). Second-passkey enrollment and recovery-code surfacing were already shipping (the latter via the §10.3 amendment) and were not rebuilt — the grounding read established this before any code. Records three decisions, one a correction caught at Step 0 grounding: the revoke guard predicate was corrected from the scoping note's "block iff passkey_count == 1 AND totp_secret IS NULL" (TOTP treated as a fallback) to "block the last passkey unconditionally" — because the real login flow is passkey-assertion → partial → then TOTP/recovery, so TOTP cannot mint a session alone and a person whose last passkey is removed is locked out even with a TOTP secret; plus hard-delete-over-migration and person-scoped-twin-over-generalize. Two build deviations CC caught and resolved: a git add -A swept a Cloudflare credential file into the 5C commit (amended out before any push; .wrangler/ gitignored; explicit-path staging adopted from 5A onward), and the hard-delete tripped the non-erasure architectural guard test_no_delete_statements.py (resolved the guard's designed way — credentials.py added to the file-level allowlist with a rationale matching the six precedents and the sibling OVA module's documented discipline; a credential is operational auth, not a MemoryObject; Operator-reviewed verbatim before push). Standing lesson extended again: grounding now covers **the architectural invariants that police the kind of change, not just signatures and placements — the guard collision surfaced at build (5A) because Step 0 read the placement site and call-sites but not the repo-wide guard suite; this was applied immediately in 5B (a read-only guard-suite scan before editing, which came back clean). Proven end-to-end in the real database (all six §7 cases on the real HTTP path; the corrected guard refuses the last-passkey-with-TOTP revoke with a real 409; invalid-code rotate leaves the old secret intact). Suite 2933/46/0; alembic 0084 on main/playground_dev/playground_test. Points to the Phase 5 completion record loomworks-stele-phase-5-completion-record-v0_1 and the governing CR cr-2026-108-stele-extraction-phase-5-v0_2. The SSO forward-dependency on the revoke guard is recorded in code and the record: when org-SSO lands the guard's "other ways in" predicate widens to "last passkey AND no SSO binding"; until then the guard counts passkeys only. The next slice is the de-engine-ing toward the standalone repository** (see the standalone-distribution milestone paragraph below; note the manifest-vs-brief tension on what Phase 6 contains, flagged there for Operator reconciliation). Otherwise carries v0.58 forward. Purpose: To serve as a fresh chat's first orientation. The manifest is a current-status record, not a foundation. The foundation is what-dunin7-is-building-v0_20.md (2026-05-02). The manifest sits above it. Scope of absorption: v0.42 spans 13 days of accumulated state (2026-05-12 to 2026-05-25) — substantially more than the per-phase absorption cadence v0.31 through v0.41 used. See §1.D for the cadence shift and §2 for the consolidation-surface shift.


How to read this manifest

Before treating any document in project knowledge as authoritative, check this manifest first. Project knowledge may contain superseded framings, deferred-or-since-shipped predictions, or pre-cleanup-arc references. The manifest reflects current state.

Cross-document hierarchy. The architecture specification (architecture/loomworks-architecture-specification-v0_4.html) is the structural source. The methodology canon (operations/loomworks-methodology-canon-v0_1.html) is the methodology source. The development assessment (substrate/where-we-are-in-loomworks-development-assessment-v0_1.html) frames the Phase A/B/C horizons. The manifest cross-references all three rather than re-stating their content.

The manifest is the absorption layer; the methodology document is the consolidation layer. This separation from v0.41 holds — with one substantive structural shift. A separate consolidation surface emerged between v0.41 and v0.42: the methodology canon in operations/. The relationship between the canon and the anticipated what-dunin7-is-building v0.21 consolidation is an open question (see §3 below).

Repos. Three code repos plus marketing, all under DUNIN7/ on GitHub:

The record repo is DUNIN7/loomworks-record, served at record.dunin7.com via Cloudflare Pages.


Section 1 — Current document authority

Repo names

Unchanged from v0.41. Three code repos plus marketing, all under DUNIN7/. Path conventions as above.

Methodology document

Updated for v0.42 (structural shift). v0.41 named the methodology v0.21 consolidation as outstanding, with the backlog "compounding noticeably." v0.42 absorbs an additional body of methodology contributions from the cleanup arc — but four of those have already been canonized at operations/loomworks-methodology-canon-v0_1, bypassing the v0.21 path entirely.

The structural shift: methodology consolidation now happens on two surfaces:

The relationship between the two surfaces is an open question for the Operator to resolve when v0.21 is undertaken. Possibilities: v0.21 absorbs the canon by reference; v0.21 absorbs only what the canon hasn't taken; the canon eventually replaces the v0.21 consolidation cadence; they coexist permanently on different cadences. v0.42 records the question but does not resolve it.

The other accumulated candidates (Phase 49/50/51/52/53/54/55/56 build findings, plus the candidates surfaced during the cleanup arc that didn't reach canon threshold) remain v0.21 lift candidates.

Current live build front

The Stele extraction is the current live build front. Stele is the principal/identity layer — the fourth Loomworks product alongside OVA, FORAY, and Loomworks itself. The extraction gives the engine's scattered identity code a clean, named module boundary and a host-agnostic contract, moving in small reversible slices with no behaviour change. Phase 0 (complete, engine e4656b4) stood up the stele/ module and moved the three zero-caller-outside-identity files (recovery.py, webauthn.py, session.py) as pure renames. Phase 1 is complete and pushed (engine origin/main f1cf170): the remaining core identity pieces — PersonRow, the two credential row models, the registry (principal view), and credentials.py — moved into stele/ under a shared Base at loomworks.identity_base; four commits, all pure renames with selective per-symbol import repoints; suite green (2920/46/0); no schema change (alembic 0083 unchanged); real-database sign-in + credential read verified from stele/. The KEK did not move (top-level credentials/, untouched). The gating persons.id FK / Base decision was locked before execution: D1 = own-its-own-table (direction), D2 = Branch 1 (code-move now, physical split deferred to Phase 6). Phase 2 is complete and pushed (engine origin/main 677c46f): the two actor constructors (actor_from_personkind="person", actor_from_companionkind="companion" bound to person.id) moved out of orchestration/helpers.py into a new dedicated module stele/actor.py; the project-membership pieces (OperatorProjectNotFoundError, verify_project_membership) stayed in orchestration/ (a split, not a whole-file move); the ActorRef type was referenced, not moved (owned by the memory substrate). Four commits (Step 0 archive, v0.2 re-archive, the collapsed move-and-repoint, the comment/docstring sync); suite green (2920/46/0); no schema change (alembic 0083 unchanged); real-DB person-actor and companion-actor stamps verified from stele/. The CR was amended v0.1→v0.2 mid-flight: v0.1 split the move from the repoints and predicted a runnable suite minus 6 files, but removing module-top-imported constructors before repointing the production routers aborts collection (33 errors); the fix collapsed Steps 2.1–2.3 into one move-and-repoint commit, restoring the Phase 1 mechanic (each move bundled with its repoints, green at every commit). Completion record: loomworks-stele-phase-2-completion-record-v0_1. Phase 3 (get_current_person / session-resolution → Stele) is next — points the auth-path actor resolution (api/deps.py) under Stele; the ~119 session-resolution callers do not move. Halt-before-push; per-step commits; database-truth regression.

Phase 3 is complete and pushed (engine origin/main d3acd84): session→principal resolution moved into Stele as resolve_session in stele/session.py, returning a ResolvedSession(person, payload); all five decode-load sites in deps.py (get_current_person, get_current_person_optional, _resolve_optional_person, _resolve_cookie_actor, _resolve_cookie_contributor) now delegate to it — zero inline decode_session remain. The totp_verified/person-exists policy stays host-side, read off the carried payload; the person actor routes through stele.actor.actor_from_person; membership, can_commit, contributor-membership, and bearer/agent builds stay host-side (the seam: Stele resolves who, the host decides what-here). Four step-commits (3.1 add operation, 3.2 thin three person resolvers, 3.2b contributor seam inspect-first, 3.3 engagement seam + actor route); Step 3.4 verification-only; suite green at every commit (2920/46/0); no schema change (alembic 0083). The CR took three amendments before any code (v0.2 two-resolver finding; v0.3 ResolvedSession carries the payload so the second-factor gate isn't dropped; v0.4 grounding read found five decode-load sites not two), each driven by reading the real engine rather than a line-coordinate guess — the standing lesson: ground the design in a full read of the real code before drafting executable steps. One recorded minor behaviour change: distinct 401 detail strings collapsed to one None-case 401 (status codes preserved, no test affected). Completion record: loomworks-stele-phase-3-completion-record-v0_1. Phase 4 (the sign-up mint↔onboard split, approach B) is complete and merged (see below).

Phase 4 (the sign-up mint↔onboard split, approach B — two-phase) is complete and merged (engine origin/main 9be25fd; branch cr-2026-107-stele-extraction-phase-4 merged fast-forward and deleted local + remote). This is the first schema change in the extraction and the first real behaviour change (Phases 0–3 were schema-neutral pure-relocation slices). The fused complete_totp_verify split into mint_principal (Stele, stele/registry.py) and onboard (host, persons/onboard.py), committing separately: mint commits durably first, then onboard; the route owns both commits with the mint commit explicit and outside get_db_session's rollback scope (viable because the session factory uses expire_on_commit=False). A new onboarding_complete boolean (migration 0084, inverted backfill — existing rows true, new mints false) marks the minted-not-onboarded orphan state; _heal_if_orphaned (both login routes, after the account-status gate, before the cookie) runs onboard(claim_token=None) to complete an orphan on next sign-in. The credit-grant claim moved from the route into onboard; create_person kept separate (bare credential-less primitive, saved-filter tail stripped → relocated to onboard). Step series 4.1 (migration) → 4.2 (mint + strip) → 4.3a/b/c (onboard, two-phase route rewrite, new-semantics test re-points) → 4.4 (heal); suite green at every commit, final 2921/46/0; alembic 0084 on main/playground_dev/playground_test. The CR took **four versions, two corrections caught in build (v0.3 mint signature — sketched from the integration design's contract vocabulary rather than the real :255–284 body; v0.4 heal placement — "before issue_session" sat before the account-status gate, which would have onboarded a suspended/deleted orphan before denying it a session, fixed by moving heal post-gate with a new regression test). Standing lesson extended:** ground the design in the real code not just for which functions exist (Phase 3) but for what a signature is and where a placement sits — a signature is derived from the real body it relocates; a placement is checked against the real code at the placement site. Proven end-to-end in the real database, both halves (a forced onboard failure leaves a clean orphan; signing that same kept orphan back in heals it). Two logged limitations on the failed-signup-with-claim path (failed-signup UX gap; orphaned claim — both rooted in the pending record being discarded at mint-commit). Completion record: loomworks-stele-phase-4-completion-record-v0_1 (loomworks-record ae3775f); session handoff: loomworks-stele-phase-4-to-5-handoff-v0_1. Phase 5 is complete and merged (see below). A correction to the repo working-model recorded at Phase 4 close: engine origin/main sat at d3acd84 through all of Phase 4 — the bcb59f5 v0.2-archive commit lived only on local main and the branch until the Phase 4 merge fast-forwarded origin to 9be25fd; do not assume local main == origin/main between phases.

Phase 5 (credential lifecycle) is complete and merged (engine origin/main 8f2665a; branch cr-2026-108-stele-extraction-phase-5 held, not yet deleted — branch deletion is the Operator's separate step after the completion record files; fast-forward 9be25fd..8f2665a, 7 files / 918 insertions, no merge commit). No schema change — alembic stays 0084 (Phases 0–3 were schema-neutral; Phase 4 was the one schema change at 0084; Phase 5 adds routes and primitives only, the locked hard-delete decision deliberately avoiding a migration). Phase 5 built the two genuinely-missing credential-lifecycle operations and closed one gap on the already-built enrollment path. Grounding first established what was already there: second-passkey enrollment and recovery-code surfacing were already shipping (the latter via the §10.3 amendment — invalidated_at soft-invalidation, the /me/security/ router), so Phase 5 did not rebuild them; the real work was passkey-revoke, person-scoped TOTP-rotate, and the display_name gap. What shipped: (1) passkey-revokeDELETE /me/security/passkeys/{id} + a new Stele remove_credential primitive (the first delete idiom in stele/, hard-delete, flush-in-primitive/commit-in-route) carrying a last-passkey guard at the primitive/service layer (not the router, per the Phase-4 placement lesson); (2) person-scoped TOTP-rotate — a new Stele twin stele/person_totp.py (begin_totp_rotation returns secret + provisioning URI without writing; confirm_totp_rotation verifies the new secret in the primitive, re-encrypts onto PersonRow.totp_secret; no import of contributors/, so stele/ did not grow a dependency on contributors/ — the twin-over-generalize decision protecting the extraction's layering); (3) the display_name field threaded through the passkey-complete route into the existing add_credential call (substrate already accepted it; the route had omitted it). Cut order 5C → 5A → 5B; five commits (archive → 5C → .wrangler/ gitignore → 5A → 5B); suite green at every commit, final 2933/46/0; alembic 0084. The CR took two versions, one a correction caught at Step 0 grounding: the revoke guard predicate was corrected from the scoping note's "block iff passkey_count == 1 AND totp_secret IS NULL" (which treated TOTP as a fallback "way in") to "block the last passkey unconditionally, regardless of TOTP" — because the real production login is passkey-assertion → partial session → then TOTP/recovery, so TOTP cannot mint a session alone and removing a person's last passkey locks them out even with a TOTP secret (the v0.1 OR-predicate would have allowed exactly that). The other two decisions: hard-delete-over-soft-delete-column (stays at 0084), and person-scoped-twin-over-generalize. Two build deviations CC caught and resolved: (a) the prescribed git add -A swept a Cloudflare credential file (.wrangler/cache/wrangler-account.json) into the 5C commit — amended out before any push (nothing left the machine), .wrangler/ gitignored as its own commit, and explicit-path staging adopted from 5A onward (the class-fix, not just the instance-fix); (b) the hard-delete tripped the non-erasure architectural guard tests/test_no_delete_statements.py (R-A28/R-B21) — resolved the guard's designed way by adding credentials.py to the file-level allowlist with a rationale matching the six existing precedents and the sibling OVA-credentials module's documented discipline (a credential is operational auth, not a MemoryObject / event-log entry* — so the delete is outside the non-erasure invariant's domain, not an exception to it; Operator-reviewed verbatim against the precedents before push). Standing lesson extended again: grounding now covers **the architectural invariants that police the kind of change being made, not just function inventory (Phase 3) and signatures/placements (Phase 4) — the guard collision surfaced at build (5A) because Step 0 read the placement site and call-sites but not the repo-wide guard suite; the lesson was applied immediately in 5B (a read-only guard-suite scan before editing, which came back clean: rotate overwrites a column, no delete). Proven end-to-end in the real database — all six §7 cases on the real HTTP path through real get_db_session, only the WebAuthn crypto verify stubbed: the corrected guard refuses a last-passkey-with-TOTP revoke with a real 409, a two-passkey person revokes one and signs in with the other, a valid rotate makes the old TOTP code fail and the new one pass on a real sign-in, an invalid-code rotate leaves the old secret intact, and no person ends a revoke at zero passkeys. The SSO forward-dependency is recorded in the guard's code comment and the completion record: SSO is not built (a seed commitment ahead of the build, per Phase 14 Decision 7 / Phase 48 deferral); the guard counts passkeys only today, and when org-SSO lands the predicate widens to "last passkey AND no SSO binding." Completion record: loomworks-stele-phase-5-completion-record-v0_1; governing CR: cr-2026-108-stele-extraction-phase-5-v0_2. The next slice is the de-engine-ing toward the standalone repository (Phases 6–7); see the standalone-distribution milestone paragraph below.** Manifest-vs-brief tension to reconcile: this manifest's standalone paragraph (below) records the physical persons → principals + host-account split as "deferred to Phase 6 (D2 = Branch 1)," while brief v0.4's §5 roadmap names Phase 6 as "de-engine completion + packaging" and reserves the table-split decision as Phase 1's call rather than a locked Phase-6 item. The two documents disagree on what Phase 6 contains; this is flagged for Operator reconciliation at the next methodology/brief pass and is not silently resolved here.

Standalone-distribution milestone (named v0.53; framed in brief v0.4). The Operator will take Stele to the Claude Code Miami group for independent testing — which requires Stele as a clone-and-run standalone repo (code + SDK + comprehensive documentation with runnable examples + a reference UI template), with no residual DUNIN7/Loomworks dependency. The persons.id FK on the credential/recovery rows is the gating design question: standalone Stele either owns its own principal table or defines the FK as a host-supplied contract. This is now locked (Phase 1): D1 = own-its-own-table (direction); the physical persons → principals + host-account split is deferred to Phase 6 (D2 = Branch 1). The Stele body-of-work brief v0.4 now works all of this out (loomworks-record main a7ed9e6): it names the standalone repository as Stele's terminal form, frames the FK decision for Phase 1 with both branches and their standalone consequences (recommendation surfaced — own-its-own-table — not pre-decided), folds the standalone deliverables into a re-sequenced phase plan (Phases 6–7: de-engine + packaging, then docs-with-runnable-examples + reference UI template) rather than a parallel track, and names the Phase 0 WebAuthn-ceremony gap as closing at the reference UI (Phase 7). The Miami date is the Operator's to set against real phase progress.

Canonical documents on loomworks-record main (brief v0.4 at a7ed9e6; the others unchanged since 047d90a):

Locked decisions (do not relitigate): (1) contract surface approved, including the white-label hooks tenant_context + locale — Stele holds no brand, outcomes are structured codes hosts translate; (2) sign-up split = approach B (mint-then-onboard with a heal path) — Phase 4, not Phase 0; (3) move, not duplicate — one implementation throughout, safety from small reversible commits, not a parallel fallback. Detail lives in the three documents above; the manifest does not duplicate it.

Loomworks engagement seed

Corrected at v0.52. Canonical seed is v0.12 (2026-06-07), not v0.9. The v0.42 deferral framing below is now stale: the seed bumps it named as candidate work have landed — v0.10 (Memory widened to N-scope), v0.11 (the Memory contribution/write-access axis), v0.12 (the two-tier sign-up posture: open signup with automatic commons membership, un-invited path volume-limited, authorized lift raises the ceiling, lift mechanism deferred to spec). The next seed bump, if warranted, is the one that absorbs the Stele/fourth-product framing — named as candidate work, not produced here.

Stale framing preserved per corrections-not-smoothed discipline: v0.41 said "defer the seed bump and revisit at manifest consolidation pace." v0.42 reassessed and named a v0.10 bump as warranted to capture the cleanup-arc framing shifts. That bump and two further bumps have since landed (see correction above).

Loomworks engagement state

Updated for v0.42. Engagement assertions accumulated through Phase 56 (E0001's Memory holds the build-up through "voice work discipline"); the cleanup arc's three CRs added implicit Memory state through the architecture spec v0.4 and methodology canon landings, but no engagement-level assertions for the cleanup arc itself were contributed. v0.42 notes this as a candidate Operator action — contribute assertions to E0001 capturing the cleanup arc's framing shifts.

Substrate state

Updated for v0.50 (engine + Operator Layer substrate-state refresh).

Engine: 2,930 tests collected / 2,884 passed at HEAD 56f2b6b (after CR-2026-099 orientation, CR-2026-100 personal recall, and the orient current-values + Path-A formatting enhancement all landed and tagged, 2026-06-10/11). Up from 2,829 at v0.49's 5472335. 46 skipped (calibration-gated and conditional tests, plus the new gated live-classifier tests for orient + personal recall). 0 failing on the 2026-06-11 full-suite run — the full suite is green; the four failures the v0.49 (2026-06-07) run recorded did not reproduce on this date (the two test_phase_44_evaluator dedup tests are the date-sensitive evaluator-dedup family — see below; test_api_assertion_retract and test_dismissal_patterns_cadence did not fail on current main at this run date).

Phase-44 flake characterization (carried from v0.49): the last two are not random flakes (both fail 3/3 deterministically in isolation) and not a fixed pair — they are a date-sensitive Phase-44 evaluator-dedup family (the dedup compares fixture timestamps against real now()), so which subset fails varies by run date. v0.42's "2 pre-existing failures" reflected its run date; on 2026-06-07 both dedup tests fail, at baseline and HEAD alike. Treat the pre-existing set as the whole dedup family, not a fixed count.

Alembic head: 0081 (was 0073 at v0.42, 0064 at v0.41). Migrations 0079–0081 — step-up auth (organizations + memberships + per-user presence; engagement always-tap override) — landed on main between v0.42 and now; CR-2026-097 itself added no migration (provenance rides the existing assertion metadata).

Substrate shape after the cleanup arc (replacing the three FORAY-shaped tables v0.41-era substrate carried):

New engine module: src/loomworks/foray/ with three files: __init__.py (re-exports), reserved_emit.py (no-op emitter), anchor_priority.py (19-entry registry). Sixteen reserved-location call sites across the engine: 3 audit + 1 memory + 12 credit. All carry # FORAY_RESERVED_LOCATION: <namespace>.<event_kind> grep markers.

Frontend state — Workshop (loomworks-ui): Unchanged from v0.41. HEAD remains at 7f35825 (2026-05-06, Phase 45 step 14). 282 vitest (29 files); eslint 0 errors / 1 pre-existing warning; tsc/build clean. Workshop is intentionally frozen at the Phase 45 four-room engine-internals shape. This is positioning, not neglect — active product development happens on the Operator Layer. The architecture spec v0.4 §10 makes this explicit; v0.42 inherits the framing.

Frontend state — Operator Layer (loomworks): Updated for v0.50. HEAD 4ffb3ff (2026-06-11, Path-A newline-honoring CSS for the navigation companion reply). Prior 4e43e9f = CR-2026-099 Step 4 (orientation surfaced on the in-engagement + navigation surfaces via SuggestedActions + the recogniser extension). Tag companion-orientation-discovery-v0_1 on OL at 4e43e9f; the Path-A CSS one-liner at 4ffb3ff is untagged. (Supersedes the stale 054b0c2 v0.42 snapshot — Entry 109 had already moved OL to a673524; the §1 block wasn't refreshed in step until now.) Earlier OL state carried forward: upload pathway operator-reachable end-to-end as of 2026-05-27 (OL 2186d13, untagged), engine writes UploadEventReceived events with provenance, assertion-drafting unbuilt (queued-directions v0.21 §15.3); voice modality matured (silence-submit threshold default 2.5s, recognizer E-prefix expansion, voice-provenance input_mode marker, in-engagement voice listening, brass microphone glyph on voice-origin turns).

Marketing repo (loomworks-marketing): Updated for v0.42. HEAD at 0d86610 (2026-05-17, "Fix four-stage phrasing on home — Memory, Manifestation, Shaping, Rendering"). This commit appears to address one of v0.41's three held marketing-site content observations (the room-order rendering issue). Status of the other two observations — "Manifestation paired with 'ships into the world'" and "broader frame-level question about substrate vocabulary outward" — awaits Operator confirmation.

Phase CRs and tags

Updated for v0.42 (substantial). Tag history since v0.41 (chronological):

| Date | Tag | Type | What | |---|---|---|---| | 2026-05-14 | phase-58-upload-pathway | Numbered phase | Upload pathway substrate | | 2026-05-15 | phase-59-upload-pathway-completion | Numbered phase | Upload pathway completion | | 2026-05-18 | voice-listening-v0_1 | Named ship | Voice listening §A + §B (preference store + Companion tune_setting) | | 2026-05-19 | sign-out-v0_1 | Named ship | POST /auth/logout endpoint | | 2026-05-19 | in-engagement-surface-fill-in-v0_1 | Named ship | Conversation-history 404 fix | | 2026-05-19 | engagement-list-scoping-v0_1 | Named ship | GET /engagements scoped to caller's memberships | | 2026-05-19 | composer-placement-and-message-order-v0_1 | Named ship | Composer placement + message_order | | 2026-05-19 | foray-audit-for-settings-v0_1 | Named ship | The audit substrate later renamed by CR-A | | 2026-05-19 | voice-tryprompts-to-tooltip-v0_1 | Named ship | Voice try-prompts → tooltip (bundled commit) | | 2026-05-19 | top-bar-cleanup-v0_1 through _v0_3 | Named ships (×3) | Three tags on same substrate commit | | 2026-05-20 | voice-pill-padding-engagement-navigation-v0_1 | Named ship | Voice pill padding (bundled with voice-provenance) | | 2026-05-20 | voice-provenance-v0_1 | Named ship | input_mode column on conversation_turns | | 2026-05-20 | voice-recognizer-e-prefix-v0_1 | Named ship | Voice recognizer E-prefix expansion | | 2026-05-20 | voice-listening-silence-submit-v0_1 | Named ship | Voice listening silence-submit | | 2026-05-24 | phase-61-audit-cleanup | Numbered phase (CR-A) | Substrate hygiene cleanup arc, first sibling | | 2026-05-24 | phase-62-memory-events-cleanup | Numbered phase (CR-B) | Substrate hygiene cleanup arc, second sibling | | 2026-05-25 | phase-63-credit-substrate-cleanup | Numbered phase (CR-C) | Substrate hygiene cleanup arc, third sibling; closes Phase A | | 2026-06-10 | companion-orientation-discovery-v0_1 | Named ship | Companion orientation & discovery (capability ships) | | 2026-06-10 | companion-orientation-discovery-v0_2 | Named ship | Orientation composition fix (server-compose, fabrication-proof) | | 2026-06-11 | personal-recall-v0_1 | Named ship | First-class cross-engagement personal recall | | 2026-06-11 | companion-orientation-discovery-v0_3 | Named ship | Orientation current-values stated + Path-A list formatting |

(Note: the table has been a v0.42 snapshot since v0.43, with intervening landings recorded via §3 entries instead. These four rows are added for the session's tags; the authoritative landing record is the §3 entries below.)

Phase 57: no engine tag. Identifier was reassigned mid-flight. Local branch phase-57-marketing-engagement-creation exists on engine and Operator Layer but never produced a tag.

Phase 60: no engine tag. Phase 60 is Companion-as-Operator-system-interface, closed mid-May on the Operator Layer at tags phase-60-close-v0_1 (835936b, 2026-05-16) and phase-60-recovery-v0_1 (7868851, 2026-05-16); no engine tag because Phase 60 was Operator-Layer-only. The phase-60-operator-layer-upload-pathway-v1 branch name that v0.42 read as "in flight" was separate, mislabeled work — upload-pathway-v1 — and is now deleted from refs; the actual upload-pathway landing is untagged at OL 2186d13 (2026-05-27). See Entry 101 correction and §15.3 for the remaining engine-side upload work (assertion-drafting from UploadEventReceived).

Investigation documents

Updated for v0.42. New investigations and substrate documents in the record since v0.41:

Phase 58 implementation notes

New for v0.42. Upload pathway substrate. Engine repo 2a6a753. (Not landed as separate implementation notes in the record at this manifest's authoring; consider whether to lift if the Operator wants the trajectory persisted.)

Phase 59 implementation notes

New for v0.42. Upload pathway completion (CR-2026-092 v0.4). Engine side. (Same posture as Phase 58 notes.)

Phase 60 implementation notes

Not in the record at this version. Phase 60 (Companion-as-Operator-system-interface) closed mid-May without producing a record-resident implementation-notes artifact; the tune_setting handler is the first shipped instance per §2.B. Any implementation-notes write-up is identified-but-not-actioned work, alongside the broader numbering-reconciliation pass named in §5. See Entry 101 correction.

Phase 61 implementation notes

New for v0.42. phase-61-implementation-notes-v0_1.{md,html} at substrate/cleanup/. Captures the CR-A close: audit.foray_eventsaudit.events; foundation module src/loomworks/foray/ established with _foray_reserved_emit no-op; 3 reserved-emit call sites; reserved slot 1 of 2 consumed (FK deviation — orphan-row protection cost exceeded benefit given Loomworks' deletion semantics). Validates the per-call-site reserved emit pattern.

Phase 62 implementation notes

New for v0.42. phase-62-implementation-notes-v0_1.{md,html} at substrate/cleanup/. Captures the CR-B close: memory_events Phase 25 wiring cleanup. The attestation column renamed to commit_webauthn_attestation as a true Alembic rename (1 existing non-null row carrying real WebAuthn proof preserved). _ANCHOR_PRIORITY registry relocated to src/loomworks/foray/anchor_priority.py. Both reserved slots consumed (test scope expansion finding + raw-SQL INSERT helper discovery — informs canon Principle 4).

Phase 63 implementation notes

New for v0.42; closes the cleanup arc. phase-63-implementation-notes-v0_1.{md,html} at substrate/cleanup/. Captures the CR-C close: credit.foray_action_flowscredit.flows via in-place RENAME. Trigger continuity verified empirically (synthetic-INSERT test confirmed the trigger fires on the renamed table; the update_balance_on_flow trigger binds to table OID and follows the rename transparently). 12 reserved-emit call sites — validates the per-call-site discipline at scale. 9-value typed event_kind taxonomy added with legacy_unknown fallback.

Methodology canon v0.1 — new in record

New for v0.42. operations/loomworks-methodology-canon-v0_1.{md,html} (commit de23c31). The standing canon of methodology principles earned through execution evidence. Four principles in v0.1 (see §2.A below). Discovery-trajectory discipline applies — v0.2/v0.3 will land alongside v0.1 when consolidation continues.

Architecture specification v0.4 — new in record

New for v0.42. architecture/loomworks-architecture-specification-v0_4.{md,html} (commit 7da12f1). v0.3 preserved untouched at architecture/loomworks-architecture-specification-v0_3.html per discovery-trajectory discipline. v0.4 absorbs four substantive sets of changes since v0.3: FORAY reframing (load-bearing), methodology canon integration, voice modality maturation, Workshop framing made explicit. Authoritative for current architectural framing.

Record-production-discipline note — new in record

New for v0.42. operations/record-production-discipline-v0_1.{md,html} (commit 73e947a, 2026-05-24). Establishes the direct-to-record production discipline: documents with discovery-record value land in the record automatically as part of producing them, not as a separate later step. Path A (Claude.ai → Downloads → Claude Code, for substantive new artifacts) and Path B (in-record editor at record.dunin7.com, for small edits) named. The Downloads-as-staging step retired for record-bound documents.

Session handoff

Updated for v0.42. The closing artifact of the substrate hygiene cleanup arc is the Phase 63 implementation notes at substrate/cleanup/phase-63-implementation-notes-v0_1.{md,html}. No standalone session handoff at v0.42; the cleanup arc's trajectory is preserved across the 14 documents in substrate/cleanup/.


Section 2 — Named principles and patterns

2.A Promotions to methodology canon v0.1

Four principles were lifted to canonical status at the cleanup arc's close (record commit de23c31). v0.42 records the promotions; the canon at operations/loomworks-methodology-canon-v0_1.html carries the authoritative statements, evidence bases, and boundary conditions. Brief summaries:

  1. Per-call-site reserved emit. When a code path is being prepared for future external integration, the reserved-location marker lives at each business-event site, not centralized in helper writers. Evidence: 3 / 1 / 12 sites across CR-A / CR-B / CR-C.
  1. Test-filename-to-current-substrate alignment. When a test's filename framing references a cleaned-up origin, rename to reflect current substrate or delete if functionality is gone. Four-instance evidence including a negative case at CR-C (zero renames needed because filenames were already accurate — validates the principle in its negative form).
  1. Migration strategy: rename when downstream bindings exist; recreate when independent. Choose by what binds, not by default preference. Evidence: CR-A drop-and-recreate (no bindings), CR-B column rename (ORM bindings followed), CR-C table rename (trigger and FK followed via table OID).
  1. Inventory enumeration vs cognitive density. Inventories enumerate references but undercount cognitive density per reference. Design steps should grep for assertion patterns and reader sites directly; per-test-function enumeration is more reliable than per-file enumeration. Evidence: CR-B's slot-1 finding (10 incidental files actually contained 4 directly-testing functions plus raw-SQL helpers), CR-C's per-file density finding (21 + 29 + 17 references in three files).

2.B New in v0.42 — from the cleanup arc

Substrate-friction-discipline-pattern (already named in v0.41 / earlier): the cleanup arc exercised this pattern across three sibling CRs. Reserved slots consumed cleanly within budget. The pattern continues to hold operationally.

Halt-and-surface beats absorb-silently (named; not yet canonized): every CR in the cleanup arc honored the Checkpoint A halt before merge. CR-B's slot 1 surfaced execution-time discoveries (4 additional test functions + raw-SQL INSERT helper); CR-C's slot 1 surfaced 4 more execution-time discoveries (multi-line JSONB predicate, UUID/str type comparison, two missed raw-SQL queries, mangled import). All surfaced cleanly through the halt-and-surface discipline rather than absorbed in CR execution.

Direct-to-record production discipline (now established as standing discipline): see operations/record-production-discipline-v0_1. The Downloads-as-staging step retired for record-bound documents. Documents land in the record automatically as part of producing them.

HTML-companion-as-part-of-producing-the-document discipline: every record document has both .md and .html with Loomworks letterpress styling. Established mid-session (commit 73e947a).

2.C Sharpening of existing principles — from the cleanup arc

Seam-and-stub progression sharpened to "reserved-location pattern." v0.41's framing of OVA integration via seam-and-stub generalized: the cleanup arc applied the same pattern at 16 sites for FORAY integration, with _foray_reserved_emit("<namespace>.<event_kind>", payload) calls at each call site plus # FORAY_RESERVED_LOCATION grep markers. The pattern is now Loomworks-wide; v0.4 of the architecture spec §09 carries the framing.

Discovery-record posture validated at scale. The cleanup arc's complete trajectory — scoping note v0.1 → inventory → scoping note v0.2 → three CR designs → three CR drafts → three implementation notes → methodology canon v0.1 → architecture spec v0.4 — lives in the record as a connected discovery sequence. Anyone reading the section indexes can follow the trajectory end-to-end. This is the strongest validation of the posture to date.

Companion-as-Operator-system-interface principle (post-Phase 60; named). The Companion is the primary surface for all Operator-system interaction including preferences, configuration, and policy — not just conversational work. Phase 60's tune_setting handler is the first instance. Listed in v0.4 architecture spec §12 as operative discipline; v0.42 records it here for absorption.

Guarantee-enforcement generalizes from composition to classification (new v0.50). The established principle — a correctness guarantee whose content is authoritative is enforced in code, not requested in a prompt, because soft guidance loses to a strong model prior under context pressure — now has its second strong instance, on a different surface. CR-2026-099's composition fix established it for replies (the orientation reply is a structural contract over generated registry data, so it is composed server-side, bypassing the responder LLM that otherwise fabricated under domain-context pressure). CR-2026-100's structural orient-guard establishes it for classification (a recall query must never land on the orientation bypass; soft classifier guidance lost to the "what can you ___" capability prior, so the guarantee is enforced by a deterministic post-classifier guard, not by classifier persuasion). The general statement: when correctness is a guarantee and the LLM holds a prior that pulls against it, enforce the guarantee deterministically in code — the prompt is where you state preferences, not where you secure invariants. Two instances across two surfaces (composition, classification); on the three-instance cadence this is a strong candidate for canon promotion at the next consolidation.

2.D Methodology candidates awaiting framing (v0.21 consolidation candidates)

Carried forward from v0.41 (still pending v0.21 consolidation pass):

New for v0.42 (cleanup-arc candidates that didn't reach canon threshold):

Structural shift in v0.42: The v0.21 path is no longer the only lift surface. Principles that earn three-instance evidence in a single arc may land in the methodology canon directly (consolidation-after-arc cadence). The relationship between the v0.21 path and the canon is an open question (see §1 above). Candidates listed here may, by the time of v0.21 consolidation, have been canonized via a different path.


Section 3 — Entries

Numbered phase entries follow the v0.41 convention: Provenance / Content / build summary / methodology contributions / trajectory / build-quantitative summary.

Earlier entries (Entry 1 through Entry 98 / Phase 56) carry forward by reference from v0.41 and prior manifests. v0.42 adds Entries 99 through 104.

Entry 99 — Phase 58: Upload pathway substrate (new v0.42)

Provenance. Tagged phase-58-upload-pathway on engine 2026-05-14. Substrate-only.

Content. Upload pathway substrate established. Foundational work for the in-engagement upload surface.

Trajectory worth recording. Phase 58 shipped before Phase 57 (Phase 57 was a reassigned identifier; see Entry 99-A note). Upload pathway became the natural next surface after the engagement-creation arc closed at Phase 56.

Build-quantitative summary. Substrate-only at Phase 58 close. Operator Layer surface-reachability landed separately, untagged, at OL 2186d13 (2026-05-27, /chat?project=<id> restoration); the in-engagement-composer upload-port (item 3, Shape 2) is identified-but-not-done. Phase identifier for the OL upload-pathway work is unreconciled (§5); this is not Phase 60's work (see Entry 101 correction).

Entry 99-A — note on Phase 57 reassignment

v0.41 anticipated Phase 57 as "Phase 32 marketing engagement" (strongest candidate), with alternates Option C (Discovery render specialists) and explain-affordance investigation. Reality: Phase 57 identifier was reassigned mid-flight. A phase-57-marketing-engagement-creation branch exists on engine and Operator Layer but never produced a tag. v0.42 records the prediction-vs-reality gap honestly — not because v0.41's selection criteria were wrong, but because the actual selection criteria turned out to be different (see §4 below for completion plan honesty).

Entry 100 — Phase 59: Upload pathway completion (new v0.42)

Provenance. Tagged phase-59-upload-pathway-completion on engine 2026-05-15. CR-2026-092 v0.4.

Content. Upload pathway completion on the engine side. The substrate is operationally complete; the Operator Layer surface-reachability landed separately at OL 2186d13 (2026-05-27, untagged), and is not Phase 60's work — Phase 60 is Companion-as-Operator-system-interface (see Entry 101 correction). The in-engagement-composer upload-port remains identified-but-not-done as item 3 (scoping note at change-requests/loomworks-composer-upload-port-scoping-note-v0_1).

Build-quantitative summary. Engine side complete. OL upload-surface reachability landed separately at 2186d13 (2026-05-27, untagged); the in-engagement-composer upload-port (item 3, Shape 2) remains identified-but-not-done. Phase identifier for the OL upload-pathway work is unreconciled (§5).

Entry 101 — Phase 60: Companion-as-Operator-system-interface (closed mid-May)

Correction note. v0.42 and earlier labeled Entry 101 "Phase 60: Upload pathway v1 (in flight)." That label was wrong. It keyed off the Operator Layer branch name phase-60-operator-layer-upload-pathway-v1, which is now deleted from refs and never produced a tag. Phase 60 in the record's canonical phases/ taxonomy is phase-60-companion-as-operator-system-interface, and this same manifest's §2.B already names Phase 60's first instance as the tune_setting handler — a Companion-as-interface deliverable, not upload work. The label is corrected here; the prior position is preserved in this note per corrections-preserved discipline.

Provenance. Operator Layer tags phase-60-close-v0_1 (835936b, 2026-05-16) and phase-60-recovery-v0_1 (7868851, 2026-05-16). No engine tag.

Content. Phase 60 is the Companion-as-Operator-system-interface work: the Companion as the primary surface for Operator-system interaction (preferences, configuration, policy), not only conversational work. The tune_setting handler is the first shipped instance. Closed mid-May.

The upload-pathway work that wore the Phase 60 branch name — landing identifier unresolved. Separate from Phase 60. The upload pathway is operator-reachable end-to-end as of 2026-05-27, restored at Operator Layer commit 2186d13 (the /chat?project=<id> route restoration), which is untagged. The engine writes UploadEventReceived Memory events with full provenance (verified 2026-05-28). The remaining engine-side gap — drafting held Assertions from those events — is tracked as queued-directions v0.21 §15.3. Which phase identifier this OL work belongs under is unreconciled; see Section 5.

Entry 105 — 2026-05-28 cleanup-and-scoping arc (new v0.43)

Content. A four-item session (plus one promoted item). Items closed: configuration-drift remediation (engine b793aef, 427c446.env.example reference checked in, RP-origin test decoupled) and the test-override audit (engine d5d57ee — two missed upload-test fixtures brought to the production session envelope; eight upload-test fixtures now uniform; conftest divergence recorded as load-bearing-by-design). Filed: queued-directions v0.21 §15.3 (upload content does not reach assertion grain; plus two independently-timed documentation corrections). In progress: item 3, file upload through the in-engagement composer — Shape 2 (shared upload hook) chosen; scoping note at change-requests/loomworks-composer-upload-port-scoping-note-v0_1 (.md/.html). Deferred: §13.3 Operator real-passkey registration (unsequenced).

Active work resumes at. Item 3's Change Request — the next artifact — beginning with the cross-layer-seam decision (composer upload direct-to-engine via existing postUpload, vs. an Operator Layer gateway route). See the scoping note's open question 1.

Detail lives in. Queued-directions v0.21 §15.3; the composer-upload-port scoping note v0.1; session handoff 2026-05-28 evening v0.1. This entry is a pointer, not a restatement.

Entry 106 — Source identification shipped and merged (2026-05-29)

What landed. Source identification — the first build on the Memory-completion path — shipped and merged to main on both code repositories. The work unifies conversation-turn provenance onto the existing ActorRef model, so conversation turns now record source the same honest, provenance-grounded way assertions always have, and the Operator Layer surface labels turns by their true source.

Governing document. Change Request CR-2026-094, document version 0.2, filed at change-requests/loomworks-source-identification-cr-v0_2.md (version 0.1 preserved alongside per the corrections-preserved discipline). Executes source-identification scoping note version 0.2 (decisions D1 through D5).

The capability, in plain terms.

Merged state (current baseline).

Baseline reconciliation (note, not a correction to earlier entries). Version 0.43 recorded the engine baseline as 573abe1. That figure is truthful-but-behind: 573abe1 (the Phase 63 credit-substrate-cleanup merge) is a clean ancestor of d5d57ee (the pre-source-identification main, three commits ahead — the 2026-05-28 cleanup arc Entry 105 records), which is in turn the parent line of the merged daee809. So the lineage is 573abe1d5d57eedaee809. The current engine main baseline is daee809 (alembic 0074). Earlier entries' 573abe1 lines are left as written; this entry states the current figure.

Acceptance. Engine suite 2687 passed / 2 pre-existing failures (unchanged by identity) / 0 errors; the migration applies and reverses cleanly. Operator Layer suite 412 passed; typecheck and lint at baseline. Live authenticated check against the running stack confirmed each source-kind renders its honest label end to end, including the additive Domain Expert marker and the Contributor-not-Operator fix. The conversation-turn path was treated as a Memory write path throughout — tested against production-session behaviour, not a green suite alone (the lesson from the upload-pathway arc, where a green suite masked a broken production path).

Tracked follow-ups (recorded, not blocking).

Position on the path. Source identification was step one of the Memory-completion path. The named next step is the four-room credit spend-gate (the major build that meters and gates the Memory → Manifestation → Shaping → Rendering pipeline before it is surfaced) — a horizon, not started. The branch merges close the development-database-ahead-of-main gap: engine main now carries migration 0074, so the next step can start from main with schema and code in agreement.

Entry 107 — Phase 64: Pipeline-Spend Credit Gate (new v0.45)

What landed. The prepaid hard-gated solvency control over the three model-rooms (Manifestation, Shaping, Rendering) — step two of the Memory-completion path, the "four-room credit spend-gate" Entry 106 named as the next horizon (and corrected in scope to three model-calling rooms; Memory writes no model). It is a solvency control, not a metering feature: the gate is primary and pre-spend, the database floor is its backstop, and reconciliation is corrective only.

Governing document. Change Request CR-2026-095 v0.1, archived in the engine repo at docs/phase-crs/phase-64-cr-pipeline-spend-credit-gate-v0_1.md; drawn from the pre-scoping document set in the record's scoping-notes/ (constraints note v0.1/v0.2, scoping note v0.2/v0.3, session handoff v0.1). Implementation notes at docs/phase-impl-notes/phase-64-implementation-notes-v0_1.md (engine repo).

Merged state (current baseline). Engine main at 95e072d, alembic head 0076 (migration 0075 adds credit.reservoir/lot/draw_down/engagement_spend_authorization + the BEFORE INSERT person-side floor trigger; 0076 adds the Operator-set refill_amount). Tag phase-64-pipeline-spend-credit-gate (annotated) at 95e072d. Fast-forward merge to main, working branch deleted (tag/branch name-collision resolved). Substrate-only — Operator Layer (1ce2542) and Workshop unchanged.

The capability, in plain terms.

Operator decisions settled during the build. Reservoir default lenient-until-provisioned; refill amount Operator-set (migration 0076, correcting an initial threshold-derived cut); gated-model = re-resolve the system key for the gated tier (the model called matches the credit debited; no stored plaintext key). Plus two execution-surfaced refinements worth carrying as methodology: the floor scoped to live spend (a naïve party-only floor would have blocked production reconciliation — surfaced because the floor's introduction broke 8 reconciliation tests), and a FIFO determinism fix (solvency FIFO must order on something monotonic; lots created in one transaction tie-broke on random UUID — grants arrive one-per-transaction).

Acceptance. Full suite 2,725 passed / 2 pre-existing pinned failures (unchanged) / 0 non-pinned; migrations 0075/0076 round-trip; floor / reservoir-refusal / authorization / FIFO invariants verified by live SQL beyond the suite. Steps 0–8 each full-suite-green at commit; +~3,550 lines / 39 files.

Tracked follow-up. No HTTP-level per-room metered-spend / 402-exhaustion end-to-end test — the gate/meter/refusal logic is unit-tested and the room wiring regression-covered (66 tests); the route-level e2e drive is the gap. (The two pinned failures and the conftest sequence-reset / TRUNCATE-deadlock infra items carry forward.)

Position on the path. Step two of the Memory-completion path is done. The §0 solvency invariant is true for the rooms (person-side gate + floor) and on the issuing side (funded reservoir). The hard precondition — the pipeline is not opened to other Operators until the prepaid gate is real — is now satisfiable.

Entry 108 — Phase 66: Spend Visibility and the Pause Preference — BUILT and merged (updated v0.47)

What landed. The Operator-facing surface Phase 64 deferred (Phase 64 was substrate-only — a pipeline run spent silently after a one-time up-front authorization). The Operator now sees spend on every metered room and approves async spend until they graduate themselves off. Built across five steps and merged to main on both code repos. (v0.46 recorded this entry as drafted/queued, not yet built; v0.47 flips it to built. The prior framing is preserved in v0.46 per corrections-preserved discipline.)

Governing document. Change Request CR-2026-096 v0.1, with scoping note v0.2 + CR-drafting handoff v0.2, all under phases/phase-66-spend-visibility-and-pause/ (record commits 9ad7bf8, f54ef55); each paired .md/.html.

Merged state (current baseline).

The capability, in plain terms (the five build steps).

  1. Spend visibility — every metered room. A new thin GET /me/spend read endpoint surfaces each recent run's actual per-run cost (the consumption_credit flow Phase 64 wrote but exposed nowhere); the Operator Layer Spend surface (/spend) shows actual cost + current balance. The scope adjustment found at drafting held — the cost figure was net-new substrate (only aggregate /me/credits existed).
  2. Spend-pause preference — default ON. persons.spend_pause (the teaching stance: a new Operator is taught the cost model by approving spend); PATCH /me/settings/spend-pause + the /me payload.
  3. Async park / resume — the load-bearing checkpoint. System-key async Shaping/Rendering spend now parks before debit (pending_approval) when pause is on, raising RoomSpendPauseRequired between the gate check and the model call; resume re-dispatches the job with re-cost (re-runs gate+model; actual debit ≤ the displayed cap, never the parked figure). Decline ends the run in declined with no debit.
  4. Approval card. action_type='spend_pause_approval' (Operator-direct), showing the cost cap ("up to N credits") with three actions — approve (resume) / decline / stop-pausing (flip the preference off and approve this run, the in-card graduation).
  5. Settings toggle + re-enable affordance. An on/off toggle mirroring ExhaustionPreferenceSection, plus a re-enable control on the visibility surface so an Operator who turned pause off from a card can turn it back on without hunting in settings.

Amendment during the build — distinct declined job state. The first cut reused the failed terminal (with a marker string) for Operator-declined spend; the Operator directed a distinct declined state so decline is not conflated with operational errors/refusals. Migration 0078 was amended in place (not released downstream), round-trip re-verified, and the full suite re-confirmed green before continuing.

Drafter decisions that held. Resume strategy = re-cost (re-dispatch on approval; the cap is a ceiling, not a commitment). Off-switch reach = all rooms, one preference. Phase 65 reserved for credit purchase; this work took 66.

Phase B — Manifestation pause — DEFERRED (unchanged). Pausing synchronous Manifestation spend stays out of scope: it runs inline in an HTTP request and cannot await an out-of-band Operator decision without a synchronous-request→job re-architecture. Phase A pauses only async Shaping/Rendering; the park branch is structurally gated to {shaping, rendering} and the settings help-text states the gap plainly ("the first drafting step always shows its spend and proceeds — it can't be paused yet"). Honest to "only show what is available": no Manifestation pause control is shown anywhere.

Acceptance. All 11 §21 acceptance criteria met (final-checkpoint walkthrough, every criterion mapped to a named test or surface). Suite state: engine 2,754 passed / 2 pinned pre-existing failures (unchanged) / 33 skipped; Operator Layer 430 passed, tsc 0 new errors (3 pre-existing in a tags test), vocabulary wall green. Migrations 0077/0078 round-trip. Per-step full-suite-green; five engine commits (Steps 1–4 + the declined amendment) + four OL commits (Steps 1, 2, 4, 5).

Known, decided behaviors (recorded, not gaps). (1) "Stop-pausing" is two sequential, non-transactional calls — PATCH spend_pause→off then approve; PATCH-first is the safe ordering (a failed approve leaves the run parked and re-approvable, never silently spent). (2) §21.1 "balance movement" is surfaced as current balance + per-run cost, not a per-run before→after delta (consistent with the CR's framing that balance is frontend-derivable and the cost figure is the net-new piece). (3) The cap's input estimate is chars/4 (no pre-call tokenizer on the hot path); it's a credible ceiling paired with max_tokens, with the actual figure shown post-run.

Position on the path. Phase 64 made spend real (substrate: gate, metering, FIFO draw-down); Phase 66 makes it visible and approvable (the Operator-facing surface). The spend loop is now closed for async rooms; Manifestation pause (Phase B) is the remaining completeness item.

Entry 109 — Axis 11: CenterPane conversation pagination — BUILT and merged (new v0.48)

What landed. The Operator can now load conversation turns older than the most recent fifty on the primary in-engagement surface (CenterPane), which was previously impossible — the surface fetched limit=50 once on mount and offered no way back. A "load earlier conversation" control, gated on the engine's existing has_more, pages back through history. Frontend only — no engine change, no Memory contact (pagination is a pure read of conversation history that already exists; it writes nothing, derives nothing, touches no provenance). This is a consumer/reader-surface capability at the Memory read boundary, not a four-room production change.

Governing document. Change Request phase-axis-11 change-request v0.2 (phases/phase-axis-11-conversation-pagination/loomworks-phase-axis-11-conversation-pagination-change-request-v0_2.{md,html}, record commit f5be7fd). Preceded by the scoping note v0.2 (record 9429b2a) and the CR-drafting handoff v0.1 (record 20bfdc1); the handoff's three-part Step 0 (0a fetch-code read, 0b live-browser scroll-model observation, 0c CenterPane-only target) was executed and Operator-accepted before the build, and the five-shape pre-flight (R1+R2) was folded into v0.2 before approval.

Merged state (current baseline).

The capability, in plain terms.

Known limitation (R2) — accepted, follow-on noted. The created_at-only, strict-< cursor can skip a turn that shares the exact boundary created_at and sorts later by id (engine ordering tiebreaks on id DESC). The dedup guard prevents duplicates but not this skip. The complete fix is an engine-side composite (created_at, id) cursor, out of this frontend-only phase's scope and recorded as a follow-on. Accepted because turns are written with distinct sub-second timestamps in practice (verified on live data: E0005's 96 turns paged as 50 + 46 with zero overlap and none lost).

Tests + acceptance. Operator Layer 438 frontend tests pass (8 new — the first CenterPane test file: has_more gating, before-cursor prepend, end-of-history, dedup, raw-oldest cursor, window-scroll mechanism, inert-effect gate, R1 staleness; jsdom has no layout engine, so the scroll test asserts the mechanism, not pixels). tsc clean (modulo the 3 pre-existing tags-test errors, unchanged); production build succeeds. Smoke test confirmed on live E0005 (Operator, 2026-05-31): loading earlier is stable (no jump), control placement reads correctly, no duplicate turns.

Position on the path. Closes the Axis 11 long-conversation-surface item the Phase-60 post-close diagnostic deferred (queued-directions §16.3, fix-shape (b) "client pagination via the existing before-cursor / has_more"). The remaining §16.3 long-conversation candidates — older-turn summarization, time-windowing, within-engagement room-segmentation — stay deferred (Memory-adjacent; out of this pure-read phase). The R2 composite-cursor follow-on is the one engine-side tail.

Entry 102 — Phase 61 (CR-A): Audit substrate cleanup (new v0.42; first sibling of the cleanup arc)

Provenance. Tagged phase-61-audit-cleanup on engine 2026-05-24. Merge commit 616bab9. First of three sibling CRs from substrate hygiene scoping note v0.2.

Content. audit.foray_eventsaudit.events. Established the src/loomworks/foray/ module foundation with the _foray_reserved_emit no-op emitter. Validated the per-call-site reserved emit pattern at 3 sites in the audit substrate.

Five methodology contributions for absorption:

  1. Per-call-site reserved emit validated (3 sites). Three near-identical 4-line emit blocks at three call sites were not awkward; preserved the business-event-vs-persistence distinction visibly. (Lifted to canon Principle 1 at the arc's close.)
  2. Test-filename-to-current-substrate alignment first application. Renamed test_voice_tune_setting_foray_audit.pytest_voice_tune_setting_audit.py. (Lifted to canon Principle 2.)
  3. Migration strategy: drop-and-recreate when no downstream bindings. audit.foray_events had no triggers, no FKs from other tables, no downstream readers. Drop-and-recreate worked cleanly. (Lifted to canon Principle 3.)
  4. Reserved-slot consumption: one slot for FK deviation (Decision 5 in the design). ORM-level FK declarations entangled the audit DeclarativeBase with persons metadata; dropping FKs from both ORM and DB was the right call given Loomworks' invariant that persons and engagements are never deleted.
  5. Halt-and-surface discipline at Checkpoint A worked cleanly; no merge without explicit Operator approval.

Trajectory worth recording. CR-A validated the reserved-location pattern at the smallest scope. The pattern then scaled cleanly through CR-B (1 site) and CR-C (12 sites).

Build-quantitative summary. ~2 hours CC execution time (under 4.5-6h estimate). Test count 2708 baseline → 2674 passed / 33 skipped / 2 pre-existing failures.

Entry 103 — Phase 62 (CR-B): memory_events Phase 25 wiring cleanup (new v0.42; second sibling of the cleanup arc)

Provenance. Tagged phase-62-memory-events-cleanup on engine 2026-05-24. Merge commit ead29a8. Second of three sibling CRs.

Content. Phase 25 readiness wiring on memory_events cleaned. The attestation column renamed to commit_webauthn_attestation as a true Alembic rename (preserving 1 existing non-null row carrying real WebAuthn proof). _ANCHOR_PRIORITY registry (19 entries) relocated from src/loomworks/memory/events.py to src/loomworks/foray/anchor_priority.py. The _foray namespace injection logic at events.py:209-220 removed. compute_content_hash function removed entirely (zero callers after column drop). content_hash and foray_tx_ref columns dropped.

Five methodology contributions for absorption:

  1. Per-call-site reserved emit scales both directions (1 site for CR-B vs 3 for CR-A). The pattern holds at fewer sites; the principle is "one emit per business event" not "centralize at the helper writer."
  2. Migration strategy: column rename when ORM bindings exist. True rename via op.alter_column(... new_column_name=...) preserved the WebAuthn row through the migration; round-trip verified.
  3. Reserved slot 1 consumed by test scope expansion finding — inventory said "10 incidental references"; execution found 4 additional phase-specific tests with test_foray_namespace_injected-style functions, 4 _ANCHOR_PRIORITY import sites, and 3 compute_content_hash import removals. (Lifted to canon Principle 4.)
  4. Reserved slot 2 consumed by raw-SQL INSERT helper findingtest_phase_48_reconciliation_evaluator.py:128 had a raw-SQL INSERT helper writing content_hash. Production paths were clean; test helpers bypass the ORM "single code path" claim from docstrings. (Reinforces canon Principle 4.)
  5. Test-filename-to-current-substrate alignment validated at second instance. Deleted test_phase_25_content_hash_and_foray.py entirely; renamed test_phase_25_commit_attestation.pytest_commit_webauthn_attestation.py. Three test functions deleted across three other phase test files. Validates the rename-or-delete distinction.

Trajectory worth recording. CR-B was the load-bearing safety operation of the arc — the 1 non-null attestation row had to survive the rename. Empirical verification: pre-migration query showed event_id 0673cfd7-354b-4e2a-8a33-9d7355ebf180's data; post-migration query under the new column name showed the same data, byte-for-byte. Round-trip preserved.

Build-quantitative summary. ~2.5 hours CC execution time (toward lower end of 3-5h estimate). Test count 2708 baseline → 2670 passed / 33 skipped / 2 pre-existing failures.

Entry 104 — Phase 63 (CR-C): Credit substrate cleanup (new v0.42; third sibling of the cleanup arc; closes Phase A)

Provenance. Tagged phase-63-credit-substrate-cleanup on engine 2026-05-25. Merge commit 573abe1. Third of three sibling CRs. Closes the substrate hygiene cleanup arc and Phase A of the development assessment.

Content. credit.foray_action_flowscredit.flows via in-place RENAME (preserving trigger + FK + indexes transparently). 9-value typed event_kind taxonomy added with legacy_unknown fallback for historical rows that don't fit the 9 patterns. Two new typed columns (turn_event_id, converted_person_id) replace JSONB-extract reader queries. Three downstream readers refactored to typed-column predicates (conversion observer, reconciliation evaluator, inline idempotency check inside write_referral_credit_flow). 12 reserved-emit call sites added across flows.py (11) and proposal_applier.py (1). metadataextra_metadata rename retires SQLAlchemy reserved-name workaround.

Five methodology contributions for absorption:

  1. Per-call-site reserved emit at scale (12 sites). The pattern is now validated across the full range Loomworks encounters: 1 → 3 → 12 sites. (Strengthens canon Principle 1.)
  2. Migration strategy: in-place RENAME when triggers and FKs bind. The credit.update_balance_on_flow trigger binds to table OID and follows ALTER TABLE ... RENAME transparently. Empirically verified — synthetic INSERT on the renamed table fires the trigger and produces the expected double-entry balance updates. (Strengthens canon Principle 3.)
  3. Inventory cognitive density per file (21 + 29 + 17 references in three test files). The 8-file inventory count was right; the per-file density was the finding. (Reinforces canon Principle 4 in a new direction — file-count accurate, cognitive density underestimated.)
  4. Test-filename-to-current-substrate alignment at fourth instance — negative case. Zero renames in CR-C because the credit test files (test_phase_47_credit_substrate.py, etc.) were named after their phase-origin rather than after the FORAY framing. The principle correctly predicted "no renames needed." (Validates canon Principle 2 in its negative form.)
  5. Three readers, not two. Inventory said 2 downstream readers; CC's design step found 3 (the inline idempotency check inside write_referral_credit_flow was the third). The design-time grep caught what the inventory missed — the principle works.

Trajectory worth recording. The PostgreSQL trigger was framed as "the main unknown going in" in the kickoff. In execution, the trigger turned out to be the smoothest piece — it binds to table OID, follows the rename, requires no DDL change. CR-C's load-bearing risk surface was the test-density work, not the trigger. The cleanup arc's overall finding: the highest-cost work was substantively cheaper than anticipated; the lowest-cost work (test sweep) absorbed the reserved-slot budget.

Build-quantitative summary. ~5 hours CC execution time (middle of 4-7h estimate). Test count 2708 collected → 2673 passed / 33 skipped / 2 pre-existing failures. Five commits on phase-63-credit-substrate-cleanup branch. Phase A complete.


Entry 110 — Companion orientation & discovery (new v0_50)

What landed. The Companion can now tell the Operator what they can do and what they can change, scoped to where they are, with current setting values, rendered as a scannable list. Asked "what can I do here?" / "what can I change?" / "I'm lost", it answers from the system's own registries (never hand-written), located lightly ("here" / "in voice listening"), with drive-it example chips. Engine + Operator Layer.

Governing document. CR-2026-099 v0.1 (capability) + v0.2 (composition fix), docs/phase-crs/phase-cr-companion-orientation-discovery-v0_{1,2}.md. Scoping note v0.1/v0.2 (scoping-notes/). Implementation notes v1.0 (phases/companion-orientation-discovery/). Current-values + Path-A formatting enhancement folded in (tag v0_3).

Merged state (current baseline). Engine: main 56f2b6b, tags companion-orientation-discovery-v0_1 (8aea79c, ship) / v0_2 (a41ebf5, composition fix) / v0_3 (56f2b6b, values + formatting). Operator Layer: main 4ffb3ff, tag companion-orientation-discovery-v0_1 (4e43e9f). Workshop: frozen, unchanged.

The capability, in plain terms.

Known limitation / follow-on. The list uses /newline, not true Markdown (Companion-turn Markdown is unbuilt — spec §10.2; see queued-directions §18.4). When Markdown rendering lands, the orient list can become true Markdown.

Tests + acceptance. Engine suite green; the orient reply is server-composed (fabrication structurally impossible — proven by a zero-character domain-injection test); live-classifier confirmed (orient classifies, no action-utterance theft); Operator browser review passed.

Position on the path. Closes the discoverability hole the Companion-as-interface standing note left open (a conversation shows nothing until asked). The composition fix (v0.2) established a methodology instance (§2.C). Deferred: the §6.4 Explain affordance (voice-calibration-gated); Markdown rendering.


Entry 111 — First-class personal recall (new v0_50)

What landed. The Companion now reliably recalls the Operator's personal memories — birthdays, preferences, who's who — from any engagement, returning the same answer wherever asked. Engine only.

Governing document. CR-2026-100, docs/phase-crs/phase-cr-personal-recall-v0_1.md. Scoping note v0.1 (scoping-notes/, edfb74a). Implementation notes v1.0 (phases/personal-recall/). Functional spec → v0.2 (§8.1, personal recall read side). Queued-directions → v0.26 (§18, follow-ons).

Merged state (current baseline). Engine: main 56f2b6b, tag personal-recall-v0_1 (ec0b383). Operator Layer: unchanged (engine-only fix). Workshop: frozen.

The capability, in plain terms.

Known limitation / follow-on. Wholesale, not topic-filtered (subset optimization deferred — §18.2). The "ask-first on genuinely ambiguous recall" clarification is deferred (§18.1); the safe-default-away-from-orient rule + structural guard handle ambiguity now.

Tests + acceptance. Engine suite green; gated live-classifier 13/13 (the bug case "birthdays" → recall_personal; the ambiguous "what can you remember for me" structurally redirected off the bypass; engagement recall and writes unaffected); Operator browser review passed in the previously-broken Fenwick engagement (E0060) — birthdays recalls identically to E0005.

Position on the path. Fixes the cross-engagement personal-recall reliability bug at the root (recall was emergent, not first-class). Advances the memory=recall reframe (§18.5) without performing it (decoupled — engineering consistency fix, not a seed change). Deferred follow-ons: queued-directions §18.1–18.5.


Entry 112 — Stele extraction: the fourth product, the live build front (new v0.52)

The current live build front (see §1 "Current live build front" for the canonical-document pointer and locked decisions). Stele — said "steel" — is the principal/identity layer: the part of Loomworks that establishes who a principal is (human or agent), authenticates by passkey + second factor, manages credentials, and produces the actor reference every recorded action is attributed to. It is the fourth product alongside OVA (authorisation), FORAY (transaction record), and Loomworks itself (governance) — the three of which all assume a principal exists and none of which creates one. Stele is what they were silently relying on, and it is what gives a Companion Agent a first-class identity to act under.

What the work is: mostly extraction, not invention — the identity code exists and works inside the engine; the work is giving it a clean module boundary and a host-agnostic contract, plus closing two real gaps the code scan exposed (passkey-revoke and person-TOTP-rotate, both absent today) and one real refactor (splitting the fused sign-up into Stele-mints-principal → host-onboards). The contract is defined complete (revoke/rotate included even where code lacks them) so the design leads the build.

Phase order (each halt-before-push, auth path tested against the database, not the suite alone): 0 — stand up the module, move the zero-caller pieces (this CR); 1 — identity records + registry; 2 — actor constructors; 3 — point session.resolve under the host's resolve-current-person dependency (the 119 callers don't move); 4 — the mint↔onboarding split (approach B); 5 — recovery-completeness + build the to-build operations; Later — agent identity (token-exchange standards) + the agent actor path.

Phase 0 is complete and pushed (engine origin/main e4656b4, 2026-06-14). Five commits: 60e7cfa (0.1 skeleton), 3d96508/e2ab1c6/3b2c585 (0.2 — move recovery.py/webauthn.py/session.py, repointing 8/20/85 importers as pure renames), e4656b4 (0.4 isolation harness). Suite 2920/46/0; real-database sign-in verified against playground_dev. Completion record: loomworks-stele-phase-0-completion-record-v0_1. Two boundary corrections happened mid-flight, both surfaced by tree-truth verification before any file moved and recorded in the CR amendment notes: (v0.1→v0.2) two of the five listed pieces were not separable files — the credential row models and credentials.py reassigned to Phase 1, the person-TOTP internals to Phases 3/4; (v0.2→v0.3) the three remaining files had ~113 importers including load-bearing modules — resolved by distinguishing forbidden logic edits from in-scope import repoints (a move's mechanical completion). The standing lesson: "zero external callers" means "zero outside the identity set"; "don't touch load-bearing code" means "don't change its behaviour," not "don't repoint its imports."

Named verification gap carried forward: a full cryptographic WebAuthn ceremony against the database was not exercised (needs a real browser/authenticator, infeasible headless). Acceptable for Phase 0 (the verify functions are byte-identical renames; the session path every request runs on got the full real-DB check); carried forward to the Claude Code Miami standalone-UI milestone, where a reference UI drives a real authenticator end to end.

Phase 1 is complete and pushed (engine origin/main f1cf170, 2026-06-14). Four commits: 6d45526 (1.1 — shared Baseloomworks.identity_base), 8f5c005 (1.2 — PersonRow + the two credential row models → stele/models.py, 18/44/0 importers, mixed lines split per-symbol), 83cd9b1 (1.3 — registry → stele/registry.py, 36/86/0), f1cf170 (1.4 — credentials.pystele/credentials.py, 5/8/0). Step 1.5 was verification-only (no commit). Suite 2920/46/0 (identical to post-Phase-0 baseline); real-database sign-in + credential read verified from stele/ against playground_dev. Completion record: loomworks-stele-phase-1-completion-record-v0_1. No schema or data change (Branch 1 invariant, confirmed three ways: empty migration diff, alembic 0083 unchanged on repo and live DB, moved table definitions byte-identical). The Person view moved verbatim — the integration-design §5.2 narrowing (dropping exhaustion_preference/spend_pause) is deferred to Phase 6, not done here.

Phase 1 gating decision — locked and recorded. The persons.id FK / Base decision (brief v0.4 §5B) was split into two and locked before any code moved: D1 = own-its-own-table (direction — standalone Stele ships its own principal table), D2 = Branch 1 (shared-Base code-move now under one MetaData, zero schema change; the physical persons → principals + host-account split deferred to Phase 6 where the standalone packaging is built). The alternative (Branch 2 — Stele-own-Base + physical split now) was set aside as the highest-risk option, correctly homed at Phase 6. The name-collision watch-item resolved clean: loomworks.stele.credentials (moved) is distinct from loomworks.credentials (KEK, untouched), proven by construction.

Two Phase 6 carry-forwards found this phase (deferred by design): (1) the engagements-stub thread — stele.models.PersonRow FKs engagements.id, whose stub stays in persons.models, so stele.models is not importable in true isolation without it; an outward-pointing FK the Phase 6 de-engine step cuts under D1 = own-table. (2) the Person-view narrowing (§5.2), held verbatim this phase, lands at Phase 6 with the physical split.

Phase 2 is complete and pushed (engine origin/main 677c46f, 2026-06-15). The two actor constructors moved out of orchestration/helpers.py into a new dedicated module stele/actor.py: actor_from_person (kind="person") and actor_from_companion (kind="companion", bound to person.id) — the integration design's actor.for_principal / actor.for_companion (the dotted names are contract vocabulary; the underscore names are the code symbols — there is no for_agent constructor, agent actors are 64 inline sites). A split, not a whole-file move: OperatorProjectNotFoundError + verify_project_membership stayed in orchestration/; the ActorRef type was referenced, not moved (owned by memory/base.py). Import partition: ActorRef + Person moved with the constructors, Person stayed on both sides (shared by the verifier), ActorRef audited out of helpers.py. Four commits (306b526 Step-0 archive, af10f6a v0.2 re-archive, 5c06423 collapsed move-and-repoint of all 7 importers, 677c46f comment/docstring sync); Step 2.5 verification-only. Suite 2920/46/0; no schema change (alembic 0083 unchanged on repo + live DB); real-DB person-actor and companion-actor stamps verified from stele/, staying verifier still resolves/raises correctly. Completion record: loomworks-stele-phase-2-completion-record-v0_1. Two findings recorded (corrections-not-smoothed): (1) the CR v0.1→v0.2 amendment — v0.1 split the move from the repoints and predicted a runnable suite minus 6 files; but removing the module-top-imported constructors before repointing the four production routers makes the app un-importable and pytest aborts at collection (33 import-path errors, zero tests run). Caught in execution, halted, amended: Steps 2.1–2.3 collapsed into one move-and-repoint commit, restoring the Phase 1 "bundle each move with its repoints" mechanic so the suite is green at every commit. The lesson: model import topology (module-top imports in collection-critical modules), not just importer count, when drafting per-step suite expectations. (2) the mixed-import-block finding — 4 of the 6 production importers pulled the actor constructor in a block shared with the staying project-membership symbols; handled by per-symbol splits (the Phase 1 mixed-line mechanic). Phase 3 (next) — get_current_person / session-resolution → Stele. Points the auth-path actor resolution in api/deps.py (get_resolved_actor, _resolve_cookie_actor, get_committing_resolved_actor) under Stele; the ~119 session-resolution callers do not move. Do not conflate with the actor constructors (Phase 2, done) or the sign-up split (Phase 4, approach B). Same move-not-duplicate discipline; bundle each move with its repoints; verify against the live tree at the current HEAD and against database truth.

Phase 3 is complete and pushed (engine origin/main d3acd84, 2026-06-15). Session→principal resolution moved into Stele as resolve_session (stele/session.py): resolve_session(token, , secret_key, now, db) -> ResolvedSession | None, where ResolvedSession carries .person + .payload; it catches SessionInvalid internally (returns None), never raises, never applies the totp_verified gate. All five decode-load sites in deps.py now delegate to it (get_current_person, get_current_person_optional, _resolve_optional_person, _resolve_cookie_actor, _resolve_cookie_contributor) — zero inline decode_session remain (the single decode-load chokepoint). Host seam held: the totp_verified/person-exists policy is read off the carried payload host-side; membership, can_commit, contributor-membership, the bearer/agent _ActorRef builds all stay in deps.py; the person _ActorRef routes through stele.actor.actor_from_person. Four step-commits (7d639c2 3.1 add operation, 3a3665c 3.2 thin three person resolvers, 088212b 3.2b contributor seam, d3acd84 3.3 engagement seam + actor route) plus three archive commits; Step 3.4 verification-only. Suite 2920/46/0 green at every commit; no schema change (alembic 0083 repo + live DB); DB-truth green (sign-in, totp-reject, both tolerant resolvers None/Person, engagement-scoped actor from stele.actor, contributor path unchanged). Completion record: loomworks-stele-phase-3-completion-record-v0_1. Trajectory recorded (three amendments before code): (1) v0.1→v0.2 — Step-0 found get_current_person is one of two* resolvers (_optional returns None, can't inherit a raising delegator); fix = return-based operation. (2) v0.2→v0.3 — bare Person | None discards the payload the totp_verified gate needs; fix = ResolvedSession(person, payload), a security-critical correction so the gate can't be silently dropped. (3) v0.3→v0.4 — a grounding read of every decode_session caller found five decode-load sites, not two (the missed _resolve_optional_person and _resolve_cookie_contributor); fix = seam all five, with the over-deferral correction (don't confuse the decode-load step, Phase 3's subject, with actor construction, which stays host-side). The standing lesson: ground the design in a full read of the real code before drafting executable steps — line-coordinate checks confirm what you look at, not what you didn't think to look for. One recorded minor behaviour change: distinct 401 detail strings collapsed to one None-case 401 (status codes preserved, no test asserts the strings). Phase 4 (next) — the sign-up mint↔onboard split (approach B). Stele-mints-principal → host-onboards, with a heal path.

Phase 4 is complete and merged (engine origin/main 9be25fd, 2026-06-15; branch merged fast-forward and deleted local + remote). The fused complete_totp_verify sign-up split into mint_principal (Stele, stele/registry.py — verbatim relocation of the live :255–284: internal TOTP encrypt, mint with onboarding_complete=False/first_login_at=now, add_credential, generate+store recovery, -> tuple[PersonRow, list[str]]; recovery_codes_count exposed as the one intentional knob) and onboard (host, persons/onboard.py — saved-filter seed + commons/E2E/org membership + personal engagement + credit claim + set flag, one atomic transaction). Two-commit route: mint_principal → db.commit() (durable, route-owned, outside the rollback scope) → discard pending → onboard → db.commit() → issue_session; viable via expire_on_commit=False. First schema change of the extraction: migration 0084, onboarding_complete boolean, inverted backfill (41 existing rows → true; new mints default false). Orphan = onboarding_complete=false ∧ personal_engagement_id=NULL; _heal_if_orphaned in both login routes after the account-status gate, before the cookie runs onboard(claim_token=None). create_person kept separate (saved-filter tail stripped → onboard). Commits: 51563ab 4.1 migration, fd8d626 4.2 mint+strip, d2d7994 4.3a onboard, b66e1d0 4.3b two-phase route, d2d54b4 4.3c new-semantics re-points, 258d056 4.4 heal (+ archive commits). Suite green at every commit, final 2921/46/0; alembic 0084 repo + playground_dev + playground_test. **Four-version CR, two corrections caught in build: (v0.3) the mint_principal signature was sketched from the integration design's contract vocabulary (totp_secret_ciphertext, -> PersonRow) and contradicted the real :255–284 body (which encrypts internally, returns recovery plaintext, carries email/mobile/first_login_at) — caught at Step 4.2 before any mint code; (v0.4) the heal placement "before issue_session" sat before the route-level account-status gate, which would onboard a suspended/deleted orphan before denying it a session — caught at Step 4.4, fixed by moving heal post-gate with a regression test (test_suspended_orphan_is_gated_not_healed). Standing lesson extended:** ground the design in the real code for what a signature is and where a placement sits, not just which functions exist — a signature is derived from the real body it relocates; a placement is checked against the real code at the placement site. Proven end-to-end in the real database both halves (forced onboard failure → clean orphan; same kept orphan signed back in → heal completes it, no auto-claim). Two logged limitations (failed-signup-with-claim path, both rooted in the pending record discarded at mint-commit): failed-signup UX gap (no session, no pending record, heal only on sign-in); orphaned claim (heal runs claim_token=None, auto-claim lost, grant survives unclaimed). Repo working-model correction: engine origin/main sat at d3acd84 through all of Phase 4 — bcb59f5 (v0.2 archive) lived only on local main/branch until the merge fast-forwarded origin to 9be25fd; do not assume local main == origin/main between phases. Completion record: loomworks-stele-phase-4-completion-record-v0_1; handoff: loomworks-stele-phase-4-to-5-handoff-v0_1. Phase 5 (next) — credential lifecycle (second-passkey enrollment, passkey-revoke, TOTP-rotate, recovery-code surfacing), scoped against the Companion-spec §10.3 account-recovery amendment already landed (/me/security/, OneTimeSecretsDisplay); first task = establish from real code what /me/security/ already provides vs. what the Phase 5 row still needs.


4.A Carryover from v0.41

Methodology v0.21 consolidation outstanding. Pressure was named in v0.41 as "compounding noticeably." v0.42 absorbs the consolidation-surface shift (canon emerged) but the v0.21 path remains an open arc — the candidates listed in §2.D carry forward.

Phase 45 OVA-spec scope sharpening. Carried from v0.41. OVA remains parked (Kaspa vProgs not ready).

"Skills" terminology three-way distinction — SETTLED 2026-06-11. See standing note loomworks-standing-note-skill-method-vocabulary-v0_6 (supersedes v0_2). Three senses named: skill (bounded engine transform), skill file (Anthropic-platform SKILL.md, kept at arm's length), method (practitioner's encoded way of working). Customization layering settled: personal side is invariant (bound to person UUID, follows across every Companion); method is optional specialization over it; vertical is a method aimed at a domain and sold.

Cross-Operator stewardship of promoted fragments. Carried as open question.

Operator content authoring. Soft deadline before alpha exhaustion. Carried.

Voice tuning iterations ongoing. Updated for v0.42: substantial voice work shipped (14 ships across the absorption interval — silence-submit threshold, recognizer E-prefix expansion, voice provenance, voice-pill padding). The iteration cadence is operationally healthy; the underlying "voice tuning ongoing" framing carries forward as accurate.

Engineering capacity decision trigger. Carried as watch-this.

Engine deployment via M4 tunnel. Phase 52 gate 7 deferred until deployment. Carried.

Marketing-site content observations held — three items. Updated for v0.42. Marketing repo commit 0d86610 (2026-05-17, "Fix four-stage phrasing on home — Memory, Manifestation, Shaping, Rendering") appears to address the room-order rendering observation. Status of the other two — "Manifestation paired with 'ships into the world'" and "broader frame-level question about substrate vocabulary outward" — awaits Operator confirmation. v0.42 records one item likely-resolved and two items unverified.

phase-56-step-0 local branch. Step 0 branch lifecycle decision pending. Carried.

**7 stale origin/phase-* refs on engine origin.** Carried. Increased by 2 local non-main branches on engine (phase-57-marketing-engagement-creation, phase-58-upload-pathway) per CC's grounding observation. Engine's full stale-branch state: 2 local + 7 remote.

4.B Closures from v0.41

Substrate hygiene cleanup arc (Phase A of the development assessment) — closed across Phases 61-63. Three FORAY-shaped substrate surfaces replaced with Loomworks-native equivalents. Reserved-location pattern in place at 16 call sites. src/loomworks/foray/ module foundation established. Phase A is genuinely complete.

The "Phase 57 strongest candidate Phase 32 marketing engagement" prediction. Closed without execution — Phase 57 identifier got reassigned; the marketing engagement work did not become Phase 57; the cleanup arc emerged as a different selection. v0.42 records the prediction-vs-reality gap honestly (see Entry 99-A and §3 below).

The "FORAY substrate operating" framing. Closed by the cleanup arc. FORAY is now correctly framed as an external service Loomworks will call. v0.41's incidental FORAY-substrate mentions are superseded. Architecture spec v0.4 §09 carries the authoritative current framing.

4.C New in v0.42

The methodology canon emerged as a separate consolidation surface. Four principles canonized at operations/loomworks-methodology-canon-v0_1 through a consolidation-after-arc cadence. This is a structural shift from v0.41's anticipation that all methodology consolidation would happen via the v0.21 path. Both surfaces now coexist; relationship to v0.21 is an open question.

Phase numbering became less canonical. Numbered phases continue (58, 59, 61, 62, 63) but the universe of "how work lands" expanded: named ships (14 across 2026-05-18 through 2026-05-20), sibling CRs within an arc (61, 62, 63 as the cleanup arc), in-flight Operator Layer work without engine tags (60). v0.42 names this explicitly as a structural shift.

Direct-to-record production became the standing discipline. The Downloads-as-staging step retired for record-bound documents. Documents land in the record as part of producing them. See operations/record-production-discipline-v0_1.

HTML-companion-as-part-of-producing-the-document became standing. Every record document has both .md and .html with letterpress styling.

Direct-to-record-friction observation. Two grounding documents in this absorption — loomworks-current-state-grounding-v0_1 (for the architecture spec) and loomworks-manifest-absorption-grounding-v0_1 (this manifest) — landed at Downloads as operational scaffolding, not in the record. The discipline correctly distinguishes record-bound documents from operational scaffolding. Worth noting as a discipline working as intended.

Operational hygiene cluster (newly named as a coherent thing in architecture spec v0.4 §13). v0.42 inherits the framing: the cluster includes the stale manifest (now closed by v0.42 itself), the stale queued-directions document (v0.11; still pre-cleanup-arc), the stale branches across three code repos, the two pre-existing test failures, and the unverified marketing-site observations.

CR-2026-100 personal-recall follow-ons (new v0.50). Five adjacent directions deferred from the personal-recall CR, captured in queued-directions §18.1–18.5: ask-first-on-ambiguous-recall clarification affordance (§18.1); topic-filtered / relevance-ranked recall as a subset of the wholesale set (§18.2); the *_about_me write-family name being narrower than its scope (§18.3); the Companion-turn Markdown rendering gap (§18.4 — also tracked at spec §10.2); the memory=recall reframe this CR advances but does not perform (§18.5, seed-level, awaiting Operator commission). Identified and deferred; none blocking.

4.D Completion plan

v0.41's table predicted Phase 57; v0.42's table is honest about the reality that prediction surfaces have become harder. No firm next-phase prediction; multiple candidates.

| Phase / Arc | What | Status | |---|---|---| | Phase 60 (Companion-as-Operator-system-interface) | First shipped instance: tune_setting handler | Closed mid-May (OL tags phase-60-close-v0_1, phase-60-recovery-v0_1) | | Upload pathway assertion-drafting | Engine work — draft held Assertions from UploadEventReceived events | Open (queued-directions v0.21 §15.3) | | Manifest v0.42 absorption | This document | Closing with this version | | Queued directions document absorption | v0.12 absorbing the cleanup-arc + canon + spec-v0.4 + 14 named ships | Identified, not started | | Phase B start | KV unification, identifier scheme normalization, job table base | Identified, not started; Operator's choice when to begin | | Phase C start | Memory stewardship, multi-backing, multi-Operator scenarios | Identified, not started; depends on Phase B sequencing | | Operational hygiene cluster pass | Stale branches, pre-existing test failures, queued directions v0.12, marketing observations status | Identified, not started; small piece compared to Phases B and C | | Loomworks engagement seed v0.10 candidate | Capture cleanup-arc framing shifts in seed vocabulary | Identified candidate; bump deferred to its own commission | | Methodology v0.21 consolidation | Lift accumulated candidates (and possibly cross-reference the canon) | Identified arc; relationship to canon is open question | | Standing-note creation | Standing notes on FORAY-as-external-service, Companion-as-Operator-system-interface, Memory backings | Identified as candidate; not started | | Personal-recall follow-ons | Ask-first clarification, subset recall, *_about_me rename consideration, Companion-Markdown rendering, memory=recall reframe | Identified, deferred — queued-directions §18 |

Cadence note for subsequent manifests. v0.42 absorbed 13 days of state; this is arc-cadence absorption. Per-phase cadence (v0.31-v0.41 style) was a different shape. Recommended posture going forward: per-arc absorption rather than per-phase, given that work increasingly lands as arcs (cleanup arc, voice modality maturation, engagement creation arc) rather than as discrete phases. The Operator may choose otherwise; v0.42 names the recommendation but does not enforce it.


Section 5 — Open questions and known issues

The methodology canon vs what-dunin7-is-building v0.21 relationship. Open question. Possibilities: v0.21 absorbs the canon by reference; v0.21 absorbs only what the canon hasn't taken; the canon eventually replaces the v0.21 consolidation cadence; they coexist permanently on different cadences. Operator decision required when v0.21 is undertaken.

Upload-pathway phase-identifier reconciliation. The upload-pathway-v1 Operator Layer work landed untagged at 2186d13 (2026-05-27) and does not belong to Phase 60 (which is Companion-as-interface). Its correct phase identifier is unreconciled. A numbering-reconciliation pass (also covering the Entry 99-A Phase 57 reassignment) is the place to settle this; not attempted in v0.43.

The marketing-site observations status. Two of three observations are awaiting Operator confirmation (room-order issue likely resolved by 0d86610; the other two unverified).

The completion plan table's predictive value. v0.41's table predicted Phase 57 confidently. v0.42's table presents multiple candidates without firm prediction. Whether the predictive framing returns when work cadence settles, or whether the completion plan permanently shifts toward "multiple candidates" — open question.

The seed bump deferral. Recommended as warranted in v0.42 but not actioned. The Operator's commission to bump candidate seed v0.9 to v0.10 (or further) is identified work.


Changelog

Updates the §1 standalone-distribution-milestone paragraph (brief v0.4 now drafted and governs — names the standalone repository as Stele's terminal form, frames the persons.id FK decision for Phase 1, re-sequences the phase plan into Phases 6–7, names the WebAuthn-ceremony gap closing at the Phase 7 reference UI), the canonical-documents list (brief v0.3 → v0.4, v0.3 preserved beside it; integration-design note that v0.4 pulls the §5.2 table-split forward to Phase 1), and the §3 Entry 112 Phase-1 FK watch-item (points at brief v0.4 §5B). Pointer bump only — no phase, substrate, or other §-state change; v0.53's Phase-0-complete state carried forward. Records the v0.4 structural choice (re-sequence over parallel-track) and the surfaced-not-pre-decided FK recommendation (own-table). Updates §1 live-front and §3 Entry 112 to Phase-0-closed / Phase-1-next; records the five-commit series, the two mid-flight boundary corrections (CR v0.1→v0.2→v0.3), the isolation proof, the real-DB sign-in result, and the named WebAuthn-ceremony gap carried forward. Names the Claude Code Miami standalone-distribution milestone (clone-and-run repo + SDK + docs-with-runnable-examples + UI template) with the persons.id FK as the gating design question, landing in Phase 1. Points to the Phase 0 completion record loomworks-stele-phase-0-completion-record-v0_1. Otherwise carries v0.52 forward.


DUNIN7 — Done In Seven LLC — Miami, Florida Loomworks Current-Status Manifest — v0.59 — 2026-06-15 The manifest is the absorption layer; the foundation document is the consolidation layer.