feat(battery): add force-discharge and manual toggles#7
Merged
Conversation
…-discharge, time remaining, daemon logs Feature parity pass against actuallymentor/battery v1.3.2, all verified live on M2 MacBook Air: - `battery charging on|off` and `battery adapter on|off`: expose the existing setChargingEnabled/setAdapterEnabled XPC calls in the CLI. When a maintain policy is active the CLI warns that the toggle may be overridden on the next evaluation (verified: it is, within seconds). - `battery maintain N --force-discharge`: the policy actively discharges down to the band by cutting adapter power while above the upper bound, and restores it once inside. Persisted as battery.force_discharge in config.toml. The evaluation loop re-asserts the cut every period, which makes it self-healing against the firmware quirk below. Switching back to a plain maintain hands the adapter back (daemon-side transition, verified both directions). - `battery status` shows time-to-empty/full from IOKit power sources (nil while the gauge is settling — mirrors pmset's "(no estimate)"). - `daemon logs [--last 1h]`: wraps `log show` with the smctl subsystem predicate. Field finding that shaped the design: writing the charging-enable key (CHTE) while an adapter cut (CHIE) is active made the SMC silently re-enable adapter power — observed live, it stalled a one-shot `battery discharge` forever at 79%. The one-shot discharge loop now re-asserts the cut every poll, and force-discharge inherits immunity from the policy loop (verified: triggering the same reset under force-discharge is corrected within one XPC call). PolicyEngine: BatteryObservation gains isAdapterEnabled (nil when adapter control is unsupported — the policy then never touches the adapter, which also keeps it out of the way of manual discharges). New transition-matrix tests for the force-discharge branches.
5fc3499 to
fa32095
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Rebuilds closed stacked PR #6 onto the current
mainafter PR #4 was squash-merged.smctl battery charging on|offandsmctl battery adapter on|offsmctl battery maintain <limit> --force-discharge, backed by daemon-owned adapter cut/restore behaviorbattery dischargeso firmware resets cannot silently stall the dischargebattery statussmctl daemon logs --last <range>as a thin wrapper around the smctl unified-log predicateChanges added while rebuilding
battery.force_dischargeinwriteConfig, so later battery/fan writes do not drop the policy100/stop) so force-discharge cannot remain armed after charge limiting is stoppedTests
swift test --disable-sandbox— 89 tests, 0 failuresgit diff --checkgit fetch origin main --quiet && git merge-tree --write-tree --merge-base $(git merge-base HEAD origin/main) HEAD origin/main