diff --git a/design/vscode/00-overview.html b/design/vscode/00-overview.html new file mode 100644 index 0000000..3a767a1 --- /dev/null +++ b/design/vscode/00-overview.html @@ -0,0 +1,471 @@ + + + + + +ZO · VS Code — Overview + + + + +
+ +
+ +

ZO in VS Code — the mockups

+

+ Static, browser-viewable design mockups for the ZO VS Code extension: + a headless tmux engine rendered through xterm.js, in place of raw panes. + Toggle each page dark or light. Every screen depicts one canonical + moment of the public MNIST demo, mid-training. +

+
+ Canonical moment + mnist-digit-classifier + · + workflow deep_learning + · + tmux zo-mnist-20260712-091412 + · + phase_4 active + · + exp-003 epoch 6/8 + · + val_acc 0.9871 +
+
+ + +
+ 01 — Process +

How to review

+

+ Eight screens, one run. Nothing here is code yet: this set is the + approval artifact before the first extension PR lands. +

+
+
+ 1 +

Open each screen

+

Pages 01 through 08, in order. Each stands alone in a browser at desktop width.

+
+
+ 2 +

Toggle themes

+

The light/dark button, top right of every page. Both renders must hold; terminals stay dark by design.

+
+
+ 3 +

Read the notes

+

Implementation notes at each page's foot tie every region to its data source. Engineers build from these.

+
+
+ 4 +

Mark up changes

+

Annotate anything to change now. Approval here freezes the design for the build PRs.

+
+
+
+ + +
+ 02 — Index +

The screens

+

+ Each page isolates one surface of the extension and shows its states. + All eight depict the same moment of the MNIST run, so a detail seen on + one screen can be traced across the others. +

+ +
+ + +
+ 03 — Scope +

What ships in v1, what waits

+

+ The line is drawn at watching and steering. v1 renders every stream + read-only and routes all input through explicit commands; anything + that would require owning the TTY waits. +

+
+
+
Ships in v1PR D2+
+
    +
  • + Read-only terminal streams + composer + Pane logs rendered in xterm.js; typed input routed through zo runtime send, never a raw TTY. +
  • +
  • + One-click gates + Approve, reject, or iterate from the card, the toast, or the palette; drives /gates:approve and /gates:reject. +
  • +
  • + Comms feed + The agent conversation as a filterable event stream over the comms JSONL. +
  • +
  • + Training dashboard + Curves, checkpoints, and lineage projected from per-experiment metrics files. +
  • +
  • + Start-run form + zo build flags as a form, with live command preview and preflight. +
  • +
  • + Reattach + Reopen VS Code, rediscover the live tmux session from .zo/runtime/session.json, catch up from STATE.md. +
  • +
+
+
+
DeferredPost-v1
+
    +
  • + Per-keystroke TTY passthrough + Fully interactive terminals. The composer covers all v1 input; passthrough needs its own security review. +
  • +
  • + Multi-project concurrent view + One window, one project in v1. Concurrent teams wait for the runtime to multiplex sessions. +
  • +
  • + Marketplace theming beyond brand / editor + v1 ships the ZO brand theme and an inherit-editor mode; theme packs come later. +
  • +
  • + ZO Studio bundled installer + v1 installs from VSIX alongside an existing ZO checkout; a bundled one-step install is a separate effort. +
  • +
+
+
+
+ + +
+ 04 — Contract +

Data sources

+

+ No invented state. Every region of the UI is a projection of a file + the ZO runtime already writes, or a CLI command it already accepts. +

+
+
Runtime contractUI region ← file → component
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
UI regionContract file / mechanismConsuming component
Sidebar + status bar.zo/runtime/session.json — heartbeat, phase, and panes map, polled on a short interval.TreeDataProvider + StatusBarItem screens 02 · 08
Terminal panel.zo/runtime/panes/p12.log (one per pane) written via tmux pipe-pane, tailed by the extension.xterm.js webview screen 03
Comms feedlogs/comms/2026-07-12.jsonl — append-only agent events, tailed and parsed per line.Feed webview screen 04
Training dashboard.zo/experiments/exp-003/metrics.jsonl + training_status.json for the live epoch state.Dashboard webview screens 01 · 06
Gate actionszo runtime send delivering /gates:approve or /gates:reject to the lead's pane.Approval card + notification screens 05 · 08
Start runzo build / zo continue --headless-tmux composed from form state, after preflight checks.Form webview → integrated CLI screen 07
+
+
+ +
+

Implementation notes

+ +
+ + +
+ + + + diff --git a/design/vscode/01-workbench.html b/design/vscode/01-workbench.html new file mode 100644 index 0000000..f420df1 --- /dev/null +++ b/design/vscode/01-workbench.html @@ -0,0 +1,452 @@ + + + + + +ZO · VS Code — Workbench + + + + +
+ +
+ +

The whole run, one window.

+

The hero composite: session tree, live agent terminal, comms stream and run heartbeat in a single VS Code workbench — the surface that replaces four raw tmux panes.

+
+ + +
+
WORKBENCH · FULL COMPOSITEPHASE_4 ACTIVE · EXP-003 RUNNING
+
+ +
+
+
mnist-digit-classifier — Zero Operators
+
+ +
+ + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+
+ + +
+
ZERO OPERATORS···
+
+ +
+ + mnist-digit-classifier + deep_learning +
+ +
Sessiontmux
+
+ + zo-mnist-20260712-091412 + 28m +
+
~/projects/mnist-deliverylive
+ +
Agents4
+
+ lead-orchestratoropus + ▸ working +
+
+ model-buildersonnet + ▸ training +
+
+ training-mnist-cnn-checkersonnet + ▸ watching +
+
+ oracle-qasonnet + · idle +
+ +
Gatessupervised
+
+ next: phase_4 → phase_5 + pending +
+
must ≥0.95 · should ≥0.98 · could ≥0.99
+ +
Trainingmps
+
+ exp-003 + epoch 6/8 +
+
+
val 0.9871 · best 0.9883 @5eta ~4m
+ +
+
+ + +
+ +
+
lead-orchestrator
+
model-builder
+
delivery ~/projects/mnist-delivery
+
+ +
+ P1 data review + P2 input representation + P3 model design + P4 ● training & iteration + P5 analysis + P6 packaging + workflow deep_learning +
+ +
zo-mnist-20260712-091412 · pane p12 — lead-orchestrator (opus) · claude code + + Read(.zo/experiments/exp-003/metrics.jsonl) + ⎿ 6 entries · last {"epoch": 6, "train_loss": 0.0341, "val_acc": 0.9871} + +exp-003 "wider conv + rotation aug" (parent exp-002) is at epoch 6/8 on mps. +Best val_acc 0.9883 came at epoch 5 — watching for regression before epoch 7. + + SendMessage(to: model-builder) + "Continue exp-003 through epoch 8. Val plateaued at 0.9871 (best 0.9883 @5). + Checkpoint best weights under .zo/experiments/exp-003/ and hold exp-004 + until oracle-qa re-runs the held-out set." + + Read(.zo/runtime/training_status.json) + ⎿ {"exp": "exp-003", "epoch": 6, "of": 8, "device": "mps", "eta_min": 4} + + Update Todos + ⎿ ☒ phase_2 input representation — human gate passed 07-11 + ☒ phase_3 model design approved · exp-003 launched (wider conv + rot aug) + ☐ monitor exp-003 through epoch 8 — training-checker watching metrics + ☐ run oracle: test_accuracy vs must ≥0.95 · should ≥0.98 · could ≥0.99 + ☐ assemble phase_4 → phase_5 gate packet (supervised) + +Checkpoint noted at epoch 5 (val_acc 0.9883) — retained as best. +training-mnist-cnn-checker reports train/val curves converging, no divergence. + +Next: read epoch 7 from metrics.jsonl, then decide on early stop vs full run. + + Waiting on epoch 7 · ETA ~4 min
+ +
+
+ COMMS + OUTPUT + TERMINAL + logs/comms/2026-07-12.jsonl +
+
+
+ 09:38:05 + checkpoint + model-builder saved epoch-5 weights — val_acc 0.9883 retained as best · .zo/experiments/exp-003/ +
+
+ 09:41:36 + message + lead-orchestratormodel-builder — continue exp-003 through epoch 8, checkpoint best weights before exp-004 +
+
+ 09:42:10 + decision + lead-orchestrator — hold exp-004 until oracle re-runs held-out set · logged to DECISION_LOG +
+
+ 09:42:58 + gate + oracle-qa — phase_4 → phase_5 pre-check: test_accuracy 0.9912 → tier could_pass (must ≥0.95 · should ≥0.98 · could ≥0.99) +
+
tail —f · 41 events today · checkpoint / message / decision / gate
+
+
+ +
+
+ +
+
zo: phase_4 · training
+
epoch 6/8 · val 0.9871
+
gate: supervised
+
+
exp-003
+
session: live
+
+ +
+
+ + +
+

Four regions, four sources.

+

Every region of the workbench is a thin view over a file the ZO runtime already writes. Nothing here invents state — the extension watches, tails and renders.

+ +
+
REGION MAPDATA SOURCES
+
+
+
+
+
+
+
+ 1 +
+
+
+
+
+
+
+
+
+
+
+ 2 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+
+
+
4
+
+
+
+
+ 1 +
+
Sidebar — session tree
+
.zo/runtime/session.json · fs watch; project, agents, gates and training summary re-render on change, no polling.
+
+
+
+ 2 +
+
Terminal — agent pane mirror
+
panes/p12.log · tmux pipe-pane stream rendered in xterm.js; input routed back via zo runtime send.
+
+
+
+ 3 +
+
Comms — event stream
+
logs/comms/2026-07-12.jsonl · incremental tail; event kind maps to accent (checkpoint dim, decision dusk, gate moss).
+
+
+
+ 4 +
+
Status bar — heartbeat
+
training_status.json · phase, epoch/val and gate mode as StatusBarItems; liveness dims when the tmux heartbeat lapses.
+
+
+
+
+
+
+ + +
+

Implementation notes

+ +
+ + +
+ + + + diff --git a/design/vscode/02-sidebar.html b/design/vscode/02-sidebar.html new file mode 100644 index 0000000..92b8c97 --- /dev/null +++ b/design/vscode/02-sidebar.html @@ -0,0 +1,335 @@ + + + + + +ZO · VS Code — Sidebar Tree + + + + +
+
+ +

Every session, at a glance.

+

The ZO sidebar is the extension's resting face: before a plan exists, between sessions, mid-training, and when a wrapper dies but the tmux session survives. Every row is read from files the CLI already writes.

+
+ +
+

One tree, four states

+

A single tree view whose root swaps with project state. No dashboards, no cards — the density and indent grammar of a file explorer, applied to agents, experiments, and gates.

+ +
+ + +
+
STATE ANO PROJECT
+
+
ZERO OPERATORS···
+
+ +

No .zo project in this workspace

+

Open a folder that contains a .zo directory, or scaffold one and put an agent team to work.

+ +

zo init <project> · zo draft

+
+
+
the tree populates itself the moment a plan lands in .zo/plans/
+
+
+ + +
+
STATE BIDLE · BETWEEN SESSIONS
+
+
ZERO OPERATORSidle
+
+
+ mnist-digit-classifier + idle +
+
deep_learning · gates supervised · lead opus
+
+ +
phasesSTATE.md
+
phase_1 · Data Review
+
phase_2 · Input Representationgate 07-11
+
phase_3 · Model Design
+
phase_4 · Training & Iterationnext
+
phase_5 · Analysis & Validation
+
phase_6 · Packaging
+ +
plan
+
.zo/plans/mnist-digit-classifier.md
+ +
experiments2
+
exp-0010.9770must
+
exp-0020.9841should
+ +
+
+ +
+
Last session: 2026-07-11 · 3h 12m · phase_3 completed
+
+
+ + +
+
STATE CRUNNING · PHASE_4
+
+
ZERO OPERATORSLIVE
+
+
+ mnist-digit-classifier + running +
+
zo-mnist-20260712-091412 · mps
~/projects/mnist-delivery
+
+ +
phases3 ✓ · phase_4 active
+ +
teamzo-mnist-digit-classifier
+
lead-orchestratoropusworking
+
model-buildersonnettraining
+
training-mnist-cnn-checkersonnetwatching
+
oracle-qasonnetidle
+
code-reviewerdone
+
test-engineerdone
+
research-scoutdone
+ +
trainingepoch 6/8
+
exp-001
+
exp-002
+
exp-003running
+
wider conv + rotation aug
+
+
epoch 6/8 · eta ~4 min
+
loss 0.0341 · val_acc 0.9871
+
checkpoint: best@5 · 0.9883
+ +
gates1 pending
+
phase_4 → phase_5awaiting
+
supervised · awaiting result
+
+
+ + +
+
STATE DENDED · REATTACH
+
+
ZERO OPERATORSstale
+
+
+ mnist-digit-classifier + ended +
+
zo-mnist-20260712-091412
+
+ +
+
wrapper heartbeat stale · 09:58
+
tmux session still alive
+
.zo/runtime/session.json last written 09:52 — the wrapper stopped reporting; agents may still be working.
+
+ +
+ + +
+ +
auto-consolidation ran · memory folded
+ +
+
last event 09:52 · logs/comms/2026-07-12.jsonl
+
+
+ +
+
+ +
+

Implementation notes

+ +
+ + +
+ + + diff --git a/design/vscode/03-terminal-panel.html b/design/vscode/03-terminal-panel.html new file mode 100644 index 0000000..c391565 --- /dev/null +++ b/design/vscode/03-terminal-panel.html @@ -0,0 +1,338 @@ + + + + + +ZO · VS Code — Terminal Panel + + + + +
+ +
+ +

Raw stream, tamed.

+

The xterm.js surface over the tmux session: read-only agent streams, one composer as the only write path, and honest edge states. Everything below is phase_4 of mnist-digit-classifier, mid-run.

+
+ + +
+

One pane, one conversation.

+

The lead's live Claude Code session, streamed read-only from tmux pane %12. The composer below is the only input surface: plain text or a slash command, delivered through the runtime CLI, never a raw TTY.

+ +
+
Terminal · single panezo-mnist-20260712-091412 · %12 · live
+
+ +
+
lead-orchestrator
+
model-builder
+
training-checker
+
oracle-qa
+
+ + read-only stream +
+
+ +
session zo-mnist-20260712-091412 · pane %12 · lead-orchestrator (opus) · zo continue --headless-tmux + + Read(.zo/plans/mnist-digit-classifier.md) + ⎿ workflow deep_learning · gate mode supervised · phases 1-3 complete, + phase_2 human gate passed 07-11 · phase_4 Training & Iteration active + + TeamCreate(team_name: "zo-mnist-digit-classifier") + team ready · 4 members live + lead-orchestrator opus working + model-builder sonnet training + training-mnist-cnn-checker sonnet watching metrics + oracle-qa sonnet idle + + SendMessage(to: "model-builder") + ⎿ "exp-003 'wider conv + rotation aug' approved, parent exp-002. + 8 epochs on mps. write per-epoch metrics to + .zo/experiments/exp-003/metrics.jsonl, live state to training_status.json." + + Bash(uv run python -m mnist.train --exp exp-003 --epochs 8 --device mps) + ⎿ 09:17:31 exp-003 started · parent exp-002 · rotation aug ±12° + epoch 1/8 train_loss 0.2814 val_acc 0.9612 + epoch 2/8 train_loss 0.1131 val_acc 0.9748 + epoch 3/8 train_loss 0.0716 val_acc 0.9803 + epoch 4/8 train_loss 0.0509 val_acc 0.9842 + epoch 5/8 train_loss 0.0407 val_acc 0.9883 best + epoch 6/8 train_loss 0.0341 val_acc 0.9871 + +◆ training-mnist-cnn-checker → lead + val plateau watch: epoch 5→6 Δ-0.0012 · best 0.9883 at epoch 5 + within tolerance 0.0020 · no action · re-check after epoch 7 + + acknowledged. holding exp-003 through epoch 7, best checkpoint retained. + oracle preflight queued for the phase_4 → phase_5 gate · run ETA ~4 min
+ +
+
+ + +
+
delivered via zo runtime send --pane %12 --submit · Enter to send
+
+ +
+
+
+ + +
+

The whole team, at a glance.

+

The grid toggle re-parents the same four xterm instances into a 2×2, hairline-separated. No re-spawn, no lost scrollback; the composer keeps addressing whichever pane holds focus.

+ +
+
Terminal · 2×2 grid4 panes · live
+
+ +
+
lead-orchestrator%12 · working
+
gate preflight queued: phase_4 → phase_5 + tiers 0.95 / 0.98 / 0.99 · oracle-qa on deck + checker: plateau watch · within tolerance · no action + holding exp-003 through epoch 7 + run ETA ~4 min
+
+ +
+
model-builder%13 · training
+
epoch 5/8 train_loss 0.0407 val_acc 0.9883 best +epoch 6/8 train_loss 0.0341 val_acc 0.9871 +checkpoint retained · ckpt-best.pt (epoch 5) +epoch 7/8 batch 118/469 loss 0.0329
+
+ +
+
training-checker%15 · watching metrics
+
$ tail -f .zo/experiments/exp-003/metrics.jsonl +{"epoch":5,"train_loss":0.0407,"val_acc":0.9883} +{"epoch":6,"train_loss":0.0341,"val_acc":0.9871} +Δ(5→6) -0.0012 · tolerance 0.0020 · ok +next check: epoch 7
+
+ +
+
oracle-qa%16 · idle
+
oracle-qa · idle +waiting for phase_5 Analysis & Validation +tiers armed: must ≥ 0.95 · should ≥ 0.98 · could ≥ 0.99 +will run on gate preflight signal from lead
+
+ +
+
+
+ + +
+

Ugly moments, handled.

+

Reattaching replays the pane log before going live, and says so. A dead pane keeps its final frame and points at the preserved log instead of vanishing.

+ +
+ +
+
State · reconnectlead-orchestrator · %12
+
+
Reattached · replaying pane log from 09:14 · 2.1 MBpanes/p12.log
+
replaying… +epoch 3/8 train_loss 0.0716 val_acc 0.9803 +epoch 4/8 train_loss 0.0509 val_acc 0.9842 +epoch 5/8 train_loss 0.0407 val_acc 0.9883 best +epoch 6/8 train_loss 0.0341 val_acc 0.9871 +▸ live + holding exp-003 through epoch 7
+
+
+ +
+
State · pane diedcode-reviewer · completed
+
+
+
code-reviewer · sonnet · pane %14 +● review complete: model.py, train.py, augment.py + 2 findings resolved · 0 open · verdict pass +● SendMessage(to: "lead-orchestrator") · report filed +● session closed · exit 0 +[pane exited at 09:41:07]
+
+
pane exited · log preserved at +.zo/runtime/panes/p14.log
+ +
+
+
+
+ +
+
+ +
+

Implementation notes

+ +
+ + +
+ + + + diff --git a/design/vscode/04-comms-feed.html b/design/vscode/04-comms-feed.html new file mode 100644 index 0000000..e752773 --- /dev/null +++ b/design/vscode/04-comms-feed.html @@ -0,0 +1,686 @@ + + + + + +ZO · VS Code — Comms Feed + + + + +
+ +
+ +

Every decision, on the record.

+

The comms feed replays the team's JSONL audit trail as a live timeline — checkpoints, messages, decisions, gates and errors, filterable by agent, type and phase, pinned to the tail while the team works.

+
+ + +
+

Phase three to four, as it happened

+

One morning of mnist-digit-classifier: the session resumes into training at 09:14, the model-design gate clears at 09:15, exp-003 launches with rotation aug, and the phase_4 gate begins evaluating at 09:43. Five event types, five distinct treatments.

+ +
+
COMMS FEED — EDITOR WEBVIEWLIVE TAIL · UNPINNED
+
+ +
+
+
mnist-digit-classifier — Zero Operators — Visual Studio Code
+
+ +
+ +
+
+
+
+
+
+
+
+
+ +
+
ZERO OPERATORSCOMMS
+
+
+
mnist-digit-classifier
+
+ plan  .zo/plans/mnist-digit-classifier.md
+ workflow deep_learning · gates supervised
+ lead opus · team zo-mnist-digit-classifier +
+
+
+
Phases
+
1Data Review
+
2Input Representation
+
3Model Design
+
4Training & Iteration
+
5Analysis & Validation
+
6Packaging
+
+
+
Agents
+
lead-orchestrator opusworking
+
model-builder sonnettraining
+
training-mnist-cnn-checker sonnetwatching
+
oracle-qa sonnetidle
+
completed earlier — research-scout ·
code-reviewer · test-engineer
+
+
+
+ +
+
+
ZO · Comms Feed
+
STATE.md
+
exp-003 · metrics.jsonl
+
+ +
+
+ All agents + All types + phase_4 + + +
+ +
+
+ + +
+
09:14
+
+
session resumed·zo-mnist-20260712-091412·phase_4 training_iteration·STATE.md loaded
+
+ + +
+
09:15
+
+
+
+
+ gate + phase_3phase_4 + model design review + pass +
+
reviewed3-block CNN spec · exp-001/002 design runs · param budget 1.2M
+
human gate · approved via /gates:approve · 09:15
+
+
+
+ + +
+
09:16
+
+
+
+
+ decision + Branch exp-003 from exp-002: keep the wider conv, add rotation aug ±12° + lead-orchestrator +
+
exp-002 stalled at 0.9841; its error grid is rotation-shaped — 7/1 and 4/9 confusions — not capacity-shaped.
+
+

exp-002's wider conv (32→64) already closed the underfit gap; the residual errors cluster where digits rotate into each other. Rotation aug ±12° attacks exactly that failure mode at zero parameter cost, leaving the 1.2M budget untouched. 8 epochs on mps; metrics stream to .zo/experiments/exp-003/metrics.jsonl.

+
alternativesdeeper 4-block stack (rejected: param budget) · lr warmup sweep (deferred to exp-004) · elastic distortions (rejected: cpu-bound on mps)
+
+ +
+
+
+ + +
+
09:17
+
+
+
+
+ error + blocking + model-builder +
+
MPS fallback: pin_memory unsupported — retried on cpu loader
+
resolved 09:17 · retried with pin_memory=false · prior appended to PRIORS.md
+
+
+
+ + +
+
09:18
+
+
+
model-builderlead-orchestratorroutine
+
exp-003 launched (parent exp-002): wider conv + rotation aug, 8 epochs on mps. Status in training_status.json.
+
+
+ + +
+
09:24
+
+
+
code-reviewermodel-builderroutine
+
augment.py review clean — two nits fixed inline (rotation-bounds constant, transform seeding). No blocking findings.
+
+
+ + +
+
09:26
+
+
phase_4·training_iteration·exp-003 epoch 3/8·val_acc 0.9803
+
+ + +
+
09:38
+
+
phase_4·training_iteration·exp-003 epoch 5/8·val_acc 0.9883·new best, checkpointed
+
+ + +
+
09:41
+
+
+
training-mnist-cnn-checkerlead-orchestratorhigh
+
best val_acc 0.9883 at epoch 5; epoch 6 reads 0.9871 — plateau watch on. Recommend holding the gate until epoch 8 confirms.
+
+
+ + +
+
09:42
+
+
phase_4·training_iteration·exp-003 epoch 6/8·train_loss 0.0341·val_acc 0.9871
+
+ + +
+
09:42
+
+
+
+
+ decision + Hold exp-004 until the oracle re-runs the held-out set + lead-orchestrator +
+
exp-003's epoch-5 best is going to the oracle for the gate packet; branching now would race the evaluation.
+ +
+

Launching exp-004 (the lr-warmup sweep) while the oracle scores the phase_4 → phase_5 gate would fork the checkpoint lineage mid-evaluation and contend for mps. If the gate returns iterate, exp-004 starts from exp-003's best.pt with the warmup grid; if it approves, exp-004 never needs to run. Logged to DECISION_LOG.

+
alternativesrun exp-004 in parallel (rejected: mps contention, lineage fork) · early-stop exp-003 at epoch 7 (rejected: epoch 8 confirms the plateau)
+
+
+
+
+ + +
+
09:43
+
+
+
+
+ gate + phase_4phase_5 + evaluating… +
+
test_accuracy0.9912≥ 0.95tier: could_pass
+
must_pass ≥ 0.95 ✓should_pass ≥ 0.98 ✓could_pass ≥ 0.99 ✓
+
oracle scored best checkpoint (epoch 5) · exp-003 finishing · then /gates:approve or /gates:reject
+
+
+
+ +
+ + +
+
+
+
+ +
+ zo: phase_4 · training + exp-003 · epoch 6/8 · val 0.9871 + zo-mnist-20260712-091412 + + comms: tailing 2026-07-12.jsonl + mps +
+ +
+
+
+ + +
+

One chip, gates only

+

The type filter collapses the morning to its gate events — the approval trail a reviewer actually audits. Pinned state shown: the auto-scroll toggle holds coral and the new-events pill never appears.

+ +
+
COMMS FEED — TYPE FILTERGATES ONLY · PINNED
+
+
+ All agents + gates + All phases + + +
+
+
+ +
+
09:15
+
+
+
+
+ gate + phase_3phase_4 + model design review + pass +
+
reviewed3-block CNN spec · exp-001/002 design runs · param budget 1.2M
+
human gate · approved via /gates:approve · 09:15
+
+
+
+ +
+
09:43
+
+
+
+
+ gate + phase_4phase_5 + evaluating… +
+
test_accuracy0.9912≥ 0.95tier: could_pass
+
must_pass ≥ 0.95 ✓should_pass ≥ 0.98 ✓could_pass ≥ 0.99 ✓
+
oracle scored best checkpoint (epoch 5) · exp-003 finishing · then /gates:approve or /gates:reject
+
+
+
+ +
+
+
+
+
+ +
+

Implementation notes

+ +
+ + +
+ + + + diff --git a/design/vscode/05-gate-approval.html b/design/vscode/05-gate-approval.html new file mode 100644 index 0000000..0e37e7d --- /dev/null +++ b/design/vscode/05-gate-approval.html @@ -0,0 +1,633 @@ + + + + + +ZO · VS Code — Gate Approval + + + + +
+ +
+ +

Approve from anywhere in the editor.

+

The human checkpoint, reduced to one decision. The oracle presents its evidence in a single card; you approve, reject with a reason, or send the team back to iterate, without leaving your file.

+
+ + +
+

The inline gate card

+

Everything needed to decide, nothing else: the oracle metric, the tier ladder it climbed, the per-class breakdown, and the experiment that produced it. Three actions, one footnote explaining the mechanism.

+ +
+
INLINE GATE CARDPHASE_4 → PHASE_5 · PENDING
+
+
+
+ Gate · phase_4 → phase_5 + supervised + + 12 JUL · 09:43:07 +
+ +
+
+
0.9912
+
test_accuracy
+
oracle · 10,000 held-out samples
+
+
+
+
must_pass≥ 0.95
+
should_pass≥ 0.98
+
could_pass≥ 0.99
+
→ tiercould_pass
+
+
+ +
+
per-class accuracybar scale 0.98 – 1.00
+
+
class 00.9989
+
class 10.9965
+
class 20.9903
+
class 30.9891
+
class 40.9924
+
class 50.9887
+
class 60.9948
+
class 70.9902
+
class 80.9866
+
class 90.9838
+
+
+ +
exp-003 · wider conv + rotation aug · 8 epochs · mps
+ +
+
+ + + +
+
approve = zo runtime send --pane %12 --text "/gates:approve" --submit
+
+
+
+
+
+ + +
+

Reject, with a reason

+

Rejection is never a bare no. The reason is required, injected into the lead pane with the slash command, and recorded to the decision log so the rework has a target.

+ +
+
REJECT POPOVERREASON → DECISION_LOG
+
+
+
+
+ Gate · phase_4 → phase_5 + supervised + + 12 JUL · 09:43:07 +
+
+
+
0.9912
+
test_accuracy
+
oracle · 10,000 held-out samples
+
+
+
+
must_pass≥ 0.95
+
should_pass≥ 0.98
+
could_pass≥ 0.99
+
→ tiercould_pass
+
+
+
+
per-class accuracybar scale 0.98 – 1.00
+
+
class 00.9989
+
class 10.9965
+
class 20.9903
+
class 30.9891
+
class 40.9924
+
class 50.9887
+
class 60.9948
+
class 70.9902
+
class 80.9866
+
class 90.9838
+
+
+
exp-003 · wider conv + rotation aug · 8 epochs · mps
+
+
+ + + +
+
approve = zo runtime send --pane %12 --text "/gates:approve" --submit
+
+
+ +
+
Reason (recorded to DECISION_LOG)
+ +
+ + +
+
injects /gates:reject "<reason>" into lead pane %12
+
+
+
+
+
+ + +
+

How much autonomy

+

Gate mode is a dial, not a rewrite. Flip it mid-run and the orchestrator picks up the new setting at the next phase boundary.

+ +
+
GATE-MODE CONTROLSUPERVISED ACTIVE
+
+
+ + + +
+
+
+ supervised + Every gate blocks until a human approves, rejects, or iterates. +
+
+ auto + Gates self-approve when the oracle clears must_pass; anything below escalates to you. +
+
+ full-auto + No blocking gates. Oracle results are recorded and the run continues to packaging. +
+
+
writes <memory>/gate_mode via zo gates set — hot-reloaded by the running orchestrator
+
+
+
+ + +
+

Getting your attention

+

When a gate opens you may be three files deep in something else. A quiet toast and a coral status-bar item are the only interruptions; both lead back to the card.

+ +
+
NOTIFICATION + STATUS BARFIRED FROM COMMS TAIL
+
+
mnist-delivery › src › model.py — editor continues undisturbed
+ +
+
+ +
+
Gate pending — phase_4 awaiting your decision
+
mnist-digit-classifier · test_accuracy 0.9912 · could_pass
+
+ × +
+
+ + +
+
+
+
+ zo: gate pending + zo-mnist-20260712-091412 + + exp-003 · epoch 6/8 + mps + Ln 128, Col 41 +
+
+
+ +
+

Implementation notes

+ +
+ + +
+ + + + diff --git a/design/vscode/06-training-dashboard.html b/design/vscode/06-training-dashboard.html new file mode 100644 index 0000000..bd87842 --- /dev/null +++ b/design/vscode/06-training-dashboard.html @@ -0,0 +1,595 @@ + + + + + +ZO · VS Code — Training Dashboard + + + + +
+ +
+ +

Training, watched.

+

The zo watch-training loop, re-rendered as a webview. Live loss curves from metrics.jsonl, checkpoint state, and the experiment lineage for mnist-digit-classifier — repainted on every file change, no polling.

+
+ + +
+

The live run

+

exp-003 mid-flight in phase_4. The stat row reads the last line of metrics.jsonl; the chart replots the whole file. Epochs the run hasn't reached yet stay hatched — the dashboard never pretends to know the future.

+ +
+
ZO: TRAINING — WEBVIEW PANELLIVE RUN · EXP-003 · EPOCH 6/8
+
+
+
+
mnist-delivery — Zero Operators — Visual Studio Code
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+
+ +
+
ZERO OPERATORSlive
+
+
sessionzo-mnist-20260712-091412
+
planmnist-digit-classifier.md
+
workflowdeep_learning
+
gatessupervised
+
leadopus
+
+ +
Phases
+
phase_1 · Data Reviewdone
+
phase_2 · Input Representationgate 07-11
+
phase_3 · Model Designdone
+
phase_4 · Training & Iterationexp-003
+
phase_5 · Analysis & Validationpending
+
phase_6 · Packagingpending
+ +
Agents
+
lead-orchestratoropus · working
+
model-buildersonnet · training
+
training-mnist-cnn-checkersonnet · watching
+
oracle-qasonnet · idle
+
code-reviewerdone
+
test-engineerdone
+
research-scoutdone
+
+ +
+
+
ZO: Training — exp-003
+
STATE.md
+
mnist-digit-classifier.md
+
+ +
+ + +
+ exp-003 + wider conv + rotation aug + RUNNING + + exp-001 → exp-002 → exp-003 + ·device mps + ·started 09:17 + ·eta ~4 min + +
+ + +
+
+
best val_acc
+
0.9883
+
epoch 5
+
+
+
val_acc
+
0.9871
+
epoch 6
+
+
+
train_loss
+
0.0341
+
epoch 6
+
+
+
epoch
+
6 / 8
+
75% complete
+
+
+
+ + +
+
+ loss / epoch — exp-003 +
+ train_loss + val_loss +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.043 + + + 0.0 + 0.1 + 0.2 + 0.3 + 0.4 + 0.5 + + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + +
+ + +
+ + val_acc + + + + 0.9871 + +
+
+ +
+ +
+
+ Terminal — p12 · training + Comms + Output +
+
09:38:04 epoch 5/8 done · train_loss 0.0407 · val_acc 0.9883 · new best → checkpoints/best.pt +09:38:05 wrote .zo/experiments/exp-003/metrics.jsonl · training_status.json +09:41:02 epoch 6/8 done · train_loss 0.0341 · val_acc 0.9871 · best stays epoch 5 +09:41:44 training-mnist-cnn-checker Δ(5→6) −0.0012 · within tolerance · plateau watch on +09:42:15 epoch 7/8 · step 118/469 · train_loss 0.0329 · lr 8.1e-4
+
+
+
+ +
+ zo-mnist-20260712-091412 + phase_4 · training & iteration + exp-003 · epoch 6/8 + + val_acc 0.9871 + mps + ~/projects/mnist-delivery +
+
+
+
+ + +
+

Checkpoints, resumable

+

Everything a restart needs. Each row is a full state dict — model, optimizer, scheduler, RNG — so zo continue can resume mid-phase without losing the run.

+ +
+
CHECKPOINTSEXP-003 · EPOCH 6/8
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpochFileKindval_accSizeSaved
5best.ptBEST0.98834.7 MB09:38:05
6last.ptLAST0.98714.7 MB09:41:02
3epoch-003.ptPERIODIC0.98034.7 MB09:26:44
+
+ resumable: model + optim + sched + RNG · .zo/experiments/exp-003/checkpoints/ + should_checkpoint: every, best, last +
+
+
+
+ + +
+

The experiment lineage

+

Every run descends from a parent. The picker retargets the dashboard to any experiment in the tree — the delta column answers the only question that matters: did the child beat its parent?

+ +
+
EXPERIMENT PICKER3 EXPERIMENTS · LINEAGE
+
+
+ IDExperimentStatusOracle tierbest val_accΔ parent +
+
+ + exp-001 + baseline cnn + complete + MUST_PASS + 0.9770 + +
+
+ + exp-002 + wider conv + complete + SHOULD_PASS + 0.9841 + +0.0071 +
+
+ + exp-003 + wider conv + rotation aug + running · epoch 6/8 + RUNNING + 0.9883 + +0.0042 +
+
+
+
+ +
+

Implementation notes

+ +
+ + +
+ + + + diff --git a/design/vscode/07-start-run.html b/design/vscode/07-start-run.html new file mode 100644 index 0000000..0b5bf9d --- /dev/null +++ b/design/vscode/07-start-run.html @@ -0,0 +1,471 @@ + + + + + +ZO · VS Code — Start Run + + + + +
+
+ +

Every flag, remembered for you.

+

The start form replaces a memorized CLI incantation. Defaults hydrate from .zo/config.yaml and the plan's frontmatter; the live preview shows exactly the command that will run — nothing hidden, nothing forgotten.

+
+ +
+

Configure, preview, launch.

+

Mode preselects continue because phases 1–3 are already complete. Preflight has already run; one warning — no CUDA device, Apple mps available — is surfaced but non-blocking.

+ +
+ + +
+
START RUN · WEBVIEW PANELDEFAULTS FROM .ZO/CONFIG.YAML
+ +
+

Start a run

+ mnist-digit-classifier +
+ + +
+ Plan +
+ .zo/plans/mnist-digit-classifier.md + +
+ validated ✓ · deep_learning · oracle: test_accuracy ≥ 0.95 +
+ + +
+ Mode +
+ + +
+ phases 1–3 complete — continue resumes at phase_4 Training & Iteration +
+ + +
+ Gate mode +
+ + + +
+ Every phase gate waits for a human /gates:approve — recommended while a project is still earning trust. +
+ + +
+ Lead model +
+ opus + +
+ default · options: sonnet · haiku — reviewer tiers still route per agent +
+ + +
+ Toggles +
+
+
+ --low-token + Sonnet lead · Haiku reviewers · caps iterations — ~30% measured savings +
+
+
+
+
+ --bypass-permissions + auto-approves every tool call for this run — only for unattended runs; implied by full-auto +
+
+
+ + +
+ Max iterations +
+ + 10 + +
+ per-phase experiment budget — lead stops iterating past this count +
+ +
--headless-tmux · session owned by the extension
+ + +
+ Live command preview +
$zo continue mnist-digit-classifier --repo ~/projects/mnist-delivery --headless-tmux --gate-mode supervised
+
+ +
+ + +
+
+ + +
+
PREFLIGHTZO PREFLIGHT --JSON
+ +
+

Preflight

+ ran 09:13:58 +
+ +
claude CLI 2.1.x
+
tmux 3.4
+
uv 0.7.x
+
+ plan validates.zo/plans/mnist-digit-classifier.md + +
+
+ delivery repo clean~/projects/mnist-delivery · main + +
+
+ GPUnone — mps available + warn +
+
disk 214 GB free
+ +
7 checks · 6 pass · 1 warn · 0.8 s — warnings never block; failures disable Start run
+
+ +
+
+ +
+

Implementation notes

+ +
+ + +
+ + + + diff --git a/design/vscode/08-status-and-palette.html b/design/vscode/08-status-and-palette.html new file mode 100644 index 0000000..81c53d8 --- /dev/null +++ b/design/vscode/08-status-and-palette.html @@ -0,0 +1,483 @@ + + + + + +ZO · VS Code — Status & Palette + + + + +
+ +
+ +

Quiet signals, everywhere you look.

+

Status bar, command palette, notifications, settings: the four smallest surfaces the extension touches. Each carries the minimum useful signal and routes back to a full view in one click.

+
+ + +
+

Status bar states

+

One persistent item, three states. Idle keeps the project name warm. Running carries live metrics from the session heartbeat. A pending gate turns the whole item coral and becomes a click target.

+ +
+
STATUS BARIDLE · RUNNING · GATE-PENDING
+
+ +
+
idleno live session · last state from .zo/runtime/session.json
+
+
+ ⎇ main + zo: idle · mnist-digit-classifier · last run 2026-07-11 + + Ln 128, Col 2 + UTF-8 + Python 3.12.6 +
+
+
+ +
+
runningphase_4 active · exp-003 epoch 6/8
+
+
+ ⎇ main + zo: phase_4 · training + epoch 6/8 · val 0.9871 + gate: supervised + + exp-003 · session: live + Python 3.12.6 +
+
+
+ +
+
gate-pendingphase_4 → phase_5 · whole item is the click target
+
+
+ ⎇ main + zo: gate pending: phase_4 → phase_5 · click to review + + exp-003 · session: live + Python 3.12.6 +
+
+
+ +
+
+
+ + +
+

The palette

+

Every ZO action is a command first. Type ZO: and the whole surface of the extension is enumerable, keyboard-first, and mapped one-to-one onto the CLI.

+ +
+
COMMAND PALETTEQUICK PICK · FIRST ITEM FOCUSED
+
+
+
+
+
mnist-digit-classifier — Visual Studio Code
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ZERO OPERATORS
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ZO: Training · exp-003
+
STATE.md
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ⎇ main + zo: phase_4 · training + epoch 6/8 · val 0.9871 + + exp-003 · session: live +
+
+ +
+ +
+
ZO: 
+
+
+
ZO: Start Run
+
⌘⇧ZR
+
+
+
ZO: Attach to Session
+
+
+
+ ZO: Approve Gate + phase_4 → phase_5 · could_pass +
+
+
+
ZO: Open Training Dashboard
+
+
+
ZO: Open Comms Feed
+
+
+
ZO: Set Gate Mode
+
+
+
ZO: Send Message to Lead
+
+
+
ZO: Stop Session
+
+
+
+
+
+
+ + +
+

Notifications, rationed

+

Toasts are reserved for three things: a gate that needs a decision, a run that finished, and a degraded API. Everything else stays in the status bar.

+ +
+
NOTIFICATIONSTHREE VARIANTS · STACKED FOR REVIEW
+
+
+
+
+
mnist-digit-classifier — Visual Studio Code
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ZO: Training · exp-003
+
STATE.md
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ⎇ main + zo: phase_4 · training + epoch 6/8 · val 0.9871 + + exp-003 · session: live +
+
+ +
+ +
+
+
+
+
Gate pending — phase_4 awaiting your decision
+
oracle: test_accuracy 0.9912 → could_pass
+
+ + +
+
+ × +
+ +
+
+
+
Run complete · could_pass · 2h 58m
+
99.12% test accuracy · 3 experiments · memory folded
+
+ +
+
+ × +
+ +
+
+
+
Claude API rate-limited — backing off 42s · run continues
+
+ × +
+
+
+
+
+ + +
+

Settings, three keys

+

The only opinionated setting is appearance: whether ZO webviews speak the brand tokens or inherit the editor theme. The rest is plumbing that detects itself.

+ +
+
SETTINGSEXTENSION SECTION · GLIMPSE
+
+
Settings › Extensions › Zero Operators
+ +
+
zo.appearance
+
Visual language for ZO webviews (dashboard, comms feed, gate review).
+
+ + +
+
brand = ZO tokens · editor = inherit VS Code theme
+
+ +
+
zo.pythonPath
+
Interpreter used to launch and attach to ZO runs.
+ +
auto-detected via uv · leave blank to re-detect on activation
+
+ +
+
zo.notifications.gates
+
Where gate-pending signals surface.
+
toast+statusbar
+
statusbar-only silences toasts · gates still block until decided
+
+
+
+
+ +
+

Implementation notes

+ +
+ + +
+ + + + diff --git a/design/vscode/tokens.css b/design/vscode/tokens.css new file mode 100644 index 0000000..2622925 --- /dev/null +++ b/design/vscode/tokens.css @@ -0,0 +1,535 @@ +/* ═══════════════════════════════════════════════════════════════ + ZERO OPERATORS — VS Code Extension Mockups: shared tokens + chrome + Brand system v2 ("a quiet, precise workshop") applied to a + simulated VS Code workbench. Every mockup page links this file. + + THEME TOGGLE — each page carries this exact markup + script: + + + + + MARK — the simplified-C, used in the activity bar and mastheads: + + + + + + + + PRODUCTION NOTE (extension webviews, not these mockups): + no external fonts (bundle Geist / JetBrains Mono / Instrument + Serif woff2 — all SIL OFL), strict CSP (no CDN, nonce'd script), + every brand token maps to a --vscode-* fallback for the + "inherit editor theme" setting. Google Fonts below is a + browser-preview convenience only. + ═══════════════════════════════════════════════════════════════ */ + +@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap'); + +:root { + /* — Brand surfaces (dark) — */ + --canvas: #12110F; + --canvas-2: #17150F; + --canvas-3: #1C1A13; + --rule: #2A241C; + --rule-2: #35301F; + + /* — Text on dark — */ + --cream: #EBE3D2; + --cream-2: #C8C0AE; + --dim: #857D6B; + --ghost: #4E4738; + + /* — Paper (light-theme sources) — */ + --paper: #F4EFE6; + --paper-2: #EAE3D2; + --ink: #1A1712; + --ink-muted: #6B6254; + + /* — Accents — */ + --coral: oklch(0.74 0.14 35); + --coral-soft: oklch(0.74 0.14 35 / 0.14); + --coral-dim: oklch(0.52 0.10 35); + --dusk: oklch(0.70 0.10 245); + --dusk-soft: oklch(0.70 0.10 245 / 0.14); + --dusk-dim: oklch(0.48 0.07 245); + --moss: oklch(0.62 0.08 150); + --moss-soft: oklch(0.62 0.08 150 / 0.14); + + /* — Typography — */ + --serif: 'Instrument Serif', Georgia, serif; + --sans: 'Geist', -apple-system, system-ui, sans-serif; + --mono: 'JetBrains Mono', ui-monospace, monospace; + + /* — Motion — */ + --ease: cubic-bezier(0.2, 0.8, 0.2, 1); + + /* — Semantic chrome (theme-flipped): the simulated VS Code shell — */ + --bg: var(--canvas); /* page behind the window */ + --surface: var(--canvas-2); /* sidebar / panel */ + --surface-2: var(--canvas-3); /* hover / elevated */ + --editor: var(--canvas); /* editor + terminal ground */ + --line: var(--rule); + --line-2: var(--rule-2); + --text: var(--cream); + --text-2: var(--cream-2); + --text-3: var(--dim); + --text-4: var(--ghost); + + /* — VS Code chrome proportions (true-ish) — */ + --w-activitybar: 48px; + --w-sidebar: 300px; + --h-titlebar: 35px; + --h-tabs: 35px; + --h-statusbar: 22px; + + color-scheme: dark; +} + +[data-theme="light"] { + --bg: var(--paper); + --surface: var(--paper-2); + --surface-2: #E2D9C4; + --editor: var(--paper); + --line: #D8CFBA; + --line-2: #C6BCA4; + --text: var(--ink); + --text-2: #3D362B; + --text-3: var(--ink-muted); + --text-4: #9A9080; + color-scheme: light; +} + +* { box-sizing: border-box; margin: 0; padding: 0; } + +html, body { + background: var(--bg); + color: var(--text); + font-family: var(--sans); + font-feature-settings: 'ss01', 'cv11'; + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; + transition: background 0.25s var(--ease), color 0.25s var(--ease); +} + +body { min-height: 100vh; padding: 0 0 120px; } + +.container { max-width: 1280px; margin: 0 auto; padding: 0 48px; } + +/* ═══════════════════════════════════════════════ + MOCKUP PAGE SCAFFOLD (matches design/*.html voice) + ═══════════════════════════════════════════════ */ +.mock-masthead { + border-bottom: 1px solid var(--line); + padding: 56px 0 36px; + margin-bottom: 48px; +} +.mock-masthead .crumbs { + display: flex; + justify-content: space-between; + align-items: baseline; + font-family: var(--mono); + font-size: 11px; + color: var(--text-3); + letter-spacing: 0.18em; + text-transform: uppercase; + margin-bottom: 32px; +} +.mock-masthead .crumbs a { color: var(--text-3); text-decoration: none; } +.mock-masthead .crumbs a:hover { color: var(--coral); } +.mock-masthead h1 { + font-family: var(--serif); + font-weight: 400; + font-size: clamp(40px, 5vw, 64px); + line-height: 0.98; + letter-spacing: -0.02em; + margin-bottom: 14px; +} +.mock-masthead h1 em { font-style: italic; color: var(--coral); } +.mock-masthead .deck { + font-size: 17px; + font-weight: 300; + color: var(--text-2); + max-width: 640px; + line-height: 1.55; +} + +.theme-toggle { + font-family: var(--mono); + font-size: 11px; + letter-spacing: 0.18em; + text-transform: uppercase; + color: var(--text-3); + background: transparent; + border: 1px solid var(--line-2); + border-radius: 4px; + padding: 6px 14px; + cursor: pointer; + transition: all 0.15s var(--ease); +} +.theme-toggle:hover { color: var(--coral); border-color: var(--coral); } + +/* Labeled frame around each mock (mirrors .sample-frame) */ +.mock-frame { + border: 1px solid var(--line); + border-radius: 12px; + overflow: hidden; + background: var(--bg); + margin: 0 0 12px; +} +.mock-frame-label { + display: flex; + justify-content: space-between; + font-family: var(--mono); + font-size: 10px; + color: var(--text-3); + letter-spacing: 0.18em; + text-transform: uppercase; + padding: 10px 16px; + border-bottom: 1px solid var(--line); + background: var(--surface); +} + +/* Section scaffold inside a mock page */ +.mock-section { padding: 64px 0 8px; } +.mock-section + .mock-section { border-top: 1px solid var(--line); margin-top: 40px; } +.mock-section > h2 { + font-family: var(--serif); + font-weight: 400; + font-size: 34px; + letter-spacing: -0.01em; + margin-bottom: 8px; +} +.mock-section > h2 em { font-style: italic; color: var(--coral); } +.mock-section > .lede { + font-size: 15px; + font-weight: 300; + color: var(--text-2); + max-width: 620px; + line-height: 1.55; + margin-bottom: 32px; +} + +/* Implementation notes block (one per page, bottom) */ +.mock-notes { + border: 1px dashed var(--line-2); + border-radius: 8px; + padding: 24px 28px; + margin-top: 48px; +} +.mock-notes h3 { + font-family: var(--mono); + font-size: 10px; + font-weight: 500; + color: var(--coral); + letter-spacing: 0.22em; + text-transform: uppercase; + margin-bottom: 14px; +} +.mock-notes ul { list-style: none; display: flex; flex-direction: column; gap: 8px; } +.mock-notes li { + font-size: 13px; + font-weight: 300; + color: var(--text-2); + line-height: 1.5; + padding-left: 16px; + position: relative; +} +.mock-notes li::before { content: "—"; position: absolute; left: 0; color: var(--text-4); } +.mock-notes code { + font-family: var(--mono); + font-size: 12px; + color: var(--dusk); +} + +/* ═══════════════════════════════════════════════ + VS CODE CHROME SIMULATION + ═══════════════════════════════════════════════ */ +.vsc-window { + background: var(--editor); + display: flex; + flex-direction: column; + font-size: 13px; + min-height: 640px; +} + +/* Title bar */ +.vsc-titlebar { + height: var(--h-titlebar); + flex: none; + display: flex; + align-items: center; + gap: 8px; + padding: 0 14px; + background: var(--surface); + border-bottom: 1px solid var(--line); +} +.vsc-titlebar .dots { display: flex; gap: 7px; } +.vsc-titlebar .dots span { + width: 11px; height: 11px; border-radius: 50%; + background: var(--line-2); +} +.vsc-titlebar .title { + flex: 1; + text-align: center; + font-family: var(--mono); + font-size: 11px; + color: var(--text-3); + letter-spacing: 0.04em; +} + +/* Body row: activity bar | sidebar | main */ +.vsc-body { flex: 1; display: flex; min-height: 0; } + +.vsc-activitybar { + width: var(--w-activitybar); + flex: none; + background: var(--surface); + border-right: 1px solid var(--line); + display: flex; + flex-direction: column; + align-items: center; + padding: 10px 0; + gap: 4px; +} +.vsc-activitybar .ab-item { + width: 40px; height: 40px; + display: flex; align-items: center; justify-content: center; + color: var(--text-4); + border-left: 2px solid transparent; + cursor: pointer; +} +.vsc-activitybar .ab-item:hover { color: var(--text-2); } +.vsc-activitybar .ab-item.active { color: var(--text); border-left-color: var(--coral); } +.vsc-activitybar .ab-item svg { display: block; } +.vsc-activitybar .ab-spacer { flex: 1; } + +.vsc-sidebar { + width: var(--w-sidebar); + flex: none; + background: var(--surface); + border-right: 1px solid var(--line); + display: flex; + flex-direction: column; + min-height: 0; + overflow: hidden; +} +.vsc-sidebar-title { + font-family: var(--mono); + font-size: 10px; + letter-spacing: 0.2em; + text-transform: uppercase; + color: var(--text-3); + padding: 12px 16px 10px; + display: flex; + justify-content: space-between; + align-items: center; +} + +.vsc-main { + flex: 1; + display: flex; + flex-direction: column; + min-width: 0; + min-height: 0; +} + +/* Editor tabs */ +.vsc-tabs { + height: var(--h-tabs); + flex: none; + display: flex; + align-items: stretch; + background: var(--surface); + border-bottom: 1px solid var(--line); + overflow-x: auto; +} +.vsc-tab { + display: flex; + align-items: center; + gap: 8px; + padding: 0 16px; + font-family: var(--mono); + font-size: 11.5px; + color: var(--text-3); + border-right: 1px solid var(--line); + cursor: pointer; + white-space: nowrap; +} +.vsc-tab.active { + background: var(--editor); + color: var(--text); + box-shadow: inset 0 1px 0 var(--coral); +} +.vsc-tab .tab-dot { width: 6px; height: 6px; border-radius: 50%; } + +/* Bottom panel */ +.vsc-panel { + flex: none; + border-top: 1px solid var(--line); + background: var(--surface); + display: flex; + flex-direction: column; + min-height: 0; +} +.vsc-panel-tabs { + display: flex; + gap: 20px; + padding: 8px 18px 0; + font-family: var(--mono); + font-size: 10.5px; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--text-4); + border-bottom: 1px solid var(--line); +} +.vsc-panel-tabs span { padding-bottom: 7px; cursor: pointer; } +.vsc-panel-tabs span.active { + color: var(--text); + border-bottom: 1px solid var(--coral); +} + +/* Status bar */ +.vsc-statusbar { + height: var(--h-statusbar); + flex: none; + display: flex; + align-items: center; + gap: 18px; + padding: 0 12px; + background: var(--surface); + border-top: 1px solid var(--line); + font-family: var(--mono); + font-size: 10.5px; + color: var(--text-3); + overflow: hidden; +} +.vsc-statusbar .sb-item { display: flex; align-items: center; gap: 6px; white-space: nowrap; } +.vsc-statusbar .sb-item .sb-dot { width: 6px; height: 6px; border-radius: 50%; } +.vsc-statusbar .sb-item.accent { color: var(--coral); } +.vsc-statusbar .sb-spacer { flex: 1; } + +/* ═══════════════════════════════════════════════ + SHARED PRIMITIVES (from the brand sheet, theme-aware) + ═══════════════════════════════════════════════ */ +.zo-mark { color: var(--text); } + +.badge { + font-family: var(--mono); + font-size: 10px; + letter-spacing: 0.1em; + padding: 3px 9px; + border-radius: 3px; + display: inline-flex; + align-items: center; + gap: 6px; + border: 1px solid transparent; + text-transform: uppercase; +} +.badge-coral { background: var(--coral-soft); color: var(--coral); border-color: oklch(0.74 0.14 35 / 0.3); } +.badge-dusk { background: var(--dusk-soft); color: var(--dusk); border-color: oklch(0.70 0.10 245 / 0.3); } +.badge-moss { background: var(--moss-soft); color: var(--moss); border-color: oklch(0.62 0.08 150 / 0.3); } +.badge-dim { background: transparent; color: var(--text-3); border-color: var(--line-2); } +.badge-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; } + +.btn { + font-family: var(--sans); + font-weight: 500; + font-size: 13px; + letter-spacing: -0.005em; + padding: 8px 16px; + border-radius: 6px; + border: 1px solid transparent; + cursor: pointer; + display: inline-flex; + align-items: center; + gap: 8px; + transition: all 0.15s var(--ease); + text-decoration: none; + line-height: 1; +} +.btn-primary { background: var(--coral); color: #1A0F06; font-weight: 600; } +.btn-primary:hover { background: oklch(0.78 0.14 35); transform: translateY(-1px); } +.btn-secondary { background: transparent; color: var(--text); border-color: var(--line-2); } +.btn-secondary:hover { border-color: var(--text-2); background: var(--surface-2); } +.btn-danger { background: transparent; color: var(--coral); border-color: oklch(0.74 0.14 35 / 0.4); } +.btn-danger:hover { background: var(--coral-soft); } + +.inp { + font-family: var(--sans); + font-size: 13px; + background: var(--editor); + border: 1px solid var(--line-2); + color: var(--text); + padding: 9px 13px; + border-radius: 6px; + outline: none; + transition: border-color 0.15s var(--ease); + width: 100%; +} +.inp:focus { border-color: var(--coral); } +.inp::placeholder { color: var(--text-4); } + +.code { + font-family: var(--mono); + font-size: 12.5px; + background: var(--editor); + border: 1px solid var(--line); + border-radius: 8px; + padding: 16px 18px; + color: var(--text-2); + line-height: 1.7; + overflow-x: auto; +} +.code .c-prompt { color: var(--coral); user-select: none; margin-right: 8px; } +.code .c-cmd { color: var(--text); } +.code .c-arg { color: var(--dusk); } +.code .c-comment{ color: var(--text-4); } +.code .c-ok { color: var(--moss); } + +/* Terminal ground (xterm.js stand-in) */ +.term { + font-family: var(--mono); + font-size: 12px; + line-height: 1.65; + background: var(--canvas); + color: var(--cream-2); + padding: 14px 16px; + overflow: hidden; + white-space: pre-wrap; +} +[data-theme="light"] .term { background: #211E17; } /* terminals stay dark in light theme, like VS Code */ +.term .t-coral { color: oklch(0.74 0.14 35); } +.term .t-dusk { color: oklch(0.70 0.10 245); } +.term .t-moss { color: oklch(0.62 0.08 150); } +.term .t-dim { color: #857D6B; } +.term .t-cream { color: #EBE3D2; } +.term .caret::after { content: "▍"; color: oklch(0.74 0.14 35); animation: blink 1s steps(1) infinite; } +@keyframes blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } } + +/* Pulse for live/running dots */ +@keyframes pulse-lighthouse { + 0%, 100% { opacity: 0.4; transform: scale(1); } + 50% { opacity: 1; transform: scale(1.15); } +} +.pulse { animation: pulse-lighthouse 2.4s var(--ease) infinite; transform-origin: center; } + +/* Footer */ +.footer { + text-align: center; + padding-top: 72px; + font-family: var(--mono); + font-size: 10px; + color: var(--text-4); + letter-spacing: 0.18em; + text-transform: uppercase; +} +.footer a { color: inherit; } diff --git a/memory/zo-platform/DECISION_LOG.md b/memory/zo-platform/DECISION_LOG.md index bcc8bb7..454a7f6 100644 --- a/memory/zo-platform/DECISION_LOG.md +++ b/memory/zo-platform/DECISION_LOG.md @@ -1220,6 +1220,8 @@ The `--no-headlines` flag is preserved (not removed) for backwards compatibility **Outcome:** +28 tests (826 → 854), green on Python 3.11 AND 3.12, ruff clean, validate-docs 0 failures; 12-check real-`uv run zo` smoke passed. Follow-up commit: `apply_bypass_overlay` no-ops when bypass is already active (inherit, not clobber), so `zo report --bypass-permissions` is safe alongside a model session in bypass — closes a lingering-bypass bug (model exits first → repo left in bypass). Docs: `docs/COMMANDS.md` + `README.md` gain `zo report` / `zo consolidate`. Branch `claude/zo-report-surrogate`, PR pending. PRIORS PR-045 added. +--- + ## Decision: 2026-06-11T12:00:00Z **Type:** TESTING **Title:** CLI command-set test asserts subset, not equality — tolerate plugin-added commands @@ -1227,3 +1229,24 @@ The `--no-headlines` flag is preserved (not removed) for backwards compatibility **Rationale:** PR #99 shipped extension points whose documented purpose is letting downstream builds add CLI commands via entry points discovered at `zo.cli` import. A strict-equality command-set test makes the CORE suite fail in any environment where such a plugin is installed — the first real downstream plugin (registering a new command group) surfaced exactly that. The test's job is "core commands all present"; removals still fail under subset. **Alternatives considered:** (1) Computing `actual` minus plugin-contributed commands — `load_cli_plugins` doesn't record which commands each plugin added; tracking that adds machinery for a test. (2) Re-importing `zo.cli` with plugin discovery monkeypatched off — fragile import gymnastics for marginal benefit. (3) Leave it and tell downstream users to expect one red test — contradicts the extension point being a supported public mechanism. **Outcome:** Single-assertion diff + memory. 854 passed / 7 skipped on Python 3.11 AND 3.12, ruff clean, validate-docs 0 failures. Branch `claude/cli-test-plugin-tolerant`. + +--- + +## Decision: 2026-07-12T14:30:00Z +**Type:** ROADMAP + PLANNING +**Title:** 2026-07 feature roadmap approved — four workstreams (lit review, cross-phase backedge, Slack bridge, VS Code extension); caveman dropped; build paused pre-implementation at Sam's request + +**Decision:** Plan of record: `memory/zo-platform/roadmaps/2026-07-feature-roadmap.md` (persisted verbatim at approval). Four sequenced workstreams, each a PR series: + +1. **WS1 — Phase 0 lit review, strengthened + opt-in for all modes.** New optional `## Literature Review` plan section (`LiteratureReviewSpec`, `## Experiment Loop` parser precedent); one enriched `literature_review_phase()` + `with_phase_0()` factory composed in `_resolve_phases()` (the PR #99 seam); four enforced gate artifacts under `research/` (existence-checked, gate ITERATEs naming missing files); `AGENT_PHASE_MAP` fix (add phase_0 to research-scout, REMOVE the accidental phase_0 from data-engineer, don't add code-reviewer); low-token keeps research-scout in phase_0 only; new `_prompt_research_context`. `zo.scholar` grounding layer stays a separate follow-up PR. +2. **WS2 — `RETURN_TO_PHASE` backedge (F3 Phase A).** Per the session-028 design of record with ONE deviation: the requesting phase N goes **PENDING with M appended to `depends_on`**, NOT BLOCKED — BLOCKED means "human escalation required" (PR-037, `get_current_phase` contract); PENDING-with-deps-met resumes N automatically when M re-completes with zero consumer blast radius. Request channel = `.zo/revisit_request.json` written by the lead, centrally validated at BOTH real execution points (top of `advance_phase` AND `cli.build` between decompose and get_current_phase — `advance_phase` has no production caller today). Guardrails: global budget `--max-cross-phase-revisits` default 2 (persisted), Jaccard ≥0.9 duplicate-reason rejection (shared `text_similarity()` refactored from experiment_loop), structural validation, ESCALATE + evolution learning on rejection, budget visible in the lead prompt. New `## Revisits` STATE.md section (must be excluded from `_extract_extra_sections` or it duplicates on every save). +3. **WS3 — Slack bridge, WhatsApp later.** Standalone `zo bridge` sidecar (PRD §8's sanctioned watcher pattern; survives across runs; answers "nothing running"), registered in the liveness registry with `role="bridge"` (peer-logic consumers must filter by role). Outbound: byte-offset tail of `logs/comms/*.jsonl` (dedup by file+offset — the `event_id` dedup in `_print_status` is a latent no-op, fix in passing), templated gate/error/digest/session messages. Inbound: allowlisted Slack users; `approve`/`reject ` inject `/gates:approve`//`gates:reject` into the orchestrator pane via a new shared `src/zo/tmux_io.py` (extracted from wrapper.py:253-270/364-398); `mode` writes the hot-reloaded gate_mode file; free text relayed with provenance prefix. Surrogate lock files enriched with `tmux_pane_id`/`team_name`/`project`. Transport = Protocol; SlackTransport via official slack-sdk Socket Mode as optional extra `bridge = ["slack-sdk>=3.27"]`; empty allowlist = outbound-only. +4. **WS4 — VS Code extension, design-first.** HTML mockups in `design/vscode/` are the approval artifact — Sam's sign-off gates all Stage-2 code. Engine: additive `--headless-tmux` (`tmux new-session -d` + `pipe-pane -o`) + new `src/zo/runtime.py` + versioned `.zo/runtime/session.json` contract; the session-028 "zero wrapper.py changes" claim was optimistic. Extension in monorepo `vscode/` dir (TypeScript, xterm.js, hand-rolled SVG charts, `zo runtime send` so ALL tmux logic stays in tested Python), documented extraction path to a `zo-vscode` repo once the contract freezes. v1 input model: read-only streams + composer (no per-keystroke TTY passthrough). + +**Sequencing:** D1 mockups → A1 → B1/B2 → C1–C3 → D2–D7. **Caveman: dropped from scope by Sam** ("No need for caveman now") — remains a roadmap card, nothing built, preset untouched. + +**Rationale:** Sam requested five features; scoping questions resolved lit-review shape (in-project Phase 0, not a standalone command), messaging order (Slack first — Socket Mode needs no public endpoint; WhatsApp needs Meta/Twilio + webhook hosting), VS Code approach (design mockups first), and scope (all five sequenced, then caveman dropped). Three exploration agents + three design agents grounded every workstream in verified file:line reality; the notable discovery is the phase_0 latent bug (runtime roster `[data-engineer]`, no required artifacts — the PR-004 prior about uninformed model design was structurally guaranteed by the code). + +**Alternatives considered:** standalone `zo research` mode (rejected by Sam); WhatsApp-first (heavier transport, deferred behind the Protocol); BLOCKED for the requesting phase per the session-028 sketch (rejected — breaks the PR-037 invariant and needs an auto-unblock side channel); per-gate `gate_decision` file for remote approval (rejected — duplicates the slash commands' STATE/DECISION_LOG/comms mutations; injection reuses one tested path); separate `zo-vscode` repo immediately (deferred — contract churn makes two repos a version-skew dance for one developer); bundling `zo.scholar` into PR A1 (rejected — different review profile, network seam, optional dep). + +**Outcome:** Roadmap persisted to tracked memory (see PR-046 — the session-028 internal plan file this pattern replaces was found to have vanished from `~/.claude/plans`). PR D1 (#103) executed end-to-end on branch `claude/vscode-design-mockups`: tokens.css + 9 pages generated by a 9-agent parallel workflow, then (after Sam's brief mid-session pause) a resumed consistency-review agent reconciled cross-page timeline/metric drift onto one canonical clock and browser-verified all pages in both themes; token-purity/skeleton/no-emoji/no-external-deps/link checks clean. Sam's initial reaction on viewing: "the screens are awesome!" — formal per-screen sign-off via the PR review of `00-overview.html` still gates Stage 2. Session numbering note: upstream PRs #101/#102 landed a session-039 mid-flight, so this session renumbered to 040 and the branch rebased onto updated main. Open style question deferred to Sam in the PR: em-dashes kept as the design-file house glyph despite the prose ban. Pickup: `sessions/session-040-2026-07-12.md`. diff --git a/memory/zo-platform/PRIORS.md b/memory/zo-platform/PRIORS.md index 8ef9eb9..ded7139 100644 --- a/memory/zo-platform/PRIORS.md +++ b/memory/zo-platform/PRIORS.md @@ -1399,3 +1399,27 @@ rm -f package-lock.json # keep the diff to the intend ### Verified Solution `_launch_and_monitor` gates `cleanup_stale_overlay` on `session_role == "model"` (report sessions never touch the overlay) and threads a `consolidate_on_exit` flag; `zo report --no-consolidate` sets it False. Tests: `test_report_session_never_cleans_overlay` (report never cleans even with no peer registered), `test_launch_and_monitor_no_consolidate_skips_merge`, plus the concurrency / conflict / resume / STATE-untouched suite (`test_surrogate_edge.py`). Concurrent **bypass** is handled by the same principle: `apply_bypass_overlay` no-ops when bypass is already active (inherit, not clobber), so a second bypass session (`zo report --bypass-permissions` alongside a model session in bypass) cannot leave the repo stuck in bypass after exit (`test_apply_is_noop_when_bypass_already_active`). **Cross-reference:** PR-037 (no session lock — single-session-by-design; this is the multi-session follow-on), PR-038 / PR-043 (permission-overlay lifecycle), PR-009 / PR-041 (built-must-be-wired — here, wired *and* made robust to the unupgraded peer). + +--- + +## PR-046: Plans Referenced From Tracked Memory Must Themselves Be Tracked — ~/.claude/plans Is Ephemeral +**Source:** Session 040 (2026-07-12), roadmap planning +**Root cause category:** incomplete_rule (memory protocol covered STATE/DECISION_LOG/PRIORS but not externally-stored artifacts they reference) + +**Failure:** Session 028's STATE.md and DECISION_LOG both referenced "full internal plan at `~/.claude/plans/so-before-i-begin-peaceful-valley.md`" (effort estimates, file paths, TODO checklists for the F3 cross-phase work and the VS Code extension). In session 040 that file **no longer exists** — `~/.claude/plans/` is session tooling scratch, subject to cleanup outside ZO's control. Only the design-level summary duplicated into DECISION_LOG survived; the granular detail was unrecoverable and had to be re-derived from scratch (three exploration agents + three design agents). + +### Rules + +1. **Any artifact referenced from tracked memory must itself be tracked.** If STATE.md or DECISION_LOG says "full detail lives at ", that path must be inside the repo (for ZO-platform work: `memory/zo-platform/roadmaps/` or `sessions/`). Copy the artifact verbatim at reference time — at approval, not "later". + - **Why:** memory is only as durable as its weakest pointer. A tracked one-line reference to an untracked file silently becomes a dangling pointer, and the reader discovers it exactly when they need the detail. + - **How to apply:** when ending a session that produced an approved plan in `~/.claude/plans/`, `cp` it into `memory/zo-platform/roadmaps/-.md` with a provenance header, and reference the tracked copy (the ephemeral path at most as a courtesy note). + +2. **Treat `~/.claude/plans/`, scratchpads, and session temp dirs as ephemeral by definition.** They are fine as working locations, never as archival ones. Same reasoning as PR-028 (gitignored project memory trapped on one machine — gitignored/external files don't transfer OR persist). + +3. **Duplication into DECISION_LOG is the safety net, not the archive.** The session-028 DECISION_LOG summary is what made re-derivation possible at all — keep writing rich summaries — but a summary is lossy by design; the full artifact needs its own tracked home. + +### Verified Solution + +The 2026-07 feature roadmap was persisted verbatim to `memory/zo-platform/roadmaps/2026-07-feature-roadmap.md` (with a provenance header) in the same session it was approved, and STATE.md/DECISION_LOG reference the tracked copy. Applied retroactively where possible: the lost session-028 detail was re-derived and is superseded by the new roadmap. The rule would have caught the original failure — session 028 would have copied the peaceful-valley file at write time. + +**Cross-reference:** PR-028 (project memory must live where it transfers), PR-003/PR-005 (references and rules drift without enforcement). diff --git a/memory/zo-platform/STATE.md b/memory/zo-platform/STATE.md index fd2fd50..281ef94 100644 --- a/memory/zo-platform/STATE.md +++ b/memory/zo-platform/STATE.md @@ -8,9 +8,11 @@ status: complete ## Current Position -**Session 039 (current) — pick up here.** Test-only change making the CLI command-set test plugin-tolerant: `tests/unit/test_cli.py::TestCliGroup::test_cli_group_has_all_commands` asserted strict equality on `cli.commands`, which contradicts the extension points ZO itself shipped in PR #99 — any downstream build installing a `zo.commands` entry-point plugin (the documented mechanism in `zo.extensions.load_cli_plugins`) adds commands and turned the core suite red in that environment, despite zero core changes. Changed `assert expected == actual` → `assert expected <= actual` with an explanatory comment. Trade-off accepted: equality also caught *core* commands added without updating the test; subset still catches removals, and additions have always required updating this test's `expected` set anyway. Surfaced by the first real downstream plugin registering a new command group. No code, version, agents, or docs touched — single-assertion diff (+ memory). **854 passed / 7 skipped on Python 3.11 AND 3.12, ruff `src/` clean, validate-docs 0 failures.** **Next:** unchanged — Batch **D** / **E**, standing Tier-1 (caveman, onboarding). +**Session 040 (current) — pick up here.** Planning session + PR D1 shipped; Sam paused mid-session, then resumed to finish ("pause and start a new session once plan is firm"). Produced and got approval on the **2026-07 feature roadmap** — four sequenced workstreams: **WS1** lit review (strengthen in-project Phase 0, opt-in for all modes — includes fixing the newly-found `AGENT_PHASE_MAP` phase_0 bug where the runtime roster is `[data-engineer]` and the hard-coded agents at `_orchestrator_phases.py:264` are dead code, plus enforced `research/` gate artifacts), **WS2** cross-phase `RETURN_TO_PHASE` backedge (F3 Phase A; one planned deviation from the session-028 sketch — requesting phase goes PENDING-with-new-dependency, not BLOCKED, preserving the PR-037 "BLOCKED = human escalation" invariant), **WS3** Slack bridge (standalone `zo bridge` sidecar; comms-JSONL byte-offset tail out, tmux pane injection in via a new shared `tmux_io.py`; slack-sdk Socket Mode as optional extra; WhatsApp later behind the same Transport protocol), **WS4** VS Code extension (design-first; headless-tmux engine `tmux new-session -d` + `pipe-pane` → `.zo/runtime/` contract → xterm.js webview; monorepo `vscode/` dir with documented extraction path). **Caveman was dropped from scope by Sam** ("No need for caveman now") — stays a roadmap card, build nothing. Sequencing: **D1 mockups → A1 → B1/B2 → C1–C3 → D2+**. Plan of record persisted at `memory/zo-platform/roadmaps/2026-07-feature-roadmap.md` (PR-046: the session-028 `~/.claude/plans` roadmap file was found to have vanished — internal plan files are ephemeral, load-bearing plans now live in tracked memory). **PR D1 built** on branch `claude/vscode-design-mockups`: `design/vscode/tokens.css` (brand tokens + dark/light theme + VS Code chrome sim) + 9 mockup pages generated by a parallel workflow, all depicting one canonical MNIST-demo moment. Sam resumed mid-pause ("finish the mockups then lets pause"): the stopped workflow was resumed (10 agents total, 9 pages + reviewer) — the consistency reviewer reconciled a two-clock timeline split across pages onto one canonical clock (prior session 2026-07-11 completed phases 1–3 + exp-001/002; today resumes 09:14:12, phase_3→4 gate passes 09:15, exp-003 runs 09:17→09:43), aligned metric values everywhere (exp-001 0.9770, exp-002 0.9841, per-class breakdown averaging exactly 0.9912), and **browser-verified all 9 pages in both themes**; skeleton/token-purity/no-emoji/no-external-deps/link checks all clean. Sam viewed the screens live: **"the screens are awesome!"** — recorded as the initial design reaction; formal per-screen sign-off happens on the PR (review `00-overview.html`) and still gates all Stage-2 VS Code work. **Shipped as PR #103 (D1)** from branch `claude/vscode-design-mockups`, rebased past upstream #101/#102 (whose session claimed the 039 slot — hence this is session 040). Open style question flagged in the PR body: em-dashes retained as the design-file house glyph (mirrors `design/brand-system.html` list glyphs) despite the prose no-em-dash convention — Sam to rule. Pre-existing tree state untouched and unexplained: modified `CLAUDE.md` + untracked `paper/` (predate session 040). **Next:** Sam reviews PR D1 (sign-off gates Stage 2), then **PR A1** — WS1 Phase 0 lit-review strengthening + the `AGENT_PHASE_MAP` phase_0 bug fix, per `roadmaps/2026-07-feature-roadmap.md`. Pickup instructions in `sessions/session-040-2026-07-12.md`. -**Session 038 hand-off (prior).** Shipped **concurrent report sessions** (the *surrogate* model): `zo report` runs an Opus report-lead in an isolated git worktree ALONGSIDE a live `zo continue` model session on the same project, with safe consolidation back. New modules — `src/zo/surrogate.py` (worktree + `report/` branch + per-PID liveness lock files + delta-memory store at `.zo/surrogates//`), `src/zo/consolidate.py` (fold deltas → canonical: append DECISION_LOG, dedup PRIORS, copy session summaries, commit+merge the report branch, archive; **never** writes canonical STATE), `src/zo/report.py` (Opus report-lead prompt: verify via `oracle-qa` + `data-engineer`, write LaTeX, hard read-only boundaries on canonical memory + experiments). `flock` added to `memory.append_decision/append_prior`. New CLI: `zo report` (`--objective`/`--resume`/`--no-consolidate`/`--no-tmux`/`--bypass-permissions`) + `zo consolidate` (`--dry-run`); `_launch_and_monitor` gains per-PID registration + auto-consolidation when the **last** session exits + liveness-gated overlay cleanup. **Two safety hardenings (PRIORS PR-045):** (1) a report session NEVER touches the shared permission overlay — cleanup is gated to orchestrator-role sessions only, so a report can't disrupt a running `zo continue` even though that session predates the liveness registry; (2) `--no-consolidate` suppresses exit-merge for exactly that predates-the-registry case (merge later with `zo consolidate`). Verified: 28 new tests (unit prompt + real-git round-trip incl. deferred-merge/no-double-fold + CLI wiring + concurrency/conflict/resume/STATE-untouched/overlay-isolation + bypass-inherit), **826 → 854 passed, 7 skipped on Python 3.11 AND 3.12**, ruff clean, validate-docs 0 failures, plus a 12-check real-`uv run zo` smoke. Follow-up safety: `apply_bypass_overlay` now inherits an already-active bypass overlay (no-op) instead of clobbering it, so `zo report --bypass-permissions` is safe alongside a model session running in bypass (no lingering-bypass after exit). Surrogate sessions assume both sessions share a filesystem (same machine — matches "another tmux window"); cross-machine is out of scope. Branch `claude/zo-report-surrogate` (PR pending). **Next:** unchanged — Batch **D** / **E**, standing Tier-1 (caveman, onboarding). +**Session 039 (prior).** Test-only change making the CLI command-set test plugin-tolerant: `tests/unit/test_cli.py::TestCliGroup::test_cli_group_has_all_commands` asserted strict equality on `cli.commands`, which contradicts the extension points ZO itself shipped in PR #99 — any downstream build installing a `zo.commands` entry-point plugin (the documented mechanism in `zo.extensions.load_cli_plugins`) adds commands and turned the core suite red in that environment, despite zero core changes. Changed `assert expected == actual` → `assert expected <= actual` with an explanatory comment. Trade-off accepted: equality also caught *core* commands added without updating the test; subset still catches removals, and additions have always required updating this test's `expected` set anyway. Surfaced by the first real downstream plugin registering a new command group. No code, version, agents, or docs touched — single-assertion diff (+ memory). **854 passed / 7 skipped on Python 3.11 AND 3.12, ruff `src/` clean, validate-docs 0 failures.** **Next:** superseded by the session-040 roadmap (see current entry). + +**Session 038 (prior).** Shipped **concurrent report sessions** (the *surrogate* model): `zo report` runs an Opus report-lead in an isolated git worktree ALONGSIDE a live `zo continue` model session on the same project, with safe consolidation back. New modules — `src/zo/surrogate.py` (worktree + `report/` branch + per-PID liveness lock files + delta-memory store at `.zo/surrogates//`), `src/zo/consolidate.py` (fold deltas → canonical: append DECISION_LOG, dedup PRIORS, copy session summaries, commit+merge the report branch, archive; **never** writes canonical STATE), `src/zo/report.py` (Opus report-lead prompt: verify via `oracle-qa` + `data-engineer`, write LaTeX, hard read-only boundaries on canonical memory + experiments). `flock` added to `memory.append_decision/append_prior`. New CLI: `zo report` (`--objective`/`--resume`/`--no-consolidate`/`--no-tmux`/`--bypass-permissions`) + `zo consolidate` (`--dry-run`); `_launch_and_monitor` gains per-PID registration + auto-consolidation when the **last** session exits + liveness-gated overlay cleanup. **Two safety hardenings (PRIORS PR-045):** (1) a report session NEVER touches the shared permission overlay — cleanup is gated to orchestrator-role sessions only, so a report can't disrupt a running `zo continue` even though that session predates the liveness registry; (2) `--no-consolidate` suppresses exit-merge for exactly that predates-the-registry case (merge later with `zo consolidate`). Verified: 28 new tests (unit prompt + real-git round-trip incl. deferred-merge/no-double-fold + CLI wiring + concurrency/conflict/resume/STATE-untouched/overlay-isolation + bypass-inherit), **826 → 854 passed, 7 skipped on Python 3.11 AND 3.12**, ruff clean, validate-docs 0 failures, plus a 12-check real-`uv run zo` smoke. Follow-up safety: `apply_bypass_overlay` now inherits an already-active bypass overlay (no-op) instead of clobbering it, so `zo report --bypass-permissions` is safe alongside a model session running in bypass (no lingering-bypass after exit). Surrogate sessions assume both sessions share a filesystem (same machine — matches "another tmux window"); cross-machine is out of scope. Branch `claude/zo-report-surrogate` (PR pending). **Next:** unchanged — Batch **D** / **E**, standing Tier-1 (caveman, onboarding). **Session 037 (prior).** Website content-only change: added two contributors to the public site's footer Contributors list (`website/src/pages/index.html`), preserving the existing **alphabetical-by-surname** ordering — Bryce Bartmann (`linkedin.com/in/bryce-bartmann-8b925417`) between Agrawal and Chatfield, James Friesen (`linkedin.com/in/jamestfriesen`) between Davies and Imrie. Each reuses the existing `
  • ` pattern. User typed "Bartmaan"; the LinkedIn slug is `bryce-bartmann` → used "Bartmann" (user confirmed). **Verified** via a real Astro build (`npm install && npx astro build`, exit 0) — rendered `dist/index.html` lists all 8 names in correct order. No code/tests/agents/commands/version/model tiers touched — pure content, single-file diff (+ memory). validate-docs 0 failures. **Verification gotcha → PR-044:** `npx astro dev` died on first launch (`website/node_modules` absent → npx floated to astro@6.4.3 vs pinned `^5.0.0`); `npm install` first is the reliable path, and the stray `package-lock.json` it generates is removed to keep the diff clean. **Next:** unchanged — Batch **D** / **E**, standing Tier-1 (caveman, onboarding). @@ -188,9 +190,9 @@ ZO **v1.0.2** + **`--low-token` mode** (session-024) — cost-saving preset for ## Session Metadata -last_checkpoint: 2026-06-04T00:00:00Z -last_session: session-038 (concurrent report sessions — `zo report`/`zo consolidate` surrogate model, safe alongside a live model session; PRIORS PR-045) -branch: claude/beautiful-bhabha-69ae22 (worktree, roadmap commit pending) +last_checkpoint: 2026-07-12T00:00:00Z +last_session: session-040 (2026-07 feature roadmap approved — 4 workstreams, caveman dropped; PR D1 mockups reviewed + verified + shipped; PRIORS PR-046) +branch: claude/vscode-design-mockups (PR #103 open — awaiting Sam's design review, which gates Stage-2 VS Code work) v1_status: COMPLETE — all 8 PRD §9 acceptance criteria met, all Known Issues closed docs_site: deployed at docs.zerooperators.com via Mintlify (mint.json + 16 pages: 3 get-started + 7 concepts + 4 cli + 2 reference; redirect rule /concepts/agents → /concepts/the-team for stale-cache hardening). Build verified live 2026-04-27 — all sibling concept pages return 200 except `/concepts/the-team` which 404'd due to MDX 2 prose `<500 lines, functions <50 lines` parser bug on line 51 (`<` followed by digit treated as JSX opening tag). Fixed by replacing `<500` / `<50` with `under 500` / `under 50` natural-prose. (Original planning URL `docs.zero-operators.dev` documented in DECISION_LOG was changed to the no-hyphen `docs.zerooperators.com` during actual setup; README badge + docs/README updated to match.) test_count: 854 passed, 7 skipped (ZO platform); 16 passed (mnist demo); 19 passed (cifar10 demo); 297 passed (prod-001) diff --git a/memory/zo-platform/roadmaps/2026-07-feature-roadmap.md b/memory/zo-platform/roadmaps/2026-07-feature-roadmap.md new file mode 100644 index 0000000..563717c --- /dev/null +++ b/memory/zo-platform/roadmaps/2026-07-feature-roadmap.md @@ -0,0 +1,164 @@ + + +# ZO Feature Roadmap — Four Workstreams, Sequenced + +## Context + +Sam wants a sequenced roadmap for the next generation of ZO features, implemented as separate PR series: + +1. **Lit review mode** — strengthen the in-project Phase 0 literature review and make it opt-in for all workflow modes (user chose this over a standalone command). +2. **Cross-phase handoff** — the `RETURN_TO_PHASE` backedge primitive (F3 Phase A; design of record in DECISION_LOG session-028), addressing prior external feedback. +3. **Slack integration** (WhatsApp later, behind a transport abstraction) — bidirectional: notifications when away from desk + relay instructions/gate decisions into the live lead session. +4. **VS Code UI** — stop requiring raw tmux; **design mockups first** (ZO brand system) for approval, then build per the session-028 architecture (headless tmux engine + xterm.js renderer). + +**Caveman integration was dropped from scope by Sam** ("No need for caveman now") — remove nothing, build nothing; it stays a roadmap card. + +Recommended implementation order: **WS4-PR1 (mockups, cheap, needs Sam's approval) → WS1 (lit review) → WS2 (backedge) → WS3 (Slack bridge) → WS4 (VS Code engine + extension)**. The mockup PR is design-only and unblocks nothing else, so it goes first to give Sam something to react to while code work proceeds. + +## Verified key facts (from exploration) + +- **Latent bug (confirmed by direct read)**: `AGENT_PHASE_MAP` ([_orchestrator_phases.py:21-40](src/zo/_orchestrator_phases.py)) gives `research-scout`/`code-reviewer` phases 1–6 only, but `data-engineer` includes `phase_0`. Since `decompose_plan()` overwrites `assigned_agents` via `_agents_for_phase()` (orchestrator.py:333-336, 809-845), today's runtime phase_0 roster is `[data-engineer]` — the hard-coded `["code-reviewer","research-scout"]` at `_orchestrator_phases.py:264` is dead code. Phase 0 also has **no `required_artifacts`** — its automated gate verifies nothing. +- `GateDecision` = {PROCEED, HOLD, ITERATE, ESCALATE} ([_orchestrator_models.py:39-45](src/zo/_orchestrator_models.py)); no RETURN_TO_PHASE yet. `advance_phase()` has **no production caller** — the lead session mutates STATE.md; Python re-reads it at next launch. Backedge enforcement must hook the paths that actually run: CLI launch (between decompose and get_current_phase) AND advance_phase. +- Text injection into a running lead session exists only inline (wrapper.py:253-270 load-buffer→paste-buffer→send-keys, duplicated at :386-398) — must be extracted; shared by bridge inbound + VS Code gate approval. +- Session discovery: per-PID lock files `/.zo/surrogates/locks/.json` (surrogate.py:240-321) — but the pane id isn't in them yet (cli.py writes the lock before the pane id is known). +- Outbound substrate: `logs/comms/{date}.jsonl` (event types message|decision|gate|error|checkpoint, comms.py:31-38) — exactly PRD §8's sanctioned "integration bridge tails the JSONL" pattern. Bridge must dedup on byte offset (`_print_status`'s `event_id` dedup at cli.py:885-888 keys on a field no event has — latent no-op; fix in passing). +- No `tmux new-session -d` / `pipe-pane` support exists; wrapper's tmux path requires being inside tmux (`_is_in_tmux`, wrapper.py:973-976). The roadmap's "zero wrapper.py changes" claim was optimistic — the engine is an additive detached-launch branch. +- `_extract_extra_sections` (`_memory_formats.py:98-121`) preserves unknown STATE.md sections verbatim → any new structured section (`## Revisits`) must be excluded there or it duplicates on every save. +- An existing detailed design for grounded literature retrieval lives at `~/.claude/plans/well-if-its-open-zany-frost-agent-a339b548df8b14ce1.md` (`src/zo/scholar.py`: Semantic Scholar + arXiv + Papers-with-Code, provenance-verified SOTA numbers, optional `httpx` extra) — planned as a follow-up PR to WS1, not bundled. + +--- + +## WS1 — Lit review: strengthened, opt-in Phase 0 (1 PR, ~2–3 days; scholar follow-up ~4–5 days) + +### Design +- **Opt-in mechanism**: new optional plan section `## Literature Review` (aliases "literature review", "prior art") following the `## Experiment Loop` parser precedent (plan.py `_OPTIONAL_SECTION_ALIASES` :568-579, `_parse_experiment_loop` :668-691). New `LiteratureReviewSpec` pydantic model: `enabled`, `min_approaches` (default 3), `min_baselines` (default 2), `focus` (free text). Semantics: classical_ml/deep_learning get phase_0 iff section present and `enabled` ≠ false; **research mode keeps phase_0 always-on** (`enabled: false` → validation warning, ignored). +- **One enriched factory**: new `literature_review_phase(spec)` + `with_phase_0(phases, spec)` in `_orchestrator_phases.py`; `research_phases()` rewritten to use it (deletes the under-specified block at :259-267). Six subtasks (prior-art survey, SOTA summary, baseline definition, OSS catalog, experiment plan + oracle thresholds, references). Composition happens in `Orchestrator._resolve_phases()` (:303-319, the PR #99 seam) so subclass overrides keep working. +- **Enforced gate artifacts** (existence-checked by `_check_artifacts`; gate ITERATEs naming missing files): `research/literature_review.md`, `research/baseline_definition.md`, `research/experiment_plan.md`, `research/references.bib`. Deliberately NOT required: `sota_summary.md`, `open_source.md` (PRIORS PR-004: customer domains may have no published benchmarks — don't block), `pretrained_models.yaml` (meaningless for most classical_ml). Artifact names standardize on the research-scout contract; `specs/workflow.md:60-92` updated to drop the stale `prior_art_survey.md` naming. +- **AGENT_PHASE_MAP fix**: add `phase_0` to `research-scout`; **remove** `phase_0` from `data-engineer` (accidental current state — flag as behavior change in DECISION_LOG); do NOT add code-reviewer (no code in phase_0). Low-token exception in `_agents_for_phase` (:836-837): keep research-scout in phase_0 only (if the user opted in, silently dropping the phase's only agent defeats the opt-in) — document in `docs/reference/low-token-preset.mdx`. +- **New prompt builder** `_prompt_research_context(phase)` (modeled on `_prompt_experiment_context` :1192-1268; wired into `build_lead_prompt` :397-427): the four gate-required paths + optional ones, quality bars (≥`min_approaches` cited approaches, ≥`min_baselines` baselines, eval protocol consistent with prior art), the plan's oracle metric/threshold injected so the scout validates or challenges it, PR-004's "no benchmark ≠ blocker" escape hatch, `spec.focus`, Gate 0 review framing. + +### Files +`src/zo/plan.py` (spec + parsing + validation warning), `src/zo/_orchestrator_phases.py` (factory + map fix), `src/zo/orchestrator.py` (`_resolve_phases` composition, `_literature_review_enabled`, `_prompt_research_context`, low-token exception), `.claude/agents/research-scout.md` (+`baseline_definition.md` ownership, gate-artifact checklist). + +### Docs cascade +`specs/workflow.md` (Phase 0 section retitle + artifact reconciliation), `specs/plan.md` (new optional section), `specs/agents.md` §7, `docs/concepts/phases-and-gates.mdx`, `docs/concepts/the-plan.mdx`, `docs/reference/low-token-preset.mdx`, README phase table if present. + +### Tests +Unit: factory composition (prepend, `phase_1.depends_on == ["phase_0"]`), opt-in parsing (present/absent/`enabled: false`/aliases/int coercion/research-mode warning), decompose regressions (classical without section → 6 phases; with → 7 phases and `assigned_agents == ["research-scout"]`), low-token phase_0 exception, **negative artifact-gate tests per PRIORS PR-035 — omit each required artifact individually → ITERATE naming it**, `get_current_phase` ordering, STATE.md `phase_0:` round-trip, mid-project opt-in determinism, prompt content. Integration: full decompose → gate-ITERATE-without-artifacts → write files → PROCEED → phase_1 current; session round-trip. Python 3.11 + 3.12. + +### Follow-up PR (optional, Sam decides when reached): `zo.scholar` +Per the existing design doc: `src/zo/scholar.py` (PwC + Semantic Scholar + arXiv, pydantic models, `python -m zo.scholar` JSON CLI, `.zo/scholar-cache/`, `ZO_SCHOLAR_OFFLINE=1`, optional `scholar = ["httpx>=0.27"]` extra mirroring the fastembed pattern), recorded-fixture tests incl. phantom-SOTA rejection, research-scout contract updated to require provenance-backed numbers. WS1's gate list deliberately doesn't depend on scholar output, so this composes cleanly later. + +--- + +## WS2 — Cross-phase backedge: RETURN_TO_PHASE (2 PRs, ~5–7 days) + +### Design (follows DECISION_LOG session-028, one justified deviation) +- **State machine — deviation from the session-028 sketch (log it in DECISION_LOG)**: on applying a revisit of phase M requested by phase N: M `COMPLETED → ACTIVE` (+ clear subtasks, `_abort_running_experiments` if phase_4); **N → `PENDING` with M appended to `depends_on`** (NOT BLOCKED — BLOCKED means "human escalation required" per PR-037 and the `get_current_phase` contract; PENDING-with-deps-met already resumes N automatically the moment M re-completes, with zero changes to resolution order, no new PhaseStatus, no consumer blast radius); intermediate COMPLETED phases between M and N → PENDING with cleared subtasks (their outputs are stale by construction). +- **Request channel**: structured file `/.zo/revisit_request.json` (`from_phase`, `to_phase`, `reason`, `constraint`, `requested_by`, `requested_at`) written by the lead (works in full-auto; writing one JSON file is far more reliable than hand-editing STATE.md — PR-036 family). Consumed with central validation at BOTH points Python actually runs: top of `advance_phase()` and in `cli.build` between `decompose_plan()` and `get_current_phase()` (steps 7→8). On consumption: validate → apply or reject → archive to `.zo/revisits/handled-.json` (idempotent). `GateDecision.RETURN_TO_PHASE` added as the evaluation outcome + an explicit `apply_human_decision(..., target_phase=)` branch for the human-driven path. +- **Guardrails (convergence/token blow-up was Sam's flagged risk)**: global budget `--max-cross-phase-revisits` default **2** per project (persisted counter — survives sessions); duplicate-reason rejection via Jaccard ≥0.9 against previously applied records for the same edge (refactor `experiment_loop`'s `_tokenize`/`_jaccard` into a shared public `text_similarity()`; parity-pin test); structural validation (to_phase must precede from_phase, be COMPLETED; no self/forward edges); budget-exhausted/dead-end → ESCALATE + `_record_learning()` evolution prior, never silent; the remaining budget is shown in the lead prompt (itself a convergence guardrail); full audit to comms + DECISION_LOG + a phase snapshot on M's re-activation. +- **New module** `src/zo/_orchestrator_revisit.py` (~250 lines; orchestrator.py is already 1,666 lines): `RevisitRequest`/`RevisitRecord`/`RevisitPolicy` models, `read_pending_request` (loud ValueError on malformed JSON), `validate_request`, `archive_request`. +- **Persistence**: `SessionState` gains `revisit_count: int = 0` + `revisit_records: list[dict]` (defaults → old STATE.md parses unchanged); new `## Revisits` section in STATE.md (emitted only when records exist; pipe-delimited lines; parse-time validation with `_VALID_REVISIT_STATUSES` frozenset + drift-guard test, per PR-036). **Trap**: `_extract_extra_sections` (`_memory_formats.py:98-121`) must skip `## Revisits` like `## Phases` or it duplicates on every save. `_restore_phase_states` re-applies open records' added `depends_on` (factory resets them otherwise) and resolves records whose to_phase is COMPLETED. +- **Prompts**: `_prompt_revisit_reason(phase)` (injected when phase is a reopened to_phase: from-phase, reason, constraint, "address the constraint specifically; don't redo unrelated work"; plus a resumed-from_phase variant) and `_prompt_revisit_howto()` (teaches the JSON protocol, legitimate triggers, remaining budget; omitted in supervised mode). Both modeled on `_prompt_experiment_context`/`_render_loop_briefing`. +- **CLI/commands**: `--max-cross-phase-revisits INT` on build/continue (same plumbing as `--max-iterations`); `zo gates return-to-phase --to phase_2 --reason ... [--constraint ...]` (thin writer, `requested_by="human"`); new slash command `.claude/commands/gates/return-to-phase.md` (instructs writing the JSON, NOT hand-editing STATE.md). **validate-docs Check 3 counts command files — bump command counts in README/docs/COMMANDS.md in the same PR.** +- **Ordering rule**: a revisit request found at a phase_4 gate is processed BEFORE `_auto_iterate_if_needed` (else the loop mints a child experiment against stale upstream artifacts) — dedicated test. + +### PR split +- **PR B1 — core primitive** (~3–4 days): revisit module, enum member, state machine in `advance_phase`/`apply_human_decision`, `text_similarity` refactor, persistence + round-trip tests, unit tests. Inert without a writer — safe merge. +- **PR B2 — channel + surface** (~2–3 days): CLI-launch consumption wiring, flag, `zo gates return-to-phase`, slash command, prompt builders, integration tests (full flow incl. session-boundary resume + budget exhaustion), doc cascade (`specs/workflow.md` new section + Gate-3 text update, `phases-and-gates.mdx` gate decisions, `specs/memory.md` `## Revisits` schema, build/continue docs, roadmap.mdx item → shipped, command counts). + +--- + +## WS3 — Slack bridge (3 PRs, ~4–6 days; WhatsApp later behind the same Protocol) + +### Design +- **Process model**: standalone **`zo bridge`** sidecar (long-running CLI), not a thread in `_launch_and_monitor` — survives across runs, answers "nothing running", zero risk to the TTY-fragile orchestration core, and matches PRD §8's sanctioned watcher pattern. Registers in the liveness registry with `role="bridge"`; **`_peers_live` consumers (cli.py:758-796) must filter by role** so a running bridge never suppresses overlay cleanup or consolidation (subtlest change — explicit tests). +- **Pane discovery**: enrich the surrogate lock file with `tmux_pane_id`, `team_name`, `project`, `zo_root` via new `surrogate.update_session()`, called from `_launch_and_monitor` right after `launch_lead_session` returns (~cli.py:808). Old locks lack the field → bridge replies "session found but pane unknown (older run)". +- **Transport**: `Transport` Protocol (`send(Notification)`, message iteration, `close()`); implementations `ConsoleTransport` (always available; used by tests + `--transport console`) and `SlackTransport` via official **slack-sdk Socket Mode** (no public endpoint needed; bidirectional; hand-rolling the protocol has no upside). Packaging: optional extra `bridge = ["slack-sdk>=3.27"]` with the fastembed-style guarded import. `WhatsAppTransport` (Meta Cloud API/Twilio) later. +- **Outbound templates** (documented in `specs/comms.md` per PRD §8): gate reached/result (metric vs threshold, tier, pass/fail + "reply `approve` or `reject `" hint when mode is supervised/auto); errors — immediate only for severity blocking|critical, rest folds into digest; checkpoint digest batched (default 10 min, never per-checkpoint); session start/end (from lock lifecycle + wrapper completion checkpoint); on-demand status reply. +- **Inbound grammar** (first token): `status` (works with nothing running — live_sessions + STATE.md summary + last events), `approve` / `reject ` (inject `/gates:approve` / `/gates:reject ` into the orchestrator-role pane — the slash commands already perform the full STATE.md/DECISION_LOG/comms mutation; a parallel gate_decision file would duplicate that logic), `mode supervised|auto|full-auto` (`memory.write_gate_mode` — the already-remote hot-reloaded path, works without a session), free text → relayed into the pane prefixed `[remote instruction from human via slack]:`. Multiple live sessions → filter `role == "model"`, newest wins, ambiguity noted in reply; report-role surrogates never targeted. +- **Security**: hard allowlist `allowed_user_ids` in config; **empty allowlist = inbound disabled** (outbound-only); unauthorized senders get a terse denial + a warning-severity comms ErrorEvent for audit; every injection logged as a MessageEvent (`agent="bridge"`, recipient lead). Config at `~/.zo/bridge.yaml` (outside the public repo, chmod-600 check) + env overrides (`ZO_SLACK_APP_TOKEN`/`ZO_SLACK_BOT_TOKEN`) + optional `bridge:` block in `/.zo/local.yaml` (gitignored; `LocalConfig` gains an optional field). Tokens never tracked, never echoed. Optional `confirm_free_text: true` echo-and-confirm mode. +- **Reliability**: byte-offset tailing with daily-rotation handling (drain old file to EOF, then switch); offsets persisted to `logs/bridge/state-{project}.json` (inside gitignored `logs/`); restart resumes from offset, corruption → seek to newest EOF + one "skipped history" notice (no replay spam); Slack auto-reconnect + capped backoff on sends; single-threaded poll loop + Slack client thread feeding a `queue.Queue` (no asyncio — matches codebase style). Events carry `project` — tailer filters on it so two projects' bridges don't cross-notify. Drive-by: fix the `_print_status` dedup no-op (key on file+line, not `event_id`). + +### New modules (each <500 lines) +- `src/zo/tmux_io.py` — **shared foundation, also used by WS4**: `send_text_to_pane(pane_id, text, *, submit, verify)` (+retry via capture-pane), `load_file_to_pane`, `capture_pane`, `pane_alive` — logic lifted from wrapper.py:253-270/364-398; wrapper refactored to call it (net negative lines). +- `src/zo/_bridge_models.py` — `BridgeConfig`/`Notification`/`InboundMessage`/`TailState` + config loader. +- `src/zo/bridge_transports.py` — Protocol + Console + Slack transports. +- `src/zo/bridge.py` — `CommsTailer`, template renderers, `InstructionRouter`, `BridgeService.run()`. + +### CLI +`zo bridge -p [--repo] [--transport slack|console] [--dry-run] [--outbound-only]` (`--dry-run` renders the last ~20 events through templates and exits — template debugging without Slack). + +### Tests +Unit: tailer (offset resume, rotation, restart-after-truncation, malformed lines), templates (all five event types, severity filtering, digest batching, approve-hint only in supervised/auto), router (allowlist deny+audit, grammar, target selection, provenance prefix, confirm handshake), config (env overrides, missing token, precedence, chmod warning), tmux_io (subprocess monkeypatched; retry parity with old wrapper logic), SlackTransport with `sys.modules`-mocked slack_sdk + skip-if-not-installed guard. Integration: real CommsLogger → FakeTransport notifications; inbound `approve` → asserted `/gates:approve` injection with pane id from enriched lock; `mode auto` → gate_mode file change; zero locks → "nothing running"; wrapper regression suite green after tmux_io extraction. All green on 3.11/3.12 **without slack-sdk installed**. + +### PR split +- **PR C1** (~0.5–1 day): `tmux_io.py` extraction + wrapper refactor; lock enrichment + `update_session` + cli wiring; role-aware peer filtering; `_print_status` dedup fix; tests. **Shared foundation for WS4.** +- **PR C2** (~2–3 days): bridge core (models/config/tailer/templates/router/ConsoleTransport), `zo bridge` (console + dry-run), unit + integration tests, specs/comms.md section. +- **PR C3** (~1–2 days): SlackTransport + optional extra + reconnect/backoff + mocked tests + docs (`docs/cli/bridge.mdx` + mint.json nav, COMMANDS.md, README "Built on" slack-sdk entry, roadmap.mdx). +- **PR C4 (later, unscoped)**: WhatsAppTransport behind the same Protocol. + +--- + +## WS4 — VS Code extension, design-first (7 PRs, ~3.5–4.5 weeks total) + +### Repo placement (recommendation, adjusts the DECISION_LOG note) +Monorepo top-level **`vscode/`** directory in zero-operators, with a documented extraction path to a `zo-vscode` repo once `session.json` `schema_version: 1` freezes and the extension ships to the marketplace. Rationale: the runtime contract WILL churn during development — two repos means two-PR version-skew dances for a single developer; `vsce` publishes fine from a subdirectory; validate-docs/ruff/pytest scopes untouched; CI adds a path-filtered Node job. + +### Stage 1 — PR D1: HTML design mockups (FIRST deliverable; Sam's approval gates all Stage-2 work) (~2–3 days) +`design/vscode/` — 10 static browser-viewable files following the existing `design/*.html` convention, sharing `tokens.css` (ZO brand vars + `[data-theme="light"]` overrides + VS Code chrome-simulation vars). Each page has a dark/light toggle. Files: +- `tokens.css`, `00-overview.html` (index + v1-vs-deferred annotations) +- `01-workbench.html` — hero composite: full VS Code window (activity bar with the simplified-C mark, ZO sidebar, lead terminal as editor area, comms feed bottom panel, status bar) +- `02-sidebar.html` — tree in 4 states (no `.zo/` detected / idle / running with agent status badges + gates + training nodes / ended-reattach) +- `03-terminal-panel.html` — lead xterm.js frame, sub-agent tabs + 2×2 grid toggle, composer input, reconnect + pane-died states +- `04-comms-feed.html` — timeline with distinct treatments for the 5 event types, filters, auto-scroll pin +- `05-gate-approval.html` — inline gate card (metric vs threshold, tier, breakdown, Approve/Reject…/Iterate), reject-reason popover, gate-mode segmented control, attention toast +- `06-training-dashboard.html` — hand-rolled SVG loss curve (coral-soft area fill), stat tiles, epoch progress/ETA, checkpoint list, experiment picker +- `07-start-run.html` — plan picker, gate-mode, lead model, low-token, max-iterations, bypass-permissions (with warning copy), live `zo build … --headless-tmux` command preview, preflight panel +- `08-status-and-palette.html` — status bar items, command palette entries, notification toasts + +Webview constraints baked in so approval ≈ buildable: no runtime external fonts (bundle Geist/JetBrains Mono/Instrument Serif woff2 — all SIL OFL; fallback stacks); strict CSP (no CDN, nonce'd single script per page); ZO tokens with documented `--vscode-*` fallbacks ("brand" vs "inherit editor theme" setting); sidebar designed at 300px (min 170), panels fluid from 400px. Exit criterion: Sam reviews `00-overview.html`, approves/edits each screen, sign-off recorded in DECISION_LOG. + +### Stage 2 — implementation +- **PR D2 — Python engine** (~3–4 days): new `src/zo/runtime.py` (builds on WS3's `tmux_io.py`): `init_runtime` (creates `/.zo/runtime/` + `panes/`), `attach_pipe` (capture-pane backfill then `tmux pipe-pane -o`), `sync_panes` (poll `list-panes -s`, attach pipes to new panes — this is how sub-agent panes stream: Claude Code teammate-mode creates panes inside the detached session since TMUX is set there), atomic `write_manifest`, `resize`. **Runtime contract** (`schema_version: 1`, documented in new `docs/reference/runtime-contract.mdx`): `.zo/runtime/session.json` (project, team, tmux_session, size, heartbeat, wrapper_pid, status, absolute paths {comms_dir, memory_root, gate_mode_file, experiments_dir} — solves "comms lives in zo_root, not delivery repo", and `panes: [{pane_id, role, title, log, status}]`) + `panes/p.log` raw ANSI streams. Wrapper changes (additive): `launch_lead_session(headless_tmux=False)` new branch BEFORE the `_is_in_tmux` check; `_launch_tmux(detached=True)` swaps `new-window` for `tmux new-session -d -s zo-{team}-{ts} -x 220 -y 50`; `_wait_tmux` gains a guarded no-op `_maybe_sync_runtime` hook; `_maybe_open_training_pane` needs no change (its `_is_in_tmux` guard correctly skips). CLI: `--headless-tmux` on build/continue (mutually exclusive with `--no-tmux`); new `zo runtime` group (`send --pane … --text … --submit`, `list --json`, `kill`) — **all tmux logic stays in Python** where it's tested (PR-001/PR-022/PR-031 spirit); the extension never shells to tmux directly. Existing wrapper tests must pass unmodified — that's the regression gate. Early spike: verify ANSI/dimension coupling with a real Claude TUI before polishing. +- **PR D3 — extension scaffold** (~3 days): `vscode/` TypeScript project (esbuild; contributes viewsContainer + zoSessions TreeView + zoComms WebviewView; commands zo.startRun/attach/stop/approveGate/rejectGate/setGateMode/openTerminals/openTraining; activation `workspaceContains:.zo/**`); services: manifest reader + heartbeat staleness, per-file byte-offset logTailer, comms JSONL tailer with daily rollover, `zoCli` child_process wrapper; sessions tree, status bar; CI node job. +- **PR D4 — terminals** (~3–4 days): xterm.js webview per pane (created at manifest cols/rows — ANSI is dimension-relative), tabs/grid, FileSystemWatcher → offset-read → `postMessage` → `term.write()` pipeline, composer (send lines/slash commands via `zo runtime send`), debounced resize → `zo runtime resize`, reattach-on-reopen (tmux survives VS Code restarts; heartbeat-fresh → offer reattach). **Input model v1 is deliberate**: read-only streams + composer; full per-keystroke TTY passthrough deferred (reintroduces the TTY risk class the architecture avoids). +- **PR D5 — comms feed + gate UX** (~2–3 days): feed timeline, gate approval card (one click = `zo runtime send --pane --text "/gates:approve" --submit`; reject prompts for reason), gate-mode control (`zo gates set`), notifications. +- **PR D6 — training dashboard + start-run form** (~3 days): SVG charts hand-rolled from `.zo/experiments//metrics.jsonl` + `training_status.json` via `experiments.resolve_active_experiment_dir`; start-run form invoking `zo build --headless-tmux …`. +- **PR D7 — polish** (~2–3 days): theme mapping/light mode, bundled fonts, `vsce` packaging + marketplace CI on `vscode-v*` tags, manual e2e script (`zo build --headless-tmux` → session.json appears → logs grow → open VS Code → reattach checklist), docs (`docs/concepts/vscode-extension.mdx`, README). + +### Known risks +ANSI dimension coupling (mitigated: fixed creation size, size in manifest, resize routed through Python; spike early); sub-agent pane discovery latency (2s sub-poll; tmux hooks are a later optimization); pane.log growth from TUI redraws (truncate per session, rotate later if needed); comms midnight rollover (unit-tested). + +--- + +## Sequencing summary + +| # | PR | Workstream | Effort | +|---|----|-----------|--------| +| 1 | D1 mockups (`design/vscode/`) — Sam approval gate for Stage 2 | WS4 | 2–3 d | +| 2 | A1 Phase 0 strengthening (+ AGENT_PHASE_MAP fix) | WS1 | 2–3 d | +| 3 | B1 backedge core primitive | WS2 | 3–4 d | +| 4 | B2 backedge channel + surface | WS2 | 2–3 d | +| 5 | C1 tmux_io + lock enrichment (shared foundation) | WS3 | 0.5–1 d | +| 6 | C2 bridge core + console transport | WS3 | 2–3 d | +| 7 | C3 Slack transport + docs | WS3 | 1–2 d | +| 8 | D2 headless-tmux engine + runtime contract | WS4 | 3–4 d | +| 9 | D3–D7 extension (scaffold → terminals → gates → training → polish) | WS4 | ~3 wks | +| — | A2 `zo.scholar` grounding layer (optional follow-up) | WS1 | 4–5 d | +| — | C4 WhatsApp transport (later) | WS3 | unscoped | + +Every PR follows the repo's automatic protocols: STATE.md/DECISION_LOG/PRIORS updates before commit, doc cascade + `scripts/validate-docs.sh`, full CI mirror (ruff `src/`, pytest on 3.11 AND 3.12, validate-docs) per PRIORS PR-039, conventional commits, no AI attribution, no client identifiers. + +## Verification (per workstream) + +- **WS1**: unit + integration suites above; end-to-end sanity: a classical_ml fixture plan with `## Literature Review` decomposes to 7 phases and the phase_0 gate ITERATEs until the four artifacts exist (drive via the integration test, not a paid run). +- **WS2**: integration test runs the full backedge flow incl. a session-boundary resume and budget exhaustion; manually drive one real `zo build` on the MNIST demo plan with a hand-written `.zo/revisit_request.json` to watch the amber notice + STATE.md `## Revisits` appear. +- **WS3**: `zo bridge --transport console --dry-run` against a real project's comms logs renders templates; integration test proves approve→injection with mocked tmux; live smoke: run `zo build` (MNIST), have the bridge post gate events to a private Slack channel, reply `status` and `approve`, confirm the lead session receives `/gates:approve`. Suites green without slack-sdk installed. +- **WS4**: D1 = browser review of the 10 mockups (Sam sign-off). D2 = existing wrapper tests unmodified + new runtime tests + a real `zo build --headless-tmux` smoke asserting session.json + growing pane logs + `tmux has-session`. D3–D7 = mocha unit + `@vscode/test-electron` integration + the manual e2e checklist (kill VS Code mid-run → reopen → reattach). diff --git a/memory/zo-platform/sessions/session-040-2026-07-12.md b/memory/zo-platform/sessions/session-040-2026-07-12.md new file mode 100644 index 0000000..6344fc0 --- /dev/null +++ b/memory/zo-platform/sessions/session-040-2026-07-12.md @@ -0,0 +1,37 @@ +# Session 040 — 2026-07-12 + +## Type +Planning + PR D1 (VS Code UI mockups) shipped end-to-end; session ends paused, awaiting Sam's PR review. + +## What happened + +1. **Full context prime**: PRD, build plan, STATE.md, DECISION_LOG, PRIORS (complete), CLAUDE.md. +2. **Feature roadmap planned and approved.** Sam requested five features; after scoping questions the plan firmed to **four workstreams** (caveman explicitly dropped by Sam: "No need for caveman now"): + - **WS1** Lit review — strengthen in-project Phase 0, opt-in for all workflow modes (Sam chose this over a standalone command). + - **WS2** Cross-phase handoff — `RETURN_TO_PHASE` backedge primitive (F3 Phase A). + - **WS3** Slack bridge (WhatsApp later behind a Transport protocol) — bidirectional: comms-JSONL-tail notifications out, tmux pane injection in, remote gate approve/reject. + - **WS4** VS Code extension — design mockups FIRST (Sam approval gates Stage 2), then headless-tmux engine + xterm.js webview renderer. + - Sequencing: D1 mockups → A1 lit review → B1/B2 backedge → C1–C3 bridge → D2+ extension. Plan of record: `memory/zo-platform/roadmaps/2026-07-feature-roadmap.md` (persisted verbatim; the `~/.claude/plans` original is ephemeral — see PR-046). +3. **Three exploration agents** mapped the code; load-bearing findings recorded in the roadmap file, most notably: + - **Latent bug**: `AGENT_PHASE_MAP` omits `phase_0` for research-scout/code-reviewer but includes it for data-engineer → runtime phase_0 roster is `[data-engineer]`, the hard-coded agents at `_orchestrator_phases.py:264` are dead code; phase_0 has no `required_artifacts` so its gate verifies nothing. Fix ships in PR A1. + - The session-028 internal plan file (`~/.claude/plans/so-before-i-begin-peaceful-valley.md`) **no longer exists on disk**; only the DECISION_LOG summary survived. → PR-046 added. + - `advance_phase()` has no production caller; `_extract_extra_sections` in `_memory_formats.py` would duplicate any new STATE.md section not explicitly skipped; `_print_status` dedup keys on a nonexistent `event_id` (latent no-op). +4. **PR D1 built and shipped** (branch `claude/vscode-design-mockups`): + - Authored `design/vscode/tokens.css` (brand tokens + dark/light theme system + simulated VS Code chrome at true proportions + shared primitives). + - A 9-agent parallel workflow generated `00-overview` … `08-status-and-palette`, all depicting one canonical moment: public MNIST demo mid-phase_4, exp-003 epoch 6/8, gate test_accuracy 0.9912 → could_pass. + - Sam paused mid-session, then resumed ("finish the mockups then lets pause"). The stopped workflow was **resumed from its journal** (cached page results; 3 unjournaled pages re-ran) and the consistency reviewer completed: reconciled a two-clock timeline split onto one canonical clock (prior session 2026-07-11 completed phases 1–3 + exp-001/002; today 09:14:12 resume, phase_3→4 gate 09:15, exp-003 09:17→09:43), aligned metrics everywhere (exp-001 0.9770, exp-002 0.9841, per-class rows averaging exactly 0.9912), **browser-verified all 9 pages in both themes**. Token-purity / skeleton / no-emoji / no-external-deps / cross-link checks all clean. + - Sam viewed the screens live: **"the screens are awesome!"** — initial reaction; formal per-screen sign-off happens on the PR. + - **Session renumbering**: upstream PRs #101/#102 landed a session-039 (2026-06-11) mid-flight; this session renumbered 039 → 040 and the branch rebased onto updated main. + - Open style question deferred to Sam in the PR body: em-dashes retained as the design-file house glyph (mirrors `design/brand-system.html`) despite the prose no-em-dash convention. +5. Committed (memory + design in one conventional commit), rebased past #101/#102, pushed, **PR D1 opened (#103)**. Local `main` fast-forwarded to origin; stale merged local branches deleted; no linked worktrees existed. + +## Working-tree state at session end + +- Branch `claude/vscode-design-mockups` pushed with the PR D1 commit; local `main` up to date with origin. +- Pre-existing and NOT this session's (left untouched, still in the tree): modified `CLAUDE.md`, untracked `paper/`. + +## Next session — pick up here + +1. Check PR D1's review status (`gh pr view 103`). If Sam approved → his sign-off gates Stage-2 VS Code work (PR D2+ stays queued behind A1–C3 per the roadmap). If he requested changes → apply them on this branch first. +2. Start **PR A1**: WS1 Phase 0 lit-review strengthening + `AGENT_PHASE_MAP` phase_0 fix, per `memory/zo-platform/roadmaps/2026-07-feature-roadmap.md` (full design, file list, tests, doc cascade all specified there). +3. Remember the CI mirror before any push: `uv run ruff check src/`, `uv run --python 3.11 pytest -q`, `uv run --python 3.12 pytest -q`, `bash scripts/validate-docs.sh` (PR-039).