Navigate
HomeStart here
MusingsResearch & long-form
BuildingProjects & learnings
WorkProfessional practice
RunningTraining & races
AboutValues & identity
Life & PlacesCulture, food, travel, cities
Notes & ArchiveJournals, essays, portfolio
← Back to Building
TOOLJul 2026

Search Everything, Reach Almost Nothing

The notes corpus grew from a sync script into a searchable layer: 380 notes, ~2M characters searchable, drift checks, and a fail-closed confidentiality fence so AI can query work notes while everything personal stays unreachable by design.

notessearchprivacymcpjenn-os

380
notes archived

up from 101 when the sync first shipped

~2M
characters searchable

four curated lenses

8 of 332
reachable by default

the fence is deny-first, opened by evidence

0
network calls to search

stdlib-only, read-only, local

The sync was the start. The value showed up in the layers on top.

What the corpus became

Full text

Search reads bodies, not titles

Note titles lie — most are auto-generated. The search tool brute-forces ~2M characters of note bodies with source filters and four curated lenses: northstar, jennisms, decisions, feedback. The queries I actually run, packaged.

Inference

Which work it belongs to

Context inference maps notes to the projects and people they concern from topic-affinity priors, and writes its confidence and signals alongside every guess instead of overclaiming. 76 of 144 indexed notes carry an inferred context.

Fail closed

The fence

A read-only MCP server exposes the corpus to Claude behind a deny-first policy. Personal notes are not filtered out — they are unreachable. Work notes open one at a time, by evidence, through an explicit allowlist.

1

The sync post ended at 101 notes. The corpus is now 380 — about two million characters of note bodies sitting in local JSON. A pile that size stops being an archive and becomes either a liability or an asset, and the difference is entirely tooling.

2

The first layer is search that reads bodies, not metadata. Note titles are auto-generated and useless; the indexes I already had could tell me a note existed but not what was in it. The search tool is deliberately boring engineering — stdlib-only, read-only, no network, brute force over every note body — with source filters, date windows, and four curated lenses that encode the queries I actually run: northstar, jennisms, decisions, feedback.

3

The second layer is context inference. Notes don't say which project or team they belong to, so a script infers the context from topic-affinity priors built out of my project and people memory — and writes its confidence and its signals next to every guess. It marks what it cannot infer instead of inventing context. 76 of 144 indexed notes carry an inferred context; the rest say so.

4

The third layer is drift protection, because this corpus already burned me once: the index said one thing, the bodies said another, and searches quietly missed notes that existed. Now freshness checks fail loud when the local archive drifts from the cloud, and an index-vs-body divergence check catches the index lying about what it covers.

5

The layer I would actually show an employer is the fence. Exposing this corpus to an AI assistant is genuinely useful and genuinely dangerous — it holds personal notes next to work notes. So the MCP server that gives Claude access is read-only and deny-first: of 332 notes, about 8 are reachable by default. Personal notes are not "filtered" — the fence fails closed, so they are unreachable even when the code around them is wrong. The reachable surface grows one note at a time, through an explicit allowlist, by evidence.

6

The lesson generalizes past notes. If you have a pile of data you half-trust, the order of operations is: make it searchable by content, make its gaps explicit, make its freshness fail loud, and make privacy the default state instead of a setting. Every layer here assumes the layer below it will eventually be wrong. That assumption is the feature.

NOTES, SEARCHABLE AND FENCED
  corpus -> 380 notes, ~2M chars, local JSON
  search -> source-aware, 4 lenses, stdlib-only
  infer  -> context from topic-affinity priors
  guard  -> freshness + index-vs-body drift checks
  fence  -> read-only MCP, deny-first, 8 of 332 reachable

THE RULE
Personal notes are not filtered.
They are unreachable.