NEXT: check:attachment-caps catches count caps too, and a Swift test drives the real upload limits
Leo, 2026-10-26: "why the F*** SHOULD THERE BE A F***ING SIZE CAP ANYWAYS ... I ALREADY SAID WE NEED ARBITARRILY LARGE FILES OF ANY TYPE" (standing order: "Attachments take arbitrarily large files of any type; there is no size cap"). This is item 4 of the pattern audit. The only attachment test drove a stand-in host, so the app's own limits were never exercised, and nothing kept a new cap from coming back.
What changes
check:attachment-caps in bun run check (warning tier). scripts/cmux-next/check-attachment-caps.py from #26409 now also catches count caps:
- names like
MAX_ATTACHMENTS,MAX_*_FILES,MAX_UPLOADSandmaxAttachments/maximumFiles. In attachment and upload paths it flags every such name. Elsewhere it flags only names about attachments or uploads, so a diff's or a git listing's file limit isn't flagged. - literal count comparisons on files, attachments, batches or manifests in attachment and upload paths (
files.length > 10,list.count <= 64). cap-allow: routein a comment on the line, or on the line above, marks a comparison that only picks a route (one message or several, inline or staged).
webviews/package.json runs it as check:attachment-caps with --warn: each finding becomes a ::warning annotation and the exit is 0, because style and size checks warn and never fail. Without --warn it exits 1, which is what tests/test_attachment_caps_guard.py uses.
The open count caps the guard finds outside chat and Home are listed by exact path and symbol, so a new one still warns. They are follow-ups, not permission:
- the Chief's send tool takes 10 attachments (
MAX_SEND_ATTACHMENTS, chief-kernel); - the hosted Chief brain reads the 12 newest files of a turn (
chief-brain-cc/attachments.ts); - the Cloud upload CLI takes 64 files a call (
access_cli/uploads.rs, with its size cap in #27016).
Three are listed because they aren't admission caps: MAX_UPLOADS (uploads open at once; more wait their turn), and a checklist item's links.
A Swift test against the app's real limits. CmuxNextAppTests/AttachmentRealLimitsTests sends chat.upload.* through the production decoder (AgentPaneRequest(body:)) into the stager the app composes for the tab (AgentTabs.uploadStager, wired by AppActions.bind), for a chat on this Mac. Nothing is stood in. It covers:
- a begin for a file over 4 GiB, and its first chunk;
- a batch of 65 files, each staged, written and finished at its own path with its own bytes;
- a batch naming 65 files over 4 GiB each.
Red / green
| check | red: the test alone on base c47981d25d17 (4d2dbf9b21d5) | green 4779113e4a6c |
|---|---|---|
AttachmentRealLimitsTests (fleet Mac, Xcode 26.6) | 3/3 fail: the decoder refuses the 4 GiB begin and both 65-file batches (decoded(...) ā nil), step 25f96c97b50284c316e17d06 | pending (comment below) |
tests/test_attachment_caps_guard.py | n/a | 18/19 pass; the tree scan reports Home's MAX_ATTACHMENTS (5 lines), which #27183 removes |
No capture: this adds a lint and tests; nothing on screen changes.
š¤ Generated with Claude Code
Agent session: agent session
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Removes the native staged upload caps (1 GiB per file, 64 files per batch, and the mobile 8 MiB image cap) so attachments accept arbitrarily large files in any number, and extends the check:attachment-caps guard to flag count caps alongside size caps. The AgentPaneDraftAttachments maximumBytes exception is dropped because that cap no longer exists.
check:attachment-capsruns inbun run checkand the CI web workflow at warning tier (::warningannotations, exit 0); without--warna finding exits 1.- The guard flags count cap names like
MAX_ATTACHMENTSanywhere, and literal comparisons likefiles.length > 10orlist.count <= 64only in attachment/upload paths; acap-allow: routemarker exempts comparisons that only pick a route. AttachmentRealLimitsTestsdrives the production decoder and the app-composed stager on a local chat: a begin for a file over 4 GiB plus its first chunk, a 65-file batch staged and finished at distinct paths, and a batch naming 65 files over 4 GiB each. The suite keeps one app instance with a tab and session per test.- The remaining count caps outside chat and Home (the Chief send tool at 10, the Chief brain at 12, the Cloud CLI at 64) are listed by path and symbol as follow-ups, not permission.