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
@@ -118,6 +118,11 @@ __all__ = [
118
118
  "ShareLink",
119
119
  "AdminInvalidateCacheRequest",
120
120
  "AdminInvalidateCacheResponse",
121
+ "PlaybookRetrievalLogItem",
122
+ "PlaybookRetrievalLog",
123
+ "LineageEvent",
124
+ "LineageContext",
125
+ "RecordRef",
121
126
  ]
122
127
 
123
128
  # ===============================
@@ -179,11 +184,7 @@ class Request(BaseModel):
179
184
  """A user-issued request that begins or continues a session.
180
185
 
181
186
  A Request is the unit of work the agent reacts to. Multiple Requests
182
- share a ``session_id`` to form a multi-turn session. The optional
183
- ``metadata`` dict carries per-request key/value annotations stamped by
184
- customer integration code — distinct from ``playbook_metadata`` (a
185
- JSON-encoded string) used by ``Playbook``-family entities elsewhere in
186
- this module.
187
+ share a ``session_id`` to form a multi-turn session.
187
188
 
188
189
  Attributes:
189
190
  request_id (str): Unique identifier for this request.
@@ -192,22 +193,10 @@ class Request(BaseModel):
192
193
  to the current UTC time.
193
194
  source (str): Free-form origin tag (integration name, etc.).
194
195
  agent_version (str): The agent version that handled this request.
195
- session_id (str | None): Session this request belongs to, or None
196
- if the request is not part of a multi-turn session.
197
- metadata (dict[str, Any]): Free-form per-request annotations.
198
- Always a dict — never None. Conventional keys:
199
-
200
- - ``reflexio_retrieval_enabled`` (bool): F2 group-by signal;
201
- customer integration code stamps this to indicate whether
202
- Reflexio retrieval was active for the session. Read by the
203
- ``/api/get_evaluation_overview`` aggregator from the FIRST
204
- request of each session for sticky group assignment.
205
-
206
- Distinct from ``playbook_metadata`` on ``Playbook``-family
207
- entities (which is a JSON-encoded string, not a dict).
208
- On-the-wire serialization assumes JSON-encodable values;
209
- non-JSON values like ``datetime`` or ``set`` will fail at
210
- the storage / API boundary.
196
+ session_id (str): Non-empty session this request belongs to.
197
+ evaluation_only (bool): Whether this request is stored for
198
+ session-level evaluation only and must be excluded from
199
+ profile/playbook learning windows.
211
200
  """
212
201
 
213
202
  request_id: str
@@ -215,8 +204,8 @@ class Request(BaseModel):
215
204
  created_at: int = Field(default_factory=lambda: int(datetime.now(UTC).timestamp()))
216
205
  source: str = ""
217
206
  agent_version: str = ""
218
- session_id: str | None = None
219
- metadata: dict[str, Any] = Field(default_factory=dict)
207
+ session_id: NonEmptyStr
208
+ evaluation_only: bool = False
220
209
 
221
210
 
222
211
  # information about the user profile generated from the user interaction
@@ -237,10 +226,14 @@ class UserProfile(BaseModel):
237
226
  None # Retained provenance data column (merged on dedup); new profiles write None.
238
227
  )
239
228
  expanded_terms: str | None = None
229
+ tags: list[str] | None = None # None = not yet tagged; [] = tagged, no match
230
+ source_interaction_ids: list[int] = Field(default_factory=list)
240
231
  embedding: EmbeddingVector = []
241
232
  source_span: str | None = None
242
233
  notes: str | None = None
243
234
  reader_angle: str | None = None
235
+ merged_into: str | None = None
236
+ superseded_by: str | None = None
244
237
 
245
238
 
246
239
  # user playbook for agents
@@ -261,10 +254,13 @@ class UserPlaybook(BaseModel):
261
254
  source: str | None = None # source of the interaction that generated this playbook
262
255
  source_interaction_ids: list[int] = Field(default_factory=list)
263
256
  expanded_terms: str | None = None
257
+ tags: list[str] | None = None # None = not yet tagged; [] = tagged, no match
264
258
  embedding: EmbeddingVector = []
265
259
  source_span: str | None = None
266
260
  notes: str | None = None
267
261
  reader_angle: str | None = None
262
+ merged_into: int | None = None
263
+ superseded_by: int | None = None
268
264
 
269
265
 
270
266
  class ProfileChangeLog(BaseModel):
@@ -274,7 +270,6 @@ class ProfileChangeLog(BaseModel):
274
270
  created_at: int = Field(default_factory=lambda: int(datetime.now(UTC).timestamp()))
275
271
  added_profiles: list[UserProfile]
276
272
  removed_profiles: list[UserProfile]
277
- mentioned_profiles: list[UserProfile]
278
273
 
279
274
 
280
275
  class AgentPlaybook(BaseModel):
@@ -289,10 +284,13 @@ class AgentPlaybook(BaseModel):
289
284
  playbook_status: PlaybookStatus = PlaybookStatus.PENDING
290
285
  playbook_metadata: str = ""
291
286
  expanded_terms: str | None = None
287
+ tags: list[str] | None = None # None = not yet tagged; [] = tagged, no match
292
288
  embedding: EmbeddingVector = []
293
289
  status: Status | None = (
294
290
  None # used for tracking intermediate states during playbook aggregation. Status.ARCHIVED for playbooks during aggregation process, None for current playbooks
295
291
  )
292
+ merged_into: int | None = None
293
+ superseded_by: int | None = None
296
294
 
297
295
 
298
296
  class PlaybookOptimizationJob(BaseModel):
@@ -330,6 +328,7 @@ class PlaybookOptimizationCandidate(BaseModel):
330
328
  parent_candidate_ids: list[int] = Field(default_factory=list)
331
329
  aggregate_score: float | None = None
332
330
  is_winner: bool = False
331
+ metadata_json: str = "{}"
333
332
  created_at: int = Field(default_factory=lambda: int(datetime.now(UTC).timestamp()))
334
333
 
335
334
 
@@ -384,6 +383,7 @@ class AgentPlaybookSourceWindow(BaseModel):
384
383
 
385
384
  class AgentSuccessEvaluationResult(BaseModel):
386
385
  result_id: int = 0
386
+ user_id: str = ""
387
387
  agent_version: str
388
388
  session_id: str
389
389
  is_success: bool
@@ -398,6 +398,100 @@ class AgentSuccessEvaluationResult(BaseModel):
398
398
  embedding: EmbeddingVector = []
399
399
 
400
400
 
401
+ class PlaybookRetrievalLogItem(BaseModel):
402
+ """One retrieved agent playbook plus the serve-time attribution snapshot."""
403
+
404
+ retrieval_log_item_id: int = 0
405
+ retrieval_log_id: int = 0
406
+ ordinal: int
407
+ agent_playbook_id: int
408
+ source_user_playbook_ids: list[int] = Field(default_factory=list)
409
+ source_interaction_ids_by_user_playbook_id: dict[str, list[int]] = Field(
410
+ default_factory=dict
411
+ )
412
+
413
+
414
+ class PlaybookRetrievalLog(BaseModel):
415
+ """A retrieval-log header with ordered item rows.
416
+
417
+ Used by retrieval-capture consumers to correlate retrieval decisions with
418
+ downstream outcomes. ``retrieval_log_id`` is assigned by the storage layer;
419
+ ``shown_items`` stores ids and serve-time attribution snapshots only.
420
+ """
421
+
422
+ retrieval_log_id: int = 0
423
+ request_id: str
424
+ session_id: str
425
+ interaction_id: int | None = None
426
+ user_id: str
427
+ query: str | None = None
428
+ agent_version: str | None = None
429
+ shown_items: list[PlaybookRetrievalLogItem] = Field(default_factory=list)
430
+ created_at: int = 0
431
+
432
+
433
+ class LineageEvent(BaseModel):
434
+ """Append-only, content-free provenance record. NEVER carries content/PII.
435
+
436
+ Attributes:
437
+ event_id (int): PK assigned by storage (0 = not yet persisted).
438
+ org_id (str): Owning org (tenant) — required for RLS / isolation.
439
+ entity_type (str): One of "profile" | "user_playbook" | "agent_playbook".
440
+ entity_id (str): The affected record's id, stringified (profile_id is str).
441
+ op (str): create|revise|merge|aggregate|archive|soft_delete|hard_delete|purge|status_change.
442
+ prov_relation (str): W3C PROV relation (see spec §14).
443
+ source_ids (list[str]): Records merged/superseded into entity_id.
444
+ actor (str): Who/what triggered it (consolidator|reflection|offline_optimizer|...).
445
+ request_id (str): Triggering request — part of the idempotency key.
446
+ reason (str): Free-text rationale (no PII).
447
+ created_at (int): Unix epoch seconds (0 = unset; storage stamps it).
448
+ """
449
+
450
+ event_id: int = 0
451
+ org_id: str
452
+ entity_type: str
453
+ entity_id: str
454
+ op: str
455
+ prov_relation: str = ""
456
+ source_ids: list[str] = []
457
+ actor: str = ""
458
+ request_id: str = ""
459
+ reason: str = ""
460
+ created_at: int = 0
461
+ from_status: str | None = None
462
+ to_status: str | None = None
463
+ status_namespace: str | None = None
464
+
465
+
466
+ class LineageContext(BaseModel):
467
+ """Caller-supplied intent the storage layer can't infer.
468
+
469
+ Required for merge/supersede/aggregate; optional for create/revise/archive.
470
+ """
471
+
472
+ op_kind: str
473
+ actor: str = ""
474
+ source_ids: list[str] = []
475
+ reason: str = ""
476
+ request_id: str | None = None
477
+
478
+
479
+ class RecordRef(BaseModel):
480
+ """Result of resolve_current — the live survivor's id and whether its body was purged.
481
+
482
+ Attributes:
483
+ id: Primary key of the live survivor record.
484
+ is_purged: True when the survivor's content body has been blanked by
485
+ ``purge_content`` (GDPR/erasure). Any consumer that dereferences the
486
+ resolved record's content MUST treat ``is_purged=True`` as "erased —
487
+ skip or treat as absent." Reading blank content as if it were valid
488
+ is a silent data-quality bug.
489
+ """
490
+
491
+ id: str
492
+ is_purged: bool = False
493
+
494
+
401
495
  class ShareLink(BaseModel):
402
496
  """A shareable public link that maps a token to a resource within an org.
403
497
 
@@ -563,26 +657,21 @@ class PublishUserInteractionRequest(BaseModel):
563
657
  agent_version: str = (
564
658
  "" # this is used for aggregating interactions for generating agent playbooks
565
659
  )
566
- session_id: str | None = None # used for grouping requests together
660
+ session_id: NonEmptyStr # used for grouping requests together
567
661
  skip_aggregation: bool = (
568
662
  False # when True, extract profiles/playbooks but skip aggregation
569
663
  )
570
664
  force_extraction: bool = False # when True, bypass all extraction gates (stride_size, cheap pre-filter, LLM should_run) and always run extractors
665
+ evaluation_only: bool = False # when True, store for evaluation and permanently exclude from profile/playbook extraction
571
666
  override_learning_stall: bool = False # when True, run extraction even if a provider auth/billing stall is recorded
572
- metadata: dict[str, Any] = Field(default_factory=dict)
573
- """Per-request annotations stamped by customer integration code.
574
-
575
- Mirrors ``Request.metadata`` — the publish path copies this dict
576
- onto the ``Request`` row it creates so the eval pipeline (and the
577
- F2 sticky-group aggregator in particular) can read it back from
578
- the first request of each session.
579
667
 
580
- Conventional keys:
581
- - ``reflexio_retrieval_enabled`` (bool): F2 group assignment signal.
582
-
583
- Defaults to ``{}`` (never None) for backward compatibility — existing
584
- callers that don't pass ``metadata`` keep working unchanged.
585
- """
668
+ @model_validator(mode="after")
669
+ def validate_evaluation_only(self) -> Self:
670
+ if self.evaluation_only and self.force_extraction:
671
+ raise ValueError("evaluation_only cannot be combined with force_extraction")
672
+ if self.evaluation_only and not self.session_id:
673
+ raise ValueError("evaluation_only publishes require session_id")
674
+ return self
586
675
 
587
676
 
588
677
  # publish user interaction response
@@ -42,6 +42,10 @@ class Status(str, Enum): # noqa: UP042 - CURRENT=None is not compatible with St
42
42
  ARCHIVE_IN_PROGRESS = (
43
43
  "archive_in_progress" # temporary status during downgrade operation
44
44
  )
45
+ MERGED = "merged" # tombstone: consolidated into a survivor (merged_into set)
46
+ SUPERSEDED = (
47
+ "superseded" # tombstone: replaced by a new version (superseded_by set)
48
+ )
45
49
 
46
50
 
47
51
  class OperationStatus(StrEnum):
@@ -0,0 +1,117 @@
1
+ from __future__ import annotations
2
+
3
+ from datetime import UTC, datetime
4
+ from typing import Any, Literal
5
+
6
+ from pydantic import BaseModel, Field
7
+
8
+ AuditActorType = Literal["api_token", "jwt", "system"]
9
+ AuditOperation = Literal["READ", "EXPORT", "ERASE", "CREATE", "UPDATE", "DELETE"]
10
+ AuditEntityType = Literal[
11
+ "profile",
12
+ "user_playbook",
13
+ "agent_playbook",
14
+ "interaction",
15
+ "request",
16
+ "session",
17
+ "agent_success_evaluation_result",
18
+ "playbook_retrieval_log",
19
+ "org",
20
+ ]
21
+ AuditStatus = Literal["ok", "error"]
22
+ PurgeOperationType = Literal["user_erasure", "org_purge"]
23
+ PurgeScopeType = Literal["user", "org"]
24
+ PurgeStatus = Literal["pending", "running", "failed", "complete"]
25
+ PurgeTargetStatus = Literal["pending", "running", "failed", "complete"]
26
+ SubjectBarrierStatus = Literal["erasing", "erased", "failed"]
27
+
28
+ __all__ = [
29
+ "AuditActorType",
30
+ "AuditOperation",
31
+ "AuditEntityType",
32
+ "AuditStatus",
33
+ "PurgeOperationType",
34
+ "PurgeScopeType",
35
+ "PurgeStatus",
36
+ "PurgeTargetStatus",
37
+ "SubjectBarrierStatus",
38
+ "AuditEvent",
39
+ "PurgeOperation",
40
+ "PurgeOperationTarget",
41
+ "SubjectWriteBarrier",
42
+ "UserExportResult",
43
+ "UserEraseResult",
44
+ ]
45
+
46
+
47
+ def _now_epoch() -> int:
48
+ return int(datetime.now(UTC).timestamp())
49
+
50
+
51
+ class AuditEvent(BaseModel):
52
+ org_id: str
53
+ actor_type: AuditActorType = "system"
54
+ actor_ref: str | None = None
55
+ operation: AuditOperation
56
+ entity_type: AuditEntityType
57
+ entity_id: str | None = None
58
+ subject_ref: str | None = None
59
+ request_ref: str
60
+ idempotency_key: str | None = None
61
+ status: AuditStatus = "ok"
62
+ detail: dict[str, Any] | None = None
63
+ created_at: int = Field(default_factory=_now_epoch)
64
+
65
+
66
+ class PurgeOperation(BaseModel):
67
+ purge_id: str
68
+ org_id: str
69
+ operation_type: PurgeOperationType
70
+ scope_type: PurgeScopeType
71
+ subject_ref: str | None = None
72
+ request_ref: str
73
+ idempotency_key: str
74
+ status: PurgeStatus = "pending"
75
+ error_code: str | None = None
76
+ error_detail: str | None = None
77
+ created_at: int = Field(default_factory=_now_epoch)
78
+ updated_at: int = Field(default_factory=_now_epoch)
79
+ completed_at: int | None = None
80
+
81
+
82
+ class PurgeOperationTarget(BaseModel):
83
+ purge_id: str
84
+ target_name: str
85
+ target_ref: str = ""
86
+ phase: str
87
+ status: PurgeTargetStatus = "pending"
88
+ detail: dict[str, Any] | None = None
89
+ deleted_count: int = 0
90
+ error_detail: str | None = None
91
+ started_at: int | None = None
92
+ completed_at: int | None = None
93
+
94
+
95
+ class SubjectWriteBarrier(BaseModel):
96
+ org_id: str
97
+ subject_ref: str
98
+ purge_id: str
99
+ status: SubjectBarrierStatus
100
+ error_code: str | None = None
101
+ error_detail: str | None = None
102
+ created_at: int = Field(default_factory=_now_epoch)
103
+ updated_at: int = Field(default_factory=_now_epoch)
104
+
105
+
106
+ class UserExportResult(BaseModel):
107
+ subject_ref: str
108
+ export_id: str
109
+ bundle: dict[str, Any]
110
+
111
+
112
+ class UserEraseResult(BaseModel):
113
+ subject_ref: str
114
+ purge_id: str
115
+ status: PurgeStatus
116
+ deleted_counts: dict[str, int] = Field(default_factory=dict)
117
+ rebuilt_agent_playbook_ids: list[int] = Field(default_factory=list)
@@ -12,6 +12,7 @@ from typing import Literal, Self
12
12
  from pydantic import BaseModel, ConfigDict, Field, model_validator
13
13
 
14
14
  from reflexio.models.api_schema.validators import NonEmptyStr
15
+ from reflexio.models.structured_output import StrictStructuredOutput
15
16
 
16
17
  HeroStateLiteral = Literal["full", "early", "shadow_off", "empty"]
17
18
  BucketLiteral = Literal["day", "week"]
@@ -98,6 +99,24 @@ class ScoreDistribution(BaseModel):
98
99
  labels: list[str]
99
100
 
100
101
 
102
+ class EvaluationSourceSetRequest(BaseModel):
103
+ """One labeled request-source cohort for evaluation comparison.
104
+
105
+ ``sources`` match ``Request.source`` exactly. The empty string is valid and
106
+ represents requests published without a source.
107
+ """
108
+
109
+ label: NonEmptyStr
110
+ sources: list[str] = Field(min_length=1)
111
+
112
+ @model_validator(mode="after")
113
+ def validate_sources_are_unique(self) -> Self:
114
+ """Reject duplicate source values within a single set."""
115
+ if len(set(self.sources)) != len(self.sources):
116
+ raise ValueError("source set sources must be unique")
117
+ return self
118
+
119
+
101
120
  class GetEvaluationOverviewRequest(BaseModel):
102
121
  """Input for the overview endpoint.
103
122
 
@@ -107,18 +126,34 @@ class GetEvaluationOverviewRequest(BaseModel):
107
126
  bucket (BucketLiteral): Granularity of the hero trend buckets.
108
127
  include_shadow (bool): When False, skip the shadow-side aggregations
109
128
  (cheaper) — the hero will degrade to shadow_off state.
129
+ source_sets (list[EvaluationSourceSetRequest]): Optional labeled
130
+ request-source cohorts to compare. Sources are matched exactly
131
+ against the first request in each evaluated session.
110
132
  """
111
133
 
112
134
  from_ts: int = Field(ge=0)
113
135
  to_ts: int = Field(ge=0)
114
136
  bucket: BucketLiteral = "week"
115
137
  include_shadow: bool = True
138
+ source_sets: list[EvaluationSourceSetRequest] = Field(default_factory=list)
116
139
 
117
140
  @model_validator(mode="after")
118
- def validate_time_window(self) -> Self:
119
- """Ensure the requested time window is ordered."""
141
+ def validate_request(self) -> Self:
142
+ """Ensure the requested time window and source sets are valid."""
120
143
  if self.from_ts > self.to_ts:
121
144
  raise ValueError("from_ts must be <= to_ts")
145
+ labels = [s.label for s in self.source_sets]
146
+ if len(set(labels)) != len(labels):
147
+ raise ValueError("source set labels must be unique")
148
+ seen_sources: set[str] = set()
149
+ for source_set in self.source_sets:
150
+ overlap = seen_sources.intersection(source_set.sources)
151
+ if overlap:
152
+ overlap_list = ", ".join(sorted(repr(s) for s in overlap))
153
+ raise ValueError(
154
+ f"source values cannot appear in multiple source sets: {overlap_list}"
155
+ )
156
+ seen_sources.update(source_set.sources)
122
157
  return self
123
158
 
124
159
 
@@ -139,41 +174,6 @@ class BraintrustTileRow(BaseModel):
139
174
  delta: float
140
175
 
141
176
 
142
- class TrendPoint(BaseModel):
143
- """One point on a grouped success-rate trend curve (F2).
144
-
145
- Args:
146
- ts (int): Unix epoch seconds — bucket start.
147
- rate (float): Success rate for sessions in this bucket, [0.0, 1.0].
148
- n (int): Session count backing the rate. Must be non-negative.
149
- """
150
-
151
- ts: int
152
- rate: float
153
- n: int = Field(ge=0)
154
-
155
-
156
- class SuccessRateTrendByGroup(BaseModel):
157
- """Group-split trend data for the dashboard's dual-curve chart (F2).
158
-
159
- Grouping is by ``Request.metadata.reflexio_retrieval_enabled``, read from
160
- the first request of each session in the window. Sessions whose first
161
- request has the key absent OR a non-bool value land in ``untagged``.
162
-
163
- Args:
164
- treatment (list[TrendPoint]): Curve for sessions where the first
165
- request had ``metadata.reflexio_retrieval_enabled = True``.
166
- control (list[TrendPoint]): Curve for ``... = False``.
167
- untagged (list[TrendPoint]): Curve for sessions where the key is
168
- absent or non-bool — surfaced (not silently coerced) so
169
- customers can see how many of their sessions are untagged.
170
- """
171
-
172
- treatment: list[TrendPoint] = Field(default_factory=list)
173
- control: list[TrendPoint] = Field(default_factory=list)
174
- untagged: list[TrendPoint] = Field(default_factory=list)
175
-
176
-
177
177
  class ShadowWinRateTrendPoint(BaseModel):
178
178
  """One daily bucket of per-turn shadow-comparison verdicts (F1).
179
179
 
@@ -243,18 +243,41 @@ class ShadowWinRateTrend(BaseModel):
243
243
  judge_prompt_version: str = Field(default="v1.0.0")
244
244
 
245
245
 
246
+ class SourceSetEvaluationMetrics(BaseModel):
247
+ """Metrics for one labeled request-source set."""
248
+
249
+ label: str
250
+ sources: list[str]
251
+ session_count: int = Field(ge=0)
252
+ session_ids: list[str] = Field(default_factory=list)
253
+ success_rate_pp: float
254
+ buckets: list[HeroBucket]
255
+ context_tiles: ContextTile
256
+ score_distribution: ScoreDistribution
257
+ rule_attribution: list[RuleAttributionRow]
258
+ braintrust_tiles: list[BraintrustTileRow] = Field(default_factory=list)
259
+
260
+
261
+ class SourceSetComparison(BaseModel):
262
+ """Comparison payload for request-source cohorts."""
263
+
264
+ available_sources: list[str] = Field(default_factory=list)
265
+ sets: list[SourceSetEvaluationMetrics] = Field(default_factory=list)
266
+ unmatched_session_count: int = Field(default=0, ge=0)
267
+
268
+
246
269
  class GetEvaluationOverviewResponse(BaseModel):
247
270
  hero: HeroBlock
248
271
  context_tiles: ContextTile
249
272
  rule_attribution: list[RuleAttributionRow]
250
273
  score_distribution: ScoreDistribution
251
274
  braintrust_tiles: list[BraintrustTileRow] = Field(default_factory=list)
252
- success_rate_trend_by_group: SuccessRateTrendByGroup = Field(
253
- default_factory=SuccessRateTrendByGroup
254
- )
255
275
  shadow_win_rate_trend: ShadowWinRateTrend = Field(
256
276
  default_factory=ShadowWinRateTrend
257
277
  )
278
+ source_set_comparison: SourceSetComparison = Field(
279
+ default_factory=SourceSetComparison
280
+ )
258
281
 
259
282
 
260
283
  # ---------------------------------------------------------------------------
@@ -406,7 +429,7 @@ class GradeOnDemandResponse(BaseModel):
406
429
  # ---------------------------------------------------------------------------
407
430
 
408
431
 
409
- class ShadowComparisonOutput(BaseModel):
432
+ class ShadowComparisonOutput(StrictStructuredOutput):
410
433
  """LLM judge verdict for a per-turn Reflexio-vs-Shadow comparison (F1).
411
434
 
412
435
  Args:
@@ -26,3 +26,22 @@ class SessionDescriptor(NamedTuple):
26
26
  session_id: str
27
27
  agent_version: str
28
28
  source: str
29
+
30
+
31
+ class SessionFirstRequest(NamedTuple):
32
+ """Earliest request metadata for one session."""
33
+
34
+ session_id: str
35
+ user_id: str
36
+ source: str
37
+ created_at: int
38
+
39
+
40
+ class SessionCitation(NamedTuple):
41
+ """One cited rule/profile occurrence, keyed by user/session."""
42
+
43
+ user_id: str
44
+ session_id: str
45
+ kind: str
46
+ real_id: str
47
+ title: str
@@ -3,14 +3,21 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from datetime import datetime
6
- from typing import Any
6
+ from enum import StrEnum
7
+ from typing import TYPE_CHECKING, Any
7
8
 
8
9
  from pydantic import BaseModel, ConfigDict, Field
9
10
 
10
- from reflexio.server.services.storage.storage_base import (
11
- PendingToolCallRecord,
12
- PendingToolCallStatus,
13
- )
11
+ if TYPE_CHECKING:
12
+ from reflexio.server.services.storage.storage_base import PendingToolCallRecord
13
+
14
+
15
+ class PendingToolCallStatus(StrEnum):
16
+ PENDING = "pending"
17
+ RESOLVED = "resolved"
18
+ EXPIRED = "expired"
19
+ SUPERSEDED = "superseded"
20
+ CANCELLED = "cancelled"
14
21
 
15
22
 
16
23
  class PendingToolCallResponse(BaseModel):