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.
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
Move Project Context into the database for faster reads
Project Context files are canonical. A prior decision keeps context as files in the repo so it versions with the code and can't drift. Moving it into a database forks the source of truth — the exact failure that decision exists to prevent.
ADR · project-context-files-are-canonical
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.