Files
claude@clouddev1 a1e4932858 docs: handoff 19 update — both manual-testing bugs fixed
handoff-19 §2 now records the two bugs as fixed (was "queued
next"): the optional trailing-flag completion fix (f239ca5)
and the --resume temp-project pointer fix (3a40ae2). §5 drops
them from "what's next" — ADR-0028 is now the natural next
pick. State/§6 updated to 10 commits and 1131 tests;
requirements.md test baseline → 1131.
2026-05-19 10:28:48 +00:00

11 KiB

Session handoff — 2026-05-19 (19)

Nineteenth handover. A focused implementation run that finished ADR-0027 and then fixed two manual-testing bugs. 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. Two unrelated bugs the user found mid-run (§2) are also fixed.

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. 10 commits since handoff-18 (39b92a7), all local — push asynchronously, not blocking.

<this file>  docs: handoff 19 update — both manual-testing bugs fixed
3a40ae2 runtime: don't record an unmodified temp as the --resume target
f239ca5 walker: keep optional trailing flags completable after `--`
0e5f226 docs: handoff 19 — ADR-0027 highlight/hint wiring finished
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: 1131 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 — both fixed

Mid-run the user reported two bugs from manual testing and deferred the fixes; both are now done (commits f239ca5, 3a40ae2). They are unrelated to ADR-0027.

  1. add 1:n relationship — optional flag not completable after -- (f239ca5). Typing add 1:n relationship from X.a to Y.b -- to start --create-fk made completion go empty: the trailing -- turns the parse into a trailing-junk Mismatch, and the Mismatch arm of the completion expected-set resolution returned only [EndOfInput] — the skipped optional-flag expectations, carried in tail_expected, were dropped. completion_probe and expected_at_input now merge tail_expected into a Mismatch's expected set; the fix covers the whole optional-trailing-flag class (--create-fk, --cascade, --force-conversion / --dont-convert). This also resolved the "wrong usage hint" symptom: with --create-fk offered as a candidate the hint panel shows candidates, not the parse-error usage block. The audit (the user's requested scan) found usage_key_for_input correct for every multi-form command — add / drop / show, including the digit-led add 1:n relationship — so the "shows add column" symptom was not a code bug in the current tree; it is now regression-locked. (The [ERR] on the non-existent column is the schema-existence diagnostic working — left intact.)
  2. --resume recorded an unpersisted temp (3a40ae2). An empty temp is created on launch but auto-deleted on quit while still empty (ADR-0015); the unconditional startup write_last_project recorded its path anyway, so a later --resume resolved to a deleted directory. All three resume-pointer writes are now gated on !project.is_unmodified_temp() (startup, on-switch, and a new on-quit write — the quit write is where a launch-temp the user filled with content finally gets remembered). The "no previous project" friendly error the user asked for already existed (project.resume_no_previous) — verified, no change needed.

§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. ADR-0028 — query plans (explain). 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. The diagnostics model and the OutputLine span-styling ADR-0028 describes are both easier to reach now.
  2. The §2 bugs are done — nothing pending there.

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 — 1131 passing, 0 failing, 1 ignored.
  5. Run cargo clippy --all-targets -- -D warnings — clean.
  6. Pick the next work from §5 — ADR-0028 is the natural pick (the §2 manual-testing bugs are already fixed); prioritisation is a user decision, so ask.

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.