code-context-control 2.85.0__tar.gz → 2.88.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (439) hide show
  1. {code_context_control-2.85.0/code_context_control.egg-info → code_context_control-2.88.2}/PKG-INFO +3 -2
  2. {code_context_control-2.85.0 → code_context_control-2.88.2}/README.md +2 -1
  3. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/c3.py +146 -9
  4. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/commands/parser.py +15 -2
  5. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/guide/credentials.html +80 -0
  6. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hook_access_guard.py +25 -3
  7. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hook_pretool_enforce.py +2 -1
  8. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_server.py +47 -2
  9. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/drill_panel.js +2 -2
  10. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/hub_credentials.js +227 -23
  11. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/mcp_server.py +21 -7
  12. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/server.py +48 -10
  13. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/credentials.py +105 -4
  14. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/shell.py +108 -8
  15. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/tasks.py +22 -1
  16. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/components/credentials.js +251 -23
  17. {code_context_control-2.85.0 → code_context_control-2.88.2/code_context_control.egg-info}/PKG-INFO +3 -2
  18. {code_context_control-2.85.0 → code_context_control-2.88.2}/code_context_control.egg-info/SOURCES.txt +2 -0
  19. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/oracle_server.py +4 -4
  20. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/local_session.py +28 -0
  21. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/mobile_api.py +43 -0
  22. {code_context_control-2.85.0 → code_context_control-2.88.2}/pyproject.toml +1 -1
  23. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/access_guard.py +27 -0
  24. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/claude_md.py +1 -1
  25. code_context_control-2.88.2/services/cred_telemetry.py +303 -0
  26. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/credential_store.py +399 -23
  27. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/parser.py +24 -0
  28. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/scanner.py +35 -0
  29. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/task_store.py +63 -0
  30. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_access_guard.py +72 -0
  31. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_c3_shell.py +101 -0
  32. code_context_control-2.88.2/tests/test_cred_telemetry.py +189 -0
  33. code_context_control-2.88.2/tests/test_credential_store.py +525 -0
  34. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_credentials_routes.py +82 -0
  35. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_credentials_tool.py +96 -0
  36. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_delegate_cascade.py +52 -1
  37. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_hook_access_guard.py +30 -0
  38. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_hub_credentials_routes_write.py +54 -0
  39. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_init_scan.py +76 -0
  40. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_mobile_security_api.py +32 -1
  41. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_oracle_session_bootstrap.py +101 -0
  42. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_pm_api.py +25 -0
  43. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_shell_creds.py +85 -2
  44. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_task_store.py +45 -0
  45. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_task_tool.py +13 -0
  46. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_validate.py +57 -0
  47. code_context_control-2.85.0/tests/test_credential_store.py +0 -270
  48. {code_context_control-2.85.0 → code_context_control-2.88.2}/LICENSE +0 -0
  49. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/__init__.py +0 -0
  50. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/_hook_utils.py +0 -0
  51. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/commands/__init__.py +0 -0
  52. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/commands/common.py +0 -0
  53. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/docs.html +0 -0
  54. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/edits.html +0 -0
  55. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/guide/access.html +0 -0
  56. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/guide/bitbucket.html +0 -0
  57. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/guide/getting-started.html +0 -0
  58. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/guide/index.html +0 -0
  59. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/guide/masking.html +0 -0
  60. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/guide/oracle.html +0 -0
  61. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/guide/shared.css +0 -0
  62. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/guide/tools.html +0 -0
  63. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/guide/workflow.html +0 -0
  64. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hook_artifact.py +0 -0
  65. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hook_auto_snapshot.py +0 -0
  66. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hook_c3_signal.py +0 -0
  67. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hook_c3read.py +0 -0
  68. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hook_dispatch.py +0 -0
  69. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hook_edit_ledger.py +0 -0
  70. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hook_edit_unlock.py +0 -0
  71. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hook_filter.py +0 -0
  72. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hook_ghost_files.py +0 -0
  73. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hook_prompt_recall.py +0 -0
  74. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hook_read.py +0 -0
  75. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hook_session_stats.py +0 -0
  76. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hook_terse_advisor.py +0 -0
  77. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/app.js +0 -0
  78. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/add_project.js +0 -0
  79. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/config_editor.js +0 -0
  80. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/drill_artifacts.js +0 -0
  81. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/drill_health.js +0 -0
  82. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/drill_subprojects.js +0 -0
  83. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/drill_tasks.js +0 -0
  84. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/drill_views.js +0 -0
  85. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/global_search.js +0 -0
  86. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/hub_ci.js +0 -0
  87. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/hub_enforcement.js +0 -0
  88. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/hub_locks.js +0 -0
  89. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/mcp_manager.js +0 -0
  90. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/modals.js +0 -0
  91. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/project_card.js +0 -0
  92. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/project_tree.js +0 -0
  93. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/session_drawer.js +0 -0
  94. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/settings_modal.js +0 -0
  95. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/sidebar.js +0 -0
  96. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/summary_bar.js +0 -0
  97. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/task_board.js +0 -0
  98. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/toasts.js +0 -0
  99. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/components/topbar.js +0 -0
  100. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui/state.js +0 -0
  101. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/hub_ui.html +0 -0
  102. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/mcp_proxy.py +0 -0
  103. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/progress.py +0 -0
  104. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/__init__.py +0 -0
  105. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/_grants.py +0 -0
  106. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/_helpers.py +0 -0
  107. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/agent.py +0 -0
  108. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/artifacts.py +0 -0
  109. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/bitbucket.py +0 -0
  110. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/ci.py +0 -0
  111. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/compress.py +0 -0
  112. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/delegate.py +0 -0
  113. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/edit.py +0 -0
  114. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/edit_verify.py +0 -0
  115. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/edits.py +0 -0
  116. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/federate.py +0 -0
  117. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/filter.py +0 -0
  118. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/impact.py +0 -0
  119. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/jira.py +0 -0
  120. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/locks.py +0 -0
  121. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/memory.py +0 -0
  122. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/override.py +0 -0
  123. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/project.py +0 -0
  124. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/read.py +0 -0
  125. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/search.py +0 -0
  126. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/session.py +0 -0
  127. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/status.py +0 -0
  128. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/tools/validate.py +0 -0
  129. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/api.js +0 -0
  130. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/app.js +0 -0
  131. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/components/access.js +0 -0
  132. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/components/bitbucket.js +0 -0
  133. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/components/chat.js +0 -0
  134. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/components/dashboard.js +0 -0
  135. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/components/edits.js +0 -0
  136. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/components/enforcement.js +0 -0
  137. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/components/instructions.js +0 -0
  138. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/components/jira.js +0 -0
  139. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/components/memory.js +0 -0
  140. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/components/sessions.js +0 -0
  141. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/components/settings.js +0 -0
  142. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/components/sidebar.js +0 -0
  143. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/components/tasks.js +0 -0
  144. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/icons.js +0 -0
  145. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/pm_shared.js +0 -0
  146. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/shared.js +0 -0
  147. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui/theme.js +0 -0
  148. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui.html +0 -0
  149. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui_legacy.html +0 -0
  150. {code_context_control-2.85.0 → code_context_control-2.88.2}/cli/ui_nano.html +0 -0
  151. {code_context_control-2.85.0 → code_context_control-2.88.2}/code_context_control.egg-info/dependency_links.txt +0 -0
  152. {code_context_control-2.85.0 → code_context_control-2.88.2}/code_context_control.egg-info/entry_points.txt +0 -0
  153. {code_context_control-2.85.0 → code_context_control-2.88.2}/code_context_control.egg-info/requires.txt +0 -0
  154. {code_context_control-2.85.0 → code_context_control-2.88.2}/code_context_control.egg-info/top_level.txt +0 -0
  155. {code_context_control-2.85.0 → code_context_control-2.88.2}/core/__init__.py +0 -0
  156. {code_context_control-2.85.0 → code_context_control-2.88.2}/core/config.py +0 -0
  157. {code_context_control-2.85.0 → code_context_control-2.88.2}/core/ide.py +0 -0
  158. {code_context_control-2.85.0 → code_context_control-2.88.2}/core/mcp_toml.py +0 -0
  159. {code_context_control-2.85.0 → code_context_control-2.88.2}/core/web_security.py +0 -0
  160. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/__init__.py +0 -0
  161. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/config.py +0 -0
  162. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/mcp_oracle.py +0 -0
  163. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/oracle_ui.html +0 -0
  164. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/__init__.py +0 -0
  165. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/activity_reporter.py +0 -0
  166. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/api_auth.py +0 -0
  167. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/c3_bridge.py +0 -0
  168. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/chat_engine.py +0 -0
  169. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/chat_poll.py +0 -0
  170. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/chat_store.py +0 -0
  171. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/cross_memory.py +0 -0
  172. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/discovery_audit.py +0 -0
  173. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/federated_graph.py +0 -0
  174. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/health_checker.py +0 -0
  175. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/insight_engine.py +0 -0
  176. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/memory_reader.py +0 -0
  177. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/memory_writer.py +0 -0
  178. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/project_scanner.py +0 -0
  179. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/review_agent.py +0 -0
  180. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/tool_executor.py +0 -0
  181. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/services/tool_registry.py +0 -0
  182. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/activity.js +0 -0
  183. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/agents.js +0 -0
  184. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/app.js +0 -0
  185. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/busy.js +0 -0
  186. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/chat/conversations.js +0 -0
  187. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/chat/input.js +0 -0
  188. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/chat/markdown.js +0 -0
  189. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/chat/send.js +0 -0
  190. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/chat/stream_renderer.js +0 -0
  191. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/chat/toolbar.js +0 -0
  192. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/core.js +0 -0
  193. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/crossgraph.js +0 -0
  194. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/header.js +0 -0
  195. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/insights.js +0 -0
  196. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/projects.js +0 -0
  197. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/qrcode.js +0 -0
  198. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/settings.js +0 -0
  199. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/suggestions.js +0 -0
  200. {code_context_control-2.85.0 → code_context_control-2.88.2}/oracle/ui/theme_tabs.js +0 -0
  201. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/__init__.py +0 -0
  202. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/access_telemetry.py +0 -0
  203. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/activity_log.py +0 -0
  204. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/agent_base.py +0 -0
  205. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/agent_locks.py +0 -0
  206. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/agents.py +0 -0
  207. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/artifact_defs.py +0 -0
  208. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/artifact_store.py +0 -0
  209. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/auto_memory.py +0 -0
  210. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/bench/__init__.py +0 -0
  211. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/bench/external/__init__.py +0 -0
  212. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/bench/external/aider_polyglot.py +0 -0
  213. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/bench/external/swe_bench.py +0 -0
  214. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/benchmark_dashboard.py +0 -0
  215. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/bitbucket_client.py +0 -0
  216. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/bitbucket_credentials.py +0 -0
  217. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/ci_act.py +0 -0
  218. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/ci_cache.py +0 -0
  219. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/ci_expr.py +0 -0
  220. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/ci_failures.py +0 -0
  221. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/ci_github.py +0 -0
  222. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/ci_impact.py +0 -0
  223. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/ci_intel.py +0 -0
  224. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/ci_runner.py +0 -0
  225. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/ci_workflow.py +0 -0
  226. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/circuit_breaker.py +0 -0
  227. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/compressor.py +0 -0
  228. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/context_snapshot.py +0 -0
  229. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/conversation_store.py +0 -0
  230. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/doc_index.py +0 -0
  231. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/e2e_benchmark.py +0 -0
  232. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/e2e_evaluator.py +0 -0
  233. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/e2e_tasks.py +0 -0
  234. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/edit_ledger.py +0 -0
  235. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/embedding_index.py +0 -0
  236. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/enforcement_policy.py +0 -0
  237. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/error_reporting.py +0 -0
  238. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/file_memory.py +0 -0
  239. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/git_context.py +0 -0
  240. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/hub_service.py +0 -0
  241. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/indexer.py +0 -0
  242. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/jira_client.py +0 -0
  243. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/jira_cloud.py +0 -0
  244. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/jira_credentials.py +0 -0
  245. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/jira_data_center.py +0 -0
  246. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/jira_links.py +0 -0
  247. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/mask_activation.py +0 -0
  248. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/mask_mirror.py +0 -0
  249. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/mask_presets.py +0 -0
  250. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/memory.py +0 -0
  251. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/memory_consolidator.py +0 -0
  252. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/memory_distiller.py +0 -0
  253. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/memory_graph.py +0 -0
  254. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/memory_grounder.py +0 -0
  255. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/memory_queue.py +0 -0
  256. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/memory_scorer.py +0 -0
  257. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/metrics.py +0 -0
  258. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/notifications.py +0 -0
  259. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/ollama_bridge.py +0 -0
  260. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/ollama_client.py +0 -0
  261. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/ollama_credentials.py +0 -0
  262. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/output_filter.py +0 -0
  263. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/override_grants.py +0 -0
  264. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/override_policy.py +0 -0
  265. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/override_requests.py +0 -0
  266. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/override_wake.py +0 -0
  267. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/project_manager.py +0 -0
  268. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/project_runtime.py +0 -0
  269. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/protocol.py +0 -0
  270. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/proxy_state.py +0 -0
  271. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/repo_map.py +0 -0
  272. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/retention.py +0 -0
  273. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/retrieval_broker.py +0 -0
  274. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/router.py +0 -0
  275. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/runtime.py +0 -0
  276. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/session_benchmark.py +0 -0
  277. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/session_manager.py +0 -0
  278. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/session_preloader.py +0 -0
  279. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/subprojects.py +0 -0
  280. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/telemetry.py +0 -0
  281. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/text_index.py +0 -0
  282. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/time_tracker.py +0 -0
  283. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/tool_classifier.py +0 -0
  284. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/transcript_index.py +0 -0
  285. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/validation_cache.py +0 -0
  286. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/vector_store.py +0 -0
  287. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/watcher.py +0 -0
  288. {code_context_control-2.85.0 → code_context_control-2.88.2}/services/win_subprocess.py +0 -0
  289. {code_context_control-2.85.0 → code_context_control-2.88.2}/setup.cfg +0 -0
  290. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_access_builtin_optout.py +0 -0
  291. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_access_guard_meta.py +0 -0
  292. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_access_guard_shell_project.py +0 -0
  293. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_access_guard_surfaces.py +0 -0
  294. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_access_guard_wiring.py +0 -0
  295. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_activity_reporter.py +0 -0
  296. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_agent_locks.py +0 -0
  297. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_aider_polyglot.py +0 -0
  298. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_antigravity_transition.py +0 -0
  299. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_artifact_store.py +0 -0
  300. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_artifact_tool.py +0 -0
  301. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_bitbucket_cli_smoke.py +0 -0
  302. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_bitbucket_client.py +0 -0
  303. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_bitbucket_config_fallback.py +0 -0
  304. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_bitbucket_credentials.py +0 -0
  305. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_bitbucket_tool.py +0 -0
  306. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_c3_bridge_project_artifacts.py +0 -0
  307. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_chat_poll.py +0 -0
  308. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_ci_act.py +0 -0
  309. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_ci_cache.py +0 -0
  310. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_ci_expr.py +0 -0
  311. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_ci_impact.py +0 -0
  312. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_ci_intel.py +0 -0
  313. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_ci_runner.py +0 -0
  314. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_ci_workflow.py +0 -0
  315. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_circuit_breaker.py +0 -0
  316. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_claude_md_merge.py +0 -0
  317. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_cli_smoke.py +0 -0
  318. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_compressor_large_file.py +0 -0
  319. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_creds_cli_smoke.py +0 -0
  320. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_delegate_version_probe.py +0 -0
  321. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_e2e_benchmark.py +0 -0
  322. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_edit_ledger_deadline.py +0 -0
  323. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_edit_ledger_hook.py +0 -0
  324. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_edit_locking.py +0 -0
  325. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_edit_normalization.py +0 -0
  326. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_edit_verify.py +0 -0
  327. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_embedding_index_deadlock.py +0 -0
  328. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_enforcement_flip.py +0 -0
  329. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_enforcement_policy.py +0 -0
  330. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_enforcement_routes.py +0 -0
  331. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_federated_graph.py +0 -0
  332. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_filter_backoff.py +0 -0
  333. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_ghost_files.py +0 -0
  334. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_ghost_generation.py +0 -0
  335. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_git_branch_awareness.py +0 -0
  336. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_hook_codex_compat.py +0 -0
  337. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_hook_dispatch.py +0 -0
  338. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_hook_pretool_enforce.py +0 -0
  339. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_hook_prompt_recall.py +0 -0
  340. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_hook_smoke.py +0 -0
  341. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_hook_state.py +0 -0
  342. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_hook_utf8_stdio.py +0 -0
  343. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_hub_credentials_route.py +0 -0
  344. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_hub_enforcement_routes.py +0 -0
  345. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_hub_inspect_api.py +0 -0
  346. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_hub_locks_routes.py +0 -0
  347. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_hub_server_smoke.py +0 -0
  348. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_hub_subproject_links.py +0 -0
  349. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_ide_workflow_adaptation.py +0 -0
  350. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_install_mcp_entrypoint.py +0 -0
  351. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_jira_cli_smoke.py +0 -0
  352. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_jira_client.py +0 -0
  353. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_jira_config_fallback.py +0 -0
  354. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_jira_credentials.py +0 -0
  355. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_jira_links.py +0 -0
  356. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_jira_routes.py +0 -0
  357. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_jira_tool.py +0 -0
  358. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_lazy_store_init.py +0 -0
  359. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_mask_guard.py +0 -0
  360. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_mask_routes.py +0 -0
  361. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_mask_surfaces.py +0 -0
  362. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_mcp_host_guard.py +0 -0
  363. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_mcp_memory_timeout.py +0 -0
  364. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_mcp_server_smoke.py +0 -0
  365. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_mcp_toml.py +0 -0
  366. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_memory_distiller.py +0 -0
  367. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_memory_graph_api.py +0 -0
  368. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_memory_queue.py +0 -0
  369. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_memory_system.py +0 -0
  370. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_mobile_api.py +0 -0
  371. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_mobile_extras.py +0 -0
  372. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_mobile_override_routes.py +0 -0
  373. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_no_stale_model_pins.py +0 -0
  374. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_notification_dedup.py +0 -0
  375. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_notification_discipline.py +0 -0
  376. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_ollama_credentials.py +0 -0
  377. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_oracle_api_auth.py +0 -0
  378. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_oracle_apikey_api.py +0 -0
  379. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_oracle_c3_bridge.py +0 -0
  380. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_oracle_chat_engine.py +0 -0
  381. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_oracle_chat_store.py +0 -0
  382. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_oracle_discovery_api.py +0 -0
  383. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_oracle_discovery_audit.py +0 -0
  384. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_oracle_local_auth.py +0 -0
  385. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_oracle_ollama_bridge.py +0 -0
  386. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_oracle_scanner_cache.py +0 -0
  387. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_oracle_security_fixes.py +0 -0
  388. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_oracle_subproject_awareness.py +0 -0
  389. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_oracle_ui_bundle.py +0 -0
  390. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_output_filter.py +0 -0
  391. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_override_grants.py +0 -0
  392. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_override_grants_mcp.py +0 -0
  393. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_override_requests.py +0 -0
  394. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_override_wake.py +0 -0
  395. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_permissions.py +0 -0
  396. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_project_manager.py +0 -0
  397. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_project_manager_merge.py +0 -0
  398. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_project_tool.py +0 -0
  399. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_read_coercion.py +0 -0
  400. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_read_edit_parity.py +0 -0
  401. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_related_facts.py +0 -0
  402. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_repo_map.py +0 -0
  403. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_response_boilerplate.py +0 -0
  404. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_retention.py +0 -0
  405. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_review_digest.py +0 -0
  406. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_service_durability.py +0 -0
  407. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_session_benchmark.py +0 -0
  408. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_session_budget.py +0 -0
  409. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_shell_robustness.py +0 -0
  410. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_subproject_exclusion.py +0 -0
  411. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_subproject_federation.py +0 -0
  412. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_subprojects.py +0 -0
  413. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_swe_bench.py +0 -0
  414. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_time_tracker.py +0 -0
  415. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_token_telemetry.py +0 -0
  416. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_tool_registry.py +0 -0
  417. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_upgrade_and_version.py +0 -0
  418. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_vault_write_guard.py +0 -0
  419. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_version_sync.py +0 -0
  420. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_web_security.py +0 -0
  421. {code_context_control-2.85.0 → code_context_control-2.88.2}/tests/test_windows_reliability.py +0 -0
  422. {code_context_control-2.85.0 → code_context_control-2.88.2}/tui/__init__.py +0 -0
  423. {code_context_control-2.85.0 → code_context_control-2.88.2}/tui/backend.py +0 -0
  424. {code_context_control-2.85.0 → code_context_control-2.88.2}/tui/main.py +0 -0
  425. {code_context_control-2.85.0 → code_context_control-2.88.2}/tui/screens/__init__.py +0 -0
  426. {code_context_control-2.85.0 → code_context_control-2.88.2}/tui/screens/benchmark_view.py +0 -0
  427. {code_context_control-2.85.0 → code_context_control-2.88.2}/tui/screens/claudemd_view.py +0 -0
  428. {code_context_control-2.85.0 → code_context_control-2.88.2}/tui/screens/compress_view.py +0 -0
  429. {code_context_control-2.85.0 → code_context_control-2.88.2}/tui/screens/index_view.py +0 -0
  430. {code_context_control-2.85.0 → code_context_control-2.88.2}/tui/screens/init_view.py +0 -0
  431. {code_context_control-2.85.0 → code_context_control-2.88.2}/tui/screens/mcp_view.py +0 -0
  432. {code_context_control-2.85.0 → code_context_control-2.88.2}/tui/screens/optimize_view.py +0 -0
  433. {code_context_control-2.85.0 → code_context_control-2.88.2}/tui/screens/pipe_view.py +0 -0
  434. {code_context_control-2.85.0 → code_context_control-2.88.2}/tui/screens/projects_view.py +0 -0
  435. {code_context_control-2.85.0 → code_context_control-2.88.2}/tui/screens/search_view.py +0 -0
  436. {code_context_control-2.85.0 → code_context_control-2.88.2}/tui/screens/session_view.py +0 -0
  437. {code_context_control-2.85.0 → code_context_control-2.88.2}/tui/screens/stats.py +0 -0
  438. {code_context_control-2.85.0 → code_context_control-2.88.2}/tui/screens/ui_view.py +0 -0
  439. {code_context_control-2.85.0 → code_context_control-2.88.2}/tui/theme.tcss +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-context-control
3
- Version: 2.85.0
3
+ Version: 2.88.2
4
4
  Summary: Local MCP code-intelligence for AI coding tools: surgical search/read/edit, agent-config version history, path-level access + masking guards, and a multi-project hub.
5
5
  Author-email: Dimitri Tselenchuk <dtselenc@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -178,7 +178,7 @@ Twelve tabs. The dashboard above shows token savings, indexed files, the live se
178
178
  <img src="https://raw.githubusercontent.com/drknowhow/code-context-control/main/docs/screenshots/2026-07/ui_tasks.png" alt="C3 Tasks" width="900">
179
179
  </p>
180
180
 
181
- **Tasks** (v2.45.0, extended v2.53.0) is a durable per-project tracker — dependencies and subtasks, milestones, decision notes, full event history, health reports, and both automatic and manual time tracking. It rolls up into the Hub's cross-project board.
181
+ **Tasks** (v2.45.0, extended v2.53.0) is a durable per-project tracker — dependencies and subtasks, milestones, decision notes, full event history, health reports, and both automatic and manual time tracking. It rolls up into the Hub's cross-project board. Shipped milestones can be **completed** (v2.86.0) — they leave the board while their tasks keep the milestone link, unlike archiving, which detaches them.
182
182
 
183
183
  **Instructions** keeps your agent-facing docs in sync. C3-generated content sits inside a `<!-- C3:BEGIN … -->` block; anything you write outside it is preserved. Since v2.60.0 generated docs point at `.c3/MAP.md` — a machine-owned, byte-stable repo map C3 refreshes automatically — instead of embedding a tree that goes stale. `AGENTS.md` serves both Codex and Antigravity; `GEMINI.md` is read if present but no longer generated (the Gemini CLI profile was removed in v2.52).
184
184
 
@@ -243,6 +243,7 @@ c3 access mask activate # purge pre-mask artifacts, buil
243
243
  - **`deny` means deny-enumerate too** — denied paths never appear in search results, maps, or the vector index.
244
244
  - **Masked means read-only, always.** Cropped rows have no inverse, so an edit in transformed coordinates would corrupt the one file you protected.
245
245
  - **Four deterministic presets, no LLM in the read path:** `redact_secrets`, `redact_columns` (salted one-way pseudonyms — joins survive, no reverse dictionary), `sample_rows`, `signatures_only`.
246
+ - **Sensible defaults out of the box** (v2.86.0). A fresh install seeds `*.pem`, `id_rsa*`, and `*.key` as deny rules in global scope — visible in `c3 access list` and removable like any rule you wrote yourself. Delete one and it stays deleted.
246
247
  - **Rule changes are human-only** (UI tab or CLI) and ledger-logged. Agents have no mutation surface.
247
248
  - **Built-ins can be switched off when you need to** (v2.65.0). `**/.env*`, `**/.c3/**`, `**/.claude/settings*.json` and `**/.git/**` yield to `c3 access builtin disable <glob>`, which makes you retype the glob first. It takes **two keys** — a config entry *and* a keyring attestation — so an agent that manages to write `config.json` still cannot grant itself write access to your settings. The credential vault stays absolute.
248
249
  - **Honest coverage.** This guards *cooperative* agents against mistakes and prompt injection. It is not a sandbox — a raw shell outside C3's tools still sees the real bytes.
@@ -115,7 +115,7 @@ Twelve tabs. The dashboard above shows token savings, indexed files, the live se
115
115
  <img src="https://raw.githubusercontent.com/drknowhow/code-context-control/main/docs/screenshots/2026-07/ui_tasks.png" alt="C3 Tasks" width="900">
116
116
  </p>
117
117
 
118
- **Tasks** (v2.45.0, extended v2.53.0) is a durable per-project tracker — dependencies and subtasks, milestones, decision notes, full event history, health reports, and both automatic and manual time tracking. It rolls up into the Hub's cross-project board.
118
+ **Tasks** (v2.45.0, extended v2.53.0) is a durable per-project tracker — dependencies and subtasks, milestones, decision notes, full event history, health reports, and both automatic and manual time tracking. It rolls up into the Hub's cross-project board. Shipped milestones can be **completed** (v2.86.0) — they leave the board while their tasks keep the milestone link, unlike archiving, which detaches them.
119
119
 
120
120
  **Instructions** keeps your agent-facing docs in sync. C3-generated content sits inside a `<!-- C3:BEGIN … -->` block; anything you write outside it is preserved. Since v2.60.0 generated docs point at `.c3/MAP.md` — a machine-owned, byte-stable repo map C3 refreshes automatically — instead of embedding a tree that goes stale. `AGENTS.md` serves both Codex and Antigravity; `GEMINI.md` is read if present but no longer generated (the Gemini CLI profile was removed in v2.52).
121
121
 
@@ -180,6 +180,7 @@ c3 access mask activate # purge pre-mask artifacts, buil
180
180
  - **`deny` means deny-enumerate too** — denied paths never appear in search results, maps, or the vector index.
181
181
  - **Masked means read-only, always.** Cropped rows have no inverse, so an edit in transformed coordinates would corrupt the one file you protected.
182
182
  - **Four deterministic presets, no LLM in the read path:** `redact_secrets`, `redact_columns` (salted one-way pseudonyms — joins survive, no reverse dictionary), `sample_rows`, `signatures_only`.
183
+ - **Sensible defaults out of the box** (v2.86.0). A fresh install seeds `*.pem`, `id_rsa*`, and `*.key` as deny rules in global scope — visible in `c3 access list` and removable like any rule you wrote yourself. Delete one and it stays deleted.
183
184
  - **Rule changes are human-only** (UI tab or CLI) and ledger-logged. Agents have no mutation surface.
184
185
  - **Built-ins can be switched off when you need to** (v2.65.0). `**/.env*`, `**/.c3/**`, `**/.claude/settings*.json` and `**/.git/**` yield to `c3 access builtin disable <glob>`, which makes you retype the glob first. It takes **two keys** — a config entry *and* a keyring attestation — so an agent that manages to write `config.json` still cannot grant itself write access to your settings. The credential vault stays absolute.
185
186
  - **Honest coverage.** This guards *cooperative* agents against mistakes and prompt injection. It is not a sandbox — a raw shell outside C3's tools still sees the real bytes.
@@ -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.85.0"
95
+ __version__ = "2.88.2"
96
96
 
97
97
 
98
98
  def _compress_file_cli(compressor, path, mode="smart", **kw):
@@ -5535,6 +5535,14 @@ def cmd_install_mcp(args):
5535
5535
  except Exception as e:
5536
5536
  print(f"Warning: Could not update global CLAUDE.md: {e}")
5537
5537
 
5538
+ # ── Default Access Guard rules (first run only) ─────────────
5539
+ from services import access_guard
5540
+ seeded = access_guard.seed_default_global_rules()
5541
+ if seeded.get("seeded"):
5542
+ rules = ", ".join(seeded["rules"])
5543
+ print(f"Seeded default Access Guard deny rules into global scope: {rules}")
5544
+ print(" (remove with: c3 access remove <glob> --kind deny --global)")
5545
+
5538
5546
  # ── Install /terse skill for supported IDEs ──────────────────
5539
5547
  if profile.name in ("claude-code", "codex"):
5540
5548
  try:
@@ -5891,7 +5899,7 @@ def cmd_creds(args):
5891
5899
  """Credential vault management (global + per-project scopes)."""
5892
5900
  sub = getattr(args, "creds_cmd", None)
5893
5901
  if not sub:
5894
- print("Usage: c3 creds {set,get,list,rm,import} [args]")
5902
+ print("Usage: c3 creds {set,get,list,rm,import,usage} [args]")
5895
5903
  return
5896
5904
 
5897
5905
  project_path = getattr(args, "project_path", ".") or "."
@@ -5906,6 +5914,8 @@ def cmd_creds(args):
5906
5914
  _creds_cmd_rm(args, project_path)
5907
5915
  elif sub == "import":
5908
5916
  _creds_cmd_import(args, project_path)
5917
+ elif sub == "usage":
5918
+ _creds_cmd_usage(args, project_path)
5909
5919
  else:
5910
5920
  print(f"Unknown creds subcommand: {sub}")
5911
5921
 
@@ -5920,6 +5930,9 @@ def _creds_entry_line(name: str, entry: dict) -> str:
5920
5930
  f"{name:<24} {entry.get('scope', '?'):<8} {entry.get('type', 'token'):<10}"
5921
5931
  f" len={entry.get('value_len', '?')}",
5922
5932
  ]
5933
+ display = entry.get("display") or {}
5934
+ if display:
5935
+ parts.append(" ".join(str(v) for v in display.values() if v))
5923
5936
  if entry.get("env_var"):
5924
5937
  parts.append(f"env_var={entry['env_var']}")
5925
5938
  if flags:
@@ -5929,16 +5942,49 @@ def _creds_entry_line(name: str, entry: dict) -> str:
5929
5942
  return " ".join(parts)
5930
5943
 
5931
5944
 
5945
+ _CREDS_HIDDEN_FIELDS = {"number", "cvc", "ssn"} # prompted via getpass
5946
+
5947
+
5948
+ def _creds_prompt_structured(name: str, ctype: str) -> str:
5949
+ """Interactive per-field prompt for a structured entry; returns JSON.
5950
+ Sensitive fields use a hidden prompt; empty optional fields are skipped."""
5951
+ import getpass
5952
+ import json as _json
5953
+
5954
+ from services import credential_store as cred_store
5955
+
5956
+ required, optional = cred_store.schema_fields(ctype)
5957
+ print(f"Enter {ctype} fields for '{name}' "
5958
+ "(optional fields: press Enter to skip):")
5959
+ fields: dict = {}
5960
+ for fname in list(required) + list(optional):
5961
+ tag = "" if fname in required else " (optional)"
5962
+ if fname in _CREDS_HIDDEN_FIELDS:
5963
+ raw = getpass.getpass(f" {fname}{tag}: ")
5964
+ else:
5965
+ raw = input(f" {fname}{tag}: ")
5966
+ if raw.strip():
5967
+ fields[fname] = raw.strip()
5968
+ return _json.dumps(fields)
5969
+
5970
+
5932
5971
  def _creds_cmd_set(args, project_path: str) -> None:
5933
5972
  import getpass
5934
5973
 
5935
5974
  from services import credential_store as cred_store
5936
5975
 
5976
+ ctype = getattr(args, "ctype", "token") or "token"
5937
5977
  value = getattr(args, "value", "") or ""
5938
5978
  if getattr(args, "stdin", False):
5939
5979
  value = sys.stdin.read().rstrip("\n")
5940
5980
  if not value:
5941
- value = getpass.getpass(f"Value for {args.name}: ")
5981
+ if ctype in cred_store.STRUCTURED_TYPES:
5982
+ value = _creds_prompt_structured(args.name, ctype)
5983
+ if value == "{}":
5984
+ print("Cancelled -- no fields entered.")
5985
+ return
5986
+ else:
5987
+ value = getpass.getpass(f"Value for {args.name}: ")
5942
5988
  if not value:
5943
5989
  print("Cancelled -- value required.")
5944
5990
  return
@@ -5948,7 +5994,7 @@ def _creds_cmd_set(args, project_path: str) -> None:
5948
5994
  args.name, value,
5949
5995
  scope=scope, project_path=project_path,
5950
5996
  description=getattr(args, "desc", "") or "",
5951
- ctype=getattr(args, "ctype", "token") or "token",
5997
+ ctype=ctype,
5952
5998
  env_var=getattr(args, "env_var", "") or "",
5953
5999
  agent_readable=bool(getattr(args, "agent_readable", False)),
5954
6000
  inject=bool(getattr(args, "inject", False)),
@@ -5963,6 +6009,19 @@ def _creds_cmd_set(args, project_path: str) -> None:
5963
6009
  "into its context and transcripts.")
5964
6010
 
5965
6011
 
6012
+ def _creds_count_show(refs, project_path: str) -> None:
6013
+ """Count a terminal --show like any other use: state counter + history."""
6014
+ from services import credential_store as cred_store
6015
+ try:
6016
+ cred_store.touch_last_used(
6017
+ sorted({str(r).partition(".")[0] for r in refs}), project_path)
6018
+ from services import cred_telemetry as ct
6019
+ ct.record_use(refs, project_path=project_path,
6020
+ action=ct.ACTION_CLI_SHOW, surface="cli")
6021
+ except Exception:
6022
+ pass
6023
+
6024
+
5966
6025
  def _creds_cmd_get(args, project_path: str) -> None:
5967
6026
  from services import credential_store as cred_store
5968
6027
 
@@ -5973,11 +6032,46 @@ def _creds_cmd_get(args, project_path: str) -> None:
5973
6032
  print(_creds_entry_line(args.name, entry))
5974
6033
  print(f"storage={entry.get('storage', 'keyring')} "
5975
6034
  f"created={entry.get('created', '?')} updated={entry.get('updated', '?')}")
5976
- fp = cred_store.fingerprint(args.name, project_path=project_path)
5977
- print(f"fingerprint={fp or 'unresolvable'}")
5978
- if getattr(args, "show", False):
5979
- value = cred_store.get_value(args.name, project_path=project_path)
5980
- print(value if value is not None else "[error] value missing from store")
6035
+ stype = cred_store.structured_type(args.name, project_path=project_path)
6036
+ field = (getattr(args, "field", "") or "").strip()
6037
+ if not stype:
6038
+ fp = cred_store.fingerprint(args.name, project_path=project_path)
6039
+ print(f"fingerprint={fp or 'unresolvable'}")
6040
+ if field:
6041
+ print(f"[error] '{args.name}' is not structured -- --field does not apply")
6042
+ return
6043
+ if getattr(args, "show", False):
6044
+ value = cred_store.get_value(args.name, project_path=project_path)
6045
+ print(value if value is not None
6046
+ else "[error] value missing from store")
6047
+ if value is not None:
6048
+ _creds_count_show([args.name], project_path)
6049
+ return
6050
+ print(f"fields: {', '.join(entry.get('fields') or []) or 'none recorded'}")
6051
+ if not getattr(args, "show", False):
6052
+ if field:
6053
+ print("[hint] add --show to print the field value")
6054
+ return
6055
+ # --show: the deliberate human read-back path (terminal only; the wire
6056
+ # never carries these values). Counted as usage like any other reveal.
6057
+ if field:
6058
+ value = cred_store.get_value(args.name, project_path=project_path,
6059
+ field=field)
6060
+ if value is None:
6061
+ print(f"[error] no field '{field}' on '{args.name}'")
6062
+ return
6063
+ print(value)
6064
+ _creds_count_show([f"{args.name}.{field}"], project_path)
6065
+ else:
6066
+ fields = cred_store.get_structured_fields(
6067
+ args.name, project_path=project_path)
6068
+ if fields is None:
6069
+ print("[error] value missing from store")
6070
+ return
6071
+ width = max(len(k) for k in fields)
6072
+ for key in sorted(fields):
6073
+ print(f"{key:<{width}} {fields[key]}")
6074
+ _creds_count_show([args.name], project_path)
5981
6075
 
5982
6076
 
5983
6077
  def _creds_cmd_list(args, project_path: str) -> None:
@@ -6031,6 +6125,39 @@ def _creds_cmd_import(args, project_path: str) -> None:
6031
6125
  "(use --overwrite to replace)")
6032
6126
 
6033
6127
 
6128
+ def _creds_cmd_usage(args, project_path: str) -> None:
6129
+ import json as _json
6130
+
6131
+ from services import cred_telemetry as ct
6132
+
6133
+ name = getattr(args, "name", "") or ""
6134
+ limit = max(1, int(getattr(args, "limit", 20) or 20))
6135
+ agg = ct.aggregate(project_path, name=name)
6136
+ recent = ct.search_events(project_path, name=name, limit=limit)
6137
+ if getattr(args, "as_json", False):
6138
+ print(_json.dumps({"aggregate": agg, "recent": recent}, indent=2))
6139
+ return
6140
+ if not agg["total"]:
6141
+ target = f" for '{name}'" if name else ""
6142
+ print(f"No recorded credential uses{target} yet.")
6143
+ return
6144
+ surf = " ".join(f"{s}:{c}" for s, c in sorted(agg["by_surface"].items()))
6145
+ print(f"{agg['total']} use(s) across {len(agg['rows'])} credential(s)"
6146
+ f" [{surf}]")
6147
+ for row in agg["rows"]:
6148
+ fields = f" fields: {', '.join(row['fields'])}" if row["fields"] else ""
6149
+ print(f" {row['name']:<24} {row['hits']:>4}x last {row['last_ts'] or '?'}"
6150
+ f" projects={row['projects']}{fields}")
6151
+ print(f"recent (newest first, {len(recent['events'])}"
6152
+ f"/{recent['matched']}):")
6153
+ for e in recent["events"]:
6154
+ ref = e["name"] + (f".{e['field']}" if e.get("field") else "")
6155
+ exit_part = f" exit={e['exit']}" if "exit" in e else ""
6156
+ cmd_part = f" {e['cmd']}" if e.get("cmd") else ""
6157
+ print(f" {e.get('ts', '?')} {e.get('action', '?'):<10} {ref:<28}"
6158
+ f" [{e.get('surface', '?')}]{exit_part}{cmd_part}")
6159
+
6160
+
6034
6161
  def cmd_ci(args):
6035
6162
  """AgentCI entry point — exits with the finding.
6036
6163
 
@@ -6603,6 +6730,16 @@ def _override_audit(grant: dict, project_path: str) -> None:
6603
6730
 
6604
6731
  def cmd_access(args):
6605
6732
  """Access Guard rule management — human-only mutation surface (spec §1)."""
6733
+ from services import access_guard
6734
+
6735
+ # First `c3 access` touch seeds the removable defaults (spec §1). A
6736
+ # no-op forever after: any existing access section, even an emptied
6737
+ # one, means the user has taken over the scope.
6738
+ seeded = access_guard.seed_default_global_rules()
6739
+ if seeded.get("seeded"):
6740
+ print(f"[seeded] default global deny rules: {', '.join(seeded['rules'])}")
6741
+ print(" Remove any of them: c3 access remove <glob> --kind deny --global\n")
6742
+
6606
6743
  sub = getattr(args, "access_cmd", None)
6607
6744
  if not sub:
6608
6745
  print("Usage: c3 access {list,add,remove,check,stats,mask,builtin} [args]")
@@ -417,9 +417,14 @@ def build_parser(version: str, parse_cli_ide_arg):
417
417
  "set", help="Create or update a credential (value via hidden prompt)"
418
418
  )
419
419
  cr_set.add_argument("name", help="Entry name (env-var safe: [A-Za-z_][A-Za-z0-9_]*)")
420
- cr_set.add_argument("--value", default="", help="Secret value (prompted via getpass if omitted — preferred)")
420
+ cr_set.add_argument("--value", default="", help="Secret value (prompted via getpass if omitted — preferred). Structured types take a JSON object of fields")
421
421
  cr_set.add_argument("--stdin", action="store_true", help="Read the value from stdin (piped/multiline values)")
422
- cr_set.add_argument("--type", dest="ctype", choices=["token", "env", "multiline"], default="token", help="Entry type")
422
+ cr_set.add_argument("--type", dest="ctype",
423
+ choices=["token", "env", "multiline",
424
+ "address", "identity", "card"],
425
+ default="token",
426
+ help="Entry type; address/identity/card are structured "
427
+ "(field payload, inject-only, never revealable to the agent)")
423
428
  cr_set.add_argument("--desc", default="", help="Human description shown in list/UI")
424
429
  cr_set.add_argument("--env-var", default="", help="Env var name used at injection (default: entry name)")
425
430
  cr_set.add_argument("--agent-readable", action="store_true", help="Allow the agent to reveal the decoded value into its context (default: injection-only)")
@@ -432,6 +437,7 @@ def build_parser(version: str, parse_cli_ide_arg):
432
437
  cr_get = creds_subs.add_parser("get", help="Show entry metadata (masked; --show prints the value)")
433
438
  cr_get.add_argument("name")
434
439
  cr_get.add_argument("--show", action="store_true", help="Print the decoded value to the terminal")
440
+ cr_get.add_argument("--field", default="", help="For structured entries: limit --show to one field (e.g. number)")
435
441
  cr_get.add_argument("--path", dest="project_path", default=".", help="Project directory (default: current)")
436
442
 
437
443
  cr_list = creds_subs.add_parser("list", help="List credentials visible to this project")
@@ -448,6 +454,13 @@ def build_parser(version: str, parse_cli_ide_arg):
448
454
  cr_import.add_argument("--overwrite", action="store_true", help="Replace entries already registered in the target scope")
449
455
  cr_import.add_argument("--path", dest="project_path", default=".", help="Project directory (default: current)")
450
456
 
457
+ cr_usage = creds_subs.add_parser(
458
+ "usage", help="Usage history — when, where, and how often credentials were used")
459
+ cr_usage.add_argument("name", nargs="?", default="", help="Limit to one credential (default: all)")
460
+ cr_usage.add_argument("--limit", type=int, default=20, help="Recent events to show (default: 20)")
461
+ cr_usage.add_argument("--json", dest="as_json", action="store_true", help="Emit raw JSON")
462
+ cr_usage.add_argument("--path", dest="project_path", default=".", help="Project directory (default: current)")
463
+
451
464
  # ── Agent Locks (docs/agent-locks.md) ───────────────────────────────
452
465
  # force-release is human-only: it bumps the fencing counter so a holder
453
466
  # that comes back is stale by construction. Agents get c3_locks instead,
@@ -105,11 +105,13 @@
105
105
  <a href="#storage" class="sidebar-link"><span class="icon">🗄️</span> Where values live</a>
106
106
  <a href="#scopes" class="sidebar-link"><span class="icon">🌍</span> Scopes &amp; overriding</a>
107
107
  <a href="#agent-use" class="sidebar-link"><span class="icon">🤖</span> How agents use them</a>
108
+ <a href="#structured" class="sidebar-link"><span class="icon">💳</span> Structured kinds</a>
108
109
  <a href="#exposure" class="sidebar-link"><span class="icon">⚠️</span> Exposure flags</a>
109
110
  <a href="#hub-ui" class="sidebar-link"><span class="icon">🖥️</span> Hub UI</a>
110
111
  <a href="#search" class="sidebar-link"><span class="icon">🔎</span> Search &amp; qualifiers</a>
111
112
  <a href="#cli" class="sidebar-link"><span class="icon">💻</span> CLI commands</a>
112
113
  <a href="#actions" class="sidebar-link"><span class="icon">⚙️</span> Tool actions</a>
114
+ <a href="#usage" class="sidebar-link"><span class="icon">📊</span> Usage history</a>
113
115
  <a href="#audit" class="sidebar-link"><span class="icon">📝</span> Audit trail</a>
114
116
  <a href="#troubleshooting" class="sidebar-link"><span class="icon">🛠️</span> Troubleshooting</a>
115
117
  </div>
@@ -293,6 +295,48 @@ c3_shell(cmd=<span class="str">'terraform apply'</span>, env_creds=<span class="
293
295
 
294
296
  <hr class="divider">
295
297
 
298
+ <!-- ═══════════════════════════════════ STRUCTURED ═══ -->
299
+ <section id="structured" class="tool-section">
300
+ <h2>Structured kinds — cards, addresses, identity (v2.87.0)</h2>
301
+
302
+ <p>Three entry types hold <strong>named fields</strong> instead of one opaque value:
303
+ <code>card</code> (cardholder, number, expiry, optional cvc/billing_zip — Luhn-checked),
304
+ <code>address</code> (street1, city, state, zip, optional recipient/street2/country/phone) and
305
+ <code>identity</code> (full_name, optional dob/ssn/phone/email). The payload is stored as one
306
+ canonical JSON object through the same keyring / encrypted-sidecar path as any other value.</p>
307
+
308
+ <p>They are <strong>inject-only by construction</strong>, which is stricter than a normal secret:</p>
309
+ <ul>
310
+ <li><strong>Reveal is permanently disabled</strong> — <code>agent_readable</code> and
311
+ <code>inject</code> are refused at every surface, for every caller, forever. There is no flag to flip.</li>
312
+ <li><strong>Only single fields cross the boundary.</strong> The agent addresses a field —
313
+ <code>env_creds='CARD.number'</code> (exported as <code>$CARD_NUMBER</code>) or
314
+ <code>{{cred:CARD.number}}</code> inline — and a bare <code>{{cred:CARD}}</code> fails with
315
+ the field list rather than expanding the whole payload.</li>
316
+ <li><strong>The registry shows a projection, not the data.</strong> Lists and the UI display
317
+ <code>visa ••••4242</code> for a card (brand + last4, deliberately <em>not</em> expiry),
318
+ city/state for an address, the name for an identity. Field <em>names</em> are public;
319
+ field <em>values</em> never transit any HTTP response — a sweep test enforces this.</li>
320
+ <li><strong>Echoes redact per field</strong> to <code>[cred:NAME.field]</code>. Caveat: the
321
+ redactor only tracks values of 4+ characters, so a 3-digit CVC or 2-letter state that a
322
+ child process echoes cannot be scrubbed after the fact. The real guarantee remains
323
+ decode-at-the-subprocess-boundary; redaction is the belt over it.</li>
324
+ <li><strong>The type boundary is immutable.</strong> A card cannot be rewritten into a
325
+ plain token (or vice versa) by <code>set</code>, metadata update, or <code>.env</code>
326
+ import — delete and re-create is the only path across, and a keyring attestation keeps an
327
+ entry structured even if <code>.c3/config.json</code> is edited by hand.</li>
328
+ </ul>
329
+
330
+ <p>Updating one field never requires retyping the rest: a partial payload
331
+ <strong>merges</strong> (<code>{"expiry": "01/30"}</code> updates the expiry, JSON
332
+ <code>null</code> deletes an optional field). Read-back for <em>you</em> is terminal-only:
333
+ <code>c3 creds get NAME --show</code> (all fields) or <code>--show --field number</code> —
334
+ the browser and the mobile gateway never carry the values, and mobile cannot create
335
+ structured entries at all.</p>
336
+ </section>
337
+
338
+ <hr class="divider">
339
+
296
340
  <!-- ═══════════════════════════════════════ EXPOSURE ═══ -->
297
341
  <section id="exposure" class="tool-section">
298
342
  <h2>Exposure flags</h2>
@@ -478,6 +522,42 @@ c3_shell(cmd=<span class="str">'terraform apply'</span>, env_creds=<span class="
478
522
  <hr class="divider">
479
523
 
480
524
  <!-- ═══════════════════════════════════════ AUDIT ═══ -->
525
+ <section id="usage" class="tool-section">
526
+ <h2>Usage history (v2.88.0)</h2>
527
+
528
+ <p>Every time a value leaves the vault — an <code>env_creds</code> injection, a
529
+ <code>{{cred:NAME}}</code> expansion, a gated reveal, a terminal
530
+ <code>c3 creds get --show</code> — one event is appended to the owning scope's
531
+ <code>.c3/cred_usage.jsonl</code>: timestamp, name (and field for structured entries),
532
+ action, surface, project, exit code, and the command in its <strong>raw template
533
+ form</strong>, capped at 120 characters. Never the expanded string, never a value.
534
+ A global credential's usage from every project lands in <code>~/.c3</code>, so its
535
+ history is complete in one place.</p>
536
+
537
+ <p>Reading it back:</p>
538
+ <ul>
539
+ <li><strong>UI</strong> — the Credentials tab's <em>usage</em> sub-view (totals,
540
+ per-credential counts by surface, expandable recent events) and the hub drawer's
541
+ “Usage &amp; relationships” section.</li>
542
+ <li><strong>CLI</strong> — <code>c3 creds usage [NAME] [--limit N] [--json]</code>.</li>
543
+ <li><strong>Agent</strong> — <code>c3_credentials(action='usage')</code>. Scoped on
544
+ purpose: the agent sees full events (including command previews) only for the
545
+ <em>current</em> project; other projects' use of a shared global credential is
546
+ reduced to counts, so one project's agent cannot read another's command lines
547
+ through the vault. Your surfaces (UI/CLI) show everything.</li>
548
+ <li><strong>REST</strong> — <code>GET /api/credentials/usage</code> and
549
+ <code>GET /api/credentials/&lt;name&gt;/usage</code> (hub:
550
+ <code>/api/projects/credentials/usage</code>).</li>
551
+ </ul>
552
+
553
+ <p>The log rotates at 512KB (one <code>.1</code> generation retained), both filenames
554
+ are vault-write-protected and gitignored, and the lightweight
555
+ <code>last_used</code>/<code>use_count</code> counters you already see on list rows
556
+ keep working exactly as before — they are the summary; this is the history.</p>
557
+ </section>
558
+
559
+ <hr class="divider">
560
+
481
561
  <section id="audit" class="tool-section">
482
562
  <h2>Audit trail</h2>
483
563
 
@@ -41,7 +41,24 @@ _MAX_TOKENS = 200
41
41
  # "NTFS alternate data stream". The ADS check stays strict for real path
42
42
  # arguments (_WRITE_TOOLS/_READ_TOOLS); here it only produced false denies on
43
43
  # commit messages, curl, and gh (#50).
44
- _SCHEME_RE = re.compile(r"^[a-z][a-z0-9+.\-]*://", re.IGNORECASE)
44
+ #
45
+ # UNANCHORED, and that is the fix rather than an oversight. `^…://` only ever
46
+ # recognised a token that BEGINS with a scheme, which is the same
47
+ # whitelist-a-shape mistake #50 made and this module's own header calls out —
48
+ # and the `_SYNTAX_CHARS` generalisation does not cover the gap, because a
49
+ # token can carry a URL and no syntax at all. Observed 2026-08-11: the single
50
+ # argument of
51
+ # printf '\n---\n\nhttps://claude.ai/code/session_01Hs28…\n' >> body.md
52
+ # strips to `\n---\n\nhttps://claude.ai/…`, which has a separator (`\` and
53
+ # `/`), no syntax characters, no `::`, and no leading scheme. It reached
54
+ # ag.check, canonicalised to a residual colon, and hard-denied a command whose
55
+ # only file argument was an ordinary markdown path. Third logged instance of
56
+ # this class in five days (two on 2026-08-07 were Windows paths inside Python
57
+ # string literals).
58
+ #
59
+ # A token containing `://` anywhere is a network literal, not an NTFS stream:
60
+ # a real stream is `file:name:$TYPE`, and no spelling of it contains `//`.
61
+ _SCHEME_RE = re.compile(r"[a-z][a-z0-9+.\-]*://", re.IGNORECASE)
45
62
  # IPv6 literal or CIDR: >=2 colons, hex groups only, optional [] and /prefix.
46
63
  # 'C:/x/f.txt:stream' has one colon and non-hex parts, so it never matches.
47
64
  _IPV6_RE = re.compile(
@@ -104,8 +121,13 @@ _CD_RE = re.compile(
104
121
 
105
122
 
106
123
  def _is_network_token(tok: str) -> bool:
107
- """True for URLs and IPv6 literals/CIDRs — never for an ADS spelling."""
108
- return bool(_SCHEME_RE.match(tok) or _IPV6_RE.match(tok))
124
+ """True for URLs and IPv6 literals/CIDRs — never for an ADS spelling.
125
+
126
+ ``search`` for the scheme (a URL anywhere in the token disqualifies it as
127
+ a path), ``match`` for IPv6 — that pattern is a whole-token shape and
128
+ anchoring is what keeps `C:/x/f.txt:stream` from matching it.
129
+ """
130
+ return bool(_SCHEME_RE.search(tok) or _IPV6_RE.match(tok))
109
131
 
110
132
 
111
133
  def _is_scope_token(tok: str) -> bool:
@@ -113,7 +113,8 @@ _WRITE_CLASS_ALWAYS = frozenset({"Edit", "Write", "MultiEdit"})
113
113
  # Vault files no native write may touch, regardless of unlock state.
114
114
  # Mirrors services.credential_store.VAULT_PROTECTED_FILES (parity-tested);
115
115
  # duplicated because hooks must stay import-light.
116
- _VAULT_FILES = frozenset({"config.json", "secrets.enc", "cred_state.json"})
116
+ _VAULT_FILES = frozenset({"config.json", "secrets.enc", "cred_state.json",
117
+ "cred_usage.jsonl", "cred_usage.jsonl.1"})
117
118
 
118
119
  # Redirect messages per native tool
119
120
  _REDIRECTS = {
@@ -2026,7 +2026,9 @@ def api_projects_credentials_set():
2026
2026
  str(data.get("path") or "").strip(), scope, mutation=True)
2027
2027
  if err:
2028
2028
  return err
2029
- value = str(data.get("value") or "")
2029
+ value = data.get("value")
2030
+ # Structured kinds submit a field OBJECT; the store takes JSON text.
2031
+ value = json.dumps(value) if isinstance(value, dict) else str(value or "")
2030
2032
  ctype = str(data.get("type") or data.get("ctype") or "token")
2031
2033
  try:
2032
2034
  if value:
@@ -2123,11 +2125,40 @@ def api_projects_credentials_check(name):
2123
2125
  "name": name,
2124
2126
  "scope": entry["scope"],
2125
2127
  "storage": entry.get("storage", "keyring"),
2126
- "resolvable": cred_store.get_value(name, project_path=store_path) is not None,
2128
+ # is_resolvable, not get_value: a structured entry never resolves
2129
+ # whole, but its payload being decodable is what "check" asks.
2130
+ "resolvable": cred_store.is_resolvable(name, project_path=store_path),
2127
2131
  "fingerprint": cred_store.fingerprint(name, project_path=store_path),
2128
2132
  })
2129
2133
 
2130
2134
 
2135
+ @app.route("/api/projects/credentials/usage", methods=["GET"])
2136
+ def api_projects_credentials_usage():
2137
+ """Usage history — `path` scopes to a project (merged view); omit it for
2138
+ the global vault only. `name` filters to one credential. Names, counts
2139
+ and cmd previews only; never values."""
2140
+ from services import cred_telemetry as ct
2141
+ from services import credential_store as cred_store
2142
+ path = (request.args.get("path") or "").strip()
2143
+ if path:
2144
+ try:
2145
+ base = str(_resolve_project_path(path))
2146
+ except ValueError as e:
2147
+ return jsonify({"error": str(e)}), 404
2148
+ else:
2149
+ home = cred_store.global_base()
2150
+ if home is None:
2151
+ return jsonify({"error": "global scope unresolvable"}), 500
2152
+ base = str(home)
2153
+ name = (request.args.get("name") or "").strip()
2154
+ return jsonify({
2155
+ "path": base if path else "",
2156
+ "aggregate": ct.aggregate(base, name=name),
2157
+ "recent": ct.search_events(base, name=name,
2158
+ limit=request.args.get("limit", 100)),
2159
+ })
2160
+
2161
+
2131
2162
  @app.route("/api/hub/credentials/overview", methods=["GET"])
2132
2163
  def api_hub_credentials_overview():
2133
2164
  """Cross-project credential inventory: the global vault plus each
@@ -2740,6 +2771,20 @@ def api_pm_milestone():
2740
2771
  return jsonify({"error": "id is required"}), 400
2741
2772
 
2742
2773
  if request.method == "PUT":
2774
+ # {complete: true} / {reopen: true} switch lifecycle; tasks keep
2775
+ # their milestone link (unlike DELETE = archive + detach).
2776
+ if data.get("complete"):
2777
+ res = store.complete_milestone(ms_id)
2778
+ if "error" in res:
2779
+ return jsonify(res), 400
2780
+ _pm_audit(resolved, "milestone", "complete", res["id"])
2781
+ return jsonify({"completed": True, "milestone": res})
2782
+ if data.get("reopen"):
2783
+ res = store.reopen_milestone(ms_id)
2784
+ if "error" in res:
2785
+ return jsonify(res), 400
2786
+ _pm_audit(resolved, "milestone", "reopen", res["id"])
2787
+ return jsonify({"reopened": True, "milestone": res})
2743
2788
  res = store.update_milestone(ms_id, expected_rev=data.get("expected_rev"),
2744
2789
  **(data.get("fields") or {}))
2745
2790
  if "error" in res:
@@ -182,8 +182,8 @@ function DrillPanel({ project, tab, setTab, onClose, onChanged, onOpenModal, pro
182
182
  </button>
183
183
  </div>
184
184
  <div style={{
185
- display: 'flex', gap: 2, padding: '4px 20px 0',
186
- borderBottom: `1px solid ${T.border}`, overflowX: 'auto', flexShrink: 0,
185
+ display: 'flex', flexWrap: 'wrap', gap: 2, padding: '4px 20px 0',
186
+ borderBottom: `1px solid ${T.border}`, flexShrink: 0,
187
187
  }}>
188
188
  {tabs.map(([id, label]) => (
189
189
  <button key={id} onClick={() => setTab(id)} style={{