Skip to content

feat(update): self-update system — registry check, cron prompt v3, drift nudge, dial-out exit-75 (spec-142) - #32

Merged
antonyevans merged 2 commits into
mainfrom
fix/spec-142-self-update
Jun 12, 2026
Merged

antonyevans merged 2 commits into
mainfrom
fix/spec-142-self-update

Conversation

@antonyevans

Copy link
Copy Markdown
Owner

Keeping installed agents on the latest version

Field state: the fleet rots by default — the live host ran a 0.11.0-pinned notifier for months and a 0.15.1 gateway install after 0.17.1 shipped. Updates required a human-relayed instruction per agent.

Changes

  • edge-book self-update [--if-stale] [--dry-run]: registry check (24h-throttled, offline-silent), install-root self-resolution (refuses system-managed roots), never-downgrade, lockfile with 15-min stale takeover, smoke-verify before success, audit + flight-recorder events.
  • Notifier cron prompt v3: step 0 runs self-update --if-stale — the spec-141 migration machinery rolls this out fleet-wide with no new mechanism; agents then self-update within one cron cycle of any release.
  • Heartbeat drift nudge for cron-less agents under auto_update: "notify".
  • Dial-out drift monitor: on reconnect + 6h timer; under auto_update: "auto" (default) and dialout_respawn_expected !== false, exits 75 (EX_TEMPFAIL) so a supervising gateway respawns onto the new code.
  • Policy: auto_update: auto | notify | off (default auto); pre-1.0 auto across 0.x, post-1.0 cross-major drops to notify.

Verification

  • 495/495 tests (+25 new, red-first); lint/typecheck/build/sync-readme green; registry + npm install mocked throughout.
  • Live-host rig matrix: 16/16 on this branch (incl. direct verification that inbound block enforcement still drops with blocked_peer).

Spec: docs/spec-142-self-update.md.

🤖 Generated with Claude Code

antonyevans and others added 2 commits June 12, 2026 09:39
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nudge, dial-out exit-75

- checkLatest: npm registry /latest query, 3s timeout, 24h throttle
  (update_check_at), cached in update_latest_known, all failures silent
- edge-book self-update [--if-stale] [--dry-run]: resolves the npm prefix
  root from the running module path, refuses unwritable/system roots
  (install_not_self_updatable + manual command), never downgrades, lockfile
  in the install root, smoke-verifies the new build via a --version spawn
  (update_failed on mismatch), audits update.self {from,to} + flight record
  + config updated_at; output tells the agent about the dial-out restart
- edge-book version/--version: the smoke-verify surface
- notifier cron prompt v3: step-0 self-update --if-stale with the npm exec
  fallback; NOTIFIER_PROMPT_VERSION=3 — spec-141 machinery rolls it out
- heartbeat update nudge (update-nudge.ts): fires on known drift under
  notify (or cross-major drift under auto, post-1.0 rule), 24h throttle,
  retires when current, machine surfaces exempt
- dial-out drift monitor (update-drift.ts): running-vs-installed
  package.json on every (re)connect + 6h timer (which also runs the
  throttled registry check); exit 75 only under auto_update=auto with
  dialout_respawn_expected; log-only otherwise
- config: auto_update / update_check_at / update_latest_known /
  update_nudge_at / updated_at / dialout_respawn_expected (types +
  updateConfig allowlist)
- dialout-frames.ts: frame/ack type extraction (size split, re-exported —
  public surface unchanged)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@antonyevans
antonyevans merged commit 4785432 into main Jun 12, 2026
1 check passed

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 72461dd5be

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/self-update.ts
Comment on lines +237 to +239
if (reported !== latest) {
await recordFailure(store, from, latest, `verify_mismatch:${reported}`);
throw new EdgeBookError("update_failed", `update_failed: the new build reports "${reported}" instead of ${latest}; not trusting it. The npm tree at ${root} may need a manual reinstall.`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Prevent restart onto a failed smoke-verified install

When the smoke check reports a mismatch after npm install has already replaced node_modules/edge-book, this path only throws and leaves the new package.json on disk. The dial-out drift monitor compares that on-disk version to the in-memory version and, under the default auto_update: "auto", will exit 75 and be respawned onto exactly the build this check just declared untrusted. This defeats the smoke-verify safety rail for broken publishes; either restore/keep the previous tree or record enough state to suppress drift restarts after a failed verification.

Useful? React with 👍 / 👎.

Comment thread src/self-update.ts
const from = opts.running ?? (await runningVersion());
const config = await store.config();
const mode = config.auto_update ?? "auto";
const latest = await checkLatest(store, { now, fetchImpl: opts.fetchImpl, force: true });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep --if-stale silent when the fresh registry check fails

Because checkLatest(..., force: true) returns the cached update_latest_known on fetch failure, a cron-run self-update --if-stale with an old cached newer version will continue past this line and attempt npm install even when the registry is currently unreachable. That violates the cron-safe behavior described for --if-stale and can make offline/yanked-release scenarios produce repeated failed installs instead of the intended silent no-op.

Useful? React with 👍 / 👎.

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.

1 participant