8.2 KiB
Session handoff — 2026-05-19 (18)
Eighteenth handover. A long implementation run that built two ADRs end to end:
- ADR-0026 (complex WHERE expressions) — steps 1–4 + 6; see handoff-17 for its detail.
- ADR-0027 (input-field validity indicator) — all six build-order steps, with ADR-0026's deferred step 5 (the §7 expression flagging) folded in as the WARNING severity's first triggers, exactly as the user directed.
Headline: the validity indicator works. A debounced
[ERR] / [WRN] marker at the input row's right edge tells a
learner — before they press Enter — whether the command would
run. S6 and C5a are both satisfied; nothing from ADRs
0026/0027 is left unimplemented.
State at handoff
Branch: main. Working tree clean. 11 commits since
handoff-16 (ac41938), all local — push asynchronously, not
blocking. handoff-17 (dfd3c51) is mid-chain; it documents
the ADR-0026 landing and is superseded by this file.
a326849 ADR-0027: existing-cases sweep + docs (step F)
9e10997 runtime: debounce the validity indicator (ADR-0027 step E)
1a9d950 ui: validity indicator rendering + warning theme colour (ADR-0027 step D)
73c7470 walker: expression WARNING diagnostics (ADR-0027 step C, folds ADR-0026 §7)
827b47f walker: schema-existence ERROR diagnostics (ADR-0027 step B)
e22f933 walker: diagnostics-severity model + input_verdict (ADR-0027 step A)
dfd3c51 chore: handoff 17 — ADR-0026 complex WHERE expressions implemented
a50c6cd WHERE expressions: matrix cells + predicate_tail grammar fix (ADR-0026 step 6)
f75f71b WHERE expressions: wire into update/delete/show data + SQL gen (ADR-0026 steps 3-4)
59e6a54 grammar: WHERE-expression fragment + Expr AST + build_expr (ADR-0026 step 2)
f0b2043 walker: add Subgrammar node + recursion-depth cap (ADR-0026 step 1)
Tests: 1099 passing, 0 failing, 1 ignored (cargo test — up from 1039 at handoff-16). The ignored test is the
long-standing ```ignore doc-test in
src/friendly/mod.rs. Typing-surface matrix: 161 cells.
Clippy: clean (cargo clippy --all-targets -- -D warnings, nursery group).
§1. ADR-0026 — recap (detail in handoff-17)
Complex WHERE expressions work end to end: update /
delete / show data take a full boolean expression
(AND/OR/NOT, the six comparisons, LIKE/IN/BETWEEN/
IS [NOT] NULL, parentheses); it compiles to parameterised
SQL; show data gained where and limit. The §3 builder
realization (option 1) and the as-built deviations are in
ADR-0026's "As-built notes". Step 5 (the §7 diagnostic
flagging) was deferred at handoff-17 and is now done — see
§2.
§2. ADR-0027 — the validity indicator
Six steps, one commit each (e22f933..a326849):
- A — diagnostics model.
Severity(Error/Warning, ordered) andDiagnostic { severity, span, message }inwalker::outcome; adiagnosticsfield onWalkResult.walker::input_verdict(source, schema)is the indicator's entry point — the highest severity across the parse outcome and the diagnostics, orNonefor clean / empty input. - B — schema-existence ERRORs.
MatchedKind::Identnow carries itsIdentSource. A post-walk pass over a structuralMatchflags an unknown table (Tablesident) or unknown column (Columnsident, scoped to the table in scope) as an ERROR — new behaviour: such names used to parse cleanly and fail only at execution. - C — expression WARNINGs (ADR-0026 §7 folded in). A
type-mismatched comparison, or
= NULL/!= NULL, in a WHERE expression yields a WARNING — computed post-walk from the builtCommand'sExpragainst the table's column types. The command still parses and runs (§7 permissive posture unchanged). - D — rendering.
[ERR]/[WRN]at the input row's right edge; new ambertheme.warning. The rightmost six columns are reserved unconditionally so the typed command never shifts when the indicator appears. - E — debounce. The runtime event loop time-boxes
recvwhile a recompute is owed: a keystroke hides the indicator and arms a 1 s window; once typing pauses that long the verdict is computed and shown.update()stays pure. - F — sweep + docs.
input_verdicttests confirm the schema check fires across the identifier-taking commands.
§3. Architectural delta (vs. handoff-17)
Diagnostics
walker::outcome::{Severity, Diagnostic};WalkResult::diagnostics: Vec<Diagnostic>(re-exported aswalker::{Severity, Diagnostic}).walker::input_verdict(source, schema) -> Option<Severity>— the indicator entry point.MatchedKind::Identgainedsource: IdentSource.- Diagnostics are computed post-walk in
walk()—schema_existence_diagnosticsover the matched path,expr_warningsover the builtExpr— not emitted incrementally (keeps them off the speculative-rollback paths). See ADR-0027 "As-built notes".
App / runtime / ui
App::input_indicator: Option<Severity>— the indicator's visible state;App::input_validity_verdict()— the pure verdict (simple mode only; advanced mode is raw SQL).runtime::runevent loop: atokio::time::timeout-based debounce (INDICATOR_DEBOUNCE, 1 s).ui::render_input_panelreserves a fixed six-column right strip and renders the[ERR]/[WRN]label.theme.warning— amber, light + dark.
Catalog
- New
diagnostic:section —unknown_table,unknown_column,type_mismatch,eq_null.
§4. Known follow-ups (none blocking)
- Diagnostic highlight / hint wiring. ADR-0027 §2 says
highlighting and the hint panel "read the individual
diagnostics". The indicator and the model ship; routing a
diagnostic's span into the per-byte highlight overlay, and
its message into the hint panel beyond the existing
parse-error path, is not yet done — the build order did
not enumerate it as a step. WARNING spans are currently
coarse (the whole WHERE clause) because the
ExprAST carries no source spans; precise per-literal spans would come with that wiring. Recorded in ADR-0027 "As-built notes". - Debounce timing is integration-level, not unit-tested
— it is async event-loop glue. The pure pieces
(
input_verdict,input_validity_verdict, the indicator rendering) are covered. - LIKE-on-a-numeric-column is not flagged —
LIKEis a text-pattern test and "mismatch" there is fuzzier; a future WARNING-model extension. Compare / Between / In type-mismatch and= NULLare flagged.
§5. What's next
- ADR-0028 — query plans (
explain). The last of the handoff-16 design trio, still unimplemented.show data … where(now real) is the filtered query whose plan flips between a full scan and an index search; the diagnostics model and theOutputLinespan-styling ADR-0028 describes are both now easier to reach. - The §4 follow-ups, if the user wants the diagnostic highlight/hint detail wired now rather than later.
Other open clusters are unchanged from handoff-16/17 §3
(snapshot/undo U-series; constraints C3 — CHECK can
reuse ADR-0026's expression grammar; 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
- Read this file, then handoff-17 (ADR-0026 detail), then handoff-16 (the design trio).
- Read
CLAUDE.md— working-style rules. - Read
docs/adr/0027-input-validity-indicator.md— especially its "As-built notes" (post-walk diagnostics, the pre-rendered message, thetimeoutdebounce, coarse spans, the deferred highlight/hint wiring). - Run
cargo test— 1099 passing, 0 failing, 1 ignored. - Run
cargo clippy --all-targets -- -D warnings— clean. - Pick the next work from §5 — ADR-0028 is the natural pick; prioritisation is a user decision, so ask.
Note on the typing-surface matrix
tests/typing_surface/ is 161 cells. The validity
indicator is not matrix-covered — the matrix harness
(assess) drives parse / hint / completion, not the
debounced indicator; input_verdict is covered directly by
walker unit tests instead. After any grammar/walker change
the matrix-snapshot discipline from handoff-17 still applies.