tulving 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tulving-0.0.1/.claude/scheduled_tasks.lock +1 -0
- tulving-0.0.1/CLAUDE.md +136 -0
- tulving-0.0.1/PKG-INFO +45 -0
- tulving-0.0.1/README.md +28 -0
- tulving-0.0.1/docs/README.md +30 -0
- tulving-0.0.1/docs/adrs/README.md +28 -0
- tulving-0.0.1/docs/adrs/adr-001-python-first.md +16 -0
- tulving-0.0.1/docs/adrs/adr-002-sdk-plus-mcp.md +20 -0
- tulving-0.0.1/docs/adrs/adr-003-sqlite-default.md +21 -0
- tulving-0.0.1/docs/adrs/adr-004-local-embeddings-default.md +20 -0
- tulving-0.0.1/docs/adrs/adr-005-four-retrieval-modes.md +23 -0
- tulving-0.0.1/docs/adrs/adr-006-decisions-never-decay.md +20 -0
- tulving-0.0.1/docs/adrs/adr-007-json-serializable-content.md +16 -0
- tulving-0.0.1/docs/adrs/adr-008-agent-id-trust-model.md +21 -0
- tulving-0.0.1/docs/adrs/adr-009-summarization-archives-not-deletes.md +21 -0
- tulving-0.0.1/docs/adrs/adr-010-security-first.md +31 -0
- tulving-0.0.1/docs/adrs/adr-011-kairos-as-sibling-not-dependency.md +21 -0
- tulving-0.0.1/docs/adrs/adr-012-mcp-tool-design.md +30 -0
- tulving-0.0.1/docs/adrs/adr-013-session-detection.md +32 -0
- tulving-0.0.1/docs/adrs/adr-014-contradiction-detection.md +30 -0
- tulving-0.0.1/docs/adrs/adr-015-concurrency-model.md +31 -0
- tulving-0.0.1/docs/adrs/adr-016-v01-scope.md +51 -0
- tulving-0.0.1/docs/adrs/adr-017-project-name.md +44 -0
- tulving-0.0.1/docs/architecture/architecture.md +279 -0
- tulving-0.0.1/docs/architecture/database-strategy.md +164 -0
- tulving-0.0.1/docs/legacy_docs/CLAUDE.md +273 -0
- tulving-0.0.1/docs/legacy_docs/architecture.md +407 -0
- tulving-0.0.1/docs/legacy_docs/kairos-tulving-integration.md +258 -0
- tulving-0.0.1/docs/legacy_docs/phase2-module1-entity-extractor.md +69 -0
- tulving-0.0.1/docs/legacy_docs/phase2-module2-relationship-store.md +73 -0
- tulving-0.0.1/docs/legacy_docs/phase2-module3-graph-query.md +53 -0
- tulving-0.0.1/docs/legacy_docs/phase3-module4-working-context.md +39 -0
- tulving-0.0.1/docs/legacy_docs/phase4-module1-memory-scoping.md +52 -0
- tulving-0.0.1/docs/legacy_docs/phase4-module2-conflict-resolution.md +42 -0
- tulving-0.0.1/docs/legacy_docs/phase4-module3-subscriptions.md +49 -0
- tulving-0.0.1/docs/legacy_docs/phase4-module4-agent-registry.md +61 -0
- tulving-0.0.1/docs/legacy_docs/phase5-module1-kairos-integration.md +81 -0
- tulving-0.0.1/docs/project-management/market-research.md +123 -0
- tulving-0.0.1/docs/project-management/revision-plan.md +139 -0
- tulving-0.0.1/docs/specs/adapters-embeddings.md +110 -0
- tulving-0.0.1/docs/specs/adapters-llm.md +80 -0
- tulving-0.0.1/docs/specs/adapters-storage.md +109 -0
- tulving-0.0.1/docs/specs/context-curator.md +208 -0
- tulving-0.0.1/docs/specs/context-decay-eviction.md +137 -0
- tulving-0.0.1/docs/specs/context-lifecycle.md +338 -0
- tulving-0.0.1/docs/specs/context-summarizer.md +98 -0
- tulving-0.0.1/docs/specs/core-entry-model.md +163 -0
- tulving-0.0.1/docs/specs/core-kv-index.md +93 -0
- tulving-0.0.1/docs/specs/core-memory-store.md +228 -0
- tulving-0.0.1/docs/specs/core-semantic-index.md +160 -0
- tulving-0.0.1/docs/specs/export-import.md +99 -0
- tulving-0.0.1/docs/specs/mcp-server.md +307 -0
- tulving-0.0.1/docs/v0.1-overview.md +130 -0
- tulving-0.0.1/pyproject.toml +27 -0
- tulving-0.0.1/tulving/__init__.py +12 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"sessionId":"f5b5d2a0-03e6-446c-903b-19003d524a39","pid":65688,"procStart":"639186885348535720","acquiredAt":1783117493637}
|
tulving-0.0.1/CLAUDE.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# CLAUDE.md — Tulving Project Instructions
|
|
2
|
+
|
|
3
|
+
> Project instructions for Claude Code. Scope: **v0.1.0 only** (ADR-016).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Current State — READ FIRST
|
|
8
|
+
|
|
9
|
+
**Pre-development.** No source code exists yet. **Do not start coding until the owner gives the green light.**
|
|
10
|
+
|
|
11
|
+
Document authority order (when they disagree, higher wins):
|
|
12
|
+
1. `docs/project-management/revision-plan.md` — audit corrections, decisions D1–D12
|
|
13
|
+
2. `docs/architecture/architecture.md` + `docs/adrs/adr-015`, `adr-016`
|
|
14
|
+
3. `docs/specs/*.md` — module specs (predate the audit; apply D1–D12 when implementing)
|
|
15
|
+
4. `docs/legacy_docs/` — **superseded; never implement from these**
|
|
16
|
+
|
|
17
|
+
Reader-friendly scope tour: `docs/v0.1-overview.md`.
|
|
18
|
+
|
|
19
|
+
**Pending owner decisions (do not act without instruction):**
|
|
20
|
+
- Green light to begin coding.
|
|
21
|
+
|
|
22
|
+
**Naming (resolved 2026-07-03, ADR-017):** the project is **Tulving** — named after Endel Tulving, the psychologist who established that memory has types (episodic vs semantic), mirroring this SDK's typed-memory model. Formerly "Engram" (dropped: collision with the funded engram.org). PyPI name `tulving` verified available — register early. The future Kairos integration package will be `kairos-ai-tulving`.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Project Overview
|
|
27
|
+
|
|
28
|
+
A model-agnostic Python SDK giving a single AI agent persistent, structured, searchable working memory, with **token-budget context curation (`curate(query, token_budget)`) as the headline primitive**. Also runs as a local MCP server for Claude Code. Zero infrastructure: one SQLite file; vectors optional.
|
|
29
|
+
|
|
30
|
+
**v0.1.0 ships:** core engine (store/get/search, typed memories, key-supersede) · curation + orient mode · lazy decay & eviction · per-agent sessions with summarization · MCP server (6 tools) · embedding/LLM adapters + JSON export.
|
|
31
|
+
**Deferred (one line):** knowledge graph, all multi-agent machinery, semantic contradiction detection, extra formats/backends — see ADR-016.
|
|
32
|
+
|
|
33
|
+
## Kairos (sibling project)
|
|
34
|
+
|
|
35
|
+
Reference implementation for patterns, security stance, and testing methodology: `C:\Users\abrah\OneDrive\Documents\Projects\ClaudeCode\Kairos\kairos` · https://github.com/govanxa/kairos
|
|
36
|
+
|
|
37
|
+
- PyPI package is **`kairos-ai`** (never `kairos-sdk`); core is zero-dependency — match that discipline.
|
|
38
|
+
- Plugins ship as separate packages in a `plugins/` monorepo; **`kairos-ai-evidence`** (0.2.0) is the worked example and the packaging model for the future Tulving↔Kairos integration.
|
|
39
|
+
- Integration facts for later: `Workflow(hooks=[...])` with `ExecutorHooks` subclasses (there is no `plugins=` kwarg for hooks; `ctx.memory` injection is impossible); `kairos-ai-evidence` verdicts (verified/conflicting/insufficient) are the candidate backend for v0.2 contradiction detection.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Non-Negotiable Design Decisions (from the audit — full detail in revision-plan.md)
|
|
44
|
+
|
|
45
|
+
1. **Upsert (D1):** `store()` on an existing key supersedes — archive old (`SUPERSEDED`), back-link, insert new. Never raise on duplicate key.
|
|
46
|
+
2. **Lazy decay (D2):** importance computed on read: `base_importance * 0.5^(hours_since_last_access / half_life[type])`. No startup decay pass. `evict()` exempts `pinned` and `DECISION`.
|
|
47
|
+
3. **Data model (D3):** `last_accessed_at` (updated on get/search-hit/curate-inclusion), `archive_reason` enum, partial unique index `UNIQUE(key) WHERE archived=0`, `memory_tags` junction table, `meta` table `{schema_version, embedding_model_id, dimension, distance_metric}`, `source_entry_ids` on summaries.
|
|
48
|
+
4. **Concurrency (ADR-015):** one process/many threads; advisory lock file refuses a second writer; SQLite embedding BLOBs are source of truth, `.hnsw` is a rebuildable cache; DB write first, reconcile at `startup()`; warn on OneDrive/network paths.
|
|
49
|
+
5. **hnswlib realities:** int-label↔UUID mapping; `mark_deleted` + rebuild-on-threshold compaction; `max_elements` resize policy; `space='cosine'`, `score = 1 - distance`; exclusive lock on index writes; over-fetch to survive post-filtering.
|
|
50
|
+
6. **Exceptions (D6):** `TulvingError` → `MemoryStoreError`, `StorageError`, `SecurityError`, `ConfigError`, `VectorIndexError`, `ScopeError`. **Never** define `MemoryError` or `IndexError` (builtin shadows).
|
|
51
|
+
7. **Identity (D7):** `agent_id` bound at `Memory(...)` construction.
|
|
52
|
+
8. **Cheap `__init__` (D8):** lifecycle work lives in explicit `startup()` — time-boxed, non-fatal, single-runner. Constructors never call LLMs or full-table scan.
|
|
53
|
+
9. **Per-agent sessions:** active-session checks and abandonment detection scoped by `agent_id`, per-session `last_activity_at`.
|
|
54
|
+
10. **MCP server:** thin wrapper; tools = `store`, `get`, `search`, `curate`, `forget`, `list_keys` (orient = `curate(mode="orient")`); async handlers offload to a thread pool; `llm=None` degrades loudly, never silently; SIGTERM flush is best-effort — startup recovery is primary.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Quick Reference
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pip install -e ".[dev]"
|
|
62
|
+
pytest
|
|
63
|
+
pytest --cov=tulving --cov-report=term-missing
|
|
64
|
+
mypy tulving/ # strict
|
|
65
|
+
ruff check tulving/ tests/ && ruff format tulving/ tests/
|
|
66
|
+
tulving-mcp --memory-path ./test_memory
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Project Structure (v0.1.0)
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
tulving/
|
|
73
|
+
├── CLAUDE.md ← you are here
|
|
74
|
+
├── pyproject.toml
|
|
75
|
+
├── docs/ ← see docs/README.md for the map
|
|
76
|
+
├── tulving/
|
|
77
|
+
│ ├── __init__.py ← public API exports
|
|
78
|
+
│ ├── enums.py ← MemoryType, MatchType, ArchiveReason, SessionStatus
|
|
79
|
+
│ ├── exceptions.py ← TulvingError hierarchy (decision 6)
|
|
80
|
+
│ ├── security.py ← redact (keys + content), leaf-name sanitize, path containment
|
|
81
|
+
│ ├── memory.py ← Memory (primary API) + startup()
|
|
82
|
+
│ ├── entry.py ← MemoryEntry, SourceInfo, Relationship
|
|
83
|
+
│ ├── store.py ← MemoryStore (CRUD engine)
|
|
84
|
+
│ ├── kv_index.py ← exact match + prefix scan (no namespaces)
|
|
85
|
+
│ ├── semantic_index.py ← label mapping, mark_deleted, compaction
|
|
86
|
+
│ ├── context/
|
|
87
|
+
│ │ ├── curator.py ← ContextCurator (token-budget curation, orient mode)
|
|
88
|
+
│ │ ├── summarizer.py ← call-budgeted, source back-links
|
|
89
|
+
│ │ ├── decay.py ← lazy decay + reason-aware eviction
|
|
90
|
+
│ │ └── lifecycle.py ← per-agent sessions, gap detection
|
|
91
|
+
│ ├── adapters/
|
|
92
|
+
│ │ ├── embeddings.py ← protocol + LocalEmbedder (extra) + OpenAIEmbedder
|
|
93
|
+
│ │ ├── llm.py ← protocol + one adapter, call budget
|
|
94
|
+
│ │ └── storage.py ← protocol + SQLiteBackend + InMemoryBackend
|
|
95
|
+
│ ├── mcp/server.py ← 6 MCP tools, thread-pool offload
|
|
96
|
+
│ └── export/formats.py ← JSON round-trip (re-embed on import, ID remap)
|
|
97
|
+
├── tests/ ← mirrors source
|
|
98
|
+
└── examples/
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Build Order (TDD)
|
|
102
|
+
|
|
103
|
+
1. `enums.py`, `exceptions.py`
|
|
104
|
+
2. `tests/test_security.py` → `security.py`
|
|
105
|
+
3. `tests/test_entry.py` → `entry.py`
|
|
106
|
+
4. `adapters/storage.py` (SQLite WAL + InMemory; D3 schema; `PRAGMA user_version` migrations)
|
|
107
|
+
5. `tests/test_store.py` → `store.py`
|
|
108
|
+
6. `tests/test_kv_index.py` → `kv_index.py`
|
|
109
|
+
7. `adapters/embeddings.py`
|
|
110
|
+
8. `tests/test_semantic_index.py` → `semantic_index.py`
|
|
111
|
+
9. `tests/test_memory.py` → `memory.py` (integration; `startup()`; lock file)
|
|
112
|
+
10. `tests/test_curator.py` → `context/curator.py`
|
|
113
|
+
11. `tests/test_decay.py` → `context/decay.py`
|
|
114
|
+
12. `tests/test_summarizer.py` → `context/summarizer.py`
|
|
115
|
+
13. `tests/test_lifecycle.py` → `context/lifecycle.py`
|
|
116
|
+
14. `tests/test_mcp_server.py` → `mcp/server.py`
|
|
117
|
+
15. `tests/test_export.py` → `export/formats.py`
|
|
118
|
+
|
|
119
|
+
**Mandatory regression tests from the audit:** decay idempotency across repeated startups · supersede against an archived row holding the same key · search excludes archived vectors · curate with oversize/tiny/empty budgets · startup never abandons another agent's session · adapter swap (any model change) forces rebuild · batch-created entries are searchable · purge refuses summarization sources unless explicit · DECISION/pinned survive evict at importance ~0 · second process on same path is refused.
|
|
120
|
+
|
|
121
|
+
## Coding Standards
|
|
122
|
+
|
|
123
|
+
- Python 3.11+; `str | None`; `@dataclass` for data, `Protocol` for interfaces
|
|
124
|
+
- `ruff format` / `ruff check`; `mypy` strict; line length 100; Google docstrings
|
|
125
|
+
- pytest, TDD; 90%+ coverage on core; InMemoryBackend in tests; mock all LLM/embedding calls
|
|
126
|
+
- **Dependencies:** core = stdlib + `hnswlib`. Extras: `[local]` (sentence-transformers/torch — never core), `[mcp]`, `[openai]`, `[postgres]`, `[kairos]` → `kairos-ai`. Token counting: `tiktoken` if available, `len/4` fallback with safety margin — never block on it.
|
|
127
|
+
|
|
128
|
+
## Security Requirements
|
|
129
|
+
|
|
130
|
+
1. Redaction covers key names **and** content (token-shape regexes, word-boundary patterns) in exports, MCP responses, curated context.
|
|
131
|
+
2. `[a-zA-Z0-9_-]` whitelist for leaf names only; directories via realpath containment (Windows-aware).
|
|
132
|
+
3. Credentials from environment only; adapters reject inline API keys.
|
|
133
|
+
4. `ScopeError` ≠ `SecurityError` (decision 6).
|
|
134
|
+
5. MCP server local-only; no network binding.
|
|
135
|
+
6. No encryption at rest in v0.1 — documented warning; don't store secrets.
|
|
136
|
+
7. 100% coverage on security functions.
|
tulving-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tulving
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: The context-budget engine for AI agents — persistent typed memory with token-budget curation. Name-holding pre-release; v0.1 in active development.
|
|
5
|
+
Project-URL: Author, https://github.com/govanxa
|
|
6
|
+
Author-email: Abraham <abraham@fscoder.dev>
|
|
7
|
+
Keywords: agents,ai,context,curation,llm,mcp,memory
|
|
8
|
+
Classifier: Development Status :: 1 - Planning
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
15
|
+
Requires-Python: >=3.11
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# Tulving
|
|
19
|
+
|
|
20
|
+
> *The context-budget engine for AI agents.*
|
|
21
|
+
|
|
22
|
+
**Status: pre-release (0.0.1) — name-holding release; v0.1 is in active development.**
|
|
23
|
+
|
|
24
|
+
Tulving is a model-agnostic Python SDK that gives an AI agent persistent, structured, searchable working memory — and, as its headline capability, curates that memory back into a fixed token budget:
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
ctx = memory.curate("resuming work on the auth refactor", token_budget=4000)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Named after **Endel Tulving**, the psychologist who established that memory has types (episodic vs semantic). Typed memories — facts, decisions, observations, plans, summaries, each with its own lifecycle — are Tulving's core data model.
|
|
31
|
+
|
|
32
|
+
## What v0.1 will ship
|
|
33
|
+
|
|
34
|
+
- **Core memory engine** — store / get / semantic search over typed memories; zero infrastructure (one SQLite file, local vectors optional, no API key required)
|
|
35
|
+
- **Token-budget context curation** — `curate(query, token_budget)` selects, ranks, and trims memories into a prompt-ready block; `orient` mode for cold starts
|
|
36
|
+
- **Lazy decay & eviction** — importance fades per-type over time; decisions never decay; nothing is destroyed, only archived
|
|
37
|
+
- **Sessions** — per-agent session tracking, end-of-session summarization, abandoned-session recovery
|
|
38
|
+
- **MCP server** — six tools for Claude Code and other MCP clients, with single-writer safety
|
|
39
|
+
- **Adapters & export** — pluggable embeddings/LLM, JSON round-trip export
|
|
40
|
+
|
|
41
|
+
By the same author: [Kairos](https://github.com/govanxa/kairos) (`kairos-ai`) — contract-enforced AI workflows. A `kairos-ai-tulving` integration plugin is planned.
|
|
42
|
+
|
|
43
|
+
## License
|
|
44
|
+
|
|
45
|
+
TBD (MIT or Apache 2.0) — will be finalized with the v0.1 release.
|
tulving-0.0.1/README.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Tulving
|
|
2
|
+
|
|
3
|
+
> *The context-budget engine for AI agents.*
|
|
4
|
+
|
|
5
|
+
**Status: pre-release (0.0.1) — name-holding release; v0.1 is in active development.**
|
|
6
|
+
|
|
7
|
+
Tulving is a model-agnostic Python SDK that gives an AI agent persistent, structured, searchable working memory — and, as its headline capability, curates that memory back into a fixed token budget:
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
ctx = memory.curate("resuming work on the auth refactor", token_budget=4000)
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Named after **Endel Tulving**, the psychologist who established that memory has types (episodic vs semantic). Typed memories — facts, decisions, observations, plans, summaries, each with its own lifecycle — are Tulving's core data model.
|
|
14
|
+
|
|
15
|
+
## What v0.1 will ship
|
|
16
|
+
|
|
17
|
+
- **Core memory engine** — store / get / semantic search over typed memories; zero infrastructure (one SQLite file, local vectors optional, no API key required)
|
|
18
|
+
- **Token-budget context curation** — `curate(query, token_budget)` selects, ranks, and trims memories into a prompt-ready block; `orient` mode for cold starts
|
|
19
|
+
- **Lazy decay & eviction** — importance fades per-type over time; decisions never decay; nothing is destroyed, only archived
|
|
20
|
+
- **Sessions** — per-agent session tracking, end-of-session summarization, abandoned-session recovery
|
|
21
|
+
- **MCP server** — six tools for Claude Code and other MCP clients, with single-writer safety
|
|
22
|
+
- **Adapters & export** — pluggable embeddings/LLM, JSON round-trip export
|
|
23
|
+
|
|
24
|
+
By the same author: [Kairos](https://github.com/govanxa/kairos) (`kairos-ai`) — contract-enforced AI workflows. A `kairos-ai-tulving` integration plugin is planned.
|
|
25
|
+
|
|
26
|
+
## License
|
|
27
|
+
|
|
28
|
+
TBD (MIT or Apache 2.0) — will be finalized with the v0.1 release.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Tulving Documentation
|
|
2
|
+
|
|
3
|
+
> **Scope:** v0.1.0 — single-agent, local-first memory SDK with token-budget context curation, plus an MCP server for Claude Code.
|
|
4
|
+
|
|
5
|
+
## Start here
|
|
6
|
+
|
|
7
|
+
1. **[v0.1-overview.md](v0.1-overview.md)** — plain-language tour of the six capability areas. Read this first.
|
|
8
|
+
2. **[architecture/architecture.md](architecture/architecture.md)** — the canonical v0.1.0 architecture: API surface, storage model, concurrency, security, future roadmap.
|
|
9
|
+
3. **[specs/](specs/)** — per-module specifications (subject to the corrections in the revision plan).
|
|
10
|
+
|
|
11
|
+
## Folder map
|
|
12
|
+
|
|
13
|
+
| Folder | Contents |
|
|
14
|
+
|---|---|
|
|
15
|
+
| [architecture/](architecture/) | v0.1.0 architecture + [database strategy](architecture/database-strategy.md) |
|
|
16
|
+
| [adrs/](adrs/) | Architecture Decision Records 001–016 ([index](adrs/README.md)) |
|
|
17
|
+
| [specs/](specs/) | Module specs in play for v0.1.0 (Phase 1 core, Phase 3 context, Phase 5 adapters/MCP) |
|
|
18
|
+
| [project-management/](project-management/) | [Revision plan](project-management/revision-plan.md) (audit corrections D1–D12, authoritative over specs) · [Market research](project-management/market-research.md) |
|
|
19
|
+
| [legacy_docs/](legacy_docs/) | ⚠️ **Superseded — do not implement from these.** Old architecture, deferred Phase 2/4 specs, and Kairos integration docs written against APIs that don't exist. Reference material for future redesigns only. |
|
|
20
|
+
|
|
21
|
+
## Authority order (when documents disagree)
|
|
22
|
+
|
|
23
|
+
1. `project-management/revision-plan.md` (decisions D1–D12)
|
|
24
|
+
2. `architecture/architecture.md` + ADR-015/016
|
|
25
|
+
3. Module specs in `specs/`
|
|
26
|
+
4. Anything in `legacy_docs/` — historical only
|
|
27
|
+
|
|
28
|
+
## Naming
|
|
29
|
+
|
|
30
|
+
- **Tulving** (final, 2026-07-03) — after Endel Tulving, who established that memory has types; see [ADR-017](adrs/adr-017-project-name.md). Formerly "Engram" (dropped: collision with the unrelated, funded engram.org).
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Architecture Decision Records (ADRs)
|
|
2
|
+
|
|
3
|
+
> **Project:** Tulving
|
|
4
|
+
> **Convention:** ADRs are numbered sequentially. Once accepted, they are immutable; superseding decisions get a new ADR.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Index
|
|
9
|
+
|
|
10
|
+
| ADR | Title | Status | Notes |
|
|
11
|
+
|---|---|---|---|
|
|
12
|
+
| [001](adr-001-python-first.md) | Python as primary language | Accepted | |
|
|
13
|
+
| [002](adr-002-sdk-plus-mcp.md) | SDK library + MCP server distribution | Accepted | |
|
|
14
|
+
| [003](adr-003-sqlite-default.md) | SQLite + hnswlib as default backends | Accepted | Concurrency boundaries defined in ADR-015 |
|
|
15
|
+
| [004](adr-004-local-embeddings-default.md) | Local embeddings by default | Accepted | Revised: `[local]` extra (torch never in core); "no network" softened to "after first-run model fetch" — see revision plan D9 |
|
|
16
|
+
| [005](adr-005-four-retrieval-modes.md) | Four retrieval modes | Partially deferred | Graph retrieval deferred with Phase 2 (ADR-016); v0.1 = key, semantic, temporal |
|
|
17
|
+
| [006](adr-006-decisions-never-decay.md) | Decision memories never auto-decay or auto-evict | Accepted | |
|
|
18
|
+
| [007](adr-007-json-serializable-content.md) | String content, JSON-serializable metadata | Accepted | |
|
|
19
|
+
| [008](adr-008-agent-id-trust-model.md) | Agent identity trusted from orchestrator | Accepted | Reframed: cooperative isolation, not authZ — scope violations raise `ScopeError`, not `SecurityError` |
|
|
20
|
+
| [009](adr-009-summarization-archives-not-deletes.md) | Summarization archives originals, never destroys | Accepted | Enforced via `source_entry_ids` back-links (revision plan D3) |
|
|
21
|
+
| [010](adr-010-security-first.md) | Security as a first-class concern | Accepted | Revised per revision plan D10: content scanning, word-boundary patterns, path containment, no-encryption position |
|
|
22
|
+
| [011](adr-011-kairos-as-sibling-not-dependency.md) | Kairos is a sibling, not a dependency | Accepted | Dependency name is `kairos-ai` (not `kairos-sdk`); integration deferred, will follow the `kairos-ai-evidence` plugin packaging pattern |
|
|
23
|
+
| [012](adr-012-mcp-tool-design.md) | MCP tools designed for agent ergonomics | Accepted | Tool set trimmed to six in v0.1 (see ADR-016) |
|
|
24
|
+
| [013](adr-013-session-detection.md) | Three-layer session detection with graceful degradation | Accepted | Sessions are per-agent; startup recovery is the primary mechanism |
|
|
25
|
+
| [014](adr-014-contradiction-detection.md) | Contradiction detection flags, not blocks | Partially deferred | v0.1 keeps only deterministic key-collision supersede; semantic detection deferred (similarity ≠ contradiction) — candidate backend: `kairos-ai-evidence` |
|
|
26
|
+
| [015](adr-015-concurrency-model.md) | Single-writer concurrency model for Tier-1 | Accepted | **New** — one process/many threads; advisory lock file; index as rebuildable cache |
|
|
27
|
+
| [016](adr-016-v01-scope.md) | v0.1.0 scope: single-agent core, curation-first | Accepted | **New** — the in/out table; defers Phase 2, Phase 4, semantic contradiction |
|
|
28
|
+
| [017](adr-017-project-name.md) | Project name: Tulving | Accepted | **New** — replaces working title "Engram"; future Kairos plugin: `kairos-ai-tulving` |
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# ADR-001: Python as Primary Language
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted
|
|
4
|
+
**Date:** 2026-05-04
|
|
5
|
+
**Modules affected:** All
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
Tulving must ship in the language its target users work in. The AI agent ecosystem is overwhelmingly Python.
|
|
9
|
+
|
|
10
|
+
## Decision
|
|
11
|
+
**Python first. Same rationale as Kairos ADR-001.** TypeScript port considered for future phases.
|
|
12
|
+
|
|
13
|
+
## Consequences
|
|
14
|
+
- Immediate adoption by the agent developer community.
|
|
15
|
+
- Consistent with Kairos — both SDKs in the same language simplifies integration.
|
|
16
|
+
- Modern Python (3.11+) with type hints, `@dataclass`, `Protocol`.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# ADR-002: SDK Library + MCP Server Distribution
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted
|
|
4
|
+
**Date:** 2026-05-04
|
|
5
|
+
**Modules affected:** All, 5.6
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
Tulving needs to be usable both as a Python library imported into code AND as a standalone server that Claude Code or other MCP clients can connect to.
|
|
9
|
+
|
|
10
|
+
## Decision
|
|
11
|
+
**Tulving ships as both: `pip install tulving` for SDK use, `pip install tulving[mcp]` for MCP server.**
|
|
12
|
+
|
|
13
|
+
- The SDK is the primary distribution. Developers import it directly.
|
|
14
|
+
- The MCP server wraps the SDK and exposes it as tools via the Model Context Protocol.
|
|
15
|
+
- Both use the same underlying `Memory` class. The MCP server is a thin transport layer.
|
|
16
|
+
|
|
17
|
+
## Consequences
|
|
18
|
+
- Claude Code users get Tulving without writing Python — just configure the MCP server.
|
|
19
|
+
- Python developers get a clean import API without MCP overhead.
|
|
20
|
+
- The MCP dependency (`mcp` package) is optional — core SDK has no dependency on it.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# ADR-003: SQLite + hnswlib as Default Backends
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted
|
|
4
|
+
**Date:** 2026-05-04
|
|
5
|
+
**Modules affected:** 1.1, 1.3, 5.4
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
Tulving needs persistence and vector search. The default must require zero infrastructure — no separate database server, no cloud service, no Docker.
|
|
9
|
+
|
|
10
|
+
## Decision
|
|
11
|
+
**SQLite for structured storage, hnswlib for vector indexing. Both are file-based, zero-config, and embedded.**
|
|
12
|
+
|
|
13
|
+
- SQLite in WAL mode for concurrent read support.
|
|
14
|
+
- hnswlib for approximate nearest neighbor search (HNSW algorithm).
|
|
15
|
+
- Both persist to the same directory: `./tulving_memory/tulving.db` and `./tulving_memory/tulving.hnsw`.
|
|
16
|
+
- Production backends (Postgres, Redis, Pinecone, Qdrant) available via Phase 5 adapters.
|
|
17
|
+
|
|
18
|
+
## Consequences
|
|
19
|
+
- `pip install tulving` → works immediately. No infrastructure setup.
|
|
20
|
+
- Performance is sufficient for single-agent and small multi-agent workloads (thousands to low millions of entries).
|
|
21
|
+
- Large-scale production deployments switch backends without code changes.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# ADR-004: Local Embeddings by Default, No API Key Required
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted
|
|
4
|
+
**Date:** 2026-05-04
|
|
5
|
+
**Modules affected:** 1.3, 5.2
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
Semantic search requires embedding vectors. Cloud embedding APIs (OpenAI, Cohere) are higher quality but require API keys and network access. Local models are lower quality but zero-friction.
|
|
9
|
+
|
|
10
|
+
## Decision
|
|
11
|
+
**Default: local `sentence-transformers/all-MiniLM-L6-v2` (384 dims). No API key required.**
|
|
12
|
+
|
|
13
|
+
- `pip install tulving` includes the local embedder. Semantic search works immediately.
|
|
14
|
+
- Cloud embedders available as optional extras: `pip install tulving[openai]`.
|
|
15
|
+
- Switching embedders requires re-embedding existing memories (handled by `rebuild()` command).
|
|
16
|
+
|
|
17
|
+
## Consequences
|
|
18
|
+
- Zero-friction first experience. No account, no API key, no network.
|
|
19
|
+
- Lower embedding quality than cloud models — acceptable for working memory use cases.
|
|
20
|
+
- The `sentence-transformers` dependency adds ~500MB for the model. Documented in install notes.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# ADR-005: Four Retrieval Modes, Not One
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted
|
|
4
|
+
**Date:** 2026-05-04
|
|
5
|
+
**Modules affected:** 1.2, 1.3, 2.3, 3.1
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
Most memory systems default to one retrieval mode — usually vector search. But agents ask different kinds of questions that demand different access patterns.
|
|
9
|
+
|
|
10
|
+
## Decision
|
|
11
|
+
**Four retrieval modes, each optimized for a different query pattern:**
|
|
12
|
+
|
|
13
|
+
1. **Key-Value** — "What did I decide about X?" → exact match, deterministic, instant.
|
|
14
|
+
2. **Semantic** — "What do I know about pricing?" → similarity search, fuzzy, ranked.
|
|
15
|
+
3. **Graph** — "What's related to Acme Corp?" → traversal, structured relationships.
|
|
16
|
+
4. **Temporal** — "What did I learn yesterday?" → time-filtered scan.
|
|
17
|
+
|
|
18
|
+
The Context Curator (3.1) combines all four and ranks results by a weighted score.
|
|
19
|
+
|
|
20
|
+
## Consequences
|
|
21
|
+
- More complex curation logic than a single-mode system.
|
|
22
|
+
- Each mode has its own index (KV, vector, graph, timestamp), increasing storage.
|
|
23
|
+
- Agents get the right answer from the right access pattern instead of one-size-fits-all semantic search.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# ADR-006: Decision Memories Never Auto-Decay or Auto-Evict
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted
|
|
4
|
+
**Date:** 2026-05-04
|
|
5
|
+
**Modules affected:** 1.4, 3.3
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
The decay system reduces importance over time. But some memories are architecturally important to preserve indefinitely — particularly decisions and their reasoning.
|
|
9
|
+
|
|
10
|
+
## Decision
|
|
11
|
+
**Memories with `type=DECISION` are exempt from automatic decay and automatic eviction. They can only be manually deleted by the agent or developer.**
|
|
12
|
+
|
|
13
|
+
- Decisions are also exempt from auto-summarization. They are preserved verbatim.
|
|
14
|
+
- An agent can still manually reduce a decision's importance or delete it.
|
|
15
|
+
- This ensures that an agent can always answer "why did I choose X?" even weeks later.
|
|
16
|
+
|
|
17
|
+
## Consequences
|
|
18
|
+
- Decision entries accumulate over time. For very long-running projects, this could become large.
|
|
19
|
+
- The developer can explicitly archive old decisions if storage is a concern.
|
|
20
|
+
- The curation system still ranks decisions by relevance — old irrelevant decisions won't dominate the context window.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# ADR-007: Memory Content is Always String, Metadata is JSON-Serializable
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted
|
|
4
|
+
**Date:** 2026-05-04
|
|
5
|
+
**Modules affected:** 1.4, 1.1
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
Memories need to be embeddable (for semantic search), serializable (for export/import), and displayable (in curated context). Binary data, Python objects, and non-text content break all three.
|
|
9
|
+
|
|
10
|
+
## Decision
|
|
11
|
+
**`MemoryEntry.content` is always `str`. All metadata fields (tags, relationships, source) are JSON-serializable.** No binary data, no Python objects, no file references.
|
|
12
|
+
|
|
13
|
+
## Consequences
|
|
14
|
+
- Simple, predictable data model. Every memory can be embedded, exported, and displayed.
|
|
15
|
+
- Agents that need to reference files store the path/URL as a string, not the file itself.
|
|
16
|
+
- Structured data should be serialized to a readable string format before storing (e.g., JSON dump of a dict).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# ADR-008: Agent Identity Trusted from Orchestrator, Not Authenticated
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted
|
|
4
|
+
**Date:** 2026-05-04
|
|
5
|
+
**Modules affected:** 4.4, 4.1
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
Multi-agent memory requires knowing which agent is reading/writing. But Tulving is a library, not a service — it has no login system, no tokens, no auth server.
|
|
9
|
+
|
|
10
|
+
## Decision
|
|
11
|
+
**Tulving trusts the `agent_id` provided by the caller. It does not authenticate agents.**
|
|
12
|
+
|
|
13
|
+
- The orchestrator (Kairos, custom code, MCP server) is responsible for providing the correct agent_id.
|
|
14
|
+
- Tulving enforces scoping rules based on the provided agent_id, but does not verify identity.
|
|
15
|
+
- All operations are logged in the audit trail with the provided agent_id.
|
|
16
|
+
|
|
17
|
+
## Consequences
|
|
18
|
+
- Simple integration: no auth overhead.
|
|
19
|
+
- A malicious caller can impersonate any agent by providing a fake agent_id.
|
|
20
|
+
- This is acceptable because Tulving runs locally or within a trusted environment. If the caller is compromised, auth wouldn't help — they're already in the process.
|
|
21
|
+
- For hosted/remote deployments (future), a token-based auth layer should be added at the transport level (MCP server or API gateway), not at the Memory class level.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# ADR-009: Summarization Archives Originals, Never Destroys
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted
|
|
4
|
+
**Date:** 2026-05-04
|
|
5
|
+
**Modules affected:** 3.2, 3.3
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
When old memories are summarized into a digest, what happens to the originals? Deleting them saves space but is irreversible. Keeping them doubles storage.
|
|
9
|
+
|
|
10
|
+
## Decision
|
|
11
|
+
**Summarized entries are archived (soft-deleted), never hard-deleted. Archived entries are excluded from search and curation but remain in storage for recovery.**
|
|
12
|
+
|
|
13
|
+
- The summary entry links to its source entries via `relationships`.
|
|
14
|
+
- Archived entries can be unarchived manually.
|
|
15
|
+
- Hard-delete is available but must be explicitly called: `memory.delete(key, hard=True)`.
|
|
16
|
+
- A `purge_archived` CLI command handles bulk cleanup when storage is a concern.
|
|
17
|
+
|
|
18
|
+
## Consequences
|
|
19
|
+
- No data loss from automatic processes. All summarization is recoverable.
|
|
20
|
+
- Storage grows over time. For very long-running projects, periodic purging may be needed.
|
|
21
|
+
- Archived entries do not appear in search results, curated context, or key listings.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# ADR-010: Security as a First-Class Concern
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted
|
|
4
|
+
**Date:** 2026-05-04
|
|
5
|
+
**Modules affected:** All
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
Memory content may include sensitive data: API keys observed during work, personal information, credentials in error messages, proprietary business logic. Tulving must handle this safely.
|
|
9
|
+
|
|
10
|
+
## Decision
|
|
11
|
+
**Security controls are mandatory, enforced in code, never deferred. Same stance as Kairos ADR-016.**
|
|
12
|
+
|
|
13
|
+
### Mandatory Controls
|
|
14
|
+
|
|
15
|
+
1. **Sensitive key redaction.** Keys matching `DEFAULT_SENSITIVE_PATTERNS` (password, secret, token, key, credential, auth, api_key, private) are redacted in all exports, MCP tool responses, and curated context output. Raw values accessible only via direct `memory.get()`.
|
|
16
|
+
|
|
17
|
+
2. **Content sanitization.** Memory content is always `str` (ADR-007). No executable objects in storage.
|
|
18
|
+
|
|
19
|
+
3. **Path sanitization.** Memory paths, export file paths, and any file I/O validate against traversal attacks. Same rules as Kairos.
|
|
20
|
+
|
|
21
|
+
4. **Credential security.** Embedding and LLM adapter credentials from environment variables only. Inline credentials raise `SecurityError`.
|
|
22
|
+
|
|
23
|
+
5. **MCP server security.** Local-only binding. No network exposure. Memory path validated.
|
|
24
|
+
|
|
25
|
+
6. **Scope enforcement.** Multi-agent scoping raises `SecurityError` on unauthorized access, not silent empty results.
|
|
26
|
+
|
|
27
|
+
7. **Audit trail.** All store/read/update/delete operations logged with agent_id and timestamp.
|
|
28
|
+
|
|
29
|
+
## Consequences
|
|
30
|
+
- Every security control has tests in `tests/test_security.py`.
|
|
31
|
+
- Secure defaults. Insecure modes (e.g., disabling redaction) require explicit opt-in.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# ADR-011: Kairos is a Sibling, Not a Dependency
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted
|
|
4
|
+
**Date:** 2026-05-04
|
|
5
|
+
**Modules affected:** 5.1
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
Tulving and Kairos are natural complements. But making Tulving depend on Kairos (or vice versa) would force users to install both even if they only want one.
|
|
9
|
+
|
|
10
|
+
## Decision
|
|
11
|
+
**Tulving has zero dependency on Kairos. The Kairos integration (Module 5.1) is an optional extra: `pip install tulving[kairos]`.**
|
|
12
|
+
|
|
13
|
+
- Tulving works standalone. It doesn't need Kairos to function.
|
|
14
|
+
- Kairos works standalone. It doesn't need Tulving to function.
|
|
15
|
+
- When both are installed, `TulvingPlugin` provides seamless integration.
|
|
16
|
+
- The integration code lives in `tulving/integrations/kairos.py` and imports Kairos conditionally.
|
|
17
|
+
|
|
18
|
+
## Consequences
|
|
19
|
+
- Users can adopt one without the other.
|
|
20
|
+
- The integration module must handle the case where Kairos is not installed (graceful import error).
|
|
21
|
+
- Both SDKs share the same design philosophy (model-agnostic, security-first, Python-first) but have independent release cycles.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# ADR-012: MCP Tools Designed for Agent Ergonomics
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted
|
|
4
|
+
**Date:** 2026-05-04
|
|
5
|
+
**Modules affected:** 5.6
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
The MCP server exposes Tulving as tools that Claude Code (or any MCP client) calls. Tool design directly impacts how naturally an agent uses memory.
|
|
9
|
+
|
|
10
|
+
## Decision
|
|
11
|
+
**Tools are designed for how agents think, not how the SDK is structured.**
|
|
12
|
+
|
|
13
|
+
### Design Principles
|
|
14
|
+
|
|
15
|
+
1. **Descriptive names.** `memory_store`, `memory_search`, `memory_curate` — not `create_entry`, `vector_search`, `build_context`. The names match what an agent would naturally say: "let me store this" / "let me search for that."
|
|
16
|
+
|
|
17
|
+
2. **Minimal required parameters.** Only `content` + `type` required for `memory_store`. Everything else is optional with sensible defaults. An agent shouldn't need to think about importance scores or tags for a quick note.
|
|
18
|
+
|
|
19
|
+
3. **Rich optional parameters.** When the agent wants precision — specific tags, importance, key — the parameters are available but not forced.
|
|
20
|
+
|
|
21
|
+
4. **Context-ready output.** `memory_curate` returns formatted text ready to use as context, not raw JSON that the agent must parse and format. `memory_search` returns entries with relevance scores.
|
|
22
|
+
|
|
23
|
+
5. **One tool per intent.** `memory_store` and `memory_get` are separate tools, not one `memory_crud` tool with an `action` parameter. Each tool maps to one thing the agent wants to do.
|
|
24
|
+
|
|
25
|
+
6. **Tool descriptions guide agent behavior.** Descriptions include when and why to use the tool, not just what it does. Example: "Store a memory — a fact, decision, observation, or plan — for later retrieval."
|
|
26
|
+
|
|
27
|
+
## Consequences
|
|
28
|
+
- Tool count is higher (8 tools) than a minimal API would require.
|
|
29
|
+
- Each tool is simple and single-purpose — the agent doesn't need to read complex schemas.
|
|
30
|
+
- Claude Code and other MCP clients will naturally discover and use the right tool for the right situation.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# ADR-013: Three-Layer Session Detection with Graceful Degradation
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted
|
|
4
|
+
**Date:** 2026-05-04
|
|
5
|
+
**Modules affected:** 3.5, 5.1, 5.6, Memory class
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
Tulving is used in three modes: as a standalone Python SDK, as a Kairos plugin, and as an MCP server for Claude Code. Each mode has different session boundary signals. A standalone SDK has no natural "session ended" event — the developer's process might exit without warning.
|
|
12
|
+
|
|
13
|
+
Without session management, memory grows unbounded and end-of-session summarization never triggers.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
**Three session boundary mechanisms, layered from most reliable to least:**
|
|
18
|
+
|
|
19
|
+
1. **Explicit API** — `memory.session_start()` / `session.end()` or `with memory.session():` context manager. Works in all modes. The developer controls the boundary.
|
|
20
|
+
|
|
21
|
+
2. **Integration hooks** — MCP server shutdown (SIGTERM/SIGINT) and Kairos `on_workflow_complete` call `session.end()` internally. Automatic for those modes.
|
|
22
|
+
|
|
23
|
+
3. **Activity-gap detection** — On next `Memory.__init__`, detect unclosed sessions by checking for `status=ACTIVE` sessions with no recent activity (configurable `inactivity_threshold`, default 30 minutes). Run end-of-session summarization on the abandoned session's memories. Automatic fallback for ungraceful exits.
|
|
24
|
+
|
|
25
|
+
Each layer degrades gracefully to the next. If the developer calls `session.end()`, that's the boundary. If they don't but the MCP server shuts down cleanly, the hook handles it. If the process crashes, activity-gap detection catches it on next startup.
|
|
26
|
+
|
|
27
|
+
## Consequences
|
|
28
|
+
|
|
29
|
+
- Every mode gets session management — no mode is left without lifecycle support.
|
|
30
|
+
- Explicit API is the preferred path, documented prominently.
|
|
31
|
+
- Activity-gap detection introduces a small delay on startup (scanning for abandoned sessions). Acceptable for the reliability it provides.
|
|
32
|
+
- The 30-minute default threshold may misidentify long pauses during active work as session boundaries. Configurable via `LifecycleConfig.inactivity_threshold`.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# ADR-014: Contradiction Detection Flags, Not Blocks
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted
|
|
4
|
+
**Date:** 2026-05-04
|
|
5
|
+
**Modules affected:** 3.5, 1.2
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
Agents store facts that may later become incorrect or contradicted by new information. The system needs to handle the case where "Acme has 3 products" is stored on Monday and "Acme has 5 products" is stored on Thursday.
|
|
12
|
+
|
|
13
|
+
Two approaches: block the conflicting store and force resolution, or accept the store and flag the contradiction.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
**Contradictions are detected and flagged, not blocked.** The default policy is `flag`.
|
|
18
|
+
|
|
19
|
+
- **Key collisions** (same key, new value): the old entry is archived with a `superseded` tag, the new entry is stored with a `supersedes:{old_id}` relationship. This is an upsert — deterministic, no ambiguity.
|
|
20
|
+
|
|
21
|
+
- **Semantic contradictions** (different keys, conflicting content): detected by checking semantic similarity on store. If similarity > 0.85 and content diverges, both entries are tagged `contradiction:unresolved`. The agent or developer resolves manually.
|
|
22
|
+
|
|
23
|
+
- **Staleness**: memories not accessed for `staleness_threshold_days` (default 30) are tagged `potentially_stale`. The curator annotates them with age when included in curated context. The agent sees the warning and can verify, update, or discard.
|
|
24
|
+
|
|
25
|
+
## Consequences
|
|
26
|
+
|
|
27
|
+
- Stores never fail due to contradictions — the system is always accepting.
|
|
28
|
+
- Contradictions surface as tags, not errors — the agent or developer decides resolution.
|
|
29
|
+
- Staleness is a soft signal, not a hard rule — old memories are deprioritized, not deleted.
|
|
30
|
+
- The `ask` contradiction policy is available for high-stakes scenarios where the developer wants the store to pause and return the contradiction for explicit resolution.
|