Memory
CONTRACT DRAFT — MINI_SPHERE_CONTRACT v0.1 (DRAFT; Sep 4 2026; Mike + workspace agent; governs the workspace-local memory/map layer). NOT YET PINNED. Parent: SPHERE_GATEKEEPER_CONTRACT. Reference baseline: the live sphere db/schema.sql (D1 SQLite), with documented deviations. Evidence standard a5e10e10. Spike evidence: FTS5 confirmed, recursive CTE confirmed, DO alarms falsified (scheduled-tasks gatekeeper substitutes) — see the design entry captured alongside. Section 1 PURPOSE: every workspace gets a memory/map layer as a blueprintable Gadget DO with SQLite — the substrate the workspace agent navigates by: what exists, how it works, what was decided, where authority lives. Contract-first: if a memory capability is not described here, the gadget does not provide it. Section 2 DEFINITIONS: Mini-Sphere (the gadget); workspace agent (the consumer, via Cap'n Web RPC — no MCP surface); optional binding (a wired gatekeeper/AI binding for semantic/LLM features, default off); scheduled-tasks gatekeeper (maintenance scheduler, not an approver). Section 3 SURFACE (direct RPC, no MCP, no approval queue): Reads: recall(query, {topK, tag, kind, hops, full}), listRecent({n, tag}), getEntry(id), connections(id), getTags(), getCount(), getStats(), getBrief(), graphView({seedIds, hops}). Writes (immediate, caller-classified): capture(content, {tags, source, volatility, kind, status, importance, claimTag, evidenceRef}), append(id, addition, {...}), update(id, content), setStatus(id, status), forget(id), link(src, dst, type, {provenance, weight}), unlink(src, dst, type). Maintenance (gatekeeper-triggered): runStalenessPass({limit}). Section 4 DATA MODEL: entries(id, content, source, created_at, updated_at, recall_count, importance_score, claim_tag, evidence_ref); tags(entry_id, tag) normalized + dedicated indexed columns for status/kind/volatility; edges(src, dst, type, weight, provenance, metadata, created_at, updated_at, UNIQUE(src,dst,type)) with 8 closed types (relates_to, supersedes, caused_by, decided, about_person, part_of_project, follows, document_of), kind-gated, symmetric relates_to canonicalized by id order; revisions(entry_id, content, at) for history; fts5 virtual table over entry content (BM25). Lifecycle status canonical/draft/deprecated; volatility durable/state/volatile; kind episodic/semantic; provenance explicit/inferred/system. Section 5 RETRIEVAL: BM25 keyword arm (FTS5, spike-confirmed) + graph hops (recursive CTE, spike-confirmed) fused via RRF; rerank = time-decay (volatility floors 0.9/0.6/0.15) x log1p(recall_count) x importance x tag-overlap, MMR lambda=0.7; snippet budgeting (top-2 get 4000 chars, tail 400, total 12000); temporal query rewrite returns queryUsed; filters drop deprecated + pipeline exhaust. Scores recomputed per request (no result cache — matches the live substrate). Section 6 OPTIONAL BINDINGS (pluggable, default off): VECTOR/embedding binding → semantic recall (vectors as BLOB, cosine in JS over candidate set), semantic dedup (0.95/0.85), auto-linking (>=0.78), contradiction detection; LLM binding → classify fallback, digests/roll-ups, auto-patterns, query-tag inference. The gadget is fully functional with ZERO bindings. Section 7 MAINTENANCE: scheduled-tasks gatekeeper fires runStalenessPass on a cron (narrow named method, least-privilege, audited per run); lazy staleness on read as fallback. No self-alarms (spike: Facets cannot set alarms). Section 8 OUT OF SCOPE: MCP surface; approval queue; gatekeeper write-aperture; ingestUrl/crawl/document-extraction; cross-workspace traversal; live queries; SurrealDB/VPS substrate. Section 9 UNCERTAINTY-AS-NATIVE: claim_tag ([VERIFIED]/[INFERRED]/[UNKNOWN]) + evidence_ref as real columns — a5e10e10 as data, not convention (implements what the v2 vision only describes; the live sphere lacks it). Section 10 AMENDMENT: PRs against canonical in int_contracts, via gatekeeper-github, version bump + re-pin + verbatim duplication + evidence snapshot. Conflicts reported, never improvised around. Section 11 NAME: MINI_SPHERE_CONTRACT, registered per NAMING_CONTRACT; parent SPHERE_GATEKEEPER_CONTRACT. OPEN DECISION POINTS: DP-MS1..10 (see the design entry captured alongside). STATUS: DRAFT — pending Mike's rulings + ratification + pin. RELATED: 9c51aced (mini-sphere work item), 3e1f9f20 (sphere substrate), 2144b79b (three-layers boundary), cf00a760 (foundational vision), 6ed41ea6 (gatekeeper-family principle), a5e10e10 (evidence standard), design entry (captured alongside).
[Update Sep 6, 2026]: [Update Sep 4 2026]: [RULINGS — Mike ruled "all recommendations" on DP-MS1..10]: All decision points resolved. DP-MS1 normalized tags + dedicated columns = YES. DP-MS2 revisions table = YES. DP-MS3 vector arm in-scope, default off = YES. DP-MS4 caller-provided classification = YES. DP-MS5 exact-hash dedup baseline = YES. DP-MS6 digests/auto-patterns dropped for v1 (tag stubs kept) = YES. DP-MS7 uncertainty-as-native in v1 = YES. DP-MS8 scheduled-tasks gatekeeper + lazy staleness = YES. DP-MS9 separate child contract of SPHERE_GATEKEEPER_CONTRACT = YES. DP-MS10 FTS5/BM25 = evidence confirmed. STATUS: decision-complete DRAFT; next = finalize text with rulings fixed in -> Mike review -> commit int_contracts -> SHA-256 pin -> evidence snapshot -> register name. Decision record captured (see links).
[Update Sep 6, 2026]: [COMMITTED + PINNED, Sep 6, 2026, ~5:14pm BST — Perplexity via GitHub connector, Mike-approved]: MINI_SPHERE_CONTRACT v0.1 committed to canonical — docuclear-ai/int_contracts @ main, commit b5cfab4831e4b47b0e0a34398f1a6d06271dc593; blob b7c8dd3f4f681fbef0454a8984efa55b58de4d41; 10,468 bytes. SHA-256 pin: B846EDB4DB3F1F6D3E30534974D30ECCE59F1F9FC6D940E151627FB2D18D60F7 (computed from the exact committed bytes; byte-identity verified — GitHub's blob SHA matches the locally computed git blob SHA-1). Still outstanding: evidence snapshot to docuclear-evidence /contracts/MINI_SPHERE_CONTRACT@0.1.md + hash (repo does not yet exist); name registration per NAMING_CONTRACT §6.3. Note: v0.2 draft bb9f7907 (instruction kind, getBrief() grounding, AgentSphere boundary note, DP-MS clarifications) remains pending its AgentSphere conversation and would arrive via the §10 amendment path. Below: the finalized canonical text as committed, so this entry and GitHub canonical stay in step.
---
# MINI_SPHERE_CONTRACT
- **Version:** 0.1 (DRAFT — decision-complete; pending review, commit, pin)
- **Status:** Draft — not yet pinned. Hash-pin ritual applies at first commit to canonical.
- **Date:** 2026-09-04
- **Authors:** Mike + workspace agent
- **Boundary governed:** the workspace-local memory/map layer — a blueprintable Gadget DO with SQLite providing each workspace its own memory + map substrate, consumed by the workspace agent over Cap'n Web RPC.
- **Canonical location:** GitHub — docuclear-ai org, `int_contracts` repo. Duplicated verbatim into consuming repos. Snapshot per referenced version into docuclear-evidence at `/contracts/MINI_SPHERE_CONTRACT@<version>.md` + SHA-256.
- **SHA-256 pin:** `<computed at commit — never hand-edited>`
- **Parent contract:** SPHERE_GATEKEEPER_CONTRACT
- **Reference baseline:** the live sphere `db/schema.sql` (D1 SQLite), with documented deviations. Not the aspirational `sphere_schema_v2.surql`.
- **Evidence standard:** a5e10e10 (implemented as data — §9)
- **Spike evidence:** FTS5 confirmed; recursive-CTE graph hops confirmed; DO alarms falsified ("Facets currently cannot set alarms") → scheduled-tasks gatekeeper substitutes (§7).
- **Related decisions:** mini-sphere work item 9c51aced; sphere substrate 3e1f9f20; three-layers boundary 2144b79b; foundational vision cf00a760; gatekeeper-family principle 6ed41ea6; DP-MS1..10 ruling 667f1251.
---
## 1. Purpose
Every workspace gets a memory/map layer as a blueprintable Gadget DO with SQLite — the substrate the workspace agent navigates by: what exists, how it works, what was decided, where authority lives. Contract-first: if a memory capability is not described by this contract, the gadget does not provide it.
Mini-Sphere is the workspace-agent-native form of the sphere capability class (§1 of the parent SPHERE_GATEKEEPER_CONTRACT): no MCP surface, no approval queue, no governed write-aperture. The consumer is the workspace agent, calling the gadget's Durable Object directly over Cap'n Web RPC.
## 2. Definitions
| Term | Meaning |
|---|---|
| **Mini-Sphere** | The gadget: a Durable Object ("Facet") with SQLite storage implementing this contract. |
| **Workspace agent** | The consumer. Calls the gadget DO over Cap'n Web RPC. Supplies classification at write time (§6). |
| **Optional binding** | A wired gatekeeper/AI binding for semantic/LLM features. Default off. The gadget is fully functional with zero bindings (§5, §6). |
| **Scheduled-tasks gatekeeper** | A gatekeeper that fires the maintenance RPC on a cron. A scheduler, not an approver (§7). |
| **Claim tag** | `[VERIFIED]` / `[INFERRED]` / `[UNKNOWN]` — uncertainty as native schema (§9). |
| **Contract reference** | `NAME@version` + SHA-256 of the canonical contract text. |
## 3. Surface (direct RPC — no MCP, no approval queue)
**Reads (return immediately):**
- `recall(query, {topK?, tag?, kind?, hops?, full?})` — ranked retrieval (§5)
- `listRecent({n?, tag?})`
- `getEntry(id)`
- `connections(id)` — 1-hop linked memories
- `graphView({seedIds, hops})` — seeded multi-hop graph
- `getTags()` — tag vocabulary with counts
- `getCount()`
- `getStats()` — count, avg importance, unclassified, top topics
- `getBrief()` — recent activity, topics, resurface candidates (pure SQL, no model calls)
**Writes (immediate, caller-classified):**
- `capture(content, {tags, source, volatility, kind, status, importance, claimTag, evidenceRef})`
- `append(id, addition, {...})` — history-preserving (§4)
- `update(id, content)`
- `setStatus(id, status)` — `canonical` | `draft` | `deprecated`
- `forget(id)` — permanent delete
- `link(src, dst, type, {provenance, weight})`
- `unlink(src, dst, type)`
**Maintenance (gatekeeper-triggered only):**
- `runStalenessPass({limit})` — §7
## 4. Data model
**`entries`**
```
id TEXT PRIMARY KEY, content TEXT, source TEXT,
created_at INTEGER, updated_at INTEGER,
recall_count INTEGER DEFAULT 0, importance_score REAL DEFAULT 0,
claim_tag TEXT, evidence_ref TEXT
```
`claim_tag` ∈ {`VERIFIED`,`INFERRED`,`UNKNOWN`} + `evidence_ref` implement §9. IDs via `crypto.randomUUID()`.
**`tags` (normalized — DP-MS1)**
```
entry_id TEXT, tag TEXT, PRIMARY KEY(entry_id, tag)
```
Plus **dedicated indexed columns** on `entries` for the high-traffic filters: `status` (canonical/draft/deprecated), `kind` (episodic/semantic), `volatility` (durable/state/volatile). This fixes the count-aggregation bug class and is faster than JSON-`LIKE`. Reserved tag namespaces (`project:`, `stale:as-of`, pipeline markers `rolled-up`, `synthesized`, `auto-pattern`, `duplicate-candidate`, `contradiction-resolved`) live in the `tags` table.
**`edges`**
```
src TEXT, dst TEXT, type TEXT, weight REAL, provenance TEXT,
metadata TEXT, created_at INTEGER, updated_at INTEGER,
UNIQUE(src, dst, type)
```
- **8 closed types** (kind-gated): `relates_to` (symmetric, canonicalized by id order), `supersedes`, `caused_by`, `decided` (episodic-only), `about_person`, `part_of_project`, `follows` (episodic-only), `document_of`.
- `provenance` ∈ {`explicit`, `inferred`, `system`}.
- Indexes on `src` and `dst`.
**`revisions` (DP-MS2)**
```
entry_id TEXT, content TEXT, at INTEGER
```
History-preserving appends. `append()` writes the prior content as a revision row; the main `entries.content` holds current. Snippet rendering joins revisions for the head + latest-update pattern. (Deviation from sphere's content-string-append; recorded, not carried over.)
**`fts` (FTS5 virtual table — DP-MS10 evidence)**
```
CREATE VIRTUAL TABLE fts USING fts5(content)
```
BM25 keyword arm (§5). Spike-confirmed available in the gadget DO.
**Dedup hash (DP-MS5)**
A content hash (normalized text) on `entries` for exact-match dedup-on-capture. Semantic dedup is an optional binding (§6), not v1.
## 5. Retrieval
Pipeline (scores recomputed per request — no result cache, matching the live substrate):
1. **Temporal query rewrite** → `queryUsed` returned (time phrases → bounds; rare-term distillation).
2. **Prefilters** — `status`, `kind`, `volatility` columns + `tags` table + `created_at` range; exact, before any text cost.
3. **Keyword arm** — FTS5 `MATCH` + `bm25()` + `ORDER BY rank` (spike-confirmed). Token cap and row cap apply.
4. **Graph hops** (recursive CTE — spike-confirmed) — BFS from seed ids, `hops` 0–3, fanout ≤8/node, ≤50 nodes, `score = seedScore × 0.6^hop × edgeWeight`; deprecated filtered unless requested.
5. **Fusion** — RRF: keyword `1/(60+rank)`; graph seeds by traversal score.
6. **Rerank** — time-decay (volatility floors 0.9 / 0.6 / 0.15, never to zero) × `log1p(recall_count)` (capped 1.0) × importance × tag-overlap boost; penalties: `rolled-up` 0.4×; then MMR λ=0.7 diversity over `topK`.
7. **Snippet budgeting** — top-2 strong matches 4000 chars, tail 400, total 12000; cuts marked `[truncated · N chars · get("<id>")]`; `full=1` bypasses.
8. **Filters that always apply** — hydration drops `auto-pattern` (if present) + `status:deprecated`.
**Optional vector arm (DP-MS3, default off):** when a VECTOR/embedding binding is wired, a dense arm runs (embed query → topK → cosine in JS over the candidate set, vectors stored as BLOB) and fuses into RRF alongside keyword + graph. With zero bindings, retrieval is keyword + graph + rerank.
## 6. Writes & classification (DP-MS4)
The workspace agent supplies classification **at write time**: `kind`, `volatility`, `status`, `importance`, `claimTag`, `evidenceRef`. This replaces sphere's post-write LLM classify with caller-provided metadata — the writer knows whether it is storing a fact or an event. `capture` returns a result envelope (`stored {id}` / `blocked {matchId}` (hash dedup) / `merged` / `replaced`).
**Optional LLM binding (default off):** an LLM binding may provide a classify fallback, semantic dedup (0.95 block / 0.85 flag), auto-linking (top-3 neighbors ≥0.78 → `relates_to` inferred), contradiction/supersession detection, digests/roll-ups, and auto-patterns. None of these are required for v1.
## 7. Maintenance & staleness (DP-MS8)
Gadget DOs cannot self-alarm (spike: "Facets currently cannot set alarms"). Maintenance is therefore:
- **Scheduled:** the **scheduled-tasks gatekeeper** fires `runStalenessPass({limit})` on a cron. The gatekeeper calls only this narrow, named method (least-privilege; audited per run). Wiring = a `SCHEDULED_TASKS` binding in the workspace creation manifest (contract-at-birth).
- **Lazy fallback:** if the scheduler has not run, staleness is computed at read/hydrate time (`updated_at` age + volatility regex heuristic) and `stale:as-of` applied then.
This is a scheduler, not an approver — it does not re-introduce the governed write-aperture or approval queue.
**Out of v1 (DP-MS6):** digests/roll-ups and auto-patterns (LLM-generated) are dropped. The `rolled-up` / `auto-pattern` tag stubs are retained for later additivity. Cold rows rank lower via recency decay in the meantime.
## 8. Out of scope
MCP tool surface; approval queue; gatekeeper write-aperture; `ingestUrl` / crawl / document-extraction; cross-workspace traversal; live queries/subscriptions; the SurrealDB/VPS substrate. These belong to the parent sphere capability or the ingestion boundary, not Mini-Sphere.
## 9. Uncertainty as native schema (DP-MS7)
`claim_tag` and `evidence_ref` are real columns (§4). Every entry and edge may carry its uncertainty as data: `[VERIFIED]` / `[INFERRED]` / `[UNKNOWN]` plus a reference to the evidence backing it. This implements evidence standard a5e10e10 as data, not convention — the live sphere lacks this; Mini-Sphere implements what the v2 vision describes.
## 10. Amendment
Amendments are PRs against canonical in `int_contracts`, merged through gatekeeper-github, with version bump, re-pin (SHA-256), verbatim duplication into consuming repos, and evidence snapshot into docuclear-evidence. Conflicts are reported, never improvised around.
## 11. Name
`MINI_SPHERE_CONTRACT`, registered per NAMING_CONTRACT. Parent: `SPHERE_GATEKEEPER_CONTRACT`. First registration occurs at first canonical commit (NAMING_CONTRACT §6.3: a new boundary contract registers its name before its first canonical commit).
---
*End of MINI_SPHERE_CONTRACT v0.1 (decision-complete draft). Pin at first canonical commit; snapshot to evidence at `/contracts/MINI_SPHERE_CONTRACT@0.1.md` + SHA-256.*
[Update Sep 6, 2026]: [EVIDENCE SNAPSHOT LANDED, Sep 6, 2026, ~5:22pm BST — Mike]: MINI_SPHERE_CONTRACT@0.1 snapshot + pin uploaded to the docuclear evidence store (inside docuclear_control) at contracts/MINI_SPHERE_CONTRACT@0.1.md with .sha256 sidecar. Pin B846EDB4DB3F1F6D3E30534974D30ECCE59F1F9FC6D940E151627FB2D18D60F7; canonical commit b5cfab4831e4b47b0e0a34398f1a6d06271dc593 (docuclear-ai/int_contracts @ main); blob b7c8dd3f4f681fbef0454a8984efa55b58de4d41, 10,468 bytes. Commit → pin → evidence snapshot loop now CLOSED. Still outstanding: name registration per NAMING_CONTRACT §6.3 — the naming registry does not exist yet; location under discussion (recommendation: live registry as a machine-readable file in int_contracts, amended via gatekeeper-github PRs, with per-change snapshots into the evidence store).
[Update Sep 6, 2026]: [Update Sep 4 2026]: [PINNED — Mike uploaded MINI_SPHERE_CONTRACT v0.1 to docuclear-evidence and computed the SHA-256 pin]: SHA-256 B846EDB4DB3F1F6D3E30534974D30ECCE59F1F9FC6D940E151627FB2D18D60F7. Evidence snapshot at /contracts/MINI_SPHERE_CONTRACT@0.1.md. The SHA-256 pin placeholder in the contract header is now resolved with this value. STATUS: pinned draft (mirrors the DEPLOYER/NAMING pinned-draft pattern) — ratification to canonical is at Mike's word. NEXT: register MINI_SPHERE_CONTRACT in the name registry per NAMING_CONTRACT section 6.3 (a new boundary contract registers its name before first canonical commit); confirm canonical status when ratified. OPEN: scheduled-tasks gatekeeper wiring spike (coder) — the only remaining evidence gap; the contract already specifies the mechanism (section 7).
Tags: docuclear, mini-sphere, contract, design, sqlite, graph, fts5, gatekeeper, scheduled-tasks, project:docuclear, status:draft, kind:episodic, volatility:durable — Source: mcp — 2026-09-04 20:12:08 UTC