# Session handoff — 2026-05-24 (36) Thirty-sixth handover. This session **implemented ADR-0006 (undo/snapshot) end-to-end** (§8 steps 1–8 + a `/runda` data-loss fix) and then **drafted ADR-0035 — advanced-mode SQL DDL** (Phase 4 of the ADR-0030 roadmap, status **Proposed**). The next session **begins implementing ADR-0035, starting at sub-phase 4a**. See §4. ## §1. State at handoff **Branch:** `main`. **Tests: 1698 passing, 0 failing, 0 skipped, 1 ignored** (the unchanged `friendly/mod.rs` doctest). **Clippy:** clean (`cargo clippy --all-targets -- -D warnings`). **Latest commit (local-only):** ``` a079200 docs: ADR-0035 — advanced-mode SQL DDL (Phase 4) ``` `origin/main` is at `df6aa69`; **1 commit is local-only** (a079200). The undo/snapshot work (through `df6aa69`) is already pushed. Unpushed commits are a normal working state; pushing is the user's step — do not prompt about it. ## §2. What shipped this session - **ADR-0006 (undo/snapshot) fully implemented** — the U1/U2 half; the replay/journal half (U3/U4) had shipped via ADR-0034. Built across §8 steps 1–8 of the plan (`docs/plans/20260524-adr-0006-undo-snapshots.md`): - `src/undo.rs` — `SnapshotStore`: a persisted undo ring + redo stack under `/.snapshots/` (`index.yaml` + per-snapshot payload dirs). Hybrid whole-project snapshot — db via the online backup API + `project.yaml`/`data/*.csv` copied; restore is text-first, db-last (ADR-0015 §6). - `src/db.rs` — `snapshot_then` brackets all **19 mutating dispatch arms** (stage→run→finalise/discard), gated on a **user command `source`** (internal ops like open-time rebuild are *not* snapshotted); `BeginBatch`/`EndBatch` (a `replay`/batch = one undo step); `Undo`/`Redo`/`PeekUndo`/`PeekRedo` handled in `worker_loop` with `&mut conn`. - `undo`/`redo` app commands + `Modal::UndoConfirm` confirm flow; `--no-undo` CLI flag; `.snapshots/` git-ignored + export-excluded + temp-cleanup-allowlisted. - **`/runda` found + fixed a silent data-loss bug**: a committed mutation whose snapshot couldn't be *staged* left the redo stack stale (redo-clear was a side effect of `finalize`), so a later `redo` discarded the new work. Now `clear_redo` runs on that path (`snapshot_then`/`end_batch`); commit `df6aa69`, regression-tested. - ADR-0006 marked implemented (Amendment 1 + Implementation note); `requirements.md` U1/U2 → `[x]`; `CLAUDE.md` updated. - **ADR-0035 drafted** (`docs/adr/0035-advanced-mode-sql-ddl.md`, commit `a079200`, **Proposed**) — the next job (§3/§4). ## §3. ADR-0035 design — settled with the user (do not re-litigate) All user-confirmed through discussion this session. 1. **Own per-statement `Sql*` DDL commands** — `SqlCreateTable`, `SqlAlterTable`, `SqlDropTable`, `SqlCreateIndex`, `SqlDropIndex` (granularity mirrors the DML `Sql*` set). **Clarifies ADR-0030 §4**: DDL gets its own advanced commands, but **unlike DML they execute *structurally*, not verbatim** — raw execution would lose the playground's types, named relationships, and `STRICT`. ("Verbatim" for DML was a convenience, not a rule.) **Simple mode is untouched** (additive). Handlers **reuse the low-level schema/metadata helpers** where the op matches simple mode, **stand alone where the SQL surface is richer** (multi-FK `CREATE TABLE`) — clarity over forced refactoring. 2. **Dispatch:** `create`/`drop` reuse ADR-0033 Amendment 1's category-grouped, mode-aware dispatch (SQL-first in advanced, simple fallback); **`alter` is a new advanced-only entry word.** 3. **Type vocabulary** (ADR-0030 §5): playground keywords + standard-SQL aliases mapped (`integer`→`int`, `varchar`→`text`, `timestamp`→ `datetime`, …); length args accepted-and-ignored; no engine type names in/out. 4. **FK → named relationships:** inline `REFERENCES` + table-level `FOREIGN KEY` create the table **and** its relationship metadata in one command (= **one undo step**); `ON DELETE`/`ON UPDATE` → ADR-0013 actions; constraint name → relationship name. 5. **Column-type conversion — unified** (ADR-0017 engine, mode policy): clean auto-converts both modes; incompatible + own-type-static cases refuse both modes; **lossy refuses-by-default in simple mode (`--force-conversion`), but advanced mode performs it with a post-op loss note and relies on `undo` as the net** (no force flag, no dropping to simple mode). 6. **Table rename (`C1`)** — advanced-only `ALTER TABLE … RENAME TO`; **new low-level op** (rename table + its CSV file + the relationship metadata rows). No simple-mode form. 7. **Surface** = full, no pre-emptive cuts; **9 sub-phases 4a–4i** (ADR §13), each with exit + DA gates. 8. **Integration is structural, not free of authoring** (ADR §11): the walker *mechanisms* (highlighting, `[ERR]`/`[WRN]`, usage skeleton, completion engine) come free; each node still **authors** the right `IdentSource` on schema-name slots, its hint/usage catalog keys, and DDL-specific walker diagnostics (the DDL peers of the DML ones ADR-0033 added). 9. **Replay:** `create`/`drop`/`alter` are schema-write entry words, **not** in ADR-0034's app-lifecycle skip set, so SQL DDL **replays as a write — no replay-filter change** (unlike `undo`/`redo`). ## §4. ADR-0035 implementation — the NEXT job **Begin Phase 4 at sub-phase 4a**, test-first, following the ADR-0033 sub-phase model. **Recommended first action:** read ADR-0035 in full, then write a short plan doc (`docs/plans/-adr-0035-sql-ddl.md`) and confirm any open micro-calls with the user before coding — exactly how ADR-0033/0034/ 0006 were run. **Sub-phases (ADR-0035 §13):** - **4a** — dispatch + `CREATE TABLE` core (columns + the §3 type map + column constraints + single/compound `PRIMARY KEY`); no FK yet. - **4b** — FK in `CREATE TABLE` (inline + table-level) → relationships. - **4c** — `DROP TABLE`. - **4d** — `CREATE [UNIQUE] INDEX` / `DROP INDEX`. - **4e** — `ALTER TABLE` add/drop/rename column. - **4f** — `ALTER TABLE … ALTER COLUMN TYPE` (the §7 conversion model). - **4g** — `ALTER TABLE` add/drop constraint, add FK. - **4h** — `ALTER TABLE … RENAME TO` (the §6 new low-level op). - **4i** — verification sweep (typing-surface/matrix, engine-neutral errors, undo parity, `help`/usage). **Concrete must-not-forget for the implementer:** - **Undo wiring for the new commands.** Each `Sql*` DDL command becomes a **new `Request` variant in `src/db.rs`** and **must be wrapped with `snapshot_then`** like the existing 19 mutating arms (so it's one undo step). `handle_request`'s exhaustive match will force you to handle each new variant — wrap it, don't `reply.send` it raw. `create`/ `drop`/`alter` need **no** `is_app_lifecycle_entry_word` change (they're writes, §3.9). - **Grammar lives in `src/dsl/grammar/`** (`CommandNode` + the `REGISTRY` in `mod.rs`, tagged `CommandCategory`); mirror the ADR-0033 DML nodes (`src/dsl/grammar/sql_*`). `CHECK`/`DEFAULT` expressions reuse the ADR-0031 `sql_expr` fragment. - **`ALTER`/column ops build on the ADR-0013 rebuild-table primitive** (already used by drop/rename/change-column). - **Catalog + keys lockstep** (`src/friendly/strings/en-US.yaml` + `src/friendly/keys.rs`, validated by `keys_validate_against_catalog`): every new `help_id`/`usage_id`/diagnostic key needs both a catalog body and a keys.rs entry; engine-neutral wording (the vocab audit enforces it). - **Tests:** four tiers (ADR-0008). Per-sub-phase Tier-3 like `tests/sql_insert.rs`/`sql_update.rs`/`sql_delete.rs`, plus an end-to-end `tests/sql_ddl_e2e.rs` (mirror `sql_dml_e2e.rs`), plus typing-surface/matrix coverage. **Add a DDL undo test** (each statement = one undo step; `CREATE TABLE` with FK = one step). **Open micro-calls to escalate when reached** (not yet decided): - `CREATE UNIQUE INDEX` — ADR-0025's index model may need a `unique` flag (ADR §4/§13 4d flags this). - Exact `ALTER COLUMN … TYPE` spelling, and whether `IF [NOT] EXISTS` is admitted or an ordinary parse error (ADR §12 leans OOS). - Status flip: ADR-0035 is **Proposed**; flip to **Accepted** once 4a validates the path end-to-end (the ADR-0033 lifecycle). ## §5. Other tracked deferred items (nothing lost) - **(A)** App-lifecycle-command *runtime*-failure journalling (small ADR-0034 follow-up; recorded in ADR-0034's Implementation note). - **M4** — execution-time mode side-channel (deferred by ADR-0033 Amendment 3; needs its own ADR). - **`blob` value literal** (`src/dsl/value.rs`) — pre-existing gap. - **Undo residual edge** (ADR-0006 Implementation note): if the entire `.snapshots/` dir is unwritable, `clear_redo` can also fail and a stale redo could survive — accepted (whole undo subsystem is broken then). - **CI / TT5**, **DSL→SQL teaching echo** (ADR-0030 Phase 5), **DDL as the last SQL phase before §6 polish**. ## §6. Process pins (unchanged, still binding) - **Confirm every commit.** Propose the message; wait for the go-ahead. (Every commit this session was user-approved.) - **Push is the user's step.** Never push; never prompt about it. - **No AI attribution** in commits (global rule). - **Probe, don't reason.** The `/runda` round this session found a real silent-data-loss bug by *running a throwaway probe*, not by reasoning. Reproduce/print before concluding; delete probes before committing. - **Escalate ADR-vs-implementation mismatches and scope calls.** The whole ADR-0035 design was settled by escalating (the reuse-vs-own-command question, the conversion model) rather than guessing — and corrected twice when the user pushed back. - **Keep docs in lockstep.** ADR status flips update `docs/adr/README.md` in the same edit; behaviour changes update `requirements.md`. - **Terminology:** the **DSL is the one unified command grammar**; the real axis is **mode-availability** (simple / advanced / both), not "DSL vs SQL". Avoid calling simple-mode commands "the DSL". ## §7. How to take over 1. **Read, in order:** this file → `docs/adr/0035-advanced-mode-sql-ddl.md` (**the next job**) → `docs/adr/0030-advanced-mode-sql-surface.md` (§4/§5 architecture) + `docs/adr/0033-sql-dml-grammar.md` (the dispatch + sub-phase precedent to mirror) → `CLAUDE.md` → `docs/requirements.md` (`Q4`/`C1`). 2. **Baseline:** ``` cargo test # expect 1698 passing / 0 failing / 0 skipped / 1 ignored cargo clippy --all-targets -- -D warnings # clean ``` 3. **Start ADR-0035** per §4: read the ADR, draft a short plan, confirm the open micro-calls with the user, then implement 4a test-first. 4. **Escalate** anything not settled in ADR-0035; the user wants mismatches and scope calls surfaced, not silently decided.