From 9d66073ff79569b833af5f0cf61da88b56e8014b Mon Sep 17 00:00:00 2001 From: "claude@clouddev1" Date: Wed, 27 May 2026 22:15:34 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20session=20handoff=2046=20=E2=80=94=20DS?= =?UTF-8?q?L=E2=86=92SQL=20echo=20mid-feature=20(skeleton=20done,=20render?= =?UTF-8?q?er=20pending)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/handoff/20260527-handoff-46.md | 187 ++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 docs/handoff/20260527-handoff-46.md diff --git a/docs/handoff/20260527-handoff-46.md b/docs/handoff/20260527-handoff-46.md new file mode 100644 index 0000000..777a5be --- /dev/null +++ b/docs/handoff/20260527-handoff-46.md @@ -0,0 +1,187 @@ +# Session handoff — 2026-05-27 (46) + +Forty-sixth handover. **We are mid-feature** — the DSL → SQL teaching +echo (ADR-0038) is partially built (a working walking skeleton). Read +this carefully before continuing; §4 and §5 are the load-bearing parts. + +## §1. State at handoff + +**Branch:** `main`. **HEAD `04c8e42`.** **Tests: 1970 passing, 0 failing, +0 skipped, 1 ignored.** **Clippy: clean** (`--all-targets -D warnings`, +nursery). + +This session designed the **DSL → SQL teaching echo** (ADR-0030 §10) as a +`/runda`'d design set and began building it. Commits since handoff-45's +`2bcc55f`: + +``` +04c8e42 feat: DSL→SQL teaching echo — channel + create-table slice (ADR-0037 + ADR-0038) +9a23e28 fix: update … --all-rows falls back to the DSL instead of misparsing (ADR-0033 Am4) +338dc8a feat: advanced ALTER COLUMN SET/DROP NOT NULL & DEFAULT, SET DATA TYPE (ADR-0035 Am2) +9f15f38 docs(adr): design the DSL→SQL teaching echo (ADR-0038) + dependencies +``` + +## §2. The feature & its build plan + +**Goal:** when a **DSL-form** command runs **in advanced mode**, echo the +equivalent SQL beneath `[ok]`, so a learner reads off the SQL spelling +(ADR-0030 §10). Authoritative spec: **ADR-0038** (read it — the catalogue +in §7, the copy-paste contract §1, the three-category framework §6). + +Five ADRs, all **Accepted/Proposed and `/runda`'d** (the design `/runda` +verdict was PASS with fixes applied — see the ADRs): + +| ADR | What | Build status | +|---|---|---| +| **ADR-0035 Am2** | standard-first dialect + `ALTER COLUMN SET/DROP NOT NULL`, `SET/DROP DEFAULT`, ISO `SET DATA TYPE` | ✅ **done** (`338dc8a`) | +| **ADR-0033 Am4** | `update … --all-rows` falls back to DSL (was a misparse) | ✅ **done** (`9a23e28`) | +| **ADR-0037** | `EffectiveMode` execution-time side-channel (the echo's gate) | ✅ channel **done** (`04c8e42`) | +| **ADR-0038** | the echo + full catalogue | 🚧 **skeleton only** — `create table` echoes; rest of the catalogue pending | +| **ADR-0039** | EXPLAIN over advanced SQL | ⏸ **deferred follow-up** — decision recorded, NOT this feature | + +Build order was Am2 → Am4 → (0037+0038 merged). **0037 and 0038 were +merged into one build step** because the channel is dead code without its +consumer (`-D warnings` rejects it) — see ADR-0037 Implementation notes. + +## §3. The doc-drift fix (already committed, FYI) + +`9f15f38` also reconciled stale notes: **simple-mode column ops (B2/C2) +are implemented**, not pending. `requirements.md` C2/B2 were already +`[x]`; the project `CLAUDE.md` was corrected. (Don't re-flag this.) + +## §4. The echo architecture — how it works NOW (read before editing) + +Data flow for the **interactive** path (replay is separate — see below): + +1. **`app.rs::submit`** computes the three-way **`EffectiveMode`** + (`Simple` / `AdvancedPersistent` / `AdvancedOneShot`) — *reusing the + pre-existing `EffectiveMode` enum*, NOT a new `SubmissionMode` (ADR-0037 + was corrected to reuse it). Passes it to `dispatch_dsl`. +2. **`app.rs::dispatch_dsl(input, submission_mode: EffectiveMode)`** parses + with `submission_mode.as_mode()` (the two-way `Mode` the walker needs), + and emits **`Action::ExecuteDsl { command, source, submission_mode }`** + (new field, `action.rs`). +3. **`runtime.rs` Action::ExecuteDsl handler** → `spawn_dsl_dispatch(…, + submission_mode)`. +4. **`runtime.rs::spawn_dsl_dispatch`**: computes + `echo = crate::echo::echo_for(&command, submission_mode)` → + `Option`, executes the command, and attaches `echo` to the + **`AppEvent::DslSucceeded { …, echo }`** (new field, `event.rs`). +5. **`app.rs` update() DslSucceeded arm** stashes `self.pending_echo = echo` + just before calling `handle_dsl_success`. +6. **`app.rs::note_ok_summary`** (the shared `[ok]` pusher, called by every + success handler) pushes `[ok] …` then, if `pending_echo` is `Some`, + pushes the echo line `Executing SQL: ` (i18n key + `echo.executing_sql`). The stash is set+consumed within one synchronous + `update()`, so it's safe (no interleaving). + +**The renderer:** `src/echo.rs`. `echo_for(command, mode)` gates (advanced +effective mode + DSL-form) and calls `command_to_sql(command) -> +Option`. **`command_to_sql` currently handles only +`Command::CreateTable`** → `CREATE TABLE T (id serial PRIMARY KEY)` +(single inline / compound table-level PK, playground type vocabulary). +Everything else returns `None` (no echo yet). + +**Replay is silent for free:** `run_replay` calls `execute_command_typed` +**directly**, bypassing `spawn_dsl_dispatch`, so replayed lines never +reach the echo path. No `interactive` flag needed. + +**Where the echo is built (ADR correction):** NOT in the db.rs worker — +the worker gets *decomposed* calls, not the `Command`. The runtime's +dispatch is where `Command` + mode + result converge. ADR-0037 §3 / +ADR-0038 §4 were corrected to say so. + +## §5. What's next — expanding the renderer (the actual work) + +Per ADR-0038 §8 phasing. **The catalogue (ADR-0038 §7) is the spec** — +each row is a round-trip test (parse the echo in advanced mode → a +same-effect command; the §1 contract). Order: + +### Phase 1 — rest of Bucket A (single-statement) +Expand `command_to_sql` for: `add column`, `drop column` (non-cascade), +`rename column`, `change column` (→ `ALTER COLUMN c SET DATA TYPE ty` — +**now runnable, Am2 shipped**), `add constraint` (NotNull→`SET NOT NULL`, +Default→`SET DEFAULT v`, Unique→`ADD UNIQUE (c)`, Check→`ADD CHECK (e)`), +`drop constraint` (NotNull/Default only; Unique/Check column-level → +Bucket C), `show data` (→ `SELECT * FROM T [WHERE …] [ORDER BY LIMIT +n]`), and the `delete … --all-rows` / `update … --all-rows` fall-throughs +(**now fall back, Am4 shipped**). + +For EACH new command, also: +- add an `echo: Option` field to its success event + (`DslAddColumnSucceeded`, `DslDropColumnSucceeded`, + `DslChangeColumnSucceeded`, `DslDataSucceeded`, `DslUpdateSucceeded`, + `DslDeleteSucceeded`), +- set it from `echo` in `spawn_dsl_dispatch`'s matching arm, +- stash `self.pending_echo = echo` in the App's matching update() arm. + (`note_ok_summary` already renders it for all.) + +**Needs Expr→SQL + Value→SQL-literal renderers** (ADR-0038 §5 literal +table): for `show data` WHERE filters, `add constraint check`/`default` +values, etc. `blob` has no literal (moot — no blob literal syntax). Auto- +gen columns omitted from INSERT echoes. + +### ⚠️ CRITICAL gotcha for Bucket B + category-3 +The skeleton computes `echo` **BEFORE** `execute_command_typed` (it only +needs the `Command`). **Bucket B (resolved auto-names) and category-3 +(generated shortids, conversion counts) need the *execution result*.** So +when you implement those, **move/augment the echo build to AFTER +execution**, reading the `CommandOutcome`/result (the resolved index name, +the `client_side.*` notes — ADR-0017 §6 / ADR-0018 §9). The runtime has +both (it builds the event from command + outcome). This is the one place +the current skeleton structure must change. + +### Phase 2 — Bucket B +Resolved names (`drop index on T(cols)` → `DROP INDEX `, drop/ +add relationship, auto-named `add index`) and **multi-line** echoes (one +statement per line: `drop column --cascade`, `add relationship +--create-fk`). ADR-0038 §6 category 2. The echo payload likely becomes +`Vec` (one per statement) — generalise `Option`. + +### Phase 3 — category-3 prose expansion +shortid generation, type-conversion transforms, and the `change column +--dont-convert` **caveat** (ADR-0038 §6). De-emphasised prose from the +worker's `client_side.*` notes. + +### Polish (not yet done) +The echo line is currently a **plain `[system]` line** via `note_system`. +ADR-0038 §4 wants it **de-emphasised** (styled-runs, ADR-0028). Refine the +rendering (an `OutputLine` with `styled_runs`, dimmed `Executing SQL:` +prefix) — a TODO, deferred so the skeleton stayed small. + +## §6. Catalogue cheat-sheet (authoritative: ADR-0038 §7) + +- **Echoes** (DSL-only spellings in advanced mode): all DDL forms + + `show data` + `delete/update … --all-rows`. DSL column-op syntax is + ` column in/from/to T: c (type)` (**colon + parens**); index/rel + naming is `as N` (not `named`). +- **NOT echoed**: `insert`/`update … where`/`delete … where` (SQL-first → + `Sql*` = already SQL), `drop table`, `drop index ` (→ `Sql*`), + `show table`, `explain`, `replay`, app commands, column-level + UNIQUE/CHECK *drop* (residual gap, ADR-0035 Am2). `change column + --dont-convert` → echoes the headline + a category-3 **caveat**. + +## §7. Process pins (unchanged) + +- **Confirm every commit** (propose message, wait). **No AI attribution.** +- **Test-first**; green + clippy-clean is the only acceptable end state; + baseline **1970 / 0 / 1**. +- **Keep docs lockstep**: ADR + `README.md` index + `requirements.md`. + Amend ADRs, don't re-litigate. **Raise implementation deviations and + update the ADR** (this session corrected ADR-0035 Am2's SET DEFAULT + executor, ADR-0037's enum + build-layer, ADR-0038 §4 in-place). +- **Round-trip every catalogue row** (the §1 copy-paste contract). + +## §8. How to take over + +1. **Read, in order:** this file → **ADR-0038** (§1 contract, §6 + categories, §7 catalogue, §8 phasing) → **ADR-0037** (channel + + Implementation notes) → the four commits above → **`src/echo.rs`** (the + renderer to expand). +2. **Baseline:** `cargo test` (1970 / 0 / 1) + `cargo clippy --all-targets + -- -D warnings` (clean). +3. **Continue** with §5 Phase 1 (rest of Bucket A), test-first, one + command at a time, round-tripping each echo. Heed the §5 ⚠️ gotcha + before touching Bucket B / category-3. +4. ADR-0039 (EXPLAIN over advanced SQL) is a **separate deferred + follow-up**, not this feature.