Repository navigation
webviews: bun run check runs every piece and fails at the end - #24438
Conversation
A red text-focus guard (AddDeviceView.swift:164, 2026-10-22) stopped the `&&` chain, so fmt, lint and the type check never ran in a local `bun run check`, the web-bundles dispatch or iroh-v2. The chain moves to `check:pieces`; `check` runs scripts/cmux-next/run-check-pieces.py, which runs each piece, prints every red one and exits 1. ci-web and the pre-push lint already ran the pieces one by one and now read them from `check:pieces`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a1603a-6462-72f0-a4b0-6937eb58e4c3&host=cosmic-gray
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Unclear: CI failed on
Not re-run automatically: Written by red: cmux-next checks (god files, concurrency, crash safety, l10n); no finished base run on e7ab659 to compare; do not merge until green; see lane-rules Gallery before/after for
States
Pick other states with a |
|
Found 7 test failures on Blacksmith runners: Failures
|
|
|
|
|
|
Bead |
Review finding (codex xhigh): a change to run-check-pieces.py on feat-cmux-next after a PR's fast-gates base would not mark that result stale. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a1603a-6462-72f0-a4b0-6937eb58e4c3&host=cosmic-gray
|
Review (codex xhigh): SHIP at a583efc Round 1 (codex xhigh, at c717727) said BLOCK: scripts/cmux-next/run-check-pieces.py wasn't in scripts/ci/check-paths.txt, so a later runner change would not mark a PR's fast-gates result stale. That's fixed at a583efc, and round 2 found nothing else. |
|
Orphaned: no activity for 70 h, and no lane holds a lease on it. The orphan sweep could not merge |
|
Overlap coordination for #24438: #25548 also touches |
|
Review (codex gpt-6-astra xhigh, next-review): SHIP at e029ede No blocking findings. |
…eck-runs-every-piece # Conflicts: # webviews/package.json
|
Owned by an agent session · session |
|
Review (codex gpt-6-astra high, fast, review-router; drain-other): SHIP at 9511e33 No blocking findings. |
… NAME:pieces Since #24438 webviews' check is run-check-pieces.py over check:pieces. check_pieces() already reads SCRIPT:pieces; light_leaves() now does the same for `bun run NAME`, so a nested runner is never run whole as one (light-looking) python3 command. Tests: a heavy=0 push with the runner-shaped check runs only the allowlisted pieces, and a nested runner resolves to its pieces. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3aa8a14a36831eaec813
|
Shipped in:
|
|
Shipped in:
|
… CI (#27177) * web-lint: hosts that run no heavy checks leave the type-aware lint to CI The pre-push web lint runs webviews' whole `check` script, whose `vp lint` and `vp check` start tsgolint (about 9 GB and 5 GB, both at once). On shared agent hosts that run no builds, that filled swap. A host that sets CMUX_LOCAL_HEAVY_CHECKS=0 now runs every other piece locally and leaves the heavy ones to CI's web lint job and the pull request's fast gates, saying so and naming cmux-ci test for a pre-push run. Wherever a heavy piece does run outside CI, it runs under nice with GOMAXPROCS, GOMEMLIMIT and Node's heap capped, each only when the caller set none. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-7a592ef92c66f080e3cc * web-lint: no install or build on a host that runs no heavy checks Review of 6160990: with CMUX_LOCAL_HEAVY_CHECKS=0 the tui bindings were still installed and built (npm ci, npm run build: tsc) before the check pieces were filtered. Now such a host installs and builds nothing: light pieces run against the node_modules a package already has, and a package with none is left to CI with a named note. Regression test: a cmux-tui/frontends/web change with CMUX_LOCAL_HEAVY_CHECKS=0 spawns no npm, bun install, build, tsc or vp; it fails on 6160990 (npm ci and npm run build ran). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-7a592ef92c66f080e3cc * web-lint: cap the bindings build and the --new-only rerun; no base install without heavy checks Review of 5c38839: - the tui bindings build (npm ci, tsc) runs niced and capped outside CI, like the type check; - --new-only reruns a failed piece on the base through the same niced, capped job; - with CMUX_LOCAL_HEAVY_CHECKS=0, --new-only installs nothing in the base tree (no node_modules there: the red stays the change's), and a lint tree shares the checkout's node_modules for packages with local builds too, since nothing is built. Four regression tests; each fails on 5c38839. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-7a592ef92c66f080e3cc * web-lint: an allowlist on hosts that run no heavy checks; one capped spawn for everything Five review rounds each found another path that still ran something heavy with CMUX_LOCAL_HEAVY_CHECKS=0, so the denylist is gone. Such a host now runs only LIGHT_COMMANDS: `vp fmt --check`, python3 source checks, and `bun scripts/<name>.ts` source checks. `bun run NAME` is resolved to NAME's pieces and only the allowlisted ones run, so check:effect-cleanup's `vp lint` is skipped. ESLint runs on changed web/ files (syntax only). It does no install, no build and no --new-only base comparison; every other piece, and a package with no node_modules, is named and left to CI or cmux-ci. Every tool this script starts (installs, builds, checks, base reruns) goes through spawn(), which outside CI runs it under nice with GOMAXPROCS, GOMEMLIMIT and Node's heap capped. Tests: with heavy=0, a subprocess spy sees only allowlisted commands across --head, a lint tree (another commit), --new-only, --all and --fix. On a build host every spawn is niced and capped. The allowlist is checked exactly. Each new test fails on f9399db. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-7a592ef92c66f080e3cc * web-lint: allowlisted pieces run as argv with no shell; shell syntax is never light Review of 5a4516a: an allowlisted prefix could carry another command (`python3 noop.py ; vp lint` ran the lint with CMUX_LOCAL_HEAVY_CHECKS=0), because accepted strings ran with shell=True. Now a piece holding any shell syntax (; | & $ backticks redirections globs quotes escapes newlines) is never light. An allowlisted piece is parsed with shlex.split, checked as an argv, and run as that argv with shell=False. Tests cover ;, &&, ||, |, &, $(...), backticks, newlines and the reviewer's repro through the full main(), and assert no light piece spawns through a shell; each fails on 5a4516a. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-7a592ef92c66f080e3cc * web-lint: nice the shell itself, not the first word of a shell string Review of 5eb2e77: `nice -n 10 CHECK_MODE=1 python3 check.py` ran CHECK_MODE=1 as the program (exit 127), and `nice -n 10 true; python3 x.py` niced only `true`. A shell string now runs as `nice -n 10 /bin/sh -c STRING`, so assignments and every command of a compound string keep their meaning and their priority. Regression test fails on 5eb2e77. The bindings-build test now clears CI and GITHUB_ACTIONS itself, since it asserts outside-CI behaviour (it failed on the CI runner). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-7a592ef92c66f080e3cc * web-lint: python3 and bun are light only for a guarded source-check script Review of 3811e05: any shell-free `python3 ...` counted as light, so `python3 -m pip install ..`, `python3 -m compileall` or a bare `python3` ran with CMUX_LOCAL_HEAVY_CHECKS=0. Now the allowlist is `vp fmt --check` exactly, plus `python3 [-I] PATH.py ARGS` or `bun PATH.ts ARGS`, where PATH resolves (relative to the package, no escape) into a scripts/ folder under one of the package's `executed` paths, which the hook already refuses to lint when a push changes them. No -m, -c, other flags, absolute paths or bare interpreter. webviews' real checks all still qualify. On 3811e05, is_light("python3 -m pip install requests") is True; the new test fails there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-7a592ef92c66f080e3cc * web-lint: --dry-run lists exactly the commands a run spawns Review of 91644bb: with CMUX_LOCAL_HEAVY_CHECKS=0 the dry run skipped light_plan(), so it listed packages and ESLint areas a run drops for having no node_modules. A run and a dry run now build their commands with one function, check_jobs(), over the same light_plan(): the dry run checks the node_modules the run would see (in a lint tree only where shares_deps() holds). It prints one `<area>: <command>` line per command. A new test runs both in light mode, on the checked-out head and on another commit, and requires the dry run's list to equal the spawned list. It fails on 91644bb. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-7a592ef92c66f080e3cc * web-lint: one plan_steps() for a run and its dry run, setup and fix passes included Review of 7d129c5: `--dry-run --fix` left out the check:fix and ESLint --fix passes a run makes first, and in full mode it summarised builds and installs as one line. plan_steps() now returns everything a run does, in order: the plan (light_plan()'s with heavy checks off), the setup steps (setup_steps(): the builds that are not current and each area's install, from the same deps_command() and build_commands() ensure_deps and ensure_build run), the fix jobs and the check jobs. run_plan() executes it and --dry-run prints it one command per line, so the two can't drift. ensure_build decides "current" with the same build_current() setup_steps() uses. Test: table-driven over {light, full} x {fix, no fix} x {checked-out head, lint tree} (6 cells, --fix never runs in a lint tree). In every cell the dry run's lines equal the commands the run spawns: builds and fix passes match line for line, installs and checks (which run in parallel) match as sets, and the phases come in the run's order. On 7d129c5 the --fix cell fails because its fix lines are missing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-7a592ef92c66f080e3cc * web-lint: a light script is one the hook refuses to lint when a push changes it Review of bead8b5: light_script() accepted a scripts/ folder under the package's src/, test/ or tests/, which executed_changes() treats as source a push may change and still be linted, so `bun src/scripts/evil.ts` in a check script would have run a pushed change with CMUX_LOCAL_HEAVY_CHECKS=0. light_script() now asks executed_changes() itself: only a path the hook refuses to lint when a push changes it can be light. Tests: the src/, test/ and tests/ forms are refused (they fail on bead8b5), and every light script of both packages is one make_plan() marks untrusted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-7a592ef92c66f080e3cc * web-lint: a dry run plans the tree the run happens in A dry run of a commit that runs in a fresh lint tree read the checkout's build stamps and node_modules, so it listed only the check while the run built the bindings and installed the frontend first. setup_steps() and plan_steps() now take a TreeState: the checkout as it is, or the lint tree tree_of() makes (no build output, node_modules only where it links the checkout's). Test: TuiBindingsTests.test_a_dry_run_for_a_lint_tree_lists_the_builds_and_installs_that_tree_needs fails on c146f28 (dry run lists only `sh check.sh`) and passes here; tests/test_web_lint_prepush.py: 48 tests OK. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-a7306ef145c005ad24ab * web lint prepush: a light host resolves a nested check runner through NAME:pieces Since #24438 webviews' check is run-check-pieces.py over check:pieces. check_pieces() already reads SCRIPT:pieces; light_leaves() now does the same for `bun run NAME`, so a nested runner is never run whole as one (light-looking) python3 command. Tests: a heavy=0 push with the runner-shaped check runs only the allowlisted pieces, and a nested runner resolves to its pieces. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3aa8a14a36831eaec813 * web lint prepush: CI always runs every piece; accept a bun on a relative PATH entry Review of 014ded9: CMUX_LOCAL_HEAVY_CHECKS=0 inherited by a CI runner made CI run only the light allowlist. CI (CI or GITHUB_ACTIONS=true) now wins over the host setting. ensure_deps() refused any bun that shutil.which() found through a relative PATH entry (node_modules/.bin/bun) as "bun is not on PATH"; it now refuses only when which() finds none. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3aa8a14a36831eaec813 * web lint prepush: a stale build with no build tool always stops the run Review of 9fee512: run_plan() ran prepare_builds() only when setup_steps() listed a spawn. With neither npm nor bun, a stale bindings build spawns nothing, and a frontend with node_modules and no bun.lock installs nothing, so the frontend check ran against the old bindings. With heavy checks on, run_plan() now always goes through prepare_builds() (ensure_build's failure surfaces), and setup_steps()/plan_steps() list that refusal and no checks after it, so --dry-run matches the run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3aa8a14a36831eaec813 * tests: light-host web lint tests clear CI and GITHUB_ACTIONS CI now always runs every piece (CI or GITHUB_ACTIONS=true wins over CMUX_LOCAL_HEAVY_CHECKS=0), so the bindings tests that mean "a host with no heavy checks, outside CI" inherited the runner's GITHUB_ACTIONS=true and ran the full install and build on CI. They now pass LIGHT_HOST, which clears both. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3aa8a14a36831eaec813 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
bun run checkin webviews was one&&chain. Today a red text-focus guard (AddDeviceView.swift:164, from 1e6efa8) stops it, so fmt, lint and the type check never run. That affects a localbun run check(which CLAUDE.md tells every agent to run before pushing), the web-bundles dispatch and iroh-v2. The AddDeviceView fix itself is a separate fix-forward owned by land-and-ci; this PR makes sure no single guard can hide the rest again.check:pieces.checkrunsscripts/cmux-next/run-check-pieces.py, which runs every piece withnode_modules/.binon PATH, prints each one's output under a==> pieceheader, lists every red piece at the end and exits 1 if any failed.webviews-checkstep (the non-warn branch) and the pre-push lint (web_lint_prepush.check_pieces) already ran the pieces one by one. They now read them fromcheck:pieces, falling back tocheckfor packages without one (cmux-tui/frontends/web).checknow readcheck:piecesthe same way:test_every_part_of_bun_run_check_runs_in_the_warn_branchandtest_format_never_hides_lint_or_type_errors.Changelog
none
Testing
CheckPiecesTestsin tests/test_web_lint_prepush.py.checkruns the runner, andcheck:piecesstill has text-focus, fmt, lint and the type check.check:pieces, withcheckas the fallback.Observed / Not run
tests/test_web_lint_prepush.py32 OK.test_cmux_next_fast_gatesOK.test_cmux_next_checks_workflow.py: the check-pieces test passes; 14 PushPreflight and SwiftCanary tests fail the same way on base.actionlint ci-web.ymlclean.prepush-gate.py: no new violations.bun run checkin webviews on this Mac; CI's react-apps-check runs it.Risk: normal (CI and lint tooling; no app code).
Agent session: cosmic-gray
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
bun run checkin webviews no longer stops at the first red guard; it runs every piece and fails at the end, listing all red pieces.Refactors
&&chain moves tocheck:pieces;checkrunsrun-check-pieces.py.webviews-checkstep and the pre-push lint read their piece lists fromcheck:pieces, falling back tocheck.Written for commit 9511e33. Summary will update on new commits.