titen.dev
latest 0.8.7channel: stable
Release history

Changelog

Every release, dated in UTC, matching the npm registry time field. Keep a Changelog format, SemVer clause 4 discipline. Below 1.0.0 the minor slot is the only breaking-change signal you get.

$npm i titen-memory@0.8.7
Release cadence24 releases · 11 days
131 JUL
801 AUG
104 AUG
105 AUG
207 AUG
208 AUG
110 AUG
113 AUG
515 AUG
116 AUG
117 AUG

Nine of the twenty landed on 1 Aug in the original governance run. The tall bar is not velocity, it is a day of small corrections shipped honestly.

Read before upgrading

0.5.7 → 0.6.0 may break you, and ^0.5.0 does not match 0.6.0. Pin an exact version. The word stable around Titen names the release channel, never API stability.

data-usable upgrade floor: 0.2.0

Detailed releases

24 releases · 150 entries
v0.8.7patch

The Level 6 sidebar now restores the approved workspace-selection hierarchy without changing the live authorization or request contract.

Fixed
The exposed native workspace select is replaced by the mockup-aligned two-line trigger, workspace icon, animated chevron, active checkmark, and bounded menu explanation on desktop and mobile.
Fixed
Selecting an authorized workspace still clears stale results and scopes Memories and Workspace Graph requests with the same live workspace_id.
Security
Workspace names and selection state are cleared when the principal signs out or the adapter disconnects; no workspace or credential state enters browser storage.
v0.8.6patch

The complete Level 6 operator surface now runs on live, scoped contracts in both runtimes, with package and Cloudflare regressions closed before release.

Added
The Astro operator dashboard now implements the complete fifteen-destination product map from the approved Level 6 mockup: Atlas, Memories, Context, Subjects, Work, Audit & Events, System, Models, Federation, Access, API & Keys, Projects, Approvals, Releases, and Profile.
Added
Atlas adds a bounded workspace_graph lens over authorized claim/subject nodes and canonical relationships, with stable layout, selection, legend, truncation state, and direct Evidence Trace navigation.
Added
New principal, project, subject, reference, scoped-grant, access-simulation, and masked model-diagnostic routes run through the shared Bun/Cloudflare contract. Model probes are bounded, rate-limited, metadata-audited, and make no canonical write.
Added
Work, grant/key management, approval, and release controls now execute their existing versioned server operations with confirmation and refreshed live state. Context shows its token budget; System shows readiness detail.
Changed
Canonical reads, writes, approvals, events, Atlas, context, federation, and directories now share a visibility-plus-additive-grant boundary. Derived API keys are clamped to their declared target and their issuer’s current grants on every request; admin delegation remains bounded to its grant target.
Changed
Memories and Workspace Graph keep organization-visible records available in every selected workspace while limiting team-visible records to the matching workspace.
Changed
Dashboard navigation, responsive rail, local typography, loading/empty/error states, search, pagination, and action surfaces now match the approved warm-paper desktop and 320 px mobile system without new runtime dependencies.
Fixed
The npm package includes dist/index.html, so an installed titen dashboard serves the root redirect as well as /dashboard/ (#303).
Fixed
Atlas fallback routing remains in the shared API root, preserving the authenticated Cloudflare administrator compile path (#304).
Security
Migration 23 backfills compatibility grants without rewriting evidence; denied resources remain absent from labels, counts, facets, cursors, graph topology, disputes, citations, and directory summaries.
Security
Model configuration exposes only masked immutable tuples; dashboard secrets, provider payloads, prompts, and embeddings never enter browser-visible state.
v0.8.5patch

The dashboard now renders live Atlas evidence using the approved claim-centered Evidence Trace structure.

Added
Authorized context and active release nodes beside source observations and the focus claim.
Changed
Evidence Trace now uses a centered claim, deterministic graph layout, and labeled supports, contradicts, qualifies, selected-in, and released-as edges.
Security
Context packs fail closed when any item is unreadable, while releases are revalidated against the current active claim version and validity window.
v0.8.4patch

The dashboard now separates the actionable Memories inventory from the read-only visual Atlas. Memory records are visible immediately after login, without a compile step.

Added
GET /v1/memories lists authorized canonical claims with bounded lexical search, lifecycle/visibility filters, and stable keyset pagination.
Added
The same-origin dashboard adapter exposes the protected Memories list route.
Added
Memories has real loading, empty, error, search, and pagination states; a selected record opens its evidence graph in Atlas.
Changed
Atlas is a separate navigation destination with its graph, inspector, compile trace, and administrator boundary.
Changed
Global dashboard search now searches Memories.
Security
Memory list authorization and retention checks run in canonical SQL before FTS or pagination. Hidden records never contribute to a count or cursor.
v0.8.3patch

The 0.8.3 release closes the Atlas authorization and semantic-index readiness issues.

Added
Audited organization-admin Memory Atlas mode for owner/root operators with bounded reasons and metadata-only audit records.
Added
Explicit principal/access metadata and safe empty-state copy in the dashboard.
Changed
Pending semantic-index projections now report HTTP 200 readiness with index_projection_pending; dependency failures remain HTTP 503.
Changed
Dual-runtime contract, security, dashboard, and package smoke coverage now protects both paths.
Security
Organization-wide reads require the dedicated scope, owner/root role, same-organization binding, bounded reason, retention filtering, and limit enforcement.
Security
Audit records never contain memory content.
v0.8.2patch

titen-memory 0.8.2

Added
titen dashboard [--port 4322] serves the packaged Astro dashboard through the existing same-origin adapter. Live mode remains opt-in and requires the documented private service configuration.
Added
prepack rebuilds the dashboard and SDK before creating the npm tarball.
Security
The package includes only built dashboard assets and the adapter entrypoint; credentials, mockup source, memory content, and runtime state remain excluded.
v0.8.1patch

The live operator dashboard now follows the approved Memory Atlas visual system while keeping the authenticated adapter and six-area contracts unchanged.

Changed
Reworked the Astro dashboard rail, header, lens controls, status metadata, topology workspace, compile trace, and inspector with local Titen icons and the approved warm paper palette.
Changed
Added a live, bounded SVG topology that is derived only from authorized Atlas nodes and edges, with a synchronized accessible record list and inspector.
Changed
Added a native search dialog that fills the authorized Atlas query without moving credentials or memory data into browser storage.
Changed
Wired every visible rail item to a real destination: Memories aliases Atlas, System shows live health/readiness, Access shows the effective principal policy, and Releases loads authorized release data.
Changed
Added a private Profile view with session-backed password rotation, and fixed the readiness revision display when the upstream reports it in response metadata.
Fixed
Dashboard mobile layout now keeps the Atlas graph inside an internal scroll region and preserves a single-column reading path.
v0.8.0minorBREAKING

Titen can now bootstrap curated memory from sixteen agent and memory-system exports through one bounded, deterministic importer. This release also closes the three usability gaps that could make accepted evidence look missing, split one service across working directories, or leave an apparently successful installer without a runnable command.

Upgrade
Breaking: service commands without --db now use the absolute per-user store ~/.titen/service.db, not ./titen.db. Existing deployments should keep passing their current absolute --db path or move the database once. When a legacy cwd titen.db exists and the user store does not, Titen refuses to mutate either store and prints the explicit compatibility command.
Upgrade
The website installer now exits non-zero when titen is installed but still cannot be resolved by name. Automation that intentionally consumes the verified absolute binary path should call install.sh --print-path; its stdout contains that path only.
Added
titen import-source previews by default and applies only with an explicit local database or exact served origin. Versioned profiles cover Mem0, OpenClaw, Hermes, Claude Code, Codex, Gemini CLI, Qwen Code, ByteRover, Amazon Q, Replit, Honcho, Letta AgentFile, MemoMind, agent rule files, Basic Memory, and explicit Markdown. Imports use the existing observation and consolidation contracts, deterministic source and idempotency identities, private/unverified defaults, and exact replay accounting.
Added
Context-pack budgets now report unconsolidated_observations: the count of readable evidence in the requested subject/project scope that has not yet produced a claim. Returned context items remain claim-only.
Fixed
An accepted observation no longer looks silently lost: both Bun/SQLite and Cloudflare/D1 expose the scoped pending-evidence count without leaking hidden organizations, projects, workspaces, or private principals (#297).
Fixed
bootstrap and serve no longer choose different databases when launched from different directories, and serve refuses to create an empty store by accident (#298).
Fixed
The installer no longer reports success when the verified binary is outside PATH; it prints a predictable TITEN_BIN=... recovery value and exits 1, while --print-path provides a scripting-safe mode (#299).
Security
Source import rejects secrets before target access, symlinks, non-UTF-8 and unsafe-control text, unknown or incomplete structured exports, populated AgentFile environment values, dangling block references, more than 10,000 entries, or more than 64 MiB of selected input. Rule links and vendor frontmatter remain inert evidence and are never dereferenced or executed.
v0.7.4patch

Three fixes found while wiring a live Titen into Claude Code as a memory server, and every one of them cost hours before it was understood.

Fixed
A bridge started without its environment answered every lookup from the wrong store and said so nowhere. With neither TITEN_MCP_URL nor TITEN_API_KEY set, titen mcp falls back to ~/.titen/memory.db. That is correct, and a host configuration can reach it by accident: on the machine where this was found, a project-scoped MCP registration with an empty env shadowed the user-scoped one that carried both variables. The session looked healthy — connected, eighteen tools — while titen_compile returned zero items for a subject whose claim the served instance returned over HTTP in the same minute. Local mode now names the store it opened and both unset variables twice: once on stderr, and once appended to the instructions in the initialize result, which is the copy the model reading an empty context pack can actually see. A served deployment appends nothing.
Fixed
A failed bridged request was one sentence for every cause. A revoked key, a wrong port and a restarted server all produced exit 0, empty stderr, and the same -32000 Titen MCP request failed.; a notification produced no reply and no trace at all. The endpoint and the caught reason now go to stderr for requests and notifications alike, with the API key redacted as it already was in a response body, and an upstream answer that is not JSON-RPC reports its HTTP status. The body is still never printed, because it carries memory.
Fixed
.gitignore covered databases and no key material. titen.key, keys/owner.key and secrets/x.pem were all committable in the repository whose CLI prints an API key and a dashboard password, and whose default --db is relative to the working directory. *.key, *.pem, *.p12 and secrets/ are now ignored.
v0.7.3patch

Prompted by an external audit of b2d2fba. 61 of its claims were verified against HEAD before any of them was acted on: 32 held, 4 were already fixed, 18 held in part, and 7 were wrong. Everything below survived that check; the rejections are in PR #296 so nobody spends a day on them.

Fixed
Switching from @modelcontextprotocol/server-memory imported nothing, and said nothing. That server writes beside its own module when MEMORY_FILE_PATH is unset, so anyone who ran it the documented way has their graph in a hashed directory inside npm’s _npx cache — never searched. An MCP server launched by a desktop client also inherits the client’s working directory, so the one fallback was weakest exactly where it was relied on. Both populations imported zero entities in silence, which reads as Titen losing their memories. The search now covers the working directory, node_modules/@modelcontextprotocol/server-memory/dist beneath it, and every such install in the _npx cache, under both memory.jsonl and the older memory.json.
Fixed
memory://knowledge-graph is served. resources/list returned -32601, so a client reading the graph as an MCP resource broke on the switch however well the nine tool names matched. initialize declares resources with subscribe: false: readable, no change notifications.
Fixed
Every authenticated request paid a durable write to record that it had read. Measured on WAL with synchronous = FULL: fifty no-op CASE updates grow the WAL by 0 bytes, fifty real ones by 206,032 — one page and one fsync each, one billed write on D1. 25 of 27 GET routes paid it. Now bounded to one write per key per minute, still monotonic.
Fixed
An imported credential colliding with another organization told the operator to retry forever — advice that can never succeed, because the collision is with another organization’s row rather than a concurrent write.
Changed
score is comparable across queries (#227). Relevance was rescaled against the candidate set, pinning the best candidate to exactly 1 however poor the match, so rank 1 returned one distinct value across all 500 benchmark questions and threshold-based abstention was arithmetically impossible. It is now strength / (strength + 3.7) where strength is the bm25 magnitude per query term; rank 1 now returns 498 distinct values spanning 0.4875–0.6632. Pre-registered before any cell was scored: anchor recall@1 0.8800 → 0.8800, pooled 0.2460 → 0.2460, sign tests W0/L0/T500 at p = 1.0, compile p95 +1.21% / +0.67%.
Changed
That safety gate could not have failed, and the report says so. Both benchmark stores were ingested in one pass, so all five non-relevance components are constant across 89,467 packed items — with those constant the ordering is identical by arithmetic, making the unchanged recall a derivation rather than a finding. Where they vary the behaviour does change: at bm25 −60 against −45 the relevance gap compresses 0.250 → 0.018 and the order flips to the verified claim over the marginally better-matching asserted one. Intended, pinned by contract, and bounded — a genuinely weak match still loses to a strong one however trusted.
Changed
Two limits, stated rather than left to be discovered. 3.7 is calibrated on LongMemEval-S and BM25 is not portable across corpora, so the absolute band shifts with the corpus while the ordering does not. The vector arm’s half of the change is unmeasured: both benchmark lanes ran with vectors disabled.
Removed
Five exports that shipped in the tarball with no caller anywhere in the source, tests, scripts or dashboard: ftsQuery, canReadRecord, recordEvent, param, FEEDBACK_ENDPOINT.
Upgrade
No API change and no migration. Anyone on 0.7.2 who switched from @modelcontextprotocol/server-memory and saw an empty store should restart titen mcp: the import runs on a store that has not yet imported, and it now looks where that server actually writes.
Upgrade
@types/node and @types/bun were never installed, so tsc could not resolve process, Bun, or any node:/bun: import — 791 reported errors, none of them bugs. src/ is now clean under tsc --noEmit with no any, @ts-ignore, or new cast added.
v0.7.2patch

An urgent fix: 0.7.1 cannot serve a large single-subject store. Upgrade from 0.7.1 without delay; 0.7.0 is unaffected.

Fixed

titen-memory@0.7.1 cannot serve a large single-subject store: one context compile takes a median 74.5 seconds where 0.7.0 takes under half a second. The 0.7.1 fix for #291 wrote the disputed predicate as a join inside EXISTS while its own comment claimed the nested form, and a join inside EXISTS is still a join the planner may reorder. SQLite 3.53.0 — the version Bun 1.3.14 links — reorders it to SEARCH o USING INDEX observations_workspace_scope (org_id=?), scanning every observation in the organization once per candidate row: the exact shape src/core/authorization.ts documents as the historical 79-second failure, shipped in the release that believed it had prevented it.

Who is affected: anyone whose store holds many claims under one subject and who compiles with a large max_candidates. The cost is the product of candidates and organization-wide observations, so small and per-subject stores are unaffected — which is why no test and no published benchmark caught it. Every published pooled quality figure was measured on 0.7.0; every published pooled or scoped-anchor latency figure was measured on 0.7.0 or on this release, never on 0.7.1.

Measured, 342,129-claim / 19,829-observation store, one subject, real statement, EXPLAIN captured from bun:sqlite rather than a pasted copy:

candidate query served compile
0.7.1 as published 73,439 ms 74,474 ms
this release 232 ms 417 ms p50 / 864 ms p95

This restores 0.7.0’s behaviour; it does not make compile fast. 864 ms p95 still fails the pre-registered 250 ms gate, so the 2026-08-07 latency falsifier stands — the pre-registration predicted exactly that outcome in writing before the run.

The ranked output is byte-identical to the published 0.7.0 pooled run — equal sha256 over all 500 instances — so this restores the shipped answer rather than changing it. Full method and both plans in the report, protocol pre-registered before the A/B.

Added
Plan-shape guards for the retrieval queries (tests/integration/query-plan.test.ts). The regression above was invisible to every existing test because contract stores hold tens of rows and still return the right answer quickly. The load-bearing discovery is that the bad plan reproduces on an empty store — SQLite picks the join order from the schema, not from row counts — so a cheap deterministic test could have caught this and the 2026-08-07 occurrence before either shipped. The guards assert the plan of the candidate query, the by-id hydration, and authorized-source loading; reverting the fix fails two of the three. They assert the plan, never a duration: a timing assertion on this hardware would be flaky, and the plan is what regressed.
v0.7.1patch

⚠️ Superseded — do not install. Replaced by 0.7.2. On a store with many claims under one subject, titen-memory@0.7.1 takes a median 74.5 seconds to compile one context, where 0.7.0 and 0.7.2 take under half a second. Cause and measurement are in the 0.7.2 notes.

Added
The pooled-store measurement: quality, latency, and build cost at production store shape. All 19,829 distinct LongMemEval-S sessions in one single-subject store, all 500 questions against it, at four store sizes — the condition every published number in this field (ours included) avoids by giving each question its own ~50-session haystack. Pre-registered with five falsifiers before the first scored run (prereg, report). The system under test is the published npm tarball, not a checkout.
Added
The 2026-08-07 agent-memory landscape survey, superseding 2026-08-04 on the fame roster and correcting two of its claims, and the performance-axis answer recording which competitive axes were adversarially killed and why.
Changed

A ranking dead heat now breaks on authorized evidence depth before the arbitrary statement fallback (#288). Order changes only where weighted score and vector similarity are both exactly tied; measured byte-identical on all 500 LongMemEval-S instances, and published as capturing 0.0 of the reranking ceiling on that corpus (report).

Changed

The disputed signal now resolves through the caller’s own authorization, so a contradicting observation the caller may not read no longer marks the claim (#291). The flag was computed from a bare EXISTS over claim_sources with no join to observations, while the citations beside it were filtered correctly. A principal who could not read the contradicting source still saw the claim demoted by the 0.05 conflict term and still received a conflicts[] entry whose evidence_ids omitted the source that caused it — told a contradiction existed and told they could not see it. Fixed at all four query sites: POST /v1/context/compile (lexical and vector candidates), GET /v1/context/:id, and the Memory Atlas conflict_freshness lens. The governance review queue was already correct and now shares the same predicate.

Visible consequence: in a store that already holds a cross-scope contradiction, claims that were demoted for callers who cannot read the contradicting source stop being demoted. Their score rises by up to 0.05, their score_components.conflict reads 1 instead of 0, they leave conflicts[], and the resulting order can change. Nothing changes for a caller who can read the source, and nothing changes for a claim whose own status is disputed — that is the claim’s own field, not an inference about hidden evidence. There is no migration and no flag: the previous numbers were the leak.

Response shapes, routes, and field names are unchanged, so this is a patch under the table in release.md — the minor slot signals shape breakage, and only values that were disclosing hidden rows move here.

Fixed
The Memory Atlas review queue no longer scans every observation in the organization to decide has_contradiction. It expressed the predicate as claim_sources JOIN observations, and SQLite drove from observations, evaluating the membership and retention subqueries for all of them once per candidate. On a 424,168-claim store that is 79 s per compile against 17.8 ms. The shared predicate added above uses a nested EXISTS so claim_sources seeks its own primary key, and the review queue now uses it. Found by benchmarking the change above; the dual-runtime contract suite passed on both query shapes, because its stores hold tens of rows.
Evidence
docs/testing/2026-08-07-disputed-authorization.md — n=500, ranked output byte-identical before and after (0/0/500, p = 1.0), compile latency flat within repeat spread. It also states what it cannot show: the corpus holds zero contradicting sources, so it cannot measure the fix where the fix fires.
v0.7.0minorBREAKING

titen-memory 0.7.0

Changed
Breaking: source.ref is now required on every observation write. A caller that omitted it received 201; it now receives 400 VALIDATION_ERROR. The MCP tool spec already stated the obligation, so MCP callers are unaffected; direct HTTP callers must add a pointer back to where the content came from. Migration: add "ref" to the source object on POST /v1/observations — any stable identifier for the origin (a commit sha, a ticket id, a URL, a tool invocation id). There is no compatibility flag: an entry that cannot be traced to an origin cannot be told apart from junk, which is the whole point of the audit work below. Part of #280.
Added
Zero-config local mode. npx titen-memory mcp with no environment opens or creates ~/.titen/memory.db, provisions an organization, workspace, project and owner as real rows, and serves MCP over stdio in-process — no HTTP hop, no key to paste, no outbound call, FTS-only. The served mode and its auth path are unchanged; this is an additional entry point, not a relaxation. Closes #278.
Added
Drop-in compatibility with @modelcontextprotocol/server-memory. The nine reference-server tool names are served alongside the native ones, search_nodes is routed through Titen retrieval rather than a substring scan, and an existing memory.json is imported on first run. The switching cost is one line of MCP config. Closes #279.
Added
recalled provenance is server-issued. POST /v1/context/compile returns a signed context token; an observation written while carrying it is stamped source.type: "recalled" by the server, and a caller that merely declares recalled is refused. Stateless HMAC, so no new table and no migration. Known ceiling, stated in the code: the stamp proves the write was made while holding a Titen-issued pack, not that its content came from that pack, so it is a sound lower bound on the recall loop and never an upper one. Closes #280.
Added
titen audit. Reports exact-duplicate, near-duplicate, recall-loop, secret-pattern and stale rates over a memory.json, a Mem0 export, or a Titen store. No network, no LLM, no upload, no composite score, no leaderboard. Its first published run is against Titen’s own store and opens by naming two defects in this product. Closes #281.
Added
Concurrent-writer durability suite on both runtimes, with the invariants published before the run and each re-run with its primitive removed to prove the suite can fail. Closes #282.
Evidence
docs/testing/2026-08-07-titen-audit-self-report.md — 17.9% byte-identical duplicates six seconds after write, 96.7% never read back, and the compatibility surface turning one entity into six. It also names the number it cannot report: there is no 32-day Titen store, so nothing in it bounds long-run accumulation.
Evidence
docs/testing/2026-08-07-durability.md — invariants held on both runtimes under concurrent writers.
v0.6.1patch

Webhooks no longer silently drop events written in their own registration millisecond. Eligibility compared w.created_at < e.created_at, a strict comparison on a millisecond wall-clock string, so on a fast host the registration and the next write shared a millisecond and those events were never queued, never delivered, and never retried. Delivery now pages on the event_order.seq watermark that /v1/events and federation already use: migration 22 adds webhooks.created_seq, backfilled to the current head so an upgrade delivers only future events rather than replaying history. Both eligibility sites are converted — processWebhooks and the background deliverPending selector — because the second one would otherwise leave an organization unwoken until another event arrived. Measured on a 16-core host: the contract file went from 8 of 12 runs failing to 12 of 12 passing. Closes #265.

Fixed

Webhooks no longer silently drop events written in their own registration millisecond. Eligibility compared w.created_at < e.created_at, a strict comparison on a millisecond wall-clock string, so on a fast host the registration and the next write shared a millisecond and those events were never queued, never delivered, and never retried. Delivery now pages on the event_order.seq watermark that /v1/events and federation already use: migration 22 adds webhooks.created_seq, backfilled to the current head so an upgrade delivers only future events rather than replaying history. Both eligibility sites are converted — processWebhooks and the background deliverPending selector — because the second one would otherwise leave an organization unwoken until another event arrived. Measured on a 16-core host: the contract file went from 8 of 12 runs failing to 12 of 12 passing. Closes #265.

Fixed

Retrieval ranking is now reproducible in the FTS-only lane. Exactly-tied scores previously fell through to claim_id, a fresh uuid per ingest, so the same corpus ranked differently on every run. Ties now break on the claim statement — content-derived, and compared by code unit so Bun and Workers agree — before falling back to the id. This makes rank reproducible, not better: it picks an arbitrary-but-stable winner among genuine ties. What causes the ties is untouched and stays open as #227. Closes #226.

Fixed

Upgrading a pre-0.2.0 store now refuses instead of succeeding into silence. Migration 10 scopes team visibility to a workspace and nothing backfills the column, so a 0.1.x store migrated cleanly and then answered 404 on every claim. migrate now counts legacy team rows first and fails closed, naming the count and the 0.2.0 data floor. Rebinding is deliberately not attempted: a legacy row’s real workspace is unknowable, and inventing one would invent an authorization boundary. Closes #257.

Fixed

The logical export refuses a pre-workspace team row rather than writing a backup its own importer rejects. export_import is advertised as enabled, so an artifact that cannot be restored is worse than an error. Closes #258.

Measured, not built
The reranking stage recorded as strategic debt was measured before being written, and the measurement says do not write it. The oracle ceiling over Titen’s own top-10 is +10.2 points (recall@1 0.880 to 0.982), but every cheap reranking signal tested captured at most 0.6 of those points at p=0.61, and two were significantly worse than no reranking at all. MemPalace, which ships one, scored lower with it than without it in both embedding configurations. The gain is real and lexical signals cannot reach it. Closes #269.
Added
In-process mode for Bun hosts. serve() returns the handler it serves, and a titen-memory/bun subpath exports it, so a benchmark or embedding host can drive TitenClient through an injected fetch with no loopback hop. The transport is removed; auth, scopes, and response envelopes are unchanged because it is the same handler. An ephemeral socket is still bound and unused, tracked in PONYTAIL-DEBT.md. Closes #230.
Docs

Measured the memory-agent field on an externally authored corpus (LongMemEval-S, MIT) and recorded where Titen actually stands: landscape note. docs/testing/EVALS.md now marks recall@5/@10 as saturated on that corpus so only recall@1 and MRR@10 are quoted as discriminating, and blueprint.md no longer plans a LoCoMo run — LoCoMo is CC BY-NC 4.0 and a launch is commercial use, which an SPDX check misses because GitHub reports it as NOASSERTION. Closes #267, #270, #271.

Docs

The single-core throughput ceiling is published as an operator sizing rule in VPS deployment and deploy/README.md: at and above 10,000 claims one client saturates one process, so shard by subject across processes rather than adding clients. Cloudflare records that this is a bun:sqlite property that does not transfer to per-request isolates. Closes #259.

Docs

docs/testing/EVALS.md carries the FTS-only degradation curve, so no FTS-only quality figure is quoted without the corpus size it was measured at. Closes #260.

Docs

The cross_language:en zero is explained rather than left open: the stratum rotates document language past query language, so it is three language pairs, and English queries never retrieve a non-English document (2,000 of 2,000 top-10 hits). A provider embedding property, not a fixture defect. The fixture is unchanged because its hashes pin the locked holdout and pre-hoc threshold. Closes #245.

Docs

docs/engineering/release.md states why the tarball carries no provenance attestation — it requires a supported CI’s OIDC token and this repository publishes by hand on purpose — and gives consumers the registry checks that do work, with what they do not prove. Closes #242.

Docs

One product sentence across the GitHub description, README, and package.json. Closes #225.

v0.6.0minorBREAKING

Stable channel · npm latest · pre-1.0, the public API is not yet stable

Measured against self-hosted Mem0: parity, not superiority
Mr.TyDi Indonesian, 25 queries over 100 documents, 10 repeats, one shared embedding endpoint, against mem0ai 2.0.13 in library mode.
Deleted rather than shipped
An adversarial review rejected the first retrieval change. Isolated at 10 repeats, the score-formula rewrite earned nothing the tie-break alone does not, regressed the FTS-only lane, and coupled the lexical/semantic balance to one provider’s cosine distribution through a fitted constant. It was removed; what shipped is four lines in the comparator. Issue #227 stays open and #226 is narrowed rather than closed, in the changelog and in the debt ledger.
Corrected in the record
Figures published earlier the same day for 0.5.7 — recall@1 0.680, MRR@10 0.807, query p50 170 ms — were the top of their ranges over five repeats, not medians. The true 0.5.7 median is 0.62. They should not be requoted.
Newly measured, and uncomfortable
The service uses one core at every concurrency level, so a single client saturates it at 10,000 claims, and retrieval quality falls with corpus size (recall@1 1.00 to 0.81 to 0.49 across 10³, 10⁴, 10⁵ on a synthetic corpus). Cold start stays around 53 ms and resident memory grows 2.9% across a hundredfold corpus. The data-usable upgrade floor is 0.2.0: a 0.1.x store migrates without error and then answers 404 on every claim.
Added
An optional top_k on context compile, a standard-library-only Python client, a container image, and the release-bound retrieval harness that the evaluation spec had been waiting for.
v0.5.7patch

Stable channel · npm latest · pre-1.0, the public API is not yet stable

Docs
The npm README now gives one ordered path from CLI install through bootstrap, agent-specific keys, service readiness, and verified MCP setup for Codex, Claude Code, OpenClaw, Hermes, and generic stdio clients.
Docs
The host guide separates direct Streamable HTTP from the bundled titen mcp bridge, keeps credentials in host environments, and includes a nine-tool connection check.
Fixed
Dashboard integration and browser gates no longer share hard-coded port ranges with unrelated development servers.
v0.5.6patch

Stable channel · npm latest · pre-1.0, the public API is not yet stable

Added
titen mcp bridges newline-delimited stdio MCP clients to an existing authenticated Titen /mcp endpoint, so hosts without native remote MCP can use the same nine tools without another memory implementation.
Changed
MCP initialization now tells compatible hosts to resolve the repository and compile authorized memory once at each task or scope boundary while keeping durable writes explicit and typed.
Security
The stdio bridge accepts its endpoint and revocable key only through the inherited environment, rejects credential-bearing or ambiguous URLs, emits no notification reply, and sanitizes upstream failures without exposing the key.
v0.5.5patch

Stable channel · npm latest · pre-1.0, the public API is not yet stable

Upgrade
The canonical schema advances from 20 to 21. Take a verified backup and run titen migrate --dry-run before starting 0.5.5. The migration is additive; rollback restores the backup with the 0.5.4 binary.
Upgrade
Dashboard replicas that must preserve sessions across restarts share one base64url-encoded 32-byte TITEN_DASHBOARD_SESSION_KEY. Without it, each process uses an ephemeral key and restart signs everyone out.
Added
Context compilation accepts an explicit historical at instant and a bounded max_candidates value through REST, MCP, and the TypeScript SDK.
Added
Stable source IDs and canonical claim hashes converge exact re-ingestion after the request idempotency window while changed evidence remains append-only.
Added
POST /v1/index/verify checks a bounded set of active claims against Vectorize or sqlite-vec and queues repairs without reading embedding values.
Added
The publishable OpenClaw bundle now includes remote Streamable HTTP MCP, and the Cursor package includes the metadata and documentation expected by its public plugin repository.
Changed
Dashboard login state is an authenticated AES-GCM HttpOnly cookie instead of process-local memory, so a shared key supports replicas without a session database.
Changed
Confirmed semantic statement hashes avoid duplicate embedding calls; explicit reconciliation still forces a provider repair when an index record is absent.
Changed
Context budget units now use deterministic UTF-8 bytes across runtimes, and Vectorize queries retain the native 100-result ceiling.
Changed
The README now leads with Titen’s Level 6 collaboration model and distinguishes evidence-grounded context from storage-only and similarity-only memory.
Security
Public Cloudflare login failures consume the canonical account throttle and a native Rate Limiting binding. The key contains no password or client IP.
Security
Password changes reject common and account-context values before a verifier is stored, while retaining the 15-character minimum and forced first change.
Security
Sealed dashboard sessions reject forged, expired, or undecipherable cookies; raw short-lived API credentials remain outside browser storage.
v0.5.4patch

Stable channel · npm latest · pre-1.0, the public API is not yet stable

Added
A checked-in titen-test-* Wrangler profile provisions the isolated live Worker, D1, Vectorize, Workers AI, and Cron contract without storing an account API token in the Worker.
Changed
Cloudflare schema readiness verifies the complete migration contract in one D1 read instead of issuing one remote read per required object and column.
Changed
New dashboard passwords use six serial PBKDF2-HMAC-SHA-256 stages of 100,000 iterations each, preserving the 600,000-operation work factor within the Workers Web Crypto per-call limit. Bun retains legacy verifier compatibility.
Changed
The live semantic verifier uses an explicit bounded index drain; Cron remains a separately observed production reconciler instead of a timing dependency.
Fixed
The dashboard login username example is now the canonical bootstrap account owner, not a maintainer-specific placeholder.
Fixed
The Cloudflare runbook provisions the three Vectorize metadata indexes needed for scope-before-search filtering before the first vector upsert.
Security
Live unauthenticated and cross-organization probes fail with non-disclosing 401/404, while native D1, Vectorize, and Workers AI bindings require no account credential inside the deployed Worker.
v0.5.3patch

Stable channel · npm latest · pre-1.0, the public API is not yet stable

Added
Bootstrap creates default username owner with a random temporary password; human operators sign in with username/password, and authorized owners/admins can atomically add another account, membership, role, and one-time password. API keys remain unchanged for agents, services, SDKs, CLI recovery, and existing integrations.
Changed
Schema 20 adds canonical operator accounts. Temporary-password login is restricted to password replacement; established login issues an eight-hour revocable API credential only to the server-side adapter.
Fixed
The per-principal sign-in state now uses a focused responsive login surface; the private product sidebar and operator topbar appear only after a valid session instead of framing the unauthenticated form.
Security
Password verifiers use unique salts and PBKDF2-HMAC-SHA-256 with 600,000 iterations on both D1 and Bun/SQLite. Login failures are non-disclosing and locally throttled; password change and logout revoke short-lived dashboard credentials.
v0.5.2patch

Stable channel · npm latest · pre-1.0, the public API is not yet stable

Added
The operator dashboard now wires Memories, Context, Work, Audit, Governance, and Federation to fixed authenticated API routes, with capability-gated navigation and no fixture fallback.
Added
Per-principal dashboard login exchanges an API key for an opaque HttpOnly session, and authorized owners/admins can atomically create one human membership plus its one-time API key.
Added
The deployment guide now covers private Tailscale Serve and Cloudflare Tunnel protected by Cloudflare Access while both Titen listeners remain loopback-only.
Changed
The public SDK now types all six Memory Atlas lenses and the optional Add User fields on key creation.
Security
Dashboard routes enforce exact Host/Origin, bounded bodies and list results, credential isolation, revocation, expiry, logout/restart invalidation, and server-side authorization independent of browser navigation.
v0.5.1patch

Patch release for the live dashboard shipped in 0.5.0.

Fixed
Render the bundled Titen mark by permitting only its data URI alongside same-origin images; remote image sources remain blocked.
v0.4.1patch

Stable channel · npm latest · pre-1.0, the public API is not yet stable

Added
titen version --check explicitly reads the stable CLI/plugin release manifest from titen.dev and points users to the manual install guide without background polling or remote command execution.
Fixed
MCP initialization now reports the package SemVer as serverInfo.version instead of mislabeling a deployment revision such as dev, test, or a Git SHA as the server implementation version.
Fixed
Published SDK declarations now stay inside the package and exactly type claim inputs, readiness diagnostics/capabilities, key lifecycle fields, and a bounded event iterator that terminates on preserved cursors.
Fixed
Extraction now supports explicit strict-schema, JSON-object, and custom modes, rejects redirects and incomplete provider finishes, and uses the same model proposal validator as the locked release gate.
Fixed
Cloudflare liveness no longer waits on D1 preparation, Vectorize queries stay within the platform’s topK limit, and the documented Wrangler recovery command uses a real temporary SQL file.
Fixed
Bun allows the documented extraction timeout and releases every semantic lease acquired before or during bounded SIGTERM shutdown, so a restart can recover work immediately.
Fixed
Context packing preserves rank when every item fits, applies diversity only under budget pressure, and no longer awards disputed claims a positive score.
Fixed
Live semantic verification carries project scope, while historical comparison tooling refuses to present a current deployment as the frozen 0.3.0 target.
Security
D1 diagnostic redaction now covers secrets split across streamed byte and text chunks, and Bun creates the canonical SQLite database plus sidecars with owner-only permissions.
Security
API keys now enforce immutable not-before and expiry windows, update last_used_at monotonically, preserve lifecycle metadata across supported operator surfaces, reject unknown creation fields, and cannot gain authority through credential import.
v0.4.0minorBREAKING

titen-memory 0.4.0

Fixed
Global CLI installs now run directly on Bun and report titen --version instead of requiring a Node shim.
Fixed
Successful SDK responses now reject array, null, and primitive JSON envelopes with an INVALID_RESPONSE TitenError while preserving the HTTP status, request ID, and safe response metadata.
Fixed
Bun HTTP, Cloudflare Workers AI, and injected embedding-provider results now require exact output cardinality, ordered provider indices when present, dense configured dimensions, and finite numeric coordinates before vector query or indexing.
Fixed
Semantic readiness now distinguishes intentional FTS-only operation from partial configuration, unavailable vector initialization, legacy untracked vectors, missing requeue work, unsafe storage aliasing, empty restored projections, incompatible fingerprints, and locally observed indexing dependency failures; configured failures return a fixed local diagnostic without probing providers.
Fixed
Semantic retrieval now discards sub-threshold cosine hits before canonical hydration, so relative ranking cannot turn a best bad neighbor into useful context. Bun and Cloudflare share the same validated unit-vector boundary.
Fixed
Manual and background semantic-index drains now fence each outbox row before provider I/O, so an expired losing attempt cannot add stale failure evidence after another attempt completes the row. Lease eligibility and expiry now use the database clock at each conditional claim, so caller clock skew and earlier work cannot create an expired or stranded owner.
Fixed
Semantic-index upserts and removals now persist canonical reconciliation before external mutation and recreate it after stale or apply-then-throw outcomes, so a losing owner cannot resurrect a purged vector, erase a newer projection, or report unowned work as complete.
Changed
Capability contract version 1 reports embedding, extraction, and background enrichment separately while retaining model as a deprecated 0.3.x embedding alias. Migration 13 persists the claim-index provider, model, revision, dimensions, metric, preprocessing, and schema fingerprint and requires an explicit reindex after incompatibility. Migration 14 retains only safe embedder/vector-store failure timestamps in semantic metadata until a later complete embed/upsert proves recovery.
Changed
sqlite-vec@0.1.9 is a pinned optional peer: default installs remain dependency-light while the documented vector install is machine-verifiable.
Changed
Context compilation now treats a missing project_id as unscoped-only; explicit cross-project recall requires cross_project: true plus the separate context:compile:all capability and reports its effective scope and grant reason across REST, SDK, and MCP.
Changed
Breaking: Semantic configuration now requires an immutable model revision, a named role-aware preprocessing profile, and an operator-calibrated cosine floor in the existing index fingerprint. EmbeddingGemma uses its official asymmetric query/document prompts; Titen ships no universal threshold.
Changed
Migration 16 adds nullable owner and expiry fields to the rebuildable semantic index outbox; canonical observations and claims are unchanged.

Canonical source

These entries are generated from the versioned release pages. Full source history remains available in CHANGELOG.md.