# Session handoff — 2026-06-22 (76)

Continues from handoff-75 (D3 package managers). This session took up the
**regression-hardening** trio identified as "what's next" now that public
binaries ship: **TT4** (Tier-4 PTY tests), **NFR verification**, and a
**CHANGELOG** — plus a real palette accessibility fix the work uncovered.

## §1. State

**Branch `main`.** Commits this session (all on `main`, **not pushed** — push
is the user's step):
- `65eab71` `fix(theme)` — WCAG-AA palette fix + contrast/ΔE2000 gates +
  `scripts/palette-preview.py`.
- `fd63de3` `test(tt4)` — Tier-4 PTY end-to-end suite (`tests/e2e_pty.rs`).
- `88204f2` `docs(tt4,nfr)` — ADR-0008 Amendment 1, ADR-0057, README index,
  `requirements.md`, `CHANGELOG.md`, handoff-76, plan doc.
- `1ffe11c` `fix(tt4)` — drop the dead `pid` helper (macOS-only dead-code
  warning the Linux gate can't see; found via the user's macOS run).
- `35ca108` `docs(tt5)` — macOS Tier-4 confirmation + Windows verification
  stance (and the §7 below was added in a follow-up docs commit).

**Test baseline: 2519 passed / 0 failed / 1 ignored** (was 2509; +4 theme
gates, +6 e2e_pty). `clippy --all-targets -D warnings` + `fmt --check` clean.
Full suite verified green 3× under parallel load on Linux, and a full native
run on **macOS** (5 e2e_pty there — Linux-only RSS test cfg-skipped).

## §2. What shipped

**Palette accessibility (ADR-0057, commit `65eab71`).** Computing real WCAG
ratios while writing the gate **found two shipped defects** in v0.2.0's light
theme — `tok_string` (4.42:1) and `tok_flag` (3.15:1), below the 4.5:1 the
scheme promises — and two dark token pairs that were perceptually close
despite distinct hex. All four fixed (only `theme.rs` colours changed, 4
values). New gated tests in `src/theme.rs`:
- `all_text_colours_meet_wcag_aa_contrast` (≥4.5:1, both themes),
- `advanced_mode_border_meets_ui_contrast` (≥3:1; plain border exempt),
- `delta_e_2000_matches_reference_vectors` (CIEDE2000 validated vs Sharma data),
- `syntax_token_colours_are_perceptually_distinct` (ΔE2000 ≥15).
Dev tool **`scripts/palette-preview.py`** renders the live palette (truecolor
swatch + contrast + ΔE2000), supports `theme:key=HEX` overrides for previewing
changes.

**TT4 — Tier-4 PTY tests (ADR-0008 Amendment 1, commit `fd63de3`).**
`tests/e2e_pty.rs` drives the **real built binary** in a pseudo-terminal:
`portable-pty` 0.9 + `vt100` 0.16 (**`expectrl` dropped** — conflicting PTY
layer; replaced by a hand-rolled `wait_for` on the vt100 grid). 100×30, temp
`--data-dir`, serial, tight 3 s fail-fast waits. The four ADR-0008 flows all
green. Runs by default in `cargo test` → the Linux gate now exercises Tier 4
(**advances TT5**). PTY-in-container validated (openpty+spawn under Docker).
- **Gotchas baked into the harness:** read table presence from the Tables
  **sidebar** region (the Output panel echoes commands, polluting whole-screen
  matches); **pace commands to completion** (a command sent mid-rebuild
  misparses — issue #39); simple-mode insert needs the `values` keyword and a
  single-value insert needs `add column` (a 2nd col in `with pk …` makes a
  **compound PK**).

**NFR verification (ADR-0057).** All seven NFRs formally verified:
- NFR-1/3 **measured** via the PTY harness — release figures **~29 ms** startup
  / **~10 MB** idle RSS (well under 500 ms / 50 MB). Harness tests gate generous
  *debug*-binary bounds for gross-regression detection (tight gates declined as
  flaky — user decision).
- NFR-5/7 **gated** (the contrast/ΔE2000 tests above).
- NFR-2 by architecture (worker thread ADR-0010 + separate input task).
- NFR-4/6 reviewer note (`[/]`).

**CHANGELOG.md** — Keep a Changelog + SemVer; `[Unreleased]` + `[0.2.0]`
(0.1.0 = pre-history). v0.2.0 tag = `bd5be5e`; the palette fix + package
managers + TT4 are post-tag → Unreleased.

## §3. Decisions taken with the user

- Palette: fix the two light contrast bugs **and** the two dark near-duplicates
  (4 hex changes, approved after a rendered preview).
- Borders <3:1 → **accept + document** (decorative chrome).
- Work directly on `main`; ADR-0057 numbered now (not draft).
- NFR perf: measured + generously bounded, **not** tightly CI-gated.
- CHANGELOG depth: 0.2.0 + Unreleased only.
- Schema-cache finding → **file a Gitea issue, defer the fix** (see §4).

## §4. Open / follow-ups

- **Issue #39** (filed this session): simple-mode **Form-B insert**
  (`insert into T values (…)`) submitted faster than the post-DDL **schema-cache
  refresh** validates against stale schema and is misparsed as SQL. No
  interactive-user impact (cast driver + tests pace); deferred fix. Repro +
  diagnosis in the issue.
- **TT5 remaining:** only a **Windows execution runner** now (macOS + Tier-4
  gaps closed this session). First real CI run is the final confirmation that
  the PTY tests pass in the Gitea container (validated locally; very low risk).
- **Next focus is the open issues — see §7** (user direction 2026-06-22: clear
  the open issues before resuming feature work). Larger features (V4 session
  journal, TU1 tutorial) come after. The CHANGELOG can later feed
  `--release-notes-url` into the CI winget job (handoff-75 §6).

## §5. Process pins

- Commits user-confirmed, no AI attribution, append-only, **push is the user's
  step**.
- `/runda` + DA pass was run on both the plan and the implementation (it caught
  the two light-theme contrast bugs and the #39 schema-cache behaviour — both
  before finalizing).
- Consider a `cargo sweep` at this milestone (release build added ~ a GB).

## §6. Post-finalization (same session)

- **macOS fully verified.** A native `cargo test` on macOS was fully green —
  1813 lib + **5 `e2e_pty`** + 500 integration + 200 typing. This **confirms
  Tier 4 on macOS** (the 4 flows + startup; the Linux-only RSS probe is
  `#[cfg]`-skipped, hence 5 not 6). Closes the runda "Tier-4 unverified on macOS"
  item.
- **`fix(tt4)` `1ffe11c`** — the macOS run surfaced a `method `pid` is never
  used` warning: `rss_kib` is Linux-only and was `pid`'s only caller, so off
  Linux it was dead code. The Linux clippy gate can't catch this (pid *is* used
  on Linux). Read `child.process_id()` inline; deleted the helper.
- **Cross-platform crate downloads off-target are normal** — `cargo` fetches the
  whole locked graph (Windows ConPTY bindings, Unix libc/nix from `portable-pty`)
  but only compiles host-target crates; nothing off-target is actually built.
- **TT5 / Windows decision (2026-06-22):** a permanent Windows CI runner stays
  **open, no promises** — standing one up is more involved than the Linux/macOS
  runners already in use. Interim: Windows builds ship every release (D1/D2) and
  are **verified by running the suite on Windows by hand periodically** — the
  same builds Windows users get, manually verified rather than per-push. The TT5
  note was reworded to say this plainly and welcomingly; it stays `[/]` by
  deliberate scope. (Virtualization options explored for a future runner are not
  recorded here — they hinge on host specifics rather than project constraints.)

## §7. Next session — start with the open issues

Per user direction (2026-06-22), the next session should **work the open Gitea
issues before resuming feature work** (V4 journal, TU1 tutorial, etc.). There
are **four open** (`tea issues list --state open --limit 100`; read a body with
`tea issue <n> --fields body --output json < /dev/null | jq -r '.body'`, and
comments with `tea issue <n> --comments < /dev/null`):

| # | Label | One-line | This-session read on scope |
| --- | --- | --- | --- |
| **#36** | enhancement | `help <sql-form>` shows no distinct content — the seven advanced-mode SQL nodes carry `help_id: None` (a dedup hack for the `help` list; `src/dsl/grammar/mod.rs:915-918`), so e.g. `help select` resolves to nothing. The parse-error/usage layer (ADR-0042/H1a) already distinguishes them; only the `help` command lags. | **Contained.** Good first pick — a real, bounded gap. Touches H3/`help`; an ADR amendment may apply. |
| **#37** | enhancement | Clause-concept hints — deeper teaching when the cursor sits inside a recognized *clause* (`on delete ⟨cascade\|set null\|restrict⟩`, the `create table` constraint slots, `with pk`, `1:n`/`m:n`), between tier-2's candidate list and the whole-form tier-3 block. Deferred extension of **ADR-0053** (H2). | **Medium scope, richest teaching value** — squarely on the pedagogy mission. Likely an ADR-0053 amendment. |
| **#38** | enhancement | Pre-submit-diagnostic F1 route + ~33 `diagnostic.*` tier-3 blocks. Needs a `class`/`message_key` field threaded through **every** diagnostic-creation site (walker + validators). Deferred from ADR-0053 Phase C. | **Broad mechanism change for the most marginal value** (tier-2 already surfaces these). The issue itself says so. **Decision needed:** do, defer, or close as wontfix — escalate to the user. |
| **#39** | bug | Simple-mode **Form-B insert** (`insert into T values (…)`) submitted faster than the post-DDL **schema-cache refresh** validates against stale schema → misparsed as SQL. Filed this session; repro + diagnosis (incl. `SchemaCache` at `src/completion.rs:53`, Form-B handling `src/dsl/walker/context.rs:155-157`) in the issue. | **Low impact** (no interactive-user hit; cast driver + tests pace). Fix is its own focused change (sequence the cache refresh with command execution, or validate against the authoritative schema). |

**Suggested order (a recommendation, not a mandate — confirm with the user):**
#36 (contained warm-up) → #37 (highest on-mission value) → #39 (bug; size the fix
first) → #38 (get the user's do/defer/close call before investing in the broad
threading change). All four are hint/help/parse-adjacent except #39; reading
**ADR-0053** (the contextual-hint design) first will orient #37 and #38.

No new labels needed (`bug`/`enhancement` cover them; ask the user before
creating any). Issue-tracker etiquette + `tea` gotchas are in the project
`CLAUDE.md` ("Issue tracking — Gitea via `tea`").
