chuzom-router 0.3.1__tar.gz

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 (329) hide show
  1. chuzom_router-0.3.1/.gitignore +71 -0
  2. chuzom_router-0.3.1/.rules +50 -0
  3. chuzom_router-0.3.1/CHANGELOG.md +219 -0
  4. chuzom_router-0.3.1/CONTRIBUTING.md +145 -0
  5. chuzom_router-0.3.1/LICENSE +21 -0
  6. chuzom_router-0.3.1/PKG-INFO +423 -0
  7. chuzom_router-0.3.1/README.md +354 -0
  8. chuzom_router-0.3.1/assets/hero-light.svg +243 -0
  9. chuzom_router-0.3.1/config/agents.yaml +61 -0
  10. chuzom_router-0.3.1/config/models.yaml +161 -0
  11. chuzom_router-0.3.1/config/signals.yaml +95 -0
  12. chuzom_router-0.3.1/deploy/README.md +62 -0
  13. chuzom_router-0.3.1/deploy/helm/chuzom/Chart.yaml +11 -0
  14. chuzom_router-0.3.1/deploy/helm/chuzom/templates/_helpers.tpl +17 -0
  15. chuzom_router-0.3.1/deploy/helm/chuzom/templates/deployment.yaml +72 -0
  16. chuzom_router-0.3.1/deploy/helm/chuzom/templates/ingress.yaml +33 -0
  17. chuzom_router-0.3.1/deploy/helm/chuzom/templates/secret.yaml +20 -0
  18. chuzom_router-0.3.1/deploy/helm/chuzom/templates/service.yaml +15 -0
  19. chuzom_router-0.3.1/deploy/helm/chuzom/values.yaml +68 -0
  20. chuzom_router-0.3.1/deploy/systemd/chuzom.service +29 -0
  21. chuzom_router-0.3.1/pyproject.toml +217 -0
  22. chuzom_router-0.3.1/src/chuzom/__init__.py +34 -0
  23. chuzom_router-0.3.1/src/chuzom/admin_actions.py +210 -0
  24. chuzom_router-0.3.1/src/chuzom/admin_api.py +1410 -0
  25. chuzom_router-0.3.1/src/chuzom/agents/__init__.py +39 -0
  26. chuzom_router-0.3.1/src/chuzom/agents/base.py +207 -0
  27. chuzom_router-0.3.1/src/chuzom/agents/budget.py +139 -0
  28. chuzom_router-0.3.1/src/chuzom/agents/registry.py +95 -0
  29. chuzom_router-0.3.1/src/chuzom/agents/session.py +690 -0
  30. chuzom_router-0.3.1/src/chuzom/audit_routing.py +158 -0
  31. chuzom_router-0.3.1/src/chuzom/auto_profile.py +458 -0
  32. chuzom_router-0.3.1/src/chuzom/bandit.py +146 -0
  33. chuzom_router-0.3.1/src/chuzom/banner.py +283 -0
  34. chuzom_router-0.3.1/src/chuzom/banner_art.txt +76 -0
  35. chuzom_router-0.3.1/src/chuzom/benchmark/__init__.py +172 -0
  36. chuzom_router-0.3.1/src/chuzom/benchmark/regression.py +318 -0
  37. chuzom_router-0.3.1/src/chuzom/benchmark/runners/__init__.py +7 -0
  38. chuzom_router-0.3.1/src/chuzom/benchmark/runners/routerarena.py +173 -0
  39. chuzom_router-0.3.1/src/chuzom/benchmark_fetcher.py +627 -0
  40. chuzom_router-0.3.1/src/chuzom/benchmarks.py +662 -0
  41. chuzom_router-0.3.1/src/chuzom/budget.py +470 -0
  42. chuzom_router-0.3.1/src/chuzom/budget_backend.py +711 -0
  43. chuzom_router-0.3.1/src/chuzom/budget_backend_postgres.py +430 -0
  44. chuzom_router-0.3.1/src/chuzom/budget_envelope.py +361 -0
  45. chuzom_router-0.3.1/src/chuzom/budget_key.py +120 -0
  46. chuzom_router-0.3.1/src/chuzom/budget_store.py +77 -0
  47. chuzom_router-0.3.1/src/chuzom/cache/__init__.py +36 -0
  48. chuzom_router-0.3.1/src/chuzom/cache/classification.py +270 -0
  49. chuzom_router-0.3.1/src/chuzom/cache/store.py +45 -0
  50. chuzom_router-0.3.1/src/chuzom/calibration.py +231 -0
  51. chuzom_router-0.3.1/src/chuzom/caveman.py +117 -0
  52. chuzom_router-0.3.1/src/chuzom/chain_builder.py +162 -0
  53. chuzom_router-0.3.1/src/chuzom/classification_allowlist.py +137 -0
  54. chuzom_router-0.3.1/src/chuzom/classifier.py +306 -0
  55. chuzom_router-0.3.1/src/chuzom/claude_usage.py +513 -0
  56. chuzom_router-0.3.1/src/chuzom/cli.py +728 -0
  57. chuzom_router-0.3.1/src/chuzom/cli_init_memory.py +95 -0
  58. chuzom_router-0.3.1/src/chuzom/cli_init_policy.py +279 -0
  59. chuzom_router-0.3.1/src/chuzom/code_context.py +458 -0
  60. chuzom_router-0.3.1/src/chuzom/codex_agent.py +359 -0
  61. chuzom_router-0.3.1/src/chuzom/commands/admin_actions.py +175 -0
  62. chuzom_router-0.3.1/src/chuzom/commands/admin_api.py +110 -0
  63. chuzom_router-0.3.1/src/chuzom/commands/audit.py +100 -0
  64. chuzom_router-0.3.1/src/chuzom/commands/benchmark.py +238 -0
  65. chuzom_router-0.3.1/src/chuzom/commands/budget.py +142 -0
  66. chuzom_router-0.3.1/src/chuzom/commands/config.py +212 -0
  67. chuzom_router-0.3.1/src/chuzom/commands/dashboard.py +26 -0
  68. chuzom_router-0.3.1/src/chuzom/commands/demo.py +199 -0
  69. chuzom_router-0.3.1/src/chuzom/commands/dev_refresh.py +161 -0
  70. chuzom_router-0.3.1/src/chuzom/commands/doctor.py +828 -0
  71. chuzom_router-0.3.1/src/chuzom/commands/explain_dashboard.py +348 -0
  72. chuzom_router-0.3.1/src/chuzom/commands/gain.py +473 -0
  73. chuzom_router-0.3.1/src/chuzom/commands/install.py +863 -0
  74. chuzom_router-0.3.1/src/chuzom/commands/last.py +161 -0
  75. chuzom_router-0.3.1/src/chuzom/commands/migrate.py +141 -0
  76. chuzom_router-0.3.1/src/chuzom/commands/onboard.py +171 -0
  77. chuzom_router-0.3.1/src/chuzom/commands/policy.py +119 -0
  78. chuzom_router-0.3.1/src/chuzom/commands/profile.py +63 -0
  79. chuzom_router-0.3.1/src/chuzom/commands/replay.py +257 -0
  80. chuzom_router-0.3.1/src/chuzom/commands/retrospect.py +111 -0
  81. chuzom_router-0.3.1/src/chuzom/commands/routing.py +183 -0
  82. chuzom_router-0.3.1/src/chuzom/commands/savings_report.py +345 -0
  83. chuzom_router-0.3.1/src/chuzom/commands/serve.py +70 -0
  84. chuzom_router-0.3.1/src/chuzom/commands/set_enforce.py +117 -0
  85. chuzom_router-0.3.1/src/chuzom/commands/setup.py +152 -0
  86. chuzom_router-0.3.1/src/chuzom/commands/share.py +301 -0
  87. chuzom_router-0.3.1/src/chuzom/commands/snapshot.py +222 -0
  88. chuzom_router-0.3.1/src/chuzom/commands/sse.py +91 -0
  89. chuzom_router-0.3.1/src/chuzom/commands/stats.py +41 -0
  90. chuzom_router-0.3.1/src/chuzom/commands/status.py +296 -0
  91. chuzom_router-0.3.1/src/chuzom/commands/team.py +189 -0
  92. chuzom_router-0.3.1/src/chuzom/commands/team_sync.py +121 -0
  93. chuzom_router-0.3.1/src/chuzom/commands/test.py +111 -0
  94. chuzom_router-0.3.1/src/chuzom/commands/uninstall.py +78 -0
  95. chuzom_router-0.3.1/src/chuzom/commands/update.py +94 -0
  96. chuzom_router-0.3.1/src/chuzom/commands/verify.py +324 -0
  97. chuzom_router-0.3.1/src/chuzom/commands/verify_enterprise.py +415 -0
  98. chuzom_router-0.3.1/src/chuzom/commands/welcome.py +33 -0
  99. chuzom_router-0.3.1/src/chuzom/community.py +189 -0
  100. chuzom_router-0.3.1/src/chuzom/compaction.py +318 -0
  101. chuzom_router-0.3.1/src/chuzom/compression/__init__.py +33 -0
  102. chuzom_router-0.3.1/src/chuzom/compression/response_compressor.py +379 -0
  103. chuzom_router-0.3.1/src/chuzom/compression/rtk_adapter.py +379 -0
  104. chuzom_router-0.3.1/src/chuzom/config.py +514 -0
  105. chuzom_router-0.3.1/src/chuzom/context.py +417 -0
  106. chuzom_router-0.3.1/src/chuzom/context_optimizer.py +176 -0
  107. chuzom_router-0.3.1/src/chuzom/context_prep.py +150 -0
  108. chuzom_router-0.3.1/src/chuzom/contract.py +123 -0
  109. chuzom_router-0.3.1/src/chuzom/cost.py +3129 -0
  110. chuzom_router-0.3.1/src/chuzom/dashboard/__init__.py +0 -0
  111. chuzom_router-0.3.1/src/chuzom/dashboard/__main__.py +21 -0
  112. chuzom_router-0.3.1/src/chuzom/dashboard/server.py +1288 -0
  113. chuzom_router-0.3.1/src/chuzom/dashboard/tui.py +952 -0
  114. chuzom_router-0.3.1/src/chuzom/dashboard_data.py +397 -0
  115. chuzom_router-0.3.1/src/chuzom/data/__init__.py +0 -0
  116. chuzom_router-0.3.1/src/chuzom/data/benchmarks.json +242 -0
  117. chuzom_router-0.3.1/src/chuzom/decisions/__init__.py +14 -0
  118. chuzom_router-0.3.1/src/chuzom/decisions/engine.py +131 -0
  119. chuzom_router-0.3.1/src/chuzom/digest.py +243 -0
  120. chuzom_router-0.3.1/src/chuzom/discover.py +372 -0
  121. chuzom_router-0.3.1/src/chuzom/dynamic_routing.py +323 -0
  122. chuzom_router-0.3.1/src/chuzom/edit.py +253 -0
  123. chuzom_router-0.3.1/src/chuzom/error_sanitization.py +198 -0
  124. chuzom_router-0.3.1/src/chuzom/feedback.py +319 -0
  125. chuzom_router-0.3.1/src/chuzom/feedback_handler.py +249 -0
  126. chuzom_router-0.3.1/src/chuzom/forecast.py +148 -0
  127. chuzom_router-0.3.1/src/chuzom/frameworks/__init__.py +45 -0
  128. chuzom_router-0.3.1/src/chuzom/frameworks/agno.py +70 -0
  129. chuzom_router-0.3.1/src/chuzom/frameworks/base.py +46 -0
  130. chuzom_router-0.3.1/src/chuzom/frameworks/claude_agent_sdk.py +30 -0
  131. chuzom_router-0.3.1/src/chuzom/frameworks/crewai.py +30 -0
  132. chuzom_router-0.3.1/src/chuzom/frameworks/hermes.py +43 -0
  133. chuzom_router-0.3.1/src/chuzom/frameworks/langgraph.py +32 -0
  134. chuzom_router-0.3.1/src/chuzom/frameworks/openai_agents.py +31 -0
  135. chuzom_router-0.3.1/src/chuzom/frameworks/pydantic_ai.py +30 -0
  136. chuzom_router-0.3.1/src/chuzom/gates.py +182 -0
  137. chuzom_router-0.3.1/src/chuzom/gemini_cli_agent.py +236 -0
  138. chuzom_router-0.3.1/src/chuzom/gemini_cli_quota.py +319 -0
  139. chuzom_router-0.3.1/src/chuzom/health.py +275 -0
  140. chuzom_router-0.3.1/src/chuzom/hook_client.py +102 -0
  141. chuzom_router-0.3.1/src/chuzom/hook_deadlock_checker.py +46 -0
  142. chuzom_router-0.3.1/src/chuzom/hook_deadlock_detector.py +323 -0
  143. chuzom_router-0.3.1/src/chuzom/hook_health.py +284 -0
  144. chuzom_router-0.3.1/src/chuzom/hooks/agent-error.py +335 -0
  145. chuzom_router-0.3.1/src/chuzom/hooks/agent-route.py +620 -0
  146. chuzom_router-0.3.1/src/chuzom/hooks/agent_loop.py +363 -0
  147. chuzom_router-0.3.1/src/chuzom/hooks/auto-route.py +2714 -0
  148. chuzom_router-0.3.1/src/chuzom/hooks/bash-compress.py +208 -0
  149. chuzom_router-0.3.1/src/chuzom/hooks/cc-usage-track.py +178 -0
  150. chuzom_router-0.3.1/src/chuzom/hooks/chain_builder.py +240 -0
  151. chuzom_router-0.3.1/src/chuzom/hooks/codex-post-tool.py +85 -0
  152. chuzom_router-0.3.1/src/chuzom/hooks/cyber_grid.py +670 -0
  153. chuzom_router-0.3.1/src/chuzom/hooks/dashboard_enhanced.py +282 -0
  154. chuzom_router-0.3.1/src/chuzom/hooks/direct_executor.py +278 -0
  155. chuzom_router-0.3.1/src/chuzom/hooks/enforce-route.py +950 -0
  156. chuzom_router-0.3.1/src/chuzom/hooks/gemini-cli-auto-route.py +160 -0
  157. chuzom_router-0.3.1/src/chuzom/hooks/gemini-cli-post-tool.py +78 -0
  158. chuzom_router-0.3.1/src/chuzom/hooks/gemini-cli-session-end.py +198 -0
  159. chuzom_router-0.3.1/src/chuzom/hooks/lineage_integration.py +222 -0
  160. chuzom_router-0.3.1/src/chuzom/hooks/opencode-post-tool.py +78 -0
  161. chuzom_router-0.3.1/src/chuzom/hooks/playwright-compress.py +210 -0
  162. chuzom_router-0.3.1/src/chuzom/hooks/response-router.py +85 -0
  163. chuzom_router-0.3.1/src/chuzom/hooks/response_formatter.py +125 -0
  164. chuzom_router-0.3.1/src/chuzom/hooks/savings_logger.py +141 -0
  165. chuzom_router-0.3.1/src/chuzom/hooks/session-end-clawcode.py +258 -0
  166. chuzom_router-0.3.1/src/chuzom/hooks/session-end.py +1679 -0
  167. chuzom_router-0.3.1/src/chuzom/hooks/session-start.py +796 -0
  168. chuzom_router-0.3.1/src/chuzom/hooks/start-ollama.sh +92 -0
  169. chuzom_router-0.3.1/src/chuzom/hooks/status-bar-clawcode.py +125 -0
  170. chuzom_router-0.3.1/src/chuzom/hooks/status-bar.py +414 -0
  171. chuzom_router-0.3.1/src/chuzom/hooks/statusline-command.sh +332 -0
  172. chuzom_router-0.3.1/src/chuzom/hooks/stop-enforce.py +142 -0
  173. chuzom_router-0.3.1/src/chuzom/hooks/subagent-start.py +134 -0
  174. chuzom_router-0.3.1/src/chuzom/hooks/usage-refresh.py +174 -0
  175. chuzom_router-0.3.1/src/chuzom/hosts/__init__.py +17 -0
  176. chuzom_router-0.3.1/src/chuzom/hosts/base.py +25 -0
  177. chuzom_router-0.3.1/src/chuzom/hosts/cursor.py +50 -0
  178. chuzom_router-0.3.1/src/chuzom/hosts/gemini_cli.py +48 -0
  179. chuzom_router-0.3.1/src/chuzom/idempotency.py +223 -0
  180. chuzom_router-0.3.1/src/chuzom/identity.py +422 -0
  181. chuzom_router-0.3.1/src/chuzom/inference_robustness.py +158 -0
  182. chuzom_router-0.3.1/src/chuzom/input_validation.py +206 -0
  183. chuzom_router-0.3.1/src/chuzom/install_hooks.py +922 -0
  184. chuzom_router-0.3.1/src/chuzom/integrations/__init__.py +1 -0
  185. chuzom_router-0.3.1/src/chuzom/integrations/agno.py +375 -0
  186. chuzom_router-0.3.1/src/chuzom/integrations/helicone.py +142 -0
  187. chuzom_router-0.3.1/src/chuzom/integrations/litellm_budget.py +154 -0
  188. chuzom_router-0.3.1/src/chuzom/invoice_reconciliation/__init__.py +110 -0
  189. chuzom_router-0.3.1/src/chuzom/invoice_reconciliation/anthropic.py +148 -0
  190. chuzom_router-0.3.1/src/chuzom/invoice_reconciliation/gemini.py +235 -0
  191. chuzom_router-0.3.1/src/chuzom/invoice_reconciliation/openai.py +179 -0
  192. chuzom_router-0.3.1/src/chuzom/judge.py +266 -0
  193. chuzom_router-0.3.1/src/chuzom/judge_cascade.py +214 -0
  194. chuzom_router-0.3.1/src/chuzom/lineage/__init__.py +39 -0
  195. chuzom_router-0.3.1/src/chuzom/lineage/decision_logger.py +124 -0
  196. chuzom_router-0.3.1/src/chuzom/lineage/lineage_query.py +177 -0
  197. chuzom_router-0.3.1/src/chuzom/lineage/lineage_store.py +550 -0
  198. chuzom_router-0.3.1/src/chuzom/lineage/report_generator.py +160 -0
  199. chuzom_router-0.3.1/src/chuzom/lineage/types.py +222 -0
  200. chuzom_router-0.3.1/src/chuzom/logging.py +78 -0
  201. chuzom_router-0.3.1/src/chuzom/media.py +688 -0
  202. chuzom_router-0.3.1/src/chuzom/memory/__init__.py +26 -0
  203. chuzom_router-0.3.1/src/chuzom/memory/profiles.py +293 -0
  204. chuzom_router-0.3.1/src/chuzom/metrics.py +311 -0
  205. chuzom_router-0.3.1/src/chuzom/migrations/__init__.py +366 -0
  206. chuzom_router-0.3.1/src/chuzom/migrations/versions/001_create_chuzom_health.py +55 -0
  207. chuzom_router-0.3.1/src/chuzom/model_evaluator.py +341 -0
  208. chuzom_router-0.3.1/src/chuzom/model_registry.py +270 -0
  209. chuzom_router-0.3.1/src/chuzom/model_selector.py +213 -0
  210. chuzom_router-0.3.1/src/chuzom/model_tracking.py +499 -0
  211. chuzom_router-0.3.1/src/chuzom/monitoring/__init__.py +34 -0
  212. chuzom_router-0.3.1/src/chuzom/monitoring/live_tracker.py +153 -0
  213. chuzom_router-0.3.1/src/chuzom/monitoring/periodic.py +307 -0
  214. chuzom_router-0.3.1/src/chuzom/oauth_token_rotation.py +196 -0
  215. chuzom_router-0.3.1/src/chuzom/observability.py +388 -0
  216. chuzom_router-0.3.1/src/chuzom/onboard.py +156 -0
  217. chuzom_router-0.3.1/src/chuzom/orchestrator.py +262 -0
  218. chuzom_router-0.3.1/src/chuzom/org_policy.py +312 -0
  219. chuzom_router-0.3.1/src/chuzom/plugins/__init__.py +5 -0
  220. chuzom_router-0.3.1/src/chuzom/plugins/redaction.py +49 -0
  221. chuzom_router-0.3.1/src/chuzom/policies/aggressive.yaml +13 -0
  222. chuzom_router-0.3.1/src/chuzom/policies/balanced.yaml +13 -0
  223. chuzom_router-0.3.1/src/chuzom/policies/conservative.yaml +13 -0
  224. chuzom_router-0.3.1/src/chuzom/policies/cost_aggressive.yaml +149 -0
  225. chuzom_router-0.3.1/src/chuzom/policies/routerarena_tuned.yaml +115 -0
  226. chuzom_router-0.3.1/src/chuzom/policies/standard.yaml +178 -0
  227. chuzom_router-0.3.1/src/chuzom/policy.py +557 -0
  228. chuzom_router-0.3.1/src/chuzom/policy_diff.py +209 -0
  229. chuzom_router-0.3.1/src/chuzom/policy_versions.py +246 -0
  230. chuzom_router-0.3.1/src/chuzom/profile.py +124 -0
  231. chuzom_router-0.3.1/src/chuzom/profiles.py +496 -0
  232. chuzom_router-0.3.1/src/chuzom/prompt_cache.py +135 -0
  233. chuzom_router-0.3.1/src/chuzom/prompt_injection.py +147 -0
  234. chuzom_router-0.3.1/src/chuzom/prompts/__init__.py +1 -0
  235. chuzom_router-0.3.1/src/chuzom/prompts/classifier_v1.txt +6 -0
  236. chuzom_router-0.3.1/src/chuzom/prompts/classifier_v2.txt +7 -0
  237. chuzom_router-0.3.1/src/chuzom/provider_budget.py +243 -0
  238. chuzom_router-0.3.1/src/chuzom/provider_quirks.py +236 -0
  239. chuzom_router-0.3.1/src/chuzom/provider_registry.py +342 -0
  240. chuzom_router-0.3.1/src/chuzom/providers.py +319 -0
  241. chuzom_router-0.3.1/src/chuzom/quality_feedback.py +282 -0
  242. chuzom_router-0.3.1/src/chuzom/quickstart.py +223 -0
  243. chuzom_router-0.3.1/src/chuzom/quota_balance.py +219 -0
  244. chuzom_router-0.3.1/src/chuzom/quota_envelope_routing.py +121 -0
  245. chuzom_router-0.3.1/src/chuzom/quota_routing.py +153 -0
  246. chuzom_router-0.3.1/src/chuzom/quota_savings.py +335 -0
  247. chuzom_router-0.3.1/src/chuzom/quota_tracker.py +334 -0
  248. chuzom_router-0.3.1/src/chuzom/rbac_routing.py +228 -0
  249. chuzom_router-0.3.1/src/chuzom/receipt_store.py +184 -0
  250. chuzom_router-0.3.1/src/chuzom/redaction_routing.py +89 -0
  251. chuzom_router-0.3.1/src/chuzom/repo_config.py +217 -0
  252. chuzom_router-0.3.1/src/chuzom/response_router.py +250 -0
  253. chuzom_router-0.3.1/src/chuzom/response_validation.py +249 -0
  254. chuzom_router-0.3.1/src/chuzom/result_cache.py +396 -0
  255. chuzom_router-0.3.1/src/chuzom/retrospective.py +873 -0
  256. chuzom_router-0.3.1/src/chuzom/router.py +2714 -0
  257. chuzom_router-0.3.1/src/chuzom/routing_hints.py +274 -0
  258. chuzom_router-0.3.1/src/chuzom/rules/chuzom.md +113 -0
  259. chuzom_router-0.3.1/src/chuzom/rules/codex-rules.md +63 -0
  260. chuzom_router-0.3.1/src/chuzom/rules/copilot-cli-rules.md +52 -0
  261. chuzom_router-0.3.1/src/chuzom/rules/copilot-rules.md +45 -0
  262. chuzom_router-0.3.1/src/chuzom/rules/cursor-rules.md +25 -0
  263. chuzom_router-0.3.1/src/chuzom/rules/desktop-rules.md +48 -0
  264. chuzom_router-0.3.1/src/chuzom/rules/gemini-cli-rules.md +54 -0
  265. chuzom_router-0.3.1/src/chuzom/rules/gemini-rules.md +18 -0
  266. chuzom_router-0.3.1/src/chuzom/rules/openclaw-rules.md +27 -0
  267. chuzom_router-0.3.1/src/chuzom/rules/opencode-rules.md +28 -0
  268. chuzom_router-0.3.1/src/chuzom/rules/pi-rules.md +47 -0
  269. chuzom_router-0.3.1/src/chuzom/rules/trae-rules.md +50 -0
  270. chuzom_router-0.3.1/src/chuzom/rules/vscode-rules.md +25 -0
  271. chuzom_router-0.3.1/src/chuzom/safe_config.py +161 -0
  272. chuzom_router-0.3.1/src/chuzom/safe_subprocess.py +161 -0
  273. chuzom_router-0.3.1/src/chuzom/sanitization.py +116 -0
  274. chuzom_router-0.3.1/src/chuzom/scim_api.py +176 -0
  275. chuzom_router-0.3.1/src/chuzom/scorer.py +274 -0
  276. chuzom_router-0.3.1/src/chuzom/secret_scrubber.py +197 -0
  277. chuzom_router-0.3.1/src/chuzom/semantic_cache.py +250 -0
  278. chuzom_router-0.3.1/src/chuzom/server.py +593 -0
  279. chuzom_router-0.3.1/src/chuzom/service.py +368 -0
  280. chuzom_router-0.3.1/src/chuzom/service_manager.py +164 -0
  281. chuzom_router-0.3.1/src/chuzom/session_spend.py +310 -0
  282. chuzom_router-0.3.1/src/chuzom/sidecar.py +261 -0
  283. chuzom_router-0.3.1/src/chuzom/signals/__init__.py +22 -0
  284. chuzom_router-0.3.1/src/chuzom/signals/base.py +45 -0
  285. chuzom_router-0.3.1/src/chuzom/signals/keyword.py +41 -0
  286. chuzom_router-0.3.1/src/chuzom/signals/pii.py +59 -0
  287. chuzom_router-0.3.1/src/chuzom/state.py +113 -0
  288. chuzom_router-0.3.1/src/chuzom/stats.py +167 -0
  289. chuzom_router-0.3.1/src/chuzom/statusline_hud.py +320 -0
  290. chuzom_router-0.3.1/src/chuzom/storage/__init__.py +12 -0
  291. chuzom_router-0.3.1/src/chuzom/storage/adapters/__init__.py +8 -0
  292. chuzom_router-0.3.1/src/chuzom/storage/adapters/base.py +65 -0
  293. chuzom_router-0.3.1/src/chuzom/storage/adapters/json_adapter.py +63 -0
  294. chuzom_router-0.3.1/src/chuzom/storage/adapters/sqlite_adapter.py +207 -0
  295. chuzom_router-0.3.1/src/chuzom/storage/adapters/yaml_adapter.py +99 -0
  296. chuzom_router-0.3.1/src/chuzom/storage/models.py +53 -0
  297. chuzom_router-0.3.1/src/chuzom/storage/routing/__init__.py +13 -0
  298. chuzom_router-0.3.1/src/chuzom/storage/routing/validators.py +67 -0
  299. chuzom_router-0.3.1/src/chuzom/storage/service.py +342 -0
  300. chuzom_router-0.3.1/src/chuzom/streaming_judge.py +223 -0
  301. chuzom_router-0.3.1/src/chuzom/subscription_local_routing.py +309 -0
  302. chuzom_router-0.3.1/src/chuzom/summary.py +811 -0
  303. chuzom_router-0.3.1/src/chuzom/system_prompts.py +131 -0
  304. chuzom_router-0.3.1/src/chuzom/team.py +288 -0
  305. chuzom_router-0.3.1/src/chuzom/team_sync.py +287 -0
  306. chuzom_router-0.3.1/src/chuzom/telemetry.py +162 -0
  307. chuzom_router-0.3.1/src/chuzom/terminal_style.py +389 -0
  308. chuzom_router-0.3.1/src/chuzom/test_delta.py +443 -0
  309. chuzom_router-0.3.1/src/chuzom/tiers.py +216 -0
  310. chuzom_router-0.3.1/src/chuzom/timeout_config.py +129 -0
  311. chuzom_router-0.3.1/src/chuzom/token_budget.py +290 -0
  312. chuzom_router-0.3.1/src/chuzom/tool_tiers.py +75 -0
  313. chuzom_router-0.3.1/src/chuzom/tools/__init__.py +0 -0
  314. chuzom_router-0.3.1/src/chuzom/tools/admin.py +1619 -0
  315. chuzom_router-0.3.1/src/chuzom/tools/agents.py +311 -0
  316. chuzom_router-0.3.1/src/chuzom/tools/agoragentic.py +314 -0
  317. chuzom_router-0.3.1/src/chuzom/tools/codex.py +73 -0
  318. chuzom_router-0.3.1/src/chuzom/tools/dashboard.py +392 -0
  319. chuzom_router-0.3.1/src/chuzom/tools/fs.py +404 -0
  320. chuzom_router-0.3.1/src/chuzom/tools/gemini_cli.py +72 -0
  321. chuzom_router-0.3.1/src/chuzom/tools/media.py +93 -0
  322. chuzom_router-0.3.1/src/chuzom/tools/pipeline.py +78 -0
  323. chuzom_router-0.3.1/src/chuzom/tools/routing.py +893 -0
  324. chuzom_router-0.3.1/src/chuzom/tools/setup.py +621 -0
  325. chuzom_router-0.3.1/src/chuzom/tools/subscription.py +215 -0
  326. chuzom_router-0.3.1/src/chuzom/tools/text.py +693 -0
  327. chuzom_router-0.3.1/src/chuzom/trace_id.py +104 -0
  328. chuzom_router-0.3.1/src/chuzom/tracing.py +149 -0
  329. chuzom_router-0.3.1/src/chuzom/types.py +687 -0
@@ -0,0 +1,71 @@
1
+ # Secrets
2
+ .env
3
+ .env.backup.*
4
+ .env.bak.*
5
+
6
+ # Python build/cache
7
+ __pycache__/
8
+ *.pyc
9
+ .ruff_cache/
10
+ .pytest_cache/
11
+ .mypy_cache/
12
+ dist/
13
+ build/
14
+ *.egg-info/
15
+ .venv/
16
+ .coverage*
17
+ htmlcov/
18
+
19
+ # OS
20
+ .DS_Store
21
+ Thumbs.db
22
+
23
+ # Tessera local state (per-user)
24
+ .tessera_cache/
25
+ .tessera_lineage/
26
+ *.tessera.sqlite*
27
+ .serena/
28
+ .lore/
29
+
30
+ # Editor / IDE caches (local development only; repo has plugin configs for tests)
31
+ .claude/tasks/
32
+ .claude/task-list.md
33
+ .tasks.json
34
+ .playwright-mcp/
35
+ .playwright-cli/
36
+
37
+ # Local-only architecture & internal design notes — NEVER commit
38
+ # (User explicitly requested Docs/ stay local-only)
39
+ #
40
+ # Note: Uppercase Docs/ remains ignored (the user's original convention
41
+ # for internal scratch). Lowercase docs/ is the canonical home for
42
+ # externally-visible operator + audit + architecture documentation —
43
+ # the explicit negation closes G-019 from
44
+ # docs/audit/post-remediation/GAP_ANALYSIS.md (the INV-013 finding
45
+ # that kept the audit corpus invisible to outside readers on
46
+ # case-sensitive filesystems). On macOS the two names resolve to the
47
+ # same directory; the negation documents intent for Linux/CI.
48
+ Docs/
49
+ !docs/
50
+ !docs/**
51
+ INTERNAL.md
52
+ STRATEGY.md
53
+ MONETIZATION.md
54
+ ROADMAP.md
55
+ PRICING.md
56
+ CLAUDE.md
57
+
58
+ # Test artifacts
59
+ .router-test-results/
60
+ test_results/
61
+ *.bak
62
+ *.bak.*
63
+
64
+ # Benchmark artifacts — cache is per-machine, results bloat over time.
65
+ # Commit specific results explicitly when they're evidence-worthy.
66
+ bench/cache/
67
+ bench/results/
68
+
69
+ # Audit working dir — evidence ledger, batch checkpoints, remediation plan
70
+ # (Per audit charter — read-only audit artifacts, never committed)
71
+ .audit/
@@ -0,0 +1,50 @@
1
+ <!-- chuzom-rules-version: 1 -->
2
+ # Chuzom — Trae IDE Routing Rules
3
+
4
+ > These rules apply when using chuzom MCP tools inside Trae IDE (ByteDance).
5
+ > Trae v1.3.0+ supports MCP via mcpServers config and .rules files.
6
+
7
+ ---
8
+
9
+ ## How to Route
10
+
11
+ Trae loads MCP servers from the mcpServers config block. Once chuzom is registered,
12
+ call MCP tools by name for any substantive task:
13
+
14
+ ```
15
+ Rule: for research/generate/code/analyze tasks → call llm_auto(prompt=<the task>)
16
+ ```
17
+
18
+ ---
19
+
20
+ ## Task Type → Tool Mapping
21
+
22
+ | Task | Tool | Notes |
23
+ |---|---|---|
24
+ | Simple factual question | `llm_query` | Gemini Flash / Groq |
25
+ | Research / current events | `llm_research` | Perplexity (web-grounded) |
26
+ | Writing / content | `llm_generate` | Gemini Flash / Haiku |
27
+ | Deep analysis | `llm_analyze` | GPT-4o / Gemini Pro |
28
+ | Code generation | `llm_code` | Ollama → Codex → o3 |
29
+ | Unknown / auto-detect | `llm_auto` | Classifies + routes |
30
+
31
+ ---
32
+
33
+ ## When NOT to Route
34
+
35
+ - File edits executed by Trae's built-in editor tools
36
+ - Short inline questions you already know
37
+
38
+ ---
39
+
40
+ ## Savings Visibility
41
+
42
+ Run `llm_savings` to see cross-session totals.
43
+ `llm_auto` shows a savings reminder every 5 calls.
44
+
45
+ ---
46
+
47
+ ## Token-Efficient Responses
48
+
49
+ Skip preamble. Lead with result. Fragments fine when meaning is clear.
50
+ No trailing summaries. ≥3 items → bullets. Never restate the user's request.
@@ -0,0 +1,219 @@
1
+ # Changelog
2
+
3
+ ## v0.3.0 — 2026-06-11 — Enterprise enforcement wired + honest packaging
4
+
5
+ > Closes the audit's anchor finding (INV-010): the enterprise control plane is now **wired into and enforced on the routing path** under `CHUZOM_DEPLOYMENT_PROFILE=enterprise`, and the packaging/README are reconciled to reality. The developer router stays stable; the enterprise control plane is labelled **beta** with a per-feature status table in the README.
6
+
7
+ ### Enterprise control plane (now enforced under the enterprise profile)
8
+
9
+ - **INV-010 closed.** RBAC (`check_route_prompt` / `check_provider` / `check_model`) and the audit chain are consulted on every routed turn. The enterprise profile flips RBAC→strict, audit→mandatory, redaction→on, forecast→strict (G-001/G-003/G-012/G-016). End-to-end enforcement proof added.
10
+ - **Phase 3b — per-identity allow-lists.** The authenticated SSO/OIDC identity now carries `permissions` + per-identity `allowed_providers` / `allowed_models` from the `IdentityStore`, so a restricted token enforces through the wired gates. Empty lists normalise to `None` (unrestricted) — an empty allow-list can never silently deny-all.
11
+ - **Loop-5 / G-039.** `CHUZOM_DEPLOYMENT_PROFILE` deployment-profile detection back-ported into the auto-route hook; the self-reference bypass is refused under the enterprise profile.
12
+ - **G-029 agent ledger.** `SessionStore.recent()` / `cancel()` (cascade) / `record_tool_call()` + `last_activity_at`; admin agent status + cancel endpoints.
13
+
14
+ ### Security
15
+
16
+ - **G-004 — RBAC allow-list prefix-spoof closed.** A forged `provider/forged-model` candidate could match a bare allow-list entry (the provider prefix was stripped before comparison). `check_model` now matches the full id exactly; the `provider/model` and bare forms never cross-match.
17
+
18
+ ### Packaging & docs (P0-6)
19
+
20
+ - `chuzom --version` reports the **installed distribution's version** (installed wheels previously reported a stale hardcoded `10.1.2`).
21
+ - `chuzom install --host claude-code` / `--host claude-desktop` now resolve; generated MCP configs invoke the canonical `chuzom` stdio entry instead of the deprecated `uvx claude-code-chuzom` package.
22
+ - README rewritten concise + honest (806 → ~140 lines) with a real "How it works" section and a per-feature beta status table; the overclaimed SOC 2 / GDPR / OTEL badges were dropped.
23
+
24
+ ### Known gaps (on the roadmap; labelled beta in the README)
25
+
26
+ - SCIM mounting + role/group mapping; team-budget enforcement; multi-instance (Postgres) HA; control-plane→routing wiring for provider-disable / policy-versioning; audit-chain verify CLI/endpoint.
27
+
28
+ ## v0.2.0 — 2026-06-08 — Audit Tracks 1 & 2 + lineage API rewrite
29
+
30
+ > **Security advisory + claims reconciliation + honest test signal + lineage API rewrite.** This release closes the developer-focused subset of the 2026-06 internal audit (`Docs/audit/FINDINGS.md`): **2 Critical** and **6 High** findings across security defaults (SEC-001/002/003), session isolation (INV-007 + ROU-001), truth-in-claims (INV-001/002), and test-suite integrity (TST-001). It also lands the **v0.2.x `LineageStore` API rewrite** that was implicit in TST-001's follow-up. Multi-tenancy / identity-layer items (INV-010, INV-011, ROU-002, PRI-001, OBS-001, TST-003) are deferred to Phase 2 pending the multi-tenancy product decision.
31
+ >
32
+ > The two Critical findings (SEC-001, SEC-002) were exploitable with default settings. Operators running prior versions on a reachable network should review the mitigations below.
33
+
34
+ ### Security
35
+
36
+ - **SEC-001 — Removed `chuzom-sse` console script (BREAKING).** Prior versions installed a `chuzom-sse` binary that, when invoked, bound `0.0.0.0:$PORT` and exposed the full 60-tool MCP surface — including filesystem tools, wallet, and routing controls — with **zero authentication**. The entry point has been removed from `pyproject.toml`. The `chuzom.server.main_sse` function is retained in source for future re-introduction behind proper authentication + identity (post-INV-010); attempting to re-add the entry point without an auth wrapper is now guarded by a regression test (`tests/test_no_chuzom_sse_entry_point.py`).
37
+ - **Mitigation if you were running `chuzom-sse`:** stop the process, review any logs you have for unauthorised tool invocations during the exposure window, rotate credentials accessible from the host, and switch to the stdio transport (`chuzom`) until a hardened SSE wrapper ships.
38
+ - **SEC-002 — `llm_fs_*` tools are now opt-in and sandboxed (BREAKING).** Prior versions registered four filesystem tools (`llm_fs_find`, `llm_fs_rename`, `llm_fs_edit_many`, `llm_fs_analyze_context`) by default. `llm_fs_edit_many` accepted an arbitrary glob and read up to 32 KB per match into the model prompt; `llm_fs_edit_many(glob_pattern="~/.ssh/**")` was a one-call exfiltration vector. Two independent gates now apply:
39
+ 1. **Opt-in env.** Tools are registered only when `CHUZOM_FS_TOOLS=on` (or `1`/`true`/`yes`) is set. Without the opt-in, `mcp.list_tools()` exposes zero `llm_fs_*` entries.
40
+ 2. **`project_root` sandbox.** `llm_fs_edit_many` and `llm_fs_analyze_context` now require a `project_root` parameter. The root is resolved with `Path.resolve()` (closing the symlink-escape hole); paths that resolve outside it are rejected before any file read or route call. `project_root='/'` is refused outright.
41
+ - **SEC-003 — `agoragentic_*` MCP tools are now opt-in (BREAKING).** Prior versions registered four marketplace tools (`agoragentic_task`, `agoragentic_browse`, `agoragentic_wallet`, `agoragentic_status`) by default, even when `CHUZOM_SLIM=routing` was set. **`agoragentic_task` performs USDC settlement on the Base L2 blockchain** — it can spend real money via the credentials stored at `~/.chuzom/agoragentic.json`. An LLM agent enumerating tools, an MCP client probing the tool list, or a hallucinated tool call could trigger an unintended on-chain transaction. The four tools are now gated behind `CHUZOM_AGORAGENTIC=on` (or `1`/`true`/`yes`). Without the opt-in, `mcp.list_tools()` exposes zero `agoragentic_*` entries.
42
+ - **INV-007 / ROU-001 — Per-session classification side channel (BREAKING).** The auto-route hook previously wrote a shared `~/.chuzom/last_classification.json` that every MCP server on the machine read from. Two failure modes: (1) two Claude Code sessions raced on the same file (whoever fired last set the verdict for both); (2) any same-user process could forge a classification within the 120 s freshness window. The hook now writes `~/.chuzom/last_classification_<session_id>.json` and the MCP reader pins to `CLAUDE_SESSION_ID` from the env that Claude Code injects when it spawns the MCP server. A belt-and-braces inner-payload check rejects shards whose inner `session_id` doesn't match the env. The legacy shared file is no longer written or read; consumers that still look for it gracefully return `None` and fall back to the length heuristic.
43
+
44
+ ### Truth-in-claims
45
+
46
+ - **INV-001 — Pre-existing self-audit rescoped, not retracted.** `AUDIT_FINDINGS.txt` and `CHUZOM_AUDIT_REPORT.md` (both dated 2026-06-07, narrow lineage-subsystem reviews) previously stamped the project as "✅ APPROVED FOR IMMEDIATE PRODUCTION DEPLOYMENT" with 5★ ratings across the board. The 2026-06-08 comprehensive audit identified 3 Critical, 11 High, 11 Medium, 3 Low findings and scored enterprise-readiness at 1.65 / 5 — the prior claims were a scoping error, not a measurement of the whole project. Both files now carry a top-of-document scope notice, every overclaiming line is contextualised to "lineage subsystem only", and the documents point at `Docs/audit/` as the authoritative whole-project assessment. The lineage subsystem verdict (production-ready as a subsystem) is preserved.
47
+ - **INV-002 — README hero reconciled with `pyproject.toml` Alpha status.** The README first paragraph previously read "The enterprise-ready LLM router for developer organizations." while `pyproject.toml` classified the project `Development Status :: 3 - Alpha`. The hero now describes the project as "Local-first LLM router for developer workstations" and adds a maturity line stating that the developer-tool layer is the production path today (alpha per `pyproject.toml`) and the enterprise control plane (RBAC, tamper-evident audit chain, per-user / per-team budgets, OpenTelemetry export) is scaffolded but not yet wired into the routing path (`INV-010`). The reader of the first 30 lines of README and the first 20 lines of `pyproject.toml` now arrives at the same maturity conclusion.
48
+
49
+ ### Testing
50
+
51
+ - **TST-001 — Un-skipped 9 silently-excluded test suites.** `tests/conftest.py:collect_ignore` had dropped 206 tests at collection time, including integrity, performance, observability, session-summary rendering, framework scenarios, and lineage roundtrips. The original justification (lineage symbols missing) was stale — PR #10 restored the exports but the exclusion list was never cleaned up. The README's "766 tests passing" badge ran against a suite that hid these. `collect_ignore` is now empty (every test file is collected); the residual failures all share one root cause (`LineageStore(db_path=...)` signature drift, fixed below in the lineage rewrite) and were individually marked via `_KNOWN_BROKEN_TESTS` with reasons that show up in `pytest -v`. New meta-test `tests/test_no_silent_collect_ignore.py` guards against future silent-exclusion regressions.
52
+
53
+ ### Lineage API rewrite
54
+
55
+ - **`LineageStore` — dual-keyword constructor + planned `LineageRecord` write/query surface.** PR #16 (TST-001) exposed ~30 tests across 8 files that referenced a `LineageStore` API never implemented. That API now exists, additively:
56
+ - **Constructor** (`__init__`) accepts both `router_dir` (directory, production shape — every `src/` caller hits this) and keyword-only `db_path` (specific SQLite file, test shape). Passing both raises `ValueError`. Production callers are unchanged — none used either keyword pre-rewrite.
57
+ - **New `lineage` SQLite table** parallel to the existing `routing_decisions` table; mirrors `LineageRecord.to_row()` (22 columns including agent_id / session_id / step_index / parent_session_id / framework). Forward-compatible migration: if a pre-v0.0.2 DB is opened with a lineage table that lacks the agent-session columns, `_init_db` `ALTER`s the table to add them.
58
+ - **New methods**: `record(LineageRecord)` writes to JSONL + the new table; `inversions(kind=None)` filters by `Inversion` enum; `summary()` aggregates total / up / down / none + inversion_rate; `by_session(session_id, agent_id=None)` returns rows ordered by step_index; `by_framework(slug)` returns rows matching the framework column; `close()` is a no-op symmetry shim.
59
+ - **Result**: 14 `_KNOWN_BROKEN_TESTS` entries removed from `conftest.py`; the previously-skipped suites now contribute **~350 newly-visible passing tests** to coverage. Total: `tests/test_lineage.py` + `tests/qa/` + `tests/scenarios/` go from 116 → **470 passing** with 0 failures.
60
+
61
+ ### Breaking changes
62
+
63
+ - The `chuzom-sse` console script no longer exists. Use the stdio transport (`chuzom`) until an authenticated SSE wrapper ships.
64
+ - `llm_fs_edit_many` now requires `project_root: str` as a positional argument (was previously sandbox-less).
65
+ - `llm_fs_analyze_context` renamed its first argument from `path` (default `"."`) to `project_root` (required). The previous default that quietly analysed the process cwd is gone.
66
+ - `llm_fs_*` tools are NOT registered unless `CHUZOM_FS_TOOLS=on` is set.
67
+ - `agoragentic_*` tools are NOT registered unless `CHUZOM_AGORAGENTIC=on` is set.
68
+ - The hook → MCP classification bridge moved from `~/.chuzom/last_classification.json` to per-session shards `~/.chuzom/last_classification_<session_id>.json`. Consumers that still target the legacy filename will see no data (and the router will fall back to its length heuristic, which is the correct conservative default).
69
+
70
+ ### Added
71
+
72
+ - `tests/test_no_chuzom_sse_entry_point.py` — 3 regression tests guarding SEC-001.
73
+ - `tests/test_fs_path_validation.py` — 26 tests covering the SEC-002 env gate and sandbox helpers (`_resolve_root`, `_assert_under_root`, `_filter_files_under_root`), including symlink-escape and absolute-path-outside-root cases.
74
+ - `tests/test_agoragentic_opt_in.py` — 18 regression tests covering the SEC-003 env-gate truth table.
75
+ - `tests/test_classification_side_channel_isolation.py` — 12 tests covering session isolation, adversarial forgery (ROU-001), inner-payload mismatch, staleness, and malformed-input resilience.
76
+ - `tests/test_no_silent_collect_ignore.py` — 2 meta-tests asserting `collect_ignore` stays empty and every `_KNOWN_BROKEN_TESTS` entry carries a reason.
77
+ - `chuzom.tools.fs.FsSandboxError` — raised when a path escapes the configured `project_root`.
78
+ - `chuzom.lineage.LineageStore.{record, inversions, summary, by_session, by_framework, close}` — planned-API methods for writing and querying `LineageRecord` instances.
79
+ - `lineage` SQLite table — parallel to `routing_decisions`; mirrors `LineageRecord.to_row()` with forward-compatible migration of pre-v0.0.2 schemas.
80
+ - Security notice docstrings on `chuzom.server.main_sse`, `chuzom.tools.fs.register`, and `chuzom.tools.agoragentic.register` explaining the threat model and the conditions under which the prior behaviour may be reintroduced.
81
+
82
+ ### Notes for operators
83
+
84
+ - Anyone who was relying on the default-on filesystem tools must add `CHUZOM_FS_TOOLS=on` to their environment AND pass `project_root` on every call.
85
+ - Anyone who was intentionally using the Agoragentic marketplace must add `CHUZOM_AGORAGENTIC=on` to the environment that launches the MCP server. The credentials file at `~/.chuzom/agoragentic.json` is unchanged.
86
+ - **If you discover unauthorised on-chain activity from `~/.chuzom/agoragentic.json`'s `agent_id` predating this release:** rotate the API key, revoke the agent, and review settlements on the Base L2 explorer. The pre-fix default was exploitable.
87
+ - Symlink escapes are now closed because path validation runs after `Path.resolve()`, not against the raw user-supplied string.
88
+ - The full audit context — including findings' file:line evidence and the rejected alternatives — lives in `Docs/audit/HIGH_PRIORITY_WORK_PLAN.md` and `Docs/audit/FINDINGS.md`.
89
+
90
+ ### Phase 2 (parked pending multi-tenancy product decision)
91
+
92
+ - `INV-010` (identity → routing → audit chain wiring), `INV-011` + `TST-003` (per-identity budgets + concurrency tests), `ROU-002` (per-tenant routing tables), `PRI-001` (redaction in routing path), `OBS-001` (tenant/user/agent fields in logs). All blocked on `Q-P-2` in `Docs/audit/OPEN_QUESTIONS.md`.
93
+
94
+ ---
95
+
96
+ ## v0.1.1 — Stop misrouting display-intent prompts to llm_code
97
+
98
+ > **Patch release.** Targets the most common "Chuzom appears stuck" experience: trivial follow-ups like `show me the report` issued after code-heavy turns were being classified `code/moderate` via `code-context-inherit`, then forced through `mcp__chuzom__llm_code` — an external LLM that can't read local files. The tool would spin for 2-4 minutes before the user cancelled. No actual hang; just a misroute taking the slow path that couldn't help anyway. Full analysis in [`STUCK_PATTERNS_ANALYSIS.md`](./STUCK_PATTERNS_ANALYSIS.md).
99
+
100
+ ### Added
101
+ - **Display-intent override** (`auto-route.py`) — `_DISPLAY_INTENT_RE` matches short prompts (≤100 chars) starting with `show`/`display`/`view`/`read`/`cat`/`print`/`list`/`open`/`see` followed by a display target (`the/my/this/<file>.md/report/file/output/log/diff/...`). Such prompts always route to `llm_query` regardless of inherited context, tagged `intent-override-display` for telemetry. Does **not** save to `last_route` so subsequent genuine code follow-ups still inherit the prior code context correctly.
102
+ - **`STUCK_PATTERNS_ANALYSIS.md`** — comprehensive 4-mode taxonomy of perceived "stuck" events across Claude Code CLI, VS Code/JetBrains extensions, Cursor/Windsurf, and Claude.ai web. Includes evidence trail from `auto-route-debug.log` + the d4cd6a72 session transcript, defense-gap matrix, prioritised fix list, and an instrumentation patch proposal for catching the next one.
103
+ - **`tests/test_display_intent_override.py`** — 41 cases covering positive matches, negative matches against real code-generation prompts (`show me a function that…`), length-cap behaviour, and source-integration smoke check that asserts the override branch remains wired.
104
+
105
+ ### Changed
106
+ - **Continuation bypass narrowed to strict acks** (`auto-route.py`) — the early UserPromptSubmit bypass at `chuzom-auto-route.py:1988` now triggers only on strict `_CONTINUATION_RE` matches (single-word `yes`/`ok`/`go ahead`/etc.), not the broader `_is_short_followup` union. Multi-word directives like `please go ahead and do the change` after a code task now fall through to the classification block instead of silently exiting with no output. Behaviour change: prompts starting with `please`/`now`/`let's` no longer bypass — they're routed normally.
107
+ - **Classification branch order** (`auto-route.py`) — `_is_short_code_followup` is now checked **before** `_is_continuation` so short follow-ups after code tasks get the specific `code-context-inherit` telemetry tag instead of the generic `context-inherit`. Routing destination is functionally identical; observability is sharper.
108
+ - **`LineageStore` exported from `chuzom.lineage`** — adds `LineageStore` to `chuzom/lineage/__init__.py`'s `__all__` so `chuzom.tools.agents` (and the 5 QA-suite test modules) can import it without `ImportError`. Class existed in `lineage_store.py`; export was missing.
109
+ - **Live-hook tests find the renamed file** (`tests/test_auto_route_fix_verb.py`) — `_find_live_hook()` helper checks `~/.claude/hooks/chuzom-auto-route.py` first, falls back to legacy `llm-router-auto-route.py`. Resolves post-rebrand test drift where v0.0.2 fix-pattern assertions still pointed at the pre-rebrand binary path.
110
+
111
+ ### Fixed
112
+ - **Silent hook exit on multi-word follow-ups** — `test_short_followup_after_code_inherits_code` was failing because the broad bypass swallowed prompts like `please go ahead and do the change now`. Now correctly emits the `code-context-inherit` routing directive.
113
+ - **Perceived 2-4 minute hangs on display-intent prompts** — the misroute path is closed at the classifier. `show me the report` after a code-heavy session now routes to `llm_query` (cheap, fast) instead of `llm_code` (slow external LLM that can't help).
114
+
115
+ ### Internal
116
+ - 41 new regression tests in `test_display_intent_override.py`; 198/198 passing across `test_auto_route_*` + `test_display_intent_override` + `tests/lineage/` suites.
117
+
118
+ ---
119
+
120
+ ## v0.1.0 — Stability promise + first benchmark numbers + brand sweep
121
+
122
+ > **First stable-shape release.** The 0.0.x phase shipped fast and broke things on the way; 0.1.0 commits to:
123
+ > - SQL schema migrations land via `_safe_migrate` (idempotent ALTER TABLE) — no destructive resets.
124
+ > - Public CLI entry points (`chuzom`, `chuzom-install-hooks`, `chuzom-onboard`, `chuzom-quickstart`, `chuzom-sse`) and MCP tool names (`llm_*`, `chuzom_agent_*`) are frozen. Removals will go through a deprecation cycle in 0.2.x.
125
+ > - Enforcement mode names (`off`, `soft`, `smart`, `hard`, `strict`) are stable.
126
+ > - SQLite database file paths (`~/.chuzom/{usage,lineage,sessions,quotas,audit}.db`) are stable.
127
+
128
+ ### Added
129
+ - **First end-to-end benchmark numbers** — ran `python -m bench --easy-only` against the smoke corpus (5 prompts × 4 routers). On objective easy prompts, Chuzom matches AlwaysCheap (q=2.60, $0.00 spend) — proves the heuristic-first cascade routes correctly when no escalation is warranted. AlwaysPremium errored on OpenAI rate limit, so cost-vs-quality Pareto vs GPT-4o isn't measurable yet; see `bench/results/20260606-150229.{json,md}` for the raw data.
130
+ - **`scripts/verify_chuzom_hooks.sh`** — end-to-end verifier that pipes representative payloads into the installed hooks (`~/.claude/hooks/chuzom-*.py`) and asserts the production code paths contain the live brand + enforcement logic. 11 checks; run after every reinstall.
131
+ - **`scripts/backfill_sidecars.py`** — replays `~/.chuzom/last_route_*.json` sidecars (written by `auto-route.py` when a directive fires) into `routing_decisions`. Idempotent via stable `correlation_id` (`sidecar:<session>:<saved_at>`). Sidecars carry intent only, so rows land as `success=0, reason_code='sidecar_backfill'`.
132
+ - **`token_budget.count_tokens(text, model=None)`** — accurate per-model token counting via tiktoken when available; falls back to `chars/4` when tiktoken is missing, the model is unknown, or encoding load fails. Used by cost-attribution paths (`tools/codex.py`, `tools/gemini_cli.py`); hot-path budget checks keep `estimate_tokens()` for speed.
133
+ - **`CHUZOM_ENFORCE=strict`** — new enforcement mode that disables every escape valve: the read-only Bash exception (smart mode allows `git log`/`ls`), the loop auto-pivot (3× same tool in 2 min → unblock), and the count auto-pivot (4 violations/turn → unblock). Use when bypass discipline matters more than uninterrupted flow.
134
+ - **Outcome-stamped enforcement log** — every VIOLATION line in `~/.chuzom/enforcement.log` now carries `outcome={BLOCKED, BLOCKED(strict), ALLOWED(soft), ALLOWED(readonly_bash)}` so the log is self-explanatory without source reads.
135
+ - **Schema bootstrap in `tools/admin.py:llm_usage`** — fresh / 0-byte `usage.db` now renders the empty-state UI instead of erroring with `no such table: usage`. Matches the resilience already in `dashboard_data.py`.
136
+
137
+ ### Changed
138
+ - **Full brand sweep**: 37 source files (`.py` + `rules/*.md`) swept from `LLM Router` → `Chuzom` / `LLM ROUTER` → `CHUZOM`. Stop summary header now renders `⚡ CHUZOM`; dashboards, digests, install messages, web TUI, and routing rules are all consistent. Routing rules file regenerated as `chuzom-rules-version: 5`.
139
+ - **Cyber-grid Stop summary layout** — long classifier names (`code-context-inherit` at 20 chars, `content-generation-fast-path` at 28 chars) were rendered with `f"{name:<16}"` which pads but doesn't truncate, so labels bled into the SAVINGS column on the right. Adds method-name aliases (`build-fast`, `ctx-inherit`, `content-gen`, `heuristic·w`) plus a 16-char hard truncation guard so future classifier names can't reintroduce the overflow.
140
+
141
+ ### Fixed
142
+ - **`outcome=BLOCKED` actually means blocked.** Pre-0.1.0, VIOLATION lines in `enforcement.log` left the disposition (blocked vs auto-pivot-allowed vs soft-mode-allowed) implicit — readers had to know the source to disambiguate. Now every exit path stamps its own outcome.
143
+
144
+ ### Known gaps (will be addressed in 0.1.x)
145
+ - Easy-only benchmark can't differentiate routers (all classify as `simple` → all route to local). Moderate-corpus run with judge-grading is needed to show the classifier's value. Deferred until empty-response detection lands.
146
+ - Empty-response from local model (`ollama/qwen3.5`) on 3 of 5 easy prompts does NOT trigger cascade — the router silently returns the empty string instead of escalating. Tracked.
147
+ - AlwaysPremium baseline requires a working `OPENAI_API_KEY`; smoke run hit rate-limit. Cost-savings vs GPT-4o not yet measurable. Workaround: use `litellm`-routed Sonnet via Claude subscription as the premium baseline.
148
+ - `__version__` in `src/chuzom/__init__.py` is set to `10.1.2` (internal numbering); `pyproject.toml` is the public version source. Sync drift to be resolved.
149
+
150
+ ### Internal
151
+ - 15 new regression tests covering: schema bootstrap, sidecar backfill (7 tests), strict enforcement (4 tests), cyber-grid layout (2 tests), token counting (6 tests). Full suite green at v0.1.0 cut.
152
+
153
+ ---
154
+
155
+ ## v0.0.2 — Agent layer + framework adapters + benchmark harness
156
+
157
+ ### Added
158
+ - **`chuzom/agents/` module** — agent-aware routing without owning the agent loop.
159
+ - `AgentProfile` dataclass — tier preference, signal boosts, preferred chain, budget envelope.
160
+ - `AgentRegistry` — YAML-loaded (`config/agents.yaml`); 3 default profiles ship: `code-reviewer`, `trend-researcher`, `tdd-guide`.
161
+ - `AgentSession` + `SessionStore` — SQLite-backed at `~/.chuzom/sessions.db`. State machine: ACTIVE → COMPLETED / ERRORED / BUDGET_EXCEEDED. Nested sessions via `parent_session_id` with full descendant `rollup`.
162
+ - `BudgetEnvelope` + `BudgetExceeded` — immutable envelope, pre-emptive `would_exceed`, raise-or-pass `raise_if_would_exceed`.
163
+ - **`chuzom/tools/agents.py`** — 6 MCP tools:
164
+ - `chuzom_agent_list` / `chuzom_agent_start_session` / `chuzom_agent_check_budget` / `chuzom_agent_route` / `chuzom_agent_complete_session` / `chuzom_agent_lineage`.
165
+ - Budget enforcement at the route boundary — sessions refuse calls that would breach.
166
+ - **`chuzom/frameworks/` module** — adapter shape for agent frameworks.
167
+ - `FrameworkAdapter` protocol (3 methods: `wrap_model`, `detect_agent_id`, `is_available`).
168
+ - **Agno** — concrete, re-exports `RouteredModel` + `RouteredTeam` from `chuzom.integrations.agno`.
169
+ - **Hermes** — skeleton; v0.0.3 lands the concrete tool-use protocol.
170
+ - **LangGraph / CrewAI / OpenAI Agents SDK / Claude Agent SDK / Pydantic AI** — adapter stubs.
171
+ - **Lineage schema extension** — 5 new optional columns: `agent_id`, `session_id`, `step_index`, `parent_session_id`, `framework`. Idempotent migration handles pre-v0.0.2 databases via `ALTER TABLE ADD COLUMN` with duplicate-column guard. New indexes on `session_id` and `agent_id`.
172
+ - **Decision engine boosts** — `DecisionEngine.choose(scores, boosts={"signal": multiplier})`. Applied as score multipliers; thresholds untouched; scores clamped to [0,1]. Evidence annotated so lineage shows the boost was active.
173
+ - **`bench/` benchmark harness** — router-agnostic head-to-head comparison.
174
+ - `Router` protocol — any router that returns `RouterResult` competes.
175
+ - Built-in routers: `ChuzomRouter`, `FixedModelRouter` (cheap/premium endpoints), `StaticChainRouter` (ablation).
176
+ - Hybrid judge: deterministic substring grading for objective prompts, LLM-as-judge for subjective.
177
+ - Pareto frontier — only routers worth picking from at any quality budget.
178
+ - Smoke corpus (5 easy + 5 moderate).
179
+ - **Local installability** — `pip install -e .` now works cleanly. CLI binary `chuzom`, `chuzom doctor`, full subcommand surface verified.
180
+
181
+ ### Changed
182
+ - `chuzom/cache/` package now re-exports legacy `get_cache` / `ClassificationCache` from `cache/classification.py` (moved from `chuzom/cache.py`) alongside the new `SemanticCache` skeleton.
183
+ - `LineageRecord` gained 5 nullable fields. Existing call sites unchanged; new fields default to `None`.
184
+ - `make_record()` accepts optional `agent_id`, `session_id`, `step_index`, `parent_session_id`, `framework` keyword args.
185
+
186
+ ### Tests
187
+ - **112 passing** (51 new for v0.0.2: 35 agent tests, 11 decision-boost tests, 5 framework smoke tests via tools).
188
+ - Coverage: budget envelope (consume / would_exceed / raise patterns), session lifecycle (create / record_step / complete / error / nested rollup), registry (YAML loader, duplicate-id rejection, default-template parse), MCP tool surface (refuse on breach, clamp to hard_max, unknown-agent error shapes), decision boosts (clamp to [0,1], priority preserved, evidence annotated).
189
+
190
+ ### Deferred to v0.0.3+
191
+ - Hermes adapter concrete implementation (pending tool-use format decision).
192
+ - LangGraph / CrewAI / OpenAI Agents SDK / Claude Agent SDK / Pydantic AI concrete adapters.
193
+ - Embedding signal (`sentence-transformers/all-MiniLM-L6-v2`).
194
+ - Semantic response cache (`sqlite-vec` backend).
195
+ - `chuzom_agent_route` wiring to `chuzom.router.route_and_call` (currently returns `would_route: true` + step metadata; caller dispatches).
196
+ - Empirical `quality_gap` + `handoff_penalty` lookup tables deriving from lineage outcomes.
197
+
198
+ ---
199
+
200
+ ## v0.0.1 — Genesis (private fork from llm-router)
201
+
202
+ ### Added
203
+ - Forked llm-router → chuzom. Package renamed, CLI binary renamed, all internal references updated.
204
+ - New module skeletons: `chuzom/signals/`, `chuzom/decisions/`, `chuzom/cache/`, `chuzom/hosts/`, `chuzom/lineage.py`.
205
+ - Config template at `config/signals.yaml` defining the v0 signal/decision DSL.
206
+ - Architecture design at `Docs/ARCHITECTURE.md` (local-only, gitignored).
207
+
208
+ ### Carried over from llm-router
209
+ - Multi-provider routing chain (Ollama → Codex → cheap API → premium).
210
+ - MCP server + tool surface (`llm_query`, `llm_research`, `llm_analyze`, `llm_code`, `llm_generate`, `llm_image`, `llm_orchestrate`).
211
+ - Hooks system (auto-route, enforce-route, session-end, usage-refresh).
212
+ - Cost tracking + circuit breaker per provider.
213
+ - Caveman mode for token-efficient output.
214
+
215
+ ### Deferred to v0.2+
216
+ - Full implementation of signal/decision engine (v0 ships scaffolding only).
217
+ - Semantic response cache backed by sqlite-vec.
218
+ - Empirical lookup tables (quality_gap, handoff_penalty).
219
+ - Reask, fact-check, reasoning-effort signals.
@@ -0,0 +1,145 @@
1
+ # Contributing to Chuzom
2
+
3
+ Thanks for your interest in Chuzom — a local-first LLM router for developer
4
+ workstations. This guide gets you from clone to merged PR.
5
+
6
+ By participating you agree to abide by our [Code of Conduct](CODE_OF_CONDUCT.md).
7
+
8
+ ---
9
+
10
+ ## TL;DR
11
+
12
+ ```bash
13
+ git clone https://github.com/ypollak2/chuzom
14
+ cd chuzom
15
+ uv sync --extra dev # install runtime + dev/test deps
16
+ uv run pytest -q # run the fast test suite
17
+ uvx ruff check src/ tests/ # lint
18
+ ```
19
+
20
+ Then branch, write a failing test, make it pass, and open a PR.
21
+
22
+ ---
23
+
24
+ ## Local development
25
+
26
+ Chuzom targets **Python 3.10+** and uses [uv](https://docs.astral.sh/uv/) for
27
+ environment + dependency management.
28
+
29
+ ```bash
30
+ uv sync --extra dev # core + pytest, pytest-cov, ruff, etc.
31
+ uv run chuzom doctor # sanity-check your local install
32
+ ```
33
+
34
+ Optional extras (install only what you touch):
35
+
36
+ | Extra | Pulls in | Use when |
37
+ |---|---|---|
38
+ | `semantic` | sentence-transformers, sqlite-vec | working on the semantic cache |
39
+ | `tracing` | opentelemetry-sdk + OTLP exporter | working on observability |
40
+ | `postgres` | psycopg | working on the multi-instance budget backend |
41
+ | `code-context` | tree-sitter | working on code-context extraction |
42
+
43
+ ```bash
44
+ uv sync --extra dev --extra tracing
45
+ ```
46
+
47
+ ---
48
+
49
+ ## Tests
50
+
51
+ We follow a test-first workflow. **Write a failing test that reproduces the bug
52
+ or specifies the feature, then make it pass.**
53
+
54
+ ```bash
55
+ uv run pytest -q # fast suite (CI default markers)
56
+ uv run pytest tests/qa/ # a single area
57
+ uv run pytest tests/test_router.py -q # a single file
58
+ uv run pytest --cov=src/chuzom --cov-report=term-missing
59
+ ```
60
+
61
+ The default marker set skips `slow`, `requires_ollama`, and `requires_api_keys`
62
+ (see `addopts` in `pyproject.toml`). CI runs the same default sweep on Python
63
+ 3.11 and 3.13.
64
+
65
+ Guidelines:
66
+
67
+ - New behavior needs tests. Bug fixes start with a failing regression test.
68
+ - Name tests `test_<what>_<condition>_<expected>`.
69
+ - Keep tests isolated — no reliance on `~/.chuzom` state or network. Use the
70
+ fixtures in `tests/conftest.py` and temp paths via `CHUZOM_*_PATH` env vars.
71
+
72
+ ---
73
+
74
+ ## Code style
75
+
76
+ - **Lint:** `uvx ruff check src/ tests/` must be clean (line length 100).
77
+ - **Type hints** on all public function signatures; prefer `X | None` over
78
+ `Optional[X]` (3.10+).
79
+ - **Immutability** — return new objects, don't mutate in place. Prefer
80
+ `@dataclass(frozen=True)` for value objects.
81
+ - **Small, focused modules.** New files beat growing the existing god-modules
82
+ (`router.py`, `cost.py`, `tools/admin.py`); aim for < 800 lines.
83
+ - **Errors:** throw at boundaries, catch at entry points. No bare
84
+ `except Exception: pass` — log with context or re-raise.
85
+ - **No secrets in code or tests.** Provider keys come from env vars only.
86
+
87
+ ---
88
+
89
+ ## Commit messages
90
+
91
+ We use [Conventional Commits](https://www.conventionalcommits.org/):
92
+
93
+ ```
94
+ <type>(<scope>): <description>
95
+ ```
96
+
97
+ Types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`,
98
+ `ci`, `revert`. Example: `fix(router): release budget reservation on cancel`.
99
+
100
+ Keep one concern per PR.
101
+
102
+ ---
103
+
104
+ ## Pull requests
105
+
106
+ 1. Branch from `main`: `git checkout -b fix/short-description`.
107
+ 2. Make your change with tests; keep the diff focused.
108
+ 3. Run `uv run pytest -q` and `uvx ruff check src/ tests/` locally.
109
+ 4. Bump the version + `CHANGELOG.md` only if asked — maintainers handle releases.
110
+ 5. Fill in the PR template checklist. CI (tests + lint + security scans) must be
111
+ green.
112
+
113
+ A maintainer will review. Address review comments by pushing follow-up commits
114
+ (we squash on merge).
115
+
116
+ ---
117
+
118
+ ## Package-distribution safety (important)
119
+
120
+ Chuzom ships to PyPI. **Never** add internal docs, secrets, dev dirs, or local
121
+ venvs to the published sdist. The allowlist/exclude rules live in
122
+ `[tool.hatch.build.targets.sdist]` in `pyproject.toml`. After any packaging
123
+ change, run:
124
+
125
+ ```bash
126
+ uv build
127
+ tar tzf dist/*.tar.gz | grep -v /src/ # confirm only intended files survive
128
+ ```
129
+
130
+ No `.env`, no `CLAUDE.md`, no `tests/`, no `.venv*` in the tarball — ever.
131
+
132
+ ---
133
+
134
+ ## Reporting bugs & requesting features
135
+
136
+ Use the [issue templates](https://github.com/ypollak2/chuzom/issues/new/choose).
137
+ For **security vulnerabilities**, do **not** open a public issue — follow the
138
+ private disclosure process in [SECURITY.md](SECURITY.md).
139
+
140
+ ---
141
+
142
+ ## Questions
143
+
144
+ Open a [discussion or issue](https://github.com/ypollak2/chuzom/issues). We aim
145
+ to respond within a couple of working days.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 LLM Router Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.