Skip to content

feat: distinguish agents waiting on background work - #15666

Merged
teamleaderleo merged 7 commits into
manaflow-ai:mainfrom
teamleaderleo:fix/background-lifecycle
Sep 29, 2026
Merged

teamleaderleo merged 7 commits into
manaflow-ai:mainfrom
teamleaderleo:fix/background-lifecycle

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Sep 29, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

When an agent finishes a turn with an artifact watch, background shell, or session cron still active, cmux now reports a distinct backgroundWorkPending lifecycle phase. The phase remains hibernation-protected while the sidebar and projections can describe the agent as Waiting instead of implying an active turn.

This is the implementation for #14918. It builds on the existing journal pendingWork signal and does not duplicate the hibernation process/transcript guards in #15278 or the activity classifier in #15276.

Validation

  • python3 scripts/verify-local.py (syntax, source wiring, package groups, feature flags; native compilation intentionally omitted)
  • git diff --check

Changelog

Changed

  • Show agents waiting on live background work as Waiting while retaining hibernation protection.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

When an agent finishes a turn while an artifact watch, background shell, or session cron is still active, cmux now reports a distinct backgroundWorkPending phase instead of running. The sidebar shows these agents as Waiting rather than implying an active turn, while hibernation protection is preserved. Implements #14918.

  • Adds backgroundWorkPending to the reducer, replay policy, and hibernation lifecycle; it is not hibernatable and outranks needsInput and error in combined-phase precedence.
  • A new turnStarted keeps the phase running even while pending background work exists.
  • Sidebar glyphs and activity summaries treat backgroundWorkPending like running; Waiting sorts above Needs input and below Running, and active turns now sort ahead of newer Needs-input reports.
  • The CLI stop path emits backgroundWorkPending when unsettled work remains, session restore preserves it, and transitions from it to running count as promptSubmitted.

Written for commit 95158e0. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Agent status now distinguishes completed turns that still have background work from agents actively running or waiting for input.
    • Sidebar indicators and summaries reflect background work, and active work is prioritized over input-needed status when displaying agent activity.
  • Bug Fixes
    • Agents starting a new turn are shown as running even when background work remains pending.
    • Startup replay no longer treats agents with pending background work as active turns.

@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@teamleaderleo
teamleaderleo force-pushed the fix/background-lifecycle branch from 30e6c3b to d573d56 Compare September 29, 2026 17:40
@coderabbitai

coderabbitai Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 86b6baba-c271-46b8-8d13-f28c7948711b

📥 Commits

Reviewing files that changed from the base of the PR and between 9b0d37a and 95158e0.

📒 Files selected for processing (14)
  • CLI/cmux.swift
  • Packages/macOS/CmuxAgentJournal/Sources/CmuxAgentJournal/AgentJournalReplayPolicy.swift
  • Packages/macOS/CmuxAgentJournal/Sources/CmuxAgentJournal/AgentLifecycleActivity.swift
  • Packages/macOS/CmuxAgentJournal/Sources/CmuxAgentJournal/AgentLifecyclePhase.swift
  • Packages/macOS/CmuxAgentJournal/Sources/CmuxAgentJournal/AgentLifecycleReducer.swift
  • Packages/macOS/CmuxAgentJournal/Tests/CmuxAgentJournalTests/AgentLifecycleReducerTests.swift
  • Sources/AgentHibernation/AgentHibernationLifecycleState.swift
  • Sources/AgentJournalLifecycleCenter+Projection.swift
  • Sources/Sidebar/SidebarCompactStatusGlyph+Resolve.swift
  • Sources/SidebarAgentActivitySummary.swift
  • Sources/Workspace+SidebarStatusVisibility.swift
  • Sources/Workspace.swift
  • cmuxTests/SidebarCompactAgentStatusTests.swift
  • cmuxTests/WorkspaceSidebarObservationTests.swift

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 3 remain after this review.


📝 Walkthrough

Walkthrough

The lifecycle model adds a background-work-pending phase for completed turns with work still active. Lifecycle aggregation, journal handling, and sidebar status now recognize the phase. Sidebar status ordering also uses lifecycle urgency.

Changes

Background Work Lifecycle

Layer / File(s) Summary
Define and produce the background-work phase
Packages/macOS/CmuxAgentJournal/Sources/CmuxAgentJournal/AgentLifecyclePhase.swift, Packages/macOS/CmuxAgentJournal/Sources/CmuxAgentJournal/AgentLifecycleReducer.swift, CLI/cmux.swift, Packages/macOS/CmuxAgentJournal/Tests/CmuxAgentJournalTests/AgentLifecycleReducerTests.swift
The lifecycle phase and precedence include background work pending. Completed turns with pending work use the new phase, while a new turn remains running. CLI stop handling and lifecycle correction also recognize the phase.
Interpret and project the lifecycle phase
Packages/macOS/CmuxAgentJournal/Sources/CmuxAgentJournal/AgentLifecycleActivity.swift, Packages/macOS/CmuxAgentJournal/Sources/CmuxAgentJournal/AgentJournalReplayPolicy.swift, Sources/AgentHibernation/AgentHibernationLifecycleState.swift, Sources/AgentJournalLifecycleCenter+Projection.swift
Activity classification, startup replay, hibernation aggregation and parsing, and journal projection handle background work pending.
Display and rank sidebar status
Sources/Sidebar/SidebarCompactStatusGlyph+Resolve.swift, Sources/SidebarAgentActivitySummary.swift, Sources/Workspace+SidebarStatusVisibility.swift, Sources/Workspace.swift, cmuxTests/SidebarCompactAgentStatusTests.swift, cmuxTests/WorkspaceSidebarObservationTests.swift
The sidebar displays the phase as “Waiting” and counts it as active. Status entries use lifecycle urgency for ordering, with running ahead of needs input. Tests cover glyph and status ordering behavior.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Feature

Suggested reviewers: austinywang, lawrencecchen

Merge Risk: ⚪ Minimal · up to 95158

No actionable merge-blocking issue remains; the lifecycle change is ready for normal merge checks.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 95158

The reviewed paths keep agents with pending background work protected from hibernation while distinguishing them from agents in an active turn. No introduced security weakness was established. Compatibility across older versions and restoration after restart remain unverified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The security-relevant effect is the classification used by agent hibernation for affected panels. The reviewed path does not establish a new external entrypoint or privilege grant.

Trust Boundaries and Controls

  • observed — For the reviewed current-version path, a pending completed turn remains non-hibernatable, a new turn takes running precedence, and lifecycle eligibility is checked again before teardown.

Hardening Proposals

  • proposed — Verify restart and mixed-version behavior against persisted pending-work records, including whether every session-index producer preserves the phase as non-idle.

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Cmux Algorithmic Complexity ❌ Error The PR adds a repeated full scan on a sidebar UI path. Sources/Workspace.swift:6736-6737 calls sidebarStatusUrgencyRank(forKey:) inside the sorted comparator. `Sources/Workspace+SidebarStatusVis… Precompute a [String: Int] urgency dictionary before sorting. Scan agentLifecycleStatesByPanelId once, update only keys present in the visible status entries, and have the sort comparator perform dictionary lookups. This keeps the path …
Description check ⚠️ Warning The description includes a useful Summary, validation commands, and changelog information. It does not use the required Testing heading, and it omits the required Demo Video and Checklist sections. Th… Add the required Testing section with tests added, tests executed, and remaining verification limits. Add a Demo Video or screenshots for this UI behavior change. Include the required Checklist and mark each item or explain why it does not …
Docstring Coverage ❓ Inconclusive Docstring coverage is 30.43% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 23 functions across 12 files. (2 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (22 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: distinguishing agents that are waiting on background work.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Cloud Persistent Session And Early Input ✅ Passed PASS: The pull request does not change Cloud terminal creation, persistent cmux-tui transport, manual renderer admission, attachment input routing, or auth/idempotency/revision/lease handling. The aut…
Cmux Swift Actor Isolation ✅ Passed The production diff adds lifecycle enum cases and updates pure reducers, projections, and sidebar logic. It does not add or change a Swift actor, service protocol, Sendable reference type, logger, or …
Cmux Swift Blocking Runtime ✅ Passed The PR adds lifecycle-state handling and sidebar ordering only. The authoritative diff adds no semaphores, blocking waits, sleeps, delayed dispatch, polling loops, main-queue sync, timers, or manual l…
Cmux Browser Automation Off-Main ✅ Passed PASS. The PR changes agent lifecycle, hibernation, sidebar status, and related tests. It does not change Sources/TerminalController.swift, ControlCommandExecutionPolicy.swift, socket-worker routin…
Cmux Expensive Synchronous Load ✅ Passed The PR adds lifecycle enum handling and in-memory sidebar urgency sorting only. The diff adds no RestorableAgentSessionIndex.load(), agent-history file read, JSON/JSONL parsing, directory scan, sysc…
Cmux Cache Substitution Correctness ✅ Passed The diff does not replace any fresh authoritative read with a cached value. The CLI persists backgroundWorkPending from the current hook payload via hasActiveClaudeBackgroundWork(parsedInput), and…
Cmux No Hacky Sleeps ✅ Passed PASS: The pull request changes only Swift files. The rule applies to TypeScript, JavaScript, shell, and non-Swift build/runtime scripts. The diff adds lifecycle-state handling and does not add or modi…
Cmux Swift Concurrency ✅ Passed The PR adds lifecycle-state handling only. The authoritative Swift diff contains no new DispatchQueue, DispatchGroup, Task, Combine, completion-handler, async/await, actor, or synchronization construc…
Cmux Swift @Concurrent ✅ Passed The Swift diff adds only synchronous lifecycle, projection, sidebar, and test logic. The changed lines add no async, await, nonisolated, @concurrent, @MainActor, Task, or dispatch usage. E…
Cmux Swift Package Boundaries ✅ Passed PASS: The diff keeps the core lifecycle domain logic in the existing Packages/macOS/CmuxAgentJournal SwiftPM target, including AgentLifecyclePhase, reducer transitions, replay policy, and activity…
Cmux Swiftpm Lockfiles ✅ Passed PASS: The PR changes only lifecycle and sidebar source/tests. It does not modify any Package.swift, package-local Package.resolved, .gitignore, workflow, cmux.xcodeproj, or Xcode package-refer…
Cmux Swift Logging ✅ Passed The pull request adds no production logging. The added Swift lines contain no print, debugPrint, dump, NSLog, ad hoc file/stdout logging, or Logger declarations. Existing CLI print calls a…
Cmux User-Facing Error Privacy ✅ Passed The diff adds lifecycle state handling and the generic user-facing label “Waiting” in the sidebar tooltip/VoiceOver path. It adds no user-facing error, alert, command error, API error body, or recover…
Cmux Full Internationalization ✅ Passed The production UI text added by the PR is Waiting in Sources/Sidebar/SidebarCompactStatusGlyph+Resolve.swift. It uses `String(localized: "agent.generic.notification.subtitle.waiting", defaultValue…
Cmux Swiftui State Layout ✅ Passed PASS: The PR changes lifecycle and sidebar status logic, not SwiftUI state or layout structure. The authoritative diff adds no ObservableObject/@published state, @State wrappers, GeometryReader, lazy/…
Cmux Architecture Rethink ✅ Passed PASS: The diff adds a lifecycle enum case and carries it through the existing reducer, journal projection, hibernation state, and sidebar consumers. The reducer remains the lifecycle source of truth, …
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The PR changes agent lifecycle, sidebar status, and tests only. The authoritative diff adds no standalone NSWindow, NSPanel, NSWindowController, SwiftUI Window, or WindowGroup code, and adds no close-…
Cmux Source Artifacts ✅ Passed All 14 changed paths are tracked Swift source or test files. The diff adds lifecycle behavior, projections, sidebar logic, and related tests. No local output, generated logs, screenshots, recordings, …
Cmux No Test Or Debug Seam In Production Source ✅ Passed PASS. The PR adds no #if DEBUG or test-build seam in production Sources files, and no member named like debug…, …ForTesting, TestHook, or TestSeam. The only visibility change is `sidebarSt…
Full details: Description check

Explanation

The description includes a useful Summary, validation commands, and changelog information. It does not use the required Testing heading, and it omits the required Demo Video and Checklist sections. The validation also states that native compilation was not run.

Resolution

Add the required Testing section with tests added, tests executed, and remaining verification limits. Add a Demo Video or screenshots for this UI behavior change. Include the required Checklist and mark each item or explain why it does not apply. Keep the changelog in the required present-tense format.

Full details: Docstring Coverage

Explanation

Docstring coverage is 30.43% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 23 functions across 12 files. (2 skipped: 2 too large.)

Full details: Cmux Algorithmic Complexity

Explanation

The PR adds a repeated full scan on a sidebar UI path. Sources/Workspace.swift:6736-6737 calls sidebarStatusUrgencyRank(forKey:) inside the sorted comparator. Sources/Workspace+SidebarStatusVisibility.swift:102-105 scans every agentLifecycleStatesByPanelId value for each call. With P panel lifecycle records and S status entries, this makes sorting O(P·S·log S), instead of a single pre-sort scan plus O(S·log S). Both collections can grow with user-owned panes and status entries. No bound, cache, or benchmark documents this shape.

Resolution

Precompute a [String: Int] urgency dictionary before sorting. Scan agentLifecycleStatesByPanelId once, update only keys present in the visible status entries, and have the sort comparator perform dictionary lookups. This keeps the path linear in the lifecycle/status data plus O(S·log S) for sorting. Alternatively, maintain an invalidated urgency cache keyed by the workspace lifecycle change generation.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Warning

Some tools did not complete. Review the errors below.

🔧 OpenGrep (1.30.0)
CLI/cmux.swift

OpenGrep scan timed out


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.

@github-actions

github-actions Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

CI failure attribution

CI passes on 95158e045f (run 36611135701 attempt 1).

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's.

@teamleaderleo
teamleaderleo merged commit ea13489 into manaflow-ai:main Sep 29, 2026
74 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

Merge receipt for 95158e045f: every check was green at merge (23 verified; 21 skipped by policy). Full suite runs on main after merge.

rustybret pushed a commit to rustybret/bmux that referenced this pull request Sep 29, 2026
ea13489 Merge pull request manaflow-ai#15666 from teamleaderleo/fix/background-lifecycle
95158e0 test: keep needs input glyph case focused
a7fa170 test: align sidebar urgency expectations
ed676a6 fix: preserve background phase in stale turn correction
c12b6f9 fix: prioritize active background glyph state
2a1a337 fix: order background lifecycle statuses consistently
39e203b fix: keep new turns in running phase
d573d56 feat: distinguish agents waiting on background work
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