code-context-control 2.145.2__tar.gz → 2.149.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 (579) hide show
  1. {code_context_control-2.145.2 → code_context_control-2.149.1}/PKG-INFO +1 -1
  2. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/c3.py +3 -3
  3. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_access_guard.py +1 -0
  4. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_server.py +259 -43
  5. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/app.js +4 -1
  6. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/hub_access.js +119 -2
  7. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/hub_credentials.js +21 -14
  8. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/modals.js +34 -12
  9. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/settings_modal.js +11 -0
  10. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/state.js +7 -3
  11. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui.html +1 -1
  12. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/mcp_server.py +11 -1
  13. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/server.py +4 -4
  14. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/credentials.py +1 -2
  15. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui.html +1 -1
  16. {code_context_control-2.145.2 → code_context_control-2.149.1}/code_context_control.egg-info/PKG-INFO +1 -1
  17. {code_context_control-2.145.2 → code_context_control-2.149.1}/code_context_control.egg-info/SOURCES.txt +4 -0
  18. {code_context_control-2.145.2 → code_context_control-2.149.1}/pyproject.toml +1 -1
  19. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/access_guard.py +60 -4
  20. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/activity_log.py +43 -15
  21. code_context_control-2.149.1/services/builtin_leases.py +182 -0
  22. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ci_act.py +22 -1
  23. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ci_workflow.py +5 -2
  24. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/credential_backup.py +9 -3
  25. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/credential_store.py +72 -10
  26. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/project_manager.py +19 -2
  27. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/session_catalog.py +82 -34
  28. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_activity_log_find_last.py +29 -1
  29. code_context_control-2.149.1/tests/test_builtin_leases.py +210 -0
  30. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ci_act.py +27 -0
  31. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_cred_audit.py +2 -2
  32. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_credential_store.py +50 -0
  33. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_access_routes.py +1 -1
  34. code_context_control-2.149.1/tests/test_hub_builtin_routes.py +163 -0
  35. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_credentials_routes_write.py +1 -1
  36. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_enforcement_routes.py +1 -1
  37. code_context_control-2.149.1/tests/test_hub_ide_cmd.py +125 -0
  38. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_locks_routes.py +1 -1
  39. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_rules_routes.py +1 -1
  40. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_sessions_routes.py +1 -1
  41. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_session_catalog.py +30 -0
  42. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_token_tracking.py +2 -2
  43. {code_context_control-2.145.2 → code_context_control-2.149.1}/LICENSE +0 -0
  44. {code_context_control-2.145.2 → code_context_control-2.149.1}/README.md +0 -0
  45. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/__init__.py +0 -0
  46. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/_hook_utils.py +0 -0
  47. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/_shell_writes.py +0 -0
  48. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/commands/__init__.py +0 -0
  49. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/commands/common.py +0 -0
  50. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/commands/parser.py +0 -0
  51. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/docs.html +0 -0
  52. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/edits.html +0 -0
  53. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/access.html +0 -0
  54. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/bitbucket.html +0 -0
  55. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/ci.html +0 -0
  56. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/credentials.html +0 -0
  57. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/delegate.html +0 -0
  58. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/getting-started.html +0 -0
  59. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/index.html +0 -0
  60. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/jira.html +0 -0
  61. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/masking.html +0 -0
  62. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/oracle.html +0 -0
  63. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/sessions.html +0 -0
  64. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/shared.css +0 -0
  65. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/tools.html +0 -0
  66. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/guide/workflow.html +0 -0
  67. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_agent_model.py +0 -0
  68. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_artifact.py +0 -0
  69. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_auto_snapshot.py +0 -0
  70. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_c3_signal.py +0 -0
  71. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_c3read.py +0 -0
  72. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_codex_lifecycle.py +0 -0
  73. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_dispatch.py +0 -0
  74. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_edit_ledger.py +0 -0
  75. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_edit_unlock.py +0 -0
  76. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_filter.py +0 -0
  77. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_ghost_files.py +0 -0
  78. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_pretool_enforce.py +0 -0
  79. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_prompt_recall.py +0 -0
  80. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_read.py +0 -0
  81. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_session_end.py +0 -0
  82. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_session_open.py +0 -0
  83. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_session_stats.py +0 -0
  84. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hook_terse_advisor.py +0 -0
  85. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/add_project.js +0 -0
  86. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/config_editor.js +0 -0
  87. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/drill_artifacts.js +0 -0
  88. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/drill_health.js +0 -0
  89. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/drill_panel.js +0 -0
  90. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/drill_subprojects.js +0 -0
  91. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/drill_tasks.js +0 -0
  92. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/drill_views.js +0 -0
  93. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/global_search.js +0 -0
  94. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/hub_ci.js +0 -0
  95. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/hub_cred_audit.js +0 -0
  96. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/hub_enforcement.js +0 -0
  97. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/hub_locks.js +0 -0
  98. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/hub_sessions.js +0 -0
  99. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/hub_tokens.js +0 -0
  100. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/mcp_manager.js +0 -0
  101. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/project_card.js +0 -0
  102. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/project_tree.js +0 -0
  103. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/session_drawer.js +0 -0
  104. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/sidebar.js +0 -0
  105. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/summary_bar.js +0 -0
  106. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/task_board.js +0 -0
  107. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/toasts.js +0 -0
  108. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/hub_ui/components/topbar.js +0 -0
  109. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/mcp_proxy.py +0 -0
  110. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/progress.py +0 -0
  111. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/__init__.py +0 -0
  112. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/_grants.py +0 -0
  113. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/_helpers.py +0 -0
  114. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/agent.py +0 -0
  115. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/artifacts.py +0 -0
  116. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/bitbucket.py +0 -0
  117. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/ci.py +0 -0
  118. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/compress.py +0 -0
  119. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/delegate.py +0 -0
  120. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/edit.py +0 -0
  121. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/edit_verify.py +0 -0
  122. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/edits.py +0 -0
  123. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/federate.py +0 -0
  124. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/filter.py +0 -0
  125. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/impact.py +0 -0
  126. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/jira.py +0 -0
  127. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/locks.py +0 -0
  128. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/memory.py +0 -0
  129. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/override.py +0 -0
  130. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/project.py +0 -0
  131. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/read.py +0 -0
  132. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/search.py +0 -0
  133. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/session.py +0 -0
  134. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/shell.py +0 -0
  135. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/shell_job.py +0 -0
  136. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/shell_nudge.py +0 -0
  137. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/shell_parsers.py +0 -0
  138. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/shell_render.py +0 -0
  139. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/status.py +0 -0
  140. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/tasks.py +0 -0
  141. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/tools/validate.py +0 -0
  142. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/api.js +0 -0
  143. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/app.js +0 -0
  144. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/access.js +0 -0
  145. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/bitbucket.js +0 -0
  146. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/chat.js +0 -0
  147. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/credentials.js +0 -0
  148. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/dashboard.js +0 -0
  149. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/edits.js +0 -0
  150. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/enforcement.js +0 -0
  151. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/instructions.js +0 -0
  152. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/jira.js +0 -0
  153. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/memory.js +0 -0
  154. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/sessions.js +0 -0
  155. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/settings.js +0 -0
  156. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/sidebar.js +0 -0
  157. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/components/tasks.js +0 -0
  158. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/icons.js +0 -0
  159. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/pm_shared.js +0 -0
  160. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/shared.js +0 -0
  161. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui/theme.js +0 -0
  162. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui_legacy.html +0 -0
  163. {code_context_control-2.145.2 → code_context_control-2.149.1}/cli/ui_nano.html +0 -0
  164. {code_context_control-2.145.2 → code_context_control-2.149.1}/code_context_control.egg-info/dependency_links.txt +0 -0
  165. {code_context_control-2.145.2 → code_context_control-2.149.1}/code_context_control.egg-info/entry_points.txt +0 -0
  166. {code_context_control-2.145.2 → code_context_control-2.149.1}/code_context_control.egg-info/requires.txt +0 -0
  167. {code_context_control-2.145.2 → code_context_control-2.149.1}/code_context_control.egg-info/top_level.txt +0 -0
  168. {code_context_control-2.145.2 → code_context_control-2.149.1}/core/__init__.py +0 -0
  169. {code_context_control-2.145.2 → code_context_control-2.149.1}/core/codex_patch.py +0 -0
  170. {code_context_control-2.145.2 → code_context_control-2.149.1}/core/config.py +0 -0
  171. {code_context_control-2.145.2 → code_context_control-2.149.1}/core/grok_payload.py +0 -0
  172. {code_context_control-2.145.2 → code_context_control-2.149.1}/core/hook_command.py +0 -0
  173. {code_context_control-2.145.2 → code_context_control-2.149.1}/core/host.py +0 -0
  174. {code_context_control-2.145.2 → code_context_control-2.149.1}/core/ide.py +0 -0
  175. {code_context_control-2.145.2 → code_context_control-2.149.1}/core/mcp_toml.py +0 -0
  176. {code_context_control-2.145.2 → code_context_control-2.149.1}/core/web_security.py +0 -0
  177. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/__init__.py +0 -0
  178. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/config.py +0 -0
  179. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/listeners.py +0 -0
  180. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/mcp_oracle.py +0 -0
  181. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/oracle_server.py +0 -0
  182. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/oracle_ui.html +0 -0
  183. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/__init__.py +0 -0
  184. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/activity_reporter.py +0 -0
  185. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/api_auth.py +0 -0
  186. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/c3_bridge.py +0 -0
  187. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/chat_engine.py +0 -0
  188. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/chat_poll.py +0 -0
  189. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/chat_store.py +0 -0
  190. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/client_tokens.py +0 -0
  191. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/cross_memory.py +0 -0
  192. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/discovery_audit.py +0 -0
  193. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/federated_graph.py +0 -0
  194. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/health_checker.py +0 -0
  195. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/insight_engine.py +0 -0
  196. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/local_session.py +0 -0
  197. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/memory_reader.py +0 -0
  198. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/memory_writer.py +0 -0
  199. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/mobile_api.py +0 -0
  200. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/project_scanner.py +0 -0
  201. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/review_agent.py +0 -0
  202. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/tool_executor.py +0 -0
  203. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/services/tool_registry.py +0 -0
  204. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/activity.js +0 -0
  205. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/agents.js +0 -0
  206. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/app.js +0 -0
  207. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/busy.js +0 -0
  208. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/chat/conversations.js +0 -0
  209. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/chat/input.js +0 -0
  210. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/chat/markdown.js +0 -0
  211. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/chat/send.js +0 -0
  212. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/chat/stream_renderer.js +0 -0
  213. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/chat/toolbar.js +0 -0
  214. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/core.js +0 -0
  215. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/crossgraph.js +0 -0
  216. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/header.js +0 -0
  217. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/insights.js +0 -0
  218. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/projects.js +0 -0
  219. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/qrcode.js +0 -0
  220. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/settings.js +0 -0
  221. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/suggestions.js +0 -0
  222. {code_context_control-2.145.2 → code_context_control-2.149.1}/oracle/ui/theme_tabs.js +0 -0
  223. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/__init__.py +0 -0
  224. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/access_telemetry.py +0 -0
  225. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/agent_base.py +0 -0
  226. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/agent_downshift.py +0 -0
  227. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/agent_locks.py +0 -0
  228. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/agents.py +0 -0
  229. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/agents_workflow.py +0 -0
  230. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/artifact_defs.py +0 -0
  231. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/artifact_store.py +0 -0
  232. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/atomic_json.py +0 -0
  233. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/auto_memory.py +0 -0
  234. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/background_service.py +0 -0
  235. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bench/__init__.py +0 -0
  236. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bench/delegate_eval.py +0 -0
  237. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bench/delegate_write_eval.py +0 -0
  238. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bench/external/__init__.py +0 -0
  239. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bench/external/aider_polyglot.py +0 -0
  240. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bench/external/swe_bench.py +0 -0
  241. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bench/map_eval.py +0 -0
  242. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bench/search_eval.py +0 -0
  243. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bench/shell_eval.py +0 -0
  244. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/benchmark_dashboard.py +0 -0
  245. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bitbucket_client.py +0 -0
  246. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/bitbucket_credentials.py +0 -0
  247. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ci_cache.py +0 -0
  248. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ci_expr.py +0 -0
  249. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ci_failures.py +0 -0
  250. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ci_github.py +0 -0
  251. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ci_impact.py +0 -0
  252. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ci_intel.py +0 -0
  253. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ci_runner.py +0 -0
  254. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/circuit_breaker.py +0 -0
  255. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/claude_md.py +0 -0
  256. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/codex_integration.py +0 -0
  257. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/codex_transcript.py +0 -0
  258. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/compressor.py +0 -0
  259. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/context_snapshot.py +0 -0
  260. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/conversation_store.py +0 -0
  261. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/cred_audit.py +0 -0
  262. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/cred_telemetry.py +0 -0
  263. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/delegate_agents.py +0 -0
  264. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/delegate_hints.py +0 -0
  265. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/delegate_write.py +0 -0
  266. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/dir_map.py +0 -0
  267. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/doc_index.py +0 -0
  268. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/e2e_benchmark.py +0 -0
  269. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/e2e_evaluator.py +0 -0
  270. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/e2e_tasks.py +0 -0
  271. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/edit_ledger.py +0 -0
  272. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/embedding_index.py +0 -0
  273. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/enforcement_policy.py +0 -0
  274. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/error_reporting.py +0 -0
  275. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/file_map.py +0 -0
  276. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/file_memory.py +0 -0
  277. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/git_context.py +0 -0
  278. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/grok_integration.py +0 -0
  279. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/grok_transcript.py +0 -0
  280. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/host_sessions.py +0 -0
  281. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/hub_service.py +0 -0
  282. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/index_store.py +0 -0
  283. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/indexer.py +0 -0
  284. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/jira_client.py +0 -0
  285. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/jira_cloud.py +0 -0
  286. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/jira_credentials.py +0 -0
  287. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/jira_data_center.py +0 -0
  288. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/jira_links.py +0 -0
  289. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/lexical_index.py +0 -0
  290. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/mask_activation.py +0 -0
  291. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/mask_mirror.py +0 -0
  292. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/mask_presets.py +0 -0
  293. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/memory.py +0 -0
  294. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/memory_consolidator.py +0 -0
  295. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/memory_distiller.py +0 -0
  296. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/memory_graph.py +0 -0
  297. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/memory_grounder.py +0 -0
  298. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/memory_queue.py +0 -0
  299. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/memory_scorer.py +0 -0
  300. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/metrics.py +0 -0
  301. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/notifications.py +0 -0
  302. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ollama_bridge.py +0 -0
  303. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ollama_client.py +0 -0
  304. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/ollama_credentials.py +0 -0
  305. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/oracle_service.py +0 -0
  306. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/output_filter.py +0 -0
  307. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/override_costs.py +0 -0
  308. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/override_grants.py +0 -0
  309. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/override_policy.py +0 -0
  310. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/override_requests.py +0 -0
  311. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/override_wake.py +0 -0
  312. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/parser.py +0 -0
  313. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/project_runtime.py +0 -0
  314. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/protocol.py +0 -0
  315. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/proxy_state.py +0 -0
  316. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/repo_map.py +0 -0
  317. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/repo_shape.py +0 -0
  318. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/reranker.py +0 -0
  319. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/retention.py +0 -0
  320. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/retrieval.py +0 -0
  321. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/retrieval_broker.py +0 -0
  322. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/router.py +0 -0
  323. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/runtime.py +0 -0
  324. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/scanner.py +0 -0
  325. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/session_benchmark.py +0 -0
  326. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/session_live.py +0 -0
  327. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/session_manager.py +0 -0
  328. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/session_preloader.py +0 -0
  329. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/shell_jobs.py +0 -0
  330. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/shell_output.py +0 -0
  331. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/subprojects.py +0 -0
  332. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/task_store.py +0 -0
  333. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/telemetry.py +0 -0
  334. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/terminal_launch.py +0 -0
  335. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/text_index.py +0 -0
  336. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/time_tracker.py +0 -0
  337. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/tool_classifier.py +0 -0
  338. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/transcript_index.py +0 -0
  339. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/validation_cache.py +0 -0
  340. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/vector_store.py +0 -0
  341. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/watcher.py +0 -0
  342. {code_context_control-2.145.2 → code_context_control-2.149.1}/services/win_subprocess.py +0 -0
  343. {code_context_control-2.145.2 → code_context_control-2.149.1}/setup.cfg +0 -0
  344. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_access_builtin_optout.py +0 -0
  345. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_access_guard.py +0 -0
  346. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_access_guard_meta.py +0 -0
  347. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_access_guard_shell_project.py +0 -0
  348. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_access_guard_surfaces.py +0 -0
  349. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_access_guard_wiring.py +0 -0
  350. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_activity_reporter.py +0 -0
  351. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_agent_locks.py +0 -0
  352. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_aider_polyglot.py +0 -0
  353. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_antigravity_transition.py +0 -0
  354. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_artifact_store.py +0 -0
  355. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_artifact_tool.py +0 -0
  356. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_atomic_json.py +0 -0
  357. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_background_service.py +0 -0
  358. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_bitbucket_cli_smoke.py +0 -0
  359. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_bitbucket_client.py +0 -0
  360. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_bitbucket_config_fallback.py +0 -0
  361. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_bitbucket_credentials.py +0 -0
  362. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_bitbucket_tool.py +0 -0
  363. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_builtin_modes.py +0 -0
  364. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_c3_bridge_project_artifacts.py +0 -0
  365. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_c3_shell.py +0 -0
  366. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_chat_poll.py +0 -0
  367. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ci_cache.py +0 -0
  368. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ci_dag_ownership.py +0 -0
  369. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ci_expr.py +0 -0
  370. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ci_impact.py +0 -0
  371. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ci_intel.py +0 -0
  372. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ci_runner.py +0 -0
  373. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ci_workflow.py +0 -0
  374. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_circuit_breaker.py +0 -0
  375. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_claude_md_merge.py +0 -0
  376. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_claude_md_updater.py +0 -0
  377. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_cli_smoke.py +0 -0
  378. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_codex_mcp_transport.py +0 -0
  379. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_codex_native.py +0 -0
  380. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_compressor_large_file.py +0 -0
  381. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_confirm_guard.py +0 -0
  382. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_confirm_guard_wiring.py +0 -0
  383. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_cooccurrence_bounds.py +0 -0
  384. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_cred_telemetry.py +0 -0
  385. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_credential_backup.py +0 -0
  386. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_credential_login_kind.py +0 -0
  387. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_credential_ui_parity.py +0 -0
  388. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_credentials_routes.py +0 -0
  389. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_credentials_tool.py +0 -0
  390. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_creds_cli_smoke.py +0 -0
  391. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_adoption_d4.py +0 -0
  392. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_auto.py +0 -0
  393. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_cascade.py +0 -0
  394. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_claude_d1.py +0 -0
  395. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_eval.py +0 -0
  396. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_grok.py +0 -0
  397. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_host_d2.py +0 -0
  398. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_scout_d3.py +0 -0
  399. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_telemetry_d0.py +0 -0
  400. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_thinking_cap.py +0 -0
  401. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_tuning.py +0 -0
  402. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_version_probe.py +0 -0
  403. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_write.py +0 -0
  404. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_delegate_write_eval.py +0 -0
  405. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_dir_map_c3.py +0 -0
  406. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_e2e_benchmark.py +0 -0
  407. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_edit_ledger_deadline.py +0 -0
  408. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_edit_ledger_hook.py +0 -0
  409. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_edit_locking.py +0 -0
  410. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_edit_normalization.py +0 -0
  411. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_edit_verify.py +0 -0
  412. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_embedding_index_corrupt_store.py +0 -0
  413. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_embedding_index_deadlock.py +0 -0
  414. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_enforcement_flip.py +0 -0
  415. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_enforcement_policy.py +0 -0
  416. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_enforcement_routes.py +0 -0
  417. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_env_parser.py +0 -0
  418. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_failed_calls_do_not_unlock.py +0 -0
  419. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_federated_graph.py +0 -0
  420. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_file_map_c1.py +0 -0
  421. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_filter_backoff.py +0 -0
  422. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ghost_files.py +0 -0
  423. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ghost_generation.py +0 -0
  424. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_git_branch_awareness.py +0 -0
  425. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_grok_native.py +0 -0
  426. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_access_guard.py +0 -0
  427. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_codex_compat.py +0 -0
  428. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_dispatch.py +0 -0
  429. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_grok_compat.py +0 -0
  430. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_pretool_enforce.py +0 -0
  431. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_prompt_recall.py +0 -0
  432. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_session_end.py +0 -0
  433. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_smoke.py +0 -0
  434. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_state.py +0 -0
  435. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hook_utf8_stdio.py +0 -0
  436. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_credentials_route.py +0 -0
  437. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_hook_migration.py +0 -0
  438. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_inspect_api.py +0 -0
  439. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_oracle_service_routes.py +0 -0
  440. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_override_policy_routes.py +0 -0
  441. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_override_routes.py +0 -0
  442. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_server_smoke.py +0 -0
  443. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_hub_subproject_links.py +0 -0
  444. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ide_workflow_adaptation.py +0 -0
  445. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_index_cap_not_hardcoded.py +0 -0
  446. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_init_clear_preserves_user_content.py +0 -0
  447. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_init_scan.py +0 -0
  448. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_install_mcp_entrypoint.py +0 -0
  449. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_jira_cli_smoke.py +0 -0
  450. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_jira_client.py +0 -0
  451. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_jira_config_fallback.py +0 -0
  452. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_jira_credentials.py +0 -0
  453. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_jira_links.py +0 -0
  454. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_jira_routes.py +0 -0
  455. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_jira_tool.py +0 -0
  456. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_large_files_c4.py +0 -0
  457. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_lazy_store_init.py +0 -0
  458. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_map_eval.py +0 -0
  459. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_map_telemetry_c0.py +0 -0
  460. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mask_guard.py +0 -0
  461. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mask_routes.py +0 -0
  462. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mask_surfaces.py +0 -0
  463. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mcp_host_guard.py +0 -0
  464. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mcp_memory_timeout.py +0 -0
  465. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mcp_server_smoke.py +0 -0
  466. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mcp_toml.py +0 -0
  467. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_memory_distiller.py +0 -0
  468. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_memory_graph_api.py +0 -0
  469. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_memory_queue.py +0 -0
  470. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_memory_system.py +0 -0
  471. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mobile_api.py +0 -0
  472. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mobile_clients.py +0 -0
  473. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mobile_extras.py +0 -0
  474. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mobile_jobs_ci.py +0 -0
  475. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mobile_override_costs.py +0 -0
  476. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mobile_override_routes.py +0 -0
  477. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_mobile_security_api.py +0 -0
  478. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_no_stale_model_pins.py +0 -0
  479. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_notification_dedup.py +0 -0
  480. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_notification_discipline.py +0 -0
  481. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_notification_kinds.py +0 -0
  482. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ollama_credentials.py +0 -0
  483. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_api_auth.py +0 -0
  484. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_apikey_api.py +0 -0
  485. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_c3_bridge.py +0 -0
  486. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_chat_engine.py +0 -0
  487. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_chat_store.py +0 -0
  488. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_discovery_api.py +0 -0
  489. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_discovery_audit.py +0 -0
  490. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_health_probe.py +0 -0
  491. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_local_auth.py +0 -0
  492. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_loopback.py +0 -0
  493. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_ollama_bridge.py +0 -0
  494. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_scanner_cache.py +0 -0
  495. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_security_fixes.py +0 -0
  496. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_session_bootstrap.py +0 -0
  497. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_subproject_awareness.py +0 -0
  498. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_oracle_ui_bundle.py +0 -0
  499. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_output_filter.py +0 -0
  500. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_override_costs.py +0 -0
  501. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_override_grants.py +0 -0
  502. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_override_grants_mcp.py +0 -0
  503. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_override_requests.py +0 -0
  504. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_override_wake.py +0 -0
  505. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_permissions.py +0 -0
  506. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_pm_api.py +0 -0
  507. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_project_manager.py +0 -0
  508. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_project_manager_merge.py +0 -0
  509. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_project_tool.py +0 -0
  510. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_read_coercion.py +0 -0
  511. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_read_edit_parity.py +0 -0
  512. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_read_outside_root.py +0 -0
  513. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_related_facts.py +0 -0
  514. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_repo_map.py +0 -0
  515. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_repo_shape.py +0 -0
  516. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_response_boilerplate.py +0 -0
  517. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_retention.py +0 -0
  518. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_review_digest.py +0 -0
  519. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_search_eval.py +0 -0
  520. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_search_p1.py +0 -0
  521. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_search_p2.py +0 -0
  522. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_search_p2b.py +0 -0
  523. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_search_p3.py +0 -0
  524. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_search_p4.py +0 -0
  525. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_search_p5.py +0 -0
  526. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_service_durability.py +0 -0
  527. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_session_benchmark.py +0 -0
  528. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_session_budget.py +0 -0
  529. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_session_live.py +0 -0
  530. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_session_tool.py +0 -0
  531. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_budget_s1.py +0 -0
  532. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_creds.py +0 -0
  533. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_eval.py +0 -0
  534. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_jobs_s3.py +0 -0
  535. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_nudge_s4.py +0 -0
  536. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_output.py +0 -0
  537. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_parsers_s2.py +0 -0
  538. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_robustness.py +0 -0
  539. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_telemetry_s0.py +0 -0
  540. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_write_ledger.py +0 -0
  541. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_shell_writes.py +0 -0
  542. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_subproject_clear_scope.py +0 -0
  543. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_subproject_depth_consumers.py +0 -0
  544. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_subproject_exclusion.py +0 -0
  545. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_subproject_federation.py +0 -0
  546. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_subproject_linkage_api.py +0 -0
  547. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_subprojects.py +0 -0
  548. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_swe_bench.py +0 -0
  549. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_task_store.py +0 -0
  550. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_task_tool.py +0 -0
  551. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_time_tracker.py +0 -0
  552. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_token_telemetry.py +0 -0
  553. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_tool_registry.py +0 -0
  554. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_ui_jsx_syntax.py +0 -0
  555. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_upgrade_and_version.py +0 -0
  556. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_validate.py +0 -0
  557. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_vault_write_guard.py +0 -0
  558. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_version_sync.py +0 -0
  559. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_watcher_pruning.py +0 -0
  560. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_web_security.py +0 -0
  561. {code_context_control-2.145.2 → code_context_control-2.149.1}/tests/test_windows_reliability.py +0 -0
  562. {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/__init__.py +0 -0
  563. {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/backend.py +0 -0
  564. {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/main.py +0 -0
  565. {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/__init__.py +0 -0
  566. {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/benchmark_view.py +0 -0
  567. {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/claudemd_view.py +0 -0
  568. {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/compress_view.py +0 -0
  569. {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/index_view.py +0 -0
  570. {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/init_view.py +0 -0
  571. {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/mcp_view.py +0 -0
  572. {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/optimize_view.py +0 -0
  573. {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/pipe_view.py +0 -0
  574. {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/projects_view.py +0 -0
  575. {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/search_view.py +0 -0
  576. {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/session_view.py +0 -0
  577. {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/stats.py +0 -0
  578. {code_context_control-2.145.2 → code_context_control-2.149.1}/tui/screens/ui_view.py +0 -0
  579. {code_context_control-2.145.2 → code_context_control-2.149.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.145.2
3
+ Version: 2.149.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
@@ -91,7 +91,7 @@ console = Console() if HAS_RICH else None
91
91
  # Config
92
92
  CONFIG_DIR = ".c3"
93
93
  CONFIG_FILE = ".c3/config.json"
94
- __version__ = "2.145.2"
94
+ __version__ = "2.149.1"
95
95
 
96
96
  # The PreToolUse matcher for native subagent calls (installer and hub migration).
97
97
  AGENT_MATCHER = "Agent|Task"
@@ -6685,10 +6685,10 @@ def _creds_cmd_list(args, project_path: str) -> None:
6685
6685
  "(add --global for all projects).")
6686
6686
  return
6687
6687
  print(f"{len(entries)} credential(s) — project scope shadows global:")
6688
+ present = cred_store.presence_for(entries, project_path)
6688
6689
  missing = 0
6689
6690
  for name, entry in entries.items():
6690
- gone = not cred_store.is_resolvable(
6691
- name, project_path=project_path, scope=entry["scope"])
6691
+ gone = not present[name]
6692
6692
  missing += gone
6693
6693
  print(" " + _creds_entry_line(name, entry, gone))
6694
6694
  if missing:
@@ -447,6 +447,7 @@ def run(payload: dict, project_path: Path | None = None,
447
447
  tool_input = payload.get("tool_input", {}) or {}
448
448
  base = str(project_path if project_path is not None else Path.cwd())
449
449
  session_id = str(payload.get("session_id") or "")
450
+ ag.bind_session(session_id)
450
451
 
451
452
  if tool in _WRITE_TOOLS or tool in _READ_TOOLS:
452
453
  fp = _target(tool_input)
@@ -72,6 +72,10 @@ _HUB_CONFIG_DEFAULTS = {
72
72
  "projects_view": "list",
73
73
  "main_view": "projects",
74
74
  "oracle_url": "",
75
+ # Per-IDE launch command overrides, e.g. {"claude-code": "yep"} when the
76
+ # agent is started through a wrapper script instead of the stock binary.
77
+ # A project's own `ide_cmd` (projects.json) wins over this.
78
+ "ide_cmds": {},
75
79
  # Minutes of project silence, with no session heartbeat left, before a UI
76
80
  # server that an IDE session launched is stopped. 0 = never reap.
77
81
  "ui_reap_minutes": 30,
@@ -81,6 +85,48 @@ _HUB_CONFIG_DEFAULTS = {
81
85
  _MAIN_VIEWS = {"projects", "board", "ci", "creds", "tokens", "locks", "access",
82
86
  "enforce", "sessions"}
83
87
 
88
+ # Stock command per IDE id, and whether it takes the project path as an
89
+ # argument (GUI) instead of being run inside a terminal at that path.
90
+ _IDE_DEFAULT_CMDS = {
91
+ "claude-code": ("claude", False),
92
+ "claude-app": ("claude-app", True),
93
+ "codex": ("codex", False),
94
+ "grok": ("grok", False),
95
+ "gemini": ("gemini", False),
96
+ "antigravity": ("antigravity", False),
97
+ "vscode": ("code", True),
98
+ "cursor": ("cursor", True),
99
+ }
100
+
101
+
102
+ def _resolve_ide_cmd(ide: str, path: str, custom_cmd: str = "") -> tuple:
103
+ """Resolve the command to launch for `ide` in `path`.
104
+
105
+ Precedence: explicit custom_cmd (this launch) → the project's stored
106
+ `ide_cmd` → hub config `ide_cmds[ide]` → the stock command.
107
+ Returns (cmd, is_gui, error) — error is a message when nothing resolves.
108
+ """
109
+ default_cmd, is_gui = _IDE_DEFAULT_CMDS.get(ide, ("", False))
110
+ if ide != "custom" and not default_cmd:
111
+ return "", False, f"Unknown IDE: {ide}"
112
+ cmd = (custom_cmd or "").strip()
113
+ if not cmd:
114
+ try:
115
+ cmd = _pm().get_ide_cmd(path)
116
+ except Exception:
117
+ cmd = ""
118
+ if not cmd:
119
+ overrides = _read_hub_config().get("ide_cmds") or {}
120
+ if isinstance(overrides, dict):
121
+ cmd = str(overrides.get(ide) or "").strip()
122
+ if not cmd:
123
+ cmd = default_cmd
124
+ if not cmd:
125
+ return "", False, "custom_cmd is required for custom IDE"
126
+ # An overridden command replaces the binary, not the launch style: a
127
+ # wrapper for a terminal CLI is still a terminal CLI.
128
+ return cmd, is_gui, ""
129
+
84
130
  # How often the hub reaps orphaned UI servers and chases autostart projects.
85
131
  _UI_SWEEP_INTERVAL_S = 60
86
132
 
@@ -460,6 +506,15 @@ def api_hub_config_set():
460
506
  cfg["main_view"] = main_view
461
507
  if "oracle_url" in data:
462
508
  cfg["oracle_url"] = str(data["oracle_url"]).strip()
509
+ if "ide_cmds" in data:
510
+ raw = data["ide_cmds"]
511
+ if not isinstance(raw, dict):
512
+ return jsonify({"error": "ide_cmds must be an object"}), 400
513
+ # Empty string = "back to the stock command", so the key is dropped
514
+ # rather than stored blank.
515
+ cfg["ide_cmds"] = {
516
+ str(k): str(v).strip() for k, v in raw.items() if str(v or "").strip()
517
+ }
463
518
  if "sidebar_group" in data:
464
519
  cfg["sidebar_group"] = str(data["sidebar_group"]).strip()
465
520
  if "sidebar_collapsed" in data:
@@ -718,17 +773,11 @@ def api_projects_open():
718
773
 
719
774
  @app.route("/api/projects/launch-ide", methods=["POST"])
720
775
  def api_launch_ide():
721
- """Launch an IDE or CLI tool in the project directory. Body: {path, ide, custom_cmd?}"""
722
- _IDE_CMDS = {
723
- "claude-code": ("claude", False),
724
- "claude-app": ("claude-app", True),
725
- "codex": ("codex", False),
726
- "grok": ("grok", False),
727
- "gemini": ("gemini", False),
728
- "antigravity": ("antigravity", False),
729
- "vscode": ("code", True),
730
- "cursor": ("cursor", True),
731
- }
776
+ """Launch an IDE or CLI tool in the project directory. Body: {path, ide, custom_cmd?}
777
+
778
+ The command itself is resolved by _resolve_ide_cmd, so a project or the
779
+ hub can point `claude-code` at a wrapper such as `yep`.
780
+ """
732
781
  try:
733
782
  data = request.get_json(force=True) or {}
734
783
  path_str = (data.get("path") or "").strip()
@@ -744,14 +793,9 @@ def api_launch_ide():
744
793
  if not path.exists():
745
794
  return jsonify({"error": f"Path does not exist: {path_str}"}), 404
746
795
 
747
- if ide == "custom":
748
- if not custom_cmd:
749
- return jsonify({"error": "custom_cmd is required for custom IDE"}), 400
750
- cmd, is_gui = custom_cmd, False
751
- elif ide in _IDE_CMDS:
752
- cmd, is_gui = _IDE_CMDS[ide]
753
- else:
754
- return jsonify({"error": f"Unknown IDE: {ide}"}), 400
796
+ cmd, is_gui, err = _resolve_ide_cmd(ide, str(path), custom_cmd)
797
+ if err:
798
+ return jsonify({"error": err}), 400
755
799
 
756
800
  if is_gui:
757
801
  # GUI IDEs (VS Code, Cursor) accept a path argument directly
@@ -795,7 +839,7 @@ def api_launch_ide():
795
839
 
796
840
  @app.route("/api/projects/update", methods=["POST"])
797
841
  def api_projects_update():
798
- """Update editable project fields (name, tags, notes). Body: {path, name?, tags?, notes?}"""
842
+ """Update editable project fields. Body: {path, name?, tags?, notes?, ide_cmd?}"""
799
843
  data = request.get_json(force=True) or {}
800
844
  path = (data.get("path") or "").strip()
801
845
  if not path:
@@ -812,6 +856,9 @@ def api_projects_update():
812
856
  fields["tags"] = [t.strip() for t in str(raw).split(",") if t.strip()]
813
857
  if "notes" in data:
814
858
  fields["notes"] = str(data["notes"])
859
+ if "ide_cmd" in data:
860
+ # Blank clears the override and falls back to the stock command.
861
+ fields["ide_cmd"] = str(data["ide_cmd"] or "").strip()
815
862
  try:
816
863
  ok = _pm().update_project(path, **fields)
817
864
  return jsonify({"updated": ok})
@@ -1804,7 +1851,7 @@ def api_projects_browse():
1804
1851
  return jsonify({"error": str(e)}), 400
1805
1852
  if not resolved.is_dir():
1806
1853
  return jsonify({"error": f"Not a directory: {resolved}"}), 404
1807
- registered = {os.path.normcase(p.get("path", "")) for p in _pm()._read_projects()}
1854
+ registered = {os.path.normcase(p.get("path", "")) for p in _pm().list_registered()}
1808
1855
  dirs = []
1809
1856
  try:
1810
1857
  for child in sorted(resolved.iterdir(), key=lambda c: c.name.lower()):
@@ -1913,7 +1960,7 @@ def api_search_global():
1913
1960
  if wanted else None)
1914
1961
 
1915
1962
  candidates, skipped = [], []
1916
- for p in _pm().list_projects():
1963
+ for p in _pm().list_registered():
1917
1964
  ppath = p.get("path") or ""
1918
1965
  if wanted_norm is not None and os.path.normcase(ppath) not in wanted_norm:
1919
1966
  continue
@@ -2138,14 +2185,15 @@ def api_projects_credentials():
2138
2185
  usage = cred_store.read_usage_state(str(resolved))
2139
2186
  home = cred_store.global_base()
2140
2187
  global_names = set(cred_store.list_entries(str(home))) if home else set()
2188
+ listed = cred_store.list_entries(str(resolved))
2189
+ present = cred_store.presence_for(listed, str(resolved))
2141
2190
  entries = []
2142
- for name, entry in cred_store.list_entries(str(resolved)).items():
2191
+ for name, entry in listed.items():
2143
2192
  entries.append(_cred_entry_public(
2144
2193
  name, entry, usage=usage,
2145
2194
  shadows_global=(entry.get("scope") == "project"
2146
2195
  and name in global_names),
2147
- value_ok=cred_store.is_resolvable(
2148
- name, project_path=str(resolved), scope=entry["scope"])))
2196
+ value_ok=present[name]))
2149
2197
  return jsonify({"path": str(resolved), "entries": entries})
2150
2198
 
2151
2199
 
@@ -2360,7 +2408,7 @@ def api_hub_credentials_audit():
2360
2408
  only_global = (request.args.get("scope") or "").strip().lower() == "global"
2361
2409
 
2362
2410
  events, errors = [], []
2363
- for p in ([] if only_global else _pm().list_projects()):
2411
+ for p in ([] if only_global else _pm().list_registered()):
2364
2412
  ppath = str(p.get("path") or "")
2365
2413
  if not (Path(ppath) / ".c3").is_dir():
2366
2414
  continue
@@ -2417,9 +2465,12 @@ def api_hub_credentials_overview():
2417
2465
  from services import credential_store as cred_store
2418
2466
  home = cred_store.global_base()
2419
2467
  global_entries = cred_store.list_entries(str(home)) if home else {}
2468
+ # realm -> {name: value decodes}, probed once per vault and shared with
2469
+ # the backup banner, which asks the same question of the same entries.
2470
+ present = {"global": cred_store.value_presence("global", str(home))} if home else {}
2420
2471
  shadowed_in = {name: [] for name in global_entries}
2421
2472
  projects_out = []
2422
- for p in _pm().list_projects():
2473
+ for p in _pm().list_registered():
2423
2474
  ppath = str(p.get("path") or "")
2424
2475
  row = {"name": p.get("name") or "", "path": ppath,
2425
2476
  "initialized": True, "error": None, "entries": []}
@@ -2428,14 +2479,15 @@ def api_hub_credentials_overview():
2428
2479
  row["initialized"] = False
2429
2480
  else:
2430
2481
  usage = cred_store.read_usage_state(ppath)
2482
+ ok = cred_store.value_presence("project", ppath)
2483
+ present[cred_store.realm("project", ppath)] = ok
2431
2484
  for name, entry in cred_store.list_entries(ppath).items():
2432
2485
  if entry.get("scope") != "project":
2433
2486
  continue
2434
2487
  row["entries"].append(_cred_entry_public(
2435
2488
  name, entry, usage=usage,
2436
2489
  shadows_global=name in global_entries,
2437
- value_ok=cred_store.is_resolvable(
2438
- name, project_path=ppath, scope="project")))
2490
+ value_ok=ok.get(name, False)))
2439
2491
  if name in shadowed_in:
2440
2492
  shadowed_in[name].append(
2441
2493
  {"name": row["name"], "path": ppath})
@@ -2446,21 +2498,21 @@ def api_hub_credentials_overview():
2446
2498
  global_out = [
2447
2499
  {**_cred_entry_public(
2448
2500
  name, entry, usage=global_usage,
2449
- value_ok=cred_store.is_resolvable(
2450
- name, project_path=str(home), scope="global")),
2501
+ value_ok=present.get("global", {}).get(name, False)),
2451
2502
  "shadowed_in": shadowed_in.get(name, [])}
2452
2503
  for name, entry in global_entries.items()
2453
2504
  ]
2454
2505
  return jsonify({"global": {"entries": global_out}, "projects": projects_out,
2455
2506
  "backup": _cred_backup_summary(
2456
- [row["path"] for row in projects_out if row["initialized"]])})
2507
+ [row["path"] for row in projects_out if row["initialized"]],
2508
+ present)})
2457
2509
 
2458
2510
 
2459
- def _cred_backup_summary(project_paths) -> dict:
2511
+ def _cred_backup_summary(project_paths, present) -> dict:
2460
2512
  """Backup state as counts for the Hub banner; a broken file reports its error."""
2461
2513
  from services import credential_backup
2462
2514
  try:
2463
- st = credential_backup.status(project_paths)
2515
+ st = credential_backup.status(project_paths, presence=present)
2464
2516
  except credential_backup.BackupError as exc:
2465
2517
  return {"enabled": True, "error": str(exc), "restorable": 0, "lost": 0}
2466
2518
  return {"enabled": st["enabled"], "restorable": len(st["restorable"]),
@@ -2612,7 +2664,7 @@ def api_hub_tokens_overview():
2612
2664
  days = _hub_tokens_days(request.args.get("days"))
2613
2665
  rows, totals = [], {"tool_calls": 0, "tool_tokens": 0,
2614
2666
  "session_tokens": 0, "saved": 0}
2615
- for p in _pm().list_projects():
2667
+ for p in _pm().list_registered():
2616
2668
  ppath = str(p.get("path") or "")
2617
2669
  row = {"name": p.get("name") or "", "path": ppath, "initialized": True,
2618
2670
  "error": None, "tool_calls": 0, "tool_tokens": 0,
@@ -2662,7 +2714,7 @@ def api_hub_locks_overview():
2662
2714
  from services import agent_locks as al
2663
2715
 
2664
2716
  rows, total = [], 0
2665
- for p in _pm().list_projects():
2717
+ for p in _pm().list_registered():
2666
2718
  ppath = str(p.get("path") or "")
2667
2719
  row = {"name": p.get("name") or "", "path": ppath, "initialized": True,
2668
2720
  "error": None, "enabled": True, "mode": "advisory",
@@ -2752,7 +2804,7 @@ def api_hub_enforcement_overview():
2752
2804
 
2753
2805
  rows = []
2754
2806
  totals = {"discipline": 0, "access": 0}
2755
- for p in _pm().list_projects():
2807
+ for p in _pm().list_registered():
2756
2808
  ppath = str(p.get("path") or "")
2757
2809
  row = {"name": p.get("name") or "", "path": ppath, "initialized": True,
2758
2810
  "error": None, "mode": None, "scope": "", "set_by": "",
@@ -3428,7 +3480,7 @@ def api_hub_override_policy_overview():
3428
3480
  from services import override_policy as opol
3429
3481
 
3430
3482
  rows = []
3431
- for p in _pm().list_projects():
3483
+ for p in _pm().list_registered():
3432
3484
  ppath = str(p.get("path") or "")
3433
3485
  row = {"name": p.get("name") or Path(ppath).name, "path": ppath,
3434
3486
  "initialized": True, "error": None, "policy": None,
@@ -3740,7 +3792,7 @@ def api_hub_access_overview():
3740
3792
  empty = {"deny": [], "read_only": [], "confirm": [], "mask": 0,
3741
3793
  "corrupt": False}
3742
3794
  rows = []
3743
- for p in _pm().list_projects():
3795
+ for p in _pm().list_registered():
3744
3796
  ppath = str(p.get("path") or "")
3745
3797
  row = {"name": p.get("name") or Path(ppath).name, "path": ppath,
3746
3798
  "initialized": True, "error": None, "rules": dict(empty)}
@@ -3834,6 +3886,170 @@ def api_hub_access_rule_remove():
3834
3886
  return jsonify(result)
3835
3887
 
3836
3888
 
3889
+ # ── Builtin guard modes (v2.147.0) ─────────────────────────────────────────
3890
+
3891
+ def _hub_human():
3892
+ """The Desk client behind ``Authorization: Bearer``, else ``None``.
3893
+
3894
+ Loopback and the CSRF guard stop a browser, not a process on this
3895
+ machine: an agent can POST here as easily as a person. A Desk client
3896
+ token is minted only with ``bootstrap.key``, which Access Guard denies
3897
+ to agents, and is stored as a hash, so presenting one is the proof a
3898
+ loosening builtin change needs. A phone token does not count: builtin
3899
+ guards are not loosened from a device that leaves the building.
3900
+ """
3901
+ from oracle.services import client_tokens
3902
+ scheme, _, token = (request.headers.get("Authorization") or "").partition(" ")
3903
+ if scheme.lower() != "bearer" or not token.strip():
3904
+ return None
3905
+ who = client_tokens.principal_for(token.strip())
3906
+ return who if who and who.get("kind") == "desk" else None
3907
+
3908
+
3909
+ @app.route("/api/hub/access/builtin", methods=["GET"])
3910
+ def api_hub_access_builtin():
3911
+ """Every Tier-1 builtin with its live global mode, and each project's own.
3912
+
3913
+ Modes are read through the keyring (config and attestation must agree),
3914
+ so a mode listed here is one evaluation honours. ``projects`` holds only
3915
+ projects that set a mode of their own, or could not be read.
3916
+ ``strictness`` ranks each mode 0 (allow) to 3 (full deny), so a client
3917
+ can tell loosening from tightening without knowing the tiers.
3918
+ """
3919
+ try:
3920
+ global_modes = access_guard._scope_modes("global")
3921
+ except Exception as e:
3922
+ return jsonify({"error": str(e)}), 500
3923
+ home = access_guard._global_base()
3924
+ guards = []
3925
+ for glob in access_guard.DISABLEABLE_BUILTINS:
3926
+ canon = access_guard._norm_builtin(glob)
3927
+ guards.append({
3928
+ "glob": canon,
3929
+ "global": global_modes.get(canon, "default"),
3930
+ "strictness": {m: access_guard.builtin_strictness(canon, m)
3931
+ for m in (*access_guard.BUILTIN_MODES, "default")},
3932
+ })
3933
+ projects = []
3934
+ for p in _pm().list_registered():
3935
+ ppath = str(p.get("path") or "")
3936
+ row = {"name": p.get("name") or Path(ppath).name, "path": ppath,
3937
+ "modes": {}, "error": None}
3938
+ try:
3939
+ base = Path(ppath).resolve()
3940
+ if (base / ".c3").is_dir() and base != home:
3941
+ row["modes"] = access_guard._scope_modes("project", ppath)
3942
+ except Exception as e:
3943
+ row["error"] = str(e)
3944
+ if row["modes"] or row["error"]:
3945
+ projects.append(row)
3946
+ from services import builtin_leases
3947
+ return jsonify({"guards": guards, "projects": projects,
3948
+ "leases": builtin_leases.active()})
3949
+
3950
+
3951
+ @app.route("/api/hub/access/builtin/mode", methods=["POST"])
3952
+ def api_hub_access_builtin_mode():
3953
+ """Set a Tier-1 builtin's mode in the global realm or one project's.
3954
+
3955
+ Body: ``{scope, path?, glob, mode, confirm?}``. A mode at least as strict
3956
+ as the live one needs nothing more. A looser one needs a Desk client
3957
+ token (403 ``needs_human`` without it) and ``confirm`` equal to the glob
3958
+ (400 ``needs_confirmation``). A project is judged against what its
3959
+ agents see today, which is the global mode unless it set its own.
3960
+ """
3961
+ data = request.get_json(silent=True) or {}
3962
+ scope, project, err = _hub_access_target(data)
3963
+ if err:
3964
+ return err
3965
+ glob = str(data.get("glob") or "")
3966
+ mode = str(data.get("mode") or "").strip()
3967
+ canon = access_guard._norm_builtin(glob)
3968
+ try:
3969
+ new = access_guard.builtin_strictness(canon, mode)
3970
+ live = (access_guard._scope_modes("global") if scope == "global"
3971
+ else access_guard.effective_builtin_modes(project))
3972
+ old = access_guard.builtin_strictness(canon, live.get(canon, "default"))
3973
+ except ValueError as exc:
3974
+ return jsonify({"error": str(exc)}), 400
3975
+ if new < old:
3976
+ if _hub_human() is None:
3977
+ return jsonify({
3978
+ "error": "loosening a built-in guard needs C3 Desk",
3979
+ "needs_human": True,
3980
+ "command": f'c3 access builtin mode "{canon}" {mode}'
3981
+ + (f' --project --path "{project}"'
3982
+ if scope == "project" else ""),
3983
+ }), 403
3984
+ if access_guard._norm_builtin(data.get("confirm")) != canon:
3985
+ return jsonify({
3986
+ "error": "loosening a built-in guard weakens protection",
3987
+ "needs_confirmation": True, "confirm_with": canon,
3988
+ }), 400
3989
+ try:
3990
+ result = access_guard.set_builtin_mode(canon, mode, scope,
3991
+ project or ".")
3992
+ except ValueError as exc:
3993
+ return jsonify({"error": str(exc)}), 400
3994
+ if result["changed"]:
3995
+ _hub_access_audit(f"builtin_mode_{result['mode']}", result["glob"],
3996
+ "builtin", scope, project)
3997
+ return jsonify({**result, "loosened": new < old})
3998
+
3999
+
4000
+ @app.route("/api/hub/access/builtin/lease", methods=["POST"])
4001
+ def api_hub_access_builtin_lease():
4002
+ """Loosen a builtin for a while: every session, or one.
4003
+
4004
+ Body: ``{scope, path?, glob, mode, ttl_s, session_id?, confirm}``. A
4005
+ lease only ever loosens, so it always needs a Desk client token and the
4006
+ glob typed back, and a lease no looser than the live mode is a 400
4007
+ rather than a row that would never apply. ``ttl_s`` is 60 s to 8 h.
4008
+ """
4009
+ from services import builtin_leases
4010
+ data = request.get_json(silent=True) or {}
4011
+ scope, project, err = _hub_access_target(data)
4012
+ if err:
4013
+ return err
4014
+ who = _hub_human()
4015
+ if who is None:
4016
+ return jsonify({"error": "a temporary built-in change needs C3 Desk",
4017
+ "needs_human": True}), 403
4018
+ canon = access_guard._norm_builtin(data.get("glob"))
4019
+ mode = str(data.get("mode") or "").strip()
4020
+ if access_guard._norm_builtin(data.get("confirm")) != canon or not canon:
4021
+ return jsonify({"error": "a temporary change weakens protection",
4022
+ "needs_confirmation": True, "confirm_with": canon}), 400
4023
+ try:
4024
+ live = access_guard.effective_builtin_modes(project or ".") \
4025
+ if scope == "project" else access_guard._scope_modes("global")
4026
+ if access_guard.builtin_strictness(canon, mode) >= \
4027
+ access_guard.builtin_strictness(canon, live.get(canon, "default")):
4028
+ return jsonify({"error": f"{canon} is already {live.get(canon, 'default')}"
4029
+ f" — a {mode} lease would change nothing"}), 400
4030
+ row = builtin_leases.mint(
4031
+ canon, mode, scope=scope, project_path=project or ".",
4032
+ session_id=str(data.get("session_id") or ""),
4033
+ ttl_s=data.get("ttl_s"), created_by=who["client_id"])
4034
+ except ValueError as exc:
4035
+ return jsonify({"error": str(exc)}), 400
4036
+ _hub_access_audit(f"builtin_lease_{mode}", canon, "builtin", scope, project)
4037
+ return jsonify({"lease": row})
4038
+
4039
+
4040
+ @app.route("/api/hub/access/builtin/lease/revoke", methods=["POST"])
4041
+ def api_hub_access_builtin_lease_revoke():
4042
+ """End a lease now. Tightening, so no token. Body: ``{id}``."""
4043
+ from services import builtin_leases
4044
+ lease_id = str((request.get_json(silent=True) or {}).get("id") or "")
4045
+ gone = builtin_leases.revoke(lease_id) if lease_id else None
4046
+ if gone is None:
4047
+ return jsonify({"error": "unknown or already-expired lease"}), 404
4048
+ _hub_access_audit("builtin_lease_revoke", gone["glob"], "builtin",
4049
+ gone["scope"], gone.get("project_path") or None)
4050
+ return jsonify({"revoked": lease_id})
4051
+
4052
+
3837
4053
  # ── Project management: tasks / milestones / notes (v2.45.0) ──────────────
3838
4054
  # Direct TaskStore per request (reload-per-op store — no runtime build needed
3839
4055
  # for mutations); every write audited to the target project's activity log.
@@ -4268,7 +4484,7 @@ def api_pm_global():
4268
4484
  from services.task_store import TaskStore
4269
4485
 
4270
4486
  tasks, skipped, by_project = [], [], {}
4271
- entries = _pm()._read_projects()
4487
+ entries = _pm().list_registered()
4272
4488
  for p in entries:
4273
4489
  ppath = p.get("path") or ""
4274
4490
  if not Path(ppath).is_dir():
@@ -4808,7 +5024,7 @@ def _session_project(raw: str):
4808
5024
  if not raw:
4809
5025
  return None
4810
5026
  want = os.path.normcase(os.path.normpath(raw))
4811
- for p in _pm().list_projects():
5027
+ for p in _pm().list_registered():
4812
5028
  path = str(p.get("path") or "")
4813
5029
  if path and os.path.normcase(os.path.normpath(path)) == want:
4814
5030
  return {"name": str(p.get("name") or Path(path).name), "path": path}
@@ -4847,7 +5063,7 @@ def api_hub_sessions_overview():
4847
5063
  return row
4848
5064
 
4849
5065
  with ThreadPoolExecutor(max_workers=8) as pool:
4850
- rows = list(pool.map(one, _pm().list_projects()))
5066
+ rows = list(pool.map(one, _pm().list_registered()))
4851
5067
  rows.sort(key=lambda r: r.get("last_active") or "", reverse=True)
4852
5068
  return jsonify({"projects": rows, "features": _SESSIONS_FEATURES})
4853
5069
 
@@ -4876,7 +5092,7 @@ def api_hub_sessions_list():
4876
5092
  res["errors"] = []
4877
5093
  else:
4878
5094
  projects = [{"name": str(p.get("name") or ""), "path": str(p.get("path") or "")}
4879
- for p in _pm().list_projects()]
5095
+ for p in _pm().list_registered()]
4880
5096
  res = sc.list_many(projects, stale=stale, q=q, limit=limit, before=before)
4881
5097
  return jsonify(res)
4882
5098
  except Exception as e:
@@ -50,7 +50,10 @@ function App() {
50
50
  }, []);
51
51
 
52
52
  useEffect(() => { loadConfig(); loadProjects(); }, []);
53
- usePoll(loadProjects, 5000);
53
+ // Live status matters on the project list and in a drill-in. Elsewhere it
54
+ // only refreshes the sidebar and top-bar counts, which may lag 30 s, and
55
+ // each poll reads every project's activity log.
56
+ usePoll(loadProjects, mainView === 'projects' || drill ? 5000 : 30000);
54
57
 
55
58
  // Persisted preferences
56
59
  const toggleTheme = () => {