01Abstract
Personal-knowledge tools optimise for capture. The Volia Brain optimises for being wrong less often.
It is a single-operator memory system built around a vault of 457 markdown notes, indexed
as 550 embedding chunks in a local sqlite-vec store, with a parallel
Bayesian claim ledger (322 open claims across 15 domains) that tracks belief strength
with per-domain time decay. Auto-promotion of new findings is gated by a CoIn-style counterfactual
abduction loop modelled after arXiv:2502.11008. The brain seeds its own falsifiable predictions
and grades them with Brier loss. It tails the JSONL output of two real-money trading bots and writes
approve/warn/veto verdicts in real time, with five hard gates between paper and live.
The differentiator is not the stack. It is that every claim, every forecast, and every trade verdict is auditable, and a wrong one is recorded as a kill, not buried. The KILL_LIST.md file has 11 dead strategies on it. That is a feature.
02Motivation
Notion AI, Mem, and the long tail of "second brain" SaaS products solve a different problem. They are capture and recall layers for knowledge workers whose worst-case outcome is forgetting an idea. The operator behind this system has a different worst case: re-running a strategy that already cost him money. Three months of runway. A live wallet. A father who manages other people's capital. Forgetting is not the bottleneck — re-believing is.
The systems we evaluated all share one structural failure: they treat older notes the same as fresher ones, and they have no way to mark a belief as disproven. Obsidian is a filing cabinet. Claude's hosted memory is opaque, lossy, and resets often enough that we do not trust it for anything load-bearing. Mem ranks by recency and tags. None of them ask the question that matters: "is this claim still supported by fresh evidence?"
We built the brain because the alternative was watching a notes app politely re-suggest the BTC anti-correlation hypothesis we had already killed three times.
03System overview
The brain is structured as a unidirectional pipeline from raw capture to acted-on verdict. Every box is a real subsystem with a real file path. Nothing in this diagram is forward-looking.
Capture is multi-channel. Reasoning happens locally on Apple Silicon via Ollama. Action is gated. The only outbound network calls during reasoning are optional — the entire memory + retrieval + promotion pipeline runs offline. This is a deliberate constraint, not a marketing line: the operator's cost ceiling for the brain is zero per inference, because the alternative is paying API rates for every re-read of the same vault.
04Memory & retrieval
Vault on disk is the source of truth. The index is a derived view that can be rebuilt from scratch in under a minute.
Storage layout
The vault sits at /Users/neo/vault/ and is organised by purpose, not topic:
- memory/ — canonical long-term memory. Includes PERMANENT_FINDINGS.md (137 lines · 12 entries), KILL_LIST.md (98 lines · 11 dead strategies), HYPOTHESES_ACTIVE.md (4 active strategies, each with explicit kill and double-down criteria).
- live/ — auto-refreshed state. NOW.md, BOT_STATUS.md, DECAYED_BELIEFS.md, BRAIN_PREDICTIONS.md, BRAIN_VERDICTS.md. Scripts rewrite these. Manual edits are overwritten.
- learning/ — distilled web/agent captures, organised by domain
(
polymarket/,crypto/,security-pentest/,stocks/,business-dropshipping/, etc.). - hypotheses/ — one file per testable idea, each with a kill-criterion in frontmatter.
Ingestion
Five capture channels feed the vault: a launchd-watched drop zone at
~/Desktop/brain-inbox/ that auto-distills any URL, PDF, or text file in under
30 seconds; voice memos via the
com.neo.brain.daemon plist; bot trade logs from a London VPS; an edit-attribution
hook that records every Claude Code Edit/Write as a structured decision in
edit_log (190 rows as of writing); and content crons for RSS, X/Twitter, iMessage, and
calendar (40+ entries in crontab).
Embedding & retrieval
Embeddings are computed by nomic-embed-text (768-dim, served by local Ollama).
Vectors are stored as raw BLOB columns in a single sqlite-vec
database at brain-system/index.db. The schema is intentionally minimal:
CREATE TABLE memories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
path TEXT NOT NULL,
namespace TEXT,
type TEXT,
title TEXT,
content TEXT,
chunk_idx INTEGER DEFAULT 0,
mtime REAL,
embedded_at REAL,
embedding BLOB,
UNIQUE(path, chunk_idx)
);
Retrieval is hybrid. A query is embedded, then cosine-scored against all 550 chunks; the top-k are
re-ranked by (cosine × effective_confidence × recency). The implementation lives in
brain-system/cmd/ask.py. There is no external vector DB and no Pinecone bill.
Distillation
Two local models split the work. qwen3-coder:30b (DISTILL_MODEL)
handles long-context summarisation and PERMANENT_FINDING synthesis.
deepseek-r1:8b (FAST_MODEL) handles low-latency reasoning,
including the counterfactual gate. Both run on-device; no per-token cost.
05Confidence & decay
A claim is not a string. It is a Beta posterior over a yes/no question, with a half-life.
Every memory file is parsed for a canonical claim sentence (frontmatter claim: field, else the
H1 of the body). The sentence is normalised, SHA-256 fingerprinted, and stored in the
claims table with α=1, β=1 prior plus +1 successful evidence. Subsequent observations of the
same fingerprint update α (positive) or β (if the source frontmatter says
evidence_polarity: negative). The math, in brain-system/lib/core.py:
# effective_confidence = decayed mean of Beta(α, β)
f = exp(-Δdays / half_life_days)
# Pull α and β toward the prior (1,1) by f
α' = 1 + f·(α - 1)
β' = 1 + f·(β - 1)
return α' / (α' + β')
Half-lives are per domain, not global, because a polymarket regime read decays much faster than a security-engineering fact:
| Domain | Half-life (days) | Open claims |
|---|---|---|
| polymarket | 14 | 13 |
| crypto | 30 | 33 |
| security-pentest | 60 | 38 |
| stocks | 90 | 13 |
| general (default) | 90 | 54 |
| business-dropshipping | 120 | 15 |
| software-engineering | 180 | 9 |
| dashboards-websites | 180 | 5 |
A nightly Bayesian backfill (brain bayes, run by cron at 04:00 CT) walks every file modified in the last 24h, fingerprints the claim, and updates α/β. A weekly decay pass (brain decay, Sunday 04:00) writes live/DECAYED_BELIEFS.md for any claim whose effective confidence has fallen below 0.35. As of 2026-05-01 there are 22 decayed beliefs queued for review.
?asset_id= endpoint was returning all markets mixed (NBA, Biden,
crypto) instead of just the requested one — the hypothesis was added to
KILL_LIST.md with the post-mortem
"Root cause: contaminated API data. Once ?market= fix landed the signal vanished.
Finding was an artefact." The original claim's α/β posterior collapsed; the kill entry preserves
the lesson permanently. This is the loop the brain exists to run.
06Cross-domain learning & the counterfactual gate
Once individual claims are scored, the brain looks for clusters of corroborating evidence that justify promoting a finding to the canonical PERMANENT_FINDINGS.md file. Promotion is a two-stage gate.
Stage 1 — clustering
brain-system/cmd/promote_cross.py computes pairwise cosine similarity over all
first-chunk embeddings of vault/learning/* and vault/memory/*. Any cluster with
≥3 memories AND ≥3 distinct source URLs at cosine ≥ 0.85 is a candidate. The threshold
is an explicit constant COSINE_THRESHOLD = 0.85. We have observed real clusters of seven
sources at this threshold (e.g. the BTC 5-minute latency-arb cluster promoted 2026-04-29). We have not
yet lowered the threshold experimentally — that is on the roadmap (§12).
Stage 2 — counterfactual abduction (CoIn)
Correlation is not enough. The
brain-system/cmd/promote_counterfactual.py module implements a
CoIn-style abduction loop modelled after arXiv:2502.11008 (CounterBench).
Reported baseline: even o3 hovers near 50% on counterfactual reasoning;
CoIn-style abduction loops raise that to ~89.9%.
Before promotion, the brain runs two cheap structural checks on the cluster:
-
Source diversity. Reject if >50% of source URLs share a domain (echo chamber), or
if <2 distinct source-types appear (e.g. all 7 are tweets). The thresholds are
DOMAIN_DIVERSITY_MAX_RATIO = 0.5andMIN_SOURCE_TYPES = 2. -
LLM abduction. Pass the cluster to deepseek-r1:8b with a
structured prompt: "generate 3 counterfactuals where this cluster could exist even if the
claim is false, rate plausibility 0–10." If max plausibility ≥ 7, the gate
returns
HOLDand writes the concern to live/INBOX.md; the finding is not auto-promoted.
The synthetic test case shipped in the codebase reconstructs the contaminated ?asset_id=
cluster from March: 5 memories, all citing the same broken Polymarket endpoint, all reporting "BTC
crowd anti-correlation" with high confidence. The diversity check alone catches it (single domain,
single source-type) — no LLM call required. This is the failure mode the gate was designed for, and
it caught the historical case retroactively.
Two of the auto-promoted findings in PERMANENT_FINDINGS.md currently carry an
explicit [REVIEW: counterfactual concern …] annotation, written by the audit pass:
the BTC latency-arb cluster (7 sources but all from astralcodexten.com) and the
dropshipping supplier-vetting cluster (2 of 3 sources from oberlo.com). The brain flagged
both as domain monoculture after promotion. The annotations are advisory; the audit
does not delete or rewrite the claim.
Honest note on the cosine threshold.
The original design contemplated lowering the cosine threshold from 0.85 to 0.65 after observing an
empirical cluster maximum near 0.798, which would surface dozens more cross-domain pairs. That change
is not in the live code. The current COSINE_THRESHOLD = 0.85 still fires, just
sparingly. We will not characterise an unshipped change as shipped.
07Calibration via Brier scoring
A second brain that does not grade itself is a diary wearing a lab coat.
Once a week, the brain seeds 10 falsifiable predictions drawn from its own canonical findings.
Each one takes the shape "By date D, will fresh evidence in the brain still support claim C?"
with a stated confidence between 0 and 1. The predictions live in
live/BRAIN_PREDICTIONS.md, are managed by
brain-system/cmd/brain_brier.py, and are resolved automatically by a daily
cron (0 4 * * *) that re-checks fresh evidence for each open prediction.
Resolved predictions are scored with the standard Brier loss
BS = (p − o)2 where o ∈ {0, 1}, then bucketed by stated confidence
for calibration. Current state, dated 2026-05-01:
| Confidence bin | N | Mean stated | Actual yes-rate |
|---|---|---|---|
| 0.5–0.6 | 2 | 0.596 | 0.0 |
| 0.6–0.7 | 1 | 0.623 | 0.0 |
| 0.8–0.9 | 3 | 0.882 | 0.0 |
| 0.9–1.0 | 1 | 0.928 | 1.0 |
The headline reading: at this tiny sample (N=7) the brain has been systematically over-confident. Three predictions in the 0.8–0.9 band all resolved no. One in the 0.9+ band resolved correctly. Brier 0.491 is barely better than chance (0.25 = perfect random forecaster on 50/50 events). We are publishing this not because it is good but because it is the truth, and the existence of the table is the point. A notes app cannot show this graph because it has nothing to compare a forecast to.
With weekly seeding (10 new predictions every Sunday), the held-out set will reach N≈50 by mid-June, which is the first sample size at which calibration claims start to mean anything. We will publish the same table at every order of magnitude.
08Trade oversight — the brain in the trade loop
The most aggressive thing the brain does is veto real money. Two trading bots — delta_sniper
and sniper — each emit a JSON event to history.jsonl on every entry. A tailer
process pipes those events into brain-system/cmd/bot_oversight.py, which
embeds the event, runs vector retrieval over PERMANENT_FINDINGS +
KILL_LIST, asks deepseek-r1:8b for a verdict, and
writes the result to verdicts.db + live/BRAIN_VERDICTS.md.
Verdicts are one of approve / warn / veto, with a confidence and
cited memory slugs.
Five gates between paper and live
Live mode does not flip with a config toggle. It requires all of the following:
- Environment variable
BRAIN_OVERSIGHT_LIVE=1set in the launchd plist (not just shell). - Bot id present in the whitelist file /Users/neo/vault/config/brain-oversight-live-bots.txt.
- Last 50 verdicts show ≥60% accuracy against bot trade outcomes.
- Per-bot dollar cap on any single veto (default $5, env-overridable).
- Bot scope is hard-coded: only
delta_sniperandsniper; unknown ids raise.
If any gate fails, the system falls back to paper for that event. Code reference:
MIN_LIVE_ACCURACY = 0.60, LIVE_ACCURACY_WINDOW = 50,
ALLOWED_BOTS = {"delta_sniper", "sniper"}.
The system catching its own failure
Between 2026-04-25 and 2026-05-01 the oversight tailers were silently broken with
ModuleNotFoundError: No module named 'brain_system'. The veto path was non-functional
for six days. This was discovered not by the operator but by the
brain oversight audit cron at 23:00 CT, which flags discrepancies between
the bots' history.jsonl and the verdicts table. That is the system working. A blind veto
would have been worse than no veto — silent failure caught by an automated audit is exactly what we
instrumented for.
The verdict log itself is currently small — 2 verdicts in verdicts.db,
0 with a resolved outcome. The pipeline is freshly back online as of 2026-05-01 with
the live-mode flip. The honest summary: this is the lowest-N, highest-stakes part of the brain. Every
claim about its accuracy is conditional on the next 50 verdicts.
09Self-healing hooks
Anything that runs on every Claude Code invocation — distillation, edit attribution, identity injection — is wrapped in the @hook_safe(name) decorator from brain-system/lib/hook_safe.py. The decorator does three things:
- Crash isolation. The hook's
main()always returns an int and never raises. A traceback is logged to live/HOOK_CRASHES.md. - Lock TTL. A lock file prevents concurrent invocations.
LOCK_TTL_SECONDS = 24·3600means a 24-hour-old lock self-heals on the next call. - Auto-disable on repeated crash. A daily watchdog (brain-system/cmd/hook_watchdog.py, 11:00 CT) clears stale locks and disables hooks that have crashed repeatedly within 24 hours. The hook quietly comes back online the next day after the cooldown.
This is unglamorous, but it is the difference between a hook system that works for one week and one
that works for a year. live/HOOK_CRASHES.md currently logs three entries from
a deliberate crash test on 2026-04-30 (the test verified the decorator caught and recorded the
synthetic RuntimeError).
Eight launchd plists live under ~/Library/LaunchAgents/com.neo.brain*:
brain.daemon, brain-capture, brain-maintenance,
brain-morning-play, brain-oversight, brain-pr-watcher,
brain-study, brain-sync, brain-tunnel. Plus
71 cron entries spread across distinct minutes to avoid Ollama queue contention.
10Evidence to date
Numbers below are pulled fresh from the brain's own indexes on 2026-05-01:
Two real-world cases the brain has caught:
- Cap operator bug.
direction_entry_capscompared with>instead of>=, allowing $0.81 fills under a $0.80 cap. Three losing entries (one ETH-UP -$29.16). Surfaced via the edit-attribution hook + post-mortem in PERMANENT_FINDINGS.md §2; fixed 2026-04-22. - Wrong wallet, wrong strategy. Last 500 trades of the elite wallet we were copying
(
0xce2f…) are 497 BUYs / 3 SELLs with 96% in $0.40–$0.65. Our bot was filling 45% above $0.75 — buying their exit liquidity. Captured as PERMANENT_FINDINGS §4, killed the structure of the v1 sniper.
11Limits & open problems
We are unsentimental about what does not yet work.
- Brier sample is too small to mean anything. N=7 resolved is below any calibration-statistics floor. The 0.491 score and the 0/3 result in the 0.8–0.9 bin are not yet actionable; we publish them only because hiding them would defeat the purpose. Expect the first meaningful read at N≈50 (~mid-June).
- LoRA fine-tune has not shipped a beneficial adapter. The pipeline is wired
(brain-system/lora/):
lora-prepare-dataset.shat 23:00 CT builds a DPO JSONL from KILL_LIST/PERMANENT_FINDINGS preference pairs;lora-train.shrunsmlx_lm 0.31.3on Sundays at 21:00 CT into lora/adapters/<ISO-week>/. As of 2026-05-01, lora/adapters/ is empty and the most recent dataset (dpo-2026-W18.dryrun.jsonl, 13.7KB) is a dry-run. No adapter has been promoted toactiveyet because we have not validated that any of them improves task-specific outputs vs. the base model. - Persona drift detection has zero ground truth. The pipeline samples Claude outputs daily and compares them to a baseline persona, but we have not yet established what "drifted" means quantitatively. Currently advisory only.
- Cross-domain promotion has fired sparingly. Two clusters auto-promoted in 2026-04
at the 0.85 threshold; both received
[REVIEW: counterfactual concern]annotations for source-domain monoculture. Lowering the threshold to surface more pairs is on the roadmap but has not been validated against false-positive rate. - Mobile UX of the live
/braingraph is poor. The force-directed graph at /brain renders 1626 nodes / 610+ edges and is unreadable on a phone. Rebuild is in progress. - The vault can become the work. The blueprint at vault/memory/BRAIN_BLUEPRINT.md is explicit about this: every brain feature must justify itself in dollars-saved or decisions-clarified inside 30 days, or it gets deleted. Two skills have already been removed under that rule.
12Roadmap
Next 7 days
- Fix the
brain_systemimport path so oversight tailers stop silently failing on the VPS. - Get the next 50 oversight verdicts in (paper mode) so the live-flip accuracy gate has a real sample.
- Ship one DPO-trained LoRA adapter and A/B-test it against the base model on a held-out set of 30 prompts.
Next 30 days
- Lower the cross-domain cosine threshold experimentally to 0.65, measure false-positive rate against the counterfactual gate's HOLD output.
- Reach Brier sample N≈50; publish the calibration table at that order of magnitude.
- Rebuild
/braingraph with a mobile-first physics tier (≤200 visible nodes on phone).
Next 90 days
- Open the schema. Ship a self-host kit so other one-operator funds and trading shops can run their own brain. Same primitives, separate vault.
- Train a persona-drift classifier on 90 days of session transcripts; replace the advisory pipeline.
- Expand bot oversight from 2 bots to the full set of 4 active strategies, with per-bot whitelists and per-bot dollar caps.
13Glossary
| RAG | Retrieval-Augmented Generation. Fetch relevant chunks from a vector index, paste them into an LLM prompt, then generate. |
| CoIn | Counterfactual abduction loop (after CounterBench, arXiv:2502.11008). Generate plausible counterfactuals where the cluster could exist even if the claim is false; if any are plausible, hold promotion. |
| α / β posterior | Bayesian Beta distribution over the truth of a claim. α counts confirming observations, β counts disconfirming. The mean α/(α+β) is the brain's current belief; we apply per-domain time decay before reading it. |
| Brier score | Mean squared error between stated probability and observed outcome (0 or 1). 0 = perfect, 0.25 = chance on 50/50 events, 1.0 = maximally wrong. The standard scoring rule for forecasters. |
| DPO | Direct Preference Optimisation. Train on (preferred, rejected) pairs without an explicit reward model. We synthesise pairs from KILL_LIST (rejected) and PERMANENT_FINDINGS (preferred). |
| LoRA | Low-Rank Adaptation. Tune a small adapter on top of a frozen base model. Cheap, reversible, swappable. Our base is qwen3-coder:30b. |
| Edit attribution | A Claude Code post-tool hook that records every Edit/Write as a structured row in edit_log with file path, byte delta, before/after SHA, snippet, and session id. |
| Veto / approve / warn | Three-state output of the bot oversight pipeline. Veto blocks the trade in live mode; warn logs a concern; approve is the no-op default. |
| Kill criterion | A pre-committed threshold ("if WR < X over N trades, abandon") attached to every active hypothesis. Forces the strategy to be falsifiable before it is deployed. |