Bug-report intake + triage + fix session — different shape from the recent feature-development handovers. Fourteen distinct observations triaged into GitHub issues; six resolved across three commits (c12ed1d,6f87ad1,24c2685). ADR-0033 gained Amendment 5 (`also_valid_sql` fires on validity, not just parse). Two enhancement trackers spawned from the /runda pass on the function-call validation work. Pins for the next session: - user preference: no issue numbers in commit messages - tests: 2040 / 0 / 1 (ignored), clippy clean - open ticket categorisation in §5 with a recommended pairing for the two enhancement trackers
15 KiB
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:
- Confirmed via
ghCLI that GitHub issue tracking is available onoliversturm/rdbms-playground(the project intends to migrate to Gitea eventually, butghworks for now). - Investigated each observation before filing — grounded every ticket body in concrete file:line references the explore agent surfaced or that direct grep confirmed.
- 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).
- Picked tickets in clusters of related code paths to amortise the exploration cost.
- 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 newdiagnostic.insert_arity_mismatch_form_bERROR 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_noteinsrc/input_render.rs): refactored from a hand-rolled count check to a singleinput_verdict_in_mode(input, schema, Mode::Advanced)call. The pointer fires only when the verdict isNone— 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_notecovers under-, in-window, and over-supply. - advanced-mode dispatch pre-flight:
insert.form_b_positional_count_mismatch_note.
- simple-mode submit:
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 onlywith—(for the SQL column-def list was missing. Root cause: the shared-entry-word completion merge incompletion_probe_in_modeonly fired at the entry-word boundary. Fix: broadened to fire at any cursor depth + handleExpectation::Punctcontinuations alongsideWord/Literal. - #4:
create table T (listed only the table-level constraint keywords (primary,unique,check,constraint,foreign) — the column-name role was invisible becauseCOLUMN_DEFstarts with anIdent::NewNameslot that produces no concrete candidate. Fix: added a newHintMode::IntroProse(&'static str)variant that surfaces catalog prose at slot entry without suppressing Tab completion (unlikeProseOnly) and without requiringtyping_name_at_cursorto fire (unlikeForceProse). WrappedELEMENTinNode::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 (countandcreate table T (countboth leaked the bare keyworddouble(the first token of the dedicateddouble precisionChoice branch per ADR-0035 §6.3) alongside the regular type list. Fix: added("double", "double precision")toCOMPOSITE_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:
- Walker (
schema_existence_diagnostics): the bare-column check onsql_expr_identitems now skips when the ident is immediately followed by(— it's a function-call name, not a column reference. New helperis_followed_by_call_argsmirrors the existingis_followed_by_qualified_refguard. Cascades to the[ERR]indicator, the red highlight overlay, and the diagnostic- driven ambient hint. - Typing-time (
invalid_ident_at_cursor_in_mode): early-return atsql_expr_identpositions. 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 andpick_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 | VALUES-list completion stops giving useful hints once the first value is a string literal | bug |
| 7 | Advanced mode: explain not yet supported |
enhancement |
| 8 | Advanced-mode syntax highlighting: identifiers and type keywords share the same teal color | bug |
| 9 | [ok] explain <Table> is terse; reconsider whether [ok] line duplicates the SQL-echo line above it |
bug |
| 10 | Output panel: [error] tag color identical to [system] — gap in ADR-0037 |
enhancement |
| 11 | Copy output panel contents to the system clipboard | enhancement |
| 12 | Long input hints overflow horizontally | bug |
| 13 | Undo confirmation dialog: too narrow and language polish | bug |
| 14 | --resume should restore the last-used input mode |
enhancement |
| 15 | Tab completion: offer common SQL function names in expression positions | enhancement |
| 16 | Restore typing-time column-typo hint for SQL expressions via known-function list | enhancement |
#15 and #16 were spawned from #6's /runda pass — both want a curated SQL-function list as a single source of truth; they should be tackled together.
Categorisation (for next session's triage)
- Spec-heavy (need discussion before code): #9 (
[ok] explainredundancy), #10 ([error]tag colour — needs ADR-0037 amendment), #14 (--resumerestore last mode — ties to ADR-0015 Iter 6). - Bounded code fixes: #2 (VALUES completion regression), #8
(identifier vs type colour), #13 (undo dialog), #7 (advanced
explain— feature gap, more substantial). - Substantial scope: #11 (clipboard copy — user named it ~80% bug-report-friction reduction), #12 (long hint overflow — design call: wrap vs cap vs resize).
- Function-list cluster: #15 + #16 (do together).
Other tracks (unchanged from handoff-49, still pending)
From requirements.md:
- Track 2 project storage Iter 5/6 — export/import +
--resume+ persistent input history + migration framework. - C3a (modify relationship), C4 (m:n convenience).
- H1 friendly DB-error layer (partial), H1a syntax-help in parse errors (this session added the INSERT Form B contributions).
- Tutorial / lesson system (needs its own ADR).
- V4 session log + Markdown export.
- I1 / I1b multi-line + readline shortcuts, I3 tab completion polish, I4 syntax highlighting beyond input echo.
- ADR-0039 "explain over advanced SQL" — design agreed, implementation deferred.
§6. Process pins (carried forward)
- Confirm every commit (propose message, wait). No AI attribution. No issue numbers in commit messages (this session's specific user preference — issue bodies and close comments may freely reference issue numbers).
- Test-first; green + clippy-clean is the only acceptable end state; current baseline 2040 / 0 / 1.
- Follow CLAUDE.md solo-mode phases explicitly — requirements extraction → divergent exploration → evaluation → execution → verification. Each phase produces written artifacts. /runda is the standard tool for the DA pass between/after phases on non-trivial work; in this session every closed issue went through at least one /runda round before committing.
- Round-trip every catalogue row (the ADR-0038 §1 contract; for multi-statement, per line) — unchanged from prior handovers.
- GitHub issue tracking is in use for now, migrating to Gitea
later.
ghCLI works.teaCLI is the future-state per CLAUDE.md's Gitea section.
§7. How to take over
- Read, in order: this file →
requirements.mdfor the open tracks →docs/adr/README.mdfor the ADR index → the relevant ADR for whatever feature/bug you pick up. - Baseline:
cargo test(2040 / 0 / 1) +cargo clippy --all-targets(clean). - For a bug fix from the open list: start with the issue body,
then probe the actual behaviour (the explore agent + targeted
panic!()probe-tests in the relevant module are the fast path — seesimple_mode_submit_of_form_b_extra_value_teaches_serial_skipinsrc/app.rsfor a clean template). Then failing test → fix → green → /runda → commit-with-approval → close-with-summary. - For a fresh feature: write the ADR (or extend an existing
one), run
/rundaover the design before building, then build test-first. - Pick the next ticket by checking §5's categorisation. If tackling #15 / #16, do them together — they share the known-function-list infrastructure.