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

9.0 KiB
Raw Permalink Blame History

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.
  • G4with got its own parse.usage.with CTE template (was borrowing select's).
  • CROSS JOIN ONparse.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.