Record version. v0.2
Date. 2026-06-24 (v0.1) · amended 2026-06-25 (v0.2)
Change Request. CR-2026-121 — Companion Human Commit Affordance — v0.1 (2026-06-24)
Status. Executed and pushed. Production database migration pending (see "Production migration status" below).
Executing agent. Claude Code on DUNIN7-M4, fresh execution session.
Operator. Marvin Percival.
Grounded by. Step 0 inspection companion-commit-step0-v0_1.md (2026-06-24); seed-check against canonical Loomworks candidate seed v0.12.
> Amendment — v0.2 (2026-06-25). This record carries two corrections; the v0.1 body below is unchanged and preserved in full, with each correction added as a marked note beside the text it corrects. (1) Acceptance item #8 scope — corrected in the new section "Amendment — acceptance item #8 scope correction," after the acceptance gate; the conversational gap it understated was closed by CR-2026-122 (live at 59c8249). (2) Production migration status — corrected in a note appended to the "Production migration status" section: a 2026-06-25 read-only check established there is no production engine or database, so 0094 is not "pending a production deploy" — production deployment is unstarted. Per corrections-preserved discipline, both original claims stay visible alongside their corrections.
The Companion can now commit an Operator's held drafts without the Operator leaving the friendly surface. Before this change, knowledge added through the Companion landed as a held draft awaiting approval, but the only place to give that approval was the Workshop — the harder surface the Companion exists to replace. This change gives the Companion its own commit affordance two ways that share one numbering scheme: on the card surface the Operator can select held items and commit them, or commit all; by voice or text the Operator can say "commit held 3" or "commit all" and the Companion does it after confirming what it is about to commit.
Two correctness properties are built in and proven. Commit is recorded as the human Operator's act, never the Companion's — on both the card path and the voice path. And the Companion's language tells the truth about state: a held draft is "held, awaiting your commit," and only after commit is it "committed to the record."
The work is fully executed, both code repositories are merged to their main branches and pushed, and every test passes. One step remains before the feature is live for real users: the database migration that assigns the held numbers has run on the development and test databases but has not yet run in production. The code is on main; the schema and data change awaits the engine's deploy step.
This is the keystone build of the Companion build order. Until commit worked on the Companion, nothing downstream — deriving a Manifestation, creating a Shape, producing a Render — could be reached or tested on the Companion surface, because each of those operates on committed knowledge. With commit now working on the Companion, the downstream build items become reachable.
The open loop named in the build map — Fenwick E0060's three held drafts with no Companion path to commit them — is closed. Those drafts now carry stable numbers and were committed by both the card and the voice path against the real engagement (then rolled back so the drafts stay held; the proof was non-destructive).
The Change Request was checked against the canonical Loomworks candidate seed v0.12 before execution. No conflict. The build implements seed commitments rather than working against them:
All seven passed. The two gated decisions (V1, V6) were cleared by the Operator before any code was written.
| Verification | Result |
|---|---|
| V1 — commit-order dependency (gates D4) | Pass, no dependency. list_assertions orders by created_at; every display_number site is a display label with a null-guard; no ORDER BY display_number, no "Nth committed", no monotonic-by-commit assumption anywhere. Operator cleared toward lifecycle-stable (D4). |
| V2 — held-number uniqueness scope | Pass. Held and committed numbers draw from the single per-engagement counter (engagements.next_display_number) under the engagement-row lock — no collision. |
| V3 — current held assertions carry no number | Pass, with refinement. Fenwick E0060's three held assertions were display_number = None as predicted. Refinement surfaced: a revised-from-committed assertion is held while carrying its number forward (E0007 #14). The migration backfill therefore targets only state='held' AND display_number IS NULL, never overwriting an already-numbered held revision. This confirmed the lifecycle carry-forward already exists on the revise edge. |
| V4 — feed ordering | Pass. /me/dashboard/needs_you orders by surfaced_at DESC, item_id DESC; the held number travels in the payload as a dedicated field, decoupled from feed order (number stable, order cosmetic). |
| V5 — migration backfill determinism | Pass. Backfill draws from each engagement's counter, ordered by last_updated_at, scoped to the held-and-unnumbered predicate; reproducible and collision-free. |
| V6 — human actor on the converse path (gates D7) | Pass, human actor reachable. The converse route authenticates the human principal; actor_from_person(person) builds the kind="person" actor (the analogue the cookie path uses); the data layer accepts a person actor and rejects only kind="agent". Operator cleared toward both paths — verbal commit ships, no deferral. |
| V7 — card path authority | Pass. The card commit is a direct authenticated POST forwarding the human session, not a converse call; satisfies R-B20 with no special handling. |
Gated decisions as resolved by the Operator:
add_assertion and carried through to committed — one number for the assertion's whole life. The held-only fallback was not needed. Committed numbers may carry gaps (a held number retracted or never committed); nothing depends on contiguity, and a gap is a true fact about the assertion's life, not a defect.Per-step commits, suite green at each step, staged by explicit path.
| Commit | Change |
|---|---|
| 464dc28 | Migration 0094 — held-number backfill (run and reversible; dev and test at head 0094) |
| 9b7c93c | Add-time held-number allocation (lifecycle-stable); commit adopts the existing number |
| 48ef463 + e79dd71 | Feed enrichment (needs_you arm plus operator-dashboard / inbox translators) |
| 40eff76 | commit_assertion converse intent — two-turn confirm-back, human authority, instruction template |
Merged to main 0ae231b via --no-ff (08d0c0c..0ae231b), pushed to DUNIN7/loomworks-engine.
| Commit | Change |
|---|---|
| e53080a | Actionable held card (held number, multi-select, "Commit selected" / "Commit all"), fidelity language, verbal path wired through the existing converse pipeline (no new client endpoint) |
Merged to main bafdb07 via --no-ff (c17539a..bafdb07), pushed to DUNIN7/loomworks.
Untouched, as specified — it served as the port reference only.
display_number is unchanged across the held-to-committed transition; confirmed on Fenwick and in tests.assertion_committed event with the human as committing party (kind=person); the item leaves the held surface.commit_assertion route (resolution, human authority, confirm-back, unknown-number rejection).The acceptance gate above lists item #8 as met, worded:
> Fidelity — held drafts are never described as "saved" or "in the record"; held and committed are named distinctly.
That wording claims a property of the whole Companion. The v0.1 claim stands as a record of what was asserted at the time and is left unchanged above. The correction: what was actually built and tested under CR-2026-121 was narrower than the wording. The fidelity rule (D8) was scoped — per CR-2026-121 §5.2 — to the held card, the confirm-back, and the post-commit response only. Those are the two persona-bypassing surfaces: the server-composed commit replies and the static card copy. Both were brought under the rule and verified.
The Companion's conversational voice — free conversation through the responder LLM path, which loads companion_persona.md — was never under the fidelity rule. At the time this record was filed, that voice described held drafts as "saved" and "in the record," falsifying item #8 as worded. This was discovered on 2026-06-25 by live observation at engagement E0060: the Companion told the Operator a held draft was "saved" while three held assertions sat awaiting commit.
Root cause and fix are recorded in the conversational-fidelity scoping note (loomworks-record c60f565) and closed by CR-2026-122 — Conversational Fidelity, merged and pushed to loomworks-engine main at 59c8249. CR-2026-122's persona state-to-word mapping brings the conversational voice under the same honesty the card and commit surfaces already had, verified by deterministic tests and a live check against the original defect surface.
Net: item #8 held on the surfaces CR-2026-121 built and tested (card, commit replies). It did not hold on the conversational surface, which was outside CR-2026-121's scope and is now closed by CR-2026-122. The original wording overstated the scope; the trajectory — claim, discovery, correction, fix — is preserved here rather than smoothed.
A second conversational voice (the engagement-creation converse, seed_conversation.py / CREATION_CONVERSATION_PROMPT) is outside both CRs and may carry the same gap independently; it is recorded as standing note f9d182b for a possible follow-on.
This is the one step outstanding for the feature to be live for real users.
next_display_number counter. It has run on development (playground_dev) and test (playground_test), both confirmed at head 0094.api.loomworks.dunin7.com engine database). The push moved code only. The engine repository carries a single GitHub workflow (api-docs.yml, an API-docs freshness check) and no deploy or alembic-upgrade workflow, so merging to main does not touch the production database. This is consistent with the established "merge is not deploy" posture.display_number IS NULL predicate — but the feature is not complete in production until then.
The v0.1 section above is preserved as written. Its framing — that 0094 is "pending a production deploy" and "has not run in production" — implies a production engine and database exist and await a migration step. A read-only check on 2026-06-25 established that they do not. api.loomworks.dunin7.com fails the TLS handshake and has no cloudflared ingress entry on DUNIN7-M4 (the tunnel serves only forge/workforce/foraychallenge; the engine runs only as a local dev process on :8000). This was re-verified after unrelated foraychallenge tunnel work, ruling out a transient disruption: the tunnel config is months old and was never restarted, and there was never a loomworks/engine ingress to be "down." Engine production deployment is a deferred, unstarted item — the M4-tunnel step (spine manifest) or the unbuilt fleet (Discovery-stage deployment-strategy doc).
Accurate statement: migration 0094 is live wherever a database exists — development and test. There is no production engine, no production database, and therefore no pending production migration. 0094 will run when production is stood up, as part of standing it up. The v0.1 "pending a production deploy" wording overstated how close production is; the held-commit feature is not "awaiting one migration" in production — production itself does not yet exist. Trajectory preserved: the original framing stays above, the correction sits here.
0ae231b (pushed).bafdb07 (pushed).cr-2026-121-companion-commit-affordance retained in both repositories pending this record; safe to delete once filed.DUNIN7 — Done In Seven LLC — Miami, Florida Completion Record — Companion Human Commit Affordance — v0.2 — 2026-06-24 (amended 2026-06-25) CR-2026-121