# 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 [count] [--seed ]` — 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 ` → 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
.`, 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).