# Session handoff — 2026-06-14 (69)

Sixty-ninth handover. Continues from handoff-68 (an issue-burndown that
closed #25/#26/#31/#32/#33/#34). This session **closed the four
remaining open issues** — #29, #28, #27, #30 — each landed with the full
phased workflow + `/runda` + Devil's-Advocate passes before commit, and
each producing a new ADR. Net: **four issues closed, four commits, four
new ADRs (0049–0052), +63 tests, zero regressions, the tracker is now
empty.**

The four interlock: **#29** added the input-field readline keys, **#27**
advertises them in a state-aware status strip, and **#30**'s history
recall now respects modes. **#30** also turned into a real architecture
change (journaling relocation) — read §2.4 carefully before touching that
area.

## §1. State at handoff

**Branch:** `main`. Working tree **clean**; all work committed. The two
most recent commits are local (normal working state — push is the user's
step).

**Tests: 2471 passing / 0 failing / 0 skipped / 1 ignored** (the
long-standing `friendly` doctest). **Clippy clean** (nursery, all
targets). Breakdown: 1771 lib + 500 integration (`it`) + 200
typing-surface-matrix. **+35 over handoff-68's 2436** (net: #29 +22, #28
+0, #27 +9, #30 +4 — its new history.rs/app.rs/iteration6 tests minus the
15 retired worker-journaling tests; trust the live `cargo test` count).

**Commits this session:**
```
4aeea55 feat(history): mode-tagged history + top-of-chain journaling (#30)
eceedc1 feat(ui): context- and state-aware bottom keybinding strip (#27)
8ac3537 feat(render): incidental-DDL confirmations show structure only, no relationships (#28)
66c8bda feat(input): readline keymap — Esc-clear + Ctrl-A/E/W/K/U (#29)
```

**Open Gitea issues: none.** `tea issues list --state open` is empty.

## §2. Issues closed this session (all committed, tested, `/runda`-reviewed)

Each closed on `git.lazyeval.net/oli/rdbms-playground` with a summary
comment.

### 2.1 — #29 (`66c8bda`) — input-field readline keymap (ADR-0049)

Implements the deferred **I1b** readline shortcuts: `Esc` clears a
partly-typed command (only when no completion memo is alive — the memo
wins first, ADR-0022); `Ctrl-A`/`Ctrl-E` = Home/End; `Ctrl-W` deletes
the previous word (readline-style, UTF-8 safe); `Ctrl-K`/`Ctrl-U` kill to
end/start. Cursor-only keys leave history nav intact; buffer-mutating
keys end it. **DA caught** the need for the `Ctrl-O`+`Esc` (sidebar
nav-exit) interaction not to clear the draft — locked with a regression
test. `requirements.md` I1b → `[x]`.

### 2.2 — #28 (`8ac3537`) — incidental-DDL confirmations: structure-only (ADR-0050)

Incidental-DDL confirmation echoes (`create table`, `add`/`drop`/
`rename`/`change column`, `add`/`drop index`) now render **structure
only** — no `References:` / `Referenced by:` block. Relationship-subject
surfaces (`show table`, `add`/`drop relationship`) keep their ADR-0044
diagrams. The prose renderer (`relationship_prose_lines` + `cols_disp`)
was deleted. **Supersedes** ADR-0044 §1's incidental-DDL prose clause and
the relationship-block half of ADR-0016 §5 (both annotated).

### 2.3 — #27 (`eceedc1`) — context- and state-aware keybinding strip (ADR-0051)

The bottom status line is now keystrokes-only and **state-selected** by
priority (sidebar focus / completion-memo / history-nav / editing /
default). The editing state surfaces the #29 keys (closing ADR-0049's
deferred advertisement). Mode-switch advertisements left the strip; the
empty-input hint gained a simple-mode `` `mode advanced` for SQL `` pointer
(advanced mode shows none — user decision). New `App::is_browsing_history()`
exposes the private `history_cursor`. 15 full-panel snapshots re-accepted.

### 2.4 — #30 (`4aeea55`) — mode-tagged history + top-of-chain journaling (ADR-0052) **← read before touching journaling**

Closed both the feature (advanced history reusable in simple mode) and
the bug (the `:` one-shot prefix lost across sessions). Two halves:

1. **Mode-tagged history.** The `history.log` status token gains an
   optional `:adv` suffix (`ok` / `ok:adv` / `err` / `err:adv`); `source`
   stays last + canonical so replay is unaffected. The in-memory ring
   (still `Vec<String>`) stores advanced entries in their `: `-prefixed
   simple-mode runnable form; recall **strips the `:` in advanced mode**
   and keeps it in simple; hydration reconstructs the prefix from the tag.
   App commands journal simple and are excluded from the ring's advanced
   flag, so they recall bare.

2. **Journaling relocation (the architecture change).** Success
   journaling **moved out of the worker** to the dispatch layer
   (`spawn_dsl_dispatch` / `run_replay` / the app-command sites), next to
   the already-top-level failure journaling — so the submission mode is in
   scope with no worker plumbing. `finalize_persistence` now writes only
   the **state** sources (yaml/csv); the journal write is **best-effort**
   (the command is already committed — consistent with the failure path).
   **Amends ADR-0015 §6** (history.log out of the worker tx; commit-db-last
   scopes yaml/csv/db only), **ADR-0034** (status tag + journaling
   location), **ADR-0040** (journal-write best-effort, not fatal).

   **Two DA findings, both resolved:** (a) the app-command `advanced` flag
   must exclude app commands (else `: save as` diverges); (b) the spawn
   journals on `outcome.is_ok()`, so journaling is now **uniform** — read
   commands that didn't journal before (`show tables`/`show relationships`/
   `show indexes`, `show relationship <name>`, `explain`) now do, matching
   ADR-0034 §1. **User-confirmed** as the more-correct behaviour (harmless
   on replay — reads/`explain` don't mutate).

   **Test migration:** 15 worker-level journaling tests were retired (the
   worker no longer journals — their yaml/csv/operation assertions were
   kept) and re-covered at the new layer: `history.rs` status-tag +
   `:`-reconstruct; `app.rs` recall matrix; the cross-session regression
   `advanced_command_journalled_then_hydrated_recalls_with_colon_in_simple`
   in `iteration6_resume_history`; the replay tests cover `run_replay`
   journaling.

   Plan: `docs/plans/20260613-issue-30-top-of-chain-journaling.md`.

## §3. Next session — start here

The user's stated plan for the next session, in order:

1. **Pick up the ADR-0052 follow-up** (below).
2. **Check for any newly-filed open issues** (`tea issues list --state
   open`) — none at handoff, but check fresh.
3. **Then** take on remaining open tasks from the general requirements
   (`docs/requirements.md`) — see §5.

### The ADR-0052 follow-up — unwind the vestigial worker `source` plumbing

When journaling moved out of the worker, the `source` that the worker
threaded purely for journaling became dead. To avoid orphaning the param
across ~28 handlers, the refactor **left it in place** as vestigial:

- `finalize_persistence(conn, persistence, _source, changes)` — the
  `_source` param is now unused (kept so its ~28 callers still pass
  `source`, which they otherwise also use for `snapshot_then`).
- `do_rebuild_from_text(conn, _persistence, _source, project_path)` —
  both `_persistence` and `_source` vestigial.
- Three thin read-only wrappers in `db.rs` —
  `do_describe_table_request`, `do_query_data_request`,
  `do_run_select_request` — now just delegate to their non-`_request`
  twin (`do_describe_table` / `do_query_data` / `do_run_select`) with
  vestigial `_persistence` / `_source` params and one caller each
  (`db.rs` Request arms ~2409 / ~2749 / ~2759).

**The cleanup:** remove `_source` from `finalize_persistence` + drop the
arg at its ~28 callers (the callers keep `source` for `snapshot_then`, so
only the `finalize_persistence(...)` call loses the arg); remove the
`_persistence`/`_source` params from `do_rebuild_from_text`; and inline
the three `*_request` wrappers at their single call sites (replace
`do_describe_table_request(conn, persistence, source, name)` with
`do_describe_table(conn, &name)`, etc.), deleting the wrappers. Purely
mechanical, compiler-guided, no behaviour change. Establish the green
baseline first (`cargo test`), then verify nothing moved.

## §4. Carried-over follow-up (website branch, not `main`)

- **Website `seed` cast re-record** (from #34, handoff-68 §4) — still
  tracked on the `website` branch, not here. Likely redundant (full
  re-record sweep before publication).

## §5. Remaining roadmap — `docs/requirements.md` (next session's §3-step 3)

With the issue tracker empty, the next work comes from the document-based
requirements. Open / partial items worth weighing (the user picks):

- **H2 `hint`** — the last A1 gap (contextual help for the current
  command); its own ADR. (`requirements.md` H2.)
- **TT5 CI** — runs all tiers on Linux/macOS/Windows; no CI workflow yet
  (a `ci` branch reportedly exists — check its state first). Couples with
  **D1–D3** (cross-platform prebuilt binaries + Homebrew/Scoop).
- **TT4 PTY (Tier-4)** — ADR-0008 specifies the PTY harness + four
  critical flows; still not wired (no PTY deps/tests).
- **I1 multi-line input** (Ctrl-Enter submits, Enter inserts newline) and
  **I5 / B3 in-flight cancellation** (Ctrl-C cancels a running command).
- **V4 session journal** — scrollable per-session log + Markdown export
  (the bigger UX project; own ADR).
- **TU1 tutorial / lesson system** — design + ADR pending (acknowledged
  in scope).
- Smaller partials: **C3a** modify relationship (drop+add covers it
  today), **C4** m:n convenience, **V3** ER-diagram export, the **NFR-***
  performance/visual targets (mostly unmeasured), **N4** global rolling
  history (OOS for v1).

No strong ordering — these are the user's call. Several need a new ADR
(H2, V4, TU1); CI/release (TT5/D1–D3) is the most "shippable-product"
track if that's the priority.

## §6. How to take over

1. Read handoffs 67 → 68 → 69, `CLAUDE.md`, `docs/requirements.md`.
2. Confirm green baseline: `cargo test` (expect **2471 pass / 1 ignored**)
   + `cargo clippy --all-targets` (clean).
3. `tea issues list --state open` — pick up anything new first.
4. Then the ADR-0052 follow-up (§3), then requirements (§5).
5. Follow the project workflow: phased (requirements → divergent → eval →
   execute → verify), test-first, `/runda` + DA pass before every commit,
   ADR amendment for any decided-area change + the README index-upkeep
   rule, and confirm the commit message with the user before committing.
6. Consider a `cargo sweep` at this milestone (`target/` grows across
   sessions; see CLAUDE.md "Build hygiene"). (`sweep.timestamp` was
   removed this session.)
