Files
rdbms-playground/docs/handoff/20260606-handoff-58.md
T

186 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 G2G4 + 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 <command>` 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 <command>` 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.