From 02234e6c456404dedc6d67a45d666b847f6d26fe Mon Sep 17 00:00:00 2001 From: "claude@clouddev1" Date: Tue, 19 May 2026 12:55:24 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20handoff=2021=20=E2=80=94=20ADR-0028=20c?= =?UTF-8?q?omplete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ADR-0028 (query plans / `explain`) is fully implemented; the handoff-16 design trio (ADR-0026 / 0027 / 0028) is now closed. - handoff-21: session summary, the two deliberate deviations from handoff-20's plan, test coverage, open clusters. - requirements.md: QA1 / QA2 ticked. - CLAUDE.md: the `EXPLAIN QUERY PLAN` deferred-items line updated to "implemented per ADR-0028". --- CLAUDE.md | 5 +- docs/handoff/20260519-handoff-21.md | 161 ++++++++++++++++++++++++++++ docs/requirements.md | 17 ++- 3 files changed, 171 insertions(+), 12 deletions(-) create mode 100644 docs/handoff/20260519-handoff-21.md diff --git a/CLAUDE.md b/CLAUDE.md index 18159fc..438b8d9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -184,9 +184,8 @@ not yet implemented: rebuild-table primitive (ADR-0013) is in place; the grammar and dispatch are pending. - **Indexes**: `add index` / `drop index` done (ADR-0025). - `EXPLAIN QUERY PLAN` (QA1 / QA2) is designed in ADR-0028 — - the `explain` prefix command + span-styled plan tree — - but not yet implemented. + `EXPLAIN QUERY PLAN` (QA1 / QA2) implemented per ADR-0028 — + the `explain` prefix command + span-styled plan tree. - **Modify relationship** (C3a): drop+add covers the use case today. - **m:n convenience** (C4): auto-generates a junction table diff --git a/docs/handoff/20260519-handoff-21.md b/docs/handoff/20260519-handoff-21.md new file mode 100644 index 0000000..3c87a50 --- /dev/null +++ b/docs/handoff/20260519-handoff-21.md @@ -0,0 +1,161 @@ +# Session handoff — 2026-05-19 (21) + +Twenty-first handover. This session **finished ADR-0028** — +query plans / `explain`. Steps 2–5 (planned in full in +handoff-20 §3) are implemented, tested and committed; step 1 +landed in the previous session. **ADR-0028 is complete**, and +with it the handoff-16 design trio (ADR-0026 / ADR-0027 / +ADR-0028) is fully implemented. + +## State at handoff + +**Branch:** `main`. Working tree clean. **3 feature commits** +this session (plus this handoff); all local — push +asynchronously, not blocking. + +``` + docs: handoff 21 — ADR-0028 complete +ae99276 explain: typing-surface matrix cells (ADR-0028 step 5) +a7d459f explain: styled plan tree + annotation taxonomy (step 4) +d17addd explain: `explain` command end to end (steps 2–3) +c1fcf28 docs: handoff 20 — ADR-0028 step 1 done, 2-5 planned +03d8a09 ui: styled-output-line mechanism (ADR-0028 step 1) +``` + +**Tests:** **1172 passing, 0 failing, 1 ignored** (`cargo +test`). The ignored test is the long-standing `` ```ignore `` +doc-test in `src/friendly/mod.rs`. Typing-surface matrix: +**174 cells** (was 161 — +13 for `explain`). + +**Clippy:** clean (`cargo clippy --all-targets -- -D +warnings`, nursery group). + +## §1. What ADR-0028 delivered + +The `explain` prefix command — `explain show data …`, +`explain update …`, `explain delete from …` — captures a +query's plan via `EXPLAIN QUERY PLAN` and renders it as an +annotated, span-styled tree. `EXPLAIN QUERY PLAN` never +executes the wrapped statement, so explaining a destructive +`update` / `delete` is safe and changes nothing. + +- **Grammar** (`src/dsl/grammar/data.rs`): a new `EXPLAIN` + `CommandNode` whose shape is a `Choice` over the three + explainable query shapes, reached through `Subgrammar` — the + inner command is parsed, completed and hinted exactly as it + is standalone. `Command::Explain { query: Box }`. +- **Worker** (`src/db.rs`): SQL construction split out of + `do_query_data` / `do_update` / `do_delete` into + `build_query_data_sql` / `build_update_sql` / + `build_delete_sql`, so `EXPLAIN QUERY PLAN` runs the exact + same statement. `Request::ExplainPlan` / `do_explain_plan` + capture the plan; `QueryPlan` / `ExplainRow` carry it back. +- **Display SQL**: the executed statement with `?N` params + inlined as standard-SQL literals (`<>` for inequality, + double-quoted idents, the implicit `ORDER BY ` that + `limit` adds). +- **Render** (`src/output_render.rs`): `render_explain_plan` + draws the box-drawing tree; `PLAN_TAXONOMY` classifies each + node's `detail` and only the category-bearing keyword run + carries a semantic colour (efficient / expensive / + automatic-index). An automatic-index node also gets the + `← add an index?` advice tag. +- **Catalog**: `parse.usage.explain` plus `help.data.explain` + — `explain` appears in the in-app `help` listing. + +## §2. Decisions / deviations from handoff-20's plan + +handoff-20 §3 was followed closely. The three gotchas it +flagged all held — `static` wrappers (`EXPLAIN_SHOW_DATA` +etc.) for the `Subgrammar` `&'static` requirement; the +role-based `build_show_data` extraction; steps 2+3 combined +into one commit because the `Command::Explain` variant breaks +every exhaustive `match Command`. Two deliberate deviations: + +1. **Display SQL via param-inlining, not a parallel + `compile_operand`.** handoff-20 suggested a second + literal-rendering variant of the WHERE compiler. Instead, + `inline_params_for_display` (`src/db.rs`) takes the + executed SQL and substitutes each `?N` with its bound + literal in a single quote-aware scan. This is structurally + guaranteed to match the executed statement and avoids a + second expression compiler that could drift from the + first. (`<>`, double-quoted idents and the implicit + `ORDER BY` all come for free — they are already in the + executed SQL.) +2. **`help_id: Some("data.explain")`, not `None`.** + handoff-20 planned no help entry; at the user's request + `explain` now has a `help.data.explain` catalog entry and + appears in `help` like every other command. + +Other notes: + +- `render_explain_plan` returns `Vec` (styled). + Commit A built the tree with plain lines; commit B enriched + the *same* function with the taxonomy + styled runs — no + duplicated tree-walking logic. +- `explain` is **not** written to `history.log` + (`do_explain_plan` takes no `source`) — it is a read-only + diagnostic, and `EXPLAIN QUERY PLAN` does not execute. +- The plan tree renders wholly in the neutral foreground + colour (not the `System` green) so connectors / names stay + neutral per ADR-0028 §6; only category keywords are + coloured. Every plan line therefore carries a `styled_runs` + payload, including the display-SQL line. + +## §3. Test coverage added + +- **Parse** (`src/dsl/grammar/data.rs` `explain_tests`): each + wrapped form parses to `Command::Explain`; `explain` of an + incomplete inner command is the same parse error; `explain + show table` is rejected (`explain` covers `show data` only). +- **Worker** (`src/db.rs`): scan vs. index-search plans; + `explain delete` / `explain update` leave data untouched; + display SQL inlines literals, quotes idents, shows the + implicit `ORDER BY`, writes `<>`; missing-table errors. +- **Render** (`src/output_render.rs`): the taxonomy classes, + the automatic-index tag, neutral fallback, a cyclic-parent + guard. +- **App** (`src/app.rs`): the `DslExplainSucceeded` handler + renders the `[ok]` header, display SQL and tree. +- **Typing-surface matrix**: 13 cells in + `tests/typing_surface/explain.rs`. + +## §4. What's next + +ADR-0028 closes the handoff-16 design trio. No feature is in +flight. Open clusters, unchanged from handoff-16/17/18/19/20 +(prioritisation is a **user decision — ask**): + +- Snapshot / undo / replay `U`-series (designed in ADR-0006). +- Constraints `C3`; m:n convenience `C4`; modify-relationship + `C3a`; column drop/rename/type-change grammar `C1` (the + rebuild primitive exists). +- Friendly-error layer `H1` (partial); strong syntax-help in + parse errors `H1a`. +- Session-log / Markdown export `V4` — would be the first + real reuse of the `OutputLine` styled-runs mechanism beyond + the plan renderer. +- `SD1`; CI workflow `TT5`; readline shortcuts `I1b`; + multi-line input `I1`; `TU1`. + +## §5. How to take over + +1. **Read this file**, then `CLAUDE.md` (working-style + rules), then `docs/requirements.md` (per-item progress — + `QA1` / `QA2` now ticked). +2. **Run `cargo test`** — 1172 passing, 0 failing, 1 ignored. +3. **Run `cargo clippy --all-targets -- -D warnings`** — + clean. +4. Pick the next cluster *with the user* — §4 has no default. + +### Note on the typing-surface matrix + +`tests/typing_surface/` is **174 cells**. The matrix-snapshot +discipline from handoff-17/18/19/20 stands: a failing cell +with *correct* new behaviour → update its snapshot; with +*wrong* behaviour → the cell earned its keep. `cargo insta` +is not installed on this machine — regenerate snapshots with +`INSTA_UPDATE=always cargo test --test typing_surface_matrix +` and review the written `.snap` files before +committing. diff --git a/docs/requirements.md b/docs/requirements.md index e3baf4a..04db234 100644 --- a/docs/requirements.md +++ b/docs/requirements.md @@ -371,18 +371,17 @@ handoff-14 cleanup; 449 after B2/C2.) ## Query analysis -- [ ] **QA1** `EXPLAIN QUERY PLAN` is run on demand for queries; +- [x] **QA1** `EXPLAIN QUERY PLAN` is run on demand for queries; output is rendered as an annotated tree highlighting full scans, index use, and join order. - *(Designed in ADR-0028: the `explain` prefix over + *(Implemented per ADR-0028: the `explain` prefix over `show data` / `update` / `delete`, with a span-styled plan - tree. The pedagogical payoff — a plan that flips between a - full scan and an index search — needs a filtered query - (`show data … where`, designed in ADR-0026) plus indexes - (ADR-0025, done). Implementation pending.)* -- [ ] **QA2** Plan rendering specifics — tree layout, annotation - taxonomy, colour scheme. Designed in ADR-0028 (§3–§6); - implementation pending. + tree. `EXPLAIN QUERY PLAN` never executes, so explaining a + destructive `update` / `delete` is safe.)* +- [x] **QA2** Plan rendering specifics — tree layout, annotation + taxonomy, colour scheme. Implemented per ADR-0028 (§3–§6): + a box-drawing tree, the substring-pattern taxonomy, and the + `OutputLine` styled-runs mechanism. ## Hints, help, errors