Skip to content

feat(ios): add Chief Home to the classic mobile shell - #21287

Merged
azooz2003-bit merged 205 commits into
mainfrom
classic-ios-chief
Oct 20, 2026
Merged

azooz2003-bit merged 205 commits into
mainfrom
classic-ios-chief

Conversation

@azooz2003-bit

@azooz2003-bit azooz2003-bit commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Expose Mac-owned Chief status, conversations, transcript, send, stop, approval, answer, and open RPCs through the authenticated mobile bridge.
  • Advertise Chief capabilities and enforce ticket-scope authorization for read and mutation methods.
  • Add a classic iOS Home list with a pinned Chief entry, search, refresh, avatar, accessibility labels, scene refresh, and reset on Mac switch.
  • Add a Messages-style Chief transcript with polling, paging, queued sends, client-message correlation, typing state, stop action, and fail-closed unavailable behavior.
  • Add structured work, approval, and question cards. Approval and question actions call chief.approve / chief.answer, prevent duplicate taps, and collapse answered cards to receipts.
  • Open a dedicated Chief composer for multi-item, multi-select, and Other questions while keeping simple single-choice cards inline.
  • Keep the composer’s single Other field aligned with the existing chief.answer contract: it targets the first eligible unanswered item, then the first eligible multi-select item.
  • Add the Chief avatar to Home rows, the transcript header, and conversation details, including empty conversations.
  • Gate unsupported Chief reactions, edit, unsend, media, microphone, and accessibility affordances.
  • Preserve older pending cards across polling, bound transcript cache growth, and publish the authoritative participant identity as soon as a first send reveals it.
  • Keep answer follow-up rows from being pre-cached without events, retry Home subscriptions after transient RPC failures, and keep streamed draft tokens off the inbox refresh cursor.
  • Use messages-only owner reads for list previews so inbox refreshes do not calculate thread summaries.
  • Keep preview formatting in a constructable value type for scoped reuse and testing.
  • Build the Home conversation list from the authoritative Chief inbox on cold start, with a regression test for that path.
  • Isolate optional Chief Home from legacy workspace close/group test fixtures.

Testing

Local

  • swift package dump-package --package-path Packages/iOS/CmuxMobileShell — passed.
  • swift package dump-package --package-path Packages/iOS/CmuxMobileShellUI — passed.
  • swift package dump-package --package-path Packages/macOS/CmuxChief — passed.
  • swiftc -frontend -parse for the changed Chief backend, Home/question sheet, and backend test files — passed.
  • ./scripts/lint-ios-package-conventions.sh — passed with no unjustified convention violations.
  • git diff --check — passed.
  • python3 scripts/verify-local.py --only swift-syntax --swift-changed — passed on the final repair head.
  • swiftc -frontend -parse for the new owner preview API and its two callers — passed.
  • ./scripts/lint-ios-package-conventions.sh — passed with no unjustified convention violations on the final repair head.
  • The namespace lint included the new preview formatter and passed with no unjustified violations.
  • Per repository rules, no local Swift tests, simulator runs, or local xcodebuild test were run.

Exact-head hosted builds

  • The current final branch head is 05fd46d730112dd16523deda79f036f56778e920.
  • The earlier fleet artifacts at 17f3be65c49fa38b4b9ef90e93a1d22a763965c8 predate the final refresh-recovery repair and are retained only as historical evidence; current-head CI is the merge evidence.
  • Conflict-only merge gate passed against current main: base 709612a962a42daec52f90380ca3bfff03d8e4f8, head 05fd46d730112dd16523deda79f036f56778e920, speculative merge 437a586fcfac8693699c56d792190cf8f572a25d.

Runtime evidence

  • Fresh exact-head fleet simulator packet: artifacts/verify-remote/20261017-062726-chf30-ios-aws-m4pro-3/, verification step f20c1bca0675a5083f2dbc71, evidence SHA-256: ced090de2d1b4dc6e0f0d1beea78fc42f0c32f94f22a4d13dc284c334ab5e29.
  • The packet launched dev.cmux.ios.chf30 from the exact iOS artifact and cleaned up its isolated simulator. It reached the expected reconnect/no-paired-Mac state; Chief Home, transcript, send, stop, approval, question composer, and pairing interactions were not exercised because this verification lane does not pair a Mac.
  • The direct development backend responded at https://cmux-dev-backend-1.tail137216.ts.net:3869/; the local Tag Opener health endpoint passed and http://127.0.0.1:17320/chf30 was registered.
  • No physical-device verification was performed because the task did not authorize real-phone access.

Related work

Impact map

  • Mobile RPC source of truth: MobileChiefClient and the existing authenticated Chief owner dispatch; send correlation also crosses ChiefConversationBackend, ChiefService+Control, and the Mac mobile event stream.
  • Direct callers and sibling entrypoints inspected: WorkspaceShellView, MobilePrimaryTabScaffold, existing mobile destinations, MobileHostService capability/ticket authorization, TerminalController+Chief, and the Chief owner/control-socket paths.
  • Persistence/API/platform effects: existing Chief JSONL and capability contracts remain the source of truth; no schema or release-metadata migration; unsupported operations return typed backend errors.
  • Chief remains request/response based, so the transcript polls while visible.

HIG reference

Changelog

Added: Chief Home and conversation access to the classic mobile shell.

austinywang and others added 30 commits October 15, 2026 04:07
Copies CmuxAgentQuestion, CmuxHomeCore, CmuxHomeRender and CmuxMessagesLab
unchanged from origin/feat-cmux-next so classic can host the same
iMessage-style transcript.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An in-process conversation owner that persists Chief conversations as JSONL
in the build's Chief home, streams brain turns as drafts, tool work and
approvals, and serves them to HomeStore through ChiefLocalSource.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Memory lives in the Chief home as person.md, instructions.md and an
append-only memory.jsonl that the app and the CLI write under one lock.
The system prompt teaches the cmux CLI, agent dispatch, cloud setup and
settings editing, then appends the user's memory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Work in progress; split into logical commits before review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…row, single selection

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…anced first run

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

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

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

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sters by the composer

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

func publish(_ event: HomeEvent) {
changeCursor = UUID().uuidString

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P0 Reply chunks rescan saved history

Every streamed reply chunk now changes changeCursor, waking Home and rebuilding every conversation row through controlConversations(). Each row calls snapshot, which can scan that conversation’s full message history for thread counts. Draft chunks do not change the returned previews, so this repeatedly scans saved history without showing new content. As history grows, this consumes more Mac CPU and delays other requests to the Chief owner.

This violates the repository rule against rebuilding unbounded collections on every event. Use a separate inbox cursor that advances only when returned rows change, and fetch previews without calculating unused thread counts.

Rule Used: Flag production code that adds nested full-collection scans, per-target rescans for batch actions, repeated sort/filter/map work in hot UI/socket/search/process paths, in-memory joins that belong in the data store, or unbenchmarked slower algorithms ... (source)

Comment on lines +218 to +221
} catch {
guard !Task.isCancelled else { return }
errorMessage = String(describing: error)
return

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Home stops updating after failure

One failed conversationsSnapshot request ends waitForChanges for the current Home visit. A temporary busy response or network failure therefore stops automatic updates even after requests work again. Pull-to-refresh calls only load, so it does not restart the wait either. Users must leave the view or change the app’s active state to restart updates.

Restart the subscription through connection recovery or a cancellation-aware retry owner.

@cursor

cursor Bot commented Oct 20, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

Comment thread Sources/Chief/ChiefPreviewText.swift Outdated
/// what the transcript shows, and a waiting approval said in plain words
/// ("Needs your approval: Start Codex in “Scratch”", ``ChiefListPreview``; "Waiting
/// for you" until that line is read) instead of the card's raw prompt ("Run `…`?").
enum ChiefPreviewText {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P0 Preview helpers lack an owner

ChiefPreviewText is a new caseless enum containing only static helpers, used by production previews. The repository forbids static-only helper namespaces and requires this behavior to belong to a constructable owner. Make it a preview formatter owned by ChiefService, or move the behavior onto the existing preview model.

Rule Used: Flag new ambient global state in production Swift: a top-level (file-scope) func used as API, a top-level mutable var or a stub class/struct holding a global flag/once-token, a caseless enum/empty struct used purely as a static func/static let namesp... (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@azooz2003-bit

Copy link
Copy Markdown
Collaborator Author

Exact-head correctness review (05fd46d730112dd16523deda79f036f56778e920)

The required correctness-first review found no actionable high or medium findings on the final head.

  • answerQuestion publishes the target message before caching unseen transcript rows, so a follow-up read cannot be silently pre-cached.
  • Draft delivery still reaches the transcript while a separate inbox cursor prevents streamed tokens from rebuilding Home previews.
  • Home retries transient refresh failures with cancellation-aware recovery.
  • previewMessages(of:tail:) preserves the same bounded tail as snapshot without calculating thread summaries; both list-preview callers use it.
  • ChiefPreviewText is a constructable value type, and the regression test uses @testable import CmuxChief for its internal event publication.

Local syntax, package manifest, namespace/convention lint, and diff checks pass. Conflict-only merge verification against current main passed for this head. Hosted required checks are still running; no merge is being attempted until they settle.

@azooz2003-bit
azooz2003-bit merged commit c7bd52c into main Oct 20, 2026
@azooz2003-bit
azooz2003-bit deleted the classic-ios-chief branch October 20, 2026 09:21
@github-actions github-actions Bot added the merged-unverified A judging check was not green at merge; see the merge receipt comment label Oct 20, 2026
@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

main no longer compiles after this merge

@azooz2003-bit: after c7bd52c28b landed on main, the app-host test product (the app and cmuxTests, build-for-testing) stops compiling. The compile of the commit before it (27a2079a01) passed and its own merge commit c7bd52c28b fails, so this pull request is the cause (possibly with a semantic conflict against something merged earlier that its own CI did not see).

Evidence: https://github.com/manaflow-ai/cmux/actions/runs/39400098502/job/118552744022

CLI/CMUXCLI+CommandSuggestions.swift:53: error: function produces expected type 'Set<String>'; did you mean to call it with '()'?

Nothing blocks merging meanwhile. A fix-forward (or, failing that, a revert) is attempted automatically unless an open pull request already fixes this.

main_compile_attribution.py: post-merge, nothing here gates a merge.

austinywang added a commit that referenced this pull request Oct 21, 2026
…x-instinct-b77acc19

Merged by its real history so the Chief files use this branch's Oct 15
commit as their base. Kept this branch's pane-local conversation list over
the earlier workspace-list design (1abddf0) the iOS branch carried, and
combined the two always-allow fixes: one rules object per owner, saved to
the home that allowed the rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
austinywang added a commit that referenced this pull request Oct 21, 2026
Its tree is exactly 05fd46d (the iOS branch head, merged above) merged with
c7bd52c^ (also merged above): git merge-tree --write-tree of the two gives
c7bd52c's tree, 7afae9c.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
austinywang added a commit that referenced this pull request Oct 21, 2026
main fails to compile after #21287; the same one-line fix is open as
#22523 and merges cleanly with this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
austinywang pushed a commit that referenced this pull request Oct 21, 2026
c7bd52c (#21287) left the closure without (), so the stored property
has a closure type, not Set<String>, and the CLI does not compile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo added a commit that referenced this pull request Oct 21, 2026
* cli-contract: canvas help probe expects the chief pane type (#21287)

#21287 added chief to cmux canvas new-pane --type, so the help probe in
macOS compile admission failed on main and on every PR based on it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bf1-fdac-78a0-ac2e-a38c001e9b1e&host=cosmic-gray

* cli-contract: the canvas new-pane table row lists chief too

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bf1-fdac-78a0-ac2e-a38c001e9b1e&host=cosmic-gray

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
austinywang added a commit that referenced this pull request Nov 4, 2026
… (main red) (#35296)

* test: keep Chief Home out of the Option-digit routing suite's windows

Chief Home (#21287, on by default)
adds a pinned Home workspace at index 0 of every new main window. Two tests
in AppDelegateOptionDigitShortcutRoutingTests select `selectTab(at: 0)` and
then expect the window's initial terminal workspace to be selected, so they
selected Home instead: the terminal never took first responder and the
Option+arrow/Option+digit routing assertions saw the wrong workspace.

Disable Chief in the suite's isolation wrapper, the same way
WorkspaceGroupNumberedSelectionTests does, and restore the setting after.

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

* test: import only ChiefCatalogSection so StoredShortcut stays unambiguous

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merged-unverified A judging check was not green at merge; see the merge receipt comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants