Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@

## 0.2.3 (unreleased)

- **The inspector shows the whole field now, and pages through it.** It used to cap each field
at a fixed 8 (Payload) / 10 (Result) / 14 (Text) lines whatever the terminal, so a tall
window sat half empty under a dead `… 61 more lines (y to copy)`, and it had no scroll state
at all.
- The window is sized from the terminal, so a taller terminal shows more with no keys at all.
- `PgUp` / `PgDn` page it — no focus mode, since `j`/`k` must keep choosing which row the
inspector is describing. The foot of the pane reads `12–40 of 118 · PgUp/PgDn · y copy ·
I full`, and the offset resets when you move to another row.
- `shift+i` opens the inspector **full screen** (and from closed, opens it there directly);
`esc` returns it to the side pane. A ~40-column pane is not a JSON viewer, so this is the
"show me all of it" answer; `y` remains the answer for actually reading a large payload
somewhere with search and folding.
- **Fixed:** below 110 columns the side pane does not fit, and `i` flipped a flag that rendered
nothing and gave no feedback — the inspector was simply dead on an 80-column terminal. It now
opens full screen there, which is what DESIGN.md §7.1 promised and never shipped.

- **Turns and Calls drew the same chart.** The lane modes only ever differed by one blank cell
at each turn boundary — everything else (which events, which lanes, glyphs, colours) was
identical, so switching between them looked like nothing happened. Checking DeepSeek Harness
Expand Down
26 changes: 25 additions & 1 deletion DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,8 @@ the branch structure (ancestry axis). That is the layout:
size, red if error). Cursor position is mirrored in the lanes;
- **inspector on the right = DSH inspector**: Summary / Payload / Result / Schema /
Timing / Crop for the selected row; toggled with `i`; below 110 columns it becomes a
full-screen view instead (this is `pi-context-tree`'s *inspect* view).
full-screen view instead (this is `pi-context-tree`'s *inspect* view) — **implemented in
0.2.3**, along with `shift+i` to ask for it on any width and `PgUp`/`PgDn` to page it.

### 7.2 Mockup (≥110 columns)

Expand Down Expand Up @@ -611,6 +612,29 @@ how the Turns/Calls bug shipped.
the inspector's *Crop* facet explains protection (latest per tool, current turn,
decision, `keep` glob).


**Reading a long field (0.2.3).** The inspector used to cap each field at a fixed 8 / 10 / 14
lines whatever the terminal, ending in a dead `… 61 more lines (y to copy)`; it had no scroll
state at all, and below 110 columns `i` flipped a flag that rendered nothing and said nothing.
Three changes, in the order they matter:

1. **The caps follow the pane.** Every line is materialised (bounded by `INSPECTOR_MAX_LINES`
only so a pathological payload cannot build an unbounded array per render) and the *window*
is sized from `height()`, so a tall terminal simply shows more instead of leaving the pane
half empty under a truncation notice.
2. **`PgUp` / `PgDn` page it**, with no focus mode: `j`/`k` must keep driving the row selection,
because that is what chooses the inspector's content, and a focus concept would add modality
to a route that has none. `core/navigation.ts#paneWindow`/`scrollPane` hold the arithmetic
(clamped in the getter, so a resize or a shorter row cannot strand the view past the end);
the foot of the pane reads `12–40 of 118 · PgUp/PgDn · y copy · I full`. The offset resets
when the selected row changes — new content, new top.
3. **`shift+i` is full screen**, and is also what `i` does below 110 columns. A ~40-column pane
is not a JSON viewer; this is the "view all of it" answer, and it retires the narrow-terminal
dead end in the same mechanism.

`y` stays the answer for actually *reading* a large payload — copy it somewhere with search and
folding. The scroller is for "there were twelve more lines and I want to glance at them".

### 7.5 Filters and search (from Pi)

`f` cycles `default → no-tools → user-only → labeled → all` (default hides
Expand Down
5 changes: 3 additions & 2 deletions docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ OpenCode storage — off by default); `keybinds` overrides any route key by comm
e.g. `{ "keybinds": { "open": "ctrl+t", "up": "k,up", "copy": "none" } }` — names are
`open up down jump_up jump_down half_up half_down first last prev_branch next_branch fold
unfold toggle go branch label filter_pick filter_prev search search_next search_prev back
crop crop_toggle_mode mark auto undo merge inspector consumers copy mode_duration mode_turns
lanes_off decisions export help`.
crop crop_toggle_mode mark auto undo merge inspector inspector_full inspector_up inspector_down
consumers copy mode_duration mode_turns lanes_off decisions export help`.

## Upgrading

Expand Down Expand Up @@ -113,6 +113,7 @@ appended to the trunk as a normal message.*
| `D` `E` | decisions panel, export `ctree-decisions.md` |
| `s` | consumers: what is filling the context (`⏎` opens a bucket, `space` marks one entry for crop) |
| `i` | inspector pane on/off (auto-hidden under 110 columns) |
| `i` `I` `PgUp` `PgDn` | inspector in the side pane / full screen; page through a long payload or result. The pane shows every line it has, sized to your terminal, with `12–40 of 118` at the foot when there is more; `y` copies the untruncated text. Below 110 columns the side pane does not fit, so `i` opens full screen directly |
| `1 2` `0` | timeline lanes, x-axis by duration / one cell per event; `0` off. `│` marks a turn boundary, and the lanes show whatever the `f` filter shows — so `f` → `tools-only` is the "what did I run" view in both the rows and the lanes |
| `L` | label the selected message |
| `f` `F` | filter picker (default → no-tools → user-only → labeled → all); `F` steps back |
Expand Down
22 changes: 22 additions & 0 deletions src/core/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,25 @@ export function resolveSelection(

return land(0)
}

/**
* Window into a scrollable pane (the inspector, DESIGN.md §7.4): `room` lines drawn out of
* `total`, starting at `top`. `start` is clamped so the last page sits flush with the end
* rather than scrolling past it into blank space, and never below 0 when the content is
* shorter than the pane. `from`/`to` are 1-based and inclusive, for a `12–40 of 118` readout.
*
* Clamping lives here, not in the setter, so a resize or a shorter row cannot strand the view
* past the end of the new content.
*/
export function paneWindow(total: number, room: number, top: number): { start: number; from: number; to: number } {
const r = Math.max(1, room)
const start = Math.max(0, Math.min(Math.max(0, Math.floor(top)), total - r))
return { start, from: total === 0 ? 0 : start + 1, to: Math.min(total, start + r) }
}

/** One page up or down, overlapping by two lines so the eye keeps its place. */
export function scrollPane(total: number, room: number, top: number, dir: 1 | -1): number {
const r = Math.max(1, room)
const step = Math.max(1, r - 2)
return paneWindow(total, r, paneWindow(total, r, top).start + dir * step).start
}
Loading
Loading