engrm 0.1.0

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.
Files changed (82) hide show
  1. package/.mcp.json +9 -0
  2. package/AUTH-DESIGN.md +436 -0
  3. package/BRIEF.md +197 -0
  4. package/CLAUDE.md +44 -0
  5. package/COMPETITIVE.md +174 -0
  6. package/CONTEXT-OPTIMIZATION.md +305 -0
  7. package/INFRASTRUCTURE.md +252 -0
  8. package/LICENSE +105 -0
  9. package/MARKET.md +230 -0
  10. package/PLAN.md +278 -0
  11. package/README.md +121 -0
  12. package/SENTINEL.md +293 -0
  13. package/SERVER-API-PLAN.md +553 -0
  14. package/SPEC.md +843 -0
  15. package/SWOT.md +148 -0
  16. package/SYNC-ARCHITECTURE.md +294 -0
  17. package/VIBE-CODER-STRATEGY.md +250 -0
  18. package/bun.lock +375 -0
  19. package/hooks/post-tool-use.ts +144 -0
  20. package/hooks/session-start.ts +64 -0
  21. package/hooks/stop.ts +131 -0
  22. package/mem-page.html +1305 -0
  23. package/package.json +30 -0
  24. package/src/capture/dedup.test.ts +103 -0
  25. package/src/capture/dedup.ts +76 -0
  26. package/src/capture/extractor.test.ts +245 -0
  27. package/src/capture/extractor.ts +330 -0
  28. package/src/capture/quality.test.ts +168 -0
  29. package/src/capture/quality.ts +104 -0
  30. package/src/capture/retrospective.test.ts +115 -0
  31. package/src/capture/retrospective.ts +121 -0
  32. package/src/capture/scanner.test.ts +131 -0
  33. package/src/capture/scanner.ts +100 -0
  34. package/src/capture/scrubber.test.ts +144 -0
  35. package/src/capture/scrubber.ts +181 -0
  36. package/src/cli.ts +517 -0
  37. package/src/config.ts +238 -0
  38. package/src/context/inject.test.ts +940 -0
  39. package/src/context/inject.ts +382 -0
  40. package/src/embeddings/backfill.ts +50 -0
  41. package/src/embeddings/embedder.test.ts +76 -0
  42. package/src/embeddings/embedder.ts +139 -0
  43. package/src/lifecycle/aging.test.ts +103 -0
  44. package/src/lifecycle/aging.ts +36 -0
  45. package/src/lifecycle/compaction.test.ts +264 -0
  46. package/src/lifecycle/compaction.ts +190 -0
  47. package/src/lifecycle/purge.test.ts +100 -0
  48. package/src/lifecycle/purge.ts +37 -0
  49. package/src/lifecycle/scheduler.test.ts +120 -0
  50. package/src/lifecycle/scheduler.ts +101 -0
  51. package/src/provisioning/browser-auth.ts +172 -0
  52. package/src/provisioning/provision.test.ts +198 -0
  53. package/src/provisioning/provision.ts +94 -0
  54. package/src/register.test.ts +167 -0
  55. package/src/register.ts +178 -0
  56. package/src/server.ts +436 -0
  57. package/src/storage/migrations.test.ts +244 -0
  58. package/src/storage/migrations.ts +261 -0
  59. package/src/storage/outbox.test.ts +229 -0
  60. package/src/storage/outbox.ts +131 -0
  61. package/src/storage/projects.test.ts +137 -0
  62. package/src/storage/projects.ts +184 -0
  63. package/src/storage/sqlite.test.ts +798 -0
  64. package/src/storage/sqlite.ts +934 -0
  65. package/src/storage/vec.test.ts +198 -0
  66. package/src/sync/auth.test.ts +76 -0
  67. package/src/sync/auth.ts +68 -0
  68. package/src/sync/client.ts +183 -0
  69. package/src/sync/engine.test.ts +94 -0
  70. package/src/sync/engine.ts +127 -0
  71. package/src/sync/pull.test.ts +279 -0
  72. package/src/sync/pull.ts +170 -0
  73. package/src/sync/push.test.ts +117 -0
  74. package/src/sync/push.ts +230 -0
  75. package/src/tools/get.ts +34 -0
  76. package/src/tools/pin.ts +47 -0
  77. package/src/tools/save.test.ts +301 -0
  78. package/src/tools/save.ts +231 -0
  79. package/src/tools/search.test.ts +69 -0
  80. package/src/tools/search.ts +181 -0
  81. package/src/tools/timeline.ts +64 -0
  82. package/tsconfig.json +22 -0
package/SWOT.md ADDED
@@ -0,0 +1,148 @@
1
+ # SWOT Analysis — Engrm
2
+
3
+ ## Strengths
4
+
5
+ ### S1: Own the Full Stack
6
+ We control both the plugin (Engrm) and the backend (Candengo Vector). No dependency on third-party vector DB pricing, availability, or API changes. We can optimise the entire pipeline end-to-end.
7
+
8
+ ### S2: Production-Grade Vector Search
9
+ Candengo Vector uses BGE-M3 (state-of-the-art multilingual embeddings) with hybrid dense+sparse search and optional cross-encoder reranking. This is measurably superior to ChromaDB's default embeddings. Better search = more relevant memories surfaced = better developer experience.
10
+
11
+ ### S3: Self-Hosted / Privacy-First
12
+ Developers and enterprises increasingly resist sending code context to third-party clouds. Candengo Vector can be self-hosted on-premise. No code leaves the organisation's infrastructure.
13
+
14
+ ### S4: Offline-First Architecture
15
+ SQLite as local source of truth with sync outbox means the system works perfectly without internet. This is critical for developers who work on trains, planes, coffee shops, or behind corporate firewalls.
16
+
17
+ ### S5: Multi-Tenant from Day One
18
+ Candengo Vector's site_id/namespace model was built for multi-tenancy. Team memory, per-project isolation, and cross-project discovery are architectural features, not afterthoughts.
19
+
20
+ ### S6: Workpack Ecosystem
21
+ No competitor has curated knowledge packs. Workpacks transform the product from "memory" to "memory + expertise" — a significantly more valuable proposition.
22
+
23
+ ### S7: Existing Infrastructure
24
+ Candengo Vector is already running in production with ingest, search, query, and admin APIs. We're building on proven infrastructure, not starting from scratch.
25
+
26
+ ### S8: Market Timing
27
+ The AI coding agent market is in explosive growth (Claude Code, OpenClaw 100k+ stars, Cursor, Windsurf). Memory is the #1 requested feature across all agent communities. First mover with a cross-device, cross-agent solution captures the category.
28
+
29
+ ---
30
+
31
+ ## Weaknesses
32
+
33
+ ### W1: No Existing User Base for Memory Products
34
+ Candengo's current customers use it for domain knowledge RAG (hospitality, business intelligence). Developer tooling is a new market for us — different buyer persona, different distribution channels.
35
+
36
+ ### W2: MCP Ecosystem Immaturity
37
+ The Model Context Protocol is young. OpenClaw's MCP support is still Phase 0 (merged Feb 2026). Breaking changes to MCP could require rework. Agent-specific plugin formats may fragment the market.
38
+
39
+ ### W3: Small Team
40
+ Building and maintaining plugins for multiple agents (Claude Code, OpenClaw, future agents) requires ongoing effort across different ecosystems, languages (TypeScript, Python), and release cycles.
41
+
42
+ ### W4: Developer Tooling Distribution
43
+ Reaching developers requires different go-to-market than enterprise SaaS. GitHub presence, developer relations, documentation quality, and community engagement are table stakes. This is a capability we need to build.
44
+
45
+ ### W5: Observation Quality Dependency
46
+ The value of shared memory depends on the quality of captured observations. If the extraction produces noisy, redundant, or inaccurate observations, shared memory amplifies noise rather than signal. Quality filtering is essential but hard to get right.
47
+
48
+ ### W6: Candengo Vector Search Limitations
49
+ Currently no metadata field filtering in the search API (only site_id, namespace, source_type). This limits query flexibility. Needs to be added before launch.
50
+
51
+ ---
52
+
53
+ ## Opportunities
54
+
55
+ ### O1: Cross-Agent Memory Standard
56
+ If we establish Engrm as the de facto shared memory layer, we become the "Twilio of agent memory" — the infrastructure everyone builds on. The MCP standard makes this possible by providing a common interface.
57
+
58
+ ### O2: Workpack Marketplace Revenue
59
+ Curated knowledge packs (security, testing, framework patterns, compliance) are recurring revenue with high margins. Enterprise customers will pay for proprietary workpacks and custom knowledge curation.
60
+
61
+ ### O3: Auto-Generated Workpacks
62
+ With enough observations across users (anonymised, opt-in), we can detect cross-cutting patterns and automatically generate workpacks. "90% of FastAPI projects hit this CORS issue" → auto-curated pattern. This creates a data flywheel that competitors can't replicate.
63
+
64
+ ### O4: Team Analytics Dashboard
65
+ Visibility into team knowledge patterns: "What are the most common issues?" "Which areas have knowledge gaps?" "How is AI-assisted productivity trending?" This is valuable to engineering managers and CTOs.
66
+
67
+ ### O5: Enterprise Compliance
68
+ SOC 2, GDPR, on-premise deployment. Enterprise engineering teams want AI tools but face compliance barriers. Self-hosted Engrm with audit logging and data residency controls addresses this directly.
69
+
70
+ ### O6: Integration with Alchemy Platform
71
+ AIMY (our conversational AI) + Engrm creates a powerful combination: AIMY conducts project interviews, stores context in Candengo Vector, and all AI agents across the platform share that knowledge. End-to-end Alchemy integration is a unique selling point.
72
+
73
+ ### O7: OpenClaw's Massive Community
74
+ OpenClaw has 100k+ GitHub stars and a rapidly growing community that's actively looking for memory solutions. Being an early, high-quality memory plugin for OpenClaw could drive massive adoption.
75
+
76
+ ### O8: CI/CD and DevOps Integration
77
+ Beyond coding agents, the memory layer could capture observations from CI/CD pipelines, deployment logs, incident reports. "Last time this test failed, the fix was..." — extending memory beyond interactive sessions.
78
+
79
+ ### O9: Language and Framework Workpacks
80
+ Partner with framework communities to create official workpacks: "Django Best Practices by Django Core Team", "React Patterns by Meta Engineers". Co-branded content drives distribution and credibility.
81
+
82
+ ---
83
+
84
+ ## Threats
85
+
86
+ ### T1: Anthropic / OpenAI Building Native Memory
87
+ If Claude Code or ChatGPT build first-party cross-device memory, our plugin becomes redundant for those platforms. Mitigation: cross-agent support (no single-platform dependency), self-hosted differentiation, workpack ecosystem as defensible moat.
88
+
89
+ ### T2: claude-mem Going Cross-Device
90
+ claude-mem already has remote Chroma support in its config. If the maintainer adds cross-device sync, our Claude Code differentiation weakens. Mitigation: superior search quality (BGE-M3 vs ChromaDB defaults), team features, and multi-agent support. Our clean-room build means no licensing entanglement regardless.
91
+
92
+ ### T3: mem0 Capturing the Market
93
+ mem0 has funding, brand recognition, and multi-agent support. If they move fast on cross-device and self-hosted options, they could capture the market before us. Mitigation: self-hosted positioning (mem0 is SaaS-only), workpack ecosystem, developer trust through open-source plugin.
94
+
95
+ ### T4: MCP Standard Fragmentation
96
+ If major agents abandon MCP for proprietary plugin formats, our "write once, work everywhere" value proposition breaks. Mitigation: the MCP standard has strong momentum (Anthropic backing, broad adoption), and we can always add agent-specific adapters.
97
+
98
+ ### T5: Privacy Concerns with Shared Memory
99
+ Developers may resist syncing their code observations to any remote server, even self-hosted. Observations inevitably capture code patterns, file paths, and problem descriptions. Mitigation: secret scrubbing, sensitivity classification, clear data policies, and the self-hosted option.
100
+
101
+ ### T6: Backend Substitution
102
+ Someone forks the plugin and swaps Candengo Vector for Pinecone/Weaviate/etc., offering a competing service. Mitigation: FSL-1.1-ALv2 license explicitly prohibits competing uses. Developers can self-host with Candengo Vector (encouraged), but cannot build a competing hosted product. Sentinel (the premium AI audit feature) is in a separate private repo, not published. The deep Candengo Vector integration (provisioning, account routing, hybrid search pipeline) also makes casual swaps non-trivial.
103
+
104
+ ### T7: Quality at Scale
105
+ As team sizes grow, observation volume increases. Without good quality filtering, relevance decay, and deduplication, search results degrade. This is a hard problem that requires ongoing investment.
106
+
107
+ ---
108
+
109
+ ## Strategic Position Summary
110
+
111
+ ```
112
+ HIGH IMPACT
113
+
114
+ ┌─────────────┼─────────────┐
115
+ │ THREATS │ OPPORTUNITIES│
116
+ │ │ │
117
+ │ T1: Native │ O1: Memory │
118
+ │ platform │ standard │
119
+ │ memory │ │
120
+ │ │ O2: Workpack │
121
+ │ T3: mem0 │ marketplace │
122
+ │ momentum │ │
123
+ │ │ O7: OpenClaw │
124
+ │ │ community │
125
+ ├─────────────┼──────────────┤
126
+ │ WEAKNESSES │ STRENGTHS │
127
+ │ │ │
128
+ │ W1: New │ S1: Full │
129
+ │ market │ stack │
130
+ │ │ │
131
+ │ W4: Dev │ S2: Superior │
132
+ │ distrib. │ search │
133
+ │ │ │
134
+ │ W3: Small │ S4: Offline │
135
+ │ team │ first │
136
+ │ │ │
137
+ └─────────────┼──────────────┘
138
+
139
+ LOW IMPACT
140
+ ```
141
+
142
+ ## Key Strategic Moves
143
+
144
+ 1. **Lead with open-source plugin** → drives adoption, builds trust, creates community
145
+ 2. **Differentiate on self-hosted + offline-first** → mem0 can't match this
146
+ 3. **Workpacks as moat** → unique value that compounds over time
147
+ 4. **OpenClaw community first** → 100k+ stars, actively seeking memory solutions
148
+ 5. **Team features from day one** → enterprise upsell path built in
@@ -0,0 +1,294 @@
1
+ # Sync Architecture — Engrm
2
+
3
+ ## Date: 2026-03-10
4
+ ## Status: Reviewed & Confirmed
5
+
6
+ ---
7
+
8
+ ## Overview
9
+
10
+ Bidirectional sync between local SQLite instances and Candengo Vector, enabling cross-device and cross-agent team memory. Every device maintains a full local cache — search is always local-first and fast, even offline.
11
+
12
+ ```
13
+ Device A (Claude Code) Device B (Codex CLI)
14
+ ┌───────────────────┐ ┌───────────────────┐
15
+ │ SQLite (primary) │───push──→ │ SQLite (primary) │───push──→
16
+ │ FTS5 search │ │ │ FTS5 search │ │
17
+ │ offline-first │←──pull───┤ │ offline-first │←──pull───┤
18
+ └───────────────────┘ │ └───────────────────┘ │
19
+ ▼ ▼
20
+ ┌──────────────────────────┐
21
+ │ Candengo Vector │
22
+ │ + Sync Metadata Layer │
23
+ │ BGE-M3 embeddings │
24
+ │ hybrid search │
25
+ └──────────────────────────┘
26
+ ```
27
+
28
+ ---
29
+
30
+ ## Confirmed Decisions
31
+
32
+ ### 1. SQLite is Source of Truth Per-Device
33
+
34
+ **Status**: Confirmed ✓
35
+
36
+ - Each device has its own SQLite with WAL mode, FTS5 external content
37
+ - Offline-first: all operations work without network
38
+ - Vector downtime never blocks local operations
39
+ - Push failures queue in outbox with exponential backoff
40
+
41
+ ### 2. Candengo Vector is the Sync Hub (Not Queried at Search Time)
42
+
43
+ **Status**: Confirmed with modification ✓
44
+
45
+ - Vector stores embeddings + metadata for team-wide semantic search (future Phase 4+)
46
+ - **Change**: Add a thin **sync metadata layer** rather than overloading Vector with sync-specific queries
47
+ - Sync metadata tracks: `(source_id, ingested_at_server, action, payload_json)`
48
+ - This decouples the sync protocol from the vector search engine
49
+ - Vector remains a search index; sync metadata is the replication log
50
+
51
+ **Rationale**: Vector databases are optimised for similarity search, not for "list all documents modified since X". A separate sync metadata table (in the Candengo web backend) is cleaner and more maintainable.
52
+
53
+ ### 3. Same MCP Server for All Agents
54
+
55
+ **Status**: Confirmed ✓
56
+
57
+ Validated working with:
58
+ - Claude Code (`.mcp.json`, stdio) — **tested live**
59
+ - Codex CLI (`config.toml`, stdio) — **tested live, all 6 tools working**
60
+ - Cursor, Windsurf, Cline, VS Code Copilot, Zed (all MCP stdio compatible)
61
+
62
+ **Change**: Auto-detect agent from MCP `clientInfo` during `initialize` handshake instead of hardcoding `"claude-code"`. The protocol already exchanges this — we just need to read it.
63
+
64
+ **No agent-specific logic in the MCP server.** Hooks are agent-specific by nature (different agents have different hook systems), but the MCP server stays generic.
65
+
66
+ ### 4. Token-Budgeted Context with Blended Scoring
67
+
68
+ **Status**: Confirmed with modifications ✓
69
+
70
+ - Token budget (default 800) — implemented Sprint 1
71
+ - Blended scoring: quality * 0.6 + recency * 0.4 — implemented Sprint 2
72
+ - Tiered output: top 3 detailed (facts-first), rest title-only — implemented Sprint 1
73
+
74
+ **Changes**:
75
+ - Make `token_budget` and quality/recency weights **configurable** in settings.json
76
+ - Cap pinned observations at **5 detailed** in context injection (prevent pinned observations consuming entire budget)
77
+ - CWD-aware boosting deferred to Phase 4 (dogfood)
78
+
79
+ ### 5. Knowledge Supersession
80
+
81
+ **Status**: Confirmed with modification ✓
82
+
83
+ - `superseded_by` column, manual agent-initiated supersession — implemented Sprint 2
84
+
85
+ **Change**: Allow supersession **chains** (depth 2-3) instead of blocking already-superseded observations. When superseding, resolve to the current chain head automatically:
86
+ ```
87
+ Agent says: "supersede #1"
88
+ #1 already superseded by #2
89
+ → System resolves: supersede #2 (the chain head) instead
90
+ → All previous versions (#1, #2) remain archived
91
+ ```
92
+
93
+ **Change**: Add supersession events to the **sync outbox** — lifecycle changes (not just new observations) need to propagate to other devices.
94
+
95
+ **Keep manual**: Automatic supersession (detecting same topic) is too risky — title similarity could accidentally supersede unrelated observations. Revisit in Phase 4.
96
+
97
+ ### 6. Bidirectional Sync Protocol
98
+
99
+ **Status**: Design confirmed ✓
100
+
101
+ See detailed design below.
102
+
103
+ ---
104
+
105
+ ## Push Protocol (Local → Vector)
106
+
107
+ Already designed in PLAN.md Phase 3.2. No changes.
108
+
109
+ ```
110
+ 1. Observation saved to local SQLite
111
+ 2. Added to sync_outbox (status: pending)
112
+ 3. Background timer (every 30s): flush pending outbox items
113
+ 4. POST /v1/ingest with observation data + metadata
114
+ 5. On success: mark outbox item as synced
115
+ 6. On failure: exponential backoff (30s, 60s, 120s, max 5min)
116
+ 7. Source ID: {user_id}-{device_id}-obs-{local_id}
117
+ ```
118
+
119
+ **New**: Also push lifecycle changes (supersession, archival) to a sync change feed endpoint, not just new observations.
120
+
121
+ ---
122
+
123
+ ## Pull Protocol (Vector → Local)
124
+
125
+ ### Change Feed Approach
126
+
127
+ **Do NOT use `/v1/search` for pull.** Search is "find relevant documents for a query." Pull is "give me all changes since cursor X." These are fundamentally different.
128
+
129
+ **Endpoint**: `GET /v1/sync/changes?cursor=X&namespace=Y&limit=1000`
130
+
131
+ Returns a stream of change events:
132
+ ```json
133
+ {
134
+ "changes": [
135
+ {
136
+ "cursor": "2026-03-10T16:00:00.000Z",
137
+ "source_id": "david-macbook-obs-42",
138
+ "action": "create",
139
+ "payload": { /* full observation data as JSON */ }
140
+ },
141
+ {
142
+ "cursor": "2026-03-10T16:05:00.000Z",
143
+ "source_id": "david-macbook-obs-42",
144
+ "action": "supersede",
145
+ "superseded_by_source_id": "david-macbook-obs-55"
146
+ }
147
+ ],
148
+ "next_cursor": "2026-03-10T16:05:00.000Z",
149
+ "has_more": false
150
+ }
151
+ ```
152
+
153
+ ### Critical: Server-Side Cursor, Not Client Timestamps
154
+
155
+ **Do NOT use client-side `created_at_epoch` as the high-water-mark.** Clock skew between devices means observations can arrive at Vector with misleading timestamps.
156
+
157
+ Use **server-assigned ingestion timestamp** (`cursor`) as the ordering key. This is monotonic and eliminates clock skew issues.
158
+
159
+ ### Pull Flow
160
+
161
+ ```
162
+ 1. On startup: read last_pull_cursor from sync_state table
163
+ 2. GET /v1/sync/changes?cursor=last_pull_cursor&namespace=N&limit=1000
164
+ 3. For each change:
165
+ a. Parse source_id → extract user_id, device_id, local_id
166
+ b. Skip if source_id matches current device (it's our own data)
167
+ c. If action=create:
168
+ - Check remote_observations table for existing source_id
169
+ - If exists: update (in case of re-push after edit)
170
+ - If new: insert into observations + FTS5 index
171
+ - Record mapping in remote_observations table
172
+ d. If action=supersede:
173
+ - Look up local_id for superseded source_id
174
+ - Apply supersession locally (archive, remove from FTS)
175
+ e. If action=delete:
176
+ - Look up and remove locally
177
+ 4. Update last_pull_cursor in sync_state
178
+ 5. If has_more: repeat from step 2 (pagination)
179
+ ```
180
+
181
+ ### Pull Frequency
182
+
183
+ - **On startup**: Paginated backfill (1000 at a time, non-blocking)
184
+ - **Periodic**: Every 60 seconds (less frequent than push at 30s — pull is less latency-sensitive)
185
+ - **On-demand**: Not needed initially
186
+
187
+ ### First Install Backfill
188
+
189
+ New device joining a team should NOT slam all observations into SQLite at once. Instead:
190
+ - Pull in pages of 1000, oldest first
191
+ - Update cursor after each page
192
+ - First session can start immediately with whatever has been pulled so far
193
+ - Background continues pulling remaining pages
194
+
195
+ ### Pull Scope
196
+
197
+ Pull **ALL projects** for the user's namespace, not just the current CWD project. Reason: switching directories shouldn't require a re-pull. The data is small and lifecycle management keeps it bounded.
198
+
199
+ ---
200
+
201
+ ## New Schema: Remote Observations Mapping
202
+
203
+ Migration v3:
204
+
205
+ ```sql
206
+ CREATE TABLE remote_observations (
207
+ source_id TEXT PRIMARY KEY, -- {user_id}-{device_id}-obs-{local_id}
208
+ local_id INTEGER NOT NULL, -- local observations.id
209
+ pulled_at_epoch INTEGER NOT NULL -- when we pulled it
210
+ );
211
+
212
+ CREATE INDEX idx_remote_obs_local ON remote_observations(local_id);
213
+ ```
214
+
215
+ This maps between remote identity (source_id) and local autoincrement ID. Needed for:
216
+ - Dedup on pull (don't re-insert what we already have)
217
+ - Applying remote supersession (look up local_id from source_id)
218
+ - Identifying which observations are "ours" vs "theirs"
219
+
220
+ ---
221
+
222
+ ## Gotchas & Mitigations
223
+
224
+ ### 1. Clock Skew Between Devices
225
+
226
+ **Risk**: Two machines with different system clocks produce misleading `created_at_epoch` values.
227
+ **Mitigation**: Sync protocol uses server-assigned timestamps for ordering, never client timestamps. Client `created_at_epoch` is preserved for display only.
228
+
229
+ ### 2. SQLite Concurrent Access (Hooks vs MCP Server)
230
+
231
+ **Risk**: Hook processes open separate `MemDatabase` instances. If the MCP server is simultaneously writing, lock contention can occur.
232
+ **Mitigation**: WAL mode allows concurrent reads. For writes, SQLite's built-in locking handles this — hooks are short-lived and writes are fast. Monitor during dogfood. If contention becomes an issue, have hooks communicate via a local queue file instead of opening the DB directly.
233
+
234
+ ### 3. Storage Growth from Full Pull
235
+
236
+ **Risk**: 5-person team × 100 obs/day × 3 months = 45K observations cached locally (90-225MB).
237
+ **Mitigation**: Lifecycle management (aging → archival → purge) bounds growth. Compacted observations are much smaller. Consider pulling **metadata-only** for team observations (not your own), with lazy detail fetch via `get_observations` — would cut pull bandwidth and storage by ~80%.
238
+
239
+ ### 4. FTS5 External Content Mode
240
+
241
+ **Risk**: If observations are updated (not just superseded), FTS5 index must be manually updated.
242
+ **Mitigation**: Current code handles insert and delete. Add update logic when we implement "merge facts into existing observation" (the dedup merge path).
243
+
244
+ ### 5. Schema Evolution vs Vector Metadata
245
+
246
+ **Risk**: New SQLite columns (e.g., `superseded_by`) may not exist in Vector metadata.
247
+ **Mitigation**: Never rely on Vector metadata for anything except search filtering. The sync metadata layer stores the full observation as JSON — that's the pull source, not Vector's chunked content.
248
+
249
+ ### 6. Secret Observations
250
+
251
+ **Risk**: `sensitivity: "secret"` observations are never synced but stored in plaintext locally.
252
+ **Mitigation**: Acceptable for Phase 3. Consider encrypting narrative/facts for secret observations in Phase 5 (public launch).
253
+
254
+ ### 7. Disaster Recovery
255
+
256
+ **Risk**: If Vector loses data, no mechanism to reconstruct.
257
+ **Mitigation**: Add `engrm sync --full` CLI command that re-pushes all local observations. Since each device has its own data, all devices running `--full` reconstructs the complete dataset.
258
+
259
+ ---
260
+
261
+ ## Implementation Order
262
+
263
+ | Step | Description | Blocks |
264
+ |------|-------------|--------|
265
+ | 1 | Auto-detect agent from MCP `clientInfo` | Nothing |
266
+ | 2 | Make token_budget + scoring weights configurable | Nothing |
267
+ | 3 | Fix supersession chains (resolve to head) | Step 5 |
268
+ | 4 | Build Candengo Vector REST client (`src/sync/client.ts`) | Step 5, 7 |
269
+ | 5 | Implement push engine (outbox flush + lifecycle events) | Step 7 |
270
+ | 6 | Design sync metadata endpoint on Candengo backend | Step 7 |
271
+ | 7 | Implement pull engine (cursor-based, paginated) | Nothing |
272
+ | 8 | Add `remote_observations` mapping table (migration v3) | Step 7 |
273
+ | 9 | Add `engrm sync --full` disaster recovery | Nothing |
274
+ | 10 | Multi-agent `init` CLI (Claude Code, Codex, Cursor) | Nothing |
275
+
276
+ Steps 1-3 can be done immediately (no server-side dependencies).
277
+ Steps 4-8 are Phase 3 core (require Candengo Vector API prep).
278
+ Steps 9-10 are Phase 3.5 (polish).
279
+
280
+ ---
281
+
282
+ ## Multi-Agent Compatibility
283
+
284
+ | Agent | Config Format | Config Location | Hook Support | Status |
285
+ |-------|--------------|-----------------|-------------|--------|
286
+ | Claude Code | JSON | `.mcp.json` | PostToolUse, Stop, SessionStart | Live ✓ |
287
+ | Codex CLI | TOML | `~/.codex/config.toml` | TBD (different hook system) | MCP verified ✓ |
288
+ | Cursor | UI Settings | Cursor settings | None (MCP tools only) | Compatible |
289
+ | Windsurf | UI Settings | Windsurf settings | None (MCP tools only) | Compatible |
290
+ | Cline | JSON | VS Code settings | None (MCP tools only) | Compatible |
291
+ | VS Code Copilot | JSON | VS Code settings | None (MCP tools only) | Compatible |
292
+ | Zed | JSON | Zed settings | None (MCP tools only) | Compatible |
293
+
294
+ **Key insight**: Agents without hook support can still use all MCP tools manually. The agent calls `save_observation` explicitly instead of auto-capturing via hooks. Context injection works via `session_context` tool call (most agents support "tool use on session start" or similar).