# Session handoff — 2026-05-28 (50) Fiftieth handover. **A bug-report triage + fix session** — different shape from the recent feature-development handovers. The user surfaced fourteen distinct issues from a single session of using the app; the session triaged all of them into GitHub issues, then resolved six clusters. Three commits, three closed issues (six original tickets folded into them), two enhancement trackers spawned for follow-up work outside bug-fix scope. **ADR-0033 gained Amendment 5.** ## §1. State at handoff **Branch:** `main`. **HEAD `24c2685`.** **Tests: 2040 passing, 0 failing, 0 unexpected skips, 1 pre-existing ignored** (the same ignored doctest as previous baselines). **Clippy: clean.** Commits since handoff-49's `9468324`: ``` 24c2685 fix: SQL function-call names not flagged as columns 6f87ad1 fix: advanced CREATE TABLE completion cluster c12ed1d fix: INSERT Form B value-count UX (ADR-0033 Amendment 5) ``` Test count moved 2020 → 2040 (+20 across all three commits). ## §2. The shape of this session This session was a **bug-report intake + triage + fix** loop. The user dumped a list of fourteen distinct observations from a session of actually using the app. The session: 1. Confirmed via `gh` CLI that GitHub issue tracking is available on `oliversturm/rdbms-playground` (the project intends to migrate to Gitea eventually, but `gh` works for now). 2. **Investigated each observation** before filing — grounded every ticket body in concrete file:line references the explore agent surfaced or that direct grep confirmed. 3. **Filed all fourteen as GitHub issues** with sensible grouping: - Some bundled (undo dialog width + undo dialog wording → one ticket). - Some split (the three CREATE TABLE completion bugs → three separate tickets because each closes cleanly on its own). - Some recategorised (the `[error]` vs `[system]` tag colour was on the fence between "documented design" and "real defect"; filed as enhancement after user clarification). 4. **Picked tickets in clusters of related code paths** to amortise the exploration cost. 5. **Followed CLAUDE.md solo-mode discipline** at each step: requirements check → failing test first → implement → green + clippy → DA pass (often via `/runda`) → commit-with-approval → close-with-summary → enhancement spinoffs for adjacent ideas. ### User-preferred commit-message style — pinned The user explicitly **does not want issue numbers in commit messages** (the project will migrate trackers; numbers won't point at anything later). Issue numbers in **issue bodies and close-comments** are fine (those migrate with the tracker). Cross-referencing issues inside the tracker is encouraged. ## §3. Closed issues ### #1 — INSERT Form B value-count UX (commit `c12ed1d`) The user's original bug case: `insert into Customers values('Oli', 52, 3)` against a 4-column table (`id serial PK, Name text, Age int, SerNo serial`) failed in simple mode AND in advanced mode, and the cross-mode pointer ("valid as SQL in advanced mode") fired misleadingly. Three layered fixes plus **ADR-0033 Amendment 5**: - **Walker diagnostic** (`dml_insert_arity_diagnostics`): the function's own doc-comment recorded the Form B (no-column-list) branch as "deferred". This commit closed that gap — Form B mismatches now emit a new `diagnostic.insert_arity_mismatch_form_b` ERROR per offending tuple, keyed off the schema cache's column count. The `[ERR]` validity indicator (ADR-0027) now lights up at typing time for the user's reported scenario. - **Cross-mode pointer gate** (`advanced_alternative_note` in `src/input_render.rs`): refactored from a hand-rolled count check to a single `input_verdict_in_mode(input, schema, Mode::Advanced)` call. The pointer fires only when the verdict is `None` — the ADR-0027 sense of "valid". Any future static check added to the verdict pipeline participates automatically. - **Teaching notes** for the submit path: - simple-mode submit: `insert.form_b_extra_values_note` covers under-, in-window, and over-supply. - advanced-mode dispatch pre-flight: `insert.form_b_positional_count_mismatch_note`. The `advanced_mode.also_valid_sql` pointer was reworded to *"trying to write SQL? switch with `mode advanced`, or prefix `:` to run once"* (one insta snapshot regenerated). **ADR-0033 Amendment 5** records the gate semantics with an explicit definition of "valid". `docs/requirements.md` H1a cites the three new pedagogical strings. The /runda round on this issue surfaced and fixed a sub-issue: my initial gate was Form-B-specific, but the user pointed out that validity-verdict-driven is the principled answer. That led to the walker diagnostic (so the verdict picks up the mismatch) + the broader gate refactor. ### #3 + #4 + #5 — Advanced CREATE TABLE completion cluster (commit `6f87ad1`) Three bugs in the same advanced-mode grammar + walker path: - **#3:** `create table T ` (trailing space, advanced) offered only `with` — `(` for the SQL column-def list was missing. Root cause: the shared-entry-word completion merge in `completion_probe_in_mode` only fired at the entry-word boundary. Fix: broadened to fire at any cursor depth + handle `Expectation::Punct` continuations alongside `Word`/`Literal`. - **#4:** `create table T (` listed only the table-level constraint keywords (`primary`, `unique`, `check`, `constraint`, `foreign`) — the column-name role was invisible because `COLUMN_DEF` starts with an `Ident::NewName` slot that produces no concrete candidate. Fix: added a new **`HintMode::IntroProse(&'static str)`** variant that surfaces catalog prose at slot entry without suppressing Tab completion (unlike `ProseOnly`) and without requiring `typing_name_at_cursor` to fire (unlike `ForceProse`). Wrapped `ELEMENT` in `Node::Hinted { mode: IntroProse( "hint.create_table_element"), … }`. The prose reads *"Type a column name, or a table-level constraint: `primary`, `unique`, `check`, `constraint`, `foreign`"*. - **#5:** `create table T (count` and `create table T (count ` both leaked the bare keyword `double` (the first token of the dedicated `double precision` Choice branch per ADR-0035 §6.3) alongside the regular type list. Fix: added `("double", "double precision")` to `COMPOSITE_CANDIDATES` + extended the keyword filter to drop composite openers. The partial-typing prose case is subsumed by #4's IntroProse (user reads "Type a column name…" while mid-typing, then advances to the clean type list). **Worth flagging for future readers:** the new `HintMode::IntroProse` variant is an additive extension to the ADR-0024 HintMode-per-node model. No behaviour change to existing modes. **No ADR amendment written** — the variant is currently used at one slot and the extension is straightforward. If a second use case lands, an ADR-0024 amendment recording the variant alongside `ProseOnly` / `ForceProse` would be the right move. ### #6 — SQL function-call names not flagged as columns (commit `24c2685`) `select sum(Age) from Customers` runs cleanly at the engine but the validator was treating `sum` as a column reference and flagging "no such column `sum` on table `Customers`". Two layered fixes for the same bug class: 1. **Walker** (`schema_existence_diagnostics`): the bare-column check on `sql_expr_ident` items now skips when the ident is immediately followed by `(` — it's a function-call name, not a column reference. New helper `is_followed_by_call_args` mirrors the existing `is_followed_by_qualified_ref` guard. Cascades to the `[ERR]` indicator, the red highlight overlay, and the diagnostic- driven ambient hint. 2. **Typing-time** (`invalid_ident_at_cursor_in_mode`): early-return at `sql_expr_ident` positions. The partial could resolve to either a column reference or a function-call name; without lookahead for a trailing `(` we can't tell. Submit-time still catches genuine column typos via the schema-existence diagnostic and `pick_hint_diagnostic`. The scope question in the original ticket body (which aggregate set to enumerate?) turned out to be moot — the fix is **all function calls**, matching ADR-0031 §1's stated posture (*"the grammar admits the call shape structurally; it does not know which names are aggregates"*). No grammar change; no ADR amendment. **Trade-off worth knowing:** typing `select Agx` (no FROM yet) is now silent until FROM is added; previously the typing-time path flagged it as "No such column". This makes typing-time **consistent** with submit-time — the schema-existence pass already silently skipped no-FROM expressions ("no FROM in scope — engine catches"). For any expression-with-scope (SELECT with FROM, WHERE, etc.) the diagnostic-driven hint still fires for column typos. Pinned by the test `genuine_column_typo_in_complete_select_still_hints_via_diagnostic`. Two **enhancement trackers spawned** from the /runda DA pass on this issue — see §5 below. ## §4. ADR work **ADR-0033 Amendment 5** (2026-05-28, in `c12ed1d`): `advanced_mode.also_valid_sql` (Amendment 3's cross-mode pointer) fires on **validity**, not just **parse** — *"valid"* meaning `input_verdict_in_mode(input, schema, Mode::Advanced) == None` in the ADR-0027 sense. The amendment text spells out the exact condition so future readers can't drift back to a syntactic-only reading. Index entry in `docs/adr/README.md` updated. The user explicitly asked for the precise definition to be inlined, and agreed with the term **"valid"** (over "clean", "fully valid", etc.) because it ties cleanly to ADR-0027's existing vocabulary. No other ADRs touched. ADR-0024's `HintMode` got a new variant (`IntroProse`) without an amendment — flagged in §3 above for the next session to consider if a second use case lands. `docs/requirements.md` H1a (strong syntax-help in parse errors) got a citation line listing the three new pedagogical strings (`insert.form_b_extra_values_note`, `insert.form_b_positional_count_mismatch_note`, `diagnostic.insert_arity_mismatch_form_b`) as concrete contributions. ## §5. What's open ### Bug reports filed this session, still open | # | Title | Label | |---|---|---| | [2](https://github.com/oliversturm/rdbms-playground/issues/2) | VALUES-list completion stops giving useful hints once the first value is a string literal | bug | | [7](https://github.com/oliversturm/rdbms-playground/issues/7) | Advanced mode: `explain` not yet supported | enhancement | | [8](https://github.com/oliversturm/rdbms-playground/issues/8) | Advanced-mode syntax highlighting: identifiers and type keywords share the same teal color | bug | | [9](https://github.com/oliversturm/rdbms-playground/issues/9) | `[ok] explain