# Session handoff — 2026-05-28 (49) Forty-ninth handover. **ADR-0038 is done.** Every catalogue row of the DSL → SQL teaching echo is implemented, every echo round-trips per line per the §1 copy-paste contract, every §6 category-3 line surfaces, and the §4 de-emphasised styled-runs rendering polish landed in `2aab457`. Docs in sync. If you continue, pick a fresh feature; if you're triaging, ADR-0038 won't surprise you. ## §1. State at handoff **Branch:** `main`. **HEAD `2aab457`.** **Tests: 2019 passing, 0 failing, 0 skipped, 1 ignored.** **Clippy: clean** (`--all-targets -D warnings`, nursery). Commits since handoff-48's `df5c4e2`: ``` 2aab457 feat: DSL→SQL teaching echo — §4 styled-runs polish (ADR-0038) ``` (Plus this handoff + lockstep doc updates landing alongside it.) ## §2. ADR-0038 — done The feature shipped across **five** commits, the last of which is the §4 polish: | Commit | Phase | What | |---|---|---| | handoff-46 `04c8e42` | 1 (start) | channel + create-table slice | | `90479cb` | 1 (rest) | Bucket A renderer — every single-statement DDL row + `show data` + `--all-rows` fall-throughs; create-table contract-gap fix | | `275c726` | 2 | Bucket B — resolved-name + multi-statement (auto- and user-named `add index`, positional `drop index`, `add`/`drop relationship` in both selector forms, `drop column --cascade`, `add relationship --create-fk`) | | `e6ad1ae` | 3 | category-3 prose — `change column --dont-convert` *caveat* (the other two cat-3 lines were already in place via `client_side.*` keys) | | `2aab457` | 4 (polish) | §4 styled-runs rendering — `OutputKind::TeachingEcho` with dimmed prefix + advanced-mode lex of the SQL; `OutputStyleClass::Hint` for every cat-3 prose line | Plus the /runda DA cleanup at `5cb105b` (doc-drift + Bucket C explicit tests). ADR-0037 and ADR-0038 both **Accepted** with implementation notes referencing every shipping commit. ## §3. What the polish (Phase 4) does, in shape Per ADR-0038 §4 + §6, the de-emphasised styled-runs treatment landed in `2aab457`. The user-confirmed scope (per session discussion) went slightly beyond §4's "echo + caveat" to cover the existing illuminating cat-3 notes too — visual consistency for every cat-3 prose line, matching §6's "de-emphasised prose line" wording. **The polish in code:** - **`OutputKind::TeachingEcho`** (new). Lines with this kind go through a custom `ui::render_output_line` branch that mirrors the `OutputKind::Echo` simple-mode input-echo path: strip the canonical `crate::echo::TEACHING_ECHO_LABEL` ("Executing SQL: "), render the prefix dimmed (`theme.muted`), then lex the rest in `Mode::Advanced` via `input_render::lex_to_runs_in_mode` and emit one span per token. Tag stays `[system]` for visual consistency with other system output. - **`OutputStyleClass::Hint`** (new), resolved to `theme.muted` by `output_span_style`. Carried on category-3 prose lines as a single styled-runs span covering the whole text (so the body renders dimmed; the `[system]` tag keeps its kind tint). - **`crate::echo::TEACHING_ECHO_LABEL`** (new pub const) — the fixed byte boundary the ui.rs branch needs. The label moved out of the `echo.executing_sql` i18n key (now retired in en-US.yaml + keys.rs; a comment in en-US.yaml points future locales at re-introducing it). - **App-side helpers**: `App::push_teaching_echo(sql)` builds the TeachingEcho line; `App::push_category_three_prose(text)` builds a System line with a whole-text Hint span. `note_ok_summary` and `handle_dsl_change_column_success` / `handle_dsl_add_column_success` use these instead of plain `note_system` for the echo, the DontConvert caveat, and the illuminating client-side notes. **Where each rendering rule lives:** | Line | Built by | Renders as | |---|---|---| | `[ok] verb subject` | `note_ok_summary` via `note_system` | `[system]` tag + `system` green body (unchanged) | | `Executing SQL: ` (one per echo line) | `push_teaching_echo` | `[system]` tag + dimmed prefix + token-coloured SQL | | `[client-side] N row(s) were transformed …` | `push_category_three_prose` (auto_fill_*, transformed*) | `[system]` tag + whole-body dim | | `[client-side] --dont-convert kept …` | `push_category_three_prose` (caveat path) | `[system]` tag + whole-body dim | | structure render, row counts, etc. | `note_system` | unchanged | **Coverage:** four new tests pin the polish — `ui::tests:: teaching_echo_line_renders_dim_prefix_and_lexed_sql` (asserts the dim prefix span + keyword-coloured SQL spans confirm advanced-mode lex), `ui::tests::category_three_prose_line_renders_all_dim` (whole-text Hint coverage), `ui::tests:: hint_class_resolves_to_muted_foreground` (theme resolution across both palettes), `app::tests:: polished_echo_carries_teaching_echo_kind_and_caveat_a_hint_span` (App-side wiring kinds + styled_runs shape). The pre-existing echo tests pass unchanged — the text content is identical, only styling changed. ## §4. Notable observations carried over from handoff-48 These are the same ones flagged before the polish — none became blockers, the polish didn't introduce new ones. - **Unquoted-identifier round-trip caveat.** Echo style is bare identifiers (matching the original create-table echo aesthetic). A user-created column or table named after a SQL keyword (e.g. `ORDER`, `SELECT`) would produce an echo whose round-trip is fragile. Pre-existing limitation; the §1 contract is only formally violated for this edge case. Fix is identifier-quoting if it ever bites a learner. - **No full-spawn integration test for the echo pipeline.** Coverage is layered (pure renderers + runtime-helper unit tests with real Database + App-level rendering tests + ui.rs styling tests). The unwired glue is small; a Tier-3 end-to-end test would complete the picture, not blocking. - **Pure-Command Schema commands double-compute echo.** `echo_for` is called for every command; the Schema arm recomputes via `build_schema_echo` (whose catch-all redelegates to `command_to_sql`). Minor inefficiency, no behaviour bug. ## §5. What's next Up to you. ADR-0038 won't pull on any more rope. Candidate features: - **ADR-0039 — EXPLAIN over advanced-mode SQL queries** (`Accepted`, implementation deferred). Self-contained: lets `explain` wrap the advanced SQL commands (`Select`/`SqlInsert`/`SqlUpdate`/ `SqlDelete`) in addition to the DSL `ShowData`/`Update`/`Delete` it already covers (ADR-0028). Test-first when picked up. - **Other tracks** from `requirements.md` — see the file for the pending list. Likely candidates: track 2 (project storage Iter 5/6 — export/import + `--resume` + persistent input history + migration framework), `C3a` (modify relationship), `C4` (m:n convenience), `H1`/`H1a` (friendly error layer + syntax-help in parse errors), the tutorial/lesson system, V4 session log + Markdown export, the remaining input UX items (`I1`/`I1b` multi-line + readline shortcuts, `I3` tab completion polish, `I4` syntax highlighting beyond input echo). - **Polish-spawned ideas** from this session — none currently outstanding; the OutputStyleClass vocabulary now has `Hint` and could grow further if another consumer needs it. ## §6. Process pins (unchanged) - **Confirm every commit** (propose message, wait). **No AI attribution.** - **Test-first**; green + clippy-clean is the only acceptable end state; current baseline **2019 / 0 / 1**. - **Keep docs lockstep**: ADR + `README.md` index + `requirements.md`. This session's polish commit ships alongside this handoff and the three doc-update edits (M4 / ADR-0038 Status / ADR-0037 + ADR-0038 README index entries). - **Round-trip every catalogue row** (the §1 copy-paste contract; for multi-statement, *per line*). ## §7. How to take over 1. **Read, in order:** this file → `requirements.md` for the open tracks → the relevant ADR for whatever feature you pick up. ADR-0038 / ADR-0037 are done and well-documented; touch them only to amend if a real correction comes up. 2. **Baseline:** `cargo test` (2019 / 0 / 1) + `cargo clippy --all-targets -- -D warnings` (clean). 3. **For a fresh feature**: write the ADR (or extend an existing one), run `/runda` over the design before building, then build test-first. 4. **The ADR-0028 styled-runs vocabulary** is now richer: `Neutral`, `Efficient`, `Expensive`, `AutomaticIndex`, `Hint`. Adding a new consumer? Pattern is one variant per semantic class, theme-resolved in `ui::output_span_style`, used via `OutputLine::styled` or a dedicated kind + custom render branch (as `TeachingEcho` does for the dim-prefix + lex-rest case).