Skip to content

fix(webui): make the keyless file-backed monitor report live progress#31

Merged
ignorejjj merged 4 commits into
RUC-NLPIR:mainfrom
AlcAI-Haven:worktree-webui-keyless-fixes
Jun 25, 2026
Merged

fix(webui): make the keyless file-backed monitor report live progress#31
ignorejjj merged 4 commits into
RUC-NLPIR:mainfrom
AlcAI-Haven:worktree-webui-keyless-fixes

Conversation

@AlcAI-Haven

Copy link
Copy Markdown

Summary

Fixes the keyless, file-backed WebUI monitor (open_dashboard MCP tool / arbor web) that a host coding agent drives via the arbor mcp tools. That monitor renders a session from disk with no live RunState or EventBus, but build_session_snapshot only populated the tree, counters and scores — so the page presented a frozen run.

Symptoms addressed:

  • Runtime stuck at 0s and a blank improvement chart — no clock or score history was ever derived.
  • Token / cache counters pinned at zero — those are owned by the host LLM harness, not Arbor, and can't be observed keylessly.
  • Dead pipeline and empty Recent Activity — phase was hardcoded and there were no activity events.
  • Black (invisible) node-modal title, and the title showed the entire multi-line hypothesis instead of a headline.
  • Nodes "disappeared" when the dashboard was opened from the main checkout while the agent ran inside a linked git worktree (each worktree has its own .arbor/).

Changes

  • Timing sidecar — the Node model intentionally stores no timestamps (and must stay byte-compatible), so a new mcp/session_timing.py maintains .coordinator/activity.json: a run clock, per-node started/finished, and a capped event log. session_ops records an event on add / update / prune / worktree_create / merge.
  • session_source now derives elapsed_seconds, per-node runtime_seconds / finished_elapsed, the pipeline phase, running-node "agents", and best_score_history (which fixes the empty/flat improvement chart) from the sidecar.
  • Tokens & Cache cards are hidden in keyless mode (snapshot flagged keyless) instead of showing misleading zeros, and the stat grid reflows.
  • Worktree-stable sessions.arbor/sessions is anchored at the main working tree when driven from a linked worktree (session_ops._stable_arbor_base, mirrored in export.resolve_session_dir); normal checkouts and non-git directories are unchanged.
  • Modal fixes — the black title was caused by #overlay living outside the themed shell wrapper, so the bare <h2> inherited the browser-default color; color is now set on the overlay. Node titles render a one-line headline (oneLine), with the full hypothesis preserved in the modal's Details.

Testing

  • Added tests for the sidecar-backed snapshot, activity recording, and the stable-base behaviour.
  • Full suite: 345 passed, 2 skipped. The remaining failures (test_export path separators, test_worktree / test_zoo git-worktree & subprocess) reproduce on an untouched checkout and are pre-existing Windows-environment issues, not regressions.
  • Verified end-to-end with Playwright against a generated keyless session: runtime ticks, Tokens/Cache cards absent, modal title legible and one-lined, pipeline shows a running step, Recent Activity populated, and the improvement chart draws a real curve.

🤖 Generated with Claude Code

AlcAI-AnimeHaven and others added 4 commits June 23, 2026 19:04
The keyless WebUI (open_dashboard / `arbor web`) renders a session from disk
with no live RunState or EventBus. build_session_snapshot only filled the tree,
counters and scores, so the page showed a frozen run: runtime stuck at 0s,
token/cache counters at zero, a dead pipeline, an empty activity feed, and a
blank improvement chart. Node modals also rendered a black (invisible) title and
showed the full multi-line hypothesis instead of a headline, and sessions
created from a linked git worktree disappeared when the dashboard was opened
from the main checkout.

- Add a timing sidecar (mcp/session_timing.py -> .coordinator/activity.json):
  the Node model intentionally stores no timestamps, so session_ops now records
  a run clock, per-node started/finished, and a capped event log on add/update/
  prune/worktree_create/merge. The tree JSON stays byte-compatible.
- session_source: derive elapsed_seconds, per-node runtime_seconds/
  finished_elapsed, the pipeline phase, running-node "agents", and
  best_score_history (fixes the empty/flat improvement chart) from the sidecar.
- Hide the Tokens and Cache cards in keyless mode (flagged via snapshot.keyless)
  rather than show misleading zeros - those counters belong to the host harness,
  not Arbor - and reflow the stat grid.
- Anchor .arbor/sessions at the main working tree when driven from a linked git
  worktree (session_ops._stable_arbor_base, mirrored in export.resolve_session_dir)
  so session state survives branch/worktree switches.
- Fix the black modal title (set color on the #overlay host, which sits outside
  the themed shell wrapper) and show a one-line headline (oneLine) for node
  titles, keeping the full hypothesis in the modal Details.

Add tests for the sidecar-backed snapshot, the activity recording, and the
stable-base behaviour.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Inside a git submodule, `git rev-parse --git-common-dir` points at the parent
repo's `.git/modules/<name>`, so anchoring `.arbor` at its parent would land in
`.git/modules` rather than a working tree. Require the resolved main root to
actually hold a `.git` entry before redirecting there — normal linked worktrees
still redirect (their root has a `.git` dir), submodules no longer misfire.

Adds a linked-worktree redirect test (env-guarded like the other worktree tests).
Use a per-writer temp filename (pid + thread id) so two concurrent `_save`
calls can't clobber a shared `.tmp` mid-write — the rename onto the final path
stays atomic. Clean up the temp file on failure, and document that the
read-modify-write in record_event still assumes a single writer per session.
- flag the live snapshot `keyless: False` explicitly, so its shape matches
  empty_state_dict() and the keyless path (the browser hides token/cache cards
  only when keyless is true)
- debug-log the stable-base session-lookup fallback in export instead of
  swallowing the exception silently
- tiebreak the improvement-chart ordering on score, so legacy sessions with no
  sidecar timing (all keyed at +inf) still draw in a deterministic order
@ignorejjj ignorejjj merged commit 20adbbc into RUC-NLPIR:main Jun 25, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants