garrytan/gbrainmarkdown explorer
garrytan/gbrainmaster
skills / migrations

v0.11.0

skills/migrations/v0.11.0.md


version: 0.11.0 feature_pitch: headline: "GBrain Minions — durable background agents" description: "Turn any long-running agent task into a durable job that survives gateway restarts, streams progress, and can be paused, resumed, or steered mid-flight. Postgres-native, zero infra beyond your existing brain. Replaces flaky subagent spawns for multi-step work, parallel fan-out, and anything the user might ask about later." recipe: null tiers: null

v0.11.0 Migration: Minions — host-agent instruction manual

Audience: host agents (OpenClaw deployments, future hosts) reading this AFTER gbrain apply-migrations has run its mechanical phases. The orchestrator in src/commands/migrations/v0_11_0.ts is the runtime source of truth for the mechanical work (schema, smoke, prefs, built-in cron rewrites, autopilot install). This file tells the host agent how to finish the host-specific work that can't be done host-agnostically.

Check what gbrain left you

cat ~/.gbrain/migrations/pending-host-work.jsonl

Empty? You're done. The migration is complete; nothing for you to do.

Non-empty? Each line is a TODO. Each type routes to a section below.

type: cron-handler-needs-host-registration

Gbrain rewrites cron entries whose handler name matches a gbrain builtin (sync, embed, lint, import, extract, backlinks, autopilot-cycle). For host-specific handlers (e.g. ea-inbox-sweep, frameio-scan, x-dm-triage, calendar-sync on your OpenClaw), gbrain leaves the manifest alone and emits a TODO with shape:

{
  "type": "cron-handler-needs-host-registration",
  "handler": "ea-inbox-sweep",
  "cron_schedule": "0 */30 * * *",
  "manifest_path": "/path/to/cron/jobs.json",
  "current_cmd": "agentTurn ea-inbox-sweep",
  "recommendation": "Add a handler registration for ...",
  "status": "pending"
}

Each TODO is a full skillify, not a drive-by handler add. A properly migrated cron meets every one of these gates before its JSONL row gets marked complete:

(a) Plugin contract

Read docs/guides/plugin-handlers.md. Add a worker.register() call in your host's worker bootstrap:

import { MinionQueue, MinionWorker } from 'gbrain/minions';
const worker = new MinionWorker(engine, { queue: 'default' });
worker.register('ea-inbox-sweep', async (ctx) => {
  // Host-specific agent turn.
});
// ...register every TODO handler...
await worker.start();

(b) Ship the bootstrap in your host repo

Autopilot already spawns gbrain jobs work as a child. Configure it to spawn your custom worker binary (e.g. your-openclaw-worker) instead, or register handlers as a side-effect module that the stock worker loads on startup. Either path is documented in plugin-handlers.md.

(c) Unit tests for the handler body

Mock the LLM. Assert the happy path, the empty-input path, the network-timeout path, the LLM-failure path. Every branch of the handler's deterministic logic has a unit test.

(d) Integration tests

Submit a real Minion job against your test environment. Assert:

  • The job completes (not dead-lettered).
  • The side effects happen (brain pages written, external API called).
  • The result shape matches what your cron consumers expect.

(e) LLM evals

Whatever prompt the handler runs, add a case in your eval suite. At minimum: one happy case, one edge case, one adversarial case. If the handler's job is "sweep the EA inbox," the eval asserts urgent items surface and routine items don't.

(f) Resolver trigger update

The host's AGENTS.md dispatcher used to reference the skill name (ea-inbox-sweep) as an agentTurn route. Rewrite that route to submit_job with the same trigger phrases — the user-facing language doesn't change; the execution path does.

(g) Resolver trigger eval

Add a test: feed each trigger phrase to the resolver, assert it routes to the new submit_job path, not the old agentTurn. Without this test, your router can silently keep old behavior and nobody notices until the cron quietly breaks.

(h) E2E smoke

One test that exercises the full pipeline: scheduler → gbrain jobs submit → worker claim → handler body → side effect. Gated by your host's E2E DB fixture.

(i) Brain filing

If the handler writes brain pages, brain/RESOLVER.md needs an entry for the directory. Orphaned brain pages are worse than no brain pages — nobody can find them on read.

(j) check-resolvable

Run gbrain check-resolvable. It validates reachability (is the skill mentioned from RESOLVER.md?), MECE overlap, DRY, gap detection. If it fails, fix the skill or extend an existing one instead of creating a duplicate.

Finalize

When all ten gates are green for a handler:

gbrain apply-migrations --yes

The orchestrator detects the newly-registerable handler, rewrites the cron entry from agentTurn ea-inbox-sweep to gbrain jobs submit ... with the right engine-aware form (PGLite uses --follow; Postgres uses fire-and-forget + --idempotency-key), and marks the JSONL row status: "complete".

Iron rule: scripts/skillify-check.ts <handler-code-path> must return 10/10 before you mark a handler migrated. No partial-credit "we'll add tests later." See skills/skillify/SKILL.md for the meta.

type: agents-md-dispatcher-needs-host-review

Gbrain injects a marker into each AGENTS.md pointing to skills/conventions/subagent-routing.md. But if your dispatcher has inline sessions_spawn routing logic (custom branching on tool names or intent patterns), that's not a mechanical rewrite — it involves host judgment about which routes should flip to submit_job and which should stay on sessions_spawn for real-time tasks.

Read skills/conventions/subagent-routing.md. Walk your dispatcher's sessions_spawn blocks. For each one, decide:

  • Brain-write, multi-step, user will ask later → route through submit_job (Minions).
  • Real-time, user waiting, < 30s → keep on sessions_spawn.
  • Somewhere in betweenminion_mode: pain_triggered is the right default; let the convention's pain signals decide.

Mark the JSONL row status: "complete" by appending a new line with the same shape + updated status. Or: edit the dispatcher, rerun gbrain apply-migrations, and let gbrain re-detect + update automatically (it dedupes on file path, so no duplicate rows).

When every TODO clears

gbrain apply-migrations --list

Should show v0.11.0 as applied. Your host is fully migrated to Minions. Autopilot is dispatching through the queue, cron jobs are durable, and every handler you registered appears in worker.registeredNames on next worker startup.

  • skills/migrations/index.ts (code, not file) — the TS registry the runtime consults; apply-migrations --list reads from here, not from this markdown file.
  • skills/conventions/cron-via-minions.md — the rewrite pattern gbrain applies for builtins + the one your host ships for custom handlers.
  • skills/conventions/subagent-routing.md — runtime dispatcher rules (native subagent vs Minion) that AGENTS.md should reference.
  • docs/guides/plugin-handlers.md — the plugin contract for host handler registration.
  • skills/skillify/SKILL.md — the 10-item checklist every handler must pass before its JSONL row clears.
  • scripts/skillify-check.ts — machine-readable version of the checklist; use with --json in CI.
  • docs/guides/minions-fix.md — user-facing troubleshooting for broken-v0.11.0 installs that never ran the migration at all.
Continue exploring589 Markdown documents in the local repository