flowscript-agents 0.2.4__tar.gz → 0.2.6__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.
Files changed (59) hide show
  1. flowscript_agents-0.2.6/:memory: +29 -0
  2. flowscript_agents-0.2.6/:memory:.audit.manifest.json +10 -0
  3. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/PKG-INFO +46 -6
  4. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/README.md +45 -5
  5. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/docs/lifecycle.md +54 -1
  6. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/examples/CLAUDE.md.example +13 -7
  7. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/__init__.py +1 -1
  8. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/mcp.py +403 -26
  9. flowscript_agents-0.2.6/flowscript_agents/tool-integrity.json +15 -0
  10. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/pyproject.toml +1 -1
  11. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/tests/test_mcp.py +168 -6
  12. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/.github/workflows/test.yml +0 -0
  13. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/.gitignore +0 -0
  14. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/AUDIT_TRAIL_DESIGN.md +0 -0
  15. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/docs/adapters.md +0 -0
  16. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/docs/api-reference.md +0 -0
  17. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/docs/audit-trail.md +0 -0
  18. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/docs/brand/logo-512.png +0 -0
  19. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/docs/brand/social-preview.png +0 -0
  20. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/docs/flowscript-demo.png +0 -0
  21. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/examples/langgraph_live_test.py +0 -0
  22. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/examples/temporal_e2e_test.py +0 -0
  23. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/audit.py +0 -0
  24. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/camel_ai.py +0 -0
  25. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/crewai.py +0 -0
  26. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/embeddings/__init__.py +0 -0
  27. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/embeddings/_utils.py +0 -0
  28. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/embeddings/consolidate.py +0 -0
  29. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/embeddings/extract.py +0 -0
  30. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/embeddings/index.py +0 -0
  31. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/embeddings/providers.py +0 -0
  32. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/embeddings/search.py +0 -0
  33. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/google_adk.py +0 -0
  34. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/haystack.py +0 -0
  35. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/langgraph.py +0 -0
  36. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/llamaindex.py +0 -0
  37. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/memory.py +0 -0
  38. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/openai_agents.py +0 -0
  39. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/pydantic_ai.py +0 -0
  40. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/query.py +0 -0
  41. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/smolagents.py +0 -0
  42. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/types.py +0 -0
  43. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/flowscript_agents/unified.py +0 -0
  44. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/scripts/validate_dedup_threshold.py +0 -0
  45. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/tests/conftest.py +0 -0
  46. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/tests/test_audit.py +0 -0
  47. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/tests/test_camel_ai.py +0 -0
  48. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/tests/test_consolidation.py +0 -0
  49. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/tests/test_crewai.py +0 -0
  50. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/tests/test_embeddings.py +0 -0
  51. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/tests/test_google_adk.py +0 -0
  52. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/tests/test_haystack.py +0 -0
  53. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/tests/test_langgraph.py +0 -0
  54. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/tests/test_llamaindex.py +0 -0
  55. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/tests/test_memory.py +0 -0
  56. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/tests/test_openai_agents.py +0 -0
  57. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/tests/test_pydantic_ai.py +0 -0
  58. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/tests/test_smolagents.py +0 -0
  59. {flowscript_agents-0.2.4 → flowscript_agents-0.2.6}/tests/test_temporal.py +0 -0
@@ -0,0 +1,29 @@
1
+ {
2
+ "flowscript_memory": "1.0.0",
3
+ "ir": {
4
+ "version": "1.0.0",
5
+ "nodes": [],
6
+ "relationships": [],
7
+ "states": [],
8
+ "invariants": {
9
+ "causal_acyclic": true,
10
+ "all_nodes_reachable": true,
11
+ "tension_axes_labeled": true,
12
+ "state_fields_present": true
13
+ },
14
+ "metadata": {
15
+ "source_files": [
16
+ "memory-api"
17
+ ],
18
+ "parsed_at": "2026-03-24T15:40:53.676226+00:00",
19
+ "parser": "flowscript-agents"
20
+ }
21
+ },
22
+ "temporal": {},
23
+ "config": {
24
+ "touch_on_query": true,
25
+ "source_file": null,
26
+ "author": null,
27
+ "temporal": null
28
+ }
29
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "active_file": ":memory:.audit.jsonl",
3
+ "active_last_hash": "sha256:8dfb8c37838e7812e9c2727d8fe76ffca44f677b9d5499fa13513fac3800816f",
4
+ "active_last_seq": 0,
5
+ "files": [],
6
+ "last_cleanup": null,
7
+ "memory_file": ":memory:",
8
+ "retention_months": 84,
9
+ "version": 1
10
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flowscript-agents
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: Complete agent memory: reasoning queries + vector search + auto-extraction. Decision intelligence for LangGraph, CrewAI, Google ADK, OpenAI Agents SDK, Pydantic AI, smolagents, LlamaIndex, Haystack, and CAMEL-AI.
5
5
  Project-URL: Homepage, https://flowscript.org
6
6
  Project-URL: Repository, https://github.com/phillipclapham/flowscript-agents
@@ -70,7 +70,7 @@ Description-Content-Type: text/markdown
70
70
 
71
71
  <p align="center"><strong>Agent memory that tracks why you decided, what conflicts, and what's blocked. Not just what was said.</strong></p>
72
72
 
73
- [![Tests](https://img.shields.io/badge/tests-581%20passing-brightgreen)](https://github.com/phillipclapham/flowscript-agents) [![PyPI](https://img.shields.io/pypi/v/flowscript-agents)](https://pypi.org/project/flowscript-agents/) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Python](https://img.shields.io/badge/python-3.10%2B-blue)](https://pypi.org/project/flowscript-agents/)
73
+ [![Tests](https://img.shields.io/badge/tests-584%20passing-brightgreen)](https://github.com/phillipclapham/flowscript-agents) [![PyPI](https://img.shields.io/pypi/v/flowscript-agents)](https://pypi.org/project/flowscript-agents/) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Python](https://img.shields.io/badge/python-3.10%2B-blue)](https://pypi.org/project/flowscript-agents/)
74
74
 
75
75
  ---
76
76
 
@@ -341,11 +341,51 @@ Framework attribution is automatic — every audit entry records which adapter t
341
341
 
342
342
  ---
343
343
 
344
- ## Memory That Evolves
344
+ ## Session Lifecycle — How Memory Gets Smarter
345
345
 
346
- Nodes graduate through four temporal tiers based on actual use — `current` → `developing` → `proven` → `foundation`. Every query touches returned nodes, so knowledge that keeps getting queried earns its place. One-off observations fade naturally. Dormant nodes are pruned to the audit trail archived with full provenance, never destroyed.
346
+ Just like a mind needs sleep to consolidate memories, your agent's reasoning graph needs regular session wraps to develop intelligence over time. Without consolidation cycles, knowledge accumulates as noise instead of maturing.
347
347
 
348
- After 20 sessions, your memory is a curated knowledge base, not a pile of notes. [Session lifecycle details →](docs/lifecycle.md)
348
+ **Temporal tiers** nodes graduate based on actual use:
349
+
350
+ | Tier | Meaning | Behavior |
351
+ |:-----|:--------|:---------|
352
+ | `current` | Recent observations | May be pruned if not reinforced |
353
+ | `developing` | Emerging patterns (2+ touches) | Building confidence |
354
+ | `proven` | Validated through use (3+ touches) | Protected from pruning |
355
+ | `foundation` | Core truths | Always preserved |
356
+
357
+ Every query touches returned nodes — knowledge that keeps getting queried earns its place. One-off observations fade naturally. Dormant nodes are pruned to the audit trail — archived with full provenance, never destroyed.
358
+
359
+ **Three ways session wraps happen:**
360
+
361
+ 1. **Explicit** — the LLM calls the `session_wrap` tool when you say "let's wrap up" (best results)
362
+ 2. **Auto-wrap** — after 5 minutes of inactivity, the MCP server auto-consolidates (safety net, configurable via `FLOWSCRIPT_AUTO_WRAP_MINUTES`, set to `0` to disable)
363
+ 3. **Process exit** — when the MCP server shuts down, a final consolidation runs automatically
364
+
365
+ **For SDK users** — adapters support context managers that auto-wrap:
366
+
367
+ ```python
368
+ from flowscript_agents.adapters.langgraph import FlowScriptStore
369
+
370
+ with FlowScriptStore("agent-memory.json") as store:
371
+ # work happens — all mutations auto-save
372
+ store.put(("agents",), "key", {"value": "data"})
373
+ # close() fires automatically → session_wrap() + save
374
+ ```
375
+
376
+ After 20 sessions, your memory is a curated knowledge base, not a pile of notes. [Full lifecycle details →](docs/lifecycle.md)
377
+
378
+ ---
379
+
380
+ ## Description Integrity
381
+
382
+ MCP tool descriptions are the prompts your LLM reads. If they're mutated in-process, the LLM silently follows poisoned instructions. The FlowScript MCP server includes three-layer integrity verification — a reference implementation of [deterministic description integrity for MCP](https://github.com/modelcontextprotocol/modelcontextprotocol/discussions/2402):
383
+
384
+ 1. **`verify_integrity` tool** — LLM-callable. SHA-256 hashes of all tool definitions, deep-frozen at startup (`MappingProxyType`). Detects in-process mutation by malicious dependencies, monkey-patching, or middleware.
385
+ 2. **`flowscript://integrity/manifest` resource** — Host-verifiable. Claude Code / Cursor can verify descriptions without LLM involvement.
386
+ 3. **`tool-integrity.json`** — Build-time root of trust. Generated via `flowscript-mcp --generate-manifest`, ships in the package.
387
+
388
+ Both the Python and [TypeScript](https://www.npmjs.com/package/flowscript-core) MCP servers implement this architecture. Honest threat model: detects in-process mutation, not supply chain or transport-layer attacks. [Full discussion →](https://github.com/modelcontextprotocol/modelcontextprotocol/discussions/2402)
349
389
 
350
390
  ---
351
391
 
@@ -375,7 +415,7 @@ Under the hood: a local semantic graph with typed nodes, typed relationships, an
375
415
  | [flowscript-core](https://www.npmjs.com/package/flowscript-core) | TypeScript SDK — Memory class, 15 tools, token budgeting, audit trail | `npm install flowscript-core` |
376
416
  | [flowscript.org](https://flowscript.org) | Web editor, D3 visualization, live query panel | Browser |
377
417
 
378
- **1,312 tests** across Python (581) and TypeScript (731). Same audit trail format and canonical JSON serialization across both languages.
418
+ **1,315 tests** across Python (584) and TypeScript (731). Same audit trail format and canonical JSON serialization across both languages.
379
419
 
380
420
  ### Docs
381
421
 
@@ -6,7 +6,7 @@
6
6
 
7
7
  <p align="center"><strong>Agent memory that tracks why you decided, what conflicts, and what's blocked. Not just what was said.</strong></p>
8
8
 
9
- [![Tests](https://img.shields.io/badge/tests-581%20passing-brightgreen)](https://github.com/phillipclapham/flowscript-agents) [![PyPI](https://img.shields.io/pypi/v/flowscript-agents)](https://pypi.org/project/flowscript-agents/) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Python](https://img.shields.io/badge/python-3.10%2B-blue)](https://pypi.org/project/flowscript-agents/)
9
+ [![Tests](https://img.shields.io/badge/tests-584%20passing-brightgreen)](https://github.com/phillipclapham/flowscript-agents) [![PyPI](https://img.shields.io/pypi/v/flowscript-agents)](https://pypi.org/project/flowscript-agents/) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Python](https://img.shields.io/badge/python-3.10%2B-blue)](https://pypi.org/project/flowscript-agents/)
10
10
 
11
11
  ---
12
12
 
@@ -277,11 +277,51 @@ Framework attribution is automatic — every audit entry records which adapter t
277
277
 
278
278
  ---
279
279
 
280
- ## Memory That Evolves
280
+ ## Session Lifecycle — How Memory Gets Smarter
281
281
 
282
- Nodes graduate through four temporal tiers based on actual use — `current` → `developing` → `proven` → `foundation`. Every query touches returned nodes, so knowledge that keeps getting queried earns its place. One-off observations fade naturally. Dormant nodes are pruned to the audit trail archived with full provenance, never destroyed.
282
+ Just like a mind needs sleep to consolidate memories, your agent's reasoning graph needs regular session wraps to develop intelligence over time. Without consolidation cycles, knowledge accumulates as noise instead of maturing.
283
283
 
284
- After 20 sessions, your memory is a curated knowledge base, not a pile of notes. [Session lifecycle details →](docs/lifecycle.md)
284
+ **Temporal tiers** nodes graduate based on actual use:
285
+
286
+ | Tier | Meaning | Behavior |
287
+ |:-----|:--------|:---------|
288
+ | `current` | Recent observations | May be pruned if not reinforced |
289
+ | `developing` | Emerging patterns (2+ touches) | Building confidence |
290
+ | `proven` | Validated through use (3+ touches) | Protected from pruning |
291
+ | `foundation` | Core truths | Always preserved |
292
+
293
+ Every query touches returned nodes — knowledge that keeps getting queried earns its place. One-off observations fade naturally. Dormant nodes are pruned to the audit trail — archived with full provenance, never destroyed.
294
+
295
+ **Three ways session wraps happen:**
296
+
297
+ 1. **Explicit** — the LLM calls the `session_wrap` tool when you say "let's wrap up" (best results)
298
+ 2. **Auto-wrap** — after 5 minutes of inactivity, the MCP server auto-consolidates (safety net, configurable via `FLOWSCRIPT_AUTO_WRAP_MINUTES`, set to `0` to disable)
299
+ 3. **Process exit** — when the MCP server shuts down, a final consolidation runs automatically
300
+
301
+ **For SDK users** — adapters support context managers that auto-wrap:
302
+
303
+ ```python
304
+ from flowscript_agents.adapters.langgraph import FlowScriptStore
305
+
306
+ with FlowScriptStore("agent-memory.json") as store:
307
+ # work happens — all mutations auto-save
308
+ store.put(("agents",), "key", {"value": "data"})
309
+ # close() fires automatically → session_wrap() + save
310
+ ```
311
+
312
+ After 20 sessions, your memory is a curated knowledge base, not a pile of notes. [Full lifecycle details →](docs/lifecycle.md)
313
+
314
+ ---
315
+
316
+ ## Description Integrity
317
+
318
+ MCP tool descriptions are the prompts your LLM reads. If they're mutated in-process, the LLM silently follows poisoned instructions. The FlowScript MCP server includes three-layer integrity verification — a reference implementation of [deterministic description integrity for MCP](https://github.com/modelcontextprotocol/modelcontextprotocol/discussions/2402):
319
+
320
+ 1. **`verify_integrity` tool** — LLM-callable. SHA-256 hashes of all tool definitions, deep-frozen at startup (`MappingProxyType`). Detects in-process mutation by malicious dependencies, monkey-patching, or middleware.
321
+ 2. **`flowscript://integrity/manifest` resource** — Host-verifiable. Claude Code / Cursor can verify descriptions without LLM involvement.
322
+ 3. **`tool-integrity.json`** — Build-time root of trust. Generated via `flowscript-mcp --generate-manifest`, ships in the package.
323
+
324
+ Both the Python and [TypeScript](https://www.npmjs.com/package/flowscript-core) MCP servers implement this architecture. Honest threat model: detects in-process mutation, not supply chain or transport-layer attacks. [Full discussion →](https://github.com/modelcontextprotocol/modelcontextprotocol/discussions/2402)
285
325
 
286
326
  ---
287
327
 
@@ -311,7 +351,7 @@ Under the hood: a local semantic graph with typed nodes, typed relationships, an
311
351
  | [flowscript-core](https://www.npmjs.com/package/flowscript-core) | TypeScript SDK — Memory class, 15 tools, token budgeting, audit trail | `npm install flowscript-core` |
312
352
  | [flowscript.org](https://flowscript.org) | Web editor, D3 visualization, live query panel | Browser |
313
353
 
314
- **1,312 tests** across Python (581) and TypeScript (731). Same audit trail format and canonical JSON serialization across both languages.
354
+ **1,315 tests** across Python (584) and TypeScript (731). Same audit trail format and canonical JSON serialization across both languages.
315
355
 
316
356
  ### Docs
317
357
 
@@ -20,7 +20,19 @@ print(report.growing) # list of node IDs in growing tier
20
20
  print(report.dormant) # candidates for pruning
21
21
  ```
22
22
 
23
- Dormant nodes are pruned to the audit trail during `close()` or `sessionWrap()` — archived with full hash-chain provenance, never destroyed.
23
+ Dormant nodes are pruned to the audit trail during `close()` or `session_wrap()` — archived with full hash-chain provenance, never destroyed.
24
+
25
+ ## Why Session Wraps Matter
26
+
27
+ Just like a mind needs sleep to consolidate memories, the reasoning graph needs regular session wraps to develop intelligence over time. A session wrap is the consolidation cycle — without it, knowledge accumulates as noise instead of maturing through the temporal tiers above.
28
+
29
+ **Three mechanisms ensure consolidation happens:**
30
+
31
+ 1. **Explicit wrap** — the LLM calls `session_wrap` when the user signals session end (best results)
32
+ 2. **Auto-wrap** — the MCP server auto-consolidates after 5 minutes of inactivity (configurable via `FLOWSCRIPT_AUTO_WRAP_MINUTES` env var, `0` to disable)
33
+ 3. **Process exit** — a final consolidation runs automatically when the MCP server shuts down
34
+
35
+ For SDK users, all adapters call `session_wrap()` via their `close()` method or context manager exit.
24
36
 
25
37
  ## The `with` Pattern (Recommended)
26
38
 
@@ -99,3 +111,44 @@ mem = Memory.load_or_create("file.json",
99
111
  ## Session Start Deduplication
100
112
 
101
113
  `sessionStart()` calls both `blocked()` and `tensions()` internally (for the orientation summary). Touches from these calls are deduplicated — nodes aren't double-touched just because they appeared in both query results.
114
+
115
+ ## Writing Your Own Adapter
116
+
117
+ If you're building an adapter for a framework not yet supported, wire session wraps using this pattern:
118
+
119
+ ```python
120
+ class MyFrameworkAdapter:
121
+ def __init__(self, file_path, embedder=None, llm=None, consolidation_provider=None):
122
+ self._memory = Memory.load_or_create(file_path)
123
+ self._unified = UnifiedMemory(
124
+ file_path=file_path, embedder=embedder,
125
+ llm=llm, consolidation_provider=consolidation_provider,
126
+ )
127
+ self._memory.set_adapter_context("my_framework", "MyFrameworkAdapter", "init")
128
+ self._memory.session_start()
129
+
130
+ def close(self):
131
+ """End the session: prune dormant nodes, save. Returns SessionWrapResult."""
132
+ try:
133
+ if self._unified:
134
+ return self._unified.close()
135
+ return self._memory.session_wrap()
136
+ finally:
137
+ self._memory.clear_adapter_context()
138
+
139
+ def __enter__(self):
140
+ return self
141
+
142
+ def __exit__(self, exc_type, exc_val, exc_tb):
143
+ try:
144
+ self.close()
145
+ except Exception:
146
+ if exc_type is None:
147
+ raise # close() failure IS the error when no prior exception
148
+ ```
149
+
150
+ **Key points:**
151
+ - `close()` should call `session_wrap()` (via `UnifiedMemory.close()` or directly)
152
+ - `clear_adapter_context()` goes in the `finally` block AFTER `session_wrap()` — session lifecycle events need adapter attribution
153
+ - Context managers (`__enter__`/`__exit__`) make the `with` pattern work
154
+ - `set_adapter_context()` should be called on construction, then `set_adapter_operation()` per-operation for granular audit attribution
@@ -27,13 +27,19 @@ just report what you found or stored. Treat memory like your own notes.
27
27
  consequences before committing.
28
28
  - **To correct mistakes:** Call `remove_memory` with a node_id (use
29
29
  `search_memory` first to find it) to remove incorrect or outdated entries.
30
- - **End of session:** When the user says "wrap up", "save what we learned",
31
- or similar end-of-session phrases: review the conversation for any
32
- decisions, tradeoffs, blockers, or reasoning that wasn't already stored
33
- via `add_memory`. Save anything important you find. Then call
34
- `session_wrap` to run lifecycle maintenance (graduation, pruning,
35
- persist to disk). This is how memory gets smarter each wrap
36
- captures what matters and lets stale reasoning fade naturally.
30
+ - **End of session:** When the user says "wrap up", "let's wrap",
31
+ "save what we learned", or signals the conversation is ending:
32
+ review for any decisions/tradeoffs/reasoning not yet stored via
33
+ `add_memory`, save what's important, then call `session_wrap`.
34
+ This is the reasoning graph's consolidation cycle — like sleep for
35
+ memory. Dormant nodes get pruned to the audit trail, frequently-used
36
+ knowledge graduates through temporal tiers (current developing
37
+ proven → foundation), and the graph gets smarter over time. Without
38
+ regular wraps, knowledge accumulates as noise instead of maturing.
39
+ NOTE: An auto-wrap safety net runs after 5 minutes of inactivity
40
+ and on process exit, but explicit wraps at session boundaries
41
+ produce the best results because you can review and store final
42
+ reasoning before consolidation happens.
37
43
 
38
44
  **What to remember (call `add_memory`):**
39
45
  - Decisions and their rationale ("We chose PostgreSQL because...")
@@ -43,7 +43,7 @@ from .memory import (
43
43
  )
44
44
  from .unified import UnifiedMemory
45
45
 
46
- __version__ = "0.2.0"
46
+ __version__ = "0.2.5"
47
47
  __all__ = [
48
48
  "AuditConfig",
49
49
  "AuditQueryResult",