memleaf 0.2.78__tar.gz → 0.2.79__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 (174) hide show
  1. {memleaf-0.2.78 → memleaf-0.2.79}/CHANGELOG.md +10 -0
  2. {memleaf-0.2.78/src/memleaf.egg-info → memleaf-0.2.79}/PKG-INFO +2 -2
  3. {memleaf-0.2.78 → memleaf-0.2.79}/README.en.md +1 -1
  4. {memleaf-0.2.78 → memleaf-0.2.79}/README.md +1 -1
  5. {memleaf-0.2.78 → memleaf-0.2.79}/pyproject.toml +1 -1
  6. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/__init__.py +1 -1
  7. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/hermes_provider/plugin.yaml +1 -1
  8. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/incremental_dates.py +2 -69
  9. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/incremental_protocol.py +2 -15
  10. {memleaf-0.2.78 → memleaf-0.2.79/src/memleaf.egg-info}/PKG-INFO +2 -2
  11. {memleaf-0.2.78 → memleaf-0.2.79}/LICENSE +0 -0
  12. {memleaf-0.2.78 → memleaf-0.2.79}/MANIFEST.in +0 -0
  13. {memleaf-0.2.78 → memleaf-0.2.79}/docs/acceptance-evidence-guide.md +0 -0
  14. {memleaf-0.2.78 → memleaf-0.2.79}/docs/automatic-processing-route.md +0 -0
  15. {memleaf-0.2.78 → memleaf-0.2.79}/docs/body-compaction.md +0 -0
  16. {memleaf-0.2.78 → memleaf-0.2.79}/docs/candidate-reconciliation.md +0 -0
  17. {memleaf-0.2.78 → memleaf-0.2.79}/docs/capture-budget-design.md +0 -0
  18. {memleaf-0.2.78 → memleaf-0.2.79}/docs/config-migrations.md +0 -0
  19. {memleaf-0.2.78 → memleaf-0.2.79}/docs/core-refactor.md +0 -0
  20. {memleaf-0.2.78 → memleaf-0.2.79}/docs/development-closeout.md +0 -0
  21. {memleaf-0.2.78 → memleaf-0.2.79}/docs/evidence-retention.md +0 -0
  22. {memleaf-0.2.78 → memleaf-0.2.79}/docs/explicit-memory-update.md +0 -0
  23. {memleaf-0.2.78 → memleaf-0.2.79}/docs/extraction-latency.md +0 -0
  24. {memleaf-0.2.78 → memleaf-0.2.79}/docs/gate-evidence-boundary.md +0 -0
  25. {memleaf-0.2.78 → memleaf-0.2.79}/docs/general-processing.md +0 -0
  26. {memleaf-0.2.78 → memleaf-0.2.79}/docs/hermes-mcp-runtime.md +0 -0
  27. {memleaf-0.2.78 → memleaf-0.2.79}/docs/hermes-provider-compatibility.md +0 -0
  28. {memleaf-0.2.78 → memleaf-0.2.79}/docs/host-acceptance-runbook.md +0 -0
  29. {memleaf-0.2.78 → memleaf-0.2.79}/docs/immutable-release-assets.md +0 -0
  30. {memleaf-0.2.78 → memleaf-0.2.79}/docs/incremental-commit-contract.md +0 -0
  31. {memleaf-0.2.78 → memleaf-0.2.79}/docs/incremental-execution.md +0 -0
  32. {memleaf-0.2.78 → memleaf-0.2.79}/docs/incremental-native-comparison.md +0 -0
  33. {memleaf-0.2.78 → memleaf-0.2.79}/docs/incremental-partial-recovery.md +0 -0
  34. {memleaf-0.2.78 → memleaf-0.2.79}/docs/incremental-planner-preview.md +0 -0
  35. {memleaf-0.2.78 → memleaf-0.2.79}/docs/incremental-runtime-contract.md +0 -0
  36. {memleaf-0.2.78 → memleaf-0.2.79}/docs/incremental-scope-registration.md +0 -0
  37. {memleaf-0.2.78 → memleaf-0.2.79}/docs/incremental-selected-retention.md +0 -0
  38. {memleaf-0.2.78 → memleaf-0.2.79}/docs/installed-artifact-verification.md +0 -0
  39. {memleaf-0.2.78 → memleaf-0.2.79}/docs/memory-state-contract.md +0 -0
  40. {memleaf-0.2.78 → memleaf-0.2.79}/docs/migration-preflight.md +0 -0
  41. {memleaf-0.2.78 → memleaf-0.2.79}/docs/processing-quality-acceptance.md +0 -0
  42. {memleaf-0.2.78 → memleaf-0.2.79}/docs/public-query-integrity.md +0 -0
  43. {memleaf-0.2.78 → memleaf-0.2.79}/docs/query-performance.md +0 -0
  44. {memleaf-0.2.78 → memleaf-0.2.79}/docs/remember-incremental-route.md +0 -0
  45. {memleaf-0.2.78 → memleaf-0.2.79}/docs/runtime-state-retention.md +0 -0
  46. {memleaf-0.2.78 → memleaf-0.2.79}/docs/semantic-extraction-protocol.md +0 -0
  47. {memleaf-0.2.78 → memleaf-0.2.79}/docs/source-work-contract.md +0 -0
  48. {memleaf-0.2.78 → memleaf-0.2.79}/docs/v0.2.26-processing-status.md +0 -0
  49. {memleaf-0.2.78 → memleaf-0.2.79}/examples/README.md +0 -0
  50. {memleaf-0.2.78 → memleaf-0.2.79}/examples/basic_usage.py +0 -0
  51. {memleaf-0.2.78 → memleaf-0.2.79}/examples/incremental_acceptance.json +0 -0
  52. {memleaf-0.2.78 → memleaf-0.2.79}/examples/mcp_stdio.ndjson +0 -0
  53. {memleaf-0.2.78 → memleaf-0.2.79}/examples/query_benchmark.py +0 -0
  54. {memleaf-0.2.78 → memleaf-0.2.79}/install.ps1 +0 -0
  55. {memleaf-0.2.78 → memleaf-0.2.79}/install.sh +0 -0
  56. {memleaf-0.2.78 → memleaf-0.2.79}/setup.cfg +0 -0
  57. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/__main__.py +0 -0
  58. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/acceptance.py +0 -0
  59. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/adapters/__init__.py +0 -0
  60. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/adapters/antigravity.py +0 -0
  61. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/adapters/base.py +0 -0
  62. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/adapters/codex.py +0 -0
  63. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/adapters/hermes.py +0 -0
  64. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/admission.py +0 -0
  65. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/batch_review.py +0 -0
  66. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/budget.py +0 -0
  67. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/capture.py +0 -0
  68. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/cli.py +0 -0
  69. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/compaction.py +0 -0
  70. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/config.py +0 -0
  71. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/create_coordinator.py +0 -0
  72. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/credentials.py +0 -0
  73. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/evidence_budget.py +0 -0
  74. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/evidence_policy.py +0 -0
  75. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/evidence_structure.py +0 -0
  76. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/evidence_syntax.py +0 -0
  77. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/explicit_text_source.py +0 -0
  78. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/extraction_budget.py +0 -0
  79. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/extraction_capability.py +0 -0
  80. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/extraction_work_state.py +0 -0
  81. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/frontmatter.py +0 -0
  82. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/hermes_provider/README.md +0 -0
  83. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/hermes_provider/__init__.py +0 -0
  84. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/hermes_provider/_mcp_client.py +0 -0
  85. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/hermes_provider/_provider.py +0 -0
  86. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/hermes_provider/_shared.py +0 -0
  87. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/hermes_provider/evidence_budget.py +0 -0
  88. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/hermes_provider/provider_compatibility.py +0 -0
  89. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/hermes_runtime.py +0 -0
  90. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/host_events.py +0 -0
  91. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/host_runtime.py +0 -0
  92. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/inbox.py +0 -0
  93. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/incremental_commit.py +0 -0
  94. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/incremental_execution.py +0 -0
  95. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/incremental_explicit.py +0 -0
  96. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/incremental_journal.py +0 -0
  97. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/incremental_native.py +0 -0
  98. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/incremental_partial.py +0 -0
  99. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/incremental_preview.py +0 -0
  100. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/incremental_prompts.py +0 -0
  101. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/incremental_recovery.py +0 -0
  102. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/incremental_run_state.py +0 -0
  103. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/incremental_runtime.py +0 -0
  104. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/incremental_scopes.py +0 -0
  105. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/incremental_selection.py +0 -0
  106. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/index.py +0 -0
  107. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/inspection.py +0 -0
  108. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/installer.py +0 -0
  109. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/legacy_update_journal.py +0 -0
  110. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/llm/__init__.py +0 -0
  111. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/llm/base.py +0 -0
  112. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/llm/claude_compatible.py +0 -0
  113. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/llm/gemini.py +0 -0
  114. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/llm/openai_compatible.py +0 -0
  115. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/llm/router.py +0 -0
  116. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/llm/thinking.py +0 -0
  117. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/locking.py +0 -0
  118. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/mcp_server.py +0 -0
  119. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/memory_commit.py +0 -0
  120. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/memory_planner.py +0 -0
  121. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/memory_retraction.py +0 -0
  122. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/memory_update.py +0 -0
  123. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/memory_writer.py +0 -0
  124. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/migration.py +0 -0
  125. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/model_capabilities.py +0 -0
  126. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/model_discovery.py +0 -0
  127. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/model_execution.py +0 -0
  128. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/models.py +0 -0
  129. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/native_index.py +0 -0
  130. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/native_registration.py +0 -0
  131. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/parallel_model.py +0 -0
  132. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/planning_context.py +0 -0
  133. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/process_common.py +0 -0
  134. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/process_jobs.py +0 -0
  135. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/process_journal.py +0 -0
  136. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/process_owner.py +0 -0
  137. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/processing.py +0 -0
  138. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/processing_route.py +0 -0
  139. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/prompts.py +0 -0
  140. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/provenance.py +0 -0
  141. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/provider_compatibility.py +0 -0
  142. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/query_clock.py +0 -0
  143. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/query_progress.py +0 -0
  144. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/query_scan.py +0 -0
  145. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/receipt_codec.py +0 -0
  146. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/recording_policy.py +0 -0
  147. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/redaction.py +0 -0
  148. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/remember_route.py +0 -0
  149. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/retention.py +0 -0
  150. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/retrieval.py +0 -0
  151. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/retrieval_gate.py +0 -0
  152. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/runtime_retention.py +0 -0
  153. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/scope_maintenance.py +0 -0
  154. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/scope_state.py +0 -0
  155. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/semantic_maintenance.py +0 -0
  156. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/semantic_protocol.py +0 -0
  157. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/service.py +0 -0
  158. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/single_pass_memory_planner.py +0 -0
  159. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/single_pass_plan.py +0 -0
  160. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/source_policy.py +0 -0
  161. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/state_layout.py +0 -0
  162. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/subprocess_flags.py +0 -0
  163. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/summary_batch.py +0 -0
  164. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/target_reconciliation.py +0 -0
  165. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/turn_audit.py +0 -0
  166. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/turn_plan.py +0 -0
  167. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/update_coordinator.py +0 -0
  168. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/update_review.py +0 -0
  169. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/validation.py +0 -0
  170. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf/vault.py +0 -0
  171. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf.egg-info/SOURCES.txt +0 -0
  172. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf.egg-info/dependency_links.txt +0 -0
  173. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf.egg-info/entry_points.txt +0 -0
  174. {memleaf-0.2.78 → memleaf-0.2.79}/src/memleaf.egg-info/top_level.txt +0 -0
@@ -4,6 +4,16 @@ All notable changes to memleaf are documented here.
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 0.2.79 — 2026-09-29
8
+
9
+ ### Model-owned content dates
10
+
11
+ - Remove evidence-grounding rejection for dates in memory titles and bodies;
12
+ date content is now judged by the extraction model, without a replacement
13
+ date-format gate.
14
+ - Retain structural protocol checks and source-time calendar conversion.
15
+ - Advance the incremental semantic protocol to v8 for the changed contract.
16
+
7
17
  ## 0.2.78 — 2026-09-29
8
18
 
9
19
  ### Hermes host-turn provenance and explicit-write context
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memleaf
3
- Version: 0.2.78
3
+ Version: 0.2.79
4
4
  Summary: A local-first Markdown memory core for AI agents
5
5
  Author: memleaf contributors
6
6
  License-Expression: MIT
@@ -23,7 +23,7 @@ Dynamic: license-file
23
23
 
24
24
  [English](README.en.md) · [PyPI](https://pypi.org/project/memleaf/) · [GitHub](https://github.com/miffyblueboo/memleaf)
25
25
 
26
- > **版本:0.2.78。**
26
+ > **版本:0.2.79。**
27
27
  > 自动提炼和复核共用同一条“未来记忆价值”标准:模型综合未来复用、信息增量、再次读取时的直接可用性和忘记成本,只保留对未来理解、判断或行动有实质影响的最小核心;没有明确价值的信息不提炼,不按具体业务场景硬编码排除。
28
28
  > 提炼契约现在只有一份中文语义契约(旧版英文 B3 提示词已删除),首轮、主题选择、候选修复和 `semantic_maintenance` 使用同一套保留价值判断;同一件事只写一次。
29
29
  > Core 不再因为归属、日期、任务依据或跨项目而丢弃整条候选:归属缺失会归一到证据里唯一被点名的项目、否则落 `global`;日期只接受能在本候选证据里找到出处、且能锚定成 ISO 的写法(`明天`、`周五`、`月底` 都会被解析),无法解析时只丢掉日期字段,记忆照常写入;未获授权的改归属沿用目标原归属。
@@ -4,7 +4,7 @@
4
4
 
5
5
  [中文](README.md) · [PyPI](https://pypi.org/project/memleaf/) · [GitHub](https://github.com/miffyblueboo/memleaf)
6
6
 
7
- > **Version: 0.2.78.**
7
+ > **Version: 0.2.79.**
8
8
  > Automatic extraction and review share one future-value standard: the model weighs likely reuse, information gain, direct usability when read again, and the cost of forgetting. It keeps only the smallest core that can materially help future understanding, decisions, or actions; information without clear value is not extracted, and no business-specific exclusion rule is hard-coded.
9
9
  > A single Chinese semantic contract is sent for extraction, topic selection, candidate repair, and `semantic_maintenance`; the older English B3 prompt has been deleted and B3 remains only as a compatibility read format. One topic is written once.
10
10
  > Core no longer discards a whole candidate over ownership, dates, task basis or cross-project wording. A missing owner normalizes to the single project named by that candidate's own evidence, otherwise `global`. A deadline is accepted only when it appears in the candidate's own evidence and can be anchored to ISO (`明天`, `周五`, `月底` all resolve); when it cannot, only the date field is dropped and the memory is still written. An unauthorized ownership change keeps the target's existing scope.
@@ -4,7 +4,7 @@
4
4
 
5
5
  [English](README.en.md) · [PyPI](https://pypi.org/project/memleaf/) · [GitHub](https://github.com/miffyblueboo/memleaf)
6
6
 
7
- > **版本:0.2.78。**
7
+ > **版本:0.2.79。**
8
8
  > 自动提炼和复核共用同一条“未来记忆价值”标准:模型综合未来复用、信息增量、再次读取时的直接可用性和忘记成本,只保留对未来理解、判断或行动有实质影响的最小核心;没有明确价值的信息不提炼,不按具体业务场景硬编码排除。
9
9
  > 提炼契约现在只有一份中文语义契约(旧版英文 B3 提示词已删除),首轮、主题选择、候选修复和 `semantic_maintenance` 使用同一套保留价值判断;同一件事只写一次。
10
10
  > Core 不再因为归属、日期、任务依据或跨项目而丢弃整条候选:归属缺失会归一到证据里唯一被点名的项目、否则落 `global`;日期只接受能在本候选证据里找到出处、且能锚定成 ISO 的写法(`明天`、`周五`、`月底` 都会被解析),无法解析时只丢掉日期字段,记忆照常写入;未获授权的改归属沿用目标原归属。
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "memleaf"
7
- version = "0.2.78"
7
+ version = "0.2.79"
8
8
  description = "A local-first Markdown memory core for AI agents"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -1,6 +1,6 @@
1
1
  """Local-first Markdown memory core for AI agents."""
2
2
 
3
- __version__ = "0.2.78"
3
+ __version__ = "0.2.79"
4
4
 
5
5
  from .config import DEFAULT_CONFIG, default_config, load_config, save_config
6
6
  from .frontmatter import FrontmatterError, dump_frontmatter, dump_yaml, load_yaml, parse_frontmatter
@@ -1,5 +1,5 @@
1
1
  name: memleaf
2
- version: 0.2.78
2
+ version: 0.2.79
3
3
  description: "Hermes-native external MemoryProvider for local-first Markdown memory shared with the memleaf MCP server."
4
4
  hooks:
5
5
  - prefetch
@@ -78,8 +78,8 @@ def remove_source_time_provenance_date(body: str, events: list[Mapping[str, Any]
78
78
 
79
79
  The source chain is stored by Core. A message timestamp is not evidence for
80
80
  a date in the memory's facts or deadline, even when a model copies that day
81
- into a decorative ``来源:`` line. Leave every other date for the strict
82
- content-date guard to validate.
81
+ into a decorative ``来源:`` line. Leave every other date unchanged; provenance matching does not
82
+ authorize or reject business dates.
83
83
  """
84
84
  source_days = {
85
85
  anchor.date().isoformat()
@@ -109,73 +109,6 @@ def remove_source_time_provenance_date(body: str, events: list[Mapping[str, Any]
109
109
  return "".join(lines)
110
110
 
111
111
 
112
- def content_date_violations(fields: Mapping[str, Any], events: list[Mapping[str, Any]],
113
- preserved: Mapping[str, Any] | None = None) -> list[dict[str, Any]]:
114
- """Locate unsupported dates without weakening the existing grounding guard.
115
-
116
- Only cited sources and the selected update target may ground new wording.
117
- Existing memory wording is preserved without a new source claim.
118
- """
119
- from .process_common import _summary_date_grounding_violations
120
-
121
- source_texts = [reading_text(str(event["text"])) for event in events]
122
- grounded: set[str] = set()
123
- clock_dates: dict[str, set[str]] = {}
124
- for event, source in zip(events, source_texts):
125
- anchor = parse_source_time(event.get("source_time"))
126
- local_day = anchor.date() if anchor is not None else None
127
- normalized = normalize_relative_calendar_text(source, local_day) if local_day else None
128
- grounded.update(token.canonical for token in calendar_tokens(source, local_day) if token.canonical)
129
- if normalized is not None:
130
- grounded.update(token.canonical for token in calendar_tokens(normalized, local_day) if token.canonical)
131
- for match in _RELATIVE_CALENDAR_EXPRESSION.finditer(source):
132
- clock = _CLOCK_AFTER_DATE.match(source, match.end())
133
- if clock:
134
- resolved = normalize_relative_calendar_text(match.group(), local_day)
135
- if resolved:
136
- clock_dates.setdefault(clock.group(1), set()).add(resolved)
137
- # An explicit source date at the same clock makes a relative binding
138
- # ambiguous; in that case the guard must not claim which event it is.
139
- for date_value, clock_value in _dated_clocks(source):
140
- clock_dates.setdefault(clock_value, set()).add(date_value)
141
- prior = preserved or {}
142
- texts = {key: fields[key] for key in ("title", "body") if key in fields}
143
- violations = []
144
- anchors = [{key: event[key] for key in ("ref", "source_time") if key in event}
145
- for event in events]
146
- for field, value in texts.items():
147
- unsupported = set(_summary_date_grounding_violations(
148
- {field: value}, grounded_dates=grounded, source_texts=source_texts,
149
- preserved_texts=[prior.get("title"), prior.get("body")]))
150
- for token in calendar_tokens(value):
151
- # A yearless literal cannot borrow a year merely for display.
152
- identity = (token.canonical if token.has_year else None) or token.raw
153
- if identity in unsupported:
154
- violations.append({"field": field, "start": token.start, "end": token.end,
155
- "text": token.raw, "normalized": token.canonical or token.monthday,
156
- "reason": "not_in_cited_evidence_or_target", "anchors": anchors})
157
- preserved_pairs = set().union(*(_dated_clocks(text) for text in (prior.get("title"), prior.get("body"))
158
- if isinstance(text, str)))
159
- for field, value in texts.items():
160
- for token in calendar_tokens(value):
161
- clock = _CLOCK_AFTER_DATE.match(value, token.end)
162
- if not token.canonical or clock is None:
163
- continue
164
- date_value, clock_value = token.canonical, clock.group(1)
165
- expected = clock_dates.get(clock_value, set())
166
- if len(expected) == 1 and date_value not in expected and (date_value, clock_value) not in preserved_pairs:
167
- violations.append({"field": field, "start": token.start, "end": token.end,
168
- "text": token.raw, "normalized": date_value,
169
- "reason": "relative_clock_date_mismatch",
170
- "expected_dates": sorted(expected), "anchors": anchors})
171
- return violations
172
-
173
-
174
- def invalid_content_dates(fields: Mapping[str, Any], events: list[Mapping[str, Any]],
175
- preserved: Mapping[str, Any] | None = None) -> bool:
176
- return bool(content_date_violations(fields, events, preserved))
177
-
178
-
179
112
  def selected_calendar(text: str, evidence: Mapping[str, Any]) -> dict[str, Any]:
180
113
  """Return a lossless text/anchor projection plus an optional calendar date.
181
114
 
@@ -15,7 +15,7 @@ from copy import deepcopy
15
15
  from dataclasses import dataclass
16
16
  from typing import Any, Mapping
17
17
 
18
- from .incremental_dates import (calendar_hints, content_date_violations, parse_source_time,
18
+ from .incremental_dates import (calendar_hints, parse_source_time,
19
19
  remove_source_time_provenance_date,
20
20
  reading_text, selected_calendar, source_basis)
21
21
  from .models import Memory
@@ -24,7 +24,7 @@ from .turn_plan import revision_digest
24
24
  from .validation import ModelOutputError, parse_strict_json
25
25
 
26
26
  PROTOCOL_VERSION = "incremental-items-v1"
27
- SEMANTIC_PROTOCOL = "incremental-turn-v7"
27
+ SEMANTIC_PROTOCOL = "incremental-turn-v8"
28
28
  MAX_BYTES = 128 * 1024
29
29
  MAX_ITEMS = 64
30
30
  _TYPES = frozenset(("fact", "todo", "preference", "project", "event", "identity", "other"))
@@ -51,14 +51,6 @@ class _FieldShapeError(ValueError):
51
51
  self.detail = detail
52
52
 
53
53
 
54
- class _ContentDateError(ValueError):
55
- def __init__(self, violations: list[dict[str, Any]]):
56
- super().__init__("ungrounded_content_date")
57
- # Reuse the issue detail channel. Only offending date tokens and
58
- # reference/anchor metadata, never the complete source/body, are kept.
59
- self.detail = json.dumps(violations, ensure_ascii=False, separators=(",", ":"))
60
-
61
-
62
54
  def _normalize_create_fields(fields: Any) -> tuple[Any, list[str]]:
63
55
  """Normalize model serialization aliases that preserve one exact meaning."""
64
56
  if not isinstance(fields, dict):
@@ -594,11 +586,6 @@ def _parse_row(row: Any, state: Mapping[str, Any]) -> dict[str, Any]:
594
586
  if normalized_body != fields["body"]:
595
587
  fields["body"] = normalized_body
596
588
  result.setdefault("warnings", []).append("source_time_provenance_date_removed")
597
- date_issues = content_date_violations(
598
- fields, cited_events,
599
- state["targets"][result["target_ref"]]["memory"] if action == "UPDATE" else None)
600
- if date_issues:
601
- raise _ContentDateError(date_issues)
602
589
  if "status" in fields and fields["status"] not in ("active", "completed", "cancelled"):
603
590
  raise ValueError("invalid_status")
604
591
  if "validity" in fields and fields["validity"] not in ("valid", "retracted"):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memleaf
3
- Version: 0.2.78
3
+ Version: 0.2.79
4
4
  Summary: A local-first Markdown memory core for AI agents
5
5
  Author: memleaf contributors
6
6
  License-Expression: MIT
@@ -23,7 +23,7 @@ Dynamic: license-file
23
23
 
24
24
  [English](README.en.md) · [PyPI](https://pypi.org/project/memleaf/) · [GitHub](https://github.com/miffyblueboo/memleaf)
25
25
 
26
- > **版本:0.2.78。**
26
+ > **版本:0.2.79。**
27
27
  > 自动提炼和复核共用同一条“未来记忆价值”标准:模型综合未来复用、信息增量、再次读取时的直接可用性和忘记成本,只保留对未来理解、判断或行动有实质影响的最小核心;没有明确价值的信息不提炼,不按具体业务场景硬编码排除。
28
28
  > 提炼契约现在只有一份中文语义契约(旧版英文 B3 提示词已删除),首轮、主题选择、候选修复和 `semantic_maintenance` 使用同一套保留价值判断;同一件事只写一次。
29
29
  > Core 不再因为归属、日期、任务依据或跨项目而丢弃整条候选:归属缺失会归一到证据里唯一被点名的项目、否则落 `global`;日期只接受能在本候选证据里找到出处、且能锚定成 ISO 的写法(`明天`、`周五`、`月底` 都会被解析),无法解析时只丢掉日期字段,记忆照常写入;未获授权的改归属沿用目标原归属。
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes