# 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 <name>` 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.
