code-context-control 2.129.0__tar.gz → 2.129.2__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 (533) hide show
  1. {code_context_control-2.129.0 → code_context_control-2.129.2}/PKG-INFO +1 -1
  2. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/c3.py +1 -1
  3. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_server.py +79 -0
  4. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/hub_access.js +183 -0
  5. {code_context_control-2.129.0 → code_context_control-2.129.2}/code_context_control.egg-info/PKG-INFO +1 -1
  6. {code_context_control-2.129.0 → code_context_control-2.129.2}/code_context_control.egg-info/SOURCES.txt +2 -0
  7. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/mobile_api.py +29 -5
  8. {code_context_control-2.129.0 → code_context_control-2.129.2}/pyproject.toml +1 -1
  9. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/override_policy.py +147 -0
  10. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/watcher.py +75 -11
  11. code_context_control-2.129.2/tests/test_hub_override_policy_routes.py +154 -0
  12. code_context_control-2.129.2/tests/test_watcher_pruning.py +117 -0
  13. {code_context_control-2.129.0 → code_context_control-2.129.2}/LICENSE +0 -0
  14. {code_context_control-2.129.0 → code_context_control-2.129.2}/README.md +0 -0
  15. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/__init__.py +0 -0
  16. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/_hook_utils.py +0 -0
  17. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/_shell_writes.py +0 -0
  18. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/commands/__init__.py +0 -0
  19. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/commands/common.py +0 -0
  20. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/commands/parser.py +0 -0
  21. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/docs.html +0 -0
  22. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/edits.html +0 -0
  23. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/guide/access.html +0 -0
  24. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/guide/bitbucket.html +0 -0
  25. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/guide/credentials.html +0 -0
  26. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/guide/getting-started.html +0 -0
  27. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/guide/index.html +0 -0
  28. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/guide/masking.html +0 -0
  29. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/guide/oracle.html +0 -0
  30. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/guide/shared.css +0 -0
  31. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/guide/tools.html +0 -0
  32. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/guide/workflow.html +0 -0
  33. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hook_access_guard.py +0 -0
  34. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hook_artifact.py +0 -0
  35. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hook_auto_snapshot.py +0 -0
  36. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hook_c3_signal.py +0 -0
  37. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hook_c3read.py +0 -0
  38. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hook_codex_lifecycle.py +0 -0
  39. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hook_dispatch.py +0 -0
  40. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hook_edit_ledger.py +0 -0
  41. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hook_edit_unlock.py +0 -0
  42. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hook_filter.py +0 -0
  43. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hook_ghost_files.py +0 -0
  44. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hook_pretool_enforce.py +0 -0
  45. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hook_prompt_recall.py +0 -0
  46. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hook_read.py +0 -0
  47. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hook_session_end.py +0 -0
  48. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hook_session_open.py +0 -0
  49. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hook_session_stats.py +0 -0
  50. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hook_terse_advisor.py +0 -0
  51. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/app.js +0 -0
  52. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/add_project.js +0 -0
  53. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/config_editor.js +0 -0
  54. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/drill_artifacts.js +0 -0
  55. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/drill_health.js +0 -0
  56. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/drill_panel.js +0 -0
  57. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/drill_subprojects.js +0 -0
  58. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/drill_tasks.js +0 -0
  59. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/drill_views.js +0 -0
  60. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/global_search.js +0 -0
  61. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/hub_ci.js +0 -0
  62. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/hub_cred_audit.js +0 -0
  63. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/hub_credentials.js +0 -0
  64. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/hub_enforcement.js +0 -0
  65. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/hub_locks.js +0 -0
  66. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/hub_tokens.js +0 -0
  67. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/mcp_manager.js +0 -0
  68. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/modals.js +0 -0
  69. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/project_card.js +0 -0
  70. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/project_tree.js +0 -0
  71. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/session_drawer.js +0 -0
  72. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/settings_modal.js +0 -0
  73. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/sidebar.js +0 -0
  74. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/summary_bar.js +0 -0
  75. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/task_board.js +0 -0
  76. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/toasts.js +0 -0
  77. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/components/topbar.js +0 -0
  78. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui/state.js +0 -0
  79. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/hub_ui.html +0 -0
  80. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/mcp_proxy.py +0 -0
  81. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/mcp_server.py +0 -0
  82. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/progress.py +0 -0
  83. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/server.py +0 -0
  84. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/__init__.py +0 -0
  85. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/_grants.py +0 -0
  86. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/_helpers.py +0 -0
  87. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/agent.py +0 -0
  88. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/artifacts.py +0 -0
  89. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/bitbucket.py +0 -0
  90. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/ci.py +0 -0
  91. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/compress.py +0 -0
  92. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/credentials.py +0 -0
  93. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/delegate.py +0 -0
  94. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/edit.py +0 -0
  95. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/edit_verify.py +0 -0
  96. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/edits.py +0 -0
  97. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/federate.py +0 -0
  98. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/filter.py +0 -0
  99. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/impact.py +0 -0
  100. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/jira.py +0 -0
  101. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/locks.py +0 -0
  102. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/memory.py +0 -0
  103. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/override.py +0 -0
  104. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/project.py +0 -0
  105. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/read.py +0 -0
  106. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/search.py +0 -0
  107. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/session.py +0 -0
  108. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/shell.py +0 -0
  109. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/shell_job.py +0 -0
  110. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/shell_nudge.py +0 -0
  111. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/shell_parsers.py +0 -0
  112. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/shell_render.py +0 -0
  113. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/status.py +0 -0
  114. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/tasks.py +0 -0
  115. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/tools/validate.py +0 -0
  116. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/api.js +0 -0
  117. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/app.js +0 -0
  118. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/components/access.js +0 -0
  119. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/components/bitbucket.js +0 -0
  120. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/components/chat.js +0 -0
  121. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/components/credentials.js +0 -0
  122. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/components/dashboard.js +0 -0
  123. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/components/edits.js +0 -0
  124. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/components/enforcement.js +0 -0
  125. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/components/instructions.js +0 -0
  126. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/components/jira.js +0 -0
  127. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/components/memory.js +0 -0
  128. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/components/sessions.js +0 -0
  129. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/components/settings.js +0 -0
  130. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/components/sidebar.js +0 -0
  131. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/components/tasks.js +0 -0
  132. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/icons.js +0 -0
  133. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/pm_shared.js +0 -0
  134. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/shared.js +0 -0
  135. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui/theme.js +0 -0
  136. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui.html +0 -0
  137. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui_legacy.html +0 -0
  138. {code_context_control-2.129.0 → code_context_control-2.129.2}/cli/ui_nano.html +0 -0
  139. {code_context_control-2.129.0 → code_context_control-2.129.2}/code_context_control.egg-info/dependency_links.txt +0 -0
  140. {code_context_control-2.129.0 → code_context_control-2.129.2}/code_context_control.egg-info/entry_points.txt +0 -0
  141. {code_context_control-2.129.0 → code_context_control-2.129.2}/code_context_control.egg-info/requires.txt +0 -0
  142. {code_context_control-2.129.0 → code_context_control-2.129.2}/code_context_control.egg-info/top_level.txt +0 -0
  143. {code_context_control-2.129.0 → code_context_control-2.129.2}/core/__init__.py +0 -0
  144. {code_context_control-2.129.0 → code_context_control-2.129.2}/core/codex_patch.py +0 -0
  145. {code_context_control-2.129.0 → code_context_control-2.129.2}/core/config.py +0 -0
  146. {code_context_control-2.129.0 → code_context_control-2.129.2}/core/host.py +0 -0
  147. {code_context_control-2.129.0 → code_context_control-2.129.2}/core/ide.py +0 -0
  148. {code_context_control-2.129.0 → code_context_control-2.129.2}/core/mcp_toml.py +0 -0
  149. {code_context_control-2.129.0 → code_context_control-2.129.2}/core/web_security.py +0 -0
  150. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/__init__.py +0 -0
  151. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/config.py +0 -0
  152. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/listeners.py +0 -0
  153. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/mcp_oracle.py +0 -0
  154. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/oracle_server.py +0 -0
  155. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/oracle_ui.html +0 -0
  156. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/__init__.py +0 -0
  157. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/activity_reporter.py +0 -0
  158. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/api_auth.py +0 -0
  159. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/c3_bridge.py +0 -0
  160. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/chat_engine.py +0 -0
  161. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/chat_poll.py +0 -0
  162. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/chat_store.py +0 -0
  163. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/client_tokens.py +0 -0
  164. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/cross_memory.py +0 -0
  165. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/discovery_audit.py +0 -0
  166. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/federated_graph.py +0 -0
  167. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/health_checker.py +0 -0
  168. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/insight_engine.py +0 -0
  169. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/local_session.py +0 -0
  170. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/memory_reader.py +0 -0
  171. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/memory_writer.py +0 -0
  172. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/project_scanner.py +0 -0
  173. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/review_agent.py +0 -0
  174. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/tool_executor.py +0 -0
  175. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/services/tool_registry.py +0 -0
  176. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/activity.js +0 -0
  177. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/agents.js +0 -0
  178. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/app.js +0 -0
  179. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/busy.js +0 -0
  180. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/chat/conversations.js +0 -0
  181. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/chat/input.js +0 -0
  182. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/chat/markdown.js +0 -0
  183. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/chat/send.js +0 -0
  184. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/chat/stream_renderer.js +0 -0
  185. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/chat/toolbar.js +0 -0
  186. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/core.js +0 -0
  187. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/crossgraph.js +0 -0
  188. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/header.js +0 -0
  189. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/insights.js +0 -0
  190. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/projects.js +0 -0
  191. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/qrcode.js +0 -0
  192. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/settings.js +0 -0
  193. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/suggestions.js +0 -0
  194. {code_context_control-2.129.0 → code_context_control-2.129.2}/oracle/ui/theme_tabs.js +0 -0
  195. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/__init__.py +0 -0
  196. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/access_guard.py +0 -0
  197. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/access_telemetry.py +0 -0
  198. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/activity_log.py +0 -0
  199. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/agent_base.py +0 -0
  200. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/agent_locks.py +0 -0
  201. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/agents.py +0 -0
  202. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/artifact_defs.py +0 -0
  203. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/artifact_store.py +0 -0
  204. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/atomic_json.py +0 -0
  205. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/auto_memory.py +0 -0
  206. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/background_service.py +0 -0
  207. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/bench/__init__.py +0 -0
  208. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/bench/external/__init__.py +0 -0
  209. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/bench/external/aider_polyglot.py +0 -0
  210. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/bench/external/swe_bench.py +0 -0
  211. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/bench/map_eval.py +0 -0
  212. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/bench/search_eval.py +0 -0
  213. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/bench/shell_eval.py +0 -0
  214. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/benchmark_dashboard.py +0 -0
  215. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/bitbucket_client.py +0 -0
  216. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/bitbucket_credentials.py +0 -0
  217. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/ci_act.py +0 -0
  218. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/ci_cache.py +0 -0
  219. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/ci_expr.py +0 -0
  220. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/ci_failures.py +0 -0
  221. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/ci_github.py +0 -0
  222. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/ci_impact.py +0 -0
  223. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/ci_intel.py +0 -0
  224. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/ci_runner.py +0 -0
  225. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/ci_workflow.py +0 -0
  226. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/circuit_breaker.py +0 -0
  227. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/claude_md.py +0 -0
  228. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/codex_integration.py +0 -0
  229. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/codex_transcript.py +0 -0
  230. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/compressor.py +0 -0
  231. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/context_snapshot.py +0 -0
  232. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/conversation_store.py +0 -0
  233. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/cred_audit.py +0 -0
  234. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/cred_telemetry.py +0 -0
  235. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/credential_store.py +0 -0
  236. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/dir_map.py +0 -0
  237. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/doc_index.py +0 -0
  238. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/e2e_benchmark.py +0 -0
  239. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/e2e_evaluator.py +0 -0
  240. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/e2e_tasks.py +0 -0
  241. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/edit_ledger.py +0 -0
  242. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/embedding_index.py +0 -0
  243. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/enforcement_policy.py +0 -0
  244. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/error_reporting.py +0 -0
  245. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/file_map.py +0 -0
  246. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/file_memory.py +0 -0
  247. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/git_context.py +0 -0
  248. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/host_sessions.py +0 -0
  249. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/hub_service.py +0 -0
  250. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/index_store.py +0 -0
  251. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/indexer.py +0 -0
  252. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/jira_client.py +0 -0
  253. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/jira_cloud.py +0 -0
  254. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/jira_credentials.py +0 -0
  255. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/jira_data_center.py +0 -0
  256. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/jira_links.py +0 -0
  257. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/lexical_index.py +0 -0
  258. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/mask_activation.py +0 -0
  259. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/mask_mirror.py +0 -0
  260. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/mask_presets.py +0 -0
  261. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/memory.py +0 -0
  262. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/memory_consolidator.py +0 -0
  263. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/memory_distiller.py +0 -0
  264. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/memory_graph.py +0 -0
  265. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/memory_grounder.py +0 -0
  266. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/memory_queue.py +0 -0
  267. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/memory_scorer.py +0 -0
  268. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/metrics.py +0 -0
  269. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/notifications.py +0 -0
  270. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/ollama_bridge.py +0 -0
  271. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/ollama_client.py +0 -0
  272. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/ollama_credentials.py +0 -0
  273. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/oracle_service.py +0 -0
  274. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/output_filter.py +0 -0
  275. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/override_costs.py +0 -0
  276. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/override_grants.py +0 -0
  277. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/override_requests.py +0 -0
  278. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/override_wake.py +0 -0
  279. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/parser.py +0 -0
  280. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/project_manager.py +0 -0
  281. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/project_runtime.py +0 -0
  282. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/protocol.py +0 -0
  283. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/proxy_state.py +0 -0
  284. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/repo_map.py +0 -0
  285. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/repo_shape.py +0 -0
  286. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/reranker.py +0 -0
  287. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/retention.py +0 -0
  288. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/retrieval.py +0 -0
  289. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/retrieval_broker.py +0 -0
  290. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/router.py +0 -0
  291. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/runtime.py +0 -0
  292. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/scanner.py +0 -0
  293. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/session_benchmark.py +0 -0
  294. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/session_live.py +0 -0
  295. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/session_manager.py +0 -0
  296. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/session_preloader.py +0 -0
  297. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/shell_jobs.py +0 -0
  298. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/shell_output.py +0 -0
  299. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/subprojects.py +0 -0
  300. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/task_store.py +0 -0
  301. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/telemetry.py +0 -0
  302. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/text_index.py +0 -0
  303. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/time_tracker.py +0 -0
  304. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/tool_classifier.py +0 -0
  305. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/transcript_index.py +0 -0
  306. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/validation_cache.py +0 -0
  307. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/vector_store.py +0 -0
  308. {code_context_control-2.129.0 → code_context_control-2.129.2}/services/win_subprocess.py +0 -0
  309. {code_context_control-2.129.0 → code_context_control-2.129.2}/setup.cfg +0 -0
  310. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_access_builtin_optout.py +0 -0
  311. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_access_guard.py +0 -0
  312. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_access_guard_meta.py +0 -0
  313. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_access_guard_shell_project.py +0 -0
  314. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_access_guard_surfaces.py +0 -0
  315. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_access_guard_wiring.py +0 -0
  316. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_activity_log_find_last.py +0 -0
  317. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_activity_reporter.py +0 -0
  318. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_agent_locks.py +0 -0
  319. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_aider_polyglot.py +0 -0
  320. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_antigravity_transition.py +0 -0
  321. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_artifact_store.py +0 -0
  322. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_artifact_tool.py +0 -0
  323. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_atomic_json.py +0 -0
  324. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_background_service.py +0 -0
  325. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_bitbucket_cli_smoke.py +0 -0
  326. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_bitbucket_client.py +0 -0
  327. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_bitbucket_config_fallback.py +0 -0
  328. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_bitbucket_credentials.py +0 -0
  329. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_bitbucket_tool.py +0 -0
  330. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_builtin_modes.py +0 -0
  331. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_c3_bridge_project_artifacts.py +0 -0
  332. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_c3_shell.py +0 -0
  333. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_chat_poll.py +0 -0
  334. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_ci_act.py +0 -0
  335. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_ci_cache.py +0 -0
  336. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_ci_expr.py +0 -0
  337. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_ci_impact.py +0 -0
  338. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_ci_intel.py +0 -0
  339. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_ci_runner.py +0 -0
  340. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_ci_workflow.py +0 -0
  341. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_circuit_breaker.py +0 -0
  342. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_claude_md_merge.py +0 -0
  343. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_claude_md_updater.py +0 -0
  344. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_cli_smoke.py +0 -0
  345. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_codex_mcp_transport.py +0 -0
  346. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_codex_native.py +0 -0
  347. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_compressor_large_file.py +0 -0
  348. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_confirm_guard.py +0 -0
  349. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_confirm_guard_wiring.py +0 -0
  350. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_cooccurrence_bounds.py +0 -0
  351. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_cred_audit.py +0 -0
  352. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_cred_telemetry.py +0 -0
  353. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_credential_login_kind.py +0 -0
  354. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_credential_store.py +0 -0
  355. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_credential_ui_parity.py +0 -0
  356. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_credentials_routes.py +0 -0
  357. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_credentials_tool.py +0 -0
  358. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_creds_cli_smoke.py +0 -0
  359. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_delegate_cascade.py +0 -0
  360. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_delegate_version_probe.py +0 -0
  361. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_dir_map_c3.py +0 -0
  362. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_e2e_benchmark.py +0 -0
  363. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_edit_ledger_deadline.py +0 -0
  364. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_edit_ledger_hook.py +0 -0
  365. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_edit_locking.py +0 -0
  366. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_edit_normalization.py +0 -0
  367. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_edit_verify.py +0 -0
  368. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_embedding_index_deadlock.py +0 -0
  369. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_enforcement_flip.py +0 -0
  370. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_enforcement_policy.py +0 -0
  371. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_enforcement_routes.py +0 -0
  372. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_env_parser.py +0 -0
  373. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_failed_calls_do_not_unlock.py +0 -0
  374. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_federated_graph.py +0 -0
  375. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_file_map_c1.py +0 -0
  376. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_filter_backoff.py +0 -0
  377. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_ghost_files.py +0 -0
  378. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_ghost_generation.py +0 -0
  379. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_git_branch_awareness.py +0 -0
  380. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hook_access_guard.py +0 -0
  381. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hook_codex_compat.py +0 -0
  382. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hook_dispatch.py +0 -0
  383. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hook_pretool_enforce.py +0 -0
  384. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hook_prompt_recall.py +0 -0
  385. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hook_session_end.py +0 -0
  386. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hook_smoke.py +0 -0
  387. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hook_state.py +0 -0
  388. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hook_utf8_stdio.py +0 -0
  389. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hub_credentials_route.py +0 -0
  390. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hub_credentials_routes_write.py +0 -0
  391. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hub_enforcement_routes.py +0 -0
  392. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hub_hook_migration.py +0 -0
  393. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hub_inspect_api.py +0 -0
  394. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hub_locks_routes.py +0 -0
  395. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hub_oracle_service_routes.py +0 -0
  396. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hub_override_routes.py +0 -0
  397. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hub_server_smoke.py +0 -0
  398. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_hub_subproject_links.py +0 -0
  399. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_ide_workflow_adaptation.py +0 -0
  400. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_index_cap_not_hardcoded.py +0 -0
  401. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_init_clear_preserves_user_content.py +0 -0
  402. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_init_scan.py +0 -0
  403. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_install_mcp_entrypoint.py +0 -0
  404. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_jira_cli_smoke.py +0 -0
  405. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_jira_client.py +0 -0
  406. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_jira_config_fallback.py +0 -0
  407. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_jira_credentials.py +0 -0
  408. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_jira_links.py +0 -0
  409. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_jira_routes.py +0 -0
  410. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_jira_tool.py +0 -0
  411. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_large_files_c4.py +0 -0
  412. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_lazy_store_init.py +0 -0
  413. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_map_eval.py +0 -0
  414. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_map_telemetry_c0.py +0 -0
  415. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_mask_guard.py +0 -0
  416. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_mask_routes.py +0 -0
  417. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_mask_surfaces.py +0 -0
  418. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_mcp_host_guard.py +0 -0
  419. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_mcp_memory_timeout.py +0 -0
  420. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_mcp_server_smoke.py +0 -0
  421. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_mcp_toml.py +0 -0
  422. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_memory_distiller.py +0 -0
  423. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_memory_graph_api.py +0 -0
  424. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_memory_queue.py +0 -0
  425. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_memory_system.py +0 -0
  426. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_mobile_api.py +0 -0
  427. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_mobile_clients.py +0 -0
  428. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_mobile_extras.py +0 -0
  429. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_mobile_jobs_ci.py +0 -0
  430. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_mobile_override_costs.py +0 -0
  431. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_mobile_override_routes.py +0 -0
  432. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_mobile_security_api.py +0 -0
  433. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_no_stale_model_pins.py +0 -0
  434. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_notification_dedup.py +0 -0
  435. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_notification_discipline.py +0 -0
  436. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_notification_kinds.py +0 -0
  437. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_ollama_credentials.py +0 -0
  438. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_oracle_api_auth.py +0 -0
  439. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_oracle_apikey_api.py +0 -0
  440. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_oracle_c3_bridge.py +0 -0
  441. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_oracle_chat_engine.py +0 -0
  442. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_oracle_chat_store.py +0 -0
  443. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_oracle_discovery_api.py +0 -0
  444. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_oracle_discovery_audit.py +0 -0
  445. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_oracle_health_probe.py +0 -0
  446. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_oracle_local_auth.py +0 -0
  447. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_oracle_loopback.py +0 -0
  448. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_oracle_ollama_bridge.py +0 -0
  449. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_oracle_scanner_cache.py +0 -0
  450. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_oracle_security_fixes.py +0 -0
  451. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_oracle_session_bootstrap.py +0 -0
  452. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_oracle_subproject_awareness.py +0 -0
  453. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_oracle_ui_bundle.py +0 -0
  454. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_output_filter.py +0 -0
  455. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_override_costs.py +0 -0
  456. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_override_grants.py +0 -0
  457. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_override_grants_mcp.py +0 -0
  458. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_override_requests.py +0 -0
  459. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_override_wake.py +0 -0
  460. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_permissions.py +0 -0
  461. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_pm_api.py +0 -0
  462. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_project_manager.py +0 -0
  463. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_project_manager_merge.py +0 -0
  464. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_project_tool.py +0 -0
  465. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_read_coercion.py +0 -0
  466. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_read_edit_parity.py +0 -0
  467. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_read_outside_root.py +0 -0
  468. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_related_facts.py +0 -0
  469. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_repo_map.py +0 -0
  470. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_repo_shape.py +0 -0
  471. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_response_boilerplate.py +0 -0
  472. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_retention.py +0 -0
  473. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_review_digest.py +0 -0
  474. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_search_eval.py +0 -0
  475. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_search_p1.py +0 -0
  476. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_search_p2.py +0 -0
  477. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_search_p2b.py +0 -0
  478. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_search_p3.py +0 -0
  479. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_search_p4.py +0 -0
  480. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_search_p5.py +0 -0
  481. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_service_durability.py +0 -0
  482. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_session_benchmark.py +0 -0
  483. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_session_budget.py +0 -0
  484. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_session_live.py +0 -0
  485. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_shell_budget_s1.py +0 -0
  486. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_shell_creds.py +0 -0
  487. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_shell_eval.py +0 -0
  488. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_shell_jobs_s3.py +0 -0
  489. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_shell_nudge_s4.py +0 -0
  490. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_shell_output.py +0 -0
  491. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_shell_parsers_s2.py +0 -0
  492. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_shell_robustness.py +0 -0
  493. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_shell_telemetry_s0.py +0 -0
  494. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_shell_write_ledger.py +0 -0
  495. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_shell_writes.py +0 -0
  496. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_subproject_clear_scope.py +0 -0
  497. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_subproject_depth_consumers.py +0 -0
  498. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_subproject_exclusion.py +0 -0
  499. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_subproject_federation.py +0 -0
  500. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_subproject_linkage_api.py +0 -0
  501. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_subprojects.py +0 -0
  502. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_swe_bench.py +0 -0
  503. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_task_store.py +0 -0
  504. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_task_tool.py +0 -0
  505. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_time_tracker.py +0 -0
  506. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_token_telemetry.py +0 -0
  507. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_token_tracking.py +0 -0
  508. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_tool_registry.py +0 -0
  509. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_ui_jsx_syntax.py +0 -0
  510. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_upgrade_and_version.py +0 -0
  511. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_validate.py +0 -0
  512. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_vault_write_guard.py +0 -0
  513. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_version_sync.py +0 -0
  514. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_web_security.py +0 -0
  515. {code_context_control-2.129.0 → code_context_control-2.129.2}/tests/test_windows_reliability.py +0 -0
  516. {code_context_control-2.129.0 → code_context_control-2.129.2}/tui/__init__.py +0 -0
  517. {code_context_control-2.129.0 → code_context_control-2.129.2}/tui/backend.py +0 -0
  518. {code_context_control-2.129.0 → code_context_control-2.129.2}/tui/main.py +0 -0
  519. {code_context_control-2.129.0 → code_context_control-2.129.2}/tui/screens/__init__.py +0 -0
  520. {code_context_control-2.129.0 → code_context_control-2.129.2}/tui/screens/benchmark_view.py +0 -0
  521. {code_context_control-2.129.0 → code_context_control-2.129.2}/tui/screens/claudemd_view.py +0 -0
  522. {code_context_control-2.129.0 → code_context_control-2.129.2}/tui/screens/compress_view.py +0 -0
  523. {code_context_control-2.129.0 → code_context_control-2.129.2}/tui/screens/index_view.py +0 -0
  524. {code_context_control-2.129.0 → code_context_control-2.129.2}/tui/screens/init_view.py +0 -0
  525. {code_context_control-2.129.0 → code_context_control-2.129.2}/tui/screens/mcp_view.py +0 -0
  526. {code_context_control-2.129.0 → code_context_control-2.129.2}/tui/screens/optimize_view.py +0 -0
  527. {code_context_control-2.129.0 → code_context_control-2.129.2}/tui/screens/pipe_view.py +0 -0
  528. {code_context_control-2.129.0 → code_context_control-2.129.2}/tui/screens/projects_view.py +0 -0
  529. {code_context_control-2.129.0 → code_context_control-2.129.2}/tui/screens/search_view.py +0 -0
  530. {code_context_control-2.129.0 → code_context_control-2.129.2}/tui/screens/session_view.py +0 -0
  531. {code_context_control-2.129.0 → code_context_control-2.129.2}/tui/screens/stats.py +0 -0
  532. {code_context_control-2.129.0 → code_context_control-2.129.2}/tui/screens/ui_view.py +0 -0
  533. {code_context_control-2.129.0 → code_context_control-2.129.2}/tui/theme.tcss +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-context-control
3
- Version: 2.129.0
3
+ Version: 2.129.2
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,7 @@ 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.129.0"
94
+ __version__ = "2.129.2"
95
95
 
96
96
 
97
97
  def _compress_file_cli(compressor, path, mode="smart", **kw):
@@ -3259,6 +3259,85 @@ def api_hub_override_costs():
3259
3259
  "project": project_path})
3260
3260
 
3261
3261
 
3262
+ @app.route("/api/hub/overrides/policy", methods=["GET"])
3263
+ def api_hub_override_policy_get():
3264
+ """The effective `override` section for one project.
3265
+
3266
+ WHY THE HUB NEEDS THIS. The hub could already LIST override requests and
3267
+ DECIDE them, but not say whether requests may exist at all — that lives in
3268
+ `override.enabled`, which was reachable only from the phone API or by hand-
3269
+ editing `.c3/config.json`. So the hub could answer a question the agent was
3270
+ never allowed to ask, and the only way to change that was a text editor.
3271
+
3272
+ Registered BEFORE the POST-only ``<request_id>`` route for the same reason
3273
+ ``costs`` is: a GET on ``policy`` must never fall through to a 405 there.
3274
+ """
3275
+ from services import override_policy as opol
3276
+ raw = (request.args.get("path") or "").strip()
3277
+ if not raw:
3278
+ return jsonify({"error": "path is required"}), 400
3279
+ try:
3280
+ project_path = str(_resolve_project_path(raw))
3281
+ except ValueError as e:
3282
+ return jsonify({"error": str(e)}), 404
3283
+ policy = opol.resolve(project_path)
3284
+ return jsonify({
3285
+ "path": project_path,
3286
+ "project_name": Path(project_path).name,
3287
+ "policy": policy.as_dict(),
3288
+ "layers": list(opol.LAYER_KEYS),
3289
+ "typed_confirm_layers": sorted(opol.TYPED_CONFIRM_LAYERS),
3290
+ "hard_max_ttl_s": opol.HARD_MAX_TTL_S,
3291
+ # Verbatim from the spec, and the one thing a toggle screen must not
3292
+ # let the reader forget: policy is a floor, not a promise.
3293
+ "coverage_note": (
3294
+ "Project and global policy merge by tightening only: a layer is "
3295
+ "escalatable iff both scopes allow it, and the numeric limits take "
3296
+ "the smaller value."
3297
+ ),
3298
+ })
3299
+
3300
+
3301
+ @app.route("/api/hub/overrides/policy", methods=["POST"])
3302
+ def api_hub_override_policy_set():
3303
+ """Edit one project's `override` section from the hub.
3304
+
3305
+ Widening — enabling the feature or turning a layer on — needs
3306
+ ``confirm: "widen"``. Tightening never does: making the guard stricter is
3307
+ always allowed to be one click.
3308
+
3309
+ Validation, widening detection and the write are
3310
+ ``services.override_policy``'s, shared verbatim with the phone route. Two
3311
+ implementations of "what counts as widening" would be two chances for one
3312
+ surface to allow what the other refuses, and this is the check that decides
3313
+ whether an action needs a typed confirmation.
3314
+
3315
+ ``wake`` is accepted here and refused on the phone: it names a command this
3316
+ machine runs, and the hub is a desktop surface on this box.
3317
+ """
3318
+ from services import override_policy as opol
3319
+ data = request.get_json(silent=True) or {}
3320
+ raw = (data.get("path") or "").strip()
3321
+ if not raw:
3322
+ return jsonify({"error": "path is required"}), 400
3323
+ try:
3324
+ project_path = str(_resolve_project_path(raw))
3325
+ except ValueError as e:
3326
+ return jsonify({"error": str(e)}), 404
3327
+ try:
3328
+ written, widens = opol.apply_section(
3329
+ project_path, data.get("override"),
3330
+ confirmed=(data.get("confirm") == "widen"),
3331
+ allow_wake=True)
3332
+ except opol.PolicyEditError as exc:
3333
+ return jsonify(exc.payload), exc.status
3334
+ except (OSError, ValueError) as exc:
3335
+ return jsonify({"error": f"{type(exc).__name__}: {exc}"}), 500
3336
+ return jsonify({"path": project_path, "written": written,
3337
+ "policy": opol.resolve(project_path).as_dict(),
3338
+ "widened": widens})
3339
+
3340
+
3262
3341
  @app.route("/api/hub/overrides/<request_id>", methods=["POST"])
3263
3342
  def api_hub_override_decide(request_id):
3264
3343
  """Approve (minting a grant) or deny one request. decided_by='desktop'.
@@ -482,6 +482,187 @@ function AccGrantsPanel({ projects }) {
482
482
  }
483
483
 
484
484
  // ── The tab ────────────────────────────────────────────────────────────────
485
+ // ─── Override policy (the switch, not the requests) ───────────────────────
486
+ //
487
+ // WHY THIS PANEL EXISTS. This screen could already LIST override requests and
488
+ // DECIDE them — but not say whether requests may exist at all. That lives in
489
+ // `override.enabled`, and it was reachable only from the phone API or by hand-
490
+ // editing .c3/config.json. So the hub answered a question the agent was never
491
+ // allowed to ask, and the way to change that was a text editor.
492
+ //
493
+ // THE ONE RULE HERE: widening is never silent. Enabling the feature, or
494
+ // turning a layer on, loosens what a single approval can allow. The server
495
+ // refuses those without confirm:"widen"; this panel asks in plain words BEFORE
496
+ // sending, rather than surfacing a 400 afterwards. Tightening goes straight
497
+ // through — making the guard stricter should always be one click.
498
+
499
+ // Plain-language layer names. The raw keys are accurate and mean nothing to
500
+ // someone deciding whether to tick a box.
501
+ const ACC_LAYER_NAMES = {
502
+ discipline: 'Discipline holds (native-tool nudges)',
503
+ access_readonly: 'Read-only paths — e.g. .git/**, .c3/**',
504
+ access_deny: 'Denied paths',
505
+ access_builtin: 'Built-in guards',
506
+ access_confirm: 'Confirm holds — agent-config files',
507
+ mask: 'Masked paths',
508
+ shell_warn: 'Shell warnings',
509
+ };
510
+
511
+ function accLayerName(key) { return ACC_LAYER_NAMES[key] || key; }
512
+
513
+ function AccPolicyPanel({ projects }) {
514
+ const [path, setPath] = useState('');
515
+ const [data, setData] = useState(null);
516
+ const [draft, setDraft] = useState(null); // {enabled, layers}
517
+ const [err, setErr] = useState('');
518
+ const [msg, setMsg] = useState('');
519
+ const [busy, setBusy] = useState(false);
520
+
521
+ const load = useCallback(async (p) => {
522
+ if (!p) { setData(null); setDraft(null); setErr(''); setMsg(''); return; }
523
+ try {
524
+ const d = await api.get(`/api/hub/overrides/policy?path=${encodeURIComponent(p)}`);
525
+ setData(d);
526
+ setDraft({
527
+ enabled: !!(d.policy || {}).enabled,
528
+ layers: { ...((d.policy || {}).layers || {}) },
529
+ });
530
+ setErr(''); setMsg('');
531
+ } catch (e) { setData(null); setDraft(null); setErr(apiErr(e)); }
532
+ }, []);
533
+
534
+ // Mirrors the server's own rule so the question is asked before the request,
535
+ // not after the refusal.
536
+ const widenings = () => {
537
+ if (!data || !draft) return [];
538
+ const cur = data.policy || {};
539
+ const out = [];
540
+ if (draft.enabled && !cur.enabled) out.push('enable override requests');
541
+ Object.entries(draft.layers || {}).forEach(([k, want]) => {
542
+ if (want && !(cur.layers || {})[k]) out.push(`allow asking about: ${accLayerName(k)}`);
543
+ });
544
+ return out;
545
+ };
546
+
547
+ const save = async () => {
548
+ if (!draft || !path) return;
549
+ const widens = widenings();
550
+ if (widens.length) {
551
+ const ok = window.confirm(
552
+ `This LOOSENS the guard:\n\n • ${widens.join('\n • ')}\n\n` +
553
+ 'A yes still only lets the agent ASK — every request needs your ' +
554
+ 'approval, and a grant is single-use and path-exact.\n\nApply?');
555
+ if (!ok) { setMsg('Unchanged.'); return; }
556
+ }
557
+ setBusy(true);
558
+ try {
559
+ const d = await api.post('/api/hub/overrides/policy', {
560
+ path,
561
+ override: { enabled: draft.enabled, layers: draft.layers },
562
+ confirm: widens.length ? 'widen' : undefined,
563
+ });
564
+ setData(d);
565
+ setDraft({
566
+ enabled: !!(d.policy || {}).enabled,
567
+ layers: { ...((d.policy || {}).layers || {}) },
568
+ });
569
+ setErr('');
570
+ setMsg((d.widened && d.widened.length)
571
+ ? `Saved — widened: ${d.widened.join(', ')}`
572
+ : 'Saved.');
573
+ } catch (e) { setErr(apiErr(e)); }
574
+ setBusy(false);
575
+ };
576
+
577
+ const typed = new Set((data && data.typed_confirm_layers) || []);
578
+ const dirty = !!(data && draft) && (
579
+ draft.enabled !== !!(data.policy || {}).enabled ||
580
+ Object.entries(draft.layers || {}).some(
581
+ ([k, v]) => !!v !== !!((data.policy || {}).layers || {})[k]));
582
+
583
+ return (
584
+ <div style={{
585
+ background: T.surface, border: `1px solid ${T.border}`, borderRadius: 10,
586
+ padding: '12px 16px',
587
+ }}>
588
+ <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
589
+ <div style={{ fontSize: 12.5, fontWeight: 700, color: T.text }}>May agents ask?</div>
590
+ <select value={path}
591
+ onChange={e => { setPath(e.target.value); load(e.target.value); }}
592
+ style={{
593
+ background: T.surfaceAlt, color: T.text, border: `1px solid ${T.border}`,
594
+ borderRadius: 6, fontSize: 12, padding: '4px 8px', maxWidth: 340,
595
+ }}>
596
+ <option value="">— pick a project —</option>
597
+ {(projects || []).map(p => (
598
+ <option key={p.path} value={p.path}>{p.name || p.path}</option>
599
+ ))}
600
+ </select>
601
+ <span style={{ fontSize: 10.5, color: T.textDim }}>
602
+ off by default, per project
603
+ </span>
604
+ </div>
605
+
606
+ {err && <div style={{ marginTop: 8, fontSize: 11.5, color: T.error }}>{err}</div>}
607
+
608
+ {data && draft && (
609
+ <div style={{ marginTop: 10, display: 'flex', flexDirection: 'column', gap: 10 }}>
610
+ <label style={{ display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer', fontSize: 12 }}>
611
+ <input type="checkbox" checked={draft.enabled}
612
+ onChange={e => setDraft({ ...draft, enabled: e.target.checked })} />
613
+ <span style={{ color: T.text, fontWeight: 600 }}>
614
+ Allow override requests for this project
615
+ </span>
616
+ </label>
617
+
618
+ <div>
619
+ <div style={{
620
+ fontSize: 10.5, fontWeight: 700, letterSpacing: 1,
621
+ textTransform: 'uppercase', color: T.textDim, marginBottom: 4,
622
+ }}>Escalatable layers</div>
623
+ {(data.layers || []).map(k => (
624
+ <label key={k} style={{
625
+ display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer',
626
+ fontSize: 11.5, color: T.textMuted, padding: '2px 0',
627
+ }}>
628
+ <input type="checkbox" checked={!!draft.layers[k]}
629
+ onChange={e => setDraft({
630
+ ...draft, layers: { ...draft.layers, [k]: e.target.checked },
631
+ })} />
632
+ <span>{accLayerName(k)}</span>
633
+ {typed.has(k) && (
634
+ <span style={{ fontSize: 10, color: T.textDim }}>
635
+ — approving one makes you retype the rule
636
+ </span>
637
+ )}
638
+ </label>
639
+ ))}
640
+ </div>
641
+
642
+ <div style={{ fontSize: 10.5, color: T.textDim, lineHeight: 1.5 }}>
643
+ {data.coverage_note}
644
+ <br />
645
+ Never escalatable at any setting: the credential vault,
646
+ {' '}<span className="mono">.c3/secrets.enc</span>,
647
+ {' '}<span className="mono">.c3/cred_state.json</span>, the dispatcher
648
+ fail-closed deny, and the catastrophic shell blocks.
649
+ </div>
650
+
651
+ <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
652
+ <button onClick={save} disabled={busy || !dirty} style={{
653
+ borderRadius: 6, fontSize: 12, padding: '5px 12px', cursor: dirty ? 'pointer' : 'default',
654
+ border: `1px solid ${dirty ? T.accent : T.border}`,
655
+ background: dirty ? T.accentDim : 'transparent',
656
+ color: dirty ? T.accent : T.textDim, fontWeight: dirty ? 700 : 400,
657
+ }}>{busy ? 'Saving…' : 'Save'}</button>
658
+ {msg && <span style={{ fontSize: 11.5, color: T.textMuted }}>{msg}</span>}
659
+ </div>
660
+ </div>
661
+ )}
662
+ </div>
663
+ );
664
+ }
665
+
485
666
  function HubAccess({ projects }) {
486
667
  const [rows, setRows] = useState([]);
487
668
  const [loaded, setLoaded] = useState(false);
@@ -559,6 +740,8 @@ function HubAccess({ projects }) {
559
740
 
560
741
  <AccCostStrip onOpenRule={openRule} />
561
742
 
743
+ <AccPolicyPanel projects={projects} />
744
+
562
745
  {!loaded ? (
563
746
  <div style={{ fontSize: 12, color: T.textDim }}>Loading…</div>
564
747
  ) : rows.length === 0 ? (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-context-control
3
- Version: 2.129.0
3
+ Version: 2.129.2
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
@@ -389,6 +389,7 @@ tests/test_hub_hook_migration.py
389
389
  tests/test_hub_inspect_api.py
390
390
  tests/test_hub_locks_routes.py
391
391
  tests/test_hub_oracle_service_routes.py
392
+ tests/test_hub_override_policy_routes.py
392
393
  tests/test_hub_override_routes.py
393
394
  tests/test_hub_server_smoke.py
394
395
  tests/test_hub_subproject_links.py
@@ -507,6 +508,7 @@ tests/test_upgrade_and_version.py
507
508
  tests/test_validate.py
508
509
  tests/test_vault_write_guard.py
509
510
  tests/test_version_sync.py
511
+ tests/test_watcher_pruning.py
510
512
  tests/test_web_security.py
511
513
  tests/test_windows_reliability.py
512
514
  tui/__init__.py
@@ -2332,7 +2332,7 @@ def mobile_overrides_policy_set():
2332
2332
  section = data.get("override")
2333
2333
  if not isinstance(section, dict):
2334
2334
  return jsonify({"error": "body needs an 'override' object"}), 400
2335
- if _WAKE_KEY in section:
2335
+ if _WAKE_KEY in section: # noqa: SIM102 — kept for the phone-specific copy
2336
2336
  # `wake` is an argv this machine will execute. Everything else on this
2337
2337
  # route widens what a tap can approve; this one would decide what runs
2338
2338
  # when it does. A bearer token from a phone is authentication, not
@@ -2387,7 +2387,23 @@ def mobile_overrides_policy_set():
2387
2387
 
2388
2388
 
2389
2389
  def _override_widenings(current, section: dict) -> list:
2390
- """Which requested changes LOOSEN the policy. Names, for the challenge."""
2390
+ """Which requested changes LOOSEN the policy. Names, for the challenge.
2391
+
2392
+ DELEGATES to ``services.override_policy.widenings`` since 2.129.2, when the
2393
+ hub gained its own Security screen. Two copies of "what counts as widening"
2394
+ is two chances for one surface to quietly allow something the other
2395
+ refuses — and this is the check that decides whether a tap needs a typed
2396
+ confirmation. The name is kept because the mobile route tests call it.
2397
+ """
2398
+ from services import override_policy as _opol # noqa: PLC0415
2399
+
2400
+ return _opol.widenings(current, section)
2401
+
2402
+
2403
+ def _override_widenings_legacy(current, section: dict) -> list:
2404
+ """Retired inline copy, kept only as the reference the extraction came
2405
+ from; ``tests/test_override_policy_shared.py`` asserts it agrees with the
2406
+ service so the move can be shown to have preserved behaviour."""
2391
2407
  out = []
2392
2408
  if section.get("enabled") and not current.enabled:
2393
2409
  out.append("enabled")
@@ -2416,10 +2432,18 @@ def _override_widenings(current, section: dict) -> list:
2416
2432
  def _write_override_section(project: Path, section: dict) -> dict:
2417
2433
  """Merge *section* into the project's `.c3/config.json` `override` block.
2418
2434
 
2419
- Project scope only. A global override policy governs every project on the
2420
- machine, and the phone has no affordance for reviewing that blast radius —
2421
- same call `mobile_enforcement_set` makes about machine-wide discipline.
2435
+ DELEGATES to ``services.override_policy.write_section`` since 2.129.2 so
2436
+ the hub's Security screen and the phone write the file the same way — same
2437
+ merge semantics for `layers`, same atomic publish. The name is kept because
2438
+ the mobile route tests patch it.
2422
2439
  """
2440
+ from services import override_policy as _opol # noqa: PLC0415
2441
+
2442
+ return _opol.write_section(project, section)
2443
+
2444
+
2445
+ def _write_override_section_legacy(project: Path, section: dict) -> dict:
2446
+ """Retired inline copy; see ``_override_widenings_legacy``."""
2423
2447
  cfg_file = Path(project) / ".c3" / "config.json"
2424
2448
  cfg_file.parent.mkdir(parents=True, exist_ok=True)
2425
2449
  cfg = {}
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "code-context-control"
7
- version = "2.129.0"
7
+ version = "2.129.2"
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"
@@ -530,6 +530,153 @@ def resolve_for_path(path) -> OverridePolicy:
530
530
  return resolve(str(root)) if root else DISABLED
531
531
 
532
532
 
533
+ class PolicyEditError(ValueError):
534
+ """A rejected policy edit. `widens` is set when the reason is a widening.
535
+
536
+ Carries the same fields the mobile route already returned so a caller can
537
+ render them without re-deriving anything: `payload` is the JSON body, and
538
+ `status` the HTTP code the route should use.
539
+ """
540
+
541
+ def __init__(self, message: str, *, status: int = 400,
542
+ payload: dict | None = None, widens: list | None = None):
543
+ super().__init__(message)
544
+ self.status = status
545
+ self.payload = dict(payload or {"error": message})
546
+ self.widens = list(widens or [])
547
+
548
+
549
+ def widenings(current: "OverridePolicy", section: dict) -> list:
550
+ """Which requested changes LOOSEN the policy. Names, for the challenge.
551
+
552
+ Extracted from ``oracle.services.mobile_api`` in 2.129.2 so the hub's own
553
+ Security screen and the phone answer to ONE implementation. Two copies of
554
+ "what counts as widening" is two chances for a surface to quietly allow
555
+ something the other refuses, and this is the check that decides whether a
556
+ tap needs a typed confirmation.
557
+ """
558
+ out: list = []
559
+ if section.get("enabled") and not current.enabled:
560
+ out.append("enabled")
561
+ for key, want in (section.get("layers") or {}).items():
562
+ if want and not current.layers.get(key, False):
563
+ out.append(f"layers.{key}")
564
+ for key in ("max_ttl_s", "default_uses", "request_ttl_s",
565
+ "max_pending_per_session", "max_requests_per_hour",
566
+ # A longer TTL or a longer idle window both mean a rule grant
567
+ # outlives more of the conversation, which is a loosening even
568
+ # though nothing about it looks like a permission.
569
+ "rule_grant_ttl_s", "rule_grant_idle_s"):
570
+ if key in section:
571
+ try:
572
+ if int(section[key]) > int(getattr(current, key)):
573
+ out.append(key)
574
+ except (TypeError, ValueError):
575
+ pass
576
+ if section.get("allow_session_grants") and not current.allow_session_grants:
577
+ out.append("allow_session_grants")
578
+ if section.get("allow_rule_grants") and not current.allow_rule_grants:
579
+ out.append("allow_rule_grants")
580
+ return out
581
+
582
+
583
+ def write_section(project, section: dict) -> dict:
584
+ """Merge *section* into the project's `.c3/config.json` `override` block.
585
+
586
+ Project scope only. A global override policy governs every project on the
587
+ machine, and no remote surface has an affordance for reviewing that blast
588
+ radius.
589
+ """
590
+ from services.atomic_json import write_json_atomic # noqa: PLC0415
591
+
592
+ cfg_file = Path(project) / ".c3" / "config.json"
593
+ cfg_file.parent.mkdir(parents=True, exist_ok=True)
594
+ cfg = {}
595
+ if cfg_file.is_file():
596
+ try:
597
+ cfg = json.loads(cfg_file.read_text(encoding="utf-8")) or {}
598
+ except ValueError as exc:
599
+ raise ValueError(f"project config is not valid JSON: {exc}") from exc
600
+ if not isinstance(cfg, dict):
601
+ raise ValueError("project config is not a JSON object")
602
+ block = dict(cfg.get("override") or {})
603
+ for key, value in section.items():
604
+ if key == "layers":
605
+ merged = dict(block.get("layers") or {})
606
+ merged.update({k: bool(v) for k, v in (value or {}).items()})
607
+ block["layers"] = merged
608
+ else:
609
+ block[key] = value
610
+ cfg["override"] = block
611
+ # Shared with the CLI and the hub, and served from a threaded API, so the
612
+ # publish goes through the one race-safe writer rather than a temp name
613
+ # every writer of this file would pick.
614
+ write_json_atomic(cfg_file, cfg, ensure_ascii=False, trailing_newline=False)
615
+ return block
616
+
617
+
618
+ #: The one `override` key no REMOTE surface may write: it is an argv this
619
+ #: machine will execute. The hub is a desktop surface on localhost, so it is
620
+ #: allowed to; the phone is not. Callers pass ``allow_wake``.
621
+ WAKE_KEY = "wake"
622
+
623
+
624
+ def apply_section(project_path, section: dict, *, confirmed: bool = False,
625
+ allow_wake: bool = False) -> tuple[dict, list]:
626
+ """Validate, widening-check and write one `override` edit.
627
+
628
+ Returns ``(written_block, widens)``. Raises :class:`PolicyEditError` with
629
+ the status and body the caller should surface.
630
+
631
+ Widening — enabling the feature, turning a layer on, raising a ceiling, or
632
+ allowing session grants — needs ``confirmed=True``. Tightening never does:
633
+ making the guard stricter is always allowed to be one tap.
634
+ """
635
+ if not isinstance(section, dict):
636
+ raise PolicyEditError("body needs an 'override' object")
637
+
638
+ if WAKE_KEY in section and not allow_wake:
639
+ raise PolicyEditError(
640
+ "'wake' cannot be set from this surface — it names a command this "
641
+ "machine runs. Edit .c3/config.json on the desktop.",
642
+ status=403, payload={"error": (
643
+ "'wake' cannot be set from this surface — it names a command "
644
+ "this machine runs. Edit .c3/config.json on the desktop."),
645
+ "key": WAKE_KEY})
646
+
647
+ unknown = sorted(set(section) - set(DEFAULTS))
648
+ if unknown:
649
+ # Unknown keys are a hard error, never a silent no-op.
650
+ raise PolicyEditError(
651
+ f"unknown override key(s): {', '.join(unknown)}",
652
+ payload={"error": f"unknown override key(s): {', '.join(unknown)}",
653
+ "valid": sorted(DEFAULTS)})
654
+
655
+ layers = section.get("layers")
656
+ if layers is not None:
657
+ if not isinstance(layers, dict):
658
+ raise PolicyEditError("'layers' must be an object")
659
+ bad = sorted(set(layers) - set(LAYER_KEYS))
660
+ if bad:
661
+ raise PolicyEditError(
662
+ f"unknown layer(s): {', '.join(bad)}",
663
+ payload={"error": f"unknown layer(s): {', '.join(bad)}",
664
+ "valid": list(LAYER_KEYS)})
665
+
666
+ current = resolve(str(project_path))
667
+ widens = widenings(current, section)
668
+ if widens and not confirmed:
669
+ raise PolicyEditError(
670
+ "this widens what an approval can allow: " + ", ".join(widens),
671
+ payload={"error": ("this widens what an approval can allow: "
672
+ + ", ".join(widens)),
673
+ "widens": widens,
674
+ "needs_confirmation": True, "confirm_with": "widen"},
675
+ widens=widens)
676
+
677
+ return write_section(project_path, section), widens
678
+
679
+
533
680
  def offer_line(layer_key: str, path, tool: str, op: str) -> str:
534
681
  """The single line appended to a refusal when a layer IS escalatable.
535
682