Files
claude@clouddev1 30b2677bf3 docs: ADR-0048 Phase 2 implemented + handoff 66
- ADR-0048: status → Phase 1 + Phase 2 implemented; D2 amendment
  (quoted dates, no date-literal token) and the override × UNIQUE
  capacity-guard decision; phasing/Status blocks marked done.
- README index: 0048 entry updated (Phase 2 shipped, 2400 tests).
- requirements.md: SD2 → [x] (the override-hooks core + column-fill).
- handoff 66: this session's Phase 2 build + the two /runda passes.
2026-06-12 09:44:36 +00:00

146 lines
7.4 KiB
Markdown
Raw Permalink 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-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 D1D18 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.