claude-smart 0.2.45 → 0.2.47

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 (353) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/README.md +47 -10
  3. package/bin/claude-smart.js +535 -23
  4. package/package.json +22 -3
  5. package/plugin/.claude-plugin/plugin.json +4 -2
  6. package/plugin/.codex-plugin/plugin.json +1 -1
  7. package/plugin/README.md +27 -6
  8. package/plugin/commands/clear-all.md +1 -0
  9. package/plugin/commands/dashboard.md +1 -0
  10. package/plugin/commands/learn.md +1 -0
  11. package/plugin/commands/restart.md +1 -0
  12. package/plugin/commands/show.md +1 -0
  13. package/plugin/dashboard/app/configure/env/page.tsx +40 -14
  14. package/plugin/dashboard/app/configure/server/page.tsx +51 -1
  15. package/plugin/dashboard/app/layout.tsx +20 -0
  16. package/plugin/dashboard/app/preferences/[id]/page.tsx +8 -8
  17. package/plugin/dashboard/app/skills/project/[id]/page.tsx +7 -3
  18. package/plugin/dashboard/app/skills/shared/[id]/page.tsx +10 -3
  19. package/plugin/dashboard/lib/claude-settings-file.ts +20 -10
  20. package/plugin/dashboard/lib/reflexio-client.ts +16 -0
  21. package/plugin/dashboard/lib/status.ts +10 -3
  22. package/plugin/dashboard/lib/types.ts +18 -6
  23. package/plugin/hooks/codex-hooks.json +0 -1
  24. package/plugin/opencode/assistant-buffer.ts +108 -0
  25. package/plugin/opencode/dist/assistant-buffer.js +96 -0
  26. package/plugin/opencode/dist/internal.js +12 -0
  27. package/plugin/opencode/dist/payload.js +85 -0
  28. package/plugin/opencode/dist/server.mjs +232 -0
  29. package/plugin/opencode/internal.ts +18 -0
  30. package/plugin/opencode/package.json +3 -0
  31. package/plugin/opencode/payload.ts +90 -0
  32. package/plugin/opencode/server.mts +251 -0
  33. package/plugin/opencode/tsconfig.json +13 -0
  34. package/plugin/pyproject.toml +25 -4
  35. package/plugin/scripts/_lib.sh +5 -1
  36. package/plugin/scripts/backend-service.sh +22 -2
  37. package/plugin/scripts/ensure-plugin-root.sh +4 -4
  38. package/plugin/scripts/hook_entry.sh +1 -1
  39. package/plugin/scripts/opencode-claude-compat +4 -0
  40. package/plugin/scripts/opencode-claude-compat.cmd +3 -0
  41. package/plugin/scripts/opencode-claude-compat.js +225 -0
  42. package/plugin/scripts/smart-install.sh +17 -9
  43. package/plugin/src/README.md +1 -1
  44. package/plugin/src/claude_smart/cli.py +498 -12
  45. package/plugin/src/claude_smart/context_format.py +9 -9
  46. package/plugin/src/claude_smart/cs_cite.py +66 -19
  47. package/plugin/src/claude_smart/env_config.py +12 -4
  48. package/plugin/src/claude_smart/events/session_start.py +26 -7
  49. package/plugin/src/claude_smart/events/stop.py +1 -1
  50. package/plugin/src/claude_smart/ids.py +1 -1
  51. package/plugin/src/claude_smart/reflexio_adapter.py +5 -5
  52. package/plugin/src/claude_smart/runtime.py +7 -1
  53. package/plugin/uv.lock +5 -5
  54. package/plugin/vendor/reflexio/.env.example +54 -30
  55. package/plugin/vendor/reflexio/README.md +17 -11
  56. package/plugin/vendor/reflexio/pyproject.toml +13 -1
  57. package/plugin/vendor/reflexio/reflexio/README.md +4 -1
  58. package/plugin/vendor/reflexio/reflexio/cli/README.md +9 -7
  59. package/plugin/vendor/reflexio/reflexio/cli/__main__.py +10 -1
  60. package/plugin/vendor/reflexio/reflexio/cli/bootstrap_config.py +22 -5
  61. package/plugin/vendor/reflexio/reflexio/cli/commands/interactions.py +34 -4
  62. package/plugin/vendor/reflexio/reflexio/cli/commands/profiles.py +12 -7
  63. package/plugin/vendor/reflexio/reflexio/cli/commands/services.py +13 -6
  64. package/plugin/vendor/reflexio/reflexio/cli/commands/setup_cmd.py +212 -52
  65. package/plugin/vendor/reflexio/reflexio/cli/commands/shortcuts.py +15 -2
  66. package/plugin/vendor/reflexio/reflexio/cli/env_loader.py +292 -22
  67. package/plugin/vendor/reflexio/reflexio/cli/log_format.py +29 -4
  68. package/plugin/vendor/reflexio/reflexio/cli/run_services.py +17 -8
  69. package/plugin/vendor/reflexio/reflexio/cli/stop_services.py +13 -10
  70. package/plugin/vendor/reflexio/reflexio/cli/utils.py +44 -1
  71. package/plugin/vendor/reflexio/reflexio/client/client.py +154 -13
  72. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/README.md +135 -257
  73. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/npm/openclaw-smart/bin/openclaw-smart.js +13 -0
  74. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/npm/openclaw-smart/package.json +15 -0
  75. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/README.md +38 -0
  76. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/index.ts +151 -110
  77. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/openclaw.plugin.json +20 -10
  78. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/package.json +28 -6
  79. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/pyproject.toml +42 -0
  80. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/_lib.sh +371 -0
  81. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/backend-log-runner.sh +33 -0
  82. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/backend-service.sh +271 -0
  83. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/cli.sh +68 -0
  84. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/dashboard-open.sh +15 -0
  85. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/ensure-plugin-root.sh +84 -0
  86. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/hook_entry.sh +106 -0
  87. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/npm-cli.js +219 -0
  88. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/smart-install.sh +269 -0
  89. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/clear-all/SKILL.md +8 -0
  90. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/dashboard/SKILL.md +8 -0
  91. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/learn/SKILL.md +10 -0
  92. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/reflexio/SKILL.md +15 -44
  93. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/restart/SKILL.md +6 -0
  94. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/show/SKILL.md +8 -0
  95. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/cli.py +634 -0
  96. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/context_format.py +224 -0
  97. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/context_inject.py +79 -0
  98. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/__init__.py +0 -0
  99. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/after_tool_call.py +160 -0
  100. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/agent_end.py +187 -0
  101. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/before_prompt_build.py +69 -0
  102. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/before_tool_call.py +30 -0
  103. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/session_end.py +36 -0
  104. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/session_start.py +130 -0
  105. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/hook.py +131 -0
  106. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/ids.py +94 -0
  107. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/internal_call.py +75 -0
  108. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/oc_cite.py +196 -0
  109. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/optimizer_assistant.py +272 -0
  110. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/publish.py +96 -0
  111. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/query_compose.py +66 -0
  112. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/reflexio_adapter.py +336 -0
  113. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/runtime.py +47 -0
  114. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/stall_banner.py +61 -0
  115. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/state.py +323 -0
  116. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/__init__.py +0 -0
  117. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/__init__.py +0 -0
  118. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_e2e_session_loop.py +190 -0
  119. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_publish_to_local_reflexio_integration.py +112 -0
  120. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_recursion_guard_integration.py +86 -0
  121. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_search_inject_integration.py +144 -0
  122. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_cli.py +184 -0
  123. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_after_tool_call.py +142 -0
  124. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_agent_end.py +233 -0
  125. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_before_prompt_build.py +116 -0
  126. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_before_tool_call.py +35 -0
  127. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_session_end.py +47 -0
  128. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_session_start.py +109 -0
  129. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_hook_dispatch.py +117 -0
  130. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_ids.py +41 -0
  131. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_internal_call.py +50 -0
  132. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_oc_cite.py +88 -0
  133. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_publish.py +48 -0
  134. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_query_compose.py +48 -0
  135. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_reflexio_adapter.py +188 -0
  136. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_runtime.py +41 -0
  137. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_state.py +235 -0
  138. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests-ts/__mocks__/plugin-entry-stub.ts +6 -0
  139. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests-ts/test_npm_cli.test.ts +56 -0
  140. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests-ts/test_shim_dispatch.test.ts +171 -0
  141. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tsconfig.build.json +18 -0
  142. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/{tsconfig.json → plugin/tsconfig.json} +2 -2
  143. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/uv.lock +3835 -0
  144. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/vitest.config.ts +18 -0
  145. package/plugin/vendor/reflexio/reflexio/lib/_agent_playbook.py +246 -10
  146. package/plugin/vendor/reflexio/reflexio/lib/_base.py +15 -0
  147. package/plugin/vendor/reflexio/reflexio/lib/_config.py +11 -4
  148. package/plugin/vendor/reflexio/reflexio/lib/_generation.py +17 -5
  149. package/plugin/vendor/reflexio/reflexio/lib/_lineage_parity_readers.py +187 -0
  150. package/plugin/vendor/reflexio/reflexio/lib/_profiles.py +224 -21
  151. package/plugin/vendor/reflexio/reflexio/lib/_reflection.py +1 -1
  152. package/plugin/vendor/reflexio/reflexio/lib/_search.py +52 -25
  153. package/plugin/vendor/reflexio/reflexio/lib/_user_playbook.py +11 -1
  154. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/__init__.py +1 -0
  155. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/entities.py +127 -38
  156. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/enums.py +4 -0
  157. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/governance.py +117 -0
  158. package/plugin/vendor/reflexio/reflexio/models/api_schema/eval_overview_schema.py +64 -41
  159. package/plugin/vendor/reflexio/reflexio/models/api_schema/internal_schema.py +19 -0
  160. package/plugin/vendor/reflexio/reflexio/models/api_schema/pending_tool_call_schema.py +12 -5
  161. package/plugin/vendor/reflexio/reflexio/models/api_schema/retriever_schema.py +97 -3
  162. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/converters.py +5 -1
  163. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/entities.py +5 -1
  164. package/plugin/vendor/reflexio/reflexio/models/config_schema.py +104 -7
  165. package/plugin/vendor/reflexio/reflexio/models/structured_output.py +148 -0
  166. package/plugin/vendor/reflexio/reflexio/server/OVERVIEW.md +3 -3
  167. package/plugin/vendor/reflexio/reflexio/server/README.md +58 -33
  168. package/plugin/vendor/reflexio/reflexio/server/__init__.py +29 -5
  169. package/plugin/vendor/reflexio/reflexio/server/__main__.py +2 -2
  170. package/plugin/vendor/reflexio/reflexio/server/api.py +899 -103
  171. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/precondition_checks.py +7 -0
  172. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/request_context.py +4 -2
  173. package/plugin/vendor/reflexio/reflexio/server/auth.py +90 -0
  174. package/plugin/vendor/reflexio/reflexio/server/billing_meter.py +173 -0
  175. package/plugin/vendor/reflexio/reflexio/server/billing_signals.py +64 -0
  176. package/plugin/vendor/reflexio/reflexio/server/cache/reflexio_cache.py +46 -16
  177. package/plugin/vendor/reflexio/reflexio/server/env_utils.py +65 -0
  178. package/plugin/vendor/reflexio/reflexio/server/extensions.py +213 -0
  179. package/plugin/vendor/reflexio/reflexio/server/llm/embedding_service.py +19 -4
  180. package/plugin/vendor/reflexio/reflexio/server/llm/litellm_client.py +264 -77
  181. package/plugin/vendor/reflexio/reflexio/server/llm/llm_utils.py +69 -7
  182. package/plugin/vendor/reflexio/reflexio/server/llm/model_defaults.py +4 -4
  183. package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_provider.py +1 -1
  184. package/plugin/vendor/reflexio/reflexio/server/llm/providers/embedding_service_provider.py +75 -16
  185. package/plugin/vendor/reflexio/reflexio/server/llm/providers/openclaw_provider.py +280 -0
  186. package/plugin/vendor/reflexio/reflexio/server/llm/rerank/cross_encoder_reranker.py +12 -1
  187. package/plugin/vendor/reflexio/reflexio/server/llm/token_accounting.py +48 -0
  188. package/plugin/vendor/reflexio/reflexio/server/llm/tools.py +107 -17
  189. package/plugin/vendor/reflexio/reflexio/server/operation_limiter.py +360 -4
  190. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.6.0.prompt.md +1 -1
  191. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.7.0.prompt.md +85 -0
  192. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.2.0.prompt.md +1 -1
  193. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.3.0.prompt.md +253 -0
  194. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.2.prompt.md +1 -1
  195. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.3.prompt.md +74 -0
  196. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.3.prompt.md +1 -1
  197. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.3.0.prompt.md +266 -0
  198. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.4.0.prompt.md +278 -0
  199. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.3.0.prompt.md +1 -1
  200. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.4.0.prompt.md +137 -0
  201. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.2.0.prompt.md +1 -1
  202. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.3.0.prompt.md +34 -0
  203. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.0.0.prompt.md +5 -12
  204. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.1.0.prompt.md +5 -12
  205. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.2.0.prompt.md +155 -0
  206. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/tagging/v1.0.0.prompt.md +23 -0
  207. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_manager.py +89 -32
  208. package/plugin/vendor/reflexio/reflexio/server/services/README.md +28 -11
  209. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/README.md +22 -0
  210. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/__init__.py +1 -0
  211. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_constants.py +4 -2
  212. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_utils.py +1 -0
  213. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/components/__init__.py +7 -0
  214. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{agent_success_evaluator.py → components/evaluator.py} +3 -16
  215. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/regen_jobs.py +28 -72
  216. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{group_evaluation_runner.py → runner.py} +12 -10
  217. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{delayed_group_evaluator.py → scheduler.py} +10 -2
  218. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{agent_success_evaluation_service.py → service.py} +36 -1
  219. package/plugin/vendor/reflexio/reflexio/server/services/base_generation_service.py +160 -0
  220. package/plugin/vendor/reflexio/reflexio/server/services/configurator/base_configurator.py +5 -0
  221. package/plugin/vendor/reflexio/reflexio/server/services/deduplication_utils.py +1 -1
  222. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/README.md +9 -0
  223. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/components/__init__.py +0 -0
  224. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{rule_attribution.py → components/rule_attribution.py} +10 -9
  225. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/eval_sampler.py +15 -24
  226. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/service.py +238 -164
  227. package/plugin/vendor/reflexio/reflexio/server/services/extraction/README.md +31 -0
  228. package/plugin/vendor/reflexio/reflexio/server/services/extraction/outcome.py +13 -3
  229. package/plugin/vendor/reflexio/reflexio/server/services/extraction/pending_tool_call_dispatch.py +3 -2
  230. package/plugin/vendor/reflexio/reflexio/server/services/extraction/resumable_agent.py +32 -118
  231. package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_worker.py +47 -16
  232. package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +105 -23
  233. package/plugin/vendor/reflexio/reflexio/server/services/governance/config.py +52 -0
  234. package/plugin/vendor/reflexio/reflexio/server/services/governance/service.py +378 -0
  235. package/plugin/vendor/reflexio/reflexio/server/services/governance/subject_refs.py +34 -0
  236. package/plugin/vendor/reflexio/reflexio/server/services/lineage/__init__.py +0 -0
  237. package/plugin/vendor/reflexio/reflexio/server/services/lineage/gc_scheduler.py +219 -0
  238. package/plugin/vendor/reflexio/reflexio/server/services/lineage/resolve.py +98 -0
  239. package/plugin/vendor/reflexio/reflexio/server/services/operation_state_utils.py +26 -0
  240. package/plugin/vendor/reflexio/reflexio/server/services/playbook/README.md +18 -11
  241. package/plugin/vendor/reflexio/reflexio/server/services/playbook/aggregation_prompt_processing.py +100 -0
  242. package/plugin/vendor/reflexio/reflexio/server/services/playbook/components/__init__.py +5 -0
  243. package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_aggregator.py → components/aggregator.py} +334 -178
  244. package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_consolidator.py → components/consolidator.py} +168 -62
  245. package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_extractor.py → components/extractor.py} +5 -1
  246. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_edit_apply.py +74 -0
  247. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_utils.py +33 -3
  248. package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_generation_service.py → service.py} +121 -19
  249. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/README.md +10 -0
  250. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/models.py +2 -1
  251. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/optimizer.py +178 -30
  252. package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/README.md +9 -0
  253. package/plugin/vendor/reflexio/reflexio/server/services/profile/components/__init__.py +17 -0
  254. package/plugin/vendor/reflexio/reflexio/server/services/profile/{profile_deduplicator.py → components/consolidator.py} +7 -6
  255. package/plugin/vendor/reflexio/reflexio/server/services/profile/{profile_extractor.py → components/extractor.py} +31 -22
  256. package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service_utils.py +6 -13
  257. package/plugin/vendor/reflexio/reflexio/server/services/profile/{profile_generation_service.py → service.py} +32 -50
  258. package/plugin/vendor/reflexio/reflexio/server/services/reflection/__init__.py +4 -8
  259. package/plugin/vendor/reflexio/reflexio/server/services/reflection/components/__init__.py +7 -0
  260. package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service_utils.py +12 -1
  261. package/plugin/vendor/reflexio/reflexio/server/services/reflection/{reflection_service.py → service.py} +36 -16
  262. package/plugin/vendor/reflexio/reflexio/server/services/retrieval/recency.py +211 -0
  263. package/plugin/vendor/reflexio/reflexio/server/services/retrieval/relevance_floor.py +99 -6
  264. package/plugin/vendor/reflexio/reflexio/server/services/service_utils.py +36 -1
  265. package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/README.md +8 -0
  266. package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/outcome.py +1 -2
  267. package/plugin/vendor/reflexio/reflexio/server/services/storage/error.py +31 -0
  268. package/plugin/vendor/reflexio/reflexio/server/services/storage/governance_validation.py +681 -0
  269. package/plugin/vendor/reflexio/reflexio/server/services/storage/retention.py +9 -9
  270. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/__init__.py +16 -2
  271. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_agent_run.py +4 -1
  272. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_base.py +644 -197
  273. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_extras.py +106 -119
  274. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_governance.py +1965 -0
  275. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_lineage.py +630 -0
  276. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_operations.py +38 -6
  277. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_playbook.py +31 -1369
  278. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +756 -210
  279. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_requests.py +148 -34
  280. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_shadow_verdicts.py +23 -9
  281. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_stall_state.py +5 -2
  282. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/__init__.py +13 -0
  283. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_agent.py +952 -0
  284. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_eval_results.py +189 -0
  285. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_optimization.py +247 -0
  286. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_source_linkage.py +145 -0
  287. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_user.py +838 -0
  288. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/__init__.py +150 -23
  289. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_agent_run.py +2 -8
  290. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_base.py +5 -0
  291. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_extras.py +40 -57
  292. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_governance.py +148 -0
  293. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_lineage.py +215 -0
  294. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_operations.py +20 -0
  295. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_playbook.py +4 -677
  296. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_profiles.py +134 -1
  297. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_requests.py +62 -0
  298. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_retrieval_log.py +51 -0
  299. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_shadow_verdicts.py +17 -0
  300. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/__init__.py +13 -0
  301. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_agent.py +365 -0
  302. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_eval_results.py +124 -0
  303. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_optimization.py +85 -0
  304. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_source_linkage.py +47 -0
  305. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_user.py +333 -0
  306. package/plugin/vendor/reflexio/reflexio/server/services/tagging/README.md +8 -0
  307. package/plugin/vendor/reflexio/reflexio/server/services/tagging/__init__.py +1 -0
  308. package/plugin/vendor/reflexio/reflexio/server/services/tagging/service.py +200 -0
  309. package/plugin/vendor/reflexio/reflexio/server/services/tagging/tagging_scheduler.py +149 -0
  310. package/plugin/vendor/reflexio/reflexio/server/services/unified_search_service.py +372 -34
  311. package/plugin/vendor/reflexio/reflexio/server/site_var/README.md +2 -1
  312. package/plugin/vendor/reflexio/reflexio/server/site_var/feature_flags.py +120 -1
  313. package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/feature_flags.json +4 -0
  314. package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/search_settings.json +5 -0
  315. package/plugin/vendor/reflexio/reflexio/server/tracing.py +30 -0
  316. package/plugin/vendor/reflexio/reflexio/server/usage_metrics.py +18 -0
  317. package/plugin/vendor/reflexio/reflexio/test_support/llm_mock.py +61 -26
  318. package/plugin/vendor/reflexio/reflexio/test_support/llm_model_registry.py +41 -4
  319. package/scripts/setup-claude-smart.sh +8 -3
  320. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/TESTING.md +0 -517
  321. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/hook/handler.js +0 -473
  322. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package-lock.json +0 -2156
  323. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package.json +0 -18
  324. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/handler.ts +0 -241
  325. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/setup.ts +0 -140
  326. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/publish.ts +0 -113
  327. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/search.ts +0 -52
  328. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/server.ts +0 -103
  329. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/sqlite-buffer.ts +0 -156
  330. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/user-id.ts +0 -134
  331. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/rules/reflexio.md +0 -24
  332. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/publish_clawhub.sh +0 -278
  333. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/references/HOOK.md +0 -164
  334. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/install.sh +0 -36
  335. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/uninstall.sh +0 -35
  336. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/publish.test.ts +0 -27
  337. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/search.test.ts +0 -31
  338. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/server.test.ts +0 -42
  339. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/setup.test.ts +0 -49
  340. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/sqlite-buffer.test.ts +0 -91
  341. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/user-id.test.ts +0 -50
  342. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/vitest.config.ts +0 -13
  343. package/plugin/vendor/reflexio/reflexio/server/_auth.py +0 -25
  344. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/group_aggregation.py +0 -192
  345. package/plugin/vendor/reflexio/reflexio/server/services/extraction/invariants.py +0 -303
  346. package/plugin/vendor/reflexio/reflexio/server/services/extraction/plan.py +0 -138
  347. package/plugin/vendor/reflexio/reflexio/server/services/extraction/tools.py +0 -1125
  348. /package/plugin/vendor/reflexio/reflexio/integrations/{__init__.py → openclaw/plugin/src/openclaw_smart/__init__.py} +0 -0
  349. /package/plugin/vendor/reflexio/reflexio/integrations/openclaw/{types → plugin/types}/openclaw.d.ts +0 -0
  350. /package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{distribution.py → components/distribution.py} +0 -0
  351. /package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{hero_state.py → components/hero_state.py} +0 -0
  352. /package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{shadow_aggregation.py → components/shadow_aggregation.py} +0 -0
  353. /package/plugin/vendor/reflexio/reflexio/server/services/reflection/{reflection_extractor.py → components/extractor.py} +0 -0
@@ -23,20 +23,36 @@ from ._agent_run import (
23
23
  )
24
24
  from ._base import BaseStorageCore, matches_status_filter
25
25
  from ._extras import ExtrasMixin
26
+ from ._governance import GovernanceMixin
27
+ from ._lineage import EntityType, LineageEventMixin
26
28
  from ._operations import OperationMixin
27
- from ._playbook import PlaybookMixin
28
29
  from ._profiles import ProfileMixin
29
30
  from ._requests import RequestMixin
31
+ from ._retrieval_log import RetrievalLogMixin
30
32
  from ._shadow_verdicts import ShadowVerdictsMixin
31
33
  from ._share_links import ShareLinkMixin
32
34
  from ._stall_state import StallStateMixin
35
+ from .playbook import (
36
+ AgentEvaluationResultStoreMixin,
37
+ AgentPlaybookStoreMixin,
38
+ OptimizationJobStoreMixin,
39
+ PlaybookSourceLinkageMixin,
40
+ UserPlaybookStoreMixin,
41
+ )
33
42
 
34
43
 
35
44
  class BaseStorage(
36
45
  AgentRunMixin,
37
46
  ProfileMixin,
38
47
  RequestMixin,
39
- PlaybookMixin,
48
+ AgentPlaybookStoreMixin,
49
+ UserPlaybookStoreMixin,
50
+ PlaybookSourceLinkageMixin,
51
+ OptimizationJobStoreMixin,
52
+ AgentEvaluationResultStoreMixin,
53
+ RetrievalLogMixin,
54
+ GovernanceMixin,
55
+ LineageEventMixin,
40
56
  OperationMixin,
41
57
  ExtrasMixin,
42
58
  ShareLinkMixin,
@@ -46,6 +62,65 @@ class BaseStorage(
46
62
  ):
47
63
  """Base class for storage."""
48
64
 
65
+ def _is_lineage_tombstone(self, entity_type: EntityType, entity_id: str) -> bool:
66
+ """Return True when the entity row is a tombstone (merged_into or superseded_by set).
67
+
68
+ Uses the portable ``include_tombstones=True`` getters so the check
69
+ works for every backend without backend-specific SQL.
70
+
71
+ Args:
72
+ entity_type (EntityType): ``"profile"`` or ``"user_playbook"``.
73
+ entity_id (str): The entity's primary key as a string.
74
+
75
+ Returns:
76
+ bool: True if the row has ``merged_into`` or ``superseded_by`` set.
77
+ """
78
+ if entity_type == "profile":
79
+ row = self.get_profile_by_id(entity_id, include_tombstones=True)
80
+ if row is None:
81
+ return False
82
+ return bool(row.merged_into or row.superseded_by)
83
+ if entity_type == "user_playbook":
84
+ row = self.get_user_playbook_by_id(int(entity_id), include_tombstones=True)
85
+ if row is None:
86
+ return False
87
+ return bool(row.merged_into or row.superseded_by)
88
+ return False
89
+
90
+ def _partition_purge_vs_delete(
91
+ self, entity_type: EntityType, ids: list[str]
92
+ ) -> tuple[list[str], list[str]]:
93
+ """Split entity ids into purge-eligible and hard-delete sets.
94
+
95
+ An entity is purge-eligible when it is a tombstone (``merged_into`` or
96
+ ``superseded_by`` is set) **or** is pointed to by another row
97
+ (``has_inbound_lineage_refs`` returns True). All other ids go to the
98
+ hard-delete set.
99
+
100
+ Uses only portable storage reads so this helper works for every
101
+ backend (SQLite, Supabase, Postgres). Callers that need
102
+ backend-specific efficiency may override ``clear_user_data`` instead.
103
+
104
+ Args:
105
+ entity_type (EntityType): ``"profile"`` or ``"user_playbook"``.
106
+ ids (list[str]): Entity primary keys as strings.
107
+
108
+ Returns:
109
+ tuple[list[str], list[str]]: ``(purge_ids, delete_ids)`` where
110
+ ``purge_ids`` are content-purge candidates and ``delete_ids``
111
+ are safe to hard-delete.
112
+ """
113
+ purge_ids: list[str] = []
114
+ delete_ids: list[str] = []
115
+ for eid in ids:
116
+ if self._is_lineage_tombstone(
117
+ entity_type, eid
118
+ ) or self.has_inbound_lineage_refs(entity_type=entity_type, entity_id=eid):
119
+ purge_ids.append(eid)
120
+ else:
121
+ delete_ids.append(eid)
122
+ return purge_ids, delete_ids
123
+
49
124
  def clear_user_data(self, user_id: str) -> dict[str, int]:
50
125
  """Delete all rows scoped to a single ``user_id``.
51
126
 
@@ -57,38 +132,72 @@ class BaseStorage(
57
132
  parallel tasks without one task's clear-all nuking another
58
133
  in-flight task's rows.
59
134
 
135
+ **Lineage-aware erasure:** rows that are tombstones (``merged_into``
136
+ or ``superseded_by`` is set) *or* are pointed to by another row
137
+ (``has_inbound_lineage_refs`` returns True) are content-purged
138
+ (skeleton kept, body blanked) rather than hard-deleted. Standalone
139
+ rows with no lineage involvement are hard-deleted.
140
+
60
141
  The default implementation composes existing per-user / by-ids
61
142
  primitives so any backend that implements those (sqlite, supabase,
62
143
  postgres, ...) gets correct behaviour for free.
63
144
  Subclasses MAY override for atomic / transactional efficiency.
64
145
 
146
+ **Atomicity note (default path only):** this default implementation is
147
+ NOT wrapped in a single transaction. Each ``purge_content`` call commits
148
+ independently, so a crash mid-erasure may leave some purge-eligible rows
149
+ with PII intact until ``clear_user_data`` is re-invoked. The call is
150
+ idempotent — re-invoking it is safe and will finish the erasure.
151
+
65
152
  Args:
66
153
  user_id (str): The user id whose rows should be deleted.
67
154
 
68
155
  Returns:
69
- dict[str, int]: Per-entity deletion counts with keys
70
- ``interactions``, ``user_playbooks``, ``profiles``, and
71
- ``requests``. Counts reflect pre-deletion totals for the
72
- user (i.e. how many rows existed for that user).
156
+ dict[str, int]: Per-entity counts with keys ``interactions``,
157
+ ``user_playbooks``, ``profiles``, ``requests``,
158
+ ``purged_profiles``, and ``purged_user_playbooks``.
159
+ ``profiles`` and ``user_playbooks`` reflect hard-deleted
160
+ counts; purged rows are counted separately.
73
161
  """
74
162
  interaction_count = len(self.get_user_interaction(user_id))
75
163
 
76
- # Snapshot user_playbook ids for the user so we can both count
77
- # and delete via the existing bulk-by-ids primitive (no per-user
78
- # playbook delete primitive exists at the mixin level).
79
- user_playbook_ids = [
80
- up.user_playbook_id
164
+ # All statuses a user's row can have including tombstones (SUPERSEDED,
165
+ # MERGED). Erasure MUST reach every row the user owns regardless of
166
+ # status; the old filter excluded tombstones, leaving them in the DB
167
+ # after clear_user_data (GDPR regression).
168
+ _all_statuses: list[Status | None] = [
169
+ None, # CURRENT
170
+ Status.ARCHIVED,
171
+ Status.PENDING,
172
+ Status.ARCHIVE_IN_PROGRESS,
173
+ Status.SUPERSEDED,
174
+ Status.MERGED,
175
+ ]
176
+
177
+ # Snapshot user_playbook ids for the user and partition into
178
+ # purge vs delete sets.
179
+ raw_upb_ids = [
180
+ str(up.user_playbook_id)
81
181
  for up in self.get_user_playbooks(
82
182
  user_id=user_id,
83
183
  limit=1_000_000,
84
- status_filter=[None, Status.ARCHIVED, Status.PENDING],
184
+ status_filter=_all_statuses,
85
185
  )
86
186
  if up.user_playbook_id is not None
87
187
  ]
88
- profile_count = len(
89
- self.get_user_profile(
90
- user_id, status_filter=[None, Status.ARCHIVED, Status.PENDING]
91
- )
188
+ purge_upb_ids, delete_upb_ids = self._partition_purge_vs_delete(
189
+ "user_playbook", raw_upb_ids
190
+ )
191
+
192
+ # Snapshot profile ids for the user and partition into
193
+ # purge vs delete sets.
194
+ raw_profile_ids = [
195
+ p.profile_id
196
+ for p in self.get_user_profile(user_id, status_filter=_all_statuses)
197
+ if p.profile_id is not None
198
+ ]
199
+ purge_profile_ids, delete_profile_ids = self._partition_purge_vs_delete(
200
+ "profile", raw_profile_ids
92
201
  )
93
202
 
94
203
  # Snapshot request ids for the user so we can both count and
@@ -103,30 +212,43 @@ class BaseStorage(
103
212
  ]
104
213
 
105
214
  # Delete in dependency-safe order: interactions first (they
106
- # reference requests), then user playbooks (also reference
107
- # requests), then profiles, then the requests themselves.
215
+ # reference requests), then user playbooks, then profiles, then
216
+ # requests. Only the delete-sets are hard-deleted; purge-sets are
217
+ # content-purged below.
108
218
  self.delete_all_interactions_for_user(user_id)
109
219
  deleted_user_playbooks = (
110
- self.delete_user_playbooks_by_ids(user_playbook_ids)
111
- if user_playbook_ids
220
+ self.delete_user_playbooks_by_ids([int(i) for i in delete_upb_ids])
221
+ if delete_upb_ids
112
222
  else 0
113
223
  )
114
- self.delete_all_profiles_for_user(user_id)
224
+ deleted_profiles = (
225
+ self.delete_profiles_by_ids(delete_profile_ids) if delete_profile_ids else 0
226
+ )
115
227
  deleted_requests = (
116
228
  self.delete_requests_by_ids(request_ids) if request_ids else 0
117
229
  )
118
230
 
231
+ # Content-purge the purge-eligible rows after the hard-deletes.
232
+ for pid in purge_profile_ids:
233
+ self.purge_content(entity_type="profile", entity_id=pid)
234
+ for upid in purge_upb_ids:
235
+ self.purge_content(entity_type="user_playbook", entity_id=upid)
236
+
119
237
  return {
120
238
  "interactions": interaction_count,
121
239
  "user_playbooks": deleted_user_playbooks,
122
- "profiles": profile_count,
240
+ "profiles": deleted_profiles,
123
241
  "requests": deleted_requests,
242
+ "purged_profiles": len(purge_profile_ids),
243
+ "purged_user_playbooks": len(purge_upb_ids),
124
244
  }
125
245
 
126
246
 
127
247
  __all__ = [
128
248
  "AgentBinding",
129
249
  "AgentRunMixin",
250
+ "EntityType",
251
+ "LineageEventMixin",
130
252
  "AgentRunRecord",
131
253
  "AgentRunStatus",
132
254
  "BaseStorage",
@@ -134,7 +256,12 @@ __all__ = [
134
256
  "PendingToolCallRecord",
135
257
  "PendingToolCallStatus",
136
258
  "PendingToolCallUpsertResult",
137
- "PlaybookMixin",
259
+ "AgentEvaluationResultStoreMixin",
260
+ "AgentPlaybookStoreMixin",
261
+ "OptimizationJobStoreMixin",
262
+ "PlaybookSourceLinkageMixin",
263
+ "UserPlaybookStoreMixin",
264
+ "RetrievalLogMixin",
138
265
  "PriorAnswerMatch",
139
266
  "RunToolDependencyKind",
140
267
  "RunToolDependencyRecord",
@@ -11,6 +11,8 @@ from datetime import datetime
11
11
  from enum import StrEnum
12
12
  from typing import Any
13
13
 
14
+ from reflexio.models.api_schema.pending_tool_call_schema import PendingToolCallStatus
15
+
14
16
  _WHITESPACE_RE = re.compile(r"\s+")
15
17
 
16
18
 
@@ -28,14 +30,6 @@ class AgentRunStatus(StrEnum):
28
30
  CANCELLED = "cancelled"
29
31
 
30
32
 
31
- class PendingToolCallStatus(StrEnum):
32
- PENDING = "pending"
33
- RESOLVED = "resolved"
34
- EXPIRED = "expired"
35
- SUPERSEDED = "superseded"
36
- CANCELLED = "cancelled"
37
-
38
-
39
33
  NOT_APPLICABLE_ANSWER = "User does not have information about this question."
40
34
 
41
35
 
@@ -40,6 +40,11 @@ class BaseStorageCore(ABC): # noqa: B024
40
40
  # Capability flag — backends that implement `_get_embedding` set this to True.
41
41
  supports_embedding: ClassVar[bool] = False
42
42
 
43
+ # Capability flag — backends that can serve every unified-search arm in a
44
+ # single database round trip expose a `unified_hybrid_search` method and
45
+ # set this to True (see reflexio.server.services.unified_search_service).
46
+ supports_unified_hybrid_search: ClassVar[bool] = False
47
+
43
48
  def __init__(self, org_id: str, base_dir: str | None = None) -> None:
44
49
  self.org_id = org_id
45
50
  if base_dir is None:
@@ -6,14 +6,13 @@ from reflexio.models.api_schema.braintrust_schema import (
6
6
  )
7
7
  from reflexio.models.api_schema.domain import (
8
8
  Interaction,
9
- PlaybookAggregationChangeLog,
10
- ProfileChangeLog,
11
9
  )
10
+ from reflexio.models.api_schema.internal_schema import SessionCitation
12
11
  from reflexio.models.api_schema.retriever_schema import PlaybookApplicationStat
13
12
 
14
13
 
15
14
  class ExtrasMixin:
16
- """Mixin for dashboard, profile change logs, playbook aggregation change logs, and misc methods."""
15
+ """Mixin for dashboard, profile change logs, and misc methods."""
17
16
 
18
17
  # ==============================
19
18
  # Dashboard methods
@@ -30,10 +29,10 @@ class ExtrasMixin:
30
29
  dict: Dictionary containing:
31
30
  - current_period: Stats for the current period (days_back)
32
31
  - previous_period: Stats for the previous period (for trend calculation)
33
- - interactions_time_series: List of time series data points (raw, ungrouped)
34
- - profiles_time_series: List of time series data points (raw, ungrouped)
35
- - playbooks_time_series: List of time series data points (raw, ungrouped)
36
- - evaluations_time_series: List of time series data points (raw, ungrouped)
32
+ - interactions_time_series: Daily bucketed interaction counts
33
+ - profiles_time_series: Daily bucketed profile counts
34
+ - playbooks_time_series: Daily bucketed playbook counts
35
+ - evaluations_time_series: Daily bucketed success rates with optional counts
37
36
  """
38
37
  raise NotImplementedError
39
38
 
@@ -72,56 +71,6 @@ class ExtrasMixin:
72
71
  """
73
72
  raise NotImplementedError
74
73
 
75
- # ==============================
76
- # Profile Change Log methods
77
- # ==============================
78
-
79
- @abstractmethod
80
- def add_profile_change_log(self, profile_change_log: ProfileChangeLog) -> None:
81
- """Add a profile change log entry."""
82
- raise NotImplementedError
83
-
84
- @abstractmethod
85
- def get_profile_change_logs(self, limit: int = 100) -> list[ProfileChangeLog]:
86
- """Get profile change logs for an organization."""
87
- raise NotImplementedError
88
-
89
- @abstractmethod
90
- def delete_profile_change_log_for_user(self, user_id: str) -> None:
91
- """Delete all profile change logs for a user."""
92
- raise NotImplementedError
93
-
94
- @abstractmethod
95
- def delete_all_profile_change_logs(self) -> None:
96
- """Delete all profile change logs."""
97
- raise NotImplementedError
98
-
99
- # ==============================
100
- # Playbook Aggregation Change Log methods
101
- # ==============================
102
-
103
- @abstractmethod
104
- def add_playbook_aggregation_change_log(
105
- self, change_log: PlaybookAggregationChangeLog
106
- ) -> None:
107
- """Add a playbook aggregation change log entry."""
108
- raise NotImplementedError
109
-
110
- @abstractmethod
111
- def get_playbook_aggregation_change_logs(
112
- self,
113
- playbook_name: str,
114
- agent_version: str,
115
- limit: int = 100,
116
- ) -> list[PlaybookAggregationChangeLog]:
117
- """Get playbook aggregation change logs filtered by playbook_name and agent_version."""
118
- raise NotImplementedError
119
-
120
- @abstractmethod
121
- def delete_all_playbook_aggregation_change_logs(self) -> None:
122
- """Delete all playbook aggregation change logs."""
123
- raise NotImplementedError
124
-
125
74
  # ==============================
126
75
  # Misc methods
127
76
  # ==============================
@@ -171,6 +120,40 @@ class ExtrasMixin:
171
120
  """
172
121
  return []
173
122
 
123
+ def get_citations_by_session_ids(
124
+ self,
125
+ session_ids: list[str],
126
+ ) -> list[SessionCitation]:
127
+ """Return rule/profile citations for the requested sessions.
128
+
129
+ Default implementation uses ``get_interactions_by_session`` so legacy
130
+ backends keep working. SQL backends should override with a bulk
131
+ request/interactions join.
132
+ """
133
+ out: list[SessionCitation] = []
134
+ for session_id in set(session_ids):
135
+ for interaction in self.get_interactions_by_session(session_id):
136
+ for cite in getattr(interaction, "citations", []) or []:
137
+ if isinstance(cite, dict):
138
+ kind = cite.get("kind")
139
+ real_id = cite.get("real_id")
140
+ title = cite.get("title") or ""
141
+ else:
142
+ kind = getattr(cite, "kind", None)
143
+ real_id = getattr(cite, "real_id", None)
144
+ title = getattr(cite, "title", "") or ""
145
+ if kind and real_id:
146
+ out.append(
147
+ SessionCitation(
148
+ user_id="",
149
+ session_id=session_id,
150
+ kind=str(kind),
151
+ real_id=str(real_id),
152
+ title=str(title),
153
+ )
154
+ )
155
+ return out
156
+
174
157
  # ==============================
175
158
  # Braintrust connector (default no-ops; backends override)
176
159
  # ==============================
@@ -0,0 +1,148 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABC, abstractmethod
4
+ from typing import Literal
5
+
6
+ from reflexio.models.api_schema.domain.governance import (
7
+ AuditEvent,
8
+ PurgeOperation,
9
+ PurgeOperationTarget,
10
+ SubjectWriteBarrier,
11
+ )
12
+ from reflexio.models.config_schema import GovernanceRetentionConfig
13
+
14
+
15
+ class GovernanceMixin(ABC):
16
+ """Mixin for backend-neutral governance storage primitives."""
17
+
18
+ @abstractmethod
19
+ def append_audit_event(self, event: AuditEvent) -> bool:
20
+ raise NotImplementedError
21
+
22
+ @abstractmethod
23
+ def list_audit_events(
24
+ self, subject_ref: str | None = None, *, org_id: str | None = None
25
+ ) -> list[AuditEvent]:
26
+ raise NotImplementedError
27
+
28
+ @abstractmethod
29
+ def begin_purge_operation(
30
+ self,
31
+ purge_id: str,
32
+ idempotency_key: str,
33
+ operation_type: Literal["user_erasure", "org_purge"],
34
+ scope_type: Literal["user", "org"],
35
+ subject_ref: str | None,
36
+ request_ref: str,
37
+ ) -> PurgeOperation:
38
+ raise NotImplementedError
39
+
40
+ @abstractmethod
41
+ def record_purge_target(
42
+ self,
43
+ purge_id: str,
44
+ target_name: str,
45
+ phase: str,
46
+ status: Literal["pending", "running", "failed", "complete"],
47
+ target_ref: str = "",
48
+ detail: dict[str, object] | None = None,
49
+ deleted_count: int = 0,
50
+ error_detail: str | None = None,
51
+ ) -> None:
52
+ raise NotImplementedError
53
+
54
+ @abstractmethod
55
+ def list_purge_targets(
56
+ self, purge_id: str, phase: str | None = None
57
+ ) -> list[PurgeOperationTarget]:
58
+ raise NotImplementedError
59
+
60
+ @abstractmethod
61
+ def purge_targets_prepared(self, purge_id: str) -> bool:
62
+ raise NotImplementedError
63
+
64
+ @abstractmethod
65
+ def prepare_governance_erase_targets(
66
+ self,
67
+ purge_id: str,
68
+ user_id: str,
69
+ owned_user_playbook_ids: set[int] | None = None,
70
+ ) -> None:
71
+ raise NotImplementedError
72
+
73
+ @abstractmethod
74
+ def hide_governance_agent_playbooks_for_rebuild(self, purge_id: str) -> list[int]:
75
+ raise NotImplementedError
76
+
77
+ @abstractmethod
78
+ def apply_governance_user_data_delete(
79
+ self, purge_id: str, user_id: str
80
+ ) -> dict[str, int]:
81
+ raise NotImplementedError
82
+
83
+ @abstractmethod
84
+ def apply_governance_agent_playbook_rebuild(
85
+ self,
86
+ purge_id: str,
87
+ agent_playbook_id: int,
88
+ remaining_source_windows: list[dict[str, object]],
89
+ content: str | None,
90
+ trigger: str | None,
91
+ rationale: str | None,
92
+ blocking_issue: dict[str, object] | None,
93
+ expanded_terms: str | None,
94
+ tags: list[str] | None,
95
+ ) -> None:
96
+ raise NotImplementedError
97
+
98
+ @abstractmethod
99
+ def complete_purge_operation_with_audit(
100
+ self, purge_id: str, audit_event: AuditEvent
101
+ ) -> PurgeOperation:
102
+ raise NotImplementedError
103
+
104
+ @abstractmethod
105
+ def begin_subject_erasure_barrier(
106
+ self, subject_ref: str, purge_id: str
107
+ ) -> SubjectWriteBarrier:
108
+ raise NotImplementedError
109
+
110
+ @abstractmethod
111
+ def assert_subject_writable(self, subject_ref: str) -> None:
112
+ raise NotImplementedError
113
+
114
+ @abstractmethod
115
+ def complete_subject_erasure_barrier_after_empty_check(
116
+ self, purge_id: str, audit_event: AuditEvent
117
+ ) -> PurgeOperation:
118
+ raise NotImplementedError
119
+
120
+ @abstractmethod
121
+ def fail_subject_erasure_barrier(
122
+ self,
123
+ subject_ref: str,
124
+ purge_id: str,
125
+ error_code: str,
126
+ error_detail: str,
127
+ ) -> SubjectWriteBarrier:
128
+ raise NotImplementedError
129
+
130
+ @abstractmethod
131
+ def get_subject_write_barrier(
132
+ self, subject_ref: str
133
+ ) -> SubjectWriteBarrier | None:
134
+ raise NotImplementedError
135
+
136
+ @abstractmethod
137
+ def fail_purge_operation(
138
+ self, purge_id: str, error_code: str, error_detail: str
139
+ ) -> PurgeOperation:
140
+ raise NotImplementedError
141
+
142
+ @abstractmethod
143
+ def get_purge_operation(self, purge_id: str) -> PurgeOperation:
144
+ raise NotImplementedError
145
+
146
+ @abstractmethod
147
+ def gc_governance_retention(self, *, config: GovernanceRetentionConfig) -> int:
148
+ raise NotImplementedError