docs: session handoff 63 + ADR-0046 marked implemented (#20/#21/#23)
ADR-0046 status -> Accepted + implemented (8 commits 9f5f76b..22bec61); README index updated; the two draft-divergent decisions recorded inline (App.relationships not SchemaCache; nav overlay partial-clear + gutter). Handoff 63 covers the full UI build across Phases A/B/C; issues #20/#21/#23 closed on Gitea.
This commit is contained in:
@@ -2,12 +2,21 @@
|
|||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
Accepted (2026-06-10); **implementation pending**, phased **A → B → C**
|
Accepted (2026-06-10); **implemented 2026-06-10**, phased **A → B → C**
|
||||||
(see *Decision — phasing*). Closes Gitea issues **#20** (hint-panel
|
(see *Decision — phasing*) across commits `9f5f76b` (DA1/DA2) · `e0b9470`
|
||||||
height jumpiness), **#21** (database-structure / left-column
|
(DA3) · `41bae99` (DA4) · `386627a` (DB1) · `94825d0` (DB2/DB4) ·
|
||||||
improvements), and **#23** (long command input). Issue #23's own note
|
`c9da6ff` (DC1/DC2/DC4) · `22bec61` (DC3 + DC2 refinement). Closes Gitea
|
||||||
("handle after #21 is decided") is honoured: the input work is split so
|
issues **#20** (hint-panel height jumpiness), **#21** (database-structure
|
||||||
the part that depends on the sidebar's width budget lands with it.
|
/ left-column improvements), and **#23** (long command input). Issue
|
||||||
|
#23's own note ("handle after #21 is decided") is honoured: the input
|
||||||
|
work is split so the part that depends on the sidebar's width budget
|
||||||
|
lands with it.
|
||||||
|
|
||||||
|
Two decisions landed differently from the original draft and are
|
||||||
|
recorded inline: the relationship data lives on **`App`, not
|
||||||
|
`SchemaCache`** (DB2), and the navigation overlay clears **only the
|
||||||
|
sidebar strip + a one-column gutter** (panels stay visible behind),
|
||||||
|
not the whole area (DC2).
|
||||||
|
|
||||||
Builds on and honours: **ADR-0003** (the persistent Simple/Advanced
|
Builds on and honours: **ADR-0003** (the persistent Simple/Advanced
|
||||||
mode model — navigation mode is *not* a third input mode, see DC1),
|
mode model — navigation mode is *not* a third input mode, see DC1),
|
||||||
|
|||||||
+1
-1
@@ -51,4 +51,4 @@ This directory contains the project's ADRs, recorded per
|
|||||||
- [ADR-0043 — Compound-primary-key foreign-key references (T3)](0043-compound-pk-foreign-key-references.md) — **Accepted + implemented 2026-06-09** (all four forks confirmed at the recommended option: full-PK matching, house-style uniform lists, parenthesized DSL syntax, bare-SQL-FK auto-expansion). Closes `requirements.md` **T3** `[x]` — the relationship model went list-based across six layers (single-column preserved, no migration), DSL `from P.(a,b) to C.(x,y)` + SQL `FOREIGN KEY (a,b) REFERENCES P(x,y)` parse/execute/enforce, 12 tests in `tests/it/compound_fk.rs`. Closes the open leg of `requirements.md` **T3**: a foreign key that *references* a parent's compound primary key. A 2026-06-09 audit found single-column FK woven through ~15–20 sites (metadata table, `RelationshipSchema`, `project.yaml` `RawEndpoint`, both grammar surfaces, executor FK-DDL emission, per-column type-compat, display) — earns an ADR, not an inline build. **Decision:** reference the parent's **full** compound PK, matched **positionally** to an equal-length child column list, per-pair `fk_target_type` compat (ADR-0011, element-wise); DSL `from <P>.(a, b) to <C>.(x, y)` (single form unchanged), SQL `FOREIGN KEY (x, y) REFERENCES P(a, b)` (extend the existing one-cap lists; bare table-level FK auto-expands to the parent PK when arities match). **Storage — no migration (back-compat not required, user-confirmed 2026-06-09; no installed base):** the relationship endpoint joins the list convention `project.yaml` *already* uses — `columns: [a, b]` like `primary_key: [id]` and index `columns: [...]` (the endpoint was the lone scalar `column:` holdout); the metadata `TEXT` columns are unchanged and store the list **comma-joined** (`a,b`; the bare name for single — safe because identifiers are `[A-Za-z0-9_]+`). No F3 migrator, no version bump; accepted trade-off is that a pre-change `project.yaml` with relationships won't load (clean cutover). In-memory model goes list-based (`Vec<String>`) through all six layers; the enforced FK is the rebuilt child-table DDL (`FOREIGN KEY (a,b) REFERENCES P(x,y)`), one relationship = one undo step (ADR-0013). Genuine forks escalated: matching policy (full-PK vs subset), storage (house-style uniform lists vs normalized table), DSL syntax (parenthesized vs repeated-dotted), bare-SQL-FK auto-expansion. OOS: subset/non-PK (UNIQUE-targeted) FK references; any single-column behaviour change
|
- [ADR-0043 — Compound-primary-key foreign-key references (T3)](0043-compound-pk-foreign-key-references.md) — **Accepted + implemented 2026-06-09** (all four forks confirmed at the recommended option: full-PK matching, house-style uniform lists, parenthesized DSL syntax, bare-SQL-FK auto-expansion). Closes `requirements.md` **T3** `[x]` — the relationship model went list-based across six layers (single-column preserved, no migration), DSL `from P.(a,b) to C.(x,y)` + SQL `FOREIGN KEY (a,b) REFERENCES P(x,y)` parse/execute/enforce, 12 tests in `tests/it/compound_fk.rs`. Closes the open leg of `requirements.md` **T3**: a foreign key that *references* a parent's compound primary key. A 2026-06-09 audit found single-column FK woven through ~15–20 sites (metadata table, `RelationshipSchema`, `project.yaml` `RawEndpoint`, both grammar surfaces, executor FK-DDL emission, per-column type-compat, display) — earns an ADR, not an inline build. **Decision:** reference the parent's **full** compound PK, matched **positionally** to an equal-length child column list, per-pair `fk_target_type` compat (ADR-0011, element-wise); DSL `from <P>.(a, b) to <C>.(x, y)` (single form unchanged), SQL `FOREIGN KEY (x, y) REFERENCES P(a, b)` (extend the existing one-cap lists; bare table-level FK auto-expands to the parent PK when arities match). **Storage — no migration (back-compat not required, user-confirmed 2026-06-09; no installed base):** the relationship endpoint joins the list convention `project.yaml` *already* uses — `columns: [a, b]` like `primary_key: [id]` and index `columns: [...]` (the endpoint was the lone scalar `column:` holdout); the metadata `TEXT` columns are unchanged and store the list **comma-joined** (`a,b`; the bare name for single — safe because identifiers are `[A-Za-z0-9_]+`). No F3 migrator, no version bump; accepted trade-off is that a pre-change `project.yaml` with relationships won't load (clean cutover). In-memory model goes list-based (`Vec<String>`) through all six layers; the enforced FK is the rebuilt child-table DDL (`FOREIGN KEY (a,b) REFERENCES P(x,y)`), one relationship = one undo step (ADR-0013). Genuine forks escalated: matching policy (full-PK vs subset), storage (house-style uniform lists vs normalized table), DSL syntax (parenthesized vs repeated-dotted), bare-SQL-FK auto-expansion. OOS: subset/non-PK (UNIQUE-targeted) FK references; any single-column behaviour change
|
||||||
- [ADR-0044 — Relationship visualization (two-table connector diagrams)](0044-relationship-visualization.md) — **Accepted 2026-06-09; implemented 2026-06-10** (closes `requirements.md` V1; second `/runda` pass over the implementation; §3 last-resort helper line considered and rejected). Resolves **ADR-0016 OOS-1** and closes the open half of `requirements.md` **V1** ("a selected relationship as two tables joined by a line"). Renders a relationship as **Style A** (two structure boxes + connector). **Reach = "relationship-relevant"** (user-chosen over global / show-only): diagrams on the surfaces where the relationship is the *subject* — `show relationship <name>` (one full diagram), `show table <T>` (T's structure box then a **Relationships** section of **stacked compact** per-relationship diagrams — chosen over a focal-centred subgraph: no crossing lines, scales via scroll, two-boxes-wide fits any terminal), and relationship DDL echoes (`add`/`drop`/`modify relationship`); incidental DDL echoes (`add column`, `drop index`, `change column`, plain `create table`) keep the terse prose, via a `Diagram`|`Prose` render mode on `render_structure`. Reading convention **child(FK)-left / parent-right, arrow →, `n`…`1` cardinality**, applied uniformly; every box gets a **bold title row + rule** so the name can't read as a column. **Compound FKs** (ADR-0043) route one connector per positional pair + an explicit pairing line. **Width-aware** (first in the codebase) but **App-side**: `render_structure`/diagram rendering runs in `app.rs` (the worker only returns `TableDescription`s), a new `App::last_output_width` (set from `ui.rs`) drives side-by-side vs a **vertical-stack** fallback + last-resort "run `show relationship`" pointer; rendered once at command time, **no live reflow** (V4). `show relationship`'s worker path (`do_show_one`, prose-only) is restructured to return both endpoint `TableDescription`s. Styling reuses **ADR-0028** App-side styled runs (new classes: table-name/key/connector/cardinality/action) — no worker→UI contract change. **Partially supersedes ADR-0016 §5** (prose block replaced on relationship-subject surfaces, retained on incidental ones); extends §4 (layout width-awareness, still no cell truncation) and §6 (per-span theming). Tests: insta snapshots (single, compound, vertical fallback, helper line, self-referential, multi-rel `show table`) + width-threshold/routing unit tests + Tier-3 wiring; enumerated prose-fallout updates (`output_render.rs:121/135/793`, the relationships snapshot, `walking_skeleton.rs:477/530`). A `/runda` DA pass corrected three inverted-architecture claims (App-side rendering, untracked width, prose-in-worker show-relationship) before acceptance. OOS: user-configurable display setting (OOS-7), live reflow (V4), whole-DB ER export (V3), m:n (C4), ASCII fallback (ADR-0016 OOS-5)
|
- [ADR-0044 — Relationship visualization (two-table connector diagrams)](0044-relationship-visualization.md) — **Accepted 2026-06-09; implemented 2026-06-10** (closes `requirements.md` V1; second `/runda` pass over the implementation; §3 last-resort helper line considered and rejected). Resolves **ADR-0016 OOS-1** and closes the open half of `requirements.md` **V1** ("a selected relationship as two tables joined by a line"). Renders a relationship as **Style A** (two structure boxes + connector). **Reach = "relationship-relevant"** (user-chosen over global / show-only): diagrams on the surfaces where the relationship is the *subject* — `show relationship <name>` (one full diagram), `show table <T>` (T's structure box then a **Relationships** section of **stacked compact** per-relationship diagrams — chosen over a focal-centred subgraph: no crossing lines, scales via scroll, two-boxes-wide fits any terminal), and relationship DDL echoes (`add`/`drop`/`modify relationship`); incidental DDL echoes (`add column`, `drop index`, `change column`, plain `create table`) keep the terse prose, via a `Diagram`|`Prose` render mode on `render_structure`. Reading convention **child(FK)-left / parent-right, arrow →, `n`…`1` cardinality**, applied uniformly; every box gets a **bold title row + rule** so the name can't read as a column. **Compound FKs** (ADR-0043) route one connector per positional pair + an explicit pairing line. **Width-aware** (first in the codebase) but **App-side**: `render_structure`/diagram rendering runs in `app.rs` (the worker only returns `TableDescription`s), a new `App::last_output_width` (set from `ui.rs`) drives side-by-side vs a **vertical-stack** fallback + last-resort "run `show relationship`" pointer; rendered once at command time, **no live reflow** (V4). `show relationship`'s worker path (`do_show_one`, prose-only) is restructured to return both endpoint `TableDescription`s. Styling reuses **ADR-0028** App-side styled runs (new classes: table-name/key/connector/cardinality/action) — no worker→UI contract change. **Partially supersedes ADR-0016 §5** (prose block replaced on relationship-subject surfaces, retained on incidental ones); extends §4 (layout width-awareness, still no cell truncation) and §6 (per-span theming). Tests: insta snapshots (single, compound, vertical fallback, helper line, self-referential, multi-rel `show table`) + width-threshold/routing unit tests + Tier-3 wiring; enumerated prose-fallout updates (`output_render.rs:121/135/793`, the relationships snapshot, `walking_skeleton.rs:477/530`). A `/runda` DA pass corrected three inverted-architecture claims (App-side rendering, untracked width, prose-in-worker show-relationship) before acceptance. OOS: user-configurable display setting (OOS-7), live reflow (V4), whole-DB ER export (V3), m:n (C4), ASCII fallback (ADR-0016 OOS-5)
|
||||||
- [ADR-0045 — `create m:n relationship` convenience command (C4)](0045-mn-convenience.md) — **Accepted + implemented 2026-06-10** (closes `requirements.md` **C4**; all forks user-confirmed + a `/runda` DA pass that verified the `do_create_table` reuse against code and corrected the "no PK-less tables" assumption — advanced SQL `create table t (a int)` has none, so a parent-PK guard is retained). Implementation corrected a second ADR premise: "the walker already dispatches multiple nodes per entry word" held only in *advanced* mode — two simple-mode spots (dispatcher `decide`, completion continuation-merge) assumed ≤1 DSL form per entry word and were generalized **behaviour-preservingly** (dispatch reduces to the old single-candidate commit; completion merge gated on `simple_count > 1`). Junction echo wired (`render_create_m2n`, round-trips as SQL). `create m:n relationship from <T1> to <T2> [as <name>]` generates a junction table with one FK column per parent PK column, a **compound PK over all the FK columns** (the textbook junction — the pair is unique, no duplicate links), and **two 1:n relationships**, all in **one transaction = one undo step** (built by reusing `do_create_table`, which already takes `foreign_keys` + writes relationship metadata — no batch bracketing). Forks all user-chosen: junction PK = compound-over-FKs (vs surrogate serial / no PK); referential actions = **`CASCADE`** on delete+update (vs NO ACTION / RESTRICT); naming = auto `{T1}_{T2}` + optional `as` (vs auto-only); available in **both modes** (Simple-category DSL, like the sibling relationship commands). FK columns named `{parent_table}_{pk_column}` (disambiguates shared `id`; generalises to compound parents via ADR-0043), typed via `fk_target_type` (ADR-0011). A distinct `Command::CreateM2nRelationship` (not lowered to `CreateTable`) preserves command identity (X5) and lets the teaching echo speak in m:n terms. Cross-cutting wiring enumerated: separate `CREATE_M2N` `CommandNode` (own `help_id`/`usage_ids`), `("m","m:n")` completion composite, `HintMode`s, grammar-driven highlighting, `help`/`help create`, `parse_error_pedagogy` near-miss matrix, teaching echo. OOS: **self-referential m:n** (`from T to T`) refused outright (user-confirmed "full stop" — directional column-naming is more than this beginner convenience warrants); per-relationship action overrides; extra junction payload columns; m:n diagram echo; renaming the auto-generated relationships
|
- [ADR-0045 — `create m:n relationship` convenience command (C4)](0045-mn-convenience.md) — **Accepted + implemented 2026-06-10** (closes `requirements.md` **C4**; all forks user-confirmed + a `/runda` DA pass that verified the `do_create_table` reuse against code and corrected the "no PK-less tables" assumption — advanced SQL `create table t (a int)` has none, so a parent-PK guard is retained). Implementation corrected a second ADR premise: "the walker already dispatches multiple nodes per entry word" held only in *advanced* mode — two simple-mode spots (dispatcher `decide`, completion continuation-merge) assumed ≤1 DSL form per entry word and were generalized **behaviour-preservingly** (dispatch reduces to the old single-candidate commit; completion merge gated on `simple_count > 1`). Junction echo wired (`render_create_m2n`, round-trips as SQL). `create m:n relationship from <T1> to <T2> [as <name>]` generates a junction table with one FK column per parent PK column, a **compound PK over all the FK columns** (the textbook junction — the pair is unique, no duplicate links), and **two 1:n relationships**, all in **one transaction = one undo step** (built by reusing `do_create_table`, which already takes `foreign_keys` + writes relationship metadata — no batch bracketing). Forks all user-chosen: junction PK = compound-over-FKs (vs surrogate serial / no PK); referential actions = **`CASCADE`** on delete+update (vs NO ACTION / RESTRICT); naming = auto `{T1}_{T2}` + optional `as` (vs auto-only); available in **both modes** (Simple-category DSL, like the sibling relationship commands). FK columns named `{parent_table}_{pk_column}` (disambiguates shared `id`; generalises to compound parents via ADR-0043), typed via `fk_target_type` (ADR-0011). A distinct `Command::CreateM2nRelationship` (not lowered to `CreateTable`) preserves command identity (X5) and lets the teaching echo speak in m:n terms. Cross-cutting wiring enumerated: separate `CREATE_M2N` `CommandNode` (own `help_id`/`usage_ids`), `("m","m:n")` completion composite, `HintMode`s, grammar-driven highlighting, `help`/`help create`, `parse_error_pedagogy` near-miss matrix, teaching echo. OOS: **self-referential m:n** (`from T to T`) refused outright (user-confirmed "full stop" — directional column-naming is more than this beginner convenience warrants); per-relationship action overrides; extra junction payload columns; m:n diagram echo; renaming the auto-generated relationships
|
||||||
- [ADR-0046 — Schema sidebar focus/navigation mode and responsive input & hint layout (UI #20/#21/#23)](0046-sidebar-navigation-and-responsive-input-hint.md) — **Accepted 2026-06-10; implementation pending, phased A→B→C** (closes Gitea **#20** hint jumpiness, **#21** left-column improvements, **#23** long input — all forks user-confirmed, including the persistent show/hide toggle which is **deferred**: the Ctrl-O peek covers #21's "keystroke to show and hide"). Treats the three UI issues as one coupled decision because they share the terminal's width/height budget. **Phase A (input & hint):** the hint panel's height becomes a function of **terminal geometry, fixed between resizes** (not of hint content), eliminating the #20 jump at its source — measured catalog shows ≥ ~54-col right-column width never needs > 2 hint lines, so 3 lines is a rare narrow-terminal-only case; height buckets `H<40` compact (input 1 row + horizontal scroll / hint 2) vs `H≥40` comfortable (input 2 rows soft-wrap / hint 2), output `Min(5)` honoured first under degradation; input gains horizontal scroll (`input_scroll_offset`, single logical `String` — **not** I1 multi-line) and 2-row soft-wrap display when tall, preserving ADR-0027's 6-col indicator reserve. **Phase B (sidebar):** the 26-col Tables column is **kept but made optional and richer** (not deleted — pedagogy wins ties) — **width-derived session-only** visibility (visible iff width > 90 or a Ctrl-O peek is active — no stored field; hides at width ≤ 90 so the 90-col screencasts drop it; ADR-0015 format untouched), plus a **relationships panel** rendered narrow with endpoints broken at the arrow, ellipsized — a **separate sibling panel** that **overrides S2**'s nested-list extension model (relationships are cross-table). the full records live on a new **`App.relationships`** field (revised from the ADR's original `SchemaCache.relationship_details` at implementation — `SchemaCache` is walker-facing and needs only the names, kept in `relationships: Vec<String>`; details are UI-only, so `App` mirrors `app.tables` and avoids ~23 fixture edits), delivered by `Database::read_all_relationships` + an `AppEvent::RelationshipsRefreshed`; the two left panels split vertically with the relationships panel floored at 5 rows ("(none)" when empty) and capped at 50 % of the column (DB4). **Phase C (navigation mode):** **`Ctrl-O`** enters a focus cycle (Input → Tables → Relationships → Input; `Esc` exits) orthogonal to the ADR-0003 input mode — **`Ctrl-B` was rejected on review as the default tmux prefix** (unreachable inside tmux); the focused panel **expands to ~40–50 cols as a `Clear` overlay** (right panels stay unchanging underneath) and scrolls via **Up/Down (line) + PageUp/PageDown (page)** (context-rebind, reusing the output-scroll viewport mechanism), with an accent focus border; all non-nav keys inert in nav mode (and nav keys inert while a modal is open). Forks all user-chosen: keep-optional-richer (vs remove/narrow); navigation-mode (vs modeless modifier scroll); `Ctrl-O` (Ctrl-B rejected = tmux prefix); overlay (vs layout re-split); inert-non-nav-keys; geometry-fixed hint height; `H<40/≥40` thresholds; session-only persistence; Up/Down line-scroll; **separate relationships panel overriding S2**; **no hint-area toggle** (S4's stale "keyboard-toggleable" claim struck — never implemented, unwanted). A pre-build `/runda` DA pass drove these corrections: caught the `Ctrl-B`/tmux collision, the `SchemaCache` retype that would have broken completion, the 2-row-input/indicator placement, the missing nav-mode key disposition + modal gate, and three unreferenced requirements (S1 evolved, S2 overridden, S4 corrected); also cross-checked open issue **#22** (overlay/annotation layer — separate ADR, adjacent). OOS: true multi-line input (I1); readline shortcuts (I1b); cross-session sidebar persistence; output as a third nav focus; relationship search/edit from the panel; hint-area toggle; #22's annotation layer. Accepted consequence: the 90-col visibility threshold makes a terminal's output *narrower* when widened across the boundary (sidebar appears)
|
- [ADR-0046 — Schema sidebar focus/navigation mode and responsive input & hint layout (UI #20/#21/#23)](0046-sidebar-navigation-and-responsive-input-hint.md) — **Accepted + implemented 2026-06-10, phased A→B→C** (8 commits `9f5f76b`…`22bec61`; closes Gitea **#20** hint jumpiness, **#21** left-column improvements, **#23** long input — all forks user-confirmed, including the persistent show/hide toggle which is **deferred**: the Ctrl-O peek covers #21's "keystroke to show and hide"). Two decisions landed differently from the draft (recorded inline): relationship data on **`App`** not `SchemaCache` (DB2); the nav overlay clears **only the sidebar strip + a one-column gutter**, panels staying visible behind (DC2). Treats the three UI issues as one coupled decision because they share the terminal's width/height budget. **Phase A (input & hint):** the hint panel's height becomes a function of **terminal geometry, fixed between resizes** (not of hint content), eliminating the #20 jump at its source — measured catalog shows ≥ ~54-col right-column width never needs > 2 hint lines, so 3 lines is a rare narrow-terminal-only case; height buckets `H<40` compact (input 1 row + horizontal scroll / hint 2) vs `H≥40` comfortable (input 2 rows soft-wrap / hint 2), output `Min(5)` honoured first under degradation; input gains horizontal scroll (`input_scroll_offset`, single logical `String` — **not** I1 multi-line) and 2-row soft-wrap display when tall, preserving ADR-0027's 6-col indicator reserve. **Phase B (sidebar):** the 26-col Tables column is **kept but made optional and richer** (not deleted — pedagogy wins ties) — **width-derived session-only** visibility (visible iff width > 90 or a Ctrl-O peek is active — no stored field; hides at width ≤ 90 so the 90-col screencasts drop it; ADR-0015 format untouched), plus a **relationships panel** rendered narrow with endpoints broken at the arrow, ellipsized — a **separate sibling panel** that **overrides S2**'s nested-list extension model (relationships are cross-table). the full records live on a new **`App.relationships`** field (revised from the ADR's original `SchemaCache.relationship_details` at implementation — `SchemaCache` is walker-facing and needs only the names, kept in `relationships: Vec<String>`; details are UI-only, so `App` mirrors `app.tables` and avoids ~23 fixture edits), delivered by `Database::read_all_relationships` + an `AppEvent::RelationshipsRefreshed`; the two left panels split vertically with the relationships panel floored at 5 rows ("(none)" when empty) and capped at 50 % of the column (DB4). **Phase C (navigation mode):** **`Ctrl-O`** enters a focus cycle (Input → Tables → Relationships → Input; `Esc` exits) orthogonal to the ADR-0003 input mode — **`Ctrl-B` was rejected on review as the default tmux prefix** (unreachable inside tmux); the focused panel **expands to ~40–50 cols as a `Clear` overlay** (right panels stay unchanging underneath) and scrolls via **Up/Down (line) + PageUp/PageDown (page)** (context-rebind, reusing the output-scroll viewport mechanism), with an accent focus border; all non-nav keys inert in nav mode (and nav keys inert while a modal is open). Forks all user-chosen: keep-optional-richer (vs remove/narrow); navigation-mode (vs modeless modifier scroll); `Ctrl-O` (Ctrl-B rejected = tmux prefix); overlay (vs layout re-split); inert-non-nav-keys; geometry-fixed hint height; `H<40/≥40` thresholds; session-only persistence; Up/Down line-scroll; **separate relationships panel overriding S2**; **no hint-area toggle** (S4's stale "keyboard-toggleable" claim struck — never implemented, unwanted). A pre-build `/runda` DA pass drove these corrections: caught the `Ctrl-B`/tmux collision, the `SchemaCache` retype that would have broken completion, the 2-row-input/indicator placement, the missing nav-mode key disposition + modal gate, and three unreferenced requirements (S1 evolved, S2 overridden, S4 corrected); also cross-checked open issue **#22** (overlay/annotation layer — separate ADR, adjacent). OOS: true multi-line input (I1); readline shortcuts (I1b); cross-session sidebar persistence; output as a third nav focus; relationship search/edit from the panel; hint-area toggle; #22's annotation layer. Accepted consequence: the 90-col visibility threshold makes a terminal's output *narrower* when widened across the boundary (sidebar appears)
|
||||||
|
|||||||
@@ -0,0 +1,159 @@
|
|||||||
|
# Session handoff — 2026-06-10 (63)
|
||||||
|
|
||||||
|
Sixty-third handover. Continues from handoff-62 (C4 m:n + #19). This
|
||||||
|
was a **single-ADR, full-build session**: it designed and implemented
|
||||||
|
**ADR-0046** end to end — the UI work for the three sidebar/input
|
||||||
|
issues **#20 / #21 / #23**, all now **closed** on Gitea.
|
||||||
|
|
||||||
|
## §1. State at handoff
|
||||||
|
|
||||||
|
**Branch:** `main`. **HEAD `22bec61`** (plus an uncommitted docs
|
||||||
|
finalization — ADR status flip + this handoff — see §7). Push is the
|
||||||
|
user's step.
|
||||||
|
|
||||||
|
**Tests: 2263 passing / 0 failing / 1 ignored** (the 1 ignored is the
|
||||||
|
long-standing doc-test). **Clippy clean** (nursery, all targets). +26
|
||||||
|
over the handoff-62 baseline of 2237.
|
||||||
|
|
||||||
|
**This session's commits** (8 + the docs finalization):
|
||||||
|
```
|
||||||
|
22bec61 feat(ui): scroll the focused sidebar panel + refine the nav overlay (DC3 + DC2)
|
||||||
|
c9da6ff feat(ui): Ctrl-O navigation mode — peek + expand the schema sidebar (DC1/DC2/DC4)
|
||||||
|
94825d0 feat(ui): relationships sidebar panel + schema data (DB2/DB4)
|
||||||
|
386627a feat(ui): width-derived sidebar visibility — hide at <=90 cols (DB1)
|
||||||
|
41bae99 feat(ui): two-row input display on tall terminals (DA4)
|
||||||
|
e0b9470 feat(ui): horizontal-scroll long input so the cursor stays visible (DA3)
|
||||||
|
9f5f76b fix(ui): geometry-fixed hint-panel height kills the typing jump (DA1/DA2)
|
||||||
|
93266b9 docs: ADR-0046 UI sidebar nav-mode + responsive input/hint
|
||||||
|
```
|
||||||
|
|
||||||
|
**Issues closed:** **#20**, **#21**, **#23** (all via ADR-0046).
|
||||||
|
**#22** (in-app overlay/keystroke-annotation layer for casts/lessons)
|
||||||
|
remains **open** — its own future ADR; adjacent but out of scope here.
|
||||||
|
|
||||||
|
## §2. What shipped — ADR-0046 (read it; it's the source of truth)
|
||||||
|
|
||||||
|
Three coupled UI issues, treated as one decision because they share the
|
||||||
|
terminal width/height budget. Phased A → B → C.
|
||||||
|
|
||||||
|
**Phase A — input & hint (#20, #23).**
|
||||||
|
- **DA1/DA2 (#20):** the Hint panel height is now a pure function of
|
||||||
|
terminal geometry (`hint_rows` → later `panel_heights`), **fixed
|
||||||
|
between resizes** — it no longer resizes as you type, killing the
|
||||||
|
jump. Compact (`<40` rows) = hint 2; comfortable = hint 2, or 3 only
|
||||||
|
when the column is narrow (`inner < 54`). This **reverses issue #12's**
|
||||||
|
shrink-to-content sizing (its two tests were replaced by an anti-jump
|
||||||
|
invariant). Long hints ellipsize at the fixed budget.
|
||||||
|
- **DA3 (#23):** long input **horizontally scrolls** to keep the cursor
|
||||||
|
visible (`input_scroll_offset`, pure `input_scroll_offset()` helper),
|
||||||
|
with muted `<` / `>` edge markers; resets on submit / history.
|
||||||
|
Preserves ADR-0027's 6-col indicator reserve.
|
||||||
|
- **DA4 (#23):** on a tall terminal (`>=40` rows) the input renders
|
||||||
|
across **two visual rows** (soft-wrap of the single logical line;
|
||||||
|
indicator stays on row 1). Distinct from deferred multi-line **I1**;
|
||||||
|
`expand_runs_to_cells` is the substrate I1 should reuse.
|
||||||
|
|
||||||
|
**Phase B — the sidebar (#21).**
|
||||||
|
- **DB1:** the left column is **width-optional** — `sidebar_visible() =
|
||||||
|
width > 90`, so it's hidden at <=90 (the 90-col screencasts) and the
|
||||||
|
right column takes the full width. (Resize a terminal below ~90 to see
|
||||||
|
it; in a normal wide terminal it shows, by design.)
|
||||||
|
- **DB2/DB4:** a **Relationships panel** stacks below Tables — each
|
||||||
|
relationship is name + endpoints broken at the arrow
|
||||||
|
(`Customers.id ->` / indented `Orders.customer_id`), ellipsized. The
|
||||||
|
panel floors at 5 rows ("(none)") and grows to a 50%-of-column cap
|
||||||
|
(`relationships_panel_height`). **Overrides S2** (relations were to be
|
||||||
|
*nested* in the tables list; a sibling panel is the honest shape).
|
||||||
|
|
||||||
|
**Phase C — navigation mode (#21).**
|
||||||
|
- **DC1/DC4:** **`Ctrl-O`** enters a navigation mode orthogonal to the
|
||||||
|
input mode, cycling focus **Input → Tables → Relationships → Input**
|
||||||
|
(`Esc` exits). It's routed in the main key handler *after* the modal
|
||||||
|
gate, so it's inert behind a modal; in nav mode every non-nav key is
|
||||||
|
inert (the input is occluded). `NavFocus` enum on `App`.
|
||||||
|
- **DC2:** the focused panel is revealed (peek, even when width-hidden)
|
||||||
|
and drawn as a **45-col expanded overlay**, clearing the sidebar strip
|
||||||
|
**+ a one-column gutter** and leaving the base output/input/hint
|
||||||
|
visible (unchanged) to the right. *(Two variants were eyeballed; this
|
||||||
|
partial-clear-with-gutter was chosen over a full-area clear.)*
|
||||||
|
- **DC3:** the focused panel **scrolls** — Up/Down by a line,
|
||||||
|
PageUp/PageDown by its visible rows; per-panel offsets clamped to
|
||||||
|
content at render time, mirroring the output-panel scroll.
|
||||||
|
|
||||||
|
**`Ctrl-B` was rejected** for nav mode (it's the tmux prefix →
|
||||||
|
unreachable inside tmux); `Ctrl-O` is multiplexer-safe.
|
||||||
|
|
||||||
|
## §3. Two decisions that landed differently from the draft
|
||||||
|
|
||||||
|
Both recorded inline in the ADR (and called out in its Status):
|
||||||
|
1. **Relationship data on `App`, not `SchemaCache`** (DB2). `SchemaCache`
|
||||||
|
is walker/completion-facing and needs only relationship *names*
|
||||||
|
(untouched); the full records are UI-only, so `App.relationships`
|
||||||
|
mirrors `app.tables`, and it avoided editing ~23 `SchemaCache`
|
||||||
|
literals. Delivered via `Database::read_all_relationships` (new worker
|
||||||
|
request) + `AppEvent::RelationshipsRefreshed` from the runtime's
|
||||||
|
schema refresh.
|
||||||
|
2. **Nav overlay = partial clear + 1-col gutter** (DC2), not a full-area
|
||||||
|
clear — truer to "underneath keeps its layout."
|
||||||
|
|
||||||
|
## §4. Process notes
|
||||||
|
|
||||||
|
- **The pre-build `/runda` pass earned its keep again.** It caught the
|
||||||
|
`Ctrl-B`/tmux collision, a `SchemaCache` retype that would have broken
|
||||||
|
completion, the 2-row-input/indicator placement, the missing nav-mode
|
||||||
|
key disposition + modal gate, and **three unreferenced requirements**
|
||||||
|
(S1 evolved, S2 overridden, S4 corrected — `requirements.md` updated).
|
||||||
|
- **Snapshot discipline:** DB1's 90-col threshold collided with the
|
||||||
|
test-suite's 80-col convention — many snapshots/tests were retuned
|
||||||
|
(sidebar-dependent ones now render at 110; input tests at narrower
|
||||||
|
widths so the now-wider input still overflows). One masked-intent
|
||||||
|
integration check (matched "Customers" in output, not the panel) was
|
||||||
|
corrected.
|
||||||
|
- Each phase was committed green + clippy-clean, user-confirmed message,
|
||||||
|
no AI attribution, append-only.
|
||||||
|
|
||||||
|
## §5. Requirements / S-items touched
|
||||||
|
|
||||||
|
`requirements.md` annotated: **S1** (three-region layout → left region
|
||||||
|
width-optional), **S2** (*overridden* — relationships get a sibling
|
||||||
|
panel, not nested), **S4** (*corrected* — the "keyboard-toggleable" hint
|
||||||
|
claim was never implemented and is struck; the panel is always-on).
|
||||||
|
|
||||||
|
## §6. Remaining open landscape (unchanged from handoff-62, minus the closed items)
|
||||||
|
|
||||||
|
1. **TT5 CI** — test infra solid (2263 green); no pipeline. Gitea Actions
|
||||||
|
/ Woodpecker decision + likely a Linux-first scope call.
|
||||||
|
2. **SD1 `seed`** then **H2 `hint`** — the two unblockers for **A1**
|
||||||
|
app-commands; both net-new, own ADR. SD1 should seed m:n junctions.
|
||||||
|
3. **V2/S3 multi-result tabs** or **V4 journal** — larger output-model
|
||||||
|
redesign, design-first, own ADR.
|
||||||
|
4. **C3a modify relationship** — small follow-up (drop+add covers it).
|
||||||
|
5. **#22 overlay/annotation layer** — own ADR; shares the cast + overlay
|
||||||
|
space with DC2 (designed to coexist).
|
||||||
|
6. **Tutorial/lesson system** — acknowledged in scope; needs its own ADR.
|
||||||
|
|
||||||
|
**ADR-0046 OOS (deferred):** true multi-line input (I1); readline
|
||||||
|
shortcuts (I1b); cross-session sidebar persistence; a persistent
|
||||||
|
show/hide toggle (Ctrl-O peek covers it); output as a third nav focus;
|
||||||
|
relationship search/edit from the panel; a hint-area toggle.
|
||||||
|
|
||||||
|
## §7. How to take over
|
||||||
|
|
||||||
|
1. Read handoffs 61 → 62 → 63, then `CLAUDE.md`, `docs/requirements.md`,
|
||||||
|
`docs/adr/README.md`, and **ADR-0046** (fully landed).
|
||||||
|
2. **Pending:** an uncommitted docs finalization (ADR-0046 status →
|
||||||
|
*implemented*; README index status; this handoff). Commit it as
|
||||||
|
`docs: session handoff 63` (the user confirms commit messages).
|
||||||
|
3. **For UI/layout work:** `src/ui.rs` now has `panel_heights`,
|
||||||
|
`sidebar_visible`, `relationships_panel_height`, the nav overlay, and
|
||||||
|
`&mut App` sidebar panels (they report scroll viewports). `App` gained
|
||||||
|
`input_scroll_offset`, `nav_focus`, `relationships`, and the
|
||||||
|
`tables_scroll` / `relationships_scroll` (+ `last_*_visible`) fields.
|
||||||
|
4. **For relationship/schema-cache work:** relationship *names* are in
|
||||||
|
`SchemaCache.relationships` (completion); full records are on
|
||||||
|
`App.relationships` via `Database::read_all_relationships` +
|
||||||
|
`RelationshipsRefreshed`.
|
||||||
|
5. **Eyeball reminder honoured:** the user reviewed the nav overlay
|
||||||
|
appearance and chose the partial-clear + 1-col-gutter variant.
|
||||||
|
6. Run a `cargo sweep` at some point — `target/` has grown across this
|
||||||
|
build-heavy session.
|
||||||
Reference in New Issue
Block a user