Files
rdbms-playground/docs/handoff/20260519-handoff-18.md
T
claude@clouddev1 39b92a7558 docs: handoff 18 — record the post-ADR-0027 manual-testing pass
The multi-form usage-template fix (151ed08) and the reviewed
`add index` syntax decision (kept as-is), so the next agent
does not re-flag a settled question.
2026-05-19 08:45:45 +00:00

9.8 KiB
Raw Permalink Blame History

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 14 + 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. 12 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.

151ed08 hint: show the matching usage template for multi-form commands
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: 1100 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) and Diagnostic { severity, span, message } in walker::outcome; a diagnostics field on WalkResult. walker::input_verdict(source, schema) is the indicator's entry point — the highest severity across the parse outcome and the diagnostics, or None for clean / empty input.
  • B — schema-existence ERRORs. MatchedKind::Ident now carries its IdentSource. A post-walk pass over a structural Match flags an unknown table (Tables ident) or unknown column (Columns ident, 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 built Command's Expr against 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 amber theme.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 recv while 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_verdict tests confirm the schema check fires across the identifier-taking commands.

§2a. Post-ADR-0027 — a manual-testing pass

After ADR-0027 landed, a round of manual testing surfaced three things; all are resolved.

  • Bug, fixed (151ed08). A parse error in add index … showed the add column usage. add / drop are multi-form commands and both the ambient hint and the submit-time usage block picked the first form unconditionally. New grammar::usage_key_for_input disambiguates by the form word after the entry keyword; the hint shows the committed form, render_usage_block too (bare add / drop still shows the whole family).
  • add index syntax — reviewed, deliberately kept. The inconsistency is real: add column [to] [table] <T>: <col> (<type>) vs add index [as <name>] on <T> (<cols>). It was weighed and left as-isadd index … on <T> (<cols>) is intentionally SQL-idiomatic (CREATE INDEX … ON t (cols)), the colon shape was built for "one column with a type" and an index has neither. A future agent should not re-flag this as a bug; if the owner later wants the entity-command separators unified, that is a deliberate ADR-0025 amendment / design pass, not a drive-by fix.
  • No index parameters / no unique — by design. ADR-0025 scoped add index to plain non-unique indexes; there is no unique-index syntax and no constraint syntax at all (NOT NULL / UNIQUE / CHECK / DEFAULT are the pending C3). ADR-0018's unique handling only detects + displays an existing constraint — nothing creates one. Not a gap in the help; the help is accurate.

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

Diagnostics

  • walker::outcome::{Severity, Diagnostic}; WalkResult::diagnostics: Vec<Diagnostic> (re-exported as walker::{Severity, Diagnostic}).
  • walker::input_verdict(source, schema) -> Option<Severity> — the indicator entry point.
  • MatchedKind::Ident gained source: IdentSource.
  • Diagnostics are computed post-walk in walk()schema_existence_diagnostics over the matched path, expr_warnings over the built Expr — 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::run event loop: a tokio::time::timeout-based debounce (INDICATOR_DEBOUNCE, 1 s).
  • ui::render_input_panel reserves 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 Expr AST 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 — LIKE is a text-pattern test and "mismatch" there is fuzzier; a future WARNING-model extension. Compare / Between / In type-mismatch and = NULL are 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 the OutputLine span-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 C3CHECK 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

  1. Read this file, then handoff-17 (ADR-0026 detail), then handoff-16 (the design trio).
  2. Read CLAUDE.md — working-style rules.
  3. Read docs/adr/0027-input-validity-indicator.md — especially its "As-built notes" (post-walk diagnostics, the pre-rendered message, the timeout debounce, coarse spans, the deferred highlight/hint wiring).
  4. Run cargo test — 1100 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; 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.