Skip to content

feat(boot): auto-heal stale boot registration on supervisor startup - #707

Merged
jdx merged 2 commits into
jdx:mainfrom
gaojunran:feat/auto-heal-boot-registration
Aug 2, 2026
Merged

feat(boot): auto-heal stale boot registration on supervisor startup#707
jdx merged 2 commits into
jdx:mainfrom
gaojunran:feat/auto-heal-boot-registration

Conversation

@gaojunran

@gaojunran gaojunran commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Problem

When the binary path changes after a package-manager upgrade (e.g. brew cleanup, mise install), the launchd plist or systemd unit still points to the old version-specific path, causing the supervisor to fail on next boot with EX_CONFIG (78) on macOS or a missing binary on Linux.

See discussion #544 for details.

Solution

On supervisor startup, check whether the registered boot binary path matches the current PITCHFORK_BIN. If stale, re-register with the current path.

This runs in a background spawn_blocking task and is best-effort: errors are logged and swallowed, never blocking startup.

Changes

  • Cargo.toml: upgrade auto-launcher from 1.0.3 to 1.1
  • src/boot_manager.rs: add check_and_reregister_if_stale() which reads the registered path back from disk via auto_launcher::AutoLaunch::get_registered_app_path() (new in 1.1), compares to PITCHFORK_BIN, and re-registers by disable() + enable() when stale
  • src/supervisor/mod.rs: call the check in Supervisor::start() via tokio::task::spawn_blocking, fire-and-forget

Why not just use a stable path?

mise shims are shell scripts that require MISE_* environment variables which launchd/systemd minimal environments cannot provide. Detect-and-re-register avoids this issue entirely and works across all package managers.

auto-launcher dependency

This PR requires auto-launcher 1.1, which adds get_registered_app_path() — a new API that reads the binary path back from the on-disk launch file (plist/systemd unit/registry). See auto-launcher PR #7.

Closes #544

AI-assisted — Tool: opencode; model: astra/glm_5d2_fp8_code; version: unavailable.

Summary by CodeRabbit

  • Bug Fixes

    • Improved boot registration reliability by automatically detecting and correcting outdated launcher paths.
    • Boot registration issues are handled gracefully without interrupting application startup.
  • Maintenance

    • Updated the automatic launch support to a newer version.

When the binary path changes after a package-manager upgrade (e.g.
brew cleanup, mise install), the launchd plist or systemd unit still
points to the old version-specific path, causing the supervisor to
fail on next boot.

On supervisor startup, check whether the registered boot binary path
matches the current PITCHFORK_BIN. If stale, re-register with the
current path. This runs in a background spawn_blocking task and is
best-effort: errors are logged and swallowed, never blocking startup.

Requires auto-launcher 1.1 which adds get_registered_app_path().

Closes jdx#544
@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The update adds stale boot-registration recovery. BootManager compares the registered path with PITCHFORK_BIN, and Supervisor runs the check asynchronously during startup. The auto-launcher dependency requirement changes from 1.0.3 to 1.1.

Changes

Boot registration recovery

Layer / File(s) Summary
Stale path detection and re-registration
Cargo.toml, src/boot_manager.rs
The auto-launcher requirement changes to 1.1. BootManager detects stale paths and re-registers the current launcher.
Non-blocking startup integration
src/supervisor/mod.rs
Supervisor::start runs the recovery check in a blocking background task and ignores initialization failures.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Supervisor
  participant BootManager
  participant auto-launcher
  Supervisor->>BootManager: Initialize during startup
  BootManager->>auto-launcher: Read registered executable path
  auto-launcher-->>BootManager: Return registered path
  BootManager->>auto-launcher: Re-register when the path is stale
  BootManager-->>Supervisor: Finish without interrupting startup
Loading

Possibly related PRs

  • jdx/pitchfork#616: Both changes use PITCHFORK_BIN to resolve the current executable path.

Suggested reviewers: jdx

Poem

I hop through startup, quick and bright,
Checking paths in morning light.
If the launcher wandered away,
I register it back today.
Boot keeps moving—hip hip hooray!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: automatic repair of stale boot registration during supervisor startup.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@greptile-apps

greptile-apps Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds best-effort repair of stale boot registrations when the supervisor starts.

  • Upgrades auto-launcher to expose the registered application path.
  • Compares the registered path with the current binary and overwrites stale registration.
  • Runs repair asynchronously so supervisor startup is not blocked.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains; the previously reported registration-loss path was removed by no longer disabling the existing registration before attempting replacement.

Important Files Changed

Filename Overview
Cargo.toml Updates auto-launcher to the release required for reading the registered application path.
Cargo.lock Records the corresponding dependency resolution changes.
src/boot_manager.rs Adds stale-path detection and directly overwrites stale registration without first deleting the existing entry.
src/supervisor/mod.rs Starts boot-registration repair as a non-blocking background task during supervisor startup.

Reviews (2): Last reviewed commit: "fix(boot): overwrite stale registration ..." | Re-trigger Greptile

Comment thread src/boot_manager.rs Outdated
…ng it

Greptile review (jdx#707): calling disable() before enable() risks losing
the boot registration entirely if enable() fails. Since enable() already
overwrites the on-disk file on all platforms, skip disable() so a failed
re-register leaves the stale path intact (stale path > no path).

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/boot_manager.rs`:
- Around line 253-257: Update the repair path around self.current.enable() to
call BootManager::enable() via self.enable() directly, without first calling
disable(). Preserve the existing error handling and stale-registration behavior
while ensuring privilege-level validation and macOS legacy cleanup run during
repair.
- Around line 253-257: Update the registration write flow used by
BootManager::current.enable() to write the new contents to a temporary file and
atomically rename it over the existing registration, preserving the old file if
writing fails; alternatively extend the dependency contract with equivalent
backup-and-restore behavior. Ensure the fallback around this enable call still
retains the prior valid registration on any write error.

In `@src/supervisor/mod.rs`:
- Around line 385-387: Update the unsupported-platform BootManager
implementation in boot_manager.rs to define check_and_reregister_if_stale with
the same callable interface as the supported implementations, using a no-op body
so Supervisor::start() type-checks on all targets while BootManager::new()
continues returning its existing error.
- Around line 385-388: Update the BootManager initialization inside the
spawn_blocking closure to match on BootManager::new() instead of discarding Err
values; preserve the existing stale-registration check on success, and log the
initialization error on failure before continuing startup.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 7fccd405-a8e0-42ec-949f-50c1f3906d56

📥 Commits

Reviewing files that changed from the base of the PR and between 3a2b3e8 and 6b0cfe7.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • Cargo.toml
  • src/boot_manager.rs
  • src/supervisor/mod.rs

Comment thread src/boot_manager.rs
Comment thread src/supervisor/mod.rs
Comment thread src/supervisor/mod.rs
@jdx
jdx merged commit a8a8932 into jdx:main Aug 2, 2026
15 checks passed
@jdx jdx mentioned this pull request Aug 2, 2026
jdx added a commit that referenced this pull request Aug 2, 2026
## 🤖 New release

* `pitchfork-cli`: 2.19.0 -> 2.20.0

<details><summary><i><b>Changelog</b></i></summary><p>

<blockquote>

## [2.20.0](v2.19.0...v2.20.0)
- 2026-08-02

### Added

- *(supervisor)* expand ~ in daemon dir using effective user's home
([#708](#708))
- *(boot)* auto-heal stale boot registration on supervisor startup
([#707](#707))
- *(web)* structured log display with filters in webui
([#630](#630))
- *(supervisor)* allow disabling client auto-start
([#678](#678))
- *(supervisor)* add --json flag to supervisor status
([#601](#601))
- *(config)* expand home-relative paths
([#675](#675))
- *(logs)* let the sink serve on_output hooks
([#668](#668))
- *(usage)* declare what each command does to the world
([#666](#666))
- *(logs)* let the sink decide ready_output
([#667](#667))

### Fixed

- deterministic IPC response attribution and whole-group stop wait
([#606](#606))
- *(config)* include registries in schema
([#671](#671))

### Other

- *(deps)* update rust crate libc to v0.2.189
([#703](#703))
- *(deps)* update rust crate clap to v4.6.4
([#702](#702))
- *(deps)* update rust crate glob to v0.3.4
([#701](#701))
- *(deps)* update rust crate tokio-util to v0.7.19
([#699](#699))
- *(deps)* update rust crate libc to v0.2.188
([#698](#698))
- *(deps)* update rust crate syn to v3
([#697](#697))
- *(deps)* update rust crate hyper to v1.11.0
([#695](#695))
- *(deps)* update rust crate tokio to v1.53.1
([#692](#692))
- *(deps)* update rust crate thiserror to v2.0.19
([#691](#691))
- *(deps)* update rust crate serde to v1.0.229
([#689](#689))
- *(deps)* update rust crate quote to v1.0.47
([#687](#687))
- *(deps)* update rust crate serde_json to v1.0.151
([#690](#690))
- *(deps)* update rust crate libc to v0.2.187
([#685](#685))
- *(deps)* update rust crate proc-macro2 to v1.0.107
([#686](#686))
- *(deps)* update rust crate clx to v3.0.2
([#684](#684))
- *(deps)* update rust crate clap to v4.6.3
([#683](#683))
- *(deps)* use rust-aware cargo resolver
([#677](#677))
- *(deps)* update clx
([#672](#672))
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Metadata-only release bump and changelog; no behavioral changes in the
diff itself.
> 
> **Overview**
> Bumps **pitchfork-cli** from **2.19.0** to **2.20.0** in `Cargo.toml`,
`Cargo.lock`, and generated CLI metadata (`pitchfork.usage.kdl`,
`docs/cli/commands.json`, `docs/cli/index.md`).
> 
> Adds a **CHANGELOG** section for **2.20.0** that records what shipped
since 2.19.0 (supervisor path expansion, boot auto-heal, web UI log
filters, IPC/stop fixes, config schema, dependency updates, etc.). This
PR does not implement those features—it only publishes the release notes
and version strings for tagging/publishing.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
d7d9c08. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
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