| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| gbrain-darwin-arm64 | 2026-09-15 | 145.6 MB | |
| gbrain-linux-x64 | 2026-09-15 | 183.7 MB | |
| README.md | 2026-09-15 | 40.7 kB | |
| v0.50.1.0 source code.tar.gz | 2026-09-15 | 21.7 MB | |
| v0.50.1.0 source code.zip | 2026-09-15 | 24.8 MB | |
| Totals: 5 Items | 375.8 MB | 1 | |
The community fix wave, rebased onto 0.50.0.0: 21 contributor pull requests adopted or reworked with credit, 35 verified open issues fixed directly. gbrain sync --json prints one JSON document again, so piping it into jq works, and a sync that only swept dead pages tells you so instead of "Already up to date". Brains on Gemini embeddings get a real dollar estimate in the cost gate, facts extraction on a local Ollama model asks for schema-constrained JSON so small models stop returning malformed output, and gbrain dream --dry-run stops billing you for takes and calibration while the patterns phase skips outright when nothing new has been reflected on. A remote search on a brain that has not been reindexed says so instead of claiming a clean miss, each Codex rollout lands on its own conversation page, and gbrain config set accepts the search.* keys the search path actually reads. A source marked syncEnabled: false is left alone by the daemon, the phantom redirect no longer aborts on a canonical page that already holds facts, and emoji folder names carrying an invisible variation selector slugify cleanly. Every adopted code fix carries a regression test proven red before the fix.
To take advantage of v0.50.1.0
gbrain upgrade should do this automatically. If it didn't, or if gbrain doctor warns about a partial migration:
- Run the orchestrator manually:
bash gbrain apply-migrations --yes - No new schema migration ships in this release; the mechanical side is a binary upgrade. Brains whose pages predate the safe-chunk index now see
degraded: [safe_index_pending]on empty remotesearch/queryresults untilgbrain reindex --markdown(or a fresh import) rebuilds their chunks. - Verify the outcome:
bash gbrain doctor gbrain search modes
Say to your agent: "run the brain health check and tell me what changed in this upgrade"
Behavior changes (read before you upgrade)
gbrain sync --jsonprints exactly one JSON document. The cost-gate status object that used to print as a second top-level value now nests inside the envelope ascost_gate, for single-source and--allruns alike, sosync --json | jqandJSON.parsework as documented.schema_versionstays 1; callers that read the gate from the first stdout line must read.cost_gateinstead. (#4684)- A sweep-only sync reports what it did. When a pass only soft-deletes un-syncable pages,
deletedcounts the swept pages and the result readssyncedinstead ofup_to_date/ "Already up to date."; a run whose pull failed reports its swept pages the same way. The strategy root cause shipped in v0.48.5.0. (#4786) gbrain config setaccepts thesearch.*keys the search path actually reads. The registered keys are the camelCasesearch.tokenBudget,search.intentWeightingandsearch.searchLimitplus the reranker, cross-modal and relational knobs. The three snake_case spellings nothing read (search.token_budget,search.intent_weighting,search.limit_default) are still accepted through thesearch.prefix but have no reader; re-set any override under the namegbrain search modesprints for it. (#4605)- Remote searches on a not-yet-reindexed brain say so. Remote/MCP
searchandqueryon a brain whose pages predate the safe-chunk index now reportdegraded: [safe_index_pending]when they come back empty, instead of asserting a clean miss; the pages themselves are still withheld from remote callers, as before.gbrain doctorcounts them and names the fix,gbrain reindex --markdown. (#5004) - Company links in list sections no longer inherit a person's role. A person page whose bio says "is an advisor" or "partner at" used to type every bare company link on the page with that role, including links inside Timeline, See-also, Related, Facts, Sources, Links, Email mention links, Backlinks and Significant moments sections. New extractions type those links as
mentions; per-edge verbs still type normally everywhere. The extractor watermark moves to 2026-09-09, so the nextgbrain extract --stalere-extracts every brain, but that re-run only addsmentionsrows beside the olderworks_at/advises/invested_inedges: those rows are not removed and keep feedingwho works at Xstyle relational answers until a separate repair. (#4977, @ethanbeard) - By-mention checkpoints reset once. The
extract --by-mentionresume checkpoint now hashes every gazetteer entry, so it notices a new entity even when it shares a first word with an existing one. Existing checkpoints are invalidated once on upgrade: the firstgbrain extract links --by-mention --source dbafter upgrading rescans every page. Checkpoints are resume state, not data;gbrain extract --staledoes not perform this rescan. (#4858, @proxynico) - Gemini embeddings are priced. Cost estimates now know Google's
gemini-embedding-001andgemini-embedding-2, directly or through OpenRouter, so the sync cost gate and--max-costchecks stop tripping the no-pricing guard and stop pricing these models at another provider's rate. Expect a real dollar figure where you used to see "estimate unavailable". (#4953, @morven-ai; hosted-google coverage test from [#4989], @dov-kela) gbrain dream --dry-runno longer bills. It skipspropose_takes,grade_takesandcalibration_profile(statusskipped, reasonno_dry_run_support) instead of making model calls and writing proposal, grade and profile rows;--helpnames the trio. (#4823)- The dream patterns phase skips when nothing new happened. A completed run records the newest reflection it consumed (
dream.patterns.last_evidence_ts); until a newer reflection lands in the lookback window, re-runs skip withno_new_evidenceinstead of paying for another model pass, so autopilot's hourly tick cannot mint near-duplicate pattern pages.gbrain dream --phase patterns --onceforces a run. (#4879) context_packanddeltahonorbudget_tokenson the injectable text. Each item is costed as the line it renders to, and the envelope plus section headers are reserved up front (roughly 32 tokens forcontext_pack, 48 fordeltawith asincecursor). A budget below that reserve returns an empty pack:context_packreports it throughdropped_countequal to the item count (it has nohas_morefield), whiledeltaalso setshas_more: true.deltanever drops open threads; only pages and facts count toward the budget. Unbudgeted output is unchanged. (#4761)- Codex rollouts land one page per thread. Each forked or subagent rollout gets its own conversation page, keyed by its own per-thread id (the root session id stays as a legacy fallback), so child rollouts no longer collapse onto the parent's page, re-import on every pass, or get dropped as duplicates. Existing root-session pages keep their slug; a parent page that had absorbed child content re-imports once. (#4981)
- Emoji names with an invisible variation selector re-key. Folder and file names carrying the VS16 selector that macOS Finder and most pickers append now slugify to the clean slug, and
[[wikilinks]]typed with the same emoji resolve to it. Pages keyed under the old selector-bearing slug re-key on their next touch or onegbrain sync --full; twins that already exist are not retired for you (gbrain orphanslists them), so rename or delete them once. (#4985, @ozp) syncEnabled: falseis honored by the daemon. Autopilot's freshness dispatcher skips such a source before queuing a sync job, the full-cycle fan-out drops thesyncphase (and its pull) while keeping lint, backlinks, extract and the freshness stamp, andsync --allandgbrain sources statusagree with it, including on PGLite brains. An explicitgbrain sync --source <id>naming the source still syncs it. (#4952, @Masashi-Ono0611)- The phantom redirect no longer aborts on
idx_facts_fence_key. When the canonical page already holds fenced facts,migrateFactsToCanonical(both engines) renumbers the migrated rows past the canonical page's current maxrow_num(NULL stays NULL);extract_factsre-harmonises exact numbering against the disk fence on its next pass. (#4558) - A stall-aborted embed drain fails the phase. The dream/autopilot embed phase now reports a stall-watchdog-aborted drain (
reason: stall_timeout) as a failed phase instead of a healthy one, matching every other non-CLI embed consumer. The root cause of the wedge itself stays open. (#4599)
AI providers
- Embedding cost estimates now price Google's
gemini-embedding-001andgemini-embedding-2, so brains on Gemini embeddings (directly or through OpenRouter) get a dollar figure instead of "estimate unavailable", are no longer silently priced at another provider's rate in the sync cost gate, and no longer trip the no-pricing gate under--max-cost(#4953, thanks @morven-ai; the hosted-google coverage-gate test is folded from [#4989], thanks @dov-kela) - Facts extraction on a local Ollama model now requests schema-constrained JSON (Ollama enforces
json_schemaserver-side), so small models such as gemma3:4b stop emitting malformed extractor output; every other provider lane is unchanged. An openai-compatible backend that rejectsresponse_format: json_schemaat call time (an older Ollama build, a strict proxy) gets one retry without the schema and is remembered for the rest of the process instead of failing every extraction; the facts schema is OpenAI-strict-safe (every property required, optional ones nullable). Say to your agent: "use my local Ollama model for facts extraction" — your agent runsgbrain config set facts.extraction_model ollama:<model>(#4968, closes [#4863], thanks @ofroiland) claude-clideclares prompt caching (Claude Code caches--printruns itself), sogbrain doctorno longer tells subscription users to move a claude-cli subagent tier to the metered API for a cache they already have (#4973, thanks @LongPV)- GLM-4.5+/5.x models routed through the
ollama:(ollama:glm-5.3-flash:cloud) andopenrouter:(openrouter:z-ai/glm-5) recipes now get the same thinking-by-default output headroom thezhipu:recipe already grants, sogbrain thinkand gateway chat/tool-loop calls no longer truncate at 4000/4096 tokens while the model is still reasoning; pre-4.5 GLM tags keep the conservative caps (#4727)
Dream / cycle
gbrain dream'srecompute_emotional_weightphase no longer holds the cycle lock inside one silent full-brain UPDATE: rows whose weight is unchanged are skipped on both engines (no per-row trigger fan-out), and writes go out in bounded slices with a progress tick, cycle-lock refresh, and abort check between them, so a long first run is visible and interruptible (#4797)gbrain dream --dry-runnow skips propose_takes, grade_takes and calibration_profile (statusskipped, reasonno_dry_run_support) instead of billing LLM calls and writing proposal / grade / profile rows;--helpnames the trio as skipped (#4823, the dry-run aside only)- Dream subagent writes (synthesize agentic lane, patterns, delegated jobs) no longer mint page types the active schema pack does not declare: an explicit undeclared
type:is stored asnotewith the model's type kept infrontmatter.legacy_type, sogbrain syncstops warning every night aboutreflection/original/patternpages. Existing rows keep warning untilgbrain jobs submit unify-typesretypes them (#4852) - A completed run records the newest reflection it consumed (
dream.patterns.last_evidence_ts); until a reflection in the lookback window is newer, re-runs skip withno_new_evidenceinstead of paying for another model pass, so autopilot's hourly global tick can't mint near-duplicate pattern pages.gbrain dream --phase patterns --onceforces a run (and still records what it consumed). Say to your agent: "run the patterns phase now even though nothing changed" — your agent runsgbrain dream --phase patterns --once(#4879)
Atoms / extraction / facts
- Conversation parser: a matched speaker anchor whose date cannot be reconstructed (e.g. a localized month name in a Telegram export) now opens its own message instead of being dropped and folding its words into the previous speaker; the parse reports
date_fallback_count, andgbrain conversation-parser scanprints it asdate_fallback_countin JSON anddate_fallbacksin human output (narrow cut from [#4681], contributed by @jeanpierre121) - Per-slug extractors (sync inline, GitHub/Google source inline, cycle incremental) now resolve each slug to its real on-disk file via a shared
buildSlugPathIndexinstead of rebuildingslug + '.md', so pages whose filenames are not already slugs (spaces, capitals, punctuation) get their links and timeline extracted; a slug the index cannot resolve falls back to the legacyslug + '.md'path before being treated as deleted, so_-prefixed files and dot-dirs waived viasync.include_hiddenare still extracted inline. The sync call sites stamplinks_extracted_atonly for the slugs actually read (slugsSafeToStamp), so a skipped page stays visible togbrain extract --staleinstead of being marked fresh forever. The publishedgbrain/extractsubpath'sextractLinksForSlugs/extractTimelineForSlugsnow return{ created, processed }instead of a number (no in-repo consumer). (#4967, @IvanPham03) - Phantom redirect no longer aborts on
idx_facts_fence_keywhen the canonical page already holds fenced facts:migrateFactsToCanonical(both engines) now renumbers migrated rows past the canonical page's current maxrow_num(NULL stays NULL);extract_factsre-harmonises exact numbering against the disk fence on the next pass (#4558) - The
extract_factscycle reconcile now honorsvisibilityandnotabilityedits on existing## Factsfence rows. Editing either cell on a row whose claim, source, and row number were unchanged used to be a silent no-op (the cycle reported 0 reconciled and the DB kept the old value indefinitely); the page now re-heals once through the existing atomic wipe+reinsert, and a page whose fence and DB already agree cannot churn (#4870)
Doctor / brain health
- Schema drift self-heal: a brain whose migration ledger reads current but whose
links_link_source_checkconstraint reverted to the pre-v114 closed allowlist (drifted restore, manual DDL) silently rejected every kebab provenance link write (atom-provenance,concept-provenance).gbrain apply-migrations(and every migrate pass) now probes the live constraint shape once the ledger has reached v114 (older brains get the gate from migration v114 itself) and restores the kebab-case gate: it counts violating rows first and refuses loudly, altering nothing, when existing rows fail it; on Postgres the restore uses the same non-blocking two-phase form as v114 (ADD ... NOT VALIDin a transaction,VALIDATE CONSTRAINToutside it, validate-only when the definition is right but unvalidated), while PGLite keeps the one-shot form.gbrain doctorgained alinks_link_source_checkrow (fail when the definition rejects kebab writes; warn when the gate is absent or NOT VALID). Same self-heal class as the timeline-dedup and pages-upsert-arbiter repairs (#4613) gbrain reindex-search-vectornow survives interruption: it records an in-progress marker before flipping the FTS trigger language, checkpoints every batch so a re-run with the sameGBRAIN_FTS_LANGUAGEresumes where it stopped, andgbrain doctorfails withfts_reindex_incomplete(naming the resume command) until the run completes; previously a killed run silently left keyword search split across two tokenizers. The marker is cleared when the very first DDL statement fails on a fresh run (a missing privilege cannot leave a permanent falsefts_reindex_incomplete) and preserved when a resume fails, so doctor keeps warning about a genuinely split index and never about one that never started (#4795)gbrain doctorimage_assetsno longer reports Supabase/S3 storage objects as "missing from disk": file writers (files upload,upload-raw,files sync, thefile_uploadop) now stampmetadata.storagewith the configured backend, doctor skips explicitly non-git lanes with a note pointing atgbrain files verify, and every files upsert merges metadata on conflict so older unmarked rows heal on their next changed upload. Genuinely vanished local/git assets are still detected (#4910)gbrain doctor'ssource_config_shaperepair hint no longer promises that "anygbrain sourcesconfig write" heals a non-object source config (set-cr-mode,rename,set-pathwrite other columns and left the check red). It now leads with the paste-ready SQL, namesgbrain sources federate <id>/unfederate <id>(re-assert the source's current federation state; federate on an isolated source also flips it into default search), and lists the commands that do not repair it; the runtime warning in sources-load says the same. Text only (#5002)gbrain doctor's truncated-pages hint no longer tells you to rungbrain sync --force(a flag that never existed); it gives the working re-import steps and points at docs/integrations/reliability-repair.md. Text only.- The remote doctor's
contextual_retrieval_coveragecheck counts only the caller's granted sources, matching the other scope-aware checks.
Search / eval
- Searches through the
queryop read search-mode settings once instead of twice, saving a config read on hosted Postgres and closing a cache-key/result mismatch window (#4972, @Masashi-Ono0611) gbrain config setnow registers exactly thesearch.*keys the search path reads (the camelCasesearch.tokenBudget/search.intentWeighting/search.searchLimitplus the reranker/cross-modal/relational knobs; the three unread snake_case spellings are gone),gbrain search modesprints the real copy-pasteable config key for every overridden knob, andsearch.adaptive_return*set on the DB plane now reaches the adaptive return policy as documented. The three retired spellings (search.token_budget,search.intent_weighting,search.limit_default) are still accepted byconfig setthrough thesearch.prefix but have no reader; re-set them under the camelCase names shown bygbrain search modes(#4605)- Remote/MCP
searchandqueryon a brain whose pages have not yet been reindexed to the safe-chunk index version now reportdegraded: [safe_index_pending](the MCP empty-result block names it) instead of asserting a clean miss;gbrain doctorcounts the withheld pages and names the consequence with thegbrain reindex --markdownfix. The remote withholding itself is unchanged, and the disclosure probe uses thechunker_versionindex rather than scanning every markdown page (#5004) - The
gbrain initmode picker's cost note no longer claims the semantic result cache is free while result caching is disabled.
MCP / schema / auth
- MCP: remote
put_page/capturenow say so in the response (write_through.warning) when a write landed only in the database because the resolved source has no repo or local path configured; local CLI output is unchanged. Addresses [#4844]'s minimum ask (#4956, @javieraldape) docs/mcp/DEPLOY.mdgains an "Owner login links for AI agents" section documenting the existing owner login flow (POST /admin/api/issue-magic-linkwith the server bootstrap credential, five-minute single-use link, private delivery, never GET the link to verify it) andgbrain auth --helppoints at it, so an agent asked for the admin login link no longer falls back to the static/admin/URL or the bootstrap token. Say to your agent: "Give me the GBrain admin login link" — your agent calls POST /admin/api/issue-magic-link with the server bootstrap credential and hands you a five-minute single-use link (#5008, fixes [#5007], contributed by @garrytan-agents)gbrain schema show/graph/lint/explain/statsand theschema_graph/schema_explain_type/schema_lint/schema_statsMCP ops now resolve the active pack through the brain-wide DB-configschema_packtier, matching whatgbrain schema activeandget_active_schema_packalready report, so there are no more split answers about which pack is active within one process (#4653)- A path-shaped
schema_packvalue in the DB orgbrain.ymlconfig plane now resolves as an unknown pack instead of being joined into the schema-packs directory path. gbrain serve's idle maintenance sweep now reconciles links for the same source the stdio session resolves (.gbrain-sourcedotfile, registeredlocal_path,sources.default), not justGBRAIN_SOURCE/default, so a dotfile-scoped MCP session gets its body wikilinks reconciled without a serve restart. The brain-ops skill, theput_pagedescription and its remote hint now say plainly that MCP writes (stdio and HTTP) skip inline auto-link and are reconciled asynchronously by the serve sweep orgbrain sweep --once(#4679)context_pack/delta:budget_tokensis now honored by the injectabletext. Each item is costed as the line it renders to and the envelope plus section headers are reserved up front (roughly 32 tokens forcontext_pack, 48 fordeltawith asincecursor);budget_usedreports the token estimate oftext, envelope and headers included. A budget below the reserve returns an empty pack:context_packreports the loss asdropped_countequal to the item count (it has nohas_morefield) anddeltasetshas_more: true.deltanever budget-drops open threads: every thread is rendered whole and only pages and facts count toward the budget (dropped_count/has_morecount only pages and facts;budget_usedexceeds the budget only when the envelope plus the threads alone do). Cursor semantics are unchanged from v1 (the page keyset, no hold or skip state). Unbudgeted output is unchanged (#4761)docs/mcp/DEPLOY.mdstates the dual-mode/mcpauth contract: the same route verifies OAuth 2.1 tokens andgbrain auth createbearers, and the 401 +resource_metadatachallenge is spec-mandated discovery emitted for ANY header-less request, not proof the configured bearer failed. It adds a Troubleshooting entry for "client status shows needsAuth but tool calls succeed" (judge fromwhoami/gbrain auth test), anddocs/guides/agent-to-gbrain.md'sgbrain connectrow cross-links it (#4893)
Sync / import
gbrain import --jsonalso reportssource_id, the resolved destination source the pages were written to (sourceId ?? 'default', the same value the ingest_log row records) (#4779, @chris-conte)- Emoji folder/file names written with a variation selector (the VS16 macOS Finder and most pickers append) now slugify to the clean slug, and
[[wikilinks]]written with the same emoji resolve to it; pages previously keyed under the invisible-selector slug re-key on next touch or onegbrain sync --full. Say to your agent: "re-sync my vault in full" — your agent runsgbrain sync --full. Existing pages that were keyed under a selector-bearing slug are not retired automatically; rename or delete those twins once (gbrain orphanslists them), and remoteput_pagestill accepts selector characters in slugs (#4985, @ozp) - On durability-hardened brains,
delete_pagenow commits the page removal (path-limited, best-effort) so the post-commit hook pushes it and commit-driven sync sees it, matching the write side; thedelete_pageresult'swrite_throughcarriescommitted: truewhen the removal landed in git (hardened repos only) (#4994, @howardpark) - New persisted
sync.include_hiddenconfig key, the dot-directory waiver's twin tosync.exclude, sosync --all, autopilot and the dream cycle honour a committed.github/-style directory that--include-hidden(refused under--all, unavailable to internal callers) could only admit per invocation. Same dialect (comma/newline list, trailing/= whole subtree), unioned with the per-call flag, read above the full-sync early returns so the very first sync honours it; default unchanged (unset admits nothing). The--allrefusal and--helpnow name the key. Say to your agent: "index my repo's .github folder on every sync" — your agent runsgbrain config set sync.include_hidden '.github/'. [#4901]'s dot-directory default question stays open. (#5003, @Jey2311) gbrain syncandgbrain importnow refresh a page's recordedsource_pathon the unchanged-content skip path, so legacy rows whose bookkeeping still named a pre-rename file self-heal on the nextsync --fullinstead of being reconcile-deleted, and write-through stops recreating the old directory on every write; the stored path (now projected bygetPageon both engines) is compared first, so re-syncing an unchanged tree issues no bookkeeping writes (#4588)gbrain sync --json(single-source and--all) now emits exactly ONE JSON document on stdout: the cost-gate status object is nested inside the envelope ascost_gateinstead of printed as a second top-level value, sosync --json | jqandJSON.parsework as documented (schema_version stays 1; --json callers that read the gate from stdout line 1 must read.cost_gate) (#4684)- A sync pass that soft-deletes un-syncable pages now reports them:
deletedcounts the swept pages and a sweep-only run reportssyncedinstead ofup_to_date/ "Already up to date."; a sync whose pull failed still reports the un-syncable pages it swept indeletedon itspartial/pull_failedresult instead of zero (the strategy root cause shipped in v0.48.5.0; this closes Expected [#3] of [#4786]) - Sync no longer queues an automatic embed-backfill after a run that only swept un-syncable pages or deleted files (nothing new to embed); the jobs
synchandler reportsembed_skip_reason: 'no_new_content'for such runs, so a real import inside the old cooldown window is no longer skipped.
Transcripts / code intel
- Transcripts: Claude Code workflow-run artifacts (nested
subagents/workflows/<wf>/agent logs, theirjournal.jsonl, and title/metadata-only session stubs) no longer read as host-format drift orunknown formaterrors, sogbrain transcripts ingest --since lastadvances its watermark again instead of re-scanning the same files forever (#4969, thanks @LongPV) code_callees/gbrain code-calleesnow honor the documented "bare or qualified name" contract: a bare method name whose chunk identity is namespace/class-qualified (C#, Java, Ruby, Rust, TS class methods) resolves via an exact fallback on the chunk's bare symbol name instead of returning 0. Say to your agent: "what does SubmitAsync call?" — your agent runsgbrain code-callees SubmitAsync(#4670)- Codex transcript imports: each forked/subagent rollout now lands on its own conversation page. Identity comes from the rollout's own per-thread id (with the root session id as a legacy fallback) and the first session header wins, so child rollouts no longer collapse onto the parent's page, re-import on every pass, or get dropped as duplicates. Existing root-session pages keep their slug; a parent page that previously absorbed child content re-imports once. Say to your agent: "import my conversations from Codex" (#4981)
Minions / autopilot
- A source with
config.syncEnabled: falseis no longer auto-synced by the daemon. Autopilot's per-source freshness dispatcher skips it before queuing a sync job, and the full-cycle fan-out drops thesyncphase (and the pull that feeds it) from that source'sautopilot-cyclejob while keeping lint/backlinks/extract and the freshness stamp;sync --allshares the same predicate (and now also honours the flag when PGLite hands the config back as a JSON string), andgbrain sources status/ the status snapshot reportsync_enabled: falsefor such a source on PGLite brains, matching whatsync --allskips. An explicitgbrain sync --source <id>naming the source is unchanged. refs [#4399] (its cycle_freshness exemption ask stays open). (#4952, @Masashi-Ono0611)
Bootstrap / hooks
- Ambient writeback's Stop hook now banks the real prompt when a Claude Code turn ends in a tool call: tool-result entries (which Claude stores under a user role) no longer shadow the human prompt or suppress the wide-tail retry, and
<command-name>/<local-command-stdout>transcript records are no longer treated as the user's prompt. Say to your agent: "Turn on ambient writeback so my preferences get remembered" — your agent runsgbrain config set memory.auto_writeback salient(#4980, @markkasdorf) gbrain bootstrap harness --statusnow derives the claude-code MCP target's state from the liveclaude mcp getownership check: a registration replaced by another install (different URL, or a non-HTTP serve at user scope) readsfailed — <reason>in the human line and--json targets[]and exits 1 instead of replaying the receipt's apply-timeconfirmed; not-found/unparseable output keeps the honest degrade (#4586)gbrain frontmatter install-hooknow installs for sources registered as a subdirectory of a git repo (the<workspace>/brainlayoutgbrain bootstrapcreates): the hook lands at the enclosing repo root, scoped by git pathspec to that subdirectory so host-repo markdown is never validated; several nested sources share one hook (union of scopes, uninstall drops one at a time); root-registered sources get a byte-identical script (#4600)gbrain frontmatter install-hooknever silently disables hooks you already have. It leavescore.hooksPathunset, still writes the hook, and reportsinstalled_unwiredwith the reason and the manual wiring step when the host repo's.git/hooksalready holds active hooks, when.githooks/already holds other executable hook scripts (wiring would have started running them), or whencore.hooksPathin any scope already points somewhere other than.githooks(husky, secret-scanner templates, dotfiles); a value that already resolves to.githooksis left alone and counts as wired. Re-runs and fresh clones that already carry the committed hook now reach the wiring step:unchangedmeans current AND wired, and an inert hook reportsinstalled(wired now) orinstalled_unwired(blocked, with the reason).- The frontmatter pre-commit hook validates staged files whose names contain spaces or non-ASCII characters (NUL-separated listing and a POSIX
readloop, proven under dash and bash-as-sh).install-hookrefuses a symlinked.githooks/orpre-commitinstead of writing (or, on--uninstall, removing) through the link, and refuses a source path that contains a line terminator instead of embedding it in the generated script; in both cases the CLI prints the real skip reason for that source and continues with the remaining sources, on install and on--uninstallalike. - Bootstrap.md's install table now says
GBRAIN_STOP_PUSHandhooks.stop_push_debounce_mingovern the Stop-hook push only, documents the SessionEnd push as switch-free (GBRAIN_HOOKS=0is the only off-switch) with itsreason: push_spawnedheartbeat attribution, and adds the SessionStart crash-recovery push row (#4986)
CLI
gbrain reindex --code, a flagreindexnever parsed, now fails loud as an unknown flag instead of being accepted silently; rungbrain reindex-code. The CLI flag registry no longer legalises flags that only appeared in code comments, and the three docs that still saidreindex --codewere corrected.gbrain maintain --safe --jsonemits a single parseable JSON document; the embedded stale-extraction summary no longer leaks onto stdout.gbrain files upload-rawno longer clears a file's stored metadatatypewhen the same file is re-uploaded without--type.
CI / test infra
- Nightly hermes door: installer digest re-pinned after an upstream installer change so the door re-verifies digest + payload + version pins again; the door still loud-fails on schedule until the owner sets ANTHROPIC_API_KEY (#4991, thanks @janusch; fixes [#4990])
serve --http
gbrain serve --httpno longer retains every accepted TCP connection for the life of the process (Bun's node:http never emits socketcloseon server-side sockets), so a deployment whose health checker opens a fresh connection per probe no longer grows its memory with every check. Accepted sockets are now tracked weakly; shutdown still severs live keep-alive connections (#4955, @pavelpp-topia)gbrain serve --httpshutdown is bounded: ifserver.close()has not returned after 5s (a connection the socket tracker could no longer reach), the daemon logs one line and finishes shutting down instead of hanging, and aclose()error that arrives after that deadline is logged instead of dropped.docs/mcp/DEPLOY.mddocuments the tailnet/LAN-onlyserve --httpshapes (Tailscale Serve over the loopback bind with anhttps://--public-url; plain-HTTP bearer-only with no--public-url), adds a Troubleshooting entry for the MCP SDK'sIssuer URL must be HTTPSstartup exit and itsMCP_DANGEROUSLY_ALLOW_INSECURE_ISSUER_URLopt-in, notes that--source-guardis stdio-only (HTTP writes are token-scoped) and cross-links theGBRAIN_HTTP_CORS_ORIGINallowlist;docs/mcp/ALTERNATIVES.mdsplits Tailscale Serve (tailnet-only) from Funnel (public) (#4500)
Links / graph
- Mention linking with
link_resolution.cross_sourceon now treats same-slug pages in different sources as distinct targets (a foreign namesake of the scanning page is no longer dropped as a self-link, and two sources sharing a slug both link), and theextract --by-mentionresume checkpoint notices a new entity even when it shares a first word with an existing one (its hash now covers every gazetteer entry). Existing by-mention checkpoints are invalidated once on upgrade, so the firstgbrain extract links --by-mention --source dbafter upgrading rescans every page; checkpoints are resume state, not data (#4858, @proxynico) - Person-page role prior (bio "is an advisor" / "partner at" language) no longer types bare company links inside Timeline, See-also, Related, Facts, Sources, Links, Email mention links, Backlinks and Significant moments sections: new extractions type those links as
mentions, per-edge verbs still type normally everywhere, and a## Timeline/## See alsoheading quoted inside a fenced code block no longer suppresses the prior for the prose that follows it. Precision over recall, the same posture as [#3466]. The link-extractor watermark moves to 2026-09-09, so the nextgbrain extract --stalere-extracts every brain; that re-run only addsmentionsrows beside olderworks_at/advises/invested_inedges from list sections and does not remove or retype them, sowho works at X/who advises Xanswers that rested on those edges keep coming back until a separate, opt-in repair (#4977, @ethanbeard) - The
autopilot.incremental_extract_include_frontmatterknob is now honoured on every extraction path (sync's inline extract, the GitHub/Google source inline extracts, theextract_staleminion,gbrain maintain, and a flaglessgbrain extract --stale), not just the autopilot cycle. Those paths used to skiprelated:/sources:frontmatter edges AND stamp the page fresh, so an enabled knob was silently defeated on cron/webhook/minion/maintain runs and the cycle's stale drain never revisited the pages.1/yes/onnow count as true for the key, and a hand-edited string or number in config.json no longer resolves to false and shadowsgbrain config set(only a real boolean is a file-plane answer). No new config key; default unchanged. Say to your agent: "keep my frontmatterrelated:links up to date on every sync" — your agent runsgbrain config set autopilot.incremental_extract_include_frontmatter true. Fixes [#4997]. (#4999, @sheelcheyne) - Markdown links carrying a
#anchor([Notes](registry/tally.md#section),[see](b.md#section)) now produce a graph edge to the target page on both the DB and--source fsextract paths (the anchor is dropped, as wikilinks already did), and pass-1 markdown targets are lowercased to match how slugs are stored, so a brain that links with anchors no longer reports an empty graph (#4995)
Pages
delete_pageandrestore_pagenow say what they do to disk: the MCP tool description,gbrain delete --help,gbrain pages --help, and the TOOL_CATALOG row all state that deleting a page also removes its markdown file from the source working tree (the sourcelocal_path, orsync.repo_pathwhen the source has none; skipped whensync.write_throughis off) and that restoring re-creates it, with thewrite_throughresult field reporting the outcome. Text only; the behavior itself is unchanged (#4829)
Docs
- The context-audit skill's deterministic token pre-pass now divides
wc -cbytes by the calibrated 2.8 (ceil integer math(n*10+27)/28), so the always-loaded-stack estimate lands within about ±8% of the measured count rather than 13-24% under. This replaces the chars/4 estimate (which undercounted Claude-loaded markdown by 25-35%); the report header states the divisor (Estimate basis: bytes/2.8) and a host-reported exact context breakdown (e.g. Claude Code/context) outranks the estimate. Say to your agent: "context audit" / "reduce context size" (#4988, [#5009], contributed by @javieraldape) - The mode-bundle
expansionrow and thesearch.expansionkey govern no shipped verb:gbrain queryexpands in every mode unless--no-expand, whilesearch, the memory verbs and the eval harnesses pin expansion per call; search-modes.md, the init picker copy, the CLAUDE.md matrix, RETRIEVAL.md, eval-bench.md and thegbrain search modesper-call note now say so (#4601) docs/mcp/OPENCLAW.mdOption 2 now registers gbrain withopenclaw mcp add gbrain --command <abs path> --arg serve --env GBRAIN_HOME=$HOME(OpenClaw 2026.8.x readsmcp.serversin~/.openclaw/openclaw.json, notmcpServersinconfig.json), Verify checksopenclaw mcp list, Option 1 adds the install-the-plugin-by-id (gbrain-context-engine) step before setting thegbrain-contextslot, and a note says to leaveGBRAIN_SOURCEunset unless single-source retrieval is intended; the README OpenClaw bullet matches (#4842)- System-of-record.md's Timeline row and compiled-truth.md now say timeline extraction scans the whole page, not the section after the
<!-- timeline -->sentinel: a dated[Source: ..., YYYY-MM-DD]citation in compiled truth mints a timeline row (dated by the citation, summary = the bullet it sits in); the one placement that mints nothing is a citation alone in its own paragraph, andgbrain config set auto_timeline offdisables the write-path extraction (#4987)
Other
- The dream/autopilot embed phase now reports a stall-watchdog-aborted drain (
reason: stall_timeout) as a failed phase instead of a healthy one, matching the contract every other non-CLI embed consumer already honours (#4599, residual; root cause of the wedge stays open) - Skillopt: a validation gate where every task fails (dead target provider, e.g. a logged-out
claude-clichild) or every rollout's judge errors now ends the runerroredwith the provider message as the failure detail (exit 2) instead of finishing as a plausibleno_improvementat 0.000; steps where the optimizer proposed no edits say so on stderr and log audit reasonno_edits_proposed; the hermetic-config docs no longer claim macOS survives the empty-config-dir form (#4741) - Brainstorm/lsd: a judge-phase failure no longer deletes the run checkpoint (every paid cross result stays on disk with
judge_done=false); the advice now names the existinggbrain <brainstorm|lsd> --resume <run_id>, which re-runs only the judge and re-scores into the same saved idea page the failed run wrote (the slug rides in the run checkpoint) instead of saving a second page under a new slug, rather than a--retry-judgeflag that never existed (#4766)
With thanks to every contributor whose pull request this wave adopts: @chris-conte, @dov-kela, @ethanbeard, @garrytan-agents, @howardpark, @IvanPham03, @janusch, @javieraldape, @jeanpierre121, @Jey2311, @LongPV, @markkasdorf, @Masashi-Ono0611, @morven-ai, @ofroiland, @ozp, @pavelpp-topia, @proxynico, @sheelcheyne, and to the reporters whose verified issues drove the direct fixes.