DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path session-handoffs/cr-2026-209-checkpoint-a-v0_1.md

CR-2026-209 — Checkpoint A — v0.1

Date. 2026-08-13 · CR. change-requests/cr-2026-209-loomworks-title-both-faces-v0_1. State. Built and tested. HALTED before tag and push, per the Checkpoint A instruction. Engine main local commit f011c80 (NOT pushed; no tag). Surface untouched, as the CR anticipated — Step 1 confirmed list rows, chips, and the focus chip all read title and needed no change. Baseline note (Step 0). The CR states baseline cd91176; the tree stood at c04afd9 — exactly one commit ahead (CR-2026-207's engine half, engagement-list projection; no overlap with titling). Built on c04afd9. Tree was clean.

What is built

The backfill boundary — confirmed, with evidence

Per the Operator's Step-1 instruction: the backfill can't reach E0127/E0089, and didn't. Three layers of confirmation:

  1. Structural: the query's state = 'candidate' pin — E0127/E0089/E0104 are active. Additionally E0127/E0089 hold non-NULL titles, failing the second predicate too.
  2. Tested: test_backfill_names_null_titled_candidates_only seeds all three shapes — a NULL-titled candidate (named), a committed NULL-titled row (E0104's shape — stays NULL), a committed truncated-title row (E0127/E0089's shape — byte-identical after).
  3. Observed on live data: before/after query captured in the session. Backfill output named: 2, skipped: 0. After: E0128 = "A one-page closing procedure checklist for a community tool…", E0129 = "A sign-out sheet template for borrowed tools"; E0089 and E0127 byte-identical; E0104 still NULL. The defect stays visible on E0127/E0089 — as ruled, correct: their names are in use.

Tests and gates

New tests/test_cr_2026_209_title_both_faces.py (12 tests): face-2 clause vectors (short/comma/dash/semicolon/no-boundary — E0128's real seed text as the ellipsis case), operator-name-wins, the COALESCE guard, draft-route end-to-end, and the backfill boundary + idempotence. Face-2 failures observed against the old derivation (which shipped "A pocket field guide to urban mushrooms, with seasonal maps and a spore key for…"); face-1/backfill observed failing as missing imports. One legacy expectation updated with a comment (test_engagement_title.py — the 69-char sentence now cuts at the budget; the deliberate behavior change). Full suite 3722 passed / 68 skipped; ruff clean; mypy at the pre-existing 537-error baseline exactly (the CR's own +2 fixed via a SeedLike Protocol; the scoped CI gate will rule at push).

Step 4 eye-test — observed live

Engine restarted on the working tree (LaunchAgent kickstart — the same code that ships after the gate; CR-206/207's pre-handoff precedent). As Marvin-Test2 (minted session): door 2's seed-creation-conversation recorded 11 turns; the converse commit turn (intent_hint=create_engagement_commit) drafted E0130, a fresh conversational candidate carrying the clause label "A laminated one-page allergy reference card for the cafe…" through candidacy — verified in the DB row AND rendered in the home list (screenshot kept: /tmp/cr209-home-list.png). Cleanup per the e2e rule: E0130 discarded (204), all 22 test-persona creation-block turns deleted, leaving no residue. (First attempt used the repro persona, which hit the credit-exhaustion gate — the honest reply worked as designed; switched personas.)

Findings for the gate

  1. Candidate discard 500s on candidates that carry conversation turns — pre-existing, newly observable, TO FILE. discard_candidate_engagement deletes the engagement row without handling conversation_turns rows referencing it (conversation_turns_engagement_id_fkey violation → 500). Conversational creation now attaches turns to the candidate at draft, so every conversationally-created candidate is currently undiscardable through the endpoint — E0128 itself would 500 if discarded today. Out of CR-209's scope (nothing here touched discard or turns); found by the eye-test's cleanup. Suggested as a B-item at the gate.
  2. The conversational eye-test consumed a small amount of Marvin-Test2's trial credit (one brief-path extraction; balance visibly ~199.9k after). Named for the record.
  3. E0130's display number is consumed — discard preserves the sequence's monotonicity (E0060-survives precedent); the next candidate will be E0131. Expected, named so the gap isn't read as loss.

seed-mutability

Kind A as expected, recorded verbatim-heading style: title derivation READS the seed (what_the_work_is, additional_assertions.engagement_name) at draft/extract time and stops at the engagement row — a computed signal that stops at a boundary. If the seed later moves (B-69's standing question), the title does not follow; that was promote-time behavior before, now merely earlier. No new seed write path; the seed is untouched by naming.

What Step 5 awaits

Tag cr-2026-209-title-both-faces; push f011c80; watch the run. (No surface deploy needed. The engine already runs this code locally via the eye-test restart; the push is the record catching up.)


DUNIN7 — Done In Seven LLC — Miami, Florida — CR-2026-209 Checkpoint A — v0.1 — 2026-08-13 Named when nameable; a label, not a description; committed names stay.