claude-smart 0.2.44 → 0.2.46

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 (323) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/README.md +34 -5
  3. package/bin/claude-smart.js +295 -5
  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 +22 -2
  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/preferences/[id]/page.tsx +8 -8
  16. package/plugin/dashboard/app/skills/project/[id]/page.tsx +7 -3
  17. package/plugin/dashboard/app/skills/shared/[id]/page.tsx +10 -3
  18. package/plugin/dashboard/lib/claude-settings-file.ts +20 -10
  19. package/plugin/dashboard/lib/reflexio-client.ts +16 -0
  20. package/plugin/dashboard/lib/status.ts +10 -3
  21. package/plugin/dashboard/lib/types.ts +18 -6
  22. package/plugin/hooks/codex-hooks.json +0 -1
  23. package/plugin/opencode/assistant-buffer.ts +108 -0
  24. package/plugin/opencode/dist/assistant-buffer.js +96 -0
  25. package/plugin/opencode/dist/internal.js +12 -0
  26. package/plugin/opencode/dist/payload.js +85 -0
  27. package/plugin/opencode/dist/server.mjs +158 -0
  28. package/plugin/opencode/internal.ts +18 -0
  29. package/plugin/opencode/package.json +3 -0
  30. package/plugin/opencode/payload.ts +90 -0
  31. package/plugin/opencode/server.mts +174 -0
  32. package/plugin/opencode/tsconfig.json +13 -0
  33. package/plugin/pyproject.toml +20 -3
  34. package/plugin/scripts/_lib.sh +77 -29
  35. package/plugin/scripts/backend-service.sh +27 -5
  36. package/plugin/scripts/dashboard-service.sh +7 -5
  37. package/plugin/scripts/ensure-plugin-root.sh +4 -4
  38. package/plugin/scripts/hook_entry.sh +3 -3
  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 +10 -8
  43. package/plugin/src/README.md +1 -1
  44. package/plugin/src/claude_smart/cli.py +304 -6
  45. package/plugin/src/claude_smart/env_config.py +12 -4
  46. package/plugin/src/claude_smart/events/session_start.py +26 -7
  47. package/plugin/src/claude_smart/events/stop.py +1 -1
  48. package/plugin/src/claude_smart/ids.py +1 -1
  49. package/plugin/src/claude_smart/reflexio_adapter.py +5 -5
  50. package/plugin/src/claude_smart/runtime.py +7 -1
  51. package/plugin/uv.lock +1 -1
  52. package/plugin/vendor/reflexio/.env.example +54 -30
  53. package/plugin/vendor/reflexio/README.md +14 -8
  54. package/plugin/vendor/reflexio/pyproject.toml +13 -1
  55. package/plugin/vendor/reflexio/reflexio/README.md +1 -0
  56. package/plugin/vendor/reflexio/reflexio/cli/README.md +9 -7
  57. package/plugin/vendor/reflexio/reflexio/cli/__main__.py +10 -1
  58. package/plugin/vendor/reflexio/reflexio/cli/bootstrap_config.py +22 -5
  59. package/plugin/vendor/reflexio/reflexio/cli/commands/interactions.py +34 -4
  60. package/plugin/vendor/reflexio/reflexio/cli/commands/profiles.py +12 -7
  61. package/plugin/vendor/reflexio/reflexio/cli/commands/services.py +13 -6
  62. package/plugin/vendor/reflexio/reflexio/cli/commands/setup_cmd.py +210 -50
  63. package/plugin/vendor/reflexio/reflexio/cli/commands/shortcuts.py +15 -2
  64. package/plugin/vendor/reflexio/reflexio/cli/env_loader.py +292 -22
  65. package/plugin/vendor/reflexio/reflexio/cli/log_format.py +29 -4
  66. package/plugin/vendor/reflexio/reflexio/cli/run_services.py +17 -8
  67. package/plugin/vendor/reflexio/reflexio/cli/stop_services.py +13 -10
  68. package/plugin/vendor/reflexio/reflexio/client/client.py +57 -13
  69. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/README.md +135 -257
  70. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/npm/openclaw-smart/bin/openclaw-smart.js +13 -0
  71. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/npm/openclaw-smart/package.json +15 -0
  72. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/README.md +38 -0
  73. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/index.ts +151 -110
  74. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/openclaw.plugin.json +20 -10
  75. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/package.json +28 -6
  76. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/pyproject.toml +42 -0
  77. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/_lib.sh +371 -0
  78. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/backend-log-runner.sh +33 -0
  79. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/backend-service.sh +271 -0
  80. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/cli.sh +68 -0
  81. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/dashboard-open.sh +15 -0
  82. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/ensure-plugin-root.sh +84 -0
  83. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/hook_entry.sh +106 -0
  84. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/npm-cli.js +219 -0
  85. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/smart-install.sh +269 -0
  86. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/clear-all/SKILL.md +8 -0
  87. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/dashboard/SKILL.md +8 -0
  88. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/learn/SKILL.md +10 -0
  89. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/reflexio/SKILL.md +15 -44
  90. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/restart/SKILL.md +6 -0
  91. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/show/SKILL.md +8 -0
  92. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/cli.py +634 -0
  93. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/context_format.py +224 -0
  94. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/context_inject.py +79 -0
  95. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/__init__.py +0 -0
  96. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/after_tool_call.py +160 -0
  97. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/agent_end.py +187 -0
  98. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/before_prompt_build.py +69 -0
  99. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/before_tool_call.py +30 -0
  100. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/session_end.py +36 -0
  101. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/session_start.py +130 -0
  102. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/hook.py +131 -0
  103. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/ids.py +94 -0
  104. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/internal_call.py +75 -0
  105. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/oc_cite.py +196 -0
  106. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/optimizer_assistant.py +272 -0
  107. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/publish.py +96 -0
  108. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/query_compose.py +66 -0
  109. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/reflexio_adapter.py +336 -0
  110. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/runtime.py +47 -0
  111. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/stall_banner.py +61 -0
  112. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/state.py +323 -0
  113. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/__init__.py +0 -0
  114. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/__init__.py +0 -0
  115. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_e2e_session_loop.py +190 -0
  116. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_publish_to_local_reflexio_integration.py +112 -0
  117. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_recursion_guard_integration.py +86 -0
  118. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_search_inject_integration.py +144 -0
  119. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_cli.py +184 -0
  120. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_after_tool_call.py +142 -0
  121. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_agent_end.py +233 -0
  122. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_before_prompt_build.py +116 -0
  123. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_before_tool_call.py +35 -0
  124. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_session_end.py +47 -0
  125. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_session_start.py +109 -0
  126. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_hook_dispatch.py +117 -0
  127. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_ids.py +41 -0
  128. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_internal_call.py +50 -0
  129. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_oc_cite.py +88 -0
  130. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_publish.py +48 -0
  131. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_query_compose.py +48 -0
  132. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_reflexio_adapter.py +188 -0
  133. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_runtime.py +41 -0
  134. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_state.py +235 -0
  135. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests-ts/__mocks__/plugin-entry-stub.ts +6 -0
  136. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests-ts/test_npm_cli.test.ts +56 -0
  137. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests-ts/test_shim_dispatch.test.ts +171 -0
  138. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tsconfig.build.json +18 -0
  139. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/{tsconfig.json → plugin/tsconfig.json} +2 -2
  140. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/uv.lock +3835 -0
  141. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/vitest.config.ts +18 -0
  142. package/plugin/vendor/reflexio/reflexio/lib/_agent_playbook.py +238 -10
  143. package/plugin/vendor/reflexio/reflexio/lib/_config.py +11 -4
  144. package/plugin/vendor/reflexio/reflexio/lib/_generation.py +16 -5
  145. package/plugin/vendor/reflexio/reflexio/lib/_lineage_parity_readers.py +187 -0
  146. package/plugin/vendor/reflexio/reflexio/lib/_profiles.py +198 -6
  147. package/plugin/vendor/reflexio/reflexio/lib/_reflection.py +1 -1
  148. package/plugin/vendor/reflexio/reflexio/lib/_search.py +29 -20
  149. package/plugin/vendor/reflexio/reflexio/lib/_user_playbook.py +2 -1
  150. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/entities.py +127 -38
  151. package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/enums.py +4 -0
  152. package/plugin/vendor/reflexio/reflexio/models/api_schema/eval_overview_schema.py +64 -41
  153. package/plugin/vendor/reflexio/reflexio/models/api_schema/internal_schema.py +19 -0
  154. package/plugin/vendor/reflexio/reflexio/models/api_schema/pending_tool_call_schema.py +12 -5
  155. package/plugin/vendor/reflexio/reflexio/models/api_schema/retriever_schema.py +52 -0
  156. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/converters.py +5 -1
  157. package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/entities.py +5 -1
  158. package/plugin/vendor/reflexio/reflexio/models/config_schema.py +88 -7
  159. package/plugin/vendor/reflexio/reflexio/models/structured_output.py +148 -0
  160. package/plugin/vendor/reflexio/reflexio/server/OVERVIEW.md +3 -3
  161. package/plugin/vendor/reflexio/reflexio/server/README.md +45 -32
  162. package/plugin/vendor/reflexio/reflexio/server/__init__.py +29 -5
  163. package/plugin/vendor/reflexio/reflexio/server/__main__.py +2 -2
  164. package/plugin/vendor/reflexio/reflexio/server/_auth.py +65 -2
  165. package/plugin/vendor/reflexio/reflexio/server/api.py +734 -85
  166. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/precondition_checks.py +7 -0
  167. package/plugin/vendor/reflexio/reflexio/server/api_endpoints/request_context.py +3 -1
  168. package/plugin/vendor/reflexio/reflexio/server/billing_meter.py +173 -0
  169. package/plugin/vendor/reflexio/reflexio/server/billing_signals.py +64 -0
  170. package/plugin/vendor/reflexio/reflexio/server/cache/reflexio_cache.py +46 -16
  171. package/plugin/vendor/reflexio/reflexio/server/env_utils.py +65 -0
  172. package/plugin/vendor/reflexio/reflexio/server/llm/embedding_service.py +19 -4
  173. package/plugin/vendor/reflexio/reflexio/server/llm/litellm_client.py +264 -77
  174. package/plugin/vendor/reflexio/reflexio/server/llm/llm_utils.py +69 -7
  175. package/plugin/vendor/reflexio/reflexio/server/llm/providers/embedding_service_provider.py +75 -16
  176. package/plugin/vendor/reflexio/reflexio/server/llm/providers/openclaw_provider.py +280 -0
  177. package/plugin/vendor/reflexio/reflexio/server/llm/token_accounting.py +48 -0
  178. package/plugin/vendor/reflexio/reflexio/server/llm/tools.py +107 -17
  179. package/plugin/vendor/reflexio/reflexio/server/operation_limiter.py +360 -4
  180. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.6.0.prompt.md +1 -1
  181. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.7.0.prompt.md +85 -0
  182. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.2.0.prompt.md +1 -1
  183. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.3.0.prompt.md +253 -0
  184. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.2.prompt.md +1 -1
  185. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.3.prompt.md +74 -0
  186. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.3.prompt.md +1 -1
  187. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.3.0.prompt.md +266 -0
  188. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.4.0.prompt.md +266 -0
  189. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.3.0.prompt.md +1 -1
  190. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.4.0.prompt.md +137 -0
  191. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.2.0.prompt.md +1 -1
  192. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.3.0.prompt.md +34 -0
  193. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.0.0.prompt.md +5 -12
  194. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.1.0.prompt.md +5 -12
  195. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.2.0.prompt.md +155 -0
  196. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/tagging/v1.0.0.prompt.md +23 -0
  197. package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_manager.py +89 -32
  198. package/plugin/vendor/reflexio/reflexio/server/services/README.md +26 -11
  199. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/README.md +22 -0
  200. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/__init__.py +1 -0
  201. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_constants.py +4 -2
  202. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_utils.py +1 -0
  203. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/components/__init__.py +7 -0
  204. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{agent_success_evaluator.py → components/evaluator.py} +3 -16
  205. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/regen_jobs.py +28 -72
  206. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{group_evaluation_runner.py → runner.py} +12 -10
  207. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{delayed_group_evaluator.py → scheduler.py} +10 -2
  208. package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{agent_success_evaluation_service.py → service.py} +36 -1
  209. package/plugin/vendor/reflexio/reflexio/server/services/base_generation_service.py +160 -0
  210. package/plugin/vendor/reflexio/reflexio/server/services/configurator/base_configurator.py +5 -0
  211. package/plugin/vendor/reflexio/reflexio/server/services/deduplication_utils.py +1 -1
  212. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/README.md +9 -0
  213. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/components/__init__.py +0 -0
  214. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{rule_attribution.py → components/rule_attribution.py} +10 -9
  215. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/eval_sampler.py +15 -24
  216. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/service.py +238 -164
  217. package/plugin/vendor/reflexio/reflexio/server/services/extraction/README.md +31 -0
  218. package/plugin/vendor/reflexio/reflexio/server/services/extraction/outcome.py +13 -3
  219. package/plugin/vendor/reflexio/reflexio/server/services/extraction/pending_tool_call_dispatch.py +3 -2
  220. package/plugin/vendor/reflexio/reflexio/server/services/extraction/resumable_agent.py +32 -118
  221. package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_worker.py +39 -16
  222. package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +105 -23
  223. package/plugin/vendor/reflexio/reflexio/server/services/lineage/__init__.py +0 -0
  224. package/plugin/vendor/reflexio/reflexio/server/services/lineage/gc_scheduler.py +193 -0
  225. package/plugin/vendor/reflexio/reflexio/server/services/lineage/resolve.py +98 -0
  226. package/plugin/vendor/reflexio/reflexio/server/services/operation_state_utils.py +26 -0
  227. package/plugin/vendor/reflexio/reflexio/server/services/playbook/README.md +11 -12
  228. package/plugin/vendor/reflexio/reflexio/server/services/playbook/components/__init__.py +5 -0
  229. package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_aggregator.py → components/aggregator.py} +316 -178
  230. package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_consolidator.py → components/consolidator.py} +168 -62
  231. package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_extractor.py → components/extractor.py} +5 -1
  232. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_edit_apply.py +74 -0
  233. package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_utils.py +33 -3
  234. package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_generation_service.py → service.py} +121 -19
  235. package/plugin/vendor/reflexio/reflexio/server/services/playbook/user_detail_stripping.py +84 -0
  236. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/README.md +10 -0
  237. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/models.py +2 -1
  238. package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/optimizer.py +178 -30
  239. package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/README.md +9 -0
  240. package/plugin/vendor/reflexio/reflexio/server/services/profile/components/__init__.py +17 -0
  241. package/plugin/vendor/reflexio/reflexio/server/services/profile/{profile_deduplicator.py → components/consolidator.py} +7 -6
  242. package/plugin/vendor/reflexio/reflexio/server/services/profile/{profile_extractor.py → components/extractor.py} +30 -22
  243. package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service_utils.py +6 -13
  244. package/plugin/vendor/reflexio/reflexio/server/services/profile/{profile_generation_service.py → service.py} +32 -50
  245. package/plugin/vendor/reflexio/reflexio/server/services/reflection/__init__.py +4 -8
  246. package/plugin/vendor/reflexio/reflexio/server/services/reflection/components/__init__.py +7 -0
  247. package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service_utils.py +12 -1
  248. package/plugin/vendor/reflexio/reflexio/server/services/reflection/{reflection_service.py → service.py} +36 -16
  249. package/plugin/vendor/reflexio/reflexio/server/services/retrieval/relevance_floor.py +83 -6
  250. package/plugin/vendor/reflexio/reflexio/server/services/service_utils.py +36 -1
  251. package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/README.md +8 -0
  252. package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/outcome.py +1 -2
  253. package/plugin/vendor/reflexio/reflexio/server/services/storage/error.py +27 -0
  254. package/plugin/vendor/reflexio/reflexio/server/services/storage/retention.py +9 -9
  255. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/__init__.py +2 -0
  256. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_agent_run.py +4 -1
  257. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_base.py +642 -197
  258. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_extras.py +61 -104
  259. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_lineage.py +628 -0
  260. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_operations.py +38 -6
  261. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_playbook.py +978 -184
  262. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +519 -128
  263. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_requests.py +77 -3
  264. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_shadow_verdicts.py +23 -9
  265. package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_stall_state.py +5 -2
  266. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/__init__.py +131 -20
  267. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_agent_run.py +2 -8
  268. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_base.py +5 -0
  269. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_extras.py +36 -53
  270. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_lineage.py +215 -0
  271. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_operations.py +20 -0
  272. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_playbook.py +243 -7
  273. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_profiles.py +121 -1
  274. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_requests.py +60 -0
  275. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_retrieval_log.py +51 -0
  276. package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_shadow_verdicts.py +17 -0
  277. package/plugin/vendor/reflexio/reflexio/server/services/tagging/README.md +8 -0
  278. package/plugin/vendor/reflexio/reflexio/server/services/tagging/__init__.py +1 -0
  279. package/plugin/vendor/reflexio/reflexio/server/services/tagging/service.py +200 -0
  280. package/plugin/vendor/reflexio/reflexio/server/services/tagging/tagging_scheduler.py +149 -0
  281. package/plugin/vendor/reflexio/reflexio/server/services/unified_search_service.py +229 -32
  282. package/plugin/vendor/reflexio/reflexio/server/site_var/README.md +2 -1
  283. package/plugin/vendor/reflexio/reflexio/server/site_var/feature_flags.py +120 -1
  284. package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/feature_flags.json +4 -0
  285. package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/search_settings.json +5 -0
  286. package/plugin/vendor/reflexio/reflexio/server/tracing.py +30 -0
  287. package/plugin/vendor/reflexio/reflexio/server/usage_metrics.py +18 -0
  288. package/plugin/vendor/reflexio/reflexio/test_support/llm_mock.py +61 -26
  289. package/plugin/vendor/reflexio/reflexio/test_support/llm_model_registry.py +41 -4
  290. package/scripts/setup-claude-smart.sh +8 -3
  291. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/TESTING.md +0 -517
  292. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/hook/handler.js +0 -473
  293. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package-lock.json +0 -2156
  294. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package.json +0 -18
  295. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/handler.ts +0 -241
  296. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/setup.ts +0 -140
  297. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/publish.ts +0 -113
  298. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/search.ts +0 -52
  299. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/server.ts +0 -103
  300. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/sqlite-buffer.ts +0 -156
  301. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/user-id.ts +0 -134
  302. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/rules/reflexio.md +0 -24
  303. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/publish_clawhub.sh +0 -278
  304. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/references/HOOK.md +0 -164
  305. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/install.sh +0 -36
  306. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/uninstall.sh +0 -35
  307. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/publish.test.ts +0 -27
  308. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/search.test.ts +0 -31
  309. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/server.test.ts +0 -42
  310. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/setup.test.ts +0 -49
  311. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/sqlite-buffer.test.ts +0 -91
  312. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/user-id.test.ts +0 -50
  313. package/plugin/vendor/reflexio/reflexio/integrations/openclaw/vitest.config.ts +0 -13
  314. package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/group_aggregation.py +0 -192
  315. package/plugin/vendor/reflexio/reflexio/server/services/extraction/invariants.py +0 -303
  316. package/plugin/vendor/reflexio/reflexio/server/services/extraction/plan.py +0 -138
  317. package/plugin/vendor/reflexio/reflexio/server/services/extraction/tools.py +0 -1125
  318. /package/plugin/vendor/reflexio/reflexio/integrations/{__init__.py → openclaw/plugin/src/openclaw_smart/__init__.py} +0 -0
  319. /package/plugin/vendor/reflexio/reflexio/integrations/openclaw/{types → plugin/types}/openclaw.d.ts +0 -0
  320. /package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{distribution.py → components/distribution.py} +0 -0
  321. /package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{hero_state.py → components/hero_state.py} +0 -0
  322. /package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{shadow_aggregation.py → components/shadow_aggregation.py} +0 -0
  323. /package/plugin/vendor/reflexio/reflexio/server/services/reflection/{reflection_extractor.py → components/extractor.py} +0 -0
@@ -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):
@@ -50,6 +50,11 @@ class SearchInteractionRequest(BaseModel):
50
50
  class SearchUserProfileRequest(BaseModel):
51
51
  user_id: NonEmptyStr
52
52
  generated_from_request_id: str | None = None
53
+ # Caller correlation IDs for billing attribution on the Application line.
54
+ # Optional; when populated they flow into the usage event request_id /
55
+ # session_id columns via _meter_applied_learnings in server/api.py.
56
+ request_id: str | None = None
57
+ session_id: str | None = None
53
58
  query: str | None = None
54
59
  start_time: datetime | None = None
55
60
  end_time: datetime | None = None
@@ -59,6 +64,7 @@ class SearchUserProfileRequest(BaseModel):
59
64
  extractor_name: str | None = (
60
65
  None # Deprecated compatibility field; accepted but ignored.
61
66
  )
67
+ tags: list[str] | None = None
62
68
  threshold: float | None = Field(default=0.4, ge=0.0, le=1.0)
63
69
  enable_reformulation: bool | None = False
64
70
  search_mode: SearchMode = SearchMode.HYBRID
@@ -185,6 +191,7 @@ class GetUserProfilesRequest(BaseModel):
185
191
  end_time: datetime | None = None
186
192
  top_k: int | None = Field(default=30, gt=0)
187
193
  status_filter: list[Status | None] | None = None
194
+ tags: list[str] | None = None
188
195
 
189
196
  @model_validator(mode="after")
190
197
  def check_time_range(self) -> Self:
@@ -219,6 +226,7 @@ class GetUserPlaybooksRequest(BaseModel):
219
226
  playbook_name: str | None = None
220
227
  agent_version: str | None = None
221
228
  status_filter: list[Status | None] | None = None
229
+ tags: list[str] | None = None
222
230
 
223
231
 
224
232
  class GetUserPlaybooksResponse(BaseModel):
@@ -233,6 +241,11 @@ class GetAgentPlaybooksRequest(BaseModel):
233
241
  agent_version: str | None = None
234
242
  status_filter: list[Status | None] | None = None
235
243
  playbook_status_filter: PlaybookStatus | None = None
244
+ tags: list[str] | None = None
245
+ # Caller correlation IDs for billing attribution on the Application line.
246
+ # Optional; consumed by _meter_applied_learnings in server/api.py.
247
+ request_id: str | None = None
248
+ session_id: str | None = None
236
249
 
237
250
 
238
251
  class GetAgentPlaybooksResponse(BaseModel):
@@ -241,6 +254,30 @@ class GetAgentPlaybooksResponse(BaseModel):
241
254
  msg: str | None = None
242
255
 
243
256
 
257
+ class GetLearningProvenanceRequest(BaseModel):
258
+ kind: Literal["profile", "user_playbook", "agent_playbook"]
259
+ id: str
260
+
261
+
262
+ class SourceUserPlaybookProvenanceView(BaseModel):
263
+ user_playbook: UserPlaybookView
264
+ interactions: list[InteractionView] = Field(default_factory=list)
265
+ source_interaction_ids: list[int] = Field(default_factory=list)
266
+
267
+
268
+ class LearningProvenanceViewResponse(BaseModel):
269
+ success: bool
270
+ target_kind: Literal["profile", "user_playbook", "agent_playbook"]
271
+ target_id: str
272
+ provenance_status: Literal["exact", "best_effort", "unavailable"] = "unavailable"
273
+ trigger_request_id: str | None = None
274
+ interactions: list[InteractionView] = Field(default_factory=list)
275
+ source_user_playbooks: list[SourceUserPlaybookProvenanceView] = Field(
276
+ default_factory=list
277
+ )
278
+ msg: str | None = None
279
+
280
+
244
281
  class SearchUserPlaybookRequest(BaseModel):
245
282
  """Request for searching user playbooks with semantic/text search and filtering.
246
283
 
@@ -263,10 +300,15 @@ class SearchUserPlaybookRequest(BaseModel):
263
300
  start_time: datetime | None = None
264
301
  end_time: datetime | None = None
265
302
  status_filter: list[Status | None] | None = None
303
+ tags: list[str] | None = None
266
304
  top_k: int | None = Field(default=10, gt=0)
267
305
  threshold: float | None = Field(default=0.4, ge=0.0, le=1.0)
268
306
  enable_reformulation: bool | None = False
269
307
  search_mode: SearchMode = SearchMode.HYBRID
308
+ # Caller correlation IDs for billing attribution on the Application line.
309
+ # Optional; consumed by _meter_applied_learnings in server/api.py.
310
+ request_id: str | None = None
311
+ session_id: str | None = None
270
312
 
271
313
  @model_validator(mode="after")
272
314
  def check_time_range(self) -> Self:
@@ -316,10 +358,15 @@ class SearchAgentPlaybookRequest(BaseModel):
316
358
  end_time: datetime | None = None
317
359
  status_filter: list[Status | None] | None = None
318
360
  playbook_status_filter: PlaybookStatus | list[PlaybookStatus] | None = None
361
+ tags: list[str] | None = None
319
362
  top_k: int | None = Field(default=10, gt=0)
320
363
  threshold: float | None = Field(default=0.4, ge=0.0, le=1.0)
321
364
  enable_reformulation: bool | None = False
322
365
  search_mode: SearchMode = SearchMode.HYBRID
366
+ # Caller correlation IDs for billing attribution on the Application line.
367
+ # Optional; consumed by _meter_applied_learnings in server/api.py.
368
+ request_id: str | None = None
369
+ session_id: str | None = None
323
370
 
324
371
  @model_validator(mode="after")
325
372
  def check_time_range(self) -> Self:
@@ -621,6 +668,11 @@ class UnifiedSearchRequest(BaseModel):
621
668
  enable_reformulation: bool | None = False
622
669
  enable_agent_answer: bool | None = False
623
670
  search_mode: SearchMode = SearchMode.HYBRID
671
+ # Caller correlation IDs for billing attribution on the Application line.
672
+ # Optional; consumed by _meter_applied_learnings in server/api.py.
673
+ request_id: str | None = None
674
+ session_id: str | None = None
675
+ interaction_id: int | None = Field(default=None, gt=0)
624
676
 
625
677
 
626
678
  class UnifiedSearchResponse(BaseModel):
@@ -78,6 +78,8 @@ def to_profile_view(profile: UserProfile) -> ProfileView:
78
78
  status=profile.status,
79
79
  extractor_names=profile.extractor_names,
80
80
  source_span=profile.source_span,
81
+ source_interaction_ids=profile.source_interaction_ids,
82
+ tags=profile.tags or [],
81
83
  )
82
84
 
83
85
 
@@ -104,6 +106,7 @@ def to_user_playbook_view(rf: UserPlaybook) -> UserPlaybookView:
104
106
  source=rf.source,
105
107
  source_interaction_ids=rf.source_interaction_ids,
106
108
  source_span=rf.source_span,
109
+ tags=rf.tags or [],
107
110
  )
108
111
 
109
112
 
@@ -127,6 +130,7 @@ def to_agent_playbook_view(fb: AgentPlaybook) -> AgentPlaybookView:
127
130
  playbook_status=fb.playbook_status,
128
131
  playbook_metadata=fb.playbook_metadata,
129
132
  status=fb.status,
133
+ tags=fb.tags or [],
130
134
  )
131
135
 
132
136
 
@@ -143,6 +147,7 @@ def to_evaluation_result_view(
143
147
  """
144
148
  return EvaluationResultView(
145
149
  result_id=result.result_id,
150
+ user_id=result.user_id,
146
151
  agent_version=result.agent_version,
147
152
  session_id=result.session_id,
148
153
  is_success=result.is_success,
@@ -173,5 +178,4 @@ def to_profile_change_log_view(log: ProfileChangeLog) -> ProfileChangeLogView:
173
178
  created_at=log.created_at,
174
179
  added_profiles=[to_profile_view(p) for p in log.added_profiles],
175
180
  removed_profiles=[to_profile_view(p) for p in log.removed_profiles],
176
- mentioned_profiles=[to_profile_view(p) for p in log.mentioned_profiles],
177
181
  )
@@ -65,6 +65,8 @@ class ProfileView(BaseModel):
65
65
  status: Status | None = None
66
66
  extractor_names: list[str] | None = None
67
67
  source_span: str | None = None
68
+ source_interaction_ids: list[int] = Field(default_factory=list)
69
+ tags: list[str] = Field(default_factory=list)
68
70
 
69
71
 
70
72
  class UserPlaybookView(BaseModel):
@@ -83,6 +85,7 @@ class UserPlaybookView(BaseModel):
83
85
  source: str | None = None
84
86
  source_interaction_ids: list[int] = Field(default_factory=list)
85
87
  source_span: str | None = None
88
+ tags: list[str] = Field(default_factory=list)
86
89
 
87
90
 
88
91
  class AgentPlaybookView(BaseModel):
@@ -98,12 +101,14 @@ class AgentPlaybookView(BaseModel):
98
101
  playbook_status: PlaybookStatus = PlaybookStatus.PENDING
99
102
  playbook_metadata: str = ""
100
103
  status: Status | None = None
104
+ tags: list[str] = Field(default_factory=list)
101
105
 
102
106
 
103
107
  class EvaluationResultView(BaseModel):
104
108
  """User-facing AgentSuccessEvaluationResult — excludes embedding."""
105
109
 
106
110
  result_id: int = 0
111
+ user_id: str = ""
107
112
  agent_version: str
108
113
  session_id: str
109
114
  is_success: bool
@@ -126,4 +131,3 @@ class ProfileChangeLogView(BaseModel):
126
131
  created_at: int = Field(default_factory=lambda: int(datetime.now(UTC).timestamp()))
127
132
  added_profiles: list[ProfileView]
128
133
  removed_profiles: list[ProfileView]
129
- mentioned_profiles: list[ProfileView]
@@ -95,7 +95,13 @@ def _migrate_dict(data: Any, mapping: dict[str, str]) -> Any:
95
95
  if isinstance(data, dict):
96
96
  data = dict(data)
97
97
  for old, new in mapping.items():
98
- if old in data and new not in data:
98
+ if old not in data:
99
+ continue
100
+ # New name wins when both are present; always drop the old key so it
101
+ # doesn't survive into validation and trip ``extra="forbid"``.
102
+ if new in data:
103
+ data.pop(old)
104
+ else:
99
105
  data[new] = data.pop(old)
100
106
  return data
101
107
 
@@ -397,6 +403,16 @@ class DeduplicationConfig(BaseModel):
397
403
  SINGLETON_PROFILE_EXTRACTOR_NAME = "profile"
398
404
  SINGLETON_USER_PLAYBOOK_NAME = "playbook"
399
405
  SINGLETON_AGENT_SUCCESS_EVALUATION_NAME = "agent_success"
406
+ DEFAULT_AGENT_SUCCESS_SAMPLING_RATE = 0.05
407
+ DEFAULT_AGENT_SUCCESS_DEFINITION_PROMPT = (
408
+ "Evaluate whether the AI agent successfully handled the user's session.\n\n"
409
+ "Mark the session successful when, by the end of the conversation, the agent:\n"
410
+ "1. Identified and addressed the user's main goal or question.\n"
411
+ "2. Provided a correct, useful, and actionable response or completed the requested action.\n"
412
+ "Mark the session unsuccessful when the agent failed to understand the request,\n"
413
+ "gave incorrect or unhelpful guidance, did not complete an available action,\n"
414
+ "ignored important constraints, or left the user unsatisfied."
415
+ )
400
416
 
401
417
 
402
418
  class ProfileExtractorConfig(_ExtractorWindowOverrideCompatMixin, BaseModel):
@@ -405,7 +421,7 @@ class ProfileExtractorConfig(_ExtractorWindowOverrideCompatMixin, BaseModel):
405
421
  extractor_name: NonEmptyStr | None = None
406
422
  extraction_definition_prompt: SanitizedNonEmptyStr
407
423
  context_prompt: str | None = None
408
- metadata_definition_prompt: str | None = None
424
+ tagging_definition_prompt: str | None = None
409
425
  should_extract_profile_prompt_override: str | None = None
410
426
  request_sources_enabled: list[str] | None = (
411
427
  None # default enabled for all sources, if set, only extract profiles from the enabled request sources
@@ -456,7 +472,7 @@ class UserPlaybookExtractorConfig(_ExtractorWindowOverrideCompatMixin, BaseModel
456
472
  extractor_name: NonEmptyStr | None = None
457
473
  extraction_definition_prompt: SanitizedNonEmptyStr
458
474
  context_prompt: str | None = None
459
- metadata_definition_prompt: str | None = None
475
+ tagging_definition_prompt: str | None = None
460
476
  aggregation_config: PlaybookAggregatorConfig | None = None
461
477
  deduplication_config: DeduplicationConfig | None = None
462
478
  request_sources_enabled: list[str] | None = (
@@ -488,9 +504,15 @@ class AgentSuccessConfig(_ExtractorWindowOverrideCompatMixin, BaseModel):
488
504
  evaluation_name: NonEmptyStr | None = None
489
505
  success_definition_prompt: SanitizedNonEmptyStr
490
506
  metadata_definition_prompt: str | None = None
507
+ request_sources_enabled: list[str] | None = (
508
+ None # default enabled for all sources, if set, only evaluate requests from the enabled request sources
509
+ )
491
510
  sampling_rate: float = Field(
492
- default=1.0, ge=0.0, le=1.0
493
- ) # fraction of window of interactions to be sampled for success evaluation
511
+ default=DEFAULT_AGENT_SUCCESS_SAMPLING_RATE,
512
+ ge=0.0,
513
+ le=1.0,
514
+ description="Fraction of sessions to evaluate automatically.",
515
+ )
494
516
  window_size_override: int | None = Field(default=None, gt=0)
495
517
  stride_size_override: int | None = Field(default=None, gt=0)
496
518
 
@@ -500,6 +522,14 @@ class AgentSuccessConfig(_ExtractorWindowOverrideCompatMixin, BaseModel):
500
522
  return _migrate_dict(data, _EXTRACTOR_OVERRIDE_MIGRATION)
501
523
 
502
524
 
525
+ def _default_agent_success_config() -> AgentSuccessConfig:
526
+ return AgentSuccessConfig(
527
+ evaluation_name=SINGLETON_AGENT_SUCCESS_EVALUATION_NAME,
528
+ success_definition_prompt=DEFAULT_AGENT_SUCCESS_DEFINITION_PROMPT,
529
+ sampling_rate=DEFAULT_AGENT_SUCCESS_SAMPLING_RATE,
530
+ )
531
+
532
+
503
533
  class ReflectionConfig(BaseModel):
504
534
  """Configuration for the sliding-window reflection step.
505
535
 
@@ -559,7 +589,7 @@ class RetrievalFloorConfig(BaseModel):
559
589
  weak tail that drives false-positive citations. Calibrate per arm on real data.
560
590
  """
561
591
 
562
- enabled: bool = True
592
+ enabled: bool = False
563
593
  pool_size: int = Field(
564
594
  default=30,
565
595
  gt=0,
@@ -634,6 +664,50 @@ class PlaybookOptimizerConfig(BaseModel):
634
664
  return self
635
665
 
636
666
 
667
+ class LineageGCConfig(BaseModel):
668
+ """Configuration for the tombstone garbage-collection job (enabled by default).
669
+
670
+ Purpose
671
+ -------
672
+ Retains tombstone content for ``tombstone_grace_window_days`` days after the
673
+ row's *retirement instant* (``retired_at``) to support audit, replay of dedup
674
+ and aggregation runs, and rollback. After the window expires the row is
675
+ hard-deleted and a ``hard_delete`` lineage event is recorded.
676
+
677
+ Age basis
678
+ ---------
679
+ The GC ages on ``retired_at`` — the INTEGER epoch set when a row is tombstoned
680
+ (merged, superseded, or archived). Rows with ``retired_at = NULL`` (created
681
+ before the column was added) are never eligible; they have no retirement clock.
682
+
683
+ Grace window
684
+ ------------
685
+ 90 days is the default grace window. This matches common 90-day soft-delete
686
+ retention policies and satisfies GDPR Art. 5(1)(e) storage-limitation for
687
+ personal data in profiles. The value is a per-deployment policy knob; ratify
688
+ with your DPO before shortening it in production. The 90-day floor also
689
+ preserves tombstones long enough for B3 changelog replay and rollback
690
+ consumers — raise ``tombstone_grace_window_days`` further if your replay
691
+ horizon exceeds 90 days.
692
+
693
+ Enabled by default
694
+ ------------------
695
+ GC is ON by default so tombstones created by the soft-delete flags (also ON by
696
+ default) are reclaimed automatically. Disabling GC while soft-delete is enabled
697
+ allows tombstone counts to grow without bound — only do this deliberately (e.g.
698
+ extended audit hold) and with a plan to re-enable.
699
+
700
+ Disabling
701
+ ---------
702
+ Set ``enabled = False`` in your deployment config to hold all tombstones
703
+ indefinitely (e.g. for an extended audit window or rollback standby period).
704
+ """
705
+
706
+ enabled: bool = True
707
+ tombstone_grace_window_days: int = Field(default=90, gt=0)
708
+ poll_interval_seconds: int = Field(default=86400, gt=0)
709
+
710
+
637
711
  @dataclass(frozen=True)
638
712
  class EffectivePendingToolCallConfig:
639
713
  """Resolved pending-tool-call settings after applying tool overrides."""
@@ -733,6 +807,8 @@ def _default_user_playbook_extractor_config() -> UserPlaybookExtractorConfig:
733
807
 
734
808
 
735
809
  class Config(BaseModel):
810
+ model_config = ConfigDict(extra="forbid")
811
+
736
812
  # define where user configuration is stored at
737
813
  storage_config: StorageConfig
738
814
  storage_config_test: StorageConfigTest | None = StorageConfigTest.UNKNOWN
@@ -749,7 +825,9 @@ class Config(BaseModel):
749
825
  default_factory=_default_user_playbook_extractor_config
750
826
  )
751
827
  # agent level success
752
- agent_success_config: AgentSuccessConfig | None = None
828
+ agent_success_config: AgentSuccessConfig | None = Field(
829
+ default_factory=_default_agent_success_config
830
+ )
753
831
  # extraction preset — selects bundled window_size/stride_size values
754
832
  extraction_preset: ExtractionPreset | None = None
755
833
  # extraction parameters
@@ -767,6 +845,8 @@ class Config(BaseModel):
767
845
  playbook_optimizer_config: PlaybookOptimizerConfig = Field(
768
846
  default_factory=PlaybookOptimizerConfig
769
847
  )
848
+ # Tombstone GC job gate (opt-in, off by default — see LineageGCConfig)
849
+ lineage_gc: LineageGCConfig = Field(default_factory=LineageGCConfig)
770
850
  # Optional non-blocking async information tools for classic extraction.
771
851
  pending_tool_call_config: PendingToolCallConfig = Field(
772
852
  default_factory=PendingToolCallConfig
@@ -824,6 +904,7 @@ class Config(BaseModel):
824
904
  "stride_size",
825
905
  "reflection_config",
826
906
  "playbook_optimizer_config",
907
+ "lineage_gc",
827
908
  "pending_tool_call_config",
828
909
  "retrieval_floor",
829
910
  ):