Article — design & measurements

Hadano AI Cabinet: a local-first, single-file memory substrate for AI agents

Go Kyono — TechJapan LLC. — h-c.ai — August 2026. Measured numbers in this article are taken verbatim from the project’s measurement ledger, published machine-readably at facts.json; a verifier that gates every deployment checks that each measurement-shaped number on this page appears in that ledger, and derived numbers declare their derivation in the page source. Results still being measured are marked as such and carry no numbers.

Plain summary

AI assistants forget everything between conversations. The usual fix is to run servers that store and search your documents. This project puts the memory in one ordinary file on your own computer instead. No server, no account, and your documents stay with you. We measured three things. First: search quality is close to the standard reference method, with nothing to operate. Second: we changed how the file stores connections between documents, made it far smaller and faster to grow, and search results did not change at all — which is how it should be. Third, and most important: a small AI answered questions far better when we gave it a few searched documents (88 out of 100 right) than when we pasted everything into its input (36 out of 100), while reading twenty times less text. Pasting more made the AI worse; searching did not. Every number here can be traced to a public ledger and recomputed from the stated formulas.

Abstract

Most memory systems for AI agents are server-resident: a vector database, an embedding model, and a network between them. That shape is reasonable at scale and unreasonable for an individual: three things to operate, and the data leaves the machine. Hadano AI Cabinet takes the opposite shape — one database file on the user’s own machine, reached over the Model Context Protocol [7] by whatever AI client the user already runs. This article states the design principles, the formulas that define every reported metric, then the measurements. Three results carry the argument. Lexical retrieval lands at 89% and 84% of the published BM25 reference recorded in the ledger, on two standard benchmarks, with no embedding model and no external service. A storage-format change eliminated degree-dependent write cost, with an unchanged-to-four-decimals benchmark score acting as a tripwire that the change reached nothing else. And at the 0.5B-parameter scale, answering from search results beat pasting the whole corpus into the context window — 88% correct at 1,400 input tokens against 36% correct at 28,034 — a contrast in which the full window did not win a single paired question (exact McNemar p = 4.4e-16), and the gap did not narrow when the corpus doubled.

1. The problem

An AI agent without memory re-reads everything every session. The standard cure is retrieval-augmented generation [4] over a hosted stack, and it works — if someone operates it. For a person or a small company the accounting is different: the knowledge involved is theirs, often confidential; the operating skill is not their job; and the quantity of data rarely justifies a server. What they need is closer to a filing cabinet than a search cluster: it sits there, it holds things, it gives them back, and moving it means picking it up.

The design bet is that the cabinet shape is not a compromise, and the bet does not stand alone. That lexical ranking is a strong retrieval baseline is established independently: BM25 rests on a probabilistic relevance framework with decades of evidence [2], and the BEIR benchmark’s own central finding is that BM25 is a robust zero-shot baseline that dense models beat inconsistently out of domain [1]. That retrieval grounding helps generation is likewise established [4]. What those results leave open — and what this project must show for itself — is whether they survive the minimal configuration: a deterministic, dependency-light engine in one file, and small local models. The measurements in §4 test exactly that residue.

2. Design principles

One file is the unit of ownership. Documents, the full-text index, the knowledge graph, and optional vectors live in a single database file; the append-only audit log is kept in dated files beside it, deliberately outside, so a backup copies knowledge rather than operation records. Copying the file is backup; moving it is migration; deleting it is deletion. There is no daemon and no account. A second consequence is honesty about what a copy means: the file carries knowledge, never authorization — access control belongs to whatever hosts the file, not inside it.

Documents are the source of truth for text; text indexes are derivatives. The inverted index, chunk stores, and vectors can be rebuilt from the stored documents and are treated as disposable, which turns their repair into recomputation. Relations are the exception and are treated with the opposite care: they are primary data of their own, stored in the graph and preserved — not rebuilt — during repair.

Determinism over cleverness. Storage and search use no model and no randomness. The same query over the same file returns the same ranking every time — verified by repeated runs on the platform tested so far (Windows x64; cross-platform determinism is expected from the arithmetic and is untested, §5). This is what makes the project’s verification style possible: independent recomputations are expected to match to the digit, and do.

The defended boundary is between data and code. A database file, a document, or a query — including one produced by a hostile third party and handed to the user — must not make the engine execute anything the caller did not ask for, or reach outside the paths the caller supplied. Search results are returned as data, not instructions, and are marked as such to the AI client.

Published claims are machine-checked. Measured numbers on this site, this article included, must trace verbatim to the measurement ledger; a verifier enforces that before every deployment, and numbers derived by arithmetic declare their derivation in the page source. Features are advertised only after the acceptance tests that define them pass. The same ledger is published at facts.json.

3. Architecture in brief

The storage layer is a small engine written in C: a hash-table file with an undo journal beside it during writes, so a crash mid-write rolls back to the previous consistent state. On top of it sit a character-trigram inverted index scored with BM25 under Anserini-compatible parameters [3], a knowledge-graph store whose adjacency is kept in fixed-size groups (§4.2 explains why), and the append-only audit log in dated files beside the database. Search is two-staged by design: a deterministic lexical stage finds documents and seeds, and a second stage expands from those seeds through the graph — the system never silently substitutes semantic guessing for an empty lexical result. Everything is reachable through seven MCP tools [7]; the tool count is deliberately held at seven in this version, because every additional verb is surface to secure and to explain.

4. Measurements

4.0 Definitions — the formulas behind every reported number

Verification must be reversible: a reader with the formulas and the published inputs should be able to recompute every output. Retrieval quality uses BM25 [2] with the Lucene form of IDF and Anserini-compatible constants [3]:

score(D,Q) = Σt∈T(Q)  idf(t) · tf(t,D)·(k₁+1) / ( tf(t,D) + k₁·(1 − b + b·|D|/avgdl) )
idf(t)     = ln( 1 + (N − df(t) + 0.5) / (df(t) + 0.5) )
k₁ = 0.9,  b = 0.4,  T(Q) = character trigrams per whitespace-delimited term

Benchmark quality is nDCG@10, the BEIR primary metric [1], with graded relevance where the dataset provides it:

DCG@k  = Σi=1..k  rel(dᵢ) / log₂(i+1)        nDCG@k = DCG@k / IDCG@k

The context experiment (§4.3) is defined by a deterministic judge and three preregistered inequalities. An answer string r is correct for expected value a iff a occurs in r with no digit adjacent to a digit boundary of a (so “11948” never matches “1948”). With A the per-condition accuracy and T̄(s) the mean input tokens at corpus size s:

gret  = T̄ret(100) / T̄ret(50)      gfull = T̄full(100) / T̄full(50)
pass  ⇔  gret ≤ 1.25  ∧  gfull ≥ 1.8  ∧  Aret ≥ Afull − 10pp

Inputs live in the raw per-question run files; an independently written implementation of these definitions (its judge included) recomputes every published number from them and agrees to the digit. Uncertainty is reported as Wilson 95% intervals; paired contrasts use the exact binomial McNemar test.

4.1 Retrieval quality without an embedding stack

On BEIR SciFact [1] (5,183 documents, all 300 test queries) the engine scores nDCG@10 0.5800; on NFCorpus (3,633 documents, all 323 queries) 0.2733. Against the published Lucene BM25 reference recorded in the ledger — 0.651 and 0.327 — that is 89% and 84%; in absolute terms the deltas are −0.071 and −0.054 nDCG@10. Three framing facts keep the comparison honest. The engine tokenizes into character trigrams, which gives word-level BM25 a structural advantage in English. The reference values are published figures, not re-runs under this harness, so the ratios are approximate across evaluation toolchains [1, 3]. And the 22 NFCorpus queries that return nothing are counted, not excluded. (M-01, M-02, M-04, M-05)

4.2 Changing the physical form without moving quality

Early on, adding an edge to a popular graph node rewrote that node’s whole adjacency list: bytes written per edge grew from 1,261 B at degree ∼100 to 13,230 B at degree ∼1000, a factor of 10.5, and an adversarial graph-layer run — 1,000 edges committed one at a time onto a single node — left the file 91.3% empty. Regrouping adjacency into fixed-size groups brought the growth ratio to 0.83 — write cost no longer grows with degree — and free space to 1.2%. Retrieval quality after the change was identical to four decimal places on both benchmarks; since neither benchmark corpus contains a single graph relation, that identity is a tripwire showing the change stayed inside the storage layer, not evidence about relevance under graph load — which has no quality benchmark yet. Form changes are held to that tripwire standard here: a storage improvement that moves relevance is a bug, not a win. (M-07, M-09)

4.3 Retrieval-fed context beats the pasted window at 0.5B

The claim that most needs testing is the product’s reason to exist: that an AI answers better from a few retrieved documents than from everything pasted into its window. The test corpus is 100 synthetic facts about fictitious companies, so pretraining leakage is zero — with no documents attached, the model [6] scores 0/100 on the same questions. Queries were formed from each question by a fixed deterministic rule — subject prefix plus an attribute keyword from a fixed list mirroring the corpus schema; the input is the question text only — the role an AI client plays in production. Thresholds were preregistered before the run (§4.0; the registration was amended once, before any data was collected, and the amendment and its reasons are preserved verbatim in the registration document). With qwen2.5:0.5b [6]:

Condition (100 documents) Mean input tokensAccuracy
Paste the full corpus into the window28,03436% [27.3%, 45.8%]
Store in the cabinet, pass search results1,40088% [80.2%, 93.0%]

The contrast is paired on identical questions, and it is one-sided in the strongest sense: retrieval alone was correct on 52 questions, the full window alone on 0 (exact McNemar p = 4.4e-16). Three controls pin down where the 88% comes from. With no documents, the model scores 0/100 — the answers are not in its weights. Handed a single deliberately wrong document, it scores 0/100 and echoes the planted wrong value in 94% of answers — it answers from the context it is given. And the retrieved context contained the right document in 100 of 100 questions, so accuracy decomposes as a 100% retrieval hit rate times an 88% read-out rate: every miss is a read-out miss. The judge credits any response containing the exact value (an answer listing several values would score correct) and fails correct answers in a different surface form; both conditions are scored by the same judge, so neither failure direction favors a condition, and gaming is negligible in the data — 1 of 100 responses contains two candidate values. (M-15, M-16)

Scaling: growing the corpus from 50 to 100 documents grew the pasted-window input by 1.994× and the retrieval input by 1.002×. The token flatness is structural, not a discovery — the engine returns at most top_k documents, so the measurement confirms the mechanism. The empirical content is on the accuracy side: the full window’s point estimate fell from 46% [33.0%, 59.6%] to 36% while retrieval held at 86% then 88%. The fall is not question composition — on the identical first 50 questions the 100-document window also scores 36% — and not window position: questions whose document sits in the front half of the pasted corpus score 18/50, back half 18/50. Because the intervals of the two full-window points overlap, we read the decline as a point estimate consistent in direction with the independently established finding that models use long contexts unevenly and degrade as they fill [5], not as a measured slope; what the preregistered criteria establish is the growth contrast and that accuracy at 100 documents did not suffer from externalization. (M-15, M-16)

Two boundaries on this result. This corpus makes retrieval structurally easy: every question contains a globally unique company name, so the right document cannot be crowded out of the top 10 — the 100% hit rate quantifies that. Whether accuracy survives at corpus sizes where candidates dilute — the failure mode that would re-couple retrieval to scale — is untested here. And the model inference behind each cell was executed once; what was reproduced independently, three times and to the digit, is the judging and aggregation from the raw per-question records (the full-window token counts are reconstructed from a one-time prefix calibration under prompt-cache reuse). Runtime settings differ per condition only in context-window size (32k for the full window, the minimum that fits; 8k for retrieval), with temperature 0 throughout. The same protocol is currently being repeated at the 7B scale; the preregistered claim requires both model scales to pass, so what is established today is the 0.5B half, and the 7B cells will be added only when they clear the same verification bar. (M-15, M-16)

5. What this does not claim

The benchmark results do not claim parity with tuned dense-retrieval stacks; they claim a stated fraction of a published lexical reference, with nothing to operate. The context-externalization result is measured on simple factual questions over a synthetic single-template corpus, at two corpus sizes and, so far, one model scale (0.5B) within one model family; it demonstrates the shape of the scaling under an easy-retrieval regime, not universal superiority on all question types. The engine has been built and tested on Windows x64 only; other platforms are expected to work and are untested. Vector search exists in the file format and is currently disconnected pending its re-wiring to the storage engine. The package is not on PyPI yet. Each of these limits is tracked openly on the roadmap, and several are enforced by tests that are deliberately kept failing until the limit is removed.

6. Future work

In the order the roadmap holds them. Completing the 7B repetition of §4.3 under the same preregistration. The preregistered head-to-head against a dense stack (vector database plus embedding model) on the same corpora, measuring quality alongside resident memory, dependency count, and startup — the axes the cabinet shape trades on. A preregistered index-reduction experiment: deterministically pruning the least valuable documents from the index and measuring the quality/size trade-off curve against a random-deletion control. Builds and test runs on macOS, Linux, and ARM, which gate any release. Re-wiring vector search to the storage engine. A word-level index measured as an addition to the trigram index (walking 12.7× fewer postings for +18% index size, measured, not yet adopted). Graceful query degradation for unsegmented natural-language questions. Making a running query interruptible under a deterministic work budget. And, for the hosted variant only, an authorization design whose grants live outside the portable file — consistent with §2’s rule that a copy carries knowledge, never access. (M-11)

7. Method as a feature

A reader should not have to trust this article. The measurement ledger behind it — claims, values, conditions, methods, dates — is published machine-readably at facts.json and mirrored for language models at llms-full.txt. The context experiment was preregistered before it ran; its aggregation and judging were recomputed independently, twice, from the raw records before its numbers were called final. The site’s claims are diffed against the ledger by a verifier that gates every deployment — this article is in its scope, and the check requires each measurement-shaped number here to appear verbatim in the ledger. The practice costs effort and sometimes publishes numbers less flattering than a summary would be. It is kept because a memory product asks for long-term trust, and trust compounds from checkable statements.

References

[1] N. Thakur, N. Reimers, A. Rücklé, A. Srivastava, I. Gurevych. “BEIR: A Heterogeneous Benchmark for Zero-shot Evaluation of Information Retrieval Models.” NeurIPS Datasets and Benchmarks, 2021.

[2] S. Robertson, H. Zaragoza. “The Probabilistic Relevance Framework: BM25 and Beyond.” Foundations and Trends in Information Retrieval, 2009.

[3] P. Yang, H. Fang, J. Lin. “Anserini: Enabling the Use of Lucene for Information Retrieval Research.” SIGIR, 2017. The BM25 reference values used in §4.1 (0.651 SciFact, 0.327 NFCorpus) are the published Lucene BM25 figures recorded in this project’s ledger entries M-01/M-02.

[4] P. Lewis et al. “Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks.” NeurIPS, 2020.

[5] N. F. Liu, K. Lin, J. Hewitt, A. Paranjape, M. Bevilacqua, F. Petroni, P. Liang. “Lost in the Middle: How Language Models Use Long Contexts.” TACL, 2024.

[6] Qwen Team. “Qwen2.5 Technical Report.” arXiv:2412.15115, 2024.

[7] Anthropic. “Model Context Protocol.” modelcontextprotocol.io, 2024.