Files
rdbms-playground/docs/handoff/20260519-handoff-19.md
T
claude@clouddev1 0e5f226e6b docs: handoff 19 — ADR-0027 highlight/hint wiring finished
ADR-0027 gains a "Follow-up" section recording the completed
§2 highlight + hint wiring and precise per-literal WARNING
spans; the three stale As-built bullets point at it.
requirements.md test baseline → 1125 and the S6 entry notes
the completion + Amendment 1. handoff-19 records the run and
queues the two deferred manual-testing bugs (add 1:n
relationship completion/usage hint; --resume / last_project)
as the next session's first work.
2026-05-19 09:48:19 +00:00

10 KiB

Session handoff — 2026-05-19 (19)

Nineteenth handover. A focused implementation run that finished ADR-0027: the §4 "known follow-ups" from handoff-18 are all done. ADR-0027's §2 always specified that "highlighting and the hint panel read the individual diagnostics" — handoff-18 shipped the indicator and the model but left that wiring as a follow-up. It is now wired.

Headline: the diagnostics are visible where they happen. An unknown table / column (ERROR) and a dubious comparison (WARNING — type mismatch, = NULL, and now LIKE on a numeric column) are overlaid on the input field globally and explained in the hint panel — not just summarised by the [ERR] / [WRN] indicator.

State at handoff

Branch: main. Working tree clean. 7 commits since handoff-18 (39b92a7), all local — push asynchronously, not blocking.

<this file>  docs: handoff 19 + ADR-0027 follow-up/amendment notes
c1c9f6c runtime: extract the indicator debounce into a tested state machine
400fb71 ui: surface diagnostics in the ambient hint panel (ADR-0027 §2)
bbfb70c ui: overlay diagnostic spans on the input field (ADR-0027 §2)
437b2f2 walker: flag LIKE on a numeric column (ADR-0027 Amendment 1)
3912fb5 walker: precise per-literal spans for expression WARNINGs
426e801 command: Operand carries a source span

Tests: 1125 passing, 0 failing, 1 ignored (cargo test — up from 1100 at handoff-18). The ignored test is the long-standing ```ignore doc-test in src/friendly/mod.rs. Typing-surface matrix: 161 cells, unchanged (one cell's input was corrected — see §3).

Clippy: clean (cargo clippy --all-targets -- -D warnings, nursery group).

§1. What this run did — the three §4 follow-ups

handoff-18 §4 listed three "known follow-ups (none blocking)". The user reviewed them, judged §4-item-1 to be unfinished ADR-0027 scope (the §2 Decision text, not an optional extra), and asked for all three — including the small ADR amendment item 3 needs. All three are done.

Item 1 — diagnostic highlight + hint wiring

§2 of ADR-0027: the indicator is the summary; highlighting and the hint panel carry the where and why. Built across four commits:

  • Operand carries a source span (426e801). Each WHERE-expression operand now records the byte range of the terminal it was built from. Operand's PartialEq is hand-written to ignore the span — it is editor metadata — so Command equality stays whitespace- and position-independent and the large Expr test corpus needed no assertion changes.
  • Precise per-literal WARNING spans (3912fb5). The old WARNING span was coarse — the whole WHERE clause. predicate_warnings now anchors each WARNING to exactly the offending literal operand; where_clause_span is gone.
  • Highlight overlay (bbfb70c). render_input_runs overlays the walker's schema-aware diagnostics: ERROR in the error colour, WARNING in theme.warning. New overlay_span covers a token's whole byte range (the older overlay_error hit only the run at a single byte). The overlay is global — every flagged token is coloured wherever it sits, not just under the cursor, which is exactly the gap §Context described. The pre-existing cursor-local invalid-identifier overlay is kept (it covers in-progress idents, which produce no diagnostics); the two are additive and idempotent.
  • Hint panel (400fb71). ambient_hint surfaces a diagnostic's message. walker::input_diagnostics is non-empty only for a command that structurally parses, so a non-empty result means "complete and submittable, but wrong" — checked early, ahead of slot hints and completions, so a flawed-but-parsing command no longer shows the misleading "Submit with Enter". The diagnostic under the cursor wins, else the most severe.

Item 2 — debounce test coverage (c1c9f6c)

The indicator debounce was two locals in the event loop with no unit coverage. The decision logic is now the IndicatorDebounce state machine in runtimenote_event / settle / is_armed / visible, 7 unit tests for the keystroke / settle cycle (including: a background event mid-typing must not cancel the owed recompute). No behaviour change; the tokio timer and terminal stay in the loop. A PTY-tier test of the actual timing remains the one integration-level gap (consistent with ADR-0008's four-tier strategy).

Item 3 — LIKE on a numeric column (437b2f2)

A genuinely new WARNING trigger, so it needed an ADR change: ADR-0027 Amendment 1. LIKE is a text-pattern match; against an int / real / decimal / serial column it runs but is almost never intended. New Type::is_numeric, catalog key diagnostic.like_numeric. Scope is deliberately numeric-only — bool and the text-/blob-backed types are not flagged; rationale is in the amendment. docs/adr/ README.md updated per the index-upkeep rule.

§2. ⚠️ Two manual-testing bugs — NOT fixed, queued next

Mid-run the user reported two bugs from manual testing and explicitly deferred the fixes. These are the top of the next session's queue. They are unrelated to ADR-0027.

  1. add 1:n relationship — missing completion + wrong usage hint. Typing add 1:n relationship from Artists.album_id to Albums.id -- does not offer --create-fk. Separately, the ambient hint at the end of add 1:n relationship from … to … shows the wrong usage block — add column … — because grammar::usage_key_for_input (commit 151ed08) disambiguates add column / add index but not the 1:n relationship form, so it falls back to the first add form. Same class of bug 151ed08 fixed; the fix is to teach usage_key_for_input the relationship form, plus wire the --create-fk flag completion. (The user confirmed the [ERR] shown for the non-existent column in that input is correct and welcome — that is this run's schema-existence diagnostic working. Do not touch it.)
  2. --resume points at an unpersisted temp project. An empty temp project is created on launch but, by design (ADR-0015), not persisted when it has no content — yet last_project still records its path, so a later --resume fails with a confusing "path does not exist". The user asked for: (a) last_project updated only once a path is truly persisted with content; (b) a friendly error when --resume finds no last_project at all.

Both are recorded as tasks (#7, #8 in this session's task list) with full repro detail.

§3. Architectural delta (vs. handoff-18)

Command AST

  • Operand is now a struct-variant enum — Column { name, span } / Literal { value, span } — carrying a byte span. PartialEq is hand-written to ignore span (see the type docs); Eq still derived. Operand::span() accessor; Operand::NO_SPAN for programmatically-built operands (RowFilter::eq).

Walker

  • walker::input_diagnostics(source, schema) -> Vec<Diagnostic> — the sibling of input_verdict; the shared entry point for the highlight overlay and the hint panel.
  • predicate_warnings emits per-literal spans; pair_type_mismatch returns (message, span); where_clause_span removed.
  • like_numeric_warning — the LIKE-on-numeric WARNING (Amendment 1). Predicate::Like is no longer a no-op arm.

ui / input_render

  • render_input_runs overlays diagnostics (overlay_span, new). ambient_hint has a diagnostic branch right after the Tab-cycle memo; pick_hint_diagnostic chooses cursor-local, else most-severe.

runtime

  • IndicatorDebounce state machine replaces the indicator_pending local; app.input_indicator mirrors its visible for the renderer.

Types / catalog

  • Type::is_numeric(). New catalog key diagnostic.like_numeric (+ friendly::keys registry entry).

§4. Docs touched

  • ADR-0027 — new "Follow-up" section (the §2 wiring completed) and "Amendment 1" (LIKE on a numeric column); the three stale "As-built notes" bullets updated to point at them.
  • docs/adr/README.md — ADR-0027 line notes Amendment 1.
  • docs/requirements.md — test baseline (→ 1125) and the S6 entry note the completed wiring + amendment.

§5. What's next

  1. The two §2 bugsadd 1:n relationship completion / usage hint, and --resume / last_project. The user deferred these explicitly; they are first in line.
  2. ADR-0028 — query plans (explain). Still the last unimplemented member of the handoff-16 design trio; Accepted, not started. show data … where is the filtered query whose plan flips between a full scan and an index search.

Other open clusters unchanged from handoff-16/17/18 (snapshot/undo U-series; constraints C3; C4 m:n; C3a; C1 table rename; H1; SD1; TT5 CI; V4; I1; TU1). Prioritisation is a user product decision — ask.

§6. How to take over

  1. Read this file, then handoff-18 (ADR-0026/0027 implementation), then handoff-17 / handoff-16 as needed.
  2. Read CLAUDE.md — working-style rules.
  3. Read docs/adr/0027-input-validity-indicator.md — especially the new "Follow-up" and "Amendment 1" sections.
  4. Run cargo test — 1125 passing, 0 failing, 1 ignored.
  5. Run cargo clippy --all-targets -- -D warnings — clean.
  6. Start with §5.1 — the two manual-testing bugs. They were deferred mid-run with the user's agreement; they are the committed next step, ahead of ADR-0028.

Note on the typing-surface matrix

tests/typing_surface/ is 161 cells, unchanged. One cell — where_expression::complex_and_or_expression_parses — used a column (t) that does not exist in its schema; the new schema-existence diagnostic correctly flagged it, which revealed the cell was not testing what it claimed. Its input was corrected to a real column and the snapshot regenerated. The matrix-snapshot discipline from handoff-17/18 still applies: a failing cell with correct new behaviour → update its snapshot; with wrong behaviour → the cell earned its keep.