Files
localgenai/oc-tree/NEXT_STEPS.md

121 lines
4.7 KiB
Markdown
Raw Normal View History

# oc-tree — resumption guide
Open this file first when picking the work back up.
## What this project is
A Python TUI sidecar that subscribes to `opencode serve`'s SSE event
stream and renders a live tree of sessions → messages → tool calls in a
terminal pane next to the opencode TUI. Subagents nest under their
parent via `session.created.info.parentID`.
Roadmap entry: `localgenai/Roadmap.md` → "Layer 0: Cross-cutting
capabilities" → "Observability — partial" + prioritized step #12.
Phoenix (`opencode/.opencode/plugin/phoenix-bridge.js`) already handles
the *external* deep-trace store. oc-tree is the glanceable "what's it
doing right now" pane that lives in-harness (well, in tmux next to it).
## Where we are
- Plan agreed: Python + textual, lives at `localgenai/oc-tree/`.
- Phases: M0 → M1 → M2 → M3 → M4. See descriptions in this repo's task
list (`TaskList`) or the roadmap entry.
- **M0 — DONE** (skeleton). `uv sync` installs cleanly; `oc-tree` and
`oc-tree-probe` entry points resolve. Imports verified.
- **M0 — AWAITING USER ACTION** (schema verification). Probe is built
but hasn't been run against a live `opencode serve`. Three open
schema questions still unanswered.
## What blocks progress
User needs to run the probe against a real opencode session and report
back. Without these answers, M2's reducer design is guesswork.
Run in a tmux pane while `opencode serve` is up:
```sh
cd ~/Documents/obsidian/localgenai/oc-tree
uv run oc-tree-probe
```
Drive opencode through a session that hits **all three** triggers:
- Spawn a Task-tool subagent
- Trigger at least one permission prompt
- Make at least one regular tool call (Read/Bash/etc.)
Ctrl-C the probe. Then run:
```sh
# Q1: does session.created.info.parentID populate for subagents?
jq -r 'select(.type=="session.created") | .raw.properties.info.parentID' \
/tmp/oc-tree-probe.jsonl
# Q2: does message.part.updated carry full part or delta?
jq -c 'select(.type=="message.part.updated") | .raw.properties.part' \
/tmp/oc-tree-probe.jsonl | head
# Q3: what permission.* events actually fire?
jq -r '.type' /tmp/oc-tree-probe.jsonl | grep -i permission | sort -u
```
Paste the output (or the JSONL file path) into the next session.
## What happens next
Once probe answers are in:
1. Mark M0 complete, start **M1 (flat session list)** — textual app,
live-updating list of sessions with status, no nesting yet. Proves
the reducer + render loop. Independent of the schema answers, so
could start in parallel.
2. **M2 (tree view)** — needs probe answers to know:
- Whether to nest by `parentID` directly (Q1 yes) or fall back to
inferring subagents from `Task` tool-part response payloads.
- Whether the part-update reducer replaces by `partID` (Q2 = full
part) or merges a delta (Q2 = delta).
- What permission events to render (Q3).
3. **M3 (reconnect + state rebuild)** — heartbeat watchdog, REST replay
on disconnect. Driven by sst/opencode#15149/#22198 known leaks.
4. **M4 (polish)** — keybindings, theme, tmux layout doc.
## File layout
```
localgenai/oc-tree/
├── pyproject.toml uv project (textual, httpx, httpx-sse)
├── README.md user-facing readme
├── NEXT_STEPS.md this file
├── .python-version 3.11
└── src/oc_tree/
├── client.py OpenCodeClient: REST + SSE
├── probe.py schema-verification CLI
├── __main__.py stub for `oc-tree` (real TUI in M1)
└── widgets/ empty (populated in M1+)
```
## Key references
- opencode server docs: <https://opencode.ai/docs/server/>
- Authoritative schema: `GET /doc` on a running `opencode serve` (do
not hardcode — fetch per-version).
- sst/opencode#7451 — no per-session SSE endpoint; we filter `/event`
client-side.
- sst/opencode#6573 — Task subagent over `opencode serve` may have
bugs; this is what Q1 verifies.
- sst/opencode#11424`message.part.updated` sometimes replays full
state; this is what Q2 verifies.
- sst/opencode#15149, #22198 — SSE disconnect leaks; informs M3
shutdown discipline.
## Decisions worth not relitigating
- **Python + textual** chosen over Go+Bubbletea (faster iteration,
matches stack — uvx already in use) and Node+ink (worse SSE/UI
ergonomics; phoenix-bridge.js doesn't justify matching).
- **Read-only v1.** No sending messages, no editing. Just visibility.
- **Lives in `localgenai/oc-tree/`** rather than its own repo; can be
extracted later if it warrants a standalone release.
- **State rebuild via REST on every (re)connect** rather than trusting
SSE catchup or `Last-Event-ID` (server doesn't honor it).