5 issues raised by code-quality reviewer on c12013a:
A. exec() wrapper now captures stderr from execSync failures and
re-throws with `phase X failed: <stderr>` instead of the terse
"Command failed: ..." default. Operators see the actual git/npm
error.
B. runFullUpgrade body wrapped in try/catch; any error after phase 2
(snapshot written) carries snapshotPath + phases + hint pointing
at `ocp update --rollback`. Aligns with the post-flight failure
pattern.
C. CLI entrypoint now prints snapshotPath + hint on error.
Plus minor:
- snapshot.mjs tryCopy logs a [snapshot] warn line instead of silently
swallowing copy errors (e.g. permission-denied admin-key)
- heads-up window 1s → 3s, more operable per the policy intent
- opts.yes intent comment added (Bundle 3 will use)
One regression test added.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements the upgrade dispatcher (noop / dry-run / light delegation /
full path) and the snapshot writer/reader/list module. Full path snapshots
plist + db + admin-key + openclaw.json before mutating, runs the 6 phases
(pre-flight, snapshot, fetch+install, reconfigure, restart, post-flight),
and emits a heads-up before launchctl bootout per
notify_before_prod_service_restart.md policy.
mockExec/mockDoctor injection points let tests verify the phase ordering
without touching the real shell. fresh_install + rollback paths are
deferred to Bundle 3.
No cli.js citation needed: this is OCP-internal upgrade tooling with no
corresponding cli.js operation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>