code-context-control 2.139.0__tar.gz → 2.141.0__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 (561) hide show
  1. {code_context_control-2.139.0 → code_context_control-2.141.0}/PKG-INFO +1 -1
  2. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/c3.py +9 -2
  3. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/guide/tools.html +1 -1
  4. code_context_control-2.141.0/cli/hook_agent_model.py +68 -0
  5. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hook_dispatch.py +11 -0
  6. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_server.py +200 -7
  7. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/mcp_server.py +29 -3
  8. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/status.py +12 -1
  9. {code_context_control-2.139.0 → code_context_control-2.141.0}/code_context_control.egg-info/PKG-INFO +1 -1
  10. {code_context_control-2.139.0 → code_context_control-2.141.0}/code_context_control.egg-info/SOURCES.txt +5 -0
  11. {code_context_control-2.139.0 → code_context_control-2.141.0}/core/config.py +9 -0
  12. {code_context_control-2.139.0 → code_context_control-2.141.0}/pyproject.toml +1 -1
  13. code_context_control-2.141.0/services/agent_downshift.py +220 -0
  14. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/claude_md.py +1 -1
  15. code_context_control-2.141.0/services/delegate_hints.py +199 -0
  16. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/enforcement_policy.py +38 -0
  17. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/override_policy.py +127 -1
  18. code_context_control-2.141.0/tests/test_delegate_auto.py +362 -0
  19. code_context_control-2.141.0/tests/test_hub_rules_routes.py +330 -0
  20. {code_context_control-2.139.0 → code_context_control-2.141.0}/LICENSE +0 -0
  21. {code_context_control-2.139.0 → code_context_control-2.141.0}/README.md +0 -0
  22. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/__init__.py +0 -0
  23. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/_hook_utils.py +0 -0
  24. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/_shell_writes.py +0 -0
  25. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/commands/__init__.py +0 -0
  26. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/commands/common.py +0 -0
  27. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/commands/parser.py +0 -0
  28. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/docs.html +0 -0
  29. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/edits.html +0 -0
  30. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/guide/access.html +0 -0
  31. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/guide/bitbucket.html +0 -0
  32. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/guide/credentials.html +0 -0
  33. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/guide/getting-started.html +0 -0
  34. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/guide/index.html +0 -0
  35. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/guide/masking.html +0 -0
  36. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/guide/oracle.html +0 -0
  37. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/guide/shared.css +0 -0
  38. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/guide/workflow.html +0 -0
  39. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hook_access_guard.py +0 -0
  40. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hook_artifact.py +0 -0
  41. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hook_auto_snapshot.py +0 -0
  42. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hook_c3_signal.py +0 -0
  43. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hook_c3read.py +0 -0
  44. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hook_codex_lifecycle.py +0 -0
  45. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hook_edit_ledger.py +0 -0
  46. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hook_edit_unlock.py +0 -0
  47. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hook_filter.py +0 -0
  48. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hook_ghost_files.py +0 -0
  49. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hook_pretool_enforce.py +0 -0
  50. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hook_prompt_recall.py +0 -0
  51. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hook_read.py +0 -0
  52. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hook_session_end.py +0 -0
  53. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hook_session_open.py +0 -0
  54. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hook_session_stats.py +0 -0
  55. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hook_terse_advisor.py +0 -0
  56. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/app.js +0 -0
  57. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/add_project.js +0 -0
  58. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/config_editor.js +0 -0
  59. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/drill_artifacts.js +0 -0
  60. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/drill_health.js +0 -0
  61. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/drill_panel.js +0 -0
  62. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/drill_subprojects.js +0 -0
  63. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/drill_tasks.js +0 -0
  64. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/drill_views.js +0 -0
  65. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/global_search.js +0 -0
  66. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/hub_access.js +0 -0
  67. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/hub_ci.js +0 -0
  68. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/hub_cred_audit.js +0 -0
  69. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/hub_credentials.js +0 -0
  70. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/hub_enforcement.js +0 -0
  71. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/hub_locks.js +0 -0
  72. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/hub_tokens.js +0 -0
  73. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/mcp_manager.js +0 -0
  74. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/modals.js +0 -0
  75. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/project_card.js +0 -0
  76. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/project_tree.js +0 -0
  77. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/session_drawer.js +0 -0
  78. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/settings_modal.js +0 -0
  79. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/sidebar.js +0 -0
  80. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/summary_bar.js +0 -0
  81. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/task_board.js +0 -0
  82. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/toasts.js +0 -0
  83. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/components/topbar.js +0 -0
  84. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui/state.js +0 -0
  85. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/hub_ui.html +0 -0
  86. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/mcp_proxy.py +0 -0
  87. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/progress.py +0 -0
  88. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/server.py +0 -0
  89. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/__init__.py +0 -0
  90. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/_grants.py +0 -0
  91. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/_helpers.py +0 -0
  92. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/agent.py +0 -0
  93. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/artifacts.py +0 -0
  94. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/bitbucket.py +0 -0
  95. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/ci.py +0 -0
  96. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/compress.py +0 -0
  97. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/credentials.py +0 -0
  98. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/delegate.py +0 -0
  99. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/edit.py +0 -0
  100. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/edit_verify.py +0 -0
  101. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/edits.py +0 -0
  102. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/federate.py +0 -0
  103. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/filter.py +0 -0
  104. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/impact.py +0 -0
  105. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/jira.py +0 -0
  106. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/locks.py +0 -0
  107. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/memory.py +0 -0
  108. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/override.py +0 -0
  109. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/project.py +0 -0
  110. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/read.py +0 -0
  111. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/search.py +0 -0
  112. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/session.py +0 -0
  113. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/shell.py +0 -0
  114. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/shell_job.py +0 -0
  115. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/shell_nudge.py +0 -0
  116. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/shell_parsers.py +0 -0
  117. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/shell_render.py +0 -0
  118. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/tasks.py +0 -0
  119. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/tools/validate.py +0 -0
  120. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/api.js +0 -0
  121. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/app.js +0 -0
  122. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/components/access.js +0 -0
  123. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/components/bitbucket.js +0 -0
  124. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/components/chat.js +0 -0
  125. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/components/credentials.js +0 -0
  126. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/components/dashboard.js +0 -0
  127. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/components/edits.js +0 -0
  128. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/components/enforcement.js +0 -0
  129. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/components/instructions.js +0 -0
  130. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/components/jira.js +0 -0
  131. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/components/memory.js +0 -0
  132. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/components/sessions.js +0 -0
  133. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/components/settings.js +0 -0
  134. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/components/sidebar.js +0 -0
  135. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/components/tasks.js +0 -0
  136. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/icons.js +0 -0
  137. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/pm_shared.js +0 -0
  138. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/shared.js +0 -0
  139. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui/theme.js +0 -0
  140. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui.html +0 -0
  141. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui_legacy.html +0 -0
  142. {code_context_control-2.139.0 → code_context_control-2.141.0}/cli/ui_nano.html +0 -0
  143. {code_context_control-2.139.0 → code_context_control-2.141.0}/code_context_control.egg-info/dependency_links.txt +0 -0
  144. {code_context_control-2.139.0 → code_context_control-2.141.0}/code_context_control.egg-info/entry_points.txt +0 -0
  145. {code_context_control-2.139.0 → code_context_control-2.141.0}/code_context_control.egg-info/requires.txt +0 -0
  146. {code_context_control-2.139.0 → code_context_control-2.141.0}/code_context_control.egg-info/top_level.txt +0 -0
  147. {code_context_control-2.139.0 → code_context_control-2.141.0}/core/__init__.py +0 -0
  148. {code_context_control-2.139.0 → code_context_control-2.141.0}/core/codex_patch.py +0 -0
  149. {code_context_control-2.139.0 → code_context_control-2.141.0}/core/grok_payload.py +0 -0
  150. {code_context_control-2.139.0 → code_context_control-2.141.0}/core/hook_command.py +0 -0
  151. {code_context_control-2.139.0 → code_context_control-2.141.0}/core/host.py +0 -0
  152. {code_context_control-2.139.0 → code_context_control-2.141.0}/core/ide.py +0 -0
  153. {code_context_control-2.139.0 → code_context_control-2.141.0}/core/mcp_toml.py +0 -0
  154. {code_context_control-2.139.0 → code_context_control-2.141.0}/core/web_security.py +0 -0
  155. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/__init__.py +0 -0
  156. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/config.py +0 -0
  157. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/listeners.py +0 -0
  158. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/mcp_oracle.py +0 -0
  159. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/oracle_server.py +0 -0
  160. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/oracle_ui.html +0 -0
  161. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/__init__.py +0 -0
  162. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/activity_reporter.py +0 -0
  163. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/api_auth.py +0 -0
  164. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/c3_bridge.py +0 -0
  165. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/chat_engine.py +0 -0
  166. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/chat_poll.py +0 -0
  167. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/chat_store.py +0 -0
  168. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/client_tokens.py +0 -0
  169. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/cross_memory.py +0 -0
  170. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/discovery_audit.py +0 -0
  171. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/federated_graph.py +0 -0
  172. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/health_checker.py +0 -0
  173. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/insight_engine.py +0 -0
  174. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/local_session.py +0 -0
  175. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/memory_reader.py +0 -0
  176. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/memory_writer.py +0 -0
  177. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/mobile_api.py +0 -0
  178. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/project_scanner.py +0 -0
  179. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/review_agent.py +0 -0
  180. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/tool_executor.py +0 -0
  181. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/services/tool_registry.py +0 -0
  182. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/activity.js +0 -0
  183. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/agents.js +0 -0
  184. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/app.js +0 -0
  185. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/busy.js +0 -0
  186. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/chat/conversations.js +0 -0
  187. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/chat/input.js +0 -0
  188. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/chat/markdown.js +0 -0
  189. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/chat/send.js +0 -0
  190. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/chat/stream_renderer.js +0 -0
  191. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/chat/toolbar.js +0 -0
  192. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/core.js +0 -0
  193. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/crossgraph.js +0 -0
  194. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/header.js +0 -0
  195. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/insights.js +0 -0
  196. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/projects.js +0 -0
  197. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/qrcode.js +0 -0
  198. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/settings.js +0 -0
  199. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/suggestions.js +0 -0
  200. {code_context_control-2.139.0 → code_context_control-2.141.0}/oracle/ui/theme_tabs.js +0 -0
  201. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/__init__.py +0 -0
  202. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/access_guard.py +0 -0
  203. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/access_telemetry.py +0 -0
  204. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/activity_log.py +0 -0
  205. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/agent_base.py +0 -0
  206. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/agent_locks.py +0 -0
  207. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/agents.py +0 -0
  208. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/agents_workflow.py +0 -0
  209. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/artifact_defs.py +0 -0
  210. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/artifact_store.py +0 -0
  211. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/atomic_json.py +0 -0
  212. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/auto_memory.py +0 -0
  213. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/background_service.py +0 -0
  214. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/bench/__init__.py +0 -0
  215. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/bench/delegate_eval.py +0 -0
  216. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/bench/delegate_write_eval.py +0 -0
  217. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/bench/external/__init__.py +0 -0
  218. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/bench/external/aider_polyglot.py +0 -0
  219. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/bench/external/swe_bench.py +0 -0
  220. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/bench/map_eval.py +0 -0
  221. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/bench/search_eval.py +0 -0
  222. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/bench/shell_eval.py +0 -0
  223. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/benchmark_dashboard.py +0 -0
  224. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/bitbucket_client.py +0 -0
  225. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/bitbucket_credentials.py +0 -0
  226. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/ci_act.py +0 -0
  227. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/ci_cache.py +0 -0
  228. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/ci_expr.py +0 -0
  229. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/ci_failures.py +0 -0
  230. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/ci_github.py +0 -0
  231. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/ci_impact.py +0 -0
  232. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/ci_intel.py +0 -0
  233. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/ci_runner.py +0 -0
  234. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/ci_workflow.py +0 -0
  235. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/circuit_breaker.py +0 -0
  236. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/codex_integration.py +0 -0
  237. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/codex_transcript.py +0 -0
  238. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/compressor.py +0 -0
  239. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/context_snapshot.py +0 -0
  240. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/conversation_store.py +0 -0
  241. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/cred_audit.py +0 -0
  242. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/cred_telemetry.py +0 -0
  243. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/credential_store.py +0 -0
  244. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/delegate_agents.py +0 -0
  245. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/delegate_write.py +0 -0
  246. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/dir_map.py +0 -0
  247. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/doc_index.py +0 -0
  248. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/e2e_benchmark.py +0 -0
  249. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/e2e_evaluator.py +0 -0
  250. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/e2e_tasks.py +0 -0
  251. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/edit_ledger.py +0 -0
  252. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/embedding_index.py +0 -0
  253. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/error_reporting.py +0 -0
  254. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/file_map.py +0 -0
  255. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/file_memory.py +0 -0
  256. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/git_context.py +0 -0
  257. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/grok_integration.py +0 -0
  258. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/grok_transcript.py +0 -0
  259. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/host_sessions.py +0 -0
  260. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/hub_service.py +0 -0
  261. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/index_store.py +0 -0
  262. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/indexer.py +0 -0
  263. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/jira_client.py +0 -0
  264. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/jira_cloud.py +0 -0
  265. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/jira_credentials.py +0 -0
  266. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/jira_data_center.py +0 -0
  267. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/jira_links.py +0 -0
  268. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/lexical_index.py +0 -0
  269. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/mask_activation.py +0 -0
  270. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/mask_mirror.py +0 -0
  271. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/mask_presets.py +0 -0
  272. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/memory.py +0 -0
  273. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/memory_consolidator.py +0 -0
  274. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/memory_distiller.py +0 -0
  275. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/memory_graph.py +0 -0
  276. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/memory_grounder.py +0 -0
  277. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/memory_queue.py +0 -0
  278. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/memory_scorer.py +0 -0
  279. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/metrics.py +0 -0
  280. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/notifications.py +0 -0
  281. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/ollama_bridge.py +0 -0
  282. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/ollama_client.py +0 -0
  283. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/ollama_credentials.py +0 -0
  284. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/oracle_service.py +0 -0
  285. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/output_filter.py +0 -0
  286. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/override_costs.py +0 -0
  287. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/override_grants.py +0 -0
  288. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/override_requests.py +0 -0
  289. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/override_wake.py +0 -0
  290. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/parser.py +0 -0
  291. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/project_manager.py +0 -0
  292. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/project_runtime.py +0 -0
  293. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/protocol.py +0 -0
  294. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/proxy_state.py +0 -0
  295. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/repo_map.py +0 -0
  296. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/repo_shape.py +0 -0
  297. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/reranker.py +0 -0
  298. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/retention.py +0 -0
  299. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/retrieval.py +0 -0
  300. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/retrieval_broker.py +0 -0
  301. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/router.py +0 -0
  302. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/runtime.py +0 -0
  303. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/scanner.py +0 -0
  304. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/session_benchmark.py +0 -0
  305. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/session_live.py +0 -0
  306. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/session_manager.py +0 -0
  307. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/session_preloader.py +0 -0
  308. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/shell_jobs.py +0 -0
  309. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/shell_output.py +0 -0
  310. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/subprojects.py +0 -0
  311. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/task_store.py +0 -0
  312. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/telemetry.py +0 -0
  313. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/text_index.py +0 -0
  314. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/time_tracker.py +0 -0
  315. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/tool_classifier.py +0 -0
  316. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/transcript_index.py +0 -0
  317. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/validation_cache.py +0 -0
  318. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/vector_store.py +0 -0
  319. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/watcher.py +0 -0
  320. {code_context_control-2.139.0 → code_context_control-2.141.0}/services/win_subprocess.py +0 -0
  321. {code_context_control-2.139.0 → code_context_control-2.141.0}/setup.cfg +0 -0
  322. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_access_builtin_optout.py +0 -0
  323. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_access_guard.py +0 -0
  324. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_access_guard_meta.py +0 -0
  325. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_access_guard_shell_project.py +0 -0
  326. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_access_guard_surfaces.py +0 -0
  327. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_access_guard_wiring.py +0 -0
  328. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_activity_log_find_last.py +0 -0
  329. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_activity_reporter.py +0 -0
  330. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_agent_locks.py +0 -0
  331. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_aider_polyglot.py +0 -0
  332. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_antigravity_transition.py +0 -0
  333. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_artifact_store.py +0 -0
  334. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_artifact_tool.py +0 -0
  335. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_atomic_json.py +0 -0
  336. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_background_service.py +0 -0
  337. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_bitbucket_cli_smoke.py +0 -0
  338. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_bitbucket_client.py +0 -0
  339. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_bitbucket_config_fallback.py +0 -0
  340. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_bitbucket_credentials.py +0 -0
  341. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_bitbucket_tool.py +0 -0
  342. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_builtin_modes.py +0 -0
  343. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_c3_bridge_project_artifacts.py +0 -0
  344. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_c3_shell.py +0 -0
  345. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_chat_poll.py +0 -0
  346. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_ci_act.py +0 -0
  347. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_ci_cache.py +0 -0
  348. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_ci_dag_ownership.py +0 -0
  349. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_ci_expr.py +0 -0
  350. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_ci_impact.py +0 -0
  351. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_ci_intel.py +0 -0
  352. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_ci_runner.py +0 -0
  353. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_ci_workflow.py +0 -0
  354. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_circuit_breaker.py +0 -0
  355. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_claude_md_merge.py +0 -0
  356. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_claude_md_updater.py +0 -0
  357. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_cli_smoke.py +0 -0
  358. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_codex_mcp_transport.py +0 -0
  359. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_codex_native.py +0 -0
  360. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_compressor_large_file.py +0 -0
  361. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_confirm_guard.py +0 -0
  362. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_confirm_guard_wiring.py +0 -0
  363. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_cooccurrence_bounds.py +0 -0
  364. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_cred_audit.py +0 -0
  365. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_cred_telemetry.py +0 -0
  366. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_credential_login_kind.py +0 -0
  367. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_credential_store.py +0 -0
  368. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_credential_ui_parity.py +0 -0
  369. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_credentials_routes.py +0 -0
  370. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_credentials_tool.py +0 -0
  371. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_creds_cli_smoke.py +0 -0
  372. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_delegate_adoption_d4.py +0 -0
  373. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_delegate_cascade.py +0 -0
  374. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_delegate_claude_d1.py +0 -0
  375. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_delegate_eval.py +0 -0
  376. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_delegate_grok.py +0 -0
  377. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_delegate_host_d2.py +0 -0
  378. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_delegate_scout_d3.py +0 -0
  379. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_delegate_telemetry_d0.py +0 -0
  380. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_delegate_thinking_cap.py +0 -0
  381. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_delegate_tuning.py +0 -0
  382. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_delegate_version_probe.py +0 -0
  383. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_delegate_write.py +0 -0
  384. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_delegate_write_eval.py +0 -0
  385. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_dir_map_c3.py +0 -0
  386. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_e2e_benchmark.py +0 -0
  387. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_edit_ledger_deadline.py +0 -0
  388. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_edit_ledger_hook.py +0 -0
  389. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_edit_locking.py +0 -0
  390. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_edit_normalization.py +0 -0
  391. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_edit_verify.py +0 -0
  392. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_embedding_index_deadlock.py +0 -0
  393. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_enforcement_flip.py +0 -0
  394. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_enforcement_policy.py +0 -0
  395. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_enforcement_routes.py +0 -0
  396. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_env_parser.py +0 -0
  397. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_failed_calls_do_not_unlock.py +0 -0
  398. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_federated_graph.py +0 -0
  399. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_file_map_c1.py +0 -0
  400. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_filter_backoff.py +0 -0
  401. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_ghost_files.py +0 -0
  402. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_ghost_generation.py +0 -0
  403. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_git_branch_awareness.py +0 -0
  404. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_grok_native.py +0 -0
  405. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hook_access_guard.py +0 -0
  406. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hook_codex_compat.py +0 -0
  407. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hook_dispatch.py +0 -0
  408. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hook_grok_compat.py +0 -0
  409. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hook_pretool_enforce.py +0 -0
  410. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hook_prompt_recall.py +0 -0
  411. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hook_session_end.py +0 -0
  412. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hook_smoke.py +0 -0
  413. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hook_state.py +0 -0
  414. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hook_utf8_stdio.py +0 -0
  415. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hub_credentials_route.py +0 -0
  416. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hub_credentials_routes_write.py +0 -0
  417. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hub_enforcement_routes.py +0 -0
  418. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hub_hook_migration.py +0 -0
  419. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hub_inspect_api.py +0 -0
  420. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hub_locks_routes.py +0 -0
  421. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hub_oracle_service_routes.py +0 -0
  422. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hub_override_policy_routes.py +0 -0
  423. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hub_override_routes.py +0 -0
  424. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hub_server_smoke.py +0 -0
  425. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_hub_subproject_links.py +0 -0
  426. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_ide_workflow_adaptation.py +0 -0
  427. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_index_cap_not_hardcoded.py +0 -0
  428. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_init_clear_preserves_user_content.py +0 -0
  429. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_init_scan.py +0 -0
  430. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_install_mcp_entrypoint.py +0 -0
  431. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_jira_cli_smoke.py +0 -0
  432. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_jira_client.py +0 -0
  433. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_jira_config_fallback.py +0 -0
  434. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_jira_credentials.py +0 -0
  435. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_jira_links.py +0 -0
  436. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_jira_routes.py +0 -0
  437. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_jira_tool.py +0 -0
  438. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_large_files_c4.py +0 -0
  439. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_lazy_store_init.py +0 -0
  440. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_map_eval.py +0 -0
  441. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_map_telemetry_c0.py +0 -0
  442. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_mask_guard.py +0 -0
  443. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_mask_routes.py +0 -0
  444. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_mask_surfaces.py +0 -0
  445. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_mcp_host_guard.py +0 -0
  446. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_mcp_memory_timeout.py +0 -0
  447. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_mcp_server_smoke.py +0 -0
  448. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_mcp_toml.py +0 -0
  449. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_memory_distiller.py +0 -0
  450. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_memory_graph_api.py +0 -0
  451. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_memory_queue.py +0 -0
  452. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_memory_system.py +0 -0
  453. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_mobile_api.py +0 -0
  454. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_mobile_clients.py +0 -0
  455. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_mobile_extras.py +0 -0
  456. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_mobile_jobs_ci.py +0 -0
  457. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_mobile_override_costs.py +0 -0
  458. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_mobile_override_routes.py +0 -0
  459. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_mobile_security_api.py +0 -0
  460. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_no_stale_model_pins.py +0 -0
  461. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_notification_dedup.py +0 -0
  462. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_notification_discipline.py +0 -0
  463. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_notification_kinds.py +0 -0
  464. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_ollama_credentials.py +0 -0
  465. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_oracle_api_auth.py +0 -0
  466. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_oracle_apikey_api.py +0 -0
  467. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_oracle_c3_bridge.py +0 -0
  468. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_oracle_chat_engine.py +0 -0
  469. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_oracle_chat_store.py +0 -0
  470. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_oracle_discovery_api.py +0 -0
  471. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_oracle_discovery_audit.py +0 -0
  472. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_oracle_health_probe.py +0 -0
  473. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_oracle_local_auth.py +0 -0
  474. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_oracle_loopback.py +0 -0
  475. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_oracle_ollama_bridge.py +0 -0
  476. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_oracle_scanner_cache.py +0 -0
  477. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_oracle_security_fixes.py +0 -0
  478. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_oracle_session_bootstrap.py +0 -0
  479. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_oracle_subproject_awareness.py +0 -0
  480. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_oracle_ui_bundle.py +0 -0
  481. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_output_filter.py +0 -0
  482. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_override_costs.py +0 -0
  483. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_override_grants.py +0 -0
  484. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_override_grants_mcp.py +0 -0
  485. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_override_requests.py +0 -0
  486. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_override_wake.py +0 -0
  487. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_permissions.py +0 -0
  488. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_pm_api.py +0 -0
  489. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_project_manager.py +0 -0
  490. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_project_manager_merge.py +0 -0
  491. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_project_tool.py +0 -0
  492. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_read_coercion.py +0 -0
  493. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_read_edit_parity.py +0 -0
  494. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_read_outside_root.py +0 -0
  495. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_related_facts.py +0 -0
  496. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_repo_map.py +0 -0
  497. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_repo_shape.py +0 -0
  498. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_response_boilerplate.py +0 -0
  499. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_retention.py +0 -0
  500. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_review_digest.py +0 -0
  501. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_search_eval.py +0 -0
  502. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_search_p1.py +0 -0
  503. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_search_p2.py +0 -0
  504. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_search_p2b.py +0 -0
  505. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_search_p3.py +0 -0
  506. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_search_p4.py +0 -0
  507. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_search_p5.py +0 -0
  508. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_service_durability.py +0 -0
  509. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_session_benchmark.py +0 -0
  510. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_session_budget.py +0 -0
  511. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_session_live.py +0 -0
  512. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_shell_budget_s1.py +0 -0
  513. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_shell_creds.py +0 -0
  514. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_shell_eval.py +0 -0
  515. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_shell_jobs_s3.py +0 -0
  516. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_shell_nudge_s4.py +0 -0
  517. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_shell_output.py +0 -0
  518. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_shell_parsers_s2.py +0 -0
  519. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_shell_robustness.py +0 -0
  520. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_shell_telemetry_s0.py +0 -0
  521. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_shell_write_ledger.py +0 -0
  522. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_shell_writes.py +0 -0
  523. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_subproject_clear_scope.py +0 -0
  524. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_subproject_depth_consumers.py +0 -0
  525. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_subproject_exclusion.py +0 -0
  526. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_subproject_federation.py +0 -0
  527. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_subproject_linkage_api.py +0 -0
  528. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_subprojects.py +0 -0
  529. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_swe_bench.py +0 -0
  530. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_task_store.py +0 -0
  531. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_task_tool.py +0 -0
  532. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_time_tracker.py +0 -0
  533. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_token_telemetry.py +0 -0
  534. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_token_tracking.py +0 -0
  535. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_tool_registry.py +0 -0
  536. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_ui_jsx_syntax.py +0 -0
  537. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_upgrade_and_version.py +0 -0
  538. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_validate.py +0 -0
  539. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_vault_write_guard.py +0 -0
  540. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_version_sync.py +0 -0
  541. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_watcher_pruning.py +0 -0
  542. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_web_security.py +0 -0
  543. {code_context_control-2.139.0 → code_context_control-2.141.0}/tests/test_windows_reliability.py +0 -0
  544. {code_context_control-2.139.0 → code_context_control-2.141.0}/tui/__init__.py +0 -0
  545. {code_context_control-2.139.0 → code_context_control-2.141.0}/tui/backend.py +0 -0
  546. {code_context_control-2.139.0 → code_context_control-2.141.0}/tui/main.py +0 -0
  547. {code_context_control-2.139.0 → code_context_control-2.141.0}/tui/screens/__init__.py +0 -0
  548. {code_context_control-2.139.0 → code_context_control-2.141.0}/tui/screens/benchmark_view.py +0 -0
  549. {code_context_control-2.139.0 → code_context_control-2.141.0}/tui/screens/claudemd_view.py +0 -0
  550. {code_context_control-2.139.0 → code_context_control-2.141.0}/tui/screens/compress_view.py +0 -0
  551. {code_context_control-2.139.0 → code_context_control-2.141.0}/tui/screens/index_view.py +0 -0
  552. {code_context_control-2.139.0 → code_context_control-2.141.0}/tui/screens/init_view.py +0 -0
  553. {code_context_control-2.139.0 → code_context_control-2.141.0}/tui/screens/mcp_view.py +0 -0
  554. {code_context_control-2.139.0 → code_context_control-2.141.0}/tui/screens/optimize_view.py +0 -0
  555. {code_context_control-2.139.0 → code_context_control-2.141.0}/tui/screens/pipe_view.py +0 -0
  556. {code_context_control-2.139.0 → code_context_control-2.141.0}/tui/screens/projects_view.py +0 -0
  557. {code_context_control-2.139.0 → code_context_control-2.141.0}/tui/screens/search_view.py +0 -0
  558. {code_context_control-2.139.0 → code_context_control-2.141.0}/tui/screens/session_view.py +0 -0
  559. {code_context_control-2.139.0 → code_context_control-2.141.0}/tui/screens/stats.py +0 -0
  560. {code_context_control-2.139.0 → code_context_control-2.141.0}/tui/screens/ui_view.py +0 -0
  561. {code_context_control-2.139.0 → code_context_control-2.141.0}/tui/theme.tcss +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-context-control
3
- Version: 2.139.0
3
+ Version: 2.141.0
4
4
  Summary: Local MCP code-intelligence for AI coding tools: surgical search/read/edit, agent-config version history, path-level access + masking guards, and a multi-project hub.
5
5
  Author-email: Dimitri Tselenchuk <dtselenc@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -91,7 +91,10 @@ console = Console() if HAS_RICH else None
91
91
  # Config
92
92
  CONFIG_DIR = ".c3"
93
93
  CONFIG_FILE = ".c3/config.json"
94
- __version__ = "2.139.0"
94
+ __version__ = "2.141.0"
95
+
96
+ # The PreToolUse matcher for native subagent calls (installer and hub migration).
97
+ AGENT_MATCHER = "Agent|Task"
95
98
 
96
99
 
97
100
  def _compress_file_cli(compressor, path, mode="smart", **kw):
@@ -5078,7 +5081,7 @@ back to native tools as the task progresses.
5078
5081
  - **Filter**: `c3_filter(text=...)` — for terminal output >10 lines
5079
5082
  - **Shell**: `c3_shell(cmd, timeout=60)` — structured shell exec (tests/git/build). Auto-filters output, logs git mutations to the ledger. Native Bash for interactive/TTY only
5080
5083
  - **Memory**: `c3_memory(action='recall')` — full recall. `index` + `fetch` for token-efficient two-step retrieval
5081
- - **Delegate**: `c3_delegate(task, task_type, context|file_path)` — your own provider one tier down (default `backend='host'`, `tier='small'`; Claude Code: Haiku) for bounded answers: summarize a diff/log, explain a function, triage a traceback. `scout=true` lets it look files up itself; `write_paths='a.py,b.py'` has Sonnet make a change you specified in only those files and return the diff. Multi-step work: the `c3-scout` (haiku) / `c3-worker` (sonnet) subagents
5084
+ - **Delegate**: `c3_delegate(task, task_type, context|file_path)` — your own provider one tier down (default `backend='host'`, `tier='small'`; Claude Code: Haiku) for bounded answers: summarize a diff/log, explain a function, triage a traceback. `scout=true` lets it look files up itself; `write_paths='a.py,b.py'` has Sonnet make a change you specified in only those files and return the diff. Multi-step work: the `c3-scout` (haiku) / `c3-worker` (sonnet) subagents; an `Agent` call with no `model` runs one tier below you (pass `model=` to choose)
5082
5085
  - **Local CI** (v2.79.0+): `c3_ci(action='inspect|run|rerun|failures')` — run THIS repo's real `.github/workflows` here instead of pushing for feedback. `run` executes in `needs` order; `failures` gives {file,line,message}; `rerun` retries only what failed. Only `FULL_CI_PASS` means safe to push — `PARTIAL_PASS` means something did not run (other OS, unsupported action, or your selection).
5083
5086
  - **Bitbucket** (v2.30.0+, when `c3 bitbucket login` has run): `c3_bitbucket(action='list_prs|get_pr|merge_pr|...')` — self-hosted Bitbucket Data Center / Server. Token in OS keyring; mutating actions auto-log to the edit ledger.
5084
5087
  - **Cross-project** (v2.31.0+): `c3_project(action='list|scan|search|read|edit|...', project='<name|path>')` — discover and operate on OTHER c3-installed projects. Reads run freely; writes (edit/shell/memory) need `allow_write=true`.
@@ -5697,6 +5700,10 @@ def cmd_install_mcp(args):
5697
5700
  shell_matcher,
5698
5701
  "run_shell_command",
5699
5702
  ]
5703
+ # Native subagents (v2.140.0): a blank `model` is filled one tier below
5704
+ # the parent by hook_agent_model — without this matcher PreToolUse
5705
+ # never fires for Agent calls.
5706
+ _pre_matcher_names.append(AGENT_MATCHER)
5700
5707
  desired_pre_hooks = [
5701
5708
  {"matcher": m, "hooks": [{"type": "command", "command": hook_pretool_cmd}]}
5702
5709
  for m in _pre_matcher_names
@@ -979,7 +979,7 @@ c3_delegate(task=<span class="str">'Rename calc_total to order_total in its defi
979
979
  <div class="callout callout-info">
980
980
  <span class="callout-icon">ℹ️</span>
981
981
  <div class="callout-body">
982
- For multi-step work in Claude Code, <code>c3 install-mcp</code> also writes two subagents to <code>.claude/agents</code>: <code>c3-scout</code> (Haiku, read-only) and <code>c3-worker</code> (Sonnet). They run inside your session, so C3's hooks apply to them. Skip them with <code>--no-agents</code>. <code>c3 delegate-eval</code> measures pass rate and cost per backend and tier on your machine.
982
+ For multi-step work in Claude Code, <code>c3 install-mcp</code> also writes two subagents to <code>.claude/agents</code>: <code>c3-scout</code> (Haiku, read-only) and <code>c3-worker</code> (Sonnet). They run inside your session, so C3's hooks apply to them. Skip them with <code>--no-agents</code>. Any other <code>Agent</code> call that leaves <code>model</code> blank runs one tier below your session (Fable → Opus → Sonnet, never below Sonnet); set <code>delegate.agent_downshift</code> to <code>"off"</code> to keep the parent's model. When your own work looks delegable, a <code>[c3:delegate-hint]</code> line on the tool response names the call to make. <code>c3 delegate-eval</code> measures pass rate and cost per backend and tier on your machine.
983
983
  </div>
984
984
  </div>
985
985
  </div>
@@ -0,0 +1,68 @@
1
+ """PreToolUse sub-hook: a native subagent with no ``model`` gets one tier below its parent.
2
+
3
+ Routed by cli/hook_dispatch.py for ``Agent`` / ``Task`` on Claude Code only;
4
+ the policy lives in services/agent_downshift.py. Returns
5
+ ``hookSpecificOutput.updatedInput`` (the whole tool_input with ``model`` set),
6
+ or None to leave the call as it is. Every decision on a blank call — applied
7
+ or not, and why — is one ``agent_downshift`` telemetry row, so coverage is
8
+ measurable (how many calls fell through as ``parent_unknown``).
9
+
10
+ Opt out per project with ``delegate.agent_downshift: "off"``, or for a shell
11
+ with ``C3_AGENT_DOWNSHIFT=0``. Never raises into the tool call.
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import os
16
+ import sys
17
+ from pathlib import Path
18
+
19
+ sys.path.insert(0, str(Path(__file__).parent.parent))
20
+
21
+ from cli._hook_utils import find_project, log_hook_error # noqa: E402
22
+
23
+
24
+ def run(payload: dict, project_path: Path | None = None):
25
+ try:
26
+ return _run(payload, project_path)
27
+ except Exception as exc: # a model choice is never worth a failed tool call
28
+ log_hook_error("hook_agent_model", exc)
29
+ return None
30
+
31
+
32
+ def _run(payload: dict, project_path):
33
+ from services import agent_downshift as ad
34
+
35
+ if str(payload.get("tool_name") or "") not in ad.SUBAGENT_TOOLS:
36
+ return None
37
+ tool_input = payload.get("tool_input")
38
+ if not isinstance(tool_input, dict):
39
+ return None
40
+ if str(tool_input.get("model") or "").strip():
41
+ return None # the caller chose
42
+ if os.environ.get("C3_AGENT_DOWNSHIFT", "").strip().lower() in ("0", "off", "false", "no"):
43
+ return None
44
+ project = find_project(payload, project_path)
45
+ if project is None:
46
+ return None
47
+ from core.config import load_delegate_config
48
+
49
+ cfg = load_delegate_config(str(project))
50
+ stype = str(tool_input.get("subagent_type") or "general-purpose")
51
+ if ":" in stype:
52
+ return None # plugin agent: its definition is not ours to second-guess
53
+ if ad.definition_sets_model(stype, project):
54
+ return None
55
+ parent, source = ad.parent_model(payload, project)
56
+ target, reason = ad.resolve(stype, parent, cfg)
57
+ try:
58
+ from services.telemetry import append_telemetry_record
59
+ append_telemetry_record(project, {"tool": "agent_downshift" if target else "agent_downshift_skip",
60
+ "detail": {
61
+ "subagent_type": stype, "parent_model": parent, "parent_source": source,
62
+ "model": target, "reason": reason, "applied": bool(target)}})
63
+ except Exception:
64
+ pass
65
+ if not target:
66
+ return None
67
+ return {"hookSpecificOutput": {"hookEventName": "PreToolUse",
68
+ "updatedInput": {**tool_input, "model": target}}}
@@ -136,6 +136,10 @@ def _routes(event: str, raw_tool: str, norm_tool: str, host: str = HOST_CLAUDE):
136
136
  yield "hook_access_guard"
137
137
  # hook_pretool_enforce self-filters via its _PREREQS table.
138
138
  yield "hook_pretool_enforce"
139
+ # A native subagent with no model inherits the parent's; this fills
140
+ # one in (services/agent_downshift.py). Claude Code only.
141
+ if raw_tool in ("Agent", "Task") and host == HOST_CLAUDE:
142
+ yield "hook_agent_model"
139
143
  elif event == "posttool":
140
144
  # hook_filter is the ONE sub-hook that reads the whole tool payload:
141
145
  # it tiktoken-encodes the entire Bash output to measure savings, a
@@ -402,6 +406,7 @@ def merge_outputs(outputs: list, warnings: list, is_gemini: bool = False,
402
406
  host = HOST_GEMINI if is_gemini else HOST_CLAUDE
403
407
 
404
408
  deny_hso = None
409
+ updated_input = None
405
410
  contexts: list = []
406
411
  texts: list = []
407
412
  tool_result = None
@@ -413,6 +418,8 @@ def merge_outputs(outputs: list, warnings: list, is_gemini: bool = False,
413
418
  if isinstance(hso, dict):
414
419
  if deny_hso is None and hso.get("permissionDecision") == "deny":
415
420
  deny_hso = hso
421
+ if updated_input is None and isinstance(hso.get("updatedInput"), dict):
422
+ updated_input = hso["updatedInput"]
416
423
  nested_ctx = hso.get("additionalContext")
417
424
  if nested_ctx and hso.get("permissionDecision") != "deny":
418
425
  contexts.append(str(nested_ctx))
@@ -435,6 +442,10 @@ def merge_outputs(outputs: list, warnings: list, is_gemini: bool = False,
435
442
  result: dict = {}
436
443
  if deny_hso is not None:
437
444
  result["hookSpecificOutput"] = deny_hso
445
+ elif updated_input is not None and host == HOST_CLAUDE and event == "pretool":
446
+ # A rewritten tool input (hook_agent_model) — never alongside a deny.
447
+ result["hookSpecificOutput"] = {"hookEventName": "PreToolUse",
448
+ "updatedInput": updated_input}
438
449
  if tool_result is not None:
439
450
  if is_gemini:
440
451
  # Gemini has no tool_result replacement — degrade to context,
@@ -2982,6 +2982,65 @@ def api_projects_enforcement_set():
2982
2982
  return jsonify(result)
2983
2983
 
2984
2984
 
2985
+ @app.route("/api/projects/enforcement/clear", methods=["POST"])
2986
+ def api_projects_enforcement_clear():
2987
+ """Drop a scope's `enforcement` section so it inherits again.
2988
+
2989
+ Body: ``{path?, scope?}`` — same scope rules as the set route. There is
2990
+ no mode a surface can WRITE that means "use the global default" (resolve
2991
+ stops at the first section it finds), so "inherit" is a removal, and it
2992
+ gets its own verb rather than a magic mode string. Nothing to clear is a
2993
+ 200 with ``cleared: false``: the caller asked for the state it is in.
2994
+ Audited on the target project like a set.
2995
+ """
2996
+ from services import enforcement_policy as ep
2997
+
2998
+ data = request.get_json(silent=True) or {}
2999
+ path = (data.get("path") or "").strip()
3000
+ scope = (data.get("scope") or "project").strip().lower()
3001
+ if scope not in ("project", "global"):
3002
+ return jsonify({"error": "scope must be 'project' or 'global'"}), 400
3003
+ if scope == "project":
3004
+ if not path:
3005
+ return jsonify({"error": "path is required for project scope"}), 400
3006
+ try:
3007
+ resolved = _resolve_project_path(path)
3008
+ except ValueError as e:
3009
+ return jsonify({"error": str(e)}), 404
3010
+ else:
3011
+ resolved = "."
3012
+
3013
+ try:
3014
+ result = ep.clear(resolved, scope=scope)
3015
+ except (ValueError, TypeError) as e:
3016
+ return jsonify({"error": str(e)}), 400
3017
+
3018
+ if scope == "project" and result.get("cleared"):
3019
+ detail = {"kind": "enforcement", "action": "clear",
3020
+ "previous": result.get("previous", ""),
3021
+ "mode": result.get("mode", ""), "scope": result.get("scope", ""),
3022
+ "via": "hub"}
3023
+ summary = (f"tool discipline {result.get('previous') or 'default'} -> "
3024
+ f"inherit ({result.get('mode')} from {result.get('scope')}) "
3025
+ "via the Hub")
3026
+ try:
3027
+ from services.activity_log import ActivityLog
3028
+ ActivityLog(resolved).log("access_action", dict(detail))
3029
+ except Exception:
3030
+ pass
3031
+ try:
3032
+ from services.edit_ledger import EditLedger
3033
+ EditLedger(resolved).log_edit(
3034
+ file="enforcement://project",
3035
+ change_type="enforcement_clear",
3036
+ summary=summary,
3037
+ tags=["enforcement", "access"],
3038
+ detail=detail)
3039
+ except Exception:
3040
+ pass
3041
+ return jsonify(result)
3042
+
3043
+
2985
3044
  @app.route("/api/projects/enforcement/denials/search", methods=["GET"])
2986
3045
  def api_projects_enforcement_denials_search():
2987
3046
  """Search one project's raw denial events. Read-only; newest first.
@@ -3260,6 +3319,43 @@ def api_hub_override_costs():
3260
3319
  "project": project_path})
3261
3320
 
3262
3321
 
3322
+ #: Verbatim from the spec, and the one thing a toggle screen must not let the
3323
+ #: reader forget: policy is a floor, not a promise.
3324
+ _OVERRIDE_POLICY_NOTE = (
3325
+ "Project and global policy merge by tightening only: a layer is "
3326
+ "escalatable iff both scopes allow it, and the numeric limits take "
3327
+ "the smaller value."
3328
+ )
3329
+
3330
+
3331
+ def _hub_policy_audit(project_path: str, action: str, detail_extra: dict) -> None:
3332
+ """One activity row + ledger entry per override-POLICY edit on the target.
3333
+
3334
+ Key names and the widening list only — never values of ``wake`` (an argv
3335
+ this machine runs). A policy edit changes what a single tap can allow, so
3336
+ a surface that can make it for many projects at once must leave a trail
3337
+ on every one. Failure-safe.
3338
+ """
3339
+ detail = {"kind": "override_policy", "action": action, "via": "hub"}
3340
+ detail.update(detail_extra or {})
3341
+ widened = detail.get("widened") or []
3342
+ summary = (f"override policy {action} via the Hub"
3343
+ + (f" (widened: {', '.join(widened)})" if widened else ""))
3344
+ try:
3345
+ from services.activity_log import ActivityLog as _AL
3346
+ _AL(str(project_path)).log("access_action", dict(detail))
3347
+ except Exception:
3348
+ pass
3349
+ try:
3350
+ from services.edit_ledger import EditLedger
3351
+ EditLedger(str(project_path)).log_edit(
3352
+ file="override://policy",
3353
+ change_type=f"override_policy_{action}",
3354
+ summary=summary, tags=["override", "policy"], detail=dict(detail))
3355
+ except Exception:
3356
+ pass
3357
+
3358
+
3263
3359
  @app.route("/api/hub/overrides/policy", methods=["GET"])
3264
3360
  def api_hub_override_policy_get():
3265
3361
  """The effective `override` section for one project.
@@ -3289,13 +3385,7 @@ def api_hub_override_policy_get():
3289
3385
  "layers": list(opol.LAYER_KEYS),
3290
3386
  "typed_confirm_layers": sorted(opol.TYPED_CONFIRM_LAYERS),
3291
3387
  "hard_max_ttl_s": opol.HARD_MAX_TTL_S,
3292
- # Verbatim from the spec, and the one thing a toggle screen must not
3293
- # let the reader forget: policy is a floor, not a promise.
3294
- "coverage_note": (
3295
- "Project and global policy merge by tightening only: a layer is "
3296
- "escalatable iff both scopes allow it, and the numeric limits take "
3297
- "the smaller value."
3298
- ),
3388
+ "coverage_note": _OVERRIDE_POLICY_NOTE,
3299
3389
  })
3300
3390
 
3301
3391
 
@@ -3334,11 +3424,107 @@ def api_hub_override_policy_set():
3334
3424
  return jsonify(exc.payload), exc.status
3335
3425
  except (OSError, ValueError) as exc:
3336
3426
  return jsonify({"error": f"{type(exc).__name__}: {exc}"}), 500
3427
+ section = data.get("override") or {}
3428
+ keys = [k for k in section if k != "layers"]
3429
+ keys += [f"layers.{k}" for k in (section.get("layers") or {})]
3430
+ _hub_policy_audit(project_path, "set",
3431
+ {"keys": sorted(keys), "widened": list(widens)})
3337
3432
  return jsonify({"path": project_path, "written": written,
3338
3433
  "policy": opol.resolve(project_path).as_dict(),
3339
3434
  "widened": widens})
3340
3435
 
3341
3436
 
3437
+ @app.route("/api/hub/overrides/policy/overview", methods=["GET"])
3438
+ def api_hub_override_policy_overview():
3439
+ """Every registered project's effective override policy in one call.
3440
+
3441
+ The cross-project read a bulk editor needs (C3 Desk's Rules view), shaped
3442
+ like the enforcement overview: per-row isolation, so one unreadable
3443
+ project reports ``error`` instead of blanking the page, and a corrupt
3444
+ section is reported as corrupt rather than as the disabled policy it
3445
+ resolves to. ``project_keys`` names what the project pins itself, so a
3446
+ screen can tell an inherited value from a chosen one. The global scope is
3447
+ served READ-ONLY: ``write_section`` is project-scope by design.
3448
+ """
3449
+ from services import override_policy as opol
3450
+
3451
+ rows = []
3452
+ for p in _pm().list_projects():
3453
+ ppath = str(p.get("path") or "")
3454
+ row = {"name": p.get("name") or Path(ppath).name, "path": ppath,
3455
+ "initialized": True, "error": None, "policy": None,
3456
+ "configured": False, "corrupt": False, "project_keys": []}
3457
+ try:
3458
+ if not (Path(ppath) / ".c3").is_dir():
3459
+ row["initialized"] = False
3460
+ else:
3461
+ keys, present, corrupt = opol.scope_keys(ppath)
3462
+ row["project_keys"] = keys
3463
+ row["configured"] = present
3464
+ row["corrupt"] = corrupt
3465
+ row["policy"] = opol.resolve(ppath).as_dict()
3466
+ except Exception as e:
3467
+ row["error"] = str(e)
3468
+ rows.append(row)
3469
+
3470
+ try:
3471
+ keys, present, corrupt = opol.global_scope_keys()
3472
+ global_policy = {"configured": present, "corrupt": corrupt,
3473
+ "keys": keys, "error": None,
3474
+ "policy": opol.resolve_global().as_dict()}
3475
+ except Exception as e:
3476
+ global_policy = {"configured": False, "corrupt": False, "keys": [],
3477
+ "error": str(e), "policy": None}
3478
+
3479
+ return jsonify({
3480
+ "projects": rows,
3481
+ "global_policy": global_policy,
3482
+ "defaults": {k: v for k, v in opol.DEFAULTS.items()
3483
+ if k != opol.WAKE_KEY},
3484
+ "layers": list(opol.LAYER_KEYS),
3485
+ "typed_confirm_layers": sorted(opol.TYPED_CONFIRM_LAYERS),
3486
+ "hard_max_ttl_s": opol.HARD_MAX_TTL_S,
3487
+ "coverage_note": _OVERRIDE_POLICY_NOTE,
3488
+ # What this Hub can do beyond the per-project GET/POST, so a client
3489
+ # built against a newer C3 can hide what an older one cannot serve.
3490
+ "features": ["clear"],
3491
+ })
3492
+
3493
+
3494
+ @app.route("/api/hub/overrides/policy/clear", methods=["POST"])
3495
+ def api_hub_override_policy_clear():
3496
+ """Drop one project's own `override` opinions so it inherits global.
3497
+
3498
+ Body: ``{path, confirm?}``. Clearing can LOOSEN (the project may have
3499
+ been tighter than global), so it goes through the same widening check as
3500
+ a set and needs ``confirm: "widen"`` when it does. ``wake`` survives the
3501
+ clear. A corrupt project section is 409: it needs a human, not a reset.
3502
+ """
3503
+ from services import override_policy as opol
3504
+ data = request.get_json(silent=True) or {}
3505
+ raw = (data.get("path") or "").strip()
3506
+ if not raw:
3507
+ return jsonify({"error": "path is required"}), 400
3508
+ try:
3509
+ project_path = str(_resolve_project_path(raw))
3510
+ except ValueError as e:
3511
+ return jsonify({"error": str(e)}), 404
3512
+ try:
3513
+ kept, widens = opol.clear_section(
3514
+ project_path, confirmed=(data.get("confirm") == "widen"))
3515
+ except opol.PolicyEditError as exc:
3516
+ return jsonify(exc.payload), exc.status
3517
+ except (OSError, ValueError) as exc:
3518
+ return jsonify({"error": f"{type(exc).__name__}: {exc}"}), 500
3519
+ cleared = kept is not None
3520
+ if cleared:
3521
+ _hub_policy_audit(project_path, "clear",
3522
+ {"kept": sorted(kept), "widened": list(widens)})
3523
+ return jsonify({"path": project_path, "cleared": cleared,
3524
+ "policy": opol.resolve(project_path).as_dict(),
3525
+ "widened": widens})
3526
+
3527
+
3342
3528
  @app.route("/api/hub/overrides/<request_id>", methods=["POST"])
3343
3529
  def api_hub_override_decide(request_id):
3344
3530
  """Approve (minting a grant) or deny one request. decided_by='desktop'.
@@ -4516,9 +4702,16 @@ def c3_hook_migrations(cli_dir: Path | None = None) -> list:
4516
4702
  "command": f"{dispatch} {arg}"}]},
4517
4703
  }
4518
4704
 
4705
+ # v2.140.0: native subagent calls reach the pretool dispatcher, where
4706
+ # hook_agent_model fills a blank model. Same literal as cli.c3.AGENT_MATCHER.
4707
+ agent_entry = {"matcher": "Agent|Task",
4708
+ "hooks": [{"type": "command", "command": f"{dispatch} pretool"}]}
4709
+
4519
4710
  return [
4520
4711
  {"settings": ".claude/settings.local.json", "event": "PostToolUse",
4521
4712
  "present": c3read_present, "entry": c3read_entry},
4713
+ {"settings": ".claude/settings.local.json", "event": "PreToolUse",
4714
+ "present": _has_matcher("Agent|Task"), "entry": agent_entry},
4522
4715
  {"settings": ".gemini/settings.json", "event": "AfterTool",
4523
4716
  "present": c3read_present, "entry": c3read_entry},
4524
4717
  # Claude only — Gemini has no session-lifecycle event to hang these on.
@@ -25,6 +25,7 @@ from fastmcp import Context, FastMCP
25
25
 
26
26
  from core.host import resolve_host
27
27
  from core.ide import get_profile
28
+ from services import delegate_hints
28
29
  from services.auto_memory import AutoMemory
29
30
  from services.context_snapshot import ContextSnapshot
30
31
  from services.runtime import C3Runtime, build_runtime, start_runtime, stop_runtime
@@ -515,6 +516,21 @@ _last_badge_count: int = 0 # delta-based: only show badge when count increases
515
516
  _finalize_lock = threading.Lock()
516
517
 
517
518
 
519
+ def _with_hint(resp, make_hint) -> str:
520
+ """``resp`` plus a delegation hint line (services/delegate_hints), when the
521
+ call succeeded and a hint is due. A hint is advice: it never fails a call."""
522
+ if not isinstance(resp, str):
523
+ return resp
524
+ try:
525
+ from cli._hook_utils import response_text_failed
526
+ if response_text_failed(resp):
527
+ return resp
528
+ hint = make_hint()
529
+ except Exception:
530
+ return resp
531
+ return f"{resp}\n{hint}" if hint else resp
532
+
533
+
518
534
  def _finalize_response(ctx: Context, tool_name: str, args: dict,
519
535
  response: str, summary: str = "",
520
536
  response_tokens: int = 0) -> str:
@@ -668,10 +684,11 @@ async def c3_search(query: str, action: str = "code", top_k: int = 3,
668
684
  def finalize(name, args, resp, summ, **kw):
669
685
  return _finalize_response(ctx, name, args, resp, summ, **kw)
670
686
 
671
- return await asyncio.to_thread(handle_search, query, action, top_k, max_tokens, svc,
687
+ resp = await asyncio.to_thread(handle_search, query, action, top_k, max_tokens, svc,
672
688
  finalize, maybe_related_facts, prefetch=prefetch,
673
689
  scope=scope, ignore_case=ignore_case,
674
690
  path=path, lang=lang, kind=kind)
691
+ return _with_hint(resp, lambda: delegate_hints.after_read(svc, ""))
675
692
 
676
693
 
677
694
  @mcp.tool()
@@ -746,7 +763,10 @@ async def c3_read(file_path: str, symbols: Any = None, lines: Any = None,
746
763
  def finalize(name, args, resp, summ, **kw):
747
764
  return _finalize_response(ctx, name, args, resp, summ, **kw)
748
765
 
749
- return await asyncio.to_thread(handle_read, file_path, symbols, lines, include_docstrings, svc, finalize)
766
+ resp = await asyncio.to_thread(handle_read, file_path, symbols, lines, include_docstrings, svc, finalize)
767
+ if not (symbols or lines):
768
+ return resp # a map is the cheap way to look; it does not count toward the hint
769
+ return _with_hint(resp, lambda: delegate_hints.after_read(svc, file_path.split(",")[0].strip()))
750
770
 
751
771
 
752
772
  # c3_compress left the MCP surface in 2.124.0: c3_read(file_path) serves the
@@ -827,6 +847,10 @@ async def c3_delegate(task: str, task_type: str = "ask", context: str = "",
827
847
  task.add_done_callback(lambda done: done.exception() if not done.cancelled() else None)
828
848
  loop.call_soon_threadsafe(schedule)
829
849
  svc._agent_progress_cb = _progress_cb
850
+ try:
851
+ delegate_hints.after_delegate(svc, write=bool(str(write_paths or "").strip()), scout=bool(scout))
852
+ except Exception:
853
+ pass
830
854
  try:
831
855
  return await asyncio.to_thread(handle_delegate, task, task_type, context,
832
856
  file_path, svc, finalize, backend,
@@ -879,8 +903,10 @@ async def c3_edit(file_path: str, old_string: str = "", new_string: str = "",
879
903
  def finalize(name, args, resp, summ, **kw):
880
904
  return _finalize_response(ctx, name, args, resp, summ, **kw)
881
905
 
882
- return await asyncio.to_thread(handle_edit, file_path, old_string, new_string,
906
+ resp = await asyncio.to_thread(handle_edit, file_path, old_string, new_string,
883
907
  summary, tags, replace_all, svc, finalize, edits)
908
+ return _with_hint(resp, lambda: delegate_hints.after_edit(
909
+ svc, file_path, delegate_hints.edit_chars(new_string, edits)))
884
910
 
885
911
 
886
912
  @mcp.tool()
@@ -121,7 +121,18 @@ def _budget_view(svc, detailed, finalize):
121
121
  # (2.132.0+): how much work went one tier down, where, and what it cost.
122
122
  try:
123
123
  from services.telemetry import aggregate_tool_telemetry
124
- rows = aggregate_tool_telemetry(svc.project_path, days=7).get("delegate_by_backend") or {}
124
+ agg7 = aggregate_tool_telemetry(svc.project_path, days=7)
125
+ by_tool = agg7.get("by_tool") or {}
126
+
127
+ def _n(tool: str) -> int:
128
+ return int((by_tool.get(tool) or {}).get("calls") or 0)
129
+
130
+ moved, blank = _n("agent_downshift"), _n("agent_downshift") + _n("agent_downshift_skip")
131
+ hints, followed = _n("delegate_hint"), _n("delegate_hint_followed")
132
+ if blank or hints:
133
+ lines.append(f"[delegate-auto:7d] {moved} of {blank} model-less subagent call(s) moved to a "
134
+ f"lower model, {hints} delegation hint(s) shown, {followed} followed")
135
+ rows = agg7.get("delegate_by_backend") or {}
125
136
  used = sorted(((k, r) for k, r in rows.items() if r.get("calls")), key=lambda kv: -kv[1]["calls"])
126
137
  if used:
127
138
  calls = sum(r["calls"] for _k, r in used)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-context-control
3
- Version: 2.139.0
3
+ Version: 2.141.0
4
4
  Summary: Local MCP code-intelligence for AI coding tools: surgical search/read/edit, agent-config version history, path-level access + masking guards, and a multi-project hub.
5
5
  Author-email: Dimitri Tselenchuk <dtselenc@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -8,6 +8,7 @@ cli/c3.py
8
8
  cli/docs.html
9
9
  cli/edits.html
10
10
  cli/hook_access_guard.py
11
+ cli/hook_agent_model.py
11
12
  cli/hook_artifact.py
12
13
  cli/hook_auto_snapshot.py
13
14
  cli/hook_c3_signal.py
@@ -194,6 +195,7 @@ services/access_guard.py
194
195
  services/access_telemetry.py
195
196
  services/activity_log.py
196
197
  services/agent_base.py
198
+ services/agent_downshift.py
197
199
  services/agent_locks.py
198
200
  services/agents.py
199
201
  services/agents_workflow.py
@@ -225,6 +227,7 @@ services/cred_audit.py
225
227
  services/cred_telemetry.py
226
228
  services/credential_store.py
227
229
  services/delegate_agents.py
230
+ services/delegate_hints.py
228
231
  services/delegate_write.py
229
232
  services/dir_map.py
230
233
  services/doc_index.py
@@ -363,6 +366,7 @@ tests/test_credentials_routes.py
363
366
  tests/test_credentials_tool.py
364
367
  tests/test_creds_cli_smoke.py
365
368
  tests/test_delegate_adoption_d4.py
369
+ tests/test_delegate_auto.py
366
370
  tests/test_delegate_cascade.py
367
371
  tests/test_delegate_claude_d1.py
368
372
  tests/test_delegate_eval.py
@@ -414,6 +418,7 @@ tests/test_hub_locks_routes.py
414
418
  tests/test_hub_oracle_service_routes.py
415
419
  tests/test_hub_override_policy_routes.py
416
420
  tests/test_hub_override_routes.py
421
+ tests/test_hub_rules_routes.py
417
422
  tests/test_hub_server_smoke.py
418
423
  tests/test_hub_subproject_links.py
419
424
  tests/test_ide_workflow_adaptation.py
@@ -316,6 +316,15 @@ DELEGATE_DEFAULTS = {
316
316
  # (2026-09-14: --effort low changed nothing on Haiku 4.5 — same
317
317
  # cost and output tokens over 22 eval cases — so no default)
318
318
  "claude_max_budget_usd": 0, # --max-budget-usd per call; 0 = no cap
319
+ # Native Claude Code subagents (docs/delegate-auto.md). An Agent call with no model runs
320
+ # on the parent's model; the PreToolUse hook fills one in.
321
+ "agent_downshift": "one_down", # one_down | off | a fixed alias (haiku/sonnet/opus)
322
+ "agent_downshift_floor": "sonnet", # never below this (Haiku flailed on lookups, missed subtle specs)
323
+ "agent_downshift_skip": ["fork", "Plan"], # subagent types left on the parent's model
324
+ "agent_models": {}, # {subagent_type: alias} explicit per-type choice
325
+ # Delegation hints: one line on a c3_* response when the session's own work looks delegable.
326
+ "hints": True,
327
+ "hint_cooldown_minutes": 45, # per hint kind
319
328
  }
320
329
 
321
330
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "code-context-control"
7
- version = "2.139.0"
7
+ version = "2.141.0"
8
8
  description = "Local MCP code-intelligence for AI coding tools: surgical search/read/edit, agent-config version history, path-level access + masking guards, and a multi-project hub."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"