# Session handoff — 2026-05-26 (42) Forty-second handover. This session **completed ADR-0035 Phase 4**: it shipped **sub-phase 4i** (the verification sweep — items a–e) on top of 4h, then ran a **whole-Phase-4 `/runda`** (4a–4i seen as an integrated whole). Phase 4 (advanced-mode SQL DDL) is **done**. The `/runda` found the integrated implementation solid; it surfaced three **error-message / capability follow-ups** (all user-decided "track", below) — no correctness or data bugs. > Note: this supersedes handoff-41, which predates 4i and still said "4i > next". 4h + the case-insensitive-table-name fix (handoff-41's content) > are also done and committed. ## §1. State at handoff **Branch:** `main`. **HEAD `22e5bf5`.** **Tests: 1917 passing, 0 failing, 0 skipped, 1 ignored** (the `friendly/mod.rs` ` ```ignore ` doctest). **Clippy:** clean (`cargo clippy --all-targets -- -D warnings`). **Unpushed commits (all of this + the prior session's work; normal):** ``` f7e77a8 feat: ADR-0035 4h — ALTER TABLE … RENAME TO a95c807 fix: resolve table names case-insensitively across all executors ca64434 docs: session handoff 41 … 1afcf4e feat: ADR-0035 4i(d) — merge shared-entry-word completions f852610 feat: ADR-0035 4i(e) — colour DSL vs SQL completions when mixed c2eb8cb fix: ADR-0035 4i(c) — don't pre-flag a self-referencing FK parent 22e5bf5 feat: ADR-0035 4i(a,b) — CREATE TABLE help/usage + describe table constraints; Phase 4 complete ``` Push is the user's step; nothing blocks. ## §2. What shipped (4i + the Phase-4 `/runda`) ADR-0035 **Phase 4 is complete (4a–4i)**. 4i — the verification sweep — landed in four commits (plan `docs/plans/20260526-adr-0035-sql-ddl-4i.md`): - **4i(d)** (`1afcf4e`) — **shared-entry-word completion merge.** At the advanced-mode entry-word boundary, `completion_probe_in_mode` walks every candidate node and unions the viable (`Incomplete`) ones' continuations, so `drop ` offers `table·index·column·relationship· constraint` and `drop rel` → `relationship` (was an empty dead-end). Completion-only; the parse path is untouched; deeper positions keep the committed walk. - **4i(e)** (`f852610`) — **simple-vs-advanced completion colour.** Each continuation is classified `Both`/`Advanced`/`Simple`; **only when the list mixes modes** it is coloured (`mode_advanced`/`mode_simple`; `Both` = token-kind) and block-ordered **Both → Advanced → Simple** (user-chosen). Single-mode lists keep token-kind colours. `Candidate` gained a `mode` field (typing_surface snapshots regenerated, uniform `mode: Both`). - **4i(c)** (`c2eb8cb`) — **self-ref FK pre-submit indicator.** `schema_existence_diagnostics` collects the CREATE TABLE target(s) (`NewName`/`table_name`) into `created_tables` and exempts a `Tables` ref matching one from the unknown-table flag. (Provably scoped: the only two `NewName`/`table_name` grammar nodes are the SQL + simple CREATE-TABLE targets — verified in the `/runda`.) - **4i(a,b)** (`22e5bf5`) — **(b)** `describe` of table-level constraints (`TableDescription` gained `unique_constraints` + `check_constraints`, rendered in a "Table constraints:" section — composite UNIQUE + table CHECK incl. named); **(a)** CREATE TABLE help/usage skeleton refreshed for the DEFAULT/CHECK/REFERENCES/composite-UNIQUE/table-CHECK/FK forms. **Phase 4 docs flipped to complete** (ADR Status + §13 4i + ADR index + `requirements.md` Q1). **Whole-Phase-4 `/runda` (2026-05-26).** Probed the feature combinations no single slice tested, through the full pipeline + a *fresh* rebuild: CREATE with FK + table CHECK + composite UNIQUE → ALTER → RENAME table → fresh rebuild (all three still enforce); ALTER COLUMN TYPE on a column inside a composite UNIQUE *and* a table CHECK (both preserved); case-variant `alter`/`alter column type`/`add constraint` (all work + round-trip). **All round-tripped** — strong evidence the two DDL generators (`do_create_table` / `schema_to_ddl`) stay in sync across the full feature set, metadata stays consistent, and the case-insensitivity fix composes with every DDL path. No correctness/data bug; no ADR divergence; vocab audit holds. ## §3. Tracked follow-ups from the Phase-4 `/runda` (user-decided "track") All three are **error-message / capability** items on a rare **safe** edge (dropping a column covered by a composite UNIQUE is correctly *refused* — no corruption). None is a correctness or data bug. - **F1 — friendly message for dropping a column a composite UNIQUE covers.** `do_drop_column`'s "an index covers it — drop the index first" guard reads `read_table_indexes`, which filters to `origin='c'` (explicit `CREATE INDEX`) and **excludes the UNIQUE-constraint auto-index** (`origin='u'`). So `drop column c` when `unique (b, c)` spans `c` falls through to the raw engine refusal instead of a friendly message. Fix: detect the column in `schema.unique_constraints` and refuse with a clear engine-neutral message (e.g. "cannot drop `T.c` — it is part of a UNIQUE (b, c) constraint; recreate the table to change it"). Message-only; small. (Interacts with F3.) - **F2 — pre-existing generic-error rendering leaks a literal `{table}` (broader than Phase 4).** Replay renders refused commands via `DbError::friendly_message()` (`runtime.rs:~1202/1238`), which uses `TranslateContext::default()` → the `error.generic.*` template comes out with a **literal unsubstituted `{table}`** and `operation` (no table/operation context). Affects **every** command refused during replay (and other `friendly_message()` callsites, e.g. export) — not Phase-4-specific. Fix needs care: it's a shared path; make the hint degrade gracefully when no table is in context (drop the `… of {table}` clause, or say "the table") and check snapshots. Scope it on its own. - **F3 — provide a way to drop a composite UNIQUE constraint (user- raised; own ADR).** A composite UNIQUE is **anonymous** by design (ADR-0035 §4a.2; 4g refused naming UNIQUE) — stored as a column-list with no name, so no `drop constraint ` can target it, and it can't be removed except by recreating the table. The user wants a way to drop it. This is a **design decision / new capability** (likely a new ADR or an ADR-0035 amendment): either name composite UNIQUEs, or a positional `drop constraint unique (cols)` / `alter table T drop unique (cols)` form, executed via the rebuild primitive. F1's message becomes actionable once F3 lands. ## §4. Carried follow-ups (from handoff-41, still open) - **H1 wording — `--create-fk` leak (4g).** `ALTER … ADD FOREIGN KEY` on a missing child column reuses `do_add_relationship`'s error mentioning the DSL flag `--create-fk` — off-key in SQL. Fix the SQL-path wording. - **Case-only table rename** refusal (4h, autonomous decision) — `alter table T rename to t` refused ("differ only in capitalization"). Left as refuse unless the user wants it supported (would need a temp-name two-step). - **Column-name case strictness** — table names resolve case-insensitively now; column names are still matched case-sensitively (wrong case → "no such column"). Safe; a separate UX-consistency change if wanted. - **Coverage gap — pre-4g 3-column `CHECK_TABLE` migration** in-place path untested (can't fabricate a 3-col table via the public API). - **H1 friendly wording** for the 4e CHECK-guard refusals + 4f type-conversion diagnostics (engine-neutral but terse). - The handoff-39 §8 items: app-lifecycle-command runtime-failure journalling; M4 execution-time mode side-channel; `blob` value literal; CI/TT5; DSL→SQL teaching echo (ADR-0030 Phase 5). ## §5. What's next (no committed scope) ADR-0035 / Phase 4 of ADR-0030 is **done**. Open avenues (per `requirements.md` / CLAUDE.md "deferred"): the SQL→English friendly layer (H1), tutorial/lesson system, session-log + Markdown export (V4), readline/multiline/tab-completion/syntax-highlight input polish, ER diagram export (V3), CI (TT5), and the F1–F3 follow-ups above. None is started; pick with the user. ## §6. Process pins (unchanged) - **Confirm every commit** (propose message, wait). No AI attribution. **Push is the user's step.** Unpushed commits are normal. - **Escalate ambiguity / long tails.** This session surfaced and user-decided every fork (4h scope, case-safety scope, 4i(e) colour design, and the F1–F3 follow-ups). - **`/runda` at planning exit AND on finished slices** — it earned its keep repeatedly this session (the 4h CHECK-drift, the case-collision leak, and confirming the integrated Phase 4 is sound). - **Keep docs lockstep** — ADR status/§13 + index + requirements in the same edit. ## §7. How to take over 1. **Read, in order:** this file → `CLAUDE.md` → `docs/adr/0035-advanced-mode-sql-ddl.md` (now fully shipped) → `docs/requirements.md`. 2. **Baseline:** `cargo test` (1917 / 0 / 0 / 1 ignored) + `cargo clippy --all-targets -- -D warnings` (clean). 3. Phase 4 is complete; there is **no in-flight slice**. Pick the next piece of work with the user (§5), or take an F1–F3 follow-up.