superlocalmemory 2.5.1 → 2.6.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.
- package/README.md +86 -71
- package/api_server.py +47 -0
- package/docs/architecture-diagram.drawio +4 -4
- package/docs/plans/2026-02-13-benchmark-suite.md +1349 -0
- package/mcp_server.py +72 -17
- package/package.json +3 -3
- package/src/agent_registry.py +34 -1
- package/src/auth_middleware.py +63 -0
- package/src/cache_manager.py +1 -1
- package/src/db_connection_manager.py +16 -2
- package/src/event_bus.py +15 -0
- package/src/graph_engine.py +113 -44
- package/src/hybrid_search.py +2 -2
- package/src/memory-reset.py +17 -3
- package/src/memory_store_v2.py +80 -7
- package/src/rate_limiter.py +87 -0
- package/src/trust_scorer.py +38 -6
- package/src/webhook_dispatcher.py +17 -0
- package/ui_server.py +55 -1
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="https://
|
|
2
|
+
<img src="https://superlocalmemory.com/assets/branding/icon-512.png" alt="SuperLocalMemory V2" width="200"/>
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<h1 align="center">SuperLocalMemory V2</h1>
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
<strong>Stop re-explaining your codebase every session. 100% local. Zero setup. Completely free.</strong>
|
|
15
15
|
</p>
|
|
16
16
|
|
|
17
|
+
<p align="center">
|
|
18
|
+
<a href="https://superlocalmemory.com"><img src="https://img.shields.io/badge/🌐_Website-superlocalmemory.com-ff6b35?style=for-the-badge" alt="Official Website"/></a>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
17
21
|
<p align="center">
|
|
18
22
|
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.8+-3776AB?style=flat-square&logo=python&logoColor=white" alt="Python 3.8+"/></a>
|
|
19
23
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="MIT License"/></a>
|
|
@@ -24,6 +28,7 @@
|
|
|
24
28
|
</p>
|
|
25
29
|
|
|
26
30
|
<p align="center">
|
|
31
|
+
<a href="https://superlocalmemory.com"><strong>superlocalmemory.com</strong></a> •
|
|
27
32
|
<a href="#-quick-start">Quick Start</a> •
|
|
28
33
|
<a href="#-why-superlocalemory">Why This?</a> •
|
|
29
34
|
<a href="#-features">Features</a> •
|
|
@@ -40,24 +45,26 @@
|
|
|
40
45
|
|
|
41
46
|
---
|
|
42
47
|
|
|
43
|
-
## NEW: v2.
|
|
48
|
+
## NEW: v2.6 — Security Hardening & Performance
|
|
49
|
+
|
|
50
|
+
> **SuperLocalMemory is now production-hardened with trust enforcement, rate limiting, and accelerated graph building.**
|
|
44
51
|
|
|
45
|
-
|
|
52
|
+
| What's New in v2.6 | Why It Matters |
|
|
53
|
+
|---------------------|----------------|
|
|
54
|
+
| **Trust Enforcement** | Agents with trust below 0.3 are blocked from write/delete — Bayesian scoring now actively protects your memory. |
|
|
55
|
+
| **Profile Isolation** | Memory profiles are fully sandboxed — no cross-profile data leakage. |
|
|
56
|
+
| **Rate Limiting** | Protects against memory flooding and spam from misbehaving agents. |
|
|
57
|
+
| **SSRF Protection** | Webhook dispatcher validates URLs to prevent server-side request forgery. |
|
|
58
|
+
| **HNSW-Accelerated Graphs** | Knowledge graph edge building uses HNSW index for faster construction at scale. |
|
|
59
|
+
| **Hybrid Search Engine** | Combined semantic + FTS5 + graph retrieval for maximum accuracy. |
|
|
46
60
|
|
|
47
|
-
|
|
48
|
-
|------------|----------------|
|
|
49
|
-
| **Real-Time Event Stream** | See every memory operation live in the dashboard — no refresh needed. SSE-powered, cross-process. |
|
|
50
|
-
| **No More "Database Locked"** | WAL mode + serialized write queue. 50 concurrent agents writing? Zero errors. |
|
|
51
|
-
| **Agent Tracking** | Know exactly which AI tool wrote what. Claude, Cursor, Windsurf, CLI — all tracked automatically. |
|
|
52
|
-
| **Trust Scoring** | Bayesian trust signals detect spam, quick-deletes, and cross-agent validation. Silent in v2.5, enforced in v2.6. |
|
|
53
|
-
| **Memory Provenance** | Every memory records who created it, via which protocol, with full derivation lineage. |
|
|
54
|
-
| **Production-Grade Code** | 28 API endpoints across 8 modular route files. 13 modular JS files. 63 pytest tests. |
|
|
61
|
+
**v2.5 highlights (included):** Real-time event stream, WAL-mode concurrent writes, agent tracking, memory provenance, 28 API endpoints.
|
|
55
62
|
|
|
56
63
|
**Upgrade:** `npm install -g superlocalmemory@latest`
|
|
57
64
|
|
|
58
65
|
**Dashboard:** `python3 ~/.claude-memory/ui_server.py` then open `http://localhost:8765`
|
|
59
66
|
|
|
60
|
-
[Interactive Architecture Diagram](https://
|
|
67
|
+
[Interactive Architecture Diagram](https://superlocalmemory.com/architecture.html) | [Architecture Doc](docs/ARCHITECTURE-V2.5.md) | [Full Changelog](CHANGELOG.md)
|
|
61
68
|
|
|
62
69
|
---
|
|
63
70
|
|
|
@@ -108,7 +115,7 @@ Or clone manually:
|
|
|
108
115
|
git clone https://github.com/varun369/SuperLocalMemoryV2.git && cd SuperLocalMemoryV2 && ./install.sh
|
|
109
116
|
```
|
|
110
117
|
|
|
111
|
-
Both methods auto-detect and configure **
|
|
118
|
+
Both methods auto-detect and configure **17+ IDEs and AI tools** — Cursor, VS Code/Copilot, Codex, Claude, Windsurf, Gemini CLI, JetBrains, and more.
|
|
112
119
|
|
|
113
120
|
---
|
|
114
121
|
|
|
@@ -254,7 +261,7 @@ python ~/.claude-memory/ui_server.py
|
|
|
254
261
|
| **Hierarchical Leiden** | Recursive community detection — clusters within clusters up to 3 levels. "Python" → "FastAPI" → "Auth patterns" |
|
|
255
262
|
| **Community Summaries** | TF-IDF structured reports per cluster: key topics, projects, categories at a glance |
|
|
256
263
|
| **MACLA Confidence** | Bayesian Beta-Binomial scoring (arXiv:2512.18950) — calibrated confidence, not raw frequency |
|
|
257
|
-
| **Auto-Backup** | Configurable SQLite backups with retention policies,
|
|
264
|
+
| **Auto-Backup** | Configurable SQLite backups with retention policies, restore from any backup via CLI |
|
|
258
265
|
| **Profile UI** | Create, switch, delete profiles from the web dashboard — full isolation per context |
|
|
259
266
|
| **Profile Isolation** | All API endpoints (graph, clusters, patterns, timeline) scoped to active profile |
|
|
260
267
|
|
|
@@ -266,12 +273,12 @@ SuperLocalMemory V2.2.0 implements **hybrid search** combining multiple strategi
|
|
|
266
273
|
|
|
267
274
|
### Search Strategies
|
|
268
275
|
|
|
269
|
-
| Strategy | Method | Best For |
|
|
270
|
-
|
|
271
|
-
| **Semantic Search** | TF-IDF vectors + cosine similarity | Conceptual queries ("authentication patterns") |
|
|
272
|
-
| **Full-Text Search** | SQLite FTS5 with ranking | Exact phrases ("JWT tokens expire") |
|
|
273
|
-
| **Graph-Enhanced** | Knowledge graph traversal | Related concepts ("show auth-related") |
|
|
274
|
-
| **Hybrid Mode** | All three combined | General queries
|
|
276
|
+
| Strategy | Method | Best For |
|
|
277
|
+
|----------|--------|----------|
|
|
278
|
+
| **Semantic Search** | TF-IDF vectors + cosine similarity | Conceptual queries ("authentication patterns") |
|
|
279
|
+
| **Full-Text Search** | SQLite FTS5 with ranking | Exact phrases ("JWT tokens expire") |
|
|
280
|
+
| **Graph-Enhanced** | Knowledge graph traversal | Related concepts ("show auth-related") |
|
|
281
|
+
| **Hybrid Mode** | All three combined | General queries (default) |
|
|
275
282
|
|
|
276
283
|
### Search Examples
|
|
277
284
|
|
|
@@ -293,52 +300,65 @@ slm recall "API design patterns"
|
|
|
293
300
|
# Combines semantic + exact + graph for optimal results
|
|
294
301
|
```
|
|
295
302
|
|
|
296
|
-
### Search
|
|
303
|
+
### Measured Search Latency
|
|
297
304
|
|
|
298
|
-
|
|
|
299
|
-
|
|
300
|
-
| 100
|
|
301
|
-
| 500
|
|
302
|
-
| 1,000
|
|
303
|
-
| 5,000 | 85ms | 50ms | 110ms | 150ms |
|
|
305
|
+
| Database Size | Median | P95 | P99 |
|
|
306
|
+
|---------------|--------|-----|-----|
|
|
307
|
+
| 100 memories | **10.6ms** | 14.9ms | 15.8ms |
|
|
308
|
+
| 500 memories | **65.2ms** | 101.7ms | 112.5ms |
|
|
309
|
+
| 1,000 memories | **124.3ms** | 190.1ms | 219.5ms |
|
|
304
310
|
|
|
305
|
-
|
|
311
|
+
For typical personal databases (under 500 memories), search returns faster than you blink. [Full benchmarks →](https://github.com/varun369/SuperLocalMemoryV2/wiki/Performance-Benchmarks)
|
|
306
312
|
|
|
307
313
|
---
|
|
308
314
|
|
|
309
|
-
## ⚡ Performance
|
|
315
|
+
## ⚡ Measured Performance
|
|
316
|
+
|
|
317
|
+
All numbers measured on real hardware (Apple M4 Pro, 24GB RAM). No estimates — real benchmarks.
|
|
318
|
+
|
|
319
|
+
### Search Speed
|
|
320
|
+
|
|
321
|
+
| Database Size | Median Latency | P95 Latency |
|
|
322
|
+
|---------------|----------------|-------------|
|
|
323
|
+
| 100 memories | **10.6ms** | 14.9ms |
|
|
324
|
+
| 500 memories | **65.2ms** | 101.7ms |
|
|
325
|
+
| 1,000 memories | **124.3ms** | 190.1ms |
|
|
310
326
|
|
|
311
|
-
|
|
327
|
+
For typical personal use (under 500 memories), search results return faster than you blink.
|
|
312
328
|
|
|
313
|
-
|
|
314
|
-
|-----------|------|------------|-------|
|
|
315
|
-
| **Add Memory** | < 10ms | - | Instant indexing |
|
|
316
|
-
| **Search (Hybrid)** | 80ms | 3.3x faster than v1 | 500 memories |
|
|
317
|
-
| **Graph Build** | < 2s | - | 100 memories |
|
|
318
|
-
| **Pattern Learning** | < 2s | - | Incremental |
|
|
319
|
-
| **Dashboard Load** | < 500ms | - | 1,000 memories |
|
|
320
|
-
| **Timeline Render** | < 300ms | - | All memories |
|
|
329
|
+
### Concurrent Writes — Zero Errors
|
|
321
330
|
|
|
322
|
-
|
|
331
|
+
| Scenario | Writes/sec | Errors |
|
|
332
|
+
|----------|------------|--------|
|
|
333
|
+
| 1 AI tool writing | **204/sec** | 0 |
|
|
334
|
+
| 2 AI tools simultaneously | **220/sec** | 0 |
|
|
335
|
+
| 5 AI tools simultaneously | **130/sec** | 0 |
|
|
336
|
+
| 10 AI tools simultaneously | **25/sec** | 0 |
|
|
323
337
|
|
|
324
|
-
|
|
325
|
-
|------|-------------|-------------|---------|
|
|
326
|
-
| **Tier 1** | Active memories (0-30 days) | None | - |
|
|
327
|
-
| **Tier 2** | Warm memories (30-90 days) | 60% | Progressive summarization |
|
|
328
|
-
| **Tier 3** | Cold storage (90+ days) | 96% | JSON archival |
|
|
338
|
+
WAL mode + serialized write queue = zero "database is locked" errors, ever.
|
|
329
339
|
|
|
330
|
-
|
|
340
|
+
### Storage
|
|
331
341
|
|
|
332
|
-
|
|
342
|
+
10,000 memories = **13.6 MB** on disk (~1.9 KB per memory). Your entire AI memory history takes less space than a photo.
|
|
333
343
|
|
|
334
|
-
|
|
335
|
-
|--------------|-------------|-------------|-----------|
|
|
336
|
-
| 100 memories | 35ms | 0.5s | < 30MB |
|
|
337
|
-
| 500 memories | 45ms | 2s | < 50MB |
|
|
338
|
-
| 1,000 memories | 55ms | 5s | < 80MB |
|
|
339
|
-
| 5,000 memories | 85ms | 30s | < 150MB |
|
|
344
|
+
### Trust Defense
|
|
340
345
|
|
|
341
|
-
|
|
346
|
+
Bayesian trust scoring achieves **perfect separation** (trust gap = 1.0) between honest and malicious agents. Detects "sleeper" attacks with 74.7% trust drop. Zero false positives.
|
|
347
|
+
|
|
348
|
+
### Graph Construction
|
|
349
|
+
|
|
350
|
+
| Memories | Build Time |
|
|
351
|
+
|----------|-----------|
|
|
352
|
+
| 100 | 0.28s |
|
|
353
|
+
| 1,000 | 10.6s |
|
|
354
|
+
|
|
355
|
+
Leiden clustering discovers 6-7 natural topic communities automatically.
|
|
356
|
+
|
|
357
|
+
> **Graph Scaling:** Knowledge graph features work best with up to 10,000 memories. For larger databases, the system uses intelligent sampling (most recent + highest importance memories) for graph construction. Core search and memory storage have no upper limit.
|
|
358
|
+
|
|
359
|
+
> **LoCoMo benchmark results coming soon** — evaluation against the standardized [LoCoMo](https://snap-research.github.io/locomo/) long-conversation memory benchmark (Snap Research, ACL 2024).
|
|
360
|
+
|
|
361
|
+
[Full benchmark details →](https://github.com/varun369/SuperLocalMemoryV2/wiki/Performance-Benchmarks)
|
|
342
362
|
|
|
343
363
|
---
|
|
344
364
|
|
|
@@ -470,7 +490,7 @@ Not another simple key-value store. SuperLocalMemory implements **cutting-edge m
|
|
|
470
490
|
| **Completely Free** | Limited | Limited | Partial | ✅ | ✅ |
|
|
471
491
|
|
|
472
492
|
**SuperLocalMemory V2 is the ONLY solution that:**
|
|
473
|
-
- ✅ Works across
|
|
493
|
+
- ✅ Works across 17+ IDEs and CLI tools
|
|
474
494
|
- ✅ Remains 100% local (no cloud dependencies)
|
|
475
495
|
- ✅ Completely free with unlimited memories
|
|
476
496
|
|
|
@@ -482,7 +502,7 @@ Not another simple key-value store. SuperLocalMemory implements **cutting-edge m
|
|
|
482
502
|
|
|
483
503
|
### Multi-Layer Memory Architecture
|
|
484
504
|
|
|
485
|
-
**[View Interactive Architecture Diagram](https://
|
|
505
|
+
**[View Interactive Architecture Diagram](https://superlocalmemory.com/architecture.html)** — Click any layer for details, research references, and file paths.
|
|
486
506
|
|
|
487
507
|
```
|
|
488
508
|
┌─────────────────────────────────────────────────────────────┐
|
|
@@ -496,7 +516,7 @@ Not another simple key-value store. SuperLocalMemory implements **cutting-edge m
|
|
|
496
516
|
├─────────────────────────────────────────────────────────────┤
|
|
497
517
|
│ Layer 7: UNIVERSAL ACCESS │
|
|
498
518
|
│ MCP + Skills + CLI (works everywhere) │
|
|
499
|
-
│
|
|
519
|
+
│ 17+ IDEs with single database │
|
|
500
520
|
├─────────────────────────────────────────────────────────────┤
|
|
501
521
|
│ Layer 6: MCP INTEGRATION │
|
|
502
522
|
│ Model Context Protocol: 6 tools, 4 resources, 2 prompts │
|
|
@@ -634,23 +654,18 @@ superlocalmemoryv2:reset hard --confirm # Nuclear option
|
|
|
634
654
|
|
|
635
655
|
---
|
|
636
656
|
|
|
637
|
-
## 📊 Performance
|
|
638
|
-
|
|
639
|
-
**SEO:** Performance benchmarks, memory system speed, search latency, visualization dashboard performance
|
|
657
|
+
## 📊 Performance at a Glance
|
|
640
658
|
|
|
641
|
-
| Metric | Result |
|
|
642
|
-
|
|
643
|
-
| **
|
|
644
|
-
| **
|
|
645
|
-
| **
|
|
646
|
-
| **
|
|
647
|
-
| **
|
|
648
|
-
| **
|
|
649
|
-
| **Timeline render** | **< 300ms** | All memories visualized |
|
|
650
|
-
| **Storage compression** | **60-96% reduction** | Progressive tiering |
|
|
651
|
-
| **Memory overhead** | **< 50MB RAM** | Lightweight |
|
|
659
|
+
| Metric | Measured Result |
|
|
660
|
+
|--------|----------------|
|
|
661
|
+
| **Search latency** | **10.6ms** median (100 memories) |
|
|
662
|
+
| **Concurrent writes** | **220/sec** with 2 agents, zero errors |
|
|
663
|
+
| **Storage** | **1.9 KB** per memory at scale (13.6 MB for 10K) |
|
|
664
|
+
| **Trust defense** | **1.0** trust gap (perfect separation) |
|
|
665
|
+
| **Graph build** | **0.28s** for 100 memories |
|
|
666
|
+
| **Search quality** | **MRR 0.90** (first result correct 9/10 times) |
|
|
652
667
|
|
|
653
|
-
|
|
668
|
+
[Full benchmark details →](https://github.com/varun369/SuperLocalMemoryV2/wiki/Performance-Benchmarks)
|
|
654
669
|
|
|
655
670
|
---
|
|
656
671
|
|
package/api_server.py
CHANGED
|
@@ -51,6 +51,53 @@ app = FastAPI(
|
|
|
51
51
|
UI_DIR.mkdir(exist_ok=True)
|
|
52
52
|
app.mount("/static", StaticFiles(directory=str(UI_DIR)), name="static")
|
|
53
53
|
|
|
54
|
+
# Rate limiting (v2.6)
|
|
55
|
+
try:
|
|
56
|
+
from rate_limiter import write_limiter, read_limiter
|
|
57
|
+
|
|
58
|
+
@app.middleware("http")
|
|
59
|
+
async def rate_limit_middleware(request, call_next):
|
|
60
|
+
client_ip = request.client.host if request.client else "unknown"
|
|
61
|
+
|
|
62
|
+
# Determine if this is a write or read endpoint
|
|
63
|
+
is_write = request.method in ("POST", "PUT", "DELETE", "PATCH")
|
|
64
|
+
limiter = write_limiter if is_write else read_limiter
|
|
65
|
+
|
|
66
|
+
allowed, remaining = limiter.is_allowed(client_ip)
|
|
67
|
+
if not allowed:
|
|
68
|
+
from fastapi.responses import JSONResponse
|
|
69
|
+
return JSONResponse(
|
|
70
|
+
status_code=429,
|
|
71
|
+
content={"error": "Too many requests. Please slow down."},
|
|
72
|
+
headers={"Retry-After": str(limiter.window)}
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
response = await call_next(request)
|
|
76
|
+
response.headers["X-RateLimit-Remaining"] = str(remaining)
|
|
77
|
+
return response
|
|
78
|
+
|
|
79
|
+
except ImportError:
|
|
80
|
+
pass # Rate limiter not available — continue without it
|
|
81
|
+
|
|
82
|
+
# Optional API key authentication (v2.6)
|
|
83
|
+
try:
|
|
84
|
+
from auth_middleware import check_api_key
|
|
85
|
+
|
|
86
|
+
@app.middleware("http")
|
|
87
|
+
async def auth_middleware(request, call_next):
|
|
88
|
+
is_write = request.method in ("POST", "PUT", "DELETE", "PATCH")
|
|
89
|
+
headers = dict(request.headers)
|
|
90
|
+
if not check_api_key(headers, is_write=is_write):
|
|
91
|
+
from fastapi.responses import JSONResponse
|
|
92
|
+
return JSONResponse(
|
|
93
|
+
status_code=401,
|
|
94
|
+
content={"error": "Invalid or missing API key. Set X-SLM-API-Key header."}
|
|
95
|
+
)
|
|
96
|
+
response = await call_next(request)
|
|
97
|
+
return response
|
|
98
|
+
except ImportError:
|
|
99
|
+
pass # Auth middleware not available
|
|
100
|
+
|
|
54
101
|
|
|
55
102
|
# ============================================================================
|
|
56
103
|
# Request/Response Models
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
</mxCell>
|
|
68
68
|
|
|
69
69
|
<!-- Layer 10: A2A Agent Collaboration -->
|
|
70
|
-
<mxCell id="L10" value="<b>Layer 10: A2A Agent Collaboration</b><br><font style='font-size:10px;color:#ECFDF5;'>src/a2a_server.py (PLANNED v2.
|
|
70
|
+
<mxCell id="L10" value="<b>Layer 10: A2A Agent Collaboration</b><br><font style='font-size:10px;color:#ECFDF5;'>src/a2a_server.py (PLANNED v2.7) &mdash; Agent-to-Agent Protocol (Google/Linux Foundation)</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#10B981;fontColor=#FFFFFF;strokeColor=#059669;arcSize=8;fontSize=12;align=center;verticalAlign=middle;shadow=1;dashed=1;dashPattern=8 4;" vertex="1" parent="1">
|
|
71
71
|
<mxGeometry x="340" y="165" width="520" height="55" as="geometry" />
|
|
72
72
|
</mxCell>
|
|
73
73
|
|
|
@@ -181,7 +181,7 @@
|
|
|
181
181
|
</mxCell>
|
|
182
182
|
|
|
183
183
|
<!-- A2A Path Label -->
|
|
184
|
-
<mxCell id="a2a_label" value="<font color='#6EE7B7' style='font-size:14px;font-weight:bold;'>A2A Protocol</font><br><font color='#34D399' style='font-size:11px;'>Agent &harr; Agent</font><br><font color='#FBBF24' style='font-size:10px;font-weight:bold;'>PLANNED v2.
|
|
184
|
+
<mxCell id="a2a_label" value="<font color='#6EE7B7' style='font-size:14px;font-weight:bold;'>A2A Protocol</font><br><font color='#34D399' style='font-size:11px;'>Agent &harr; Agent</font><br><font color='#FBBF24' style='font-size:10px;font-weight:bold;'>PLANNED v2.7</font>" style="text;html=1;align=center;verticalAlign=top;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
|
|
185
185
|
<mxGeometry x="960" y="172" width="140" height="60" as="geometry" />
|
|
186
186
|
</mxCell>
|
|
187
187
|
|
|
@@ -316,11 +316,11 @@
|
|
|
316
316
|
<mxGeometry x="105" y="600" width="110" height="25" as="geometry" />
|
|
317
317
|
</mxCell>
|
|
318
318
|
|
|
319
|
-
<!-- Legend: Planned v2.
|
|
319
|
+
<!-- Legend: Planned v2.7 -->
|
|
320
320
|
<mxCell id="legend_planned_box" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#10B981;strokeColor=#059669;arcSize=30;dashed=1;dashPattern=4 2;" vertex="1" parent="1">
|
|
321
321
|
<mxGeometry x="85" y="628" width="14" height="14" as="geometry" />
|
|
322
322
|
</mxCell>
|
|
323
|
-
<mxCell id="legend_planned_text" value="<font color='#D1D5DB' style='font-size:10px;'>Planned v2.
|
|
323
|
+
<mxCell id="legend_planned_text" value="<font color='#D1D5DB' style='font-size:10px;'>Planned v2.7 (A2A)</font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
|
|
324
324
|
<mxGeometry x="105" y="623" width="120" height="25" as="geometry" />
|
|
325
325
|
</mxCell>
|
|
326
326
|
|