@osolmaz/pi-workflows 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -21
- package/dist/extension/executor.d.ts +14 -1
- package/dist/extension/executor.js +11 -1
- package/dist/extension/executor.js.map +1 -1
- package/dist/extension/index.js +79 -7
- package/dist/extension/index.js.map +1 -1
- package/dist/extension/recorder.d.ts +85 -0
- package/dist/extension/recorder.js +525 -0
- package/dist/extension/recorder.js.map +1 -0
- package/dist/extension/session-events.d.ts +134 -0
- package/dist/extension/session-events.js +60 -0
- package/dist/extension/session-events.js.map +1 -0
- package/dist/extension/widget.js +25 -24
- package/dist/extension/widget.js.map +1 -1
- package/dist/render/canvas.d.ts +1 -1
- package/dist/render/canvas.js +5 -0
- package/dist/render/canvas.js.map +1 -1
- package/dist/render/graph-render.d.ts +5 -0
- package/dist/render/graph-render.js +211 -48
- package/dist/render/graph-render.js.map +1 -1
- package/dist/viewer/render.js +19 -3
- package/dist/viewer/render.js.map +1 -1
- package/dist/viewer/session-reducer.d.ts +45 -0
- package/dist/viewer/session-reducer.js +266 -0
- package/dist/viewer/session-reducer.js.map +1 -0
- package/dist/workflows/artifacts.d.ts +40 -0
- package/dist/workflows/artifacts.js +155 -0
- package/dist/workflows/artifacts.js.map +1 -0
- package/dist/workflows/engine.d.ts +2 -0
- package/dist/workflows/engine.js +38 -7
- package/dist/workflows/engine.js.map +1 -1
- package/dist/workflows/index.d.ts +3 -2
- package/dist/workflows/index.js +2 -1
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/store.d.ts +53 -9
- package/dist/workflows/store.js +523 -43
- package/dist/workflows/store.js.map +1 -1
- package/dist/workflows/types.d.ts +126 -3
- package/docs/development.md +43 -19
- package/docs/live-replay-protocol.md +155 -0
- package/docs/plans/piw-viewer-experience-implementation-plan.md +674 -0
- package/docs/plans/replayable-run-bundles-implementation-plan.md +65 -0
- package/docs/plans/session-event-replay-implementation-plan.md +494 -0
- package/docs/plans/tui-viewer-implementation-plan.md +64 -0
- package/docs/run-bundles.md +320 -55
- package/docs/session-event-journal.md +470 -0
- package/docs/tui-viewer.md +218 -0
- package/package.json +2 -1
- package/src/extension/executor.ts +28 -1
- package/src/extension/index.ts +87 -7
- package/src/extension/recorder.ts +633 -0
- package/src/extension/session-events.ts +119 -0
- package/src/extension/widget.ts +26 -24
- package/src/render/canvas.ts +19 -1
- package/src/render/graph-render.ts +277 -44
- package/src/viewer/render.ts +21 -3
- package/src/viewer/session-reducer.ts +347 -0
- package/src/workflows/artifacts.ts +188 -0
- package/src/workflows/engine.ts +39 -7
- package/src/workflows/index.ts +15 -0
- package/src/workflows/store.ts +649 -49
- package/src/workflows/types.ts +141 -3
|
@@ -0,0 +1,674 @@
|
|
|
1
|
+
# PIW viewer experience implementation plan
|
|
2
|
+
|
|
3
|
+
## Objective
|
|
4
|
+
|
|
5
|
+
Make `piw` a state-rich, terminal-native workflow viewer with Catppuccin as
|
|
6
|
+
its complete default visual system, a Herdr-style theme picker, clearer replay
|
|
7
|
+
and run states, a useful inspector, a real timeline, and resilient remote
|
|
8
|
+
viewing.
|
|
9
|
+
|
|
10
|
+
The result is verified by styled ratatui buffer tests, graph parity fixtures,
|
|
11
|
+
remote reconnect tests, real-run end-to-end tests, and manual PTY checks across
|
|
12
|
+
dark, light, narrow, and wide terminal layouts.
|
|
13
|
+
|
|
14
|
+
## Boundaries
|
|
15
|
+
|
|
16
|
+
- Keep `piw` a standalone Rust TUI. Do not imitate browser-only effects such
|
|
17
|
+
as shadows, smooth camera animation, or fractional text animation.
|
|
18
|
+
- Do not modify Pi internals or undocumented Pi APIs.
|
|
19
|
+
- Do not write or rewrite Pi session history.
|
|
20
|
+
- Do not change the workflow run-bundle schemas or persisted run documents.
|
|
21
|
+
- Persist only viewer preferences under the user's normal config directory.
|
|
22
|
+
Do not store replay positions, run data, or session data there.
|
|
23
|
+
- Preserve the existing TypeScript/Rust graph layout contract. Any textual or
|
|
24
|
+
geometric graph change must be made in both renderers and reflected in the
|
|
25
|
+
shared fixtures.
|
|
26
|
+
- Keep compact line nodes as an optional density mode; bordered nodes remain
|
|
27
|
+
the default.
|
|
28
|
+
- Keep all remote access loopback-only unless the existing SSH-tunnel workflow
|
|
29
|
+
is used.
|
|
30
|
+
|
|
31
|
+
## Product decisions
|
|
32
|
+
|
|
33
|
+
### Terminal-native ACPX parity
|
|
34
|
+
|
|
35
|
+
Adopt ACPX ideas that improve inspection and state comprehension:
|
|
36
|
+
|
|
37
|
+
- semantic, surface-backed graph nodes;
|
|
38
|
+
- separate running and replay-focus presentation;
|
|
39
|
+
- a visible timeline and playback speed controls;
|
|
40
|
+
- detailed attempt and event inspection;
|
|
41
|
+
- graph-node selection;
|
|
42
|
+
- a collapsible run browser;
|
|
43
|
+
- structured tool-call and tool-result rendering; and
|
|
44
|
+
- reliable live reconnection.
|
|
45
|
+
|
|
46
|
+
Do not adopt ELK, React Flow, browser card decoration, smooth zoom, animated
|
|
47
|
+
edges, multiple ACP-session concepts, or character-by-character replay.
|
|
48
|
+
|
|
49
|
+
### Stable full node cards
|
|
50
|
+
|
|
51
|
+
Box mode is the canonical graph presentation. Each node is a full card with a
|
|
52
|
+
border, an interior surface, and enough padding to keep its outer dimensions
|
|
53
|
+
stable. Compact line mode remains an explicit density option and does not set
|
|
54
|
+
the box-mode contract.
|
|
55
|
+
|
|
56
|
+
The graph computes one card width and one card height before it runs layout.
|
|
57
|
+
Every real node uses those dimensions. The calculation uses the largest card
|
|
58
|
+
required by the immutable definition and reserves fixed rows for every runtime
|
|
59
|
+
field. Shorter cards receive blank padding. A status change, timer tick, new
|
|
60
|
+
attempt, replay seek, selection change, or live event may replace text inside a
|
|
61
|
+
reserved slot, but it must never resize a node or move the graph. Terminal
|
|
62
|
+
resize changes the viewport only. A small viewport pans over the graph instead
|
|
63
|
+
of shrinking or clipping cards.
|
|
64
|
+
|
|
65
|
+
A full card contains the same classes of information as an ACPX workflow card:
|
|
66
|
+
|
|
67
|
+
- the exact node id and full node type;
|
|
68
|
+
- a status symbol with its text label;
|
|
69
|
+
- semantic markers for start, branch count, and terminal position;
|
|
70
|
+
- every branch label associated with the node;
|
|
71
|
+
- not-visited or attempt-count metadata;
|
|
72
|
+
- live elapsed time or final duration; and
|
|
73
|
+
- the complete node `statusDetail` or short terminal outcome when present.
|
|
74
|
+
|
|
75
|
+
Use the established symbols consistently:
|
|
76
|
+
|
|
77
|
+
| Meaning | Symbol |
|
|
78
|
+
| ------------- | ------ |
|
|
79
|
+
| queued | `·` |
|
|
80
|
+
| running | `◐` |
|
|
81
|
+
| replay focus | `◆` |
|
|
82
|
+
| completed | `✓` |
|
|
83
|
+
| failed | `✗` |
|
|
84
|
+
| timed out | `×` |
|
|
85
|
+
| waiting | `⏸` |
|
|
86
|
+
| cancelled | `~` |
|
|
87
|
+
| start node | `▶` |
|
|
88
|
+
| branch node | `◇N` |
|
|
89
|
+
| terminal node | `■` |
|
|
90
|
+
|
|
91
|
+
Node-card fields must not use ellipses or disappear because another state needs
|
|
92
|
+
the space. Long fixed text wraps during the initial card measurement, and all
|
|
93
|
+
nodes are padded to the resulting graph-wide dimensions. Prompts, outputs,
|
|
94
|
+
errors, tool payloads, and other unbounded attempt details remain in the
|
|
95
|
+
inspector; they are not node-card fields.
|
|
96
|
+
|
|
97
|
+
### Theme model
|
|
98
|
+
|
|
99
|
+
Use a purpose-built `piw` theme contract rather than Pi's 51-token theme JSON
|
|
100
|
+
format. `piw` is a standalone viewer and needs graph, timeline, run-state, and
|
|
101
|
+
node-surface tokens that Pi themes do not define.
|
|
102
|
+
|
|
103
|
+
Use the same operating model as Herdr:
|
|
104
|
+
|
|
105
|
+
- Catppuccin Mocha is the default;
|
|
106
|
+
- built-in dark and light themes are selectable;
|
|
107
|
+
- moving through the picker previews immediately;
|
|
108
|
+
- Apply persists the choice;
|
|
109
|
+
- Cancel restores the exact original palette;
|
|
110
|
+
- config and CLI selection are supported; and
|
|
111
|
+
- optional per-token overrides layer on top of a built-in palette.
|
|
112
|
+
|
|
113
|
+
The initial built-in list should match Herdr's user-facing list and names:
|
|
114
|
+
|
|
115
|
+
- `catppuccin`
|
|
116
|
+
- `catppuccin-latte`
|
|
117
|
+
- `terminal`
|
|
118
|
+
- `tokyo-night`
|
|
119
|
+
- `tokyo-night-day`
|
|
120
|
+
- `dracula`
|
|
121
|
+
- `nord`
|
|
122
|
+
- `gruvbox`
|
|
123
|
+
- `gruvbox-light`
|
|
124
|
+
- `one-dark`
|
|
125
|
+
- `one-light`
|
|
126
|
+
- `solarized`
|
|
127
|
+
- `solarized-light`
|
|
128
|
+
- `kanagawa`
|
|
129
|
+
- `kanagawa-lotus`
|
|
130
|
+
- `rose-pine`
|
|
131
|
+
- `rose-pine-dawn`
|
|
132
|
+
- `vesper`
|
|
133
|
+
|
|
134
|
+
Theme names are normalized by lowercasing and replacing spaces and underscores
|
|
135
|
+
with hyphens. Unknown names produce a visible diagnostic and fall back to
|
|
136
|
+
Catppuccin instead of panicking.
|
|
137
|
+
|
|
138
|
+
### Surface hierarchy
|
|
139
|
+
|
|
140
|
+
Every frame must be painted from theme tokens. Do not rely on the terminal's
|
|
141
|
+
default background except in the explicit `terminal` theme.
|
|
142
|
+
|
|
143
|
+
For Catppuccin Mocha, use a clear hierarchy:
|
|
144
|
+
|
|
145
|
+
- application background: Crust (`#11111b`);
|
|
146
|
+
- panel background: Mantle (`#181825`);
|
|
147
|
+
- graph canvas: Base (`#1e1e2e`);
|
|
148
|
+
- ordinary node surface: Surface 0 (`#313244`);
|
|
149
|
+
- selected/running node surface: Surface 1 (`#45475a`);
|
|
150
|
+
- main text: Text (`#cdd6f4`);
|
|
151
|
+
- secondary text: Subtext 0 (`#a6adc8`);
|
|
152
|
+
- muted lines: Overlay 0 (`#6c7086`);
|
|
153
|
+
- accent/running: Blue (`#89b4fa`);
|
|
154
|
+
- replay focus: Mauve (`#cba6f7`);
|
|
155
|
+
- completed: Green (`#a6e3a1`);
|
|
156
|
+
- waiting: Yellow (`#f9e2af`);
|
|
157
|
+
- failed: Red (`#f38ba8`);
|
|
158
|
+
- timed out/interrupted: Peach (`#fab387`);
|
|
159
|
+
- branch/tool accent: Teal (`#94e2d5`).
|
|
160
|
+
|
|
161
|
+
A node box must always have a background distinct from its graph canvas. State
|
|
162
|
+
is carried primarily by the border, glyph, and accent text rather than by
|
|
163
|
+
painting every state a different card color.
|
|
164
|
+
|
|
165
|
+
## Theme architecture
|
|
166
|
+
|
|
167
|
+
### Semantic palette
|
|
168
|
+
|
|
169
|
+
Add `tui/src/theme/` with a `Theme` or `Palette` value containing semantic
|
|
170
|
+
colors rather than component-specific ad hoc styles. At minimum, define:
|
|
171
|
+
|
|
172
|
+
- surfaces: `appBg`, `panelBg`, `canvasBg`, `nodeBg`, `nodeFocusBg`,
|
|
173
|
+
`selectionBg`, `surfaceDim`;
|
|
174
|
+
- structure: `border`, `borderFocused`, `edge`, `edgeBack`, `edgeTaken`;
|
|
175
|
+
- text: `text`, `subtext`, `muted`;
|
|
176
|
+
- interaction: `accent`, `replayFocus`;
|
|
177
|
+
- state: `running`, `success`, `warning`, `error`, `timedOut`, `cancelled`;
|
|
178
|
+
- content: `branch`, `user`, `assistant`, `tool`; and
|
|
179
|
+
- timeline: `timelineTrack`, `timelineFill`, `timelineThumb`.
|
|
180
|
+
|
|
181
|
+
Components must request semantic styles from the active theme. Remove direct
|
|
182
|
+
`Color::Cyan`, `Color::Green`, and similar choices from `tui/src/ui/` and
|
|
183
|
+
`tui/src/ui/conversation.rs`. Literal colors should remain only in built-in
|
|
184
|
+
palette definitions, color parsing, and theme tests.
|
|
185
|
+
|
|
186
|
+
### Canvas roles and node backgrounds
|
|
187
|
+
|
|
188
|
+
The current `CanvasStyle` combines node and edge meanings, and sparse spaces
|
|
189
|
+
cannot carry a background. Replace it with semantic canvas roles that
|
|
190
|
+
separate:
|
|
191
|
+
|
|
192
|
+
- ordinary text;
|
|
193
|
+
- muted text;
|
|
194
|
+
- queued, taken, active, and back edges; and
|
|
195
|
+
- queued, running, replay-focused, completed, failed, timed-out, waiting, and
|
|
196
|
+
cancelled nodes.
|
|
197
|
+
|
|
198
|
+
Add an intentional-space/fill operation to `CharCanvas` so every cell inside a
|
|
199
|
+
bordered node carries `nodeBg` or `nodeFocusBg`. Draw the node surface before
|
|
200
|
+
its border and content, and ensure graph edges cannot bleed through node
|
|
201
|
+
interiors.
|
|
202
|
+
|
|
203
|
+
Node content should use separate roles for the status glyph, node id, node
|
|
204
|
+
type, and metadata instead of applying one color to the whole line. Plain-text
|
|
205
|
+
fixture output must remain deterministic.
|
|
206
|
+
|
|
207
|
+
### Configuration
|
|
208
|
+
|
|
209
|
+
Add viewer configuration at:
|
|
210
|
+
|
|
211
|
+
1. `PIW_CONFIG_PATH`, when set;
|
|
212
|
+
2. `$XDG_CONFIG_HOME/piw/config.toml`; or
|
|
213
|
+
3. `~/.config/piw/config.toml`.
|
|
214
|
+
|
|
215
|
+
Use this shape:
|
|
216
|
+
|
|
217
|
+
```toml
|
|
218
|
+
[theme]
|
|
219
|
+
name = "catppuccin"
|
|
220
|
+
auto_switch = false
|
|
221
|
+
dark_name = "catppuccin"
|
|
222
|
+
light_name = "catppuccin-latte"
|
|
223
|
+
|
|
224
|
+
[theme.custom]
|
|
225
|
+
# canvas_bg = "#1e1e2e"
|
|
226
|
+
# node_bg = "#313244"
|
|
227
|
+
# accent = "#89b4fa"
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Color values accept `#rrggbb`, `#rgb`, `rgb(r,g,b)`, named terminal colors,
|
|
231
|
+
and `reset` aliases. Invalid overrides are reported and ignored individually;
|
|
232
|
+
they do not invalidate the entire theme.
|
|
233
|
+
|
|
234
|
+
Configuration precedence is:
|
|
235
|
+
|
|
236
|
+
1. an explicit picker selection made during the current session;
|
|
237
|
+
2. `--theme <name>`;
|
|
238
|
+
3. `PIW_THEME`;
|
|
239
|
+
4. config file; and
|
|
240
|
+
5. `catppuccin`.
|
|
241
|
+
|
|
242
|
+
Add `--list-themes`. A picker Apply writes only the theme selection, preserves
|
|
243
|
+
unknown config keys and comments, and uses a same-directory temporary file plus
|
|
244
|
+
atomic rename. Applying a manual theme disables `auto_switch`, matching Herdr.
|
|
245
|
+
|
|
246
|
+
Host light/dark detection and automatic sibling switching are a final theme
|
|
247
|
+
phase, not a prerequisite for manual theme selection. When added, query the
|
|
248
|
+
host terminal background only through standard terminal escape sequences,
|
|
249
|
+
restore terminal modes on exit, and retain the manually configured theme when
|
|
250
|
+
the terminal does not answer.
|
|
251
|
+
|
|
252
|
+
### Theme picker
|
|
253
|
+
|
|
254
|
+
Add a modal opened with `,`:
|
|
255
|
+
|
|
256
|
+
- list every built-in theme;
|
|
257
|
+
- show compact color swatches;
|
|
258
|
+
- preview on Up/Down, `j`/`k`, or mouse selection;
|
|
259
|
+
- Apply with Enter;
|
|
260
|
+
- Cancel with Escape and restore the original palette exactly;
|
|
261
|
+
- mark the persisted/current theme with a checkmark; and
|
|
262
|
+
- show config write errors inside the modal without closing it.
|
|
263
|
+
|
|
264
|
+
The modal must be usable at 80x24, clip or scroll at smaller sizes, and paint
|
|
265
|
+
its own panel background. Update the footer help to advertise the picker
|
|
266
|
+
without displacing essential replay controls.
|
|
267
|
+
|
|
268
|
+
## State presentation
|
|
269
|
+
|
|
270
|
+
Replace the current overloaded active state with these distinct graph states:
|
|
271
|
+
|
|
272
|
+
- queued;
|
|
273
|
+
- running;
|
|
274
|
+
- replay focus;
|
|
275
|
+
- completed;
|
|
276
|
+
- failed;
|
|
277
|
+
- timed out;
|
|
278
|
+
- waiting;
|
|
279
|
+
- cancelled.
|
|
280
|
+
|
|
281
|
+
Requirements:
|
|
282
|
+
|
|
283
|
+
- Running uses the active glyph, active color, live elapsed timer, and heavy
|
|
284
|
+
border.
|
|
285
|
+
- Replay focus uses a distinct glyph/color and heavy border, but never says or
|
|
286
|
+
looks like it is currently running.
|
|
287
|
+
- Timed out has a width-stable glyph and the `timedOut` color instead of using
|
|
288
|
+
the failed presentation.
|
|
289
|
+
- Waiting remains distinct.
|
|
290
|
+
- `paused: true` is visible in the graph title and transport even if the run's
|
|
291
|
+
persisted status is `running`.
|
|
292
|
+
- `statusDetail`, `waitingOn`, and run errors are shown consistently without
|
|
293
|
+
overflowing node cells.
|
|
294
|
+
- `(live)`, `(latest)`, and `(replay)` remain separate from the persisted run
|
|
295
|
+
outcome.
|
|
296
|
+
|
|
297
|
+
Where glyph or node text changes affect graph fixture output, update both
|
|
298
|
+
`src/render/` and `tui/src/render.rs`, regenerate the fixtures, and retain
|
|
299
|
+
byte-for-byte plain rendering parity.
|
|
300
|
+
|
|
301
|
+
## Inspector
|
|
302
|
+
|
|
303
|
+
Refactor the inspector out of `tui/src/ui/mod.rs` into focused modules and make
|
|
304
|
+
it useful for debugging without changing bundle data.
|
|
305
|
+
|
|
306
|
+
### Steps
|
|
307
|
+
|
|
308
|
+
- Keep the visible attempt list.
|
|
309
|
+
- Provide summary and expanded detail modes.
|
|
310
|
+
- Render full wrapped prompt, output, and error content in expanded mode.
|
|
311
|
+
- Render complete action receipts: action type, command, arguments, working
|
|
312
|
+
directory, exit code, signal, and duration.
|
|
313
|
+
- Show the selected attempt id and timestamps.
|
|
314
|
+
- Resolve local artifact-backed fields within existing containment and size
|
|
315
|
+
limits.
|
|
316
|
+
- Use a side-by-side attempt-list/detail layout when wide and a stacked layout
|
|
317
|
+
when narrow.
|
|
318
|
+
|
|
319
|
+
### Trace
|
|
320
|
+
|
|
321
|
+
Make trace rows selectable and add three explicit scopes:
|
|
322
|
+
|
|
323
|
+
- selected attempt;
|
|
324
|
+
- replay-visible trace; and
|
|
325
|
+
- full run.
|
|
326
|
+
|
|
327
|
+
For replay-visible trace, derive the cutoff from events associated with the
|
|
328
|
+
visible attempt ids and include run-level events only up to that sequence. The
|
|
329
|
+
full-run mode must be labeled because it can reveal events after the current
|
|
330
|
+
replay position.
|
|
331
|
+
|
|
332
|
+
Enter expands the selected event's sanitized JSON payload. Preserve trace tail
|
|
333
|
+
following only while the user is at the bottom and the scope includes live
|
|
334
|
+
events.
|
|
335
|
+
|
|
336
|
+
### Info
|
|
337
|
+
|
|
338
|
+
Keep and theme the existing run Info tab. Continue showing source, status,
|
|
339
|
+
status detail, error, counts, interruption warning, and final output.
|
|
340
|
+
|
|
341
|
+
Store selection and scroll state per inspector tab so switching tabs does not
|
|
342
|
+
lose the user's place.
|
|
343
|
+
|
|
344
|
+
## Replay timeline
|
|
345
|
+
|
|
346
|
+
Replace the text-only footer with a responsive terminal timeline:
|
|
347
|
+
|
|
348
|
+
- a Unicode track, completed segment, and playhead;
|
|
349
|
+
- `step n/m`, before-first, latest, and LIVE labels;
|
|
350
|
+
- mouse click and drag seeking;
|
|
351
|
+
- previous, play/pause, next, start, and latest hit areas;
|
|
352
|
+
- 1x, 2x, 5x, and 10x playback speeds;
|
|
353
|
+
- the existing `[`, `]`, Space, Home, End, `g`, `G`, and `L` controls; and
|
|
354
|
+
- `{` and `}` for slower/faster playback.
|
|
355
|
+
|
|
356
|
+
Playback remains discrete. At 1x, retain the current 700 ms step interval;
|
|
357
|
+
other speeds divide that interval. Do not synthesize fractional attempt state.
|
|
358
|
+
|
|
359
|
+
Use two footer rows when the terminal has enough height and a compact one-row
|
|
360
|
+
fallback in short terminals. Seeking backward detaches from live; selecting
|
|
361
|
+
latest rejoins live. Appended steps advance automatically only when the viewer
|
|
362
|
+
was already following latest.
|
|
363
|
+
|
|
364
|
+
## Remote reliability and artifacts
|
|
365
|
+
|
|
366
|
+
Refactor `RemoteRuns` into a reconnecting client:
|
|
367
|
+
|
|
368
|
+
- bounded exponential backoff with jitter;
|
|
369
|
+
- explicit connecting, reconnecting, connected, and disconnected states;
|
|
370
|
+
- automatic `watch_runs` and selected-run resubscription after reconnect;
|
|
371
|
+
- existing revision-gap resnapshot behavior;
|
|
372
|
+
- cached data remains visible with a prominent stale/disconnected label; and
|
|
373
|
+
- dropping the client stops and joins the background worker cleanly.
|
|
374
|
+
|
|
375
|
+
Do not treat commands sent while offline as delivered. Keep desired
|
|
376
|
+
subscriptions in shared state and reconcile them after each successful hello.
|
|
377
|
+
|
|
378
|
+
Wire the existing artifact protocol into the inspector. Cache bounded artifact
|
|
379
|
+
content by `(runId, path)`, serialize requests so the current protocol's errors
|
|
380
|
+
can be associated with the outstanding request, and retain path containment
|
|
381
|
+
and maximum-size checks. Do not change the replay protocol schema for this
|
|
382
|
+
feature.
|
|
383
|
+
|
|
384
|
+
## Graph and run-browser interaction
|
|
385
|
+
|
|
386
|
+
### Graph semantics
|
|
387
|
+
|
|
388
|
+
Replace the current one-line box interior with the stable full-card contract.
|
|
389
|
+
Every boxed node shows identity, type, current status, semantic markers, and
|
|
390
|
+
branch labels. It also shows attempt metadata and timing plus the available
|
|
391
|
+
short detail or outcome. The exact node id remains visible.
|
|
392
|
+
|
|
393
|
+
Compute canonical graph-wide card dimensions before placing ranks and routing
|
|
394
|
+
edges. Pass those fixed bounds into layout, drawing, camera targeting, mouse hit
|
|
395
|
+
testing, and edge attachment. Fill unused rows and columns with intentional
|
|
396
|
+
node-surface padding. Live and replay updates redraw card cells without
|
|
397
|
+
re-running layout.
|
|
398
|
+
|
|
399
|
+
Keep branch labels on edges as routing labels and repeat them inside branch
|
|
400
|
+
cards as node metadata, matching ACPX. Show all labels instead of taking a
|
|
401
|
+
fixed prefix.
|
|
402
|
+
|
|
403
|
+
Implement card measurement and rendering in both graph renderers, regenerate
|
|
404
|
+
parity fixtures, and verify that every replay position has identical
|
|
405
|
+
`NodeBounds` for each node.
|
|
406
|
+
|
|
407
|
+
### Graph selection
|
|
408
|
+
|
|
409
|
+
Return node bounds with the rendered canvas. Use those bounds for:
|
|
410
|
+
|
|
411
|
+
- precise active/replay camera targeting instead of searching styled text;
|
|
412
|
+
- mouse hit testing; and
|
|
413
|
+
- selecting the latest visible attempt for a clicked node.
|
|
414
|
+
|
|
415
|
+
A queued node click may focus the definition node but must not invent an
|
|
416
|
+
attempt. Panning and clicking must remain distinguishable by a drag threshold.
|
|
417
|
+
|
|
418
|
+
### Run browser
|
|
419
|
+
|
|
420
|
+
Add expanded and collapsed browser modes:
|
|
421
|
+
|
|
422
|
+
- expanded retains title, status, elapsed time, and interrupted marker;
|
|
423
|
+
- collapsed is a narrow status rail;
|
|
424
|
+
- `b` toggles the mode;
|
|
425
|
+
- a single directly opened run continues to hide the browser; and
|
|
426
|
+
- narrow terminals start collapsed without overwriting an explicit user
|
|
427
|
+
toggle during that session.
|
|
428
|
+
|
|
429
|
+
Theme selected rows with `selectionBg` and preserve a visible status color in
|
|
430
|
+
both modes.
|
|
431
|
+
|
|
432
|
+
## Conversation rendering
|
|
433
|
+
|
|
434
|
+
Keep Pi's recorded session entries and explicit conversation ranges as the
|
|
435
|
+
authoritative source.
|
|
436
|
+
|
|
437
|
+
- Preserve replay-safe progressive reveal; do not show future messages while
|
|
438
|
+
rewound.
|
|
439
|
+
- Preserve the selected attempt's visible gutter.
|
|
440
|
+
- Render tool calls with tool name and a compact argument summary.
|
|
441
|
+
- Render tool results with running/success/error state and a short preview.
|
|
442
|
+
- Let Enter expand the selected tool payload as sanitized JSON.
|
|
443
|
+
- Add sticky live auto-follow: remain at the bottom while new entries arrive,
|
|
444
|
+
detach when the user scrolls upward, and reattach with End.
|
|
445
|
+
- Keep thinking text distinguishable but readable under every built-in theme.
|
|
446
|
+
|
|
447
|
+
Do not add a multiple-session selector; the current bundle contract records one
|
|
448
|
+
Pi conversation per run.
|
|
449
|
+
|
|
450
|
+
## Responsive layout
|
|
451
|
+
|
|
452
|
+
Introduce explicit layout tiers rather than relying only on percentages:
|
|
453
|
+
|
|
454
|
+
- **wide:** run browser, graph, and split attempt detail use available width;
|
|
455
|
+
- **standard:** current graph-over-inspector layout;
|
|
456
|
+
- **narrow:** collapsed browser, compact timeline, and stacked inspector; and
|
|
457
|
+
- **very short:** one-row transport and minimum viable pane titles.
|
|
458
|
+
|
|
459
|
+
Every tier must preserve access to run status, replay position, graph content,
|
|
460
|
+
and inspector tabs. Avoid silently dropping information solely because the
|
|
461
|
+
terminal resized.
|
|
462
|
+
|
|
463
|
+
## Implementation sequence
|
|
464
|
+
|
|
465
|
+
### 1. Theme foundation
|
|
466
|
+
|
|
467
|
+
- Add semantic palette, built-ins, parser, config loader, CLI override, and
|
|
468
|
+
Catppuccin default.
|
|
469
|
+
- Paint the full frame and every panel from palette surfaces.
|
|
470
|
+
- Replace all hard-coded UI colors.
|
|
471
|
+
- Add node-surface canvas roles and filled node rectangles.
|
|
472
|
+
- Add styled buffer tests for Catppuccin and one light theme.
|
|
473
|
+
|
|
474
|
+
Exit criterion: Catppuccin is visibly applied to the whole viewer, and every
|
|
475
|
+
boxed node has a surface color distinct from the graph background.
|
|
476
|
+
|
|
477
|
+
### 2. Theme picker and persistence
|
|
478
|
+
|
|
479
|
+
- Add the `,` modal with preview/apply/cancel and mouse support.
|
|
480
|
+
- Persist atomically while preserving unrelated config.
|
|
481
|
+
- Add all Herdr-aligned built-ins and custom overrides.
|
|
482
|
+
- Add invalid-config diagnostics and `--list-themes`.
|
|
483
|
+
|
|
484
|
+
Exit criterion: a user can preview, cancel, apply, restart, and retain any
|
|
485
|
+
built-in theme.
|
|
486
|
+
|
|
487
|
+
### 3. State correctness
|
|
488
|
+
|
|
489
|
+
- Split running from replay focus.
|
|
490
|
+
- Add timed-out and paused presentation.
|
|
491
|
+
- Apply semantic state colors consistently to graph, run rows, inspector, and
|
|
492
|
+
timeline.
|
|
493
|
+
- Update both renderers and fixtures where plain graph output changes.
|
|
494
|
+
|
|
495
|
+
Exit criterion: no historical replay position appears live, and every persisted
|
|
496
|
+
run/node state has a distinct tested presentation.
|
|
497
|
+
|
|
498
|
+
### 4. Inspector depth
|
|
499
|
+
|
|
500
|
+
- Refactor inspector modules.
|
|
501
|
+
- Add full attempt details and complete action receipts.
|
|
502
|
+
- Add selectable trace scopes and expandable payloads.
|
|
503
|
+
- Preserve per-tab selection and scroll state.
|
|
504
|
+
|
|
505
|
+
Exit criterion: all existing step and trace fields can be inspected without
|
|
506
|
+
opening bundle files manually.
|
|
507
|
+
|
|
508
|
+
### 5. Replay timeline
|
|
509
|
+
|
|
510
|
+
- Add the responsive timeline, hit areas, seeking, and speeds.
|
|
511
|
+
- Keep discrete deterministic playback and live-follow semantics.
|
|
512
|
+
|
|
513
|
+
Exit criterion: keyboard and mouse can seek any recorded step and reliably
|
|
514
|
+
return to live.
|
|
515
|
+
|
|
516
|
+
### 6. Remote resilience
|
|
517
|
+
|
|
518
|
+
- Add reconnect state machine, resubscription, cancellation, and server-restart
|
|
519
|
+
tests.
|
|
520
|
+
- Connect remote artifact fetching to expanded inspector fields.
|
|
521
|
+
|
|
522
|
+
Exit criterion: restarting `piw serve` does not require restarting the viewer,
|
|
523
|
+
and cached data is never presented as current while disconnected.
|
|
524
|
+
|
|
525
|
+
### 7. Graph and browser interaction
|
|
526
|
+
|
|
527
|
+
- Replace one-line boxed interiors with stable full node cards.
|
|
528
|
+
- Measure one canonical card size from all node-card fields before layout.
|
|
529
|
+
- Add node bounds and click selection.
|
|
530
|
+
- Add start/end semantics and branch metadata in both renderers. Include status
|
|
531
|
+
and attempt counts. Timing and the short detail use their own slots.
|
|
532
|
+
- Add collapsed run browser and responsive layout tiers.
|
|
533
|
+
|
|
534
|
+
Exit criterion: every node-card field is visible, node bounds stay unchanged
|
|
535
|
+
across every live and replay state, graph nodes are selectable, and an
|
|
536
|
+
80-column terminal remains usable through panning.
|
|
537
|
+
|
|
538
|
+
### 8. Conversation polish and host-theme switching
|
|
539
|
+
|
|
540
|
+
- Add structured tool rows, expansion, and sticky auto-follow.
|
|
541
|
+
- Add optional host appearance detection and dark/light sibling switching.
|
|
542
|
+
- Verify terminal state restoration after normal exit, errors, and Ctrl-C.
|
|
543
|
+
|
|
544
|
+
Exit criterion: live tool activity remains readable and auto-switching never
|
|
545
|
+
leaves terminal modes or colors altered after exit.
|
|
546
|
+
|
|
547
|
+
## Expected file changes
|
|
548
|
+
|
|
549
|
+
Likely additions:
|
|
550
|
+
|
|
551
|
+
```text
|
|
552
|
+
tui/src/theme/mod.rs
|
|
553
|
+
tui/src/theme/builtins.rs
|
|
554
|
+
tui/src/theme/config.rs
|
|
555
|
+
tui/src/ui/theme_picker.rs
|
|
556
|
+
tui/src/ui/timeline.rs
|
|
557
|
+
tui/src/ui/inspector.rs
|
|
558
|
+
tui/src/ui/runs.rs
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
Likely modifications:
|
|
562
|
+
|
|
563
|
+
```text
|
|
564
|
+
tui/Cargo.toml
|
|
565
|
+
tui/src/main.rs
|
|
566
|
+
tui/src/lib.rs
|
|
567
|
+
tui/src/canvas.rs
|
|
568
|
+
tui/src/render.rs
|
|
569
|
+
tui/src/client.rs
|
|
570
|
+
tui/src/ui/mod.rs
|
|
571
|
+
tui/src/ui/graph.rs
|
|
572
|
+
tui/src/ui/conversation.rs
|
|
573
|
+
src/render/* # only for shared graph text/geometry changes
|
|
574
|
+
fixtures/layout/* # regenerated only when shared output changes
|
|
575
|
+
docs/tui-viewer.md
|
|
576
|
+
docs/development.md
|
|
577
|
+
README.md
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
Avoid leaving theme logic split between components. Palette definitions,
|
|
581
|
+
parsing, resolution, and style derivation belong under `tui/src/theme/`.
|
|
582
|
+
|
|
583
|
+
## Verification
|
|
584
|
+
|
|
585
|
+
### Unit tests
|
|
586
|
+
|
|
587
|
+
- Every built-in theme resolves by canonical name and documented aliases.
|
|
588
|
+
- Catppuccin is the default.
|
|
589
|
+
- Invalid theme names and colors fall back predictably with diagnostics.
|
|
590
|
+
- Config precedence and atomic save behavior are deterministic.
|
|
591
|
+
- Picker preview, Cancel, and Apply preserve the correct palette.
|
|
592
|
+
- Every non-terminal built-in has distinct `canvasBg` and `nodeBg` values.
|
|
593
|
+
- Styled ratatui buffers contain the expected frame, panel, canvas, node, and
|
|
594
|
+
focused-node backgrounds.
|
|
595
|
+
- No state shares the wrong semantic role, especially failed/timed-out and
|
|
596
|
+
running/replay-focus.
|
|
597
|
+
- Timeline coordinate mapping is correct at step `-1`, first, middle, latest,
|
|
598
|
+
and after terminal resize.
|
|
599
|
+
- Trace replay cutoffs cannot reveal later attempt events.
|
|
600
|
+
- Node hit testing accounts for viewport offsets.
|
|
601
|
+
- Every boxed node in one graph has the same outer dimensions.
|
|
602
|
+
- Node bounds remain identical across every runtime state. Selection and replay
|
|
603
|
+
focus also leave the bounds unchanged.
|
|
604
|
+
- Long node ids, status details, and branch labels wrap without truncation and
|
|
605
|
+
without changing the graph-wide card size after layout.
|
|
606
|
+
- Every documented status and semantic symbol appears with the matching text
|
|
607
|
+
label and color role.
|
|
608
|
+
|
|
609
|
+
### Integration tests
|
|
610
|
+
|
|
611
|
+
- Existing plain graph parity fixtures are regenerated for the full-card
|
|
612
|
+
geometry and continue to match between TypeScript and Rust.
|
|
613
|
+
- Shared fixtures assert identical node bounds at every replay position.
|
|
614
|
+
- Theme changes do not alter plain fixture output unless an intentional shared
|
|
615
|
+
graph change updates both renderers.
|
|
616
|
+
- A remote client reconnects after a server restart and receives a fresh
|
|
617
|
+
snapshot.
|
|
618
|
+
- Subscription changes made while disconnected are reconciled after reconnect.
|
|
619
|
+
- Local and remote expanded artifact views enforce the same size and path
|
|
620
|
+
limits.
|
|
621
|
+
- Narrow and wide TestBackend layouts retain all required controls.
|
|
622
|
+
|
|
623
|
+
### Manual PTY checks
|
|
624
|
+
|
|
625
|
+
Exercise at least:
|
|
626
|
+
|
|
627
|
+
- Catppuccin Mocha at 80x24 and 140x40;
|
|
628
|
+
- Catppuccin Latte on a light terminal;
|
|
629
|
+
- `terminal` theme with a custom terminal palette;
|
|
630
|
+
- a completed run, a live run, a waiting run, a timed-out run, and a cancelled
|
|
631
|
+
run;
|
|
632
|
+
- replay before the first step, detached replay, and return to live;
|
|
633
|
+
- theme preview followed by Cancel and Apply;
|
|
634
|
+
- a stopped and restarted remote server; and
|
|
635
|
+
- tool calls, action receipts, long output, and artifact-backed values;
|
|
636
|
+
- a graph containing every node state and semantic symbol; and
|
|
637
|
+
- long ids, status details, and branch labels in an 80-column viewport.
|
|
638
|
+
|
|
639
|
+
### Repository checks
|
|
640
|
+
|
|
641
|
+
Before finishing each coherent implementation slice, run the relevant focused
|
|
642
|
+
Rust tests. Before finishing the complete work, run:
|
|
643
|
+
|
|
644
|
+
```bash
|
|
645
|
+
cargo fmt --check --manifest-path tui/Cargo.toml
|
|
646
|
+
cargo clippy --manifest-path tui/Cargo.toml --all-targets -- -D warnings
|
|
647
|
+
cargo test --manifest-path tui/Cargo.toml
|
|
648
|
+
npm run check
|
|
649
|
+
npm run test:e2e
|
|
650
|
+
npx slophammer-ts@latest dry .
|
|
651
|
+
npx slophammer-ts@latest check . --only ts.dependency-boundaries-required
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
## Completion criteria
|
|
655
|
+
|
|
656
|
+
The work is complete when:
|
|
657
|
+
|
|
658
|
+
1. Catppuccin Mocha is the default and colors every visible viewer surface.
|
|
659
|
+
2. Boxed nodes are full cards with one stable graph-wide size, intentional
|
|
660
|
+
padding, and every documented card field visible without truncation.
|
|
661
|
+
3. Users can preview, apply, persist, and cancel built-in theme choices from
|
|
662
|
+
the TUI.
|
|
663
|
+
4. No component chooses ad hoc colors outside the theme layer.
|
|
664
|
+
5. Running, replay focus, completed, failed, timed out, waiting, cancelled,
|
|
665
|
+
paused, latest, replay, and live states are unambiguous.
|
|
666
|
+
6. Full attempt, action, trace, run, and conversation details are inspectable.
|
|
667
|
+
7. The timeline supports keyboard and mouse seeking plus playback speeds.
|
|
668
|
+
8. Remote viewing reconnects safely and labels stale cached data.
|
|
669
|
+
9. Graph selection and the collapsed browser work in narrow terminals.
|
|
670
|
+
10. Node status and semantic markers use the documented ACPX-style slots and
|
|
671
|
+
symbols. Attempt counts and timing use reserved slots, as do short details,
|
|
672
|
+
without changing node bounds.
|
|
673
|
+
11. Graph parity, bundle schemas, Pi session state, and Pi internals remain
|
|
674
|
+
unchanged except for intentional shared renderer fixture updates.
|