Files
rdbms-playground/docs/handoff/20260515-handoff-14.md
T
claude@clouddev1 41043d686b docs: record ADR-0024 completion, reconcile requirements.md + handoff-14
ADR-0024 audited as fully implemented. Amend the ADR with a "Phase F
minimal" implementation note (parser.rs retained as the router +
ParseError home) and update the README index line to match.

Reconcile docs/requirements.md against handoffs 10-14: refresh the
test baseline (449 -> 1006), mark U4 (replay) satisfied, correct the
A1 / H1a / H3 progress notes.

Amend handoff-14: §3 flagged items both resolved (ranker kept,
CommandNode.hint_mode removed); §4 rewritten as a concrete next-work
pointer at the reconciled requirements.md.
2026-05-15 23:03:18 +00:00

285 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Session handoff — 2026-05-15 (14)
Fourteenth handover. This session cleared the remaining
handoff-12 backlog: every §2.1 carry-forward and the §2.2
deferred items. Eight focused commits, each a deliberate
decision the user signed off on.
**Headline: the handoff-12 §2 catalogue is now empty of
actionable items, and ADR-0024 is confirmed fully
implemented.** The two items §3 originally flagged are both
resolved. The next session's work is the product roadmap in
`docs/requirements.md` (reconciled this session) — see §4.
## State at handoff
**Branch:** `main`. Working tree clean. `origin/main` is at
`42cf851` (handoff-13); local HEAD is **8 commits ahead** — this
session's work, unpushed (the user pushes asynchronously).
Commits since handoff-13:
```
50b7825 Remove dead parse.token.* catalog entries
bcc5ad2 Matrix: pin natural candidate ordering
f1ff597 Hint: pedagogical Form-A pointer at Form B's first value slot
911a537 Walker: node-attached HintMode via Node::Hinted
9bbb96e Walker: memoize DynamicSubgrammar resolution to bound the Box::leak
90e3f5d Insert grammar: Form C type-awareness via lookahead
f46606b Runtime: schema-aware replay parsing
03dd900 Help: consume CommandNode.help_id — REGISTRY-driven in-app help
```
**Tests:** **1006 passing, 0 failing, 1 ignored** (up from 989).
The ignored test is the long-standing `` ```ignore `` doc-test
in `src/friendly/mod.rs`.
**Clippy:** clean with `nursery` lints + `-D warnings`.
## §1. What shipped — handoff-12 backlog cleared
### Dead `parse.token.*` catalog entries removed (50b7825)
The 5 structural-class + 3 lex-error entries handoff-12 §2.1
listed as unreachable are gone (catalog YAML + `keys.rs`).
### Ranker / natural candidate ordering (bcc5ad2)
The user's actual ranker need — `to` before `table` so
`add column to table T` reads in order; keywords before schema
identifiers — **already worked** via declaration-order
preservation + keywords-first sectioning in
`candidates_at_cursor`. Nothing pinned it; 8 matrix tests in
`tests/typing_surface/candidate_ordering.rs` now do. See §3 for
the `Ranker` *type* itself.
### serial/shortid pedagogical Form-A hint (f1ff597)
handoff-12 §2.2: at the first value slot of `insert into T
values (…)` for a table with auto-generated columns, the hint
now appends "(`id` auto-generated — skipped here; list columns
explicitly … to set it)". `hint_resolution_at_input` derives
the skipped columns from the post-walk `WalkContext` (Form B =
no `user_listed_columns` + table has serial/shortid columns);
the note fires only at the first slot. New
`HintResolution::form_b_autogen_skipped`, catalog key
`hint.value_slot_autogen_skipped`.
### Node-attached HintMode (911a537)
handoff-12 §2.1: the hint resolver's signature-matching (does
the expected set contain all five literal forms? an
`Ident{NewName}`?) is replaced by a grammar-declared
annotation. New `Node::Hinted { mode, inner }` wrapper; the
walker records the mode in `WalkContext::pending_hint_mode` on
entry and clears it on **any successful match** (the cursor
moved past the slot — this also undoes the leak where a failed
`Hinted` branch of a `Choice` would strand a stale mode). The
resolver reads `pending_hint_mode` directly.
Mechanism note: handoff-12 sketched threading `HintMode` through
the `Expectation` enum. ADR-0024 §HintMode only says "nodes
carry `HintMode`, the walker propagates it" — mechanism-
agnostic. The `WalkContext::pending_hint_mode` route (mirroring
the existing `pending_value_type`) was chosen as lower-risk; the
user was told and did not object.
### DynamicSubgrammar memoization (9bbb96e)
handoff-12 §2.1's `Box::leak`-per-walk. The handoff's arena
sketch was unworkable (it needs a lifetime-generic `Node` — a
major refactor). Instead `resolve_dynamic` memoizes factory
output on the schema state the factory reads (keyed by factory
fn-pointer + ctx fields). Each distinct value-list shape leaks
**once** — total leak bounded by distinct (schema × form)
combinations, not keystroke count. `TableColumn` gained `Hash`.
### Form C type-awareness (90e3f5d)
handoff-12 §2.2. Form C (`insert into T (vals)`) shared the `(`
opener with Form A, so its values weren't typed. The
explicit-`Choice`-branch split is impossible (committed-choice
semantics commit after `(` matches), so a new
`Node::Lookahead(fn(&WalkContext, &str, usize) -> Node)`
variant peeks the source: a value-literal first token routes
the paren through the typed `column_value_list` (Form B
dispatch contract); an identifier or empty paren routes to a
Form A column-name list. Form C values are now type- and
count-checked at parse time. `insert into T (` cleanly shows
Form A column candidates instead of mixed Form-A/C suggestions.
### Schema-aware replay (f46606b)
handoff-12 §2.1: `run_replay` parsed schemalessly. It now
re-snapshots the schema per line (extracted `build_schema_cache`,
shared with the interactive path) and parses with
`parse_command_with_schema` — typed-slot rejections fire at
replay parse time, matching interactive. New integration test
`replay_rejects_typed_slot_violation_at_parse_time`.
### help_id consumption (03dd900)
handoff-12 §2.1: every `CommandNode` declared an unused
`help_id`. `note_help` now iterates the command `REGISTRY` and
translates each `help_id` — a new command appears in `help`
automatically. 20 per-command catalog entries + 3 framing
entries; `help.in_app_body` removed. `CommandNode.help_id` lost
its `#[allow(dead_code)]`.
## §2. Bug found this session
**`libyml` 0.0.5 scanner panic on long space runs in
double-quoted YAML scalars.** While authoring the help entries,
a space-aligned double-quoted catalog string
(`"quit — exit"`) panicked the YAML scanner with
"String join would overflow memory bounds". Block scalars
(`|-`) are unaffected — that's why the old block-scalar help
worked. Bisected and worked around: all per-command help
entries use `|-`. **If you author new catalog entries, avoid
long internal space runs in double-quoted (`"…"`) values — use
a block scalar or keep runs short.** A catalog comment in
`en-US.yaml` records this.
## §3. Flagged items — both now resolved
Both items this section originally flagged were ruled on by
the user after the main work:
**3.1 The `Ranker` type — KEEP.** `completion::Ranker` /
`candidates_at_cursor_with` have no production caller passing a
non-identity ranker (the candidate-ordering need is met by
declaration-order preservation). The user ruled: **keep it** —
it is intentional scaffolding for future frequency / content-
aware ranking (ADR-0024 §"out of scope" explicitly anticipates
this). No longer an open question.
**3.2 `CommandNode.hint_mode` — REMOVED.** The per-command
`hint_mode` field predated the node-attached HintMode work and
was read by nothing. Removed (field + 20 `None` initialisers)
in commit `6d2b929`.
## §4. What's next — the standing roadmap
**handoff-12 §2's backlog is cleared, and ADR-0024 is
confirmed fully implemented** (audited this session — Phases
AF done; Phase F shipped "minimal" with `parser.rs` retained
as the router, now recorded in an ADR-0024 implementation
note). There is no migration or carry-forward debt left.
**The next session's work is the product roadmap, tracked in
`docs/requirements.md`** — reconciled this session against
what handoffs 1014 actually built (test baseline refreshed to
1006; `U4` replay marked satisfied; `A1` / `H1a` / `H3`
progress notes corrected). `requirements.md` is now the
trustworthy "what's open" tracker — read it, not the
(coarser) `CLAUDE.md` "Things deliberately deferred" list.
Notable open clusters in `requirements.md` (prioritisation is
a **user product decision** — do not pick unilaterally):
- **Indexes** (`C3` partial) — `add index` / `drop index`,
then `EXPLAIN QUERY PLAN` rendering (`QA1`). Self-contained.
- **Complex WHERE expressions** (`C5a`, `[~]`) — AND/OR /
comparison / LIKE in UPDATE/DELETE/show-data filters. Needs
an ADR. The bridge from DSL toward real SQL.
- **SQL in advanced mode** (`Q1`/`Q4`, `[~]`) — `sqlparser-rs`
+ a defined subset. Needs an ADR.
- **Snapshot / undo** (`U1`/`U2`) — designed in ADR-0006, not
built. (`replay`, `U4`, is now done.)
- **m:n convenience** (`C4`), **modify relationship** (`C3a`,
`[~]`), **table rename** (`C1`).
- **Friendly error layer** (`H1`) — partial; full SQL→English
translation pending. **Syntax-help in parse errors**
(`H1a`) — piecemeal so far.
- **Session log + Markdown export** (`V4`, `[~]`),
**multi-line input** (`I1`), **readline shortcuts**
(`I1b`), **seeding** (`SD1`), **CI** (`TT5`),
**tutorial system** (`TU1`, `[~]`).
Two handoff-13 items the user already **accepted** (not work,
just recorded):
- **Partial entry words classify as `DefiniteErrorAt`**
(handoff-13 §3) — documented by the matrix test
`app_commands::partial_entry_word_classifies_as_definite_error_but_completes`.
- **Matrix scope** (handoff-13 §4) — cursor coverage is
"meaningful transitions" not every byte offset; assertion (5)
is parse-layer, not a live dispatch differential.
## §5. Architectural delta (vs. handoff-13)
### New `Node` variants
- `Node::Hinted { mode: HintMode, inner: &'static Node }` —
node-attached hint-mode annotation.
- `Node::Lookahead(fn(&WalkContext, &str, usize) -> Node)` —
source-aware dynamic subgrammar (Form A/C discrimination).
### New `WalkContext` field
- `pending_hint_mode: Option<HintMode>` — set on `Hinted`
entry, cleared on any match.
### Walker driver
- `walk_node` split into a wrapper (clears `pending_hint_mode`
on match) + `walk_node_inner` (the dispatch).
- `resolve_dynamic` + `DYNAMIC_CACHE` — memoized
`DynamicSubgrammar` resolution.
- `Node::Lookahead` arm — not memoized (source-dependent),
returns a small node.
### New API surface
- `input_render::classify_input_with_schema` (added handoff-13,
noted here for completeness).
- `HintResolution::form_b_autogen_skipped: Vec<String>`.
- `runtime::build_schema_cache` (extracted from
`refresh_schema_cache`).
### Catalog
- Removed: `parse.token.*` (×8), `help.in_app_body`.
- Added: `hint.value_slot_autogen_skipped`,
`parse.custom.insert_form_a_missing_values` (handoff-13),
`help.intro` / `help.dsl_section` / `help.types_reference`,
`help.{app,ddl,data}.*` (×20).
### Post-handoff cleanup (this section's work)
After the eight items above, three follow-ups landed:
- `CommandNode.hint_mode` field removed (commit `6d2b929`) —
see §3.2.
- ADR-0024 amended with a "Phase F minimal" implementation
note (`parser.rs` retained as the router); `docs/adr/README.md`
index line updated to match.
- `docs/requirements.md` reconciled — see §4.
## §6. How to take over
1. **Read this file, then handoff-13, then 12** for the chain.
2. **Read `CLAUDE.md`** — the working-style rules. This session
escalated every ambiguous fork (HintMode mechanism, the
`Box::leak` arena's true cost, the Form C restructure twice)
rather than deciding unilaterally.
3. **Read `docs/requirements.md`** — reconciled this session;
it is the authoritative "what's open" tracker (§4).
4. **Run `cargo test`** — 1006 passing, 0 failing, 1 ignored.
5. **Run `cargo clippy --all-targets -- -D warnings`** — clean.
6. **Pick the next work from §4 / `requirements.md`** — but
prioritisation is a user product decision; ask, don't
assume. handoff-12's backlog and ADR-0024 are both fully
done — there is no carry-forward debt.
### Note on the typing-surface matrix
`tests/typing_surface/` (now 144 cells) is the regression net
for everything walker/hint/completion. After any grammar or
walker change: a failing matrix cell with *correct* new
behaviour → update its snapshot
(`INSTA_UPDATE=always cargo test --test typing_surface_matrix
<family>`); a failing cell with *wrong* behaviour → the cell
earned its keep. The Form C type-awareness work this session
was guarded entirely by it.