code-context-control 2.63.2__tar.gz → 2.64.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 (383) hide show
  1. {code_context_control-2.63.2 → code_context_control-2.64.0}/PKG-INFO +1 -1
  2. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/c3.py +80 -4
  3. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/commands/parser.py +8 -0
  4. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_access_guard.py +23 -0
  5. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_server.py +0 -6
  6. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/settings_modal.js +0 -6
  7. {code_context_control-2.63.2 → code_context_control-2.64.0}/code_context_control.egg-info/PKG-INFO +1 -1
  8. {code_context_control-2.63.2 → code_context_control-2.64.0}/code_context_control.egg-info/SOURCES.txt +5 -1
  9. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/config.py +3 -0
  10. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/oracle_server.py +141 -11
  11. code_context_control-2.64.0/oracle/services/chat_store.py +245 -0
  12. code_context_control-2.64.0/oracle/services/discovery_audit.py +164 -0
  13. code_context_control-2.64.0/oracle/services/local_session.py +149 -0
  14. {code_context_control-2.63.2 → code_context_control-2.64.0}/pyproject.toml +1 -1
  15. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/access_guard.py +11 -0
  16. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/claude_md.py +97 -16
  17. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/e2e_benchmark.py +40 -6
  18. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/jira_data_center.py +119 -9
  19. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_e2e_benchmark.py +46 -2
  20. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_federated_graph.py +6 -3
  21. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hook_access_guard.py +66 -0
  22. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hub_server_smoke.py +7 -4
  23. code_context_control-2.64.0/tests/test_ide_workflow_adaptation.py +121 -0
  24. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_jira_client.py +78 -0
  25. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_apikey_api.py +6 -3
  26. code_context_control-2.64.0/tests/test_oracle_chat_store.py +176 -0
  27. code_context_control-2.64.0/tests/test_oracle_discovery_audit.py +194 -0
  28. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_local_auth.py +31 -11
  29. code_context_control-2.64.0/tests/test_oracle_session_bootstrap.py +160 -0
  30. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_ui_bundle.py +4 -2
  31. code_context_control-2.63.2/cli/hub.html +0 -3889
  32. code_context_control-2.63.2/oracle/services/chat_store.py +0 -155
  33. code_context_control-2.63.2/oracle/services/local_session.py +0 -54
  34. {code_context_control-2.63.2 → code_context_control-2.64.0}/LICENSE +0 -0
  35. {code_context_control-2.63.2 → code_context_control-2.64.0}/README.md +0 -0
  36. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/__init__.py +0 -0
  37. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/_hook_utils.py +0 -0
  38. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/commands/__init__.py +0 -0
  39. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/commands/common.py +0 -0
  40. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/docs.html +0 -0
  41. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/edits.html +0 -0
  42. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/access.html +0 -0
  43. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/bitbucket.html +0 -0
  44. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/credentials.html +0 -0
  45. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/getting-started.html +0 -0
  46. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/index.html +0 -0
  47. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/masking.html +0 -0
  48. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/oracle.html +0 -0
  49. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/shared.css +0 -0
  50. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/tools.html +0 -0
  51. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/guide/workflow.html +0 -0
  52. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_artifact.py +0 -0
  53. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_auto_snapshot.py +0 -0
  54. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_c3_signal.py +0 -0
  55. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_c3read.py +0 -0
  56. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_dispatch.py +0 -0
  57. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_edit_ledger.py +0 -0
  58. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_edit_unlock.py +0 -0
  59. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_filter.py +0 -0
  60. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_ghost_files.py +0 -0
  61. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_pretool_enforce.py +0 -0
  62. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_prompt_recall.py +0 -0
  63. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_read.py +0 -0
  64. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_session_stats.py +0 -0
  65. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hook_terse_advisor.py +0 -0
  66. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/app.js +0 -0
  67. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/add_project.js +0 -0
  68. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/config_editor.js +0 -0
  69. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/drill_artifacts.js +0 -0
  70. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/drill_health.js +0 -0
  71. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/drill_panel.js +0 -0
  72. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/drill_subprojects.js +0 -0
  73. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/drill_tasks.js +0 -0
  74. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/drill_views.js +0 -0
  75. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/global_search.js +0 -0
  76. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/hub_credentials.js +0 -0
  77. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/mcp_manager.js +0 -0
  78. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/modals.js +0 -0
  79. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/project_card.js +0 -0
  80. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/project_tree.js +0 -0
  81. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/session_drawer.js +0 -0
  82. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/sidebar.js +0 -0
  83. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/summary_bar.js +0 -0
  84. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/task_board.js +0 -0
  85. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/toasts.js +0 -0
  86. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/components/topbar.js +0 -0
  87. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui/state.js +0 -0
  88. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/hub_ui.html +0 -0
  89. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/mcp_proxy.py +0 -0
  90. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/mcp_server.py +0 -0
  91. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/progress.py +0 -0
  92. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/server.py +0 -0
  93. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/__init__.py +0 -0
  94. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/_helpers.py +0 -0
  95. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/agent.py +0 -0
  96. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/artifacts.py +0 -0
  97. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/bitbucket.py +0 -0
  98. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/compress.py +0 -0
  99. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/credentials.py +0 -0
  100. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/delegate.py +0 -0
  101. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/edit.py +0 -0
  102. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/edits.py +0 -0
  103. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/federate.py +0 -0
  104. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/filter.py +0 -0
  105. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/impact.py +0 -0
  106. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/jira.py +0 -0
  107. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/memory.py +0 -0
  108. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/project.py +0 -0
  109. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/read.py +0 -0
  110. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/search.py +0 -0
  111. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/session.py +0 -0
  112. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/shell.py +0 -0
  113. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/status.py +0 -0
  114. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/tasks.py +0 -0
  115. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/tools/validate.py +0 -0
  116. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/api.js +0 -0
  117. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/app.js +0 -0
  118. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/access.js +0 -0
  119. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/bitbucket.js +0 -0
  120. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/chat.js +0 -0
  121. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/credentials.js +0 -0
  122. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/dashboard.js +0 -0
  123. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/edits.js +0 -0
  124. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/instructions.js +0 -0
  125. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/jira.js +0 -0
  126. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/memory.js +0 -0
  127. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/sessions.js +0 -0
  128. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/settings.js +0 -0
  129. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/sidebar.js +0 -0
  130. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/components/tasks.js +0 -0
  131. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/icons.js +0 -0
  132. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/pm_shared.js +0 -0
  133. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/shared.js +0 -0
  134. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui/theme.js +0 -0
  135. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui.html +0 -0
  136. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui_legacy.html +0 -0
  137. {code_context_control-2.63.2 → code_context_control-2.64.0}/cli/ui_nano.html +0 -0
  138. {code_context_control-2.63.2 → code_context_control-2.64.0}/code_context_control.egg-info/dependency_links.txt +0 -0
  139. {code_context_control-2.63.2 → code_context_control-2.64.0}/code_context_control.egg-info/entry_points.txt +0 -0
  140. {code_context_control-2.63.2 → code_context_control-2.64.0}/code_context_control.egg-info/requires.txt +0 -0
  141. {code_context_control-2.63.2 → code_context_control-2.64.0}/code_context_control.egg-info/top_level.txt +0 -0
  142. {code_context_control-2.63.2 → code_context_control-2.64.0}/core/__init__.py +0 -0
  143. {code_context_control-2.63.2 → code_context_control-2.64.0}/core/config.py +0 -0
  144. {code_context_control-2.63.2 → code_context_control-2.64.0}/core/ide.py +0 -0
  145. {code_context_control-2.63.2 → code_context_control-2.64.0}/core/mcp_toml.py +0 -0
  146. {code_context_control-2.63.2 → code_context_control-2.64.0}/core/web_security.py +0 -0
  147. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/__init__.py +0 -0
  148. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/mcp_oracle.py +0 -0
  149. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/oracle_ui.html +0 -0
  150. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/__init__.py +0 -0
  151. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/activity_reporter.py +0 -0
  152. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/api_auth.py +0 -0
  153. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/c3_bridge.py +0 -0
  154. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/chat_engine.py +0 -0
  155. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/cross_memory.py +0 -0
  156. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/federated_graph.py +0 -0
  157. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/health_checker.py +0 -0
  158. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/insight_engine.py +0 -0
  159. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/memory_reader.py +0 -0
  160. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/memory_writer.py +0 -0
  161. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/project_scanner.py +0 -0
  162. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/review_agent.py +0 -0
  163. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/tool_executor.py +0 -0
  164. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/services/tool_registry.py +0 -0
  165. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/activity.js +0 -0
  166. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/agents.js +0 -0
  167. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/app.js +0 -0
  168. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/busy.js +0 -0
  169. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/chat/conversations.js +0 -0
  170. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/chat/input.js +0 -0
  171. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/chat/markdown.js +0 -0
  172. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/chat/send.js +0 -0
  173. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/chat/stream_renderer.js +0 -0
  174. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/chat/toolbar.js +0 -0
  175. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/core.js +0 -0
  176. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/crossgraph.js +0 -0
  177. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/header.js +0 -0
  178. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/insights.js +0 -0
  179. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/projects.js +0 -0
  180. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/settings.js +0 -0
  181. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/suggestions.js +0 -0
  182. {code_context_control-2.63.2 → code_context_control-2.64.0}/oracle/ui/theme_tabs.js +0 -0
  183. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/__init__.py +0 -0
  184. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/activity_log.py +0 -0
  185. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/agent_base.py +0 -0
  186. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/agents.py +0 -0
  187. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/artifact_defs.py +0 -0
  188. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/artifact_store.py +0 -0
  189. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/auto_memory.py +0 -0
  190. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/bench/__init__.py +0 -0
  191. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/bench/external/__init__.py +0 -0
  192. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/bench/external/aider_polyglot.py +0 -0
  193. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/bench/external/swe_bench.py +0 -0
  194. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/benchmark_dashboard.py +0 -0
  195. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/bitbucket_client.py +0 -0
  196. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/bitbucket_credentials.py +0 -0
  197. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/circuit_breaker.py +0 -0
  198. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/compressor.py +0 -0
  199. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/context_snapshot.py +0 -0
  200. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/conversation_store.py +0 -0
  201. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/credential_store.py +0 -0
  202. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/doc_index.py +0 -0
  203. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/e2e_evaluator.py +0 -0
  204. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/e2e_tasks.py +0 -0
  205. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/edit_ledger.py +0 -0
  206. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/embedding_index.py +0 -0
  207. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/error_reporting.py +0 -0
  208. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/file_memory.py +0 -0
  209. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/git_context.py +0 -0
  210. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/hub_service.py +0 -0
  211. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/indexer.py +0 -0
  212. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/jira_client.py +0 -0
  213. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/jira_cloud.py +0 -0
  214. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/jira_credentials.py +0 -0
  215. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/jira_links.py +0 -0
  216. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/mask_activation.py +0 -0
  217. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/mask_mirror.py +0 -0
  218. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/mask_presets.py +0 -0
  219. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/memory.py +0 -0
  220. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/memory_consolidator.py +0 -0
  221. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/memory_distiller.py +0 -0
  222. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/memory_graph.py +0 -0
  223. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/memory_grounder.py +0 -0
  224. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/memory_queue.py +0 -0
  225. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/memory_scorer.py +0 -0
  226. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/metrics.py +0 -0
  227. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/notifications.py +0 -0
  228. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/ollama_bridge.py +0 -0
  229. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/ollama_client.py +0 -0
  230. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/ollama_credentials.py +0 -0
  231. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/output_filter.py +0 -0
  232. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/parser.py +0 -0
  233. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/project_manager.py +0 -0
  234. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/project_runtime.py +0 -0
  235. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/protocol.py +0 -0
  236. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/proxy_state.py +0 -0
  237. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/repo_map.py +0 -0
  238. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/retention.py +0 -0
  239. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/retrieval_broker.py +0 -0
  240. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/router.py +0 -0
  241. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/runtime.py +0 -0
  242. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/scanner.py +0 -0
  243. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/session_benchmark.py +0 -0
  244. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/session_manager.py +0 -0
  245. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/session_preloader.py +0 -0
  246. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/subprojects.py +0 -0
  247. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/task_store.py +0 -0
  248. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/telemetry.py +0 -0
  249. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/text_index.py +0 -0
  250. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/time_tracker.py +0 -0
  251. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/tool_classifier.py +0 -0
  252. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/transcript_index.py +0 -0
  253. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/validation_cache.py +0 -0
  254. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/vector_store.py +0 -0
  255. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/watcher.py +0 -0
  256. {code_context_control-2.63.2 → code_context_control-2.64.0}/services/win_subprocess.py +0 -0
  257. {code_context_control-2.63.2 → code_context_control-2.64.0}/setup.cfg +0 -0
  258. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_access_guard.py +0 -0
  259. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_access_guard_meta.py +0 -0
  260. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_access_guard_shell_project.py +0 -0
  261. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_access_guard_surfaces.py +0 -0
  262. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_access_guard_wiring.py +0 -0
  263. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_activity_reporter.py +0 -0
  264. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_aider_polyglot.py +0 -0
  265. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_antigravity_transition.py +0 -0
  266. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_artifact_store.py +0 -0
  267. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_artifact_tool.py +0 -0
  268. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_bitbucket_cli_smoke.py +0 -0
  269. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_bitbucket_client.py +0 -0
  270. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_bitbucket_config_fallback.py +0 -0
  271. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_bitbucket_credentials.py +0 -0
  272. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_bitbucket_tool.py +0 -0
  273. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_c3_bridge_project_artifacts.py +0 -0
  274. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_c3_shell.py +0 -0
  275. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_circuit_breaker.py +0 -0
  276. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_claude_md_merge.py +0 -0
  277. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_cli_smoke.py +0 -0
  278. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_compressor_large_file.py +0 -0
  279. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_credential_store.py +0 -0
  280. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_credentials_routes.py +0 -0
  281. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_credentials_tool.py +0 -0
  282. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_creds_cli_smoke.py +0 -0
  283. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_delegate_cascade.py +0 -0
  284. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_edit_ledger_hook.py +0 -0
  285. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_edit_normalization.py +0 -0
  286. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_enforcement_flip.py +0 -0
  287. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_filter_backoff.py +0 -0
  288. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_ghost_files.py +0 -0
  289. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_ghost_generation.py +0 -0
  290. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_git_branch_awareness.py +0 -0
  291. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hook_dispatch.py +0 -0
  292. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hook_pretool_enforce.py +0 -0
  293. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hook_prompt_recall.py +0 -0
  294. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hook_smoke.py +0 -0
  295. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hook_state.py +0 -0
  296. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hook_utf8_stdio.py +0 -0
  297. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hub_credentials_route.py +0 -0
  298. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hub_credentials_routes_write.py +0 -0
  299. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hub_inspect_api.py +0 -0
  300. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_hub_subproject_links.py +0 -0
  301. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_init_scan.py +0 -0
  302. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_install_mcp_entrypoint.py +0 -0
  303. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_jira_cli_smoke.py +0 -0
  304. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_jira_config_fallback.py +0 -0
  305. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_jira_credentials.py +0 -0
  306. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_jira_links.py +0 -0
  307. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_jira_routes.py +0 -0
  308. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_jira_tool.py +0 -0
  309. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_lazy_store_init.py +0 -0
  310. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_mask_guard.py +0 -0
  311. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_mask_routes.py +0 -0
  312. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_mask_surfaces.py +0 -0
  313. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_mcp_host_guard.py +0 -0
  314. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_mcp_memory_timeout.py +0 -0
  315. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_mcp_server_smoke.py +0 -0
  316. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_mcp_toml.py +0 -0
  317. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_memory_distiller.py +0 -0
  318. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_memory_graph_api.py +0 -0
  319. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_memory_queue.py +0 -0
  320. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_memory_system.py +0 -0
  321. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_no_stale_model_pins.py +0 -0
  322. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_notification_dedup.py +0 -0
  323. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_notification_discipline.py +0 -0
  324. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_ollama_credentials.py +0 -0
  325. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_api_auth.py +0 -0
  326. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_c3_bridge.py +0 -0
  327. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_chat_engine.py +0 -0
  328. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_discovery_api.py +0 -0
  329. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_ollama_bridge.py +0 -0
  330. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_scanner_cache.py +0 -0
  331. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_security_fixes.py +0 -0
  332. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_oracle_subproject_awareness.py +0 -0
  333. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_output_filter.py +0 -0
  334. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_permissions.py +0 -0
  335. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_pm_api.py +0 -0
  336. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_project_manager.py +0 -0
  337. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_project_manager_merge.py +0 -0
  338. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_project_tool.py +0 -0
  339. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_read_coercion.py +0 -0
  340. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_read_edit_parity.py +0 -0
  341. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_related_facts.py +0 -0
  342. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_repo_map.py +0 -0
  343. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_response_boilerplate.py +0 -0
  344. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_retention.py +0 -0
  345. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_review_digest.py +0 -0
  346. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_service_durability.py +0 -0
  347. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_session_benchmark.py +0 -0
  348. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_session_budget.py +0 -0
  349. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_shell_creds.py +0 -0
  350. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_shell_robustness.py +0 -0
  351. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_subproject_exclusion.py +0 -0
  352. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_subproject_federation.py +0 -0
  353. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_subprojects.py +0 -0
  354. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_swe_bench.py +0 -0
  355. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_task_store.py +0 -0
  356. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_task_tool.py +0 -0
  357. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_time_tracker.py +0 -0
  358. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_token_telemetry.py +0 -0
  359. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_tool_registry.py +0 -0
  360. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_upgrade_and_version.py +0 -0
  361. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_validate.py +0 -0
  362. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_vault_write_guard.py +0 -0
  363. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_version_sync.py +0 -0
  364. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_web_security.py +0 -0
  365. {code_context_control-2.63.2 → code_context_control-2.64.0}/tests/test_windows_reliability.py +0 -0
  366. {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/__init__.py +0 -0
  367. {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/backend.py +0 -0
  368. {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/main.py +0 -0
  369. {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/__init__.py +0 -0
  370. {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/benchmark_view.py +0 -0
  371. {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/claudemd_view.py +0 -0
  372. {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/compress_view.py +0 -0
  373. {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/index_view.py +0 -0
  374. {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/init_view.py +0 -0
  375. {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/mcp_view.py +0 -0
  376. {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/optimize_view.py +0 -0
  377. {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/pipe_view.py +0 -0
  378. {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/projects_view.py +0 -0
  379. {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/search_view.py +0 -0
  380. {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/session_view.py +0 -0
  381. {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/stats.py +0 -0
  382. {code_context_control-2.63.2 → code_context_control-2.64.0}/tui/screens/ui_view.py +0 -0
  383. {code_context_control-2.63.2 → code_context_control-2.64.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.63.2
3
+ Version: 2.64.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
@@ -92,7 +92,7 @@ console = Console() if HAS_RICH else None
92
92
  # Config
93
93
  CONFIG_DIR = ".c3"
94
94
  CONFIG_FILE = ".c3/config.json"
95
- __version__ = "2.63.2"
95
+ __version__ = "2.64.0"
96
96
 
97
97
 
98
98
  def _compress_file_cli(compressor, path, mode="smart", **kw):
@@ -4046,14 +4046,22 @@ def cmd_pipe(args):
4046
4046
 
4047
4047
 
4048
4048
  from services.claude_md import C3_COMPACT_WORKFLOW as _SHARED_C3_COMPACT_WORKFLOW
4049
+ from services.claude_md import VSCODE_SESSION_INIT as _VSCODE_SESSION_INIT
4050
+ from services.claude_md import adapt_workflow_for_ide as _adapt_workflow_for_ide
4049
4051
 
4050
4052
  _C3_COMPACT_WORKFLOW = _SHARED_C3_COMPACT_WORKFLOW
4051
4053
 
4052
4054
  _CLAUDE_MD_CONTENT = _C3_COMPACT_WORKFLOW
4053
4055
 
4054
- _COPILOT_INSTRUCTIONS_CONTENT = _C3_COMPACT_WORKFLOW
4056
+ # Copilot and Codex run without PreToolUse hooks and without /clear, so both
4057
+ # docs get the hookless restatement of the mandate (see PROFILES in core/ide.py).
4058
+ _C3_HOOKLESS_WORKFLOW = _adapt_workflow_for_ide(
4059
+ _C3_COMPACT_WORKFLOW, supports_hooks=False, supports_clear=False
4060
+ )
4061
+
4062
+ _COPILOT_INSTRUCTIONS_CONTENT = _VSCODE_SESSION_INIT + "\n\n" + _C3_HOOKLESS_WORKFLOW
4055
4063
 
4056
- _AGENTS_MD_CONTENT = _C3_COMPACT_WORKFLOW + """
4064
+ _AGENTS_MD_CONTENT = _C3_HOOKLESS_WORKFLOW + """
4057
4065
 
4058
4066
  ## IDE Configuration (Codex)
4059
4067
  This project uses project-scoped MCP servers. Ensure your `.codex/config.toml` includes:
@@ -5989,6 +5997,10 @@ def _access_cmd_list(args, project_path: str) -> None:
5989
5997
  if sec.get("corrupt"):
5990
5998
  print(" [warn] access section invalid — scope fails closed "
5991
5999
  "(deny-all); fix config.json 'access' by hand")
6000
+ if scope == "builtin":
6001
+ print(" spelling rules (deny by how a path is written, no glob):")
6002
+ for name, why in access_guard.SYNTHETIC_RULES:
6003
+ print(f" {name:<18} {why}")
5992
6004
  print()
5993
6005
  from services import mask_activation
5994
6006
  summary = mask_activation.summary_line(project_path)
@@ -6404,6 +6416,66 @@ def _jira_cmd_set_default(args, project_path: str) -> None:
6404
6416
  print(f"[OK] Default Jira project: {args.project}")
6405
6417
 
6406
6418
 
6419
+ def _oracle_open(args):
6420
+ """Mint a single-use sign-in URL for a running Oracle dashboard (#31).
6421
+
6422
+ Plain ``GET /`` no longer issues the session cookie, so a dashboard opened
6423
+ by hand is read-only until a bootstrap code is redeemed. Reading the
6424
+ owner-only key file is what proves we are the same OS user as the server.
6425
+ """
6426
+ import json as _json
6427
+ import urllib.error
6428
+ import urllib.request
6429
+ import webbrowser
6430
+
6431
+ from oracle.config import ORACLE_DIR, load_config
6432
+ from oracle.services import local_session
6433
+
6434
+ cfg = load_config()
6435
+ host = cfg.get("bind_host", "127.0.0.1")
6436
+ disp_host = "127.0.0.1" if host in ("0.0.0.0", "") else host
6437
+ port = getattr(args, "port", None) or cfg.get("port", 3331)
6438
+ base = f"http://{disp_host}:{port}"
6439
+
6440
+ key = local_session.read_bootstrap_key(ORACLE_DIR)
6441
+ if not key:
6442
+ print(f"[oracle:open] no bootstrap key at "
6443
+ f"{ORACLE_DIR / local_session.BOOTSTRAP_KEY_FILENAME}")
6444
+ print(" The key is written when the server starts. Is Oracle running?")
6445
+ print(" Start it with: c3 oracle serve")
6446
+ return
6447
+
6448
+ req = urllib.request.Request(
6449
+ f"{base}/api/session/bootstrap",
6450
+ data=_json.dumps({"key": key}).encode("utf-8"),
6451
+ headers={"Content-Type": "application/json"},
6452
+ method="POST",
6453
+ )
6454
+ try:
6455
+ with urllib.request.urlopen(req, timeout=10) as resp:
6456
+ payload = _json.loads(resp.read().decode("utf-8"))
6457
+ except urllib.error.HTTPError as e:
6458
+ detail = e.read().decode("utf-8", "replace")[:200]
6459
+ print(f"[oracle:open] server refused the request ({e.code}): {detail}")
6460
+ if e.code == 401:
6461
+ print(" The key on disk is stale — restart the server to rewrite it.")
6462
+ return
6463
+ except OSError as e:
6464
+ print(f"[oracle:open] could not reach {base}: {e}")
6465
+ print(" Start it with: c3 oracle serve")
6466
+ return
6467
+
6468
+ url = payload.get("url", "")
6469
+ if not url:
6470
+ print("[oracle:open] server returned no URL")
6471
+ return
6472
+ ttl = payload.get("expires_in", local_session.CODE_TTL_SECONDS)
6473
+ print(f"[oracle:open] single-use sign-in link (valid {ttl}s, one use):")
6474
+ print(f" {url}")
6475
+ if not getattr(args, "no_browser", False):
6476
+ webbrowser.open(url)
6477
+
6478
+
6407
6479
  def cmd_oracle(args):
6408
6480
  """Oracle dashboard server + Discovery API key management."""
6409
6481
  sub = getattr(args, "oracle_cmd", None)
@@ -6414,8 +6486,12 @@ def cmd_oracle(args):
6414
6486
  run_oracle(port=getattr(args, "port", None),
6415
6487
  open_browser=not getattr(args, "no_browser", False))
6416
6488
  return
6489
+ if sub == "open":
6490
+ _oracle_open(args)
6491
+ return
6417
6492
  if sub != "api":
6418
- print("Usage: c3 oracle {serve,api} — serve: launch the dashboard; "
6493
+ print("Usage: c3 oracle {serve,open,api} — serve: launch the dashboard; "
6494
+ "open: sign in to a running dashboard; "
6419
6495
  "api {info,key,rotate,clear}: manage the Discovery key")
6420
6496
  return
6421
6497
 
@@ -540,6 +540,14 @@ def build_parser(version: str, parse_cli_ide_arg):
540
540
  help="Server port (default: config 'port', 3331)")
541
541
  or_serve.add_argument("--no-browser", action="store_true",
542
542
  help="Don't open the browser")
543
+ or_open = or_subs.add_parser(
544
+ "open",
545
+ help="Sign in to a running dashboard via a single-use URL",
546
+ )
547
+ or_open.add_argument("--port", type=int, default=None,
548
+ help="Server port (default: config 'port', 3331)")
549
+ or_open.add_argument("--no-browser", action="store_true",
550
+ help="Print the URL without opening a browser")
543
551
  or_api = or_subs.add_parser(
544
552
  "api",
545
553
  help="Show connection info / manage the Discovery API key",
@@ -31,6 +31,23 @@ _SHELL_TOOLS = {"Bash"} # normalize_tool_name folds run_shell_command in
31
31
  _TOKEN_SPLIT = re.compile(r"\s+")
32
32
  _MAX_TOKENS = 200
33
33
 
34
+ # A colon in a shell token overwhelmingly means "URL scheme" or "IPv6", not
35
+ # "NTFS alternate data stream". The ADS check stays strict for real path
36
+ # arguments (_WRITE_TOOLS/_READ_TOOLS); here it only produced false denies on
37
+ # commit messages, curl, and gh (#50).
38
+ _SCHEME_RE = re.compile(r"^[a-z][a-z0-9+.\-]*://", re.IGNORECASE)
39
+ # IPv6 literal or CIDR: >=2 colons, hex groups only, optional [] and /prefix.
40
+ # 'C:/x/f.txt:stream' has one colon and non-hex parts, so it never matches.
41
+ _IPV6_RE = re.compile(
42
+ r"^\[?[0-9a-f]{0,4}(?::[0-9a-f]{0,4}){2,}\]?(?:/\d{1,3})?$",
43
+ re.IGNORECASE,
44
+ )
45
+
46
+
47
+ def _is_network_token(tok: str) -> bool:
48
+ """True for URLs and IPv6 literals/CIDRs — never for an ADS spelling."""
49
+ return bool(_SCHEME_RE.match(tok) or _IPV6_RE.match(tok))
50
+
34
51
 
35
52
  def _deny(reason: str) -> dict:
36
53
  return {
@@ -57,6 +74,10 @@ def _scan_shell(cmd: str, base: str):
57
74
  Confident = the token resolves to an EXISTING path that a ``deny`` rule
58
75
  covers (existence-gating keeps regex/pattern arguments like '\\.env'
59
76
  from false-denying), or the evaluator flags the spelling itself.
77
+
78
+ URLs and IPv6 literals are skipped outright: they trip the ADS spelling
79
+ check, which is exempt from existence-gating, so a token naming nothing
80
+ on disk would otherwise hard-deny (#50).
60
81
  """
61
82
  for raw in _TOKEN_SPLIT.split(cmd)[:_MAX_TOKENS]:
62
83
  tok = raw.strip("\"'`;,()")
@@ -64,6 +85,8 @@ def _scan_shell(cmd: str, base: str):
64
85
  continue
65
86
  if "/" not in tok and "\\" not in tok and not tok.startswith("."):
66
87
  continue
88
+ if _is_network_token(tok):
89
+ continue
67
90
  if re.match(r"^/[a-z]/", tok): # MSYS /c/foo → C:/foo
68
91
  tok = f"{tok[1]}:{tok[2:]}"
69
92
  denial = ag.check(tok, "read", base)
@@ -379,12 +379,6 @@ def index():
379
379
  return Response(_hub_html_cache, mimetype="text/html")
380
380
 
381
381
 
382
- @app.route("/legacy")
383
- def index_legacy():
384
- """Frozen pre-2.44 hub UI — escape hatch for one release, then removed."""
385
- return send_from_directory(str(Path(__file__).parent), "hub.html")
386
-
387
-
388
382
  @app.route("/guide/")
389
383
  @app.route("/guide/<path:filename>")
390
384
  def serve_guide(filename="index.html"):
@@ -187,12 +187,6 @@ function SettingsModal({ onClose, onChanged }) {
187
187
  </div>
188
188
  )}
189
189
 
190
- <div style={{ marginTop: 18, paddingTop: 12, borderTop: `1px solid ${T.border}` }}>
191
- <a href="/legacy" style={{ fontSize: 11, color: T.textMuted, textDecoration: 'none' }}>
192
- Legacy UI (pre-2.44)
193
- </a>
194
- </div>
195
-
196
190
  {confirmAction === 'stop' && (
197
191
  <ConfirmDialog title="Stop Hub"
198
192
  message="The page will become unreachable until the hub is restarted (c3 hub)."
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-context-control
3
- Version: 2.63.2
3
+ Version: 2.64.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
@@ -21,7 +21,6 @@ cli/hook_prompt_recall.py
21
21
  cli/hook_read.py
22
22
  cli/hook_session_stats.py
23
23
  cli/hook_terse_advisor.py
24
- cli/hub.html
25
24
  cli/hub_server.py
26
25
  cli/hub_ui.html
27
26
  cli/mcp_proxy.py
@@ -132,6 +131,7 @@ oracle/services/c3_bridge.py
132
131
  oracle/services/chat_engine.py
133
132
  oracle/services/chat_store.py
134
133
  oracle/services/cross_memory.py
134
+ oracle/services/discovery_audit.py
135
135
  oracle/services/federated_graph.py
136
136
  oracle/services/health_checker.py
137
137
  oracle/services/insight_engine.py
@@ -285,6 +285,7 @@ tests/test_hub_credentials_routes_write.py
285
285
  tests/test_hub_inspect_api.py
286
286
  tests/test_hub_server_smoke.py
287
287
  tests/test_hub_subproject_links.py
288
+ tests/test_ide_workflow_adaptation.py
288
289
  tests/test_init_scan.py
289
290
  tests/test_install_mcp_entrypoint.py
290
291
  tests/test_jira_cli_smoke.py
@@ -314,11 +315,14 @@ tests/test_oracle_api_auth.py
314
315
  tests/test_oracle_apikey_api.py
315
316
  tests/test_oracle_c3_bridge.py
316
317
  tests/test_oracle_chat_engine.py
318
+ tests/test_oracle_chat_store.py
317
319
  tests/test_oracle_discovery_api.py
320
+ tests/test_oracle_discovery_audit.py
318
321
  tests/test_oracle_local_auth.py
319
322
  tests/test_oracle_ollama_bridge.py
320
323
  tests/test_oracle_scanner_cache.py
321
324
  tests/test_oracle_security_fixes.py
325
+ tests/test_oracle_session_bootstrap.py
322
326
  tests/test_oracle_subproject_awareness.py
323
327
  tests/test_oracle_ui_bundle.py
324
328
  tests/test_output_filter.py
@@ -14,6 +14,9 @@ DEFAULTS = {
14
14
  "api_enabled": True, # expose /api/discovery/* REST surface
15
15
  "api_require_auth": True, # require Bearer token on /api/discovery/*
16
16
  "api_max_tier": "action", # cap exposed tools: "read" | "action"
17
+ "api_rate_limit_per_min": 60, # per-caller tool-call budget; 0 disables
18
+ "api_rate_burst": 0, # bucket size; 0 = quarter-minute of budget
19
+ "api_audit_enabled": True, # JSONL audit line per discovery tool call
17
20
  "mcp_enabled": True, # start FastMCP HTTP/SSE discovery server
18
21
  "mcp_port": 3332, # discovery MCP transport port (loopback)
19
22
  "ollama_base_url": "https://ollama.com",
@@ -6,6 +6,7 @@ import logging
6
6
  import socket
7
7
  import sys
8
8
  import threading
9
+ import time
9
10
  import urllib.request
10
11
  import webbrowser
11
12
  from pathlib import Path
@@ -15,7 +16,7 @@ _PROJECT_ROOT = Path(__file__).resolve().parent.parent
15
16
  if str(_PROJECT_ROOT) not in sys.path:
16
17
  sys.path.insert(0, str(_PROJECT_ROOT))
17
18
 
18
- from flask import Flask, Response, jsonify, request # noqa: E402
19
+ from flask import Flask, Response, jsonify, redirect, request, url_for # noqa: E402
19
20
 
20
21
  from oracle.config import ORACLE_DIR, load_config, save_config # noqa: E402
21
22
  from oracle.mcp_oracle import mcp_url, start_mcp_thread # noqa: E402
@@ -143,6 +144,42 @@ _install_web_guard(
143
144
  )
144
145
 
145
146
 
147
+ # ── Discovery API rate limit + audit (#33) ────────────────
148
+ from oracle.services import discovery_audit # noqa: E402
149
+
150
+ # Only tool-executing routes are throttled; /tools, /openapi.json and
151
+ # /mcp-info are cheap reads.
152
+ _RATE_LIMITED_PATHS = {"/api/discovery/call", "/api/discovery/call/stream"}
153
+
154
+ _limiter: discovery_audit.RateLimiter | None = None
155
+ _limiter_key: tuple[int, int] | None = None
156
+
157
+
158
+ def _rate_limiter() -> discovery_audit.RateLimiter:
159
+ """Rebuild the bucket only when the configured budget actually changes,
160
+ so a config reload does not silently reset every caller's usage."""
161
+ global _limiter, _limiter_key
162
+ key = (int(_cfg.get("api_rate_limit_per_min", 60) or 0),
163
+ int(_cfg.get("api_rate_burst", 0) or 0))
164
+ if _limiter is None or key != _limiter_key:
165
+ _limiter = discovery_audit.RateLimiter(per_minute=key[0], burst=key[1])
166
+ _limiter_key = key
167
+ return _limiter
168
+
169
+
170
+ def _audit_call(name: str, args: dict, started: float, status: str) -> None:
171
+ if not _cfg.get("api_audit_enabled", True):
172
+ return
173
+ token = extract_bearer(request.headers.get("Authorization"))
174
+ discovery_audit.record(
175
+ name,
176
+ caller=discovery_audit.caller_id(token, request.remote_addr),
177
+ args=args,
178
+ duration_ms=(time.monotonic() - started) * 1000.0,
179
+ status=status,
180
+ )
181
+
182
+
146
183
  # ── Discovery API auth guard ──────────────────────────────
147
184
  @app.before_request
148
185
  def _discovery_auth_guard():
@@ -154,10 +191,28 @@ def _discovery_auth_guard():
154
191
  return None # allow CORS preflight
155
192
  if not _cfg.get("api_enabled", True):
156
193
  return jsonify({"error": "discovery API disabled"}), 404
194
+ token = extract_bearer(request.headers.get("Authorization"))
157
195
  if _cfg.get("api_require_auth", True):
158
- token = extract_bearer(request.headers.get("Authorization"))
159
196
  if not verify_api_key(token):
160
197
  return jsonify({"error": "unauthorized"}), 401
198
+
199
+ # Throttle the endpoints that actually execute tools. Listing tools, the
200
+ # OpenAPI doc, and mcp-info are cheap and read-only, so they stay open —
201
+ # a limiter that blocks discovery of the API is just a worse error message.
202
+ if request.path.rstrip("/") in _RATE_LIMITED_PATHS or \
203
+ request.path.startswith("/api/discovery/tools/"):
204
+ limiter = _rate_limiter()
205
+ allowed, retry_after = limiter.check(
206
+ discovery_audit.caller_id(token, request.remote_addr)
207
+ )
208
+ if not allowed:
209
+ resp = jsonify({
210
+ "error": "rate limited",
211
+ "detail": f"exceeded {limiter.per_minute} tool calls/min",
212
+ "retry_after": round(retry_after, 2),
213
+ })
214
+ resp.headers["Retry-After"] = str(max(1, int(retry_after + 0.999)))
215
+ return resp, 429
161
216
  return None
162
217
 
163
218
 
@@ -178,6 +233,10 @@ def _local_write_guard():
178
233
  return None
179
234
  if request.method in ("GET", "HEAD", "OPTIONS"):
180
235
  return None
236
+ # The bootstrap mint is how a browser ACQUIRES the cookie, so it cannot
237
+ # require one. It runs its own loopback + bootstrap-key/Bearer check.
238
+ if path == "/api/session/bootstrap":
239
+ return None
181
240
  if verify_api_key(extract_bearer(request.headers.get("Authorization"))):
182
241
  return None
183
242
  if local_session.verify(request.cookies.get(local_session.COOKIE_NAME)):
@@ -237,14 +296,48 @@ _oracle_html_cache: str | None = None
237
296
  @app.route("/")
238
297
  def index():
239
298
  global _oracle_html_cache
299
+ # A single-use bootstrap code is the ONLY way to obtain the session
300
+ # cookie (#31). Redeeming it redirects to a clean "/" so the code does
301
+ # not linger in the address bar, browser history, or a Referer header.
302
+ code = request.args.get(local_session.BOOTSTRAP_PARAM)
303
+ if code:
304
+ if local_session.is_loopback(request.remote_addr) and \
305
+ local_session.consume_code(code):
306
+ resp = redirect(url_for("index"))
307
+ local_session.attach_cookie(resp)
308
+ return resp
309
+ return redirect(url_for("index", stale="1"))
310
+
240
311
  if _oracle_html_cache is None:
241
312
  _oracle_html_cache = _build_oracle_html()
242
- resp = Response(_oracle_html_cache, mimetype="text/html")
243
- # Issue the dashboard session cookie only to loopback browsers; remote
244
- # viewers (LAN bind) can read GET dashboards but cannot mutate.
245
- if local_session.is_loopback(request.remote_addr):
246
- local_session.attach_cookie(resp)
247
- return resp
313
+ # No cookie here by design: plain GET / is readable by any local process,
314
+ # including one running as a different OS user.
315
+ return Response(_oracle_html_cache, mimetype="text/html")
316
+
317
+
318
+ @app.route("/api/session/bootstrap", methods=["POST"])
319
+ def api_session_bootstrap():
320
+ """Mint a single-use bootstrap URL. Used by ``c3 oracle open``.
321
+
322
+ Authorized by the on-disk bootstrap key (owner-only) or the Discovery
323
+ Bearer token — both prove same-OS-user access, which is the boundary
324
+ this feature enforces.
325
+ """
326
+ if not local_session.is_loopback(request.remote_addr):
327
+ return jsonify({"error": "loopback only"}), 403
328
+ data = request.get_json(silent=True) or {}
329
+ presented = (data.get("key") or "").strip() or \
330
+ request.headers.get("X-C3-Bootstrap-Key", "")
331
+ authorized = local_session.verify_bootstrap_key(presented) or \
332
+ verify_api_key(extract_bearer(request.headers.get("Authorization")))
333
+ if not authorized:
334
+ return jsonify({"error": "unauthorized"}), 401
335
+ code = local_session.mint_code()
336
+ base = request.host_url.rstrip("/")
337
+ return jsonify({
338
+ "url": f"{base}/?{local_session.BOOTSTRAP_PARAM}={code}",
339
+ "expires_in": local_session.CODE_TTL_SECONDS,
340
+ })
248
341
 
249
342
 
250
343
  # ── Health ────────────────────────────────────────────────
@@ -778,7 +871,15 @@ def api_discovery_call():
778
871
  args = data.get("args") or {}
779
872
  if not isinstance(args, dict):
780
873
  return jsonify({"error": "'args' must be an object"}), 400
781
- return jsonify(_tool_registry.call_tool(name, args))
874
+ started = time.monotonic()
875
+ try:
876
+ result = _tool_registry.call_tool(name, args)
877
+ except Exception:
878
+ _audit_call(name, args, started, "error")
879
+ raise
880
+ _audit_call(name, args, started,
881
+ "error" if isinstance(result, dict) and result.get("error") else "ok")
882
+ return jsonify(result)
782
883
 
783
884
 
784
885
  @app.route("/api/discovery/tools/<name>", methods=["POST"])
@@ -789,7 +890,25 @@ def api_discovery_call_named(name):
789
890
  args = request.get_json(silent=True) or {}
790
891
  if not isinstance(args, dict):
791
892
  return jsonify({"error": "request body must be a JSON object of arguments"}), 400
792
- return jsonify(_tool_registry.call_tool(name, args))
893
+ started = time.monotonic()
894
+ try:
895
+ result = _tool_registry.call_tool(name, args)
896
+ except Exception:
897
+ _audit_call(name, args, started, "error")
898
+ raise
899
+ _audit_call(name, args, started,
900
+ "error" if isinstance(result, dict) and result.get("error") else "ok")
901
+ return jsonify(result)
902
+
903
+
904
+ @app.route("/api/activity/discovery", methods=["GET"])
905
+ def api_activity_discovery():
906
+ """Recent Discovery tool calls for the Activity tab (args are hashed)."""
907
+ try:
908
+ limit = max(1, min(500, int(request.args.get("limit", 100))))
909
+ except (TypeError, ValueError):
910
+ limit = 100
911
+ return jsonify({"calls": discovery_audit.read_recent(limit)})
793
912
 
794
913
 
795
914
  @app.route("/api/discovery/call/stream", methods=["POST"])
@@ -1019,6 +1138,12 @@ def run_oracle(port: int = None, open_browser: bool = None):
1019
1138
  url = f"http://localhost:{actual_port}"
1020
1139
  print(f"Oracle Memory Agent → {url} (model: {cfg.get('model', 'gemma4:31b-cloud')})")
1021
1140
 
1141
+ # Publish the bootstrap key so a same-user `c3 oracle open` can mint a
1142
+ # sign-in link. Loading the URL above shows the dashboard read-only (#31).
1143
+ local_session.write_bootstrap_key(ORACLE_DIR)
1144
+ print(f"Sign in with: c3 oracle open"
1145
+ f"{'' if actual_port == 3331 else f' --port {actual_port}'}")
1146
+
1022
1147
  # Start review agent if enabled
1023
1148
  if cfg.get("review_enabled", True) and _agent:
1024
1149
  _agent.start()
@@ -1045,7 +1170,12 @@ def run_oracle(port: int = None, open_browser: bool = None):
1045
1170
  logging.getLogger("oracle").warning("MCP server not started: %s", e)
1046
1171
 
1047
1172
  if open_browser:
1048
- threading.Timer(0.8, lambda: webbrowser.open(url)).start()
1173
+ # Auto-open lands signed in: the server mints its own code rather
1174
+ # than making the common case require a second command. This grants
1175
+ # nothing extra — the server already holds the secret, and it opens
1176
+ # the default browser as the same OS user that launched it.
1177
+ signed_in = f"{url}/?{local_session.BOOTSTRAP_PARAM}={local_session.mint_code()}"
1178
+ threading.Timer(0.8, lambda: webbrowser.open(signed_in)).start()
1049
1179
 
1050
1180
  app.run(host=cfg.get("bind_host", "127.0.0.1"), port=actual_port, debug=False, use_reloader=False)
1051
1181