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
@@ -0,0 +1,148 @@
1
+ """Provider-safe base class for LLM structured-output Pydantic models.
2
+
3
+ Every Pydantic model sent to an LLM as a structured-output schema (a
4
+ ``response_format`` or a tool's parameter schema) should inherit
5
+ ``StrictStructuredOutput``. It carries a ``__get_pydantic_json_schema__`` hook
6
+ (via ``ProviderSafeUnionMixin``) that folds a discriminated union's ``oneOf`` into
7
+ ``anyOf`` and drops ``discriminator`` in the *emitted* JSON schema, so strict
8
+ structured-output endpoints (OpenAI, minimax) accept it **by construction** — with
9
+ no provider-detection gate and no post-processing. Only the wire schema is
10
+ rewritten; the core (validation) schema keeps the discriminator, so keyed dispatch
11
+ and precise per-variant errors are preserved.
12
+
13
+ This module lives under ``models/`` (depending only on pydantic) so both
14
+ ``models/api_schema/`` schemas and ``server/services/*`` models can inherit the
15
+ base without a layering inversion (a ``models/`` file importing from
16
+ ``server/llm/`` would invert the dependency direction).
17
+ """
18
+
19
+ from typing import TYPE_CHECKING, Any
20
+
21
+ from pydantic import BaseModel, GetJsonSchemaHandler
22
+ from pydantic.json_schema import JsonSchemaValue
23
+ from pydantic_core import CoreSchema
24
+
25
+ # Keys whose *values* are name→subschema maps: their entries are user-chosen names
26
+ # (field names, $def names), not JSON-Schema keywords. Traversals must recurse into
27
+ # the subschemas but never treat the names themselves as keywords — otherwise a
28
+ # model with a field literally named ``oneOf`` would be mishandled.
29
+ _SCHEMA_NAME_MAP_KEYS = ("properties", "$defs", "definitions", "patternProperties")
30
+
31
+
32
+ def _fold_oneof_to_anyof(node: Any) -> None:
33
+ """Rewrite ``oneOf`` to ``anyOf`` and drop ``discriminator`` in place (recursive).
34
+
35
+ Pydantic emits ``oneOf`` + ``discriminator`` for a discriminated union, which
36
+ strict structured-output endpoints (OpenAI, minimax) reject. Folding into
37
+ ``anyOf`` keeps the identical variant set so generation stays constrained;
38
+ Pydantic still enforces the discriminator after parse, so semantics are
39
+ preserved.
40
+
41
+ Structure-aware: under a name→subschema map (``properties``/``$defs``/…) it
42
+ recurses into the subschemas but does NOT treat a property/``$def`` *name* as a
43
+ keyword — so a model field literally named ``oneOf``/``discriminator`` is
44
+ preserved (only keyword-position occurrences are folded). Precondition:
45
+ ``node`` is a finite acyclic tree, as produced by ``model_json_schema()``
46
+ (which expresses recursion via ``$ref``/``$defs`` strings, never in-memory
47
+ cycles) — there is no cycle guard.
48
+
49
+ Args:
50
+ node (Any): A JSON-schema fragment (dict, list, or scalar); mutated in place.
51
+ """
52
+ if isinstance(node, dict):
53
+ one_of = node.pop("oneOf", None)
54
+ node.pop("discriminator", None)
55
+ if isinstance(one_of, list):
56
+ node["anyOf"] = node.get("anyOf", []) + one_of
57
+ for key, value in node.items():
58
+ if key in _SCHEMA_NAME_MAP_KEYS and isinstance(value, dict):
59
+ for sub in value.values():
60
+ _fold_oneof_to_anyof(sub)
61
+ else:
62
+ _fold_oneof_to_anyof(value)
63
+ elif isinstance(node, list):
64
+ for item in node:
65
+ _fold_oneof_to_anyof(item)
66
+
67
+
68
+ # Statically the mixin must appear to derive from ``BaseModel`` so the ``super()``
69
+ # call below type-checks; at runtime it is a bare mixin (``object`` base), and
70
+ # ``super()`` resolves to ``BaseModel.__get_pydantic_json_schema__`` via the MRO
71
+ # of the concrete model (e.g. ``class X(ProviderSafeUnionMixin, BaseModel)``).
72
+ _ProviderSafeUnionBase = BaseModel if TYPE_CHECKING else object
73
+
74
+
75
+ class ProviderSafeUnionMixin(_ProviderSafeUnionBase):
76
+ """Make a model emit a provider-safe JSON schema by construction.
77
+
78
+ A model containing a Pydantic discriminated union serializes to JSON Schema
79
+ with ``oneOf`` + ``discriminator``, which strict structured-output endpoints
80
+ reject (the Sentry ``PYTHON-FASTAPI-9J`` incident). Mixing this in folds
81
+ ``oneOf`` into ``anyOf`` (and drops ``discriminator``) at the model boundary,
82
+ so every caller of ``model_json_schema()`` — litellm, instructor, our own
83
+ path — gets a provider-safe schema **unconditionally**, without depending on
84
+ a provider-detection gate (e.g. ``litellm.supports_response_schema``, which
85
+ under-reports some providers). Only the JSON (wire) schema is rewritten; the
86
+ core validation schema keeps the discriminator, so keyed dispatch and precise
87
+ per-variant errors are preserved.
88
+
89
+ Prefer inheriting ``StrictStructuredOutput`` (below) on output models rather
90
+ than mixing this in directly.
91
+ """
92
+
93
+ @classmethod
94
+ def __get_pydantic_json_schema__(
95
+ cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler
96
+ ) -> JsonSchemaValue:
97
+ # Chain via super() (not handler() directly) so a cooperative base that
98
+ # also customizes __get_pydantic_json_schema__ is not silently shadowed;
99
+ # BaseModel's default impl just invokes handler(core_schema).
100
+ schema = super().__get_pydantic_json_schema__(core_schema, handler)
101
+ _fold_oneof_to_anyof(schema)
102
+ return schema
103
+
104
+
105
+ class StrictStructuredOutput(ProviderSafeUnionMixin, BaseModel):
106
+ """Base for every Pydantic model sent to an LLM as a structured-output schema.
107
+
108
+ Inherits the provider-safe schema hook from ``ProviderSafeUnionMixin`` so the
109
+ emitted JSON schema folds any discriminated union (``oneOf``→``anyOf``, drop
110
+ ``discriminator``) by construction — accepted by strict structured-output
111
+ providers with no provider gate, including any *future* discriminated union.
112
+
113
+ Deliberately adds NO ``model_config``: each model keeps its own ``extra=`` and
114
+ ``json_schema_extra`` exactly as before. This base unifies the *provider-safety
115
+ guarantee*, not the per-model config (centralizing config is a separate change —
116
+ ``extra=`` is not uniform across models, so a blanket dedup would silently shift
117
+ validation/serialization behavior).
118
+ """
119
+
120
+
121
+ def find_schema_keyword(node: Any, keyword: str) -> bool:
122
+ """Report whether ``keyword`` appears as a JSON-Schema *keyword* anywhere in ``node``.
123
+
124
+ Structure-aware: an occurrence of ``keyword`` as a property/``$defs`` *name*
125
+ (e.g. a model field literally named ``oneOf``) is NOT a match — only an
126
+ occurrence in JSON-Schema keyword position counts. Use this (not a blind
127
+ ``in``-walk) to check a schema for provider-unsafe keywords.
128
+
129
+ Args:
130
+ node (Any): A JSON-schema fragment (dict, list, or scalar).
131
+ keyword (str): The JSON-Schema keyword to search for (e.g. ``"oneOf"``).
132
+
133
+ Returns:
134
+ bool: True if ``keyword`` appears in keyword position, else False.
135
+ """
136
+ if isinstance(node, dict):
137
+ if keyword in node:
138
+ return True
139
+ for key, value in node.items():
140
+ if key in _SCHEMA_NAME_MAP_KEYS and isinstance(value, dict):
141
+ if any(find_schema_keyword(sub, keyword) for sub in value.values()):
142
+ return True
143
+ elif find_schema_keyword(value, keyword):
144
+ return True
145
+ return False
146
+ if isinstance(node, list):
147
+ return any(find_schema_keyword(item, keyword) for item in node)
148
+ return False
@@ -23,7 +23,7 @@ Client (SDK/Web)
23
23
  -> GenerationService (server/services/)
24
24
  ├─> ProfileGenerationService -> ProfileExtractor(s) -> Storage
25
25
  ├─> PlaybookGenerationService -> PlaybookExtractor(s) -> Storage
26
- └─> GroupEvaluationScheduler (deferred 10 min) -> Evaluator(s) -> Storage
26
+ └─> agent_success_evaluation/scheduler.py:GroupEvaluationScheduler (deferred 10 min) -> agent_success_evaluation/runner.py:run_group_evaluation -> agent_success_evaluation/service.py -> agent_success_evaluation/components/evaluator.py -> Storage
27
27
  ```
28
28
 
29
29
  ## Prerequisites
@@ -41,7 +41,7 @@ cp .env.example .env # Configure environment (set at lea
41
41
  uv sync # Install Python dependencies (includes workspace packages)
42
42
  npm --prefix src/website install # Install frontend dependencies
43
43
  npm --prefix src/public_docs install # Install docs dependencies
44
- ./run_services.sh # Starts API (8081), Website (8080), Docs (8082)
44
+ ./run_services.sh # Starts API (8061), Website (8080), Docs (8062)
45
45
  ./stop_services.sh # Stop all services
46
46
  ```
47
47
 
@@ -56,7 +56,7 @@ npm --prefix src/public_docs install # Install docs dependencies
56
56
  **Testing:**
57
57
  ```python
58
58
  import reflexio
59
- client = reflexio.ReflexioClient(api_key="your-api-key", url_endpoint="http://127.0.0.1:8081/")
59
+ client = reflexio.ReflexioClient(api_key="your-api-key", url_endpoint="http://127.0.0.1:8061/")
60
60
  ```
61
61
  See `notebooks/reflexio_cookbook.ipynb` and `src/tests/readme.md`
62
62
 
@@ -19,6 +19,7 @@ Description: FastAPI backend server that processes user interactions to generate
19
19
  - [Reflection and Async Extraction](#reflection-and-async-extraction)
20
20
  - [Shadow Comparison and Evaluation Overview](#shadow-comparison-and-evaluation-overview)
21
21
  - [Playbook Optimizer and Braintrust](#playbook-optimizer-and-braintrust)
22
+ - [Lineage](#lineage)
22
23
  - [Query Reformulator](#query-reformulator)
23
24
  - [Unified Search Service](#unified-search-service)
24
25
  - [Storage](#storage)
@@ -182,10 +183,11 @@ python -m reflexio.server.scripts.manage_invitation_codes list --show-used
182
183
  - **Publish pipeline**: `generation_service.py` coordinates interaction persistence, profile generation, playbook generation, reflection, and deferred evaluation scheduling.
183
184
  - **Profile memory**: `profile/` extracts, deduplicates, and applies user profile updates.
184
185
  - **Playbook memory**: `playbook/` extracts user playbooks, consolidates them against existing rows, aggregates them into agent playbooks, and tracks aggregation change logs.
185
- - **Evaluation**: `agent_success_evaluation/`, `shadow_comparison/`, and `evaluation_overview/` handle session grading, per-turn shadow verdicts, regeneration jobs, and dashboard-facing rollups.
186
+ - **Evaluation**: `agent_success_evaluation/service.py`, `agent_success_evaluation/runner.py`, `agent_success_evaluation/scheduler.py`, `agent_success_evaluation/components/evaluator.py`, `shadow_comparison/`, and `evaluation_overview/` handle session grading, per-turn shadow verdicts, regeneration jobs, and dashboard-facing rollups.
186
187
  - **Async clarification**: `extraction/` and `reflection/` manage resumable agent runs, pending tool calls, prior-answer search, and long-horizon reflection updates.
187
188
  - **Search preparation**: `pre_retrieval/` and `unified_search_service.py` handle query reformulation, document expansion, embeddings, and cross-entity search orchestration.
188
189
  - **Optimization/integrations**: `playbook_optimizer/` and `braintrust/` run candidate playbook optimization, rollout support, and Braintrust export/sync.
190
+ - **Lineage**: `lineage/` resolves active records across superseded chains and schedules tombstone garbage collection for profile/playbook storage.
189
191
  - **Persistence/config**: `storage/`, `configurator/`, and `operation_state_utils.py` provide storage abstractions, config loading, locks, bookmarks, progress, and cancellation.
190
192
 
191
193
  ### Orchestrator
@@ -221,7 +223,7 @@ Called by API endpoints via `Reflexio`
221
223
  - `extractor_config_utils.py`: Shared utility for filtering extractor configs by source, `allow_manual_trigger`, and extractor names
222
224
  - `extractor_interaction_utils.py`: Per-extractor utilities for stride_size checking and source filtering
223
225
  - `operation_state_utils.py`: Centralized `OperationStateManager` for all `_operation_state` table interactions (progress tracking, concurrency locks, extractor/aggregator bookmarks, simple locks)
224
- - `deduplication_utils.py`: Shared utilities for LLM-based deduplication (used by ProfileDeduplicator and PlaybookConsolidator)
226
+ - `deduplication_utils.py`: Shared utilities for LLM-based deduplication (used by ProfileConsolidator and PlaybookConsolidator)
225
227
  - `service_utils.py`: Utilities (`construct_messages_from_interactions()`, `format_interactions_to_history_string()` (prepends tool usage info when `tools_used` is present), `extract_json_from_string()`, `log_model_response()` for colored LLM response logging)
226
228
 
227
229
  **Operation State Management** (via `OperationStateManager` in `operation_state_utils.py`):
@@ -242,12 +244,11 @@ Called by API endpoints via `Reflexio`
242
244
  **Directory**: `services/profile/`
243
245
 
244
246
  Key files:
245
- - `profile_generation_service.py`: Service orchestrator
246
- - `profile_extractor.py`: Extractor that generates profile updates
247
- - `profile_updater.py`: Applies updates (add/delete/mention) to storage
248
- - `profile_deduplicator.py`: Deduplicates newly extracted profiles against existing DB profiles using LLM
247
+ - `service.py`: Service orchestrator and profile persistence/finalization
248
+ - `components/extractor.py`: Extractor that generates profile updates
249
+ - `components/consolidator.py`: Consolidates newly extracted profiles against existing DB profiles using LLM
249
250
 
250
- **Flow**: Interactions → ProfileExtractor (extraction-only) → ProfileDeduplicator (deduplicates new vs existing DB profiles) → ProfileUpdater → Storage
251
+ **Flow**: Interactions → ProfileExtractor (extraction-only) → ProfileConsolidator (deduplicates new vs existing DB profiles) → ProfileGenerationService → Storage
251
252
 
252
253
  **Generation Modes** (detailed comparison):
253
254
 
@@ -308,10 +309,10 @@ Users can regenerate and manage profile versions using a four-state system:
308
309
  **Detailed Documentation**: See [`services/playbook/README.md`](services/playbook/README.md) for detailed component documentation.
309
310
 
310
311
  Key files:
311
- - `playbook_generation_service.py`: Service orchestrator
312
- - `playbook_extractor.py`: Extractor that extracts user playbooks
313
- - `playbook_aggregator.py`: Aggregates similar user playbooks (with cluster-level change detection to skip unchanged clusters)
314
- - `playbook_consolidator.py`: Reconciles newly extracted playbooks against existing DB playbooks using LLM
312
+ - `service.py`: Service orchestrator
313
+ - `components/extractor.py`: Extractor that extracts user playbooks
314
+ - `components/aggregator.py`: Aggregates similar user playbooks (with cluster-level change detection to skip unchanged clusters)
315
+ - `components/consolidator.py`: Reconciles newly extracted playbooks against existing DB playbooks using LLM
315
316
 
316
317
  **Flow**:
317
318
  - Interactions → PlaybookExtractor (extraction-only) → PlaybookConsolidator (consolidates new vs existing DB playbooks) → UserPlaybook (with optional `blocking_issue`) → Storage
@@ -321,7 +322,7 @@ Key files:
321
322
 
322
323
  **Rerun Behavior**: Groups interactions by `user_id` for per-user playbook extraction (fetches all users, then processes each user's interactions together)
323
324
 
324
- **Playbook Aggregation with Cluster Change Detection** (`playbook_aggregator.py`):
325
+ **Playbook Aggregation with Cluster Change Detection** (`components/aggregator.py`):
325
326
 
326
327
  Aggregation clusters user playbooks by embedding similarity, then calls LLM per cluster to produce aggregated agent playbooks. Cluster-level change detection avoids redundant LLM calls on subsequent runs:
327
328
 
@@ -339,7 +340,7 @@ Aggregation clusters user playbooks by embedding similarity, then calls LLM per
339
340
  | No changes | Logs skip message, updates bookmark, returns early |
340
341
  | Error during save | Restores only selectively archived playbooks |
341
342
 
342
- **Change Log Tracking**: After each aggregation run, a `PlaybookAggregationChangeLog` is saved with before/after snapshots of added, removed, and updated playbooks. Viewable via `GET /api/playbook_aggregation_change_logs`. Change log saving is best-effort (failures are logged but don't block aggregation).
343
+ **Change Log Tracking**: The legacy `playbook_aggregation_change_logs` table is retired (Track B, 2026-06-24) — the aggregator no longer writes it. The change-log view served by `GET /api/playbook_aggregation_change_logs` is reconstructed on demand from `lineage_event` rows via `reconstruct_playbook_aggregation_change_log` (`lib/_agent_playbook.py`): each run's `op=aggregate` events form the "added" side and its `status_change→superseded` events form the "removed" side, grouped by `request_id`. Per-row `updated` pairing is not reconstructed (`updated_agent_playbooks=[]`, a tolerated parity delta).
343
344
 
344
345
  **Generation Modes** (detailed comparison):
345
346
 
@@ -381,16 +382,16 @@ Similar to profiles, user playbooks support versioning:
381
382
  **Directory**: `services/agent_success_evaluation/`
382
383
 
383
384
  Key files:
384
- - `agent_success_evaluation_service.py`: Service orchestrator (tracks run outcome flags: `last_run_result_count`, `has_run_failures()`)
385
- - `agent_success_evaluator.py`: Evaluates success at session level (all interactions as one group)
385
+ - `service.py`: `AgentSuccessEvaluationService`, the request-path service orchestrator (tracks run outcome flags: `last_run_result_count`, `has_run_failures()`)
386
+ - `components/evaluator.py`: `AgentSuccessEvaluator`, evaluates success at session level (all interactions as one group)
386
387
  - `agent_success_evaluation_constants.py`: Output schema (`AgentSuccessEvaluationOutput`)
387
388
  - `agent_success_evaluation_utils.py`: Message construction utilities
388
- - `delayed_group_evaluator.py`: `GroupEvaluationScheduler` singleton - min-heap priority queue with daemon thread, defers evaluation until 10 min after last request in session
389
- - `group_evaluation_runner.py`: `run_group_evaluation()` - fetches all requests/interactions for a session, builds `RequestInteractionDataModel` list, runs evaluation
389
+ - `scheduler.py`: `GroupEvaluationScheduler` singleton - min-heap priority queue with daemon thread, defers evaluation until 10 min after last request in session
390
+ - `runner.py`: `run_group_evaluation()` - fetches all requests/interactions for a session, builds `RequestInteractionDataModel` list, runs `service.py`
390
391
 
391
- **Flow**: Interactions → (deferred 10 min) GroupEvaluationSchedulerrun_group_evaluationAgentSuccessEvaluator → AgentSuccessEvaluationResult → Storage
392
+ **Flow**: Interactions → `agent_success_evaluation/scheduler.py``agent_success_evaluation/runner.py``agent_success_evaluation/service.py``agent_success_evaluation/components/evaluator.py``AgentSuccessEvaluationResult` → Storage
392
393
 
393
- **Session-Level Evaluation**: Evaluator treats all `request_interaction_data_models` in a session as a single conversation. Sampling rate checked once per session (not per-request). Result keyed by `session_id` (not `request_id`).
394
+ **Session-Level Evaluation**: Evaluator treats one user's `request_interaction_data_models` in a session as a single conversation. Sampling rate checked once per session (not per-request). Results are keyed by `(user_id, session_id, evaluation_name)` so reused session IDs across users do not clobber each other.
394
395
 
395
396
  **Tool Context**: Reads `tool_can_use` from root `Config` level (shared with playbook extraction).
396
397
 
@@ -401,14 +402,14 @@ Key files:
401
402
  **Directories**: `services/reflection/`, `services/extraction/`
402
403
 
403
404
  Key files:
404
- - `reflection/reflection_service.py`: Post-horizon reflection orchestration for synthesizing longer-range memory artifacts
405
- - `reflection/reflection_extractor.py`: LLM extractor used by the reflection service
405
+ - `reflection/service.py`: Post-horizon reflection orchestration for synthesizing longer-range memory artifacts
406
+ - `reflection/components/extractor.py`: LLM extractor used by the reflection service
406
407
  - `extraction/resumable_agent.py`: Resumable extraction agent runtime
407
408
  - `extraction/resume_scheduler.py` and `extraction/resume_worker.py`: Background scheduling/worker loop for paused extraction runs
408
- - `extraction/tools.py` and `extraction/prior_answer_search.py`: Tool surface for async extraction agents
409
+ - `extraction/pending_tool_call_dispatch.py` and `extraction/prior_answer_search.py`: Tool surface and prior-answer context for async extraction agents
409
410
  - `extraction/agent_run_records.py`: Persistence helpers for extraction-agent run state
410
411
 
411
- **Pattern**: Synchronous profile/playbook/evaluation services still follow `BaseGenerationService`; async extraction uses resumable agent-run records and worker scheduling so long-running or tool-mediated extraction can continue outside the request path.
412
+ **Pattern**: Synchronous profile/playbook/evaluation services still follow `BaseGenerationService`; async extraction is a shared runtime package that uses resumable agent-run records and worker scheduling so long-running or tool-mediated extraction can continue outside the request path.
412
413
 
413
414
  ### Shadow Comparison and Evaluation Overview
414
415
 
@@ -418,7 +419,8 @@ Key files:
418
419
  - `shadow_comparison/judge.py`: Per-turn regular-vs-shadow judge that writes shadow verdicts through storage
419
420
  - `shadow_comparison/outcome.py`: Verdict outcome model helpers
420
421
  - `evaluation_overview/service.py`: Aggregates evaluation-page metrics
421
- - `evaluation_overview/hero_state.py`, `distribution.py`, `group_aggregation.py`, `rule_attribution.py`, `shadow_aggregation.py`: Focused aggregation helpers
422
+ - `evaluation_overview/components/hero_state.py`, `evaluation_overview/components/distribution.py`, `evaluation_overview/components/rule_attribution.py`, `evaluation_overview/components/shadow_aggregation.py`: Focused aggregation helpers
423
+ - `evaluation_overview/eval_sampler.py`: Evaluation sampling helpers that remain root-level
422
424
 
423
425
  **Pattern**: Session-level agent success evaluation remains in `agent_success_evaluation/`; dashboard-facing rollups and per-turn shadow verdict analysis live in these companion directories.
424
426
 
@@ -435,6 +437,17 @@ Key files:
435
437
 
436
438
  **Pattern**: These are evaluation/optimization integrations around the core playbook pipeline. Keep production extraction changes in `services/playbook/`; use optimizer/Braintrust modules for experiments, rollouts, and external eval sync.
437
439
 
440
+ ### Lineage
441
+
442
+ **Directory**: `services/lineage/`
443
+
444
+ | File | Purpose |
445
+ |------|---------|
446
+ | `resolve.py` | Helpers for resolving current records across supersede chains and status transitions. |
447
+ | `gc_scheduler.py` | Tombstone garbage-collection scheduler for lineage-aware storage cleanup. |
448
+
449
+ **Pattern**: profile/playbook update paths preserve lineage metadata in storage; service code asks lineage helpers to find current records rather than walking superseded chains ad hoc.
450
+
438
451
  ### Query Reformulator
439
452
 
440
453
  **File**: `services/pre_retrieval/_query_reformulator.py` - `QueryReformulator`
@@ -464,8 +477,8 @@ Pre-computed embeddings passed to storage methods via `query_embedding` paramete
464
477
 
465
478
  | File | Purpose |
466
479
  |------|---------|
467
- | `storage_base/` | BaseStorage interface split by domain (`_profiles.py`, `_playbook.py`, `_requests.py`, `_operations.py`, `_agent_run.py`, `_shadow_verdicts.py`, `_stall_state.py`, `_share_links.py`) |
468
- | `sqlite_storage/` | SQLite-backed implementation split across the same domains |
480
+ | `storage_base/` | BaseStorage interface split by domain (`_profiles.py`, `_playbook.py`, `_requests.py`, `_operations.py`, `_agent_run.py`, `_lineage.py`, `_shadow_verdicts.py`, `_stall_state.py`, `_share_links.py`) |
481
+ | `sqlite_storage/` | SQLite-backed implementation split across the same domains, including lineage/tombstone support in `_lineage.py` |
469
482
  | `retention.py`, `retention_mixin.py` | Data retention and cleanup helpers |
470
483
  | `constants.py`, `error.py` | Storage constants and shared errors |
471
484
 
@@ -513,7 +526,7 @@ API Request (api.py)
513
526
  -> GenerationService
514
527
  ├─> ProfileGenerationService → Storage
515
528
  ├─> PlaybookGenerationService → Storage
516
- └─> GroupEvaluationScheduler (deferred 10 min) → run_group_evaluation → Storage
529
+ └─> agent_success_evaluation/scheduler.py:GroupEvaluationScheduler (deferred 10 min) → agent_success_evaluation/runner.py:run_group_evaluation → agent_success_evaluation/service.py → Storage
517
530
  ```
518
531
 
519
532
  ```mermaid
@@ -529,9 +542,9 @@ flowchart TB
529
542
  subgraph ProfileService["ProfileGenerationService"]
530
543
  E --> F1[ProfileExtractor 1]
531
544
  E --> F2[ProfileExtractor N]
532
- F1 --> PD[ProfileDeduplicator]
533
- F2 --> PD
534
- PD --> PU[ProfileUpdater]
545
+ F1 --> PC[ProfileConsolidator]
546
+ F2 --> PC
547
+ PC --> PU[ProfileUpdater]
535
548
  end
536
549
 
537
550
  subgraph PlaybookService["PlaybookGenerationService"]
@@ -542,7 +555,7 @@ flowchart TB
542
555
  end
543
556
 
544
557
  subgraph EvalService["AgentSuccessEvaluationService"]
545
- E -.->|deferred 10 min| SCH[GroupEvaluationScheduler]
558
+ E -.->|deferred 10 min| SCH[agent_success_evaluation/scheduler.py<br/>GroupEvaluationScheduler]
546
559
  SCH --> H1[AgentSuccessEvaluator 1]
547
560
  SCH --> H2[AgentSuccessEvaluator N]
548
561
  end
@@ -561,7 +574,7 @@ flowchart TB
561
574
  J -.-> F1
562
575
  J -.-> G1
563
576
  J -.-> H1
564
- J -.-> PD
577
+ J -.-> PC
565
578
  J -.-> FD
566
579
  K -.-> F1
567
580
  K -.-> G1
@@ -38,9 +38,6 @@ LOCAL_STORAGE_PATH = (
38
38
  INTERACTION_CLEANUP_THRESHOLD = int(
39
39
  os.environ.get("INTERACTION_CLEANUP_THRESHOLD", "250000")
40
40
  )
41
- INTERACTION_CLEANUP_DELETE_COUNT = int(
42
- os.environ.get("INTERACTION_CLEANUP_DELETE_COUNT", "50000")
43
- )
44
41
 
45
42
  # Logging
46
43
 
@@ -131,10 +128,37 @@ class _LLMIOFormatter(_TZAwareFormatter):
131
128
  )
132
129
 
133
130
 
134
- DEBUG_LOG_TO_CONSOLE = os.environ.get("DEBUG_LOG_TO_CONSOLE", "").strip().lower()
131
+ def _truthy_env(name: str) -> bool:
132
+ """Return whether an environment variable is explicitly truthy."""
133
+ raw = os.environ.get(name, "").strip().lower()
134
+ return raw in ("true", "yes", "1", "on")
135
+
136
+
137
+ def _is_production_environment() -> bool:
138
+ """Return whether this process is running in a production deployment."""
139
+ return os.environ.get("ENVIRONMENT", "").strip().lower() in ("prod", "production")
140
+
141
+
142
+ def _debug_log_to_console_enabled() -> bool:
143
+ """Return whether verbose console logging should be enabled.
144
+
145
+ ``DEBUG_LOG_TO_CONSOLE`` is a local/dev switch. Deployments with
146
+ ``ENVIRONMENT=production`` must stay quiet by default even if a copied local
147
+ env file accidentally sets it;
148
+ use ``REFLEXIO_ALLOW_PRODUCTION_DEBUG_LOGS=true`` for a deliberate incident
149
+ override.
150
+ """
151
+ if not _truthy_env("DEBUG_LOG_TO_CONSOLE"):
152
+ return False
153
+ return not _is_production_environment() or _truthy_env(
154
+ "REFLEXIO_ALLOW_PRODUCTION_DEBUG_LOGS"
155
+ )
156
+
157
+
158
+ DEBUG_LOG_TO_CONSOLE = _debug_log_to_console_enabled()
135
159
  root_logger = logging.getLogger()
136
160
 
137
- if DEBUG_LOG_TO_CONSOLE and DEBUG_LOG_TO_CONSOLE not in ("false", "0", "no"):
161
+ if DEBUG_LOG_TO_CONSOLE:
138
162
  # Correlation ID filter — injects %(correlation_id)s into every record
139
163
  from reflexio.server.correlation import CorrelationIdFilter
140
164
 
@@ -3,10 +3,10 @@
3
3
  Run the FastAPI backend with Reflexio's uvicorn log config applied upfront::
4
4
 
5
5
  # Dev mode (autoreload, single process):
6
- python -m reflexio.server --port 8081 --reload
6
+ python -m reflexio.server --port 8061 --reload
7
7
 
8
8
  # Daemon mode (multi-worker with recycling):
9
- python -m reflexio.server --port 8081 --workers 2 --max-requests 10000
9
+ python -m reflexio.server --port 8061 --workers 2 --max-requests 10000
10
10
 
11
11
  Flags mirror the subset of ``uvicorn`` CLI options that
12
12
  :func:`reflexio.cli.run_services.build_backend_service` uses.
@@ -9,17 +9,80 @@ import graph acyclic.
9
9
 
10
10
  from __future__ import annotations
11
11
 
12
+ from collections.abc import Callable
13
+ from functools import cache
14
+
12
15
  DEFAULT_ORG_ID = "self-host-org"
13
16
 
14
17
 
15
18
  def default_get_org_id() -> str:
16
19
  """Return the default organization ID for local hosting.
17
20
 
18
- Enterprise deployments override this via
21
+ Reads ``REFLEXIO_DEFAULT_ORG_ID`` (unset/blank falls back to
22
+ :data:`DEFAULT_ORG_ID`) so a no-auth deployment can run under a distinct
23
+ org id without colliding with another local backend that shares
24
+ ``~/.reflexio/configs/``. claude-smart and the self-host backend otherwise
25
+ both default to ``self-host-org`` and fight over the same
26
+ ``config_self-host-org.json``.
27
+
28
+ Enterprise deployments never reach this: they override the dependency via
19
29
  ``app.dependency_overrides[default_get_org_id] = <bearer_auth_resolver>``
20
30
  inside :func:`reflexio.server.api.create_app`.
21
31
 
22
32
  Returns:
23
33
  str: The default org identifier used for self-hosted deployments.
24
34
  """
25
- return DEFAULT_ORG_ID
35
+ # Lazy import keeps this deliberately cycle-free module independent of the
36
+ # ``reflexio.server`` package init (see module docstring).
37
+ from reflexio.server.env_utils import env_str
38
+
39
+ return env_str("REFLEXIO_DEFAULT_ORG_ID", DEFAULT_ORG_ID)
40
+
41
+
42
+ def default_get_caller_type() -> str:
43
+ """Return the default caller type for local / self-hosted deployments.
44
+
45
+ Every call is treated as ``"internal"`` (no billing discrimination) in the
46
+ OSS build. Enterprise deployments override this via
47
+ ``app.dependency_overrides[default_get_caller_type] = <classifier>``
48
+ inside :func:`reflexio.server.api.create_app`, exactly like
49
+ :func:`default_get_org_id`.
50
+
51
+ Returns:
52
+ str: The literal ``"internal"`` — equals ``BillingCallerType.INTERNAL.value``
53
+ (kept as a plain string here so OSS stays free of reflexio_ext imports).
54
+ """
55
+ return "internal" # == BillingCallerType.INTERNAL.value; literal keeps OSS clean
56
+
57
+
58
+ @cache
59
+ def default_billing_gate(line: str) -> Callable[..., None]: # noqa: ARG001
60
+ """Return a stable no-op FastAPI dependency for the billing gate.
61
+
62
+ OSS / self-hosted deployments run without enforcement — this factory
63
+ always returns a dependency that does nothing. Enterprise deployments
64
+ supply a real gate factory via the ``get_billing_gate`` parameter of
65
+ :func:`reflexio.server.api.create_app`, exactly mirroring how
66
+ ``get_caller_type`` overrides :func:`default_get_caller_type`.
67
+
68
+ ``lru_cache`` ensures the **same callable object** is returned for the
69
+ same ``line`` value. FastAPI uses callable identity for
70
+ ``dependency_overrides``, so caching is essential: without it, each
71
+ ``Depends(default_billing_gate("application"))`` would create a fresh
72
+ closure and overrides would silently never fire.
73
+
74
+ OSS code must never import from ``reflexio_ext`` — the gate wiring is
75
+ purely additive and backwards-compatible.
76
+
77
+ Args:
78
+ line (str): Billing line (e.g. ``"application"``, ``"learnings_generated"``).
79
+ Accepted but unused in the default no-op implementation.
80
+
81
+ Returns:
82
+ Callable[..., None]: A FastAPI dependency that always passes through.
83
+ """
84
+
85
+ def _noop() -> None:
86
+ """No-op billing gate for OSS / self-hosted deployments."""
87
+
88
+ return _noop