test: verify the launchd system scope on macOS with root and a reboot (#310)
- Dominant language
- Rust
- Stars
- 279
- Forks
- 28
- Avg merge
- 8h 35m
- Merged PRs (30d)
- 30
Description
## Background
#310 (PR #321) landed the launchd backend of the `all-smi service` subcommand. The code is written, integrated, and dispatched from the shipped binary on macOS. What is not done is verification of the system scope: four acceptance criteria from #310 were deliberately left unticked because they need root on a macOS host plus a reboot, and no authorization for root-level macOS changes was available during implementation. Every one of those gaps is recorded honestly in PR #321's body, and none of them is a code defect.
This is group C of the four groups split out of #332.
## Why this was split out
The four groups in #332 are unblocked by four unrelated environments and are independently actionable. Holding them in one issue meant none of them could be scheduled, assigned, or closed independently: whoever gained access to one environment could not close anything. #332's own first acceptance criterion permits exactly this action, and its closing note says to shrink it as groups get split out. #332 stays open as the umbrella until all four children are resolved.
## Scope
Three of the original 19 unticked items across #309, #310 and #311 are already tracked by #330, which covers the `systemd-service` CI job's system-scope lifecycle path never having executed. Those three are **excluded** here and from the other three split issues so the trackers do not overlap:
- The `kill -9` crash-restart check.
- The tarball system-scope install flow (`sudo all-smi service install --now`, then `uninstall` leaving no unit).
- `/etc/all-smi/config.toml` being honored by a running daemon.
## Needs root on a macOS host plus a reboot (from #310)
- [ ] `sudo brew services start all-smi` bootstraps into the system domain; the service persists across reboot without login.
- [ ] From a zip or tarball install: `sudo all-smi service install --now` creates the LaunchDaemon; `all-smi service status` reports running with a pid; `sudo all-smi service uninstall` boots it out and removes the plist, leaving logs in place.
- [ ] The boot-time daemon context reports the full Apple Silicon metric set, or degradations are documented with a follow-up issue.
- [ ] `/Library/Application Support/all-smi/config.toml` is honored and listed by `all-smi config path`.
Notes:
- Only the user scope was verified, and deliberately so. A LaunchAgent was installed into `gui/$UID` on an M1 Ultra running macOS 26.6, checked end to end (install, start, restart, stop, uninstall, idempotent reinstall, marker refusal, `launchctl disable` handling, 72 `all_smi_*` lines served, energy WAL flush on bootout), and removed. `/Library/LaunchDaemons` was never touched and `sudo launchctl bootstrap system` was never run.
- The fourth item is half done. `all-smi config path` listing the candidate is verified live: it reports as candidate 3, ordered last. The open half is a running daemon actually loading it, because creating that file needs root. The load path is the same `discover_existing_config()` the Linux `/etc` candidate uses, and is unit-tested for presence, ordering, and never being the `config init` target.
- On the third item, what is already demonstrated is that IOReport, the SMC and `NSProcessInfo.thermalState` all resolve from a launchd context with no TTY and no sudo, at background QoS, with a metric name set byte-identical to a foreground `all-smi api`. What is not demonstrated is a boot-time LaunchDaemon with nobody logged in, since a `gui/$UID` agent still belongs to a login session. No degradation was found in the reachable part, so no follow-up was filed; if the system-domain test surfaces one, that is when to file it.
- Two environment facts worth knowing before running these. `ProcessType=Background` pushes first-bind to roughly 6 s as a LaunchAgent (0.6 s foreground), so poll `/metrics` for content rather than trusting `service status`. And a binary on an external volume hangs under launchd, blocking in `dyld` `open()` on its own binary because of the TCC gate for launchd-spawned processes on removable volumes. Install from an internal disk path.
## Acceptance Criteria
- [ ] Every box above is ticked with evidence (a command transcript, a CI run link, or a screenshot).
- [ ] When a criterion here is verified, the corresponding box is also ticked on #310, so it ends up truthful rather than permanently understating what was delivered.
- [ ] Any degradation found during verification is filed as its own issue and linked here, rather than being absorbed into a checkbox comment.
## How to pick this up
This group wants root on any Apple Silicon Mac plus one reboot. Nothing about it depends on the tap work in the group B issue, since the subcommand path is separate from the brew path.
## References
- Umbrella: #332
- Issues: #310 (macOS launchd), #330 (systemd CI system-scope path, owns the three excluded items)
- PRs: #321 (launchd implementation), #323 (launchd smoke test readiness gate), #331 (technical reports)
Contributor guide
No contributing guide indexed for this repository
Research direction
Start on an Apple Silicon Mac using an internal disk path, then read the launchd scope notes and run the listed brew and tarball service commands with root, including one reboot. Check service status and /metrics rather than status alone, and verify the four system-scope criteria. Record command, CI, or screenshot evidence, update the corresponding boxes on #310, and file any degradation separately.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, rust
- Domain
- cli, operating-systems, testing
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 48/100