# Session handoff — 2026-05-18 (16)

Sixteenth handover. This session was a **design run**:
three interlocking ADRs were designed and committed —
**ADR-0026** (complex WHERE expressions), **ADR-0027**
(input-field validity indicator), **ADR-0028** (query
plans / `EXPLAIN QUERY PLAN`) — plus one small code fix
(the `with pk` column-spec syntax).

**Headline: nothing from the three ADRs is implemented
yet.** This was deliberate design-ahead, chosen by the
user. The next session's job is **implementation**, and
**ADR-0026 is the keystone** — start there (see §3).

## State at handoff

**Branch:** `main`. Working tree clean. Four commits since
handoff-15 (`f4eedf3`), all local — the user pushes
asynchronously, so do not treat them as blocking:

```
d9a98bb Grammar: with-pk column specs use name(type), matching add column
9aa7e2e docs: add ADR-0028 — query plans (EXPLAIN QUERY PLAN)
032a050 docs: add ADR-0027 — input-field validity indicator
6e42a11 docs: add ADR-0026 — complex WHERE expressions
```

**Tests:** **1039 passing, 0 failing, 1 ignored** (`cargo
test`) — unchanged from handoff-15's baseline. The `with
pk` fix is syntax-only, so the count did not move. The
ignored test is the long-standing `` ```ignore `` doc-test
in `src/friendly/mod.rs`. Typing-surface matrix: **152
cells** (two renamed, none added/removed).

**Clippy:** clean (`cargo clippy --all-targets -- -D
warnings`).

## §1. What shipped

### ADR-0026 — Complex WHERE expressions (`6e42a11`)

The `C5a` design. A **stratified, recursive expression
grammar** — `AND` / `OR` / `NOT`, comparisons (`= != <>
< <= > >=`), `LIKE`, `IS [NOT] NULL`, `IN`, `BETWEEN`,
parentheses — for `update` / `delete` / `show data`
filters. `show data` gains an optional `where` and an
optional `limit <n>` (a limit implies an implicit
primary-key `ORDER BY`).

Key decisions (settled with the user — do not
re-litigate):

- **In-grammar recursion (option B).** A new
  `Subgrammar(&'static Node)` `Node` variant lets the
  grammar reference a fragment (incl. itself); the
  expression grammar is stratified to avoid left
  recursion. *Not* the opaque-leaf / pass-through
  approach.
- **`MatchedPath` stays flat.** The expression fragment
  carries its own AST-fragment builder, invoked by the
  walker as it recurses — structured output "selectively",
  only where the grammar is recursive. A new recursive
  `Expr` AST.
- **SQL generation** is parameterised (`?`-bound,
  type-converted literals); no raw-text pass-through. The
  displayed SQL renders literals inline and `<>` for
  inequality.
- **Permissive type handling.** Type-mismatched
  comparisons and `= NULL` are *flagged* (highlight +
  hint), never block submission, and still run — this
  *relaxes* the current bind-time rejection.

### ADR-0027 — Input-field validity indicator (`032a050`)

A debounced `[ERR]` / `[WRN]` marker at the input row's
right edge, summarising — before submit — whether the
current command would run. Backed by a **walker
diagnostics-severity model**: ERROR = known to fail (parse
error, unknown table/column); WARNING = valid but likely
not intended (type mismatch, `= NULL`). Advisory only —
**never blocks submission**. ~1 s debounce; the marker
strip is reserved unconditionally (6 columns). Needs a new
`warning` theme colour. The WARNING severity has **no
triggers until ADR-0026 is implemented**.

### ADR-0028 — Query plans (`9aa7e2e`)

`QA1` + `QA2`. An `explain` prefix command over `show
data` / `update` / `delete` running `EXPLAIN QUERY PLAN`
(which never executes — so explaining a destructive
command is safe). Renders an annotated tree; engine
`detail` text verbatim; an annotation taxonomy (full scan
/ index search / covering index / PK lookup / **automatic
index** — the standout teaching moment / temp B-tree).
Introduces a **styled-output-line mechanism** — `OutputLine`
gains optional per-span styling, realising the per-span
theming ADR-0016 deferred (its OOS-3). The explained SQL
is shown above the tree as standard, copy-pasteable SQL.

### with-pk grammar fix (`d9a98bb`)

`create table … with pk` column specs changed from
`name:type` to `name(type)`, matching `add column`'s
`col(type)` — column-type syntax is now consistent across
the DSL. One grammar node (`COL_SPEC`: `:` → `( … )`);
`build_create_table` was unaffected (reads columns by
role). Swept the test suite, the friendly catalog's usage
templates, ADR-0009's example, and `requirements.md`. The
`:` separating table from column in `add column` /
`drop column` is unchanged.

### Docs

- New **`docs/simple-mode-limitations.md`** — a running
  list of what simple-mode DSL queries cannot express that
  advanced SQL can, seeded from ADR-0026 §10. It feeds the
  future `Q4` SQL-subset spec. Grow it as new boundaries
  surface.
- `requirements.md`: `C5a` `[~]` → `[ ]`; `QA1` / `QA2`
  updated and the stale QA1 note reconciled; new `S6` (the
  validity indicator) and a new **Documentation** section
  with `DOC1`.

## §2. Notes for the next agent

- This session produced **no implementation** of the three
  ADRs. Each ADR has an `## Implementation notes` section
  with a step-by-step build order — follow it.
- The three ADRs **interlock**. ADR-0026's `Subgrammar`
  node is reused by ADR-0028's `explain`. ADR-0027's
  "general mechanism, single current consumer" shape is
  echoed by ADR-0028's styled-output-line mechanism.
- **Loose end:** `CLAUDE.md`'s "Things deliberately
  deferred" list still says `QA1` "needs its own QA2
  rendering ADR" — that ADR (0028) now exists. Reconcile
  the CLAUDE.md list against ADRs 0026/0027/0028 when
  convenient (a small edit).
- The two follow-up ADRs the validity-indicator discussion
  spawned are *done* — ADR-0027 is the indicator ADR; the
  `with pk` fix is the other. No tracked follow-ups remain
  open from this session.

## §3. What's next — implement ADR-0026 first

The three ADRs must be **implemented**. Recommended order:

1. **ADR-0026 (C5a) — the keystone.** Its build order:
   (1) the `Subgrammar` node; (2) the expression grammar
   fragment + `Expr` AST + the fragment-builder; (3) wire
   into `update` / `delete` / `show data`; (4) `Expr` →
   parameterised SQL + implicit PK `ORDER BY` for `limit`;
   (5) schema-aware type-mismatch / `= NULL` flagging in
   the walker; (6) typing-surface matrix cells.
2. **ADR-0027** and **ADR-0028** — in either order after
   0026. ADR-0027's WARNING severity and ADR-0028's
   index-flipping plan payoff both depend on 0026's
   `show data … where`.

Other open clusters (unchanged from handoff-15 §4):

- **Snapshot / undo** (`U1`/`U2`) — designed in ADR-0006,
  not built.
- **Constraints** (`C3` — `NOT NULL` / `UNIQUE` / `CHECK`
  / `DEFAULT`). `CHECK` can now reuse ADR-0026's
  expression grammar — the ordering problem that paused
  the constraints discussion this session is resolved.
- **m:n convenience** (`C4`), **modify relationship**
  (`C3a`), **table rename** (`C1`).
- **Friendly error layer** (`H1`), **seeding** (`SD1`),
  **CI** (`TT5`), **session log + Markdown export**
  (`V4`), **multi-line input** (`I1`), **tutorials**
  (`TU1`).

Prioritisation is a user product decision — ask.

## §4. How to take over

1. **Read this file, then handoff-15** for the chain.
2. **Read `CLAUDE.md`** — the working-style rules. This
   session escalated every design fork to the user before
   drafting each ADR.
3. **Read the three new ADRs — `0026`, `0027`, `0028`** —
   including each one's `## Implementation notes`. Then
   `docs/simple-mode-limitations.md`.
4. **Read `docs/requirements.md`** — reconciled this
   session.
5. **Run `cargo test`** — 1039 passing, 0 failing, 1
   ignored.
6. **Run `cargo clippy --all-targets -- -D warnings`** —
   clean.
7. **Start implementing ADR-0026** (§3). The three ADRs
   are design-complete; the forks are settled in the ADR
   text — build to them, don't re-open them.
