Skip to content

cnx-ios: fix full-verify defects D1–D14 (Chief, teams, previews, Codex default, polish) - #22354

Closed
azooz2003-bit wants to merge 31 commits into
feat-cnx-iosfrom
feat-cnx-ios-fixes-r1
Closed

azooz2003-bit wants to merge 31 commits into
feat-cnx-iosfrom
feat-cnx-ios-fixes-r1

Conversation

@azooz2003-bit

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

Copy link
Copy Markdown
Collaborator

Summary

Fixes the defects a fresh verifier found in the cmux-next iOS app at 3e6a2b5 (cmux INTERNAL 1.2.0); report: cnx-ios/verify/full-verify-app-20261019.md on feat-cnx-ios-fullverify-app.

ID Fix
D2 Chief never loads The Mac app hands cnx-hostd its own Chief owner (CNX_CHIEF_SESSION, and CNX_CHIEF_SOCKET once connected), for tagged and Release builds. The phone shows "Chief isn't available" with the reason and Try Again instead of an endless spinner.
D3 Chief send drops the message Until Chief takes sends, Send keeps the text in the composer and offers Try Again or Send When Chief Connects (the outbox); voice and + are off meanwhile.
D1 Create team fails silently Stack refuses client-side team creation in both projects (client_team_creation_enabled: false). New Worker route POST /v1/teams creates the team with the project's server key; the phone uses it and rereads Stack's list.
D9 File previews refused cnx-hostd's file service also reads the folders of the Mac daemon's tabs (the agentcwd roots acpmux already shares), dropping /, home and its ancestors. SECURITY.md updated.
D4 Codex default model acpmux skips a catalog start model the harness does not list (only the catalog default, only when the harness reports catalog ids); phone Default uses the Mac's own pick; model errors read as sentences; the composer model menu shows whenever models are listed.
D8 Claude Start Chat A request while another opens says "Still opening …"; every request is logged. Root cause pending live check.
D5 Autocorrect and auto-capitals off in name fields and the agent composer.
D7/D11 The loading skeleton no longer overlays the Mac lines, so Connect gets its tap.
D10 Short inline Feed rows draw as native text instead of a web view each.
D6/D12/D13/D14 No "line 0"; Codex's bare "finished" says where to look; "Allowed"/"Allowed once"; Home previews the newest reply; VoiceOver's time matches "now".

CmuxTabsKit and CmuxConversation are unchanged. No transport files changed.

Tests

  • Swift (mini-cmux11s, cnxkit-test.sh): ChiefUnavailableTests, ChiefFailureTests, ServiceTeamCreationTests, AgentCatalog*, TurnFailureCopyTests, LastAnswerTests, RelativeStampSpokenTests, FeedPlainTextTests, TerminalFeedTests, FeedPendingTests: pass.
  • Mac Swift (fleet cmux-ci run): IPhoneHostChiefTests, CnxHostTests.
  • Rust (rbx): cnx-hostd all tests + clippy; acpmux 521 tests (nextest) + clippy, new a_catalog_default_the_harness_does_not_offer_is_not_used.
  • Worker (mini-cmux11s, vitest): 45 pass incl. new test/teams.test.ts; http.test.ts expected API 0.8.0 (stale on base, wrangler says 0.9.0).
  • Red runs: each failing test was committed before its fix; red was a compile failure (missing API) or, for acpmux, the catalog model being set. Separate red runs were not executed.

Review

Correctness-first subagent review found no blockers; should-fix items (HOME fallback in hostd, stored-spelling compare, acpmux skip limited to catalog defaults, Try Again stuck, voice/+ send paths, team-creation limiter) and nits are fixed in later commits.

Open

  • D1 live: the Workers need STACK_SECRET_SERVER_KEY for the dev and prod Stack projects, and the TEAM_LIMIT binding deploys with them. Not deployed here.
  • Live verification over the real link: see cnx-ios/verify/fixes-r1-20261020.md.

Mac-side counterpart against feat-cnx-ios-macnext: see linked PR.

Changelog

  • Fixed: cmux-next iOS Chief, team creation, file previews, Codex default model and several smaller issues found by a full verification.

🤖 Generated with Claude Code


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


Summary by cubic

Fixes the 14 defects a full verification found in the cmux-next iOS app, across the phone app, the Mac's host daemon, the acpmux harness hub, and the backend Worker.

Chief on the phone now says why it's unavailable instead of an endless spinner, offers Try Again (which ends on every exit and never opens Chief twice), and keeps a message written before Chief connected; a prompt reuses one acpmux id on resend so the Mac never runs it twice, a returned draft for a prompt the Mac was already running is withdrawn from the composer, and unsent text survives a rebuild. The Mac app hands hostd its own Chief owner and socket, so DEV and tagged builds serve the right Chief.

Team creation goes through the Worker (POST /v1/teams) with the project's server key instead of Stack's refused client call, and a per-user rate limit with the phone's Try Again shown when it fails; creation is rate-limited to 3 a minute. File previews like the agent-chat workspaces (never /, home or its ancestors), a catalog default model applies only when the harness offers it (never a saved pick), and a running chat's model and mode menus come from the session detail _acpmux/attach returns. Close All Tabs now asks first, like Safari.

Smaller fixes: autocorrect and auto-capitalization off in code-like fields, the loading skeleton no longer blocks Mac rows, short feed rows draw as native text, plain-English failure messages replace raw JSON, VoiceOver reads times and lines correctly, and copy is clearer. Tests added for each fix; no transport files changed.

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

View guided diff Turn on auto-fix

azooz2003-bit and others added 21 commits October 19, 2026 20:22
… no Chief placement in the launch)

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

A DEV or tagged build keeps its Chief at ~/.cmux/chief/<bundle id>, but the
app never set CnxHostLaunch.chiefSession, so hostd dialed the default home's
owner and refused every phone chief channel. The wiring now passes the app's
ChiefConversationOwner session (always) and its socket once connected
(CNX_CHIEF_SOCKET), for tagged and Release builds alike.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… keeps the message (red)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…T /v1/teams)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… key; phone test (red)

Stack refuses client-side team creation in both projects
(client_team_creation_enabled is false), so a team made from the phone
never existed. The Worker now creates it as the caller with the server key
and says team_creation_unavailable when it has none.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…reads Stack's list

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

The conversation's first-load spinner never ended without the Mac's Chief,
and its composer cleared and dropped a message sent before Chief connected.
Chief's bar now shows the reason (in plain words, hostd's text goes to the
log) with Try Again, which opens the chief channel again. The send button
goes through a gate: until Chief takes sends the text stays in the composer
and an alert offers Try Again or Send When Chief Connects (the outbox).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…iOS-only), tests there

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ers, never home (red)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ntcwd roots), never home or above

Files and Artifacts lists files the phone's chat edited in its workspace
folder, but hostd's file service only knew the Chat Folders, so every
preview was refused. A file outside the Chat Folders is now checked against
the folders of the tabs the Mac's daemon lists (the same folders the app
shares with phones for agent chats), dropping /, home and its ancestors as
acpmux does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…(cnx-ios D4)

A Codex account without GPT-6.1 Sol accepted session/set_model and then
failed every prompt, so a new chat (the phone's Default) never worked.
The catalog default now applies only when the harness lists it (or lists
nothing, as Claude Code); otherwise New Agent Chat says no start model and
the chat runs the harness's own default, its config's model. A soft start
model this session's harness does not list is skipped with
start_default_skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…named, model refusals read plain (red)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…reads plainly; model menu in a running chat

- New Agent Chat on a named agent with Default starts on the Mac's own last
  pick for that agent, and does not name a default the Mac's account does
  not list.
- A refused prompt's raw JSON error ({"type":"error","status":400,...})
  becomes a sentence ("Codex can't use this model with the Mac's account.
  Pick another model."), in the toast and on the failed-turn card.
- The composer's model menu shows whenever the agent lists models, even when
  the running model is not among them, so a chat can switch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… a second tab request says so

D8: a tab request while another opens returned silently; it now shows
"Still opening ..." and every request is logged with its option.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nect works); plain diff and Feed wording

- D7/D11: while loading, the skeleton was an overlay over the List and drew
  over the Mac section lines and took their Connect taps; with Mac lines it
  now sits below them as a non-interactive row.
- D6: a snippet edit's rows read without a line number, never "line 0".
- D12: an empty terminal finished event reads "Finished its turn in the
  terminal..."; an Allow reads "Allowed" / "Allowed once", not
  "Allowed: Allow".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…me previews the newest reply; VoiceOver's time matches "now"

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

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… harness lists catalog ids

A saved pick is never skipped. A harness whose reported ids are not the
catalog's (Claude Code's aliases) keeps the catalog default; DSH route ids
match as model_catalog::resolve accepts them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…compare in the stored spelling as acpmux does

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ce; voice and + gated before Chief connects; team creation limiter; copy nits

- LiveCoordinator.startChief ends a Try Again on every exit (defer) and a
  retry while one opens does nothing.
- Before Chief connects, the record and + buttons are off too (they clear and
  drop like Send); package views are looked up once.
- POST /v1/teams: its own TEAM_LIMIT (3 a minute), no control characters.
- A capacity error naming the model stays a capacity error; setext and
  thematic breaks keep the Feed's web renderer.
- http.test.ts expected API 0.8.0 while wrangler says 0.9.0 (stale on base).

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

coderabbitai Bot commented Oct 20, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • 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.

@azooz2003-bit

Copy link
Copy Markdown
Collaborator Author

Correctness-first review (fresh subagent) of 3e6a2b5..186b62f: no blockers. Findings and resolution:

  • hostd HOME fallback to / could share home: fixed (no workspace folders without a resolvable HOME), e96061c.
  • hostd canonicalize vs acpmux stored spelling: fixed (F_GETPATH spelling for home and folders), e96061c.
  • acpmux skip applied to saved picks and could drop Claude's alias-listed default: fixed (catalog default only, only when reported ids are catalog ids, DSH route ids match), 903b7ac.
  • Chief Try Again could stay stuck / open twice: fixed (defer endReconnect, one open at a time), 186b62f.
  • Voice/+ send paths dropped before Chief connects: fixed (off until Chief takes sends), 186b62f. Send When Chief Connects keeps plain text only (formatting not kept): open, minor.
  • Unlimited team creation: fixed (TEAM_LIMIT 3/min, no control characters), 186b62f.
  • Nits fixed: capacity errors stay capacity; setext/thematic breaks use the web renderer; cached package view lookups. Not fixed: teamsCache is per isolate (60 s), chiefSocket read at hostd start (session fallback covers a restart in the same folder).

@blacksmith-sh

blacksmith-sh Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Found 14 test failures on Blacksmith runners:

Failures

Test View Logs
cnx-ios-testflight.yml job testflight never runs scripts/
select-ci-xcode.sh, so it builds with the image's default Xcode
View Logs
GitHub-hosted runner label: .github/workflows/
pr-red-checks-comment.yml:16: runs-on: ubuntu-24.04
View Logs
GitHub-hosted runner label: .github/workflows/
pr-red-checks-comment.yml:16: runs-on: ubuntu-24.04
View Logs
test_every_mac_job_reads_the_placement (main.CmuxNextWiring.test_every_mac_job_read
s_the_placement) (job='cmux-scheme-compile')/
test_every_mac_job_reads_the_placement (main.CmuxNextWiring.test_every_mac_job_read
s_the_placement) (job='cmux-scheme-compile')
View Logs
test_every_mac_job_reads_the_placement (main.CmuxNextWiring.test_every_mac_job_read
s_the_placement) (job='daemon-test')/
test_every_mac_job_reads_the_placement (main.CmuxNextWiring.test_every_mac_job_read
s_the_placement) (job='daemon-test')
View Logs
test_every_mac_job_reads_the_placement (main.CmuxNextWiring.test_every_mac_job_read
s_the_placement) (job='generated-files')/
test_every_mac_job_reads_the_placement (main.CmuxNextWiring.test_every_mac_job_read
s_the_placement) (job='generated-files')
View Logs
test_every_mac_job_reads_the_placement (main.CmuxNextWiring.test_every_mac_job_read
s_the_placement) (job='release-compile')/
test_every_mac_job_reads_the_placement (main.CmuxNextWiring.test_every_mac_job_read
s_the_placement) (job='release-compile')
View Logs
test_every_mac_job_reads_the_placement (main.CmuxNextWiring.test_every_mac_job_read
s_the_placement) (job='swift-test')/
test_every_mac_job_reads_the_placement (main.CmuxNextWiring.test_every_mac_job_read
s_the_placement) (job='swift-test')
View Logs
test_every_shadow_job_is_compare_only (main.ShadowJobTests.test_every_shadow_job_is
_compare_only) (workflow='cmux-tui-artifacts.yml', shadow='macos-cross-runtime-x86_64')
/test_every_shadow_job_is_compare_only (main.ShadowJobTests.test_every_shadow_job_i
s_compare_only) (workflow='cmux-tui-artifacts.yml', shadow='macos-cross-runtime-x86_64'
)
View Logs
test_every_shadow_job_is_compare_only (main.ShadowJobTests.test_every_shadow_job_is
_compare_only) (workflow='cmux-tui-artifacts.yml', shadow='macos-cross-shadow')/
test_every_shadow_job_is_compare_only (main.ShadowJobTests.test_every_shadow_job_is
_compare_only) (workflow='cmux-tui-artifacts.yml', shadow='macos-cross-shadow')
View Logs

...and 4 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

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Probably yours: CI fast guards failed: a guard step failed, FAIL 0.2s workflow-guard-tests / ci: Validate macOS jobs select a pinned Xcode.

CI failed on e9e9bf0b23 (run 39374396380 attempt 1): 3 code, 5 unknown.
macOS jobs did not run: compile and app tests were skipped: Fast static checks failure.

Job Verdict Why
CI fast guards code a guard step failed
Fast static checks code a static check failed
guards / workflow-guard-history unknown no known signature; failed step: Validate SwiftPM lockfile policy
guards / workflow-guard-tests / app-host-cache unknown no known signature; failed step: Validate iOS video recording failures
guards / workflow-guard-tests / release-tooling unknown no known signature; failed step: Validate retried Ghostty Zig package fetches
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
guards / workflow-guard-tests / release-ios unknown no known signature; failed step: Validate iOS simulator build-once contract
Matched log lines
CI fast guards: FAIL    0.2s  workflow-guard-tests / ci: Validate macOS jobs select a pinned Xcode
Fast static checks: FAILED localization (0.92s)
guards / workflow-guard-tests / quality-determinism: FAIL: test_scans_only_test_sources (__main__.CommandLine.test_scans_only_test_sources)

Not re-run automatically: CI fast guards, Fast static checks, guards / workflow-guard-history, guards / workflow-guard-tests / app-host-cache, guards / workflow-guard-tests / release-tooling 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.

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

Validate macOS jobs select a pinned Xcode

Test: python3 tests/test_ci_macos_xcode_selection.py

cnx-ios-testflight.yml job testflight never runs scripts/select-ci-xcode.sh, so it builds with the image's default Xcode

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 macOS jobs select a pinned Xcode'

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

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/pr-red-checks-comment.yml:16:    runs-on: ubuntu-24.04

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

    result, count = run_package_step("CmuxUpdater", [(startup, 1), (passed, 0)])
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/_work/cmux/cmux/tests/test_ci_select_package_tests.py", line 102, in run_package_step
    count = int((root / "calls").read_text())
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/pathlib.py", line 1029, in read_text
    with self.open(mode='r', encoding=encoding, errors=errors) as f:
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/pathlib.py", line 1015, in open
    return io.open(self, mode, buffering, encoding, errors, newline)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmp_q43bpw3/calls'

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

/tmp/guard-steps-b5lwcu1d/runner_temp/actionlint.tar.gz: OK
/tmp/guard-steps-b5lwcu1d/runner_temp/actionlint
.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/nightly.yml:34:3: maximum number of inputs for "workflow_dispatch" event is 10 but 15 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 side-lane placement onto idle owned runners

  • CmuxNextWiring.test_every_mac_job_reads_the_placement (job='cmux-scheme-compile')
AssertionError: False is not true : ${{ !(github.event_name == 'pull_request' && github.base_ref == 'feat-cmux-next') && (!cancelled() && ((inputs.same_tree_sha == '' && needs.path_route.outputs.scheme == 'true' && needs.push-head-preflight.outputs.current == 'true' && needs.path_route.outputs.tree_state == 'ready' && (github.event_name != 'workflow_dispatch' || github.ref == 'refs/heads/feat-cmux-next' || startsWith(github.ref, 'refs/heads/next-batch/'))) || (inputs.same_tree_sha != '' && inputs.same_tree_state == 'ready' && contains(inputs.same_tree_tiers, 'scheme')))) }}
  • CmuxNextWiring.test_every_mac_job_reads_the_placement (job='release-compile')
AssertionError: False is not true : ${{ !(github.event_name == 'pull_request' && github.base_ref == 'feat-cmux-next') && (!cancelled() && needs.path_route.outputs.native == 'true' && needs.push-head-preflight.outputs.current == 'true' && (github.event_name != 'workflow_dispatch' || github.ref == 'refs/heads/feat-cmux-next' || startsWith(github.ref, 'refs/heads/next-batch/'))) }}
  • CmuxNextWiring.test_every_mac_job_reads_the_placement (job='swift-test')
AssertionError: False is not true : ${{ !(github.event_name == 'push' && github.ref == 'refs/heads/feat-cmux-next') && (!cancelled() && needs.path_route.outputs.swift == 'true' && needs.push-head-preflight.outputs.current == 'true' && (github.event_name != 'workflow_dispatch' || github.ref == 'refs/heads/feat-cmux-next' || startsWith(github.ref, 'refs/heads/next-batch/'))) }}
  • CmuxNextWiring.test_every_mac_job_reads_the_placement (job='daemon-test')
AssertionError: False is not true : ${{ !((github.event_name == 'push' && github.ref == 'refs/heads/feat-cmux-next') || (github.event_name == 'pull_request' && github.base_ref == 'feat-cmux-next')) && inputs.same_tree_origin != 'push' && (!cancelled() && ((inputs.same_tree_sha == '' && needs.path_route.outputs.daemon == 'true' && needs.push-head-preflight.outputs.current == 'true' && needs.path_route.outputs.tree_state == 'ready' && (github.event_name != 'workflow_dispatch' || github.ref == 'refs/heads/feat-cmux-next' || startsWith(github.ref, 'refs/heads/next-batch/'))) || (inputs.same_tree_sha != '' && inputs.same_tree_state == 'ready' && contains(inputs.same_tree_tiers, 'daemon')))) }}

... 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 side-lane placement onto idle owned runners'

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_tui_republish_same_commit.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 notification semantics gates

Test: python3 tests/test_ci_notification_semantics.py

  • NotificationSemanticsTests.test_a_failing_package_does_not_hide_later_packages
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmpjhdlfpkj/calls.jsonl'
  • NotificationSemanticsTests.test_packages_prebuild_in_parallel_then_test_serially
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmpujlgr26w/calls.jsonl'

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 notification semantics gates'

Validate the macOS cross-compile shadow jobs stay compare-only

  • ShadowJobTests.test_every_shadow_job_is_compare_only (workflow='cmux-tui-artifacts.yml', shadow='macos-cross-shadow')
AssertionError: Lists differ: ['notify-unpublished-tree'] != []

First list contains 1 additional elements.
First extra element 0:
'notify-unpublished-tree'

- ['notify-unpublished-tree']
+ [] : cmux-tui-artifacts.yml: ['notify-unpublished-tree'] must not need macos-cross-shadow
  • ShadowJobTests.test_every_shadow_job_is_compare_only (workflow='cmux-tui-artifacts.yml', shadow='macos-cross-runtime-x86_64')
AssertionError: Lists differ: ['notify-unpublished-tree'] != []

First list contains 1 additional elements.
First extra element 0:
'notify-unpublished-tree'

- ['notify-unpublished-tree']
+ [] : cmux-tui-artifacts.yml: ['notify-unpublished-tree'] must not need macos-cross-runtime-x86_64

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 macOS cross-compile shadow jobs stay compare-only'

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

Agents: python3 scripts/ci/guard_attribution.py fix applies the mechanical fixes locally.

azooz2003-bit and others added 2 commits October 19, 2026 21:39
Results table for D1-D14 on fleet build cnx-e2e-4a31def5 and a Demo phone
build of the same SHA; the fresh verifier's fv.py/fvr.sh driver, with FV_ENV
launch variables for the app.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… Again; plain refusal copy; onboarding team name not autocorrected

- D2: after Try Again connected, the open Chief screen kept drawing the old
  store and spun; the screen is now keyed by the session's store.
- D2: hostd closing the chief channel (owner socket missing) reads "Chief
  isn't running on <Mac>" instead of "didn't answer (daemon channel closed)".
- D5: the onboarding Create your team field was missed.

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

Copy link
Copy Markdown
Collaborator Author

Live recheck over the real link (simulator + hidden tagged Mac rig cnx-e2e-4a31def5 on mini-cmuxs-mac-mini-2, phone Demo build from mini-cmux7s, Xcode 26.6), at 4a31def; results in cnx-ios/verify/fixes-r1-20261020.md, evidence git-ignored under cnx-ios/verify/evidence/2026-10-20/fixes-r1/.

Pass: D2 Chief loads (hostd gets CNX_CHIEF_SESSION/SOCKET), D2 unavailable bar, D3, D9 (inside folder opens, ~/ file refused), D4 Default (plain "Default", full turn ran), D8 (Claude tab opens), D5, D7/D11, D10 (16.8 hitch ms/s vs 91.3; p99 34.6 vs 49.2 ms; rig load lower than before), D12, D14.

Fixed after the recheck (ffbcd54, not re-run live): Try Again left the open Chief screen spinning on the old store; refusal copy read "daemon channel closed"; onboarding Create your team field still autocorrected. The review fixes 903b7ac, e96061c, 186b62f were also not in the live build.

Open: D1 live (the Workers need STACK_SECRET_SERVER_KEY; none deployed); D4 model pill does not appear in a running Codex chat (acpmux appears to list no models for the codex harness; needs a look at _acpmux/models for the app-server bridge); D13 Home preview not confirmed (no preview line after relaunch); D6 not run. New, out of scope: a sent prompt came back into the composer after a link drop (double-send risk); Close All Tabs has no confirmation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
azooz2003-bit and others added 6 commits October 19, 2026 21:47
…ac ran is withdrawn (red)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ft the Mac ran leaves the composer

After a link drop, session/prompt's reply was lost although the Mac had
run the prompt, so it came back into the composer and Send would run it
twice. The prompt's promptId now travels with the returned draft; sending
the same text again reuses it with resend (acpmux runs each id once), and
when the replayed transcript shows that id ran or queued, the draft is
withdrawn from the composer. Also updates two preview refusal tests for
the D9 hint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…/attach's session detail (red)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ch, so a running chat has its model menu

The phone took models and modes only from later session updates, which a
Codex chat never sends after it starts; acpmux keeps them in the session
detail _acpmux/attach returns. A config option of category model also
serves as the list. The menu's check follows a pick.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tachments count and leave with a withdrawn draft; Chief keeps unsent text across a rebuild; attach state after the page

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

azooz2003-bit commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator Author

Round 2 (coordinator follow-up), commits after 186b62f:

  • Prompt resend: a prompt keeps one acpmux promptId across a resend (resend: true); a returned draft leaves the composer once the transcript shows that id ran or queued; no draft comes back for a prompt already seen running; attachments are part of the match. Tests: PromptResendTests.
  • Close All Tabs asks first ("Close All N Tabs"/Cancel) and closes exactly the tabs it asked about: CmuxTabsKit upstream feat-cmux-next-tabs-kit d785980 and 087c69c, synced byte-identical (check-tabskit-sync.sh ok). Tests: CloseAllConfirmationTests.
  • D4 model menu: the phone now reads a chat's models, modes and options from _acpmux/attach's session detail (applied after the replayed page); a model config option also serves. Root cause: models only ever came from later session updates, which a running Codex chat doesn't send. Tests: SessionStateTests.
  • Chief rebuild after Try Again keeps unsent composer text; visibility and pop-gesture delegates survive the rebuild.
  • Full CnxKit suite on mini-cmux11s: 783+ tests pass.

Second fresh review (correctness first) of 186b62f..a553ef2: no blockers; should-fix items (seen-running draft, attachments in the match/withdrawal, Chief text lost on rebuild, attach state applied before older records) and the Close All count nit are fixed in 5180efa and 087c69c (head d79ea22). Not fixed: knownModels doesn't follow a model change made through a config option (check mark only).

Live re-run on the new head is in progress; results go to cnx-ios/verify/fixes-r1-20261020.md.

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

Copy link
Copy Markdown
Collaborator Author

Live pass 2 (real link; Mac rig fleet job 8ddc14f818104818f5d51e2e, tag cnx-e2e-a553ef2b; phone Demo build of d79ea22 on mini-cmux7s, Xcode 26.6), results in the Second pass section of cnx-ios/verify/fixes-r1-20261020.md (e9e9bf0):

  • Pass: Chief Try Again redraws the conversation in place and keeps text typed while unavailable; refusal copy "Chief isn't running on …"; Chief + and record disabled while unavailable; onboarding team name kept as typed; Codex on Default; D9 inside-folder preview opens, ~ refused.
  • Pass: prompt resend. cnx-hostd killed mid-turn, link back in 2 s, composer stayed empty, the transcript has the prompt once (the resend-with-same-id path was not exercised because the draft never came back).
  • Pass: D4 model menu in a running Codex chat lists the account's models, mode and effort; switching to GPT-5.6-Luna took effect on the Mac (Codex session log).
  • Pass with note: Close All Tabs asks "Close All 2 Tabs"; iOS 26 shows the dialog as a popover with no Cancel row, tapping outside cancels and both tabs stay.
  • D13 pass (Home shows the newest reply). D6 partial: no "line 0" any more, but snippet diffs still have no line numbers (positions are unknown for snippet edits).
  • D1 untouched (no Worker deployed, no keys): waiting on the user.

@azooz2003-bit

Copy link
Copy Markdown
Collaborator Author

Superseded by #22555, which merged this branch's head into feat-cmux-next (merge commit f3842ff) together with #22260, #22354, #22355, #22337, #22419, #22387 and #22574. Closing as folded in; the branch is kept.

This branch was previously deployed

1 inactive deployment
artifacts — e9e9bf0b Deployed Oct 20, 2026 by azooz2003-bit
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