# 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.
