mirror of
https://github.com/garrytan/gbrain.git
synced 2026-08-14 08:53:22 +00:00
docs: sync documentation for v0.46.0.0
The brain-currency wave shipped new user-facing surface the guides did not carry: the trustworthy autopilot --status exit codes (0/1/2 + paused), the keyless-safe sync-and-embed chain, and the migrate quiesce fence. - docs/guides/live-sync.md: keyless clean-refusal note on the embed --stale primitive; new "gate on the daemon's heartbeat" verify item with the exit-code contract. - docs/guides/cron-schedule.md: the recommended autopilot health-gate cron line (the status classifier already special-cases this monitor line so it never reads as an install). - docs/ENGINES.md: migrate --to now documents the pause-marker mutex, worker job-pickup fence, DB-lock drain (GBRAIN_MIGRATE_QUIESCE_SECONDS, default 300), crash-safe release, and daemon relaunch after the flip. - docs/operations/headless-install.md: keyless mode's "refuse cleanly" claim made concrete — the documented chain exits 0 on a bare stale embed. - INSTALL_FOR_AGENTS.md Step 7: health-gate bullet + keyless-safe chain note. - skills/maintain/SKILL.md: autopilot check now teaches the exit-code semantics and the --json report fields. - docs/TESTING.md: inventory entries for the two new harness-tier serial suites (real-launchd lifecycle, agent-scheduler shell-chain contract). - llms-full.txt regenerated (TESTING.md is inlined in the bundle). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
d2fb2023b8
commit
f43e626c71
@@ -251,7 +251,13 @@ Set up using your platform's scheduler (OpenClaw cron, Railway cron, crontab), o
|
||||
platform glue entirely with `gbrain autopilot --install` (built-in self-maintaining daemon):
|
||||
|
||||
- **Live sync** (every 15 min): `gbrain sync --repo ~/brain && gbrain embed --stale`
|
||||
— or `gbrain sync --watch` for a continuous loop.
|
||||
— or `gbrain sync --watch` for a continuous loop. Safe on keyless brains:
|
||||
a bare `gbrain embed --stale` exits 0 with a stderr note when embeddings
|
||||
are disabled, so the chain doesn't break.
|
||||
- **Health gate** (daily): `gbrain autopilot --status` — exit 0 fresh (or
|
||||
nothing installed), 1 needs attention (stale heartbeat, never ran, or
|
||||
paused), 2 the daemon took itself out of rotation. Filesystem-only, so it
|
||||
works during DB outages.
|
||||
- **Auto-update** (daily): `gbrain check-update --json` (tell user, never auto-install).
|
||||
- **Dream cycle** (nightly): `gbrain dream` runs the 8-phase overnight maintenance cycle.
|
||||
Entity sweep, citation fixes, memory consolidation, plus (v0.23+) overnight conversation
|
||||
|
||||
@@ -177,6 +177,19 @@ live in `test/postgres-engine-rls-scope.test.ts`.
|
||||
|
||||
**Migration:** `gbrain migrate --to supabase` exports everything (pages, chunks, embeddings, links, tags, timeline) and imports into Supabase. `gbrain migrate --to pglite` goes the other direction. Bidirectional, lossless.
|
||||
|
||||
The migration and the autopilot daemon do not race: `migrate --to` claims a
|
||||
cooperative pause marker before touching the target. The marker doubles as a
|
||||
migration mutex — a second concurrent migrate refuses to run, and a marker
|
||||
that cannot be written refuses the migration outright. Background job workers
|
||||
stop picking up new work while it is parked, and the migration waits for
|
||||
in-flight sync/embed/cycle work and running jobs to actually drain (watching
|
||||
the DB lock table, capped by `GBRAIN_MIGRATE_QUIESCE_SECONDS` — default 300;
|
||||
`0` skips the wait). The marker is released even when the migration fails or
|
||||
is killed; `gbrain autopilot --status` reports `paused` (exit 1) while it is
|
||||
parked. After a clean flip the daemon detects the engine change on its next
|
||||
tick and relaunches onto the new engine, and the migration warns if an
|
||||
exported connection-string env var would override the new config.
|
||||
|
||||
### Troubleshooting: startup abort (`RuntimeError: Aborted()`)
|
||||
|
||||
**Symptom:** every PGLite-touching command dies at startup with
|
||||
|
||||
@@ -175,6 +175,8 @@ Unit tests and what they cover:
|
||||
- `test/volunteer-context.test.ts` — push-based context core (#2095), hermetic in-memory PGLite: `parseWindow` lenient `user:`/`assistant:` parsing, multi-turn window extraction, confidence-gated volunteering (arm confidences, multi-turn/newest-turn boosts, `min_confidence` gate, max-pages cap), slug-only suppression, privacy (rationales are deterministic templates; synopses pass the takes/facts fence), and the approximate usage-stats join.
|
||||
- `test/watch-command.test.ts` — `gbrain watch` push transport (#2095): streaming loop, rolling window, session dedupe, `--json` JSONL shape, `channel: 'watch'` event logging, clean EOF return. Hermetic PGLite + injected line/write deps (no subprocess, no real stdin).
|
||||
- `test/watch-sigint.serial.test.ts` — `gbrain watch` SIGINT lifecycle against a real spawned CLI subprocess with a tmpdir brain. SERIAL: parallel unit shards flake on concurrent subprocess spawns (same rationale as `apply-migrations-pglite-spawn.serial.test.ts`).
|
||||
- `test/autopilot-launchd-lifecycle.serial.test.ts` — autopilot lifecycle behavior, not generated-string assertions: the full install → self-disable → status → reinstall → uninstall arc with `launchctl` replaced by an argv recorder and the generated wrapper executed by a REAL bash against a genuinely deleted repo (every platform), plus a darwin-only fail-SKIP describe against the real launchd under a per-run unique label (`GBRAIN_AUTOPILOT_LABEL`) so it can never collide with — or tear down — a real install on the host. Serial: spawns subprocesses and pins HOME/GBRAIN_HOME for the whole file.
|
||||
- `test/agent-scheduler-contract.serial.test.ts` — the documented external agent-scheduler shell chain (`gbrain sync --repo X && gbrain embed --stale`, live-sync.md / INSTALL_FOR_AGENTS.md Step 7) driven end-to-end through a real `/bin/sh` against a keyless PGLite brain: the `&&` short-circuit IS the contract (argv arrays can't exercise it), the keyless bare stale embed exits 0, and the pull-failure case that must break the chain does. Anti-vacuity: the fixture commits a real page and every read-back asserts pages >= 1. Serial: real spawned CLI + tmpdir HOME.
|
||||
- `test/cli-format-volunteer.test.ts` — `formatResult`'s `volunteer_context` human rendering: pointer lines with confidence/arm/rationale, the empty-result message, the approximate stats summary.
|
||||
- `test/config.test.ts` — config redaction.
|
||||
- `test/files.test.ts` — MIME/hash.
|
||||
|
||||
@@ -65,6 +65,12 @@ For scheduling `sync` + `embed --stale` specifically, the home doc is
|
||||
# Brain health — weekly Mondays at 6 AM
|
||||
0 6 * * 1 gbrain doctor --json >> /tmp/gbrain-health.log 2>&1 && gbrain embed --stale
|
||||
|
||||
# Autopilot health gate — daily at 7 AM. The exit code is the signal:
|
||||
# 0 fresh (or nothing installed), 1 needs attention (stale heartbeat,
|
||||
# never ran, or paused), 2 the daemon took itself out of rotation.
|
||||
# Status is filesystem-only, so it works even during a DB outage.
|
||||
0 7 * * * gbrain autopilot --status >> /tmp/gbrain-autopilot-health.log 2>&1 || your-notify "gbrain autopilot needs attention"
|
||||
|
||||
# Dream cycle — nightly at 2 AM
|
||||
0 2 * * * /path/to/dream-cycle.sh
|
||||
```
|
||||
|
||||
@@ -51,6 +51,10 @@ gbrain sync --repo /path/to/brain && gbrain embed --stale
|
||||
[spend controls](../operations/spend-controls.md).
|
||||
- `gbrain embed --stale` -- backfill embeddings for any chunks that don't have
|
||||
them. Safety net for large syncs (>100 files) or prior `--no-embed` runs.
|
||||
On a keyless brain (installed with `--no-embedding`), a bare stale embed
|
||||
refuses cleanly — exit 0 with a stderr note — so this chain is safe to
|
||||
schedule on keyless installs; keyword search keeps working. Explicit embed
|
||||
requests (a slug, `--slugs`, `--all`) still exit 1 on a keyless brain.
|
||||
- `gbrain sync --watch --repo <path>` -- foreground polling loop, every 60s
|
||||
(configurable with `--interval N`). Embeds inline for small changesets. Exits
|
||||
after 5 consecutive failures, so run under a process manager or pair with a
|
||||
@@ -178,6 +182,15 @@ vars — incident-time escape hatches, not everyday knobs.
|
||||
`gbrain embed --stale` isn't running after sync, leaving chunks invisible
|
||||
to vector search.
|
||||
|
||||
4. **Gate on the daemon's heartbeat.** If the built-in daemon runs your sync
|
||||
(`gbrain autopilot --install`), wire your scheduler's health check to
|
||||
`gbrain autopilot --status`. The exit code is the signal: 0 fresh (or
|
||||
nothing installed), 1 needs attention (stale heartbeat, never ran, or
|
||||
paused by a migration), 2 the daemon took itself out of rotation.
|
||||
`--json` emits the full report, including `heartbeat_age_seconds`. Status
|
||||
reads only the filesystem — no database connection — so it keeps working
|
||||
during the exact outages it exists to diagnose.
|
||||
|
||||
---
|
||||
|
||||
*Part of the [GBrain Skillpack](../GBRAIN_SKILLPACK.md).*
|
||||
|
||||
@@ -61,7 +61,7 @@ The runtime `gbrain init --force` re-runs the init flow against the now-populate
|
||||
|
||||
## Pattern 3: No key, ever (keyless mode)
|
||||
|
||||
`--no-embedding` isn't only a deferral — it's also the install shape for **keyless mode**, a first-class supported end state (not a broken one). With zero provider keys, gbrain runs keyword-only (BM25) search and takes memory from agent-authored `## Facts` fences and write ops; embedding and extraction paths refuse cleanly instead of failing silently.
|
||||
`--no-embedding` isn't only a deferral — it's also the install shape for **keyless mode**, a first-class supported end state (not a broken one). With zero provider keys, gbrain runs keyword-only (BM25) search and takes memory from agent-authored `## Facts` fences and write ops; embedding and extraction paths refuse cleanly instead of failing silently. Concretely: the documented always-current chain (`gbrain sync --repo <path> && gbrain embed --stale`) is safe to schedule on a keyless brain — a bare stale embed exits 0 with a stderr note instead of breaking the chain, while explicit embed requests (a slug, `--slugs`, `--all`) still exit 1.
|
||||
|
||||
```dockerfile
|
||||
FROM oven/bun:1
|
||||
|
||||
+39
-1
@@ -1264,7 +1264,13 @@ Set up using your platform's scheduler (OpenClaw cron, Railway cron, crontab), o
|
||||
platform glue entirely with `gbrain autopilot --install` (built-in self-maintaining daemon):
|
||||
|
||||
- **Live sync** (every 15 min): `gbrain sync --repo ~/brain && gbrain embed --stale`
|
||||
— or `gbrain sync --watch` for a continuous loop.
|
||||
— or `gbrain sync --watch` for a continuous loop. Safe on keyless brains:
|
||||
a bare `gbrain embed --stale` exits 0 with a stderr note when embeddings
|
||||
are disabled, so the chain doesn't break.
|
||||
- **Health gate** (daily): `gbrain autopilot --status` — exit 0 fresh (or
|
||||
nothing installed), 1 needs attention (stale heartbeat, never ran, or
|
||||
paused), 2 the daemon took itself out of rotation. Filesystem-only, so it
|
||||
works during DB outages.
|
||||
- **Auto-update** (daily): `gbrain check-update --json` (tell user, never auto-install).
|
||||
- **Dream cycle** (nightly): `gbrain dream` runs the 8-phase overnight maintenance cycle.
|
||||
Entity sweep, citation fixes, memory consolidation, plus (v0.23+) overnight conversation
|
||||
@@ -2230,6 +2236,19 @@ live in `test/postgres-engine-rls-scope.test.ts`.
|
||||
|
||||
**Migration:** `gbrain migrate --to supabase` exports everything (pages, chunks, embeddings, links, tags, timeline) and imports into Supabase. `gbrain migrate --to pglite` goes the other direction. Bidirectional, lossless.
|
||||
|
||||
The migration and the autopilot daemon do not race: `migrate --to` claims a
|
||||
cooperative pause marker before touching the target. The marker doubles as a
|
||||
migration mutex — a second concurrent migrate refuses to run, and a marker
|
||||
that cannot be written refuses the migration outright. Background job workers
|
||||
stop picking up new work while it is parked, and the migration waits for
|
||||
in-flight sync/embed/cycle work and running jobs to actually drain (watching
|
||||
the DB lock table, capped by `GBRAIN_MIGRATE_QUIESCE_SECONDS` — default 300;
|
||||
`0` skips the wait). The marker is released even when the migration fails or
|
||||
is killed; `gbrain autopilot --status` reports `paused` (exit 1) while it is
|
||||
parked. After a clean flip the daemon detects the engine change on its next
|
||||
tick and relaunches onto the new engine, and the migration warns if an
|
||||
exported connection-string env var would override the new config.
|
||||
|
||||
### Troubleshooting: startup abort (`RuntimeError: Aborted()`)
|
||||
|
||||
**Symptom:** every PGLite-touching command dies at startup with
|
||||
@@ -2859,6 +2878,10 @@ gbrain sync --repo /path/to/brain && gbrain embed --stale
|
||||
[spend controls](../operations/spend-controls.md).
|
||||
- `gbrain embed --stale` -- backfill embeddings for any chunks that don't have
|
||||
them. Safety net for large syncs (>100 files) or prior `--no-embed` runs.
|
||||
On a keyless brain (installed with `--no-embedding`), a bare stale embed
|
||||
refuses cleanly — exit 0 with a stderr note — so this chain is safe to
|
||||
schedule on keyless installs; keyword search keeps working. Explicit embed
|
||||
requests (a slug, `--slugs`, `--all`) still exit 1 on a keyless brain.
|
||||
- `gbrain sync --watch --repo <path>` -- foreground polling loop, every 60s
|
||||
(configurable with `--interval N`). Embeds inline for small changesets. Exits
|
||||
after 5 consecutive failures, so run under a process manager or pair with a
|
||||
@@ -2986,6 +3009,15 @@ vars — incident-time escape hatches, not everyday knobs.
|
||||
`gbrain embed --stale` isn't running after sync, leaving chunks invisible
|
||||
to vector search.
|
||||
|
||||
4. **Gate on the daemon's heartbeat.** If the built-in daemon runs your sync
|
||||
(`gbrain autopilot --install`), wire your scheduler's health check to
|
||||
`gbrain autopilot --status`. The exit code is the signal: 0 fresh (or
|
||||
nothing installed), 1 needs attention (stale heartbeat, never ran, or
|
||||
paused by a migration), 2 the daemon took itself out of rotation.
|
||||
`--json` emits the full report, including `heartbeat_age_seconds`. Status
|
||||
reads only the filesystem — no database connection — so it keeps working
|
||||
during the exact outages it exists to diagnose.
|
||||
|
||||
---
|
||||
|
||||
*Part of the [GBrain Skillpack](../GBRAIN_SKILLPACK.md).*
|
||||
@@ -3063,6 +3095,12 @@ For scheduling `sync` + `embed --stale` specifically, the home doc is
|
||||
# Brain health — weekly Mondays at 6 AM
|
||||
0 6 * * 1 gbrain doctor --json >> /tmp/gbrain-health.log 2>&1 && gbrain embed --stale
|
||||
|
||||
# Autopilot health gate — daily at 7 AM. The exit code is the signal:
|
||||
# 0 fresh (or nothing installed), 1 needs attention (stale heartbeat,
|
||||
# never ran, or paused), 2 the daemon took itself out of rotation.
|
||||
# Status is filesystem-only, so it works even during a DB outage.
|
||||
0 7 * * * gbrain autopilot --status >> /tmp/gbrain-autopilot-health.log 2>&1 || your-notify "gbrain autopilot needs attention"
|
||||
|
||||
# Dream cycle — nightly at 2 AM
|
||||
0 2 * * * /path/to/dream-cycle.sh
|
||||
```
|
||||
|
||||
@@ -195,6 +195,13 @@ Verify autopilot is running:
|
||||
```bash
|
||||
gbrain autopilot --status
|
||||
```
|
||||
The exit code is trustworthy for gating: 0 fresh (or nothing installed),
|
||||
1 needs attention (stale heartbeat, never ran, or paused by a migration),
|
||||
2 the daemon disabled itself (its repo path vanished). `--json` emits the
|
||||
full report (`state`, `heartbeat_age_seconds`, `paused_reason`,
|
||||
`disabled_reason`). Status reads only the filesystem, so it works even
|
||||
when the database is down.
|
||||
|
||||
If not running, install it:
|
||||
```bash
|
||||
gbrain autopilot --install --repo ~/brain
|
||||
|
||||
Reference in New Issue
Block a user