superlocalmemory 2.8.5 → 3.0.0

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 (434) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE +9 -1
  3. package/NOTICE +63 -0
  4. package/README.md +165 -480
  5. package/bin/slm +17 -449
  6. package/bin/slm-npm +2 -2
  7. package/bin/slm.bat +4 -2
  8. package/conftest.py +5 -0
  9. package/docs/api-reference.md +284 -0
  10. package/docs/architecture.md +149 -0
  11. package/docs/auto-memory.md +150 -0
  12. package/docs/cli-reference.md +276 -0
  13. package/docs/compliance.md +191 -0
  14. package/docs/configuration.md +182 -0
  15. package/docs/getting-started.md +102 -0
  16. package/docs/ide-setup.md +261 -0
  17. package/docs/mcp-tools.md +220 -0
  18. package/docs/migration-from-v2.md +170 -0
  19. package/docs/profiles.md +173 -0
  20. package/docs/troubleshooting.md +310 -0
  21. package/{configs → ide/configs}/antigravity-mcp.json +3 -3
  22. package/ide/configs/chatgpt-desktop-mcp.json +16 -0
  23. package/{configs → ide/configs}/claude-desktop-mcp.json +3 -3
  24. package/{configs → ide/configs}/codex-mcp.toml +4 -4
  25. package/{configs → ide/configs}/continue-mcp.yaml +4 -3
  26. package/{configs → ide/configs}/continue-skills.yaml +6 -6
  27. package/ide/configs/cursor-mcp.json +15 -0
  28. package/{configs → ide/configs}/gemini-cli-mcp.json +2 -2
  29. package/{configs → ide/configs}/jetbrains-mcp.json +2 -2
  30. package/{configs → ide/configs}/opencode-mcp.json +2 -2
  31. package/{configs → ide/configs}/perplexity-mcp.json +2 -2
  32. package/{configs → ide/configs}/vscode-copilot-mcp.json +2 -2
  33. package/{configs → ide/configs}/windsurf-mcp.json +3 -3
  34. package/{configs → ide/configs}/zed-mcp.json +2 -2
  35. package/{hooks → ide/hooks}/context-hook.js +9 -20
  36. package/ide/hooks/memory-list-skill.js +70 -0
  37. package/ide/hooks/memory-profile-skill.js +101 -0
  38. package/ide/hooks/memory-recall-skill.js +62 -0
  39. package/ide/hooks/memory-remember-skill.js +68 -0
  40. package/ide/hooks/memory-reset-skill.js +160 -0
  41. package/{hooks → ide/hooks}/post-recall-hook.js +2 -2
  42. package/ide/integrations/langchain/README.md +106 -0
  43. package/ide/integrations/langchain/langchain_superlocalmemory/__init__.py +9 -0
  44. package/ide/integrations/langchain/langchain_superlocalmemory/chat_message_history.py +201 -0
  45. package/ide/integrations/langchain/pyproject.toml +38 -0
  46. package/{src/learning → ide/integrations/langchain}/tests/__init__.py +1 -0
  47. package/ide/integrations/langchain/tests/test_chat_message_history.py +215 -0
  48. package/ide/integrations/langchain/tests/test_security.py +117 -0
  49. package/ide/integrations/llamaindex/README.md +81 -0
  50. package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/__init__.py +9 -0
  51. package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/base.py +316 -0
  52. package/ide/integrations/llamaindex/pyproject.toml +43 -0
  53. package/{src/lifecycle → ide/integrations/llamaindex}/tests/__init__.py +1 -2
  54. package/ide/integrations/llamaindex/tests/test_chat_store.py +294 -0
  55. package/ide/integrations/llamaindex/tests/test_security.py +241 -0
  56. package/{skills → ide/skills}/slm-build-graph/SKILL.md +6 -6
  57. package/{skills → ide/skills}/slm-list-recent/SKILL.md +5 -5
  58. package/{skills → ide/skills}/slm-recall/SKILL.md +5 -5
  59. package/{skills → ide/skills}/slm-remember/SKILL.md +6 -6
  60. package/{skills → ide/skills}/slm-show-patterns/SKILL.md +7 -7
  61. package/{skills → ide/skills}/slm-status/SKILL.md +9 -9
  62. package/{skills → ide/skills}/slm-switch-profile/SKILL.md +9 -9
  63. package/package.json +13 -22
  64. package/pyproject.toml +85 -0
  65. package/scripts/build-dmg.sh +417 -0
  66. package/scripts/install-skills.ps1 +334 -0
  67. package/{install.ps1 → scripts/install.ps1} +36 -4
  68. package/{install.sh → scripts/install.sh} +14 -13
  69. package/scripts/postinstall.js +2 -2
  70. package/scripts/start-dashboard.ps1 +52 -0
  71. package/scripts/start-dashboard.sh +41 -0
  72. package/scripts/sync-wiki.ps1 +127 -0
  73. package/scripts/sync-wiki.sh +82 -0
  74. package/scripts/test-dmg.sh +161 -0
  75. package/scripts/test-npm-package.ps1 +252 -0
  76. package/scripts/test-npm-package.sh +207 -0
  77. package/scripts/verify-install.ps1 +294 -0
  78. package/scripts/verify-install.sh +266 -0
  79. package/src/superlocalmemory/__init__.py +0 -0
  80. package/src/superlocalmemory/attribution/__init__.py +9 -0
  81. package/src/superlocalmemory/attribution/mathematical_dna.py +235 -0
  82. package/src/superlocalmemory/attribution/signer.py +153 -0
  83. package/src/superlocalmemory/attribution/watermark.py +189 -0
  84. package/src/superlocalmemory/cli/__init__.py +5 -0
  85. package/src/superlocalmemory/cli/commands.py +245 -0
  86. package/src/superlocalmemory/cli/main.py +89 -0
  87. package/src/superlocalmemory/cli/migrate_cmd.py +55 -0
  88. package/src/superlocalmemory/cli/post_install.py +99 -0
  89. package/src/superlocalmemory/cli/setup_wizard.py +129 -0
  90. package/src/superlocalmemory/compliance/__init__.py +0 -0
  91. package/src/superlocalmemory/compliance/abac.py +204 -0
  92. package/src/superlocalmemory/compliance/audit.py +314 -0
  93. package/src/superlocalmemory/compliance/eu_ai_act.py +131 -0
  94. package/src/superlocalmemory/compliance/gdpr.py +294 -0
  95. package/src/superlocalmemory/compliance/lifecycle.py +158 -0
  96. package/src/superlocalmemory/compliance/retention.py +232 -0
  97. package/src/superlocalmemory/compliance/scheduler.py +148 -0
  98. package/src/superlocalmemory/core/__init__.py +0 -0
  99. package/src/superlocalmemory/core/config.py +391 -0
  100. package/src/superlocalmemory/core/embeddings.py +293 -0
  101. package/src/superlocalmemory/core/engine.py +701 -0
  102. package/src/superlocalmemory/core/hooks.py +65 -0
  103. package/src/superlocalmemory/core/maintenance.py +172 -0
  104. package/src/superlocalmemory/core/modes.py +140 -0
  105. package/src/superlocalmemory/core/profiles.py +234 -0
  106. package/src/superlocalmemory/core/registry.py +117 -0
  107. package/src/superlocalmemory/dynamics/__init__.py +0 -0
  108. package/src/superlocalmemory/dynamics/fisher_langevin_coupling.py +223 -0
  109. package/src/superlocalmemory/encoding/__init__.py +0 -0
  110. package/src/superlocalmemory/encoding/consolidator.py +485 -0
  111. package/src/superlocalmemory/encoding/emotional.py +125 -0
  112. package/src/superlocalmemory/encoding/entity_resolver.py +525 -0
  113. package/src/superlocalmemory/encoding/entropy_gate.py +104 -0
  114. package/src/superlocalmemory/encoding/fact_extractor.py +775 -0
  115. package/src/superlocalmemory/encoding/foresight.py +91 -0
  116. package/src/superlocalmemory/encoding/graph_builder.py +302 -0
  117. package/src/superlocalmemory/encoding/observation_builder.py +160 -0
  118. package/src/superlocalmemory/encoding/scene_builder.py +183 -0
  119. package/src/superlocalmemory/encoding/signal_inference.py +90 -0
  120. package/src/superlocalmemory/encoding/temporal_parser.py +426 -0
  121. package/src/superlocalmemory/encoding/type_router.py +235 -0
  122. package/src/superlocalmemory/hooks/__init__.py +3 -0
  123. package/src/superlocalmemory/hooks/auto_capture.py +111 -0
  124. package/src/superlocalmemory/hooks/auto_recall.py +93 -0
  125. package/src/superlocalmemory/hooks/ide_connector.py +204 -0
  126. package/src/superlocalmemory/hooks/rules_engine.py +99 -0
  127. package/src/superlocalmemory/infra/__init__.py +3 -0
  128. package/src/superlocalmemory/infra/auth_middleware.py +82 -0
  129. package/src/superlocalmemory/infra/backup.py +317 -0
  130. package/src/superlocalmemory/infra/cache_manager.py +267 -0
  131. package/src/superlocalmemory/infra/event_bus.py +381 -0
  132. package/src/superlocalmemory/infra/rate_limiter.py +135 -0
  133. package/src/{webhook_dispatcher.py → superlocalmemory/infra/webhook_dispatcher.py} +104 -101
  134. package/src/superlocalmemory/learning/__init__.py +0 -0
  135. package/src/superlocalmemory/learning/adaptive.py +172 -0
  136. package/src/superlocalmemory/learning/behavioral.py +490 -0
  137. package/src/superlocalmemory/learning/behavioral_listener.py +94 -0
  138. package/src/superlocalmemory/learning/bootstrap.py +298 -0
  139. package/src/superlocalmemory/learning/cross_project.py +399 -0
  140. package/src/superlocalmemory/learning/database.py +376 -0
  141. package/src/superlocalmemory/learning/engagement.py +323 -0
  142. package/src/superlocalmemory/learning/features.py +138 -0
  143. package/src/superlocalmemory/learning/feedback.py +316 -0
  144. package/src/superlocalmemory/learning/outcomes.py +255 -0
  145. package/src/superlocalmemory/learning/project_context.py +366 -0
  146. package/src/superlocalmemory/learning/ranker.py +155 -0
  147. package/src/superlocalmemory/learning/source_quality.py +303 -0
  148. package/src/superlocalmemory/learning/workflows.py +309 -0
  149. package/src/superlocalmemory/llm/__init__.py +0 -0
  150. package/src/superlocalmemory/llm/backbone.py +316 -0
  151. package/src/superlocalmemory/math/__init__.py +0 -0
  152. package/src/superlocalmemory/math/fisher.py +356 -0
  153. package/src/superlocalmemory/math/langevin.py +398 -0
  154. package/src/superlocalmemory/math/sheaf.py +257 -0
  155. package/src/superlocalmemory/mcp/__init__.py +0 -0
  156. package/src/superlocalmemory/mcp/resources.py +245 -0
  157. package/src/superlocalmemory/mcp/server.py +61 -0
  158. package/src/superlocalmemory/mcp/tools.py +18 -0
  159. package/src/superlocalmemory/mcp/tools_core.py +305 -0
  160. package/src/superlocalmemory/mcp/tools_v28.py +223 -0
  161. package/src/superlocalmemory/mcp/tools_v3.py +286 -0
  162. package/src/superlocalmemory/retrieval/__init__.py +0 -0
  163. package/src/superlocalmemory/retrieval/agentic.py +295 -0
  164. package/src/superlocalmemory/retrieval/ann_index.py +223 -0
  165. package/src/superlocalmemory/retrieval/bm25_channel.py +185 -0
  166. package/src/superlocalmemory/retrieval/bridge_discovery.py +170 -0
  167. package/src/superlocalmemory/retrieval/engine.py +390 -0
  168. package/src/superlocalmemory/retrieval/entity_channel.py +179 -0
  169. package/src/superlocalmemory/retrieval/fusion.py +78 -0
  170. package/src/superlocalmemory/retrieval/profile_channel.py +105 -0
  171. package/src/superlocalmemory/retrieval/reranker.py +154 -0
  172. package/src/superlocalmemory/retrieval/semantic_channel.py +232 -0
  173. package/src/superlocalmemory/retrieval/strategy.py +96 -0
  174. package/src/superlocalmemory/retrieval/temporal_channel.py +175 -0
  175. package/src/superlocalmemory/server/__init__.py +1 -0
  176. package/src/superlocalmemory/server/api.py +248 -0
  177. package/src/superlocalmemory/server/routes/__init__.py +4 -0
  178. package/src/superlocalmemory/server/routes/agents.py +107 -0
  179. package/src/superlocalmemory/server/routes/backup.py +91 -0
  180. package/src/superlocalmemory/server/routes/behavioral.py +127 -0
  181. package/src/superlocalmemory/server/routes/compliance.py +160 -0
  182. package/src/superlocalmemory/server/routes/data_io.py +188 -0
  183. package/src/superlocalmemory/server/routes/events.py +183 -0
  184. package/src/superlocalmemory/server/routes/helpers.py +85 -0
  185. package/src/superlocalmemory/server/routes/learning.py +273 -0
  186. package/src/superlocalmemory/server/routes/lifecycle.py +116 -0
  187. package/src/superlocalmemory/server/routes/memories.py +399 -0
  188. package/src/superlocalmemory/server/routes/profiles.py +219 -0
  189. package/src/superlocalmemory/server/routes/stats.py +346 -0
  190. package/src/superlocalmemory/server/routes/v3_api.py +365 -0
  191. package/src/superlocalmemory/server/routes/ws.py +82 -0
  192. package/src/superlocalmemory/server/security_middleware.py +57 -0
  193. package/src/superlocalmemory/server/ui.py +245 -0
  194. package/src/superlocalmemory/storage/__init__.py +0 -0
  195. package/src/superlocalmemory/storage/access_control.py +182 -0
  196. package/src/superlocalmemory/storage/database.py +594 -0
  197. package/src/superlocalmemory/storage/migrations.py +303 -0
  198. package/src/superlocalmemory/storage/models.py +406 -0
  199. package/src/superlocalmemory/storage/schema.py +726 -0
  200. package/src/superlocalmemory/storage/v2_migrator.py +317 -0
  201. package/src/superlocalmemory/trust/__init__.py +0 -0
  202. package/src/superlocalmemory/trust/gate.py +130 -0
  203. package/src/superlocalmemory/trust/provenance.py +124 -0
  204. package/src/superlocalmemory/trust/scorer.py +347 -0
  205. package/src/superlocalmemory/trust/signals.py +153 -0
  206. package/ui/index.html +278 -5
  207. package/ui/js/auto-settings.js +70 -0
  208. package/ui/js/dashboard.js +90 -0
  209. package/ui/js/fact-detail.js +92 -0
  210. package/ui/js/feedback.js +2 -2
  211. package/ui/js/ide-status.js +102 -0
  212. package/ui/js/math-health.js +98 -0
  213. package/ui/js/recall-lab.js +127 -0
  214. package/ui/js/settings.js +2 -2
  215. package/ui/js/trust-dashboard.js +73 -0
  216. package/api_server.py +0 -724
  217. package/bin/aider-smart +0 -72
  218. package/bin/superlocalmemoryv2-learning +0 -4
  219. package/bin/superlocalmemoryv2-list +0 -3
  220. package/bin/superlocalmemoryv2-patterns +0 -4
  221. package/bin/superlocalmemoryv2-profile +0 -3
  222. package/bin/superlocalmemoryv2-recall +0 -3
  223. package/bin/superlocalmemoryv2-remember +0 -3
  224. package/bin/superlocalmemoryv2-reset +0 -3
  225. package/bin/superlocalmemoryv2-status +0 -3
  226. package/configs/chatgpt-desktop-mcp.json +0 -16
  227. package/configs/cursor-mcp.json +0 -15
  228. package/docs/SECURITY-QUICK-REFERENCE.md +0 -214
  229. package/hooks/memory-list-skill.js +0 -139
  230. package/hooks/memory-profile-skill.js +0 -273
  231. package/hooks/memory-recall-skill.js +0 -114
  232. package/hooks/memory-remember-skill.js +0 -127
  233. package/hooks/memory-reset-skill.js +0 -274
  234. package/mcp_server.py +0 -1800
  235. package/requirements-core.txt +0 -22
  236. package/requirements-learning.txt +0 -12
  237. package/requirements.txt +0 -12
  238. package/src/agent_registry.py +0 -411
  239. package/src/auth_middleware.py +0 -61
  240. package/src/auto_backup.py +0 -459
  241. package/src/behavioral/__init__.py +0 -49
  242. package/src/behavioral/behavioral_listener.py +0 -203
  243. package/src/behavioral/behavioral_patterns.py +0 -275
  244. package/src/behavioral/cross_project_transfer.py +0 -206
  245. package/src/behavioral/outcome_inference.py +0 -194
  246. package/src/behavioral/outcome_tracker.py +0 -193
  247. package/src/behavioral/tests/__init__.py +0 -4
  248. package/src/behavioral/tests/test_behavioral_integration.py +0 -108
  249. package/src/behavioral/tests/test_behavioral_patterns.py +0 -150
  250. package/src/behavioral/tests/test_cross_project_transfer.py +0 -142
  251. package/src/behavioral/tests/test_mcp_behavioral.py +0 -139
  252. package/src/behavioral/tests/test_mcp_report_outcome.py +0 -117
  253. package/src/behavioral/tests/test_outcome_inference.py +0 -107
  254. package/src/behavioral/tests/test_outcome_tracker.py +0 -96
  255. package/src/cache_manager.py +0 -518
  256. package/src/compliance/__init__.py +0 -48
  257. package/src/compliance/abac_engine.py +0 -149
  258. package/src/compliance/abac_middleware.py +0 -116
  259. package/src/compliance/audit_db.py +0 -215
  260. package/src/compliance/audit_logger.py +0 -148
  261. package/src/compliance/retention_manager.py +0 -289
  262. package/src/compliance/retention_scheduler.py +0 -186
  263. package/src/compliance/tests/__init__.py +0 -4
  264. package/src/compliance/tests/test_abac_enforcement.py +0 -95
  265. package/src/compliance/tests/test_abac_engine.py +0 -124
  266. package/src/compliance/tests/test_abac_mcp_integration.py +0 -118
  267. package/src/compliance/tests/test_audit_db.py +0 -123
  268. package/src/compliance/tests/test_audit_logger.py +0 -98
  269. package/src/compliance/tests/test_mcp_audit.py +0 -128
  270. package/src/compliance/tests/test_mcp_retention_policy.py +0 -125
  271. package/src/compliance/tests/test_retention_manager.py +0 -131
  272. package/src/compliance/tests/test_retention_scheduler.py +0 -99
  273. package/src/compression/__init__.py +0 -25
  274. package/src/compression/cli.py +0 -150
  275. package/src/compression/cold_storage.py +0 -217
  276. package/src/compression/config.py +0 -72
  277. package/src/compression/orchestrator.py +0 -133
  278. package/src/compression/tier2_compressor.py +0 -228
  279. package/src/compression/tier3_compressor.py +0 -153
  280. package/src/compression/tier_classifier.py +0 -148
  281. package/src/db_connection_manager.py +0 -536
  282. package/src/embedding_engine.py +0 -63
  283. package/src/embeddings/__init__.py +0 -47
  284. package/src/embeddings/cache.py +0 -70
  285. package/src/embeddings/cli.py +0 -113
  286. package/src/embeddings/constants.py +0 -47
  287. package/src/embeddings/database.py +0 -91
  288. package/src/embeddings/engine.py +0 -247
  289. package/src/embeddings/model_loader.py +0 -145
  290. package/src/event_bus.py +0 -562
  291. package/src/graph/__init__.py +0 -36
  292. package/src/graph/build_helpers.py +0 -74
  293. package/src/graph/cli.py +0 -87
  294. package/src/graph/cluster_builder.py +0 -188
  295. package/src/graph/cluster_summary.py +0 -148
  296. package/src/graph/constants.py +0 -47
  297. package/src/graph/edge_builder.py +0 -162
  298. package/src/graph/entity_extractor.py +0 -95
  299. package/src/graph/graph_core.py +0 -226
  300. package/src/graph/graph_search.py +0 -231
  301. package/src/graph/hierarchical.py +0 -207
  302. package/src/graph/schema.py +0 -99
  303. package/src/graph_engine.py +0 -52
  304. package/src/hnsw_index.py +0 -628
  305. package/src/hybrid_search.py +0 -46
  306. package/src/learning/__init__.py +0 -217
  307. package/src/learning/adaptive_ranker.py +0 -682
  308. package/src/learning/bootstrap/__init__.py +0 -69
  309. package/src/learning/bootstrap/constants.py +0 -93
  310. package/src/learning/bootstrap/db_queries.py +0 -316
  311. package/src/learning/bootstrap/sampling.py +0 -82
  312. package/src/learning/bootstrap/text_utils.py +0 -71
  313. package/src/learning/cross_project_aggregator.py +0 -857
  314. package/src/learning/db/__init__.py +0 -40
  315. package/src/learning/db/constants.py +0 -44
  316. package/src/learning/db/schema.py +0 -279
  317. package/src/learning/engagement_tracker.py +0 -628
  318. package/src/learning/feature_extractor.py +0 -708
  319. package/src/learning/feedback_collector.py +0 -806
  320. package/src/learning/learning_db.py +0 -915
  321. package/src/learning/project_context_manager.py +0 -572
  322. package/src/learning/ranking/__init__.py +0 -33
  323. package/src/learning/ranking/constants.py +0 -84
  324. package/src/learning/ranking/helpers.py +0 -278
  325. package/src/learning/source_quality_scorer.py +0 -676
  326. package/src/learning/synthetic_bootstrap.py +0 -755
  327. package/src/learning/tests/test_adaptive_ranker.py +0 -325
  328. package/src/learning/tests/test_adaptive_ranker_v28.py +0 -60
  329. package/src/learning/tests/test_aggregator.py +0 -306
  330. package/src/learning/tests/test_auto_retrain_v28.py +0 -35
  331. package/src/learning/tests/test_e2e_ranking_v28.py +0 -82
  332. package/src/learning/tests/test_feature_extractor_v28.py +0 -93
  333. package/src/learning/tests/test_feedback_collector.py +0 -294
  334. package/src/learning/tests/test_learning_db.py +0 -602
  335. package/src/learning/tests/test_learning_db_v28.py +0 -110
  336. package/src/learning/tests/test_learning_init_v28.py +0 -48
  337. package/src/learning/tests/test_outcome_signals.py +0 -48
  338. package/src/learning/tests/test_project_context.py +0 -292
  339. package/src/learning/tests/test_schema_migration.py +0 -319
  340. package/src/learning/tests/test_signal_inference.py +0 -397
  341. package/src/learning/tests/test_source_quality.py +0 -351
  342. package/src/learning/tests/test_synthetic_bootstrap.py +0 -429
  343. package/src/learning/tests/test_workflow_miner.py +0 -318
  344. package/src/learning/workflow_pattern_miner.py +0 -655
  345. package/src/lifecycle/__init__.py +0 -54
  346. package/src/lifecycle/bounded_growth.py +0 -239
  347. package/src/lifecycle/compaction_engine.py +0 -226
  348. package/src/lifecycle/lifecycle_engine.py +0 -355
  349. package/src/lifecycle/lifecycle_evaluator.py +0 -257
  350. package/src/lifecycle/lifecycle_scheduler.py +0 -130
  351. package/src/lifecycle/retention_policy.py +0 -285
  352. package/src/lifecycle/tests/test_bounded_growth.py +0 -193
  353. package/src/lifecycle/tests/test_compaction.py +0 -179
  354. package/src/lifecycle/tests/test_lifecycle_engine.py +0 -137
  355. package/src/lifecycle/tests/test_lifecycle_evaluation.py +0 -177
  356. package/src/lifecycle/tests/test_lifecycle_scheduler.py +0 -127
  357. package/src/lifecycle/tests/test_lifecycle_search.py +0 -109
  358. package/src/lifecycle/tests/test_mcp_compact.py +0 -149
  359. package/src/lifecycle/tests/test_mcp_lifecycle_status.py +0 -114
  360. package/src/lifecycle/tests/test_retention_policy.py +0 -162
  361. package/src/mcp_tools_v28.py +0 -281
  362. package/src/memory/__init__.py +0 -36
  363. package/src/memory/cli.py +0 -205
  364. package/src/memory/constants.py +0 -39
  365. package/src/memory/helpers.py +0 -28
  366. package/src/memory/schema.py +0 -166
  367. package/src/memory-profiles.py +0 -595
  368. package/src/memory-reset.py +0 -491
  369. package/src/memory_compression.py +0 -989
  370. package/src/memory_store_v2.py +0 -1155
  371. package/src/migrate_v1_to_v2.py +0 -629
  372. package/src/pattern_learner.py +0 -34
  373. package/src/patterns/__init__.py +0 -24
  374. package/src/patterns/analyzers.py +0 -251
  375. package/src/patterns/learner.py +0 -271
  376. package/src/patterns/scoring.py +0 -171
  377. package/src/patterns/store.py +0 -225
  378. package/src/patterns/terminology.py +0 -140
  379. package/src/provenance_tracker.py +0 -312
  380. package/src/qualixar_attribution.py +0 -139
  381. package/src/qualixar_watermark.py +0 -78
  382. package/src/query_optimizer.py +0 -511
  383. package/src/rate_limiter.py +0 -83
  384. package/src/search/__init__.py +0 -20
  385. package/src/search/cli.py +0 -77
  386. package/src/search/constants.py +0 -26
  387. package/src/search/engine.py +0 -241
  388. package/src/search/fusion.py +0 -122
  389. package/src/search/index_loader.py +0 -114
  390. package/src/search/methods.py +0 -162
  391. package/src/search_engine_v2.py +0 -401
  392. package/src/setup_validator.py +0 -482
  393. package/src/subscription_manager.py +0 -391
  394. package/src/tree/__init__.py +0 -59
  395. package/src/tree/builder.py +0 -185
  396. package/src/tree/nodes.py +0 -202
  397. package/src/tree/queries.py +0 -257
  398. package/src/tree/schema.py +0 -80
  399. package/src/tree_manager.py +0 -19
  400. package/src/trust/__init__.py +0 -45
  401. package/src/trust/constants.py +0 -66
  402. package/src/trust/queries.py +0 -157
  403. package/src/trust/schema.py +0 -95
  404. package/src/trust/scorer.py +0 -299
  405. package/src/trust/signals.py +0 -95
  406. package/src/trust_scorer.py +0 -44
  407. package/ui/app.js +0 -1588
  408. package/ui/js/graph-cytoscape-monolithic-backup.js +0 -1168
  409. package/ui/js/graph-cytoscape.js +0 -1168
  410. package/ui/js/graph-d3-backup.js +0 -32
  411. package/ui/js/graph.js +0 -32
  412. package/ui_server.py +0 -266
  413. /package/docs/{ACCESSIBILITY.md → v2-archive/ACCESSIBILITY.md} +0 -0
  414. /package/docs/{ARCHITECTURE.md → v2-archive/ARCHITECTURE.md} +0 -0
  415. /package/docs/{CLI-COMMANDS-REFERENCE.md → v2-archive/CLI-COMMANDS-REFERENCE.md} +0 -0
  416. /package/docs/{COMPRESSION-README.md → v2-archive/COMPRESSION-README.md} +0 -0
  417. /package/docs/{FRAMEWORK-INTEGRATIONS.md → v2-archive/FRAMEWORK-INTEGRATIONS.md} +0 -0
  418. /package/docs/{MCP-MANUAL-SETUP.md → v2-archive/MCP-MANUAL-SETUP.md} +0 -0
  419. /package/docs/{MCP-TROUBLESHOOTING.md → v2-archive/MCP-TROUBLESHOOTING.md} +0 -0
  420. /package/docs/{PATTERN-LEARNING.md → v2-archive/PATTERN-LEARNING.md} +0 -0
  421. /package/docs/{PROFILES-GUIDE.md → v2-archive/PROFILES-GUIDE.md} +0 -0
  422. /package/docs/{RESET-GUIDE.md → v2-archive/RESET-GUIDE.md} +0 -0
  423. /package/docs/{SEARCH-ENGINE-V2.2.0.md → v2-archive/SEARCH-ENGINE-V2.2.0.md} +0 -0
  424. /package/docs/{SEARCH-INTEGRATION-GUIDE.md → v2-archive/SEARCH-INTEGRATION-GUIDE.md} +0 -0
  425. /package/docs/{UI-SERVER.md → v2-archive/UI-SERVER.md} +0 -0
  426. /package/docs/{UNIVERSAL-INTEGRATION.md → v2-archive/UNIVERSAL-INTEGRATION.md} +0 -0
  427. /package/docs/{V2.2.0-OPTIONAL-SEARCH.md → v2-archive/V2.2.0-OPTIONAL-SEARCH.md} +0 -0
  428. /package/docs/{WINDOWS-INSTALL-README.txt → v2-archive/WINDOWS-INSTALL-README.txt} +0 -0
  429. /package/docs/{WINDOWS-POST-INSTALL.txt → v2-archive/WINDOWS-POST-INSTALL.txt} +0 -0
  430. /package/docs/{example_graph_usage.py → v2-archive/example_graph_usage.py} +0 -0
  431. /package/{completions → ide/completions}/slm.bash +0 -0
  432. /package/{completions → ide/completions}/slm.zsh +0 -0
  433. /package/{configs → ide/configs}/cody-commands.json +0 -0
  434. /package/{install-skills.sh → scripts/install-skills.sh} +0 -0
@@ -0,0 +1,347 @@
1
+ # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
+ # Licensed under the MIT License - see LICENSE file
3
+ # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
+
5
+ """SuperLocalMemory V3 — Bayesian Trust Scorer (Beta Distribution).
6
+
7
+ Per-agent and per-fact trust using conjugate Beta(alpha, beta) priors.
8
+ Trust = alpha / (alpha + beta). Prior decay toward uniform when idle.
9
+
10
+ Encoding into existing schema (no ALTER TABLE):
11
+ trust_score = alpha / (alpha + beta)
12
+ evidence_count = round(alpha + beta - 2) (subtract the default prior)
13
+ Reconstruct: alpha = trust_score * (evidence_count + 2)
14
+ beta = (1 - trust_score) * (evidence_count + 2)
15
+
16
+ Backward-compatible: update_on_confirmation / contradiction / access
17
+ delegate to record_signal internally.
18
+
19
+ Part of Qualixar | Author: Varun Pratap Bhardwaj
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import logging
25
+ import math
26
+ from datetime import UTC, datetime
27
+
28
+ from superlocalmemory.storage.models import TrustScore
29
+
30
+ logger = logging.getLogger(__name__)
31
+
32
+ # Default Beta(1,1) = uniform prior => trust 0.5
33
+ _DEFAULT_ALPHA = 1.0
34
+ _DEFAULT_BETA = 1.0
35
+ _DEFAULT_TRUST = 0.5
36
+
37
+ # Signal strengths (how much each event shifts alpha/beta)
38
+ _SIGNAL_WEIGHTS: dict[str, tuple[float, float]] = {
39
+ # (delta_alpha, delta_beta)
40
+ "store_success": (1.0, 0.0),
41
+ "store_rejected": (0.0, 2.0),
42
+ "recall_hit": (0.5, 0.0),
43
+ "contradiction": (0.0, 3.0),
44
+ "deletion": (0.0, 1.5),
45
+ }
46
+
47
+ # Prior decay: days of inactivity before decay starts, and rate per day
48
+ _DECAY_IDLE_DAYS = 30
49
+ _DECAY_RATE = 0.05 # 5% per day toward prior
50
+
51
+
52
+ class TrustScorer:
53
+ """Bayesian trust scoring with Beta distribution.
54
+
55
+ Trust(agent) = alpha / (alpha + beta).
56
+ - Positive evidence increments alpha.
57
+ - Negative evidence increments beta.
58
+ - Idle decay shrinks both toward 1.0 (uniform prior).
59
+
60
+ Facts inherit their source agent's trust, penalized by contradictions.
61
+ """
62
+
63
+ def __init__(self, db) -> None:
64
+ self._db = db
65
+
66
+ # ------------------------------------------------------------------
67
+ # Public API: per-agent trust
68
+ # ------------------------------------------------------------------
69
+
70
+ def get_agent_trust(self, agent_id: str, profile_id: str) -> float:
71
+ """Get trust score for an agent. Returns 0.5 if unknown."""
72
+ alpha, beta = self._get_beta_params("agent", agent_id, profile_id)
73
+ return self._compute_trust(alpha, beta)
74
+
75
+ def get_fact_trust(self, fact_id: str, profile_id: str) -> float:
76
+ """Get trust for a fact. Inherits source agent trust, modified by
77
+ any contradiction evidence recorded directly against the fact."""
78
+ alpha, beta = self._get_beta_params("fact", fact_id, profile_id)
79
+ return self._compute_trust(alpha, beta)
80
+
81
+ def get_entity_trust(self, entity_id: str, profile_id: str) -> float:
82
+ """Convenience: get trust for an entity."""
83
+ return self.get_trust("entity", entity_id, profile_id)
84
+
85
+ def get_trust(
86
+ self, target_type: str, target_id: str, profile_id: str
87
+ ) -> float:
88
+ """Generic trust lookup — backward compatible with V3 Task 3."""
89
+ alpha, beta = self._get_beta_params(target_type, target_id, profile_id)
90
+ return self._compute_trust(alpha, beta)
91
+
92
+ # ------------------------------------------------------------------
93
+ # Public API: record signals
94
+ # ------------------------------------------------------------------
95
+
96
+ def record_signal(
97
+ self, agent_id: str, profile_id: str, signal_type: str
98
+ ) -> float:
99
+ """Record a trust signal and return updated trust score.
100
+
101
+ Args:
102
+ agent_id: The agent whose trust is being updated.
103
+ profile_id: Active profile scope.
104
+ signal_type: One of store_success, store_rejected, recall_hit,
105
+ contradiction, deletion.
106
+
107
+ Returns:
108
+ Updated trust score for the agent.
109
+ """
110
+ weights = _SIGNAL_WEIGHTS.get(signal_type, (0.0, 0.0))
111
+ delta_alpha, delta_beta = weights
112
+
113
+ alpha, beta = self._get_beta_params("agent", agent_id, profile_id)
114
+ new_alpha = alpha + delta_alpha
115
+ new_beta = beta + delta_beta
116
+
117
+ self._persist_beta("agent", agent_id, profile_id, new_alpha, new_beta)
118
+ score = self._compute_trust(new_alpha, new_beta)
119
+ logger.debug(
120
+ "trust signal: agent=%s signal=%s trust=%.3f (a=%.1f b=%.1f)",
121
+ agent_id, signal_type, score, new_alpha, new_beta,
122
+ )
123
+ return score
124
+
125
+ # ------------------------------------------------------------------
126
+ # Public API: propagation
127
+ # ------------------------------------------------------------------
128
+
129
+ def propagate_recall_trust(
130
+ self, agent_id: str, profile_id: str
131
+ ) -> float:
132
+ """Boost trust for agents whose memories are recalled.
133
+
134
+ A recall-hit means the system found the agent's data useful.
135
+ """
136
+ return self.record_signal(agent_id, profile_id, "recall_hit")
137
+
138
+ # ------------------------------------------------------------------
139
+ # Public API: direct set (testing & migration)
140
+ # ------------------------------------------------------------------
141
+
142
+ def set_trust(
143
+ self,
144
+ agent_id: str,
145
+ profile_id: str,
146
+ alpha: float = _DEFAULT_ALPHA,
147
+ beta_param: float = _DEFAULT_BETA,
148
+ ) -> float:
149
+ """Set trust directly via Beta params. Primarily for testing."""
150
+ alpha = max(0.01, alpha)
151
+ beta_param = max(0.01, beta_param)
152
+ self._persist_beta("agent", agent_id, profile_id, alpha, beta_param)
153
+ return self._compute_trust(alpha, beta_param)
154
+
155
+ # ------------------------------------------------------------------
156
+ # Public API: bulk query
157
+ # ------------------------------------------------------------------
158
+
159
+ def get_all_scores(self, profile_id: str) -> list[dict]:
160
+ """Get all trust scores for a profile as dicts.
161
+
162
+ Returns list of {target_type, target_id, trust_score,
163
+ alpha, beta_param, evidence_count, last_updated}.
164
+ """
165
+ rows = self._db.execute(
166
+ "SELECT * FROM trust_scores WHERE profile_id = ?",
167
+ (profile_id,),
168
+ )
169
+ results: list[dict] = []
170
+ for r in rows:
171
+ d = dict(r)
172
+ alpha, beta = self._decode_beta(
173
+ d["trust_score"], d["evidence_count"]
174
+ )
175
+ results.append({
176
+ "trust_id": d["trust_id"],
177
+ "target_type": d["target_type"],
178
+ "target_id": d["target_id"],
179
+ "trust_score": d["trust_score"],
180
+ "alpha": alpha,
181
+ "beta_param": beta,
182
+ "evidence_count": d["evidence_count"],
183
+ "last_updated": d["last_updated"],
184
+ })
185
+ return results
186
+
187
+ # ------------------------------------------------------------------
188
+ # Backward-compatible delegators
189
+ # ------------------------------------------------------------------
190
+
191
+ def update_on_confirmation(
192
+ self, target_type: str, target_id: str, profile_id: str
193
+ ) -> float:
194
+ """V3-compat: confirmation -> store_success signal."""
195
+ alpha, beta = self._get_beta_params(target_type, target_id, profile_id)
196
+ new_alpha = alpha + 1.0
197
+ self._persist_beta(target_type, target_id, profile_id, new_alpha, beta)
198
+ return self._compute_trust(new_alpha, beta)
199
+
200
+ def update_on_contradiction(
201
+ self, target_type: str, target_id: str, profile_id: str
202
+ ) -> float:
203
+ """V3-compat: contradiction -> contradiction signal."""
204
+ alpha, beta = self._get_beta_params(target_type, target_id, profile_id)
205
+ new_beta = beta + 3.0
206
+ self._persist_beta(target_type, target_id, profile_id, alpha, new_beta)
207
+ return self._compute_trust(alpha, new_beta)
208
+
209
+ def update_on_access(
210
+ self, target_type: str, target_id: str, profile_id: str
211
+ ) -> float:
212
+ """V3-compat: access -> recall_hit signal (small boost)."""
213
+ alpha, beta = self._get_beta_params(target_type, target_id, profile_id)
214
+ new_alpha = alpha + 0.5
215
+ self._persist_beta(
216
+ target_type, target_id, profile_id, new_alpha, beta
217
+ )
218
+ return self._compute_trust(new_alpha, beta)
219
+
220
+ # ------------------------------------------------------------------
221
+ # Prior decay
222
+ # ------------------------------------------------------------------
223
+
224
+ def apply_prior_decay(self, profile_id: str) -> int:
225
+ """Decay idle trust scores toward uniform prior Beta(1,1).
226
+
227
+ Called periodically (e.g., daily maintenance).
228
+ Returns number of scores decayed.
229
+ """
230
+ cutoff = datetime.now(UTC).isoformat()
231
+ rows = self._db.execute(
232
+ "SELECT * FROM trust_scores WHERE profile_id = ?",
233
+ (profile_id,),
234
+ )
235
+ decayed = 0
236
+ for r in rows:
237
+ d = dict(r)
238
+ last = d.get("last_updated", "")
239
+ if not last:
240
+ continue
241
+ try:
242
+ last_dt = datetime.fromisoformat(last)
243
+ idle_days = (
244
+ datetime.now(UTC) - last_dt.replace(tzinfo=UTC)
245
+ ).days
246
+ except (ValueError, TypeError):
247
+ continue
248
+
249
+ if idle_days < _DECAY_IDLE_DAYS:
250
+ continue
251
+
252
+ alpha, beta = self._decode_beta(
253
+ d["trust_score"], d["evidence_count"]
254
+ )
255
+ excess_days = idle_days - _DECAY_IDLE_DAYS
256
+ decay_factor = max(0.0, 1.0 - _DECAY_RATE * excess_days)
257
+
258
+ new_alpha = _DEFAULT_ALPHA + (alpha - _DEFAULT_ALPHA) * decay_factor
259
+ new_beta = _DEFAULT_BETA + (beta - _DEFAULT_BETA) * decay_factor
260
+
261
+ new_alpha = max(0.01, new_alpha)
262
+ new_beta = max(0.01, new_beta)
263
+
264
+ score = self._compute_trust(new_alpha, new_beta)
265
+ ev = max(0, round(new_alpha + new_beta - 2))
266
+ self._db.execute(
267
+ "UPDATE trust_scores SET trust_score = ?, evidence_count = ?, "
268
+ "last_updated = ? WHERE trust_id = ?",
269
+ (score, ev, cutoff, d["trust_id"]),
270
+ )
271
+ decayed += 1
272
+ return decayed
273
+
274
+ # ------------------------------------------------------------------
275
+ # Internal helpers
276
+ # ------------------------------------------------------------------
277
+
278
+ @staticmethod
279
+ def _compute_trust(alpha: float, beta: float) -> float:
280
+ """Trust = alpha / (alpha + beta), clamped to [0, 1]."""
281
+ total = alpha + beta
282
+ if total <= 0:
283
+ return _DEFAULT_TRUST
284
+ return max(0.0, min(1.0, alpha / total))
285
+
286
+ @staticmethod
287
+ def _decode_beta(
288
+ trust_score: float, evidence_count: int
289
+ ) -> tuple[float, float]:
290
+ """Reconstruct Beta params from encoded trust_score + evidence_count.
291
+
292
+ Encoding: trust_score = a/(a+b), evidence_count = round(a+b-2).
293
+ """
294
+ total = float(evidence_count) + 2.0
295
+ alpha = trust_score * total
296
+ beta = (1.0 - trust_score) * total
297
+ return max(0.01, alpha), max(0.01, beta)
298
+
299
+ def _get_beta_params(
300
+ self, target_type: str, target_id: str, profile_id: str
301
+ ) -> tuple[float, float]:
302
+ """Load Beta(alpha, beta) from DB, or return default prior."""
303
+ rows = self._db.execute(
304
+ "SELECT trust_score, evidence_count FROM trust_scores "
305
+ "WHERE target_type = ? AND target_id = ? AND profile_id = ?",
306
+ (target_type, target_id, profile_id),
307
+ )
308
+ if rows:
309
+ d = dict(rows[0])
310
+ return self._decode_beta(d["trust_score"], d["evidence_count"])
311
+ return _DEFAULT_ALPHA, _DEFAULT_BETA
312
+
313
+ def _persist_beta(
314
+ self,
315
+ target_type: str,
316
+ target_id: str,
317
+ profile_id: str,
318
+ alpha: float,
319
+ beta: float,
320
+ ) -> None:
321
+ """Encode and persist Beta params into existing schema."""
322
+ score = self._compute_trust(alpha, beta)
323
+ ev = max(0, round(alpha + beta - 2))
324
+ now = datetime.now(UTC).isoformat()
325
+
326
+ existing = self._db.execute(
327
+ "SELECT trust_id FROM trust_scores "
328
+ "WHERE target_type = ? AND target_id = ? AND profile_id = ?",
329
+ (target_type, target_id, profile_id),
330
+ )
331
+ if existing:
332
+ tid = dict(existing[0])["trust_id"]
333
+ self._db.execute(
334
+ "UPDATE trust_scores SET trust_score = ?, evidence_count = ?, "
335
+ "last_updated = ? WHERE trust_id = ?",
336
+ (score, ev, now, tid),
337
+ )
338
+ else:
339
+ from superlocalmemory.storage.models import _new_id
340
+
341
+ tid = _new_id()
342
+ self._db.execute(
343
+ "INSERT INTO trust_scores "
344
+ "(trust_id, profile_id, target_type, target_id, trust_score, "
345
+ "evidence_count, last_updated) VALUES (?,?,?,?,?,?,?)",
346
+ (tid, profile_id, target_type, target_id, score, ev, now),
347
+ )
@@ -0,0 +1,153 @@
1
+ # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
+ # Licensed under the MIT License - see LICENSE file
3
+ # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
+
5
+ """SuperLocalMemory V3 — Trust Signal Recorder with Burst Detection.
6
+
7
+ Records trust signals and detects anomalous write patterns.
8
+ Burst detection uses an in-memory sliding window (collections.deque)
9
+ per agent. Signals are published via the event bus rather than a
10
+ separate table, keeping the storage footprint minimal.
11
+
12
+ Part of Qualixar | Author: Varun Pratap Bhardwaj
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import logging
18
+ import time
19
+ from collections import defaultdict, deque
20
+ from typing import Any
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+ # Valid signal types (must match scorer._SIGNAL_WEIGHTS keys)
25
+ VALID_SIGNAL_TYPES = frozenset({
26
+ "store_success",
27
+ "store_rejected",
28
+ "recall_hit",
29
+ "contradiction",
30
+ "deletion",
31
+ })
32
+
33
+
34
+ class SignalRecorder:
35
+ """Records trust signals and detects anomalous write patterns.
36
+
37
+ Burst detection: tracks write timestamps in a per-agent deque.
38
+ If > threshold writes occur within the window, burst is flagged.
39
+ Burst-flagged signals are still recorded but logged as anomalous.
40
+ """
41
+
42
+ def __init__(
43
+ self,
44
+ db: Any,
45
+ burst_window_seconds: int = 60,
46
+ burst_threshold: int = 20,
47
+ ) -> None:
48
+ self._db = db
49
+ self._burst_window = burst_window_seconds
50
+ self._burst_threshold = burst_threshold
51
+
52
+ # Per-agent sliding window: key = (agent_id, profile_id)
53
+ # Value = deque of timestamps (float, time.monotonic)
54
+ self._windows: dict[tuple[str, str], deque[float]] = defaultdict(
55
+ lambda: deque(maxlen=max(1, burst_threshold * 2))
56
+ )
57
+
58
+ # In-memory signal log for get_recent_signals
59
+ self._recent: dict[tuple[str, str], deque[dict]] = defaultdict(
60
+ lambda: deque(maxlen=200)
61
+ )
62
+
63
+ def record(
64
+ self,
65
+ agent_id: str,
66
+ profile_id: str,
67
+ signal_type: str,
68
+ context: dict[str, Any] | None = None,
69
+ ) -> bool:
70
+ """Record a trust signal.
71
+
72
+ Args:
73
+ agent_id: The agent generating the signal.
74
+ profile_id: Active profile scope.
75
+ signal_type: One of VALID_SIGNAL_TYPES.
76
+ context: Optional metadata about the signal.
77
+
78
+ Returns:
79
+ True if signal was accepted (even during burst).
80
+ False if signal_type is invalid.
81
+ """
82
+ if signal_type not in VALID_SIGNAL_TYPES:
83
+ logger.warning("invalid signal type: %s", signal_type)
84
+ return False
85
+
86
+ now = time.monotonic()
87
+ key = (agent_id, profile_id)
88
+
89
+ # Update sliding window
90
+ window = self._windows[key]
91
+ window.append(now)
92
+ self._prune_window(window, now)
93
+
94
+ # Check burst before recording
95
+ is_burst = len(window) >= self._burst_threshold
96
+ if is_burst:
97
+ logger.warning(
98
+ "burst detected: agent=%s profile=%s count=%d in %ds",
99
+ agent_id, profile_id, len(window), self._burst_window,
100
+ )
101
+
102
+ # Record signal in memory log
103
+ entry = {
104
+ "agent_id": agent_id,
105
+ "profile_id": profile_id,
106
+ "signal_type": signal_type,
107
+ "timestamp": now,
108
+ "burst_flagged": is_burst,
109
+ "context": context or {},
110
+ }
111
+ self._recent[key].append(entry)
112
+
113
+ return True
114
+
115
+ def is_burst_detected(self, agent_id: str, profile_id: str) -> bool:
116
+ """True if agent has exceeded burst_threshold writes in window."""
117
+ key = (agent_id, profile_id)
118
+ window = self._windows.get(key)
119
+ if window is None:
120
+ return False
121
+
122
+ now = time.monotonic()
123
+ self._prune_window(window, now)
124
+ return len(window) >= self._burst_threshold
125
+
126
+ def get_recent_signals(
127
+ self, agent_id: str, profile_id: str, limit: int = 50
128
+ ) -> list[dict]:
129
+ """Get recent signals for an agent, most recent first."""
130
+ key = (agent_id, profile_id)
131
+ signals = list(self._recent.get(key, []))
132
+ signals.reverse()
133
+ return signals[:limit]
134
+
135
+ def get_burst_status(self, profile_id: str) -> dict[str, bool]:
136
+ """Get burst status for all agents in a profile.
137
+
138
+ Returns dict mapping agent_id -> is_bursting.
139
+ """
140
+ result: dict[str, bool] = {}
141
+ now = time.monotonic()
142
+ for (aid, pid), window in self._windows.items():
143
+ if pid != profile_id:
144
+ continue
145
+ self._prune_window(window, now)
146
+ result[aid] = len(window) >= self._burst_threshold
147
+ return result
148
+
149
+ def _prune_window(self, window: deque[float], now: float) -> None:
150
+ """Remove timestamps older than the burst window."""
151
+ cutoff = now - self._burst_window
152
+ while window and window[0] < cutoff:
153
+ window.popleft()