# Session handoff — 2026-05-23 (34)

Thirty-fourth handover. This session completed **ADR-0033
sub-phase 3k** — the Phase-3 verification sweep — closing Phase 3
of the ADR-0030 advanced-mode SQL surface. A user-invoked
`/runda` round hardened the matrix attributions and closed two
small coverage gaps. **ADR-0033 is now Accepted.**

The next session (or the continuation of this one) starts the
**ADR-0034** implementation. See §4.

## §1. State at handoff

**Branch:** `main`. **Tests: 1645 passing, 0 failing, 0 skipped,
1 ignored** (the unchanged `friendly/mod.rs` doctest). **Clippy:**
clean (`cargo clippy --all-targets -- -D warnings`).

**Latest committed (local-only):**

```
380c423 test+docs: 3k Phase-3 verification sweep — e2e DML + filled cross-cut matrix
```

`origin/main` is at `6b8888f` (3h), so **10 commits are
local-only** (the 3i series, handoff-32, 3j `d5c7f63`, handoff-33
`a5cdb00`, and this session's 3k `380c423`). Unpushed commits are
a normal working state; pushing is the user's step — do not prompt
about it.

**Uncommitted at the moment of writing this handoff** (the
ADR-0033 acceptance flip + this handoff doc):

- `docs/adr/0033-sql-dml-grammar.md` — Status `Proposed` →
  `Accepted`.
- `docs/adr/README.md` — ADR-0033 index line flipped to
  `Accepted` (same-edit index-upkeep rule).
- `docs/handoff/20260523-handoff-34.md` — this file.

These three should be committed together (proposed message in §8).

## §2. What shipped this session (3k)

Authoritative detail lives in the phase-exit report:
**`docs/handoff/20260523-phase-3-verification.md`** — read it for
the filled matrix, the requirements-to-test mapping, and the DA
review. Summary:

- **`tests/sql_dml_e2e.rs` (new)** — 11 Tier-3 end-to-end DML
  tests (parse-in-Advanced → worker → persist/history): INSERT…
  SELECT cross-table, all-ten-type multi-row INSERT + `RETURNING`
  type recovery, UPDATE-with-subquery-in-SET, cascade DELETE,
  UPSERT round-trip, `RETURNING` ×3, `history.log` replay of
  Phase-3 forms, the full §13 OOS rejections, a trailing-`;` guard,
  and the `[WRN]` validity indicator driven by a SQL DML diagnostic.
- **Cross-cut gap-fill** in `src/`: `walker/mod.rs` (5
  inherited-diagnostic cross-cuts — DELETE/UPDATE WHERE
  schema-existence, like-numeric on DELETE WHERE, the corrected
  row-scoped predicate slots), `highlight.rs` (DML-keyword
  highlight), `completion.rs` (`INSERT INTO` target-table),
  `input_render.rs` (advanced-mode DML hint-panel — added in the
  `/runda` round).
- **Cross-cut matrix filled** in
  `docs/plans/20260520-adr-0033-phase-3.md` — **85 ✅, 1 N/A, 0
  ❌**, every row a verified `file::function`.
- **ADR-0033 → Accepted** (this handoff's commit).

## §3. Decisions settled this session (do not re-litigate)

Both escalated and **user-confirmed** before any matrix/test edit
(via `AskUserQuestion`); recorded in the phase-exit report §4 and
the matrix footnotes [d]/[e]:

1. **Predicate-warning-in-VALUES (matrix I7) — claim corrected.**
   Predicate warnings (`eq_null` / `like_numeric` / `type_mismatch`)
   fire on every DML `sql_expr` slot with **row scope** (UPDATE/
   DELETE WHERE, UPDATE SET incl. CASE, INSERT…SELECT projection &
   WHERE) but **not** in plain `INSERT … VALUES` — a VALUES literal
   has no row to compare against. This matches ADR-0033 §8.4 ("WHERE
   and CASE"); the original "(e.g. = with NULL in VALUES)" example
   was an over-statement. Backed by new row-scoped tests.

2. **Auto-snapshot (ADR-0006 / ADR-0033 §10) — N/A, deferred.**
   ADR-0006 auto-snapshot/undo is unimplemented for **both** the
   DSL and SQL paths (the U-series). The "same as DSL" parity holds
   vacuously; Phase 3 introduces no regression. The matrix row is
   N/A, not red.

The `/runda` round additionally **corrected the A6 attribution**
(the hint-panel tests ran in Simple mode via `ambient_hint`, which
defaults to `Mode::Simple`; added an advanced-mode DML hint test)
and **closed OOS-5/OOS-6** (INDEXED BY / multi-statement — both
parse-reject; a single trailing `;` still parses).

## §4. ADR-0034 — the NEXT job

**Implement ADR-0034** (`docs/adr/0034-history-journal-and-replay-filter.md`,
**Accepted**). This is the user's standing "extra tasks after
Phase 3" item; it subsumes the old TASK #8 + TASK #9 and fixes a
**real, currently-broken behaviour** verified this session:

> `replay history.log` fails on line 1. `run_replay`
> (`src/runtime.rs:1630`) feeds each whole raw line straight to
> `parse_command_with_schema` and only skips blank/`#` lines — it
> does **not** understand the `<ts>|<status>|<source>` journal
> format that `history.rs` already writes. So replay only works on
> hand-written bare-command `.commands` scripts, never on the
> actual journal. No test catches this (existing replay tests +
> the new 3k e2e replay test all use bare-command scripts).

Concrete work (ADR-0034 §§1–4):

1. **Writer records every command, tagged `ok` / `err`** (today
   `history.rs` hardcodes `ok`). `err` lines are journalled
   best-effort from the runtime/app error path (a parse failure
   never reaches the worker); `ok` lines stay worker-journalled,
   transactionally coupled to the state change.
2. **Hydration reads all records** (ok + err) so cross-session
   recall matches the in-session ring (req I2 is marked done but
   only covers `ok` today — err lines are lost across sessions).
3. **Replay learns the journal format**: detect the
   `<iso8601>|<status>|` prefix, extract+unescape `<source>`, skip
   non-`ok`; bare commands still replay as-is. Detection by the
   leading timestamp+status prefix so a `|` inside a bare command
   isn't misread.
4. Escape/unescape parity with the existing `history.rs` helpers.

**Test-first (global rule):** the first move is a **failing** test
that replays an actual `history.log` (with the `<ts>|ok|` prefix)
and currently dies on line 1 — then make it green. Also add an
`err`-line round-trip test (write → hydrate-reads-it →
replay-skips-it).

**Open question to settle with the user first:** ADR-0034 has **no
plan doc** (unlike Phases 2–3). It is smaller; a lightweight
phased pass in one session may suffice. The user said we can
"continue in this session afterwards with the ADR-0034 plan" — so
the immediate next action is to produce that plan (or confirm a
plan-less test-first pass), then implement.

## §5. Other tracked deferred items (nothing lost)

- **ADR-0006 auto-snapshot / undo** (U-series) — surfaced by 3k's
  N/A matrix row; implement for **both** DSL and SQL worker
  handlers so parity is real, not vacuous.
- **M4 — execution-time mode side-channel** (three-way `Mode`
  threaded `Action`→worker, for mode-dependent *output*). Needs
  its own ADR (ADR-0033 Amendment 3; `requirements.md` M4). Not a
  prerequisite for anything above.
- **Phase 4 — DDL as SQL** (`CREATE`/`DROP`/`ALTER TABLE`,
  `CREATE`/`DROP INDEX`). The next ADR-0030 roadmap phase, but
  **no ADR exists yet** (latest is 0034) — needs its own ADR
  before implementation.
- **`blob` value literal** — `src/dsl/value.rs` has no blob
  literal yet; the 3k all-types test inserts NULL for blob (type
  still round-trips). Pre-existing gap.
- **Q1 / Q2** (SQL subset completeness; polished out-of-subset
  rejection message naming the construct) — multi-phase, still
  `[ ]`; the 3k OOS tests assert rejection only, not message
  quality (Q2 is "Implementation pending").
- Cosmetic: `tests/sql_*.rs` helper names (`run_sqlinsert` etc.)
  keep their dev-word-era spelling though they parse the real
  words.

## §6. Process pins (unchanged, still binding)

- **Confirm every commit.** Propose the message; wait for the
  go-ahead. (The 3k commit `380c423` and the acceptance flip were
  both user-approved.)
- **Push is the user's step.** Never push; never prompt about it.
- **No AI attribution** in commits (global rule).
- **Probe, don't reason.** This session's catalog sub-agents
  fabricated test names and mis-attributed dispatch/inherited-
  diagnostic rows; every matrix row was re-verified by reading the
  actual test. The `/runda` round caught a mode mismatch the same
  way. Reproduce/print before concluding.
- **Escalate ADR-vs-implementation mismatches; never classify work
  "out of scope" without user confirmation.** Both 3k findings
  (I7, auto-snapshot) were escalated, not silently resolved.

## §7. How to take over

1. **Read, in order:** this file →
   `docs/handoff/20260523-phase-3-verification.md` (the Phase-3
   close-out) → `docs/adr/0034-history-journal-and-replay-filter.md`
   (**the next job**) → `CLAUDE.md` → `docs/requirements.md`.
2. **Baseline:**
   ```
   cargo test    # expect 1645 passing / 0 failing / 0 skipped / 1 ignored
   cargo clippy --all-targets -- -D warnings   # clean
   ```
3. **Start ADR-0034** per §4: settle plan-vs-no-plan with the
   user, then a test-first pass beginning with the failing
   `replay history.log` reproduction.
4. **Escalate** anything not settled in ADR-0034; the user wants
   mismatches surfaced, not silently fixed.
