Skip to content

fix(pmset): Skip unsupported settings based on hardware capabilities - #5

Merged
Ryan Zhu (underthestars-zhy) merged 1 commit into
mainfrom
ryan/fix-pmset
May 24, 2026
Merged

fix(pmset): Skip unsupported settings based on hardware capabilities#5
Ryan Zhu (underthestars-zhy) merged 1 commit into
mainfrom
ryan/fix-pmset

Conversation

@underthestars-zhy

@underthestars-zhy Ryan Zhu (underthestars-zhy) commented May 23, 2026

Copy link
Copy Markdown
Member

Summary

  • Query pmset -g cap per source and filter the desired settings down to those the hardware actually supports before checking or applying.
  • check() no longer reports drift for unsupported keys (e.g. autopoweroff on Apple Silicon, standby on hardware that doesn't expose it).
  • apply() no longer feeds unsupported keys to pmset, which would otherwise fail or surface "not supported on this machine" warnings.

Motivation

pmset exposes a different capability set per power source and per machine. Asking it to set a key that isn't listed under pmset -g cap produces a no-op (best case) or a hard error (worst case), and the next check() would re-read the original value and report drift forever — re-triggering apply() on every loop tick. Filtering by the live capability set keeps PmsetSetting converged on heterogeneous hardware (Apple Silicon laptops, Intel desktops, machines on UPS, etc.) without per-target conditionals in user code.

Changes

File Change
Sources/Astrolabe/Steps/Sys/PmsetSetting.swift Parse pmset -g cap into [section: Set<key>]. Extract settingsAreSatisfied, supportedSettings, targetSections, targetSectionNames, and isSupported helpers. check() ignores unsupported keys; apply() filters them out and short-circuits if nothing remains. Fall back to the original behavior when the capability probe fails.
Tests/AstrolabeTests/AstrolabeTests.swift Add coverage for parseCapabilities, drift filtering when a setting is unsupported, drift still firing when a supported key is missing, and apply filtering down to supported settings.

Test plan

  • swift build succeeds.
  • swift test passes (new pmsetParseCapabilities, pmsetUnsupportedSettingsDoNotForceDrift, pmsetSupportedMissingSettingStillDrifts, pmsetApplyFiltersUnsupportedSettings).
  • On a desktop (no battery), declaring a battery-only setting no longer flaps.
  • On Apple Silicon, declaring autopoweroff / standby is silently skipped instead of producing recurring drift.
  • On hardware where every declared key is supported, behavior matches the previous implementation.

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag @codesmith with what you need. Autofix is disabled.

Summary by CodeRabbit

  • Bug Fixes

    • Power management settings now validate against device capabilities before applying, ensuring only supported settings are applied for the active power source. Unsupported settings are automatically filtered out to prevent errors.
  • Tests

    • Added test coverage for capability parsing and validation of settings filtering based on supported device capabilities.

Review Change Stack

Query `pmset -g cap` to determine which settings each power source
actually supports, then filter out unsupported keys during both check
and apply. This prevents false drift detection and avoids passing
invalid arguments on machines that lack certain power features (e.g.,
desktops with no battery or hardware without autopoweroff).
Copilot AI review requested due to automatic review settings May 23, 2026 23:56
@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cc8f99a2-9d82-4ce4-847e-eb78e8736f2b

📥 Commits

Reviewing files that changed from the base of the PR and between 7666725 and 5aa05a6.

📒 Files selected for processing (2)
  • Sources/Astrolabe/Steps/Sys/PmsetSetting.swift
  • Tests/AstrolabeTests/AstrolabeTests.swift
📜 Recent review details
🔇 Additional comments (11)
Sources/Astrolabe/Steps/Sys/PmsetSetting.swift (7)

19-31: LGTM!


33-45: LGTM!


69-90: LGTM!


92-114: LGTM!


116-127: LGTM!


129-143: LGTM!


145-170: LGTM!

Tests/AstrolabeTests/AstrolabeTests.swift (4)

317-332: LGTM!


334-351: LGTM!


353-369: LGTM!


371-382: LGTM!


📝 Walkthrough

Walkthrough

PmsetSetting now queries pmset -g cap to determine supported settings per power source, then filters validation and application to only capability-supported keys. New parsing and helper functions enable this capability-aware workflow, and tests ensure correct parsing and filtering behavior.

Changes

PMSet Capability-Aware Filtering

Layer / File(s) Summary
Capability parsing and support validation
Sources/Astrolabe/Steps/Sys/PmsetSetting.swift
parseCapabilities parses pmset capability output into supported key sets per power source. Helper functions supportedSettings, targetSections, targetSectionNames, and isSupported compute which sections apply and whether a key is supported for a given section.
Check and apply with capability filtering
Sources/Astrolabe/Steps/Sys/PmsetSetting.swift
check() and apply() now capture capabilities via pmset -g cap, filter configured settings against supported keys, and return early when no supported settings exist for the selected power source.
Capability and filtering test coverage
Tests/AstrolabeTests/AstrolabeTests.swift
Four new tests exercise parseCapabilities parsing, unsupported settings drift behavior, supported missing settings drift behavior, and the supportedSettings filter.

🎯 3 (Moderate) | ⏱️ ~20 minutes

🐰 A pmset power source dares,
Queries caps with utmost care,
Filters settings one by one,
Only runs the supported ones! ⚡

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title directly and clearly summarizes the main change: adding capability-based filtering to skip unsupported pmset settings.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ryan/fix-pmset

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates PmsetSetting to probe pmset -g cap and use those per-power-source capabilities to ignore unsupported pmset keys during drift checks and when applying settings, preventing perpetual “drift” and avoiding attempts to set keys that aren’t supported on the current hardware/power configuration.

Changes:

  • Parse pmset -g cap into a per-section capabilities map and use it to filter settings.
  • Refactor drift detection into a helper that skips unsupported keys.
  • Add tests covering capability parsing and supported/unsupported drift + apply filtering behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
Sources/Astrolabe/Steps/Sys/PmsetSetting.swift Adds capability probing + helpers; filters unsupported keys during check()/apply().
Tests/AstrolabeTests/AstrolabeTests.swift Adds unit tests for capability parsing and filtering behavior.
Comments suppressed due to low confidence (1)

Sources/Astrolabe/Steps/Sys/PmsetSetting.swift:44

  • When source == .all, apply() still invokes pmset with -a, but the capability filtering is per power-source section. A key that is supported in only one section (e.g. Battery Power) will still be included in settingsToApply, and passing it via -a can reintroduce the exact “not supported on this machine” warnings/errors this PR aims to avoid for the other sections. Consider applying per power source when .all (run separate pmset -b/-c/-u commands with per-section filtered settings), or otherwise change the filtering/command strategy so unsupported-by-section keys are never sent to pmset for that section.
    public func apply() async throws {
        let capabilitiesOutput = try? await captureOutput("/usr/bin/pmset", ["-g", "cap"])
        let capabilities = capabilitiesOutput.map(Self.parseCapabilities) ?? [:]
        let settingsToApply = Self.supportedSettings(settings, for: source, capabilities: capabilities)
        guard !settingsToApply.isEmpty else { return }

        var arguments = [source.rawValue]
        for setting in settingsToApply {
            arguments.append(setting.key)
            arguments.append(String(setting.intValue))
        }
        try await run("/usr/bin/pmset", arguments)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@underthestars-zhy
Ryan Zhu (underthestars-zhy) merged commit 360f06d into main May 24, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants