dhee 7.4.2__tar.gz → 7.4.4__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 (551) hide show
  1. {dhee-7.4.2/dhee.egg-info → dhee-7.4.4}/PKG-INFO +1 -1
  2. {dhee-7.4.2 → dhee-7.4.4}/dhee/__init__.py +1 -1
  3. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/decay.py +31 -1
  4. {dhee-7.4.2 → dhee-7.4.4}/dhee/db/sqlite.py +48 -1
  5. {dhee-7.4.2 → dhee-7.4.4}/dhee/decisions/facts.py +49 -1
  6. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/core.py +30 -3
  7. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/main.py +23 -3
  8. {dhee-7.4.2 → dhee-7.4.4/dhee.egg-info}/PKG-INFO +1 -1
  9. {dhee-7.4.2 → dhee-7.4.4}/dhee.egg-info/SOURCES.txt +1 -0
  10. {dhee-7.4.2 → dhee-7.4.4}/pyproject.toml +1 -1
  11. dhee-7.4.4/tests/test_decay_cadence.py +135 -0
  12. {dhee-7.4.2 → dhee-7.4.4}/tests/test_decisions.py +47 -0
  13. {dhee-7.4.2 → dhee-7.4.4}/LICENSE +0 -0
  14. {dhee-7.4.2 → dhee-7.4.4}/MANIFEST.in +0 -0
  15. {dhee-7.4.2 → dhee-7.4.4}/README.md +0 -0
  16. {dhee-7.4.2 → dhee-7.4.4}/dhee/adapters/__init__.py +0 -0
  17. {dhee-7.4.2 → dhee-7.4.4}/dhee/adapters/gstack.py +0 -0
  18. {dhee-7.4.2 → dhee-7.4.4}/dhee/adapters/gstack_parser.py +0 -0
  19. {dhee-7.4.2 → dhee-7.4.4}/dhee/adapters/morpho_adapter.py +0 -0
  20. {dhee-7.4.2 → dhee-7.4.4}/dhee/agent_runtime/__init__.py +0 -0
  21. {dhee-7.4.2 → dhee-7.4.4}/dhee/agent_runtime/auth.py +0 -0
  22. {dhee-7.4.2 → dhee-7.4.4}/dhee/agent_runtime/client.py +0 -0
  23. {dhee-7.4.2 → dhee-7.4.4}/dhee/agent_runtime/events.py +0 -0
  24. {dhee-7.4.2 → dhee-7.4.4}/dhee/agent_runtime/models.py +0 -0
  25. {dhee-7.4.2 → dhee-7.4.4}/dhee/agent_runtime/policy.py +0 -0
  26. {dhee-7.4.2 → dhee-7.4.4}/dhee/agent_runtime/run.py +0 -0
  27. {dhee-7.4.2 → dhee-7.4.4}/dhee/agent_runtime/server.py +0 -0
  28. {dhee-7.4.2 → dhee-7.4.4}/dhee/agent_runtime/tools.py +0 -0
  29. {dhee-7.4.2 → dhee-7.4.4}/dhee/benchmarks/__init__.py +0 -0
  30. {dhee-7.4.2 → dhee-7.4.4}/dhee/benchmarks/arc_agi.py +0 -0
  31. {dhee-7.4.2 → dhee-7.4.4}/dhee/benchmarks/decades.py +0 -0
  32. {dhee-7.4.2 → dhee-7.4.4}/dhee/benchmarks/hippocamp.py +0 -0
  33. {dhee-7.4.2 → dhee-7.4.4}/dhee/benchmarks/longmemeval.py +0 -0
  34. {dhee-7.4.2 → dhee-7.4.4}/dhee/benchmarks/phase0_context_audit.py +0 -0
  35. {dhee-7.4.2 → dhee-7.4.4}/dhee/benchmarks/portability.py +0 -0
  36. {dhee-7.4.2 → dhee-7.4.4}/dhee/benchmarks/raw_extractors.py +0 -0
  37. {dhee-7.4.2 → dhee-7.4.4}/dhee/benchmarks/replay_corpus.py +0 -0
  38. {dhee-7.4.2 → dhee-7.4.4}/dhee/benchmarks/router_replay.py +0 -0
  39. {dhee-7.4.2 → dhee-7.4.4}/dhee/checkpoint_runtime.py +0 -0
  40. {dhee-7.4.2 → dhee-7.4.4}/dhee/cli.py +0 -0
  41. {dhee-7.4.2 → dhee-7.4.4}/dhee/cli_config.py +0 -0
  42. {dhee-7.4.2 → dhee-7.4.4}/dhee/cli_mcp.py +0 -0
  43. {dhee-7.4.2 → dhee-7.4.4}/dhee/cli_onboard.py +0 -0
  44. {dhee-7.4.2 → dhee-7.4.4}/dhee/cli_pretty.py +0 -0
  45. {dhee-7.4.2 → dhee-7.4.4}/dhee/cli_setup.py +0 -0
  46. {dhee-7.4.2 → dhee-7.4.4}/dhee/cli_update.py +0 -0
  47. {dhee-7.4.2 → dhee-7.4.4}/dhee/configs/__init__.py +0 -0
  48. {dhee-7.4.2 → dhee-7.4.4}/dhee/configs/active.py +0 -0
  49. {dhee-7.4.2 → dhee-7.4.4}/dhee/configs/base.py +0 -0
  50. {dhee-7.4.2 → dhee-7.4.4}/dhee/configs/presets.py +0 -0
  51. {dhee-7.4.2 → dhee-7.4.4}/dhee/context_ir.py +0 -0
  52. {dhee-7.4.2 → dhee-7.4.4}/dhee/context_kernel.py +0 -0
  53. {dhee-7.4.2 → dhee-7.4.4}/dhee/context_state.py +0 -0
  54. {dhee-7.4.2 → dhee-7.4.4}/dhee/contract_runtime.py +0 -0
  55. {dhee-7.4.2 → dhee-7.4.4}/dhee/contract_supervisor.py +0 -0
  56. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/__init__.py +0 -0
  57. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/alaya.py +0 -0
  58. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/answer_orchestration.py +0 -0
  59. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/artifacts.py +0 -0
  60. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/belief.py +0 -0
  61. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/buddhi.py +0 -0
  62. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/category.py +0 -0
  63. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/codex_artifacts.py +0 -0
  64. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/codex_stream.py +0 -0
  65. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/cognition.py +0 -0
  66. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/cognition_kernel.py +0 -0
  67. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/conflict.py +0 -0
  68. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/context_bootstrap.py +0 -0
  69. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/contrastive.py +0 -0
  70. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/distillation.py +0 -0
  71. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/echo.py +0 -0
  72. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/engram.py +0 -0
  73. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/engram_consolidator.py +0 -0
  74. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/engram_extractor.py +0 -0
  75. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/engram_tiering.py +0 -0
  76. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/engram_verification.py +0 -0
  77. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/enrichment.py +0 -0
  78. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/episode.py +0 -0
  79. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/episodic_index.py +0 -0
  80. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/evolution.py +0 -0
  81. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/file_baseline.py +0 -0
  82. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/file_read_tracker.py +0 -0
  83. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/forgetting.py +0 -0
  84. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/fusion.py +0 -0
  85. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/graph.py +0 -0
  86. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/handoff_snapshot.py +0 -0
  87. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/heuristic.py +0 -0
  88. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/intent.py +0 -0
  89. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/intention.py +0 -0
  90. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/kernel.py +0 -0
  91. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/learnings.py +0 -0
  92. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/live_context.py +0 -0
  93. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/log_parser.py +0 -0
  94. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/meta_buddhi.py +0 -0
  95. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/pattern_detector.py +0 -0
  96. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/policy.py +0 -0
  97. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/profile.py +0 -0
  98. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/provenance.py +0 -0
  99. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/resolvers.py +0 -0
  100. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/retrieval.py +0 -0
  101. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/samskara.py +0 -0
  102. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/scene.py +0 -0
  103. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/session_tracker.py +0 -0
  104. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/shared_tasks.py +0 -0
  105. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/strategy.py +0 -0
  106. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/task_state.py +0 -0
  107. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/thread_state.py +0 -0
  108. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/traces.py +0 -0
  109. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/trigger.py +0 -0
  110. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/viveka.py +0 -0
  111. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/workspace_line.py +0 -0
  112. {dhee-7.4.2 → dhee-7.4.4}/dhee/core/workspace_line_bus.py +0 -0
  113. {dhee-7.4.2 → dhee-7.4.4}/dhee/corpus/__init__.py +0 -0
  114. {dhee-7.4.2 → dhee-7.4.4}/dhee/corpus/extract.py +0 -0
  115. {dhee-7.4.2 → dhee-7.4.4}/dhee/corpus/index.py +0 -0
  116. {dhee-7.4.2 → dhee-7.4.4}/dhee/corpus/search.py +0 -0
  117. {dhee-7.4.2 → dhee-7.4.4}/dhee/corpus/store.py +0 -0
  118. {dhee-7.4.2 → dhee-7.4.4}/dhee/corpus/tree.py +0 -0
  119. {dhee-7.4.2 → dhee-7.4.4}/dhee/db/__init__.py +0 -0
  120. {dhee-7.4.2 → dhee-7.4.4}/dhee/db/sqlite_analytics.py +0 -0
  121. {dhee-7.4.2 → dhee-7.4.4}/dhee/db/sqlite_artifacts.py +0 -0
  122. {dhee-7.4.2 → dhee-7.4.4}/dhee/db/sqlite_common.py +0 -0
  123. {dhee-7.4.2 → dhee-7.4.4}/dhee/db/sqlite_domains.py +0 -0
  124. {dhee-7.4.2 → dhee-7.4.4}/dhee/debugger_api.py +0 -0
  125. {dhee-7.4.2 → dhee-7.4.4}/dhee/decisions/__init__.py +0 -0
  126. {dhee-7.4.2 → dhee-7.4.4}/dhee/decisions/jev.py +0 -0
  127. {dhee-7.4.2 → dhee-7.4.4}/dhee/decisions/regate.py +0 -0
  128. {dhee-7.4.2 → dhee-7.4.4}/dhee/decisions/select.py +0 -0
  129. {dhee-7.4.2 → dhee-7.4.4}/dhee/demo.py +0 -0
  130. {dhee-7.4.2 → dhee-7.4.4}/dhee/doctor.py +0 -0
  131. {dhee-7.4.2 → dhee-7.4.4}/dhee/embeddings/__init__.py +0 -0
  132. {dhee-7.4.2 → dhee-7.4.4}/dhee/embeddings/base.py +0 -0
  133. {dhee-7.4.2 → dhee-7.4.4}/dhee/embeddings/gemini.py +0 -0
  134. {dhee-7.4.2 → dhee-7.4.4}/dhee/embeddings/nvidia.py +0 -0
  135. {dhee-7.4.2 → dhee-7.4.4}/dhee/embeddings/ollama.py +0 -0
  136. {dhee-7.4.2 → dhee-7.4.4}/dhee/embeddings/openai.py +0 -0
  137. {dhee-7.4.2 → dhee-7.4.4}/dhee/embeddings/openrouter.py +0 -0
  138. {dhee-7.4.2 → dhee-7.4.4}/dhee/embeddings/qwen.py +0 -0
  139. {dhee-7.4.2 → dhee-7.4.4}/dhee/embeddings/simple.py +0 -0
  140. {dhee-7.4.2 → dhee-7.4.4}/dhee/exceptions.py +0 -0
  141. {dhee-7.4.2 → dhee-7.4.4}/dhee/fs/__init__.py +0 -0
  142. {dhee-7.4.2 → dhee-7.4.4}/dhee/fs/mounts.py +0 -0
  143. {dhee-7.4.2 → dhee-7.4.4}/dhee/fs/types.py +0 -0
  144. {dhee-7.4.2 → dhee-7.4.4}/dhee/fs/uri.py +0 -0
  145. {dhee-7.4.2 → dhee-7.4.4}/dhee/fs/workspace.py +0 -0
  146. {dhee-7.4.2 → dhee-7.4.4}/dhee/graph_projection_hardening.py +0 -0
  147. {dhee-7.4.2 → dhee-7.4.4}/dhee/graph_proof_bundle.py +0 -0
  148. {dhee-7.4.2 → dhee-7.4.4}/dhee/harness/__init__.py +0 -0
  149. {dhee-7.4.2 → dhee-7.4.4}/dhee/harness/base.py +0 -0
  150. {dhee-7.4.2 → dhee-7.4.4}/dhee/harness/claude_code.py +0 -0
  151. {dhee-7.4.2 → dhee-7.4.4}/dhee/harness/codex.py +0 -0
  152. {dhee-7.4.2 → dhee-7.4.4}/dhee/harness/install.py +0 -0
  153. {dhee-7.4.2 → dhee-7.4.4}/dhee/hooks/__init__.py +0 -0
  154. {dhee-7.4.2 → dhee-7.4.4}/dhee/hooks/claude_code/__init__.py +0 -0
  155. {dhee-7.4.2 → dhee-7.4.4}/dhee/hooks/claude_code/__main__.py +0 -0
  156. {dhee-7.4.2 → dhee-7.4.4}/dhee/hooks/claude_code/assembler.py +0 -0
  157. {dhee-7.4.2 → dhee-7.4.4}/dhee/hooks/claude_code/chunker.py +0 -0
  158. {dhee-7.4.2 → dhee-7.4.4}/dhee/hooks/claude_code/ingest.py +0 -0
  159. {dhee-7.4.2 → dhee-7.4.4}/dhee/hooks/claude_code/install.py +0 -0
  160. {dhee-7.4.2 → dhee-7.4.4}/dhee/hooks/claude_code/migrate.py +0 -0
  161. {dhee-7.4.2 → dhee-7.4.4}/dhee/hooks/claude_code/privacy.py +0 -0
  162. {dhee-7.4.2 → dhee-7.4.4}/dhee/hooks/claude_code/renderer.py +0 -0
  163. {dhee-7.4.2 → dhee-7.4.4}/dhee/hooks/claude_code/signal.py +0 -0
  164. {dhee-7.4.2 → dhee-7.4.4}/dhee/hooks/scene_world.py +0 -0
  165. {dhee-7.4.2 → dhee-7.4.4}/dhee/incremental_context.py +0 -0
  166. {dhee-7.4.2 → dhee-7.4.4}/dhee/install_cleanup.py +0 -0
  167. {dhee-7.4.2 → dhee-7.4.4}/dhee/integrations/__init__.py +0 -0
  168. {dhee-7.4.2 → dhee-7.4.4}/dhee/integrations/context_sources.py +0 -0
  169. {dhee-7.4.2 → dhee-7.4.4}/dhee/integrations/hermes.py +0 -0
  170. {dhee-7.4.2 → dhee-7.4.4}/dhee/integrations/hermes_provider/__init__.py +0 -0
  171. {dhee-7.4.2 → dhee-7.4.4}/dhee/integrations/hermes_provider/provider.py +0 -0
  172. {dhee-7.4.2 → dhee-7.4.4}/dhee/llms/__init__.py +0 -0
  173. {dhee-7.4.2 → dhee-7.4.4}/dhee/llms/anthropic.py +0 -0
  174. {dhee-7.4.2 → dhee-7.4.4}/dhee/llms/base.py +0 -0
  175. {dhee-7.4.2 → dhee-7.4.4}/dhee/llms/dhee.py +0 -0
  176. {dhee-7.4.2 → dhee-7.4.4}/dhee/llms/gemini.py +0 -0
  177. {dhee-7.4.2 → dhee-7.4.4}/dhee/llms/mock.py +0 -0
  178. {dhee-7.4.2 → dhee-7.4.4}/dhee/llms/nvidia.py +0 -0
  179. {dhee-7.4.2 → dhee-7.4.4}/dhee/llms/ollama.py +0 -0
  180. {dhee-7.4.2 → dhee-7.4.4}/dhee/llms/openai.py +0 -0
  181. {dhee-7.4.2 → dhee-7.4.4}/dhee/llms/teacher_logger.py +0 -0
  182. {dhee-7.4.2 → dhee-7.4.4}/dhee/mcp_registry.py +0 -0
  183. {dhee-7.4.2 → dhee-7.4.4}/dhee/mcp_server.py +0 -0
  184. {dhee-7.4.2 → dhee-7.4.4}/dhee/mcp_slim.py +0 -0
  185. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/__init__.py +0 -0
  186. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/admission.py +0 -0
  187. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/base.py +0 -0
  188. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/cost.py +0 -0
  189. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/episodic.py +0 -0
  190. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/narrative_scene.py +0 -0
  191. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/orchestration.py +0 -0
  192. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/parallel.py +0 -0
  193. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/projects.py +0 -0
  194. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/quality.py +0 -0
  195. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/reranker.py +0 -0
  196. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/retrieval_helpers.py +0 -0
  197. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/scene_profile.py +0 -0
  198. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/scoping.py +0 -0
  199. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/search_pipeline.py +0 -0
  200. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/smart.py +0 -0
  201. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/tasks.py +0 -0
  202. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/utils.py +0 -0
  203. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/vectors.py +0 -0
  204. {dhee-7.4.2 → dhee-7.4.4}/dhee/memory/write_pipeline.py +0 -0
  205. {dhee-7.4.2 → dhee-7.4.4}/dhee/mini/__init__.py +0 -0
  206. {dhee-7.4.2 → dhee-7.4.4}/dhee/mini/karma_evaluator.py +0 -0
  207. {dhee-7.4.2 → dhee-7.4.4}/dhee/mini/progressive_trainer.py +0 -0
  208. {dhee-7.4.2 → dhee-7.4.4}/dhee/mini/replay_gate.py +0 -0
  209. {dhee-7.4.2 → dhee-7.4.4}/dhee/observability.py +0 -0
  210. {dhee-7.4.2 → dhee-7.4.4}/dhee/patch_families.py +0 -0
  211. {dhee-7.4.2 → dhee-7.4.4}/dhee/plugin.py +0 -0
  212. {dhee-7.4.2 → dhee-7.4.4}/dhee/profiles/__init__.py +0 -0
  213. {dhee-7.4.2 → dhee-7.4.4}/dhee/profiles/elevenlabs.py +0 -0
  214. {dhee-7.4.2 → dhee-7.4.4}/dhee/profiles/gemini.py +0 -0
  215. {dhee-7.4.2 → dhee-7.4.4}/dhee/profiles/openai.py +0 -0
  216. {dhee-7.4.2 → dhee-7.4.4}/dhee/protocol/__init__.py +0 -0
  217. {dhee-7.4.2 → dhee-7.4.4}/dhee/protocol/v1.py +0 -0
  218. {dhee-7.4.2 → dhee-7.4.4}/dhee/provider_defaults.py +0 -0
  219. {dhee-7.4.2 → dhee-7.4.4}/dhee/providers/__init__.py +0 -0
  220. {dhee-7.4.2 → dhee-7.4.4}/dhee/providers/base.py +0 -0
  221. {dhee-7.4.2 → dhee-7.4.4}/dhee/providers/elevenlabs.py +0 -0
  222. {dhee-7.4.2 → dhee-7.4.4}/dhee/providers/gemini.py +0 -0
  223. {dhee-7.4.2 → dhee-7.4.4}/dhee/providers/openai.py +0 -0
  224. {dhee-7.4.2 → dhee-7.4.4}/dhee/release_hygiene.py +0 -0
  225. {dhee-7.4.2 → dhee-7.4.4}/dhee/replay_branching.py +0 -0
  226. {dhee-7.4.2 → dhee-7.4.4}/dhee/repo_intelligence.py +0 -0
  227. {dhee-7.4.2 → dhee-7.4.4}/dhee/repo_link.py +0 -0
  228. {dhee-7.4.2 → dhee-7.4.4}/dhee/router/__init__.py +0 -0
  229. {dhee-7.4.2 → dhee-7.4.4}/dhee/router/agent_digest.py +0 -0
  230. {dhee-7.4.2 → dhee-7.4.4}/dhee/router/bash_digest.py +0 -0
  231. {dhee-7.4.2 → dhee-7.4.4}/dhee/router/bootstrap.py +0 -0
  232. {dhee-7.4.2 → dhee-7.4.4}/dhee/router/critical_surface.py +0 -0
  233. {dhee-7.4.2 → dhee-7.4.4}/dhee/router/digest.py +0 -0
  234. {dhee-7.4.2 → dhee-7.4.4}/dhee/router/edit_ledger.py +0 -0
  235. {dhee-7.4.2 → dhee-7.4.4}/dhee/router/grep_digest.py +0 -0
  236. {dhee-7.4.2 → dhee-7.4.4}/dhee/router/handlers.py +0 -0
  237. {dhee-7.4.2 → dhee-7.4.4}/dhee/router/install.py +0 -0
  238. {dhee-7.4.2 → dhee-7.4.4}/dhee/router/intent.py +0 -0
  239. {dhee-7.4.2 → dhee-7.4.4}/dhee/router/policy.py +0 -0
  240. {dhee-7.4.2 → dhee-7.4.4}/dhee/router/pre_tool_gate.py +0 -0
  241. {dhee-7.4.2 → dhee-7.4.4}/dhee/router/ptr_store.py +0 -0
  242. {dhee-7.4.2 → dhee-7.4.4}/dhee/router/quality_report.py +0 -0
  243. {dhee-7.4.2 → dhee-7.4.4}/dhee/router/stats.py +0 -0
  244. {dhee-7.4.2 → dhee-7.4.4}/dhee/router/tune.py +0 -0
  245. {dhee-7.4.2 → dhee-7.4.4}/dhee/runtime.py +0 -0
  246. {dhee-7.4.2 → dhee-7.4.4}/dhee/runtime_daemon.py +0 -0
  247. {dhee-7.4.2 → dhee-7.4.4}/dhee/runtime_io.py +0 -0
  248. {dhee-7.4.2 → dhee-7.4.4}/dhee/schemas/__init__.py +0 -0
  249. {dhee-7.4.2 → dhee-7.4.4}/dhee/schemas/narrative.py +0 -0
  250. {dhee-7.4.2 → dhee-7.4.4}/dhee/schemas/scene_card.py +0 -0
  251. {dhee-7.4.2 → dhee-7.4.4}/dhee/secret_store.py +0 -0
  252. {dhee-7.4.2 → dhee-7.4.4}/dhee/simple.py +0 -0
  253. {dhee-7.4.2 → dhee-7.4.4}/dhee/skills/__init__.py +0 -0
  254. {dhee-7.4.2 → dhee-7.4.4}/dhee/skills/discovery.py +0 -0
  255. {dhee-7.4.2 → dhee-7.4.4}/dhee/skills/executor.py +0 -0
  256. {dhee-7.4.2 → dhee-7.4.4}/dhee/skills/hashing.py +0 -0
  257. {dhee-7.4.2 → dhee-7.4.4}/dhee/skills/miner.py +0 -0
  258. {dhee-7.4.2 → dhee-7.4.4}/dhee/skills/outcomes.py +0 -0
  259. {dhee-7.4.2 → dhee-7.4.4}/dhee/skills/schema.py +0 -0
  260. {dhee-7.4.2 → dhee-7.4.4}/dhee/skills/store.py +0 -0
  261. {dhee-7.4.2 → dhee-7.4.4}/dhee/skills/structure.py +0 -0
  262. {dhee-7.4.2 → dhee-7.4.4}/dhee/skills/trajectory.py +0 -0
  263. {dhee-7.4.2 → dhee-7.4.4}/dhee/task_contracts.py +0 -0
  264. {dhee-7.4.2 → dhee-7.4.4}/dhee/temporal_fact_integration.py +0 -0
  265. {dhee-7.4.2 → dhee-7.4.4}/dhee/temporal_fact_ledger.py +0 -0
  266. {dhee-7.4.2 → dhee-7.4.4}/dhee/temporal_scenes.py +0 -0
  267. {dhee-7.4.2 → dhee-7.4.4}/dhee/training/__init__.py +0 -0
  268. {dhee-7.4.2 → dhee-7.4.4}/dhee/training/data_formatter.py +0 -0
  269. {dhee-7.4.2 → dhee-7.4.4}/dhee/training/karma.py +0 -0
  270. {dhee-7.4.2 → dhee-7.4.4}/dhee/training/nididhyasana.py +0 -0
  271. {dhee-7.4.2 → dhee-7.4.4}/dhee/training/smrti.py +0 -0
  272. {dhee-7.4.2 → dhee-7.4.4}/dhee/training/train.py +0 -0
  273. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/__init__.py +0 -0
  274. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/cli.py +0 -0
  275. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/server.py +0 -0
  276. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/dist/assets/CanvasView-DTRgXBzE.js +0 -0
  277. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/dist/assets/index-CDViJ0N1.js +0 -0
  278. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/dist/assets/index-CIsLOp4u.css +0 -0
  279. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/dist/dhee-logo.png +0 -0
  280. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/dist/index.html +0 -0
  281. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/index.html +0 -0
  282. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/package-lock.json +0 -0
  283. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/package.json +0 -0
  284. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/public/dhee-logo.png +0 -0
  285. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/App.js +0 -0
  286. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/App.tsx +0 -0
  287. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/api.js +0 -0
  288. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/api.ts +0 -0
  289. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/AssetDrawer.js +0 -0
  290. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/AssetDrawer.tsx +0 -0
  291. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/ChatMessage.js +0 -0
  292. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/ChatMessage.tsx +0 -0
  293. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/FirstRunPanel.js +0 -0
  294. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/FirstRunPanel.tsx +0 -0
  295. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/LinePanel.js +0 -0
  296. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/LinePanel.tsx +0 -0
  297. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/MorphoGraph.js +0 -0
  298. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/MorphoGraph.tsx +0 -0
  299. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/NavRail.js +0 -0
  300. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/NavRail.tsx +0 -0
  301. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/OrgDrawer.js +0 -0
  302. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/OrgDrawer.tsx +0 -0
  303. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/TopBar.js +0 -0
  304. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/TopBar.tsx +0 -0
  305. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/TweaksPanel.js +0 -0
  306. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/TweaksPanel.tsx +0 -0
  307. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/WorkspaceManagerModal.js +0 -0
  308. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/WorkspaceManagerModal.tsx +0 -0
  309. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/CanvasControls.js +0 -0
  310. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/CanvasControls.tsx +0 -0
  311. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/CanvasSkeleton.js +0 -0
  312. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/CanvasSkeleton.tsx +0 -0
  313. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/DirectionHints.js +0 -0
  314. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/DirectionHints.tsx +0 -0
  315. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/Minimap.js +0 -0
  316. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/Minimap.tsx +0 -0
  317. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/NodeCard.js +0 -0
  318. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/NodeCard.tsx +0 -0
  319. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/forceLayout.js +0 -0
  320. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/forceLayout.ts +0 -0
  321. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/layout.js +0 -0
  322. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/layout.ts +0 -0
  323. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/treeLayout.js +0 -0
  324. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/treeLayout.ts +0 -0
  325. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/useInfiniteCanvas.js +0 -0
  326. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/useInfiniteCanvas.ts +0 -0
  327. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/cards/Cards.js +0 -0
  328. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/cards/Cards.tsx +0 -0
  329. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/graph/CanvasNodeCard.js +0 -0
  330. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/graph/CanvasNodeCard.tsx +0 -0
  331. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/ui/DecayBar.js +0 -0
  332. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/ui/DecayBar.tsx +0 -0
  333. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/ui/Markdown.js +0 -0
  334. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/ui/Markdown.tsx +0 -0
  335. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/ui/SectionHeader.js +0 -0
  336. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/ui/SectionHeader.tsx +0 -0
  337. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/ui/StatPill.js +0 -0
  338. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/ui/StatPill.tsx +0 -0
  339. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/ui/TierBadge.js +0 -0
  340. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/components/ui/TierBadge.tsx +0 -0
  341. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/main.js +0 -0
  342. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/main.tsx +0 -0
  343. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/styles.css +0 -0
  344. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/types.js +0 -0
  345. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/types.ts +0 -0
  346. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/CanvasView.js +0 -0
  347. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/CanvasView.tsx +0 -0
  348. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/ChannelView.js +0 -0
  349. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/ChannelView.tsx +0 -0
  350. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/ConflictView.js +0 -0
  351. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/ConflictView.tsx +0 -0
  352. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/ContextView.js +0 -0
  353. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/ContextView.tsx +0 -0
  354. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/EvolutionView.js +0 -0
  355. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/EvolutionView.tsx +0 -0
  356. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/LaunchView.js +0 -0
  357. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/LaunchView.tsx +0 -0
  358. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/MemoryView.js +0 -0
  359. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/MemoryView.tsx +0 -0
  360. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/NotepadView.js +0 -0
  361. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/NotepadView.tsx +0 -0
  362. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/OrgCanvas.js +0 -0
  363. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/OrgCanvas.tsx +0 -0
  364. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/ProductViews.js +0 -0
  365. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/ProductViews.tsx +0 -0
  366. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/RouterView.js +0 -0
  367. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/RouterView.tsx +0 -0
  368. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/TasksView.js +0 -0
  369. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/TasksView.tsx +0 -0
  370. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/WorkspaceView.js +0 -0
  371. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/src/views/WorkspaceView.tsx +0 -0
  372. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/tsconfig.json +0 -0
  373. {dhee-7.4.2 → dhee-7.4.4}/dhee/ui/web/vite.config.ts +0 -0
  374. {dhee-7.4.2 → dhee-7.4.4}/dhee/update_capsules.py +0 -0
  375. {dhee-7.4.2 → dhee-7.4.4}/dhee/utils/__init__.py +0 -0
  376. {dhee-7.4.2 → dhee-7.4.4}/dhee/utils/factory.py +0 -0
  377. {dhee-7.4.2 → dhee-7.4.4}/dhee/utils/math.py +0 -0
  378. {dhee-7.4.2 → dhee-7.4.4}/dhee/utils/prompts.py +0 -0
  379. {dhee-7.4.2 → dhee-7.4.4}/dhee/utils/repo_identity.py +0 -0
  380. {dhee-7.4.2 → dhee-7.4.4}/dhee/vector_stores/__init__.py +0 -0
  381. {dhee-7.4.2 → dhee-7.4.4}/dhee/vector_stores/base.py +0 -0
  382. {dhee-7.4.2 → dhee-7.4.4}/dhee/vector_stores/memory.py +0 -0
  383. {dhee-7.4.2 → dhee-7.4.4}/dhee/vector_stores/sqlite_vec.py +0 -0
  384. {dhee-7.4.2 → dhee-7.4.4}/dhee/vector_stores/zvec_store.py +0 -0
  385. {dhee-7.4.2 → dhee-7.4.4}/dhee/verification_runner.py +0 -0
  386. {dhee-7.4.2 → dhee-7.4.4}/dhee/verifier_engine.py +0 -0
  387. {dhee-7.4.2 → dhee-7.4.4}/dhee/webhooks/__init__.py +0 -0
  388. {dhee-7.4.2 → dhee-7.4.4}/dhee/webhooks/elevenlabs.py +0 -0
  389. {dhee-7.4.2 → dhee-7.4.4}/dhee/world_memory/__init__.py +0 -0
  390. {dhee-7.4.2 → dhee-7.4.4}/dhee/world_memory/capture_store.py +0 -0
  391. {dhee-7.4.2 → dhee-7.4.4}/dhee/world_memory/causal_graph.py +0 -0
  392. {dhee-7.4.2 → dhee-7.4.4}/dhee/world_memory/encoder.py +0 -0
  393. {dhee-7.4.2 → dhee-7.4.4}/dhee/world_memory/gem_extractor.py +0 -0
  394. {dhee-7.4.2 → dhee-7.4.4}/dhee/world_memory/predictor.py +0 -0
  395. {dhee-7.4.2 → dhee-7.4.4}/dhee/world_memory/schema.py +0 -0
  396. {dhee-7.4.2 → dhee-7.4.4}/dhee/world_memory/service.py +0 -0
  397. {dhee-7.4.2 → dhee-7.4.4}/dhee/world_memory/session_graph.py +0 -0
  398. {dhee-7.4.2 → dhee-7.4.4}/dhee/world_memory/store.py +0 -0
  399. {dhee-7.4.2 → dhee-7.4.4}/dhee.egg-info/dependency_links.txt +0 -0
  400. {dhee-7.4.2 → dhee-7.4.4}/dhee.egg-info/entry_points.txt +0 -0
  401. {dhee-7.4.2 → dhee-7.4.4}/dhee.egg-info/requires.txt +0 -0
  402. {dhee-7.4.2 → dhee-7.4.4}/dhee.egg-info/top_level.txt +0 -0
  403. {dhee-7.4.2 → dhee-7.4.4}/dhee_shared/__init__.py +0 -0
  404. {dhee-7.4.2 → dhee-7.4.4}/dhee_shared/model_paths.py +0 -0
  405. {dhee-7.4.2 → dhee-7.4.4}/engram/__init__.py +0 -0
  406. {dhee-7.4.2 → dhee-7.4.4}/engram-bus/engram_bus/__init__.py +0 -0
  407. {dhee-7.4.2 → dhee-7.4.4}/engram-bus/engram_bus/bus.py +0 -0
  408. {dhee-7.4.2 → dhee-7.4.4}/engram-bus/engram_bus/pubsub.py +0 -0
  409. {dhee-7.4.2 → dhee-7.4.4}/engram-bus/engram_bus/server.py +0 -0
  410. {dhee-7.4.2 → dhee-7.4.4}/engram-bus/engram_bus/store.py +0 -0
  411. {dhee-7.4.2 → dhee-7.4.4}/engram-bus/engram_bus/workspace.py +0 -0
  412. {dhee-7.4.2 → dhee-7.4.4}/setup.cfg +0 -0
  413. {dhee-7.4.2 → dhee-7.4.4}/tests/test_accel.py +0 -0
  414. {dhee-7.4.2 → dhee-7.4.4}/tests/test_accel_benchmark.py +0 -0
  415. {dhee-7.4.2 → dhee-7.4.4}/tests/test_agent_digest.py +0 -0
  416. {dhee-7.4.2 → dhee-7.4.4}/tests/test_agent_provider_examples.py +0 -0
  417. {dhee-7.4.2 → dhee-7.4.4}/tests/test_agent_runtime_before.py +0 -0
  418. {dhee-7.4.2 → dhee-7.4.4}/tests/test_agent_runtime_http_auth.py +0 -0
  419. {dhee-7.4.2 → dhee-7.4.4}/tests/test_agent_runtime_lifecycle.py +0 -0
  420. {dhee-7.4.2 → dhee-7.4.4}/tests/test_agent_runtime_tool.py +0 -0
  421. {dhee-7.4.2 → dhee-7.4.4}/tests/test_agent_runtime_voice_policy.py +0 -0
  422. {dhee-7.4.2 → dhee-7.4.4}/tests/test_artifacts.py +0 -0
  423. {dhee-7.4.2 → dhee-7.4.4}/tests/test_auto_lifecycle.py +0 -0
  424. {dhee-7.4.2 → dhee-7.4.4}/tests/test_backward_compat.py +0 -0
  425. {dhee-7.4.2 → dhee-7.4.4}/tests/test_batch.py +0 -0
  426. {dhee-7.4.2 → dhee-7.4.4}/tests/test_belief_debugger.py +0 -0
  427. {dhee-7.4.2 → dhee-7.4.4}/tests/test_causal_scene_memory.py +0 -0
  428. {dhee-7.4.2 → dhee-7.4.4}/tests/test_claude_code_hooks.py +0 -0
  429. {dhee-7.4.2 → dhee-7.4.4}/tests/test_cli_config.py +0 -0
  430. {dhee-7.4.2 → dhee-7.4.4}/tests/test_cli_harness_commands.py +0 -0
  431. {dhee-7.4.2 → dhee-7.4.4}/tests/test_cli_onboard_update.py +0 -0
  432. {dhee-7.4.2 → dhee-7.4.4}/tests/test_cli_pretty.py +0 -0
  433. {dhee-7.4.2 → dhee-7.4.4}/tests/test_codex_stream.py +0 -0
  434. {dhee-7.4.2 → dhee-7.4.4}/tests/test_cognition_evals.py +0 -0
  435. {dhee-7.4.2 → dhee-7.4.4}/tests/test_cognition_kernel.py +0 -0
  436. {dhee-7.4.2 → dhee-7.4.4}/tests/test_cognition_v3.py +0 -0
  437. {dhee-7.4.2 → dhee-7.4.4}/tests/test_context_state.py +0 -0
  438. {dhee-7.4.2 → dhee-7.4.4}/tests/test_contract_runtime_recovery.py +0 -0
  439. {dhee-7.4.2 → dhee-7.4.4}/tests/test_core_memory.py +0 -0
  440. {dhee-7.4.2 → dhee-7.4.4}/tests/test_corpus_index.py +0 -0
  441. {dhee-7.4.2 → dhee-7.4.4}/tests/test_corpus_tree.py +0 -0
  442. {dhee-7.4.2 → dhee-7.4.4}/tests/test_cosine_similarity.py +0 -0
  443. {dhee-7.4.2 → dhee-7.4.4}/tests/test_data_dir_paths.py +0 -0
  444. {dhee-7.4.2 → dhee-7.4.4}/tests/test_decades_eval.py +0 -0
  445. {dhee-7.4.2 → dhee-7.4.4}/tests/test_dedup.py +0 -0
  446. {dhee-7.4.2 → dhee-7.4.4}/tests/test_deferred_enrichment.py +0 -0
  447. {dhee-7.4.2 → dhee-7.4.4}/tests/test_demo.py +0 -0
  448. {dhee-7.4.2 → dhee-7.4.4}/tests/test_dhee_init.py +0 -0
  449. {dhee-7.4.2 → dhee-7.4.4}/tests/test_dhee_model_paths.py +0 -0
  450. {dhee-7.4.2 → dhee-7.4.4}/tests/test_dheefs.py +0 -0
  451. {dhee-7.4.2 → dhee-7.4.4}/tests/test_distillation.py +0 -0
  452. {dhee-7.4.2 → dhee-7.4.4}/tests/test_e2e_all_features.py +0 -0
  453. {dhee-7.4.2 → dhee-7.4.4}/tests/test_elevenlabs_cli.py +0 -0
  454. {dhee-7.4.2 → dhee-7.4.4}/tests/test_elevenlabs_correction_memory.py +0 -0
  455. {dhee-7.4.2 → dhee-7.4.4}/tests/test_elevenlabs_no_secret_storage.py +0 -0
  456. {dhee-7.4.2 → dhee-7.4.4}/tests/test_elevenlabs_profile.py +0 -0
  457. {dhee-7.4.2 → dhee-7.4.4}/tests/test_elevenlabs_two_call_memory.py +0 -0
  458. {dhee-7.4.2 → dhee-7.4.4}/tests/test_elevenlabs_webhook.py +0 -0
  459. {dhee-7.4.2 → dhee-7.4.4}/tests/test_engram_tiering.py +0 -0
  460. {dhee-7.4.2 → dhee-7.4.4}/tests/test_engram_tiering_promotion.py +0 -0
  461. {dhee-7.4.2 → dhee-7.4.4}/tests/test_evolution_meta_loop.py +0 -0
  462. {dhee-7.4.2 → dhee-7.4.4}/tests/test_evolution_session_gate.py +0 -0
  463. {dhee-7.4.2 → dhee-7.4.4}/tests/test_forgetting.py +0 -0
  464. {dhee-7.4.2 → dhee-7.4.4}/tests/test_gemini_provider.py +0 -0
  465. {dhee-7.4.2 → dhee-7.4.4}/tests/test_graph_proof_bundle.py +0 -0
  466. {dhee-7.4.2 → dhee-7.4.4}/tests/test_gstack_adapter.py +0 -0
  467. {dhee-7.4.2 → dhee-7.4.4}/tests/test_handoff_snapshot.py +0 -0
  468. {dhee-7.4.2 → dhee-7.4.4}/tests/test_harness_adapters.py +0 -0
  469. {dhee-7.4.2 → dhee-7.4.4}/tests/test_harness_install.py +0 -0
  470. {dhee-7.4.2 → dhee-7.4.4}/tests/test_hashing.py +0 -0
  471. {dhee-7.4.2 → dhee-7.4.4}/tests/test_hermes_provider.py +0 -0
  472. {dhee-7.4.2 → dhee-7.4.4}/tests/test_hippocamp_benchmark.py +0 -0
  473. {dhee-7.4.2 → dhee-7.4.4}/tests/test_incremental_context.py +0 -0
  474. {dhee-7.4.2 → dhee-7.4.4}/tests/test_install_cleanup.py +0 -0
  475. {dhee-7.4.2 → dhee-7.4.4}/tests/test_intent.py +0 -0
  476. {dhee-7.4.2 → dhee-7.4.4}/tests/test_karma_evaluator.py +0 -0
  477. {dhee-7.4.2 → dhee-7.4.4}/tests/test_learnings.py +0 -0
  478. {dhee-7.4.2 → dhee-7.4.4}/tests/test_locomo_plus_runner.py +0 -0
  479. {dhee-7.4.2 → dhee-7.4.4}/tests/test_log_parser.py +0 -0
  480. {dhee-7.4.2 → dhee-7.4.4}/tests/test_longmemeval_config.py +0 -0
  481. {dhee-7.4.2 → dhee-7.4.4}/tests/test_mcp_artifact_tools.py +0 -0
  482. {dhee-7.4.2 → dhee-7.4.4}/tests/test_mcp_tools_slim.py +0 -0
  483. {dhee-7.4.2 → dhee-7.4.4}/tests/test_memory_admission.py +0 -0
  484. {dhee-7.4.2 → dhee-7.4.4}/tests/test_memory_os_service.py +0 -0
  485. {dhee-7.4.2 → dhee-7.4.4}/tests/test_memory_quality_contract.py +0 -0
  486. {dhee-7.4.2 → dhee-7.4.4}/tests/test_memory_types.py +0 -0
  487. {dhee-7.4.2 → dhee-7.4.4}/tests/test_meta_buddhi_group_relative.py +0 -0
  488. {dhee-7.4.2 → dhee-7.4.4}/tests/test_migration.py +0 -0
  489. {dhee-7.4.2 → dhee-7.4.4}/tests/test_miner.py +0 -0
  490. {dhee-7.4.2 → dhee-7.4.4}/tests/test_narrative_scene_intelligence.py +0 -0
  491. {dhee-7.4.2 → dhee-7.4.4}/tests/test_nvidia_embedder.py +0 -0
  492. {dhee-7.4.2 → dhee-7.4.4}/tests/test_nvidia_llm.py +0 -0
  493. {dhee-7.4.2 → dhee-7.4.4}/tests/test_openai_provider.py +0 -0
  494. {dhee-7.4.2 → dhee-7.4.4}/tests/test_openclaw.py +0 -0
  495. {dhee-7.4.2 → dhee-7.4.4}/tests/test_orchestration_core.py +0 -0
  496. {dhee-7.4.2 → dhee-7.4.4}/tests/test_oss_61_regressions.py +0 -0
  497. {dhee-7.4.2 → dhee-7.4.4}/tests/test_packaging.py +0 -0
  498. {dhee-7.4.2 → dhee-7.4.4}/tests/test_parallel.py +0 -0
  499. {dhee-7.4.2 → dhee-7.4.4}/tests/test_patch_families.py +0 -0
  500. {dhee-7.4.2 → dhee-7.4.4}/tests/test_plugin_learnings.py +0 -0
  501. {dhee-7.4.2 → dhee-7.4.4}/tests/test_portability_eval.py +0 -0
  502. {dhee-7.4.2 → dhee-7.4.4}/tests/test_power_packages.py +0 -0
  503. {dhee-7.4.2 → dhee-7.4.4}/tests/test_presets.py +0 -0
  504. {dhee-7.4.2 → dhee-7.4.4}/tests/test_profile.py +0 -0
  505. {dhee-7.4.2 → dhee-7.4.4}/tests/test_progressive_trainer.py +0 -0
  506. {dhee-7.4.2 → dhee-7.4.4}/tests/test_projects.py +0 -0
  507. {dhee-7.4.2 → dhee-7.4.4}/tests/test_protocol_v1.py +0 -0
  508. {dhee-7.4.2 → dhee-7.4.4}/tests/test_provider_runtime_profiles.py +0 -0
  509. {dhee-7.4.2 → dhee-7.4.4}/tests/test_query_cache.py +0 -0
  510. {dhee-7.4.2 → dhee-7.4.4}/tests/test_release_hygiene.py +0 -0
  511. {dhee-7.4.2 → dhee-7.4.4}/tests/test_replay_branching.py +0 -0
  512. {dhee-7.4.2 → dhee-7.4.4}/tests/test_replay_corpus_export.py +0 -0
  513. {dhee-7.4.2 → dhee-7.4.4}/tests/test_replay_gate.py +0 -0
  514. {dhee-7.4.2 → dhee-7.4.4}/tests/test_repo_intelligence.py +0 -0
  515. {dhee-7.4.2 → dhee-7.4.4}/tests/test_repo_link.py +0 -0
  516. {dhee-7.4.2 → dhee-7.4.4}/tests/test_reranker_defaults.py +0 -0
  517. {dhee-7.4.2 → dhee-7.4.4}/tests/test_router.py +0 -0
  518. {dhee-7.4.2 → dhee-7.4.4}/tests/test_router_replay.py +0 -0
  519. {dhee-7.4.2 → dhee-7.4.4}/tests/test_router_stats_agents.py +0 -0
  520. {dhee-7.4.2 → dhee-7.4.4}/tests/test_runtime.py +0 -0
  521. {dhee-7.4.2 → dhee-7.4.4}/tests/test_runtime_hardening.py +0 -0
  522. {dhee-7.4.2 → dhee-7.4.4}/tests/test_scene.py +0 -0
  523. {dhee-7.4.2 → dhee-7.4.4}/tests/test_scene_maintenance.py +0 -0
  524. {dhee-7.4.2 → dhee-7.4.4}/tests/test_scene_world_hook.py +0 -0
  525. {dhee-7.4.2 → dhee-7.4.4}/tests/test_secret_store.py +0 -0
  526. {dhee-7.4.2 → dhee-7.4.4}/tests/test_session_tracker.py +0 -0
  527. {dhee-7.4.2 → dhee-7.4.4}/tests/test_shared_tasks.py +0 -0
  528. {dhee-7.4.2 → dhee-7.4.4}/tests/test_simple_zero_config.py +0 -0
  529. {dhee-7.4.2 → dhee-7.4.4}/tests/test_skills.py +0 -0
  530. {dhee-7.4.2 → dhee-7.4.4}/tests/test_smart_memory.py +0 -0
  531. {dhee-7.4.2 → dhee-7.4.4}/tests/test_sqlite_connection_pool.py +0 -0
  532. {dhee-7.4.2 → dhee-7.4.4}/tests/test_sqlite_vec.py +0 -0
  533. {dhee-7.4.2 → dhee-7.4.4}/tests/test_structural.py +0 -0
  534. {dhee-7.4.2 → dhee-7.4.4}/tests/test_structured_resolution.py +0 -0
  535. {dhee-7.4.2 → dhee-7.4.4}/tests/test_task_contracts.py +0 -0
  536. {dhee-7.4.2 → dhee-7.4.4}/tests/test_tasks.py +0 -0
  537. {dhee-7.4.2 → dhee-7.4.4}/tests/test_temporal_fact_integration.py +0 -0
  538. {dhee-7.4.2 → dhee-7.4.4}/tests/test_temporal_fact_ledger.py +0 -0
  539. {dhee-7.4.2 → dhee-7.4.4}/tests/test_temporal_scenes.py +0 -0
  540. {dhee-7.4.2 → dhee-7.4.4}/tests/test_thread_state.py +0 -0
  541. {dhee-7.4.2 → dhee-7.4.4}/tests/test_traces.py +0 -0
  542. {dhee-7.4.2 → dhee-7.4.4}/tests/test_trajectory.py +0 -0
  543. {dhee-7.4.2 → dhee-7.4.4}/tests/test_ui.py +0 -0
  544. {dhee-7.4.2 → dhee-7.4.4}/tests/test_unified_enrichment.py +0 -0
  545. {dhee-7.4.2 → dhee-7.4.4}/tests/test_update_capsules.py +0 -0
  546. {dhee-7.4.2 → dhee-7.4.4}/tests/test_vector_store_factory.py +0 -0
  547. {dhee-7.4.2 → dhee-7.4.4}/tests/test_verification_runner.py +0 -0
  548. {dhee-7.4.2 → dhee-7.4.4}/tests/test_verifier_engine.py +0 -0
  549. {dhee-7.4.2 → dhee-7.4.4}/tests/test_workspace_line_agent_emit.py +0 -0
  550. {dhee-7.4.2 → dhee-7.4.4}/tests/test_workspace_line_bus.py +0 -0
  551. {dhee-7.4.2 → dhee-7.4.4}/tests/test_zvec_store.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dhee
3
- Version: 7.4.2
3
+ Version: 7.4.4
4
4
  Summary: Dhee - world memory layer and context compiler for AI agents
5
5
  Author: Sankhya AI Labs
6
6
  License-Expression: MIT
@@ -50,7 +50,7 @@ from dhee.memory.admission import (
50
50
  # Default import remains model-free for backwards compatibility.
51
51
  Memory = CoreMemory
52
52
 
53
- __version__ = "7.4.2"
53
+ __version__ = "7.4.4"
54
54
  __all__ = [
55
55
  # Memory classes
56
56
  "Engram",
@@ -5,7 +5,7 @@ Uses dhee-accel (Rust) when available, pure-Python fallback otherwise.
5
5
 
6
6
  import math
7
7
  from datetime import datetime, timezone
8
- from typing import TYPE_CHECKING
8
+ from typing import Any, Optional, TYPE_CHECKING
9
9
 
10
10
  if TYPE_CHECKING:
11
11
  from dhee.configs.base import FadeMemConfig
@@ -67,6 +67,36 @@ def calculate_decayed_strength(
67
67
  )
68
68
 
69
69
 
70
+ def _as_utc(value: Any) -> Optional[datetime]:
71
+ if value is None or value == "":
72
+ return None
73
+ if isinstance(value, datetime):
74
+ moment = value
75
+ else:
76
+ try:
77
+ moment = datetime.fromisoformat(str(value).replace("Z", "+00:00"))
78
+ except ValueError:
79
+ return None
80
+ return moment if moment.tzinfo else moment.replace(tzinfo=timezone.utc)
81
+
82
+
83
+ def decay_since(last_accessed: Any, last_decayed: Any = None) -> datetime:
84
+ """The moment a memory's stored strength describes.
85
+
86
+ `calculate_decayed_strength` fades the strength it is given by the time
87
+ elapsed since this moment. The stored strength is what the LAST decay pass
88
+ left — so the clock must start at that pass, not at the last access, or
89
+ every pass fades the already-faded strength by the whole elapsed time again
90
+ and forgetting compounds with how often the pass runs. Measured: a memory
91
+ meant to last 115 days was forgotten in under one day at a five-minute
92
+ cadence, and in 15 at a daily one. With the later of the two moments, any
93
+ number of passes over a span fades a memory exactly as one pass would.
94
+ """
95
+ accessed = _as_utc(last_accessed) or datetime.now(timezone.utc)
96
+ decayed = _as_utc(last_decayed)
97
+ return max(accessed, decayed) if decayed is not None else accessed
98
+
99
+
70
100
  def should_forget(strength: float, config: "FadeMemConfig") -> bool:
71
101
  if math.isnan(strength):
72
102
  return True
@@ -5,7 +5,8 @@ import sqlite3
5
5
  import threading
6
6
  import uuid
7
7
  from contextlib import contextmanager
8
- from typing import Any, Dict, List, Optional
8
+ from datetime import datetime, timezone
9
+ from typing import Any, Dict, List, Optional, Set
9
10
 
10
11
  from .sqlite_analytics import SQLiteAnalyticsMixin
11
12
  from .sqlite_artifacts import SQLiteArtifactMixin
@@ -23,6 +24,52 @@ logger = logging.getLogger(__name__)
23
24
  class _SQLiteBase:
24
25
  """Base class for SQLite managers with common functionality."""
25
26
 
27
+ def latest_event_times(self, event: str) -> Dict[str, str]:
28
+ """When each memory last had `event` logged, as the history table wrote it.
29
+
30
+ Read once per decay pass, so the pass can start each memory's clock at
31
+ its own last decay (see `core.decay.decay_since`).
32
+ """
33
+ with self._get_connection() as conn:
34
+ if not getattr(self, "_history_event_index", False):
35
+ conn.execute(
36
+ "CREATE INDEX IF NOT EXISTS idx_memory_history_event_memory "
37
+ "ON memory_history(event, memory_id)"
38
+ )
39
+ self._history_event_index = True
40
+ rows = conn.execute(
41
+ "SELECT memory_id, MAX(timestamp) FROM memory_history WHERE event = ? GROUP BY memory_id",
42
+ (event,),
43
+ ).fetchall()
44
+ return {str(row[0]): str(row[1]) for row in rows if row[1]}
45
+
46
+ def memory_ids_holding_current_facts(self) -> Set[str]:
47
+ """Memories that are still the source of a fact nothing has replaced.
48
+
49
+ Forgetting a memory deletes the facts extracted from it (see
50
+ `_delete_memory_query_artifacts_conn`). Decay asks this first, so a
51
+ conversation can fade without taking "exam on 21 October" with it.
52
+ """
53
+ with self._get_connection() as conn:
54
+ exists = conn.execute(
55
+ "SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'engram_facts'"
56
+ ).fetchone()
57
+ if not exists:
58
+ return set()
59
+ columns = {row[1] for row in conn.execute("PRAGMA table_info(engram_facts)")}
60
+ where, params = [], []
61
+ if "superseded_by_id" in columns:
62
+ where.append("superseded_by_id IS NULL")
63
+ if "valid_until" in columns:
64
+ where.append("(valid_until IS NULL OR valid_until = '' OR valid_until > ?)")
65
+ params.append(datetime.now(timezone.utc).isoformat())
66
+ rows = conn.execute(
67
+ "SELECT DISTINCT memory_id FROM engram_facts"
68
+ + (" WHERE " + " AND ".join(where) if where else ""),
69
+ params,
70
+ ).fetchall()
71
+ return {str(row[0]) for row in rows if row[0]}
72
+
26
73
  def __init__(self, db_path: str):
27
74
  self.db_path = db_path
28
75
  db_dir = os.path.dirname(db_path)
@@ -193,7 +193,7 @@ class FactGate:
193
193
  if self.vocabulary:
194
194
  criteria = {
195
195
  name: (
196
- {k: v for k, v in meaning.items() if k not in ("many", "retires")}
196
+ {k: v for k, v in meaning.items() if k not in ("many", "retires", "per")}
197
197
  if isinstance(meaning, dict)
198
198
  else meaning
199
199
  )
@@ -263,6 +263,12 @@ class FactGate:
263
263
  continue
264
264
  top = ranked(answers, f"label_{index}")
265
265
  if top and top[0][0] == label and top[0][1] >= RELABEL_SUBJECT_FLOOR:
266
+ meaning = self.vocabulary.get(label)
267
+ if isinstance(meaning, dict) and meaning.get("per"):
268
+ # "JEE Main | scheduled_in | April" is the date of the exam
269
+ # its subject names; keep the name, or the value is a bare
270
+ # month that no longer says which exam.
271
+ facts[index].value = f"{facts[index].subject}: {facts[index].value}"
266
272
  retry[index] = f"{self.canonical_subject} | {label} | {facts[index].value}"
267
273
  if not retry:
268
274
  return judged
@@ -291,6 +297,7 @@ class FactGate:
291
297
  questions: Dict[str, Any] = {}
292
298
  state_items: Dict[str, Any] = {}
293
299
  offered: Dict[int, List[Tuple[str, str]]] = {}
300
+ keyed: Dict[int, List[Tuple[str, str]]] = {}
294
301
  for index, fact in enumerate(facts):
295
302
  try:
296
303
  stored = existing(fact.subject, fact.predicate)[:MAX_EXISTING]
@@ -309,6 +316,34 @@ class FactGate:
309
316
  # update, and storage supersedes the old one. Asking "same
310
317
  # topic?" here merged "class 12" into "class 11" — measured.
311
318
  continue
319
+ per = meaning.get("per") if isinstance(meaning, dict) else None
320
+ if per:
321
+ # One value per thing — per exam, say. The question is not
322
+ # "same topic?" but "same exam?", and a match is an update of
323
+ # that exam's value, not a restatement. Measured without this:
324
+ # the JEE date (April) replaced the boards date (March).
325
+ keyed[index] = stored
326
+ criteria = {f"stored_{k}": value for k, (value, _key) in enumerate(stored)}
327
+ criteria[NEW_FACT] = f"A different {per} from every stored value."
328
+ questions[f"same_{index}"] = {
329
+ "type": "choice",
330
+ "instructions": {
331
+ "relation": f"{fact.subject} {fact.predicate}",
332
+ "new_value": fact.value,
333
+ "question": (
334
+ f"Is the new value for the same {per} as one of the stored values, "
335
+ f"whatever else differs? Pick that stored value, or new_fact for a "
336
+ f"different {per}."
337
+ ),
338
+ },
339
+ "criteria": criteria,
340
+ }
341
+ state_items[str(index)] = {
342
+ "relation": f"{fact.subject} {fact.predicate}",
343
+ "new_value": fact.value,
344
+ "stored_values": criteria,
345
+ }
346
+ continue
312
347
  offered[index] = stored
313
348
  criteria = {f"stored_{k}": value for k, (value, _key) in enumerate(stored)}
314
349
  criteria[NEW_FACT] = "A different topic from every stored value."
@@ -344,6 +379,19 @@ class FactGate:
344
379
  if answers is None:
345
380
  return 0
346
381
  merged = 0
382
+ for index, stored in keyed.items():
383
+ top = ranked(answers, f"same_{index}")
384
+ if not top or top[0][0] == NEW_FACT or top[0][1] < self.same_floor:
385
+ continue
386
+ try:
387
+ pick = int(top[0][0].split("_", 1)[1])
388
+ except (IndexError, ValueError):
389
+ continue
390
+ if 0 <= pick < len(stored):
391
+ value, key = stored[pick]
392
+ fact = facts[index]
393
+ # The same thing with a new value replaces the old value.
394
+ _add_retirement(fact, key or f"{fact.subject}|{fact.predicate}|{value}")
347
395
  for index, stored in offered.items():
348
396
  top = ranked(answers, f"same_{index}")
349
397
  if not top or top[0][0] == NEW_FACT or top[0][1] < self.same_floor:
@@ -19,7 +19,7 @@ from datetime import datetime, timezone
19
19
  from typing import Any, Dict, List, Optional
20
20
 
21
21
  from dhee.configs.base import MemoryConfig
22
- from dhee.core.decay import calculate_decayed_strength, should_forget, should_promote
22
+ from dhee.core.decay import calculate_decayed_strength, decay_since, should_forget, should_promote
23
23
  from dhee.core.retrieval import composite_score
24
24
  from dhee.core.traces import (
25
25
  boost_fast_trace,
@@ -403,6 +403,13 @@ class CoreMemory:
403
403
  logger.warning("Vector delete failed: %s", e)
404
404
  return {"id": memory_id, "event": "DELETE"}
405
405
 
406
+ def _log_decay(self, mem: Dict[str, Any], new_strength: float) -> None:
407
+ """Record the pass, which is what the next pass starts its clock from."""
408
+ if callable(getattr(self.db, "log_event", None)):
409
+ self.db.log_event(
410
+ mem["id"], "DECAY", old_strength=mem.get("strength"), new_strength=new_strength
411
+ )
412
+
406
413
  def apply_decay(
407
414
  self,
408
415
  user_id: Optional[str] = None,
@@ -420,6 +427,19 @@ class CoreMemory:
420
427
  decayed = 0
421
428
  forgotten = 0
422
429
  promoted = 0
430
+ # Each memory's clock starts at its own last decay. See `decay_since`.
431
+ last_decayed = (
432
+ self.db.latest_event_times("DECAY")
433
+ if callable(getattr(self.db, "latest_event_times", None))
434
+ else {}
435
+ )
436
+ # A memory still the source of a current fact fades only to the
437
+ # threshold: forgetting it would delete the fact with it.
438
+ holding_facts = (
439
+ self.db.memory_ids_holding_current_facts()
440
+ if callable(getattr(self.db, "memory_ids_holding_current_facts", None))
441
+ else set()
442
+ )
423
443
 
424
444
  for mem in memories:
425
445
  if mem.get("immutable"):
@@ -438,12 +458,17 @@ class CoreMemory:
438
458
 
439
459
  new_strength = calculate_decayed_strength(
440
460
  current_strength=float(mem.get("strength", 1.0)),
441
- last_accessed=mem.get("last_accessed", mem.get("created_at", "")),
461
+ last_accessed=decay_since(
462
+ mem.get("last_accessed", mem.get("created_at", "")),
463
+ last_decayed.get(str(mem.get("id"))),
464
+ ),
442
465
  access_count=int(mem.get("access_count", 0)),
443
466
  layer=mem.get("layer", "sml"),
444
467
  config=self.fade_config,
445
468
  )
446
469
  new_strength = enforce_quality_strength(new_strength, quality)
470
+ if should_forget(new_strength, self.fade_config) and str(mem.get("id")) in holding_facts:
471
+ new_strength = self.fade_config.forgetting_threshold
447
472
 
448
473
  if should_forget(new_strength, self.fade_config):
449
474
  access_count = int(mem.get("access_count", 0))
@@ -486,9 +511,11 @@ class CoreMemory:
486
511
  self.fade_config,
487
512
  ) and quality.layer == "lml" and not quality.suppress_from_default_recall:
488
513
  self.db.update_memory(mem["id"], {"strength": new_strength, "layer": "lml"})
514
+ self._log_decay(mem, new_strength)
489
515
  promoted += 1
490
- else:
516
+ elif new_strength != float(mem.get("strength", 1.0)):
491
517
  self.db.update_memory(mem["id"], {"strength": new_strength})
518
+ self._log_decay(mem, new_strength)
492
519
 
493
520
  decayed += 1
494
521
 
@@ -17,7 +17,7 @@ from pathlib import Path
17
17
  from typing import Any, Dict, List, Optional, Tuple, Union
18
18
 
19
19
  from dhee.configs.base import MemoryConfig
20
- from dhee.core.decay import calculate_decayed_strength, should_forget, should_promote
20
+ from dhee.core.decay import calculate_decayed_strength, decay_since, should_forget, should_promote
21
21
  from dhee.core.conflict import resolve_conflict
22
22
  from dhee.core.distillation import ReplayDistiller
23
23
  from dhee.core.echo import EchoProcessor, EchoDepth, EchoResult
@@ -1523,10 +1523,28 @@ class FullMemory(SmartMemory, SceneProfileMixin):
1523
1523
  decayed = 0
1524
1524
  forgotten = 0
1525
1525
  promoted = 0
1526
+ # Each memory's clock starts at its own last decay, not its last
1527
+ # access: the stored strength is what that pass left. See `decay_since`.
1528
+ last_decayed = (
1529
+ self.db.latest_event_times("DECAY")
1530
+ if callable(getattr(self.db, "latest_event_times", None))
1531
+ else {}
1532
+ )
1533
+ # Forgetting a memory deletes the facts extracted from it, so one that
1534
+ # is still the source of a current fact fades only to the threshold.
1535
+ holding_facts = (
1536
+ self.db.memory_ids_holding_current_facts()
1537
+ if callable(getattr(self.db, "memory_ids_holding_current_facts", None))
1538
+ else set()
1539
+ )
1526
1540
 
1527
1541
  for memory in memories:
1528
1542
  if memory.get("immutable"):
1529
1543
  continue
1544
+ since = decay_since(
1545
+ memory.get("last_accessed", memory.get("created_at")),
1546
+ last_decayed.get(str(memory.get("id"))),
1547
+ )
1530
1548
 
1531
1549
  # Shruti-tier memories are immune to decay
1532
1550
  _tier_md = memory.get("metadata") or {}
@@ -1573,7 +1591,7 @@ class FullMemory(SmartMemory, SceneProfileMixin):
1573
1591
  s_fast=float(memory.get("s_fast", 0.0)),
1574
1592
  s_mid=float(memory.get("s_mid", 0.0)),
1575
1593
  s_slow=float(memory.get("s_slow", 0.0)),
1576
- last_accessed=memory.get("last_accessed", datetime.now(timezone.utc).isoformat()),
1594
+ last_accessed=since,
1577
1595
  access_count=memory.get("access_count", 0),
1578
1596
  config=self.distillation_config,
1579
1597
  )
@@ -1581,7 +1599,7 @@ class FullMemory(SmartMemory, SceneProfileMixin):
1581
1599
  else:
1582
1600
  new_strength = calculate_decayed_strength(
1583
1601
  current_strength=memory.get("strength", 1.0),
1584
- last_accessed=memory.get("last_accessed", datetime.now(timezone.utc).isoformat()),
1602
+ last_accessed=since,
1585
1603
  access_count=memory.get("access_count", 0),
1586
1604
  layer=memory.get("layer", "sml"),
1587
1605
  config=self.fade_config,
@@ -1598,6 +1616,8 @@ class FullMemory(SmartMemory, SceneProfileMixin):
1598
1616
  weak = min(int(ref_state.get("weak", 0)), 10)
1599
1617
  forget_threshold = forget_threshold / (1.0 + weak * 0.25)
1600
1618
 
1619
+ if new_strength < forget_threshold and str(memory.get("id")) in holding_facts:
1620
+ new_strength = forget_threshold
1601
1621
  if new_strength < forget_threshold:
1602
1622
  self.delete(memory["id"])
1603
1623
  forgotten += 1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dhee
3
- Version: 7.4.2
3
+ Version: 7.4.4
4
4
  Summary: Dhee - world memory layer and context compiler for AI agents
5
5
  Author: Sankhya AI Labs
6
6
  License-Expression: MIT
@@ -438,6 +438,7 @@ tests/test_corpus_tree.py
438
438
  tests/test_cosine_similarity.py
439
439
  tests/test_data_dir_paths.py
440
440
  tests/test_decades_eval.py
441
+ tests/test_decay_cadence.py
441
442
  tests/test_decisions.py
442
443
  tests/test_dedup.py
443
444
  tests/test_deferred_enrichment.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dhee"
7
- version = "7.4.2"
7
+ version = "7.4.4"
8
8
  description = "Dhee - world memory layer and context compiler for AI agents"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -0,0 +1,135 @@
1
+ """Forgetting depends on time, not on how often the decay pass runs.
2
+
3
+ `calculate_decayed_strength` fades the CURRENT strength by the time since the
4
+ memory was last accessed. Applied once, that is right. Applied again on the
5
+ next pass, it fades the already-faded strength by the whole elapsed time again,
6
+ so the result compounds with every run. Tura runs the pass every five minutes;
7
+ measured with this module's own function, a memory meant to last 115 days was
8
+ forgotten in under one, and on production (2026-10-07) none of the 12 students
9
+ who had studied in the previous fortnight had a single memory left.
10
+ """
11
+
12
+ import math
13
+ import os
14
+ from datetime import datetime, timedelta, timezone
15
+
16
+ import pytest
17
+
18
+ from dhee import CoreMemory
19
+
20
+ def _ago(days):
21
+ return (datetime.now(timezone.utc) - timedelta(days=days)).isoformat()
22
+
23
+
24
+ def _memory(factory, data_dir):
25
+ # A store of its own: a shared one dedupes the text and keeps old DECAY events.
26
+ os.environ["DHEE_DATA_DIR"] = str(data_dir)
27
+ if factory == "core":
28
+ return CoreMemory(preset="minimal")
29
+ from dhee.memory.main import FullMemory
30
+
31
+ return FullMemory(preset="minimal")
32
+
33
+
34
+ def _aged(memory, text, days):
35
+ try:
36
+ added = memory.add(text, user_id="student", infer=False)
37
+ except TypeError: # CoreMemory never infers, and takes no such argument
38
+ added = memory.add(text, user_id="student")
39
+ memory_id = added["results"][0]["id"]
40
+ memory.db.update_memory(memory_id, {"last_accessed": _ago(days), "strength": 1.0})
41
+ return memory_id
42
+
43
+
44
+ def _strength_after(tmp_path, factory, passes, days):
45
+ memory = _memory(factory, tmp_path / f"{factory}-{passes}-{days}")
46
+ try:
47
+ memory_id = _aged(memory, "Prefers derivations before worked examples", days)
48
+ for _ in range(passes):
49
+ memory.apply_decay(scope={"user_id": "student"})
50
+ row = memory.db.get_memory(memory_id)
51
+ return None if row is None or row.get("tombstone") else float(row["strength"])
52
+ finally:
53
+ memory.close()
54
+
55
+
56
+ @pytest.mark.parametrize("factory", ["core", "full"])
57
+ def test_thirty_passes_fade_a_memory_as_much_as_one(tmp_path, monkeypatch, factory):
58
+ monkeypatch.setenv("DHEE_DATA_DIR", str(tmp_path))
59
+ # Old enough to fade, young enough that one pass keeps it.
60
+ once = _strength_after(tmp_path, factory, 1, days=2)
61
+ assert once is not None and once < 1.0, "the fixture must fade, and survive one pass"
62
+ thirty = _strength_after(tmp_path, factory, 30, days=2)
63
+ assert thirty is not None, "thirty passes forgot what one pass keeps"
64
+ assert math.isclose(thirty, once, abs_tol=0.01), f"one pass leaves {once:.3f}, thirty leave {thirty:.3f}"
65
+
66
+
67
+ def test_a_memory_still_fades_with_time(tmp_path, monkeypatch):
68
+ """The fix must not stop forgetting: a pass long after the last one fades it."""
69
+ monkeypatch.setenv("DHEE_DATA_DIR", str(tmp_path))
70
+ assert (_strength_after(tmp_path, "core", 1, days=2) or 0.0) < 1.0
71
+ assert (_strength_after(tmp_path, "full", 1, days=2) or 0.0) < 1.0
72
+
73
+
74
+ def _hold_fact(memory, memory_id, value="21 October"):
75
+ """A fact extracted from `memory_id`, as the extractor would have stored it."""
76
+ import uuid
77
+
78
+ fact_id = str(uuid.uuid4())
79
+ with memory.db._get_connection() as conn:
80
+ conn.execute(
81
+ "INSERT INTO engram_facts (id, memory_id, subject, predicate, value, canonical_key) "
82
+ "VALUES (?, ?, 'user', 'exam_on', ?, ?)",
83
+ (fact_id, memory_id, f"computational stats: {value}", f"user|exam_on|{value}"),
84
+ )
85
+ return fact_id
86
+
87
+
88
+ def _facts_from(memory, memory_id):
89
+ with memory.db._get_connection() as conn:
90
+ return conn.execute(
91
+ "SELECT count(*) FROM engram_facts WHERE memory_id = ?", (memory_id,)
92
+ ).fetchone()[0]
93
+
94
+
95
+ @pytest.mark.parametrize("factory", ["core", "full"])
96
+ def test_a_memory_holding_a_current_fact_is_not_forgotten(tmp_path, monkeypatch, factory):
97
+ """Forgetting a memory deletes its facts; decay must not take a current one.
98
+
99
+ Measured on production 2026-09-30: a student's "exam date is 21 october"
100
+ was extracted and kept by the gate, then deleted with its conversation
101
+ when decay forgot it. One of 38 student stores held any fact a week later.
102
+ """
103
+ monkeypatch.setenv("DHEE_DATA_DIR", str(tmp_path))
104
+ memory = _memory(factory, tmp_path / factory)
105
+ try:
106
+ memory_id = _aged(memory, "The subject is computational stats and the exam is on 21 October", 2000)
107
+ _hold_fact(memory, memory_id)
108
+ memory.apply_decay(scope={"user_id": "student"})
109
+ row = memory.db.get_memory(memory_id)
110
+ assert row is not None and not row.get("tombstone"), "a memory holding a current fact was forgotten"
111
+ assert _facts_from(memory, memory_id) == 1
112
+ assert float(row["strength"]) == pytest.approx(memory.fade_config.forgetting_threshold)
113
+
114
+ # Once the fact is replaced, the memory fades like any other. Time
115
+ # passes for the last decay too: the clock now starts there.
116
+ with memory.db._get_connection() as conn:
117
+ conn.execute("UPDATE engram_facts SET superseded_by_id = 'newer' WHERE memory_id = ?", (memory_id,))
118
+ conn.execute("UPDATE memory_history SET timestamp = ? WHERE memory_id = ?", (_ago(2000), memory_id))
119
+ memory.apply_decay(scope={"user_id": "student"})
120
+ row = memory.db.get_memory(memory_id)
121
+ assert row is None or row.get("tombstone"), "a memory whose facts were replaced was kept"
122
+ finally:
123
+ memory.close()
124
+
125
+
126
+ def test_a_memory_with_no_facts_is_still_forgotten(tmp_path, monkeypatch):
127
+ monkeypatch.setenv("DHEE_DATA_DIR", str(tmp_path))
128
+ memory = _memory("full", tmp_path / "plain")
129
+ try:
130
+ memory_id = _aged(memory, "Said hello and left", 2000)
131
+ memory.apply_decay(scope={"user_id": "student"})
132
+ row = memory.db.get_memory(memory_id)
133
+ assert row is None or row.get("tombstone")
134
+ finally:
135
+ memory.close()
@@ -532,3 +532,50 @@ def test_a_fact_filed_under_a_thing_is_asked_again_as_the_persons():
532
532
  gate = FactGate(Scripted(answer), vocabulary=vocabulary, subjects=["the student"])
533
533
  kept, report = gate.apply("my JEE got moved to April", [fact("JEE Main", "scheduled_in", "April")])
534
534
  assert [(f.subject, f.predicate, f.value) for f in kept] == [("user", "exam_on", "April")]
535
+
536
+
537
+ def test_one_date_per_exam_not_one_date_per_student():
538
+ """Measured over a simulated hundred days: `exam_on` held one value, so the
539
+ JEE date (April) replaced the boards date (March)."""
540
+ tmp = tempfile.mkdtemp()
541
+ db = FullSQLiteManager(os.path.join(tmp, "t.db"))
542
+ with db._get_connection() as conn:
543
+ for mid in ("m1", "m2", "m3"):
544
+ conn.execute("INSERT INTO memories (id, memory, user_id) VALUES (?, ?, ?)", (mid, mid, "u"))
545
+ resolver = ContextResolver(db)
546
+ vocabulary = {"exam_on": {"what": "the date of an exam, as '<exam>: <date>'", "many": True, "per": "exam"}}
547
+
548
+ def answer(qid, q):
549
+ if qid.startswith(("about", "support")):
550
+ return {"noul": 0.95}
551
+ if qid.startswith("label"):
552
+ return choice("exam_on", 0.95, [NONE_OF_THESE])
553
+ if qid.startswith("same"):
554
+ new = q["instructions"]["new_value"].split(":")[0]
555
+ for option, value in q["criteria"].items():
556
+ if option.startswith("stored") and value.split(":")[0] == new:
557
+ return choice(option, 0.95, [NEW_FACT])
558
+ return choice(NEW_FACT, 0.95)
559
+ return {"noul": 0.05}
560
+
561
+ gate = FactGate(Scripted(answer), vocabulary=vocabulary, subjects=["the student"])
562
+
563
+ def existing(subject, predicate):
564
+ with db._get_connection() as conn:
565
+ rows = conn.execute(
566
+ "SELECT value, canonical_key FROM engram_facts WHERE subject=? AND predicate=? "
567
+ "AND superseded_by_id IS NULL",
568
+ (subject, predicate),
569
+ ).fetchall()
570
+ return [(r[0], r[1]) for r in rows]
571
+
572
+ for memory_id, value in (("m1", "JEE Main: January"), ("m2", "CBSE boards: March"), ("m3", "JEE Main: April")):
573
+ f = fact("user", "exam", value)
574
+ f.valid_from = "2026-06-0" + memory_id[-1]
575
+ kept, _ = gate.apply("…", [f], existing)
576
+ resolver.store_engram(_engram(kept), memory_id)
577
+
578
+ with db._get_connection() as conn:
579
+ active = [r[0] for r in conn.execute(
580
+ "SELECT value FROM engram_facts WHERE superseded_by_id IS NULL ORDER BY value").fetchall()]
581
+ assert active == ["CBSE boards: March", "JEE Main: April"]
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
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