feat: evidence-driven review hub, agent review chains, and process layer v2#1022
Open
web3dev1337 wants to merge 23 commits into
Open
feat: evidence-driven review hub, agent review chains, and process layer v2#1022web3dev1337 wants to merge 23 commits into
web3dev1337 wants to merge 23 commits into
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…esis) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…arted
- prReviewAutomationService passed {provider, skipPermissions} but
startAgentWithConfig validates {agentId, mode, flags} — spawn always
failed validation, so PR review automation could never launch a reviewer
- session id now uses the workspace terminal's local repo name instead of
the GitHub slug (they can differ)
- prompt is submitted with a separate \r write (a trailing \n inside the
paste is not a submit)
- codex launches get the yolo flag in both reviewer + batch launch paths;
sandboxed codex stalls on approval prompts in unattended flows
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…/standards/handoff/diffStats) Normalized nested evidence object per the 2026-07-15 plan: what a human reviewer needs at a glance before approving/merging. Populated by evidenceService (next commit) from PR bodies/comments, worktree files, or direct API. All strings capped, arrays bounded, verdicts validated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Parses fenced ```agent-evidence JSON blocks from PR body, issue comments, and review bodies (travels with the PR, cross-machine; reviewer agents append their own blocks as comments) - Reads .agent-evidence.json from the task's worktree for local flows - Merge semantics: later sources win per section; reviews/media/data accumulate with de-dupe; standards union - Aggregates PR diff stats (files/additions/deletions) server-side — agent-supplied numbers never trusted for PRs - Media endpoint resolves only inside the server-recorded worktree root (agent blocks cannot set worktreePath), extension whitelist, traversal rejected - Routes: POST /api/process/evidence/:id/refresh, PUT /api/process/ evidence/:id, GET /api/process/evidence/:id/media/:idx Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e/merge Badge row (tests/app-ran/agent-reviews/media/data/diff-size) + expandable sections: per-role review verdicts with findings/fixed counts, screenshot thumbnails with a full-screen opaque viewer (no darkened-overlay modal), before/after data table, standards list, handoff notes, and a Refresh button that re-collects from PR comments + worktree. New focused files (client/queue-evidence.js + styles/queue-evidence.css); two-line wiring into showQueuePanel's renderDetail. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- config/review-workflows.json: named chains (standard/hardened/full-gate)
with per-stage role + agentId + model + effort; riskDefaults map risk →
chain length per the research (p_chain = Πp: 30% → 9% → 2.7%); user
override deep-merged from ~/.agent-workspace/review-workflows.json
- reviewWorkflowService: sequential stage runner — spawns each reviewer
into an idle worktree, detects its GitHub review verdict by polling,
records the outcome into evidence.reviews[], advances / blocks on
needs_fix / stalls on timeout; run state persists on the task record
(reviewWorkflow field) so restarts resume polling
- agentSpawnHelper: extracted the worktree-locate + agent-launch mechanics
shared with prReviewAutomationService (one spawn path, DRY)
- sessionManager.buildClaudeCommand supports --model for per-role Claude
routing; codex stages use existing model/reasoning support
- Queue detail: 'Review workflow' block — chain picker (default chosen by
task risk), run/skip-stage/cancel, live stage chips with verdicts
- Routes: GET /api/process/review-workflows, POST .../:id/{start,advance,
cancel}
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
docs/agents/EVIDENCE_PROTOCOL.md is the canonical reference (schema, three reporting channels, reviewer-stage obligations, self-orchestrated chains, handoff notes for fresh-window reprompts). A compact self-contained snippet is appended to every batch-launched task prompt (toggle: global.ui.tasks.evidencePromptEnabled) — the snippet's own example block round-trips through the evidence parser, verified by test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The open-source release hid the whole workflow layer behind ~40 individual
ui.visibility flags with no Settings UI to flip them. Settings → UI Mode
now switches presets in one click: 'simple' = shipped defaults, 'power' =
process banner + workflow modes + tier filters + PRs/Review Route/Activity/
Diff + dashboard process cards + commander controls (intent hints stay
opt-in since they can call a model API).
Also removes the hardcoded display:none that overrode header.queue=true —
the Review Hub ('📥 Review') is visible by default again as the single
review entry point.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Anthropic prompt caches expire after ~1h idle. Review feedback now routes by cache age: warm original session (<55m since last prompt) gets the feedback inline as before; cold/missing sessions get a FRESH fixer agent spawned in a free worktree, seeded with the review feedback + the evidence handoff notes (this also implements the previously-stubbed autoSpawnFixer path — it only logged 'would spawn fixer'). Queue detail header shows a 🧊 'cache cold — fresh window on reprompt' chip past the threshold. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Local-only JSONL log (~/.agent-workspace/telemetry/context-switches.jsonl, never leaves the machine) of worktree focus, workspace switches, workflow mode changes and review start/end. Summary endpoint estimates refocus cost (research default 10 min/switch) and surfaces top thrash pairs + review focus minutes in the dashboard Telemetry overlay. Client hooks are fire-and-forget and deduped. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Captured slash-commands were forwarded to the Commander PTY as a single '/clear\r' chunk, which agent CLIs receive as a bracketed paste — inserted as literal text, never executed. Split into two writes (text, 300ms, \r) per the established two-write submit pattern. Normal keystrokes were unaffected because they stream char-by-char, which is why only slash commands appeared broken. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- plugins/youtube-transcript: first working example plugin — paste a YouTube URL (Commander tools button or 'youtube-transcript-transcribe' command) → yt-dlp subtitles → clean plain-text transcript saved to ~/Downloads/transcripts/. Helpful error when yt-dlp is missing. - New 'post_route' slot action type (local routes only, optional single prompted input) — lets manifest-only plugins trigger their own server routes from UI buttons; validated in the loader, executed by plugin-host - New 'commander.tools' slot renderer: plugin buttons strip in the Commander panel (results echo into the Commander terminal) - Plugin routers get express.json() so plugin POST routes actually see req.body (previously undefined — app uses per-route parsers) - Settings → Plugins: loaded AND failed plugins visible (bad manifests no longer fail silently) + reload button - plugins/README.md: documents client.slots + action types + rendered slots (previously entirely undocumented) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…oded hytopia)
The server-control start path had 'hytopia start' hardcoded for every
project type. Launch commands now resolve from the cascaded config:
serverCommand template + {{gameMode}}/{{commonFlags}} substitution
(gameModes/commonFlags were already merged by the cascade but nothing
consumed them — the templating the docs promised now exists). Fallbacks:
hytopia-game → 'hytopia start', everything else → 'npm run dev'.
Client: un-commented the Start Server ▶ dropdown (game modes from
getDynamicLaunchOptions) + Launch Settings gear, still gated behind the
existing terminal.startServer/serverLaunchMenu visibility flags (hidden by
default; the Power preset enables them).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
package.json was pinned to 1.13.4 in the supply-chain fix but this lockfile entry kept the caret range. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…r post-mortem Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nt model/effort syntax
Any CLI agent (Gemini, OpenCode, Grok, aider, ...) can now be registered
in ~/.agent-workspace/custom-agents.json (skeletons + docs in
config/custom-agents.example.json) with zero code changes:
- agentManager merges custom agents into the registry at boot (validated;
built-ins protected unless override:true); they surface automatically in
the /api/agents picker, batch launches, and review-workflow stages
- Per-agent CLI syntax for model/effort: modelFlag/reasoningFlag templates
('--model {model}' etc.); codex keeps -m + model_reasoning_effort,
claude keeps --model aliases; reasoning is only appended for agents that
declare support
- agentSpawnHelper resolves launch flags (agent's defaultFlags) and init
delay from the registry instead of hardcoded claude/codex branches, so
reviewer/fixer/workflow-stage spawns work for any registered agent
- statusDetector already carries gemini/opencode busy-idle heuristics —
custom agents with those ids get proper status lights out of the box
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…chestrating AIs)
CommanderManager holds N commander instances keyed by id; the primary keeps
id 'commander' so every existing route (no commanderId → primary) and the
single-panel behavior are byte-for-byte unchanged. Additional commanders
each get their own PTY + Claude launch + data dir (own CLAUDE.md persona).
- Server: id-aware PTY-lifecycle routes (status/start/start-claude/input/
resize/stop/restart/output/clear default to primary), scoped socket
payloads ({...,commanderId}), new list/spawn/remove routes, limit of 6,
primary is un-removable, unknown ids never auto-create ghosts
- Client: tab strip in the commander titlebar rebinds the one xterm to a
different backend PTY (tab-style, lowest DOM risk); output/exit socket
events filtered by active id; hidden by default (commander.tabs), on in
the Power preset
- 10 manager/instance unit tests
Full N-panel side-by-side rendering remains the documented follow-up; this
delivers the capability (multiple independent commanders) via switching.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
An independent gpt-5.5 review of the full diff surfaced 8 issues; all fixed with tests (new server/utils/shellSafety.js + tests/unit/securityFixes.test.js): HIGH 1. Custom-agent command construction was shell-injectable — model/reasoning values + flag/template strings are now validated against a shell-safe allowlist; unsafe values are dropped and unsafe custom-agent configs are rejected at load. 2. serverLaunchCommandResolver interpolated repo-config flags/gameArgs into a shell command — same allowlist; a template carrying metacharacters falls back to the safe built-in default. 3. Evidence media endpoint was lexical-only — a symlink inside the worktree pointing out (…/leak.png -> ~/.ssh/id_rsa) could be served. Now realpath- confines target under root and rejects non-regular files. 4. refresh() trusted an arbitrary req.body.worktreePath as the media root — an explicit path is now honored only if it resolves to a known workspace worktree; the task-identity worktree:<path> stays trusted but is still realpath-confined at serve time. MEDIUM 5. Review-workflow poll cycles weren't serialized — added an in-flight guard + re-read/CAS on run state before patching (no double reviewer spawn). 6. Stage completion could be misattributed to a stray human/bot review in the window — now prefers a review whose body carries the stage's agent-evidence marker/role, falling back to latest. 7. Missing promptSentAt was treated as cold cache — now unknown+live-session delivers to the session; fresh fixer only on a known-stale timestamp. 8. post_route allowed '//host' and arbitrary same-origin paths — restricted to the plugin's own /api/plugins/<id>/ namespace (server + client). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the tier-workflow vision from the
optimal-agent-orcestration-systemresearch on top of the existing (mostly hidden) Jan–Feb process layer. Full design rationale:PLANS/2026-07-15/EVIDENCE_REVIEW_WORKFLOWS_PLAN.md.The evidence system (centerpiece)
Everything a human needs at a glance before approve/merge, per finished task:
evidencefield on task records: tests (ran/command/passed/failed), appRun proof (puppeteer/server-smoke/studio/manual), agent review chain verdicts with findings/fixed counts, screenshots/video, before/after data for balance changes, standards reviewed against, handoff notes, diff statsevidenceServicecollects it from fencedagent-evidenceblocks in PR bodies/comments (travels with the PR),.agent-evidence.jsonin worktrees, or direct API; PR diff stats are computed server-side, never agent-claimeddocs/agents/EVIDENCE_PROTOCOL.mdteaches agents to self-report; a compact snippet is auto-appended to batch launch prompts (media endpoint only serves from the server-recorded worktree root — traversal rejected, extension whitelist)Multi-agent review chains (data-driven)
config/review-workflows.json: standard (1 general) / hardened (security→general) / full-gate (security+perf+general) with per-stage agent, model, effort; risk level picks the default chain (research: p_chain = Πp — 30% → 9% → 2.7%)reviewWorkflowServicespawns each stage into an idle worktree, detects its GitHub verdict, records the outcome intoevidence.reviews[], advances/blocks/stalls; run state persists across restartsclaude --model <alias>support added; codex uses existing model/reasoning flagsBugs found & fixed (the "spammed out, untested" batch)
startAgentWithConfigwas called with{provider, skipPermissions}instead of{agentId, mode, flags}— failed validation every time; also wrong repo name in session ids, and prompt+\nin one write (bracketed paste, never submits)/clear(and all slash commands): forwarded as a single"/clear\r"paste chunk — now text + delayed\r--dangerously-bypass-approvals-and-sandbox→ stalled on approvalsreq.body(no JSON parser on plugin routers)hytopia startfor every project typeResurfacing the hidden process layer
ui.visibilityflags that had no UI at all; the Review Hub (📥 Review) header button is visible by default again (a hardcodeddisplay:nonewas overriding itstrueflag)Prompt-cache freshness
autoSpawnFixer); 🧊 cache-cold chip in Queue detailContext-switch telemetry (local-only)
Plugins made real
~/Downloads/transcripts/)post_routeslot action (local routes only, optional prompted input), newcommander.toolsslot renderer, Settings → Plugins admin (failed plugins finally visible) + reload,client.slotsfinally documented inplugins/README.mdPlay buttons revived
serverCommand+{{gameMode}}/{{commonFlags}}templating — the substitution the docs promised now exists); Start Server dropdown re-enabled behind existing visibility flags (Power preset turns them on)Follow-up
PLANS/2026-07-15/MULTI_COMMANDER_FEASIBILITY.md(PR-sized follow-up)Test plan
npm run test:unit: 652 tests / 111 suites green (39 new tests across 8 new/extended suites)node scripts/check-command-surface-drift.js: clean🤖 Generated with Claude Code
Agent-agnostic launches (added after review)
Any CLI agent — Gemini, OpenCode, Grok, aider, anything — registers via
~/.agent-workspace/custom-agents.json(documented skeletons inconfig/custom-agents.example.json) with zero code changes: it appears in the agent picker, batch launches, and review-workflow stages, with its own launch flags, init delay, and per-agent model/effort CLI syntax (modelFlag/reasoningFlagtemplates). Reviewer/fixer/stage spawns resolve flags from the registry instead of hardcoded claude/codex branches. Status-light heuristics for gemini/opencode already existed and apply automatically.Multiple Commanders (added after review)
CommanderManagerruns N independent commander instances keyed by id — the primary keeps idcommanderso every existing route and the single-panel behavior are byte-for-byte unchanged. Additional commanders each get their own PTY + Claude launch + data dir (own CLAUDE.md persona). Id-aware PTY-lifecycle routes (default to primary), scoped socket payloads,list/spawn/removeroutes (limit 6, primary un-removable), and a titlebar tab-switcher that rebinds the one xterm to another backend PTY. Hidden by default (commander.tabs), on in the Power preset.Independent security review (Codex/gpt-5.5) + 8 fixes
Ran an independent review of the full branch diff; all 8 findings fixed with tests (
server/utils/shellSafety.js,tests/unit/securityFixes.test.js):{{gameMode}}/{{commonFlags}}templating → shell-safe allowlist on all config-derived values; unsafe configs rejected at load / fall back to safe defaults.refresh()trusted an arbitrary request-bodyworktreePath→ an explicit path is honored only if it resolves to a known workspace worktree.post_routeis restricted to the plugin's own/api/plugins/<id>/namespace (rejects//host).All 679 unit tests pass (114 suites).