Skip to content

Feat/phase 2 agent focus - #107

Merged
nutt-adam merged 9 commits into
mainfrom
feat/phase-2-agent-focus
Mar 21, 2026
Merged

Feat/phase 2 agent focus#107
nutt-adam merged 9 commits into
mainfrom
feat/phase-2-agent-focus

Conversation

@nutt-adam

@nutt-adam nutt-adam commented Mar 21, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Issue:
  • What changed:

Versioning (required)

  • I updated Cargo.toml version
  • I added/updated CHANGELOG.md
  • I documented release impact in this PR
  • If no bump, I explicitly justify why this is docs/chore/no behavior change

SemVer choice

  • PATCH (bugfix/reliability/non-breaking internal change)
  • MINOR (new capability/new CLI/workflow contract change)
  • MAJOR (breaking contract)

Version selected: v__________

Validation

  • cargo test -q
  • CI green

Release

  • Tag planned/applied (vX.Y.Z)
  • Tag notes include issue IDs

Summary by CodeRabbit

  • New Features

    • Agent Focus Mode: full-screen agent drill-down with live terminal output, token usage stats, diffs, and context health percentage
    • Dispatch panel for triggering workflow runs from the dashboard
    • Animated run tracking with detailed step timeline showing status badges and durations
    • Real-time SSE workflow step events for progress tracking
    • Mobile-responsive dashboard with swipeable sidebar tabs
  • Bug Fixes

    • Fixed dispatch response validation check
    • Increased startup grace period to improve agent initialization stability
  • Documentation

    • Updated README with concrete dashboard features and completed roadmap items
    • Added comprehensive operator debugging guide
  • Chores

    • Version bump to 0.6.0

nutt-adam and others added 7 commits March 21, 2026 19:31
The Factorio zoom-in: click a stage card on the factory floor and the
dashboard transitions to a full-screen Agent Focus Mode showing:
- Live terminal output (polled every 2s via single /focus endpoint)
- Token usage stats (input, output, cache read/write)
- Context % with color-coded fill bar (green/amber/red)
- Git diff of agent's worktree changes (syntax highlighted)
- Workflow progress (step X/Y)
- Prompt input bar to send instructions to the agent
- "Agent not running — Start Agent" CTA when agent is stopped

Backend: single GET /v1/agents/{ws}/{agent}/focus endpoint combines
terminal capture, usage scanning, diff resolution, and context %
extraction in one response. Eliminates polling race conditions.

Design: follows DESIGN.md tokens throughout. Smart auto-scroll on
terminal (stays put if user scrolled up). Mobile layout with swipeable
tabs (<768px). Keyboard: Escape returns to factory floor.

Also fixes dispatch panel json.status bug (was checking json.status
instead of json.ok).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The default 30s grace period was too short — the implementer agent
was being marked idle before it had time to read the codebase and
start writing code, causing premature "no commit" failures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Make stage cards keyboard-activatable (Enter/Space keydown handler)
- Prevent overlapping focus polls from racing (focusPolling guard flag)
- Check /up response status before marking as successful
- Escape statRow values via escapeHtml to prevent innerHTML injection
- Replace deprecated word-break: break-word with overflow-wrap: anywhere
- Clamp lines query param to [1, 10000] before pane capture
- Validate agent exists in workspace config before building focus data

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pre-populate agent name, status, and session from appState.agents
on click instead of waiting for the first /focus poll. Reduces
perceived latency from ~2s to near-instant.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
scan_workspace_usage() does expensive filesystem I/O (~11s on large
projects). Move it to a separate slow poll (?usage=1, every 30s)
so the main focus endpoint (terminal + diff + context) responds in
~35ms for instant terminal updates.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- README: dashboard section updated from "Planned" to "Built" with
  Agent Focus Mode details, roadmap checkboxes updated
- CHANGELOG: added Unreleased section with Phase 2 features
- DESIGN.md: added Agent Focus Mode design specifications
- Cargo.toml: bumped version to 0.6.0

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Documents the repeatable workflow from failed run to root cause:
run inspection → step timeline → agent check → log analysis.
Covers provider, policy, and tool failure patterns with concrete
CLI examples. Links dashboard Focus Mode for visual debugging.

Closes #79

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Mar 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 855f57d0-075c-48ed-a49d-9aed2c67c3eb

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This pull request introduces Agent Focus Mode, a full-screen drill-down UI feature for the dashboard that displays live terminal output, token usage metrics, Git diffs, and context health percentages for individual agents. It includes a new consolidated API endpoint /v1/agents/{workspace}/{agent}/focus, updated documentation, configuration adjustments, and a version bump to 0.6.0.

Changes

Cohort / File(s) Summary
Documentation & Release Notes
CHANGELOG.md, DESIGN.md, README.md, docs/OPERATOR_DEBUGGING.md
Added comprehensive documentation for Agent Focus Mode UI behavior, mobile responsive design, context fill thresholds, and debugging workflows. Updated CHANGELOG with unreleased features (Agent Focus, new SSE events, event rotation, dispatch panel) and fixes. Marked dashboard as built in README with factory-floor visuals. Version bumped to 0.6.0 in Cargo.toml.
Dashboard HTML & CSS Structure
dashboard/index.html, dashboard/style.css
Added full-screen Agent Focus Mode container with header bar, terminal pane, multi-section sidebar (usage/changes/progress), and prompt input. Implemented responsive layout: 70% terminal / 30% sidebar on desktop, collapsed single-column on mobile (<768px) with swipeable tabs. Added animations, terminal styling with tool/prompt colors, context fill percentage bar, and empty-state UI.
Dashboard JavaScript Logic
dashboard/app.js
Implemented Agent Focus Mode lifecycle: click stage card or press Enter/Space to enter focus mode; polls /v1/agents/{ws}/{agent}/focus at 2s (terminal/diff) and 30s (usage); renders status, terminal content with auto-scroll, token counts, diffs with HTML escaping, and derived progress. Added exitFocusMode() with Escape key support, reconnection messaging, and stale-response guards. Fixed dispatch response check from json.status to json.ok.
Dashboard Tests
dashboard/test.html
Added unit tests for new helpers: formatTokens() (raw/K/M formatting), escapeHtml() (HTML entity escaping), and simulated focus-mode state transitions and stale-response guards.
Backend API Endpoint & Support
src/cli/serve.rs, src/cli/snapshot.rs
Added new GET /v1/agents/{workspace}/{agent}/focus endpoint that consolidates terminal capture (tmux pane), context percentage, usage stats (when ?usage=1), and Git diff. Implemented agent_focus_data() and parse_diff_stat() helpers. Made extract_context_pct_for_runtime crate-visible (pub(crate)) for use in focus endpoint.
Configuration
tutti.toml
Increased implement_code workflow step's startup_grace_secs from implicit default to explicit 120 to prevent premature idle detection during agent exploration phase.

Sequence Diagram

sequenceDiagram
    participant Browser as Browser Client
    participant Server as Dashboard Server
    participant Tmux as Tmux Session
    participant Git as Git Repository
    participant Usage as Usage Tracker

    Browser->>Browser: User clicks agent card
    Browser->>Browser: Enter focus mode (hide factory, show focus view)
    
    par Terminal & Diff Poll (2s interval)
        loop Poll terminal
            Browser->>Server: GET /v1/agents/{ws}/{agent}/focus?lines=100
            Server->>Tmux: Capture pane output
            Server->>Git: Read git diff HEAD
            Server->>Server: Extract context %
            Server-->>Browser: {terminal, diff, context}
            Browser->>Browser: Render terminal (auto-scroll), diff
        end
    and Usage Stats Poll (30s interval)
        loop Poll usage
            Browser->>Server: GET /v1/agents/{ws}/{agent}/focus?usage=1
            Server->>Usage: Query aggregated stats
            Server-->>Browser: {tokens, cache_io}
            Browser->>Browser: Update usage/stats display
        end
    end
    
    Browser->>Server: User presses Escape
    Browser->>Browser: Exit focus mode (stop polls, restore factory view)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 A rabbit hops into focus mode,
Terminal glowing, metrics on the road,
Git diffs unfold, tokens dance and twirl,
Full-screen drill-down makes workflows whirl!

🚥 Pre-merge checks | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description contains only the empty template checklist with all fields unchecked and no filled-in summary, SemVer choice, or explicit version selection despite significant changes and version bump to v0.6.0. Complete the template by filling in the summary of changes, selecting MINOR for SemVer (new capability), confirming version 0.6.0, and documenting validation status and release plan.
Docstring Coverage ⚠️ Warning Docstring coverage is 44.44% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title "Feat/phase 2 agent focus" is vague and does not clearly summarize the main change; it lacks specificity about what Agent Focus Mode does or its significance. Provide a more descriptive title that clearly communicates the primary feature (e.g., 'Add Agent Focus Mode with live terminal and stats') to help readers understand the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/phase-2-agent-focus

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
README.md (1)

502-512: ⚠️ Potential issue | 🟡 Minor

Duplicate roadmap entry for web dashboard.

Lines 502 and 512 both contain [x] Web dashboard (factory floor + Agent Focus Mode). One of these entries should be removed.

📝 Remove duplicate entry

Remove line 512:

 - [x] SDLC automation framework (issue → implement → test → PR → review → merge)
 - [x] Published on crates.io (`cargo install tutti`)
 - [ ] Agent-to-agent message bus
 - [ ] Phrase registry (community prompts/skills)
 - [ ] Arrangement sharing (community team configs)
-- [x] Web dashboard (factory floor + Agent Focus Mode)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 502 - 512, Remove the duplicate checklist entry "Web
dashboard (factory floor + Agent Focus Mode)" — keep a single instance and
delete the second occurrence so the README checklist contains only one "[x] Web
dashboard (factory floor + Agent Focus Mode)" entry.
🧹 Nitpick comments (2)
dashboard/index.html (1)

50-50: Consider role="region" instead of role="main" to avoid duplicate landmarks.

When focus-view becomes visible, both it (role="main") and <main id="factory"> would be present as main landmarks, which can confuse screen reader navigation. Since the factory main is hidden when focus-view is shown, this may be acceptable, but using role="region" with an aria-label would be semantically cleaner.

♿ Optional accessibility refinement
-  <div id="focus-view" role="main" style="display:none">
+  <div id="focus-view" role="region" aria-label="Agent focus view" style="display:none">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dashboard/index.html` at line 50, Change the landmark role on the focus view
to avoid duplicate main landmarks: update the element with id "focus-view" to
use role="region" (instead of role="main") and add an appropriate aria-label
(e.g., aria-label="Focus view" or context-specific label) so screen readers can
identify it; ensure the existing <main id="factory"> remains role="main" and
that visibility toggling still controls which landmark is exposed.
src/cli/serve.rs (1)

1115-1136: Add timeouts to git diff commands to prevent hanging requests.

The git diff HEAD and git diff HEAD --stat commands (lines 1115 and 1123) have no timeout. Since this endpoint is polled every 2 seconds by the dashboard, a hung git command would compound quickly. On large repositories or with network-attached storage, these operations can block indefinitely.

The wait-timeout crate (already in dependencies) can wrap the command execution. The pattern is established in src/automation/mod.rs at line 2474 using spawn() with wait_timeout() to handle timeouts gracefully.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cli/serve.rs` around lines 1115 - 1136, The git diff and git diff --stat
invocations must be converted to spawn + wait_timeout (like the pattern in
automation::mod.rs) to avoid hanging: replace the .output() calls for the two
std::process::Command::new("git").args([...]).current_dir(&worktree_path).output()
chains with spawn(), call wait_timeout(Duration::from_secs(5)) (or another short
timeout), capture stdout on success, and on timeout kill the process and treat
the result as empty string (and log/warn); keep the subsequent
parse_diff_stat(&stat) usage unchanged so (diff, fc, ins, del) semantics remain
the same and ensure errors map to String::new()/0s instead of blocking.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@dashboard/app.js`:
- Around line 637-640: The focus-mode entry code sets inline styles to hide
`#detail-drawer`, `#dispatch-panel`, and `#timeline` (e.g.,
document.getElementById("detail-drawer").style.display = "none") but never
clears them, so later toggles (selectAgent()/selectRun() using the .open class)
don't make the drawer visible; update the focus-mode exit/close path to restore
these elements by removing the inline display (set .style.display = "" or call
.removeProperty('display')) or explicitly set the correct display value so the
.open class can take effect; apply the same fix to the other occurrence that
mirrors lines 672-675.
- Around line 726-731: The header always shows "working" because renderFocusView
only checks data.running; change logic to prefer a specific runtime state field
(e.g., data.state or data.status) when present and fall back to data.running.
Update renderFocusView to read a canonical state (e.g., const state = data.state
|| data.status || (data.running ? "working" : "stopped")), map known values
("idle","blocked","auth-failed","running"/"working") to user-facing labels and
CSS classes, then set $focusStatus.textContent and $focusStatus.className from
that mapped state (leave the stopped fallback when neither state nor running
indicate active).
- Around line 626-629: The sendFocusPrompt function is vulnerable to re-entry
(Enter can trigger it while a request is in-flight); add a re-entry guard:
introduce or reuse a boolean flag (e.g., focusPolling or a new focusSending) and
at the start of sendFocusPrompt return immediately if the flag is true, set the
flag true before initiating the async POST to /v1/actions/send and clear it in a
finally block after the request completes or errors; apply the same pattern to
the analogous function referenced around lines 840-874 to prevent duplicate
non-idempotent submissions.
- Around line 699-723: The error branch and pollFocusUsage() only guard by agent
name, causing cross-workspace leaks; update both the fetch().catch handler (the
earlier reconnect catch that sets focusPolling = false and updates
$focusTerminal) and the early-return in pollFocusUsage() to verify both
workspace and agent match appState.focusAgent (compare fa.workspace and fa.agent
to appState.focusAgent.workspace and .agent) before updating UI so stale
responses for the same agent name from a different workspace are ignored.
- Around line 803-818: The progress pane is showing the first running run
globally; narrow it to the focused agent by only considering runs where
run.status === "running" AND run.steps[run.stepIndex] (or the active step) has
an agent that matches the current focus (e.g. appState.focusedAgent or
focusedAgent). Update the loop over appState.runs to skip runs whose active
step.agent !== appState.focusedAgent (and if workspace collisions are possible,
ensure the step stored at run.steps[idx] includes evt.workspace when created and
compare that too). Keep using statRow("workflow", run.workflowName),
statRow("step", ...), and statRow("started", ...) for the matched run and fall
back to the "No active run." message if none match.

---

Outside diff comments:
In `@README.md`:
- Around line 502-512: Remove the duplicate checklist entry "Web dashboard
(factory floor + Agent Focus Mode)" — keep a single instance and delete the
second occurrence so the README checklist contains only one "[x] Web dashboard
(factory floor + Agent Focus Mode)" entry.

---

Nitpick comments:
In `@dashboard/index.html`:
- Line 50: Change the landmark role on the focus view to avoid duplicate main
landmarks: update the element with id "focus-view" to use role="region" (instead
of role="main") and add an appropriate aria-label (e.g., aria-label="Focus view"
or context-specific label) so screen readers can identify it; ensure the
existing <main id="factory"> remains role="main" and that visibility toggling
still controls which landmark is exposed.

In `@src/cli/serve.rs`:
- Around line 1115-1136: The git diff and git diff --stat invocations must be
converted to spawn + wait_timeout (like the pattern in automation::mod.rs) to
avoid hanging: replace the .output() calls for the two
std::process::Command::new("git").args([...]).current_dir(&worktree_path).output()
chains with spawn(), call wait_timeout(Duration::from_secs(5)) (or another short
timeout), capture stdout on success, and on timeout kill the process and treat
the result as empty string (and log/warn); keep the subsequent
parse_diff_stat(&stat) usage unchanged so (diff, fc, ins, del) semantics remain
the same and ensure errors map to String::new()/0s instead of blocking.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 8c1a6747-b355-48cc-b759-d96911ddbbdb

📥 Commits

Reviewing files that changed from the base of the PR and between 9c6e1be and 25c4678.

📒 Files selected for processing (12)
  • CHANGELOG.md
  • Cargo.toml
  • DESIGN.md
  • README.md
  • dashboard/app.js
  • dashboard/index.html
  • dashboard/style.css
  • dashboard/test.html
  • docs/OPERATOR_DEBUGGING.md
  • src/cli/serve.rs
  • src/cli/snapshot.rs
  • tutti.toml

Comment thread dashboard/app.js
Comment thread dashboard/app.js
Comment thread dashboard/app.js
Comment thread dashboard/app.js
Comment thread dashboard/app.js
nutt-adam and others added 2 commits March 21, 2026 23:12
Keep Phase 2a agent focus features (query param, agent validation,
keyboard accessibility, focus polling guard, XSS escaping).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

1 participant