mindforge-memory 6.4.2__tar.gz → 6.4.3__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 (137) hide show
  1. {mindforge_memory-6.4.2/mindforge_memory.egg-info → mindforge_memory-6.4.3}/PKG-INFO +7 -6
  2. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/README.md +6 -5
  3. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/core/storage.py +9 -0
  4. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/core/version.py +2 -2
  5. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3/mindforge_memory.egg-info}/PKG-INFO +7 -6
  6. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge_memory.egg-info/SOURCES.txt +1 -0
  7. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v568_fixes.py +1 -1
  8. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v575_release_consistency.py +2 -2
  9. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v612_fixes.py +2 -2
  10. mindforge_memory-6.4.3/tests/test_v643_fixes.py +99 -0
  11. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/LICENSE +0 -0
  12. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/MindForge.py +0 -0
  13. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/__init__.py +0 -0
  14. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/adapters/__init__.py +0 -0
  15. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/adapters/claude_adapter.py +0 -0
  16. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/adapters/crewai_memory.py +0 -0
  17. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/adapters/generic_api.py +0 -0
  18. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/adapters/langgraph_store.py +0 -0
  19. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/adapters/openclaw_adapter.py +0 -0
  20. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/api/__init__.py +0 -0
  21. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/api/server.py +0 -0
  22. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/cli/__init__.py +0 -0
  23. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/cli/main.py +0 -0
  24. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/core/__init__.py +0 -0
  25. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/core/embedding.py +0 -0
  26. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/core/encryption.py +0 -0
  27. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/core/indexer.py +0 -0
  28. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/core/mindforge.py +0 -0
  29. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/core/paths.py +0 -0
  30. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/core/query.py +0 -0
  31. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/core/types.py +0 -0
  32. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/daemon/__init__.py +0 -0
  33. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/daemon/server.py +0 -0
  34. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/mcp/__init__.py +0 -0
  35. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/mcp/server.py +0 -0
  36. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/__init__.py +0 -0
  37. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/categorizer.py +0 -0
  38. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/conflict_detector.py +0 -0
  39. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/connectors.py +0 -0
  40. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/context_window.py +0 -0
  41. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/event_bus.py +0 -0
  42. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/evolution.py +0 -0
  43. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/experience.py +0 -0
  44. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/federated.py +0 -0
  45. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/federated_acl.py +0 -0
  46. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/follow_up.py +0 -0
  47. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/hybrid_search.py +0 -0
  48. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/importer.py +0 -0
  49. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/integrator.py +0 -0
  50. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/intent_router.py +0 -0
  51. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/knowledge_graph.py +0 -0
  52. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/memory_compressor.py +0 -0
  53. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/memory_decay.py +0 -0
  54. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/memory_passport.py +0 -0
  55. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/multi_agent.py +0 -0
  56. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/multimodal.py +0 -0
  57. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/outcome_learning.py +0 -0
  58. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/personality.py +0 -0
  59. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/principled_forgetting.py +0 -0
  60. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/privacy.py +0 -0
  61. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/recall.py +0 -0
  62. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/session_focus.py +0 -0
  63. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/share_conflict.py +0 -0
  64. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/skill_extractor.py +0 -0
  65. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/skill_pack.py +0 -0
  66. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/timeline_viz.py +0 -0
  67. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge/modules/v6.py +0 -0
  68. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge_memory.egg-info/dependency_links.txt +0 -0
  69. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge_memory.egg-info/entry_points.txt +0 -0
  70. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge_memory.egg-info/requires.txt +0 -0
  71. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/mindforge_memory.egg-info/top_level.txt +0 -0
  72. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/pyproject.toml +0 -0
  73. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/setup.cfg +0 -0
  74. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/setup.py +0 -0
  75. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_core.py +0 -0
  76. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_security_hardening.py +0 -0
  77. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v546_features.py +0 -0
  78. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v547_fixes.py +0 -0
  79. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v548_features.py +0 -0
  80. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v550_features.py +0 -0
  81. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v552_features.py +0 -0
  82. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v554_features.py +0 -0
  83. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v556_features.py +0 -0
  84. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v557_banner_insight_wal.py +0 -0
  85. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v557_security_fixes.py +0 -0
  86. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v557_webhook_sig_export.py +0 -0
  87. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v558_audit_fixes.py +0 -0
  88. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v558_features.py +0 -0
  89. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v560_decay_gc.py +0 -0
  90. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v560_kdf_versioning.py +0 -0
  91. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v560_module_coverage.py +0 -0
  92. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v561_security.py +0 -0
  93. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v562_p2_fixes.py +0 -0
  94. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v563_entry_coverage.py +0 -0
  95. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v563_perf_fixes.py +0 -0
  96. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v565_security.py +0 -0
  97. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v566_encrypted_search.py +0 -0
  98. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v567_security_fixes.py +0 -0
  99. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v569_fts_sync.py +0 -0
  100. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v570_coverage_expansion.py +0 -0
  101. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v570_drama_and_utils.py +0 -0
  102. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v570_encrypted_fallback.py +0 -0
  103. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v571_fixes.py +0 -0
  104. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v572_security.py +0 -0
  105. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v573_encrypted_export.py +0 -0
  106. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v573_security.py +0 -0
  107. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v576_bitemporal.py +0 -0
  108. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v576_gdpr.py +0 -0
  109. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v577_agent_governance.py +0 -0
  110. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v578_embedding.py +0 -0
  111. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v579_graph.py +0 -0
  112. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v580_experience.py +0 -0
  113. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v5812_bugfixes.py +0 -0
  114. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v583_security.py +0 -0
  115. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v584_adapters.py +0 -0
  116. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v585_benchmark.py +0 -0
  117. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v586_federated_mcp.py +0 -0
  118. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v590_features.py +0 -0
  119. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v592_features.py +0 -0
  120. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v593_features.py +0 -0
  121. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v595_features.py +0 -0
  122. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v600_forgetting_followup.py +0 -0
  123. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v600_import_timeline.py +0 -0
  124. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v600_multi_agent_formal.py +0 -0
  125. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v600_outcome_passport.py +0 -0
  126. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v600_skillpack_evolution.py +0 -0
  127. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v611_fixes.py +0 -0
  128. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v612_cascade_fixes.py +0 -0
  129. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v613_integrity.py +0 -0
  130. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v620_growth_governance.py +0 -0
  131. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v630_search_explain.py +0 -0
  132. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v631_scrypt.py +0 -0
  133. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v632_explain_interfaces.py +0 -0
  134. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v635_features.py +0 -0
  135. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v635_integration.py +0 -0
  136. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v636_fixes.py +0 -0
  137. {mindforge_memory-6.4.2 → mindforge_memory-6.4.3}/tests/test_v6_ports.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mindforge-memory
3
- Version: 6.4.2
3
+ Version: 6.4.3
4
4
  Summary: AI Agent 终身记忆系统 - 四层记忆架构 · 知识图谱 · 多模态支持
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/opok-ops/MindForge
@@ -36,11 +36,11 @@ Dynamic: license-file
36
36
 
37
37
  MindForge gives AI agents a persistent, structured long-term memory: a four-tier lifecycle model, knowledge graphs, hybrid retrieval, end-to-end encryption, and MCP / CLI / REST interfaces. All data stays on your machine.
38
38
 
39
- > **The story** — one developer, seven months, from v1.0 (March 2026) to v6.4.2: no team, no funding, 1,224 passing tests. [Read the journey →](https://opok-ops.github.io/MindForge/#developer)
39
+ > **The story** — one developer, seven months, from v1.0 (March 2026) to v6.4.3: no team, no funding, 1,227 passing tests. [Read the journey →](https://opok-ops.github.io/MindForge/#developer)
40
40
 
41
41
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
42
42
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
43
- [![Version](https://img.shields.io/badge/version-6.4.2-green.svg)](https://github.com/opok-ops/MindForge/releases)
43
+ [![Version](https://img.shields.io/badge/version-6.4.3-green.svg)](https://github.com/opok-ops/MindForge/releases)
44
44
  [![Stars](https://img.shields.io/github/stars/opok-ops/MindForge.svg)](https://github.com/opok-ops/MindForge/stargazers)
45
45
  [![Forks](https://img.shields.io/github/forks/opok-ops/MindForge.svg)](https://github.com/opok-ops/MindForge/forks)
46
46
  [![Open Issues](https://img.shields.io/github/issues/opok-ops/MindForge.svg)](https://github.com/opok-ops/MindForge/issues)
@@ -96,9 +96,10 @@ MindForge stats
96
96
 
97
97
  ## What's New
98
98
 
99
- v6.1.3 – v6.4.2 shipped in nine days (2026-11-01 → 11-09), guarded by **1,224 tests** (all passing).
99
+ v6.1.3 – v6.4.3 shipped in ten days (2026-11-01 → 11-10), guarded by **1,228 tests** (1,227 passing, 1 environment-skipped).
100
100
 
101
- - **v6.4.2 — tens-of-thousands-chars latency: another 2×** (2026-11-09). Same-machine A/B benchmark (400 memories / ~47k chars, 3 runs each): **search p50 6.3→3.0ms (2.1×), p95 11.7→4.2ms (2.8×)**; 24k-char library p50 2.5ms; fast machine state 1.8ms. Five surgical cuts: WAL + `synchronous=NORMAL` (commits skip per-write fsync), enum-downgrade memo, `row.keys()` set reuse, first-visit access-count batching merged into one `flush_access()` transaction per search, and search-audit INSERT folded into the same commit. The v5.6.3 throttle contract and v5.5.4 `recently_accessed` semantics are pinned by 23 contract tests — all green. Compliance-grade audits still commit immediately.
101
+ - **v6.4.3 — documentation-code consistency fix** (2026-11-10). Pre-release audit found that v6.4.2's claimed first cut — WAL + `synchronous=NORMAL` — **never landed in code**: `_get_conn()` set only `journal_mode=WAL`, leaving `synchronous` at SQLite's default FULL. The 2.1× search gain was real, but carried entirely by the other four cuts — real numbers, misattributed cause. This release adds `PRAGMA synchronous=NORMAL` on the WAL branch (per-connection, cross-thread; network-FS DELETE fallback stays FULL by design). Same-machine A/B on SSD shows no statistically significant latency delta (search p50 1.8 → 1.8ms — fsync is ~0.1ms-scale here); the benefit targets slow disks and IO-saturated containers, and more importantly makes the documented power-loss semantics (un-checkpointed access counts / search audits may be lost; compliance audits still commit immediately) actually hold. 4 new guard tests in `tests/test_v643_fixes.py`.
102
+ - **v6.4.2 — tens-of-thousands-chars latency: another 2×** (2026-11-09). Same-machine A/B benchmark (400 memories / ~47k chars, 3 runs each): **search p50 6.3→3.0ms (2.1×), p95 11.7→4.2ms (2.8×)**; 24k-char library p50 2.5ms; fast machine state 1.8ms. Five surgical cuts: WAL + `synchronous=NORMAL` (commits skip per-write fsync), enum-downgrade memo, `row.keys()` set reuse, first-visit access-count batching merged into one `flush_access()` transaction per search, and search-audit INSERT folded into the same commit. The v5.6.3 throttle contract and v5.5.4 `recently_accessed` semantics are pinned by 23 contract tests — all green. Compliance-grade audits still commit immediately. *(Note: the `synchronous=NORMAL` cut landed in v6.4.3 — see above.)*
102
103
  - **v6.4.1 — million-character millisecond search** (2026-11-09). Scale benchmark (8,000 memories / ~990k chars) exposed a fuzzy-fallback long tail: search p95 881ms. Root causes: SequenceMatcher wasted on mathematically-impossible matches (ratio = 2M/(m+n), M ≤ m, so n ≥ 4m can never pass 0.4) + a ~50μs/entry Python full-scan tax. Fixed with a math-capped prune + SQLite-level candidate pre-filtering: **search p95 881→30.7ms (28×)**, add p50 2.6ms flat at 10k-scale. New `scripts/bench_scale.py` + CI scale guard (3000 memories, millisecond contract) + 4 behavior-level regression tests pin the semantics.
103
104
 
104
105
  - **v6.4.0 — resident daemon & performance guards** (2026-11-08). New `mindforge daemon` subcommand: line-JSON over stdio, engine resident in a long-lived process — per-request p50 2.5ms vs 400–700ms for CLI subprocess spawning (two orders of magnitude; 2026-11-09 quiet-machine re-bench: 2.5ms vs 401ms p50, ~160×). CI now guards latency (engine in-process thresholds) and daemon 13-step E2E alongside the 16-step CLI E2E guard.
@@ -166,7 +167,7 @@ v6.1.3 – v6.4.2 shipped in nine days (2026-11-01 → 11-09), guarded by **1,22
166
167
 
167
168
  ```
168
169
  ┌──────────────────────────────────────────────────────┐
169
- │ MindForge v6.4.2 │
170
+ │ MindForge v6.4.3 │
170
171
  │ Cognitive Layer Personality · KnowledgeGraph │
171
172
  │ MemoryEvolution · FederatedMemory │
172
173
  ├──────────────────────────────────────────────────────┤
@@ -6,11 +6,11 @@
6
6
 
7
7
  MindForge gives AI agents a persistent, structured long-term memory: a four-tier lifecycle model, knowledge graphs, hybrid retrieval, end-to-end encryption, and MCP / CLI / REST interfaces. All data stays on your machine.
8
8
 
9
- > **The story** — one developer, seven months, from v1.0 (March 2026) to v6.4.2: no team, no funding, 1,224 passing tests. [Read the journey →](https://opok-ops.github.io/MindForge/#developer)
9
+ > **The story** — one developer, seven months, from v1.0 (March 2026) to v6.4.3: no team, no funding, 1,227 passing tests. [Read the journey →](https://opok-ops.github.io/MindForge/#developer)
10
10
 
11
11
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
12
12
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
13
- [![Version](https://img.shields.io/badge/version-6.4.2-green.svg)](https://github.com/opok-ops/MindForge/releases)
13
+ [![Version](https://img.shields.io/badge/version-6.4.3-green.svg)](https://github.com/opok-ops/MindForge/releases)
14
14
  [![Stars](https://img.shields.io/github/stars/opok-ops/MindForge.svg)](https://github.com/opok-ops/MindForge/stargazers)
15
15
  [![Forks](https://img.shields.io/github/forks/opok-ops/MindForge.svg)](https://github.com/opok-ops/MindForge/forks)
16
16
  [![Open Issues](https://img.shields.io/github/issues/opok-ops/MindForge.svg)](https://github.com/opok-ops/MindForge/issues)
@@ -66,9 +66,10 @@ MindForge stats
66
66
 
67
67
  ## What's New
68
68
 
69
- v6.1.3 – v6.4.2 shipped in nine days (2026-11-01 → 11-09), guarded by **1,224 tests** (all passing).
69
+ v6.1.3 – v6.4.3 shipped in ten days (2026-11-01 → 11-10), guarded by **1,228 tests** (1,227 passing, 1 environment-skipped).
70
70
 
71
- - **v6.4.2 — tens-of-thousands-chars latency: another 2×** (2026-11-09). Same-machine A/B benchmark (400 memories / ~47k chars, 3 runs each): **search p50 6.3→3.0ms (2.1×), p95 11.7→4.2ms (2.8×)**; 24k-char library p50 2.5ms; fast machine state 1.8ms. Five surgical cuts: WAL + `synchronous=NORMAL` (commits skip per-write fsync), enum-downgrade memo, `row.keys()` set reuse, first-visit access-count batching merged into one `flush_access()` transaction per search, and search-audit INSERT folded into the same commit. The v5.6.3 throttle contract and v5.5.4 `recently_accessed` semantics are pinned by 23 contract tests — all green. Compliance-grade audits still commit immediately.
71
+ - **v6.4.3 — documentation-code consistency fix** (2026-11-10). Pre-release audit found that v6.4.2's claimed first cut — WAL + `synchronous=NORMAL` — **never landed in code**: `_get_conn()` set only `journal_mode=WAL`, leaving `synchronous` at SQLite's default FULL. The 2.1× search gain was real, but carried entirely by the other four cuts — real numbers, misattributed cause. This release adds `PRAGMA synchronous=NORMAL` on the WAL branch (per-connection, cross-thread; network-FS DELETE fallback stays FULL by design). Same-machine A/B on SSD shows no statistically significant latency delta (search p50 1.8 → 1.8ms — fsync is ~0.1ms-scale here); the benefit targets slow disks and IO-saturated containers, and more importantly makes the documented power-loss semantics (un-checkpointed access counts / search audits may be lost; compliance audits still commit immediately) actually hold. 4 new guard tests in `tests/test_v643_fixes.py`.
72
+ - **v6.4.2 — tens-of-thousands-chars latency: another 2×** (2026-11-09). Same-machine A/B benchmark (400 memories / ~47k chars, 3 runs each): **search p50 6.3→3.0ms (2.1×), p95 11.7→4.2ms (2.8×)**; 24k-char library p50 2.5ms; fast machine state 1.8ms. Five surgical cuts: WAL + `synchronous=NORMAL` (commits skip per-write fsync), enum-downgrade memo, `row.keys()` set reuse, first-visit access-count batching merged into one `flush_access()` transaction per search, and search-audit INSERT folded into the same commit. The v5.6.3 throttle contract and v5.5.4 `recently_accessed` semantics are pinned by 23 contract tests — all green. Compliance-grade audits still commit immediately. *(Note: the `synchronous=NORMAL` cut landed in v6.4.3 — see above.)*
72
73
  - **v6.4.1 — million-character millisecond search** (2026-11-09). Scale benchmark (8,000 memories / ~990k chars) exposed a fuzzy-fallback long tail: search p95 881ms. Root causes: SequenceMatcher wasted on mathematically-impossible matches (ratio = 2M/(m+n), M ≤ m, so n ≥ 4m can never pass 0.4) + a ~50μs/entry Python full-scan tax. Fixed with a math-capped prune + SQLite-level candidate pre-filtering: **search p95 881→30.7ms (28×)**, add p50 2.6ms flat at 10k-scale. New `scripts/bench_scale.py` + CI scale guard (3000 memories, millisecond contract) + 4 behavior-level regression tests pin the semantics.
73
74
 
74
75
  - **v6.4.0 — resident daemon & performance guards** (2026-11-08). New `mindforge daemon` subcommand: line-JSON over stdio, engine resident in a long-lived process — per-request p50 2.5ms vs 400–700ms for CLI subprocess spawning (two orders of magnitude; 2026-11-09 quiet-machine re-bench: 2.5ms vs 401ms p50, ~160×). CI now guards latency (engine in-process thresholds) and daemon 13-step E2E alongside the 16-step CLI E2E guard.
@@ -136,7 +137,7 @@ v6.1.3 – v6.4.2 shipped in nine days (2026-11-01 → 11-09), guarded by **1,22
136
137
 
137
138
  ```
138
139
  ┌──────────────────────────────────────────────────────┐
139
- │ MindForge v6.4.2 │
140
+ │ MindForge v6.4.3 │
140
141
  │ Cognitive Layer Personality · KnowledgeGraph │
141
142
  │ MemoryEvolution · FederatedMemory │
142
143
  ├──────────────────────────────────────────────────────┤
@@ -757,6 +757,15 @@ class StorageEngine:
757
757
  conn.execute("PRAGMA journal_mode=DELETE")
758
758
  else:
759
759
  conn.execute("PRAGMA journal_mode=WAL")
760
+ # v6.4.3 fix: WAL 配套 synchronous=NORMAL(SQLite 官方推荐
761
+ # 组合)。v6.4.2 文档宣称了该优化但代码从未落地——本补丁
762
+ # 将其补齐:WAL+NORMAL 下 commit 免逐次 fsync,挂账批量
763
+ # 落库(search 尾事务)不再付 fsync 代价。
764
+ # 注意:synchronous 是 per-connection 参数,必须在每个
765
+ # 新连接创建时设置,仅在 WAL 分支生效;网络 FS 降级
766
+ # DELETE journal 的分支维持默认 FULL(远程盘耐久性语义
767
+ # 从严,不做削弱)。
768
+ conn.execute("PRAGMA synchronous=NORMAL")
760
769
  conn.execute("PRAGMA foreign_keys=ON")
761
770
  conn.execute("PRAGMA busy_timeout=5000")
762
771
  self._conn_local.conn = conn
@@ -20,10 +20,10 @@ core/mindforge.py、cli/main.py、mcp/server.py),每处都带一份硬编码
20
20
  from typing import Tuple
21
21
 
22
22
  #: 当前发布版本(唯一真值)
23
- __version__: str = "6.4.2"
23
+ __version__: str = "6.4.3"
24
24
 
25
25
  #: 结构化版本元组,便于比较(如 `VERSION_INFO >= (6, 1, 0)`)
26
- VERSION_INFO: Tuple[int, int, int] = (6, 4, 2)
26
+ VERSION_INFO: Tuple[int, int, int] = (6, 4, 3)
27
27
 
28
28
  #: 下一个大版本的目标版本号(供 v6 端口预留引用)
29
29
  NEXT_MAJOR_TARGET: str = "7.0.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mindforge-memory
3
- Version: 6.4.2
3
+ Version: 6.4.3
4
4
  Summary: AI Agent 终身记忆系统 - 四层记忆架构 · 知识图谱 · 多模态支持
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/opok-ops/MindForge
@@ -36,11 +36,11 @@ Dynamic: license-file
36
36
 
37
37
  MindForge gives AI agents a persistent, structured long-term memory: a four-tier lifecycle model, knowledge graphs, hybrid retrieval, end-to-end encryption, and MCP / CLI / REST interfaces. All data stays on your machine.
38
38
 
39
- > **The story** — one developer, seven months, from v1.0 (March 2026) to v6.4.2: no team, no funding, 1,224 passing tests. [Read the journey →](https://opok-ops.github.io/MindForge/#developer)
39
+ > **The story** — one developer, seven months, from v1.0 (March 2026) to v6.4.3: no team, no funding, 1,227 passing tests. [Read the journey →](https://opok-ops.github.io/MindForge/#developer)
40
40
 
41
41
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
42
42
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
43
- [![Version](https://img.shields.io/badge/version-6.4.2-green.svg)](https://github.com/opok-ops/MindForge/releases)
43
+ [![Version](https://img.shields.io/badge/version-6.4.3-green.svg)](https://github.com/opok-ops/MindForge/releases)
44
44
  [![Stars](https://img.shields.io/github/stars/opok-ops/MindForge.svg)](https://github.com/opok-ops/MindForge/stargazers)
45
45
  [![Forks](https://img.shields.io/github/forks/opok-ops/MindForge.svg)](https://github.com/opok-ops/MindForge/forks)
46
46
  [![Open Issues](https://img.shields.io/github/issues/opok-ops/MindForge.svg)](https://github.com/opok-ops/MindForge/issues)
@@ -96,9 +96,10 @@ MindForge stats
96
96
 
97
97
  ## What's New
98
98
 
99
- v6.1.3 – v6.4.2 shipped in nine days (2026-11-01 → 11-09), guarded by **1,224 tests** (all passing).
99
+ v6.1.3 – v6.4.3 shipped in ten days (2026-11-01 → 11-10), guarded by **1,228 tests** (1,227 passing, 1 environment-skipped).
100
100
 
101
- - **v6.4.2 — tens-of-thousands-chars latency: another 2×** (2026-11-09). Same-machine A/B benchmark (400 memories / ~47k chars, 3 runs each): **search p50 6.3→3.0ms (2.1×), p95 11.7→4.2ms (2.8×)**; 24k-char library p50 2.5ms; fast machine state 1.8ms. Five surgical cuts: WAL + `synchronous=NORMAL` (commits skip per-write fsync), enum-downgrade memo, `row.keys()` set reuse, first-visit access-count batching merged into one `flush_access()` transaction per search, and search-audit INSERT folded into the same commit. The v5.6.3 throttle contract and v5.5.4 `recently_accessed` semantics are pinned by 23 contract tests — all green. Compliance-grade audits still commit immediately.
101
+ - **v6.4.3 — documentation-code consistency fix** (2026-11-10). Pre-release audit found that v6.4.2's claimed first cut — WAL + `synchronous=NORMAL` — **never landed in code**: `_get_conn()` set only `journal_mode=WAL`, leaving `synchronous` at SQLite's default FULL. The 2.1× search gain was real, but carried entirely by the other four cuts — real numbers, misattributed cause. This release adds `PRAGMA synchronous=NORMAL` on the WAL branch (per-connection, cross-thread; network-FS DELETE fallback stays FULL by design). Same-machine A/B on SSD shows no statistically significant latency delta (search p50 1.8 → 1.8ms — fsync is ~0.1ms-scale here); the benefit targets slow disks and IO-saturated containers, and more importantly makes the documented power-loss semantics (un-checkpointed access counts / search audits may be lost; compliance audits still commit immediately) actually hold. 4 new guard tests in `tests/test_v643_fixes.py`.
102
+ - **v6.4.2 — tens-of-thousands-chars latency: another 2×** (2026-11-09). Same-machine A/B benchmark (400 memories / ~47k chars, 3 runs each): **search p50 6.3→3.0ms (2.1×), p95 11.7→4.2ms (2.8×)**; 24k-char library p50 2.5ms; fast machine state 1.8ms. Five surgical cuts: WAL + `synchronous=NORMAL` (commits skip per-write fsync), enum-downgrade memo, `row.keys()` set reuse, first-visit access-count batching merged into one `flush_access()` transaction per search, and search-audit INSERT folded into the same commit. The v5.6.3 throttle contract and v5.5.4 `recently_accessed` semantics are pinned by 23 contract tests — all green. Compliance-grade audits still commit immediately. *(Note: the `synchronous=NORMAL` cut landed in v6.4.3 — see above.)*
102
103
  - **v6.4.1 — million-character millisecond search** (2026-11-09). Scale benchmark (8,000 memories / ~990k chars) exposed a fuzzy-fallback long tail: search p95 881ms. Root causes: SequenceMatcher wasted on mathematically-impossible matches (ratio = 2M/(m+n), M ≤ m, so n ≥ 4m can never pass 0.4) + a ~50μs/entry Python full-scan tax. Fixed with a math-capped prune + SQLite-level candidate pre-filtering: **search p95 881→30.7ms (28×)**, add p50 2.6ms flat at 10k-scale. New `scripts/bench_scale.py` + CI scale guard (3000 memories, millisecond contract) + 4 behavior-level regression tests pin the semantics.
103
104
 
104
105
  - **v6.4.0 — resident daemon & performance guards** (2026-11-08). New `mindforge daemon` subcommand: line-JSON over stdio, engine resident in a long-lived process — per-request p50 2.5ms vs 400–700ms for CLI subprocess spawning (two orders of magnitude; 2026-11-09 quiet-machine re-bench: 2.5ms vs 401ms p50, ~160×). CI now guards latency (engine in-process thresholds) and daemon 13-step E2E alongside the 16-step CLI E2E guard.
@@ -166,7 +167,7 @@ v6.1.3 – v6.4.2 shipped in nine days (2026-11-01 → 11-09), guarded by **1,22
166
167
 
167
168
  ```
168
169
  ┌──────────────────────────────────────────────────────┐
169
- │ MindForge v6.4.2 │
170
+ │ MindForge v6.4.3 │
170
171
  │ Cognitive Layer Personality · KnowledgeGraph │
171
172
  │ MemoryEvolution · FederatedMemory │
172
173
  ├──────────────────────────────────────────────────────┤
@@ -131,4 +131,5 @@ tests/test_v632_explain_interfaces.py
131
131
  tests/test_v635_features.py
132
132
  tests/test_v635_integration.py
133
133
  tests/test_v636_fixes.py
134
+ tests/test_v643_fixes.py
134
135
  tests/test_v6_ports.py
@@ -39,7 +39,7 @@ import mindforge.core.version as core_version
39
39
 
40
40
 
41
41
  _REPO = Path(__file__).resolve().parent.parent
42
- _EXPECTED_VERSION = "6.4.2"
42
+ _EXPECTED_VERSION = "6.4.3"
43
43
 
44
44
  # 本轮修复涉及的、必须与 mindforge/core/version.py 保持一致的源码文件
45
45
  _VERSION_TRUTH_FILES = (
@@ -40,8 +40,8 @@ class TestVersionTruth(unittest.TestCase):
40
40
  def test_core_version_matches_release(self):
41
41
  # 版本推进时必须一并更新此处的钉值(与 test_v568_fixes 的
42
42
  # _EXPECTED_VERSION 同一约定:让「忘记 bump 版本」在测试里显形)。
43
- self.assertEqual(core_version.__version__, "6.4.2")
44
- self.assertEqual(core_version.VERSION_INFO, (6, 4, 2))
43
+ self.assertEqual(core_version.__version__, "6.4.3")
44
+ self.assertEqual(core_version.VERSION_INFO, (6, 4, 3))
45
45
 
46
46
  def test_pyproject_matches_core_version(self):
47
47
  # v5.8.13 起 pyproject 不再写死静态版本:
@@ -662,8 +662,8 @@ class TestVersionConsistency(unittest.TestCase):
662
662
  def test_version_is_612(self):
663
663
  from mindforge.core.version import VERSION_INFO, __version__
664
664
  # v6.1.3:版本钉值随发版推进更新(历史方法名保留)
665
- self.assertEqual(__version__, "6.4.2")
666
- self.assertEqual(VERSION_INFO, (6, 4, 2))
665
+ self.assertEqual(__version__, "6.4.3")
666
+ self.assertEqual(VERSION_INFO, (6, 4, 3))
667
667
 
668
668
  def test_json_round_trip_safety_of_preview(self):
669
669
  """save_evolution 的预览序列化不得抛(不可 json 化的对象走 str 兜底)。"""
@@ -0,0 +1,99 @@
1
+ """
2
+ MindForge v6.4.3 回归测试
3
+
4
+ 覆盖测试过程中发现的 1 个文档-代码不一致缺陷(2026-11-10):
5
+
6
+ - Bug-A(P0): v6.4.2 宣称的「WAL + synchronous=NORMAL」五刀第一刀
7
+ 从未落地——CHANGELOG/README/website 与 commit message 均宣称该
8
+ 组合已上线,但 _get_conn() 仅设置了 journal_mode=WAL,
9
+ synchronous 维持 SQLite 默认 FULL(WAL 下逐 commit fsync)。
10
+ 修复:WAL 分支补 PRAGMA synchronous=NORMAL(per-connection,
11
+ 每连接创建时设置;网络 FS 降级 DELETE 分支维持 FULL 从严)。
12
+
13
+ 守卫目标:让「PRAGMA 只在部分连接生效」「优化宣称了但没落地」
14
+ 这两类回归在测试里显形。
15
+ """
16
+
17
+ import os
18
+ import sys
19
+ import tempfile
20
+ import threading
21
+ import unittest
22
+ from pathlib import Path
23
+
24
+ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
25
+
26
+ from mindforge.core import storage as core_storage
27
+ from mindforge.core.version import __version__
28
+
29
+
30
+ class _WALCase(unittest.TestCase):
31
+ """本地盘临时库(走 WAL 分支)公共脚手架。"""
32
+
33
+ def setUp(self):
34
+ self.tmpdir = tempfile.TemporaryDirectory(prefix="mf_v643_fix_")
35
+ self.db = os.path.join(self.tmpdir.name, "memory.db")
36
+ self.storage = core_storage.StorageEngine(
37
+ db_path=self.db, encrypted=False
38
+ )
39
+
40
+ def tearDown(self):
41
+ try:
42
+ self.storage.close()
43
+ finally:
44
+ self.tmpdir.cleanup()
45
+
46
+
47
+ class TestSynchronousNormalGuard(_WALCase):
48
+ """Bug-A 守卫:WAL + synchronous=NORMAL 必须真实生效。"""
49
+
50
+ def test_synchronous_normal_on_local_wal(self):
51
+ # SQLite PRAGMA synchronous 返回值:0=OFF, 1=NORMAL, 2=FULL。
52
+ # v6.4.2 缺陷形态即此值恒为 2(FULL)。
53
+ conn = self.storage._get_conn()
54
+ mode = conn.execute("PRAGMA synchronous").fetchone()[0]
55
+ self.assertEqual(
56
+ mode, 1,
57
+ f"synchronous 应为 NORMAL(1),实际 {mode}——"
58
+ "v6.4.3 的 WAL+synchronous=NORMAL 修复未生效或被回退",
59
+ )
60
+
61
+ def test_journal_mode_wal_on_local_disk(self):
62
+ conn = self.storage._get_conn()
63
+ journal = conn.execute("PRAGMA journal_mode").fetchone()[0]
64
+ self.assertEqual(
65
+ str(journal).lower(), "wal",
66
+ f"本地盘 journal_mode 应为 wal,实际 {journal}",
67
+ )
68
+
69
+ def test_synchronous_is_per_connection(self):
70
+ # synchronous 是 per-connection 参数:StorageEngine 用
71
+ # threading.local 维护连接,新线程的连接也必须带上 NORMAL,
72
+ # 否则只保护了首线程(REST/daemon 多线程场景将静默回退 FULL)。
73
+ results = {}
74
+
75
+ def probe():
76
+ try:
77
+ conn = self.storage._get_conn()
78
+ results["mode"] = conn.execute(
79
+ "PRAGMA synchronous"
80
+ ).fetchone()[0]
81
+ except Exception as exc: # pragma: no cover - 显形优先
82
+ results["error"] = repr(exc)
83
+
84
+ t = threading.Thread(target=probe)
85
+ t.start()
86
+ t.join(timeout=10)
87
+ self.assertNotIn("error", results, results.get("error", ""))
88
+ self.assertEqual(results.get("mode"), 1)
89
+
90
+
91
+ class TestVersionBump(unittest.TestCase):
92
+ """版本钉值:忘记 bump 时在此显形(与 v568/v575/v612 守卫同一约定)。"""
93
+
94
+ def test_version_is_643(self):
95
+ self.assertEqual(__version__, "6.4.3")
96
+
97
+
98
+ if __name__ == "__main__":
99
+ unittest.main()