|
1 | 1 | # Changelog |
2 | 2 |
|
| 3 | +## v1.0.0 |
| 4 | + |
| 5 | +Initial release -- fork of BatteryOptimizer_for_Mac with full rebrand. |
| 6 | + |
| 7 | +- `battery` command renamed to `apple-juice`, config directory moved from `~/.battery` to `~/.apple-juice` |
| 8 | +- Removed Electron GUI app (CLI only) and donation prompts |
| 9 | +- Root-owned executables in `/usr/local/co.apple-juice` with symlinks in `/usr/local/bin` |
| 10 | +- mktemp for visudo temp files, `-h` flag on chown calls to prevent symlink attacks |
| 11 | + |
| 12 | +## v1.0.1 |
| 13 | + |
| 14 | +- Auto-detect installation directory for Homebrew compatibility |
| 15 | +- Process detection fix (use `args` instead of `comm`) |
| 16 | +- osascript quote escaping fix in setup dialog |
| 17 | +- Removed Chinese language support (English only) |
| 18 | +- Status now shows "Longevity mode active" when using longevity preset |
| 19 | + |
| 20 | +## v1.0.2 |
| 21 | + |
| 22 | +- Create config file automatically if missing (fixes brew installs) |
| 23 | + |
3 | 24 | ## v2.0.0 |
4 | 25 |
|
5 | 26 | Complete rewrite from bash to Swift. Apple Silicon only. |
6 | 27 |
|
7 | | -### Added |
8 | 28 | - Native Swift binary via Swift Package Manager (no runtime dependencies) |
9 | 29 | - LaunchAgent with `KeepAlive` for automatic daemon restart on crash/SIGKILL/OOM |
10 | | -- IOKit direct battery reads (replaces all `ioreg | grep | awk` chains) |
| 30 | +- IOKit direct battery reads (replaces `ioreg | grep | awk` chains) |
11 | 31 | - IOKit sleep/wake notifications with CHWA management (replaces sleepwatcher) |
12 | 32 | - `IOPMAssertionCreateWithName` for sleep prevention (replaces caffeinate) |
13 | 33 | - Startup recovery check: re-enables charging if daemon is not running |
14 | 34 | - SMC write verification with consecutive failure detection |
15 | 35 | - Serial dispatch queue for thread-safe SMC access across main loop, sleep/wake, and signal handlers |
16 | | -- Daily log rotation (365 entries, ~1 year) |
17 | | -- Main log rotation (5MB threshold) |
18 | | -- PID file write error handling with stderr fallback |
19 | | -- `ProcessType: Interactive` and `ExitTimeOut: 30` in LaunchAgent plist |
20 | | -- LaunchAgent migration for v1.x users upgrading (auto-regenerates plist with KeepAlive) |
21 | | -- Config key migration from old formats |
| 36 | +- Daemon lifecycle managed by `launchctl bootstrap`/`bootout` instead of `nohup` |
| 37 | +- Config uses file-per-key storage with atomic writes (replaces single parsed file) |
| 38 | +- Daily log rotation (365 entries), main log rotation (5MB threshold) |
22 | 39 | - `status --csv` flag for machine-readable output |
23 | | -- `advanceCalibrateNext` for proper `week_period`/`month_period` enforcement |
24 | | -- Webhook events for calibration Method 2 |
25 | 40 | - CI/CD: GitHub Actions for build/test and release binary generation |
| 41 | +- Dropped Intel Mac support, bash script, sleepwatcher dependency, and sleep/wake hook scripts |
26 | 42 |
|
27 | | -### Changed |
28 | | -- Daemon lifecycle managed by `launchctl bootstrap`/`bootout` instead of `nohup` |
29 | | -- `maintain stop` uses `launchctl bootout` for clean daemon shutdown |
30 | | -- `uninstall` properly unloads LaunchAgent before removing plist |
31 | | -- Signal ACK setup occurs before sending SIGUSR1 (fixes race condition) |
32 | | -- Clean stop exits with code 0 (KeepAlive does not restart); crashes exit non-zero (restart) |
33 | | -- Config uses file-per-key storage with atomic writes (replaces single parsed file) |
34 | | -- All curl calls have `--max-time` timeouts with exponential backoff |
| 43 | +## v2.0.1 |
35 | 44 |
|
36 | | -### Removed |
37 | | -- Intel Mac support (Apple Silicon M1+ only) |
38 | | -- Bash script (`apple-juice.sh`) |
39 | | -- sleepwatcher dependency |
40 | | -- `setup.sh` (installation via Homebrew) |
41 | | -- Sleep/wake hook scripts (`.sleep`, `.wakeup`, `.reboot`, `.shutdown`) |
42 | | -- `notification_permission.scpt` |
43 | | -- `shutdown.sh` and `apple-juice_shutdown.plist` |
| 45 | +- Resolve binary path when invoked via PATH |
44 | 46 |
|
45 | | -## v1.0.2 |
| 47 | +## v2.0.2 |
46 | 48 |
|
47 | | -### Fixed |
48 | | -- Create config file automatically if missing (fixes brew installs) |
| 49 | +- Register maintain-daemon as top-level subcommand |
49 | 50 |
|
50 | | -## v1.0.1 |
| 51 | +## v2.0.3 |
51 | 52 |
|
52 | | -### Fixed |
53 | | -- Auto-detect installation directory for Homebrew compatibility |
54 | | -- Process detection now works correctly (use `args` instead of `comm`) |
55 | | -- osascript quote escaping in setup dialog |
| 53 | +- Daemon startup, cell voltage reading, and launchctl logging fixes |
56 | 54 |
|
57 | | -### Changed |
58 | | -- Removed Chinese language support (English only) |
59 | | -- Status now shows "Longevity mode active" when using longevity preset |
60 | | -- Clean up orphaned language config on update |
| 55 | +## v2.0.4 |
61 | 56 |
|
62 | | -## v1.0.0 |
| 57 | +- Use stable symlink path in LaunchAgent plists (survives Homebrew upgrades) |
| 58 | + |
| 59 | +## v2.0.5 |
| 60 | + |
| 61 | +- Redesigned status output with extended battery telemetry: capacity (mAh), adapter details, battery current draw, time estimates |
| 62 | +- Cell imbalance warnings at >20mV and >=50mV |
| 63 | +- Calibration skipped when cells are balanced (<50mV imbalance) |
| 64 | + |
| 65 | +## v2.0.6 |
| 66 | + |
| 67 | +- Version line in status output with update check and brew upgrade command |
| 68 | + |
| 69 | +## v2.0.7 |
| 70 | + |
| 71 | +- Safety recovery and watchdog now attempt to restart the daemon before falling back to re-enabling charging |
| 72 | + |
| 73 | +## v2.0.8 |
| 74 | + |
| 75 | +- Status power description uses IOKit instead of lagging SMC keys |
| 76 | +- Daemon applies charging control immediately on startup |
| 77 | +- Status warns when longevity is configured but daemon isn't running |
| 78 | + |
| 79 | +## v2.0.9 |
| 80 | + |
| 81 | +- `startDaemon()` ensures the LaunchAgent service is enabled before bootstrap, preventing `Input/output error` after `maintain stop` + `maintain longevity` cycle |
| 82 | +- Suppressed expected launchctl bootout errors from user-facing output |
| 83 | + |
| 84 | +## v2.1.0 |
| 85 | + |
| 86 | +- Added `aj` as a shorthand alias for the `apple-juice` CLI |
| 87 | + |
| 88 | +## v2.1.1 |
| 89 | + |
| 90 | +- Safety watchdog switched from `StartInterval` (affected by kqueue sleep bug) to `StartCalendarInterval`, which coalesces missed intervals and fires on wake |
| 91 | +- Always run launchctl enable/bootout/bootstrap for the safety daemon, even when the plist is unchanged on disk |
| 92 | +- SMC failure backoff increased to 30s with threshold raised to 10 consecutive failures, preventing premature daemon exits during Power Nap |
| 93 | + |
| 94 | +## v2.1.2 |
| 95 | + |
| 96 | +- Added delay and retry between launchd `bootout` and `bootstrap` calls, preventing bootstrap race conditions during daemon startup |
| 97 | +- Removed immediate kickstart of the safety watchdog during daemon startup (was causing false "daemon not running" detection) |
| 98 | +- `maintain` now waits up to 5s for the old daemon process to exit before starting the new one |
63 | 99 |
|
64 | | -Initial release - fork of BatteryOptimizer_for_Mac with full rebrand. |
| 100 | +## v3.0.0 |
65 | 101 |
|
66 | | -### Security |
67 | | -- Root-owned executables in `/usr/local/co.apple-juice` |
68 | | -- Symlinks in `/usr/local/bin` for PATH accessibility |
69 | | -- mktemp for visudo temp files (isolated from user config) |
70 | | -- `-h` flag on chown calls to prevent symlink attacks |
| 102 | +Safety watchdog fix and CLI cleanup. **Breaking**: six commands removed (see below). Scripts referencing `aj schedule`, `aj ssd`, `aj dailylog`, `aj calibratelog`, `aj ssdlog`, or `aj reinstall` will fail with an unknown-command error. |
71 | 103 |
|
72 | | -### Changes |
73 | | -- Full rebrand: `battery` command is now `apple-juice` |
74 | | -- Config directory: `~/.battery` is now `~/.apple-juice` |
75 | | -- Removed Electron GUI app (CLI only) |
76 | | -- Removed donation prompts |
| 104 | +- Safety watchdog stale PID detection now uses system uptime (monotonic clock) instead of wall clock time, preventing false triggers after sleep |
| 105 | +- When a hung daemon is detected, the watchdog kills it for launchd restart instead of re-enabling charging (which fought the daemon's own control loop) |
| 106 | +- Stale PID threshold tightened from 5 minutes to 2 minutes of awake time |
| 107 | +- Removed commands: `schedule`, `ssd`, `ssd-log`, `daily-log`, `calibrate-log`, `reinstall` |
| 108 | +- Hidden commands: `charge`, `discharge`, `visudo` (still functional, used internally) |
| 109 | +- Longevity mode schedule setup no longer depends on the `schedule` command |
| 110 | +- Added CodeRabbit configuration for automated PR reviews |
0 commit comments