Skip to content

base red: acpmux process pages and retry delays without an index (panic ratchet 697 > 686, #30726, #31709) - #31773

Merged
lawrencecchen merged 4 commits into
feat-cmux-nextfrom
base-red/acpmux-process-pages-index
Nov 2, 2026
Merged

lawrencecchen merged 4 commits into
feat-cmux-nextfrom
base-red/acpmux-process-pages-index

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Culprit: #30726 (fbaa7a5, Leo), "feat(acpmux): byte-bound background-process history with opt-in pages (SW-11)". It added ten clippy::indexing_slicing hits in cmux-tui/crates/acpmux/src/hub/processes.rs:

  • self.processes[start..end] in ProcessTable::page_snapshot (line 327).
  • Nine serde_json indexes row["..."] in the too-large row of process_page_values (lines 384-388).

The Rust panic ratchet is red on feat-cmux-next: acpmux 697 > baseline 686 at 7da73fe (hq run 41384159581), and 696 after #31695 removed the #30712 hit. The broken Cargo.lock from #31462 hid this red until #31717.

This PR:

  • reads the window with self.processes.get(start..end).unwrap_or_default(). start is an ID's slot + 1 (at most len) or 0, and end = min(start + limit, len), so the range is always in bounds and the fallback never applies.
  • reads the row fields with row.get(..). An Option<&Value> serializes None as null, the same as an index on a missing key, so the reply does not change.

It also fixes one more hit that came on the tip after #31695: #31709 (030cb46, Leo, "Settings > Retry After Errors sets acpmux's retry loop") added DEFAULT_DELAYS_MS[n.min(DEFAULT_DELAYS_MS.len() - 1)] in hub/auto_resume/settings.rs. It now reads DEFAULT_DELAYS_MS.get(n).or(DEFAULT_DELAYS_MS.last()): past the defaults the last wait repeats, as before. The array is a non-empty const ([u64; 4]), so the MIN_DELAY_MS fallback never applies.

No baseline change and no allow.

Testing

Focused command (fleet, Linux route): cmux-ci run --class light --script scripts/ci/cmux-tui-rust-check.sh --arg panic --os linux --ref <sha>.

Observed / Not run

  • Observed: the fleet logs above. prepush-gate.py: no new violations. rustfmt --check on the file: clean.
  • Not run: no local cargo build, clippy or test (fleet only). I did not drive _acpmux/process/list pages or the retry settings by hand.

Changelog

none

Related: #31697 (Linux clippy fix for #31462's plugin_manager.rs). The two fixes are independent: each step fails on its own, and neither step needs the other fix to run.

…het indexing_slicing 696 > 686, #30726)

#30726 (fbaa7a5, "byte-bound background-process history with opt-in pages")
added ten clippy::indexing_slicing hits in acpmux hub/processes.rs: the page
window self.processes[start..end] in ProcessTable::page_snapshot and nine
serde_json indexes row["..."] in the too-large row of process_page_values.
With #31695 merged, acpmux is 696 > baseline 686, so the Rust panic ratchet
is red on feat-cmux-next.

The window is now processes.get(start..end): start is an ID's slot + 1 (at most
len) and end = min(start + limit, len), so the range is always in bounds and the
fallback never applies. The row fields use row.get(..), which serializes a
missing field as null, the same as an index on a missing key. The output does
not change. No baseline change and no allow.

Fleet panic step: RED at tip 7da73fe (indexing_slicing 697 > 686, hq run
41384159581) and at 4a94625 with the get_mut fix (696 > 686, hq run
41384159646, hits at processes.rs:327 and 384-388).
@lawrencecchen lawrencecchen added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Nov 2, 2026
@github-actions

github-actions Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review d561fd2: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr31773 -f ref=base-red/acpmux-process-pages-index -f platform=macos -f backend_mode=local

web and size checks: green

Shipped in:

@blacksmith-sh

blacksmith-sh Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Found 4 test failures on Blacksmith runners:

Failures

Test View Logs
main.DeveloperIdAppTests.test_download_prints_the_active_profile_only/
test_download_prints_the_active_profile_only
View Logs
stubs: /System/Library/Frameworks/Security.framework/Versions/A/Security has no stub/
Security has no stub
View Logs
stubs: CoreFoundation.tbd: install-name /System/Library/Frameworks/
CoreFoundation.framework/Versions/A/CoreFoundation, missing 1: ['_CFRetain']/
CoreFoundation, missing 1: ['_CFRetain']
View Logs
stubs: CoreFoundation.tbd: install-name /System/Library/Frameworks/
CoreFoundation.framework/Versions/A/CoreFoundation, missing 1: ['_log2']/
CoreFoundation, missing 1: ['_log2']
View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

… (panic ratchet, #31709)

#31709 (030cb46, "Settings > Retry After Errors sets acpmux's retry loop")
added DEFAULT_DELAYS_MS[n.min(DEFAULT_DELAYS_MS.len() - 1)] in
hub/auto_resume/settings.rs, one more clippy::indexing_slicing hit in acpmux.
With the #30726 hits fixed, acpmux is still 687 > 686 (hq run 41386195677).

get(n), else last(), is the same wait: past the defaults the last one repeats.
The array is a non-empty const, so the MIN_DELAY_MS fallback never applies.
lawrencecchen added a commit that referenced this pull request Nov 2, 2026
clippy -D warnings (2e0f23045b77e7d0788701b3) refused an unneeded
`crate::json::` path in ffi_tests.rs; the panic ratchet
(ef9f5b7e0893ccd47e3cfc62) counted one cast_possible_truncation in the
new crate (available_parallelism as u32), now a checked conversion.
The two other reds of those runs are base reds with open fixes:
cmux-tui plugin_manager.rs suspicious_open_options (#31697) and acpmux
indexing_slicing 697 > 686 (#31773); this branch adds no acpmux hit.
@lawrencecchen lawrencecchen changed the title base red: acpmux process pages read rows without an index (panic ratchet 696 > 686, #30726) base red: acpmux process pages and retry delays without an index (panic ratchet 697 > 686, #30726, #31709) Nov 2, 2026
@lawrencecchen

Copy link
Copy Markdown
Contributor Author

Review (subagent, correctness first): SHIP at d561fd2

Checked (net diff against origin/feat-cmux-next, 2 files, +15/-7):

  • ProcessTable::page_snapshot: by_id is written only in insert, which stores at = processes.len() and then pushes. No code removes, truncates or reorders processes. upsert replaces a slot in place. read_processes / rebuild_processes replace the whole table, so by_id and processes always change together. So every by_id value is < len, start <= len, and start <= end = min(start + limit, len) <= len. get(start..end) is always Some, and the reply is the same as before. If the invariant ever broke, the old code panicked and the new code returns an empty page. That is no change for any reply the old code could send. unwrap_or_default() on Option<&[Process]> uses Default for &[T].
  • process_page_values stub: json! serializes each value through to_value(&expr). Option<&Value> gives Null for None and a clone of the value for Some, and Value's Index gives &Null for a missing key. So the output is the same. The macro builds the new Value from borrows of row and then assigns it, the same as the index form did. one_oversized_command_yields_a_stop_capable_stub covers this path.
  • settings_delays: DEFAULT_DELAYS_MS: [u64; 4] (auto_resume.rs:123). For n < 4, get(n) is arr[n]. For n >= 4, .or(last()) is arr[3], which is arr[n.min(3)]. The MIN_DELAY_MS fallback cannot run. This also removes one arithmetic_side_effects hit (len() - 1): acpmux 1488 -> 1487 in the logs.
  • The comments are accurate. rustfmt --check --edition 2024 --config-path cmux-tui/rustfmt.toml passes on both files.
  • Fleet logs: run 41388454113 at 8fad072 shows acpmux: clippy::indexing_slicing 697 > baseline 686, exit 1. Run 41388454076 at d561fd2 passes with no indexing_slicing line. Runs 41388453748 (process_: 145 passed) and 41388454078 (auto_resume: 101 passed) both checked out d561fd2.
  • The PR description matches the code. There is no baseline change and no allow.

@lawrencecchen lawrencecchen added the ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds label Nov 2, 2026
@cmux-bot
cmux-bot Bot temporarily deployed to ci-routing-agent November 2, 2026 05:21 Inactive
@lawrencecchen
lawrencecchen merged commit 418f3c7 into feat-cmux-next Nov 2, 2026
130 of 133 checks passed
@lawrencecchen
lawrencecchen deleted the base-red/acpmux-process-pages-index branch November 2, 2026 05:24
lawrencecchen added a commit that referenced this pull request Nov 2, 2026
… app's level rules and their C ABI (no FFI input yet) (#31799)

* test(host-budget): the app's host pressure rules as Rust tests, before the port

Moves acpmux's host_pressure module (the formula, the verdict, the probe,
the meter and their tests) into a new crate, cmux-host-budget, unchanged;
acpmux re-exports it from src/host_pressure.rs, so its daemon status and
send warnings read the same Meter. The macOS app keeps a hand copy of this
formula, its sampler and its level tracker in CmuxNextHostPressure; the
next commit ports the copy's rules into this crate so the app can link
them through cmux-app-ffi instead.

This commit adds the app's tests of those rules as the Rust corpus
(level_tests.rs from HostPressureTrackerTests and HostBudgetFormulaTests,
json_tests.rs for the app's JSON calls) with stub rules: level_for always
says normal, the tracker never moves, and with_pressure keeps the old
pressure. Red step: the level and rejudge tests fail here.

* feat(host-budget): the app's level, rejudge and C ABI in Rust

Ports the rules the macOS app keeps in Swift (CmuxNextHostPressure) into
cmux-host-budget, and links the crate into cmux-app-ffi:

- level.rs: HostPressureTracker. The level a verdict calls for (critical
  at critical memory pressure or two reasons, warning at one reason or a
  load at 75% of its limit, a 10% deadband while raised) and the tracker
  that falls only after calm_samples calm verdicts.
- rejudge.rs: HostBudgetVerdict.with(pressure:). A verdict (the daemon's,
  with its session facts, or the app's) judged again with the pressure
  the dispatch source reports; the memory reason goes last, as in Swift.
- json.rs and ffi.rs (header include/cmux_host_budget_ffi.h, module
  CCmuxHostBudgetFFI, re-exported by cmux-app-ffi as palette_ranker is):
  the app's own verdict from the process's Meter when no daemon answers
  (the same formula, override file, probe and swap rate as acpmux's
  daemon), the rejudge, a judge of given numbers (Debug Settings
  samples), the level and a tracker handle. JSON in acpmux's
  host_pressure shape, about once per 15 s; no call panics across the
  boundary. The C ABI is in the workspace crate, so workspace clippy and
  tests build and check it (ffi_tests.rs).

app-ffi-release.yml gets the new crate in its push paths, as
check-app-ffi-pin.sh --list-inputs now lists it
(app-ffi-release-paths.test.sh: ok). No Swift change: the app keeps the
pinned FFI until the re-pin; the Swift half deletes its copy after it.

* fix(host-budget): clippy findings of the first fleet run

clippy -D warnings (2e0f23045b77e7d0788701b3) refused an unneeded
`crate::json::` path in ffi_tests.rs; the panic ratchet
(ef9f5b7e0893ccd47e3cfc62) counted one cast_possible_truncation in the
new crate (available_parallelism as u32), now a checked conversion.
The two other reds of those runs are base reds with open fixes:
cmux-tui plugin_manager.rs suspicious_open_options (#31697) and acpmux
indexing_slicing 697 > 686 (#31773); this branch adds no acpmux hit.

* refactor(host-budget): the crate move lands without the app FFI link

The rule for app FFI moves changed (cmux-ad 04:35Z): a change to an FFI
input lands in one PR with its re-pin and its Swift call. This branch
now keeps only what is no FFI input: the cmux-host-budget crate (the
move from acpmux, the ported level and rejudge rules and their C ABI,
built and tested in the workspace), used by acpmux alone. cmux-app-ffi,
build-app-ffi.sh and app-ffi-release.yml are back at the base; the FFI
move PR adds the link, the re-pin and the Swift half together.

---------

Co-authored-by: cmux-bot[bot] <348531757+cmux-bot[bot]@users.noreply.github.com>

This branch was previously deployed

3 inactive deployments
artifacts — 9ac3951c Deployed Nov 2, 2026 by cmux-bot[bot] via publish tree-addressed cmux-tui #99471
sentry-dsyms — 9ac3951c Deployed Nov 2, 2026 by cmux-bot[bot] via upload cmux-tui dSYMs to Sentry #99471
ci-routing-agent — 9ac3951c Deployed Nov 2, 2026 by cmux-bot[bot] via cmux-tui tree preflight #99471
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant