This document is for human operators and developers using Codex directly in code.
It assumes you are working with the low-level public library surface exposed at
the package root through initCodexTables, read, write, types, and
errors.
If you are wiring Codex into an agent or LLM harness, read LLM.md
instead. That document covers the additive soul, tools, and skills
runtime. This document is about humans using the underlying library directly.
Contracts and vocabulary live in CONCEPT.md. Exact entity
details live in the entity manuals under entities/.
Human-facing direct usage usually looks like:
import { errors, initCodexTables, read, types, write } from '@ghostpaw/codex';Use this surface when a human is still deciding what to capture, how to model it, and when to revise — in application code, scripts, CLIs, backends, or custom interfaces.
| Symbol | Role |
|---|---|
initCodexTables |
One-shot DDL for the canonical schema |
read |
Query namespace (recall, getBeliefDetail, listFlags, …) |
write |
Mutation namespace (remember, confirmBelief, correctBelief, …) |
types |
Shared TypeScript types and enums |
errors |
Error classes and isCodexError guard |
CodexDb |
Type alias for the database interface |
resolveNow, withTransaction |
Plumbing hooks for time and transactions |
Root re-exports also surface concrete error classes without the errors.
prefix.
import { DatabaseSync } from 'node:sqlite';
import { initCodexTables, read, write } from '@ghostpaw/codex';
const db = new DatabaseSync(':memory:');
db.exec('PRAGMA journal_mode = WAL');
db.exec('PRAGMA foreign_keys = ON');
initCodexTables(db);
// Capture a belief
const belief = write.remember(db, {
claim: 'TypeScript improves maintainability',
source: 'explicit',
category: 'fact',
});
// Recall by topic
const results = read.recall(db, 'TypeScript benefits');
// Confirm when seen again
write.confirmBelief(db, belief.id);
// Inspect in detail
const detail = read.getBeliefDetail(db, belief.id);
// Check what needs attention
const flags = read.listFlags(db);Codex works best when a human keeps its epistemic boundaries clean:
- Put one testable proposition per belief. Split compound claims.
- Choose the honest source:
explicitif stated,observedif seen,distilledif extracted,inferredif concluded. - Choose the narrowest category:
preference,fact,procedure,capability, orcustom. - Do not inflate certainty. Let the source-weighted default start the belief honestly.
- Use provenance to record where the information came from.
If those boundaries blur — compound claims, inflated sources, wrong categories — every downstream surface (recall, flags, status, trends) works against distorted data.
A belief is one assertable proposition with confidence metadata: "The API uses GraphQL", not "Meeting notes from March 14." If you want to preserve meeting content, that is a journal or transcript. Codex stores what you believe, not what you heard.
- Active: currently held and retrievable through recall.
- Superseded: replaced by a successor. Still visible in lineage for audit and reflection, but exits active recall.
- Deleted: no trace remains. Reserved for privacy and hard erasure.
Use correctBelief to supersede. Use forgetBelief to exit active recall
while preserving the audit trail. Use deleteBelief only for hard erasure.
Source answers: how do I know this? Category answers: what kind of claim is
this? "The user prefers dark mode" is source explicit (they told me) and
category preference (it is a taste). "The API probably supports pagination"
is source inferred (I concluded it) and category capability (it is about
what something can do). Keep these separate.
Certainty is confidence in the claim right now (0 to 1). Evidence is how many times the belief has been confirmed. A single strong confirmation can set high certainty. Many weak confirmations accumulate evidence. Both affect recall scoring and flag priority differently.
All queries are deterministic, require no LLM, and carry transparency metadata.
| Function | Returns |
|---|---|
read.recall(db, query, options?) |
Ranked active beliefs by semantic + lexical match |
read.getBeliefDetail(db, beliefId) |
One belief with certainty, freshness, strength, lineage depth, proximity, version diff |
read.getBeliefLineage(db, beliefId) |
Full chain of predecessors and successors |
read.listFlags(db, now?) |
Beliefs needing attention with reason codes and priority scores |
read.getStatus(db, now?) |
Portfolio state: integrity, distributions, averages |
read.listLog(db, limit?) |
Recent activity: remembers, confirms, revisions, forgets, merges |
read.getTrends(db) |
Growing categories, calibration alerts, revision patterns |
read.listBeliefProximity(db, beliefId) |
Active beliefs semantically near a given belief |
read.recall(db, 'deployment process', {
limit: 10,
minScore: 0.1,
category: 'procedure',
source: 'explicit',
});Category and source filters narrow the candidate set before scoring. The
minScore threshold controls the quality cutoff.
Every write returns the mutated record with derived state already computed.
| Function | What it does |
|---|---|
write.remember(db, input, options?) |
Create a new belief. Returns the belief plus proximity matches. |
write.confirmBelief(db, beliefId, options?) |
Reinforce an existing belief. Certainty rises via EMA, evidence increments, verifiedAt refreshes. |
write.correctBelief(db, beliefId, input, options?) |
Create a successor belief and supersede the old one. Returns the new belief, the superseded id, and proximity. |
write.mergeBeliefs(db, input, options?) |
Consolidate multiple beliefs into one richer successor. |
write.forgetBelief(db, beliefId, options?) |
Supersede a belief out of active recall. Audit trail preserved. Optional successorId for directed supersession. |
write.deleteBelief(db, beliefId) |
Permanently destroy a belief and its lineage chain. No trace remains. |
write.deferBelief(db, beliefId, deferredUntil, options?) |
Postpone flag eligibility until a future timestamp. No other state changes. |
write.dismissProximityPair(db, beliefA, beliefB, options?) |
Record that two beliefs are not meaningfully related. Uses exponential backoff. |
write.remember(db, {
claim: 'The billing API has a 5-second timeout',
source: 'observed',
category: 'fact',
provenance: 'incident-2024-11',
});The certainty field is optional — it defaults to the source-weighted value
(explicit = 0.9, observed = 0.8, distilled = 0.6, inferred = 0.5).
Only override it when you have a specific reason.
write.correctBelief(db, oldBeliefId, {
claim: 'The billing API has a 10-second timeout',
source: 'observed',
certainty: 0.85,
});The replacement can change the claim, source, category, and certainty. The old belief is superseded. Lineage records what changed and when.
write.mergeBeliefs(db, {
beliefIds: [12, 34],
claim: 'SQLite supports databases up to 281TB with WAL mode for concurrent reads',
});When called with a successorId instead of a new claim, the existing belief
becomes the winner and the others are superseded to it.
write.forgetBelief(db, weakerBeliefId, {
successorId: strongerBeliefId,
});This is how you express "belief A already covers belief B" without creating a new entry.
The direct-code operating loop is:
- Capture beliefs as they arise — one claim per belief, honest source.
- Search before creating to avoid duplicates —
read.recall()first. - Confirm beliefs when evidence accumulates —
write.confirmBelief(). - Correct beliefs when understanding changes —
write.correctBelief(). - Process flags periodically —
read.listFlags()drives the maintenance queue. - Inspect before acting —
read.getBeliefDetail()gives full context. - Check status to monitor health —
read.getStatus()shows integrity. - Review trends for systemic patterns —
read.getTrends()catches calibration drift.
When new information arrives, decide whether it is a belief worth storing.
Split compound claims: "The API uses REST and requires VPN access" becomes two separate beliefs, each independently confirmable.
Choose the strongest honest source:
| Source | When to use |
|---|---|
explicit |
The person directly stated this |
observed |
You saw this behavior or evidence |
distilled |
You extracted this from a conversation, document, or session |
inferred |
You concluded this from indirect evidence |
write.remember(db, {
claim: 'The frontend will use React',
source: 'explicit',
category: 'fact',
provenance: 'kickoff-meeting-2025-03',
});Human habit:
- one claim per belief
- honest source
- use provenance to record where it came from
- do not inflate certainty
Before adding a new belief, check whether it already exists:
const existing = read.recall(db, 'frontend framework', { minScore: 0 });If a match exists: confirm it (same meaning) or correct it (updated meaning). Do not create a duplicate.
// Same meaning — reinforce
write.confirmBelief(db, existingBeliefId);
// Updated meaning — supersede
write.correctBelief(db, existingBeliefId, {
claim: 'The frontend will use Svelte',
});The remember function returns proximity matches in the result. If
result.proximity is non-empty, inspect the matches before moving on.
Each confirmation strengthens the belief through exponential moving average:
write.confirmBelief(db, beliefId);Certainty rises toward the ceiling (0.99). Evidence increments. verifiedAt
refreshes, resetting the freshness clock. A belief confirmed 4 times decays at
half the rate. A belief confirmed 16 times decays at a quarter the rate.
Human habit:
- confirm when you see the same evidence again
- do not confirm automatically just to boost certainty
- each confirmation should represent a genuine re-observation
When the claim is no longer accurate, correct rather than delete:
write.correctBelief(db, oldBeliefId, {
claim: 'The team deploys on Thursdays, not Fridays',
source: 'observed',
});The old belief is superseded. The new belief enters with fresh certainty. The
lineage chain records what was believed before and when it changed. The version
diff is available through read.getBeliefDetail().
Human habit:
- prefer correct over delete
- correct preserves the epistemic record
- delete destroys it
Flags are the maintenance surface. They tell you what needs attention and why.
const flags = read.listFlags(db);Each flag carries reason codes and a review priority. The reason codes tell you why the belief surfaced:
| Code | Meaning | Typical action |
|---|---|---|
stale |
Freshness below threshold | Confirm if still valid, correct if changed, forget if irrelevant |
fading |
Freshness declining | Same as stale, but less urgent |
single_evidence |
Only confirmed once | Confirm with genuine re-observation or defer |
unstable |
Lineage depth exceeds threshold | Inspect why it was revised so often |
low_trust |
Source is inferred or distilled | Confirm with stronger evidence |
gap |
Category underrepresented | Consider capturing beliefs in the thin category |
Flags respect deferredUntil — deferred beliefs do not appear until their
deferral expires.
Human habit:
- process flags weekly
- inspect before acting —
read.getBeliefDetail()first - choose the right verb for the situation
- do not blanket-confirm to clear the queue
Before revising a belief, get full context:
const detail = read.getBeliefDetail(db, beliefId);This returns:
- certainty, freshness, strength tier, evidence count
- source, category, provenance
- lineage depth
- proximity matches (nearby active beliefs)
- version diff (if superseded or superseding)
Proximity matches are the overlap detection surface. If a nearby belief is a genuine duplicate, merge or forget one. If the pair is genuinely distinct, dismiss it:
write.dismissProximityPair(db, beliefA, beliefB);const status = read.getStatus(db);Key fields:
integrity— percentage of active beliefs in the Strong tier. Above 70% is healthy. Below 50% needs immediate attention.strengthCounts— how many beliefs are strong, fading, or faint.certaintyDistribution— spread of confidence levels.evidenceDistribution— how well-confirmed the portfolio is.sourceCounts— balance between explicit, observed, distilled, and inferred.categoryCounts— balance across preference, fact, procedure, capability, custom.
Human habit:
- check status after maintenance passes
- watch for declining integrity as a signal that flags are accumulating
- watch for imbalanced source counts as a signal that too many beliefs are inferred
const trends = read.getTrends(db);Key fields:
growingCategories— which categories are gaining beliefs fastest.calibrationAlerts— warnings when high-certainty beliefs are frequently revised, signaling systematic overconfidence.revisedHighCertaintyCount— how many confident beliefs were corrected.repeatedlyRevisedCount— how many beliefs have unstable revision history.
If calibration alerts appear repeatedly, lower your default certainty for the problematic source or category combination.
| Verb | Function | When to use |
|---|---|---|
| Remember | write.remember() |
New proposition enters the Codex |
| Confirm | write.confirmBelief() |
Same evidence seen again |
| Correct | write.correctBelief() |
Understanding changed — supersede with replacement |
| Merge | write.mergeBeliefs() |
Two beliefs consolidate into a richer successor |
| Forget | write.forgetBelief() |
Belief exits active recall — audit trail preserved |
| Delete | write.deleteBelief() |
Hard erasure — no trace remains |
| Defer | write.deferBelief() |
Postpone flag eligibility until a future date |
| Dismiss | write.dismissProximityPair() |
Suppress a false-positive proximity pair |
Good usage:
- one claim per belief, honestly sourced
- search before creating to avoid duplicates
- correct and confirm regularly to keep the active set honest
- process flags before they accumulate
- use lineage as a growth record, not a failure trail
- check status and trends for systemic health
Bad usage:
- compound claims bundled into single beliefs
- inflated sources to boost certainty artificially
- blanket-confirming flags without genuine re-evaluation
- deleting beliefs instead of correcting to avoid lineage
- ignoring proximity warnings after captures
- never processing flags