Skip to content

v0.42.12.0 feat: self-upgrading gbrain — invocation-riding update check + opt-in auto-upgrade#1798

Merged
garrytan merged 9 commits into
masterfrom
garrytan/gbrain-upgrade-cron
Jun 3, 2026
Merged

v0.42.12.0 feat: self-upgrading gbrain — invocation-riding update check + opt-in auto-upgrade#1798
garrytan merged 9 commits into
masterfrom
garrytan/gbrain-upgrade-cron

Conversation

@garrytan

@garrytan garrytan commented Jun 3, 2026

Copy link
Copy Markdown
Owner

What this ships

Self-upgrading gbrain, modeled on how gstack stays current: an update check that rides every invocation instead of installing a cron. Every gbrain command becomes a heartbeat — on a new release it prints a one-line nudge to stderr, and gbrain self-upgrade applies it. Works identically across Claude Code, Codex, OpenClaw, Hermes, and Perplexity because they all run gbrain. No per-agent capability detection.

Default is notify (a nudge, never a surprise). Always-on installs opt into hands-off auto with one line: gbrain config set self_upgrade.mode auto.

Architecture (two channels, one shared state)

  • Channel 1 — invocation marker (universal): check-update gains gstack-style cache + escalating snooze + markers. cli.ts emits the marker on startup, cache-read-only on the hot path (statSync+read, sub-ms; a warm gbrain search is not slower); the network refresh is detached + single-flighted and never blocks a command. Skip-set + GBRAIN_SKIP_STARTUP_HOOKS recursion guard + NODE_ENV=test gate. Surfaced on get_brain_identity (_meta) too.
  • Channel 2 — autopilot silent channel (opt-in auto): applies only during quiet hours, only when idle (no jobs / no in-flight requests), only after a post-upgrade gbrain doctor passes. swap-only + pre-swap breadcrumb + exit-for-relaunch. Bun has no execve, so the daemon relies on supervisor relaunch: installSystemd now writes Restart=always, and gbrain upgrade rewrites an existing Restart=on-failure unit in place (only when it matches the generated template; hand-edited units are left alone).
  • Real atomic binary self-update (src/core/binary-self-update.ts) for macOS-arm64 / Linux-x64: download → fsync → smoke (--version) → atomic rename over the running binary. Any failure leaves the old binary intact; no half-written brick path. Other platforms degrade to notify.

auto is opt-in everywhere (no magical headless classification). Trust = TLS + GitHub, same as the existing gbrain upgrade; the marker action is the hardcoded command (forged-marker-proof) and the version is regex + monotonic validated (no downgrade-as-upgrade).

Per-agent behavior

Agent What happens Default
Claude Code / Codex nudge on stderr → gbrain self-upgrade notify
OpenClaw / Hermes daemon nudge; auto for hands-off notify
gbrain serve host nudge; auto for hands-off (idle-gated) notify
Perplexity / thin client nudge is informational; server self-upgrades n/a

Reviews

Plan went through /plan-ceo-review (SELECTIVE EXPANSION), /codex outside-voice (drove auto from default to opt-in everywhere; 11 hardenings folded), and /plan-eng-review (caught: Bun has no execve → supervisor-relaunch + systemd fix is load-bearing; the prior "atomic swap" claim was unowned → now a real binary self-update). Ship-time Codex review of the diff: no P1 blockers; one P3 fixed in this PR (the JUST_UPGRADED confirmation path was dead — nothing wrote just-upgraded-from; now written after a successful swap + stale cache/snooze cleared).

Tests

New: pure decision matrix, atomic cache/snooze, marker grammar (forged-marker rejection), canSelfUpdate platform/arch matrix, breadcrumb reconcile, a real-HTTP-server binary-swap E2E (test/e2e/self-upgrade-binary-swap.test.ts — real download + real execFileSync smoke + real atomic rename + --version round-trip, plus smoke-fail/404/empty/no-asset/unsupported keeps-old-binary cases), and a network-stubbed refresh-orchestration serial test. typecheck clean, bun run verify 29/29, all affected + new test files green. (The 4-shard parallel suite OOMs on this box; verified via the affected-file subset + the one full run that completed.)

Deferred (TODOS.md)

P2 signature/checksum verification (the prerequisite before auto could ever be a default), P2 serve graceful request-drain, P3 Windows binary self-update, P3 true rollback.

Note

Branch is garrytan/gbrain-upgrade-cron but the Conductor workspace is tel-aviv-v4; left as-is per the no-unprompted-rename rule. Rename + recreate if the Conductor PR view needs it.

🤖 Generated with Claude Code

garrytan and others added 9 commits June 2, 2026 21:59
…self-update

Pure decideSelfUpgrade (invocation + autopilot channels), atomic untrusted
cache + escalating snooze + shared marker grammar (forged-marker rejection),
semver helpers, and real darwin-arm64/linux-x64 binary self-update
(download -> fsync -> smoke -> atomic rename; failure leaves old binary intact).
Tests incl. real-HTTP-server swap E2E.
… CLI heartbeat hook

check-update gains gstack-style cache/snooze/markers + refreshUpdateCache +
exported fetchLatestRelease. New 'gbrain self-upgrade' command. cli.ts emits the
update marker on every invocation (cache-read-only hot path, detached
single-flight refresh, skip-set + recursion guard + NODE_ENV=test gate).
…grade setup, config + identity marker

autopilot opt-in silent channel (auto+quiet+idle, swap-only+breadcrumb+exit-relaunch)
+ installSystemd Restart=always + migrateSystemdUnitToRestartAlways. doctor
self_upgrade_health. runPostUpgrade applySelfUpgradeSetup (one-time consent +
systemd rewrite). init defaults mode=notify. config self_upgrade plane +
KNOWN_CONFIG_KEYS. get_brain_identity carries update marker.
…to-update doc reversal, HEARTBEAT

New skills/gbrain-upgrade agent flow (mirror gstack-upgrade) wired into RESOLVER +
manifest. upgrades-auto-update.md reversed to document opt-in auto + conservative
gates. HEARTBEAT self-upgrade --check-only line. llms-full regenerated.
Self-upgrading gbrain: invocation-riding update marker + opt-in autopilot
silent channel + real atomic binary self-update. Mirrors gstack's mechanism.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…cache after upgrade

Codex ship-review P3: the CLI startup hook reads just-upgraded-from to print the
one-time JUST_UPGRADED confirmation, but nothing wrote it — dead path. runUpgrade
now writes the breadcrumb (covers full + --swap-only) and clears the update-check
cache + snooze so a now-applied 'upgrade available' marker stops nudging.
…rade-cron

# Conflicts:
#	CHANGELOG.md
#	TODOS.md
#	VERSION
#	package.json
…tion (AGENTS.md, HEARTBEAT) + e2e

- self-upgrade --check-only --json now includes changelog_diff + release_url
  (export fetchChangelog); the gbrain-upgrade skill shows 3-5 what's-new bullets
  before the 4-option prompt instead of just version numbers.
- setup injects a self-upgrade marker protocol into AGENTS.md so interactive
  agents (Claude Code, Codex) act on the UPGRADE_AVAILABLE stderr marker — the
  piece that makes notify actually fire for them.
- HEARTBEAT daily beat routes through the gbrain-upgrade skill (OpenClaw/Hermes
  cron cadence); auto-mode daemons ride the autopilot tick.
- e2e: real subprocess invocation proves the marker fires (notify emits;
  off/snooze/up-to-date silent; JUST_UPGRADED fires+clears; --quiet suppresses).
  Serial test: --check-only surfaces the changelog.
@garrytan garrytan merged commit a57d98b into master Jun 3, 2026
21 checks passed
mgunnin added a commit to mgunnin/gbrain that referenced this pull request Jun 3, 2026
* upstream/master:
  v0.42.23.0 feat(jobs): --nice scheduling-priority flag for jobs work/supervisor (garrytan#1815) (garrytan#1820)
  v0.42.22.0 fix(minions): supervisor progress watchdog + worker DB self-defense — alive-but-wedged worker self-heals (garrytan#1801) (garrytan#1824)
  v0.42.21.0 fix(postgres): module-singleton ownership — canonical landing for the dream-cycle "connect() has not been called" class (garrytan#1404/garrytan#1471/garrytan#1619) (garrytan#1805)
  v0.42.20.0 fix: reliability wave — PGLite capture lock-pin + Postgres reconnect race + search embed-hang (garrytan#1762 garrytan#1745 garrytan#1775) (garrytan#1810)
  v0.42.19.0 fix(skillopt): close the last gap in the AI SDK v6 tool-loop fix (write-capture mapper + regression test) (garrytan#1809)
  v0.42.18.0 fix: sync orphan-pileup watchdog (garrytan#1633) + links-lag µs stamp (garrytan#1768) (garrytan#1807)
  v0.42.17.0 fix(sync): resumable incremental sync — killed mid-import no longer loses progress (garrytan#1794) (garrytan#1808)
  v0.42.16.0 feat(doctor): brain health as a solved problem — cause-ranked doctor + OOM-loop line + auto-drain + pool-reap (garrytan#1685) (garrytan#1802)
  v0.42.15.0 fix: decouple CLI primary output from process.stdout.isTTY (garrytan#1784) (garrytan#1806)
  v0.42.14.0 fix(zero-config): code-* readiness signal + init embedding-key validation + lock self-heal (garrytan#1780) (garrytan#1804)
  v0.42.13.0 fix(search): archive/ content findable by default, demoted not hard-excluded (garrytan#1777) (garrytan#1797)
  v0.42.12.0 feat: self-upgrading gbrain — invocation-riding update check + opt-in auto-upgrade (garrytan#1798)
  v0.42.11.0 feat(skillopt): held-out eval gate, honest receipts, ENFORCE + ablation opts (garrytan#1759)
  v0.42.10.0 feat(extract): opt-in global-basename wikilink resolution (closes garrytan#972) (garrytan#1388)
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