1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
|
# Visual review
## Contrast choices and local collapse
The fifteen native palettes now give comments vivid color and keep line
numbers subdued. The current number uses muted ink and bold weight instead
of a tag-colored background block, in SDL and TTY. Active pane and column
tags use a small tonal shift without reversing their light/dark polarity.
Column tag text starts at the column edge without the former two-cell inset.
Forge has neutral coal
and silver-blue chrome. `forge_black` and `orchard_black` use pure black;
`forge_soft` joins `dusk`, `lagoon` and `solarium` as deliberately softer
alternatives. Light and Acme-inspired choices remain available.
`Themes` opens with the native collection, followed by a separate legacy
and imported section. Keyboard navigation skips both section headings.
`Collapse` now transfers all released rows to one expanded pane, preferring
the nearest one above and falling back below. Unrelated pane heights stay
unchanged. Expansion borrows from one neighbor too, limited by its available
body space. Tests cover exact unchanged sibling rectangles, repeated inverse
toggles, already-folded neighbors, tiny resizes, drag expansion and Dump/Restore.
The refreshed builds pass 791 TTY and 822 SDL unit tests, with one skipped
in each suite, plus all 98 interaction snapshots. Snapshot review found only
the intended style changes, the expanded grouped theme picker, and flush-left
column text/carets (including newly visible text in one- and two-cell columns).
The isolated 9P harness `test/collapse_layout.py` passes seven collapse/expand
pairs on each host, checking rendered tag boundaries and unchanged contents.
The live OS gallery checks all fifteen native themes for bold current-line
numbers, unchanged gutter backgrounds and no active-tag polarity inversion.
Both hosts pass all twelve column input checks, including first-cell execution,
editing and caret reveal. Agave source bytes stay unchanged and no input is
sent to the user's session.
- [Six contrast studies, OS screenshot crops](screenshots/theme-preferences.png)
- [Neutral Forge, full workspace](screenshots/theme-preferences-forge.png)
- [Native-first Themes, full workspace](screenshots/theme-selector.png)
## Compact rails, classic palettes and workspace pets
`New` now belongs to column tags only. Pane tags keep their local save,
terminal and close actions: `Tty` opens a terminal, and `Mode`
cycles raw input, normal editing and insert mode. Historical
default pane tails upgrade during Restore; explicitly customized text remains
owned by the user.
SDL paints adjacent tag backgrounds to their full row height, leaving only
the thin separator. Square scroll markers share the column's left edge, and
a one-pixel continuous line joins its column tag, pane tags and bodies.
Pointer targets and the TTY grid are unchanged.
`Font MartianMono-NrRg:18` now applies both face and size. The isolated
`test/font_size.py` checks startup sizing, fractional sizing, retaining the
size when omitted, and rejecting invalid requests without partial changes.
Six [classic-inspired themes](typ/themes.typ) add `forge`, `lagoon`, `solarium`,
`spectrum`, `harvest` and `clay`. ANSI colors retain their terminal meanings
instead of borrowing a similarly positioned syntax color. Optional SDL
`Pet cat` and `Pet frog` companions walk, idle and reverse in the unused
workspace tag; `Pet off` is the default. Editing that tag hides the pet.
The original pixel sprites use no external assets or input handlers.
`test/appearance_gallery.py` recreates a two-column Agave review with stacked
right-hand panes, an embedded terminal, Font 18 and TaglineSize 80. It checks
all six new themes, font and pet reports, changing pet frames, and unchanged
Agave source bytes. Its `--live-window` mode captures the owned SDL window
through the OS, identified by its child PID. It never resizes or sends input
to the user's existing Pardes window.
- [Compact columns, native OS capture](screenshots/compact-columns.png)
- [Six classic adaptations, screenshot contact sheet](screenshots/classic-themes.png)
- [Cat and frog, enlarged nearest-neighbor screenshot crops](screenshots/pets.png)
- [Gallery checks](screenshots/classic-gallery.json)
The full suites passed 807 SDL and 776 TTY tests, with one skipped in each;
all 97 interaction snapshots passed. A private mount namespace redirected
test-only `/tmp` writes after the host's temporary-file quota was exhausted,
without deleting files or changing the user's `/tmp`. These counts include
the pet/geometry/font/command changes; palette corrections additionally pass
the native contrast tests.
## PDF and terminal tag cleanup
PDFs now use `filename.pdf [page/total] Tty Del PdfSections PdfTint Collapse`,
keeping sections and tint commands visible without the long generated
control/status prefix. Terminal tags include `Mode`, which cycles the body mode
even when invoked from an edited tag. Ctrl-B keeps its two-way toggle.
`test/tag_cleanup.py` verifies the compact PDF tag, middle-click `Mode`, Ctrl-B,
and tag-edit/Tab execution through real host input and 9P observations on both
SDL and TTY. The PDF source stays unchanged. The full unit suites pass 773 TTY
tests and 797 SDL tests; SDL image/PDF and Kitty PDF rendering harnesses pass.
[Native PDF and terminal screenshot](screenshots/pdf-and-tty-tags.png).
## Column and editable-tag follow-up
The follow-up adds editable workspace and column command rows, compact pane
tags, staged buffer-name edits, and caret reveal for long tags. See [editable tags](typ/guide.typ) for the
exact interaction and save-target rules.
`test/column_tags.py` exercises isolated SDL and TTY sessions against the same
Agave source. It sends actual host input bytes while observing through 9P:
header typing and selection replacement, UTF-8 deletion, inactive-column
`New`/`Tty`, pane-tail edits, filename cancellation, terminal input, and
custom-tag Dump/Restore. Source bytes remain unchanged. Input goes through
the host PTY parser; compact SDL pixel coordinates are covered separately by
round-trip mapping tests, not claimed as physical SDL mouse automation.
All 11 live checks passed on each frontend. All 7,200 foreground/background
cells and 48 text rows matched for the three final frames after normalizing
only the isolated `ct-sdl`/`ct-tty` directory names.
The screenshots below are native GPU captures, after removing test-only
Unicode markers through normal tag editing. The tested CJK text has correct
grid/editing behavior, but the selected font lacks its glyph; this is not
claimed as complete font-fallback coverage.
- [Two-column Orchard workspace](screenshots/columns-orchard.png)
- [Two-column Atelier workspace](screenshots/columns-atelier.png)
- [Long tag revealing its actions and caret](screenshots/columns-tag-reveal.png)
- [Final SDL/TTY parity evidence](screenshots/columns-parity.json)
The final unit suites passed 771 TTY tests and 795 SDL tests. Native image and PDF harnesses
passed, including continuous PDF layout and reload. The PDF fixture gains one
screen row to preserve its original document area; its pixel assertions are
unchanged.
Existing terminal snapshots were migrated by adding one screen row and moving
pane mouse coordinates down one row, preserving their original body area.
Raw SGR mouse sequences were migrated too. The tag-padding/name/navigation
fixtures were explicitly rewritten for the new behavior. Review found 86
fixtures with identical text tokens after removing the new column row and
normalizing spacing; the remaining differences were reviewed for tag edits,
nested editor chrome, resize handles, and debug overlays. All 97 scripts
passed both when regenerating the reviewed goldens and in a subsequent
independent run with retries disabled.
## Initial palette pass
The UI pass was exercised against Agave's real `gossip/src/crds_value.rs`,
using isolated named Pardes sessions and the existing Python 9P client.
The workflow opened Find and Grep results, ran harmless commands in an
embedded terminal, requested Rust document symbols and hover, and sent `gd`
through the host's actual terminal input parser. Agave source bytes were
checked unchanged after the session.
Native SDL screenshots use the GPU capture path. TTY captures contain the
real core grid and its styles; they are not screenshots of an independent
terminal emulator. Resolving cells to their grapheme, foreground and
background yielded **7,200 of 7,200 matching cells** at 150 × 48 for each of
`orchard`, `dusk`, `ink`, `paper`, `daybreak`, and `atelier`.
Rust-analyzer returned 52 document-symbol rows and one definition result.
The initial baseline hover timed out; the updated run returned no hover
text for the declaration. No hover popup is claimed as verified. Agave's
gossip crate is feature-gated, and workspace loading was still substantial;
the exact cause of that empty result was not established.
## Reproduce
Run from the Pardes checkout, using an existing SDL binary and an Agave
checkout. The output directory is private and also holds isolated startup
configuration. ImageMagick and an X11 display are required for PNG captures;
the LSP pass additionally needs rust-analyzer (located through rustup unless
`--rust-analyzer` is supplied).
```sh
python3 -B test/ui_review.py zig-out/ui-review/bin/pardes-gui \
/tmp/pardes-ui-review --project /path/to/agave \
--theme orchard --themes orchard dusk ink paper daybreak atelier
```
For subsequent palette captures, add `--skip-lsp`. To repeat LSP work without
rebuilding dependencies, use `--cargo-target /path/to/previous/cargo-target`.
Cargo runs offline and stores build output in that isolated directory.
For the TTY pass, use the TTY binary and add `--tty`. The script requires
Find/Grep results and observed terminal output, fails missing or malformed
SDL captures, and writes `report.json` with the actual outcomes. LSP absence
or failure is recorded separately rather than passing as a successful popup.
Review artifacts from this pass:
- [Baseline workspace](screenshots/before.png)
- [Orchard: mild dark](screenshots/orchard.png)
- [Dusk: warm dark](screenshots/dusk.png)
- [Ink: high contrast dark](screenshots/ink.png)
- [Paper: mild light](screenshots/paper.png)
- [Daybreak: high contrast light](screenshots/daybreak.png)
- [Atelier: Acme homage](screenshots/atelier.png)
- [Cell parity evidence](screenshots/parity.json)
- [Actual Rust LSP responses](screenshots/agave-lsp.txt)

## Regression checks
Both native binaries built in ReleaseFast. The full TTY and SDL unit suites
passed with the inherited nesting variables `PARDES_PID`, `PARDES_9P`
and `PARDES_PANE` removed from the test process. Those variables exposed an
existing environment-ownership issue in native subprocess tests: libc's
environment was changed while the Zig test I/O retained the old slice. This
pass does not change that environment code or skip the affected tests.
The appearance checks cover native palette contrast, old ThemeFile documents,
wrapped search matches, selection precedence, immediate body colors during
theme fades, light-theme carets and both quiet and bold syntax preferences.
The 9P walkthrough also verifies `FocusTint` and `SyntaxBold` through `DumpConfig`.
All 97 terminal snapshot scripts passed without retries after reviewing and
refreshing 32 appearance goldens. Of those, 27 preserve identical visible text,
cursor positions and grid geometry; the remaining five contain the new default
theme name or the expanded theme list. SDL image and PDF harnesses also passed,
including continuous PDF layout and idle document reload. The PDF color fixture
explicitly selects legacy `helix` to preserve its fixed pixel expectations.
## Possible interaction follow-ups
These were not needed for the appearance pass:
- A way to reveal an abbreviated pane path on demand could recover title
space in deep workspaces. The full path should remain selectable and
available to Look; replacing it outright would weaken an existing workflow.
- Show a query's busy state until its response arrives, and distinguish an
empty answer from a timeout. The first full-workspace Rust hover provided
little visible feedback while indexing; explicit status would tell users
whether to wait or change their selection. This needs clear cancellation
and stale-response behavior before changing the interaction.
|