Skip to content

Commit 41558ce

Browse files
committed
chore(release): 0.2.0
1 parent 7403447 commit 41558ce

2 files changed

Lines changed: 35 additions & 204 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 34 additions & 203 deletions
Original file line numberDiff line numberDiff line change
@@ -5,217 +5,48 @@ All notable changes to `@corbits/memory` are documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## [Unreleased]
8+
## [0.2.0] — 2026-09-25
99

1010
### Changed
1111

12-
- `@intx/*`, `drizzle-orm`, `hono`, `hono-openapi` and `postgres` are peer
13-
dependencies; the host supplies them. `engines` is removed.
12+
- **Breaking:** `@intx/*`, `drizzle-orm`, `hono`, `hono-openapi` and
13+
`postgres` are peer dependencies; the host supplies them. `engines` is
14+
removed.
15+
- **Breaking:** `createMemoryRoutes({ memory, requireGrant, callerResolver? })`
16+
returns the memory routes as a `Hono<TenantEnv>` sub-app with paths relative
17+
to its mount point; hosts mount it at `/api/tenants/:tenantId/memory`. It
18+
replaces `createMemory({ app, callerResolver })` and `registerMemoryRoutes`,
19+
and `RouteDeps` no longer carries `grants`. `createMemory` only builds the
20+
plane.
21+
- **Breaking:** the package root exports only the public API. Internal
22+
services and helpers (transform, retention, feed, share materialization,
23+
corroboration, embed model registry, degrade metrics, FTS helpers), the test
24+
fakes, and `resolveGrantConfig` are no longer exported. The distiller stays
25+
at `@corbits/memory/distiller` and migrations at
26+
`@corbits/memory/migrations`.
27+
- **Breaking:** `runMemoryMigrations(config, { schema, ftsLanguage })` takes
28+
the same `DBConfig` as Interchange `runMigrations` instead of a database
29+
URL. `schema` names the host schema holding Interchange's `tenant` and
30+
`principal` tables (the value passed to `runMigrations`, e.g. `"public"`);
31+
memory's tables stay in the `memory` schema. `ftsLanguage` is required, and
32+
the runner no longer reads `FTS_LANGUAGE` from the environment or accepts a
33+
`log` option.
34+
- Every migration file is idempotent and replayed on each run, with a 5 s
35+
`lock_timeout`. The `memory._migrations` ledger is dropped.
1436
- `MEMORY_GRANT_REQUIREMENTS` is read from `package.json`
1537
`interchange.grantRequirements`, now the only declaration.
1638
`MEMORY_CAPABILITY_IDS` is typed `string[]`.
17-
- `createMemoryRoutes({ memory, requireGrant, callerResolver? })` returns the
18-
memory routes as a `Hono<TenantEnv>` sub-app with paths relative to its
19-
mount point; hosts mount it at `/api/tenants/:tenantId/memory`. It replaces
20-
`createMemory({ app })` and `registerMemoryRoutes`, and `RouteDeps` no
21-
longer carries `grants`. `createMemory` only builds the plane.
22-
- The package root exports only the public API. Internal services and
23-
helpers (transform, retention, feed, share materialization, corroboration,
24-
embed model registry, degrade metrics, FTS helpers), the test fakes, and
25-
`resolveGrantConfig` are no longer exported. The distiller stays at
26-
`@corbits/memory/distiller` and migrations at `@corbits/memory/migrations`.
27-
- `runMemoryMigrations(config, { schema, ftsLanguage })` takes the same
28-
`DBConfig` as Interchange `runMigrations` instead of a database URL.
29-
`schema` names the host schema holding Interchange's `tenant` and
30-
`principal` tables (the value passed to `runMigrations`, e.g. `"public"`);
31-
memory's tables stay in the `memory` schema. `ftsLanguage` is required, and
32-
the runner no longer reads `FTS_LANGUAGE` from the environment or accepts a `log` option.
33-
Every migration file is idempotent and replayed on each run. The
34-
`memory._migrations` ledger is dropped.
35-
36-
### Added
37-
38-
- Retention HTTP routes (CL-6288): `POST …/memory/documents/:documentId/forget`
39-
(tombstone, grant `memory:forget`), `POST …/memory/documents/:documentId/purge`
40-
(hard delete, grant `memory:purge`), and
41-
`POST …/memory/versions/:versionId/retention-class` (grant `memory:forget`).
42-
Forget and purge are separate routes with separate grant actions — never one
43-
route with a boolean flag — and both are refused with 403 unless the caller
44-
is the document/version's creator, independent of any share grant that lets
45-
them merely see it. `sweepEphemeral` stays off the HTTP surface (maintenance
46-
sweep, not a user action); a host schedules it on its own cron against the
47-
in-process `Memory`. New `memory:forget` / `memory:purge` grant requirements
48-
(`source: "creator"`) and `capabilityIdsForSurface()` so distiller/tools
49-
installs no longer pick up routes-only capabilities by accident.
50-
- `RouteDeps.callerResolver` — an
51-
optional host-supplied resolver from a request to a `{ tenantId,
52-
principalId }` scope, for a caller that never goes through the host's
53-
tenant-session middleware (e.g. a workflow-run child authenticating with
54-
its own sidecar bearer token). Unset by default: every route still reads
55-
identity from `c.get("principal")` exactly as before. When set, the
56-
resolved identity is seated as the request's principal/tenant ahead of
57-
`grantGuard`, so the same `requireGrant` authorization path applies to a
58-
machine caller — never a separate, weaker one. Identity from the resolver
59-
always wins over anything a request body claims. The resolver's return
60-
value is parsed with arktype (non-empty `tenantId`/`principalId`); a
61-
resolver returning a malformed identity is rejected with `500` (a host
62-
bug), never seated as a garbage scope.
63-
64-
### Fixed
65-
66-
- `loadMemoryConfig` / `EngineConfig.embed` no longer requires an embed
67-
endpoint: a host with a pgvector Postgres and no embed endpoint now
68-
constructs and serves `add` + lexical `search`. Dense retrieval is skipped
69-
(not attempted-and-failed) and `search` reports
70-
`degraded: ["dense_unavailable", "lexical_only"]` so the state stays
71-
observable (CL-6287). **Migration note:** `dense_unavailable` is now also
72-
emitted on every search for a deliberately-unconfigured engine, not only on
73-
a transient dense-retrieval failure — a host with an existing alert rule
74-
keyed on `dense_unavailable` alone should also check for `lexical_only` in
75-
the same `degraded` array to distinguish "opted into lexical-only" from an
76-
actual regression.
77-
- `add`'s `degraded` is now a reason array (`["embed_unavailable"]` and/or
78-
`["embed_unavailable", "lexical_only"]`), matching `search`'s shape —
79-
previously a bare boolean, which made it impossible to write one
80-
"is this response degraded" check across both verbs (CL-6287). **Breaking
81-
if a host coded against the boolean:** `degraded: true` is now
82-
`degraded: [...]`; check array presence/length instead of truthiness (both
83-
are still falsy/omitted when the document captured cleanly).
84-
- `Memory.capabilities.embeddingsConfigured` (and the underlying
85-
`DocumentStore.capabilities`) let a host learn recall is lexical-only at
86-
construction time, without issuing a search first (CL-6287).
87-
- Feed `nextCursor` advances past the examined raw page after grant-tag
88-
post-filter (a fully denied page no longer stalls the consumer forever).
89-
- Distiller default system prompt uses the configured `agentId` for
90-
`exclude_generator` / `generator_agent_id` (not only the package default id).
91-
92-
### Changed
93-
94-
- **Breaking:** `createResidentDistiller` runs on a `mail` trigger (CL-8798).
95-
`CreateResidentDistillerOpts.cron` is replaced by a required `mailTo`, the
96-
address the workflow's run is triggered at, and
97-
`RESIDENT_DISTILLER_CRON_DEFAULT` is removed. The `schedule` trigger was
98-
reserved with nothing behind it in `@intx/workflow`, so the distiller never
99-
ticked, and 0.4.0 rejects it at `defineWorkflow`. Ticking is the host's job:
100-
mail `mailTo` on a schedule, e.g. from `@corbits/cron`.
101-
- `@intx/*` dependencies move to 0.4.0 (CL-8797).
102-
- **Product narrative:** default path is **add → ingest elements → process**
103-
(one host pipeline). Pull feed + `createResidentDistiller` are optional
104-
multi-writer / backfill process helpers, not the primary ingest story.
105-
See `PRODUCT.md`, `docs/DISTILLER.md`, `docs/FEED.md`.
106-
- **Breaking:** Postgres schema renamed from `knowledge` to **`memory`**. Fresh
107-
installs only — drop/recreate the old schema (or rename) on existing DBs.
108-
Citation `open.type` is now `"memory"`.
109-
- **Breaking:** env var is `DATABASE_URL` (was `KNOWLEDGE_DATABASE_URL`); pass
110-
`memory.databaseUrl` on config as an alternative. No deprecated alias.
111-
- `add` (plane + HTTP) returns `{ documentId, versionId }` so share-grant audit
112-
and provenance can name the version that carried the write.
113-
- Interchange `defineTool` factories at `@corbits/memory/tools` (`memory_add`,
114-
`memory_search`, `memory_list`) — HTTP clients for mounted hub routes with
115-
install env `memoryBaseUrl` / `memoryTenantId` / `memoryAuthToken`. Declared
116-
via `package.json` `interchange.tools` and `exports["./tools"]`.
117-
118-
### Previously
119-
120-
- **Breaking:** package and public surface renamed from `@corbits/knowledge-engine`
121-
to `@corbits/memory`. Public APIs: `createMemory` (optional `app` registers HTTP),
122-
`registerMemoryRoutes`.
123-
124-
`createMemory`, `loadMemoryConfig`, `runMemoryMigrations`, `Memory`,
125-
`MemoryConfig`, `MemoryError`. HTTP paths are under
126-
`/api/tenants/:tenantId/memory/`; grants are
127-
`memory:add` / `memory:search`; access tags use `memory.owner:` / `memory.tenant:`
128-
/ `memory.space:`. Postgres schema is `memory`.
129-
- **Breaking:** config reads `DATABASE_URL` (was `KNOWLEDGE_DATABASE_URL`) for
130-
the engine's own pgvector Postgres connection.
131-
- **Breaking:** memory plane surface is `add` / `search` / `list` with
132-
`principalId` + `tenantId` only. Inference is host-owned (no answer endpoint
133-
or personal-memory side-channel on the plane).
134-
135-
- **Breaking:** HTTP routes are `POST /api/tenants/:tenantId/memory/add`,
136-
`POST /api/tenants/:tenantId/memory/search`,
137-
`GET /api/tenants/:tenantId/memory/list` (inherits hub `resolveTenant`).
138-
Old unscoped `/api/memory/*` paths are not mounted.
139-
- **Breaking:** grant actions are `add` and `search` (was `capture` / `find` /
140-
knowledge `search`). `list` uses the `search` grant. Capability resource is
141-
`memory`. Document-tag checks use action `search`.
142-
- **Breaking:** `add` returns `{ documentId }`; search body uses `limit` (not `k`);
143-
search wire uses `items` (not `hits`).
144-
- **Breaking:** document access is Interchange **grant tags** (`accessTags` +
145-
creator-always + host `GrantStore`), not the visibility-mode / block-list
146-
mini-ACL. Share sugar only mints tags. See `docs/AUTHZ-DOCUMENT-ACCESS.md`.
147-
- **Breaking:** Postgres baseline is two files (`0001_extensions` +
148-
`0002_memory_baseline`) with `access_tags` and no `visibility_*` columns.
149-
Fresh installs only — drop/recreate the `memory` schema on existing DBs.
150-
- **Breaking:** `grantStore` + `conditionRegistry` are top-level `createMemory`
151-
options (no nested `grants: { … }`).
152-
153-
### Added
154-
155-
- Optional `TextExtractor` + `file` XOR `content` on `add`
156-
- `share` sugar on `add` (maps to access tags; principals also materialize
157-
grants when the host grant store is writable); `grantsMaterialized` on the
158-
add result when peers were requested
159-
- `access_tags` on `memory.document` (baseline schema)
160-
- Claim-bearing schema, temporal model, transform/replay, share grants
161-
(resident memory distillation foundation — CL-5865/5866/5872/5873)
162-
- Living relevancy: corroboration factor from supports/contradicts edges;
163-
strong evidence gate (CL-5867). See `docs/RELEVANCY.md`
164-
- Capture feed: `memory.feed` + `GET .../memory/feed` with `feed_seq` cursor
165-
(CL-5868). See `docs/FEED.md`
166-
- **Wire attribution (CL-5870):** search hits carry additive `attribution`
167-
(versionId, provenance, source/temporal class, createdByKind,
168-
generatorAgentId, occurredAt/validUntil, corroboration counts, derivedFrom)
169-
- **Retention (CL-5871):** `retention_class` on versions; plane APIs
170-
`deprecateVersion` / `tombstoneDocument` / `hardDeleteDocument` /
171-
`sweepEphemeral` / `setRetentionClass`; `includeDeprecated` on search.
172-
See `docs/RETENTION.md`
173-
- **Resident distiller (CL-5869):** `@corbits/memory/distiller` —
174-
`createResidentDistiller({ inference })` schedule workflow + `runDistillTick`
175-
+ `buildDistilledClaim`. Claim-aware `add` (generator_agent_id, provenance,
176-
derived_from, …). `memory_feed` tool. Feed entries include `accessTags`.
177-
See `docs/DISTILLER.md`
178-
179-
### Removed
180-
181-
- Host-injected generate path on the plane (use host inference + `add` / `search`)
182-
183-
## [0.1.2] — 2026-07-31
184-
185-
### Added
186-
- Public `createMemory` export for out-of-band capture and search (CLI seeders, batch ingesters, tests) without mounting HTTP routes (`#8`)
187-
188-
### Fixed
189-
190-
- Fail-closed document ACL: withhold hits whose `acl_block` is unreadable or non-string (`#9`)
191-
- Timeline titles use the same document ACL post-filter as search (`#12`)
192-
- Return 401 (not 500) when the host has not resolved a principal (`#7`)
193-
- ACL wiring tests mock `sql.unsafe` for FTS verification so the suite stays green under the search path
194-
195-
## [0.1.1] — 2026-07-31
196-
197-
### Added
198-
199-
- Halfvec expression indexes for embedding models above 2000 dimensions (up to 4000); dense search ORDER BY uses the same expression as the index (`#1`)
200-
- Configurable lexical FTS language (`FTS_LANGUAGE` / `EngineConfig.ftsLanguage`) with parse, catalog verify, and rebuild recipe; public `DEFAULT_FTS_LANGUAGE` export (`#4`)
201-
- Named chunk FK with `ON DELETE CASCADE` and composite tenant index on per-model embedding tables created at activation (`#3`)
202-
203-
### Changed
204-
205-
- Dense search scales `hnsw.ef_search` to the overfetch limit (floor 40) and probes `hnsw.iterative_scan = relaxed_order` once per process when available (`#2`)
206-
- Package install docs point at `@corbits/memory` (`#6`)
207-
208-
### Fixed
20939

210-
- Rerank document truncation to fit cross-encoder token limits (`#10`)
211-
- Degrade metrics: surface full rerank failure detail and count DegradeFlags so silent degradation is visible (`#11`)
40+
### Upgrading from 0.1.0
21241

213-
## [0.1.0] — 2026-07
42+
- Call the new `runMemoryMigrations` once; it upgrades a 0.1.0 database in
43+
place with no data loss.
44+
- After the upgrade, do not run 0.1.0 against the database: its ledger is
45+
gone, so there is no downgrade.
21446

215-
### Added
47+
## [0.1.0] — 2026-09-25
21648

217-
- Initial cut: mountable memory capture + search SDK for Interchange hubs
49+
First release on npm.
21850

219-
[0.1.2]: https://github.com/corbitsdev/corbits-memory/compare/v0.1.1...v0.1.2
220-
[0.1.1]: https://github.com/corbitsdev/corbits-memory/compare/v0.1.0...v0.1.1
221-
[0.1.0]: https://github.com/corbitsdev/corbits-memory/releases/tag/v0.1.0
51+
[0.2.0]: https://github.com/corbitsdev/corbits-memory/releases/tag/v0.2.0
52+
[0.1.0]: https://www.npmjs.com/package/@corbits/memory/v/0.1.0

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@corbits/memory",
3-
"version": "0.1.0",
3+
"version": "0.2.0",
44
"description": "Mountable memory add/search/list SDK for Interchange hubs — includes resident distiller",
55
"main": "./dist/index.js",
66
"types": "./dist/index.d.ts",

0 commit comments

Comments
 (0)