Skip to content

cmux next chat: files open on the right beside the chat (labs chatViewer) - #22057

Merged
lucasr1b merged 43 commits into
next-chat-uifrom
next-chat-viewer
Oct 20, 2026
Merged

lucasr1b merged 43 commits into
next-chat-uifrom
next-chat-viewer

Conversation

@lucasr1b

@lucasr1b lucasr1b commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

stacked on #21315 (base next-chat-ui), retarget to feat-cmux-next once that lands. split out of #21315 so that pr stays the render engine and lawrence's #21760 fixes.

files and files the chat links to open in one column on the right of the chat, inside the chat, instead of a new column or a tab over it. behind agentPane.labs.chatViewer (debug settings, pages section), on by default. changes (the diff) opens exactly as on production today, with the switch on or off.

Summary

the viewer

  • the header's files opens the chat's folder in a column on the right of the transcript: folders open in place, .. goes up (never above the chat's folder), search across the folder, a file opens in the same column. listing is the session host's git.files.list (new file.list), search its git.files.search, so untracked ignored files never show (a tracked file shows even if it matches .gitignore).
  • a path link in a reply shows the file there too, read through the app (link.readPath): same checks as opening a path link today (deny list, agentPane.links.outsideRoots, a user gesture), text only, capped at 1 MiB. a binary file still opens in the app's tab, a folder in finder.
  • files and a file take 320px, about thread details' width; below 820px the column takes the transcript's place. changes is not part of this pr: it and a changed file's open work as before (a tab).
  • the column runs full height on the right, like the browser beside a chat. the transcript, composer and pr dock stay centered in what is left.

header and thread details

  • files lights while open, in every header style (including the tray styles), and every header button hovers and reads on the same way as thread details' button (no accent fill).
  • the files list and a file have one way out, an x at the end of their title row; no back to transcript chevron. escape still closes.
  • one panel on the right: opening files or a file closes thread details; while the viewer is open, thread details floats under its header button, as it does beside the browser.
  • files and a file read like thread details' column: rounded, its shadow, a 28px title row, no line under it.
Preview (files open, thread details open)
Preview
Preview (files closed, thread details open)
Preview

Testing

  • web (bun, one file each): chat-viewer, chat-files-view, chat-viewer-one-panel, chat-header-changes, labs-precedence, live-render; bun run typecheck: 10 errors and 7 warnings, all in HMR consumers this pr does not touch (same on the base).

  • swift (ci only): AgentPaneReplyReadPathTests, AgentPaneFilesListTests, AgentPaneLabsTests.

  • checked in the mock pane (?mock) at 1683 and 1100 px wide; lucas dogfooded the earlier rounds in a tagged dev app.

  • the red-then-green commits for these behaviors are on next-chat-ui (7f9cc9c..c62dfbd, reverted there in ea7e91a and 189a6c5); this branch restores them in one commit. the layout and header styling commits are css only, with no failing test first: happy-dom does not lay out.

  • 2026-10-20, after merging next-chat-ui (cmux next: chat ui parity pass (thoughts, header, thread details, side column, files) #21315 with the latest feat-cmux-next and cmux next chat: site icons for thread details sources (labs sourceIcons) #22058):

    • dev server file.list now resolves the path and stays inside the chat folder (security pass finding, low, dev only): bun test test/dev-host-file-list.test.ts failed 2 before 018738a0dba (../ and an escaping symlink listed outside names) and passes 4 after.
    • files survive a failed or outside-the-viewer file open: bun test test/chat-viewer.test.tsx failed 6 at 8445c43366f, 32 pass after 45c505cac78.

Observed / Not run

  • ran: the web tests above one file each (119 pass), site icon, header and chip tests (39 pass), bundle build and budgets, prepush-gate.py (no new violations), xcstrings lint, the mock pane at 1683, 1100 and 760 px.
  • scripts/web-lint.sh reds are outside this pr's files: text focus rings in CmuxNextBrowser and Checklist, formatting in settings pages.
  • not run: swift tests and native compile (ci), a fresh tagged-app dogfood on this head.

Changelog

Added: files and linked files open in a column beside the agent chat, with the chat's folder, search and file view (labs, on by default).

lucasr1b and others added 2 commits October 19, 2026 21:08
…, restored on top of next-chat-ui for its own review

Brings back the chat viewer commits that moved out of #21315: files and changes in one column beside the
transcript, the header's files list, a file's view, active header buttons, the x, one panel beside the chat
with thread details floating over it, and the composer centered under the transcript.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed, its shadow, a 28px title row and the x

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

cursor Bot commented Oct 19, 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.

@coderabbitai

coderabbitai Bot commented Oct 19, 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: 5828b91b-6a74-4e88-ae4f-9eb8c581a327

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 19, 2026 •

Copy link
Copy Markdown

Found 77 test failures on Blacksmith runners:

Failures

Test View Logs
.github/workflows/
nightly-next-tick.yml: triggers on the display names ['cmux-next', 'cmux-tui artifacts'
] and declares no SOURCE_WORKFLOW_PATHS, so renaming any of those workflows stops this
one from ever triggering and nothing reports it
View Logs
main.IOSWiring.test_test_ios_macos_jobs_take_the_runner_jobs_pool/
test_test_ios_macos_jobs_take_the_runner_jobs_pool
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
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

...and 67 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 19, 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: composer-type-scale.test.ts fails here but not on main's latest full suite. Seen on other PRs too (likely flaky): whats-new-text-selection.test.ts, whats-new-text-selection.test.ts, whats-new-text-selection.test.ts and 19 more.

CI failed on eaf447f97e (run 39480078250 attempt 1): 8 code, 3 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 / app-host-execution code a Python test failed
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
web / react-apps-check (3) code a web test failed
web / react-apps-check (1) code a web test failed
web / react-apps-check (4) code a web test failed
web / react-apps-check (2) code a web test failed
web / react-apps-check unknown no known signature; failed step: Check webview test shards

Failures:

  • seen on other PRs whats-new-text-selection.test.ts chromium > the Updated card's changes select with a drag and a double-click, and fire nothing: failed (job)
  • seen on other PRs whats-new-text-selection.test.ts chromium > in a sidebar-wide card a long change wraps to two lines, never cut on one: failed (job)
  • seen on other PRs whats-new-text-selection.test.ts webkit > the Updated card's changes select with a drag and a double-click, and fire nothing: failed (job)
  • seen on other PRs whats-new-text-selection.test.ts webkit > in a sidebar-wide card a long change wraps to two lines, never cut on one: failed (job)
  • seen on other PRs editors.test.tsx editors > every schema row renders the editor for its kind: failed (job)
  • seen on other PRs agent-pane-no-capsules.test.ts agent pane page > rounds its controls as small-radius rects, not capsules: failed (job)
  • seen on other PRs markdown-table-keys.test.ts markdown table keys > Cmd-A selects the cell's text, then the whole table, then lets the document ta...: failed (job)
  • new in this PR composer-type-scale.test.ts agent-pane.composer model-menu-starred draws its text on the type scale: failed (job)
  • seen on other PRs new-tab-warm-first-frame.test.ts chromium: Cmd-T paints its final chats and project on its first frame: failed (job)
  • seen on other PRs new-tab-warm-first-frame.test.ts webkit: Cmd-T paints its final chats and project on its first frame: failed (job)
  • ... 13 more in the job logs
Matched log lines
Fast static checks: FAILED localization (1.23s)
CI fast guards: FAIL    0.3s  workflow-guard-tests / ci: Validate repository variable defaults
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)
web / react-apps-check (3): (fail) chromium > the Updated card's changes select with a drag and a double-click, and fire nothing [340.57ms]
web / react-apps-check (1): (fail) editors > every schema row renders the editor for its kind [3872.39ms]
web / react-apps-check (4): (fail) agent-pane.composer model-menu-starred draws its text on the type scale [2296.69ms]
web / react-apps-check (2): (fail) markdown selection (chromium) > Cmd-A selects the document and reveals no syntax [1512.25ms]

Not re-run automatically: Fast static checks, CI fast guards, guards / workflow-guard-tests / release-tooling, guards / workflow-guard-tests / app-host-execution, guards / workflow-guard-tests / preflight 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 eaf447f97e (https://github.com/manaflow-ai/cmux/actions/runs/39480078250). It does not block the merge; a red guard merged into main breaks it for every open PR.

Validate repository variable defaults

Test: python3 tests/test_ci_repo_variable_defaults.py

Repository variables that an unset value makes expensive:
  - cmux-next-perf-bench.yml:36: runs-on reads vars.CI_SWIFT_PACKAGE_TESTS_STEP_GATEWAY with no literal runner label to fall back to; a fork pull request gets an empty runs-on
  - cmux-next-terminal.yml:44: runs-on reads vars.CI_SIDE_LANE_RUNNER with no literal runner label to fall back to; a fork pull request gets an empty runs-on
  - cmux-next-terminal.yml:82: runs-on reads vars.CI_SIDE_LANE_RUNNER with no literal runner label to fall back to; a fork pull request gets an empty runs-on

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 repository variable defaults'

Validate macOS jobs select a pinned Xcode

Test: python3 tests/test_ci_macos_xcode_selection.py

macos-matrix-fuzz.yml job fuzz 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'

Validate scripts keep full clones full

Test: python3 tests/test_ci_no_shallow_dev_fetch.py

  • NoShallowDevFetchTests.test_every_depth_fetch_checks_for_a_shallow_checkout
AssertionError: Lists differ: ['cnx-ios/scripts/demo-build.sh:244', 'scr[341 chars]:14'] != []

First list contains 7 additional elements.
First extra element 0:
'cnx-ios/scripts/demo-build.sh:244'

+ []
- ['cnx-ios/scripts/demo-build.sh:244',
-  'scripts/ci/ios_internal_builder.py:194',
-  'workers/cmux-vm/scripts/test-fork-capture-compat.ts:13',
-  'workers/cmux-vm/scripts/test-generated-creation-compat.ts:14',
-  'workers/cmux-vm/scripts/test-pending-history-compat.ts:13',
-  'workers/cmux-vm/scripts/test-snapshot-capture-compat.ts:13',
-  'workers/cmux-vm/scripts/test-snapshot-key-fence-compat.ts:14'] : depth-limited fetch without an `is-shallow-repository` check; pass --depth only when the checkout is already shallow (see this file's docstring)

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 scripts keep full clones full'

Check that push and pull_request path filters agree

Test: python3 tests/test_ci_workflow_path_filter_parity.py

           ^^^^^^^^^^^
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/**, .github/workflows/cmux-next-base-autofix.yml, 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/**, tests/test_cmux_next_base_autofix_finishes.py
  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-developer-id-intermediates.sh, scripts/prune_nightly_release_assets.py
cmux-vm-cloud.yml: push and pull_request filter different files
  paths: guarded on pull requests, not on push: backend/apps/api/src/cloud-vm-api*, backend/apps/api/src/team-vm-api*, backend/apps/api/test/clou ...

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'

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'

Validate workflow_run triggers name workflows that exist (red on main too, not this PR)

Main has failed this step since #22466 by @lawrencecchen (self-merged) (#22467). Merge main again once the fix lands there.

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 pull request macOS pool choice

Test: python3 tests/test_ci_pr_runner_pool.py

  • IOSWiring.test_test_ios_macos_jobs_take_the_runner_jobs_pool
AssertionError: "${{ inputs.runner || ((github.event_name[139 chars]) }}" != '${{ inputs.runner }}'
- ${{ inputs.runner || ((github.event_name == 'push' || (github.base_ref == 'feat-cmux-next' && github.event.pull_request.head.repo.full_name == github.repository)) && 'owned' || '') }}
+ ${{ inputs.runner }}

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 pull request macOS pool choice'

Validate every workflow guard is wired

Test: python3 tests/test_ci_workflow_guards_are_wired.py

  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_ci_cmux_tui_latest_acpmux.py
  tests/test_cmux_next_web_base_push.py
  tests/test_cmux_next_web_bundle_cache.py
  tests/test_cmux_tui_republish_same_commit.py
  tests/test_nightly_builder.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'

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

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

lucasr1b and others added 8 commits October 19, 2026 21:52
…eturns focus, transcript changes closes thread details, a cut folder says so, file.list stays in the chat folder, a fifo fails fast (red)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s show instead of passing silently, focus returns to the opener, every changes entrypoint closes thread details, a truncated folder says so, file.list is bound to the chat's real folder with symlinks resolved, readPath opens nonblocking and needs a regular file (review)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@lucasr1b lucasr1b changed the title cmux next chat: files and changes beside the chat (labs chatViewer) cmux next chat: files open on the right beside the chat (labs chatViewer) Oct 19, 2026
lucasr1b and others added 7 commits October 19, 2026 23:28
…y files use the viewer column (red)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ipt), only files and linked files use the column beside the chat

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mn (check-layers), format agentGitHost

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

cursor Bot commented Oct 19, 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.

@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.

@lucasr1b

Copy link
Copy Markdown
Collaborator Author

@greptile review

@greptile-apps

greptile-apps Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The changes affect file browsing and linked-file viewing within local chat sessions.

Fix Quick Chat's hidden file viewer before merging.

Findings

  1. P1 Quick Chat links do nothing ▶
  2. P2 Empty files fail to open ▶
  3. P2 PDFs show their source ▶

Summary

Adds a default-on chat viewer for Files and linked text files, backed by folder listing and checked file reads.

  • Local chats can browse folders and open files beside the conversation.
  • Reply path links can show text files in the chat viewer.
  • The in-chat viewer shares the right-side panel with Thread details.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[File link] --> B{Viewer registered?}
  B -->|No| C[Open through app]
  B -->|Yes| D[Check path and user gesture]
  D --> E{File content}
  E -->|Text| F[Chat file viewer]
  E -->|Detected binary| C
  E -->|Folder| G[Finder]
Loading

Reviews (1) · Last reviewed commit: "format the merged viewer dock condition" · Reviewed by Greptile

Comment on lines +3454 to +3457
if (!chatViewer) return undefined;
setPathViewer(viewFile);
return () => setPathViewer(undefined);
}, [chatViewer, viewFile]);

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.

P1 Quick Chat links do nothing

Quick Chat registers viewFile, but its early return renders only QuickSurface, never FileViewer. With chatViewer enabled by default, clicking a text-file link reads the file into hidden state instead of opening the app's file tab. Only register the viewer on surfaces that render it; keep link.openPath for Quick Chat.

Comment on lines +131 to +132
guard let read = try? handle.read(upToCount: Self.maximumBytes + 1) else { return nil }
let body = read ?? Data()

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 Empty files fail to open

FileHandle.read(upToCount:) returns nil at the end of an empty file. The guard let returns before read ?? Data() can turn that into empty content, so clicking an empty text file fails. Preserve a successful empty read as Data() and return nil only when the read throws.

bytes = max(size, body.count)
truncated = body.count > Self.maximumBytes
let kept = body.prefix(Self.maximumBytes)
text = kept.prefix(8192).contains(0) ? nil : String(decoding: kept, as: UTF8.self)

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 PDFs show their source

A NUL check alone does not identify all files that should open in a tab. A valid PDF with uncompressed, ASCII-only objects can contain no NUL bytes, so this code returns its PDF source as text and skips the existing PDF viewer. Check known image, PDF, and media types before treating the file as text, and add a PDF case to the fallback tests.

@lucasr1b

Copy link
Copy Markdown
Collaborator Author

@greptile review

1 similar comment
@lucasr1b

Copy link
Copy Markdown
Collaborator Author

@greptile review

lucasr1b added a commit that referenced this pull request Oct 20, 2026
… the files viewer joins the chat pr

conflicts: localizable.xcstrings (kept every key from both sides), markdown.tsx (kept the render engine's revealed and received-render blocks, added feat-cmux-next's away blocks and cached fence check). dropped an unused chatLook memo dependency.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@lucasr1b
lucasr1b merged commit b62d16b into next-chat-ui Oct 20, 2026
@lucasr1b
lucasr1b deleted the next-chat-viewer branch October 20, 2026 20:51
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