In advanced mode an entry word like `create`/`drop` has several candidate nodes (the SQL forms + the DSL fallback), but the walker commits to one, so completion offered only that node's continuations — `drop ` showed just `table`, and `drop rel` dead-ended at an empty list even though the DSL drops parse via fallback. At the entry-word boundary (advanced mode), walk every candidate, keep the viable (Incomplete) ones, and union their next-keyword continuations: `drop ` → table·index·column·relationship·constraint; `drop rel` → relationship; `create ` → table·unique·index. Deeper positions keep the committed walk untouched (no change to insert/update/delete/select). Each continuation is classified by producing category (Both/Advanced/ Simple) and block-ordered Both → Advanced → Simple, so they read as contiguous groups (the foundation for the 4i(e) colour, landing next). CompletionProbe carries a parallel expected_modes; the parse path is unchanged (the merge is completion-only). Tests: completion merge + partial + block-order cases; the two tests that encoded the old single-node behaviour updated. Full suite 1911 passing / 0 failing / 1 ignored; clippy clean.
8.1 KiB
Plan: ADR-0035 Phase 4, sub-phase 4i — verification sweep (completes Phase 4)
The closing sub-phase. Canonical scope: ADR-0035 §13 4i. Items:
- (a) Refresh the
CREATE TABLEhelp/usage skeleton for the 4a.2DEFAULT/CHECK/composite-UNIQUE, 4a.3 table-CHECK, and 4b FK forms (the only help/usage debt — 4d/4e/4f/4g/4h carry their own). - (b)
describedisplay of table-level constraints (compositeUNIQUE+ tableCHECK, incl. named CHECKs from 4g). - (c) 4b self-ref FK pre-submit indicator: stop false-flagging a
references <self>parent as unknown. - (d) shared-entry-word completion merge.
- (e) visually distinguish simple- vs advanced-mode completions.
- staples: typing-surface + matrix coverage, engine-neutral error pass, undo-parity (one step per statement).
User-chosen sequencing (2026-05-26): the (d)/(e) design conversation first, then build. (d)/(e) are designed (below); (a)/(b)/(c) + staples follow.
1. Baseline
- HEAD
ca64434; 1909 passing / 0 failing / 0 skipped / 1 ignored; clippy clean.
2. (d) + (e) — settled design (user-confirmed 2026-05-26)
(d) Shared-entry-word completion merge
Bug: in advanced mode the walker's decide() (walker/mod.rs)
commits one candidate node for a shared entry word, so only that
node's continuations reach completion — drop offers only table, and
drop rel returns empty, even though the DSL drops parse via fallback.
Fix: in completion_probe_in_mode, for an advanced-mode shared
entry word (the entry word resolves to >1 candidate), walk each
candidate node speculatively (the existing scratch/walk_one_command
machinery on a fresh context), extract each one's expected continuations
(the same WalkOutcome→expected match the single-walk path uses), and
union them. Simple mode is unchanged (its single DSL node already
offers all DSL continuations; SQL isn't offered). A candidate that
mismatches the current input contributes an empty set, so as the input
disambiguates (drop table …) the union naturally narrows to the
surviving candidate.
(e) Visual simple-vs-advanced distinction
Each merged continuation is classified by which categories produced
it — a new ModeClass:
Both— produced by ≥1Advancedand ≥1Simplecandidate (a continuation valid either way, e.g.drop table).Advanced— onlyAdvancedcandidates (SQL-only, e.g.create index).Simple— onlySimplecandidates (DSL-only, e.g.drop relationship).
Colour + order apply only when the candidate list is mixed (>1
distinct ModeClass) — the only place the signal is informative; a
single-mode list (deep inside any command) keeps today's token-kind
colours, no mode tint (avoids redundant noise duplicating the mode
indicator). When mixed:
- Colour:
Both→ today's token-kind colour (neutral);Advanced→theme.mode_advanced(orange);Simple→theme.mode_simple(cyan). These two mode colours already exist (used by the mode indicator). - Order (user refinement): group the continuations into contiguous
colour blocks in the order
Both→Advanced→Simple, soAdvancedsits between the other two and each colour reads as one block rather than interleaving.
3. Architecture & change list (d/e)
src/dsl/walker/outcome.rs(orCompletionProbe): add a parallelexpected_modes: Vec<ModeClass>(same length/order asexpected), defaulting to allBoth(so the single-walk path is neutral). NewModeClassenum (likely incompletion.rs, re-exported).src/dsl/walker/mod.rscompletion_probe_in_mode: factor the expected-extraction (lines 333-356) into a helper; add the advanced-mode multi-candidate branch that walks each candidate (modeAdvanced), classifies each expectation by the producing category, and fillsexpected+expected_modes.src/completion.rs:Candidategainsmode: ModeClass; the keyword-building (Expectation::Word) carries the parallelModeClassthrough prefix filtering; when the keyword set is mixed, block-order byModeClass(Both→Advanced→Simple) within the keyword group; non-keyword kinds and single-mode lists are allBoth.src/ui.rsrender_candidate_line(≈907): when the candidate list contains >1ModeClass, colour each by itsModeClass(Both=kind-colour, Advanced=mode_advanced, Simple=mode_simple); otherwise unchanged.- Tests:
tests/typing_surface/—drop(advanced) offerstable·index·column·relationship·constraint;drop rel→relationship;create→table(Both) +index(Advanced); block-order assertion (Both then Advanced then Simple); simple mode unchanged. Aui.rssnapshot for the mixed-mode coloured hint line.
4. (a)/(b)/(c) — outline (build after d/e)
- (a) Extend the
sql_create_tablehelp/usage strings (friendly/strings/en-US.yaml) forDEFAULT/CHECK/composite-UNIQUE(4a.2), table-CHECK(4a.3), and inline + table-levelFOREIGN KEY(4b). Catalog-lockstep + vocab-audit guard wording. - (b)
describe(do_describe_table/ the structure renderer): show table-level compositeUNIQUEand tableCHECKconstraints (named CHECKs show their name). Tier-2 snapshot + Tier-3 describe assertions. - (c) The pre-submit schema-existence diagnostic: treat a FK parent
equal to the in-statement
CREATE TABLEtarget as valid (self-ref), so the[ERR]/[WRN]indicator stops lying. Tier-1/typing-surface test.
5. Phase 2/3 — candidates & selection (d/e)
Settled via the design conversation (§2). The merge alternative
("modify decide/walk to merge in the core parser") was rejected —
it would change the shared parser used everywhere; doing the merge in the
completion-only completion_probe_in_mode is lower-risk. The colour
alternatives (always-by-mode; marker tag; defer) were presented to the
user, who chose mode-colour-when-mixed + block ordering.
6. Devil's Advocate review of this plan
- Forks escalated? The (e) visual treatment was put to the user with four options + previews; they chose option 1 with the block-ordering refinement. (d)'s behaviour is ADR/handoff-specified. ✓
- Core-parser risk? The merge lives in
completion_probe_in_mode(completion-only), notwalk/decide— the parse path is untouched, so no risk to execution/dispatch. ✓ - Simple mode unaffected? The merge branch is advanced-only; simple-mode completion keeps the single-DSL-node path. A test pins it. ✓
- Noise? Colour/order apply only when the list is genuinely mixed; single-mode lists are visually unchanged. ✓
- Perf? Completion walks each candidate per keystroke — candidates per entry word are few (≤ ~3), and completion is already a per-keystroke walk; negligible. ✓
- Ordering vs existing kind-order? Block-ordering applies within the keyword group (where shared-entry continuations live); the identifiers-first kind ordering is preserved. ✓
7. Implementation sequence (test-first)
- (d) merge —
ModeClass+expected_modes; the advanced-mode multi-candidate walk + union incompletion_probe_in_mode; thread throughcompletion.rs(functional merge, classes computed but not yet coloured). Typing-surface tests (merge + simple-mode-unchanged) → green. - (e) order + colour — block-ordering when mixed;
render_candidate_linecolours byModeClass. Ordering test + a UI snapshot → green. - (c) self-ref FK indicator → test-first.
- (b) describe table-level constraints → snapshot/e2e.
- (a) CREATE TABLE help/usage skeleton + catalog lockstep.
- Staples — typing-surface/matrix sweep, engine-neutral error pass, undo-parity spot-check.
- Full sweep + finished-slice
/runda→ commit proposal(s).
8. Exit gate
All §13 4i items done or explicitly deferred-with-user-confirmation; all
tiers green, zero skips; no regression from 1909; clippy clean; written-DA
/ /runda PASS; ADR-0035 §13 4i + README + requirements lockstep. 4i
completes ADR-0035 Phase 4 — flip the ADR Status from "4i pending".