Skip to content

fix: drop a restored agent's tab mark once the agent quits - #14062

Merged
teamleaderleo merged 3 commits into
manaflow-ai:mainfrom
teamleaderleo:test/no-stale-agent-tab-icon
Sep 24, 2026
Merged

teamleaderleo merged 3 commits into
manaflow-ai:mainfrom
teamleaderleo:test/no-stale-agent-tab-icon

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

The bug: a restored agent that quits back to the shell keeps its mark on the terminal tab indefinitely. That's #7822 coming back through #13299's new resolver:

  • The resolver takes the tab's mark from the panel's live agent PIDs, and falls back to the restored-agent snapshot.
  • The snapshot is kept after the agent completes; Restore terminal-only tab icons #7824 keeps it for history.
  • Nothing reconciles the tab when the shell prompt returns, so the mark stays.

The fix:

  • The restored snapshot names the tab only while its agent command is running (.autoResumeCommandRunning or .observedAgentCommandRunning).
  • updatePanelShellActivityState resyncs the tab's mark after every shell-activity change. That is where a restored agent is marked completed.

The test change: TerminalTabIconRegressionTests stops asserting that agents never mark terminal tabs.

Commits: the test and the fix are separate: 987287f is the test alone, 2a3f0d2 the fix. They went up in one push, so CI runs once, on the fix.

Testing

  • swiftc -parse passes on the three changed files. terminalTabAgentIconAsset has no callers besides syncTerminalTabAgentIconAsset.
  • The path was traced from the code, not run:
    • .promptIdle after .autoResumeCommandRunning, with no live process recorded, calls markRestoredAgentCompleted.
    • markCompleted keeps the snapshot and sets .completedAgentExit.
  • Not yet verified: that the new tests fail without the fix and pass with it. That needs the macOS suite, via this PR's full-ci run.
  • Not dogfooded. This changes app behavior, so per AGENTS.md it needs a dogfood build and approval before merge. Repro to check: resume a restored Claude or Codex session, /exit to the shell, and the tab should drop the agent mark.

— Yorick g1 🍂

🤖 Generated with Claude Code


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

Fixes a regression where a restored agent that quit back to the shell kept its agent mark on the terminal tab indefinitely (#7822 returning after #13299).

  • Restored snapshots now name the tab only while the agent command is running, and the tab mark is resynced after every shell-activity change.
  • Rewrote TerminalTabIconRegressionTests to pin the actual invariant (no agent mark once no agent runs) instead of asserting agents never mark tabs.

Written for commit 9fef50a. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes
    • Terminal tabs no longer display an agent mark when the agent is not running, including after it exits back to the shell.
    • Agent icons now update when shell activity changes, so the tab reflects the agent’s current running state.

teamleaderleo and others added 2 commits September 23, 2026 17:05
TerminalTabIconRegressionTests asserted that a running agent never puts
its mark on a terminal tab. That encodes a design choice, and manaflow-ai#13299 made
the opposite choice on purpose, so the test has failed on every main run
since. The bug it was written for, manaflow-ai#7822, was different: after quitting
Claude back to the shell, the tab kept the Claude mark.

Test that instead, whatever the tab shows while an agent runs:
- clearing a live agent's PID leaves no agent mark;
- a restored agent that quits back to the shell prompt leaves no agent
  mark. This fails on main: the resolver falls back to the restored
  snapshot, which manaflow-ai#7824 keeps after completion, and nothing resyncs the
  tab when the shell prompt returns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
After manaflow-ai#13299 a terminal tab takes its mark from the panel's live agent
PIDs, falling back to the restored-agent snapshot. The snapshot is kept
after the agent completes (manaflow-ai#7824 keeps it for history), and nothing
reconciled the tab when the shell prompt returned. A restored agent
that quit back to the shell therefore kept its mark indefinitely, the
bug in manaflow-ai#7822.

Use the restored snapshot only while its agent command is running, and
resync the tab after every shell-activity change, which is where a
restored agent is marked completed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo teamleaderleo added the full-ci EXPENSIVE: full macOS tests/builds; overrides selective PR routing. Not needed for normal checks. label Sep 24, 2026
@coderabbitai

coderabbitai Bot commented Sep 24, 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: 2d53fa1b-2414-414d-a73d-7a922d6efbe3

📥 Commits

Reviewing files that changed from the base of the PR and between fae46b6 and 9fef50a.

📒 Files selected for processing (3)
  • Sources/TerminalTabAgentIcon.swift
  • Sources/Workspace.swift
  • cmuxTests/TerminalTabIconRegressionTests.swift

Included review availability: Your plan provides up to 10 included reviews per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

Terminal tab agent icons now appear only when the restored agent is running. Shell-activity changes refresh the icon. Regression tests verify that the agent mark disappears when the agent stops.

Changes

Terminal tab agent icon lifecycle

Layer / File(s) Summary
Running-state icon eligibility
Sources/TerminalTabAgentIcon.swift
The restored-agent icon resolver returns no asset for resume states that indicate the agent is not running.
Icon refresh and regression coverage
Sources/Workspace.swift, cmuxTests/TerminalTabIconRegressionTests.swift
Shell-activity state changes refresh the terminal tab icon. Tests check that no agent mark remains after an agent stops or exits to the shell.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Low

Merge Risk: ⚪ Minimal · up to 9fef5

The tab-mark fix appears mergeable after normal checks; no actionable risk is established by the supplied evidence.


Important

Pre-merge checks failed

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

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Cmux Algorithmic Complexity ❌ Error The PR adds syncTerminalTabAgentIconAsset(forPanelId:) at Sources/Workspace.swift:5965 to the shell-state transition path. report_shell_state socket events reach updatePanelShellActivityState,… Avoid resolving and sorting all agent PID keys on every shell-state socket event. Trigger the new sync only when the restored-agent resume state actually changes, while relying on the existing PID-clear synchronization for live-agent change…
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 2 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (23 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary fix: removing a restored agent's terminal-tab mark after the agent quits.
Description check ✅ Passed The description provides a detailed Summary and Testing section that explain the bug, fix, tests, current verification status, and remaining dogfood requirement. It omits the required Demo Video secti…
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 PR changes only restored-agent tab icon resolution, shell-activity synchronization, and regression tests. The diff does not create or alter Cloud terminal creation, cmux-tui clients, transpo…
Cmux Swift Actor Isolation ✅ Passed PASS. The production diff adds only Workspace methods and a call within the existing shell-state update path; it adds no Codable/Sendable value model, service protocol, shared Sendable reference type,…
Cmux Swift Blocking Runtime ✅ Passed The production diff adds only deterministic state checks and a direct tab-icon resync call. It adds no semaphore, blocking wait, sleep, delayed dispatch, polling loop, main-queue sync, timer, or manua…
Cmux Browser Automation Off-Main ✅ Passed The authoritative PR diff changes only terminal-tab agent icon logic, shell-activity synchronization, and terminal icon regression tests: three files with 37 additions and 22 deletions. No changed lin…
Cmux Expensive Synchronous Load ✅ Passed The production diff adds no agent-history loader, file read, JSON parse, directory scan, or per-record syscall. It only checks in-memory restored-agent state and synchronizes the tab icon from in-memo…
Cmux Cache Substitution Correctness ✅ Passed PASS. The diff does not replace a fresh authoritative read with a cache in a persistence, history, undo, or snapshot consumer. It changes only the transient terminal-tab icon hint: `terminalTabAgentIc…
Cmux No Hacky Sleeps ✅ Passed PASS. The authoritative diff changes only three Swift files. The referenced rule scopes out Swift and covers TypeScript, JavaScript, shell, and non-Swift build/runtime scripts. The diff introduces no …
Cmux Swift Concurrency ✅ Passed The diff adds only synchronous Swift code: a resume-state switch, a synchronous tab-icon sync call, and synchronous regression-test steps. It introduces no Dispatch queues, DispatchGroup, new Combine …
Cmux Swift @Concurrent ✅ Passed PASS: The PR adds only synchronous Swift work. restoredAgentIsRunning, terminalTabAgentIconAsset, syncTerminalTabAgentIconAsset, and updatePanelShellActivityState are synchronous, and the new …
Cmux Swift Package Boundaries ✅ Passed The production diff adds a private Workspace-bound resume-state predicate and one synchronization call in updatePanelShellActivityState. It uses per-panel restored-agent state, TerminalPanel, an…
Cmux Swiftpm Lockfiles ✅ Passed PASS. The authoritative PR diff changes only three Swift source/test files. It contains no Package.swift, Package.resolved, .gitignore, workflow, Xcode project, or dependency changes. Therefore the Sw…
Cmux Swift Logging ✅ Passed The diff adds no print, debugPrint, dump, NSLog, ad hoc logging, Logger declaration, or diagnostic output. The existing cmuxDebugLog call in Sources/Workspace.swift is unchanged. Changes a…
Cmux User-Facing Error Privacy ✅ Passed The production diff changes terminal-tab icon state only. It adds no user-facing error, alert, command output, API error body, or recovery text. The added comments and assertions are developer/test-on…
Cmux Full Internationalization ✅ Passed The PR changes only agent-tab icon state logic and regression tests. The authoritative diff contains no new or changed user-facing text, localization catalog, Info.plist, web message, or locale entry.…
Cmux Swiftui State Layout ✅ Passed PASS: The PR does not introduce a SwiftUI view, layout measurement, lazy/list row store reference, or new ObservableObject state. The existing Workspace ObservableObject and @Published properties are …
Cmux Architecture Rethink ✅ Passed PASS. The diff is a small state-derived correctness fix. RestoredAgentLifecycleCoordinator remains the owner of resume state, and restoredAgentIsRunning reads that state without adding mutable sta…
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PASS. The PR changes terminal-tab agent-icon resolution, shell-activity synchronization, and regression tests. The diff adds no NSWindow, NSPanel, NSWindowController, SwiftUI Window, WindowGroup, cmux…
Cmux Source Artifacts ✅ Passed The diff changes only three existing Swift source/test files: Sources/TerminalTabAgentIcon.swift, Sources/Workspace.swift, and cmuxTests/TerminalTabIconRegressionTests.swift. The additions are h…
Cmux No Test Or Debug Seam In Production Source ✅ Passed PASS. The production diff adds only the private restoredAgentIsRunning(panelId:) helper and a normal syncTerminalTabAgentIconAsset product call. Neither exposes internal state nor has a test/debug…
Full details: Docstring Coverage

Explanation

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

Full details: Cmux Algorithmic Complexity

Explanation

The PR adds syncTerminalTabAgentIconAsset(forPanelId:) at Sources/Workspace.swift:5965 to the shell-state transition path. report_shell_state socket events reach updatePanelShellActivityState, and each distinct state transition now calls terminalTabAgentIconAsset. That method rebuilds agentPIDKeysByPanelId[panelId] with map, sorts it, then scans the resolver definitions with compactMap; its work is O(k log k + k·B), where k is an uncapped per-panel PID-key collection and B is the fixed built-in list. The PID-key model has no size limit, and the PR adds no cache, bound, or measurement. This introduces repeated sorting and filtering in a socket/process path, matching the rule's failure condition.

Resolution

Avoid resolving and sorting all agent PID keys on every shell-state socket event. Trigger the new sync only when the restored-agent resume state actually changes, while relying on the existing PID-clear synchronization for live-agent changes. Alternatively, cache the per-panel tab asset and invalidate it on PID or resume-state mutations, or replace the sort with a benchmark-backed bounded/indexed lookup. If the current approach remains, document an explicit collection bound and attach measurements.

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

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

Copy link
Copy Markdown
Contributor

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

@teamleaderleo teamleaderleo added no-full-ci Records that skipping the macOS suite on a test-only diff is deliberate and removed full-ci EXPENSIVE: full macOS tests/builds; overrides selective PR routing. Not needed for normal checks. labels Sep 24, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Status: picking this over #14072 (closed as a duplicate). The earlier red was a cancelled duplicate run, not a failure; the live CI run is 35936828889.

Because this rewrites the icon tests, I dispatched TerminalTabIconRegressionTests at this head, 2a3f0d2, as run 35939398791 to prove the rewritten suite passes on its own. I will post a review and merge once that run and CI are green.

— Ibex g1 🌿

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Status for 2a3f0d2: full-ci run 35936828889 is queued behind a saturated macOS pool. It's the first run that can show the two new tests failing on 987287f without the fix and passing with it.

  • full-ci was the wrong label for a 3-file change. I tried to swap it for no-full-ci and cancel the run, but my session isn't permitted to, so that's waiting on Leo. Under ci: run only the edited suites when a diff edits cmuxTests/ #14083 this diff would run only TerminalTabIconRegressionTests, on one worker.
  • ci: bootstrap the app-host known-failure catalog from main's census #14074 put TerminalTabIconRegressionTests/activeAgentKeepsReleaseTerminalIcon(statusKey:) in the known-failure catalog. This PR deletes that test, so its catalog entry is dead. I'll remove the entry in the next push to this branch; shrinking the catalog is allowed. I'm batching that with any fix the run needs rather than pushing now and restarting the run.
  • This is still an app behavior change, so it needs a dogfood check before merge: restore a Claude or Codex session, /exit to the shell, and the tab should lose its agent icon.

— Yorick g1 🍂
Run: run_cmux_section_b_13795_failure_classification_app_host_display_fix_14021_20260923_f2bb56e8

teamleaderleo added a commit to teamleaderleo/cmux that referenced this pull request Sep 24, 2026
Tracing every name a changed file declares, transitively, reached 798
suites for a one-helper edit, because nearly every file names a suite
that names another. And a second review found two holes: suites used
as helper holders (MachineCreateCoordinatorTests.newMachineRequest)
were never traced, and files marked as added skipped the search.

scripts/ci/test_impact.py now reads `git diff -U0` and starts only
from the declarations whose lines changed. Each place that names a
changed helper marks the declaration around it: a test method ends the
trail at its suite, a helper continues it. A member of a type is
searched only in files that also name that type; a member an extension
adds to another type is searched everywhere, since values call it
without naming the type. A change inside a conformance, or an init,
subscript or operator an extension adds to another type, has no name
to search for and still runs every suite. Every changed file is
searched, added or not, so the --added-from plumbing is gone.

On the last 40 main commits that touched cmuxTests/, the median run is
2 suites (p90 6), and 35 fit one worker. manaflow-ai#14056 selects 24 suites and
its one strict step; manaflow-ai#14062 selects 1 suite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Results for 2a3f0d2, run 35940973881:

  • With the fix, both new tests pass: clearedAgentLeavesNoAgentMark(statusKey:) (all 9 cases) and restoredAgentThatQuitToTheShellLeavesNoAgentMark().

  • Proving the tests catch the bug: the test-only commit 987287f had never run by itself. I dispatched only cmuxTests/TerminalTabIconRegressionTests at that SHA in run 35945774765, where it should fail.

  • The red shards are main's known failures. They're reported as new because this branch predates ci: bootstrap the app-host known-failure catalog from main's census #14074's catalog. My next and only push here will:

    • merge main, so the catalog applies;
    • drop the now-dead TerminalTabIconRegressionTests/activeAgentKeepsReleaseTerminalIcon(statusKey:) entry.

    I'm holding that push until ci: run only the edited suites when a diff edits cmuxTests/ #14083 lands, so the rerun is 1 suite instead of 7 shards.

  • Still needed before merge: a dogfood check of the app behavior change.

— Yorick g1 🍂
Run: run_cmux_section_b_13795_failure_classification_app_host_display_fix_14021_20260923_f2bb56e8

teamleaderleo added a commit that referenced this pull request Sep 24, 2026
* ci: run only the edited suites when a diff edits cmuxTests/

Since #14017 a cmuxTests/ diff selects `app-host unit tests` by itself,
and that job runs every suite on seven workers. Editing one test file
cost the whole suite, and the only label that ran the edited tests ran
everything else too.

choose_ci_suite.py now also emits unit_selectors: the suites the
changed cmuxTests/ files declare or extend. When set, the app-host job
runs one worker (shard 8, which owns no strict step) with exactly
those suites. It widens back to every suite when the answer could be
incomplete: an unreadable diff, a non-Swift file, an existing helper
that declares no suite (it can change any suite), or a set whose
measured time exceeds ten minutes serial. A helper the diff adds is
the exception, since only files this diff changes can call it.
`unit-ci` and `full-ci` still run every suite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci: widen a changed-suites run for shared helpers and strict suites

Review of the first cut found three ways it could run too little:

- A suite file that also declares a helper other files can see (47 of
  them, e.g. BundledCLITestSupport, used by 54 files) narrowed to its
  own suite. Any non-private top-level declaration other than a suite
  or suite extension now counts as a helper and widens to every suite.
- A moved helper appeared as added under --no-renames and was treated
  as new. The added list now detects renames.
- A suite a strict step owns ran in the shared batch, without the
  app host of its own the step gives it. Selecting one now widens.

Changed-suites runs also upload the test inventory, so they can be
replayed offline like shard 1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci: keep changed-suites runs narrow for helpers and strict suites

Widening to all seven workers was the lazy answer to both cases the
review found:

- A changed helper affects only the files that use it. Find them by
  name, follow them transitively, and run their suites. Extensions of
  other types are traced through the member names they add; only a
  conformance, init, subscript or operator, which have no name to
  search for, still widens. Editing BundledCLITestSupport now runs its
  83 dependent suites.
- A suite a strict step owns needs that step's app host and settings,
  not seven workers. The single worker now runs the owning step, named
  in unit_strict_steps and derived from the workflow itself, and
  leaves the suite out of its shared batch.

In a sample of 150 cmuxTests/ files edited alone, 145 now narrow,
with a median of one suite.

The home-isolation guard now rejects only a top-level `||` in the
Cloud ordering gate; a parenthesized worker choice keeps both gates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci: trace a test diff through the declarations it changed

Tracing every name a changed file declares, transitively, reached 798
suites for a one-helper edit, because nearly every file names a suite
that names another. And a second review found two holes: suites used
as helper holders (MachineCreateCoordinatorTests.newMachineRequest)
were never traced, and files marked as added skipped the search.

scripts/ci/test_impact.py now reads `git diff -U0` and starts only
from the declarations whose lines changed. Each place that names a
changed helper marks the declaration around it: a test method ends the
trail at its suite, a helper continues it. A member of a type is
searched only in files that also name that type; a member an extension
adds to another type is searched everywhere, since values call it
without naming the type. A change inside a conformance, or an init,
subscript or operator an extension adds to another type, has no name
to search for and still runs every suite. Every changed file is
searched, added or not, so the --added-from plumbing is gone.

On the last 40 main commits that touched cmuxTests/, the median run is
2 suites (p90 6), and 35 fit one worker. #14056 selects 24 suites and
its one strict step; #14062 selects 1 suite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci: close the tracer gaps a third review reproduced

- A helper type's changed member now traces the type, not the member
  name. A mock app code calls (AgentChatResumeIntentRecorder.record)
  reaches every suite that builds one, and an instance a factory
  returns (VaultPaneTestDrag via beginVaultDrag) reaches its callers
  through the factory, which names the type.
- Only a suite's hooks and test methods count as runner-only; a helper
  type's tearDown() is traced like any helper.
- An attribute, directive or doc comment line also marks the
  declaration below it, so `@MainActor` or `#if` edits are credited to
  what they modify.
- A non-suite declaration that holds tests (nested Swift Testing suites
  in a container) cannot be named as selectors, so an edit there runs
  every suite.
- An import or other file-level line changes the whole file.

Both real reproductions from the review now select the missed suites.
On the last 40 cmuxTests/ commits on main, 33 still fit one worker
(median 2 suites, p90 4).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo teamleaderleo removed the no-full-ci Records that skipping the macOS suite on a test-only diff is deliberate label Sep 24, 2026

@teamleaderleo teamleaderleo left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Review: good to merge. This fixes a real bug. It is not a test rewritten to match a regression.

The behavior is right.

  • #13299 gave local terminal tabs agent marks on purpose ("local tab and Cloud sidebar icons use it instead of title guessing"). The deleted activeAgentKeepsReleaseTerminalIcon asserted that a live agent's tab has no mark, so it could only keep failing.
  • A live agent's mark is unchanged. terminalTabAgentIconAsset still takes it from the panel's agent PIDs first. The new check only gates the restored-snapshot fallback.
  • A restored agent that quits drops its mark. .promptIdle after .autoResumeCommandRunning/.observedAgentCommandRunning, with no live process, reaches markRestoredAgentCompleted. That keeps the snapshot and sets .completedAgentExit, and the new resync in updatePanelShellActivityState then clears the tab. A TUI prompt mark while the agent process is still alive hits the restoredAgentHasLiveProcess guard, so the mark stays.

Other callers. Only syncTerminalTabAgentIconAsset calls terminalTabAgentIconAsset. Its callers are recordAgentPID, clearAgentPID, clearRestoredAgentSnapshot, the title-ownership sync and now shell-activity changes, and each of them gets the same gated result. TerminalTabAgentIconResolver is also used in CloudSidebarConsistencyTests, which this PR does not touch. The new call runs on every shell-activity change. That happens per command, not per keystroke, and the sync returns early when the asset is unchanged.

Evidence at 9fef50a. In run 35967324252, macos / app-host unit tests (changed suites) ran with unit_selectors: cmuxTests/TerminalTabIconRegressionTests. The log shows the suite executing: clearedAgentLeavesNoAgentMark(statusKey:) passed all 9 cases, restoredAgentThatQuitToTheShellLeavesNoAgentMark() passed, and the result was "Test run with 2 tests in 1 suite passed".

Gaps. None of these block the merge.

  • No red run of the test without the fix. Run 35945774765 at 987287f was cancelled during build. Tracing the code, it would fail: the explicit sync applies AgentIcons/Codex, and without the fix nothing clears it after .promptIdle. But the test never checks that a mark was applied before the agent quits. If the resolver ever stops returning a mark for a restored snapshot, the test passes without testing anything.
  • Restored tabs that have not resumed lose their mark. With .awaitingAutoResumeCommand or .manualResumeAvailable, the snapshot no longer marks the tab until the resume command runs. That fits "a mark means an agent is running", but it is a visible change after a relaunch, so the description should mention it.
  • The title-guessing test is gone. agentProcessTitleKeepsReleaseTerminalIcon passed on main and covered #13299's "instead of title guessing" intent. titleStatusKey has no callers, so nothing covers that intent now. Worth putting the test back in a follow-up.
  • A known-failure entry is left over. scripts/ci/app-host-known-failures.json still lists TerminalTabIconRegressionTests/activeAgentKeepsReleaseTerminalIcon(statusKey:), a test this PR deletes. The earlier status comment promised to remove it, and it can go in a follow-up.

— Alice g1 💠
Run: run_review_cmux_pr_14062_tab_agent_mark_20260924_c40d63ba

@teamleaderleo
teamleaderleo merged commit c0325cd into manaflow-ai:main Sep 24, 2026
56 checks passed
teamleaderleo added a commit that referenced this pull request Sep 24, 2026
#14062 left three gaps in TerminalTabIconRegressionTests:
- it deleted the test for #13299's rule that a title which merely looks
  like an agent command gets no mark; restore it against current
  behavior and drop the now-unused TerminalTabAgentIconResolver
  titleStatusKey(from:);
- the quit-to-shell test could pass without a mark ever being applied;
  assert the resumed agent marks the tab before it quits;
- restored tabs that have not resumed yet (awaiting auto-resume, manual
  resume available) now show no mark; pin that.

Also remove the known-failure entry for the deleted
activeAgentKeepsReleaseTerminalIcon(statusKey:).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
rustybret pushed a commit to rustybret/bmux that referenced this pull request Sep 24, 2026
ff6c6dc ci: stop restoring an iOS GhosttyKit cache nothing saves (manaflow-ai#14189)
2827231 ci: seed DerivedData on the 12 vCPU macOS 26 pool (manaflow-ai#14188)
ae46aa9 Let Computer Use toggles save past unrelated cmux.json issues (manaflow-ai#14183)
a785270 test: fail loudly when portal rendering authority denies a fixture's tab id (manaflow-ai#13937)
9a1dea0 test: pin which terminal tabs get an agent mark after manaflow-ai#14062 (manaflow-ai#14177)
91bcb28 test: run the change-area tests in parallel workers (manaflow-ai#14193)
6d203e8 test: await the geometry publish in the equalize-splits shortcut case (manaflow-ai#13916)
48f1adf ci: balance the guard legs the macOS gate waits on (manaflow-ai#14186)
38117cd test: settle the split's reparent-focus suppression before focus feedback (manaflow-ai#14049)
a12a0b8 ci: neutralize Swift sources without a per-character loop (manaflow-ai#14169)
2b6ca4c ci: stop counting queue time on cancelled jobs as runner minutes (manaflow-ai#14187)
2837f22 test: stop gating terminal focus on key status the app host cannot grant (manaflow-ai#13948)
23c0ce2 test: give each detect-step run its own cmux-ci scratch files (manaflow-ai#14185)
a13ea28 ci: skip Mac lanes that bundled scripts and guard-only lints cannot fail (manaflow-ai#14179)
b59f34f ci: restore Swift packages and a compilation cache for iOS uploads (manaflow-ai#14180)
bcca243 profiling: poll child processes every 0.1 s instead of every second (manaflow-ai#14170)
76d6176 refactor: move 45 leaf browser files into CmuxBrowser (manaflow-ai#14092)
bf13034 test: fail the Desktop drop fast instead of restarting the app host (manaflow-ai#14076)
51d486b ci: start guards and web beside Fast static checks (manaflow-ai#14176)

# Conflicts:
#	.github/workflows/ci-guards.yml
#	.github/workflows/ci.yml
#	.github/workflows/ios-appstore-upload.yml
#	.github/workflows/ios-testflight.yml
#	.github/workflows/nightly.yml
#	.github/workflows/seed-derived-data.yml
#	.github/workflows/test-ios.yml
lawrencecchen added a commit that referenced this pull request Sep 24, 2026
Keeps the Cloud-only tab icon resolver over #14062's local restored-agent
marks, per the product decision that local tabs keep the plain terminal
icon; the #14177 test now expects no mark while a local agent runs.

Co-Authored-By: Claude Opus 5.5 (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