agmem 0.1.2__py3-none-any.whl → 0.1.3__py3-none-any.whl

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 (45) hide show
  1. {agmem-0.1.2.dist-info → agmem-0.1.3.dist-info}/METADATA +138 -14
  2. {agmem-0.1.2.dist-info → agmem-0.1.3.dist-info}/RECORD +45 -26
  3. memvcs/cli.py +10 -0
  4. memvcs/commands/add.py +6 -0
  5. memvcs/commands/audit.py +59 -0
  6. memvcs/commands/clone.py +7 -0
  7. memvcs/commands/daemon.py +28 -0
  8. memvcs/commands/distill.py +16 -0
  9. memvcs/commands/federated.py +53 -0
  10. memvcs/commands/fsck.py +31 -0
  11. memvcs/commands/garden.py +14 -0
  12. memvcs/commands/gc.py +51 -0
  13. memvcs/commands/merge.py +55 -1
  14. memvcs/commands/prove.py +66 -0
  15. memvcs/commands/pull.py +27 -0
  16. memvcs/commands/resolve.py +130 -0
  17. memvcs/commands/verify.py +74 -23
  18. memvcs/core/audit.py +124 -0
  19. memvcs/core/consistency.py +9 -9
  20. memvcs/core/crypto_verify.py +280 -0
  21. memvcs/core/distiller.py +25 -25
  22. memvcs/core/encryption.py +169 -0
  23. memvcs/core/federated.py +86 -0
  24. memvcs/core/gardener.py +23 -24
  25. memvcs/core/ipfs_remote.py +39 -0
  26. memvcs/core/knowledge_graph.py +1 -0
  27. memvcs/core/llm/__init__.py +10 -0
  28. memvcs/core/llm/anthropic_provider.py +50 -0
  29. memvcs/core/llm/base.py +27 -0
  30. memvcs/core/llm/factory.py +30 -0
  31. memvcs/core/llm/openai_provider.py +36 -0
  32. memvcs/core/merge.py +36 -23
  33. memvcs/core/objects.py +16 -6
  34. memvcs/core/pack.py +92 -0
  35. memvcs/core/privacy_budget.py +63 -0
  36. memvcs/core/remote.py +38 -0
  37. memvcs/core/repository.py +82 -2
  38. memvcs/core/temporal_index.py +9 -0
  39. memvcs/core/trust.py +103 -0
  40. memvcs/core/vector_store.py +15 -1
  41. memvcs/core/zk_proofs.py +26 -0
  42. {agmem-0.1.2.dist-info → agmem-0.1.3.dist-info}/WHEEL +0 -0
  43. {agmem-0.1.2.dist-info → agmem-0.1.3.dist-info}/entry_points.txt +0 -0
  44. {agmem-0.1.2.dist-info → agmem-0.1.3.dist-info}/licenses/LICENSE +0 -0
  45. {agmem-0.1.2.dist-info → agmem-0.1.3.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agmem
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: Agentic Memory Version Control System - Git for AI agent memories
5
5
  Home-page: https://github.com/vivek-tiwari-vt/agmem
6
6
  Author: agmem Team
@@ -10,7 +10,7 @@ Project-URL: Homepage, https://github.com/vivek-tiwari-vt/agmem
10
10
  Project-URL: Documentation, https://github.com/vivek-tiwari-vt/agmem#readme
11
11
  Project-URL: Repository, https://github.com/vivek-tiwari-vt/agmem
12
12
  Project-URL: Bug Tracker, https://github.com/vivek-tiwari-vt/agmem/issues
13
- Keywords: ai,agent,memory,version-control,git,vcs,llm
13
+ Keywords: ai,agent,memory,version-control,git,vcs,llm,merkle,audit,encryption,differential-privacy,trust,multi-agent
14
14
  Classifier: Development Status :: 3 - Alpha
15
15
  Classifier: Intended Audience :: Developers
16
16
  Classifier: License :: OSI Approved :: MIT License
@@ -22,6 +22,7 @@ Classifier: Programming Language :: Python :: 3.11
22
22
  Classifier: Programming Language :: Python :: 3.12
23
23
  Classifier: Topic :: Software Development :: Version Control
24
24
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
25
+ Classifier: Topic :: Security :: Cryptography
25
26
  Requires-Python: >=3.8
26
27
  Description-Content-Type: text/markdown
27
28
  License-File: LICENSE
@@ -32,6 +33,9 @@ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
32
33
  Requires-Dist: black==24.10.0; extra == "dev"
33
34
  Requires-Dist: flake8>=5.0.0; extra == "dev"
34
35
  Requires-Dist: mypy>=1.0.0; extra == "dev"
36
+ Provides-Extra: llm
37
+ Requires-Dist: openai>=1.0.0; extra == "llm"
38
+ Requires-Dist: anthropic>=0.18.0; extra == "llm"
35
39
  Provides-Extra: mcp
36
40
  Requires-Dist: mcp>=1.0.0; extra == "mcp"
37
41
  Provides-Extra: vector
@@ -46,6 +50,8 @@ Requires-Dist: google-cloud-storage>=2.0.0; extra == "cloud"
46
50
  Provides-Extra: gardener
47
51
  Requires-Dist: scikit-learn>=1.3.0; extra == "gardener"
48
52
  Requires-Dist: openai>=1.0.0; extra == "gardener"
53
+ Provides-Extra: anthropic
54
+ Requires-Dist: anthropic>=0.18.0; extra == "anthropic"
49
55
  Provides-Extra: pii
50
56
  Requires-Dist: presidio-analyzer>=2.2.0; extra == "pii"
51
57
  Provides-Extra: daemon
@@ -58,8 +64,13 @@ Provides-Extra: distill
58
64
  Requires-Dist: openai>=1.0.0; extra == "distill"
59
65
  Provides-Extra: verify
60
66
  Requires-Dist: openai>=1.0.0; extra == "verify"
67
+ Provides-Extra: crypto
68
+ Requires-Dist: cryptography>=41.0.0; extra == "crypto"
69
+ Provides-Extra: ipfs
70
+ Requires-Dist: requests>=2.28.0; extra == "ipfs"
61
71
  Provides-Extra: all
62
72
  Requires-Dist: mcp>=1.0.0; extra == "all"
73
+ Requires-Dist: cryptography>=41.0.0; extra == "all"
63
74
  Requires-Dist: sqlite-vec>=0.1.0; extra == "all"
64
75
  Requires-Dist: sentence-transformers>=2.0.0; extra == "all"
65
76
  Requires-Dist: fastapi>=0.100.0; extra == "all"
@@ -68,8 +79,12 @@ Requires-Dist: boto3>=1.34.0; extra == "all"
68
79
  Requires-Dist: google-cloud-storage>=2.0.0; extra == "all"
69
80
  Requires-Dist: scikit-learn>=1.3.0; extra == "all"
70
81
  Requires-Dist: openai>=1.0.0; extra == "all"
82
+ Requires-Dist: anthropic>=0.18.0; extra == "all"
71
83
  Requires-Dist: watchdog>=3.0.0; extra == "all"
72
84
  Requires-Dist: networkx>=3.0; extra == "all"
85
+ Requires-Dist: tiktoken>=0.5.0; extra == "all"
86
+ Requires-Dist: presidio-analyzer>=2.2.0; extra == "all"
87
+ Requires-Dist: requests>=2.28.0; extra == "all"
73
88
  Dynamic: author
74
89
  Dynamic: home-page
75
90
  Dynamic: license-file
@@ -105,10 +120,23 @@ agmem solves all of these problems with a familiar Git-like interface.
105
120
  - ✅ **Branch/tag names with `/`** — Git-style refs: `feature/test`, `releases/v1` (path-validated)
106
121
  - ✅ **Content-addressable storage** — SHA-256 deduplication like Git
107
122
  - ✅ **Memory-type-aware merging** — Episodic append, semantic consolidate, procedural prefer-new
108
- - ✅ **Remote (file://)** — `clone`, `push`, `pull`, `remote`; pull merges into current branch
123
+ - ✅ **Remote (file://)** — `clone`, `push`, `pull`, `remote`; pull merges into current branch; push conflict detection (non–fast-forward reject)
109
124
  - ✅ **Search** — Semantic with `agmem[vector]`, or plain text over `current/` when vector deps missing
110
125
  - ✅ **Knowledge graph** — `agmem graph` from wikilinks/tags; `--no-similarity`, `--format d3`, `--serve` (optional `agmem[web]`)
111
- - ✅ **Integrity** — `agmem fsck`; path/ref/hash validation throughout (no path traversal)
126
+ - ✅ **Integrity** — `agmem fsck` (objects, refs, vector store, Merkle/signature); `agmem verify --crypto`; path/ref/hash validation (no path traversal)
127
+ - ✅ **Cryptographic commit verification** — Merkle tree over blobs; Ed25519 signing of root; verify on checkout, pull, `verify`, `fsck`; Merkle proofs for single-blob verification
128
+ - ✅ **Encryption at rest** — Optional AES-256-GCM with Argon2id key derivation; hash-then-encrypt preserves deduplication
129
+ - ✅ **Tamper-evident audit trail** — Append-only hash-chained log (init, add, commit, checkout, merge, push, pull, config); `agmem audit` and `agmem audit --verify`
130
+ - ✅ **Multi-agent trust** — Trust store (full / conditional / untrusted) per public key; applied on pull/merge; clone copies remote keys
131
+ - ✅ **Conflict resolution** — `agmem resolve` with ours/theirs/both; conflicts persisted in `.mem/merge/`; path-safe
132
+ - ✅ **Differential privacy** — Epsilon/delta budget in `.mem/privacy_budget.json`; `--private` on `agmem distill` and `agmem garden` when enabled
133
+ - ✅ **Pack files & GC** — `agmem gc` (reachable from refs, prune loose, optional repack); pack format and index in core
134
+ - ✅ **Multi-provider LLM** — OpenAI and Anthropic via `memvcs.core.llm`; config/repo or env; used by gardener, distiller, consistency, merge
135
+ - ✅ **Temporal querying** — Point-in-time and range queries in temporal index; frontmatter timestamps
136
+ - ✅ **Federated collaboration** — `agmem federated push|pull` (stub) for coordinator-based summary sharing
137
+ - ✅ **Zero-knowledge proofs** — `agmem prove` (stub) for keyword containment and memory freshness
138
+ - ✅ **Daemon health** — Periodic Merkle verification in daemon loop; safe auto-remediation hooks
139
+ - ✅ **GPU acceleration** — Vector store detects GPU for embedding model when available
112
140
  - ✅ **Optional** — `serve`, `daemon` (watch + auto-commit), `garden` (episode archival), MCP server; install extras as needed
113
141
 
114
142
  ## Quick Start
@@ -227,12 +255,18 @@ All commands are listed below. Highlights: **`agmem blame <file>`** (who changed
227
255
 
228
256
  | Command | Description |
229
257
  |---------|-------------|
230
- | `agmem clone <url> [dir]` | Clone repo (file:// URLs); path-validated |
258
+ | `agmem clone <url> [dir]` | Clone repo (file:// URLs); path-validated; copies remote public keys |
231
259
  | `agmem remote add <name> <url>` | Add remote |
232
260
  | `agmem remote show` | List remotes |
233
- | `agmem push <remote> <branch>` | Push branch (refs validated) |
234
- | `agmem pull [--remote <name>] [--branch <b>]` | Fetch and merge into current branch |
235
- | `agmem fsck` | Check objects, refs, optional vector store |
261
+ | `agmem push <remote> <branch>` | Push branch (refs validated); rejects non–fast-forward |
262
+ | `agmem pull [--remote <name>] [--branch <b>]` | Fetch and merge into current branch; optional crypto/trust checks |
263
+ | `agmem fsck` | Check objects, refs, optional vector store, Merkle roots and signatures |
264
+ | `agmem verify [ref]` | Belief consistency (contradictions); use `--crypto` to verify commit Merkle/signature |
265
+ | `agmem audit [--verify] [--max n]` | Show tamper-evident audit log; `--verify` checks hash chain |
266
+ | `agmem resolve [path]` | Resolve merge conflicts (ours/theirs/both); path under `current/` |
267
+ | `agmem gc [--dry-run] [--prune-days n]` | Garbage collection: delete unreachable loose objects; optional repack |
268
+ | `agmem prove --memory <path> --property keyword\|freshness --value <v> [-o out]` | Generate ZK proofs (stub) |
269
+ | `agmem federated push\|pull` | Federated collaboration (stub; requires coordinator in config) |
236
270
 
237
271
  ### Optional (install extras)
238
272
 
@@ -301,7 +335,81 @@ Configure in `.mem/config.json` (e.g. `archive_dir`, consolidation thresholds).
301
335
  agmem fsck
302
336
  ```
303
337
 
304
- Verifies objects, refs, and (if installed) the vector store. Run after cloning or if something looks wrong.
338
+ Verifies objects, refs, and (if installed) the vector store. When commit metadata includes `merkle_root` and optionally `signature`, fsck also runs cryptographic verification. Run after cloning or if something looks wrong.
339
+
340
+ ---
341
+
342
+ ## Security, trust & advanced features
343
+
344
+ The following 18 capabilities are implemented (or stubbed) per the agmem features implementation plan. They are grouped by tier.
345
+
346
+ ### Tier 1 — Security and trust
347
+
348
+ | # | Feature | Description |
349
+ |---|---------|-------------|
350
+ | **1** | **Cryptographic commit verification** | Merkle tree over commit blobs; Ed25519 signing of Merkle root; verification on checkout, pull, `agmem verify --crypto`, and `agmem fsck`. Merkle proofs for single-blob verification. Keys: `.mem/keys/`; private key from env `AGMEM_SIGNING_PRIVATE_KEY` or `AGMEM_SIGNING_PRIVATE_KEY_FILE`. Old commits without `merkle_root` are unverified. |
351
+ | **2** | **Encryption at rest** | Optional AES-256-GCM for object contents; key from passphrase via Argon2id; hash-then-encrypt preserves deduplication. Config in `.mem/encryption.json` or repo config; opt-in. |
352
+ | **3** | **Tamper-evident audit trail** | Append-only, hash-chained log in `.mem/audit/` for init, add, commit, checkout, merge, push, pull, config. **Commands:** `agmem audit` (show entries), `agmem audit --verify` (verify chain). |
353
+
354
+ ### Tier 2 — Multi-agent collaboration
355
+
356
+ | # | Feature | Description |
357
+ |---|---------|-------------|
358
+ | **4** | **Multi-agent trust and identity** | Trust store (full / conditional / untrusted) per public key; applied on pull and merge. Clone copies remote public keys; user adds them to trust store. Identity = keypair (same as commit signing). |
359
+ | **5** | **Federated memory collaboration** | Agents share summaries or aggregated updates via a coordinator. **Command:** `agmem federated push` / `agmem federated pull` (stub). Config: `federated.enabled`, `coordinator_url`. |
360
+ | **6** | **Conflict resolution interface** | Structured resolution: ours / theirs / both per path. **Command:** `agmem resolve [path]`. Conflicts persisted in `.mem/merge/conflicts.json`; path traversal protected. |
361
+
362
+ ### Tier 3 — Privacy
363
+
364
+ | # | Feature | Description |
365
+ |---|---------|-------------|
366
+ | **7** | **Differential privacy** | Epsilon/delta budget per repo in `.mem/privacy_budget.json`. **Usage:** `agmem distill --private`, `agmem garden --private`; blocks when budget exceeded. Config: `differential_privacy.max_epsilon`, `delta`. |
367
+ | **8** | **Zero-knowledge proofs** | zk-SNARK-style proofs for keyword containment and memory freshness. **Command:** `agmem prove --memory <path> --property keyword|freshness --value <v> [-o out]` (stub). |
368
+
369
+ ### Tier 4 — Storage and distribution
370
+
371
+ | # | Feature | Description |
372
+ |---|---------|-------------|
373
+ | **9** | **Decentralized storage (IPFS)** | Push/pull via IPFS CIDs; pinning and gateway fallback. Stub in `memvcs.core.ipfs_remote`; optional dependency. |
374
+ | **10** | **Pack files and garbage collection** | Pack loose objects into pack file + index; GC deletes unreachable objects. **Command:** `agmem gc [--dry-run] [--prune-days n]`. Config: `gc_prune_days` (default 90). |
375
+ | **11** | **Enhanced cloud remote operations** | Push conflict detection: non–fast-forward push rejected with a clear message. S3/GCS remotes and distributed locking in storage layer. |
376
+
377
+ ### Tier 5 — Intelligence and retrieval
378
+
379
+ | # | Feature | Description |
380
+ |---|---------|-------------|
381
+ | **12** | **Multi-provider LLM** | `memvcs.core.llm`: OpenAI and Anthropic; factory by config or env. Used by gardener, distiller, consistency checker, merge. Credentials via env (e.g. `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`). |
382
+ | **13** | **Enhanced semantic compression** | Multi-stage pipeline (chunk → fact extraction → dedup → embed → tiered storage); hybrid retrieval. Docstrings and design in distiller/vector store. |
383
+ | **14** | **Temporal querying and time-travel** | Point-in-time and range queries in `memvcs.core.temporal_index`; frontmatter timestamps; “state at T” resolution. |
384
+ | **15** | **Cross-memory relationship graph** | Knowledge graph extended with co-occurrence, semantic similarity, causal and entity edges; incremental updates. Docstrings in `knowledge_graph.py`. |
385
+
386
+ ### Tier 6 — Operations and maintenance
387
+
388
+ | # | Feature | Description |
389
+ |---|---------|-------------|
390
+ | **16** | **Automated memory health monitoring** | Daemon runs periodic Merkle verification; safe auto-remediation hooks; unsafe actions alert only. |
391
+ | **17** | **GPU-accelerated operations** | Vector store detects GPU for embedding model (e.g. sentence-transformers with CUDA/Metal); transparent CPU fallback. |
392
+ | **18** | **Test suite and quality** | Broad tests: object store, merge, crypto (Merkle, proofs, verify), trust, privacy budget, pack/GC, resolve helpers, encryption, LLM provider; CI with coverage. |
393
+
394
+ ### New files and config (summary)
395
+
396
+ | Addition | Purpose |
397
+ |----------|---------|
398
+ | `memvcs/core/crypto_verify.py` | Merkle build/verify, Ed25519 sign/verify, Merkle proofs |
399
+ | `memvcs/core/audit.py` | Tamper-evident audit append and verify |
400
+ | `memvcs/core/trust.py` | Trust store (key → level) |
401
+ | `memvcs/core/privacy_budget.py` | Epsilon/delta budget for DP |
402
+ | `memvcs/core/pack.py` | Pack format, index, GC |
403
+ | `memvcs/core/encryption.py` | AES-256-GCM, Argon2id, config |
404
+ | `memvcs/core/llm/` | LLM provider interface and OpenAI/Anthropic |
405
+ | `memvcs/core/zk_proofs.py` | ZK proof stubs |
406
+ | `memvcs/core/federated.py` | Federated push/pull stubs |
407
+ | `.mem/audit/` | Audit log |
408
+ | `.mem/keys/` | Public (and optional private) keys |
409
+ | `.mem/trust/` or config | Trust store |
410
+ | `.mem/privacy_budget.json` | DP budget state |
411
+ | `.mem/merge/conflicts.json` | Unresolved merge conflicts |
412
+ | Commit `metadata` | `merkle_root`, `signature` |
305
413
 
306
414
  ---
307
415
 
@@ -450,10 +558,20 @@ Repository configuration is stored in `.mem/config.json`:
450
558
  "summarizer_model": "default",
451
559
  "max_episode_size": 1048576,
452
560
  "consolidation_threshold": 100
561
+ },
562
+ "differential_privacy": {
563
+ "max_epsilon": 1.0,
564
+ "delta": 1e-5
565
+ },
566
+ "federated": {
567
+ "enabled": false,
568
+ "coordinator_url": ""
453
569
  }
454
570
  }
455
571
  ```
456
572
 
573
+ Optional sections: **`differential_privacy`** (for `--private` on distill/garden); **`federated`** (for `agmem federated`); **`signing`** (public key for commit verification); trust store under `.mem/trust/` or config; encryption in `.mem/encryption.json` when enabled.
574
+
457
575
  ### agmem config (cloud and PII)
458
576
 
459
577
  Optional user/repo config for S3/GCS and PII hooks:
@@ -515,13 +633,17 @@ mypy memvcs/
515
633
  - [x] Basic commands (init, add, commit, status, log, diff, show, reset, tag, stash, reflog, blame, tree, clean)
516
634
  - [x] HEAD~n resolution; branch/tag names with `/` (Git-style)
517
635
  - [x] Branching and checkout; merging with memory-type-aware strategies
518
- - [x] Remote operations (clone, push, pull, remote) — file:// URLs; pull merges into current branch
636
+ - [x] Remote operations (clone, push, pull, remote) — file:// URLs; pull merges into current branch; push conflict detection
519
637
  - [x] Search — semantic with `agmem[vector]`, plain text fallback
520
638
  - [x] Knowledge graph (`agmem graph`) — wikilinks, tags, optional similarity; `--no-similarity`, `--serve`
521
- - [x] Integrity (`agmem fsck`); path/ref/hash validation (security)
639
+ - [x] Integrity (`agmem fsck`); path/ref/hash validation; Merkle/signature verification
522
640
  - [x] Web UI (`agmem serve`); MCP server (`agmem mcp`); daemon (`agmem daemon`); garden (`agmem garden`)
523
- - [ ] Garbage collection
524
- - [ ] Pack files for efficiency
641
+ - [x] Cryptographic commit verification (Merkle tree, Ed25519 signing, verify on checkout/pull/fsck)
642
+ - [x] Tamper-evident audit trail (`agmem audit`); multi-agent trust store; conflict resolution (`agmem resolve`)
643
+ - [x] Encryption at rest (optional AES-256-GCM); differential privacy budget (`--private` on distill/garden)
644
+ - [x] Pack files and garbage collection (`agmem gc`); ZK proofs and federated stubs (`agmem prove`, `agmem federated`)
645
+ - [x] Multi-provider LLM (OpenAI, Anthropic); temporal range queries; daemon health checks; GPU detection; test suite and CI
646
+ - [ ] IPFS remote (stub in place); full ZK circuits and federated coordinator
525
647
 
526
648
  ## Integrations
527
649
 
@@ -614,8 +736,10 @@ agmem graph --serve # Serve knowledge graph UI (same extra)
614
736
 
615
737
  - **Full history:** `agmem log`, `agmem reflog`
616
738
  - **Line-level attribution:** `agmem blame <file>` — see which commit and author last changed each line (e.g. `agmem blame current/semantic/user-preferences.md`)
739
+ - **Tamper-evident audit:** `agmem audit` and `agmem audit --verify` for hash-chained operation log
740
+ - **Cryptographic verification:** `agmem verify --crypto` and `agmem fsck` for Merkle roots and Ed25519 signatures
617
741
  - **Visual audit:** `agmem serve` for browser-based history and diff viewer
618
- - **Integrity:** `agmem fsck` to verify objects and refs
742
+ - **Integrity:** `agmem fsck` to verify objects, refs, and commit signatures
619
743
 
620
744
  ## Ecosystem Plugin Patterns
621
745
 
@@ -1,34 +1,39 @@
1
- agmem-0.1.2.dist-info/licenses/LICENSE,sha256=X_S6RBErW-F0IDbM3FAEoDB-zxExFnl2m8640rTXphM,1067
1
+ agmem-0.1.3.dist-info/licenses/LICENSE,sha256=X_S6RBErW-F0IDbM3FAEoDB-zxExFnl2m8640rTXphM,1067
2
2
  memvcs/__init__.py,sha256=mXwHTSlUPWo4ERqJLGJnxmxtGQQHPSbXb4IpO61l04M,193
3
- memvcs/cli.py,sha256=0bIdOVz23ZON4i8LoAsepiII-DpiGTGysllXFwmG0GI,5771
3
+ memvcs/cli.py,sha256=YF06oMNjKWUmiNahILmfjrIXgoXzU-5BJFmbunSb8Sc,6075
4
4
  memvcs/commands/__init__.py,sha256=A2D6xWaO6epU7iV4QSvqvF5TspnwRyDN7NojmGatPrE,510
5
- memvcs/commands/add.py,sha256=5Bia5nLfaREyp-ujqReDOyZu6zF5WveQk_N8XkWmqnM,8511
5
+ memvcs/commands/add.py,sha256=k9eM7qf2NFvneiJkFQNiAYFB2GgKmyPw_NXmkCxblQE,8736
6
+ memvcs/commands/audit.py,sha256=E6m54B726tqDQR3rrgRXWrjE-seu2UocqrFxN1aHkY4,1680
6
7
  memvcs/commands/base.py,sha256=yWvIYuofRxbHXvChlSd_DL_hJMaQdbZwa2XBDWj5Bio,634
7
8
  memvcs/commands/blame.py,sha256=2tEXyXpAebm_zQFAyw-6d3K09Lnh1GVLYGp6htlEmI0,5605
8
9
  memvcs/commands/branch.py,sha256=ghsK4tnGe7XApxQSgou7V0BASBC8PL8nQs_yBt0notQ,3150
9
10
  memvcs/commands/checkout.py,sha256=xaYZSbCQ-MyLWPtwA2FdH6WqGMI3oF3R2JmCufGBVFg,3182
10
11
  memvcs/commands/clean.py,sha256=e0OhSQdHfFnOPTRbyKbM8IcX4yJD5n_kaBKjIeoaRBo,1973
11
- memvcs/commands/clone.py,sha256=EAeojcUpRyCj1tVLR5zqnbkdF6Cvpza0_gyjZoCHysw,2895
12
+ memvcs/commands/clone.py,sha256=aB0LcugIWJE9IEez6y70KlpZu4eIF2EdXZxE24jXyac,3260
12
13
  memvcs/commands/commit.py,sha256=W4ulVZuEETJh1SHpscaQfNjyQMqeIE0AYZIbMbTrsq4,6801
13
- memvcs/commands/daemon.py,sha256=B9_a7DFXMde9Fphpo7J9-osXqYCby-KfvITObJ3VqIo,8589
14
+ memvcs/commands/daemon.py,sha256=dD20IPjwebtmMCO8vE5hVQoTDzLomxPiCoDwkrST7OU,9895
14
15
  memvcs/commands/decay.py,sha256=QcgOTMJZxrfw_AOz94YHA3LGoNXRMDn69TxWlUrpSw4,2421
15
16
  memvcs/commands/diff.py,sha256=KcgD57_fae4uvQ8G9ZbXmLpAYYIDiWiBuVcjsDtyE1U,5480
16
- memvcs/commands/distill.py,sha256=Inl6igvjewGTT1L4nH48PIi8_oUtlFgJwq1gUTosI9E,2171
17
- memvcs/commands/fsck.py,sha256=PQWEoqmGKhjZEEMYBf1pnORz8j-YaOLFojmQkND3m3Q,6545
18
- memvcs/commands/garden.py,sha256=0ZbohharxBC6-n1Y2Cgpyfpwuzlq_vmWi3Yu0pQRQBA,3269
17
+ memvcs/commands/distill.py,sha256=YbPU1_os8GBFMjznNoOsevdqJa_MtiGO8B5vFxIjE9g,2858
18
+ memvcs/commands/federated.py,sha256=D4UiRFZWnQrW7kM4KqY0s2ttAqM2t-xeJN5-b_WKSHE,1633
19
+ memvcs/commands/fsck.py,sha256=AdJBMLA2myQ0cJJcjUgsYptsE3qvX4JQc9UAwVmSHlA,7772
20
+ memvcs/commands/garden.py,sha256=vSmI6XPpxK3EkLHCVpjWRg7eJPszHHzbcH8B14csueI,3820
21
+ memvcs/commands/gc.py,sha256=fHQl99HckZ8CcF2iI-PSH46aN-RmbPk6cRrC0WEE_94,1360
19
22
  memvcs/commands/graph.py,sha256=MDi6bK2w0OrpK5VOE8XXw5gQX7BuD7VzUyqJ5Ra9Bsg,4746
20
23
  memvcs/commands/init.py,sha256=TsrLFLXwkDFT0opsYJTfwu0NIxLrNiiba5SpzRtxjDI,1614
21
24
  memvcs/commands/log.py,sha256=eNlLs0-PS2nF0pMAMI8izKGUiEb2m3S0RB4Zh6cUQpE,2859
22
25
  memvcs/commands/mcp.py,sha256=PMfwVD6uHltN58Jh7IOiS1w7oND42tg14QKRCJNudmY,1740
23
- memvcs/commands/merge.py,sha256=kB9bXBagZrZYz1mozVGwelMTJ3ATm9QyINrE90FhXhA,2417
26
+ memvcs/commands/merge.py,sha256=s3QLZp-_I6OvhllLhL9yFZAQ8d4M4FbvxkXV7gUgw5M,4877
24
27
  memvcs/commands/pack.py,sha256=rIDjMpxJG0oxrWnB3vCGHqviCITIeIbdy3nhuHVHzM8,3629
25
- memvcs/commands/pull.py,sha256=qeEtBEuXo-BLsOqBU146V2lUK1WrCNp1d8z6qqWhhyU,2113
28
+ memvcs/commands/prove.py,sha256=o_RPvSK061WiaM4YfNIGlTC357s5_AfY4iOx4-hwFyE,2094
29
+ memvcs/commands/pull.py,sha256=hn9FIlNc3KUr5EUDo4_66KQSK0BSSXjOn32xaDNxf0Q,3621
26
30
  memvcs/commands/push.py,sha256=0abEdHkCMfHpH_Nmlw3OaU7Hzi0-RXF-cTVHpiSPw6k,5086
27
31
  memvcs/commands/recall.py,sha256=7nwC4mFYpdjKWG-Cs3cpDLr5_SgYJ6HkVSXDOkFke5A,4592
28
32
  memvcs/commands/reflog.py,sha256=j8Rxw_4jZuldS1k1g3wF2EItmPxBEmogWcbccOZrGkw,1117
29
33
  memvcs/commands/remote.py,sha256=4PXDZjoU4YA4IbGrn_1KbFVCSVxVB_pVdI2nIn1NSbw,1761
30
34
  memvcs/commands/repair.py,sha256=OBVa30Zc9rOjUw2GoiSAC6iZrnuCZN_J8nHpCnk5BzM,2312
31
35
  memvcs/commands/reset.py,sha256=3TG7qOu2k1uji-TdSyXsdZ6LV2wqc2MB8aSJ6q71IGk,2778
36
+ memvcs/commands/resolve.py,sha256=SFjCCYlcBqP9pjykWIPrDivtk_714VhsWl1Vt7gjyfM,4093
32
37
  memvcs/commands/resurrect.py,sha256=zi4ErN1jWVCn8I5rV4g_Dlbg1YadGEU6Xhc7srzlwfg,2503
33
38
  memvcs/commands/search.py,sha256=NOMbkQmVurQ-_d7bZVf9vjOH6OgVPeErqpLZiSxsvBA,5322
34
39
  memvcs/commands/serve.py,sha256=n8DroVRIQVm5UO2-o-9JU17pQYF-HYOMIJKycdRcBMs,1408
@@ -39,30 +44,44 @@ memvcs/commands/tag.py,sha256=CaCnA3JifVrdr8DfX4g0bp-_oRvagJkQFcI4bJbW1uM,3004
39
44
  memvcs/commands/test.py,sha256=HZrpGZQhu9HnGZLjiq8TXi8jfOZqP-wc3bW6mgpP2yk,3926
40
45
  memvcs/commands/timeline.py,sha256=xdOr2jz-_ArSPY-GxwXBloiwhfBzIfz4MAi-JEhP8H0,3666
41
46
  memvcs/commands/tree.py,sha256=vdULq4vIXA_4gNfMnHn_Y78BwE0sJoeTBOnFJR3WsZ4,4927
42
- memvcs/commands/verify.py,sha256=aH0FN_7xRulRV2oSLYSB4BiAw_U81IkZ5sFdBRmxdZ0,1858
47
+ memvcs/commands/verify.py,sha256=04CVW5NYWkUlPJ5z1Kci6dfQFM6UmPTGZh9ZextFLMc,3887
43
48
  memvcs/commands/when.py,sha256=MMQ15PFXFCTmjIq7dr0tC0XvGAdndMvckVnnWehc60Y,3692
44
49
  memvcs/core/__init__.py,sha256=dkIC-4tS0GhwV2mZIbofEe8xR8uiFwrxslGf1aXwhYg,493
45
50
  memvcs/core/access_index.py,sha256=HhacnzSUASzRV2jhDHkwRFoPS3rtqh9n9yE1VV7JXpk,5596
51
+ memvcs/core/audit.py,sha256=8APkm9Spl_-1rIdyRQz1elyxOeK3nlpwm0CLkpLlhTE,3732
46
52
  memvcs/core/config_loader.py,sha256=j-jgLDp2TRzWN9ZEZebfWSfatevBNYs0FEb3ud1SIR8,8277
47
- memvcs/core/consistency.py,sha256=JUUlrGB8b2DMmozoP7KFNqd6nSLzKDZaHGbYyKlK_l8,7464
53
+ memvcs/core/consistency.py,sha256=YOG8xhqZLKZCLbai2rdcP0KxYPNGFv5RRMwrQ6qCeyc,7462
48
54
  memvcs/core/constants.py,sha256=WUjAb50BFcF0mbFi_GNteDLCxLihmViBm9Fb-JMPmbM,220
55
+ memvcs/core/crypto_verify.py,sha256=WrOgDtIEwpjcPfDj2uqwdyg3sIM3j1hUSVPEFvptWnc,9936
49
56
  memvcs/core/decay.py,sha256=ROGwnqngs7eJNkbKmwyOdij607m73vpmoJqzrIDLBzk,6581
50
57
  memvcs/core/diff.py,sha256=koEHTLciIUxYKVJVuvmY0GDXMgDgGZP_qg5RayhF-iE,13226
51
- memvcs/core/distiller.py,sha256=QBoTz3xFVepwGHOXVuIr5qfln2tkNo1CtcBpKIjsnqc,10337
52
- memvcs/core/gardener.py,sha256=bFMyHU5H5-rYZIahT8j14ZOvBs5LSVhYZiTbyw7SQl4,16080
58
+ memvcs/core/distiller.py,sha256=fsZqOHxHTro0yy7rrMW3j5oUMibsVOShlikn2UjOieQ,10440
59
+ memvcs/core/encryption.py,sha256=epny_nlW6ylllv1qxs1mAcFq-PrLIisgfot4llOoAqw,5289
60
+ memvcs/core/federated.py,sha256=H9U5-TgiY_OjQ6Adn85Pw6hV1FYtlXgjjQYMTor35EY,2828
61
+ memvcs/core/gardener.py,sha256=_io40S0OQzPz3euKpS0M6QqEApxxkaX1UXs8uYttQag,16193
53
62
  memvcs/core/hooks.py,sha256=XF9z8J5sWjAcuOyWQ2nuvEzK0UV8s4ThrcltaBZttzw,5448
54
- memvcs/core/knowledge_graph.py,sha256=fjDZ-68tUHA6AZcn-p0d32r8X3SyrMME1OyuRPxtI_0,12875
55
- memvcs/core/merge.py,sha256=eBdPd8loe7G6F8C3fMNdnm_kvlKgZ4JC5z4xnboteOI,19165
56
- memvcs/core/objects.py,sha256=zlTcNHc3ehFnLm0UoI1Ct2gw5CU4moaRLhN8hZXm3p4,9943
63
+ memvcs/core/ipfs_remote.py,sha256=985xAtSw4P9yxxw-WXtQvNSY8b2hOpFp9TNBbHpIDBk,1062
64
+ memvcs/core/knowledge_graph.py,sha256=sa2jw9AwJIaKs8obHHXdnExxHx-CebtVrgjJaa2qo14,12939
65
+ memvcs/core/merge.py,sha256=x2eSaxr4f63Eq00FCJ6DDe2TZU8H5yHQpzKzMhYsaFw,19871
66
+ memvcs/core/objects.py,sha256=I4UlqQoBPuzyPHKWboZbZP6cy5hL1Dz18IfBm6lInNk,10455
67
+ memvcs/core/pack.py,sha256=zXwsRWSzfup6KrkxX6_jIw6gwxmRbmEnFCoVvhNZXHQ,2999
57
68
  memvcs/core/pii_scanner.py,sha256=T6gQ1APFrSDk980fjnv4ZMF-UztbJgmUFSwGrwWixEw,10802
69
+ memvcs/core/privacy_budget.py,sha256=fOPlxoKEAmsKtda-OJCrSaKjTyw7ekcqdN7KfRBw1CY,2113
58
70
  memvcs/core/refs.py,sha256=4Nx2ZVRa_DzfUZ4O1AwzOHEjoGAEICJKqSd9GxaiD_g,16754
59
- memvcs/core/remote.py,sha256=MhQTfxpzmH0mAMb7hoQJrTOAoqX0tqZxx1Yq5Q5niS8,10117
60
- memvcs/core/repository.py,sha256=fu6ZxkF3RY7yV1FHRQ2gVOpxkwJzeffna2sZixd8puI,17894
71
+ memvcs/core/remote.py,sha256=a-Nwr7m4fUK86K-dxG1CawMID7JX2MZ6V94RHkGjkeI,11625
72
+ memvcs/core/repository.py,sha256=NzC2UFPv6ePxi5lfiSKyZFLclH4bJpWJz88pY7tDiv4,20605
61
73
  memvcs/core/schema.py,sha256=_CrEWCdArc0yDJ04GT7fyvjHqkal7gegdFSsFOjVpBc,15287
62
74
  memvcs/core/staging.py,sha256=dptdGi_74lhDkcGqGVU39ZyTkb25j-Rnkz0GWi83W1k,7221
63
- memvcs/core/temporal_index.py,sha256=OmgfznlScItVf2sML7JOj_WaGtKJZMIsP818YKUlMAw,3554
75
+ memvcs/core/temporal_index.py,sha256=81hZHlVElp2UpXjseFVCdDUwxGM45zIU-y1dDlOhFHI,4012
64
76
  memvcs/core/test_runner.py,sha256=7-0jCvji63JRbVfy3LNQWIQ7VL5weulOoG7SY1-YJbw,11496
65
- memvcs/core/vector_store.py,sha256=JqyiPbznxEkuD1CIna5DKm0PwrlQ4tVARJpt6W0mESE,10599
77
+ memvcs/core/trust.py,sha256=msx80Cl3bxyQTY8mFUKWY9P6l3zb1s8FafympgHwtpo,3494
78
+ memvcs/core/vector_store.py,sha256=yUAp5BlaAtjkrtsdY1I-vmAp_YIFgJykBoNlp5hcg0I,11063
79
+ memvcs/core/zk_proofs.py,sha256=xo0uB6sbufz9OcnZLJK2iH3CXtuVAMopGNp0S1ne_Wo,967
80
+ memvcs/core/llm/__init__.py,sha256=vnjtE9Xlv9a2pZV88DMT9JaINkZ30hC9VLPL5lJRlps,236
81
+ memvcs/core/llm/anthropic_provider.py,sha256=O1eaCb9r464ajLJz-Gy8lGxBie5ojRUZ_5HdgRXO5KY,1540
82
+ memvcs/core/llm/base.py,sha256=qPzg3KPAMeoyWGc_2JoVR4-plpdft5Rc2g9uO-Z4fJQ,623
83
+ memvcs/core/llm/factory.py,sha256=sRl4XiAHs1eReXjCdwYLvbjUaIxdfQZV93hiME-i8j8,912
84
+ memvcs/core/llm/openai_provider.py,sha256=hGOdEPWf96zP7PqC5FzwISXoNDvLSOXCHJjbRj2HgI8,885
66
85
  memvcs/core/storage/__init__.py,sha256=yJE7bm5G7VlFLpSVFrrTkP4eOyQlWRPfBvEP9T5PW44,1901
67
86
  memvcs/core/storage/base.py,sha256=IK4To8Cb-LHv5ltlaQLdB6LE-69euFK3hNqBtMCe7-g,9956
68
87
  memvcs/core/storage/gcs.py,sha256=-cWuGw1jkFh-Xig-Abmwr9HGwjW5lWQJuF2xcAR1l78,10632
@@ -79,8 +98,8 @@ memvcs/retrieval/recaller.py,sha256=8KY-XjMUz5_vcKf46zI64uk1DEM__u7wM92ShukOtsY,
79
98
  memvcs/retrieval/strategies.py,sha256=26yxQQubQfjxWQXknfVMxuzPHf2EcZxJg_B99BEdl5c,11458
80
99
  memvcs/utils/__init__.py,sha256=8psUzz4Ntv2GzbRebkeVsoyC6Ck-FIwi0_lfYdj5oho,185
81
100
  memvcs/utils/helpers.py,sha256=37zg_DcQ2y99b9NSLqxFkglHe13rJXKhFDpEbQ7iLhM,4121
82
- agmem-0.1.2.dist-info/METADATA,sha256=uIzEeVVPQ36Kdy0NQ0ygJS9pvMSglfYSTo_oNjG5TsM,26608
83
- agmem-0.1.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
84
- agmem-0.1.2.dist-info/entry_points.txt,sha256=at7eWycgjqOo1wbUMECnXUsNo3gpCkJTU71OzrGLHu0,42
85
- agmem-0.1.2.dist-info/top_level.txt,sha256=HtMMsKuwLKLOdgF1GxqQztqFM54tTJctVdJuOec6B-4,7
86
- agmem-0.1.2.dist-info/RECORD,,
101
+ agmem-0.1.3.dist-info/METADATA,sha256=gtN5tU3wSR8trf5kKJIBP6KgAGQrjm66dCs8NRvu_ao,36834
102
+ agmem-0.1.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
103
+ agmem-0.1.3.dist-info/entry_points.txt,sha256=at7eWycgjqOo1wbUMECnXUsNo3gpCkJTU71OzrGLHu0,42
104
+ agmem-0.1.3.dist-info/top_level.txt,sha256=HtMMsKuwLKLOdgF1GxqQztqFM54tTJctVdJuOec6B-4,7
105
+ agmem-0.1.3.dist-info/RECORD,,
memvcs/cli.py CHANGED
@@ -58,6 +58,11 @@ from .commands.decay import DecayCommand
58
58
  from .commands.resurrect import ResurrectCommand
59
59
  from .commands.verify import VerifyCommand
60
60
  from .commands.repair import RepairCommand
61
+ from .commands.audit import AuditCommand
62
+ from .commands.federated import FederatedCommand
63
+ from .commands.resolve import ResolveCommand
64
+ from .commands.prove import ProveCommand
65
+ from .commands.gc import GcCommand
61
66
 
62
67
 
63
68
  # List of available commands
@@ -100,6 +105,11 @@ COMMANDS = [
100
105
  ResurrectCommand,
101
106
  VerifyCommand,
102
107
  RepairCommand,
108
+ AuditCommand,
109
+ FederatedCommand,
110
+ ResolveCommand,
111
+ ProveCommand,
112
+ GcCommand,
103
113
  ]
104
114
 
105
115
 
memvcs/commands/add.py CHANGED
@@ -198,6 +198,12 @@ class AddCommand:
198
198
  print(f"Rejected {rejected_count} file(s) - use --force to override")
199
199
  if staged_count > 0:
200
200
  print("Run 'agmem commit -m \"message\"' to save snapshot")
201
+ try:
202
+ from ..core.audit import append_audit
203
+
204
+ append_audit(repo.mem_dir, "add", {"staged_count": staged_count})
205
+ except Exception:
206
+ pass
201
207
  else:
202
208
  print("No files staged")
203
209
 
@@ -0,0 +1,59 @@
1
+ """
2
+ agmem audit - Tamper-evident audit trail.
3
+
4
+ Read and verify the append-only audit log.
5
+ """
6
+
7
+ import argparse
8
+
9
+ from ..commands.base import require_repo
10
+ from ..core.audit import read_audit, verify_audit
11
+
12
+
13
+ class AuditCommand:
14
+ """Show and verify the tamper-evident audit log."""
15
+
16
+ name = "audit"
17
+ help = "Show and verify the tamper-evident audit log"
18
+
19
+ @staticmethod
20
+ def add_arguments(parser: argparse.ArgumentParser):
21
+ parser.add_argument(
22
+ "-n",
23
+ "--max",
24
+ type=int,
25
+ default=50,
26
+ metavar="N",
27
+ help="Show at most N entries (default 50)",
28
+ )
29
+ parser.add_argument(
30
+ "--verify",
31
+ action="store_true",
32
+ help="Verify the audit chain and report first tampering point",
33
+ )
34
+
35
+ @staticmethod
36
+ def execute(args) -> int:
37
+ repo, code = require_repo()
38
+ if code != 0:
39
+ return code
40
+
41
+ if args.verify:
42
+ valid, first_bad = verify_audit(repo.mem_dir)
43
+ if valid:
44
+ print("Audit log chain is valid.")
45
+ return 0
46
+ print(f"Audit log chain invalid at entry index {first_bad}.")
47
+ return 1
48
+
49
+ entries = read_audit(repo.mem_dir, max_entries=args.max)
50
+ if not entries:
51
+ print("No audit entries.")
52
+ return 0
53
+ for e in entries:
54
+ ts = e.get("timestamp", "")
55
+ op = e.get("operation", "")
56
+ details = e.get("details", {})
57
+ detail_str = " ".join(f"{k}={v}" for k, v in sorted(details.items()) if v is not None)
58
+ print(f"{ts} {op} {detail_str}")
59
+ return 0
memvcs/commands/clone.py CHANGED
@@ -90,5 +90,12 @@ class CloneCommand:
90
90
  }
91
91
  config_file.write_text(json.dumps(config, indent=2))
92
92
 
93
+ # Copy remote's public key to .mem/keys/remotes/origin.pub for trust store
94
+ remote_keys = remote_mem / "keys" / "public.pem"
95
+ if remote_keys.exists():
96
+ keys_remotes = target / ".mem" / "keys" / "remotes"
97
+ keys_remotes.mkdir(parents=True, exist_ok=True)
98
+ shutil.copy2(remote_keys, keys_remotes / "origin.pub")
99
+
93
100
  print(f"Cloned into {target}")
94
101
  return 0
memvcs/commands/daemon.py CHANGED
@@ -203,10 +203,38 @@ class DaemonCommand:
203
203
  signal.signal(signal.SIGTERM, signal_handler)
204
204
  signal.signal(signal.SIGINT, signal_handler)
205
205
 
206
+ # Health monitoring: periodic integrity check (configurable interval)
207
+ last_health_check = 0
208
+ health_check_interval = 3600 # 1 hour
209
+
206
210
  try:
207
211
  while running:
208
212
  time.sleep(1)
209
213
 
214
+ # Periodic health check (Merkle/signature, optional)
215
+ if (
216
+ health_check_interval
217
+ and (time.time() - last_health_check) >= health_check_interval
218
+ ):
219
+ try:
220
+ from ..core.crypto_verify import verify_commit, load_public_key
221
+
222
+ head = repo.refs.get_branch_commit(
223
+ repo.refs.get_current_branch() or "main"
224
+ ) or (repo.refs.get_head() or {}).get("value")
225
+ if head:
226
+ ok, err = verify_commit(
227
+ repo.object_store,
228
+ head,
229
+ load_public_key(repo.mem_dir),
230
+ mem_dir=repo.mem_dir,
231
+ )
232
+ if not ok and err and "tampered" in (err or "").lower():
233
+ sys.stderr.write(f"Health check: {err}\n")
234
+ except Exception:
235
+ pass
236
+ last_health_check = time.time()
237
+
210
238
  if handler.pending:
211
239
  elapsed = time.time() - handler.last_change
212
240
  if elapsed >= debounce:
@@ -41,6 +41,11 @@ class DistillCommand:
41
41
  action="store_true",
42
42
  help="Do not create safety branch",
43
43
  )
44
+ parser.add_argument(
45
+ "--private",
46
+ action="store_true",
47
+ help="Use differential privacy (spend epsilon from budget)",
48
+ )
44
49
 
45
50
  @staticmethod
46
51
  def execute(args) -> int:
@@ -48,6 +53,17 @@ class DistillCommand:
48
53
  if code != 0:
49
54
  return code
50
55
 
56
+ if getattr(args, "private", False):
57
+ from ..core.privacy_budget import load_budget, spend_epsilon
58
+
59
+ spent, max_eps, _ = load_budget(repo.mem_dir)
60
+ epsilon_cost = 0.1
61
+ if not spend_epsilon(repo.mem_dir, epsilon_cost):
62
+ print(f"Privacy budget exceeded (spent {spent:.2f}, max {max_eps}).")
63
+ return 1
64
+ if spent + epsilon_cost > max_eps * 0.8:
65
+ print(f"Privacy budget low: {spent + epsilon_cost:.2f}/{max_eps}")
66
+
51
67
  config = DistillerConfig(
52
68
  source_dir=args.source,
53
69
  target_dir=args.target,
@@ -0,0 +1,53 @@
1
+ """
2
+ agmem federated - Federated memory collaboration.
3
+
4
+ Push local summaries to coordinator; pull merged summaries.
5
+ """
6
+
7
+ import argparse
8
+
9
+ from ..commands.base import require_repo
10
+ from ..core.federated import get_federated_config, produce_local_summary, push_updates, pull_merged
11
+
12
+
13
+ class FederatedCommand:
14
+ """Federated memory collaboration with coordinator."""
15
+
16
+ name = "federated"
17
+ help = "Push/pull federated summaries (coordinator must be configured)"
18
+
19
+ @staticmethod
20
+ def add_arguments(parser: argparse.ArgumentParser):
21
+ parser.add_argument(
22
+ "action",
23
+ choices=["push", "pull"],
24
+ help="Push local summary or pull merged from coordinator",
25
+ )
26
+
27
+ @staticmethod
28
+ def execute(args) -> int:
29
+ repo, code = require_repo()
30
+ if code != 0:
31
+ return code
32
+
33
+ cfg = get_federated_config(repo.root)
34
+ if not cfg:
35
+ print(
36
+ "Federated collaboration not enabled. Set federated.enabled and coordinator_url in config."
37
+ )
38
+ return 1
39
+
40
+ if args.action == "push":
41
+ summary = produce_local_summary(repo.root, cfg["memory_types"])
42
+ msg = push_updates(repo.root, summary)
43
+ print(msg)
44
+ return 0 if "Pushed" in msg else 1
45
+ else:
46
+ data = pull_merged(repo.root)
47
+ if data is None:
48
+ print("Pull failed or coordinator unavailable.")
49
+ return 1
50
+ print("Merged summary from coordinator:")
51
+ for k, v in (data or {}).items():
52
+ print(f" {k}: {v}")
53
+ return 0