From ca158e8b25c24464299c903874bc62e2878c83ff Mon Sep 17 00:00:00 2001 From: "claude@clouddev1" Date: Sat, 6 Jun 2026 12:29:47 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20session=20handoff=2058=20=E2=80=94=20H1?= =?UTF-8?q?a=20done=20via=20ADR-0042=20systematic=20pass?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/handoff/20260606-handoff-58.md | 185 ++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 docs/handoff/20260606-handoff-58.md diff --git a/docs/handoff/20260606-handoff-58.md b/docs/handoff/20260606-handoff-58.md new file mode 100644 index 0000000..d8ecd08 --- /dev/null +++ b/docs/handoff/20260606-handoff-58.md @@ -0,0 +1,185 @@ +# Session handoff — 2026-06-06 (58) + +Fifty-eighth handover. Continues from handoff-57, whose **next job +was H1a**. This session did exactly that, end to end: **H1a +(strong syntax-help in parse errors) is now done and marked `[x]`** +in `requirements.md`, via a new ADR-0042 systematic pass. The arc +was audit → ADR → test-first matrix → four gap fixes → two +adversarial review passes that each caught a real defect. See §2. + +## §1. State at handoff + +**Branch:** `main`. **HEAD `c305dc7`.** **origin/main at `10f8c2a`** +(pushed mid-session) → **4 commits unpushed** (`649fdcb`, `1d4923b`, +`d6e229f`, `c305dc7`). Push is the user's step. + +**Tests: 2158 passing / 0 failing / 1 ignored** (lib 1578, it 388, +typing_surface_matrix 192; the 1 ignored is the pre-existing one). +**Clippy clean** (nursery, all targets, `-D warnings`). + +This session's commits (since handoff-57's `a8d0138`): + +``` +c305dc7 docs: mark H1a done via the ADR-0042 systematic pass +d6e229f feat: H1a CROSS JOIN ON teaching message; advanced-SQL gaps re-verified (ADR-0042) +1d4923b fix: H1a G3 advanced usage shows all valid forms; complete near-miss matrix (ADR-0042) +649fdcb feat: H1a parse-error gaps G2–G4 + advanced near-miss matrix (ADR-0042) +10f8c2a test: H1a near-miss matrix + friendlier `add 1:n relationship` label (ADR-0042) +0e6f767 docs: ADR-0042 — continue H1a parse-error pedagogy on the grammar tree +``` + +## §2. What happened this stretch — H1a, start to finish + +### Audit first (the big correction) + +The handoff-57 §6 pointer said "read ADR-0021 + ADR-0020". **Both +are obsolete.** They specify a `chumsky`-over-tokens mechanism +(`UsageEntry` registry, `parse.token.*` keys, a lexer) that +**ADR-0024 deleted** — chumsky is not a dependency; the parser is +the scannerless unified grammar-tree walker. ADR-0020/0021 are now +marked **Superseded** (status notes + README), kept as memory. +ADR-0021's *intent* survived and was already ~80% shipped via the +grammar tree. **Read `docs/adr/0042-h1a-parse-error-pedagogy-grammar-tree.md`, +not 0020/0021, for the live H1a design.** + +### ADR-0042 + the user's three scope decisions + +Wrote **ADR-0042** (continues H1a against the grammar tree). Three +forks escalated and decided by the user: (1) ADR hygiene = +superseded-notes + new ADR; (2) scope = matrix-verify + friendlier +literal labels; (3) advanced-SQL **in scope**. + +### The near-miss matrix (the definition of done) + +`tests/it/parse_error_pedagogy.rs` now holds a per-command +near-miss matrix, built **test-first** from an empirical baseline +capture. Covers, in both modes: every entry word's bare / +missing-clause / wrong-token cases, the app-lifecycle trailing-junk +cases, and the **committed multi-forms** (`add index`, +`add constraint`, `add 1:n relationship`, `drop index/constraint/ +relationship`, `show table`, `change column`, `create index`, +`alter table add/drop`). Tests: `near_miss_matrix_simple_mode`, +`near_miss_matrix_advanced_mode`, `near_miss_matrix_committed_multiforms`, +plus per-gap tests. + +### Four gap fixes (each test-first) + +- **G1** — bare `1` cardinality literal → `` `1:n relationship` `` in + `format_expectation` (render-only; completion still offers `1`). +- **G2** — bare `select`'s 14-item expression first-set → "a + projection: `*`, a column, or an expression", detected by the + `distinct`+`all` quantifier pair (unique to a projection start; + empirically verified non-misfiring). Render-only in + `format_walker_error`. +- **G3** — usage block was mode-blind. Added `usage_*_in_mode` + (`src/dsl/grammar/mod.rs`) + mode threading through + `render_usage_block` (`app.rs`) and the ambient usage + (`input_render.rs`). **Decision (user, after review):** advanced + mode shows **all forms valid in the mode, SQL-first then the DSL + fallback forms** — DSL forms (`create table … with pk`, + `drop column …`) remain valid input in advanced mode (verified), + so a usage hint must not hide them. Simple mode = DSL only. +- **G4** — `with` got its own `parse.usage.with` CTE template + (was borrowing `select`'s). +- **CROSS JOIN ON** — `parse.cross_join_no_on` teaches "a CROSS JOIN + has no ON clause …" when the failing token is `on` and the most + recent consumed join is a CROSS join. `is_cross_join_on` in + `parser.rs`; render-only. + +### Two adversarial review passes earned their keep + +- Pass 1 caught **G3 over-correction**: an initial "SQL-only" + advanced usage block *hid* valid DSL fallback forms. Escalated → + user chose "show all valid forms" → fixed (`1d4923b`). +- "Verify, don't trust the survey" **reversed two of three** + advanced-SQL "gaps": INSERT…SELECT count and RETURNING scope were + *already handled* (the Explore-survey list was wrong, twice). + Only CROSS JOIN ON was real. +- The matrix itself caught a regression mid-work (advanced + insert/update/delete falling back to available-commands because + the SQL nodes have empty `usage_ids`; fixed with a union fallback). + +### Deferred by decision (low-priority residual) + +At **submit** time, a non-projection expression position (bare +`where `, `returning `, `having `, `set col=`) still renders the raw +~14-item expression first-set; only the SELECT projection is glossed +(G2). Low-impact because **typing-time completion already offers the +right candidates** there. User chose to leave it. Documented in +ADR-0042 + `requirements.md`. + +Plus one **pre-existing caveat** (not this session's work, noted in +ADR-0042): `insert into T (one_col) select * from Multi` isn't +pre-caught for arity — `SELECT *` isn't expanded; the engine rejects +it at execution (brushes ADR-0019 §OOS-2 engine-error territory). + +## §3. ⚠️ Where parse-error pedagogy lives now (read before touching) + +- **Usage templates:** `parse.usage.*` in `src/friendly/strings/en-US.yaml`; + `usage_ids` on each `CommandNode` (`src/dsl/grammar/mod.rs`). + Mode-aware selection: `usage_keys_for_input_in_mode` / + `usage_key_for_input_in_mode`. +- **Structural error wording:** `format_walker_error` + + `format_expectation` in `src/dsl/parser.rs` (this is where the G1 + label, G2 projection gloss, and CROSS JOIN message live — + render-only, they do **not** mutate the `Expectation` set the + completion/hint layer consumes). +- **Catalog discipline (ADR-0019):** every new key goes in + `en-US.yaml` **and** `src/friendly/keys.rs::KEYS_AND_PLACEHOLDERS` + (the `keys_validate_against_catalog` test enforces it). +- **Tests:** integration parse-error tests live in `tests/it/` per + the handoff-57 §3 rule — drop the file in `tests/it/` + add a + `mod` line to `tests/it/main.rs`. Schema-aware diagnostics are + tested at the walker level with a `SchemaCache` (`vschema` helper + in `tests/it/sql_insert.rs`). + +## §4. Carried / unchanged + +- **arboard decisions** (handoff-55 §3): X11-only on Linux; `copy` + reproduces `[system]` tags. One-line changes if revisited. +- No open GitHub issues (`gh issue list` empty; the project's issue + tracker is GitHub, not the gitea host `tea` is configured for). + +## §5. Other tracks (from `requirements.md`) + +Unchanged: Track 2 Iter 6 leftovers (history.log input-history +hydration polish, migration-framework exercise); C3a modify +relationship; C4 m:n convenience; **H1 done** (ADR-0019), **H1a +done** (ADR-0042); H2 `hint`; H3 `help` (partial — general +reference + `help ` still missing); V4 session-log / +Markdown export; I1/I1b multi-line + readline; I3 tab completion / +I4 syntax highlighting (the walker already exposes the hooks); TU1 +tutorial (needs ADR); TT5 CI (not configured). + +## §6. Next job — pick one + +No single forced next step. Candidates, roughly by readiness: + +1. **H3 `help` completion** — the grammar tree already iterates the + REGISTRY for the command list; the missing pieces are a general + reference and `help ` per-command detail. The + `help_id` per `CommandNode` is the hook. Small-to-medium. +2. **I3 tab completion** — the walker's expected-set + completion + candidates already exist (used by ambient hints); I3 is the + **UI/UX** (cursor handling, menu, accept). Needs its own ADR. +3. **The deferred H1a residual** (§2) — generalise the projection + gloss to other expression positions. Low value (completion + already covers typing-time); only if it bugs you. +4. **CI (TT5)** — test infra is solid (2158 green); no workflow yet. + +## §7. How to take over + +1. Read handoffs 56 → 57 → 58, then `CLAUDE.md`, then + `docs/requirements.md` (H1 and **H1a now `[x]`**), + `docs/adr/README.md`. +2. **For anything parse-error/pedagogy: read ADR-0042, not + ADR-0020/0021** (those are superseded; chumsky is gone). +3. Codebase on `main` at `c305dc7`, clean, 4 unpushed. +4. Process pins that paid off this arc, again: **audit before + assuming** (ADR-0021 was obsolete; H1a was mostly already + shipped), **verify empirically — don't trust the docs/survey** + (the advanced-SQL gap list was wrong twice; a regression hid in + "looks fine"), **escalate genuine forks** (the G3 all-forms + decision was the user's, not mine), and **test-first + matrix as + a regression lock** (it caught a regression I introduced). + Commits user-confirmed, append-only, no AI attribution.