code-context-control 2.76.2__tar.gz → 2.77.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 (417) hide show
  1. {code_context_control-2.76.2/code_context_control.egg-info → code_context_control-2.77.0}/PKG-INFO +1 -1
  2. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/c3.py +1 -1
  3. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hook_access_guard.py +103 -37
  4. {code_context_control-2.76.2 → code_context_control-2.77.0/code_context_control.egg-info}/PKG-INFO +1 -1
  5. {code_context_control-2.76.2 → code_context_control-2.77.0}/pyproject.toml +1 -1
  6. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_hook_access_guard.py +138 -0
  7. {code_context_control-2.76.2 → code_context_control-2.77.0}/LICENSE +0 -0
  8. {code_context_control-2.76.2 → code_context_control-2.77.0}/README.md +0 -0
  9. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/__init__.py +0 -0
  10. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/_hook_utils.py +0 -0
  11. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/commands/__init__.py +0 -0
  12. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/commands/common.py +0 -0
  13. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/commands/parser.py +0 -0
  14. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/docs.html +0 -0
  15. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/edits.html +0 -0
  16. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/guide/access.html +0 -0
  17. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/guide/bitbucket.html +0 -0
  18. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/guide/credentials.html +0 -0
  19. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/guide/getting-started.html +0 -0
  20. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/guide/index.html +0 -0
  21. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/guide/masking.html +0 -0
  22. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/guide/oracle.html +0 -0
  23. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/guide/shared.css +0 -0
  24. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/guide/tools.html +0 -0
  25. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/guide/workflow.html +0 -0
  26. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hook_artifact.py +0 -0
  27. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hook_auto_snapshot.py +0 -0
  28. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hook_c3_signal.py +0 -0
  29. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hook_c3read.py +0 -0
  30. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hook_dispatch.py +0 -0
  31. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hook_edit_ledger.py +0 -0
  32. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hook_edit_unlock.py +0 -0
  33. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hook_filter.py +0 -0
  34. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hook_ghost_files.py +0 -0
  35. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hook_pretool_enforce.py +0 -0
  36. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hook_prompt_recall.py +0 -0
  37. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hook_read.py +0 -0
  38. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hook_session_stats.py +0 -0
  39. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hook_terse_advisor.py +0 -0
  40. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_server.py +0 -0
  41. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/app.js +0 -0
  42. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/add_project.js +0 -0
  43. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/config_editor.js +0 -0
  44. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/drill_artifacts.js +0 -0
  45. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/drill_health.js +0 -0
  46. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/drill_panel.js +0 -0
  47. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/drill_subprojects.js +0 -0
  48. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/drill_tasks.js +0 -0
  49. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/drill_views.js +0 -0
  50. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/global_search.js +0 -0
  51. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/hub_credentials.js +0 -0
  52. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/hub_enforcement.js +0 -0
  53. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/hub_locks.js +0 -0
  54. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/mcp_manager.js +0 -0
  55. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/modals.js +0 -0
  56. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/project_card.js +0 -0
  57. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/project_tree.js +0 -0
  58. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/session_drawer.js +0 -0
  59. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/settings_modal.js +0 -0
  60. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/sidebar.js +0 -0
  61. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/summary_bar.js +0 -0
  62. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/task_board.js +0 -0
  63. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/toasts.js +0 -0
  64. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/components/topbar.js +0 -0
  65. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui/state.js +0 -0
  66. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/hub_ui.html +0 -0
  67. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/mcp_proxy.py +0 -0
  68. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/mcp_server.py +0 -0
  69. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/progress.py +0 -0
  70. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/server.py +0 -0
  71. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/__init__.py +0 -0
  72. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/_grants.py +0 -0
  73. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/_helpers.py +0 -0
  74. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/agent.py +0 -0
  75. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/artifacts.py +0 -0
  76. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/bitbucket.py +0 -0
  77. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/compress.py +0 -0
  78. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/credentials.py +0 -0
  79. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/delegate.py +0 -0
  80. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/edit.py +0 -0
  81. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/edit_verify.py +0 -0
  82. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/edits.py +0 -0
  83. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/federate.py +0 -0
  84. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/filter.py +0 -0
  85. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/impact.py +0 -0
  86. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/jira.py +0 -0
  87. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/locks.py +0 -0
  88. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/memory.py +0 -0
  89. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/override.py +0 -0
  90. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/project.py +0 -0
  91. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/read.py +0 -0
  92. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/search.py +0 -0
  93. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/session.py +0 -0
  94. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/shell.py +0 -0
  95. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/status.py +0 -0
  96. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/tasks.py +0 -0
  97. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/tools/validate.py +0 -0
  98. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/api.js +0 -0
  99. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/app.js +0 -0
  100. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/components/access.js +0 -0
  101. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/components/bitbucket.js +0 -0
  102. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/components/chat.js +0 -0
  103. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/components/credentials.js +0 -0
  104. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/components/dashboard.js +0 -0
  105. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/components/edits.js +0 -0
  106. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/components/enforcement.js +0 -0
  107. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/components/instructions.js +0 -0
  108. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/components/jira.js +0 -0
  109. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/components/memory.js +0 -0
  110. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/components/sessions.js +0 -0
  111. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/components/settings.js +0 -0
  112. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/components/sidebar.js +0 -0
  113. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/components/tasks.js +0 -0
  114. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/icons.js +0 -0
  115. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/pm_shared.js +0 -0
  116. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/shared.js +0 -0
  117. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui/theme.js +0 -0
  118. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui.html +0 -0
  119. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui_legacy.html +0 -0
  120. {code_context_control-2.76.2 → code_context_control-2.77.0}/cli/ui_nano.html +0 -0
  121. {code_context_control-2.76.2 → code_context_control-2.77.0}/code_context_control.egg-info/SOURCES.txt +0 -0
  122. {code_context_control-2.76.2 → code_context_control-2.77.0}/code_context_control.egg-info/dependency_links.txt +0 -0
  123. {code_context_control-2.76.2 → code_context_control-2.77.0}/code_context_control.egg-info/entry_points.txt +0 -0
  124. {code_context_control-2.76.2 → code_context_control-2.77.0}/code_context_control.egg-info/requires.txt +0 -0
  125. {code_context_control-2.76.2 → code_context_control-2.77.0}/code_context_control.egg-info/top_level.txt +0 -0
  126. {code_context_control-2.76.2 → code_context_control-2.77.0}/core/__init__.py +0 -0
  127. {code_context_control-2.76.2 → code_context_control-2.77.0}/core/config.py +0 -0
  128. {code_context_control-2.76.2 → code_context_control-2.77.0}/core/ide.py +0 -0
  129. {code_context_control-2.76.2 → code_context_control-2.77.0}/core/mcp_toml.py +0 -0
  130. {code_context_control-2.76.2 → code_context_control-2.77.0}/core/web_security.py +0 -0
  131. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/__init__.py +0 -0
  132. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/config.py +0 -0
  133. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/mcp_oracle.py +0 -0
  134. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/oracle_server.py +0 -0
  135. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/oracle_ui.html +0 -0
  136. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/__init__.py +0 -0
  137. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/activity_reporter.py +0 -0
  138. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/api_auth.py +0 -0
  139. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/c3_bridge.py +0 -0
  140. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/chat_engine.py +0 -0
  141. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/chat_poll.py +0 -0
  142. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/chat_store.py +0 -0
  143. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/cross_memory.py +0 -0
  144. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/discovery_audit.py +0 -0
  145. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/federated_graph.py +0 -0
  146. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/health_checker.py +0 -0
  147. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/insight_engine.py +0 -0
  148. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/local_session.py +0 -0
  149. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/memory_reader.py +0 -0
  150. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/memory_writer.py +0 -0
  151. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/mobile_api.py +0 -0
  152. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/project_scanner.py +0 -0
  153. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/review_agent.py +0 -0
  154. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/tool_executor.py +0 -0
  155. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/services/tool_registry.py +0 -0
  156. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/activity.js +0 -0
  157. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/agents.js +0 -0
  158. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/app.js +0 -0
  159. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/busy.js +0 -0
  160. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/chat/conversations.js +0 -0
  161. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/chat/input.js +0 -0
  162. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/chat/markdown.js +0 -0
  163. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/chat/send.js +0 -0
  164. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/chat/stream_renderer.js +0 -0
  165. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/chat/toolbar.js +0 -0
  166. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/core.js +0 -0
  167. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/crossgraph.js +0 -0
  168. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/header.js +0 -0
  169. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/insights.js +0 -0
  170. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/projects.js +0 -0
  171. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/qrcode.js +0 -0
  172. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/settings.js +0 -0
  173. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/suggestions.js +0 -0
  174. {code_context_control-2.76.2 → code_context_control-2.77.0}/oracle/ui/theme_tabs.js +0 -0
  175. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/__init__.py +0 -0
  176. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/access_guard.py +0 -0
  177. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/access_telemetry.py +0 -0
  178. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/activity_log.py +0 -0
  179. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/agent_base.py +0 -0
  180. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/agent_locks.py +0 -0
  181. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/agents.py +0 -0
  182. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/artifact_defs.py +0 -0
  183. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/artifact_store.py +0 -0
  184. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/auto_memory.py +0 -0
  185. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/bench/__init__.py +0 -0
  186. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/bench/external/__init__.py +0 -0
  187. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/bench/external/aider_polyglot.py +0 -0
  188. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/bench/external/swe_bench.py +0 -0
  189. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/benchmark_dashboard.py +0 -0
  190. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/bitbucket_client.py +0 -0
  191. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/bitbucket_credentials.py +0 -0
  192. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/circuit_breaker.py +0 -0
  193. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/claude_md.py +0 -0
  194. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/compressor.py +0 -0
  195. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/context_snapshot.py +0 -0
  196. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/conversation_store.py +0 -0
  197. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/credential_store.py +0 -0
  198. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/doc_index.py +0 -0
  199. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/e2e_benchmark.py +0 -0
  200. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/e2e_evaluator.py +0 -0
  201. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/e2e_tasks.py +0 -0
  202. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/edit_ledger.py +0 -0
  203. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/embedding_index.py +0 -0
  204. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/enforcement_policy.py +0 -0
  205. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/error_reporting.py +0 -0
  206. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/file_memory.py +0 -0
  207. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/git_context.py +0 -0
  208. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/hub_service.py +0 -0
  209. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/indexer.py +0 -0
  210. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/jira_client.py +0 -0
  211. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/jira_cloud.py +0 -0
  212. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/jira_credentials.py +0 -0
  213. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/jira_data_center.py +0 -0
  214. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/jira_links.py +0 -0
  215. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/mask_activation.py +0 -0
  216. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/mask_mirror.py +0 -0
  217. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/mask_presets.py +0 -0
  218. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/memory.py +0 -0
  219. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/memory_consolidator.py +0 -0
  220. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/memory_distiller.py +0 -0
  221. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/memory_graph.py +0 -0
  222. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/memory_grounder.py +0 -0
  223. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/memory_queue.py +0 -0
  224. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/memory_scorer.py +0 -0
  225. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/metrics.py +0 -0
  226. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/notifications.py +0 -0
  227. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/ollama_bridge.py +0 -0
  228. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/ollama_client.py +0 -0
  229. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/ollama_credentials.py +0 -0
  230. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/output_filter.py +0 -0
  231. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/override_grants.py +0 -0
  232. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/override_policy.py +0 -0
  233. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/override_requests.py +0 -0
  234. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/override_wake.py +0 -0
  235. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/parser.py +0 -0
  236. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/project_manager.py +0 -0
  237. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/project_runtime.py +0 -0
  238. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/protocol.py +0 -0
  239. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/proxy_state.py +0 -0
  240. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/repo_map.py +0 -0
  241. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/retention.py +0 -0
  242. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/retrieval_broker.py +0 -0
  243. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/router.py +0 -0
  244. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/runtime.py +0 -0
  245. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/scanner.py +0 -0
  246. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/session_benchmark.py +0 -0
  247. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/session_manager.py +0 -0
  248. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/session_preloader.py +0 -0
  249. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/subprojects.py +0 -0
  250. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/task_store.py +0 -0
  251. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/telemetry.py +0 -0
  252. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/text_index.py +0 -0
  253. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/time_tracker.py +0 -0
  254. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/tool_classifier.py +0 -0
  255. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/transcript_index.py +0 -0
  256. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/validation_cache.py +0 -0
  257. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/vector_store.py +0 -0
  258. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/watcher.py +0 -0
  259. {code_context_control-2.76.2 → code_context_control-2.77.0}/services/win_subprocess.py +0 -0
  260. {code_context_control-2.76.2 → code_context_control-2.77.0}/setup.cfg +0 -0
  261. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_access_builtin_optout.py +0 -0
  262. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_access_guard.py +0 -0
  263. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_access_guard_meta.py +0 -0
  264. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_access_guard_shell_project.py +0 -0
  265. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_access_guard_surfaces.py +0 -0
  266. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_access_guard_wiring.py +0 -0
  267. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_activity_reporter.py +0 -0
  268. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_agent_locks.py +0 -0
  269. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_aider_polyglot.py +0 -0
  270. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_antigravity_transition.py +0 -0
  271. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_artifact_store.py +0 -0
  272. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_artifact_tool.py +0 -0
  273. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_bitbucket_cli_smoke.py +0 -0
  274. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_bitbucket_client.py +0 -0
  275. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_bitbucket_config_fallback.py +0 -0
  276. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_bitbucket_credentials.py +0 -0
  277. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_bitbucket_tool.py +0 -0
  278. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_c3_bridge_project_artifacts.py +0 -0
  279. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_c3_shell.py +0 -0
  280. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_chat_poll.py +0 -0
  281. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_circuit_breaker.py +0 -0
  282. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_claude_md_merge.py +0 -0
  283. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_cli_smoke.py +0 -0
  284. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_compressor_large_file.py +0 -0
  285. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_credential_store.py +0 -0
  286. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_credentials_routes.py +0 -0
  287. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_credentials_tool.py +0 -0
  288. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_creds_cli_smoke.py +0 -0
  289. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_delegate_cascade.py +0 -0
  290. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_delegate_version_probe.py +0 -0
  291. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_e2e_benchmark.py +0 -0
  292. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_edit_ledger_deadline.py +0 -0
  293. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_edit_ledger_hook.py +0 -0
  294. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_edit_locking.py +0 -0
  295. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_edit_normalization.py +0 -0
  296. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_edit_verify.py +0 -0
  297. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_embedding_index_deadlock.py +0 -0
  298. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_enforcement_flip.py +0 -0
  299. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_enforcement_policy.py +0 -0
  300. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_enforcement_routes.py +0 -0
  301. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_federated_graph.py +0 -0
  302. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_filter_backoff.py +0 -0
  303. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_ghost_files.py +0 -0
  304. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_ghost_generation.py +0 -0
  305. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_git_branch_awareness.py +0 -0
  306. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_hook_dispatch.py +0 -0
  307. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_hook_pretool_enforce.py +0 -0
  308. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_hook_prompt_recall.py +0 -0
  309. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_hook_smoke.py +0 -0
  310. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_hook_state.py +0 -0
  311. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_hook_utf8_stdio.py +0 -0
  312. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_hub_credentials_route.py +0 -0
  313. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_hub_credentials_routes_write.py +0 -0
  314. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_hub_enforcement_routes.py +0 -0
  315. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_hub_inspect_api.py +0 -0
  316. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_hub_locks_routes.py +0 -0
  317. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_hub_server_smoke.py +0 -0
  318. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_hub_subproject_links.py +0 -0
  319. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_ide_workflow_adaptation.py +0 -0
  320. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_init_scan.py +0 -0
  321. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_install_mcp_entrypoint.py +0 -0
  322. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_jira_cli_smoke.py +0 -0
  323. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_jira_client.py +0 -0
  324. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_jira_config_fallback.py +0 -0
  325. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_jira_credentials.py +0 -0
  326. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_jira_links.py +0 -0
  327. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_jira_routes.py +0 -0
  328. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_jira_tool.py +0 -0
  329. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_lazy_store_init.py +0 -0
  330. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_mask_guard.py +0 -0
  331. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_mask_routes.py +0 -0
  332. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_mask_surfaces.py +0 -0
  333. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_mcp_host_guard.py +0 -0
  334. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_mcp_memory_timeout.py +0 -0
  335. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_mcp_server_smoke.py +0 -0
  336. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_mcp_toml.py +0 -0
  337. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_memory_distiller.py +0 -0
  338. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_memory_graph_api.py +0 -0
  339. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_memory_queue.py +0 -0
  340. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_memory_system.py +0 -0
  341. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_mobile_api.py +0 -0
  342. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_mobile_extras.py +0 -0
  343. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_mobile_override_routes.py +0 -0
  344. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_mobile_security_api.py +0 -0
  345. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_no_stale_model_pins.py +0 -0
  346. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_notification_dedup.py +0 -0
  347. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_notification_discipline.py +0 -0
  348. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_ollama_credentials.py +0 -0
  349. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_oracle_api_auth.py +0 -0
  350. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_oracle_apikey_api.py +0 -0
  351. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_oracle_c3_bridge.py +0 -0
  352. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_oracle_chat_engine.py +0 -0
  353. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_oracle_chat_store.py +0 -0
  354. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_oracle_discovery_api.py +0 -0
  355. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_oracle_discovery_audit.py +0 -0
  356. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_oracle_local_auth.py +0 -0
  357. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_oracle_ollama_bridge.py +0 -0
  358. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_oracle_scanner_cache.py +0 -0
  359. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_oracle_security_fixes.py +0 -0
  360. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_oracle_session_bootstrap.py +0 -0
  361. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_oracle_subproject_awareness.py +0 -0
  362. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_oracle_ui_bundle.py +0 -0
  363. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_output_filter.py +0 -0
  364. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_override_grants.py +0 -0
  365. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_override_grants_mcp.py +0 -0
  366. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_override_requests.py +0 -0
  367. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_override_wake.py +0 -0
  368. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_permissions.py +0 -0
  369. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_pm_api.py +0 -0
  370. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_project_manager.py +0 -0
  371. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_project_manager_merge.py +0 -0
  372. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_project_tool.py +0 -0
  373. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_read_coercion.py +0 -0
  374. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_read_edit_parity.py +0 -0
  375. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_related_facts.py +0 -0
  376. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_repo_map.py +0 -0
  377. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_response_boilerplate.py +0 -0
  378. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_retention.py +0 -0
  379. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_review_digest.py +0 -0
  380. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_service_durability.py +0 -0
  381. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_session_benchmark.py +0 -0
  382. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_session_budget.py +0 -0
  383. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_shell_creds.py +0 -0
  384. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_shell_robustness.py +0 -0
  385. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_subproject_exclusion.py +0 -0
  386. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_subproject_federation.py +0 -0
  387. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_subprojects.py +0 -0
  388. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_swe_bench.py +0 -0
  389. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_task_store.py +0 -0
  390. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_task_tool.py +0 -0
  391. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_time_tracker.py +0 -0
  392. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_token_telemetry.py +0 -0
  393. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_tool_registry.py +0 -0
  394. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_upgrade_and_version.py +0 -0
  395. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_validate.py +0 -0
  396. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_vault_write_guard.py +0 -0
  397. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_version_sync.py +0 -0
  398. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_web_security.py +0 -0
  399. {code_context_control-2.76.2 → code_context_control-2.77.0}/tests/test_windows_reliability.py +0 -0
  400. {code_context_control-2.76.2 → code_context_control-2.77.0}/tui/__init__.py +0 -0
  401. {code_context_control-2.76.2 → code_context_control-2.77.0}/tui/backend.py +0 -0
  402. {code_context_control-2.76.2 → code_context_control-2.77.0}/tui/main.py +0 -0
  403. {code_context_control-2.76.2 → code_context_control-2.77.0}/tui/screens/__init__.py +0 -0
  404. {code_context_control-2.76.2 → code_context_control-2.77.0}/tui/screens/benchmark_view.py +0 -0
  405. {code_context_control-2.76.2 → code_context_control-2.77.0}/tui/screens/claudemd_view.py +0 -0
  406. {code_context_control-2.76.2 → code_context_control-2.77.0}/tui/screens/compress_view.py +0 -0
  407. {code_context_control-2.76.2 → code_context_control-2.77.0}/tui/screens/index_view.py +0 -0
  408. {code_context_control-2.76.2 → code_context_control-2.77.0}/tui/screens/init_view.py +0 -0
  409. {code_context_control-2.76.2 → code_context_control-2.77.0}/tui/screens/mcp_view.py +0 -0
  410. {code_context_control-2.76.2 → code_context_control-2.77.0}/tui/screens/optimize_view.py +0 -0
  411. {code_context_control-2.76.2 → code_context_control-2.77.0}/tui/screens/pipe_view.py +0 -0
  412. {code_context_control-2.76.2 → code_context_control-2.77.0}/tui/screens/projects_view.py +0 -0
  413. {code_context_control-2.76.2 → code_context_control-2.77.0}/tui/screens/search_view.py +0 -0
  414. {code_context_control-2.76.2 → code_context_control-2.77.0}/tui/screens/session_view.py +0 -0
  415. {code_context_control-2.76.2 → code_context_control-2.77.0}/tui/screens/stats.py +0 -0
  416. {code_context_control-2.76.2 → code_context_control-2.77.0}/tui/screens/ui_view.py +0 -0
  417. {code_context_control-2.76.2 → code_context_control-2.77.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.76.2
3
+ Version: 2.77.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.76.2"
95
+ __version__ = "2.77.0"
96
96
 
97
97
 
98
98
  def _compress_file_cli(compressor, path, mode="smart", **kw):
@@ -10,6 +10,7 @@ Bash coverage is a best-effort, existence-gated token scan — advisory by
10
10
  design (docs/access-guard.md §3/§6); it catches an agent naming a denied
11
11
  path, not an adversary hiding one.
12
12
  """
13
+ import os
13
14
  import re
14
15
  import sys
15
16
  from pathlib import Path
@@ -84,6 +85,23 @@ _DOUBLE_COLON_RE = re.compile(r"::(?!\$)")
84
85
  _GIT_REVSPEC_RE = re.compile(r"^(?P<rev>[^:\s]+):(?P<path>[^:\s]+)$")
85
86
  _GIT_CMD_RE = re.compile(r"^\s*(?:[\w.\-]*[/\\])?git(?:\.exe)?\b", re.IGNORECASE)
86
87
 
88
+ # Where one command ends and the next begins. Anchoring "is this git?" to the
89
+ # start of the whole string was wrong in the most ordinary way possible:
90
+ # `cd /repo && git show origin/main:pyproject.toml` starts with `cd`, so the
91
+ # revspec rewrite never fired for the shape people actually type. Caught by a
92
+ # live probe after release, not by the unit tests — which passed the command as
93
+ # `git show …` because that is how the test author writes it, not how a shell
94
+ # call arrives.
95
+ _SEGMENT_SPLIT = re.compile(r"&&|\|\||[;|\n]")
96
+
97
+ # `cd <dir>` — the segment that moves the ground under every later one. Handles
98
+ # a quoted target, since project paths on this platform contain spaces, and the
99
+ # Windows `/d` flag.
100
+ _CD_RE = re.compile(
101
+ r"""^\s*cd\s+(?:/d\s+)?(?P<dir>"[^"]+"|'[^']+'|\S+)\s*$""",
102
+ re.IGNORECASE,
103
+ )
104
+
87
105
 
88
106
  def _is_network_token(tok: str) -> bool:
89
107
  """True for URLs and IPv6 literals/CIDRs — never for an ADS spelling."""
@@ -190,6 +208,20 @@ def _target(tool_input: dict) -> str:
190
208
  )
191
209
 
192
210
 
211
+ def _cd_target(segment: str, cwd: str) -> str | None:
212
+ """The directory a `cd` segment moves to, resolved against ``cwd``."""
213
+ m = _CD_RE.match(segment or "")
214
+ if not m:
215
+ return None
216
+ target = m.group("dir").strip("\"'")
217
+ if not target or target.startswith("-"):
218
+ return None
219
+ try:
220
+ return os.path.abspath(os.path.join(cwd, os.path.expanduser(target)))
221
+ except (OSError, ValueError):
222
+ return None
223
+
224
+
193
225
  def _scan_shell(cmd: str, base: str):
194
226
  """(denial, token) for the first confident deny-rule hit, else (None, '').
195
227
 
@@ -201,44 +233,78 @@ def _scan_shell(cmd: str, base: str):
201
233
  outright, as are URLs and IPv6 literals: all of them trip the ADS spelling
202
234
  check, which is exempt from existence-gating, so a token naming nothing on
203
235
  disk would otherwise hard-deny (#50).
236
+
237
+ Scanning is per **command segment**, not per whole string. A segment is what
238
+ sits between `&&`, `||`, `;`, `|` or a newline, and each one answers "am I a
239
+ git command?" for itself — so the revspec rewrite applies to the tokens of
240
+ the git segment and to no others. `cat notes.txt:hidden && git status` must
241
+ not have its first token reinterpreted just because a later segment is git.
204
242
  """
205
- for raw in _TOKEN_SPLIT.split(cmd)[:_MAX_TOKENS]:
206
- tok = raw.strip("\"'`;,()")
207
- if not tok or tok.startswith("-"):
208
- continue
209
- if "/" not in tok and "\\" not in tok and not tok.startswith("."):
210
- continue
211
- # Order matters only for readability: a URL is also syntax-free, so
212
- # either check alone would skip 'https://x'. Both are kept because they
213
- # answer different questions — "is this a network literal" and "is this
214
- # a path at all" — and the second is the one that generalizes.
215
- if not _looks_like_a_path(tok) or _is_network_token(tok):
216
- continue
217
- # `tests/x.py::TestThing` is a node id, not a stream spelling.
218
- if _is_scope_token(tok):
219
- continue
220
- # `git show <rev>:<path>` — judge the PATH, not the whole token. This
221
- # is the one place the scan rewrites what it checks rather than skipping
222
- # it, because skipping would let `git show HEAD:.env` through.
223
- revspec_path = _git_revspec_path(cmd, tok)
224
- from_revspec = revspec_path is not None
225
- if from_revspec:
226
- tok = revspec_path
227
- if re.match(r"^/[a-z]/", tok): # MSYS /c/foo → C:/foo
228
- tok = f"{tok[1]}:{tok[2:]}"
229
- denial = ag.check(tok, "read", base)
230
- if denial and denial.kind == "deny":
231
- try:
232
- p = Path(tok)
233
- exists = (p if p.is_absolute() else Path(base) / p).exists()
234
- except OSError:
235
- exists = False
236
- # A revspec names a path in HISTORY, so the working tree is the
237
- # wrong place to ask whether it is real. `git show HEAD~5:.env`
238
- # reads a denied file whether or not that file exists today, and
239
- # existence-gating it would be a hole this rewrite opened.
240
- if exists or from_revspec or denial.rule.startswith("<"):
241
- return denial, tok
243
+ budget = _MAX_TOKENS
244
+ cwd = base
245
+ for segment in _SEGMENT_SPLIT.split(cmd or ""):
246
+ if budget <= 0:
247
+ break
248
+ is_git = bool(_GIT_CMD_RE.match(segment))
249
+ for raw in _TOKEN_SPLIT.split(segment)[:budget]:
250
+ budget -= 1
251
+ tok = raw.strip("\"'`;,()")
252
+ if not tok or tok.startswith("-"):
253
+ continue
254
+ # A revspec's path half need not contain a separator — `HEAD:.env`
255
+ # has none, so it used to be dropped here before any rule saw it.
256
+ if ("/" not in tok and "\\" not in tok and not tok.startswith(".")
257
+ and not (is_git and _GIT_REVSPEC_RE.match(tok))):
258
+ continue
259
+ # Order matters only for readability: a URL is also syntax-free, so
260
+ # either check alone would skip 'https://x'. Both are kept because
261
+ # they answer different questions — "is this a network literal" and
262
+ # "is this a path at all" — and the second is the one that
263
+ # generalizes.
264
+ if not _looks_like_a_path(tok) or _is_network_token(tok):
265
+ continue
266
+ # `tests/x.py::TestThing` is a node id, not a stream spelling.
267
+ if _is_scope_token(tok):
268
+ continue
269
+ # `git show <rev>:<path>` — judge the PATH, not the whole token.
270
+ # This is the one place the scan rewrites what it checks rather than
271
+ # skipping it, because skipping would let `git show HEAD:.env`
272
+ # through.
273
+ revspec_path = _git_revspec_path(segment, tok) if is_git else None
274
+ from_revspec = revspec_path is not None
275
+ if from_revspec:
276
+ tok = revspec_path
277
+ if re.match(r"^/[a-z]/", tok): # MSYS /c/foo C:/foo
278
+ tok = f"{tok[1]}:{tok[2:]}"
279
+ # Resolve against the cwd the command will actually run in, not the
280
+ # session root. `cd /elsewhere && cat .env` used to compute the
281
+ # denial correctly and then throw it away, because the existence
282
+ # gate looked for `.env` under the project root where it does not
283
+ # live (#82). The rule base stays `base` — policy is the project's;
284
+ # only the path being judged follows the shell.
285
+ probe = tok
286
+ if not os.path.isabs(probe):
287
+ try:
288
+ probe = os.path.join(cwd, probe)
289
+ except (OSError, ValueError):
290
+ probe = tok
291
+ denial = ag.check(probe, "read", base)
292
+ if denial and denial.kind == "deny":
293
+ try:
294
+ exists = Path(probe).exists()
295
+ except OSError:
296
+ exists = False
297
+ # A revspec names a path in HISTORY, so the working tree is the
298
+ # wrong place to ask whether it is real. `git show HEAD~5:.env`
299
+ # reads a denied file whether or not that file exists today, and
300
+ # existence-gating it would be a hole this rewrite opened.
301
+ if exists or from_revspec or denial.rule.startswith("<"):
302
+ return denial, tok
303
+ # AFTER the segment's own tokens: `cd x` moves the ground for what
304
+ # follows, not for its own argument.
305
+ moved = _cd_target(segment, cwd)
306
+ if moved is not None:
307
+ cwd = moved
242
308
  return None, ""
243
309
 
244
310
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-context-control
3
- Version: 2.76.2
3
+ Version: 2.77.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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "code-context-control"
7
- version = "2.76.2"
7
+ version = "2.77.0"
8
8
  description = "Local MCP code-intelligence for AI coding tools: surgical search/read/edit, agent-config version history, path-level access + masking guards, and a multi-project hub."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -323,6 +323,144 @@ class TestShellScanSyntaxTokens(HookGuardBase):
323
323
  self.assertIsNotNone(denial)
324
324
  self.assertEqual(tok, "secrets/gone.txt")
325
325
 
326
+ def test_a_git_command_is_recognised_after_a_shell_separator(self):
327
+ """`cd /repo && git show <rev>:<path>` — the shape people actually type.
328
+
329
+ The first cut anchored "is this git?" to the start of the whole command
330
+ string, so a leading `cd` disabled the rewrite entirely. Every unit test
331
+ passed, because a test author writes the command as `git show …`. A live
332
+ probe after release is what caught it.
333
+ """
334
+ for cmd in (
335
+ "cd /tmp/repo && git show origin/main:pyproject.toml",
336
+ "git fetch -q; git show origin/main:pyproject.toml",
337
+ "cd x || git show HEAD:setup.py",
338
+ ):
339
+ with self.subTest(cmd=cmd):
340
+ denial, tok = hag._scan_shell(cmd, str(self.proj))
341
+ self.assertIsNone(denial, f"{cmd!r} denied on {tok!r}")
342
+
343
+ def test_a_denied_revspec_is_still_caught_after_a_separator(self):
344
+ denial, tok = hag._scan_shell(
345
+ f'cd "{self.proj}" && git show HEAD:secrets/key.txt', str(self.proj))
346
+ self.assertIsNotNone(denial)
347
+ self.assertEqual(tok, "secrets/key.txt")
348
+
349
+ def test_a_revspec_path_without_a_separator_now_reaches_the_rules(self):
350
+ """`HEAD:.env` — no slash, so the token gate used to drop it (#82).
351
+
352
+ It also never reached the ADS check, which is the claim #81's body got
353
+ wrong. It reaches the rules now, and the revspec bypass of the existence
354
+ gate is what makes the verdict right: a blob in history is denied
355
+ whether or not that file is in the working tree today.
356
+ """
357
+ denial, tok = hag._scan_shell(
358
+ "git show HEAD:.env", str(self.proj))
359
+ self.assertIsNotNone(denial)
360
+ self.assertEqual(tok, ".env")
361
+
362
+
363
+ class TestShellScanFollowsCd(HookGuardBase):
364
+ """#82 — the scan judged paths against the session root, not the cwd.
365
+
366
+ `cd <elsewhere> && cat .env` computed the denial correctly and then threw it
367
+ away, because the existence gate looked for `.env` under the project root
368
+ where it does not live. The rule was never wrong; the question was asked
369
+ about the wrong directory.
370
+ """
371
+
372
+ def test_a_denied_file_read_after_cd_is_caught(self):
373
+ """The reported case, reproduced with the rule that made it reachable.
374
+
375
+ Session rooted in one directory, command `cd`-ing to another, and a
376
+ builtin `**/.env*` deny — builtin because it binds on any path, which is
377
+ why the live failure was a secret file rather than a project-scoped one.
378
+ Before this fix the denial was computed and then discarded, because the
379
+ existence gate looked under the session root.
380
+ """
381
+ (self.proj / ".env").write_text("SECRET=x", encoding="utf-8")
382
+ denial, _ = hag._scan_shell(
383
+ f'cd "{self.proj}" && cat .env', str(self.proj.parent))
384
+ self.assertIsNotNone(denial)
385
+ self.assertEqual(denial.rule, "**/.env*")
386
+
387
+ def test_cd_out_then_relative_back_in_is_caught(self):
388
+ denial, _ = hag._scan_shell(
389
+ f'cd "{self.proj.parent}" && cat {self.proj.name}/secrets/key.txt',
390
+ str(self.proj))
391
+ self.assertIsNotNone(denial)
392
+
393
+ def test_cd_out_then_absolute_back_in_is_caught(self):
394
+ denial, _ = hag._scan_shell(
395
+ f'cd "{self.proj.parent}" && cat "{self.proj / "secrets/key.txt"}"',
396
+ str(self.proj))
397
+ self.assertIsNotNone(denial)
398
+
399
+ def test_the_existence_gate_still_applies_at_the_new_cwd(self):
400
+ """Following the shell must not mean flagging files that are not there.
401
+
402
+ A `cd` into a directory without the file leaves nothing to read, and a
403
+ deny on nothing is the false positive this scanner keeps being fixed for.
404
+ """
405
+ denial, _ = hag._scan_shell(
406
+ f'cd "{self.proj.parent}" && cat secrets/key.txt', str(self.proj))
407
+ self.assertIsNone(denial)
408
+
409
+ def test_cd_moves_only_the_segments_after_it(self):
410
+ """`cat secrets/key.txt && cd /elsewhere` reads before it moves."""
411
+ denial, _ = hag._scan_shell(
412
+ "cat secrets/key.txt && cd /tmp", str(self.proj))
413
+ self.assertIsNotNone(denial)
414
+
415
+ def test_a_quoted_cd_target_with_spaces_is_parsed(self):
416
+ spaced = self.proj / "a dir"
417
+ spaced.mkdir()
418
+ denial, _ = hag._scan_shell(
419
+ f'cd "{spaced}" && cat ../secrets/key.txt', str(self.proj))
420
+ self.assertIsNotNone(denial)
421
+
422
+ def test_the_cd_target_itself_is_still_scanned(self):
423
+ """`cd` into a denied directory is itself a token worth refusing."""
424
+ denial, tok = hag._scan_shell(
425
+ f'cd "{self.proj / "secrets"}"', str(self.proj))
426
+ self.assertIsNotNone(denial)
427
+
428
+ def test_a_bare_filename_is_still_out_of_scope(self):
429
+ """Stated rather than implied: the token gate is unchanged.
430
+
431
+ `cd <denied dir> && type key.txt` is caught only incidentally, by the
432
+ `cd` argument. A separator-free filename still never reaches the rules,
433
+ which is a known limit of the token gate and not what #82 was about.
434
+ """
435
+ self.assertIsNone(hag._cd_target("type key.txt", str(self.proj)))
436
+ denial, tok = hag._scan_shell(
437
+ f'cd "{self.proj / "secrets"}" && type key.txt', str(self.proj))
438
+ self.assertIsNotNone(denial)
439
+ self.assertNotIn("key.txt", tok)
440
+
441
+ def test_a_git_segment_does_not_license_rewrites_in_other_segments(self):
442
+ """Per-segment, not per-string: `cat a:b && git status` is two commands.
443
+
444
+ Attributing the whole string to git would let a non-git token be
445
+ reinterpreted — the scan would check `hidden` instead of the real
446
+ spelling, which is a hole rather than a false positive.
447
+ """
448
+ self.assertIsNone(
449
+ hag._git_revspec_path("cat ./notes.txt:hidden", "./notes.txt:hidden"))
450
+
451
+ @unittest.skipUnless(WIN, "NTFS ADS semantics")
452
+ def test_a_non_git_segment_beside_a_git_one_still_denies(self):
453
+ """The end-to-end half of the above, and Windows-only for a reason.
454
+
455
+ `<ads>` is an NTFS spelling rule, so on POSIX this command denies
456
+ nothing and the assertion would be about the platform rather than the
457
+ code. Shipping it undecorated turned six of nine CI jobs red — the
458
+ matrix caught in a minute what a Windows-only local run could not.
459
+ """
460
+ denial, _ = hag._scan_shell(
461
+ "cat ./secrets/key.txt:hidden && git status", str(self.proj))
462
+ self.assertIsNotNone(denial)
463
+
326
464
  def test_revspec_rewriting_only_applies_to_git(self):
327
465
  """`<word>:<word>` means something else in every other command."""
328
466
  path = hag._git_revspec_path("cat HEAD:secrets/key.txt", "HEAD:secrets/key.txt")