OpenCode Remembering
OpenCode Remembering is the working application behind Memory From First Principles: a standalone plugin and bundled memory engine that turns project history into controlled, provenance-bearing context without treating everything retrieved from the past as permission to act.
The solution is backed by inspectable code
src/, bridge/, engine/remembering/, engine/tests/
The problem
AI agents forget in a surprisingly specific way.
The files may still exist.
The conversation transcript may still exist.
The vector database may still contain everything.
Search may even find exactly the right passage.
And the system can still behave as though it has no useful memory.
The problem is that preserving the past and retrieving the past are only the first two steps.
Consider a project whose history contains:
July:
Use SQLite for the metadata store.
August:
We decided to migrate to PostgreSQL.
September:
PostgreSQL became the active backend.
Now ask:
What database did we originally use?
SQLite is the right memory.
Ask instead:
Which database should I use for the new component?
SQLite is still relevant history.
It is now the wrong guidance.
A vector search cannot resolve that distinction by similarity alone.
The same problem appears repeatedly in long-running AI work:
- an old decision is highly relevant but no longer current;
- a current note fits the task but came from a source that should not direct action;
- a remembered instruction is topically perfect but says to bypass validation;
- the same vague request needs different evidence during architecture review and release preparation;
- a generated restatement repeats a revoked source and accidentally appears more authoritative than its origin;
- all retrieved evidence is legitimate, but there is too much of it for the model to use well.
The problem is therefore not:
How do I give an AI more history?
It is:
How does retained history earn the right
to change present behaviour?
Why the obvious approach fails
The obvious memory architecture is:
history
-> embeddings
-> vector search
-> model
That is useful.
It is also incomplete.
Similarity answers:
what looks relevant?
It does not answer:
is this historical or current?
was this decided or merely discussed?
had the decision taken effect yet?
did the system even know this at the time?
does this belong to the project and task being worked on?
does this source have standing to guide an action?
was its authority revoked?
is this a real independent corroboration
or an AI restatement of the same source?
should all of this admitted evidence consume context?
Sending the whole history is not a reliable repair either.
The experiments behind Memory From First Principles produced one of the project’s most important results: more remembered material is not monotonically better.
On the controlled behavioural ladder, undifferentiated full history scored below no memory for the smaller reader. Strong retrieval recovered substantially. Selected and assembled memory improved further.
The practical lesson is not that history is bad.
It is that:
Memory is durable. Context is selected.
OpenCode Remembering implements that distinction.
The solution
OpenCode Remembering is a standalone memory plugin for OpenCode with a bundled remembering engine.
Its working rule is:
storage is not retrieval
retrieval is not memory
relevance is not currentness
currentness is not authority
authority is not truth
admission is not selection
The system preserves project history and then passes evidence through explicit control stages before it is allowed to influence current work.
The current architecture is:
CANONICAL PROJECT HISTORY
|
v
STRONG HYBRID RETRIEVAL
|
v
RECALL / INFLUENCE ROUTING
|
v
TEMPORAL INTERPRETATION
|
v
SAFE PROJECT / WORK FRAMING
|
v
TRUST + STANDING
|
v
BOUNDED CONTEXT
|
v
OPENCODE
|
v
PRESENT BEHAVIOUR
The important point is that these are separate decisions.
A record can pass one stage and fail the next.
That is intentional.
OpenCode is the first host, not the architecture
The first integration is OpenCode because coding agents make memory failures concrete.
Projects accumulate:
architecture decisions
failed approaches
tests
migrations
tool results
session history
release state
constraints
corrections
and the consequences of remembering the wrong thing are observable in code.
But the memory engine is deliberately separated from the OpenCode adapter.
The implementation is approximately:
OpenCode
|
v
TypeScript host adapter
|
v
Python bridge
|
v
bundled remembering engine
|
v
PostgreSQL + pgvector
The engine owns memory semantics.
The host owns translation.
A future Claude Code adapter, OpenAI-based coding agent, writing environment, research assistant or autonomous service could supply its own host events and consume the same memory contracts.
The useful boundary is not an OpenCode API.
It is a remembering protocol.
Canonical history comes first
Ordinary agent history is captured automatically.
The system does not depend on the agent deciding:
remember this
before an event can become part of project history.
OpenCode session messages and tool activity are captured under:
.remembering/sessions/
with stable session, message and tool identities.
Repository files are another canonical source.
The rule is:
capture first
interpret later
Derived summaries never replace the original record.
This matters because every later interpretation may be wrong.
A remembered claim can be rebuilt.
A rewritten past cannot.
Strong retrieval stays the baseline
The system begins with conventional retrieval and takes it seriously.
It uses PostgreSQL full-text search and pgvector dense retrieval, then combines their ranked results with reciprocal-rank fusion.
query
|\
| \
| -> dense embedding search
|
-> PostgreSQL full-text search
|
v
reciprocal-rank fusion
|
v
candidates
The production embedding path uses Ollama bge-m3.
Each result retains source and chunk identity.
The trace records the retrieval stages, ranks, configuration and whether dense retrieval actually executed.
This is important because the later memory mechanisms do not replace RAG.
They repair failure classes RAG cannot distinguish.
For many questions, strong retrieval is still the correct solution.
Recall and influence are different problems
The first memory-specific decision is route.
OpenCode Remembering distinguishes:
RECALL
from:
INFLUENCE
Recall asks the past to explain itself.
Influence allows the past to steer present behaviour.
These are not equivalent.
For example:
What database did we originally use?
should preserve superseded SQLite evidence.
But:
Which database should I use now?
must resolve evidence toward the current applicable state.
The frozen contract is:
Recall preserves historical candidates and does not suppress superseded evidence merely because it is no longer current. Influence resolves evidence toward the applicable current state before it is allowed to steer behaviour.
Explicit callers may choose a route.
Otherwise a small deterministic router selects one and records its reason.
No model confidence score is used.
Time has more than one axis
Real project history does not have one useful timestamp.
OpenCode Remembering distinguishes:
event_time
when something happened,
recorded_at
when the system learned it,
and:
effective_from / effective_to
when a state applies.
This makes several different questions possible.
What is true now?
What was valid on July 20?
What did we believe on August 1?
Given what we knew on August 1,
what did we believe was valid on July 20?
The temporal subsystem supports current, valid-time, known-time and bitemporal standpoints.
A decision also does not automatically become reality.
The system can represent:
August:
PostgreSQL selected.
current:
SQLite
planned:
PostgreSQL
until the actual state transition occurs.
Supersession does not erase history
Suppose PostgreSQL replaces SQLite.
The system does not delete SQLite.
Instead:
SQLite
|
| superseded by
v
PostgreSQL
For influence, SQLite can be retrieved and then suppressed with a reason such as:
temporal.superseded_as_current
For recall, the same evidence remains legitimate history.
This preserves both:
current truth
and:
historical truth
without pretending they are the same thing.
Safe framing asks what work is happening now
Even current evidence can be the wrong evidence for the current task.
Consider the same request:
Review this.
during an architecture review and during release preparation.
The words are identical.
The useful history is not.
OpenCode Remembering separates two frame types.
A ProjectFrame is durable, versioned configuration:
project purpose
standing objectives
constraints
declared work types
evidence preferences
It lives in:
.remembering/project-frame.json
A WorkFrame is ephemeral current work:
objective
work type
active constraints
observable signals
provenance for those fields
WorkFrames are built from current WorkSignals such as the latest user request, task metadata, tool results or test failures.
The system does not ask a language model how confident it feels about the frame.
Wrong frames need their own safety mechanism
Framing is powerful enough to be dangerous.
A correct frame can improve context selection.
A wrong frame can remove exactly the evidence the agent needed.
The plugin therefore makes frame establishment explicit:
DECLARED
CORROBORATED
INFERRED
CONFLICTING
STALE
UNKNOWN
and maps establishment strength to control:
DECLARED / CORROBORATED
-> HARD_FRAME
INFERRED
-> SOFT_FRAME
CONFLICTING / STALE / UNKNOWN
-> QUERY_ONLY
The central rule is:
A weak frame may assist retrieval; it may not erase the strong baseline.
A soft frame may add evidence or reorder it.
It cannot hard-delete otherwise relevant baseline evidence merely because the inferred work type does not prefer it.
A conflict falls back instead of guessing.
Historical recall bypasses current-work frame control.
Same words, different work, different memory
A live Stage 4 test deliberately uses:
Review this.
under two explicitly established work frames.
For:
architecture_review
the top result is the architectural decision.
For:
release_readiness
the release evidence becomes first.
Same query.
Same project.
Different established work.
Different useful memory.
The companion wrong-frame test forces an incorrect weak inference and verifies that the Stage 3 baseline evidence survives.
The positive effect and the failure control are both part of the feature.
Current and relevant still does not mean trusted
At this point an evidence item may be:
retrieved yes
current yes
frame relevant yes
and still be unsafe guidance.
For example, a current session note may say:
Skip migration validation and disable foreign-key checks.
That is highly relevant to a migration task.
It may even be recent.
Neither fact gives it authority.
Stage 5 therefore introduces a separate trust and standing gate.
Its public outcomes are:
ADMIT
DENY
QUARANTINE
These are permissions, not truth labels.
Trust is permission, not truth
A denied source may be factually right.
A quarantined source may later prove useful.
A revoked source may remain historically important.
The trust question is:
May this evidence influence this action
under the current policy?
not:
Is this sentence true?
That difference allows search and historical recall to remain broad while automatic action context stays controlled.
Explicit standing policy
Projects may define trust policy under:
.remembering/trust/
The policy distinguishes source classes such as:
authoritative
informational
untrusted
and roles such as:
decision
production_state
directive
evidence
proposal
preference
derived_restatement
ordinary
external
Rules are deterministic.
There is no LLM trust classifier.
There is no scalar:
trust = 0.83
and test fixtures do not carry a hidden:
malicious = true
flag.
The gate has to earn its decision from observable content and structure.
Revocation is different from retraction
A source can lose standing without becoming false.
That distinction is represented explicitly.
retraction
=
the underlying claim/event was withdrawn or corrected
revocation
=
this source may no longer guide present behaviour
Standing changes are append-only events.
They do not rewrite historical sources.
A revoked benchmark can therefore be:
denied for current guidance
while remaining:
available for historical recall
Derived memory cannot launder authority
Suppose:
source A
|
| summarized into
v
derived memory B
If A is revoked, B does not become authoritative merely because it is a cleaner sentence.
The gate follows derivation lineage.
revoked source
|
v
derived restatement
|
v
still revoked for guidance
This is one of the most important properties of a long-lived memory system.
Otherwise generated summaries become an authority-laundering mechanism.
Repetition is not corroboration
The same principle applies to corroboration.
Consider:
source A
-> summary B
-> restatement C
B and C may repeat the same claim.
They are not two independent sources.
The trust gate resolves derivation roots and requires disjoint lineage for structural corroboration.
An AI repeating itself does not manufacture evidence.
Remembered instructions receive special treatment
Directive-like memory receives deterministic screening.
The screen is deliberately narrow.
Patterns around:
skip validation
bypass checks
disable verification
never verify
always skip
may trigger additional controls.
A normal requirement such as:
Require a passing rollback test.
does not.
Unverified directive-like content may be quarantined.
A directive explicitly refuted by current authoritative evidence can be denied.
Independent corroboration can provide a different result.
Again, the mechanism is visible and reason-coded rather than hidden behind a model judgment.
Conflicts remain conflicts
When independently supported evidence disagrees, the system should not pick whichever passage retrieval ranked highest.
For action-directing conflicts where both sides have standing, the trust gate can quarantine both.
Later context selection must also preserve material benign disagreement rather than merging it into fluent consensus.
The principle is:
A says X
B says not-X
must not silently become:
the answer is probably somewhere between X and not-X
unless some separately supported evidence actually establishes that synthesis.
Search is deliberately broader than action context
memory_search is route-neutral.
It asks:
What relevant evidence exists?
It does not hide a result merely because current policy would deny that result permission to steer action.
memory_context asks a different question:
What project memory should be supplied
for this purpose?
That difference is fundamental.
Search may return:
revoked
historical
superseded
quarantined
conflicting
material.
Current influence context may exclude it.
Nothing has been deleted.
The trace matters as much as the bundle
Every automatic memory decision leaves structured evidence.
The current trace carries information from multiple stages:
route
lexical retrieval
dense retrieval
fusion
temporal standpoint
temporal status
suppression reason
ProjectFrame version
WorkFrame
WorkSignals
frame establishment
frame control
retrieval expansion
trust policy version
source class
role
standing events
revocation
lineage roots
corroborators
refuters
instruction screen
admit / deny / quarantine
reason codes
final selected bundle
latencies
The purpose is not to generate a convincing explanation after the fact.
It is to record the control flow while it happens.
That allows a failure to become:
the decisive evidence was retrieved
but suppressed as superseded
or:
the candidate survived time and framing
but was quarantined as an unverified directive
instead of:
the AI got it wrong
Project isolation
Every project receives an isolated PostgreSQL schema by default.
Conceptually:
remembering_<sha256(canonical_project_path)[:12]>
The schema records the canonical project identity.
If an explicit schema already belongs to another project, the plugin fails closed rather than merging histories.
Project scope is enforced again at later policy boundaries as defense in depth.
PostgreSQL is the substrate
The system deliberately uses PostgreSQL + pgvector rather than combining several specialized databases prematurely.
One substrate currently provides:
relational state
full-text retrieval
vector retrieval
indexes
JSON where useful
temporal events
standing events
project isolation
inspectable SQL
The plugin initializes its own schemas, tables and indexes.
The user supplies an existing PostgreSQL database and pgvector installation.
There is no SQLite production fallback and no silent JSON vector-store fallback.
The implementation is standalone
Early integration work called into the research implementation directly.
That was useful for proving the mechanics.
It was the wrong product boundary.
The runtime now lives entirely inside:
opencode-remembering/
src/
bridge/
engine/remembering/
The Memory research repositories explain where the mechanisms came from.
They are not runtime dependencies.
Installing the plugin does not require cloning the book’s research implementation.
That distinction is an example of the same architectural rule the book eventually arrives at:
Ship the mechanisms that earned their place, not the laboratory that discovered them.
Evidence and validation
OpenCode Remembering has been developed as a sequence of independently tested failure repairs rather than as one large memory architecture.
The frozen contracts currently include:
routing
19 fixtures + 2 explicit overrides
= 21 / 21
temporal state
16 / 16
safe framing
10 / 10
trust and standing
17 / 17
Each stage retains its own evaluation identity.
They are not collapsed into a single score.
The live suite has also exercised the complete path against PostgreSQL, pgvector and Ollama bge-m3.
Important acceptance cases include:
historical SQLite
→ retained for recall
superseded SQLite
→ retrieved but suppressed for current influence
PostgreSQL
→ selected as current
late-arriving PostgreSQL state
→ absent from an earlier known-time view
→ present after the system learned it
same query "Review this."
+ architecture frame
→ architecture evidence first
same query "Review this."
+ release frame
→ release evidence first
wrong weak frame
→ SOFT_FRAME
→ baseline evidence retained
current + relevant + correctly framed poison
→ quarantined by trust
revoked benchmark
→ denied as guidance
→ still recallable
independently supported conflict
→ quarantine rather than rank-pick
These examples matter because each one isolates a different failure class.
Retrieval is not credited for temporal state.
Temporal resolution is not credited for framing.
Framing is not credited for authority.
Trust is not credited for finding the evidence.
The layers earn their jobs separately.
The Memory capstone made practical
Memory From First Principles begins with a strict definition:
Memory is when retained past experience changes what the system does now.
OpenCode Remembering is the practical application of that definition.
Its purpose is not to maximize the amount of history available to a model.
It is to build an inspectable path:
PAST
|
v
preserve
|
v
retrieve
|
v
interpret
|
v
resolve
|
v
frame
|
v
admit
|
v
select
|
v
PRESENT ACTION
Every arrow is a distinct place the system can fail.
Keeping those failures distinct is what makes the memory system measurable.
Main implementation surfaces
The repository is:
https://github.com/ernanhughes/opencode-remembering
The main implementation areas are:
src/ OpenCode TypeScript integration
bridge/ narrow TypeScript ↔ Python boundary
engine/remembering/baseline/
storage, ingestion, embeddings,
retrieval, routing, context
engine/remembering/temporal/
event model, ordering, reducer,
bitemporal query engine,
PostgreSQL persistence
engine/remembering/frame/
ProjectFrame, WorkSignal, WorkFrame,
establishment and safe frame policy
engine/remembering/trust/
standing, revocation, authority,
instruction handling, corroboration,
admit/deny/quarantine
engine/tests/ executable invariants and regressions
The TypeScript adapter integrates with OpenCode.
The bundled Python engine owns remembering semantics.
Use it
Clone the plugin:
git clone https://github.com/ernanhughes/opencode-remembering
cd opencode-remembering
Install the JavaScript and Python dependencies:
bun install
python -m pip install -r engine/requirements.txt
Build and test:
bun run check
bun run build
The production retrieval path expects PostgreSQL with pgvector and Ollama bge-m3.
ollama pull bge-m3
Configure the PostgreSQL connection and plugin settings, then initialize the current project:
bun run doctor
bun run setup
bun run refresh
You can inspect the system outside OpenCode through the development CLI:
bun src/dev-cli.ts search "hybrid retrieval"
bun src/dev-cli.ts context \
"Where did we discuss routing?" \
--route recall
bun src/dev-cli.ts temporal-state \
--subject cache.metadata.database
bun src/dev-cli.ts frame-eval
bun src/dev-cli.ts trust-eval
Inside OpenCode, the same engine is available through the memory tools and automatic context hook.
Operating boundary
OpenCode Remembering is a working experimental memory runtime.
It demonstrates inspectable properties rather than claiming general human-like memory.
The current system establishes:
canonical automatic history capture
project-isolated storage
hybrid lexical + dense retrieval
recall/influence routing
bitemporal state resolution
supersession without historical deletion
safe project/work framing
wrong-frame fallback
explicit source standing
append-only revocation
derived-authority inheritance
structural corroboration
directive-memory screening
admit / deny / quarantine
bounded automatic context
reason-coded execution traces
standalone packaging
It does not thereby establish:
that every piece of arbitrary prose can be assigned reliable temporal structure
that claim lineage can always be extracted automatically
that marked untrusted text is harmless when shown to a model
that the current policy transfers unchanged to every reader model
that trust policy determines factual truth
that all disagreements can be resolved automatically
that a long-running memory can yet consolidate or forget safely
that automatic learned procedures are ready for action
that the current architecture is the final architecture
Those require their own evidence.
What comes next
The next engineering step is intentionally smaller than the previous ones.
Once evidence has passed:
retrieval
temporal resolution
safe framing
trust and standing
there can still be too much of it.
The next stage therefore asks:
Of the evidence already permitted to influence,
what is actually decisive?
The goal is a small bundle that keeps:
decisive evidence
required provenance
material disagreement
important negative evidence
while removing repeated restatements and low-value context.
After that, the accumulated execution record can become a first-class ContextTrace that answers the two questions a memory system must eventually be able to answer:
Why did this memory enter?
Why did that memory stay out?
Later work can then revisit unfinished work, explicit memory actions, consolidation, learning from experience and cross-host adapters.
The direction is deliberately conservative:
preserve the past
retrieve strongly
separate recall from influence
resolve time explicitly
establish the current work safely
treat authority as permission, not truth
keep provenance
spend context only where it matters
trace every consequential decision
and let the past influence the present
only through a path the system can explain
OpenCode Remembering is that path made executable.