Repository navigation
ci(risk): an update channel setting is normal; the update path stays high - #23371
Conversation
…high Leo, after #22781: a settings-only channel toggle that reuses the signed feeds is not high-risk. UpdateTrack.swift and UpdatePreferences.swift (the channel and preference values) are now normal. Parsing, probing, installing and verifying an update stay high. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bf1-fdac-78a0-ac2e-a3aef81402c7&host=cosmic-gray
|
Owned by ci-speed on cosmic-gray · session |
|
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)
|
Review of #23371: UpdateTrack is the build's release line and decides whether Sparkle runs, so it stays high (now pinned by the test). The user's ring is UpdateRing in the CmuxUpdater package. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bf1-fdac-78a0-ac2e-a3aef81402c7&host=cosmic-gray
|
Review (independent subagent, correctness first): SHIP at 34b13f3. Nit carried forward: the high-table note in docs/ci/risk-tiers.md says "CmuxNextUpdater (except the channel and preference values below)" while UpdateRing.swift lives in CmuxUpdater; the bullet below names both paths correctly. This PR edits risk_tier.py, so it is risk:high and waits for a collaborator approval or risk:human-ok. |
|
Bead |
Signature verification, the feed resolver, the Sparkle driver and the install code graded normal because no high rule named the package. Only UpdateRing stays normal; each file is pinned by a test that fails on base. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bf1-fdac-78a0-ac2e-a3aef81402c7&host=cosmic-gray
|
Review (independent subagent, correctness first): SHIP at 0b7d7fe. All 44 non-test CmuxUpdater files except UpdateRing.swift grade high, its tests grade low, and nothing outside the updater changes tier. Nits, not fixed: docs/ci/risk-tiers.md says Package.resolved grades normal, but CmuxUpdater/Package.resolved (the Sparkle pin) now grades high, which is intended. UpdateRing.acceptedSparkleChannels grading normal follows the requested channel decision. risk:high: this waits for a collaborator approval or risk:human-ok. |
|
Review (independent subagent): SHIP at 0b7d7fe |
|
Found 1 test failure on Blacksmith runners: Failure
|
|
Review (independent subagent, correctness first): SHIP at b75370c Re-review of the feat merge into the reviewed 0b7d7fe: same changed lines (3 files, +57/-3); feat has no commits to risk_tier.py, test_risk_tier.py or risk-tiers.md since the old base; tests/test_risk_tier.py 31 OK at the merged head (huge-blue). The fast-tier red (run 39597903330: PaletteMenuVocabularyTests.swift #expect without try) is in a file this PR does not touch. |
|
Shipped in:
|
… read or a pending compile warns and merges (#24265) * merge-compile-guard tests: only a compile that finished red refuses (red) The guard's GitHub reads timed out under load on cosmic-gray and refused #23660 and #23371 for hours with a SHIP receipt at the head and a green compile. These tests expect a pending compile, an unreadable GitHub, a merge the guard can't name and guards it can't load to warn and let the merge through. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a1602e-bc09-7990-8c75-5c412a66b114&host=Air-Blue * merge-compile-guard: only a compile that finished red refuses; the rest warns and merges Under load on cosmic-gray (2026-10-21) the guard's GitHub reads timed out and refused #23660 and #23371 for hours with a SHIP receipt at the head and a green compile. Leo: "IF THE MERGE HOOK IS WRONG THEN JUST FUCKING MERGE". HQ's landing gate (require-cmux-guards.py, cmuxterm-hq#2976) already refuses only a missing SHIP, a failed compile, --admin and an unpinned --auto; this repo hook now agrees with it. - A compile still waiting, a GitHub read that failed or ran out of time, a merge the guard can't name and a checkout it can't read are a Hold: a systemMessage plus additionalContext, no permissionDecision, and the merge goes ahead. - A red compile still refuses, and a Hold earlier in the command never hides a red later in it. - guards-from-base.sh and the settings hook warn instead of refusing when they can't load the guards from the base. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a1602e-bc09-7990-8c75-5c412a66b114&host=Air-Blue * merge-compile-guard tests: a red fleet compile, a crashing guard and a hidden update-branch warning (red) From the Codex review of #24265: a failed build-fleet compile next to a queued Release compile read as a wait; a guard exiting 2 blocks the tool call; a merge warning short-circuited the update-branch warning. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a1602e-bc09-7990-8c75-5c412a66b114&host=Air-Blue * merge-compile-guard: a red fleet compile refuses beside a queued Release compile; a guard's failure and a merge warning never block or hide From the Codex review of #24265: - fleet_red(): a build-fleet compile that finished red with no passing attempt (of it or of the Release compile) refuses before any pending state, and compile_wait() no longer reads it as a wait, so neither a queued Release compile nor a fleet pass turns it into a warning. - guards-from-base.sh runs both guards. A refusal is the answer at once; otherwise every warning is joined into one answer, so a merge's warning never hides the update-branch warning of the same command. A guard that exits non-zero is a warning, never the exit 2 that blocks a tool call. - The settings hook exits 1 (a non-blocking error) when the launcher itself fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a1602e-bc09-7990-8c75-5c412a66b114&host=Air-Blue * guards-from-base tests: a refusal in any JSON spacing still refuses (red) Codex review of #24265, round 2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a1602e-bc09-7990-8c75-5c412a66b114&host=Air-Blue * guards-from-base: read a guard's refusal as JSON, not as text The loop matched "permissionDecision": "deny" literally, so a valid refusal written with other spacing was merged into a warning and lost (Codex review of #24265, round 2). The merger now parses each answer and passes a refusal through as it is before joining warnings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a1602e-bc09-7990-8c75-5c412a66b114&host=Air-Blue * guards-from-base tests: a refusal never waits for the next guard (red) Codex review of #24265, round 3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a1602e-bc09-7990-8c75-5c412a66b114&host=Air-Blue * guards-from-base: a guard's refusal is the answer the moment it is given Both guards ran before any refusal was read, so a slow update-branch warning could run the hook past its 120 s timeout with the refusal unprinted, and the merge went through (Codex review of #24265, round 3). Each answer is read as JSON right after its guard; a refusal is printed and the loop ends. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a1602e-bc09-7990-8c75-5c412a66b114&host=Air-Blue --------- 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)
Summary
Asked by claude-sr2 (relayed by held-queue triage), 2026-10-21. Leo approved #22781 after the fact and said that update-channel and dev-build settings changes like it do not feel high-risk to him. The decision: keep the updater's install, signing and feed-verification code at risk:high, and let a settings-only channel toggle that reuses the existing signed feeds be normal. The gate has no "medium" tier; normal is the middle tier.
scripts/ci/risk_tier.pynow has a normal rule, ahead of the high update-path rule, for the two files that only hold the channel and preference values:CmuxUpdater/UpdateRing.swift: the user's ring, theupdates.channelsetting (Stable, Nightly, Canary or Dev) and the Sparkle channels each ring accepts;CmuxNextUpdater/UpdatePreferences.swift: install-on-quit, how to notify, how many versions to keep.Every other updater code file stays high (the updater's views, share sheet and strings were already normal or low and are unchanged), including:
UpdateTrack.swift, the build's own release line, which also decides whether Sparkle runs at all;AppcastParser,AppcastSelector,UpdateProberandUpdaterService+Flow;UpdateInstallPreflight,RollbackSwapandUpdateTransfer.The settings schema and
CmuxNextSettingswere already normal or low.docs/ci/risk-tiers.mdrecords the distinction.#22781 itself would still grade high, since it also changed the appcast parser and the prober.
The
CmuxUpdaterpackage is now high too (coord-deputy, 2026-10-21: in this PR, so the risk gate changes once). Before this PR no high rule coveredPackages/macOS/CmuxUpdater/, so these files graded normal:AppSignatureVerificationandSecurityAppSignatureInspector;UpdateFeedResolver;UpdateDriver*);UpdateController+InstallAttempt,+BackgroundInstall,InstallWatchdog).The high update-path rule now includes
Packages/macOS/CmuxUpdater/*.UpdateRing.swiftstays normal, because the channel rule sits above it, and the package'sTests/stay low.Nothing else changes: no other path changes tier.
Testing
python3 tests/test_risk_tier.pyon huge-blue: 31 tests OK. On the baserisk_tier.py, both new tests fail (12 failures).test_an_update_channel_setting_is_normal_and_the_update_path_stays_highchecks two things:UpdateTrack.swiftamong them) grades it high.test_the_cmux_updater_package_is_the_update_pathchecks that each of these grades high on its own: the signature check, the signature inspector, the channel switcher, the feed resolver, the three Sparkle driver files, the two install-attempt files,InstallWatchdogandPackage.swift. It also checks thatUpdateRing.swiftis normal and that the package's tests are low.Observed / Not run
Observed: the test runs above, and
prepush-gate.pywith no new violations. Not run: the risk-tier workflow on a real channel-only PR.Changelog
none
Agent session: cosmic-gray
🤖 Generated with Claude Code