Repository navigation
ci(cmux-next): the DEV compile can record the fleet whole-app build's REF (off by default) - #25740
Conversation
… REF (off by default) The Linux Darling build of the cmux NEXT DEV app plans its Swift compiles and links from the rules of one real Mac build of the same shape (its REF). The only REF was assembled by hand from a 10-18 nightly build, and the Linux path stopped as soon as Package.resolved moved. With CMUX_NEXT_HYBRID_REF_CAPTURE=1 the per-landing DEV compile records one, on a mini in host mode, when its REF key (Package.resolved, cmux.xcodeproj, the macOS xcconfigs, the DEV build settings, the toolchain) has no complete capture yet: - a decide step before the compile turns on EMIT_FRONTEND_COMMAND_LINES=YES for that compile only (the one added xcodebuild setting); - a last step, continue-on-error with a 20 minute timeout, checks that every SwiftDriver module has a frontend compile line (else the capture is incomplete and uploads nothing), packs the log, XCBuildData, DerivedData without objects or the cache and the workspace, and puts them in the build fleet's private store (cmux-ci artifact-put); the manifest artifact names sizes and digests only; - the compiled-out browser sources now come from one file both the compile and the capture read. No new permission: the decide step reads artifacts with the job's actions: read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c1e0761c3d79f629ab33
Review (cmux#25740 at 17829d4): the capture read the shared host tree and DerivedData after compile-dev-release.sh had released the host lock, so another runner on that Mac could replace them first. With the capture on, the script now clones both (one clonefile(2) each, about a second) into RUNNER_TEMP while it still holds the lock; the capture reads that snapshot, records the build's own paths, and removes it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c1e0761c3d79f629ab33
|
Found 7 test failures on Blacksmith runners: Failures
|
|
Bead |
|
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)
red: cmux-next checks (god files, concurrency, crash safety, l10n); no finished base run on 2d14c08 to compare; do not merge until green; see lane-rules |
|
|
…ey on manifests and the recipe Review (cmux#25740 at e459de9): - The capture holds the push compile slot inside a 60 minute job: it now starts only while the job is under 30 minutes and stops after 10, and the decide step has 1 minute. A skipped capture is taken by the next landing with that key. - A capture counts only while its packs are readable: unexpired artifacts from the last 13 days (the store keeps packs 14 days), and the manifest keeps 14 days instead of 90. - The key also covers the local macOS and shared package manifests and the compile recipe (check-cmux-scheme-compile.sh, compile-dev-release.sh, lib/compilation-cache.sh), which set build lines too. - The DerivedData pack leaves out .git in SourcePackages checkouts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c1e0761c3d79f629ab33
Review (cmux#25740 at 75640f8): the 30 minute guard counted from the decide step, which runs after checkout, the web bundles and the Debug compile, so a capture could still start near the job's 60 minute limit. The capture step now reads this job's started_at from the run's jobs (its runner, in progress) and starts only under 40 minutes; an unknown start skips it. The capture has 8 minutes and the manifest upload 2, so both end by minute 50. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c1e0761c3d79f629ab33
…ument list and toolchain - The decide step no longer tests the product lookup's hit: test_dev_release_product_reuse.py allows that only for steps a dev_daily run skips, and a reused product compiles nothing, so the capture step finds no build mode and skips anyway. - The manifest adds xcodebuild_args (the wrapper's shell-quoted line split, so OTHER_SWIFT_FLAGS=... stays one argument, as the Linux DEV planner reads it) and toolchain (Xcode version and build, developer dir, SDK build). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c1e0761c3d79f629ab33
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c1e0761c3d79f629ab33
|
Shipped in:
|
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Lets the per-landing Mac DEV Release compile record the fleet whole-app build's REF. The REF is the stored rules of one real Mac build of the same shape, which the fleet build plans its Swift compiles and links from. This is off by default, behind the repository variable
CMUX_NEXT_HYBRID_REF_CAPTURE=1.Leo, 2026-10-26: "but we have the fleet... why are we STILL TALKING ABOUT BLACKSMITH MACOS"
The only REF today (hybrid-11) was assembled by hand from a 2026-10-18 nightly build. The fleet path refuses the current tip because Package.resolved has since gained swift-atomics. The DEV app also has its own build shape, so it needs its own REF:
cmux;DEBUG_INFORMATION_FORMAT=dwarf;This change records one from the DEV compile itself, at the paths every mini shares in host mode. The private HQ side assembles the pack from it.
Change
Decide step (before the compile;
continue-on-error, 2 min timeout). It runs on a mini, with the variable on, and only when the compile isn't reused. It computesscripts/cmux-next/hybrid_ref_capture.py key, a sha256 over:check-cmux-scheme-compile.sh,compile-dev-release.sh,lib/compilation-cache.sh);xcodebuild -versionand the SDK build.It then looks for an unexpired artifact named
hybrid-ref-capture-<key>from the last 13 days, using the job's existingactions: read. The store keeps packs 14 days and the manifest keeps the same 14. If there is none, it setscapture=true. In the last 48 h, 18 of 887 feat-cmux-next landings changed these inputs, so almost every landing skips the capture.The compile. When
capture=true,check-cmux-scheme-compile.shaddsEMIT_FRONTEND_COMMAND_LINES=YES, the only added xcodebuild setting. Measured on the nightly shape (HQ HYBRID.md section 9), it changed no output: 5767 of 5767.oand 176 of 176.swiftmodulewere identical with and without it.compile-dev-release.shalso writesbuild_mode,build_rootandderived_datato the step outputs.Capture step (the last step of the job;
continue-on-error, 10 min timeout). It runs only after a successful host-mode compile, from a snapshotcompile-dev-release.shcloned while it still held the host lock (oneclonefile(2)each for the tree and DerivedData), and only while the job is under 30 minutes, so it cannot reach the job's 60-minute limit.missing: [...]) and nothing is uploaded.cmux-ci artifact-put --lane hybrid-ref-dev.hybrid-ref-capture-<key>, or...-incomplete-<run>for an incomplete capture. It holds only names, sizes, sha256, paths and settings. No file content goes to this public repository.Shared constant. The compiled-out
browser-sources.jsonnow comes fromscripts/cmux-next/lib/browser-sources-compiled-out.json, read by both the compile and the capture, with byte-identical content (scheme-compile-browser-import.test.shchecks the bytes).Settings. The decide and capture steps get the compile's settings as one
HYBRID_REF_SETTINGSblock, so only the compile step carriesCMUX_NEXT_BROWSER_DATA_IMPORT(test_cmux_next_dev_release_import_out.py). A test keeps the block equal to the compile step's env.Tests
tests/test_cmux_next_hybrid_ref_capture.py(checks group and the linux-guard lane) checks:continue-on-errorwith a timeout, capture after the compile on host mode only, only the EMIT setting added, and no permission change.Also passing:
test_cmux_next_dev_release_import_out.py,test_cmux_next_checks_workflow.py,test_cmux_next_dev_release_host_root.py,scheme-compile-browser-import.test.sh.Risk and what is not measured yet
cmux-cicall on a mini does.Agent session: agent session
🤖 Generated with Claude Code