MemLore vs SDD: When to Choose What
A story about the wrong patch that looked right, the specs you already wrote, and the runtime layer that helps coding agents load governed why.
The agent finished the refund handler in eleven minutes. Tests green. Diff readable. Reviewer almost clicked approve.
Then someone asked the boring question: Are we still allowed to post to the ledger in-process? Silence. The code said yes. A comment from last year said yes. A merged PR from six months ago had introduced an outbox and never deleted the old path. An ADR in docs/adr said outbox. A hallway conversation - nowhere the agent could see - had already called the in-process write a bug.
The model had not been lazy. It had been helpful with incomplete context. It read the repo. It did not know which era of truth it was living in.
That gap is why I built MemLore. MemLore (memlore on the CLI and in MCP) is open source: an engineering intelligence layer for humans and for coding agents in Cursor, Claude Code, Codex, or anything that speaks MCP. Not another chat plugin. A place to compile current, evidenced intent before someone edits the payment path.
"We already have specs."
I hear this in every serious team now, and they are right to say it.
If you practice specification-driven development - feature specs, plans, research.md, a constitution - you have already done the hard cultural work. Decisions get written. Scope gets argued. That git tree is the system of record for the feature you are building. MemLore is not here to replace specify, plan, implement. I am not selling you a reason to skip SDD.
The friction shows up later, when the repo is large and the agent is new to this ticket.
One active spec folder and a team that always opens research.md is a good life. You may never need what I built. The story changes when you have many modules, many past decisions, and several agents grazing the same boundaries. Then the work stops being "write the spec" and becomes find the paragraph, trust it over a stale note, and fit the answer into a context window before the model confidently guesses.
SDD optimizes authoring. MemLore optimizes the moment someone - human or agent - asks what do we still believe?
On the repos where this has clicked for me, the rhythm is simple. Write the full story in your spec artifacts. When the feature lands, distill one to three cross-cutting decisions into MemLore with evidence pointing back at those files - not a paste of the whole plan. Agents call get_for_task at session start; humans still live in plan.md while they implement.
The fork in the road
I sketched this for a lead who asked, bluntly, whether MemLore was an alternative to SDD. I said no, and then we walked through when each path is enough.
If your work rarely leaves one feature folder, if people still read ADRs, if PR review does not re-open settled architecture every week - stay on SDD alone. MemLore without a habit of remember, review, and supersede is just another way to grep git. Wait until the pain is real.
Add MemLore when the questions start to rhyme: Why did we do it this way in module A when module C already decided the opposite? When agents miss a decision buried in spec 047. When reviewers chase links in the diff for the third time. When three tools need the same briefing and keep inventing different versions of history.
Do not add it to dodge specs or to dump entire plans into a database. That only gives you two truths and zero sleep.
The desk full of tools
Nobody wins by picking a single hero product. You stack tools because each one answers a different question when you are tired.
Git and SDD are where you write what the team means. Versioned, reviewable, yours forever. They do not, by themselves, tell an agent which paragraph outranks yesterday's model note, or pack a task-sized briefing inside a token budget. Keep AGENTS.md for how to run tests; keep specs for the contract of the feature.
Code intelligence - the graph, the IDE, the explorer - tells you how the code connects. MemLore is for why the team chose a pattern and what is still approved. On a hard change you want both: a map of the mine and a note about which tunnels are closed.
Generic AI memory is good at déjà vu. It is weak at still true. Superseded decisions, quiet conflicts, agent self-notes that read like policy - similarity search serves them all and hopes for the best.
Pull requests are where judgment lives. MemLore on that path can compile context for the files you touched, attach decision and risk sidecars, and leave accepted lore for the next session. It does not approve your PR. It makes "has anyone already decided this?" a shorter conversation.
When similarity lies
Most teams already try to help agents. AGENTS.md, pasted wikis, memory plugins. They work until the repository carries more than one era of truth.
Then similarity search returns everything - the ADR, the obsolete comment, the half-migrated PR - and the model picks a sentence. Guessing is how you ship a patch that violates a decision you already paid for.
Engineering context is not generic text. It has a source (human, ADR, git, agent). It has rank (verified beats inferred). It has time (superseded should not win by default). It can disagree with the code without someone erasing half the story. And it has a budget: you cannot dump the wiki and call it retrieval.
MemLore's constitution says the quiet part out loud: this is not a generic memory store. It is also not Git, Jira, or the agent runtime. It sits in between - capture rationale, compile for the task, surface drift, let humans decide what becomes canon.
One repository, one boundary at a time
Everything in MemLore is scoped - usually a repository like github.com/org/repo, with room for org, team, project, task. Retrieval respects that boundary so your payment service does not accidentally inherit another team's folklore.
Reads follow scope, not ego. actor_id in local MCP mode is who is calling for audit on writes; it does not mean "only show me my lore." The team shares one graph of decisions; the trail shows who verified or superseded what.
What I want the agent to see first
I do not want the model to "search documents about refunds." I want it to ask for a context packet: this repo, this task, these files, this budget, a profile like coding or debugging. The entry point is memlore.get_for_task.
Under the hood it is a pipeline, not a rummage sale:
Each item in the packet carries more than words: trust band, authority factors, which plane it came from (governance or graph). memlore.explain tells you why something was included - evidence, verification, supersession - without inventing a bedtime story.
Unverified agent inference cannot become canonical. Verified human ADR-class knowledge can. Observations from the repo describe what the code does; they do not silently rewrite what the team intended. If a gotcha never fit the budget, the compile metadata says so. The model still writes the patch; MemLore narrows what it may treat as current.
Decisions, not footnotes
Architecture decisions are not "memories" with a ribbon on them. In MemLore they are objects: question, choice, owner, scope, lifecycle. ADRs can project into that shape; compile surfaces them as a named section with the same authority rules as everything else.
Agents read through get_for_task, knowledge_search with intent why, the explainers. They must not mint canon in a tool call and walk away - the second session should not treat "the model documented it" as law.
Ask why (REST /v1/why or MCP with "intent": "why"). You get decisions, lore, evidence. Empty is an honest answer. Fabrication is not.
How lore earns its place
Before retrieval works, something has to capture the world - carefully:
Ingest from git, PRs, ADRs, docs. Candidates land with provenance: this came from a commit, this from a file. Humans review on CLI and REST. Until someone accepts or verifies, extracted text does not behave like verified architecture. Accepted ADRs get trusted-source rules; audit and evidence stay anyway. The line I will not cross: silently promoting a guess to policy.
Cold start is boring on purpose: MVP quickstart, Docker minimal profile, Postgres and API on :8080, set REPO_SCOPE, ingest docs/adr, record one decision if you want, attach MCP. Full profile adds Neo4j and the graph worker when you want semantic search in the mix.
Two stores, one front door
PostgreSQL holds governance - scopes, verification, audit, the outbox. A thin Python graph-service holds Graphiti/Neo4j for temporal and semantic retrieval. Go MemLore Core faces agents; they do not speak Graphiti raw.
Writes commit in Postgres and sync asynchronously. If the graph is down, governance still answers. The agent contract is MCP with a fixed surface (ADR 0003): ten tools, stable names, extra intents on knowledge_search so the surface does not sprawl every week.
Wire Cursor to stdio and Postgres:
{
"mcpServers": {
"memlore": {
"type": "stdio",
"command": "/absolute/path/to/memlore",
"args": ["mcp"],
"env": {
"MEMLORE_POSTGRES_DSN": "postgresql://memlore:memlore@localhost:15432/memlore"
}
}
}
}
Mutating calls want an explicit actor_id in local mode. Annoying until you need to know whether a human verified a fact or an agent "helped" by writing it down.
A Thursday afternoon with the stack
Imagine you pick up the refund ticket again - the one that almost shipped wrong.
You open the agent and call get_for_task with the repo scope, plain words for the task, the files you will touch. You read sections.decisions and sections.gotchas before anyone types func. If the packet shows conflicts, you stop and ask a human which side is live. You do not let the model vote.
The packet is coarse on one file. You use knowledge_search with explain_file or why_line - archaeology, not invention. You write code; the repo owns syntax. MemLore owns intent: approved, superseded, forbidden.
When compile returns meta.packet_id, you can log what helped later. That signal may tune ranking; it does not override an ADR.
After the PR, drift checks can compare intent to what landed. A GitHub check or review bot can say this diff fights decision X without erasing history. Humans resolve it; the next session inherits the fix.
Humans have CLI parity too: memlore context, memlore why, ingest and review for the maintainers. v0.10.x ships the flywheel - ingest, review, decisions, compile, drift, read-only metrics. Web UI is still ahead; CLI, REST, and MCP are the governance surfaces today.
What I will not pretend
Empty knowledge stays empty. If nobody ingested ADRs and nobody recorded a decision, why returns nothing. That is better than a confident lie.
Agent-written lore is untrusted input. Prompt injection lives in stored context like anywhere else. Authority is not authorization; isolation still matters.
Token budgets drop items. You can measure what never made the packet; you cannot let popularity beat a verified decision.
Today MCP is local stdio (memlore mcp). Teams share REST, pin a release, agree on REPO_SCOPE. That is operational reality, not a keynote slide.
If you want to try one thing
Clone MemLore. Run the minimal Docker profile. Pick one repository scope. Ingest ADRs or write one decision by hand. Attach MCP. On the next non-trivial task, make get_for_task the first call - before the model touches the refund path.
Keep SDD for writing the feature. Reach for MemLore when retrieval, trust, and PR-time context become the bottleneck - not when you want permission to skip specs. Used that way, it is not an alternative to the discipline you already built. It is the layer that helps agents - and reviewers - respect the story you already wrote down.