Skip to content
Fredrin

One project memory, shared by every Worker

Run ten tickets at once and every Worker inherits the same project memory — the decisions you've made, the reasons behind them, and a warning the moment a new ticket fights one. It lives in your repo, grows on its own, and is ranked by a retrieval engine you'd have to rebuild to roll yourself.

Project memory that survives the merge

Fredrin’s project memory lives as plain files in your repo — a wiki of concepts and an append-only log of decisions, cross-linked to each other. Every Worker pulls the slice that matters to its ticket before it writes a line, so context compounds across the fleet instead of scattering into one-off chats. It survives the merge, the worktree teardown, and the next ticket.

The retrieval is the part that’s hard to copy: relevance-scoped recall — BM25 with synonym expansion and a code-symbol join, walked one to two hops and supersession-aware — plus a re-litigation guard that reads the decision log at dispatch and flags a ticket that fights a settled decision, before the work starts rather than after.

FIG 0.4 · Project memory

Lives in your repo

Memory is plain markdown committed alongside your code — a concept wiki for how the system works now plus an append-only decision log for why each costly-to-reverse call was made. Nothing is injected at runtime; a Worker reads the files in its own worktree, so memory scopes to the project it ships with. Because the knowledge ships in the same PR as the change, it can't drift from the code — six months in it's denser and more useful, not stale and half-true.

The files are canonical, versioned with the code — no side wiki to maintain.

At dispatch

Re-litigation guard

Send in a ticket that contradicts a decision already on the books and Fredrin catches it at dispatch — with the conflicting record in hand — instead of after a Worker has spent the tokens undoing last month's work. The check fires on every build, needs no agent discipline, and is conservative and best-effort: it never blocks a build and never fabricates a conflict.

Every example in the mockup is a real decision from Fredrin's own Project Context — switch drafts to see a clean dispatch and two flagged ones.

A new ticket is dispatched

Ticket

Move Project Context into the database for faster reads

Relevance retrieval

Each ticket pulls just the slice of memory it needs — relevance, not the whole archive dumped on the context window. The same engine backs the guard above, the context pack a Worker pulls at session start, and the in-app “Ask why” panel.

A context graph, not keyword grep
Every doc, decision, and glossary term is lifted into a linked graph — ranked with BM25, expanded by your own synonyms, and joined to the code symbols a ticket actually touches.
Relevance, walked — not recency, dumped
Retrieval seeds from the ticket and walks the link graph one to two hops, decaying by distance, returning a tight token-budgeted pack instead of the whole log by date.
The living doc out-ranks its own history
A matched concept doc is boosted above its decision trail, so “how does X work now” returns current state — while a reversed call is demoted, never dropped.
No embeddings, no vector store
A hand-cross-linked corpus is exactly where lexical + graph beats vectors. A guardrail test fails the build if an embedding call ever sneaks into the retrieval path.
Cached by content hash
The built graph is keyed to the blob SHAs of your tracked docs, so an unchanged tree never re-parses and retrieval stays instant as the log grows.

Decision log

The decisions you've settled become a recall surface, not a graveyard of files. The Memory tab parses your decision records into a searchable, status-filtered timeline you glance at — and the same data answers questions about why a call was made.

A searchable decision timeline
Every accepted decision (its ADR) is parsed into a chronological log — what was decided, its status, the one-line why, and how it links to the rest — read-only, straight off the canonical files.
Ask why
Pose a natural-language question and get the settled decisions that answer it, each cited to its record — deterministic retrieval, no LLM, no synthesis to drift.
Status-aware, never stale
Superseded, deprecated, or rejected calls are labelled historical and their replacement is promoted in their place, so the archive never gets served back as current truth.
Append-only, conflict-free
One frozen file per decision means ten tickets can each record a decision in the same week without ever fighting over the same file.

One-click cleanup

When Memory health flags drift, one click queues a cleanup pass — its prompt already carries this project's measured retrieval gaps, so the Worker knows exactly what to fix. It trims corpus noise like near-duplicate decisions and records that never should have been decisions, without losing a single load-bearing rationale, and opens one PR you review and ship like any other.

Near-duplicate decisions
Decisions that say the same thing twice are clustered and folded into one consolidation record — every rejected-alternative rationale quoted verbatim, so no “why” is ever lost.
Routine records that shouldn't be decisions
An ADR that a re-run of the significance gate reads as routine is flagged to fold back into the concept docs, keeping the decision log to genuine, costly-to-reverse calls.
One click, never a delete
You trigger it from Memory health when you want it; the pass opens a context: cleanup PR that goes through normal review, and it never deletes a record or rewrites history, only ever appending a consolidation on top.

Benchmarked

Measured, not vibed

Retrieval is tuned on numbers, not on hoping the right file came back. Precision and recall are benchmarked offline against the link graph as ground truth, under-recall is surfaced as concrete seeding-gap candidates, and the corpus is linted for rot — so the engine gets sharper as your decision log grows.

Point Fredrin at a repo and you get all of it. Self-hosting a folder of markdown gets you none of it.

The whole engine, pointed at your repo, from the first ticket.