fix(launchd): detect profile-scoped updater jobs#96924
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 26, 2026, 7:54 PM ET / 23:54 UTC. Summary PR surface: Source +8, Tests +69. Total +77 across 2 files. Reproducibility: yes. source-reproducible: current main rejects the reported profile-scoped updater label before cleanup, and the PR body includes after-fix macOS launchctl output for the same detection and disable path. Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Next step before merge
Security Review detailsBest possible solution: Land the shared launchd normalizer and focused regression tests after ordinary maintainer merge gating. Do we have a high-confidence way to reproduce the issue? Yes, source-reproducible: current main rejects the reported profile-scoped updater label before cleanup, and the PR body includes after-fix macOS launchctl output for the same detection and disable path. Is this the best way to solve the issue? Yes. The shared launchd normalizer is the narrow owner boundary used by update cleanup, deep status, doctor notes, and explicit stale-job disabling; patching only the update command would leave diagnostics inconsistent. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against e0932e0bc4e1. Label changesLabel justifications:
Evidence reviewedPR surface: Source +8, Tests +69. Total +77 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
|
@clawsweeper re-review Addressed both blockers from the last review:
Local verification passed:
|
|
🦞🧹 I asked ClawSweeper to review this item again. |
0ab61c7 to
53ce1e6
Compare
|
closing this as unsafe to land in its current shape. the observed |
What Problem This Solves
A macOS profile-scoped updater launchd job can get stuck repeatedly rerunning
openclaw update --yes.Observed locally with profile
tayoun: launchd jobai.openclaw.tayoun.update.20260625T201026-0400ran the updater 300 times. The first run upgraded OpenClaw from2026.6.1to2026.6.10; the next 299 runs were no-op updates from2026.6.10to2026.6.10, repeatedly stopping/killing the gateway. The stuck job used the profile-scoped label shapeai.openclaw.<profile>.update.<timestamp>.The existing launchd updater cleanup/detection parser recognized legacy
ai.openclaw.update.*andai.openclaw.manual-update.<digits>labels, but not profile-scoped updater labels. That meant the update CLI startup cleanup did not disable the current updater job, and status/doctor could not reliably surface the stale profile-scoped update job.Summary
ai.openclaw.tayoun.update.20260625T201026-0400.ai.openclaw.dev.team.update.20260625T201026-0400.status/doctor can surface stuck update jobs.KeepAlivefree to rerunopenclaw update --yes.Evidence
Local incident evidence:
update-20260625T201026-0400.logcontained 300Updating OpenClawentries.Update Result: OKentries.Before: 2026.6.1andAfter: 2026.6.10.Before: 2026.6.10andAfter: 2026.6.10.update-20260625T201026-0400.err.logcontained 300 gateway restart/kill entries.ai.openclaw.tayoun.update.20260625T201026-0400.Live macOS launchd proof after this patch:
The proof job was a temporary benign user LaunchAgent using
/bin/sleep 600withKeepAlive=true; it was booted out and removed after the proof capture.Regression coverage added in this PR:
ai.openclaw.tayoun.update.20260625T201026-0400fromlaunchctl list.ai.openclaw.dev.team.update.20260625T201026-0400.findStaleOpenClawUpdateLaunchdJobs().disableCurrentOpenClawUpdateLaunchdJob().Verification run locally:
node scripts/run-vitest.mjs src/daemon/launchd.test.ts— 92 passed.pnpm exec oxfmt --check src/daemon/launchd.ts src/daemon/launchd.test.ts.node scripts/run-oxlint.mjs src/daemon/launchd.ts src/daemon/launchd.test.ts.pnpm tsgo:core.git diff --check.