dhee 7.4.3__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.
- {dhee-7.4.3/dhee.egg-info → dhee-7.4.4}/PKG-INFO +1 -1
- {dhee-7.4.3 → dhee-7.4.4}/dhee/__init__.py +1 -1
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/decay.py +31 -1
- {dhee-7.4.3 → dhee-7.4.4}/dhee/db/sqlite.py +48 -1
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/core.py +30 -3
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/main.py +23 -3
- {dhee-7.4.3 → dhee-7.4.4/dhee.egg-info}/PKG-INFO +1 -1
- {dhee-7.4.3 → dhee-7.4.4}/dhee.egg-info/SOURCES.txt +1 -0
- {dhee-7.4.3 → dhee-7.4.4}/pyproject.toml +1 -1
- dhee-7.4.4/tests/test_decay_cadence.py +135 -0
- {dhee-7.4.3 → dhee-7.4.4}/LICENSE +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/MANIFEST.in +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/README.md +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/adapters/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/adapters/gstack.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/adapters/gstack_parser.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/adapters/morpho_adapter.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/agent_runtime/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/agent_runtime/auth.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/agent_runtime/client.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/agent_runtime/events.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/agent_runtime/models.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/agent_runtime/policy.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/agent_runtime/run.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/agent_runtime/server.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/agent_runtime/tools.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/benchmarks/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/benchmarks/arc_agi.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/benchmarks/decades.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/benchmarks/hippocamp.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/benchmarks/longmemeval.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/benchmarks/phase0_context_audit.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/benchmarks/portability.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/benchmarks/raw_extractors.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/benchmarks/replay_corpus.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/benchmarks/router_replay.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/checkpoint_runtime.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/cli.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/cli_config.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/cli_mcp.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/cli_onboard.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/cli_pretty.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/cli_setup.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/cli_update.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/configs/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/configs/active.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/configs/base.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/configs/presets.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/context_ir.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/context_kernel.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/context_state.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/contract_runtime.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/contract_supervisor.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/alaya.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/answer_orchestration.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/artifacts.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/belief.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/buddhi.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/category.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/codex_artifacts.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/codex_stream.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/cognition.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/cognition_kernel.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/conflict.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/context_bootstrap.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/contrastive.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/distillation.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/echo.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/engram.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/engram_consolidator.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/engram_extractor.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/engram_tiering.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/engram_verification.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/enrichment.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/episode.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/episodic_index.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/evolution.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/file_baseline.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/file_read_tracker.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/forgetting.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/fusion.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/graph.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/handoff_snapshot.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/heuristic.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/intent.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/intention.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/kernel.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/learnings.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/live_context.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/log_parser.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/meta_buddhi.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/pattern_detector.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/policy.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/profile.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/provenance.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/resolvers.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/retrieval.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/samskara.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/scene.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/session_tracker.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/shared_tasks.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/strategy.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/task_state.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/thread_state.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/traces.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/trigger.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/viveka.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/workspace_line.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/core/workspace_line_bus.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/corpus/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/corpus/extract.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/corpus/index.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/corpus/search.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/corpus/store.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/corpus/tree.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/db/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/db/sqlite_analytics.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/db/sqlite_artifacts.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/db/sqlite_common.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/db/sqlite_domains.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/debugger_api.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/decisions/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/decisions/facts.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/decisions/jev.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/decisions/regate.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/decisions/select.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/demo.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/doctor.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/embeddings/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/embeddings/base.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/embeddings/gemini.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/embeddings/nvidia.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/embeddings/ollama.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/embeddings/openai.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/embeddings/openrouter.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/embeddings/qwen.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/embeddings/simple.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/exceptions.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/fs/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/fs/mounts.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/fs/types.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/fs/uri.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/fs/workspace.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/graph_projection_hardening.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/graph_proof_bundle.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/harness/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/harness/base.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/harness/claude_code.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/harness/codex.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/harness/install.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/hooks/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/hooks/claude_code/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/hooks/claude_code/__main__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/hooks/claude_code/assembler.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/hooks/claude_code/chunker.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/hooks/claude_code/ingest.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/hooks/claude_code/install.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/hooks/claude_code/migrate.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/hooks/claude_code/privacy.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/hooks/claude_code/renderer.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/hooks/claude_code/signal.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/hooks/scene_world.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/incremental_context.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/install_cleanup.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/integrations/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/integrations/context_sources.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/integrations/hermes.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/integrations/hermes_provider/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/integrations/hermes_provider/provider.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/llms/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/llms/anthropic.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/llms/base.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/llms/dhee.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/llms/gemini.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/llms/mock.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/llms/nvidia.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/llms/ollama.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/llms/openai.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/llms/teacher_logger.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/mcp_registry.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/mcp_server.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/mcp_slim.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/admission.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/base.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/cost.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/episodic.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/narrative_scene.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/orchestration.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/parallel.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/projects.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/quality.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/reranker.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/retrieval_helpers.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/scene_profile.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/scoping.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/search_pipeline.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/smart.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/tasks.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/utils.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/vectors.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/memory/write_pipeline.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/mini/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/mini/karma_evaluator.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/mini/progressive_trainer.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/mini/replay_gate.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/observability.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/patch_families.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/plugin.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/profiles/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/profiles/elevenlabs.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/profiles/gemini.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/profiles/openai.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/protocol/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/protocol/v1.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/provider_defaults.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/providers/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/providers/base.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/providers/elevenlabs.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/providers/gemini.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/providers/openai.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/release_hygiene.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/replay_branching.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/repo_intelligence.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/repo_link.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/router/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/router/agent_digest.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/router/bash_digest.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/router/bootstrap.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/router/critical_surface.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/router/digest.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/router/edit_ledger.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/router/grep_digest.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/router/handlers.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/router/install.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/router/intent.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/router/policy.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/router/pre_tool_gate.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/router/ptr_store.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/router/quality_report.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/router/stats.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/router/tune.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/runtime.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/runtime_daemon.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/runtime_io.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/schemas/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/schemas/narrative.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/schemas/scene_card.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/secret_store.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/simple.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/skills/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/skills/discovery.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/skills/executor.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/skills/hashing.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/skills/miner.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/skills/outcomes.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/skills/schema.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/skills/store.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/skills/structure.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/skills/trajectory.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/task_contracts.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/temporal_fact_integration.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/temporal_fact_ledger.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/temporal_scenes.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/training/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/training/data_formatter.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/training/karma.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/training/nididhyasana.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/training/smrti.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/training/train.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/cli.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/server.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/dist/assets/CanvasView-DTRgXBzE.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/dist/assets/index-CDViJ0N1.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/dist/assets/index-CIsLOp4u.css +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/dist/dhee-logo.png +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/dist/index.html +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/index.html +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/package-lock.json +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/package.json +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/public/dhee-logo.png +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/App.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/App.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/api.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/api.ts +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/AssetDrawer.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/AssetDrawer.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/ChatMessage.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/ChatMessage.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/FirstRunPanel.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/FirstRunPanel.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/LinePanel.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/LinePanel.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/MorphoGraph.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/MorphoGraph.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/NavRail.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/NavRail.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/OrgDrawer.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/OrgDrawer.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/TopBar.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/TopBar.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/TweaksPanel.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/TweaksPanel.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/WorkspaceManagerModal.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/WorkspaceManagerModal.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/CanvasControls.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/CanvasControls.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/CanvasSkeleton.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/CanvasSkeleton.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/DirectionHints.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/DirectionHints.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/Minimap.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/Minimap.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/NodeCard.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/NodeCard.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/forceLayout.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/forceLayout.ts +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/layout.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/layout.ts +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/treeLayout.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/treeLayout.ts +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/useInfiniteCanvas.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/canvas/useInfiniteCanvas.ts +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/cards/Cards.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/cards/Cards.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/graph/CanvasNodeCard.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/graph/CanvasNodeCard.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/ui/DecayBar.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/ui/DecayBar.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/ui/Markdown.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/ui/Markdown.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/ui/SectionHeader.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/ui/SectionHeader.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/ui/StatPill.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/ui/StatPill.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/ui/TierBadge.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/components/ui/TierBadge.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/main.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/main.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/styles.css +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/types.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/types.ts +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/CanvasView.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/CanvasView.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/ChannelView.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/ChannelView.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/ConflictView.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/ConflictView.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/ContextView.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/ContextView.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/EvolutionView.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/EvolutionView.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/LaunchView.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/LaunchView.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/MemoryView.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/MemoryView.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/NotepadView.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/NotepadView.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/OrgCanvas.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/OrgCanvas.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/ProductViews.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/ProductViews.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/RouterView.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/RouterView.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/TasksView.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/TasksView.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/WorkspaceView.js +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/src/views/WorkspaceView.tsx +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/tsconfig.json +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/ui/web/vite.config.ts +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/update_capsules.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/utils/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/utils/factory.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/utils/math.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/utils/prompts.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/utils/repo_identity.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/vector_stores/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/vector_stores/base.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/vector_stores/memory.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/vector_stores/sqlite_vec.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/vector_stores/zvec_store.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/verification_runner.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/verifier_engine.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/webhooks/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/webhooks/elevenlabs.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/world_memory/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/world_memory/capture_store.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/world_memory/causal_graph.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/world_memory/encoder.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/world_memory/gem_extractor.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/world_memory/predictor.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/world_memory/schema.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/world_memory/service.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/world_memory/session_graph.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee/world_memory/store.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee.egg-info/dependency_links.txt +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee.egg-info/entry_points.txt +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee.egg-info/requires.txt +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee.egg-info/top_level.txt +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee_shared/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/dhee_shared/model_paths.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/engram/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/engram-bus/engram_bus/__init__.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/engram-bus/engram_bus/bus.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/engram-bus/engram_bus/pubsub.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/engram-bus/engram_bus/server.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/engram-bus/engram_bus/store.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/engram-bus/engram_bus/workspace.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/setup.cfg +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_accel.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_accel_benchmark.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_agent_digest.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_agent_provider_examples.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_agent_runtime_before.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_agent_runtime_http_auth.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_agent_runtime_lifecycle.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_agent_runtime_tool.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_agent_runtime_voice_policy.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_artifacts.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_auto_lifecycle.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_backward_compat.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_batch.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_belief_debugger.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_causal_scene_memory.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_claude_code_hooks.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_cli_config.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_cli_harness_commands.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_cli_onboard_update.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_cli_pretty.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_codex_stream.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_cognition_evals.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_cognition_kernel.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_cognition_v3.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_context_state.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_contract_runtime_recovery.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_core_memory.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_corpus_index.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_corpus_tree.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_cosine_similarity.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_data_dir_paths.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_decades_eval.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_decisions.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_dedup.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_deferred_enrichment.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_demo.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_dhee_init.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_dhee_model_paths.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_dheefs.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_distillation.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_e2e_all_features.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_elevenlabs_cli.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_elevenlabs_correction_memory.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_elevenlabs_no_secret_storage.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_elevenlabs_profile.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_elevenlabs_two_call_memory.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_elevenlabs_webhook.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_engram_tiering.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_engram_tiering_promotion.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_evolution_meta_loop.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_evolution_session_gate.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_forgetting.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_gemini_provider.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_graph_proof_bundle.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_gstack_adapter.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_handoff_snapshot.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_harness_adapters.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_harness_install.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_hashing.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_hermes_provider.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_hippocamp_benchmark.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_incremental_context.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_install_cleanup.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_intent.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_karma_evaluator.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_learnings.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_locomo_plus_runner.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_log_parser.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_longmemeval_config.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_mcp_artifact_tools.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_mcp_tools_slim.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_memory_admission.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_memory_os_service.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_memory_quality_contract.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_memory_types.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_meta_buddhi_group_relative.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_migration.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_miner.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_narrative_scene_intelligence.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_nvidia_embedder.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_nvidia_llm.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_openai_provider.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_openclaw.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_orchestration_core.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_oss_61_regressions.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_packaging.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_parallel.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_patch_families.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_plugin_learnings.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_portability_eval.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_power_packages.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_presets.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_profile.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_progressive_trainer.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_projects.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_protocol_v1.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_provider_runtime_profiles.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_query_cache.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_release_hygiene.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_replay_branching.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_replay_corpus_export.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_replay_gate.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_repo_intelligence.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_repo_link.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_reranker_defaults.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_router.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_router_replay.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_router_stats_agents.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_runtime.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_runtime_hardening.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_scene.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_scene_maintenance.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_scene_world_hook.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_secret_store.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_session_tracker.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_shared_tasks.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_simple_zero_config.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_skills.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_smart_memory.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_sqlite_connection_pool.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_sqlite_vec.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_structural.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_structured_resolution.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_task_contracts.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_tasks.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_temporal_fact_integration.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_temporal_fact_ledger.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_temporal_scenes.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_thread_state.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_traces.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_trajectory.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_ui.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_unified_enrichment.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_update_capsules.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_vector_store_factory.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_verification_runner.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_verifier_engine.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_workspace_line_agent_emit.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_workspace_line_bus.py +0 -0
- {dhee-7.4.3 → dhee-7.4.4}/tests/test_zvec_store.py +0 -0
|
@@ -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
|
|
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)
|
|
@@ -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=
|
|
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
|
-
|
|
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=
|
|
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=
|
|
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
|
|
@@ -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()
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|