code-context-control 2.125.0__tar.gz → 2.126.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (523) hide show
  1. {code_context_control-2.125.0/code_context_control.egg-info → code_context_control-2.126.1}/PKG-INFO +1 -1
  2. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/_hook_utils.py +34 -0
  3. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/c3.py +23 -1
  4. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_dispatch.py +12 -3
  5. code_context_control-2.126.1/cli/hook_session_end.py +103 -0
  6. code_context_control-2.126.1/cli/hook_session_open.py +97 -0
  7. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/mcp_server.py +114 -1
  8. {code_context_control-2.125.0 → code_context_control-2.126.1/code_context_control.egg-info}/PKG-INFO +1 -1
  9. {code_context_control-2.125.0 → code_context_control-2.126.1}/code_context_control.egg-info/SOURCES.txt +6 -0
  10. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/mobile_api.py +159 -3
  11. {code_context_control-2.125.0 → code_context_control-2.126.1}/pyproject.toml +1 -1
  12. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ci_runner.py +32 -0
  13. code_context_control-2.126.1/services/host_sessions.py +95 -0
  14. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/notifications.py +31 -0
  15. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/shell_jobs.py +93 -1
  16. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hook_codex_compat.py +11 -0
  17. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hook_dispatch.py +9 -0
  18. code_context_control-2.126.1/tests/test_hook_session_end.py +291 -0
  19. code_context_control-2.126.1/tests/test_mobile_jobs_ci.py +327 -0
  20. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mobile_override_routes.py +35 -0
  21. code_context_control-2.126.1/tests/test_notification_kinds.py +294 -0
  22. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_jobs_s3.py +4 -1
  23. {code_context_control-2.125.0 → code_context_control-2.126.1}/LICENSE +0 -0
  24. {code_context_control-2.125.0 → code_context_control-2.126.1}/README.md +0 -0
  25. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/__init__.py +0 -0
  26. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/_shell_writes.py +0 -0
  27. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/commands/__init__.py +0 -0
  28. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/commands/common.py +0 -0
  29. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/commands/parser.py +0 -0
  30. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/docs.html +0 -0
  31. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/edits.html +0 -0
  32. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/access.html +0 -0
  33. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/bitbucket.html +0 -0
  34. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/credentials.html +0 -0
  35. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/getting-started.html +0 -0
  36. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/index.html +0 -0
  37. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/masking.html +0 -0
  38. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/oracle.html +0 -0
  39. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/shared.css +0 -0
  40. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/tools.html +0 -0
  41. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/guide/workflow.html +0 -0
  42. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_access_guard.py +0 -0
  43. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_artifact.py +0 -0
  44. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_auto_snapshot.py +0 -0
  45. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_c3_signal.py +0 -0
  46. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_c3read.py +0 -0
  47. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_codex_lifecycle.py +0 -0
  48. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_edit_ledger.py +0 -0
  49. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_edit_unlock.py +0 -0
  50. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_filter.py +0 -0
  51. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_ghost_files.py +0 -0
  52. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_pretool_enforce.py +0 -0
  53. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_prompt_recall.py +0 -0
  54. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_read.py +0 -0
  55. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_session_stats.py +0 -0
  56. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hook_terse_advisor.py +0 -0
  57. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_server.py +0 -0
  58. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/app.js +0 -0
  59. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/add_project.js +0 -0
  60. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/config_editor.js +0 -0
  61. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/drill_artifacts.js +0 -0
  62. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/drill_health.js +0 -0
  63. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/drill_panel.js +0 -0
  64. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/drill_subprojects.js +0 -0
  65. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/drill_tasks.js +0 -0
  66. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/drill_views.js +0 -0
  67. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/global_search.js +0 -0
  68. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/hub_access.js +0 -0
  69. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/hub_ci.js +0 -0
  70. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/hub_cred_audit.js +0 -0
  71. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/hub_credentials.js +0 -0
  72. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/hub_enforcement.js +0 -0
  73. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/hub_locks.js +0 -0
  74. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/hub_tokens.js +0 -0
  75. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/mcp_manager.js +0 -0
  76. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/modals.js +0 -0
  77. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/project_card.js +0 -0
  78. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/project_tree.js +0 -0
  79. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/session_drawer.js +0 -0
  80. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/settings_modal.js +0 -0
  81. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/sidebar.js +0 -0
  82. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/summary_bar.js +0 -0
  83. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/task_board.js +0 -0
  84. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/toasts.js +0 -0
  85. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/components/topbar.js +0 -0
  86. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui/state.js +0 -0
  87. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/hub_ui.html +0 -0
  88. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/mcp_proxy.py +0 -0
  89. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/progress.py +0 -0
  90. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/server.py +0 -0
  91. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/__init__.py +0 -0
  92. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/_grants.py +0 -0
  93. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/_helpers.py +0 -0
  94. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/agent.py +0 -0
  95. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/artifacts.py +0 -0
  96. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/bitbucket.py +0 -0
  97. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/ci.py +0 -0
  98. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/compress.py +0 -0
  99. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/credentials.py +0 -0
  100. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/delegate.py +0 -0
  101. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/edit.py +0 -0
  102. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/edit_verify.py +0 -0
  103. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/edits.py +0 -0
  104. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/federate.py +0 -0
  105. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/filter.py +0 -0
  106. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/impact.py +0 -0
  107. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/jira.py +0 -0
  108. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/locks.py +0 -0
  109. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/memory.py +0 -0
  110. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/override.py +0 -0
  111. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/project.py +0 -0
  112. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/read.py +0 -0
  113. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/search.py +0 -0
  114. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/session.py +0 -0
  115. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/shell.py +0 -0
  116. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/shell_job.py +0 -0
  117. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/shell_nudge.py +0 -0
  118. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/shell_parsers.py +0 -0
  119. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/shell_render.py +0 -0
  120. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/status.py +0 -0
  121. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/tasks.py +0 -0
  122. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/tools/validate.py +0 -0
  123. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/api.js +0 -0
  124. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/app.js +0 -0
  125. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/access.js +0 -0
  126. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/bitbucket.js +0 -0
  127. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/chat.js +0 -0
  128. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/credentials.js +0 -0
  129. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/dashboard.js +0 -0
  130. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/edits.js +0 -0
  131. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/enforcement.js +0 -0
  132. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/instructions.js +0 -0
  133. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/jira.js +0 -0
  134. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/memory.js +0 -0
  135. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/sessions.js +0 -0
  136. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/settings.js +0 -0
  137. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/sidebar.js +0 -0
  138. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/components/tasks.js +0 -0
  139. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/icons.js +0 -0
  140. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/pm_shared.js +0 -0
  141. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/shared.js +0 -0
  142. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui/theme.js +0 -0
  143. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui.html +0 -0
  144. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui_legacy.html +0 -0
  145. {code_context_control-2.125.0 → code_context_control-2.126.1}/cli/ui_nano.html +0 -0
  146. {code_context_control-2.125.0 → code_context_control-2.126.1}/code_context_control.egg-info/dependency_links.txt +0 -0
  147. {code_context_control-2.125.0 → code_context_control-2.126.1}/code_context_control.egg-info/entry_points.txt +0 -0
  148. {code_context_control-2.125.0 → code_context_control-2.126.1}/code_context_control.egg-info/requires.txt +0 -0
  149. {code_context_control-2.125.0 → code_context_control-2.126.1}/code_context_control.egg-info/top_level.txt +0 -0
  150. {code_context_control-2.125.0 → code_context_control-2.126.1}/core/__init__.py +0 -0
  151. {code_context_control-2.125.0 → code_context_control-2.126.1}/core/codex_patch.py +0 -0
  152. {code_context_control-2.125.0 → code_context_control-2.126.1}/core/config.py +0 -0
  153. {code_context_control-2.125.0 → code_context_control-2.126.1}/core/host.py +0 -0
  154. {code_context_control-2.125.0 → code_context_control-2.126.1}/core/ide.py +0 -0
  155. {code_context_control-2.125.0 → code_context_control-2.126.1}/core/mcp_toml.py +0 -0
  156. {code_context_control-2.125.0 → code_context_control-2.126.1}/core/web_security.py +0 -0
  157. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/__init__.py +0 -0
  158. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/config.py +0 -0
  159. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/listeners.py +0 -0
  160. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/mcp_oracle.py +0 -0
  161. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/oracle_server.py +0 -0
  162. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/oracle_ui.html +0 -0
  163. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/__init__.py +0 -0
  164. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/activity_reporter.py +0 -0
  165. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/api_auth.py +0 -0
  166. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/c3_bridge.py +0 -0
  167. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/chat_engine.py +0 -0
  168. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/chat_poll.py +0 -0
  169. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/chat_store.py +0 -0
  170. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/client_tokens.py +0 -0
  171. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/cross_memory.py +0 -0
  172. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/discovery_audit.py +0 -0
  173. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/federated_graph.py +0 -0
  174. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/health_checker.py +0 -0
  175. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/insight_engine.py +0 -0
  176. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/local_session.py +0 -0
  177. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/memory_reader.py +0 -0
  178. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/memory_writer.py +0 -0
  179. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/project_scanner.py +0 -0
  180. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/review_agent.py +0 -0
  181. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/tool_executor.py +0 -0
  182. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/services/tool_registry.py +0 -0
  183. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/activity.js +0 -0
  184. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/agents.js +0 -0
  185. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/app.js +0 -0
  186. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/busy.js +0 -0
  187. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/chat/conversations.js +0 -0
  188. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/chat/input.js +0 -0
  189. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/chat/markdown.js +0 -0
  190. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/chat/send.js +0 -0
  191. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/chat/stream_renderer.js +0 -0
  192. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/chat/toolbar.js +0 -0
  193. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/core.js +0 -0
  194. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/crossgraph.js +0 -0
  195. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/header.js +0 -0
  196. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/insights.js +0 -0
  197. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/projects.js +0 -0
  198. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/qrcode.js +0 -0
  199. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/settings.js +0 -0
  200. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/suggestions.js +0 -0
  201. {code_context_control-2.125.0 → code_context_control-2.126.1}/oracle/ui/theme_tabs.js +0 -0
  202. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/__init__.py +0 -0
  203. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/access_guard.py +0 -0
  204. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/access_telemetry.py +0 -0
  205. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/activity_log.py +0 -0
  206. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/agent_base.py +0 -0
  207. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/agent_locks.py +0 -0
  208. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/agents.py +0 -0
  209. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/artifact_defs.py +0 -0
  210. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/artifact_store.py +0 -0
  211. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/atomic_json.py +0 -0
  212. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/auto_memory.py +0 -0
  213. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/background_service.py +0 -0
  214. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/bench/__init__.py +0 -0
  215. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/bench/external/__init__.py +0 -0
  216. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/bench/external/aider_polyglot.py +0 -0
  217. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/bench/external/swe_bench.py +0 -0
  218. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/bench/map_eval.py +0 -0
  219. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/bench/search_eval.py +0 -0
  220. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/bench/shell_eval.py +0 -0
  221. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/benchmark_dashboard.py +0 -0
  222. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/bitbucket_client.py +0 -0
  223. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/bitbucket_credentials.py +0 -0
  224. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ci_act.py +0 -0
  225. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ci_cache.py +0 -0
  226. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ci_expr.py +0 -0
  227. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ci_failures.py +0 -0
  228. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ci_github.py +0 -0
  229. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ci_impact.py +0 -0
  230. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ci_intel.py +0 -0
  231. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ci_workflow.py +0 -0
  232. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/circuit_breaker.py +0 -0
  233. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/claude_md.py +0 -0
  234. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/codex_integration.py +0 -0
  235. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/codex_transcript.py +0 -0
  236. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/compressor.py +0 -0
  237. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/context_snapshot.py +0 -0
  238. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/conversation_store.py +0 -0
  239. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/cred_audit.py +0 -0
  240. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/cred_telemetry.py +0 -0
  241. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/credential_store.py +0 -0
  242. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/dir_map.py +0 -0
  243. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/doc_index.py +0 -0
  244. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/e2e_benchmark.py +0 -0
  245. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/e2e_evaluator.py +0 -0
  246. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/e2e_tasks.py +0 -0
  247. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/edit_ledger.py +0 -0
  248. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/embedding_index.py +0 -0
  249. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/enforcement_policy.py +0 -0
  250. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/error_reporting.py +0 -0
  251. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/file_map.py +0 -0
  252. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/file_memory.py +0 -0
  253. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/git_context.py +0 -0
  254. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/hub_service.py +0 -0
  255. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/index_store.py +0 -0
  256. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/indexer.py +0 -0
  257. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/jira_client.py +0 -0
  258. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/jira_cloud.py +0 -0
  259. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/jira_credentials.py +0 -0
  260. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/jira_data_center.py +0 -0
  261. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/jira_links.py +0 -0
  262. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/lexical_index.py +0 -0
  263. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/mask_activation.py +0 -0
  264. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/mask_mirror.py +0 -0
  265. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/mask_presets.py +0 -0
  266. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/memory.py +0 -0
  267. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/memory_consolidator.py +0 -0
  268. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/memory_distiller.py +0 -0
  269. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/memory_graph.py +0 -0
  270. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/memory_grounder.py +0 -0
  271. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/memory_queue.py +0 -0
  272. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/memory_scorer.py +0 -0
  273. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/metrics.py +0 -0
  274. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ollama_bridge.py +0 -0
  275. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ollama_client.py +0 -0
  276. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/ollama_credentials.py +0 -0
  277. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/oracle_service.py +0 -0
  278. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/output_filter.py +0 -0
  279. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/override_grants.py +0 -0
  280. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/override_policy.py +0 -0
  281. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/override_requests.py +0 -0
  282. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/override_wake.py +0 -0
  283. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/parser.py +0 -0
  284. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/project_manager.py +0 -0
  285. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/project_runtime.py +0 -0
  286. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/protocol.py +0 -0
  287. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/proxy_state.py +0 -0
  288. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/repo_map.py +0 -0
  289. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/repo_shape.py +0 -0
  290. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/reranker.py +0 -0
  291. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/retention.py +0 -0
  292. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/retrieval.py +0 -0
  293. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/retrieval_broker.py +0 -0
  294. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/router.py +0 -0
  295. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/runtime.py +0 -0
  296. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/scanner.py +0 -0
  297. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/session_benchmark.py +0 -0
  298. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/session_manager.py +0 -0
  299. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/session_preloader.py +0 -0
  300. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/shell_output.py +0 -0
  301. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/subprojects.py +0 -0
  302. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/task_store.py +0 -0
  303. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/telemetry.py +0 -0
  304. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/text_index.py +0 -0
  305. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/time_tracker.py +0 -0
  306. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/tool_classifier.py +0 -0
  307. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/transcript_index.py +0 -0
  308. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/validation_cache.py +0 -0
  309. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/vector_store.py +0 -0
  310. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/watcher.py +0 -0
  311. {code_context_control-2.125.0 → code_context_control-2.126.1}/services/win_subprocess.py +0 -0
  312. {code_context_control-2.125.0 → code_context_control-2.126.1}/setup.cfg +0 -0
  313. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_access_builtin_optout.py +0 -0
  314. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_access_guard.py +0 -0
  315. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_access_guard_meta.py +0 -0
  316. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_access_guard_shell_project.py +0 -0
  317. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_access_guard_surfaces.py +0 -0
  318. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_access_guard_wiring.py +0 -0
  319. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_activity_reporter.py +0 -0
  320. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_agent_locks.py +0 -0
  321. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_aider_polyglot.py +0 -0
  322. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_antigravity_transition.py +0 -0
  323. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_artifact_store.py +0 -0
  324. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_artifact_tool.py +0 -0
  325. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_atomic_json.py +0 -0
  326. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_background_service.py +0 -0
  327. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_bitbucket_cli_smoke.py +0 -0
  328. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_bitbucket_client.py +0 -0
  329. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_bitbucket_config_fallback.py +0 -0
  330. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_bitbucket_credentials.py +0 -0
  331. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_bitbucket_tool.py +0 -0
  332. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_builtin_modes.py +0 -0
  333. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_c3_bridge_project_artifacts.py +0 -0
  334. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_c3_shell.py +0 -0
  335. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_chat_poll.py +0 -0
  336. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ci_act.py +0 -0
  337. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ci_cache.py +0 -0
  338. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ci_expr.py +0 -0
  339. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ci_impact.py +0 -0
  340. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ci_intel.py +0 -0
  341. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ci_runner.py +0 -0
  342. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ci_workflow.py +0 -0
  343. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_circuit_breaker.py +0 -0
  344. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_claude_md_merge.py +0 -0
  345. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_claude_md_updater.py +0 -0
  346. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_cli_smoke.py +0 -0
  347. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_codex_mcp_transport.py +0 -0
  348. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_codex_native.py +0 -0
  349. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_compressor_large_file.py +0 -0
  350. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_confirm_guard.py +0 -0
  351. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_confirm_guard_wiring.py +0 -0
  352. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_cooccurrence_bounds.py +0 -0
  353. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_cred_audit.py +0 -0
  354. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_cred_telemetry.py +0 -0
  355. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_credential_login_kind.py +0 -0
  356. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_credential_store.py +0 -0
  357. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_credential_ui_parity.py +0 -0
  358. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_credentials_routes.py +0 -0
  359. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_credentials_tool.py +0 -0
  360. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_creds_cli_smoke.py +0 -0
  361. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_delegate_cascade.py +0 -0
  362. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_delegate_version_probe.py +0 -0
  363. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_dir_map_c3.py +0 -0
  364. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_e2e_benchmark.py +0 -0
  365. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_edit_ledger_deadline.py +0 -0
  366. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_edit_ledger_hook.py +0 -0
  367. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_edit_locking.py +0 -0
  368. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_edit_normalization.py +0 -0
  369. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_edit_verify.py +0 -0
  370. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_embedding_index_deadlock.py +0 -0
  371. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_enforcement_flip.py +0 -0
  372. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_enforcement_policy.py +0 -0
  373. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_enforcement_routes.py +0 -0
  374. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_env_parser.py +0 -0
  375. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_failed_calls_do_not_unlock.py +0 -0
  376. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_federated_graph.py +0 -0
  377. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_file_map_c1.py +0 -0
  378. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_filter_backoff.py +0 -0
  379. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ghost_files.py +0 -0
  380. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ghost_generation.py +0 -0
  381. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_git_branch_awareness.py +0 -0
  382. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hook_access_guard.py +0 -0
  383. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hook_pretool_enforce.py +0 -0
  384. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hook_prompt_recall.py +0 -0
  385. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hook_smoke.py +0 -0
  386. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hook_state.py +0 -0
  387. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hook_utf8_stdio.py +0 -0
  388. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hub_credentials_route.py +0 -0
  389. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hub_credentials_routes_write.py +0 -0
  390. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hub_enforcement_routes.py +0 -0
  391. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hub_inspect_api.py +0 -0
  392. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hub_locks_routes.py +0 -0
  393. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hub_oracle_service_routes.py +0 -0
  394. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hub_override_routes.py +0 -0
  395. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hub_server_smoke.py +0 -0
  396. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_hub_subproject_links.py +0 -0
  397. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ide_workflow_adaptation.py +0 -0
  398. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_index_cap_not_hardcoded.py +0 -0
  399. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_init_clear_preserves_user_content.py +0 -0
  400. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_init_scan.py +0 -0
  401. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_install_mcp_entrypoint.py +0 -0
  402. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_jira_cli_smoke.py +0 -0
  403. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_jira_client.py +0 -0
  404. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_jira_config_fallback.py +0 -0
  405. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_jira_credentials.py +0 -0
  406. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_jira_links.py +0 -0
  407. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_jira_routes.py +0 -0
  408. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_jira_tool.py +0 -0
  409. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_large_files_c4.py +0 -0
  410. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_lazy_store_init.py +0 -0
  411. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_map_eval.py +0 -0
  412. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_map_telemetry_c0.py +0 -0
  413. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mask_guard.py +0 -0
  414. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mask_routes.py +0 -0
  415. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mask_surfaces.py +0 -0
  416. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mcp_host_guard.py +0 -0
  417. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mcp_memory_timeout.py +0 -0
  418. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mcp_server_smoke.py +0 -0
  419. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mcp_toml.py +0 -0
  420. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_memory_distiller.py +0 -0
  421. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_memory_graph_api.py +0 -0
  422. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_memory_queue.py +0 -0
  423. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_memory_system.py +0 -0
  424. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mobile_api.py +0 -0
  425. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mobile_clients.py +0 -0
  426. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mobile_extras.py +0 -0
  427. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_mobile_security_api.py +0 -0
  428. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_no_stale_model_pins.py +0 -0
  429. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_notification_dedup.py +0 -0
  430. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_notification_discipline.py +0 -0
  431. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ollama_credentials.py +0 -0
  432. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_api_auth.py +0 -0
  433. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_apikey_api.py +0 -0
  434. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_c3_bridge.py +0 -0
  435. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_chat_engine.py +0 -0
  436. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_chat_store.py +0 -0
  437. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_discovery_api.py +0 -0
  438. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_discovery_audit.py +0 -0
  439. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_health_probe.py +0 -0
  440. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_local_auth.py +0 -0
  441. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_loopback.py +0 -0
  442. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_ollama_bridge.py +0 -0
  443. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_scanner_cache.py +0 -0
  444. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_security_fixes.py +0 -0
  445. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_session_bootstrap.py +0 -0
  446. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_subproject_awareness.py +0 -0
  447. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_oracle_ui_bundle.py +0 -0
  448. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_output_filter.py +0 -0
  449. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_override_grants.py +0 -0
  450. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_override_grants_mcp.py +0 -0
  451. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_override_requests.py +0 -0
  452. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_override_wake.py +0 -0
  453. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_permissions.py +0 -0
  454. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_pm_api.py +0 -0
  455. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_project_manager.py +0 -0
  456. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_project_manager_merge.py +0 -0
  457. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_project_tool.py +0 -0
  458. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_read_coercion.py +0 -0
  459. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_read_edit_parity.py +0 -0
  460. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_related_facts.py +0 -0
  461. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_repo_map.py +0 -0
  462. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_repo_shape.py +0 -0
  463. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_response_boilerplate.py +0 -0
  464. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_retention.py +0 -0
  465. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_review_digest.py +0 -0
  466. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_search_eval.py +0 -0
  467. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_search_p1.py +0 -0
  468. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_search_p2.py +0 -0
  469. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_search_p2b.py +0 -0
  470. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_search_p3.py +0 -0
  471. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_search_p4.py +0 -0
  472. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_search_p5.py +0 -0
  473. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_service_durability.py +0 -0
  474. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_session_benchmark.py +0 -0
  475. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_session_budget.py +0 -0
  476. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_budget_s1.py +0 -0
  477. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_creds.py +0 -0
  478. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_eval.py +0 -0
  479. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_nudge_s4.py +0 -0
  480. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_output.py +0 -0
  481. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_parsers_s2.py +0 -0
  482. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_robustness.py +0 -0
  483. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_telemetry_s0.py +0 -0
  484. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_write_ledger.py +0 -0
  485. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_shell_writes.py +0 -0
  486. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_subproject_clear_scope.py +0 -0
  487. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_subproject_depth_consumers.py +0 -0
  488. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_subproject_exclusion.py +0 -0
  489. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_subproject_federation.py +0 -0
  490. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_subproject_linkage_api.py +0 -0
  491. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_subprojects.py +0 -0
  492. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_swe_bench.py +0 -0
  493. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_task_store.py +0 -0
  494. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_task_tool.py +0 -0
  495. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_time_tracker.py +0 -0
  496. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_token_telemetry.py +0 -0
  497. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_token_tracking.py +0 -0
  498. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_tool_registry.py +0 -0
  499. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_ui_jsx_syntax.py +0 -0
  500. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_upgrade_and_version.py +0 -0
  501. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_validate.py +0 -0
  502. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_vault_write_guard.py +0 -0
  503. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_version_sync.py +0 -0
  504. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_web_security.py +0 -0
  505. {code_context_control-2.125.0 → code_context_control-2.126.1}/tests/test_windows_reliability.py +0 -0
  506. {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/__init__.py +0 -0
  507. {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/backend.py +0 -0
  508. {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/main.py +0 -0
  509. {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/__init__.py +0 -0
  510. {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/benchmark_view.py +0 -0
  511. {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/claudemd_view.py +0 -0
  512. {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/compress_view.py +0 -0
  513. {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/index_view.py +0 -0
  514. {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/init_view.py +0 -0
  515. {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/mcp_view.py +0 -0
  516. {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/optimize_view.py +0 -0
  517. {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/pipe_view.py +0 -0
  518. {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/projects_view.py +0 -0
  519. {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/search_view.py +0 -0
  520. {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/session_view.py +0 -0
  521. {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/stats.py +0 -0
  522. {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/screens/ui_view.py +0 -0
  523. {code_context_control-2.125.0 → code_context_control-2.126.1}/tui/theme.tcss +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-context-control
3
- Version: 2.125.0
3
+ Version: 2.126.1
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
@@ -500,6 +500,40 @@ def record_json_unlocks(
500
500
  pass
501
501
 
502
502
 
503
+ _PROJECT_WALK_UP_LEVELS = 4
504
+
505
+
506
+ def find_project(payload: dict, project_path=None) -> Path | None:
507
+ """The nearest ancestor (≤ 4 levels) of ``project_path`` / ``payload.cwd``
508
+ that owns a ``.c3`` directory, or None.
509
+
510
+ Claude Code runs hooks from the project root, Codex passes ``--project``;
511
+ either way the payload's ``cwd`` may be a subdirectory (a session opened
512
+ in ``src/``). The walk is lexical on purpose — no path canonicalisation
513
+ happens here (see tests/test_access_guard_meta.py).
514
+ """
515
+ candidates = []
516
+ if project_path:
517
+ candidates.append(Path(str(project_path)))
518
+ cwd = payload.get("cwd") if isinstance(payload, dict) else None
519
+ if cwd:
520
+ candidates.append(Path(str(cwd)))
521
+ if not candidates:
522
+ candidates.append(Path.cwd())
523
+ for base in candidates:
524
+ node = base
525
+ for _ in range(_PROJECT_WALK_UP_LEVELS):
526
+ try:
527
+ if (node / ".c3").is_dir():
528
+ return node
529
+ except OSError:
530
+ break
531
+ if node.parent == node:
532
+ break
533
+ node = node.parent
534
+ return None
535
+
536
+
503
537
  def emit_additional_context(text: str, is_gemini: bool) -> None:
504
538
  """Write additionalContext JSON to stdout in the correct format for the IDE."""
505
539
  if is_gemini:
@@ -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.125.0"
95
+ __version__ = "2.126.1"
96
96
 
97
97
 
98
98
  def _compress_file_cli(compressor, path, mode="smart", **kw):
@@ -5558,6 +5558,8 @@ def cmd_install_mcp(args):
5558
5558
  hook_posttool_cmd = f"{_dispatch_base} posttool"
5559
5559
  hook_stop_cmd = f"{_dispatch_base} stop"
5560
5560
  hook_prompt_cmd = f"{_dispatch_base} prompt"
5561
+ hook_start_cmd = f"{_dispatch_base} start"
5562
+ hook_end_cmd = f"{_dispatch_base} end"
5561
5563
 
5562
5564
  shell_matcher = "Bash"
5563
5565
  read_matcher = "Read"
@@ -5696,6 +5698,25 @@ def cmd_install_mcp(args):
5696
5698
  )
5697
5699
  settings.setdefault("hooks", {})[prompt_event] = existing_prompt
5698
5700
 
5701
+ # ── SessionStart / SessionEnd hooks (v2.126.0: session_open /
5702
+ # session_end activity rows + `session` notifications, the join key
5703
+ # a desktop client needs). Same merge discipline: replace only C3's
5704
+ # own dispatcher entries, keep user-added ones. SessionStart's
5705
+ # matcher is the payload `source` (startup|resume|clear|compact);
5706
+ # empty matches all — the hook itself ignores `compact`.
5707
+ for _lifecycle_event, _lifecycle_cmd in (
5708
+ ("SessionStart", hook_start_cmd),
5709
+ ("SessionEnd", hook_end_cmd),
5710
+ ):
5711
+ _kept = [
5712
+ h for h in settings.get("hooks", {}).get(_lifecycle_event, [])
5713
+ if not _is_c3_prompt_hook(h)
5714
+ ]
5715
+ _kept.append(
5716
+ {"matcher": "", "hooks": [{"type": "command", "command": _lifecycle_cmd}]}
5717
+ )
5718
+ settings.setdefault("hooks", {})[_lifecycle_event] = _kept
5719
+
5699
5720
  # Claude Code only: enable MCP server prompt settings
5700
5721
  if profile.name == "claude-code":
5701
5722
  settings["enableAllProjectMcpServers"] = True
@@ -5742,6 +5763,7 @@ def cmd_install_mcp(args):
5742
5763
  print(f" Hooks ({hook_event}): dispatcher (1 spawn/event) — filter/ghost/read-guard/ledger/unlock/signal via cli/hook_dispatch.py posttool")
5743
5764
  print(f" Hooks ({pre_event}): dispatcher — {read_matcher}/{grep_matcher}/{glob_matcher}/{edit_matcher}/{write_matcher} (c3 enforcement)")
5744
5765
  print(" Hooks (Stop): dispatcher — session_stats + auto_snapshot + terse_advisor")
5766
+ print(" Hooks (SessionStart/SessionEnd): dispatcher — session_open / session_end rows + session notifications")
5745
5767
  if profile.name == "claude-code":
5746
5768
  print(" Claude MCP prompt settings enabled for this project")
5747
5769
  if perm_tier and profile.name == "claude-code":
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python3
2
2
  """Per-event hook dispatcher: ONE process per Claude Code / Gemini hook event.
3
3
 
4
- Usage: python hook_dispatch.py <pretool|posttool|stop|prompt>
4
+ Usage: python hook_dispatch.py <pretool|posttool|stop|prompt|start|compact|end>
5
5
 
6
6
  Before v2.42 every hook was registered as its own "cmd /c python <hook>.py"
7
7
  subprocess, so a single native Read fired up to three interpreter spawns
@@ -167,8 +167,17 @@ def _routes(event: str, raw_tool: str, norm_tool: str, host: str = HOST_CLAUDE):
167
167
  yield "hook_terse_advisor"
168
168
  elif event == "prompt":
169
169
  yield "hook_prompt_recall"
170
- elif event in ("start", "compact", "end") and host == HOST_CODEX:
171
- yield "hook_codex_lifecycle"
170
+ elif event in ("start", "compact", "end"):
171
+ # Codex's thread-bound handoff runs first (it may return context on
172
+ # SessionStart); the session bookkeeping below is host-agnostic and
173
+ # returns nothing (v2.126.0: session_open / session_end rows + the
174
+ # `session` notifications a desktop client wakes on).
175
+ if host == HOST_CODEX:
176
+ yield "hook_codex_lifecycle"
177
+ if event == "start":
178
+ yield "hook_session_open"
179
+ elif event == "end":
180
+ yield "hook_session_end"
172
181
 
173
182
 
174
183
  _RUN_CACHE: dict = {}
@@ -0,0 +1,103 @@
1
+ """SessionEnd hook: record that a host session ended (D0b, v2.126.0).
2
+
3
+ Claude Code's ``SessionEnd`` event delivers on stdin::
4
+
5
+ {
6
+ "session_id": "<Claude Code UUID>",
7
+ "transcript_path": "...",
8
+ "cwd": "...",
9
+ "hook_event_name": "SessionEnd",
10
+ "reason": "clear" | "logout" | "prompt_input_exit" | "other"
11
+ }
12
+
13
+ Codex's ``SessionEnd`` carries its thread id in the same ``session_id``
14
+ field; the dispatcher routes both here (``hook_dispatch._routes``, event
15
+ ``end``).
16
+
17
+ Why this exists: this repo's activity log held 525 ``session_start`` rows
18
+ and 14 ``session_save`` rows — ``session_save`` is only written when a human
19
+ ends a session from the hub, so for a client the end of a conversation was
20
+ invisible. Two records fix that:
21
+
22
+ - ``{type: "session_end", session_id: <C3 id if known>, host_session_id,
23
+ reason, source}`` appended to ``.c3/activity_log.jsonl``. The C3 id comes
24
+ from the link file the MCP server wrote at session start
25
+ (``services.host_sessions``); it is ``""`` when the server never learned
26
+ the host id.
27
+ - a ``session`` notification (``kind="session"``, ``ref_id=host id``,
28
+ severity ``info``, title ``Session ended <short id>``) in
29
+ ``.c3/notifications.jsonl`` — the write that wakes a ``/feed?wait=``
30
+ client.
31
+
32
+ Runs in a short-lived subprocess with a few seconds of budget; every step is
33
+ best-effort and nothing here can fail the session that is already ending.
34
+ """
35
+ from __future__ import annotations
36
+
37
+ import sys
38
+ from pathlib import Path
39
+
40
+ sys.path.insert(0, str(Path(__file__).parent.parent))
41
+
42
+ from cli._hook_utils import detect_host, find_project, log_hook_error # noqa: E402
43
+
44
+ SHORT_ID_CHARS = 8
45
+
46
+
47
+ def short_id(session_id: str) -> str:
48
+ return str(session_id or "")[:SHORT_ID_CHARS] or "?"
49
+
50
+
51
+ def run(payload: dict, project_path: Path | None = None):
52
+ """Core logic — importable by the dispatcher and tests. Returns None."""
53
+ project = find_project(payload, project_path)
54
+ if project is None:
55
+ return None
56
+ host = detect_host(payload)
57
+ host_sid = str(payload.get("session_id") or "").strip()
58
+ reason = str(payload.get("reason") or "").strip()
59
+ c3_sid = ""
60
+ try:
61
+ from services.host_sessions import linked_c3_session_id
62
+ c3_sid = linked_c3_session_id(project, host, host_sid)
63
+ except Exception:
64
+ c3_sid = ""
65
+ try:
66
+ from services.activity_log import ActivityLog
67
+ ActivityLog(str(project)).log("session_end", {
68
+ "session_id": c3_sid,
69
+ "host_session_id": host_sid,
70
+ "reason": reason,
71
+ "source": host,
72
+ })
73
+ except Exception as exc:
74
+ log_hook_error("hook_session_end", exc)
75
+ try:
76
+ from services.notifications import notify
77
+ notify(project, agent="session", severity="info",
78
+ title=f"Session ended {short_id(host_sid)}",
79
+ message=(f"{host} session {host_sid or '?'} ended"
80
+ + (f" ({reason})" if reason else "")
81
+ + (f"; C3 session {c3_sid}" if c3_sid else "")),
82
+ kind="session", ref_id=host_sid)
83
+ except Exception:
84
+ pass
85
+ return None
86
+
87
+
88
+ def main() -> None:
89
+ import json
90
+ try:
91
+ data = json.load(sys.stdin)
92
+ except Exception as exc:
93
+ log_hook_error("hook_session_end", exc)
94
+ sys.exit(0)
95
+ try:
96
+ run(data)
97
+ except Exception as exc:
98
+ log_hook_error("hook_session_end", exc)
99
+ sys.exit(0)
100
+
101
+
102
+ if __name__ == "__main__":
103
+ main()
@@ -0,0 +1,97 @@
1
+ """SessionStart hook: record that a host session opened (D0b, v2.126.0).
2
+
3
+ Claude Code's ``SessionStart`` event delivers on stdin::
4
+
5
+ {
6
+ "session_id": "<Claude Code UUID>",
7
+ "transcript_path": "...",
8
+ "cwd": "...",
9
+ "hook_event_name": "SessionStart",
10
+ "source": "startup" | "resume" | "clear" | "compact"
11
+ }
12
+
13
+ Codex's ``SessionStart`` carries its thread id in the same ``session_id``
14
+ field and no ``source``; the dispatcher routes both here (event ``start``).
15
+
16
+ Records:
17
+
18
+ - ``{type: "session_open", host_session_id, source: <host>, start_source}``
19
+ in ``.c3/activity_log.jsonl``. ``source`` is the HOST (``claude`` /
20
+ ``codex`` / ``gemini``), matching ``session_end``; the payload's own
21
+ ``source`` (startup / resume / clear) is kept as ``start_source``.
22
+ - a ``session`` notification (``kind="session"``, ``ref_id=host id``,
23
+ ``info``, title ``Session started <short id>``).
24
+
25
+ ``source: "compact"`` writes NOTHING: a compaction is the same session and
26
+ the same MCP process, and a "Session started" toast on every compaction
27
+ would teach the user to ignore the real ones.
28
+
29
+ The MCP server's own ``session_start`` row is untouched — it carries the C3
30
+ id and, when the host put its id in the environment, ``host_session_id``
31
+ too. This hook is what lets a client see the session before the runtime has
32
+ finished starting (~seconds), and it is the row the desktop's "MCP failed to
33
+ connect" sentinel starts its 30 s clock from.
34
+
35
+ Returns None always: SessionStart hook stdout becomes model context, and
36
+ this hook has nothing to tell the model.
37
+ """
38
+ from __future__ import annotations
39
+
40
+ import sys
41
+ from pathlib import Path
42
+
43
+ sys.path.insert(0, str(Path(__file__).parent.parent))
44
+
45
+ from cli._hook_utils import detect_host, find_project, log_hook_error # noqa: E402
46
+ from cli.hook_session_end import short_id # noqa: E402
47
+
48
+ _SILENT_SOURCES = {"compact"}
49
+
50
+
51
+ def run(payload: dict, project_path: Path | None = None):
52
+ """Core logic — importable by the dispatcher and tests. Returns None."""
53
+ start_source = str(payload.get("source") or "").strip().lower()
54
+ if start_source in _SILENT_SOURCES:
55
+ return None
56
+ project = find_project(payload, project_path)
57
+ if project is None:
58
+ return None
59
+ host = detect_host(payload)
60
+ host_sid = str(payload.get("session_id") or "").strip()
61
+ try:
62
+ from services.activity_log import ActivityLog
63
+ ActivityLog(str(project)).log("session_open", {
64
+ "host_session_id": host_sid,
65
+ "source": host,
66
+ "start_source": start_source,
67
+ })
68
+ except Exception as exc:
69
+ log_hook_error("hook_session_open", exc)
70
+ try:
71
+ from services.notifications import notify
72
+ notify(project, agent="session", severity="info",
73
+ title=f"Session started {short_id(host_sid)}",
74
+ message=(f"{host} session {host_sid or '?'} started"
75
+ + (f" ({start_source})" if start_source else "")),
76
+ kind="session", ref_id=host_sid)
77
+ except Exception:
78
+ pass
79
+ return None
80
+
81
+
82
+ def main() -> None:
83
+ import json
84
+ try:
85
+ data = json.load(sys.stdin)
86
+ except Exception as exc:
87
+ log_hook_error("hook_session_open", exc)
88
+ sys.exit(0)
89
+ try:
90
+ run(data)
91
+ except Exception as exc:
92
+ log_hook_error("hook_session_open", exc)
93
+ sys.exit(0)
94
+
95
+
96
+ if __name__ == "__main__":
97
+ main()
@@ -100,6 +100,92 @@ def _build_instructions(ide_name: str) -> str:
100
100
  )
101
101
 
102
102
 
103
+ # ── Host session id (the join key between hook rows and MCP rows) ──────────
104
+ # The PreToolUse hooks write .c3/enforcement_state.json with `session_id` =
105
+ # the host's id for the session that just called. When the host also put its
106
+ # id in this process's environment (CLAUDE_CODE_SESSION_ID / CODEX_THREAD_ID)
107
+ # the SessionManager already carries it and no file is read. Otherwise the
108
+ # state file is consulted at most once per _HOST_SID_TTL_S — a tool call is
109
+ # far hotter than that, and a per-call read would be a stat+parse on every
110
+ # c3_* invocation for a value that changes once per session.
111
+ _HOST_SID_TTL_S = 5.0
112
+ _host_sid_cache = {"value": "", "read_at": 0.0, "linked": ""}
113
+ _host_sid_lock = threading.Lock()
114
+
115
+
116
+ def _host_session_id(svc) -> str:
117
+ """The host session id for this process, or ``""`` when nobody knows it."""
118
+ try:
119
+ session = getattr(getattr(svc, "session_mgr", None), "current_session", None) or {}
120
+ env_sid = str(session.get("host_session_id") or "").strip()
121
+ except Exception:
122
+ env_sid = ""
123
+ if env_sid:
124
+ _link_host_session(svc, env_sid)
125
+ return env_sid
126
+ now = time.monotonic()
127
+ with _host_sid_lock:
128
+ if now - _host_sid_cache["read_at"] < _HOST_SID_TTL_S:
129
+ return _host_sid_cache["value"]
130
+ _host_sid_cache["read_at"] = now
131
+ value = ""
132
+ try:
133
+ import json as _json
134
+
135
+ from cli._hook_utils import ENFORCEMENT_STATE_FILE
136
+ state_path = Path(svc.project_path) / ENFORCEMENT_STATE_FILE
137
+ if state_path.is_file():
138
+ data = _json.loads(state_path.read_text(encoding="utf-8"))
139
+ if isinstance(data, dict):
140
+ value = str(data.get("session_id") or "").strip()
141
+ except Exception:
142
+ value = ""
143
+ with _host_sid_lock:
144
+ _host_sid_cache["value"] = value
145
+ if value:
146
+ _link_host_session(svc, value)
147
+ return value
148
+
149
+
150
+ def _link_host_session(svc, host_sid: str) -> None:
151
+ """Write the host→C3 link file once per distinct host id (services.host_sessions)."""
152
+ with _host_sid_lock:
153
+ if _host_sid_cache["linked"] == host_sid:
154
+ return
155
+ _host_sid_cache["linked"] = host_sid
156
+ try:
157
+ session = getattr(getattr(svc, "session_mgr", None), "current_session", None) or {}
158
+ c3_id = str(session.get("id") or "")
159
+ if c3_id:
160
+ from services.host_sessions import write_link
161
+ write_link(svc.project_path, getattr(svc, "ide_name", "") or _IDE_NAME, host_sid, c3_id)
162
+ except Exception:
163
+ pass
164
+
165
+
166
+ def _notify_mcp_ready(svc) -> None:
167
+ """``kind="mcp"`` / ``C3 connected`` — the runtime is ready to serve (D0b).
168
+
169
+ ref_id is the C3 session id, the same value ``session_start`` carries;
170
+ the host id rides in the message when known. Best-effort: a notification
171
+ failure must never keep the server from serving.
172
+ """
173
+ try:
174
+ session = getattr(getattr(svc, "session_mgr", None), "current_session", None) or {}
175
+ c3_id = str(session.get("id") or "")
176
+ host_sid = _host_session_id(svc)
177
+ short = (host_sid or c3_id)[:8] or "?"
178
+ from services.notifications import notify
179
+ notify(svc.project_path, agent="c3", severity="info",
180
+ title=f"C3 connected {short}",
181
+ message=(f"C3 {C3_VERSION} MCP runtime ready for {_IDE_NAME}"
182
+ f" (session {c3_id}"
183
+ + (f", host {host_sid}" if host_sid else "") + ")"),
184
+ kind="mcp", ref_id=c3_id)
185
+ except Exception:
186
+ pass
187
+
188
+
103
189
  @asynccontextmanager
104
190
  async def lifespan(server):
105
191
  """Initialize all services, auto-start session, start file watcher."""
@@ -223,9 +309,16 @@ async def lifespan(server):
223
309
  services.auto_memory = AutoMemory(services.memory, services.session_mgr, auto_mem_cfg)
224
310
 
225
311
  if services.session_mgr.current_session:
312
+ # host_session_id (the Claude Code UUID / Codex thread id) joins this
313
+ # row to the hooks' session_open / session_end rows, which only know
314
+ # the host id. Absent when the host did not put its id in the
315
+ # environment; the link file below is written lazily in that case
316
+ # the first time a hook reveals it (see _host_session_id).
317
+ _host_sid = _host_session_id(services)
226
318
  services.activity_log.log("session_start", {
227
319
  "session_id": services.session_mgr.current_session["id"],
228
320
  "source_system": started_session.get("source_system", ""),
321
+ **({"host_session_id": _host_sid} if _host_sid else {}),
229
322
  })
230
323
 
231
324
  # Auto-restore latest snapshot if recent (< 30 min).
@@ -288,6 +381,12 @@ async def lifespan(server):
288
381
  )
289
382
  _t.Thread(target=_bg_validation_sweep, daemon=True, name="c3-validate-sweep").start()
290
383
 
384
+ # Runtime is ready to serve: say so where a client can hear it. A desktop
385
+ # "MCP failed to connect" sentinel keys on a session_open with no `mcp`
386
+ # notification within 30 s, so this must be the LAST thing before the
387
+ # handshake proceeds and must never be skipped on a partial init.
388
+ _notify_mcp_ready(services)
389
+
291
390
  try:
292
391
  yield services
293
392
  finally:
@@ -430,8 +529,22 @@ def _finalize_response(ctx: Context, tool_name: str, args: dict,
430
529
  call_ok = not _failed(response)
431
530
  except Exception:
432
531
  call_ok = True
532
+ # Both session ids on every tool_call row (D0b): C3's own id joins the
533
+ # row to session_start / the saved session file, the host id joins it to
534
+ # the hooks' session_open / session_end rows. Either may be absent.
535
+ _ids: dict = {}
536
+ try:
537
+ _c3_sid = str((svc.session_mgr.current_session or {}).get("id") or "")
538
+ if _c3_sid:
539
+ _ids["session_id"] = _c3_sid
540
+ _host_sid = _host_session_id(svc)
541
+ if _host_sid:
542
+ _ids["host_session_id"] = _host_sid
543
+ except Exception:
544
+ pass
433
545
  svc.activity_log.log("tool_call", {"tool": tool_name, "args": args,
434
- "result_summary": summary, "ok": call_ok})
546
+ "result_summary": summary, "ok": call_ok,
547
+ **_ids})
435
548
  tracker = getattr(svc, "time_tracker", None)
436
549
  if tracker is not None:
437
550
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-context-control
3
- Version: 2.125.0
3
+ Version: 2.126.1
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,6 +21,8 @@ cli/hook_ghost_files.py
21
21
  cli/hook_pretool_enforce.py
22
22
  cli/hook_prompt_recall.py
23
23
  cli/hook_read.py
24
+ cli/hook_session_end.py
25
+ cli/hook_session_open.py
24
26
  cli/hook_session_stats.py
25
27
  cli/hook_terse_advisor.py
26
28
  cli/hub_server.py
@@ -231,6 +233,7 @@ services/error_reporting.py
231
233
  services/file_map.py
232
234
  services/file_memory.py
233
235
  services/git_context.py
236
+ services/host_sessions.py
234
237
  services/hub_service.py
235
238
  services/index_store.py
236
239
  services/indexer.py
@@ -372,6 +375,7 @@ tests/test_hook_codex_compat.py
372
375
  tests/test_hook_dispatch.py
373
376
  tests/test_hook_pretool_enforce.py
374
377
  tests/test_hook_prompt_recall.py
378
+ tests/test_hook_session_end.py
375
379
  tests/test_hook_smoke.py
376
380
  tests/test_hook_state.py
377
381
  tests/test_hook_utf8_stdio.py
@@ -414,11 +418,13 @@ tests/test_memory_system.py
414
418
  tests/test_mobile_api.py
415
419
  tests/test_mobile_clients.py
416
420
  tests/test_mobile_extras.py
421
+ tests/test_mobile_jobs_ci.py
417
422
  tests/test_mobile_override_routes.py
418
423
  tests/test_mobile_security_api.py
419
424
  tests/test_no_stale_model_pins.py
420
425
  tests/test_notification_dedup.py
421
426
  tests/test_notification_discipline.py
427
+ tests/test_notification_kinds.py
422
428
  tests/test_ollama_credentials.py
423
429
  tests/test_oracle_api_auth.py
424
430
  tests/test_oracle_apikey_api.py