* docs(designs): agent-bootstrap plan + design docs (normative, review-absorbed) The scrubbed, in-repo sources of truth for the gbrain bootstrap wave: AGENT_BOOTSTRAP_DESIGN.md (product scope/sequencing) and AGENT_BOOTSTRAP_PLAN.md (implementation; all review-finding IDs inlined). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(bootstrap): format spec, question bank, identity templates, bundled assets agent.json manifest (format_version 1, initialized sentinel) + machine-local install receipt [CX2-1, CX2-12]; 12-question/6-required interview bank with consent keys and a persist:false sink for the optional provider key [CX2-13]; ten {{TOKEN}} identity templates (generic, adapted to gbrain ops — gates call recall/query/put_page, write-through-ops rule, keyless agent-authored facts, silence contract); assets embedded compiled-binary-safe via file-type imports [ENG-6]. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(bootstrap): runbook, README paste block, bootstrap guide, TODOS entries BOOTSTRAP_FOR_AGENTS.md (agent-driven install runbook: CLI phase list is the source of truth, never-invent rules, Codex approvals preflight, keyless posture, failure-modes table, version stamp for the skew check); README gains the full-agent paste block pinned to latest-stable inside the Claude Code/Codex quick start (memory-only tier stays); docs/guides/bootstrap.md carries the full install/security/consent/degradation/uninstall contract. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(designs): spike instrument for the bootstrap wave (build order 0) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(bootstrap): interview + render engines Interview gate with read-back confirm-hash (any later answer change clears the confirmation — the hostile single-batch case is structurally impossible), per-answer provenance, caps + escaping at set time, config-sink routing for the provider key; renderer with hard-fail token sweep, subordinate fencing of principal input, never-clobber + backups, deterministic minimal mode for the template repo, scaled byte floors. 58 unit tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(bootstrap): private-repo lifecycle — repo create, attach, uninstall, run lock gh-gated private repo creation with API-verified privacy (rate-limit distinct from public), refuse-foreign-origin with attach as the sanctioned path, atomic bootstrap mutex (pid liveness + age + token), receipt-keyed uninstall that never wholesale-deletes the gbrain home and only offers --delete-brain for a brain it created; read-only PGLite lock probe (never opens the engine). 54 unit tests, injectable exec seam throughout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(release): latest-stable ref, template-repo publish job, bootstrap CI guards release.yml advances the latest-stable tag only after assets publish (the paste block's permanent ref — copies in the wild never rot) and gains a PAT-gated publish-template job verified against the vendored tree; two skip-graceful guards (sanctioned-ref + runbook stamp; template/token bijection + placeholder assertion + generator byte-diff) wired into verify; README + runbook re-admitted to the CI cache hash; vendored deterministic template tree generated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(context): IPC v2 turn_context + 8KB assembly + visibility resolver + session identity Discriminated-union IPC with handler map, protocol echo (stale-serve detection), shared-secret gate, server-side source binding, per-kind budgets; turn-context assembly (reflex pointers + volunteered pages + world-only hot facts) under a data-not-instructions envelope trimmed to the harness's 10KB hook-output cap; facts.default_visibility resolved through one helper at all four sites (explicit caller wins, typos fail closed); typed sessionId threads _meta.session_id into the hot-memory cache key. 50 new tests; 180 adjacent tests confirmed green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(persistence): secret-scan, gbrain sources push, durability unification Pattern secret scanner (own runtime allowlist, redacted previews, corpus-write redaction mode); sources push runs the whole scan→stage→commit→pull→push sequence under one cross-platform lock (mkdir-atomic, pid+age+token) with a deny-glob backstop, commit-first divergence-safe pull, refuse-unverifiable visibility, and push-status telemetry; gbrain-home choke point unifies GBRAIN_HOME semantics with config (0700); durability is parent-repo-aware and rotates its push log at 0600. 35 new tests; 200 existing green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(sources): harden/pull gates accept sources inside a parent git repo The bootstrap workspace registers brain/ (a subdirectory) as the source; the durability core already resolves the repo root, so the command gates now check inside-a-repo rather than .git-right-here [CX2-3]. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(serve): resident maintenance sweep + keyless capability probe The lock-owning serve process now closes the persistence loop: startup (3s post-connect, best-effort, unref'd) and idle (10-min quiet intervals through the injectable timer seam) sweeps run facts-fence reconciliation, deterministic link/timeline extraction over recent workspace pages, and spend-gated corpus ingest (skipped keyless — agent-authored fences cover it). gbrain sweep --once is the trusted CLI seam bootstrap verify uses. Capability probe renders the honest keyless/keyed report. Full reuse of the cycle extractor + extract cores; 26 new tests, neighbors green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(hooks): engine-free gbrain hook command, settings writers, transcript parser Four hook events (session-start digest + crashed-session recovery push, user-prompt turn-context injection under an 800ms deadline and the 10KB cap, stop buffers, session-end corpus write with redaction/retention/dedup + best-effort push); structural JSON settings merger keyed by a _gbrain marker (foreign hooks and permissions survive); dated host-spec registry; Claude Code .jsonl parser as a spec-target with a scrubbed 7-shape fixture. Heartbeat is counters-only by construction. 59 tests; zero engine modules in the import graph. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(bootstrap): cross-link the full-agent path from the connection docs Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(bootstrap): dispatcher, verify, status — the command assembled gbrain bootstrap {status,interview,render,repo,hooks,verify,uninstall,attach}: engine-free except verify (owns its engine, in-process sweep — no live-serve conflict); phase list is the TS source of truth with install.jsonl telemetry and the support blob; verify's fail-soft check suite covers the real write path (put_page → write-through file → sweep → graph floor → recall), passes keyless, persists snapshots, and ends with the first-run tour. cli.ts wired per the three-touchpoint rule; doctor gains the bootstrap check group (silent on machines with no bootstrap state). 28 new tests; 353 adjacent green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: KEY_FILES bootstrap cluster + CLAUDE.md dispatcher row (+ build:llms) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(bootstrap): e2e pins — hook-under-live-serve, attach, degraded modes, compiled binary, Docker harness The permanent pins: a real serve holds the PGLite lock while the engine-free hook completes (and a direct engine open provably throws LiveServeLockError); stale-socket fail-open; machine-2 attach with marker-keyed hook repair; decline-everything installs verify green with every degradation named; the compiled binary renders bundled templates in an empty cwd. Offline Docker harness (networkless, read-only) gated into heavy-tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(bootstrap): register doctor check categories + system-of-record allow comments The six bootstrap doctor checks join OPS_CHECK_NAMES; the sweep's batch link/ timeline inserts carry the explicit extract-path allow comments (the sweep IS the extraction path for workspace pages). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(test): shard wedge cap tracks suite growth (1500s -> 1800s) At ~9000 tests a healthy shard finished at 1466s and two progressing shards were false-killed at the old cap; 1800s restores ~25% headroom over the slowest observed healthy shard. Real hangs still hit it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(ci): cache-hash policy — README + runbook edits must invalidate [C2] The old deny-list assertion predates the paste block; README.md and BOOTSTRAP_FOR_AGENTS.md are policy-doc re-admissions now, so their edits must change the hash (a paste-block edit shipping under a cached green was the C2 hole). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(test): classify post-suite exit-hangs as warn-pass; file the leak forensics A shard killed by the wedge watchdog with every assigned file started and zero fail markers did all its work and leaked a handle at exit — pre-existing and master-reproducible (P1 TODO carries the full bisect forensics). Bun's per-test timeout turns a hung test into a (fail), so the classifier cannot mask one. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(test): shard cap 2400s — the count-balanced heavy shard needs it under contention Observed: the heavy shard still progressing 22s before an 1800s kill while siblings finish at 1150-1550s (split balances file count, not weight). Filed the load-sensitive WAL-repair flake (pre-existing, master's v0.42.75.0 wave). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(bootstrap): quarantine env-mutating suites to the serial lane check-test-isolation R1: six new files mutate GBRAIN_HOME/env at module scope — the serial lane (one process per file) is the guard's prescribed home for them. All 114 tests pass post-rename. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(readme): per-harness install sections — Codex, Claude Code, then OpenClaw/Hermes Each harness gets its own complete paste-block section (desktop app first, terminal noted — Claude Code CLI is the identical harness; Codex CLI works pull-based today); the OpenClaw/Hermes platform path keeps equal weight with its one-click deploys and INSTALL_FOR_AGENTS block intact; memory-only and remote-connect tiers consolidated under 'Lighter ways in'. Supersedes the review's D5 ordering by user direction; stale heading references updated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(readme): Codex as the recommended first step; OpenClaw/Hermes framed as-intended, high-cost The install section now routes newcomers explicitly: Codex first (subscription-priced, nothing to deploy), OpenClaw/Hermes as GBrain used the way it was designed — always on, at real server + API cost. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: doc-audit code chasers — broken recovery hints, stale op description, auto_link key Four small code fixes surfaced by the markdown accuracy audit: - doctor's auto-RLS recovery hint pointed at `apply-migrations --force-retry 35`, which cannot work (--force-retry targets the vX.Y.Z orchestrator registry, not the numeric schema MIGRATIONS array). Hint now points at the recreate SQL in docs/guides/rls-and-you.md; test pins against regression. - v0_11_0 migration printed the same broken-mechanism class of hint (`config set minion_mode` writes DB config nothing reads); now names `apply-migrations --mode` + preferences.json, the real setter. - submit_job's op description hardcoded a stale handler list; now points at registerBuiltinHandlers as the source plus the --follow discovery trick. - `auto_link` added to KNOWN_CONFIG_KEYS: read by link-extraction, reconcile-links, and sweep, and documented as the off-switch in brain-ops/maintain, but the allowlist rejected `config set auto_link false`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: repo-wide accuracy + MECE reform from the 9-bucket markdown audit A code-grounded audit of every markdown file (root, architecture, guides, mcp, tutorials, docs-root, operations/eval/designs, skills, recipes) followed by a fix wave with per-bucket ownership. Four classes of change: Accuracy — every documented command/flag verified against src/ before writing: dead commands replaced with working ones (pages purge-deleted, jobs watch --follow, gbrain restore, import-based Obsidian flow, space-separated --scopes, real thin-client recipes, working isolation verification, real supervisor restart procedure, curl-based ngrok health check, real minion_mode setter); count drift fixed with rot-proof phrasing (100+ ops, 50+ bundled skills via skills/manifest.json, 140+ engine methods, KNOBS_HASH_VERSION pointer instead of hardcoded versions); stale claims corrected (search-mode defaults, RETRIEVAL pipeline order incl. autocut, sentinel rules, refusal-list mechanism, engine snapshot, shard cap 2400s + EXIT-HANG classifier in TESTING.md, latest-stable + publish-template documented in RELEASING.md as release.yml promises). MECE — one home per concept, pointers elsewhere: test isolation → TESTING.md; OAuth registration + --bind/--public-url lore → DEPLOY.md; mode bundles → guides/search-modes.md (the home the CLAUDE.md dispatcher always promised); merge contract → schema-packs.md; WAL ladder → ENGINES.md; quiet-hours → quiet-hours.md; capture taxonomy → entity-detection.md; person-page taxonomy → compiled-truth.md; brain-first protocol → brain-first-lookup.md; refresh semantics → refresh-algorithm.md; KEY_FILES.md deduplicated (58 extension entries merged, one entry per file); infra-layer.md rewritten as a pointer page. Privacy — placeholder sweep across guides, docs, skills, and recipes per the iron rule; per-release narration stripped from reference docs (current-state prose only). Bootstrap coverage — AGENTS.md pointer, RESOLVER routing row, INSTALL.md path, tutorial cross-links, keyless-mode sections in spend-controls/headless-install. skills.lock.json regenerated; llms.txt/llms-full.txt rebuilt. Gates: verify 36/36, typecheck clean, doctor 96/96, skills-integrity + resolver + build-llms + config-set + migrations all green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(readme): refresh production-brain stats to current brain-repo counts 155,795 pages / 24,589 people / 5,340 companies, counted from the brain repo's current HEAD; the "100K-page brain" framing moves to 150K to match. Cron-fleet count unchanged (its store lives on the deployment host, not in the repos available for verification). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(scan,push): modern OpenAI/Voyage key patterns, scan staged blobs not disk - secret-scan matches sk-proj-/sk-svcacct-/sk-None- and pa- Voyage keys (the bare sk- pattern missed every current OpenAI key format). - workspacePush stages first, then scans the staged index blobs via git cat-file, closing the scan-then-stage TOCTOU where a file changed between snapshot and commit shipped unscanned. - shared binary-sniff helper, memoized glob regexes, atomic push-status write, and tests for pull_conflict + gitignored deny-match paths. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ci): regenerate flag registry for new commands, harden shard classifier + release token - cli-flag-registry.generated.ts regenerated: bootstrap/hook/sweep and sources push --message/--allow-unverified-remote were missing, so the strict #2185 validator rejected real invocations and skipped the new commands entirely. - EXIT-HANG shard classifier now requires every assigned file to have started before warn-passing a watchdog kill (was fail-open). - release.yml passes TEMPLATE_REPO_PAT via http.extraheader, off the argv. - compiled-binary e2e fails loud in CI instead of a silent permanent skip. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(hook,sweep,ipc): non-blocking hook pushes, bounded sweep + cache, source-bound resolve - session-start/session-end no longer run synchronous git + inline push inside their self-deadline; a detached child does the push and the hook returns immediately (blocked Claude Code startup for minutes on a dirty tree before). - serve sweep drops the unbounded listAllPageRefs, resolves only candidate targets, claims corpus files atomically (no double-LLM-spend race), and caps the fence LIKE scan; heartbeat writes are O_APPEND with rare compaction. - hot-memory cache evicts expired entries and bounds entry count (the key is caller-controlled via _meta.session_id). - v1 resolve IPC honors boundSourceId like turn_context; turn-context runs its arms concurrently. doctor reads push/heartbeat thresholds from hook.ts. - new tests: doctor bootstrap checks, hook push-gate + deadline, concurrent sweep claims, cache eviction, bound-source resolve. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(bootstrap): origin-ownership gate, world visibility, collision-safe source id, consent + templates - repo adoption requires an exact receipt repo_url match or authed-owner check (undefined repo_url was a wildcard); create verifies privacy BEFORE the first push. - verify sets facts.default_visibility=world if unset, so agent-authored facts surface in per-turn context (they defaulted private before). - source_id derives a path-hash suffix when 'workspace' is taken by another checkout; every consumer reads manifest.source_id. - skipped HOOKS_CONSENT now declines (was falling through to default yes); --minimal refuses on an initialized manifest; tilde fences escaped. - MCP registration pins --surface full; status hard-fails a public origin (template door); receipt writers guard against newer/corrupt receipts; uninstall only claims brain-deleted after a real rm. - templates ship jobs disabled + provider-consent + support-relay lines; soul-audit re-runs over the shared interview bank. TODOS: 11 follow-ups. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(security): close adversarial-review findings — scan fails closed, whole-PEM redaction, bound repo push Cross-model adversarial pass (Claude + Codex) on the bootstrap wave: - secret scan fails CLOSED: an unreadable, oversized, or binary staged blob now blocks the push (blocked_unscannable, exit 5) instead of committing unscanned; only a confirmed staged deletion is skipped. This was the headline "block secrets before they leave the machine" property failing open. - private-key redaction spans the whole PEM block (header+body+footer), not just the header line — the base64 body no longer survives into the corpus the sweep sends to an extraction provider. - bootstrap repo commits the workspace (secret-scan-gated) before the first push and verifies the remote actually received it, so a push-fail retry can't adopt an empty remote as success. - privacy verify is re-bound to origin immediately before push (a concurrent origin rewrite between verify and push is refused). - session-end corpus write is atomic and clears the stale ingested/in-progress sidecars so a resumed session's appended transcript is re-ingested. - public-origin refusal enforced at render (not only status); MCP "already registered" is verified to target this workspace, not blessed blindly; verify probe cleanup scopes deletes to its own slugs, not a token substring; allowlist fingerprint floor raised 8→16 hex. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * v0.45.0.0 feat(bootstrap): paste-in personal-agent install for Codex + Claude Code Turns a Codex or Claude Code session into a persistent personal agent: interview-rendered identity files, a local PGLite brain, per-turn context via serve IPC (Claude Code hooks / Codex pull protocol), session-triggered persistence, and a private GitHub repo as the agent's portable body. Keyless- first (the harness model is the LLM; one optional key adds embeddings + extraction). New `gbrain bootstrap` command family + `gbrain hook` + `gbrain sweep`; doctor bootstrap health checks; latest-stable distribution ref + template-repo publish job. Opt-in, additive — existing installs untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: regenerate flag registry for security-fix flags; drop fabricated gbrain capabilities doc ref CI caught two real failures under the merged state: - the flag registry lagged the blocked_unscannable/exit-5 flags the security round added, tripping the #2185 freshness guard. - headless-install.md described the keyless capability report as a `gbrain capabilities` command, which the #3502 doc-command resolver rejects — reworded to prose (the real surface is bootstrap verify's report). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: sync KEY_FILES + bootstrap plan to security-fix behavior Cross-referenced the security-fix round against the reference docs and corrected the drift those commits introduced: - workspace-push.ts entry: stage-FIRST-then-scan order (the TOCTOU fix), fail-closed blocked_unscannable, and the sources-push status -> exit-code map. - hooks.ts entry: MCP registration pins `serve --surface full`. - hook.ts entry: session-start/session-end pushes run in a detached child (non-blocking); atomic corpus write clears stale sidecars. - bootstrap.ts entry: render hard-refuses a public origin (template door). - verify.ts entry: source_id collision resolution (workspace-<path-hash>). - AGENT_BOOTSTRAP_PLAN as-shipped delta note for the scan/stage reorder. llms bundle unchanged (KEY_FILES is link-only); build:llms and test/build-llms.test.ts green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ci): silence SC2016 on the intentional askpass literal in release.yml The one-shot GIT_ASKPASS script must contain literal $1 and $TEMPLATE_REPO_PAT so they expand when /bin/sh runs it at git's credential prompt, not when the outer shell writes the file — single quotes are correct. Add a scoped shellcheck disable so actionlint passes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(skills): declare 'bootstrap my data' trigger in cold-start frontmatter The doc reform added 'bootstrap my data' to cold-start's RESOLVER.md row (to disambiguate data-bootstrap from agent-bootstrap) but not to the skill's own frontmatter triggers, tripping the RESOLVER↔frontmatter round-trip contract (resolver.test.ts). Declare it; regenerate skills.lock.json. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(bootstrap): default per-turn hooks + search mode ON without a prompt Installing gbrain for your coding agent IS the consent for the behaviors that make it work, so stop re-litigating them with install-time questions whose "no" defeats the product: - Per-turn hooks (Claude Code) install ON by default — no prompt. Off-ramps: `--no-hooks` at install, `GBRAIN_HOOKS=0` at runtime, `bootstrap uninstall`. The "hooks installed" line now surfaces the kill switch so default-on is never silent. A persisted HOOKS_CONSENT=no (interview --skip) still declines. - Search mode defaults to `balanced` silently (nobody knows the modes at install; `gbrain search modes` changes it any time). - MCP scope stays the ONE deliberate prompt — project vs user is a real cross-repo privacy choice, not friction. Marks the two consents `silent: true` in the question bank (new QuestionSpec field), rewrites the runbook phases so the agent no longer asks them, adds the `--no-hooks` flag (+ registry regen), and adds default-on / opt-out tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(bootstrap): real end-to-end coverage — cross-session recall, per-turn content, Codex door, realistic corpus Closes the seven e2e gaps a coverage audit surfaced: the plumbing was well-unit-tested but the product claims ("Codex works, context shows up every turn with real content, it remembers across restarts, machine two recovers, Postgres works") were unproven end to end. Test-only wave — zero src changes. - Hermetic synthetic corpus (test/fixtures/bootstrap-corpus/ + a loader helper): 12 interlinked pages (52 edges, timelines), 12 world/private beliefs, 8 gold queries — curated from the gbrain-evals synthetic corpora, 100% placeholder names, so recall is asserted on a real multi-entity brain instead of a 2-node self-planted probe. - GAP1 magic moment: author a fact via the real write path, disconnect the engine, reopen against the same DB, recall it — a real session boundary, not verify.ts's same-connection SQL read-back. Plus a source-isolation assertion. - GAP2 per-turn content: hook-under-serve Pin 1 now seeds a known fact and asserts its text lands in the injected block AND private beliefs never do (was: empty brain, empty_block accepted as a pass). - GAP3 Codex door: assert the rendered AGENTS.md carries the Gate-3 brain-first pull protocol; make the fake codex shim implement `mcp get` so the [FIX7] target-verification can actually fail; the Docker cold-machine harness now exercises the hooks/MCP registration step instead of skipping it. - GAP4 corpus recall: turn-context + verify graph-floor/qrels run on the real multi-entity brain with real edges. - GAP5 attach: machine-two now re-ingests the cloned brain/ into a fresh DB and recalls a fact authored only on machine one — the multi-device payoff. - GAP6 keyed + Postgres (env-gated): real embeddings prove semantic recall a paraphrase query can reach but keyless BM25 cannot; bootstrap verify drives a real Postgres engine (skipIf DATABASE_URL/keys absent). - GAP7 persistence: session-end runs the REAL push (not the mocked seam) to a local bare remote and the remote receives the content; a planted secret is blocked at the gate; the 15-min cron installs and fires a scan-gated push. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(bootstrap): real-agent e2e — drive the actual claude + codex binaries end to end Closes the audit's biggest gap ("no real harness ever drives a turn"). Adapts gstack's PTY/headless agent harness to prove the bootstrap install + smoke work against the REAL binaries, not PATH shims. Test/CI/docs only — zero src changes. - test/helpers/agent-harness.ts: hermetic clean-room child env (ported from gstack; drops CONDUCTOR_/CLAUDE_/GSTACK_/MCP_/GBRAIN_, promotes GSTACK_ANTHROPIC_API_KEY→ANTHROPIC_API_KEY), real-binary resolvers + auth probes, headless `claude -p --output-format stream-json` and `codex exec --json` turn runners, a gbrain stdio MCP-config writer, and a keyless brain seeder. + a fixture-parse unit test (no binary needed). - test/e2e/bootstrap-real-claude.serial.test.ts: real `gbrain bootstrap` install → REAL `claude mcp add` (verified via `claude mcp get`) → verify exit 0 → a real `claude -p --mcp-config --strict-mcp-config` turn that invokes mcp__gbrain__search and answers from the brain (proven: toolCalls include mcp__gbrain__search, final text carries the seeded fact). - test/e2e/bootstrap-real-codex.serial.test.ts: same install with REAL `codex mcp add` into a real ~/.codex/config.toml + Gate-3 pull-protocol assertion, then a real `codex exec --json` turn surfacing the fact (MCP or the pull- protocol shell path). Bounded retry absorbs codex's occasional MCP-call cancellation without softening the fact-requiring assertion. - Everything hermetic (temp HOME/CLAUDE_CONFIG_DIR/CODEX_HOME/GBRAIN_HOME; real ~/.codex auth copied read-only) and skipIf-gated so it self-skips cleanly where the binaries/auth are absent. - heavy-tests.yml: gated `real-agent-e2e` job (nightly/label, never the PR shard; no-op on a runner without authed binaries). - TODOS: compiled `gbrain` binary can't serve a PGLite brain (bun compile omits the WASM/extension payloads); harness falls back to `bun run` serve. Verified against live claude 4.6 + codex 0.147.0: 15 pass / 0 fail; verify 36/36; typecheck clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ci): real-agent-e2e job — bash array + --timeout (actionlint SC2086 + bun-test-timeout guard) The real-agent-e2e job's file loop used an unquoted $FILES (SC2086) and ran `bun test` without --timeout (check-bun-test-timeout guard). Switch to a bash array and add --timeout=600000 (real-agent turns are slow; the tests self-skip without authed binaries so it's a no-op elsewhere). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(pglite): embed WASM + extension assets so the compiled binary can serve A `bun build --compile` gbrain binary could not `serve` a PGLite brain: the compile bundles JS but not PGLite's runtime payload (pglite.wasm, initdb.wasm, pglite.data, vector/pg_trgm tarballs), so `serve` on PGLite died with a bunfs/ENOENT. Now the assets ride inside the binary. - src/core/pglite-embedded-assets.ts: embeds the five assets via `import … with { type: 'file' }` (the ENG-6 idiom) and exposes getEmbeddedPgliteOptions() → { pgliteWasmModule, initdbWasmModule, fsBundle, extensions:{vector,pg_trgm} }. WASM/fsBundle are consumed as bytes; the two extension tarballs are materialized to a content-addressed temp file (atomic, size-verified reuse) because PGLite reads them via fs.createReadStream, which cannot read a /$bunfs path. Unconditional (works in bun-run and compiled), so no fragile mode branch. - src/core/pglite-engine.ts: static-import getEmbeddedPgliteOptions (engine path stays static per the engine-dynamic-import invariant); spread into both PGlite.create sites (initial + WAL-repair retry). The bunfs classifier stays as a backstop but no longer fires for a correct binary. - scripts/check-pglite-embedded.sh (+ smoketest): compiles a focused binary and asserts it boots PGLite, CREATE EXTENSION vector/pg_trgm, and round-trips a page — wired into `bun run verify` (now 37 checks), check:all, and check:pglite-embedded. Fail-soft only when compile is unavailable. - agent-harness.ts probeCompiledPglite now passes → the real-agent e2e uses the fast compiled MCP server. TODOS: the P2 "can't serve PGLite" item is closed. Verified: fresh compiled binary ran `search`/`query` against a PGLite brain and returned the seeded row (no bunfs/ENOENT); verify 37/37; pglite-engine 120/0 source-mode; typecheck clean; engine-dynamic-import + parity guards pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
63 KiB
Brain: The LLM-Maintained Knowledge Base
A system prompt for any AI agent that wants to build and maintain a personal knowledge base. This describes the pattern, the architecture, and the operational discipline that makes it work.
Drop this into your agent's workspace as a skill or system prompt. Your agent will build the rest.
Relationship to schema packs: this document is the prose, paste-in version of the schema pattern. gbrain also ships a machine-enforced counterpart — schema packs (
gbrain schema, typed pages, extraction, aliases, lint) — documented indocs/architecture/schema-packs.mdanddocs/schema-author-tutorial.md. The prose schema here and the active schema pack should describe the same brain; when you evolve one, evolve the other.
What this is
A personal intelligence system where your AI agent builds and maintains an interlinked wiki of everything you know about your world — people, companies, deals, projects, meetings, ideas — as structured, cross-referenced markdown files. The agent writes and maintains all of it. You direct, curate, and think.
This is Karpathy's LLM wiki pattern, but extended from research notes into a full operational knowledge base — one that integrates with your calendar, email, meetings, social media, and contacts to stay continuously current.
The key insight: knowledge management has failed for 30 years because maintenance falls on humans. LLM agents change the equation — they don't get bored, don't forget to update cross-references, and can touch 50 files in one pass. Your wiki stays alive because the cost of maintenance is near zero.
Three Founding Principles
1. Every Piece of Knowledge Has a Primary Home (MECE Directories)
Every piece of knowledge passes through a decision tree and lands in exactly one directory. No duplicated pages, no ambiguity about where something goes.
This is the single most important structural decision. Without it, knowledge bases rot — the same fact lives in three places with three different versions, nobody knows which is current, and the agent (or human) stops trusting the system. MECE directories with explicit resolver rules prevent this.
Every directory has a README.md (the resolver) that answers two questions:
- What goes here — a positive definition with a concrete test
- What does NOT go here — the key distinctions from neighboring directories that the agent might confuse
The brain also has a top-level RESOLVER.md — a numbered decision tree the agent walks when filing anything. When two directories seem to fit, disambiguation rules break the tie. When nothing fits, the item goes in inbox/ — which is itself a signal the schema needs to evolve.
The agent must read the resolver before creating any new page. This is not optional.
Important nuance: MECE applies to directories, not to reality. Real people and entities are multi-faceted — a political founder can also be a friend, donor, media actor, and hiring candidate. The resolver picks the primary home for their page (people/), but the page itself uses typed backlinks and cross-references to surface all their facets. The MECE rule prevents duplicate pages, not duplicate relationships. Cross-references are how adjacency is preserved without breaking the one-page-per-entity rule.
2. Compiled Truth + Timeline (Two-Layer Pages)
Every brain page has two layers, separated by a horizontal rule (---):
Above the line — Compiled Truth. Always current, always rewritten when new information arrives. Starts with a one-paragraph executive summary. If you read only this, you know the state of play. Followed by structured State fields, Open Threads (active items — removed when resolved), and See Also (cross-links).
Below the line — Timeline. Append-only, never rewritten. Reverse-chronological evidence log. Each entry: date, source, what happened. When an open thread gets resolved, it moves here with its resolution.
If someone asks "what's the current state?" — read above the line. If someone asks "what happened?" — read below the line. The top is the current summary. The bottom is the source log.
This is the Karpathy wiki pattern's killer feature: the synthesis is pre-computed. Unlike RAG, where the LLM re-derives knowledge from scratch every query, your brain has already done the work. The cross-references are already there. The contradictions have already been flagged.
3. Enrichment Fires on Every Signal
Every time any signal touches a person or company — meeting, email, tweet, calendar event, contact sync, conversation mention — the enrichment pipeline fires. The brain grows as a side effect of normal operations, not as a separate task you remember to do.
This is what distinguishes an operational brain from Karpathy's research wiki. He describes ingesting sources you manually add. An operational brain goes further — every pipeline (meetings, email, social media, contacts) automatically triggers enrichment on every entity it touches. You never have to remember to update someone's page. The system does it because the plumbing is wired correctly.
Wiring It Into Your Agent
The brain must be referenced in your agent's configuration (AGENTS.md or equivalent) as a hard rule, not a suggestion. Specifically:
- Before creating any brain page → read RESOLVER.md. This should be in your agent's operational rules, not buried in documentation.
- Before answering any question about people, companies, deals, or strategy → search the brain first. Even if the agent thinks it knows the answer. File contents are current; the agent's memory of them goes stale.
- The enrich skill fires on every signal. Every ingest pathway — meeting processing, email triage, social monitoring, contact sync — should call the enrichment pipeline when it encounters a person or company. This is wiring, not discipline. If it depends on the agent remembering, it will eventually be forgotten.
- Corrections are the highest-value data. If the user corrects the agent about a person, company, deal, or decision — it gets written to the brain immediately. No batching, no deferring.
The chain of authority: Agent config (AGENTS.md) says "read RESOLVER.md" → RESOLVER.md is the decision tree → each directory README.md is the local resolver → schema.md defines page structure → the enrich skill defines the enrichment protocol.
Architecture
Three layers:
Raw sources — meeting transcripts, emails, tweets, web research, API responses, calendar events, contact data. Immutable. The agent reads from these but never modifies them. Stored in sources/ and .raw/ sidecar directories.
The brain — a directory of interlinked markdown files. People pages, company pages, deal pages, meeting pages, project pages, concept pages. The agent owns this layer entirely. It creates pages, updates them when new information arrives, maintains cross-references, and keeps everything consistent. You read it; the agent writes it.
The schema — a document (this one, plus schema.md and RESOLVER.md) that tells the agent how the brain is structured, what the conventions are, and what workflows to follow. This is the key configuration file — it makes your agent a disciplined knowledge maintainer rather than a generic chatbot.
The Database + Markdown Architecture
The markdown wiki is the human-facing layer — the primary interface for humans and LLMs. But it's not the sole source of truth. A structured database layer provides the foundation, and the markdown is generated from it.
The Four Database Primitives
Entity registry — canonical ID, all aliases, all external IDs (LinkedIn member ID, X user ID, email addresses, phone numbers) in one table. This is the single source of truth for "is this the same person?" When you merge two entities, it's a database operation (point both IDs at the same canonical record), not a file-merge operation with cross-reference fixups.
Event ledger — every signal that touches the brain is an immutable event: meeting attended, email received, tweet published, enrichment completed, user correction applied. Events have provenance: source, timestamp, confidence, raw payload reference. The timeline section of markdown pages is generated from this ledger. You never lose events because a page rewrite went wrong.
Fact store — structured claims with provenance. "Jane Doe is CTO of Acme" with source=crustdata, confidence=high, observed_at=2026-04-07. When two sources disagree (LinkedIn says CTO, company website says VP Engineering), the conflict is visible as two facts for the same field with different values. The compiled truth section above the line is generated from the fact store's latest-confident values. Contradictions become data, not bugs.
Relationship graph — typed edges between entities. Person→Company (role: CTO, started: 2024-01), Person→Person (relationship: co-founded company together), Company→Deal (type: Series A, date: 2025-03). Enables graph queries that markdown grep can't answer: "who do I know who's invested in AI infrastructure companies?" becomes a traversal, not a prayer.
Why This Matters
- Identity resolution becomes a database operation (merge entity IDs), not a file-merge operation with manual cross-reference fixups
- Contradictions are structural (two facts with different values for the same field and different sources) rather than textual (hoping the LLM notices a discrepancy buried in prose)
- Concurrency is solved — events append to a ledger, facts upsert to a store, markdown is rebuilt. No more merge conflicts on shared files
- Graph queries work — "who do I know at this company?" and "what companies has this investor backed that I also know the founders of?" become database queries, not impossible grep chains
File-Layer Conventions
The markdown layer uses conventions that map directly to the database primitives:
- Use frontmatter for structured metadata — anything you'd want to query (role, company, stage, score, tags) goes in YAML frontmatter, not buried in prose. These map to the fact store.
- Use
.raw/for provenance — save every API response with source and timestamp. These map to provenance records in the fact store. - Treat the timeline as an event stream — dated, sourced, append-only. These map to the event ledger.
- Keep compiled truth conceptually separate from evidence — above the line is synthesis; below the line is evidence. The synthesis is a generated view; the evidence is queryable records.
- Use canonical slugs consistently — every cross-reference uses the filename slug. These are the entity IDs in the registry.
Directory Structure
brain/
├── RESOLVER.md — master decision tree for filing (agent reads this first)
├── schema.md — page conventions, templates, workflows
├── index.md — content catalog with one-line summaries
├── log.md — chronological record of all ingests/updates
├── people/ — one page per human being
│ ├── README.md — resolver: what goes here, what doesn't
│ └── .raw/ — raw API responses per person (JSON sidecars)
├── companies/ — one page per organization
│ ├── README.md
│ └── .raw/
├── deals/ — financial transactions with terms and decisions
│ └── README.md
├── meetings/ — records of specific events with transcripts
│ └── README.md
├── projects/ — things being actively built (has a repo, spec, or team)
│ └── README.md
├── ideas/ — raw possibilities nobody is building yet
│ └── README.md
├── concepts/ — mental models and frameworks you'd teach
│ └── README.md
├── writing/ — prose artifacts (essays, philosophy, drafts)
│ └── README.md
├── programs/ — major life workstreams (the forest, not the trees)
│ └── README.md
├── org/ — your institution's strategy and operations
│ └── README.md
├── civic/ — political landscape, policy, government
│ └── README.md
├── media/ — public narrative, content ops, social monitoring
│ └── README.md
├── personal/ — private notes, health, personal reflections
│ └── README.md
├── household/ — domestic operations, properties, logistics
│ └── README.md
├── hiring/ — candidate pipelines and evaluations
│ └── README.md
├── sources/ — raw data imports and archived snapshots
│ └── README.md
├── prompts/ — reusable LLM prompt library
├── inbox/ — unsorted quick captures (temporary)
└── archive/ — dead pages, historical record
Every directory has a README.md resolver. Adapt directories to your life — add or remove domains as needed. Not everyone needs civic/ or hiring/ or household/. The invariant is: one directory per knowledge domain, one file per entity, every directory has a resolver, and RESOLVER.md is the master decision tree that guarantees MECE filing.
Entity Identity and Deduplication
In a system fed by meetings, email, social media, contacts, and APIs, entity identity is the first real failure mode. Without a canonical identity layer, you will end up with subtle split-brain pages — "Jane Smith" from a meeting transcript and "J. Smith" from an email and "jsmith" from Twitter all creating separate pages for the same person.
Canonical slugs
Every entity gets a canonical slug that serves as its stable ID:
- People:
first-last.md(all lowercase, hyphens for spaces) - Companies:
company-name.md - If collisions arise, disambiguate:
david-liu-crustdata.md,david-liu-meta.md
The filename IS the identity. All references, cross-links, and .raw/ sidecars use this slug.
Aliases
People have many names across sources. The frontmatter aliases field captures all known variants:
aliases: ["Jenny Shao", "Jenny G. Shao", "JennyGShao", "jennifer.shao@company.com"]
Aliases include: misspellings from meeting transcripts, maiden names, nicknames, email addresses, social handles, and phonetic variants. When the enrich skill encounters a new name variant for a known entity, it adds the variant to aliases — it does NOT create a new page.
Deduplication protocol
Before creating any new page, the agent must:
- Search existing pages by name (exact and fuzzy)
- Search aliases across all pages:
grep -rl "NAME_VARIANT" /data/brain/people/ --include="*.md" - Check .raw/ sidecars for matching email addresses or social handles
- If a match is found → UPDATE the existing page (add alias if the name variant is new)
- If no match → CREATE a new page
Merge protocol
When you discover two pages are the same person:
- Pick the more complete page as the survivor
- Merge all timeline entries from the duplicate into the survivor (chronological order)
- Merge all aliases
- Update all cross-references that pointed to the duplicate
- Delete the duplicate
- Commit with message:
merge: [duplicate] into [survivor]
During weekly lint, actively look for potential duplicates: similar names, same company, same email across different pages.
Key Disambiguation Rules
The most common filing confusions and how to resolve them:
- Concept vs. Idea: Could you teach it as a framework? → concept. Could you build it? → idea.
- Concept vs. Personal: Would you share it in a professional talk? → concept. Is it private reflection? → personal.
- Idea vs. Project: Is anyone working on it? Yes → project. No → idea. The graduation moment is when work starts.
- Writing vs. Media: Writing is the artifact (the essay). Media is the production and distribution infrastructure (content pipeline, social monitoring).
- Writing vs. Concepts: A concept page is distilled (200 words of compiled truth). An essay is developed prose (argument, narrative, story).
- Person vs. Company: Is it about them as a human? → people/. Is it about the organization? → companies/. Both pages link to each other.
- Household vs. Personal: Would a PA execute on it? → household (operational). Is it private reflection? → personal.
- Sources vs. .raw/ sidecars: Per-entity enrichment data → .raw/ sidecar. Bulk multi-entity imports → sources/.
When nothing fits, file in inbox/ and flag it. That's a signal the schema needs to evolve.
Page Types and Templates
Person
The most important page type. A great person page is a well-researched briefing — not a LinkedIn scrape.
# Person Name
> Executive summary: who they are, why they matter, what you should
> know walking into any interaction with them.
## State
- **Role:** Current title
- **Company:** Current org
- **Relationship:** To you (friend, colleague, investor, etc.)
- **Key context:** 2-4 bullets of what matters right now
## What They Believe
Worldview, positions, first principles. The hills they die on.
Every claim must cite its source and type:
- [Belief] — observed: [tweet/meeting/article, date]
- [Belief] — self-described: [interview/bio, date]
- [Belief] — inferred: [pattern across N interactions, confidence: high/medium/low]
## What They're Building
Current projects, recent ships, product direction.
## What Motivates Them
Ambition drivers, career arc, what gets them out of bed.
Distinguish between what they say motivates them (self-described) and
what their behavior suggests (observed/inferred).
## Communication Style
How they prefer to communicate. How they handle disagreement.
What energizes them in conversation.
This section is high-value but requires careful sourcing.
Rules: only write here from direct observation (meeting behavior,
language in emails/tweets, visible patterns). Never generalize
from a single data point. Mark confidence level.
## Hobby Horses
Topics they return to obsessively. Recurring themes in their public voice.
## Assessment
- **Strengths:** What they're great at. Be specific.
- **Gaps:** Where they could grow. Be specific and fair.
- **Net read:** One-line synthesis.
- **Confidence:** high (5+ interactions) / medium (2-4) / low (1 or inferred)
- **Last assessed:** YYYY-MM-DD
## Trajectory
Ascending, plateauing, pivoting, declining? Evidence.
## Relationship
History of interactions, temperature, dynamic.
## Contact
- Email, phone, LinkedIn, X handle, location
## Network
- **Close to:** People they're frequently seen with
- **Crew:** Which cluster they belong to
## Open Threads
- Active items, pending intros, follow-ups
---
## Timeline
- **YYYY-MM-DD** | Source — What happened.
All sections are optional — include what you have, leave empty sections as [No data yet] rather than omitting them. The structure itself is a prompt for future enrichment. When a section says [No data yet], the agent knows what to look for next time it encounters this person.
The principle: facts are table stakes. Context is the value.
Epistemic discipline on people pages
The context sections (Beliefs, Motivations, Communication Style, Assessment) are the highest-value parts of the system but also the most prone to hallucination. An agent can over-generalize from sparse evidence or overfit to one recent interaction. Rules:
- Every claim cites its source. Not "she's aggressive" but "she pushed back hard on pricing in the March 15 meeting (observed)."
- Three source types:
observed(you saw it happen),self-described(they said it about themselves),inferred(you're reading between lines). Label each. - Confidence tracks interaction count. One meeting = low confidence. Five meetings = high. Don't write definitive assessments from thin data.
- Recency matters. A belief from 2 years ago may not be current. Mark dates.
- Never generalize from a single data point. "She seemed frustrated in one meeting" is a timeline entry. Patterns require multiple observations.
- The user's corrections override everything. If the user says "that's wrong about her," update immediately — that correction is the highest-confidence signal in the system.
Company
# Company Name
> What they do, stage, why they matter.
## State
- **What:** One-line description
- **Stage:** Seed / Series A / Growth / Public
- **Key people:** Names with links to people pages
- **Key metrics:** Revenue, headcount, funding
- **Connection:** How they relate to your world
## Open Threads
---
## Timeline
Meeting
# Meeting Title
> YOUR analysis — not a copy of the AI meeting notes.
> What matters given everything else going on.
> What was decided. What was left unsaid.
## Attendees
## Key Decisions
## Action Items
## Connections to other brain pages
---
## Full Transcript
Deal, Project, Concept — same pattern. Compiled truth on top, timeline on bottom.
The Enrichment Pipeline
This is the most important operational pattern. Every time your agent encounters a person or company — in a meeting, email, tweet, calendar event, contact sync — it should enrich the corresponding brain page.
Enrichment is not just "look up their LinkedIn." It's:
- What they believe — positions, worldview, public stances
- What they're building — current projects, what's shipping
- What motivates them — ambition, career trajectory
- Their communication style — how they engage, what energizes them
- Their relationship to you — history, context, open threads
- Hard facts — role, company, contact info, funding (table stakes)
Facts are table stakes. Context is the value.
When to enrich
Any time a person or company signal appears:
- Someone is mentioned in a meeting transcript → enrich
- Someone emails you → enrich
- Someone interacts with you on social media → enrich
- A new contact appears → enrich
- You mention someone in conversation and their page is thin → enrich
- A company announces funding, ships a product, makes news → enrich
Enrichment sources (in order of value)
- Your own interactions — what you said about them, what they said to you (highest signal)
- Meeting transcripts — richest context source
- Email threads — tone, urgency, relationship dynamics
- Social media — beliefs, public positioning, who they engage with
- Web search — background, press, talks
- People APIs — structured profile data (career history, education, skills, contact info)
- Company APIs — funding, investors, valuations, headcount, financials
- Contact data — email, phone, location
Data source skills
Each external data source should be its own named skill with full API documentation, auth patterns, and usage notes. The enrich skill orchestrates them — it decides which sources to call based on tier, then delegates to the individual skill for how to call the API.
This keeps things DRY: the enrich skill owns the logic (when to enrich, what tier, what to extract), and each data source skill owns the API contract (endpoints, auth, rate limits, gotchas, validation rules).
Recommended data source skills:
- Web search — broad keyword search (Brave, Google, etc.). Quick background, press, funding.
- Semantic search — better than keyword for finding specific people, LinkedIn URLs, personal writing. (Exa, Perplexity, etc.)
- Social search — X/Twitter, Bluesky, etc. for public voice: beliefs, projects, engagement patterns.
- People enrichment — structured LinkedIn-like data: career history, education, skills, contact info. (Crustdata, Proxycurl, People Data Labs, etc.)
- Network search — search your professional network for warm intros and connections. (Happenstance, Clay, etc.)
- Company intelligence — Pitchbook-grade data: funding rounds, investors, valuations, headcount, financials. (Captain API, Crunchbase, etc.)
- Meeting history — search past meetings for interactions with this entity. (Circleback, Otter, Fireflies, etc.)
- Contact data — email, phone, location from your contacts. (Google Contacts, etc.)
The typical enrichment flow for a new person:
- Network search → find LinkedIn URL, career arc, alternate names
- People enrichment → deep structured data (skills, work history, education, contact info)
- Semantic search → find personal sites, talks, writing that reveal beliefs and perspective
- Social search → their public voice, who they engage with, hobby horses
- Web search → press coverage, recent news, talks
- Meeting history → past interactions with you
For a new company:
- Company intelligence → funding, investors, headcount, financials
- Web search → product, press, traction
- Social search → company's public positioning
- People enrichment → enrich founders/key team members (each triggers person enrichment)
Enrichment tiers (don't over-enrich)
- Tier 1 (key people): Full pipeline — all sources. Inner circle, business partners, important collaborators.
- Tier 2 (notable): Web search + social + brain cross-reference. People you interact with occasionally.
- Tier 3 (minor mentions): Extract signal from source only, append to timeline. Everyone else worth tracking.
A thin page with real interaction data is better than a fat page stuffed with generic web results. Don't waste 10 API calls on someone with no public presence.
Raw data sidecars
Every enrichment API response gets saved as a JSON sidecar:
people/jane-doe.md ← brain page (curated, readable)
people/.raw/jane-doe.json ← raw API responses
The JSON is keyed by source with fetch timestamps:
{
"sources": {
"crustdata": { "fetched_at": "2026-04-05T...", "data": { ... } },
"web_search": { "fetched_at": "...", "data": { ... } }
}
}
The brain page is the distilled version. Raw data is the archive.
What goes in the brain page (distilled): location, current title, company, headline, education (one line), career arc (condensed), top skills, social handles, profile picture permalink.
What stays in .raw/ only: full work history with job descriptions, complete skill lists, company descriptions for each employer, platform-specific IDs, follower/connection counts, full API response bodies.
When re-enriching: overwrite the source key with fresh data + new timestamp. Don't append — replace.
Validation rules
When auto-enriching from people/company APIs:
- Low connection/follower count (e.g., <20): Likely wrong person. Save to .raw/ with a
"validation": "low_connections"flag. Don't auto-write to the brain page. - Name mismatch: If the returned name doesn't share a last name with the entity, skip.
- Obviously joke profiles: Career arcs mentioning absurd titles — skip.
- When in doubt: Save raw data but don't update the brain page. Wrong data is worse than no data.
Browser budget
If enrichment involves browser-based lookups (LinkedIn, authenticated pages), set a daily budget (e.g., 20 lookups/day) to avoid account flagging. Prefer API-based enrichment services for bulk work — they don't touch the user's browser session.
Entry Criteria — Who Gets a Page
Not everyone deserves a brain page. Scale page creation to relationship importance:
Always create a page for:
- Anyone you've had a 1:1 or small-group meeting with
- Key colleagues, partners, and direct collaborators
- Anyone with a strong working relationship or better
- Family, close friends, inner circle
Create if signal exists:
- People from contacts with recent interaction
- Anyone mentioned by name in conversation with context
- Event contacts with multiple shared events
Do NOT create:
- Random names from mass event guest lists with no interaction
- Single-name entries with no identifying context
- Contacts with no relationship signal at all
When in doubt: does the user benefit from this entry existing? If no, skip it.
The Skill Architecture
Skills are the modular building blocks of the system. There are three types, and understanding how they compose is critical.
1. Data source skills (leaf nodes)
Each external API or data source gets its own named skill. The skill owns the API contract: endpoints, authentication, rate limits, error handling, validation rules, and what the response looks like.
Examples:
- People enrichment (Crustdata, Proxycurl, People Data Labs) — structured LinkedIn-like data
- Network search (Happenstance, Clay) — search professional network, find mutual connections
- Company intelligence (Captain API/Pitchbook, Crunchbase) — funding, investors, financials
- Semantic search (Exa, Perplexity) — find LinkedIn URLs, personal sites, writing
- Meeting history (Circleback, Otter, Fireflies) — past meeting transcripts and notes
- Calendar/contacts (Google Calendar, Google Contacts via integration tools) — schedule, contact info
- Social media (X API, Bluesky API) — public posts, engagement, follower data
- Workspace tools (Gmail, Slack, Drive via integration tools) — email threads, messages, documents
Data source skills are never called directly by the user. They're called by orchestration skills (below).
2. Orchestration skills (coordinators)
These skills contain the logic — they decide what to do, then delegate to data source skills for how to do it.
The enrich skill is the most important orchestration skill. It decides:
- Is this a CREATE (new page) or UPDATE (new signal)?
- What tier is this entity? (determines which data sources to call)
- What signal types to extract from the source material?
- Which data source skills to call, in what order?
- How to write the results to the brain?
Other orchestration skills:
- Meeting ingestion — pulls meetings from a meeting tool, creates brain meeting pages with analysis, then calls enrich for every attendee and company discussed
- Email triage / executive assistant — processes inbox, handles scheduling, then calls enrich when it encounters people or companies
- Social monitoring — scans public social media for mentions and engagement, then calls enrich for notable accounts
3. Pipeline skills (end-to-end workflows)
These are the user-facing skills that chain multiple orchestration and data source skills together:
- Morning briefing — reads calendar + tasks + brain state + recent signals → produces a briefing
- Person research — given a name, runs full Tier 1 enrichment and presents the result
- Weekly brain maintenance — runs lint, flags stale pages, suggests enrichment targets
How they compose
User says "tell me about Jane Doe"
→ Agent searches brain (grep/index)
→ Page is thin → calls enrich skill (orchestration)
→ enrich determines Tier 1
→ calls happenstance skill (data source) → gets LinkedIn URL
→ calls crustdata skill (data source) → gets full profile
→ calls exa skill (data source) → finds personal writing
→ calls web_search (built-in tool) → gets press coverage
→ calls meeting history (data source) → finds past meetings
→ writes brain page, saves .raw/ sidecar, cross-references
→ Agent presents the enriched page to user
Cron fires "meeting ingestion" every afternoon
→ meeting-ingestion skill (orchestration) pulls new meetings
→ for each meeting: creates brain meeting page
→ for each attendee: calls enrich skill (orchestration)
→ enrich calls relevant data source skills based on tier
→ for each company discussed: calls enrich skill
→ extracts tasks, commits brain repo
The key insight: data source skills are stateless and reusable. The enrich skill can call Crustdata whether the trigger was a meeting, an email, a social mention, or a direct user request. The data source skill doesn't care where the request came from.
How Enrich Wires Into Everything
The enrich skill is the central hub. Every ingest pathway converges on it:
Meeting ingestion ───────┬─────────────────────────┬─── people enrichment API
Email triage ────────────┤ ├─── company intelligence API
Social monitoring ───────┤ ENRICH SKILL ├─── network search API
Contact sync ────────────┤ (orchestration) ├─── semantic search API
Manual conversation ─────┤ ├─── social search API
Calendar events ─────────┤ ├─── web search
Webhooks ────────────────┴─────────────────────────┴─── meeting history API
│
▼
BRAIN REPO
(people/, companies/,
meetings/, deals/)
Every arrow into the enrich skill carries a signal (the raw information from the source) and an entity (the person or company to enrich). The enrich skill:
- Checks brain state — does a page exist? Is it thin?
- Determines tier — Tier 1 (full pipeline), Tier 2 (web + social + cross-ref), Tier 3 (source extraction only)
- Extracts signal from the source material (beliefs, motivations, trajectory, facts)
- Calls data source skills based on tier (each skill is a named, documented module)
- Writes to brain — CREATE (via RESOLVER.md) or UPDATE (append timeline, update compiled truth)
- Cross-references — updates all linked entity pages
- Saves raw data to
.raw/sidecar - Commits to the brain repo
The critical wiring rule: every ingest skill must call enrich. This is not optional or aspirational. It's structural. If a new ingest pathway is added (say, a Slack monitoring skill), its implementation must include "for each person/company mentioned, call the enrich skill." If that line is missing, the brain stops compounding from that source.
Automated Cron Jobs
The brain doesn't just grow when you're actively using it. Cron jobs make the system autonomous — the brain is maintained, the inbox is triaged, meetings are ingested, and mentions are monitored even while you sleep.
The cron architecture
Cron jobs run as isolated agent sessions — they get their own context, read their own skills, and don't block the main conversation thread. They can post to specific notification channels (Telegram topics, Slack channels, Discord threads) or work silently.
Each cron job is essentially: "wake up, read a skill, do the work, post results (or stay silent if nothing happened), go back to sleep."
Recommended cron jobs for a brain-powered system
High frequency (every 10-30 minutes):
- Email monitor — scan inbox, classify by priority, post digest to a notification channel. Handle low-risk items (scheduling, acknowledgments) directly.
- Message monitor — check key communication channels for unreplied messages from important contacts. Surface them with suggested responses.
Medium frequency (every 1-3 hours):
- Social radar — scan public social media for mentions of you or your organization, engagement, emerging narratives. Alert on items that need attention. Call enrich for notable new accounts engaging with you.
- Heartbeat — the omnibus check. Calendar lookahead, task review, email scan, brain state review. Post if something needs attention; stay silent if not.
Daily:
- Morning briefing — calendar + tasks + urgent items + overnight signals → one notification. The "here's your day" message.
- Task prep — archive yesterday's completed tasks, build today's list from calendar + backlog + recurring items.
- Meeting ingestion — pull all new meetings from your meeting tool, run full ingestion (create meeting pages, propagate to entity pages, extract tasks). This is the heaviest cron job — it touches the most brain pages.
- Social media collection — archive your own posts, track engagement velocity, detect deletions. Feed into media/ pages.
Weekly:
- Brain lint — run the full maintenance pass: contradictions, stale pages, orphans, missing cross-references, MECE filing violations. Post a report.
- Enrichment sweep — find brain pages that haven't been enriched in 90+ days, or pages with many
[No data yet]sections. Queue them for re-enrichment. - Contact sync — pull recent additions from your contacts, cross-reference with brain. Create pages for significant new contacts.
How crons feed the brain
The key insight: cron jobs are the autonomous enrichment engine. Without them, the brain only grows when you're actively talking to the agent. With them:
- The email monitor encounters a person → calls enrich → brain grows
- The meeting ingestion processes a transcript → calls enrich for every attendee → brain grows
- The social radar detects a new notable account → calls enrich → brain grows
- The contact sync finds a new contact → calls enrich → brain grows
- The enrichment sweep finds stale pages → calls enrich with fresh data → brain stays current
The brain compounds 24/7 because the cron jobs are wired to call enrich. The user sleeps; the brain doesn't.
Cron job design rules
- Silent when nothing happens. If a cron finds nothing new, it should produce no output. No "nothing to report" messages. This is critical — noisy crons get disabled.
- Post to specific channels. Each cron posts to its designated notification channel (e.g., email cron → Emails topic, social radar → Social Alerts topic). Don't mix signals.
- Spawn sub-agents for heavy work. The cron session should stay lightweight. If meeting ingestion needs to process 5 meetings and update 30 entity pages, spawn sub-agents for the entity propagation.
- Idempotent and checkpoint-aware. Every cron should track what it's already processed (in a state file like
meeting-notes-state.json) so it doesn't redo work on the next run. - Respect quiet hours. Don't post between 11 PM and 7 AM unless something is genuinely urgent. Crons should check the time before posting.
- Every ingest cron must call enrich. This is the structural rule. A cron that processes meetings but doesn't enrich attendees is a bug, not a feature.
Example: how it all fits together
A typical afternoon in an autonomous brain system:
-
3:00 PM — Email monitor cron fires. Scans inbox. Finds 3 new emails: a scheduling request, a funding announcement, and a founder asking for advice.
- Handles the scheduling request directly (checks calendar, replies with available times)
- Calls enrich on the company in the funding announcement → updates company page with new round
- Posts the founder's email to notification channel for the user to handle
-
3:15 PM — Meeting ingestion cron fires. Finds 2 new meetings from today.
- Creates 2 brain meeting pages with analysis
- Calls enrich for 8 attendees across both meetings → updates 8 people pages
- Calls enrich for 3 companies discussed → updates 3 company pages
- Extracts 4 action items → adds to task list
-
3:30 PM — Social radar cron fires. Detects a journalist writing a thread about the user's organization.
- Posts alert to Social Alerts channel
- Calls enrich on the journalist → creates/updates their people page with recent activity
-
4:00 PM — Heartbeat fires. Calendar shows a meeting in 1 hour. Brain page for the attendee was last enriched 3 months ago.
- Triggers a fresh enrichment pass on the attendee
- Posts a prep note: "Meeting with X in 1 hour. Here's what's changed since you last met."
The user didn't ask for any of this. The brain grew by 12 pages and the user walked into their 4:00 PM meeting fully prepared — because the plumbing is wired correctly.
Worked Examples From a Production System
These examples show how the architecture operates end-to-end. Names and specifics are genericized, but the skill chains are exact — every skill call, every file write, every cron trigger is how it actually works.
Example 1: Meeting Ingestion — The Full Chain
A cron job fires at 3:00 PM daily with the prompt: "Read skills/meeting-ingestion/SKILL.md and process today's meetings."
Step 1: Skill chain loads. The meeting-ingestion skill's preamble says "Read skills/enrich/SKILL.md" — so the agent loads the enrichment protocol before touching any data. This is critical: it means the agent knows how to handle every person and company it encounters.
Step 2: Pull new meetings. The agent calls the meeting history data source skill (in this system, Circleback). It checks a state file (memory/meeting-notes-state.json) that tracks the last processed meeting ID. Finds 2 new meetings since last run.
Step 3: Process Meeting 1 — "Product Review with Sarah Chen and Mike Torres."
The agent creates brain/meetings/2026-04-07-product-review.md with:
- Its own analysis above the line (not a copy of the AI summary — reframed through what the brain already knows about the attendees and the project)
- Key decisions, action items, and connections to other brain pages
- Full transcript below the line
Step 4: Enrich attendees.
For Sarah Chen — the agent searches the brain: grep -rl "Sarah Chen" /data/brain/people/. Finds people/sarah-chen.md. Reads it. Page was last enriched 2 weeks ago and has good coverage. → Tier 3: extract signal from this meeting only. Appends to her timeline: "2026-04-07 | Meeting — Pushed back on timeline for launch, wants more QA. Concerned about API stability." Updates her Open Threads with the new follow-up item.
For Mike Torres — brain search finds people/mike-torres.md. Page exists but is thin: just a name, title, and one previous meeting entry. → Tier 2: web search + social + brain cross-reference. Agent finds his recent blog posts (feeds into What They Believe), his X activity (feeds into Hobby Horses), and cross-references him with two other brain pages that mention him. Updates compiled truth above the line.
For "Alex from Meridian Labs" (mentioned in the meeting but not an attendee) — brain search finds nothing. → CREATE path:
- Reads RESOLVER.md: "a specific named person" →
people/ - Creates
people/alex-rivera.mdusing the person template from schema.md - Runs Tier 1 enrichment (full pipeline): network search → finds LinkedIn URL. People enrichment API → full structured profile. Semantic search → finds a conference talk. Web search → finds press coverage of Meridian Labs' recent funding.
- Saves raw API responses to
people/.raw/alex-rivera.json - Cross-references: updates
companies/meridian-labs.mdto link to Alex's page
Step 5: Enrich companies discussed. Meridian Labs was discussed extensively. Agent checks companies/meridian-labs.md — exists but funding data is 4 months stale. Calls company intelligence API → gets fresh round data. Updates the page.
Step 6: Extract action items. Finds 3 action items in the transcript → appends to ops/tasks.md.
Step 7: Repeat for Meeting 2. Same flow.
Step 8: Commit and notify.
cd /data/brain && git add -A && git commit -m "meetings: 2026-04-07 product review, investor sync" && git push
Posts summary to the Meetings notification channel: "Processed 2 meetings. Created 1 new person page (Alex Rivera). Updated 4 entity pages. 5 action items extracted."
Files touched in this run:
brain/
├── meetings/
│ ├── 2026-04-07-product-review.md (CREATED)
│ └── 2026-04-07-investor-sync.md (CREATED)
├── people/
│ ├── sarah-chen.md (UPDATED — timeline + open threads)
│ ├── mike-torres.md (UPDATED — Tier 2 enrichment)
│ ├── alex-rivera.md (CREATED — Tier 1 enrichment)
│ └── .raw/
│ └── alex-rivera.json (CREATED — raw API responses)
├── companies/
│ └── meridian-labs.md (UPDATED — fresh funding data)
ops/
└── tasks.md (UPDATED — 5 new action items)
memory/
└── meeting-notes-state.json (UPDATED — checkpoint)
Example 2: Email Triage — Resolver + Enrichment in Action
An email monitor cron fires at 12:00 PM. Its prompt: "Read skills/executive-assistant/SKILL.md and skills/gmail/SKILL.md. Triage the inbox."
Step 1: Pull inbox. The agent calls the Gmail data source skill via its workspace integration. Gets 8 new emails since last check.
Step 2: Classify and handle. Most emails are routine: 2 scheduling confirmations (handled directly — checks calendar, sends confirmations), 3 newsletters (archived), 1 internal FYI (noted). But one stands out:
An email from "David Park, GP at Ridgeline Ventures" — subject: "Series A for NovaTech — co-invest opportunity." The agent has never seen this person before.
Step 3: Enrich the unknown sender.
The agent calls the enrich skill. Enrich searches the brain:
grep -rl "David Park" /data/brain/people/ --include="*.md" # no results
grep -rl "Ridgeline" /data/brain/companies/ --include="*.md" # no results
grep -rl "david.park@ridgeline" /data/brain/people/ --include="*.md" # no results (alias search)
No match. → CREATE path.
- Reads RESOLVER.md: "a specific named person" →
people/ - Runs Tier 2 enrichment (this is an unsolicited email, not a key relationship yet):
- Web search: finds David Park's profile on Ridgeline's website. GP, focuses on enterprise SaaS. Previously at two other funds.
- Social search: finds his X account. Recent posts about AI infrastructure, developer tools. Reposted an article about NovaTech last week.
- Brain cross-reference: searches for NovaTech → finds
companies/novatech.mdexists (from a meeting 2 months ago). Cross-links.
- Creates
people/david-park.mdwith what it found — role, fund, investment focus, public voice, connection to NovaTech. - Also checks
companies/ridgeline-ventures.md— doesn't exist. Creates a thin page with what's known from the web search.
Step 4: Back in the EA skill. Now the agent has context. It classifies the email:
- Priority: Medium (co-invest opportunity, not urgent)
- Context: David Park is a GP at a fund that focuses on enterprise SaaS. NovaTech is already in the brain from a previous meeting.
- Action needed: User should review
Posts to the Emails notification channel:
Co-invest opportunity — NovaTech Series A From: David Park, GP at Ridgeline Ventures He's reaching out about co-investing in NovaTech's Series A. Ridgeline focuses on enterprise SaaS. NovaTech is already in the brain — you met their founder in February. Open in Gmail
The email monitor didn't just triage — it grew the brain by two pages (one person, one company) and cross-linked them to an existing entity.
Example 3: The Compound Effect — How Context Builds Before a Meeting
This example shows how a completely unknown person becomes a rich brain page across 4 autonomous cron runs over 48 hours, with zero manual intervention. The result: you walk into a meeting fully prepared.
Hour 0 — Social radar cron (Tuesday, 3:00 PM)
The social radar cron scans for mentions and engagement on X. It detects a reply to one of the user's posts from an account named @lena_builds — a thoughtful, technical response about developer tooling that got 50+ likes.
The agent calls enrich. Brain search: no match for "Lena" or "lena_builds." → CREATE, Tier 3 (minor mention — just a social interaction, not a relationship yet).
Creates people/lena-kovac.md with minimal data: X handle, display name, the reply text, and a note that she seems technical. No API calls — Tier 3 is source-extraction only.
# Lena Kovac
> Technical builder. Engaged with a post about developer tooling on X.
## State
- **X:** @lena_builds
- **Relationship:** None yet — social interaction only
- **Confidence:** low (1 interaction)
---
## Timeline
- **2026-04-07** | X reply — Replied to post about developer tools.
Thoughtful technical take on compiler-driven UX. 50+ likes.
Hour 18 — Email monitor cron (Wednesday, 9:00 AM)
The morning email sweep finds an email from lena@kovac.dev — subject: "Loved your talk at the devtools summit — would love to chat about what we're building."
The agent calls enrich. Searches the brain:
grep -rl "lena" /data/brain/people/ --include="*.md" # finds people/lena-kovac.md
grep -rl "kovac.dev" /data/brain/people/ --include="*.md" # no alias match yet
Finds the existing page. Reads it — it's thin (Tier 3, just the X reply). The email adds a new signal AND an email address. → Upgrade to Tier 2.
- Adds
lena@kovac.devto aliases in frontmatter - Web search: finds her personal site (
kovac.dev) — she's building a developer tools startup called Lattice. Previously at a major tech company on their compiler team. - Social search: deeper X dive. She posts regularly about developer experience, compilers, and Rust. Has 3K followers.
- Brain cross-reference: searches for "Lattice" and "compiler" — finds a concept page about developer tooling that links to 2 companies in the same space.
- Updates
people/lena-kovac.mdwith real substance: career history, what she's building, what she believes about developer tooling, her public voice.
Hour 26 — Executive assistant cron (Wednesday, 5:00 PM)
The afternoon EA sweep processes scheduling requests. One of the emails it triages is Lena's — she asked to chat. The user's calendar is open Thursday at 2 PM.
But the EA skill also checks: is there a calendar event already scheduled with this person? It searches the calendar — finds that Lena's email (lena@kovac.dev) appears in a calendar event for Thursday at 2 PM (she booked through the user's public booking link).
The EA skill sees the meeting is tomorrow. Calls enrich again. Page exists and is now Tier 2 with decent coverage, but there's a meeting tomorrow. → Upgrade to Tier 1.
- Network search: finds her LinkedIn URL. She has 2 mutual connections with the user.
- People enrichment API: full structured profile — Stanford CS, 4 years at a major tech company, founded Lattice 8 months ago.
- Semantic search: finds a conference talk she gave on "Why Developer Tools Are Stuck in 2015."
- Saves everything to
people/.raw/lena-kovac.json - Updates the brain page with full Tier 1 depth: beliefs, trajectory, what she's building, assessment, network connections.
Hour 40 — Morning briefing cron (Thursday, 7:30 AM)
The morning briefing cron builds the daily prep. It reads the calendar: meeting with Lena Kovac at 2 PM. It reads people/lena-kovac.md — which is now a rich page.
Produces a prep note in the daily briefing:
2:00 PM — Lena Kovac (Lattice) Building a developer tools startup focused on compiler-driven UX. Stanford CS, 4 years on compilers at [major tech co]. Founded Lattice 8 months ago. She replied to your devtools post on X last Tuesday (the technical one about compiler-driven UX that got traction). Then emailed the next morning — "loved your talk, want to chat about what we're building." Her public writing argues that developer tools are stuck in a 2015 paradigm and that compiler intelligence should drive the entire editing experience. She gave a talk on this at DevTools Summit. 2 mutual connections. She's technical, has founder energy, and is building in a space you care about.
The compound effect: Lena went from unknown → thin Tier 3 page → substantive Tier 2 page → rich Tier 1 page → meeting prep note. Four cron runs over 48 hours. Zero manual enrichment requests. The user walks into the meeting knowing exactly who Lena is, what she cares about, and why she reached out — because every pipeline is wired to call enrich, and enrich knows how to escalate tier based on relationship signals.
This is the core insight of the brain system: knowledge compounds autonomously when the plumbing is wired correctly. Each cron job doesn't just do its own job — it feeds the enrichment pipeline, which feeds every future cron job. The meeting ingestion cron creates pages that the morning briefing cron reads. The email monitor enriches people that the social radar first detected. The whole system is a flywheel.
Ingest Workflows
These are the specific ingest patterns. Each one calls enrich as its terminal step.
Meeting ingestion
After every meeting (via Circleback, Otter, Fireflies, or manual notes):
- Pull meeting notes + full transcript
- Create a brain meeting page with your own analysis (not just regurgitated AI summary) — reframe through what you know about the attendees' world
- Propagate to entity pages — call enrich for every person and company discussed. A meeting is NOT fully ingested until entity pages are updated.
- Extract action items to task list
- Commit
Email ingestion
When processing email:
- Extract people and companies mentioned
- Call enrich with email context (tone, requests, relationship signals)
- Note scheduling, commitments, follow-ups
Social media ingestion
When monitoring social media:
- Capture what people you track are saying publicly (beliefs, projects, opinions)
- Detect engagement patterns (who's replying to you, who's amplifying you)
- Call enrich for notable accounts → feed into "What They Believe" and "Hobby Horses" sections
Manual ingestion
When you mention someone or something in conversation:
- Your own comments are the highest-value signal — always capture these
- "Really sharp on the technical side, could be a good advisor for the infra project" → that goes in the person's page immediately
- If the brain page is thin, trigger a full enrichment
Navigation and Concurrency
index.md — content catalog. Every page listed with a one-line summary. Useful for navigation and query routing.
log.md — chronological record of ingests and updates. Append-only.
At scale (500+ pages), add search tooling (embeddings, BM25, or tools like gbrain). At moderate scale, grep works well.
Write hotspots and concurrency
Once you have cron jobs, ingest jobs, and sub-agents all touching the brain repo, index.md and log.md become merge-conflict magnets. Every workflow wants to append to log.md and update index.md on every commit.
Practical mitigations:
- Treat index.md as derived, not hand-maintained. Instead of updating it in every ingest workflow, rebuild it periodically (daily or on-demand) by scanning the directory tree. This eliminates it as a write hotspot.
- Make log.md append-safe. Each entry is a self-contained line with a timestamp prefix. Concurrent appends to the end of the file rarely conflict. If they do, both sides are correct — just keep both lines.
- Commit in batches, not per-page. When an ingest job updates 10 entity pages, commit once at the end, not 10 times. This reduces conflict surface.
- Pull before push. Every workflow should
git pull --rebasebefore pushing. With append-only log and independent entity pages, rebases almost always auto-resolve. - Entity pages rarely conflict. Two workflows updating
people/jane-doe.mdat the same time is rare because they're triggered by different signals about different people. The real conflict hotspots are the shared files (index.md, log.md), which is why those should be append-only or derived.
Maintenance (Lint)
Periodically (weekly), the agent should:
- Deduplication scan: Look for potential duplicate pages — similar names, same company, same email across different pages. Merge when confirmed.
- Contradictions: Check for conflicting facts between pages (e.g., two pages listing different roles for the same person at the same company).
- Staleness: Flag State sections superseded by newer Timeline entries.
- Orphans: Find pages with no inbound links.
- Open Threads: Check for items that seem resolved but weren't moved to Timeline.
- Missing cross-references: Entity A mentions Entity B but doesn't link to their page.
- Missing pages: Entities mentioned frequently but lacking their own page.
- MECE filing: Flag any pages that seem to be in the wrong directory.
- Source audit: Check people pages for unsourced claims in high-value sections (Beliefs, Motivations, Assessment). Flag claims without source type or date.
- Alias coverage: Check if recent meeting transcripts or emails contain name variants not yet in any page's aliases field.
What makes this different from RAG
RAG re-derives knowledge from scratch on every query. The brain pre-computes synthesis and keeps it current. Specifically:
- Cross-references are pre-built. You don't need the LLM to discover that Person A works at Company B and was in Meeting C — that's already linked.
- Contradictions are pre-flagged. When new data conflicts with old data, the agent resolves or flags it during ingest, not at query time.
- The compilation is persistent. Each source ingested makes the brain richer. Nothing is thrown away or re-derived.
- The structure itself is a prompt. Empty sections ("What They Believe: [No data yet]") tell the agent what to look for next.
Page Lifecycle
Brain pages can have implicit lifecycle states:
- Active: Current, recently updated, ongoing relationship or relevance
- Dormant: Not updated in 6+ months, relationship cooled, but still potentially relevant
- Archived: Moved to
archive/— dead companies, ended relationships, resolved deals. Historical record only. - Graduated: For ideas that became projects, or projects that became programs — the old page links to the new one
During lint passes, flag pages that haven't been updated in 6+ months for review. Some should be archived; others just need a fresh enrichment pass.
What makes a great brain
A great brain lets you walk into any meeting, call, or decision already knowing:
- Who this person is and what they care about (30 seconds of reading)
- What the company's actual state is (not what they said 6 months ago)
- What open threads exist between you (promises, follow-ups, deals)
- What changed recently (latest timeline entries)
- What to watch for (patterns, concerns, opportunities)
A bad brain is a pile of LinkedIn scrapes and meeting transcripts nobody reads. A good brain is compiled context that makes you more effective in every interaction.
The Resolver
When creating or filing a new page, walk this decision tree. Every piece of knowledge has exactly one home.
Decision Tree
Start here: what is the primary subject?
- A specific named person →
people/ - A specific organization (company, fund, nonprofit, government body) →
companies/ - A financial transaction with terms and a decision to make →
deals/ - A record of a specific meeting/call that happened at a specific time →
meetings/ - Something being actively built (has a repo, spec, team, or active work) →
projects/ - A raw possibility that nobody is building yet →
ideas/ - A reusable mental model or thesis about how the world works →
concepts/ - A piece of prose that could be published as a standalone work →
writing/ - Your institution's strategy, org, processes, internal dynamics →
org/ - Political or civic landscape — policy, legislation, elections, government →
civic/ - Public narrative or content operations — social monitoring, content pipeline, published posts →
media/ - A major life program — an enduring domain of commitment containing multiple projects →
programs/ - Domestic operations — properties, logistics, household management →
household/ - Private notes — health, personal reflections, inner life →
personal/ - A hiring pipeline — candidate evaluations, role specs, interview notes →
hiring/ - A reusable LLM prompt — templates for getting specific outputs from models →
prompts/ - A raw data import or snapshot — bulk exports, API dumps, periodic captures →
sources/ - Agent deliverables — briefings, digests, and research produced by your agent →
agent/ - Unsorted / quick capture — you don't know where it goes yet →
inbox/ - Dead / no longer relevant — historical pages with no active references →
archive/
Disambiguation Rules
When two directories seem to fit, apply these tiebreakers:
- Person vs. Company: If the page is about them as a human (beliefs, relationship, trajectory), it's people/. If it's about the organization they run, it's companies/. Both pages link to each other.
- Concept vs. Idea: Could you teach it to someone as a framework? Concept. Could you build it? Idea.
- Concept vs. Personal: Would you share it in a professional talk? Concept. Is it private reflection? Personal.
- Idea vs. Project: Is anyone working on it? If yes, project. If no, idea. The graduation moment is when work starts.
- Writing vs. Concepts: Concepts are distilled (200 words of compiled truth). Writing is developed prose (argument, narrative, story).
- Writing vs. Media: Writing is the artifact. Media is the production and distribution infrastructure.
- Org vs. Programs: org/ is institutional knowledge about your organization. programs/ is about your personal role and priorities within it.
- Civic vs. People: Political figures get people/ pages. Their legislative agenda and political positioning as civic actors goes in civic/.
- Household vs. Personal: If a PA would execute on it, it's household (operational). If it's private reflection, it's personal (inner life).
- Sources vs. .raw/ sidecars: Per-entity enrichment data → .raw/ sidecar next to the entity. Bulk multi-entity imports → sources/.
- Agent vs. Sources: Sources feed into the brain. Agent deliverables are synthesized output that feeds into your reading.
Special directories (not knowledge)
These exist in the brain repo but aren't knowledge directories:
- templates/ — page templates for each type (structural, not content)
- attachments/ — binary attachments (images, PDFs). Managed by your editor, not by the agent.
MECE Check
Every piece of knowledge should pass through the decision tree above and land in exactly one directory. If you find something that genuinely doesn't fit any category, file it in inbox/ and flag it — that's a signal the schema needs to evolve.
Getting started
- Create the directory structure above (or let your agent create it)
- Write a
RESOLVER.mddecision tree and aREADME.mdresolver for each directory - Write a
schema.mdwith your page conventions and templates - Add the brain rules to your agent's config (AGENTS.md or equivalent) as hard rules
- Start with one meeting transcript or one person you want to track
- Let the agent build the first few pages, review them, and iterate on the schema
- Wire up your meeting tool to trigger ingestion
- Wire up enrichment to fire on every new person/company signal
- The brain compounds from there
The human's job: curate sources, direct analysis, ask good questions, and think about what it all means. The agent's job: everything else.