v0.47.4.0 fix(tests): the test-gap closure wave — 52 new suites, registry ratchets, fail-closed remote-surface hardening (#4654)
- fix(ops): route salience/anomaly/contradiction reads through source scope
get_recent_salience, find_anomalies, and find_contradictions now honor the caller’s source scope like every other read op: SalienceOpts/AnomaliesOpts carry sourceId/sourceIds (array wins over scalar), both engines filter in lockstep, the ops spread sourceScopeOpts(ctx), and a contradictions finding surfaces only when both endpoints resolve inside the caller’s scope. New two-source isolation suite with anti-vacuity controls; the contradictions op-mechanics fixture moves to a trusted local brain-wide ctx. types.ts ratchet ceiling raised 1882->1890 for the two documented opts fields.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- fix(ops): stable error codes + gate suite for run_skillopt
Four throw sites passed (message, code) into the (code, message) OperationError constructor, so remote callers matched on prose instead of stable codes (the open ErrorCode union hid it from tsc). Args swapped; a serial-lane suite pins the name validation, the remote allowlist deny-all default (incl. malformed config), the local bypass, and the caller-supplied path confinement incl. the symlinked-skills-dir acceptance branch — with the optimizer stubbed via mock.module so no real LLM run can launch from tests.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- fix(ops): extend job-envelope credential redaction to cancel/retry + registry sweep
cancel_job/retry_job now apply the same private_queue_owner_token redaction as get_job/list_jobs. The suite gains both ops’ redaction + null-passthrough cases and a registry-driven sweep: every id-taking jobs op is dispatched against token-bearing fixtures in two statuses and its whole envelope must never carry the raw capability — a new jobs op is swept automatically.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- fix(schema-pack): validate pack names before any path resolution
locateMutablePackFile now requires kebab-case pack names (new INVALID_PACK_NAME error code) before joining them into the schema-packs directory; both applyMutationsAtomic entry points route through it and the guard’s message never echoes a resolved path. Confinement suite covers the rejection matrix, the preserved PACK_READONLY bundled contract, a positive-accept fork-shape name, and a byte-identical sentinel above the packs dir.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(ops): pin run_onboard scope gate, spend cap, and check-mode contracts
Serial suite (mock.module on the dynamic runAllOnboardChecks import) pins: protected jobs land in skipped_missing_scope without the extra grant, the grant admits them, auto modes refuse without max_usd, check mode never submits, and probe failures degrade open. Also pins that the run_protected_onboard literal is absent from ALLOWED_SCOPES_LIST — making that grant mintable is a capability-model change that must arrive as its own reviewed decision, not a drive-by.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- fix(conversation-parser): confine raw_transcript sidecar reads to the sync repo
Frontmatter-supplied transcript paths are ingested content, not trusted config: absolute paths are refused, relative paths must realpath-resolve inside sync.repo_path (symlinks included), and refusals emit one class-only warn before falling back to the summary body. Suite covers the refusal matrix, legit nested sidecars (incl. under a symlinked repo path), and the compiled/timeline summary join.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(fuzz): make the upload-path confinement properties actually bite
The fs-backed validateUploadPath properties passed their arguments in the wrong order and swallowed every throw, so the traversal and symlink cases proved nothing. Candidates now join into the box with the box as root, any RETURNED path must live inside the box’s realpath, and a new strict:false block pins loose-mode resolution plus the always-on final-component symlink rejection.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- fix(minions): settle embed-backfill spend into the per-client ledger
recordMinionJobSpend/getJobClientId existed but had no callers, so the per-client daily spend cap enforced against a ledger generic handlers never wrote. embed-backfill now settles the tracker’s spend in its finally block — every exit path, ceil’d to cents, attributed to job.data.client_id (NULL for local submissions), best-effort so telemetry can never fail the job. Suite drives the real AsyncLocalStorage tracker seam.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- ci(e2e): PR-time selected-e2e lane driven by select-e2e + wiring guard
New selected-e2e job runs the diff-relevant e2e files on every push/PR: scripts/select-e2e.ts picks them (fail-closed — uncertain diffs emit ALL, selector failure fails the job), named-job and live-key files are excluded with a loud per-file echo, the job carries no repository secrets so fork PRs run it natively, and scheduled runs early-exit green (the nightly full glob already covers them and cache-writes depend on success()). Wired into e2e-cache-write and e2e-status. The wiring test pins all of that plus a shrink-only unmapped-file baseline: a new e2e file must be mapped in e2e-test-map.ts or consciously baselined, and map entries must point at real files.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(ops): satisfy required OperationContext.sourceId in contradictions fixture
Follow-up to the salience/contradiction scoping commit: OperationContext declares sourceId as a required member; the brain-wide fixture ctx now carries an explicitly-unset value (sourceScopeOpts treats falsy as unscoped) instead of omitting the key.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- feat(test): registry-walking source-isolation matrix + sources_status scope fence
Every non-localOnly read op now carries an explicit disposition in one matrix suite: isolated (scoped callers see nothing from other sources, with an anti-vacuity control ladder that must SEE the foreign marker before the scoped assertions count), brain-wide (rationale string required), or skip (reason + owning suite). The table is ratcheted against the registry, so a new read op fails until classified. sources_status now answers not_found for out-of-scope source ids (anti-enumeration, matching get_agent_job’s uniform envelope).
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(ops): op-coverage ledger ratchet + shared registry enumeration helper
Every op in the registry must map to a covering test file (existence + op-name mention verified) or sit on a shrink-only UNCOVERED allowlist (seeded with the 8 ops that genuinely have zero text-level hits today). The jobs redaction sweep and the ledger now share one registry enumeration helper so the two walkers cannot drift.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(ops): derive the localOnly snapshot + fs/child_process inverse scan
KNOWN_LOCAL_ONLY was a stale hand-rolled list (missing two ops that had since gone localOnly); it is now derived from the registry and pinned to a sorted literal that catches both additions and drops. New inverse assertion: any ops module with a top-level fs/child_process import may only contribute localOnly ops or reasoned exemptions (empty today), with regex self-tests so the scan itself can’t rot green.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(sync): pin lock-busy classification in both consumers
A held per-source sync lock must classify as skipped, never failed: the minion sync handler resolves {skipped, reason:’sync_in_progress’} with the job completing, and the cycle sync phase reports status ‘skipped’ with syncStatus ‘lock_busy’ — each pinned end-to-end through the real worker/cycle with a non-lock red control proving the classifier can fail. formatLockBusyMessage’s holder/remediation text and its degraded legacy path are pinned too.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(storage): first behavioral suites for the Supabase/S3 backends + injection seams
Both storage classes gain an optional constructor-injected transport seam (fetch impl / S3 client; defaults unchanged) so the previously untested backends run in the fast loop: the signed-URL prefix ladder, TUS-vs-POST size routing, server-offset TUS resume, delete/exists error taxonomies, ETag dequoting, and list URL joins are all pinned, with real-vs-assumed behavior differences documented in the tests.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- fix(serve): rate-limit the admin auth entry points + real-server scope-gate sweep
The admin login and magic-link issuance routes now sit behind the same per-IP limiter that already guarded magic-link consumption (red-first: the exhaustion test failed before the attach), with the happy path pinned so a correct token below the limit still succeeds. The oauth e2e gains the real-server enforcement sweep: insufficient-scope envelopes + denied_after_list request-log rows, the agent-scope request_tools carve-out, scope-filtered tools/list, success_with_warnings rows, and tool_count logging.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(e2e): cross-engine INDEX parity via the dormant schema-diff helpers
schema-drift now snapshots and diffs the full index set between fresh PGLite and Postgres boots (two documented one-sided allowlist entries), asserts each allowlist entry stays genuinely one-sided, and pins the three ON-CONFLICT-load-bearing unique indexes by name and definition on BOTH engines.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(e2e): whole-brain migrate-engine journey PGLite -> Postgres
The previous coverage stopped at copyMigrationSources; this drives the full runMigrateEngine transfer against real Postgres: exact per-table row parity, jsonb columns land as objects (never double-encoded strings), 1536-d vectors survive with a NULL-embedding control, the facts id sequence accepts fresh inserts post-migration, config-plane rows copy with the engine row denylisted, the file config flips, and the manifest clears. The failure arm runs the real CLI in a child process (the entrypoint exits the process on validation failures) and proves config did NOT flip and the source brain is intact. Mapped in e2e-test-map so the selected-e2e lane runs it on migrate-engine diffs.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- feat(guards): runtime-reachability orphan-module guard with a test-only tier
New self-tested scanner walks static + dynamic relative imports from the runtime entrypoints (CLI, MCP server, plugin engines, embedded admin) plus every package.json exports target: a src module unreachable from every entrypoint AND every test hard-fails unless it carries a reasoned allowlist entry (4 seeded, each with rationale; a stale entry fails the guard), and the 46 modules today reachable only from tests ride a shrink-only count ratchet so the tier can’t quietly grow. knip v5 was evaluated first per the boring-by-default rule and rejected with evidence (hard crash on this repo layout; rationale in the script header). Registered in guards-manifest with bad/good fixtures — including a dynamic-import-only module in the good tree so the lazy-seam form stays counted — and wired into the verify battery.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- fix(ops): authenticated sender identity for remote job sidechannel messages
send_job_message called remotely previously persisted the literal ‘admin’ into any live job’s inbox regardless of caller. Fail-closed now: remote callers need an authenticated client identity (persisted as mcp: per the existing actor convention) and are refused without one; local callers keep the explicit-sender/default behavior. Red-first suite pins both trust tiers plus terminal-state refusals on each. Ledger updated: four newly covered ops move from UNCOVERED to LEDGER (shrink-only ratchet at work); serve-http ceiling raised for the limiter attach.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(serve): structural requireAdmin guard over every /admin registration
Scans all app.get/post/put/delete/patch/all/use ‘/admin*’ registrations in serve-http (multi-line shapes and the static SPA mount included, comment lines excluded) and requires requireAdmin as pre-handler middleware modulo a rationale-bearing allowlist (credential/token entry points + SPA arms, each pinned with its expected count and mandatory middleware). Embedded bad-fixture self-test proves the extractor can fail; stale allowlist entries fail loudly.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(e2e): salience write-path parity — mixed batches, touch semantics, score maps
setEmotionalWeightBatch parity pinned across engines with a mixed batch (changed / same-value / missing / wrong-source rows): identical matched counts and stored weights, salience_touched_at advancing ONLY for rows whose weight actually changed, and getSalienceScores returning identical source::slug score maps with analytic expectations for the take term.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(advisor): pin the CLI exit-verdict mapping and the non-TTY apply gate
runAdvisorCli driven end-to-end over a stubbed engine: critical/warn/info findings map to exits 2/1/0, –apply under a non-TTY stdin aborts with ‘Aborted. Nothing was run.’ and never reaches spawnSync (spied without mock.module via named-import live bindings), and unknown apply ids exit 2 listing what IS runnable — including the nothing-runnable suffix branch.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(sync): mounted-brain gate + all remediation in the delegate ladder
New cases pin the ladder’s brain gate: a non-host –brain under a live serve falls through to the direct path; a resolver throw is swallowed and the ladder CONTINUES (fail-open reality pinned, both facets); –source all under a live serve returns handled with verdict 1 and the one-source-at-a-time remediation; an invalid –source is refused with verdict 1. Also fixes the file’s pre-existing process.exitCode leak so it exits 0 standalone.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(e2e): takes write-op journey on real Postgres
Op-layer coverage for takes_add/update/resolve/supersede over live PG: fence-first writes with the DB mirror, the takes_mirror_unavailable envelope on both unset and missing repo paths, concurrent takes_add on one slug serializing under the page lock (plus the deterministic lock-held-past-budget retryable arm), resolved-row immutability with per-op suggestions, and supersede close+link column semantics. Mapped in e2e-test-map for the selected-e2e lane.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- fix(cycle): cast the two propose-takes JSONB binds + pin cycle writers on real Postgres
Both uncast positional binds feeding the dedup fence rows and the empty-extraction tombstone double-encoded to jsonb string scalars on real Postgres (captured red-first: jsonb_typeof returned ‘string’); PGLite hides the class, which is why no unit test ever saw it. Fixed via the blessed $N::text::jsonb hop. New DATABASE_URL-gated suites drive runPhaseProposeTakes (both write sites) and runPhaseCalibrationProfile (object typeof + text[] round-trip) end-to-end. The check-jsonb-params scanner now also flags UNCAST positional binds fed JSON.stringify into known-JSONB columns, with bad/good self-test fixtures; both new e2e files are mapped for the selected lane.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(sync): pin collectGitVisibleFiles edge arms
Tracked-then-gitignored files are excluded via the ls-files -ci subtraction (proven against –cached, not untracking), tracked and dangling symlinks are skipped without throwing, results are sorted absolute paths from the cached+others union, non-git dirs return null, and acceptRelPath sees forward-slash relative paths with veto power.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(e2e): /ingest fails closed on the pre-v85 client-binding rung
With oauth_clients.bound_slug_prefixes absent (simulated by a rename with finally-restore against the live server), a valid write token gets 403 with the apply-migrations remediation — the degraded projection can never fall open to an unbound write. Control + recovery arms prove the same request is accepted with the column intact.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- fix(chronicle): scope the event-page join + diary redaction on timeline reads
The chronicle read paths’ event-page LEFT JOIN was unscoped in both engines (the same far-endpoint class the links ops fixed in #2200): a scoped caller’s own timeline row could surface an out-of-scope event page’s slug, date, and kind, and last-seen could date-stamp an entity from an out-of-scope sighting. The join now carries the caller’s scope in lockstep on both engines (rows survive; foreign event fields null out; trusted brain-wide callers unchanged). Timeline ops also gain the diary redaction the ontology siblings already had, fail-closed on remote-or-undefined trust. Red-first suite pins scoping, the cross-row arm, redaction on all five ops, and the brain-wide controls; one residual last-seen shape gap is documented in the suite rather than silently widened.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(skillpack): pin the resident-skill locate fences
getResidentSkillDetail’s three fences pinned with anti-vacuity controls: the 64-char kebab slug gate fires before any engine or fs access (counting-engine proof + exact boundary at 64/65), out-of-scope federated and scalar sources answer not_found with in-scope fetch controls, and a manifest-listed skill dir swapped for an outside symlink hits the realpath confinement error.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(e2e): pin the cross-engine CJK keyword asymmetry as a documented gap
PGLite’s bigram/ILIKE branch finds CJK substring queries; Postgres has no CJK branch and its degradation shape is locale-regime dependent — C-locale websearch_to_tsquery silently DROPS CJK terms (mixed queries can false- positive) while UTF-8 keeps them as whole-run AND lexemes. The suite pins the shared empty-result invariant unbranched, probes the regime at runtime for the divergent mixed-query arm, and carries flip instructions pointing at the filed pgroonga follow-ups for whoever builds the Postgres branch.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(code-intel): pin per-op scope contracts — fenced walks, scoped edges, documented brain-wide lookups
code_blast/code_flow’s resolveCodeIntelScope fence pinned (remote-no-scope refused, multi-source grants rejected, walks + disambiguation stay in scope with cross-source controls); code_callees’ remote scalar/federated isolation pinned with all_sources grant-collapse; code_def/code_refs pinned as the in-code documented brain-wide contract with a deliberate tripwire so any future scoping change fails this suite consciously.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- feat(evals): takes-bootstrap graduation instrument — 123-case corpus, scorer, live/replay harness
The TODO-E gate gets its instrument: a deterministic 41-archetype x 3 label-invariant-variant corpus (privacy-safe placeholders) spanning the four take kinds plus the precision classes (empty pages, attribution traps, injection/noise adversarials); a pure scorer with per-kind precision/recall bars where an unparseable case is a FAILURE never a skip and forbid-regex violations block graduation; and a harness that drives the REAL extractTakesFromPages path per case against throwaway PGLite in live mode with a $0 replay re-scorer. Keyless CI validates the corpus, the arithmetic, the graduation boundary, and label satisfiability via an oracle pass; the autopilot tier stays manual_only until a live run graduates.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(context): unsafe session ids round-trip checkpoint compaction + tri-copy sanitizer drift guard
‘oc:sess/2026-08’ survives compact->assemble with the same sanitized key on every wire request and corpus filename; the sanitizer contract is pinned (null for degenerate ids, charset, 120-char clamp); and a drift guard maps a probe set identically across all THREE sanitizer copies (context-engine, hook.ts, corpus-segments) while pinning their deliberate sentinel divergence loudly.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- fix(ops): dry-run short-circuit for pause_job/resume_job + lifecycle behavioral suite
The lifecycle suite surfaced that pause_job and resume_job lacked the mutating-op dry-run convention — a dry_run:true dispatch still flipped the row. Both handlers now short-circuit with the declared envelope and carry mutating:true. The new suite pins all seven queue-row ops end-to-end on a real PGLite queue: dry-run postures, the actual state machine (cancel’s lock-clearing set, retry’s fresh-run column reset, replay creating a NEW row with the source untouched and cancelled deliberately non-replayable, token-fenced progress reads), and incompatible-status refusals.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(e2e): mount routing journey — resolver tiers, dotfile trust, disable fallback
Real-CLI journey over two live PGLite brains pins the resolver ladder (flag > env > dotfile walk-up > registered-mount path prefix > host), the dotfile trust guards (symlinked and world-writable dotfiles refused fail-closed to host), the host opt-out, write-side routing, and disable → ambient host fallback with explicit –brain failing loudly. 20 spawns, ~25s, hermetic env scrub incl. the homedir-derived mounts path.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(e2e): autopilot linux lifecycle under PATH-shimmed crontab/systemctl
Install/reinstall/status/uninstall driven through the real CLI with a round-tripping crontab shim and a systemctl argv recorder: foreign cron lines survive byte-identical through every phase, reinstall is idempotent (no table rewrite), uninstall removes only the autopilot line, the systemd unit lands 0644 with the exact command sequence, and status exit codes pin the installed-but-never-run contract. CI’s ubuntu runners finally get behavioral coverage of this platform’s only install path.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(doctor): behavioral suites for four previously-inspection-only check modules
Schema-pack consistency (worst-source attribution, the 10% warn boundary pinned at 10.0 vs 9.9, fail-open on probe throw, source-drift arms), brainstorm health (all four track_retrieval off-variants, cold-start messages, degraded-probe warn), skill checks (corrupt manifest is an ok skip never a warn, tamper listing, +N-more truncation, missing-bundled recommendation), and the memory-verbs sidecar (torn-line fail-open truth pinned via the module’s own path seam — stronger than the planned warn).
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(minions): dream quota degradation across all three consumers
Pins the admission-quota degradation contract (plan C3, TODOS.md:930) at each consumer: cycle patterns phase reports skipped/admission_quota with zero child rows; synthesize latches after one refusal (1 submit attempt for 3 transcripts, cooldown unstamped, filler untouched); agent fanout tree-cancels (aggregator + submitted children cancelled, exit 1). Three anti-vacuity controls prove ample quotas admit. Uses the real admission policy cache reset seam; no mock.module.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(protocol): pin the MEMORY_VERBS protocol document shape
Plan B5: ordered deep-equality of Object.keys(doc.verbs) against VERB_NAMES kills the filter(Boolean) silent-drop class; every verb entry carries non-empty input_schema.properties + a response_schema requiring protocol_version const 1; doc.protocol_version pinned to literal 1; the error_schema enum must contain all seven documented error codes (containment, not equality — the contract is additive-forever).
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(serve): sync IPC kill-switch narrows without blinding
Plan F4: with GBRAIN_SERVE_SYNC_IPC=0 a real startMcpServer (child process — its stdio transport wires onclose to process.exit) answers sync_start/status/abort with unsupported_kind while resolve and turn_context still work; a control child with the switch unset answers unknown_job, killing the broken-import masquerade. Client side: maybeDelegateSyncToServe returns HANDLED with the documented remediation and exit verdict 1 — the direct sync path never runs.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- fix(audit): timestamp stamp survives an explicit undefined ts + advisor/suggest suites
Plan E4. Src fix (red-first): connection-audit’s ts stamp now lands after the event spread, so a caller passing ts: undefined can no longer erase the timestamp from the JSONL row. New suites: advisor collectMigration (fail-toward-migrate on probe failure pinned as reality) + collectUninstalledBrainPack five-gate matrix (remote suppresses before touching the engine); connection-audit ISO-week filename drift guard across implementations + URL credential redaction; schema-pack suggest confidence clamps (non-finite falls to 0), dedup keeps first, and the 0.5 heuristic fallback sits below the 0.6 auto-apply floor (source-text guard pins both literals).
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(e2e): thin-client daily-driver verbs live over the wire
Plan G3: search/query/recall –json run from both the host HOME and the thin-client HOME against a live serve — per-row key-set equality pins routed results identical to local; invalid client secret and a stopped host both exit 1 with the canonical RemoteMcpError surfaces and a fail-fast bound.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(e2e): getHealth parity on real Postgres
Plan D8 (TODOS.md:643-655 item b): mirrors the PGLite-only islanded-liveness unit fixture onto both engines — entity_page_count below/at the coverage floor, null link/timeline coverage below the floor with identical real ratios at it, and orphan_pages agreeing on the dead-inbound/dead-outbound islanded JOIN semantics. Mapped in the e2e test map on all four engine rows.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(skillopt): dream-cycle cost caps behavioral suite
Plan H2 — the only brake on an unattended nightly LLM spender. Pins: strict-string feature-flag gate skips with zero runner calls; once mode runs without persisting the flag (per-skill last_run bookkeeping still banks); the brain-wide cap boundary is >= and checked before the run (at-cap skips, a cent below runs capped to remaining); effective per-skill budget is min(perSkillCap, remaining); abort breaks the loop rather than skipping. Ample-cap control proves all candidates run with the default budget and nightly-safety opts (epochs 1, noMutate).
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- fix(eval): conversation-parser scorer fails positive fixtures with unrecognized headings
Plan H3 (red-first pair): a heading-anchored pattern regression that folds an out-of-set heading into another speaker’s turn kept perfect recall, so scoreFixture passed silently. Positive fixtures now fail with a reason naming the folded labels; the adversarial (pattern null) fixture class keeps its semantics. Corpus gate stays 24/24.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(e2e): –surface verbs ceiling over a real HTTP serve
Plan G6: hermetic PGLite serve boot pins the frozen 7-verb tools/list for both bare and full-preset clients, the fail-closed unknown_operation envelope on hidden ops, that GBRAIN_MCP_FORCE_SURFACE is narrow-only by construction (min() into the CLI ceiling — cannot widen), and a remember/recall round-trip carrying protocol_version 1. Mapped on the surface implementation module.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(e2e): legacy no-grant token federated widening over /mcp
Plan G6 (TODOS.md:643-655 item a): transport wiring for the no-grant-federated-scope decision — a legacy token without a source grant sees exactly the locally-federated source set over real /mcp (list_pages source set + cross-source get_page), while a grant-bearing token stays confined to its grant even though the granted source is itself federated (the anti-vacuity contrast pair). Construction-site pin on verifyAccessToken’s hasSourceGrant flag.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(claw-test): exhaustive every-fixture-loads guard with orphan ratchet
Plan G6 (TODOS.md:5529-5545, guard half): every shipped claw-test scenario fixture must load with coherent config; listScenarios silently filtering a dir missing scenario.json is now visible. The voice-agent-install fixture joins a two-sided KNOWN_ORPHANS ratchet — it must stay well-formed AND keep failing to load, so landing the ScenarioKind wiring forces the entry out of the map. The wiring half stays infra-gated: claw-test’s phase runner branches only on ‘upgrade’, so a loader-only extension would run a bogus fresh-install pass — noted in the ratchet.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(cli): promptLine EOF/timeout/stream contracts
Plan E3 wave-5 slice: child-process-driven pins on the interactive prompt helpers — promptLineStderr resolves null (never ‘’) on EOF, bare Enter is ‘’ not null (the truthiness footgun from both sides), answers are trimmed, timeouts with stdin held open resolve null, prompts route to the right stream, and promptLine’s no-EOF-handler hang is pinned as reality so a contract change surfaces.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(ops): file_upload defaults to strict confinement when remote is unset
Plan A6 op-level companion (eng E24): remote: undefined on the dispatched op takes the strict path exactly like remote: true — an outside-cwd probe is rejected invalid_params — while the trusted remote: false control genuinely uploads the identical probe (loose mode relaxes confinement only; final-component symlinks stay rejected in both modes).
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(dream): keyless dream exits 0 with the documented degraded posture
Plan G6 (TODOS.md:1661-1674): the nightly cron’s unattended keyless run is pinned — exit 0 with status partial across three invocations (json and plain spellings), embed is the only structured-fail phase (the –no-embedding refusal text), propose_takes/synthesize skip with their real keyless diagnoses, no phase carries a crash signature, and the sync half still banks a page (anti-vacuity). Child env is allowlist-built so every provider var is absent by construction.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(verbs): error-path conformance fixtures for entity, context_pack, synthesize
Plan B6: every verb that can error now carries an error fixture — entity missing its required param, context_pack malformed since (advertised-only so pre-v0.45.7 endpoints still certify), and the keyless synthesize arm now actually executes in CI via a forced-keyless runConformance self-cert (previously nothing exercised the synthesize error arm). Each new envelope is pinned directly for protocol_version 1, non-empty suggestion, and ERROR_SCHEMA validity. recall stays error-fixture-free by design (degrade-never-error).
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(cli): cache/remote/sources-demo hardening batch
Plan E3: cache clear refuses without –yes (zero deletions), scoped clear and TTL prune delete exactly their rows, and the ‘clear –source –yes’ ordering footgun is pinned as reality (binds sourceId=’–yes’, deletes nothing, exits 0). remote CLI: –timeout 90s/5m/2h parse to real second budgets and malformed input takes the 15m default (never 0/NaN), one poll blip survives, failed jobs exit 1 with failed_reason in –json, non-thin-client config refuses with the init hint before contacting the host. sources demo: writes only under –dir, honors –limit, usage errors exit 2 writing nothing.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(e2e): read-path parity batch — graph traversal, restore, code edges, ontology merge, event projection
Plan D7. engine-parity gains traverseGraph/traversePaths blocks (cycle guard terminates identically at depth 25, in/out/both endpoint scoping, sourceIds variants) and the restorePage arc (second restore false; scoped restore never crosses sources). New suites: code-edges read parity (parsed edge_metadata objects would catch a double-encode), ontology merge matrix (inserted/corroborated/noop/superseded_prior with row-for-row facts dumps, quarantine visibility, asof time-travel, conflict detection), and the first tests anywhere for upsertEventProjection (idempotent single timeline row updated in place — proves the partial dedup index exists on real Postgres).
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- fix(engine): mergeOntologyFact returns supersededId as a number on Postgres
Surfaced by the D7 ontology parity suite: the Postgres engine passed current.id through un-normalized, returning a runtime BigInt where the OntologyMergeResult contract says number | null (PGLite returns plain numbers; factId was already Number()’d). The parity test now pins the runtime type instead of comparing value-normalized.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(e2e): upgrade bun-link arc under a PATH-shimmed toolchain
Plan G6: the from-source upgrade journey fully offline — detection via the .git/config remote marker walk (foreign-remote negative control), real git pull –ff-only against a local bare origin ordered before the shimmed bun install (recorder proves the clone was at origin HEAD at install time), the post-upgrade migration ledger advancing exactly one completed entry then idempotent on rerun, and –swap-only stopping after the swap. The dev checkout is tripwired against ever being the upgrade target.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(e2e): real SIGKILL mid-sync resumes exactly-once on Postgres
Plan F7: a child sync with CHECKPOINT_EVERY=1 is killed on the first banked op_checkpoint_paths row (DB-polled, never sleep-then-kill). Pins: partial banked set with last_commit frozen, the stranded lock refuses an immediate retry naming the dead pid (grace fail-closed), and after the holder ages past TTL + steal grace the second sync resumes from the checkpoint — 31 pages, all distinct, bookmark advanced, checkpoint and lock rows cleared. Suite-scoped source id keeps the shared DB safe.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(engine): mechanical surface sweep + searchVector escalation positives
Plan D9 (TODOS.md:508-517): a two-way interface census pins all 152 BrainEngine methods against the PGLite prototype (new methods force a visible list edit) with a runtime shrink-only UNCALLED ratchet scanning the whole test corpus. Five never-called methods gain real-shape smokes; getPageTimestamps (deprecated since v0.29.1) and getTakeEmbeddings are flagged as zero-src-caller deletion candidates. Escalation wiring: fire-at-cap positive (1120 dense chunks walk 100→400→1000 with underfilled telemetry) and the exact-scan lane for
2000-dim columns, proving the cap keys on the column descriptor, not the physical index. Postgres halves stay e2e-deferred.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- docs: strike completed test-gap TODOs and document the new ratchets and lanes
TODOS.md: seven entries marked done with what-landed notes (parser scorer strictness, chennai test-debt trio incl. one refuted item, dream quota degradation, keyless dream contract, searchVector escalation positives, PR-time e2e selection, request-log rows); TODO-E annotated instrument-shipped/graduation-pending; the coverage-gate flip and claw-test wiring annotated with their remaining gates. TESTING.md gains the registry-walking ratchets section (ops ledger, source isolation matrix, e2e wiring, engine surface census, orphan-modules guard, takes-bootstrap instrument guard) and a grouped inventory bullet for the wave’s e2e journey suites.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(evals): corpus privacy tripwire sources banned tokens from the guard scripts
The takes-bootstrap corpus lives under evals/, outside the privacy guards’ scan surface, so the keyless test re-applies their token lists to it — but the first version embedded the literals, tripping check-privacy and check-test-real-names on the test file itself. The tokens now parse out of the two guard scripts (their one allowlisted home) via a line-state walk that skips comment text, so the tripwire tracks the guards’ lists automatically.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- chore: regenerate structural-suites.tsv for the guard-sourced privacy tripwire
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(sources): scope the sources_status happy-path fixture to its own source
The wave’s scope fence on sources_status (out-of-scope id answers not_found) correctly rejects this fixture’s default-scoped remote ctx reading a different source. The test pins the status payload, not scoping (the fence has its own suite), so the caller is now scoped to the source under test.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- fix: pre-landing review fixes — validation parity, scope-boundary alignment, ratchet tightening
Src: the pack-name validation now guards every pack lookup surface through one shared predicate, with its charset aligned to the manifest schema’s own rule (pre-existing packs with dots/underscores stay mutable); the sources_status confinement now mirrors the documented sources_list boundary (federated grants confine, the scalar floor and trusted local do not) with an anti-enumeration answer shape; remote-submitted job payloads carry the authenticated client identity for spend attribution; find_contradictions filters before its scope pass (bounded existence probes), early-exits at the limit, and applies the same world-visibility filtering as its sibling read ops; the admin auth limiter answers 429 with a JSON envelope.
Tests/guards: coverage-ledger and e2e-baseline ratchets lose their stale slack (seeds track current lengths); the corpus freshness test now byte-compares and never dirties the tree; the isolation matrix rejects non-OperationError crashes on scoped calls, derives all dates from one captured instant (leap-day-safe), and expresses the federated-vs-scalar boundary per row; supabase upload failure arms pinned; six previously-unclaimed e2e files mapped (baseline 159→153); the contradictions e2e mechanics fixture uses a trusted brain-wide ctx.
Docs: KEY_FILES chronicle entry updated to current redaction behavior.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- fix(ops): contradiction fences verify before the limit cutoff
Adversarial-review finding: the scope and world-visibility fences ran after the limit-bounded keep loop, so droppable findings ahead of visible ones could starve the response (fewer rows than exist, with total_in_run claiming completeness). Both fences now run before a finding counts toward the limit, batched so the visibility keep-list stays one query per batch. Red-first regression pin included.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- chore: bump version and changelog (v0.47.1.0)
Five-file version lockstep (VERSION, package.json, openclaw + codex + claude plugin manifests), runbook stamp, regenerated template repo and plugin trees, refreshed lockfile, and the v0.47.1.0 CHANGELOG entry. Slot advanced past open PR claims (0.46.35.0 x2, 0.47.0.0) per the queue-aware allocator.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test: absorb master-wave deltas the census and storage precondition surfaced
The D9 engine census classifies master’s three new methods (bulk config read, takes-embedding update, scoped link removal) and shrinks UNCALLED — wave-k gave getTakeEmbeddings real coverage, so its shape pin moves out of the allowlist-driven smoke map. The file_upload trust-default suite configures a local storage backend, required since master’s no-backend refusal landed ahead of the insert.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- test(e2e): absorb master-wave behavior changes surfaced by the full-glob run
The CJK suite flips its documented-degradation pins to parity per their own flip instructions — master’s #3986 gave both engines the shared CJK keyword branch, so the asymmetry the suite pinned no longer exists (the locale-regime probe goes with it). The autopilot lifecycle suite passes –force and pins master’s new PGLite single-writer refusal (install without –force exits 1 recommending gbrain serve, crontab untouched). The thin-client seed clears a stale shared-DB sync.repo_path left by prior suites in the glob, which made put_page’s reverse-write refuse.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- docs: absorb the v0.47.1.0 scope-fence and CJK-parity outcomes into the reference docs
qm-harness.md’s isolation-model section stops listing the activity/anomaly/ contradiction/source reads as brain-wide (they now honor the federated grant) and documents the one residual — find_contradictions matches findings by slug within the grant, with the harness-layer mitigation and the filed follow-up. TESTING.md’s e2e journey inventory updates the engine-parity-cjk.test.ts description from the pre-#3986 documented- degradation pins to the current cross-engine parity pins.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
- fix(ci): classify sweepDreamVerdicts in the engine census + annotate corpus-regex sites for semgrep
The D9 census fired on wave-k’s sweepDreamVerdicts (TTL housekeeping, covered by test/dream-verdict-cache-ttl.test.ts) — classified into INTERFACE_METHODS. Semgrep’s non-literal-RegExp rule flagged the three takes-bootstrap scorer sites: the patterns come from the committed, PR-reviewed corpus (regex-compiles pinned in the keyless suite), never runtime user input — annotated with the repo’s nosemgrep idiom and the rationale inline.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
Co-authored-by: Claude Fable 5 noreply@anthropic.com
版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9
京公网安备 11010802047560号
GBrain
Search gives you raw pages. GBrain gives you the answer. It’s the brain layer your AI agent has been missing — the only one that does synthesis, graph traversal, and gap analysis in one box. Run a full autonomous agent on top of it, or just wire it into Claude Code or Codex as a supercharged retrieval layer in one command; either way your coding agent stops being amnesiac about everything that isn’t code.
I’m Garry Tan, President and CEO of Y Combinator. I built GBrain to run my own AI agents. It’s the production brain behind my OpenClaw and Hermes deployments: 155,795 pages, 24,589 people, 5,340 companies, 66 cron jobs running autonomously. My agent ingests meetings, emails, tweets, voice calls, and original ideas while I sleep. It enriches every person and company it encounters. It fixes its own citations and consolidates memory overnight. I wake up smarter than when I went to bed — and so will you.
And now it works as a company brain too. Each person on the team gets their own slice of the brain, scoped by login. When you query, you only see what you’re allowed to see — never another person’s notes, never another team’s data. We fuzz-tested this across every way you can read the brain (search, list, lookup, multi-source reads) and got zero leaks. Drop GBrain in as your team’s shared institutional memory — the company-brain shape YC just put on its Request for Startups. If you’re building in that space, you might as well build on this. Tutorial: set up GBrain as your company brain →
Lots of personal-knowledge systems give you keyword matching and grep in a box. GBrain does that, and adds two things nobody else ships together:
attended,works_at,invested_in,founded,advises) with zero LLM calls. Ask “who works at Acme AI?” or “what did Bob invest in this quarter?” and get answers vector search alone can’t reach. Benchmarked: P@5 49.1%, R@5 97.9% on a 240-page Opus-generated rich-prose corpus, +31.4 points P@5 over its graph-disabled variant and over ripgrep-BM25 + vector-only RAG by a similar margin. Full BrainBench scorecards live in the sibling gbrain-evals repo.The point of building a 150K-page brain is to use it as a strategic moat. To never lose context. To query what’s in your own head without re-reading it. The brain layer is what makes the moat usable. The 24/7 dream cycle is what keeps it sharp. Both run on your hardware, your DB, your keys.
It’s easier to ship a daemon that runs 24/7 to ingest, enrich, and consolidate than it is to keep an agent in chat working hard. GBrain is that daemon, generalized. Install in 30 minutes. Your agent does the work. As my personal agent gets smarter, so does yours.
What this looks like
Say you have a meeting with Alice tomorrow. You want to walk in remembering what she works on, when you last talked, and what’s still open between you. Here’s what you’d type, and what you’d get back.
You ask:
Most personal-knowledge tools give you back a list of pages. Something like:
Five pages you now have to open and read yourself to actually prepare. The tool found the right material, but it didn’t do the work.
GBrain gives you back the answer, with sources:
Every claim has a source page behind it. The “heads up” at the end tells you what the brain doesn’t know yet, so you can ask Alice about it directly instead of being surprised. The brain just did your meeting prep.
This is the difference between a search engine and a brain. Search finds the pages. The brain reads them for you and writes the answer.
Install
GBrain is designed to be installed and operated by an AI agent. New to GBrain? Start with Codex — it runs on the ChatGPT subscription you already have, takes ~15 minutes, and deploys nothing. Already living in Claude Code? Its path is identical. Want GBrain running the way it was designed to run — always on, enriching your brain around the clock? That’s OpenClaw or Hermes, at real server + API cost. Each path below is complete on its own. (Wiring it up by hand instead? Jump to CLI standalone or the MCP table.)
For Codex — the recommended first step
Turn Codex into your persistent personal agent. (Just want the brain + skills without the full agent?
codex plugin marketplace add garrytan/gbrain@codex-pluginthencodex plugin add gbrain@gbrain— see docs/mcp/CODEX.md. The paste block below builds the whole agent.) Works in the ChatGPT desktop app (open Codex on a folder) and in the Codex CLI (codexin a terminal) — same install, same result. Open Codex in a new, empty folder (not an existing code project) — that folder becomes your agent’s own private GitHub repo, which bootstrap creates and privacy-verifies for you. Then paste:Codex will ask for command approvals during the install — approving them is the sandbox working as intended. What you get, in about 15 minutes: a short interview (6 required questions) → your agent’s identity (SOUL.md, USER.md, MEMORY.md) rendered from your own answers, never invented → a local PGLite brain (2 seconds, no server, no Docker) → MCP wired so every session can search and write memory → a private GitHub repo, created and privacy-verified, as your agent’s durable body. Works with zero API keys — keyword search plus memory your agent writes itself; one optional key upgrades capabilities (OpenAI: semantic search + automatic fact extraction; Voyage: semantic search; Anthropic: fact extraction). Codex reads brain context through its tools each turn (pull-based). The click moment: tell it one small thing to remember, restart Codex, then ask for it back — the answer comes from the brain, not from this chat’s context (which the restart cleared). That cross-session round-trip is the whole product; “what’s my name / my top jobs?” is answered from your identity files, which is nice but not the same trick.
Two things worth understanding once it’s running: you own the brain — every memory is a markdown file in that private repo (read it, clone it to a second machine, delete it and the brain is gone) — and the first skill to run is
cold-start: say “fill my brain” and your agent imports your Gmail, calendar, and contacts — via the native connector (gbrain google setup, tokens in gbrain’s local credential vault, never held by the agent), via ClawVisor (a hosted OAuth gateway), or from offline archives like Google Takeout — one consented step at a time. An empty brain is a database; a filled one is a memory.For Claude Code — turn it into your persistent personal agent
Works in the desktop app and in the CLI (
claudein a terminal) — identical harness, identical result. Open Claude Code in a new, empty folder (not an existing code project) — that folder becomes your agent’s own private GitHub repo, created and privacy-verified for you. Then paste the same block:Everything from the Codex path applies — interview, identity from your own answers, local brain, private repo, keyless mode — plus Claude Code gets per-turn context hooks (on by default, with an opt-out): your brain loads automatically into every prompt, and your work persists to your private repo on a per-turn cadence (debounced ~5 min locally, every turn in a cloud sandbox — this covers the
/exitcase the harness never fires a session-end hook on), with a notice on your next turn if a push ever fails. This works in a Claude Code cloud session too, not just on your laptop: verification falls back to pure git protocol when the sandbox blocks the GitHub API, andgbrain bootstrap cloud-setup-scriptprints the environment setup recipe. The click moment: tell it one small thing to remember, restart the session, then ask for it back — a fresh session has no chat context, so the answer can only come from the brain. That cross-session round-trip is the whole product (“what’s my name?” is answered from your identity files — nice, but not the same trick). Same two follow-ups as the Codex path: you own the brain (markdown in your private repo), andcold-startis the first skill to run — “fill my brain” imports your email, calendar, and contacts (ClawVisor) or offline archives, one consented step at a time. Full contract, security posture, cloud sandboxes, and uninstall: docs/guides/bootstrap.md.For OpenClaw or Hermes — GBrain as intended, always on
This is GBrain used the way it was designed to be used: a server-hosted agent with 24/7 crons, continuous ingestion, and the overnight dream cycle that enriches your brain while you sleep — your agent works whether your laptop is open or not. It’s also the highest-cost path: a deployed server (8GB+ RAM) plus raw API token usage that scales with how hard your agent runs, well beyond a chat subscription. Start here if you want the full experience from day one; start with Codex above if you want to feel it first. If you don’t have a platform running yet, both deploy in one click:
Then paste this into your agent:
The agent installs GBrain, creates the brain, asks for your API keys, loads the 50+ bundled skills, configures the dream cycle, and verifies the install end-to-end. ~30 minutes. You answer questions, it does the work.
Lighter ways in
Just want a memory for your coding agent — no identity, no repo. Spin up a local brain and connect it in two commands — zero server, zero token, zero tunnel.
--surface verbsgives your agent the seven-verb memory protocol (recall,remember,entity,synthesize,forget, pluscontext_pack+deltasince v0.45.7 — MEMORY_VERBS v1, frozen + additive-forever) instead of the full tool wall; drop the flag for every operation:If
claudeis not found, install Claude Code first — or use the per-harness blocks in the protocol doc. Heads-up: memories agents save default to brain-wide visibility (every connected agent can recall them); passvisibility: "private"for local-only facts.Already have a brain on a remote host (OpenClaw, Hermes, or any
gbrain serve --http)? Point your laptop agents at it with one command each —--installwires it up and smoke-tests the token before handoff:Onboarding a whole agent harness onto a shared brain? On the brain host,
gbrain agent register <name> --harness claude-codemints a scoped OAuth client plus a 30-day token and prints the paste-ready wiring block — presets for daily-driver and write-isolated coding agents. The onboarding decision table says which path fits.Brain-only install into another coding agent (Cursor, Claude Cowork, or anything that can fetch a URL and run shell commands) — paste the OpenClaw/Hermes block above (
INSTALL_FOR_AGENTS.md); it installs the brain, skills, and dream cycle without the personal-agent identity layer. Tested with Codex, Claude Code, Claude Cowork, Cursor, and AlphaClaw.→ Full walkthrough: give your coding agent a memory — the memory-only paths end to end, plus the brain-first protocol you paste into
CLAUDE.md/AGENTS.mdand the four habits that make it actually change how you work.CLI standalone (no agent)
Postgres-at-scale, Supabase, and thin-client setup paths live in
docs/INSTALL.md.Connect GBrain to your AI client (MCP)
GBrain exposes nearly all of its 100+ operations as MCP tools (stdio and HTTP; a handful of local-only ops stay CLI-side) — or exactly the seven memory verbs with
--surface verbs. The specific snippet depends on which client you use:/plugin marketplace add garrytan/gbrain+/plugin install gbrain@gbrain(MCP + skills; persona variantsgbrain-coding/gbrain-dailyinstall curated subsets — pick exactly one gbrain plugin). Marketplace-free skills:gbrain skillpack scaffold --harness claude-codecopies a persona-curated skill set into your user-scope skills dir with a local-edit-respecting update lens. Or local one-liner:claude mcp add gbrain -- gbrain serve(zero server, zero tunnel). Remote with just a bearer token:gbrain connect https://your-host/mcp --token gbrain_xxxprints a paste-ready block (or--installwires it up and smoke-tests the token).codex plugin marketplace add garrytan/gbrain@codex-plugin+codex plugin add gbrain@gbraininstalls the MCP server AND the curated skill set. Or connect-only:gbrain connect https://your-host/mcp --token gbrain_xxx --agent codex(or--install); Codex reads the bearer from$GBRAIN_REMOTE_TOKENat runtime, so the token never lands in Codex config.{"command": "gbrain", "args": ["serve"]}to your MCP config.printf 'Y\n' | hermes mcp add gbrain --env GBRAIN_HOME=$HOME --connect-timeout 60 --command $(which gbrain) --args serve. Keep--argslast, and verify withhermes mcp test gbrain(the add exits 0 even on failure).grok mcp add gbrain -e "GBRAIN_HOME=$HOME" -- gbrain serve --surface verbs. The add is lazy (exit 0 without connecting) — verify withgrok mcp doctor gbrain, which spawns the server and reports7 tools discovered. Verified against Grok Build v1.0.4.opencode mcp add gbrain --env GBRAIN_HOME=$HOME -- gbrain serve --surface verbs, or letgbrain bootstrap hooks --harness opencodewrite the config for you (opencode is a bootstrap-supported harness — it reads AGENTS.md natively). The add is lazy — verify withopencode mcp list, which spawns the server (✓ gbrain connected). Remote:gbrain connect https://your-host/mcp --token gbrain_xxx --agent opencode [--install]— the config stores only the{env:GBRAIN_REMOTE_TOKEN}interpolation. Verified against opencode v1.18.18.openclaw.plugin.jsonships in this repo), or add{"command": "gbrain", "args": ["serve"]}to~/.openclaw/config.json‘smcpServers.claude_desktop_config.jsondoes not work for remote servers.gbrain connect https://your-host/mcp --agent perplexity --oauth --registermints a least-privilege OAuth client and prints the Issuer/Client ID/Secret to paste into Settings → Connectors (OAuth is the right path for a cloud connector; a bearer token also works for local use). Pro subscription required.chatgptclient from the admin dashboard with grant typeauthorization_code.For the HTTP server itself:
The HTTP server includes DCR-style client registration, scope-gated access (
read/write/admin), and rate limiting. Deployment guides (ngrok, Railway, Fly.io) live underdocs/mcp/.Two ways to query your brain
Raw retrieval (what most personal-knowledge tools ship) and a synthesis layer that gives you an actual answer. They serve different jobs.
gbrain searchreturns the top retrieved pages, ranked by hybrid scoring (vector + keyword + RRF + source-tier boost + reranker). Use it when you want raw material to skim: agent context windows, citation lookups, finding a specific quote.gbrain thinkruns the same retrieval, then composes a synthesized answer across the results with explicit citations to the source pages AND an honest note on what the brain doesn’t know yet. The gap analysis is the differentiator: the answer tells you when a page is stale, when a claim is uncited, when two pages contradict each other, when there’s a hole you should fill.Say to your agent: “What do we know about acme-example?” — “Tell me about alice-example before my meeting tomorrow” — “Search for who’s working on AI agents.” Your agent routes these to the brain automatically; you never type the commands yourself.
Why it compounds. Pair the brain layer with
find_trajectoryand you get answers like “how have the company’s metrics changed AND what does the team look like right now AND what did they promise / share AND when did we last meet AND what’s the value-add I can offer here”: well-scored, well-cited, in one shot. That’s the strategic moat. That’s why building a 150K-page brain is worth the effort.gbrain agent run "..."exposes the same surface to a sub-agent through the Minions queue, with crash-safe two-phase persistence. Same answers, durable.How to get data in
One command, local or hosted, synchronous receipt:
The page lands in the database and on disk in one move. Default slug
inbox/YYYY-MM-DD-<hash8>so captures cluster in a predictable triage location. On thin-client installs the verb routes through MCP to the server: same command, same UX.Say to your agent: “Remember this: …” — “Save this thought to my brain” — “Capture this.” And to fill an empty brain from your existing life: “Fill my brain” (the cold-start skill walks your email, calendar, contacts, and archives one consented step at a time).
For webhook ingestion (Zapier / IFTTT / Apple Shortcuts):
For mobile capture, the inbox folder source picks up anything dropped into
~/.gbrain/inbox/from iOS Shortcuts / AirDrop / Drafts / Finder.Your Gmail, calendar, and contacts sync natively.
gbrain google setupwalks bring-your-own OAuth end to end (your own free Google Cloud client — you own the app and the tokens, which live only in a local credential vault), registers a--kind googlesource, runs a bounded first sync, and ends with the open-loop engine’s killer output:Setup + troubleshooting:
docs/guides/google-connect.md. How the open-loop engine decides who’s waiting:docs/guides/open-loops.md.Your other agents’ histories import in one command.
gbrain transcripts ingestparses agent session logs (Claude Code, Codex, OpenClaw, Hermes) and extracted consumer chat exports (ChatGPT / Claude.aiconversations.json) into readable conversation pages with provenance back to the exact session file. Secrets are scrubbed from message bodies, titles, speakers, and session metadata before anything is written, embedding is off by default for bulk backfills, and re-runs are free — unchanged sessions skip on content hash:Say to your agent: “Import my conversations from my chatgpt export at ~/Downloads/conversations.json” — “Archive my session transcripts” — and later, “When did I first discuss agent memory?” (the archive answers origin questions with dated quotes).
Or connect the account and skip the manual export entirely.
gbrain connectorssyncs your ChatGPT and Claude conversation history live, using your own browser session cookie — incrementally (a durable per-provider watermark, plus a trailing-window gap-heal), through the same redaction + idempotency pipeline, and optionally on a schedule. Credentials stay on your machine (~/.gbrain/connectors/*.json, 0600) and are sent only to the provider’s own host:Say to your agent: “Connect my chatgpt account and pull my whole history into the brain” — “Connect my claude account” — “Keep my conversations synced automatically.” Your agent walks you through the cookie capture, runs the dry-run → sample → full sequence, and sets up the schedule if you opt in.
Full contract, automation lanes, and the Cloudflare caveat: docs/guides/chat-connectors.md.
(Not to be confused with the inbound “Connectors” above — those add gbrain as an MCP connector inside ChatGPT/Claude/Perplexity so those assistants can search your brain.
gbrain connectorsgoes the other way: it pulls your conversation history from those accounts into the brain.)Third-party skillpacks can ship custom ingestion sources (Granola, Linear, voice, OCR) against the versioned
IngestionSourcecontract atgbrain/ingestion. Seedocs/skillpack-anatomy.md.Your brain’s shape (schema packs)
Most personal-knowledge tools force one fixed layout: their idea of “notes” + “people” + “tags.” Drop a Notion export or your own years-old Obsidian vault on top, and the agent doesn’t know what a
Projects/folder means or whetherReading/is people or sources.gbrain doesn’t have a fixed layout. It ships with bundled schema packs and lets you author your own when none fit:
gbrain-base-v2(default as of v0.41.22) — 15-type DRY/MECE canonical taxonomy (14 canonical +notecatch-all):person,company,media,tweet,social-digest,analysis,atom,concept,source,deal,email,slack,writing,project,note. Subtypes/format/origin pushed to frontmatter. The taxonomy that responds to issue #1479.gbrain-base(legacy, v0.41 and earlier brains) — the original 24-type layout. Stays bundled for back-compat; brains on it can upgrade viagbrain onboard --check --explain→gbrain jobs submit unify-types --allow-protected --params '{"target_pack":"gbrain-base-v2","apply":true}'(omit"apply":truefor a dry-run preview — that is the default).gbrain-recommended— extendsgbrain-basewith the 13 additional directories fromdocs/GBRAIN_RECOMMENDED_SCHEMA.md(source, place, trip, conversation, personal, civic, project, etc.). Activate withgbrain schema use gbrain-recommended.gbrain schema detectclusters your actual filesystem into proposed types,gbrain schema suggestruns an LLM pass over them, andgbrain schema review-candidates --applypromotes the ones you like. Three commands and the brain knows your shape. Authoring a successor pack (declaresmigration_from:so existing brains can opt in): seedocs/architecture/pack-upgrade-mechanism.md.Say to your agent: “My schema isn’t matching my notes — propose new types from my corpus” — “Add a page type for lab results to my brain’s schema.” The schema-author skill runs the detect → suggest → review flow for you.
The active pack threads through every read + write path:
parseMarkdowninfers page type from the pack’s path prefixes;whoknowsscopes expert routing to types declaredexpert_routing: true;extract_factsruns only onextractable: truetypes; the search cache folds the pack name + version into its key so cross-pack contamination is structurally impossible. Switch packs and the brain re-interprets itself; switch back and nothing’s lost.Seven-tier resolution chain (per-call flag → env var → per-source DB key → brain-wide DB key →
gbrain.yml→~/.gbrain/config.json→gbrain-basedefault). Full reference + authoring guide:docs/architecture/schema-packs.md.Tutorials
Step-by-step walkthroughs for getting the most out of GBrain. Each one takes you from zero to a working outcome, with concrete commands and real numbers.
gbrain skillopt— treat aSKILL.mdas a trainable parameter. Generate a starter benchmark straight from the skill with--bootstrap-from-skill(or write your own), strengthen the judges, then watch the optimizer propose edits and keep only the ones that measurably score higher. ~20 minutes, ~$1 in API calls. Flag + cost + safety reference:docs/guides/skillopt.md.More walkthroughs in progress: connecting an existing agent (Claude Code, Cursor, OpenClaw, Hermes) to a GBrain memory layer; setting up GBrain for VC dealflow with founder scorecards and meeting prep; migrating an existing Notion or Obsidian vault; indexing a codebase as a queryable code brain. Full tutorial index:
docs/tutorials/.Want to see a tutorial that isn’t here yet? Open an issue describing the workflow you want documented.
What it does (the loop)
[[wiki/people/bob]]style references. New entity → new page stub → graph grows.The whole loop is described in
docs/architecture/topologies.mdwith diagrams.Say to your agent: “Set up autopilot” (installs the cron that runs the loop) — “Run dream” — “Did the dream cycle run?”
Capabilities
Hybrid search. Vector (HNSW on pgvector) + BM25 keyword + reciprocal-rank fusion + source-tier boost + intent-aware query rewriting. Three named search modes (
conservative,balanced,tokenmax) bundle the cost/quality knobs into a single config key. Live cost/recall comparisons indocs/eval/SEARCH_MODE_METHODOLOGY.md. The install picker default-appliestokenmax(it recommendsconservativefor Haiku-class subagent tiers or keyless setups); a brain withsearch.modeunset resolves tobalancedat query time. The cross-encoder reranker is on inbalancedandtokenmax, off inconservative— new installs get Voyagererank-2.5; brains that never setsearch.reranker.modelstill fall back to the deprecated ZeroEntropyzerank-2(hosted API ends 2026-09-04) until the September cutover. Per-query graph signals notice when a top result is a hub for THAT query (adjacency boost), is corroborated across team brains (cross-source boost), or is being crowded out by weak chunks from a chatty session (session demote). Rungbrain search "<query>" --explainto see per-stage attribution: base score, every boost that fired, what it multiplied.gbrain doctorships agraph_signals_coveragecheck;gbrain search statsshows fire counts and failure breakdowns. Vector retrieval pools the best chunk per page, so a page surfaces on its strongest evidence instead of losing to a neighbor on one weak chunk. Queries that match a page’s title phrase or a declared free-text alias (gbrain reindex --aliasesbackfills existing pages) get boosted to the page they name. Every result carries anevidencetag (why it matched) and acreate_safetyhint (exists/probable/unknown) so an agent decides whether a page already exists instead of guessing from a raw score.gbrain search diagnose "<query>" --target <slug>traces which retrieval layer surfaces (or misses) a page. Say to your agent: “Tune my retrieval” — “What search mode am I running?” — “Why did this page rank first?” (your agent runsgbrain search --explain).Self-wiring knowledge graph. Every
put_pageextracts entity refs from markdown/wikilinks/typed-link syntax and writes edges with zero LLM calls. Typed edges (attended,works_at,invested_in,founded,advises,mentions, …). Multi-hop traversal viagbrain graph-query. The graph is what produces the +31.4 P@5 lift over vector-only RAG. Say to your agent: “Who works at acme-example?” — “What’s the relationship between fund-a and widget-co?” — “What connections does alice-example have?” Obsidian-style vaults: bare[[note-name]]wikilinks that point across folders — you wrote[[struktura]]but the page lives atprojects/struktura.md— resolve by basename once you opt in withgbrain config set link_resolution.global_basename true. Off by default;gbrain doctortells you how many edges you’d gain before you flip it. See migrating an Obsidian vault.Job queue (Minions). BullMQ-shaped, Postgres-native job queue. Durable subagents (LLM tool loops that survive crashes via two-phase pending→done persistence), shell jobs with audit, child jobs with cascading timeouts, rate leases for outbound providers, attachments via S3/Supabase storage. Opt-in per-job process isolation (
gbrain jobs work --job-isolation process) runs each claimed job in its own SIGKILL-able child process, so a stuck handler dies for real and a crash takes one job instead of the whole worker; when the worker’s DB health probe fails, it names the failing layer (pool_starvedvsserver_unreachable) instead of a blanket “DB unreachable”. Sizing and rollout guidance indocs/guides/minions-deployment.md; probe-verdict triage indocs/guides/queue-operations-runbook.md. Replaces “spawn subagent as fire-and-forget Promise” with something that recovers from anything. Say to your agent: “Run this as a background task and tell me when it’s done” — “Submit a gbrain job for the backfill” — “What’s running in the background?”Non-English brains (FTS language config). The Postgres full-text search tokenizer is configurable via
GBRAIN_FTS_LANGUAGE. Defaults toenglish. Set it to any text-search configuration that exists in your Postgres instance:List available configs:
psql -c "SELECT cfgname FROM pg_ts_config". Both the query side (websearch_to_tsquery) and the write side (the trigger functions that populatepages.search_vectorandcontent_chunks.search_vector) honorGBRAIN_FTS_LANGUAGE. On first install (or upgrade), theconfigurable_fts_languageschema migration reads the env var and creates trigger functions in the configured language; subsequent inserts/updates tokenize using that setting. To change language on a brain that has already run the migration, use the dedicated CLI command:The command is idempotent (re-running with the same language is a no-op for vector content) and uses the same recreate-and-backfill primitives as the migration. For accent-insensitive Portuguese (
pt_br), see docs/guides/multi-language-fts.md for theunaccent+ portuguese stemmer recipe. Say to your agent: “Set my brain’s search language to Portuguese and reindex.”50+ curated skills (the current list lives in
skills/manifest.json). Routing lives inskills/RESOLVER.md. Covers signal capture, ingest (idea / media / meeting), enrichment, querying, brain ops, citation fixing, daily task management, cron scheduling, reports, voice, soul audit, skill creation, eval framework, and migrations. Skills are markdown files (tool-agnostic), packaged as a single skillpack the installer drops into your agent workspace.Say to your agent — the phrasebook. You never invoke a skill by name; you say what you want and your agent routes it. Every skill declares its trigger phrases in its frontmatter, and
skills/RESOLVER.mdis the full human-readable phrasebook — one table of “when you say this, this skill fires.” A taste: “Ingest this PDF” (media-ingest) — “What’s happening today?” (briefing) — “Fill my brain” (cold-start) — “Brain health” / “check backlinks” (maintain — either phrase routes there) — “Is my brain set up right?” (gbrain-advisor) — “Did the restart break anything?” (smoke-test) — “Run this as a background task” (minion-orchestrator). If you’re ever unsure what to say, ask your agent: “What can my brain do?” and have it read the resolver back to you.Eval framework.
gbrain eval longmemevalruns the public LongMemEval benchmark against your hybrid retrieval.gbrain eval export+gbrain eval replaycapture real queries and replay them against code changes (setGBRAIN_CONTRIBUTOR_MODE=1).gbrain eval cross-modalcross-checks an output against the task using three different-provider frontier models.gbrain eval retrieval-qualityruns NamedThingBench, which hard-gates the named-thing retrieval families (title-substring, alias-synonym, generic-to-named, multi-chunk-dilution) so a regression in “find the page this query names” fails CI loudly.gbrain eval brainbenchruns the cross-harness memory conformance suite: know-to-ask, push precision/recall, write-back fidelity, and cross-session continuity, scored per harness seam (your OpenClaw’s production pipeline plus Claude Code and Codex injection contracts) against a committed 141-fixture synthetic corpus — hermetic by default (in-memory PGLite, no keys, seconds), and CI gates every PR against master’s committed baseline. Methodology indocs/eval/BRAINBENCH.md; search-mode methodology indocs/eval/SEARCH_MODE_METHODOLOGY.md. Say to your agent: “Run a regression check on retrieval” — “Run a search benchmark against LongMemEval” — your agent runsgbrain eval brainbench/gbrain eval longmemevalfor the full suites.Brain consistency.
gbrain eval suspected-contradictionssamples retrieval pairs, layered date pre-filter, query-conditioned LLM judge, persistent cache. Surfaces conflicts between takes + facts the agent has written. Wired into the daily dream cycle. Say to your agent: “Did the dream cycle run — what contradictions did it surface?” — “Fact-check what we have on acme-example” (claim-by-claim live-source verification) — or have your agent rungbrain eval suspected-contradictionsdirectly.Agent-authored schema (v0.40.7.0). Your brain has a shape — what page types exist (
person,meeting,paper,case,lab-result), what they link to (attended,authored,prescribed-by), what facts get extracted automatically. The default ships with 22 universal types, but your brain’s actual shape is not the default shape. Agents can now evolve that shape on your behalf via 14gbrain schemaCLI verbs + a batched MCP op (schema_apply_mutations, admin scope, NOT localOnly so remote agents reach it over HTTPS). Atomic file locks, audit log with the agent’s identity, chunked UPDATE backfill in 1000-row batches that never wedge concurrent writers. The brain stops being a pile of notes and becomes something with structure. Say to your agent: “Add a page type to my schema for case files” — “My brain has untyped pages — propose new types from my corpus.” Why it matters:docs/what-schemas-unlock.md— 7 killer use cases (4000 invisible meetings, founder ops brain, research brain, legal brain, team brain, agent-as-co-curator). 5-minute walkthrough:docs/schema-author-tutorial.md. Agent skill:skills/schema-author/SKILL.md.Integrations
Data flowing into the brain. Each integration is a recipe — markdown + setup hints — that ships in
recipes/and is discoverable viagbrain integrations list. Say to your agent: “Set up voice calls into my brain” — “Wire my email and calendar into the brain” — your agent reads the recipe and walks the setup with you.recipes/twilio-voice-brain.md.gbrain waiting). Setup:docs/guides/google-connect.md; recipes:recipes/email-to-brain.md,recipes/calendar-to-brain.md.docs/integrations/meeting-webhooks.md.voyage-4@ 1024d), OpenAI, OpenRouter, Google Gemini, Azure OpenAI, MiniMax, Alibaba DashScope, Zhipu, Ollama (local), llama.cpp llama-server (local), LiteLLM proxy, plus ZeroEntropy (deprecated — hosted API ends 2026-09-04). Pricing matrix + decision tree indocs/integrations/embedding-providers.md.rerank-2.5hosted (the new-install default; reranking is on inbalancedandtokenmaxmodes, sameVOYAGE_API_KEYas embeddings), ZeroEntropyzerank-2(deprecated — hosted API ends 2026-09-04; still the fallback for brains that never setsearch.reranker.model), plus thellama-server-rerankerrecipe for fully-local cross-encoder rerank via llama.cpp — runs Qwen3-Reranker or self-hosted zerank weights against the samegateway.rerank()seam. Setup walkthrough indocs/ai-providers/llama-server-reranker.md.gbrain credsmanages OAuth and API credentials in a local vault (recipes/credential-gateway.md); agent-side vault-aware secret distribution:docs/integrations/credential-gateway.md.docs/mcp/per-client setup.Architecture
Two engines, one contract. PGLite (Postgres 17 via WASM, zero-config, default) for personal brains up to ~50K pages. Postgres + pgvector (Supabase or self-hosted) for shared / large / multi-machine deployments. The contract-first
BrainEngineinterface insrc/core/engine.tsdefines the 140+ methods both engines implement; CLI and MCP server are generated from one source.Brain repo is the system of record. Your knowledge lives in a regular git repo (your “brain repo”) as markdown files. GBrain syncs the repo into Postgres for retrieval; deletes in git become soft-deletes in DB. You can publish public subsets, share team mounts, run thin-client setups pointing at a colleague’s brain server. Topologies in
docs/architecture/topologies.md.Two organizational axes (brain ⊥ source). A brain is a database (your personal brain, a team mount you joined). A source is a repo inside that brain (wiki, gstack, an essay, a knowledge base). Routing lives in
.gbrain-sourcedotfiles and resolves via a documented 6-tier precedence chain. Full diagrams indocs/architecture/brains-and-sources.md.Why the graph matters. Vector search returns chunks that are semantically close. The graph returns chunks that are factually connected. Hybrid search pulls from both; auto-linking on every write keeps the graph fresh. Deep dive:
docs/architecture/RETRIEVAL.md.Troubleshooting
Say to your agent first: “Run a brain health check and fix what you find” — this routes to the maintain skill, which runs
gbrain doctorand either auto-fixes or prints the exact repair command; your agent can run the whole loop (“Get my brain health score to 90” uses the remediation planner with a cost cap). The sections below are for when you want the manual path.PGLite crashes at startup with
RuntimeError: Aborted()(often right after a macOS upgrade)? Not a macOS incompatibility — the OS-upgrade reboot killed gbrain mid-write and tore the data dir’s WAL. gbrain now repairs this automatically on the next command (data preserved, backup kept); if auto-repair is disabled or skipped, rungbrain pglite-repair --dry-runto diagnose andgbrain pglite-repair --yesto repair in place. Full recovery ladder (repair → rebuild → engine switch) indocs/ENGINES.md— Troubleshooting: startup abort anddocs/INSTALL.md.gbrain importfails withexpected N dimensions, not M? Rungbrain doctor. It will print the exactgbrain config set ...orgbrain migrate embeddingscommand to repair the mismatch. You should not need to delete~/.gbrain. Freshgbrain init --pgliteauto-detects your embedding provider from API keys: setVOYAGE_API_KEY(orOPENAI_API_KEY/ another provider key) in the environment — or in~/.gbrain/config.json, which init also reads — before running init, or pass--embedding-model <provider>:<model>explicitly. With multiple keys set, init fires an interactive picker (non-TTY auto-picks the Voyage default when its key is present). With no keys at all, init continues keyless (keyword-only search) with a loud notice; add a key later and re-rungbrain init --force --embedding-model voyage:voyage-4to enable embeddings, or pass--no-embeddingup front to make keyless explicit. Seedocs/integrations/embedding-providers.mdfor the full provider matrix anddocs/operations/headless-install.mdfor Docker/CI sequencing.Hourly cron sync keeps timing out on a federated brain? Switch your cron to a per-source loop with shell
timeout(1)doing the OS-level kill and gbrain self-terminating gracefully half-a-minute earlier:When
--timeoutfires mid-import,gbrain syncexits 0 with statuspartialandlast_commitUNCHANGED — the next run re-walks the same diff andcontent_hashshort-circuits already-imported files. The--max-age 1800first command self-heals any wedged-but-alive locks left by a hung previous run, keyed on the lock’s last refresh time (NOT when it was acquired) so healthy long-running holders are safe by construction. Scope note: the extract + embed phases still run to completion once started;--timeoutinterrupts the import walk only.Dream cycle silently losing wiki links on Supabase? The engine self-retries every bulk batch write (
addLinksBatch/addTimelineEntriesBatch/upsertChunks) on Supavisor pooler blips, with a 12s worst-case wait that covers the full 5-10s circuit-breaker recovery window.gbrain doctorsurfaces incidents via thebatch_retry_healthcheck (reads the last 24h of~/.gbrain/audit/batch-retry-YYYY-Www.jsonl). To tune for an unusually slow pooler:Bad values surface at
gbrain doctorstartup with a paste-ready fix (not at first-retry mid-cycle). PGLite-only installs pay zero cost — the retry wrap is engine-level, but PGLite has no pooler so retries never fire in practice.Dream cycle losing ~150 link rows per run with
'No database connection: connect() has not been called'errors in the log? The retry layer self-heals on a nulled-out database singleton: areconnectcallback onwithRetryrebuilds the connection between attempts, andPostgresEngine.batchRetryinjects() => this.reconnect()so engine-level batch writes survive a mid-cycle disconnect by something else in the same process.gbrain capturealso no longer trails a'No database connection'stderr line from a background facts:absorb worker firing after CLI exit — op dispatch awaitsgetFactsQueue().drainPending({timeout: 1000})beforeengine.disconnect(). To find which code path is still calling disconnect mid-process, rungbrain doctor --json | jq '.checks[] | select(.id=="batch_retry_health")'; the check surfaces the 24h disconnect-call count and the most-recent caller frame from the~/.gbrain/audit/db-disconnect-YYYY-Www.jsonlaudit.gbrain brainstormreturningjudge_failed: truewith 0 scored ideas? Two historical bugs caused it, both fixed: the judge hard-coded a 4K-token output cap (any run past ~40 ideas truncated mid-JSON and the parser threw), and slash-form model ids (gbrain brainstorm --judge-model anthropic/claude-sonnet-4-6 --max-cost 5) failed withBudgetExhausted reason=no_pricingbecause pricing lookups only matched the colon form. Both shapes work now. No config change, no schema migration —gbrain upgradeis the whole fix.gbrain reindex --markdownwiped your auto/dream/signal-detector tags? Upgrade — tag reconciliation is add-only now. Re-import andreindex --markdownADD current frontmatter tags and never delete, so enrichment tags written to the DB (auto-tag, dream synthesize, signal-detector) survive a re-chunk. The reindex DB-only fallback also reconstructs the full markdown (frontmatter + body + timeline) before re-chunking, so a page with no on-disk source keeps its frontmatter, title, and timeline instead of getting overwritten with empty frontmatter. Trade-off: removing a tag from a page’s frontmatter no longer removes it from the DB on the next sync (frontmatter-tag removal needs a provenance column, deferred).gbrain syncwedges on a large brain (no progress, high CPU)? Three tools. First, name the stalling file:The last
[sync] begin import: <path>line with no following completion is the file being processed when the hang hit. Second, if you suspect a schema-packinference.regexwith catastrophic backtracking, complete the sync with the pack disabled and re-run extraction later:gbrain schema lintwarns on the classic nested-quantifier ReDoS shapes ((a+)+,(a*)*, …) in pack regexes, and the runtime caps inference-regex input length (override viaGBRAIN_MAX_REGEX_INPUT_CHARS). Third, on a PGLite brain with a livegbrain serve(your agent’s MCP server),gbrain syncdelegates the run to the serve process over its local IPC socket — the lock owner does the work, your agent stays up, and Ctrl-C aborts to a checkpoint the next sync resumes from. Embeds defer to the serve’s background sweep. Seedocs/architecture/serve-sync-concurrency.mdfor the limits (unsupported flags,serve --http) and the full triage.gbrain init --migrate-only/ a schema migration fails on Windows withgetaddrinfo ENOTFOUND? Upgrade — schema bring-up now runs its phases in-process instead of spawning a childgbrain init --migrate-onlyper phase. The spawned child died on Windows + bun + Supabase pooler with a DNS-resolution failure even though the parent connected fine; running in-process removes the spawn entirely. The grandfather migration that used to hang 70+ minutes on an 80K-page PGLite brain also runs as a chunked bulk SQL pass now (keyed on the page PK, soft-delete-filtered, source-safe) and completes in seconds.Docs
docs/INSTALL.md— every install path, end to enddocs/guides/bootstrap.md— the persistent-personal-agent bootstrap contract (interview, identity files, hooks, private repo, security posture, uninstall), plus local harness mode (gbrain bootstrap harness) for wiring framework-spawned Claude Code/Codex sessions to a running servedocs/what-schemas-unlock.md— why schemas matter: 7 killer use cases, the structural argument for typed page kinds, the agent-co-curates pattern (v0.40.7.0)docs/schema-author-tutorial.md— 5-minute walkthrough: fork the bundled pack, add a custom type, backfill existing pages, prove the wiring viagbrain whoknowsdocs/architecture/— system design, topologies, retrieval theorydocs/guides/— how-to runbooks (google connect, open loops, sub-agent routing, minion deployment, skill development, brain-first lookup, idea capture, diligence ingestion)docs/integrations/— connecting external data sources (voice, email, calendar, embedding providers)docs/mcp/— per-client MCP setup (Claude Desktop, Code, Cursor, ChatGPT, Perplexity, Cowork)docs/eval/— eval framework, metric glossary, methodologydocs/ethos/— philosophy (thin harness, fat skills, markdown as recipes, origin story)AGENTS.md— entry point for non-Claude agentsCLAUDE.md— entry point for Claude Code (deep operating context)CONTRIBUTING.md— contributor guide, test discipline, eval-capture modeSECURITY.md— install-path trust model, self-update integrity, automated scanning, OAuth threat model, hardening defaultsContributing
Run
bun run testfor the fast loop,bun run verifyfor the pre-push gate,bun run ci:localto run the full Docker-backed CI stack locally. Detailed test discipline inCONTRIBUTING.md.Community PRs are batched into release waves rather than merged one-by-one — see the “PR wave workflow” section in
CLAUDE.md. Contributor attribution stays attached viaCo-Authored-By:trailers. We credit every accepted contribution inCHANGELOG.md.If you find a bug or want a feature: open an issue first. Quick fixes (typo, doc bug, obvious regression) can go straight to a PR. Anything touching schema, retrieval ranking, MCP protocol, or the security boundary needs a design discussion in the issue first.
License + credit
MIT. I built GBrain to run my OpenClaw and Hermes deployments — the production brain behind my AI agents.
Origin story:
docs/ethos/ORIGIN.md.Community PR contributors are credited in
CHANGELOG.mdper release. ZeroEntropy (@zeroentropy) for the embedding + reranker stack that shipped as the default from v0.36 through v0.46. Voyage AI for the asymmetric-encoding recipe template. Ramp Labs for the search quality improvements lineage.