Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ jobs:
with:
bun-version: latest
- run: bun install --frozen-lockfile
- run: bun run lint
- run: bun run format:check
- run: bun run typecheck
- run: bun run test
- run: bun run test:e2e
Expand Down
4 changes: 4 additions & 0 deletions .oxfmtrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"printWidth": 80
}
6 changes: 6 additions & 0 deletions .oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"categories": {
"correctness": "error"
}
}
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ A library, not a service. `src/` is the whole product: a memory **add / search /
list** SDK that **mounts onto a host Interchange app**. There is no server,
port, or process entrypoint here, and there never should be.


## Commands

```bash
Expand Down Expand Up @@ -61,6 +60,7 @@ CI runs `typecheck` + `test` — both must pass before any push.
the host's own grant store / `callerResolver` closure, resolved down to
`{ tenantId, principalId }` before it ever reaches this package — not in a
wider `ResolvedCaller`.

2. **One Postgres**: `DATABASE_URL`, the engine's own vector plane, under the
`memory` schema — never the host's control-plane DB. No foreign keys into
control-plane tables; cross-refs (`tenant_id`, `principal_id`) are plain
Expand Down
8 changes: 4 additions & 4 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,16 @@ helpers are optional multi-writer / backfill — not the primary path.
- **Grants delegate to the host.** Pass `grantStore` + `conditionRegistry`;
routes use `createRequireGrant("memory", action)`.
- **Two authorization mechanisms, not one — know which is source of truth
for what.** (1) Grant tags decide *capability* (may this principal call
`add`/`search`/`forget`/`purge` at all — `requireGrant`) and *visibility*
for what.** (1) Grant tags decide _capability_ (may this principal call
`add`/`search`/`forget`/`purge` at all — `requireGrant`) and _visibility_
(which documents a principal may see — `accessTags` + `canAccessDocument`
in `grant-tags.ts`, where a share grant legitimately widens who can find a
document). (2) A separate, imperative **ownership** check — the creator
lookup in `services/retention-ownership.ts`, called from `memory.ts` —
decides who may *forget or purge* a specific document, and is the sole
decides who may _forget or purge_ a specific document, and is the sole
source of truth for "whose document is this": it is never derived from
grant tags and a share grant never satisfies it. `MemoryGrantRequirement.
installHint` (`grant-requirements.ts`) looks adjacent to this but is not:
installHint` (`grant-requirements.ts`) looks adjacent to this but is not:
it is advisory metadata for install tooling sizing a capability grant,
read by nothing at request time. Do not extend mechanism (1) expecting it
to cover ownership — extend `retention-ownership.ts` instead.
Expand Down
151 changes: 80 additions & 71 deletions IMPLEMENTATION.md

Large diffs are not rendered by default.

46 changes: 23 additions & 23 deletions PRODUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ package: they carry `@corbits/memory/sidecar-bundle` and hit the parallel
add → ingest elements → process (optional)
```

| Stage | Meaning | Where |
| --- | --- | --- |
| **add** | Something arrives (agent tool, host job, webhook body) | Caller → `memory.add` / `POST …/memory/add` |
| **ingest elements** | Normalize → raw capture → chunks / edges → embed → search-ready | Default `DocumentStore` capture path (sync on `add`) |
| **process** | Optional brain work: classify, claims, links, forget | Host workflow / injected inference — same run as ingest when possible |
| Stage | Meaning | Where |
| ------------------- | --------------------------------------------------------------- | --------------------------------------------------------------------- |
| **add** | Something arrives (agent tool, host job, webhook body) | Caller → `memory.add` / `POST …/memory/add` |
| **ingest elements** | Normalize → raw capture → chunks / edges → embed → search-ready | Default `DocumentStore` capture path (sync on `add`) |
| **process** | Optional brain work: classify, claims, links, forget | Host workflow / injected inference — same run as ingest when possible |

Preferred host shape: **one ingest workflow** receives the event, calls `add`
(ingest elements), then runs process steps in the same body (or a child step).
Expand All @@ -34,24 +34,24 @@ or polish when other code also `add`s outside the ingest workflow. See
**`src/` is the `@corbits/memory` SDK.** Interchange is the hub — the SDK
never creates one; it mounts onto yours.

| Surface | Role |
| --- | --- |
| `createMemory({ … })` | Build the plane |
| `createMemoryRoutes({ memory, requireGrant })` | Hono sub-app the host mounts at `/api/tenants/:tenantId/memory` |
| `mountWorkflowMemory(app, { memory, agentToken })` | Parallel run-scoped `/api/workflow-memory/*` for deployed agents |
| `loadMemoryConfig()` | Config from env |
| `runMemoryMigrations(dbConfig, { schema, ftsLanguage })` | Apply pgvector schema |
| `@corbits/memory/sidecar-bundle` | Deployed-agent factory — no client code, no base URL, no token |
| `@corbits/memory/distiller` | Optional process helpers: `runDistillTick`, `createResidentDistiller` |
| Surface | Role |
| -------------------------------------------------------- | --------------------------------------------------------------------- |
| `createMemory({ … })` | Build the plane |
| `createMemoryRoutes({ memory, requireGrant })` | Hono sub-app the host mounts at `/api/tenants/:tenantId/memory` |
| `mountWorkflowMemory(app, { memory, agentToken })` | Parallel run-scoped `/api/workflow-memory/*` for deployed agents |
| `loadMemoryConfig()` | Config from env |
| `runMemoryMigrations(dbConfig, { schema, ftsLanguage })` | Apply pgvector schema |
| `@corbits/memory/sidecar-bundle` | Deployed-agent factory — no client code, no base URL, no token |
| `@corbits/memory/distiller` | Optional process helpers: `runDistillTick`, `createResidentDistiller` |

### Verbs

| Method | HTTP | Grant | Meaning |
| --- | --- | --- | --- |
| `add` | `POST /api/tenants/:tenantId/memory/add` | `memory:add` | Ingest: capture + derive (chunk/embed on default store) |
| Method | HTTP | Grant | Meaning |
| -------- | ------------------------------------------- | --------------- | ----------------------------------------------------------------------------------- |
| `add` | `POST /api/tenants/:tenantId/memory/add` | `memory:add` | Ingest: capture + derive (chunk/embed on default store) |
| `search` | `POST /api/tenants/:tenantId/memory/search` | `memory:search` | Hybrid retrieval (+ optional live sources); hits may include additive `attribution` |
| `list` | `GET /api/tenants/:tenantId/memory/list` | `memory:search` | Recent documents for the principal |
| `feed` | `GET /api/tenants/:tenantId/memory/feed` | `memory:search` | Cursor pull of new live versions (optional multi-writer / backfill) |
| `list` | `GET /api/tenants/:tenantId/memory/list` | `memory:search` | Recent documents for the principal |
| `feed` | `GET /api/tenants/:tenantId/memory/feed` | `memory:search` | Cursor pull of new live versions (optional multi-writer / backfill) |

Engine-only plane helpers (no HTTP yet): transform/replay, retention
(`deprecateVersion` / `tombstoneDocument` / … — see `docs/RETENTION.md`),
Expand Down Expand Up @@ -107,10 +107,10 @@ Deployed agent (sidecar-bundle)

### Ports

| Port | Purpose |
| --- | --- |
| `DocumentStore` | Sole durable backend for add/search/list (default: pgvector). Inject fakes or a host/adapter store to skip Postgres. |
| `SourceProvider` | Optional live search merge (fail-soft). Not a store replacement. |
| Port | Purpose |
| ---------------- | -------------------------------------------------------------------------------------------------------------------- |
| `DocumentStore` | Sole durable backend for add/search/list (default: pgvector). Inject fakes or a host/adapter store to skip Postgres. |
| `SourceProvider` | Optional live search merge (fail-soft). Not a store replacement. |

Optional sibling packages (not in this tree): Mem0 / Supermemory document
stores, Linear tools. Core never imports vendor SDKs.
Expand Down
Loading
Loading