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

12 KiB
Raw Permalink Blame History

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.