A passing note from a quieter corner of the workshop. We've been talking lately about what pouch holds, what mytraces knows, what the family-voice system looks like across our small apps. Alongside all of those — and older than most of them — another internal tool has been growing. We call it poi, short for Project Orientation & Intelligence. It's the index our codebase keeps about itself. It's been around for several iterations and we hadn't gotten around to mentioning it.
The frustration
Every time we sit down with an AI assistant on this codebase, the same family of mistakes shows up. It suggests removing a build flag we settled on six weeks ago. It re-opens a decision that lives in someone's head but not anywhere mechanical. It writes code that crosses a boundary we'd already drawn. The mistakes aren't really the model's fault — the codebase doesn't have a place to put institutional memory in a form the model can reliably consult before the edit, rather than after.
What we tried first
The convention everyone uses is a CLAUDE.md
at the project root. We grew ours to ~600 lines and the
model still forgot half of it. Skills are good for
procedures (/commit, /deploy)
but less so for facts that need to fire when a specific
file is touched. Hooks check shapes; they don't carry
knowledge. Reading the README harder, you can imagine
how that went.
What's been brewing
POI is a typed knowledge index, one canonical YAML file per module, sitting next to the code. The schema is small and deliberate:
- gotchas with file-glob triggers — "this
fires when you're about to edit
internal/store/sqlite.go" - decisions with the options considered, the one chosen, and why — so we stop re-litigating
- claims with
file:lineevidence — mechanically verified; broken evidence is rejected on ingest - boundaries with deny/allow lists —
poi boundary check <file> --import <pkg>is a real gate, exit 1 on violation - non-features — the things this module deliberately doesn't do, with rationale, so the agent stops hallucinating them into existence
The YAML renders to a DESIGN.md you can publish
or read. The render is the publish step; humans edit the
typed YAML, not the rendered prose. A pre-commit hook
(poi check) blocks commits when the knowledge
and the rendered docs drift apart.
The piece that makes it not turn into auto-derived slop is
a propose / review / accept loop. An LLM (or a human)
drafts entries; they sit in a pending queue; a human runs
poi review and accepts what's right. The schema
enforces shape. The human enforces relevance.
-tags fts5; bare go build
silently omits FTS, queries fail at runtime" — before
the edit happened. The build flag landed on the first try.
No detour through "wait, why is FTS broken now."
Where it sits today
Several iterations in. Schema v1 was prose-heavy. Schema v2
unified two earlier files into one canonical store. We've
shed pieces that turned out to be footguns — a global
focus environment variable nobody actually used; a
brief command that read from the rendered
artifact instead of the source. The most recent round
simplified the entry surface: bare poi inside
a module dir gives you that module's brief; bare
poi at the workspace root gives you the
overview; every command prints
[workspace: X · scope: Y] so you always know
what slice you're seeing.
Internal dogfood for now. It's used across the thirty-some modules in our workspace — pouch, the ontology in mytraces, the voice tooling, the auth library, even POI's own knowledge about itself. It's become the thing we reach for first when we sit down with the codebase. A few people who've seen bits of it have asked whether they can use it. We'll have more to say about that some other time.
The shape that keeps showing up
The recent post about the ontology and the model was about giving an LLM a curated structure to anchor on, in the travel domain. POI is the same shape applied to a different domain: a curated structure that anchors an AI assistant in the facts of a codebase, instead of letting it improvise from whatever it can reach. Two domains, same instinct — that models are stronger when they have somewhere structured to stand.
For now this is just a note that the tool exists and we've been quietly building on it. We'll write about it in more depth when there's something specific worth saying.
← All journal posts