Merge branch 'main' into website
This commit is contained in:
@@ -8,9 +8,8 @@ to end across three phases + a restyle).
|
||||
|
||||
## §1. State at handoff
|
||||
|
||||
**Branch:** `main`. **HEAD `2d0f4b2`** plus an **uncommitted docs
|
||||
finalization** (ADR-0047 status → implemented, README index, this
|
||||
handoff — see §6). Push is the user's step.
|
||||
**Branch:** `main`. **HEAD `f0afec3`** — all work committed, nothing
|
||||
pending. Unpushed (push is the user's step; normal working state).
|
||||
|
||||
**Tests: 2290 passing / 0 failing / 0 skipped / 1 ignored** (the 1
|
||||
ignored is the long-standing `friendly` doctest). **Clippy clean**
|
||||
@@ -18,6 +17,7 @@ ignored is the long-standing `friendly` doctest). **Clippy clean**
|
||||
|
||||
**This session's commits:**
|
||||
```
|
||||
f0afec3 docs: session handoff 64 + ADR-0047 implemented (#22/#24)
|
||||
2d0f4b2 feat(ui): flat filled rectangles for demo overlays (#22, ADR-0047 D4)
|
||||
241f60c feat(ui): demo-mode step-caption stealth buffer (#22, ADR-0047 D3/D4)
|
||||
2584e76 feat(ui): demo-mode keystroke badges (#22, ADR-0047 D2/D4/D5)
|
||||
@@ -26,8 +26,9 @@ e9eb1b1 docs: ADR-0047 — demonstration overlay layer for casts/teaching (#22)
|
||||
638b4c9 feat(app): vi-style j/k/g/G navigation in the load picker (#24)
|
||||
```
|
||||
|
||||
**Issues closed:** **#24** (vi nav) and **#22** (demo overlays) — close
|
||||
#22 once the docs finalization commit lands.
|
||||
**Issues closed:** both **#24** (vi nav) and **#22** (demo overlays) are
|
||||
**closed on Gitea** with closing comments — verified via the filtered
|
||||
issue list. Nothing left open from this session's scope.
|
||||
|
||||
## §2. #24 — vi-style load-picker navigation (commit `638b4c9`)
|
||||
|
||||
@@ -107,13 +108,15 @@ existing `IndicatorDebounce` already takes. A future Tier-4 PTY harness
|
||||
|
||||
## §6. How to take over
|
||||
|
||||
**Nothing is pending from this session** — both issues are closed, all
|
||||
docs landed (`f0afec3`), tree is green. The next session **returns to the
|
||||
open requirements backlog** (§7). Suggested start: run `/whatsnext`
|
||||
(it reads this handoff), or pick from §7 below.
|
||||
|
||||
1. Read handoffs 62 → 63 → 64, `CLAUDE.md`, `docs/requirements.md`,
|
||||
`docs/adr/README.md`, and **ADR-0047** (fully landed).
|
||||
2. **Pending:** the docs finalization commit (ADR-0047 status →
|
||||
implemented; README index; this handoff). Commit as
|
||||
`docs: session handoff 64 + ADR-0047 implemented (#22/#24)` (the user
|
||||
confirms commit messages). Then close **#22** on Gitea.
|
||||
3. **For demo-overlay work:** `App` has `demo_mode`, `demo_badge`,
|
||||
`docs/adr/README.md`. ADR-0047 is fully landed; revisit only for
|
||||
demo-overlay follow-ups.
|
||||
2. **For demo-overlay work:** `App` has `demo_mode`, `demo_badge`,
|
||||
`demo_badge_seq`, `demo_caption`, `demo_caption_capturing`,
|
||||
`demo_caption_buffer`, `last_output_area`. Rendering:
|
||||
`render_demo_overlays` / `render_badge_box` / `render_caption_box` /
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
# Session handoff — 2026-06-11 (65)
|
||||
|
||||
Sixty-fifth handover. Continues from handoff-64 (ADR-0047 demo
|
||||
overlays). This session designed and shipped **ADR-0048 — the `seed`
|
||||
fake-data generation command (SD1)**, Phase 1, end to end: an ADR with
|
||||
an extended fork dialogue + two `/runda` passes, then a phased
|
||||
test-first build.
|
||||
|
||||
## §1. State at handoff
|
||||
|
||||
**Branch:** `main`. **HEAD will be the doc-wrap-up commit** (see §6) —
|
||||
all seed work committed, nothing pending. Unpushed (push is the user's
|
||||
step; normal working state).
|
||||
|
||||
**Tests: 2358 passing / 0 failing / 0 skipped / 1 ignored** (the long
|
||||
-standing `friendly` doctest). **Clippy clean** (nursery, all targets).
|
||||
+68 over handoff-64's 2290.
|
||||
|
||||
**`cargo sweep` run** at wrap-up: `target/` 1.6 G → 183 M.
|
||||
|
||||
**This session's commits:**
|
||||
```
|
||||
202e25a feat(seed): fake-data generation library + fake dependency (P1.1)
|
||||
f1e9484 feat(seed): command plumbing + walking skeleton (P1.2)
|
||||
73493fa feat(seed): FK sampling, empty-parent error, block guard (P1.3a)
|
||||
9c13501 feat(seed): uniqueness, junction distinct-combos, IN-CHECK (P1.3b)
|
||||
0b3ab3c feat(seed): SeedResult outcome, capped preview, advisory, count cap (P1.3c)
|
||||
e6ff63d perf(seed): single-transaction multi-row insert path (P1.3d)
|
||||
fbd219b feat(seed): --seed flag, ambient wiring, and /runda hardening (P1.4 + DA)
|
||||
```
|
||||
(plus the earlier `4d0ae77` multi-tab-scope withdrawal and `0af7f56`
|
||||
ADR-0048 doc, and the wrap-up doc commit.)
|
||||
|
||||
## §2. What `seed` does (Phase 1 — read ADR-0048)
|
||||
|
||||
`seed <table> [count] [--seed <n>]` — populate a table with realistic
|
||||
fake data. **Available in both modes** (A1).
|
||||
|
||||
- **Realistic, name-aware generation:** the **`fake` crate** (v5,
|
||||
English) driven by a **type-gated heuristic catalogue** (`src/seed/
|
||||
heuristics.rs`) — `email`→email, `first_name`→first name, `price`→
|
||||
currency, etc., each only firing when the column *type* is
|
||||
compatible. **Table-context** disambiguates `name`/`title`
|
||||
(`products.name`→a hand-rolled **product** name, `users.name`→person,
|
||||
`vendors.name`→company). **Bounded dates** (`dob`/`created_at`/
|
||||
`date`/`timestamp` → recent windows, never "all of history", anchored
|
||||
to a fixed reference epoch for reproducibility). Type-based fallback
|
||||
otherwise.
|
||||
- **Uniqueness (D10):** the user-fillable PK, compound UNIQUE
|
||||
constraints, single-column UNIQUE, and identifier-named columns
|
||||
(`id`/`code`/…) stay distinct across the batch and vs existing rows;
|
||||
**junction tables** get **distinct FK combinations** (capped at the
|
||||
available product, reported). Identifier ints get a monotonic
|
||||
sequence.
|
||||
- **FK (D14):** every FK column samples an existing parent row (compound
|
||||
FK reads one consistent parent row); **empty parent → friendly
|
||||
error**.
|
||||
- **`IN`-CHECK (D17):** a simple `col IN ('a','b')` CHECK becomes the
|
||||
value source (enum-as-CHECK just works); complex CHECKs are flagged in
|
||||
the advisory and best-effort generated (a violation rolls the batch
|
||||
back).
|
||||
- **Reproducibility (D4):** `--seed <n>` → identical data on the same DB
|
||||
state. **Holds with no exceptions** — serial (rowid/MAX+1), FK
|
||||
(`ORDER BY`), **shortid (seeded RNG)**, all generators.
|
||||
- **Output:** the seeded-row count, a **capped preview** (first 20
|
||||
rows), and a **Hint-styled advisory** naming enum-ish / underivable-
|
||||
CHECK columns filled generically. Count cap 10 000; `seed t 0` no-op.
|
||||
- **Safety:** one **undo** step (snapshot wraps the whole seed);
|
||||
**replay** re-runs it as a data write; the insert path is a single
|
||||
transaction (O(N), atomic, commit-db-last preserved).
|
||||
|
||||
## §3. Where the code lives
|
||||
|
||||
- **`src/seed/`** — the pure generation library (no DB): `mod.rs`
|
||||
(`ColumnSpec`, `Generator`, `SeedRng`, `make_rng`), `heuristics.rs`
|
||||
(`choose_generator` + the catalogue + `is_enum_ish`), `generators.rs`
|
||||
(`generate_value` + the `product` generator + bounded dates),
|
||||
`check.rs` (`parse_in_check_values`). ~40 Tier-1 tests, deterministic.
|
||||
- **`src/db.rs`** — `do_seed` (+ `SeedColPlan`, `sample_parent_key_
|
||||
tuples`, `seed_value_list_key`, `seed_max_int`, `SeedResult`,
|
||||
`DEFAULT_SEED_COUNT`/`MAX_SEED_COUNT`/`SEED_PREVIEW_CAP`), the new
|
||||
**`insert_one_row`** core extracted from `do_insert` (shared, no
|
||||
tx/persist — so seed runs N rows in one tx), and the `Request::Seed` /
|
||||
`Database::seed` / worker wiring.
|
||||
- **`src/dsl/grammar/data.rs`** — `SEED` `CommandNode`, `build_seed`,
|
||||
the `--seed` flag grammar (`Seq[Flag("seed"), NumberLit]`, the first
|
||||
DSL flag with a value). `Command::Seed` in `command.rs`.
|
||||
- **Runtime/render** — `CommandOutcome::Seed`, `AppEvent::
|
||||
DslSeedSucceeded`, `App::handle_dsl_seed_success`. Catalog keys
|
||||
`ok.rows_seeded` / `seed.capped` / `seed.advisory_generic` /
|
||||
`help.data.seed` / `parse.usage.seed`.
|
||||
- **Tests** — `tests/it/seed.rs` (25 integration tests),
|
||||
`tests/typing_surface/mod.rs` (`seed_completion_and_validity`),
|
||||
`tests/it/parse_error_pedagogy.rs` (bare-`seed` near-miss row),
|
||||
`src/app.rs` (two render tests), `src/dsl/shortid.rs`
|
||||
(`generate_with_rng`).
|
||||
|
||||
## §4. Process notes (the two `/runda` passes)
|
||||
|
||||
- **Pre-build `/runda`** (on the ADR) found six blockers — undo
|
||||
integration (D15), replay semantics (D16), `set`-value quoting (D2),
|
||||
CHECK handling (D17), an advisory phase-ordering bug (D13), auto-show
|
||||
flooding (D18) — all folded into ADR-0048 before any code; the three
|
||||
genuine forks re-escalated and user-resolved.
|
||||
- **Post-implementation `/runda`** (on the whole implementation) found
|
||||
**eight gaps**, all closed: FK-sampling determinism (→ `ORDER BY`),
|
||||
**shortid not reproducible** (→ seeded RNG, fixed not documented — the
|
||||
user chose the fix), and six **untested ADR decisions** (D5 advanced
|
||||
mode, D15 undo, D16 replay, D17 complex-CHECK advisory, atomic
|
||||
rollback, zero-count) — tests added for each.
|
||||
|
||||
## §5. Phase 2 (deferred — designed in ADR-0048, NOT built)
|
||||
|
||||
These are the only seed pieces left; both have full designs in
|
||||
ADR-0048:
|
||||
|
||||
1. **The `set` override clause (D2)** — `seed t 20 set role in
|
||||
('a','b'), status = 'x', work_addr as email, price between 10 and
|
||||
100`. Value / pick-from-list / explicit-generator / range, **quoted
|
||||
literals** (grammar-consistent). This is the SD2 "override hooks"
|
||||
core. The `ColumnSpec.check_in_values` → `PickFrom` plumbing and the
|
||||
`Generator` vocabulary already exist; this adds the grammar + a `set`
|
||||
clause that overrides the per-column plan.
|
||||
2. **Column-fill (`seed <table>.<column>`, D1 form 2)** — fill one
|
||||
column across *existing* rows (an UPDATE). Refuses PK/autogen targets;
|
||||
empty-table no-op.
|
||||
|
||||
`requirements.md`: **SD1 `[x]`**, **SD2 `[/]`** (core done; the two
|
||||
above open), **A1 14/15** (only `hint`/**H2** unregistered).
|
||||
|
||||
## §6. How to take over
|
||||
|
||||
1. Read handoffs 63 → 64 → 65, `CLAUDE.md`, `docs/requirements.md`,
|
||||
`docs/adr/0048-seed-fake-data-generation.md` (the whole thing — D1
|
||||
–D18 + the as-built status block).
|
||||
2. **Seed is feature-complete for Phase 1; nothing pending.** Next
|
||||
options (user's call): seed **Phase 2** (`set` clause + column-fill);
|
||||
**H2 `hint`** (closes A1) — own ADR; **TT5 CI**; or the larger
|
||||
**V4 journal** / **tutorial** ADRs.
|
||||
3. Two minor, user-deferred observations (non-blocking): the uniqueness
|
||||
retry cap (`MAX_ATTEMPTS=200`) can cap a *medium* unique domain
|
||||
slightly below its true size (junction/small domains are exact);
|
||||
`literal_to_value` doesn't type-check an IN-CHECK literal vs a numeric
|
||||
column (a malformed `int IN ('a')` CHECK fails cleanly at bind).
|
||||
@@ -0,0 +1,145 @@
|
||||
# Session handoff — 2026-06-11 (66)
|
||||
|
||||
Sixty-sixth handover. Continues from handoff-65 (ADR-0048 `seed`
|
||||
Phase 1). This session built **ADR-0048 Phase 2** end to end: the
|
||||
**`set` override clause** (D2) and the **`<table>.<column>`
|
||||
column-fill** form (D1 form 2) — the two surfaces Phase 1 deliberately
|
||||
deferred. Designed-then-DA-vetted (a `/runda` pass that caught a real
|
||||
ADR-vs-grammar conflict), then built test-first.
|
||||
|
||||
## §1. State at handoff
|
||||
|
||||
**Branch:** `main`. All Phase-2 work is in the working tree;
|
||||
**commits are pending the user's approval** (see §6). Unpushed is the
|
||||
normal working state.
|
||||
|
||||
**Tests: 2400 passing / 0 failing / 0 skipped / 1 ignored** (the
|
||||
long-standing `friendly` doctest). **Clippy clean** (nursery, all
|
||||
targets). +42 over handoff-65's 2358.
|
||||
|
||||
## §2. What landed (read ADR-0048 — Status + D1/D2/D9/D13)
|
||||
|
||||
`seed <T>[.<col>] [count] [set <overrides>] [--seed <n>]`.
|
||||
|
||||
- **`set` override clause (D2):** four forms, comma-separated —
|
||||
`status = 'active'` (fixed), `role in ('a','b')` (pick-list),
|
||||
`work_addr as email` (named generator), `price between 10 and 100`
|
||||
(range; numeric **and quoted dates**). Type-aware; an override
|
||||
**drops its column from the generic-fill advisory** (D13). Value
|
||||
slots reuse `update`'s typed `current_column_value` (quoting
|
||||
enforced structurally — a bare word is rejected).
|
||||
- **Column-fill (D1 form 2):** `seed users.email [set …]` fills one
|
||||
column across **existing** rows (an UPDATE). Refuses PK / autogen
|
||||
(`serial`/`shortid`/`blob`) targets; **empty table → friendly
|
||||
no-op**; FK target samples the parent; UNIQUE/identifier target gets
|
||||
collision-free values; **one undo step**; `set` may only adjust the
|
||||
filled column; a row count is refused.
|
||||
- **Named-generator vocabulary (D9):** `src/seed/vocabulary.rs` —
|
||||
`KNOWN_GENERATORS` + `generator_for_name` + `is_known_generator_prefix`,
|
||||
the single source of truth for completion, validity, and the executor.
|
||||
- **Range generator:** `Generator::Range { low, high }` in
|
||||
`src/seed/generators.rs`, interpreted per destination type;
|
||||
`range_bounds_reason` validates compatibility before generation.
|
||||
- **Ambient wiring:** completion (generator names after `as`, the
|
||||
`set <col>` and `.col` column slots, the `set` keyword); highlight
|
||||
(new `HighlightClass::Function` → existing `tok_function`); validity
|
||||
(new `IdentSource::Generators` — unknown generator flagged `[ERR]`;
|
||||
unknown column in `set`/`.col` flagged via the existing Columns
|
||||
path); help (`help.data.seed`); parse-error pedagogy near-miss rows;
|
||||
the D13 advisory's **Phase-2/3 wording** (points at `set` and the
|
||||
column-fill repair). Both modes (D5).
|
||||
|
||||
## §3. The ADR amendment (a real DA find)
|
||||
|
||||
The pre-build `/runda` pass found that **ADR-0048 D2's "dates stay
|
||||
unquoted" was impossible** — this DSL has **no date-literal token**
|
||||
(`Value` is `Number`/`Text`; dates are quoted strings validated by
|
||||
`bind_date`). Escalated to the user, who chose **quoted dates +
|
||||
amend the ADR** (the grammar-consistent option). D2 now carries a
|
||||
dated amendment; the range form uses `between '2023-01-01' and
|
||||
'2024-12-31'`. This was the only divergence from the ADR text; numbers
|
||||
remain unquoted.
|
||||
|
||||
## §4. Where the code lives
|
||||
|
||||
- **`src/dsl/command.rs`** — `Command::Seed` gains `target_column:
|
||||
Option<String>` + `overrides: Vec<SeedOverride>`; new `SeedOverride`
|
||||
/ `SeedOverrideKind`.
|
||||
- **`src/dsl/grammar/data.rs`** — `SEED_SET_CLAUSE` + `SEED_DOT_COLUMN`
|
||||
grammar; `SEED_GENERATOR` slot (`IdentSource::Generators`,
|
||||
`HighlightClass::Function`); `build_seed` + the override fold
|
||||
(`build_seed_overrides` / `parse_seed_override_tail`).
|
||||
- **`src/dsl/grammar/mod.rs`** — `IdentSource::Generators` +
|
||||
`HighlightClass::Function`.
|
||||
- **`src/db.rs`** — `apply_seed_overrides` / `seed_override_plan` /
|
||||
`seed_override_literal`; `do_seed_column_fill`; `do_seed` +
|
||||
`Database::seed` + worker wiring threaded with the new params.
|
||||
- **`src/seed/`** — `vocabulary.rs` (new); `generators.rs` (range
|
||||
generator + `range_bounds_reason`); `mod.rs` (`Generator::Range`).
|
||||
- **`src/completion.rs`** — generator candidates after `as`; generator
|
||||
validity. **`src/input_render.rs`** — `"generator"` invalid-ident
|
||||
kind. **`src/theme.rs`** — `Function → tok_function`.
|
||||
- **Catalog** — `help.data.seed`, `parse.usage.seed`,
|
||||
`seed.advisory_generic` (Phase-2/3 wording) in `en-US.yaml`;
|
||||
`keys.rs` placeholders updated.
|
||||
- **Tests** — `tests/it/seed.rs` (+~30: builder fold, executor
|
||||
set/column-fill, undo, advanced mode), `src/seed/{vocabulary,
|
||||
generators}.rs` (range + vocabulary units), `src/completion.rs`
|
||||
(generator + column validity), `src/dsl/walker/highlight.rs`,
|
||||
`tests/typing_surface/mod.rs` (completion slots),
|
||||
`tests/it/parse_error_pedagogy.rs` (near-miss rows).
|
||||
|
||||
## §5. Two implementation refinements vs. the ADR (both met the contract)
|
||||
|
||||
- **Quoted dates** (the D2 amendment, §3).
|
||||
- **Value slots reuse `current_column_value`** (the `update … set`
|
||||
typed slot) rather than the raw ADR-0026 expression operand — no
|
||||
spurious column-ref match, typed narrowing, consistent with
|
||||
`update`. The user-facing contract (quoted literals, type-aware) is
|
||||
fully met.
|
||||
|
||||
The `seed_take_value` / `seed_set_error` builder paths are
|
||||
drift-guards (the typed slots only ever match value literals, so a bare
|
||||
word is rejected at the grammar level) — they use the generic
|
||||
`parse.error_wrapper`, mirroring `expr::build_expr`.
|
||||
|
||||
## §6. How to take over / next steps
|
||||
|
||||
1. Read handoffs 64 → 65 → 66, `CLAUDE.md`, `docs/requirements.md`,
|
||||
`docs/adr/0048-…md` (Status block + D1/D2/D9/D13 + the amendment).
|
||||
2. **Seed is feature-complete (SD1 + SD2).** `requirements.md`: **SD1
|
||||
`[x]`, SD2 `[x]`**. The only open A1 gap is `hint`/**H2** (own ADR).
|
||||
3. **Commits pending approval.** Suggested split:
|
||||
- `feat(seed): set override clause + column-fill (ADR-0048 Phase 2)`
|
||||
— all `src/` + `tests/` changes.
|
||||
- `docs: ADR-0048 Phase 2 implemented + handoff 66` — ADR / README /
|
||||
requirements / this file.
|
||||
4. Next options (user's call): **H2 `hint`** (closes A1); **TT5 CI**;
|
||||
the larger **V4 journal** / **tutorial** ADRs; or Tier-4 PTY (TT4).
|
||||
5. Consider a `cargo sweep` at this milestone (`target/` grows).
|
||||
|
||||
## §7. Post-implementation `/runda` pass (done this session)
|
||||
|
||||
A DA pass over the completed code found **no correctness bugs and no
|
||||
dropped requirements**; all D1–D18 acceptance criteria verified met,
|
||||
tests confirmed to catch regressions. One **design fork** was surfaced
|
||||
and **resolved by the user**:
|
||||
|
||||
- **Bounded override × UNIQUE column** — a fixed value / too-short
|
||||
pick-list on a single-column-UNIQUE target used to silently cap the
|
||||
run (e.g. `seed users 100 set email = 'x'` → 1 row). Now a **friendly
|
||||
error** up front (`seed_override_capacity_guard`, `src/db.rs`), for
|
||||
both whole-row and column-fill; generators/ranges stay cap-based
|
||||
(unbounded sources). ADR-0048 D2 documents it; two tests pin it.
|
||||
|
||||
Remaining **non-blocking** edges (noted, not bugs):
|
||||
|
||||
- Overriding an **FK column** with a literal: the override wins (D2); a
|
||||
non-parent value fails safely through the FK-error layer.
|
||||
- **Column-fill of one column of a *compound* FK** samples that column
|
||||
independently → an invalid tuple fails safely (UPDATE rejected,
|
||||
rollback), never corrupts. Single-column FKs / non-FK columns are
|
||||
exact.
|
||||
- The generator slot uses the **default candidate-ladder hint** (offers
|
||||
the vocabulary), not a dedicated prose intro — discoverability is met
|
||||
by completion; a prose intro is optional polish.
|
||||
@@ -0,0 +1,119 @@
|
||||
# Session handoff — 2026-06-12 (67)
|
||||
|
||||
Sixty-seventh handover. Continues directly from handoff-66 (ADR-0048
|
||||
`seed` Phase 2, committed). This was a **manual-testing pass**: the user
|
||||
exercised the app, found several rough edges, and we triaged each into
|
||||
*fix now* vs *file an issue*. Net result: **three bug fixes committed**
|
||||
and **three enhancement issues filed**.
|
||||
|
||||
## §1. State at handoff
|
||||
|
||||
**Branch:** `main`. Working tree **clean**; all work committed. Unpushed
|
||||
(push is the user's step).
|
||||
|
||||
**Tests: 2407 passing / 0 failing / 0 skipped / 1 ignored** (the
|
||||
long-standing `friendly` doctest). **Clippy clean** (nursery, all
|
||||
targets). +7 over handoff-66's 2400.
|
||||
|
||||
**Commits since handoff-65:**
|
||||
```
|
||||
f7155ce fix(input): thread the `:` one-shot escape into live SQL feedback
|
||||
4cacb82 fix(completion): don't flag a table alias used before its FROM clause
|
||||
c3e0103 fix(completion): flag-aware partial so a dash completes flags, not keywords
|
||||
30b2677 docs: ADR-0048 Phase 2 implemented + handoff 66
|
||||
a12facc feat(seed): set override clause + column-fill (ADR-0048 Phase 2)
|
||||
```
|
||||
(`a12facc`/`30b2677` are the Phase-2 work documented in handoff-66.)
|
||||
|
||||
## §2. Bug fixes this session (all committed, all tested)
|
||||
|
||||
1. **`c3e0103` — flag completion ate the dash.** Typing a flag at a
|
||||
flag position (`add 1:n relationship … -`) offered the `on` keyword
|
||||
and, on accept, produced `-on` / `---create-fk`: the partial-token
|
||||
walk stopped at `-`, so the dash was outside the replaced range.
|
||||
Fix: flag-aware partial detection (a dash-prefixed token at a word
|
||||
boundary is a flag-in-progress, **gated on a flag being expected** so
|
||||
`where x = -5` stays a number) + a unified flag matcher
|
||||
(`trim_start_matches('-')`). Affected **all** flags. 4 tests + 2
|
||||
partial-flag snapshots updated (they'd captured the latent bug).
|
||||
|
||||
2. **`4cacb82` — table alias flagged as an unknown column.** In a
|
||||
SELECT, the projection (`sum(ol.count*…)`) can reference an alias
|
||||
whose `FROM … OrderLines ol` sits *after* the cursor. The candidate
|
||||
engine recovers that via the §10.6 full-input lookahead (ADR-0032),
|
||||
but `invalid_ident_at_cursor` only walked text *before* the cursor —
|
||||
so `ol` matched no scope and got a red "ERR" overlay on an otherwise
|
||||
valid query. Fix: give the validity check the same full-input
|
||||
lookahead and bail when the partial prefix-matches a binding's alias
|
||||
or table. 1 test.
|
||||
|
||||
3. **`f7155ce` — the `:` one-shot escape broke live SQL feedback.**
|
||||
Submission strips the `:` (ADR-0003), but the *live* feedback kept it
|
||||
in the buffer handed to the walker, which bailed at the `:`. Effect:
|
||||
under `:`, Tab completed nothing and a valid query could flash `[ERR]`
|
||||
— while the same line in full `mode advanced` worked. (The hint
|
||||
already stripped it, hence "hint shows the name but Tab does
|
||||
nothing".) Fix: one shared `App::feedback_view()` (the `:`-stripped
|
||||
SQL + mapped cursor + stripped offset) routed through completion (with
|
||||
a `replaced_range` offset shift), the validity verdict, and rendering
|
||||
(new `render_input_runs_feedback` highlights/overlays the view shifted
|
||||
by the offset; the `:` renders as plain text); the ambient hint was
|
||||
consolidated onto it (removing the duplicate `strip_one_shot_prefix`).
|
||||
3 tests + the 9 existing colon tests still green.
|
||||
|
||||
## §3. Investigated, **no code change** (working as designed)
|
||||
|
||||
- **Comma-`FROM` implicit join** (`select … from A, B, C`) is
|
||||
**deliberately rejected** — ADR-0032 §11 / OOS-3: *"comma-FROM teaches
|
||||
habits we do not want to encourage; `CROSS JOIN` covers the same shape
|
||||
explicitly."* The explicit equivalent (`CROSS JOIN … WHERE …`) works.
|
||||
- **`sum(…)` returning one row** with no `GROUP BY` is **correct SQL**
|
||||
(the aggregate collapses the result to one row; SQLite/the playground
|
||||
allow the non-aggregated columns where Postgres would error). The
|
||||
user's query needed `group by o.id`. Verified (1 row).
|
||||
|
||||
## §4. Open issues filed this session — **next session's candidates**
|
||||
|
||||
All on `git.lazyeval.net/oli/rdbms-playground`, label `enhancement`:
|
||||
|
||||
- **#26 — `seed <table>` hint omits the optional count.** A complete
|
||||
command's optional positional *number* has no Tab candidate, so it's
|
||||
invisible. `IntroProse` doesn't fit (it only fires for incomplete
|
||||
required slots; the completing Seq match clears the hint). Needs a way
|
||||
to advertise optional positional non-keyword args. *(I attempted +
|
||||
reverted this during Phase 2; see the analysis in the issue.)*
|
||||
- **#27 — Bottom status line: keybindings-only, context- and
|
||||
state-aware.** Per-nav-focus keybindings (Input vs sidebar), **include
|
||||
transient states** (Tab-cycle, history) — user preference — and add
|
||||
`mode advanced` to the empty-input hint. May warrant a small ADR.
|
||||
- **#28 — Reconsider relationship prose in `add column` (incidental DDL)
|
||||
confirmations.** Currently by design (ADR-0044 §1 keeps prose, not
|
||||
diagrams, for incidental DDL). **User preference: do NOT show the
|
||||
`References:` / `Referenced by:` block** in the add-column
|
||||
confirmation at all — focus on the change just made. This revisits a
|
||||
decided area → land as a **new ADR** superseding the relevant part of
|
||||
ADR-0016 §5 / ADR-0044 §1; confirm scope (just `add column`, or all
|
||||
incidental DDL).
|
||||
|
||||
## §5. Other open work (unchanged from handoff-66 §6)
|
||||
|
||||
`seed` is **feature-complete** (`requirements.md` SD1 `[x]`, SD2 `[x]`).
|
||||
Remaining roadmap, user's call:
|
||||
|
||||
- **H2 `hint`** — the last A1 gap (its own ADR).
|
||||
- **TT5 CI** — test infra exists; no CI workflow yet.
|
||||
- **TT4 PTY (Tier-4)** — ADR-0008 specifies it; not wired.
|
||||
- Larger: **V4 journal**, **tutorial/lesson system** (each needs an ADR).
|
||||
|
||||
A possible quick follow-up: a friendlier "use an explicit `JOIN`"
|
||||
parse-error for comma-`FROM` (point 1) — not filed; mention if wanted.
|
||||
|
||||
## §6. How to take over
|
||||
|
||||
1. Read handoffs 65 → 66 → 67, `CLAUDE.md`, `docs/requirements.md`.
|
||||
2. `seed` Phase 2 is done (ADR-0048 Status block is current). The
|
||||
manual-testing fixes (§2) are committed and green.
|
||||
3. Pick from §4 (filed issues #26/#27/#28) or §5 (roadmap). #28 is a
|
||||
decision/ADR; #27 is UX (maybe ADR); #26 is a hint-system enhancement.
|
||||
4. Consider a `cargo sweep` at this milestone (`target/` grows across
|
||||
sessions).
|
||||
Reference in New Issue
Block a user