Skip to content

[CMUX Next] Chief pet: agent notices as a glass deck - #21732

Closed
teamleaderleo wants to merge 1 commit into
feat/chief-pet-panelfrom
feat/chief-pet-notices
Closed

teamleaderleo wants to merge 1 commit into
feat/chief-pet-panelfrom
feat/chief-pet-notices

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Second of four Chief pet PRs, stacked on #21728. The pet now pops up agent events as they arrive. They show as notice capsules above the pet, as Leo's pill-stack references draw them.

What shows

  • Anything that would alert on this Mac also appears over the pet. "Would alert" is the same NotificationPolicy decision a banner uses, so muted workspaces, quiet hours and notifications.desktop apply. It shows even when the poster asked for no banner.
  • The hook in NotificationCenterService is two lines: notifyChiefPet in deliver, and chiefPet?.read in acknowledge.

How it looks

  • Glass capsules, about 330 × 56 pt, with a bold title and one muted line of the banner's text. There's no status glyph, matching the references and Codex's "quiet" dock style from its unpushed follow-up.
  • The older notices peek out 8 pt below the front one, each 16 pt narrower per side, like a deck. They float 48 pt above the pet.
  • Under Reduce Transparency the capsules use the solid overlay surface.
  • A gold badge on the character counts notices that wait for you (questions, failures), as in reference fd383405.

Interaction

  • The rail's chevron unfolds the deck into a column of up to three capsules and flips to point down. With no notices, the chevron opens the Chief.
  • Clicking a capsule opens its tab, the same way a banner click does.

Motion and lifetime

  • One notice per tab. When the front notice gets identical content again, nothing redraws or animates.
  • The only motion is a single fade-in when the capsules first appear, and it follows Reduce Motion. Nothing loops or blinks.
  • A finished turn leaves after 8 s. A question or failure stays until its tab is read.

Reference

Matched: cmux-design-references/research/chief-chat-source-captures/d154d558-….png, at the same 1034 × 670 pixel size.

Folded:
folded

Unfolded with the chevron:
unfolded

The right side is a composite: the bundled mascot, the rail and the capsules drawn at this PR's point sizes at @2x. It is not a screen capture. The live look needs a dogfood build, since no Mac capture host is reachable from the Linux build host.

Testing

ChiefPetFeedTests (CmuxNextFloatingTests) covers:

  • the feed: ordering, one notice per tab, no re-animation, the deck limit keeping waiting notices, read, expiry and the badge count;
  • building a notice from a daemon notification;
  • the capsules redrawing only on change;
  • folded vs. unfolded click targets;
  • the reference deck heights;
  • the chevron unfolding the deck, and opening the Chief when there are no notices;
  • placement above or below the pet.

ChiefPetNoticeTests (CmuxNextAppTests) drives the real NotificationCenterService.deliver and acknowledge with a DaemonStore:

  • alerts reach the capsules and the badge counts them;
  • a capsule click opens its tab;
  • a read tab's notice leaves;
  • a non-alerting arrival stays off the pet;
  • the 8 s expiry, on a ManualClock.

These run in this PR's cmux-next CI lane. They were not run locally (Linux host). The App's source shrinks by 2 lines; the floating chat's tunable moved into CmuxNextFloating to pay for the hook.

Changelog

none (off by default behind a Debug Settings toggle)

🤖 Generated with Claude Code


Summary by cubic

The Chief pet now pops up agent events as glass notice capsules above it. Anything that would alert on this Mac appears over the pet, using the same NotificationPolicy decision a banner does—muted workspaces, quiet hours, and notifications.desktop apply—even when the poster asked for no banner.

  • Notices are ~330×56pt glass capsules with a bold title and one muted line (per the reference captures); older ones peek out behind as a deck, and the rail's chevron unfolds up to three into a column.
  • A gold badge on the character counts notices that wait for you (questions, failures); clicking a capsule opens its tab, and with no notices the chevron opens the Chief.
  • One notice per tab, identical content never redraws or animates, and the only motion is a fade-in on first appearance that follows Reduce Motion; finished turns leave after 8s, while questions and failures stay until read.
  • Wired via notifyChiefPet in NotificationCenterService.deliver and chiefPet?.read in acknowledge; off by default behind a Debug Settings toggle.

Written for commit f741982. Summary will update on new commits.

View guided diff Turn on auto-fix

What alerts on this Mac (a banner's rules) also shows over the pet, matching
chief-chat-source-captures d154d558: glass capsules of the references' size
(330 x 56 pt) with a bold title and one muted line and no status glyph, the
older ones peeking out below as a deck; the rail's chevron unfolds them into
a column and each capsule opens its tab. One notice per tab; identical
content never re-animates; a finished turn leaves after 8 s while a question
or failure stays, counted on the character's badge, until its tab is read.

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

coderabbitai Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 146eb886-1005-4b22-b638-bbe5eb3a5321

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
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@blacksmith-sh

blacksmith-sh Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Found 55 test failures on Blacksmith runners:

Failures

Test View Logs
main.SideLanes.test_a_completed_failed_blacksmith_retry_is_not_watched_again/
test_a_completed_failed_blacksmith_retry_is_not_watched_again
View Logs
main.SideLanes.test_a_real_failure_on_cmux_next_attempt_two_is_not_rescued/
test_a_real_failure_on_cmux_next_attempt_two_is_not_rescued
View Logs
cmux-next.yml fast-tier: a job holding the R2 write credentials must declare environmen
t: ${{ github.ref == 'refs/heads/main' && 'ci-cache-writer'
debug info {'CMUX_SWIFT_SANITIZE': 'address', 'CMUX_SWIFT_TEST_DEBUG_INFO': 'none'}: 's
wift --version' lacks '-debug-info-format none'/
debug info {'CMUX_SWIFT_SANITIZE': 'address', 'CMUX_SWIFT_TEST_DEBUG_INFO': 'none'}: 's
wift --version' lacks '-debug-info-format none'
View Logs
debug info {'CMUX_SWIFT_SANITIZE': 'address', 'CMUX_SWIFT_TEST_DEBUG_INFO': 'none'}: 's
wift package resolve --package-path Packages/macOS/Pkg --scratch-path Packages/macOS/
Pkg/.build-sanitize-address' lacks '-debug-info-format none'
View Logs
debug info {'CMUX_SWIFT_SANITIZE': 'address', 'CMUX_SWIFT_TEST_DEBUG_INFO': 'none'}: wa
nt one build and two suites: ['swift package resolve --package-path Packages/macOS/
Pkg --scratch-path Packages/macOS/Pkg/
.build-sanitize-address', 'swift --version', 'swift build --build-tests -c debug -debug
-info-format none --sanitize=address --scratch-path Packages/macOS/Pkg/
.build-sanitize-address -Xlinker -no_compact_unwind --package-path Packages/macOS/
Pkg', 'swift test -c debug -debug-info-format none --sanitize=address --scratch-path Pa
ckages/macOS/Pkg/
.build-sanitize-address -Xlinker -no_compact_unwind --package-path Packages/macOS/
Pkg --skip-build --filter ATests', 'swift test -c debug -debug-info-format none --sanit
ize=address --scratch-path Packages/macOS/Pkg/
.build-sanitize-address -Xlinker -no_compact_unwind --package-path Packages/macOS/
Pkg --skip-build --filter BTests']
View Logs
debug info {'CMUX_SWIFT_SANITIZE': 'address'}: want one build and two suites: ['swift p
ackage resolve --package-path Packages/macOS/Pkg --scratch-path Packages/macOS/Pkg/
.build-sanitize-address', 'swift --version', 'swift build --build-tests -c debug --sani
tize=address --scratch-path Packages/macOS/Pkg/
.build-sanitize-address -Xlinker -no_compact_unwind --package-path Packages/macOS/
Pkg', 'swift test -c debug --sanitize=address --scratch-path Packages/macOS/Pkg/
.build-sanitize-address -Xlinker -no_compact_unwind --package-path Packages/macOS/
Pkg --skip-build --filter ATests', 'swift test -c debug --sanitize=address --scratch-pa
th Packages/macOS/Pkg/
.build-sanitize-address -Xlinker -no_compact_unwind --package-path Packages/macOS/
Pkg --skip-build --filter BTests']
View Logs
debug info {'CMUX_SWIFT_TEST_DEBUG_INFO': 'dwarf'}: want one build and two suites: ['sw
ift package resolve --package-path Packages/macOS/
Pkg', 'swift --version', 'swift build --build-tests -c debug --package-path Packages/
macOS/Pkg', 'swift test -c debug --package-path Packages/macOS/
Pkg --skip-build --filter ATests', 'swift test -c debug --package-path Packages/macOS/
Pkg --skip-build --filter BTests']
View Logs
debug info {'CMUX_SWIFT_TEST_DEBUG_INFO': 'none'}: 'swift --version' lacks '-debug-info
-format none'/
debug info {'CMUX_SWIFT_TEST_DEBUG_INFO': 'none'}: 'swift --version' lacks '-debug-info
-format none'
View Logs
debug info {'CMUX_SWIFT_TEST_DEBUG_INFO': 'none'}: 'swift package resolve --package-pat
h Packages/macOS/Pkg' lacks '-debug-info-format none'
View Logs

...and 45 more test failures. View all on Blacksmith

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

@github-actions

Copy link
Copy Markdown
Contributor

Probably yours: Fast static checks failed: a static check failed, FAILED localization (0.82s).

CI failed on f741982561 (run 39139907576 attempt 1): 4 code, 4 unknown.
macOS jobs did not run: compile and app tests were skipped: Fast static checks failure.

Job Verdict Why
Fast static checks code a static check failed
CI fast guards code a guard step failed
guards / workflow-guard-tests / release-tooling unknown no known signature; failed step: Validate retried Ghostty Zig package fetches
guards / workflow-guard-tests / release-ios unknown no known signature; failed step: Validate iOS simulator build-once contract
guards / workflow-guard-tests / app-host-execution code a Python test failed
guards / workflow-guard-tests / app-host-cache unknown no known signature; failed step: Validate iOS video recording failures
guards / workflow-guard-tests / preflight unknown no known signature; failed step: Validate macOS runner guards
guards / workflow-guard-tests / quality-determinism code a Python test failed
Matched log lines
Fast static checks: FAILED localization (0.82s)
CI fast guards: FAIL    1.3s  workflow-guard-tests / ci: Check that push and pull_request path filters agree
guards / workflow-guard-tests / app-host-execution: ERROR: test_failures_and_crashes_keep_swift_test_exit_status (__main__.DirectBundleSuiteTests.test_failures_and_crashes_keep_swift_test_exit_status)
guards / workflow-guard-tests / quality-determinism: FAIL: test_scans_only_test_sources (__main__.CommandLine.test_scans_only_test_sources)

Not re-run automatically: Fast static checks, CI fast guards, guards / workflow-guard-tests / release-tooling, guards / workflow-guard-tests / release-ios, guards / workflow-guard-tests / app-host-execution are not machine failures.

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; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

@github-actions

Copy link
Copy Markdown
Contributor

CI fast guards failed on f741982561 (https://github.com/manaflow-ai/cmux/actions/runs/39139907576). It does not block the merge; a red guard merged into main breaks it for every open PR.

Check that push and pull_request path filters agree

Test: python3 tests/test_ci_workflow_path_filter_parity.py

Traceback (most recent call last):
  File "/home/runner/_work/cmux/cmux/tests/test_ci_workflow_path_filter_parity.py", line 245, in <module>
    test_push_and_pull_request_filter_the_same_files()
  File "/home/runner/_work/cmux/cmux/tests/test_ci_workflow_path_filter_parity.py", line 156, in test_push_and_pull_request_filter_the_same_files
    assert not drifted, (
           ^^^^^^^^^^^
AssertionError: Every workflow that filters both events must filter them identically, or declare the difference in EXEMPTIONS or PUSH_ONLY_PATTERNS with a reason.
backend.yml: push and pull_request filter different files
  paths: guarded on push, not on pull requests: scripts/cmux-next/release/prod-promote.ts, scripts/cmux-next/release/production-approvals.json
cmux-next.yml: push and pull_request filter different files
  paths: guarded on pull requests, not on push: .github/actions/**, .github/workflows/**, Assets.xcassets/**, Native/**, Resources/**, TunnelExtension/**, cmuxTests/**, cmuxUITests/**, daemon/**, docs/configuration.md, scripts/cmux-next/**, scripts/cmux-next/state-roots-baseline.tsv, scripts/whats-new/**, tests/**
  paths: guarded on push, not on pull requests: .github/workflows/nightly.yml, scripts/apple-developer-id-certs/**, scripts/ci/*nightly*, scripts/ci/download-run-artifact.py, scripts/ci/finalize-release.py, scripts/ci/publish-release-assets.py, scripts/ci/signing-keychain.sh, scripts/ci/update-release-tag.py, scripts/ci/upload-r2-object.py, scripts/import-apple-devel ...

Fix: the assertion above names what the guard expects; change the tree to match it.
Reproduce in seconds, no build: scripts/ci/guards-local.sh --step 'Check that push and pull_request path filters agree'

Validate local hook trust boundary

Test: python3 tests/test_preflight_trust.py

  • PreflightTrustTests.test_annotated_tag_push_does_not_execute_candidate_code
subprocess.CalledProcessError: Command '['bash', 'scripts/install-git-hooks.sh']' returned non-zero exit status 1.
  • PreflightTrustTests.test_hook_installation_has_no_candidate_code_runner
subprocess.CalledProcessError: Command '['bash', 'scripts/install-git-hooks.sh']' returned non-zero exit status 1.
  • PreflightTrustTests.test_push_does_not_execute_candidate_check_through_unchanged_wrapper
subprocess.CalledProcessError: Command '['bash', 'scripts/install-git-hooks.sh']' returned non-zero exit status 1.
  • PreflightTrustTests.test_push_does_not_execute_candidate_runner
subprocess.CalledProcessError: Command '['bash', 'scripts/install-git-hooks.sh']' returned non-zero exit status 1.

... and 1 more failing tests in the run log.
Fix: the assertion above names what the guard expects; change the tree to match it.
Reproduce in seconds, no build: scripts/ci/guards-local.sh --step 'Validate local hook trust boundary'

Run canonical CMUX CI guard profile

GitHub-hosted runner label: .github/workflows/gallery-link.yml:23:    runs-on: ubuntu-24.04
GitHub-hosted runner label: .github/workflows/intent-familiar-review.yml:21:    runs-on: ubuntu-24.04
GitHub-hosted runner label: .github/workflows/cmux-next-split-guard.yml:13:    runs-on: ubuntu-24.04
GitHub-hosted runner label: .github/workflows/nightly.yml:1461:    runs-on: ${{ inputs.nightly_next_unsigned_run != '' && 'ubuntu-24.04' || github.repository_owner != 'manaflow-ai' && 'macos-15' || (needs.decide.outputs.fast_build == 'true' && 'blacksmit

... and 1 more failing tests in the run log.
Fix: the assertion above names what the guard expects; change the tree to match it.
Reproduce in seconds, no build: scripts/ci/guards-local.sh --step 'Run canonical CMUX CI guard profile'

Validate package test selection

Test: python3 tests/test_ci_select_package_tests.py

Traceback (most recent call last):
  File "/home/runner/_work/cmux/cmux/tests/test_ci_select_package_tests.py", line 229, in <module>
    sys.exit(main())
             ^^^^^^
  File "/home/runner/_work/cmux/cmux/tests/test_ci_select_package_tests.py", line 131, in main
    check_package_output_behavior()
  File "/home/runner/_work/cmux/cmux/tests/test_ci_select_package_tests.py", line 112, in check_package_output_behavior
    assert result.returncode == 1 and count == 1, f"{package}: real error incorrectly tolerated: {result.returncode}"
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: GhosttyFixture: real error incorrectly tolerated: 1

Fix: the assertion above names what the guard expects; change the tree to match it.
Reproduce in seconds, no build: scripts/ci/guards-local.sh --step 'Validate package test selection'

Lint every workflow

.github/workflows/cmux-next-defaults-guard.yml:94:28: expected scalar node for string value but found alias node with "" tag [syntax-check]
   |
94 |           sparse-checkout: *defaults-paths
   |                            ^~~~~~~~~~~~~~~
.github/workflows/cmux-next-frame-pacing.yml:198:33: property "resolve-ref" is not defined in object type {build: {outputs: {}; result: string}; gate: {outputs: {run: string; tag: string}; result: string}} [expression]
    |
198 |       CMUX_PERF_SOURCE_SHA: ${{ needs.resolve-ref.outputs.sha }}
    |                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.github/workflows/nightly.yml:34:3: maximum number of inputs for "workflow_dispatch" event is 10 but 17 inputs are provided. see https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#providing-inputs [events]
   |
34 |   workflow_dispatch:
   |   ^~~~~~~~~~~~~~~~~~

Fix: the assertion above names what the guard expects; change the tree to match it.
Reproduce in seconds, no build: scripts/ci/guards-local.sh --step 'Lint every workflow'

Validate the package test lane's single-suite phase

debug info {'CMUX_SWIFT_TEST_DEBUG_INFO': 'none'}: want one build and two suites: ['swift package resolve --package-path Packages/macOS/Pkg', 'swift --version', 'swift build --build-tests -c debug -debug-info-format none --package-path Packages/macOS/Pkg', 'swift test -c debug -debug-info-format none --package-path Packages/macOS/Pkg --skip-build --filter ATests', 'swift test -c debug -debug-info-format none --package-path Packages/macOS/Pkg --skip-build --filter BTests']
debug info {'CMUX_SWIFT_TEST_DEBUG_INFO': 'none'}: 'swift package resolve --package-path Packages/macOS/Pkg' lacks '-debug-info-format none'
debug info {'CMUX_SWIFT_TEST_DEBUG_INFO': 'none'}: 'swift --version' lacks '-debug-info-format none'
debug info {}: want one build and two suites: ['swift package resolve --package-path Packages/macOS/Pkg', 'swift --version', 'swift build --build-tests -c debug -debug-info-format none --package-path Packages/macOS/Pkg', 'swift test -c debug -debug-info-format none --package-path Packages/macOS/Pkg --skip-build --filter ATests', 'swift test -c debug -debug-info-format none --package-path Packages/macOS/Pkg --skip-build --filter BTests']

... and 7 more failing tests in the run log.
Fix: the assertion above names what the guard expects; change the tree to match it.
Reproduce in seconds, no build: scripts/ci/guards-local.sh --step 'Validate the package test lane'"'"'s single-suite phase'

Validate side-lane placement onto idle owned runners

  • CmuxNextWiring.test_every_mac_job_reads_the_placement
AssertionError: Items in the first set but not the second:
'fast-tier'
  • CmuxNextWiring.test_placement_starts_only_where_attempt_1_may_take_the_side_label
AssertionError: False is not true

Fix: the assertion above names what the guard expects; change the tree to match it.
Reproduce in seconds, no build: scripts/ci/guards-local.sh --step 'Validate side-lane placement onto idle owned runners'

Validate the persistent-pool rescue

Test: python3 tests/test_ci_owned_pool_rescue.py

  • SideLanes.test_a_completed_failed_blacksmith_retry_is_not_watched_again
AssertionError: True is not false
  • SideLanes.test_a_real_failure_on_cmux_next_attempt_two_is_not_rescued
AssertionError: 'rerun-failed' unexpectedly found in ['jobs:2', 'run', 'pull', 'run', 'rerun-failed']

Fix: the assertion above names what the guard expects; change the tree to match it.
Reproduce in seconds, no build: scripts/ci/guards-local.sh --step 'Validate the persistent-pool rescue'

Validate every workflow guard is wired

Test: python3 tests/test_ci_workflow_guards_are_wired.py

Traceback (most recent call last):
  File "/home/runner/_work/cmux/cmux/tests/test_ci_workflow_guards_are_wired.py", line 110, in <module>
    test_every_workflow_guard_is_run_by_a_workflow()
  File "/home/runner/_work/cmux/cmux/tests/test_ci_workflow_guards_are_wired.py", line 89, in test_every_workflow_guard_is_run_by_a_workflow
    assert not unwired, (
           ^^^^^^^^^^^
AssertionError: these tests read .github/workflows/ but no workflow runs them, so the invariants they assert are not enforced:
  tests/test_cmux_next_web_bundle_cache.py
  tests/test_cmux_tui_republish_same_commit.py
  tests/test_nightly_next_post_publish.py
Add a step to .github/workflows/ci-guards.yml, or add an entry to UNWIRED in this file explaining why not.

Fix: the assertion above names what the guard expects; change the tree to match it.
Reproduce in seconds, no build: scripts/ci/guards-local.sh --step 'Validate every workflow guard is wired'

Validate required checks are bounded

Test: python3 tests/test_ci_required_checks_are_bounded.py

unbounded CI:
  - .github/workflows/cmux-next-batch.yml runs on pull_request with no concurrency group, so every push leaves the superseded run running
  - .github/workflows/cmux-next-split-guard.yml runs on pull_request with no concurrency group, so every push leaves the superseded run running

Fix: the assertion above names what the guard expects; change the tree to match it.
Reproduce in seconds, no build: scripts/ci/guards-local.sh --step 'Validate required checks are bounded'

... and 6 more failed steps in the run log.

Agents: python3 scripts/ci/guard_attribution.py fix applies the mechanical fixes locally. This comment is updated in place on each push.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by chief-ui on cosmic-gray · session

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Closing as landed: the notices deck shipped in #21738 (6327df6, "Chief pet: floating pet, notices, quick reply and Settings (whole stack)") and was refined since in #22563, #23000 and #23318. This stacked PR targets feat/chief-pet-panel, which never merges.

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