* feat(self-upgrade): decision/cache/snooze foundation + atomic binary 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. * feat(self-upgrade): check-update cache/markers, self-upgrade command, 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). * feat(self-upgrade): autopilot silent channel, doctor check, runPostUpgrade 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. * docs(self-upgrade): gbrain-upgrade agent skill, RESOLVER/manifest, auto-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. * chore: bump version and changelog (v0.42.12.0) 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> * fix(self-upgrade): write just-upgraded-from breadcrumb + clear stale 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. * feat(self-upgrade): surface what's-new in notify + wire agent integration (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. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
8.6 KiB
Upgrades and Auto-Update Notifications
Goal
Users get notified of new GBrain features conversationally, and the agent walks them through upgrading with post-upgrade migrations that make the new version actually work.
What the User Gets
Without this: GBrain ships updates but nobody knows. The user stays on an old
version with stale skills and missing features. Or worse, someone runs
gbrain upgrade but skips the post-upgrade steps, leaving new code with old
agent behavior.
With this: the agent checks for updates daily, sells the upgrade with punchy benefit-focused bullets, waits for explicit permission, then runs the full upgrade flow including re-reading skills, running migrations, and syncing schema. The user gets new capabilities automatically.
Self-upgrade modes (v0.42)
gbrain now stays current the way gstack does: it rides invocation frequency. A
throttled, cache-read-only check runs at the start of every gbrain invocation
(CLI and MCP) and emits an UPGRADE_AVAILABLE <old> <new> marker on stderr. No
host cron required — every agent kind (Claude Code, Codex, OpenClaw, Hermes, the
gbrain serve host behind a Perplexity thin client) converges to current by
construction. The behavior is governed by one file-plane config key,
self_upgrade.mode:
| Mode | Behavior | Who it's for |
|---|---|---|
notify (default) |
Emit the marker + a 4-option prompt; never apply without confirmation. | Interactive installs / anyone with a human in the loop. |
auto (opt-in) |
Apply silently, but ONLY during quiet hours, ONLY when the brain is idle, doctor-gated, and never re-trying a known-bad version. | Headless / always-on installs (autopilot daemon, the gbrain serve host). |
off |
Never check. | Air-gapped / pinned installs. |
Enable hands-off upgrades on an always-on install with one line:
gbrain config set self_upgrade.mode auto
auto is deliberately NOT a default anywhere — it's an explicit autonomy grant,
because applying code from GitHub unattended is, by design, remote code
execution. The trust model is TLS + GitHub (same as gbrain upgrade);
signature verification is a tracked follow-up. Apply manually any time with
gbrain self-upgrade.
Implementation
The Check (cron-initiated)
check_for_update():
result = run("gbrain check-update --json")
if not result.update_available:
exit_silently() // do NOT message the user
// Sell the upgrade — lead with what they can DO, not what changed
message = compose_upgrade_message(
current: result.current_version,
latest: result.latest_version,
changelog: result.changelog
)
send_to_user(message, respect_quiet_hours=true)
The Upgrade Message
Sell the upgrade. The user should feel "hell yeah, I want that." Lead with what they can DO now that they couldn't before, not what files changed.
> **GBrain v0.5.0 is available** (you're on v0.4.0)
>
> What's new:
> - Your brain never falls behind. Live sync keeps the vector DB current
> automatically, so edits show up in search within minutes
> - New verification runbook catches silent failures before they bite you
> - New installs set up live sync automatically. No more manual setup step
>
> Want me to upgrade? I'll update everything and refresh my playbook.
>
> (Reply **yes** to upgrade, **not now** to skip, **weekly** to check
> less often, or **stop** to turn off update checks)
Handling Responses
| User says | Action |
|---|---|
| yes / y / sure / ok / do it / upgrade | Run the full upgrade flow (below) |
| not now / later / skip / snooze | Acknowledge, check again next cycle |
| weekly | Store preference, switch cron to weekly |
| daily | Store preference, switch cron back to daily |
| stop / unsubscribe / no more | Disable the cron. Tell user how to resume |
In notify mode (the default), never auto-upgrade — always wait for explicit
confirmation. The auto mode (opt-in, see "Self-upgrade modes" above) is the
only path that applies without a prompt, and only under its conservative gates
(quiet hours + idle + doctor-gate). This per-cron-prompt flow is the notify
experience.
The Full Upgrade Flow (after user says yes)
full_upgrade():
// Step 1: Update the binary/package
run("gbrain upgrade")
// Step 2: Re-read all updated skills
for skill in find("skills/*/SKILL.md"):
read_and_internalize(skill) // updated skills = better agent behavior
// Step 3: Re-read production reference docs
read("docs/GBRAIN_SKILLPACK.md")
read("docs/GBRAIN_RECOMMENDED_SCHEMA.md")
// Step 4: Check for version-specific migration directives
for version in range(old_version, new_version):
migration = find(f"skills/migrations/v{version}.md")
if migration exists:
read_and_execute(migration) // in order, don't skip
// Step 5: Schema sync — suggest new, respect declined
state = read("~/.gbrain/update-state.json")
for recommendation in new_schema_recommendations:
if recommendation not in state.declined:
suggest_to_user(recommendation)
update(state, new_choices)
// Step 6: Report what changed
summarize_to_user(actions_taken)
Migration Files
Migration files live at skills/migrations/vX.Y.Z.md. They contain agent
instructions (not scripts) for post-upgrade actions that make the new version
work for existing users. Example: v0.5.0 migration sets up live sync and
runs the verification runbook.
The agent reads migration files in version order and executes them step by step. Without migrations, the agent has new code but the user's environment hasn't changed.
Cron Registration
Name: gbrain-update-check
Default schedule: 0 9 * * * (daily 9 AM)
Weekly schedule: 0 9 * * 1 (Monday 9 AM)
Prompt: "Run gbrain check-update --json. If update_available is true,
summarize the changelog and message me asking if I'd like to upgrade.
If false, stay silent."
Frequency Preferences
Default: daily. Store in agent memory as gbrain_update_frequency: daily|weekly|off.
Also persist in ~/.gbrain/update-state.json so it survives agent context resets.
Standalone Skillpack Users
If you loaded this SKILLPACK directly (copied or read from GitHub) without installing gbrain, you can still stay current. Both GBRAIN_SKILLPACK.md and GBRAIN_RECOMMENDED_SCHEMA.md have version markers:
curl -s https://raw.githubusercontent.com/garrytan/gbrain/master/docs/GBRAIN_SKILLPACK.md | head -1
# Returns: <!-- skillpack-version: X.Y.Z -->
If the remote version is newer, fetch the full file and replace your local copy. Set up a weekly cron to check automatically.
Tricky Spots
-
In
notifymode, never auto-install. The upgrade waits for the user's explicit "yes." Even if the check detects an update and the changelog looks great, the agent messages the user and waits. Theautomode (opt-in) exists for headless/always-on installs where there's no human to prompt — it applies only during quiet hours, only when idle, doctor-gated, never retrying a known-bad version. Don't enableautoon an interactive workstation; the prompt-firstnotifyflow is the right default there. -
Migration files are agent instructions, not scripts. They tell the agent what to do step by step in plain language. They are NOT bash scripts to execute blindly. The agent reads them, understands the context, and adapts to the user's specific environment (e.g., skip a step if the user already has live sync configured).
-
check-update should run on a daily cron. Don't rely on the user remembering to check for updates. The cron runs
gbrain check-update --jsondaily at 9 AM (respecting quiet hours). If there's nothing new, it stays completely silent. The user only hears about updates when there IS something worth upgrading to.
How to Verify
-
Run check-update and verify detection. Execute
gbrain check-update --json. Verify it returns the current version and correctly reports whether an update is available. Ifupdate_availableis false, verify the version matches the latest release on GitHub. -
Verify migration files are readable. List
skills/migrations/and check that each file follows the naming conventionvX.Y.Z.md. Open one and verify it contains step-by-step agent instructions, not raw scripts. The agent should be able to read and execute each step. -
Test the full upgrade flow end-to-end. If an update is available, say "yes" and watch the agent execute the full flow: upgrade, re-read skills, run migrations, sync schema, report. Verify each step completes and the agent reports what changed.
Part of the GBrain Skillpack.