code-context-control 2.53.0__tar.gz → 2.54.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (326) hide show
  1. {code_context_control-2.53.0 → code_context_control-2.54.0}/PKG-INFO +1 -1
  2. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/c3.py +54 -17
  3. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/commands/parser.py +1 -0
  4. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_server.py +4 -2
  5. code_context_control-2.54.0/cli/progress.py +49 -0
  6. {code_context_control-2.53.0 → code_context_control-2.54.0}/code_context_control.egg-info/PKG-INFO +1 -1
  7. {code_context_control-2.53.0 → code_context_control-2.54.0}/code_context_control.egg-info/SOURCES.txt +3 -0
  8. {code_context_control-2.53.0 → code_context_control-2.54.0}/pyproject.toml +1 -1
  9. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/compressor.py +5 -13
  10. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/doc_index.py +21 -17
  11. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/embedding_index.py +49 -5
  12. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/indexer.py +58 -21
  13. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/protocol.py +37 -26
  14. code_context_control-2.54.0/services/scanner.py +120 -0
  15. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/subprojects.py +3 -1
  16. code_context_control-2.54.0/tests/test_init_scan.py +195 -0
  17. {code_context_control-2.53.0 → code_context_control-2.54.0}/LICENSE +0 -0
  18. {code_context_control-2.53.0 → code_context_control-2.54.0}/README.md +0 -0
  19. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/__init__.py +0 -0
  20. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/_hook_utils.py +0 -0
  21. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/commands/__init__.py +0 -0
  22. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/commands/common.py +0 -0
  23. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/docs.html +0 -0
  24. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/edits.html +0 -0
  25. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/guide/bitbucket.html +0 -0
  26. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/guide/getting-started.html +0 -0
  27. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/guide/index.html +0 -0
  28. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/guide/oracle.html +0 -0
  29. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/guide/shared.css +0 -0
  30. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/guide/tools.html +0 -0
  31. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/guide/workflow.html +0 -0
  32. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hook_artifact.py +0 -0
  33. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hook_auto_snapshot.py +0 -0
  34. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hook_c3_signal.py +0 -0
  35. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hook_c3read.py +0 -0
  36. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hook_dispatch.py +0 -0
  37. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hook_edit_ledger.py +0 -0
  38. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hook_edit_unlock.py +0 -0
  39. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hook_filter.py +0 -0
  40. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hook_ghost_files.py +0 -0
  41. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hook_pretool_enforce.py +0 -0
  42. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hook_prompt_recall.py +0 -0
  43. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hook_read.py +0 -0
  44. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hook_session_stats.py +0 -0
  45. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hook_terse_advisor.py +0 -0
  46. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub.html +0 -0
  47. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/app.js +0 -0
  48. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/add_project.js +0 -0
  49. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/config_editor.js +0 -0
  50. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/drill_artifacts.js +0 -0
  51. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/drill_health.js +0 -0
  52. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/drill_panel.js +0 -0
  53. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/drill_tasks.js +0 -0
  54. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/drill_views.js +0 -0
  55. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/global_search.js +0 -0
  56. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/mcp_manager.js +0 -0
  57. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/modals.js +0 -0
  58. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/project_card.js +0 -0
  59. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/project_tree.js +0 -0
  60. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/session_drawer.js +0 -0
  61. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/settings_modal.js +0 -0
  62. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/sidebar.js +0 -0
  63. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/summary_bar.js +0 -0
  64. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/task_board.js +0 -0
  65. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/toasts.js +0 -0
  66. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/components/topbar.js +0 -0
  67. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui/state.js +0 -0
  68. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/hub_ui.html +0 -0
  69. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/mcp_proxy.py +0 -0
  70. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/mcp_server.py +0 -0
  71. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/server.py +0 -0
  72. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/__init__.py +0 -0
  73. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/_helpers.py +0 -0
  74. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/agent.py +0 -0
  75. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/artifacts.py +0 -0
  76. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/bitbucket.py +0 -0
  77. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/compress.py +0 -0
  78. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/delegate.py +0 -0
  79. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/edit.py +0 -0
  80. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/edits.py +0 -0
  81. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/federate.py +0 -0
  82. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/filter.py +0 -0
  83. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/impact.py +0 -0
  84. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/memory.py +0 -0
  85. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/project.py +0 -0
  86. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/read.py +0 -0
  87. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/search.py +0 -0
  88. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/session.py +0 -0
  89. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/shell.py +0 -0
  90. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/status.py +0 -0
  91. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/tasks.py +0 -0
  92. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/tools/validate.py +0 -0
  93. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui/api.js +0 -0
  94. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui/app.js +0 -0
  95. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui/components/bitbucket.js +0 -0
  96. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui/components/chat.js +0 -0
  97. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui/components/dashboard.js +0 -0
  98. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui/components/edits.js +0 -0
  99. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui/components/instructions.js +0 -0
  100. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui/components/memory.js +0 -0
  101. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui/components/sessions.js +0 -0
  102. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui/components/settings.js +0 -0
  103. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui/components/sidebar.js +0 -0
  104. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui/components/tasks.js +0 -0
  105. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui/icons.js +0 -0
  106. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui/pm_shared.js +0 -0
  107. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui/shared.js +0 -0
  108. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui/theme.js +0 -0
  109. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui.html +0 -0
  110. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui_legacy.html +0 -0
  111. {code_context_control-2.53.0 → code_context_control-2.54.0}/cli/ui_nano.html +0 -0
  112. {code_context_control-2.53.0 → code_context_control-2.54.0}/code_context_control.egg-info/dependency_links.txt +0 -0
  113. {code_context_control-2.53.0 → code_context_control-2.54.0}/code_context_control.egg-info/entry_points.txt +0 -0
  114. {code_context_control-2.53.0 → code_context_control-2.54.0}/code_context_control.egg-info/requires.txt +0 -0
  115. {code_context_control-2.53.0 → code_context_control-2.54.0}/code_context_control.egg-info/top_level.txt +0 -0
  116. {code_context_control-2.53.0 → code_context_control-2.54.0}/core/__init__.py +0 -0
  117. {code_context_control-2.53.0 → code_context_control-2.54.0}/core/config.py +0 -0
  118. {code_context_control-2.53.0 → code_context_control-2.54.0}/core/ide.py +0 -0
  119. {code_context_control-2.53.0 → code_context_control-2.54.0}/core/mcp_toml.py +0 -0
  120. {code_context_control-2.53.0 → code_context_control-2.54.0}/core/web_security.py +0 -0
  121. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/__init__.py +0 -0
  122. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/config.py +0 -0
  123. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/mcp_oracle.py +0 -0
  124. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/oracle_server.py +0 -0
  125. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/oracle_ui.html +0 -0
  126. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/services/__init__.py +0 -0
  127. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/services/activity_reporter.py +0 -0
  128. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/services/api_auth.py +0 -0
  129. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/services/c3_bridge.py +0 -0
  130. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/services/chat_engine.py +0 -0
  131. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/services/chat_store.py +0 -0
  132. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/services/cross_memory.py +0 -0
  133. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/services/federated_graph.py +0 -0
  134. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/services/health_checker.py +0 -0
  135. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/services/insight_engine.py +0 -0
  136. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/services/local_session.py +0 -0
  137. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/services/memory_reader.py +0 -0
  138. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/services/memory_writer.py +0 -0
  139. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/services/project_scanner.py +0 -0
  140. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/services/review_agent.py +0 -0
  141. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/services/tool_executor.py +0 -0
  142. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/services/tool_registry.py +0 -0
  143. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/ui/activity.js +0 -0
  144. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/ui/agents.js +0 -0
  145. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/ui/app.js +0 -0
  146. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/ui/busy.js +0 -0
  147. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/ui/chat/conversations.js +0 -0
  148. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/ui/chat/input.js +0 -0
  149. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/ui/chat/markdown.js +0 -0
  150. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/ui/chat/send.js +0 -0
  151. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/ui/chat/stream_renderer.js +0 -0
  152. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/ui/chat/toolbar.js +0 -0
  153. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/ui/core.js +0 -0
  154. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/ui/crossgraph.js +0 -0
  155. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/ui/header.js +0 -0
  156. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/ui/insights.js +0 -0
  157. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/ui/projects.js +0 -0
  158. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/ui/settings.js +0 -0
  159. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/ui/suggestions.js +0 -0
  160. {code_context_control-2.53.0 → code_context_control-2.54.0}/oracle/ui/theme_tabs.js +0 -0
  161. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/__init__.py +0 -0
  162. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/activity_log.py +0 -0
  163. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/agent_base.py +0 -0
  164. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/agents.py +0 -0
  165. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/artifact_defs.py +0 -0
  166. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/artifact_store.py +0 -0
  167. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/auto_memory.py +0 -0
  168. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/bench/__init__.py +0 -0
  169. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/bench/external/__init__.py +0 -0
  170. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/bench/external/aider_polyglot.py +0 -0
  171. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/bench/external/swe_bench.py +0 -0
  172. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/benchmark_dashboard.py +0 -0
  173. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/bitbucket_client.py +0 -0
  174. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/bitbucket_credentials.py +0 -0
  175. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/circuit_breaker.py +0 -0
  176. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/claude_md.py +0 -0
  177. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/context_snapshot.py +0 -0
  178. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/conversation_store.py +0 -0
  179. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/e2e_benchmark.py +0 -0
  180. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/e2e_evaluator.py +0 -0
  181. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/e2e_tasks.py +0 -0
  182. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/edit_ledger.py +0 -0
  183. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/error_reporting.py +0 -0
  184. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/file_memory.py +0 -0
  185. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/git_context.py +0 -0
  186. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/hub_service.py +0 -0
  187. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/memory.py +0 -0
  188. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/memory_consolidator.py +0 -0
  189. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/memory_distiller.py +0 -0
  190. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/memory_graph.py +0 -0
  191. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/memory_grounder.py +0 -0
  192. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/memory_queue.py +0 -0
  193. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/memory_scorer.py +0 -0
  194. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/metrics.py +0 -0
  195. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/notifications.py +0 -0
  196. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/ollama_bridge.py +0 -0
  197. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/ollama_client.py +0 -0
  198. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/ollama_credentials.py +0 -0
  199. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/output_filter.py +0 -0
  200. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/parser.py +0 -0
  201. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/project_manager.py +0 -0
  202. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/project_runtime.py +0 -0
  203. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/proxy_state.py +0 -0
  204. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/retention.py +0 -0
  205. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/retrieval_broker.py +0 -0
  206. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/router.py +0 -0
  207. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/runtime.py +0 -0
  208. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/session_benchmark.py +0 -0
  209. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/session_manager.py +0 -0
  210. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/session_preloader.py +0 -0
  211. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/task_store.py +0 -0
  212. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/telemetry.py +0 -0
  213. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/text_index.py +0 -0
  214. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/time_tracker.py +0 -0
  215. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/tool_classifier.py +0 -0
  216. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/transcript_index.py +0 -0
  217. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/validation_cache.py +0 -0
  218. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/vector_store.py +0 -0
  219. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/watcher.py +0 -0
  220. {code_context_control-2.53.0 → code_context_control-2.54.0}/services/win_subprocess.py +0 -0
  221. {code_context_control-2.53.0 → code_context_control-2.54.0}/setup.cfg +0 -0
  222. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_activity_reporter.py +0 -0
  223. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_aider_polyglot.py +0 -0
  224. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_antigravity_transition.py +0 -0
  225. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_artifact_store.py +0 -0
  226. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_artifact_tool.py +0 -0
  227. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_bitbucket_cli_smoke.py +0 -0
  228. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_bitbucket_client.py +0 -0
  229. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_bitbucket_config_fallback.py +0 -0
  230. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_bitbucket_credentials.py +0 -0
  231. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_bitbucket_tool.py +0 -0
  232. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_c3_bridge_project_artifacts.py +0 -0
  233. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_c3_shell.py +0 -0
  234. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_circuit_breaker.py +0 -0
  235. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_claude_md_merge.py +0 -0
  236. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_cli_smoke.py +0 -0
  237. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_compressor_large_file.py +0 -0
  238. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_delegate_cascade.py +0 -0
  239. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_e2e_benchmark.py +0 -0
  240. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_edit_ledger_hook.py +0 -0
  241. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_edit_normalization.py +0 -0
  242. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_enforcement_flip.py +0 -0
  243. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_federated_graph.py +0 -0
  244. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_filter_backoff.py +0 -0
  245. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_ghost_files.py +0 -0
  246. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_ghost_generation.py +0 -0
  247. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_git_branch_awareness.py +0 -0
  248. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_hook_dispatch.py +0 -0
  249. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_hook_pretool_enforce.py +0 -0
  250. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_hook_prompt_recall.py +0 -0
  251. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_hook_smoke.py +0 -0
  252. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_hook_state.py +0 -0
  253. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_hook_utf8_stdio.py +0 -0
  254. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_hub_inspect_api.py +0 -0
  255. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_hub_server_smoke.py +0 -0
  256. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_install_mcp_entrypoint.py +0 -0
  257. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_lazy_store_init.py +0 -0
  258. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_mcp_host_guard.py +0 -0
  259. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_mcp_memory_timeout.py +0 -0
  260. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_mcp_server_smoke.py +0 -0
  261. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_mcp_toml.py +0 -0
  262. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_memory_distiller.py +0 -0
  263. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_memory_graph_api.py +0 -0
  264. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_memory_queue.py +0 -0
  265. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_memory_system.py +0 -0
  266. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_notification_dedup.py +0 -0
  267. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_notification_discipline.py +0 -0
  268. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_ollama_credentials.py +0 -0
  269. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_oracle_api_auth.py +0 -0
  270. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_oracle_apikey_api.py +0 -0
  271. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_oracle_c3_bridge.py +0 -0
  272. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_oracle_chat_engine.py +0 -0
  273. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_oracle_discovery_api.py +0 -0
  274. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_oracle_local_auth.py +0 -0
  275. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_oracle_ollama_bridge.py +0 -0
  276. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_oracle_scanner_cache.py +0 -0
  277. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_oracle_security_fixes.py +0 -0
  278. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_oracle_subproject_awareness.py +0 -0
  279. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_oracle_ui_bundle.py +0 -0
  280. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_output_filter.py +0 -0
  281. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_permissions.py +0 -0
  282. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_pm_api.py +0 -0
  283. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_project_manager.py +0 -0
  284. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_project_manager_merge.py +0 -0
  285. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_project_tool.py +0 -0
  286. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_read_coercion.py +0 -0
  287. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_read_edit_parity.py +0 -0
  288. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_related_facts.py +0 -0
  289. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_response_boilerplate.py +0 -0
  290. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_retention.py +0 -0
  291. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_review_digest.py +0 -0
  292. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_service_durability.py +0 -0
  293. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_session_benchmark.py +0 -0
  294. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_session_budget.py +0 -0
  295. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_shell_robustness.py +0 -0
  296. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_subproject_exclusion.py +0 -0
  297. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_subproject_federation.py +0 -0
  298. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_subprojects.py +0 -0
  299. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_swe_bench.py +0 -0
  300. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_task_store.py +0 -0
  301. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_task_tool.py +0 -0
  302. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_time_tracker.py +0 -0
  303. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_token_telemetry.py +0 -0
  304. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_tool_registry.py +0 -0
  305. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_upgrade_and_version.py +0 -0
  306. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_validate.py +0 -0
  307. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_web_security.py +0 -0
  308. {code_context_control-2.53.0 → code_context_control-2.54.0}/tests/test_windows_reliability.py +0 -0
  309. {code_context_control-2.53.0 → code_context_control-2.54.0}/tui/__init__.py +0 -0
  310. {code_context_control-2.53.0 → code_context_control-2.54.0}/tui/backend.py +0 -0
  311. {code_context_control-2.53.0 → code_context_control-2.54.0}/tui/main.py +0 -0
  312. {code_context_control-2.53.0 → code_context_control-2.54.0}/tui/screens/__init__.py +0 -0
  313. {code_context_control-2.53.0 → code_context_control-2.54.0}/tui/screens/benchmark_view.py +0 -0
  314. {code_context_control-2.53.0 → code_context_control-2.54.0}/tui/screens/claudemd_view.py +0 -0
  315. {code_context_control-2.53.0 → code_context_control-2.54.0}/tui/screens/compress_view.py +0 -0
  316. {code_context_control-2.53.0 → code_context_control-2.54.0}/tui/screens/index_view.py +0 -0
  317. {code_context_control-2.53.0 → code_context_control-2.54.0}/tui/screens/init_view.py +0 -0
  318. {code_context_control-2.53.0 → code_context_control-2.54.0}/tui/screens/mcp_view.py +0 -0
  319. {code_context_control-2.53.0 → code_context_control-2.54.0}/tui/screens/optimize_view.py +0 -0
  320. {code_context_control-2.53.0 → code_context_control-2.54.0}/tui/screens/pipe_view.py +0 -0
  321. {code_context_control-2.53.0 → code_context_control-2.54.0}/tui/screens/projects_view.py +0 -0
  322. {code_context_control-2.53.0 → code_context_control-2.54.0}/tui/screens/search_view.py +0 -0
  323. {code_context_control-2.53.0 → code_context_control-2.54.0}/tui/screens/session_view.py +0 -0
  324. {code_context_control-2.53.0 → code_context_control-2.54.0}/tui/screens/stats.py +0 -0
  325. {code_context_control-2.53.0 → code_context_control-2.54.0}/tui/screens/ui_view.py +0 -0
  326. {code_context_control-2.53.0 → code_context_control-2.54.0}/tui/theme.tcss +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-context-control
3
- Version: 2.53.0
3
+ Version: 2.54.0
4
4
  Summary: Local code-intelligence layer for AI coding tools (Claude Code, Codex, Copilot, Cursor, Antigravity). Retrieve less, read less, edit safer — and version the configs that shape your agent (CLAUDE.md, skills, hooks, MCP).
5
5
  Author-email: Dimitri Tselenchuk <dtselenc@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -92,7 +92,7 @@ console = Console() if HAS_RICH else None
92
92
  # Config
93
93
  CONFIG_DIR = ".c3"
94
94
  CONFIG_FILE = ".c3/config.json"
95
- __version__ = "2.53.0"
95
+ __version__ = "2.54.0"
96
96
 
97
97
 
98
98
  def _command_deps() -> CommandDeps:
@@ -165,6 +165,7 @@ def _build_init_config(project_path: str) -> dict:
165
165
  "project_path": project_path,
166
166
  "version": __version__,
167
167
  "index_auto_update": True,
168
+ "index_max_files": 2000,
168
169
  "compression_mode": "smart",
169
170
  "mcp": {"mode": "direct"},
170
171
  "hybrid": deepcopy(HYBRID_DEFAULTS),
@@ -890,7 +891,7 @@ def _parse_cli_ide_arg(value: str) -> str:
890
891
  return normalized
891
892
 
892
893
 
893
- def _do_init(project_path: str, ide_name: str = None):
894
+ def _do_init(project_path: str, ide_name: str = None, no_embed: bool = False):
894
895
  """Run the core init steps (shared by new install and re-init after clear/reset)."""
895
896
  config = _build_init_config(project_path)
896
897
  save_config(config, project_path)
@@ -898,10 +899,27 @@ def _do_init(project_path: str, ide_name: str = None):
898
899
  for subdir in _C3_INIT_SUBDIRS:
899
900
  (Path(project_path) / CONFIG_DIR / subdir).mkdir(parents=True, exist_ok=True)
900
901
 
902
+ import time as _t
903
+
904
+ from cli.progress import ProgressLine
905
+
901
906
  print("Building code index...")
907
+ _prog = ProgressLine()
908
+ _t0 = _t.perf_counter()
902
909
  indexer = CodeIndex(project_path)
903
- result = indexer.build_index()
904
- print(f" Indexed {result['files_indexed']} files, {result['chunks_created']} chunks")
910
+ result = indexer.build_index(
911
+ on_progress=lambda entries, files, chunks: _prog.update(
912
+ f" scanning: {entries:,} entries | {files:,} files | {chunks:,} chunks"))
913
+ _prog.done()
914
+ entries = result.get("entries_scanned", 0)
915
+ print(f" Indexed {result['files_indexed']} files, {result['chunks_created']} chunks "
916
+ f"in {_t.perf_counter() - _t0:.1f}s ({entries:,} entries scanned)")
917
+ capped = result.get("files_capped", 0)
918
+ if capped:
919
+ total = result["files_indexed"] + capped
920
+ print(f" [!] Indexed {result['files_indexed']} of {total} candidate files "
921
+ f"(cap: index_max_files={result.get('max_files')}).")
922
+ print(" Raise index_max_files in .c3/config.json for full coverage.")
905
923
 
906
924
  # Build embedding index if Ollama is available (non-blocking on failure)
907
925
  try:
@@ -912,13 +930,24 @@ def _do_init(project_path: str, ide_name: str = None):
912
930
  ollama = OllamaClient(ollama_url)
913
931
  embed_model = config.get("embed_model", "nomic-embed-text")
914
932
  ei = EmbeddingIndex(project_path, ollama, embed_model=embed_model)
915
- if ei.ready:
933
+ if no_embed:
934
+ print(" Embedding index skipped (--no-embed)")
935
+ elif ei.probe()["ready"]:
936
+ # probe() initializes the lazy backends; checking .ready on a
937
+ # fresh instance is always False and silently skipped the build.
916
938
  print("Building embedding index...")
917
- ei_result = ei.build(indexer)
939
+ _t0 = _t.perf_counter()
940
+ _eprog = ProgressLine()
941
+ ei_result = ei.build(
942
+ indexer,
943
+ on_progress=lambda done, total, chunks: _eprog.update(
944
+ f" embedding: file {done}/{total} | {chunks:,} chunks"))
945
+ _eprog.done()
918
946
  print(f" Embedded {ei_result.get('chunks_embedded', 0)} chunks "
919
- f"({ei_result.get('files_processed', 0)} files)")
947
+ f"({ei_result.get('files_processed', 0)} files) "
948
+ f"in {_t.perf_counter() - _t0:.1f}s")
920
949
  else:
921
- print(" Embedding index skipped (Ollama not available or model not pulled)")
950
+ print(f" Embedding index skipped ({ei.unavailable_reason()})")
922
951
  except Exception:
923
952
  _log.debug("Embedding index build failed", exc_info=True)
924
953
 
@@ -926,15 +955,22 @@ def _do_init(project_path: str, ide_name: str = None):
926
955
  try:
927
956
  from services.doc_index import DocIndex
928
957
  print("Building doc index...")
958
+ _t0 = _t.perf_counter()
959
+ _dprog = ProgressLine()
929
960
  di = DocIndex(project_path)
930
- di_result = di.build()
931
- print(f" Indexed {di_result['docs_indexed']} docs, {di_result['chunks_created']} chunks")
961
+ di_result = di.build(
962
+ on_progress=lambda done, total: _dprog.update(
963
+ f" docs: {done}/{total}"))
964
+ _dprog.done()
965
+ print(f" Indexed {di_result['docs_indexed']} docs, "
966
+ f"{di_result['chunks_created']} chunks in {_t.perf_counter() - _t0:.1f}s")
932
967
  except Exception:
933
968
  _log.debug("Doc index build failed", exc_info=True)
934
969
 
935
970
  print("Building compression dictionary...")
936
971
  protocol = CompressionProtocol(project_path)
937
- new_terms = protocol.build_project_dictionary()
972
+ # Mine the in-memory index instead of re-reading the whole tree.
973
+ new_terms = protocol.build_project_dictionary(code_index=indexer)
938
974
  print(f" Added {len(new_terms)} project-specific terms")
939
975
 
940
976
  from core.ide import detect_ide, load_ide_config
@@ -966,11 +1002,12 @@ def cmd_init(args):
966
1002
  if requested_ide != "auto":
967
1003
  requested_ide = normalize_ide_name(requested_ide)
968
1004
  git_requested = getattr(args, "git", False)
1005
+ no_embed = bool(getattr(args, "no_embed", False))
969
1006
 
970
1007
  # ── Brand-new install ──────────────────────────────────────
971
1008
  if not c3_dir.exists() or not (c3_dir / "config.json").exists():
972
1009
  print_header(f"Initializing C3 for: {project_path}")
973
- _do_init(project_path, ide_name=requested_ide)
1010
+ _do_init(project_path, ide_name=requested_ide, no_embed=no_embed)
974
1011
  try:
975
1012
  from services.project_manager import ProjectManager
976
1013
  ProjectManager().add_project(project_path)
@@ -1123,7 +1160,7 @@ def cmd_init(args):
1123
1160
  ti_manifest = c3_dir / "transcript_index" / "manifest.json"
1124
1161
  if ti_manifest.exists():
1125
1162
  ti_manifest.write_text("{}", encoding="utf-8")
1126
- _do_init(project_path, ide_name=requested_ide)
1163
+ _do_init(project_path, ide_name=requested_ide, no_embed=no_embed)
1127
1164
  if git_requested:
1128
1165
  _init_local_git_repo(project_path)
1129
1166
  _run_install_mcp(project_path, requested_ide, mcp_mode=getattr(args, "mcp_mode", "direct"), banner="Updating MCP tools...")
@@ -1152,7 +1189,7 @@ def cmd_init(args):
1152
1189
  # ── Non-interactive (--force) ──────────────────────────────
1153
1190
  if getattr(args, "force", False):
1154
1191
  print("\n[--force] Applying update...")
1155
- _do_init(project_path, ide_name=requested_ide)
1192
+ _do_init(project_path, ide_name=requested_ide, no_embed=no_embed)
1156
1193
  if git_requested:
1157
1194
  _init_local_git_repo(project_path)
1158
1195
  _run_install_mcp(project_path, requested_ide, mcp_mode=getattr(args, "mcp_mode", "direct"), banner="Updating MCP tools...")
@@ -1176,7 +1213,7 @@ def cmd_init(args):
1176
1213
 
1177
1214
  if selected.startswith("Update"):
1178
1215
  print()
1179
- _do_init(project_path, ide_name=requested_ide)
1216
+ _do_init(project_path, ide_name=requested_ide, no_embed=no_embed)
1180
1217
  if git_requested:
1181
1218
  _init_local_git_repo(project_path)
1182
1219
  _prompt_install_mcp(project_path, requested_ide, default_mode=getattr(args, "mcp_mode", "direct"), banner="Updating MCP tools...")
@@ -1192,7 +1229,7 @@ def cmd_init(args):
1192
1229
  shutil.rmtree(target)
1193
1230
  print(f" Removed .c3/{subdir}/")
1194
1231
  print()
1195
- _do_init(project_path, ide_name=requested_ide)
1232
+ _do_init(project_path, ide_name=requested_ide, no_embed=no_embed)
1196
1233
  if git_requested:
1197
1234
  _init_local_git_repo(project_path)
1198
1235
  _prompt_install_mcp(project_path, requested_ide, default_mode=getattr(args, "mcp_mode", "direct"), banner="Updating MCP tools...")
@@ -1209,7 +1246,7 @@ def cmd_init(args):
1209
1246
  shutil.rmtree(c3_dir)
1210
1247
  print(" Deleted .c3/")
1211
1248
  print()
1212
- _do_init(project_path, ide_name=requested_ide)
1249
+ _do_init(project_path, ide_name=requested_ide, no_embed=no_embed)
1213
1250
  if git_requested:
1214
1251
  _init_local_git_repo(project_path)
1215
1252
  _prompt_install_mcp(project_path, requested_ide, default_mode=getattr(args, "mcp_mode", "direct"), banner="Re-installing MCP tools...")
@@ -24,6 +24,7 @@ def build_parser(version: str, parse_cli_ide_arg):
24
24
  p_init.add_argument("--ide", default="auto", type=parse_cli_ide_arg, metavar="{auto,claude,vscode,cursor,codex,antigravity}", help="Target IDE for MCP config (default: auto-detect)")
25
25
  p_init.add_argument("--mcp-mode", choices=["direct", "proxy"], default="direct", help="Default MCP mode if install is selected during init (default: direct)")
26
26
  p_init.add_argument("--git", action="store_true", help="Initialize a local Git repository during init/update")
27
+ p_init.add_argument("--no-embed", action="store_true", help="Skip building the semantic embedding index during init")
27
28
  p_init.add_argument("--permissions", choices=["read-only", "c3-strict", "standard", "permissive"], default=None, help="Apply Claude Code permission tier (Claude Code only, used with --force)")
28
29
  p_init.add_argument("--include-mcp-wildcard", action="store_true", help="Add mcp__* wildcard so non-C3 MCP servers don't prompt per-call")
29
30
 
@@ -1027,8 +1027,10 @@ def api_run_component():
1027
1027
  ollama = OllamaClient(ollama_url)
1028
1028
  embed_model = cfg.get("embed_model", "nomic-embed-text")
1029
1029
  ei = EmbeddingIndex(resolved, ollama, embed_model=embed_model)
1030
- if not ei.ready:
1031
- return jsonify({"success": True, "output": "Embedding index skipped (Ollama not available or model not pulled)."})
1030
+ # probe() initializes lazy backends; a fresh instance's .ready
1031
+ # is always False and would skip the build unconditionally.
1032
+ if not ei.probe()["ready"]:
1033
+ return jsonify({"success": True, "output": f"Embedding index skipped ({ei.unavailable_reason()})."})
1032
1034
  indexer = CodeIndex(resolved)
1033
1035
  if not indexer.chunks:
1034
1036
  indexer._load_index()
@@ -0,0 +1,49 @@
1
+ """
2
+ Single-line TTY progress for long CLI phases (index/embedding builds).
3
+
4
+ Quiet when stdout is piped - CI logs and command substitutions see only
5
+ the final summary lines, never carriage-return spam.
6
+ """
7
+ import sys
8
+ import time
9
+
10
+
11
+ class ProgressLine:
12
+ """Rewrites one status line in place; time-throttled; TTY-only."""
13
+
14
+ def __init__(self, stream=None, min_interval: float = 0.1):
15
+ self.stream = stream if stream is not None else sys.stdout
16
+ self.min_interval = min_interval
17
+ self._last = 0.0
18
+ self._width = 0
19
+ try:
20
+ self._tty = bool(self.stream.isatty())
21
+ except Exception:
22
+ self._tty = False
23
+
24
+ def update(self, text: str) -> None:
25
+ if not self._tty:
26
+ return
27
+ now = time.monotonic()
28
+ if now - self._last < self.min_interval:
29
+ return
30
+ self._last = now
31
+ pad = ' ' * max(0, self._width - len(text))
32
+ try:
33
+ self.stream.write('\r' + text + pad)
34
+ self.stream.flush()
35
+ except Exception:
36
+ self._tty = False
37
+ return
38
+ self._width = len(text)
39
+
40
+ def done(self) -> None:
41
+ """Clear the in-place line so the following prints start clean."""
42
+ if not self._tty or not self._width:
43
+ return
44
+ try:
45
+ self.stream.write('\r' + ' ' * self._width + '\r')
46
+ self.stream.flush()
47
+ except Exception:
48
+ pass
49
+ self._width = 0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-context-control
3
- Version: 2.53.0
3
+ Version: 2.54.0
4
4
  Summary: Local code-intelligence layer for AI coding tools (Claude Code, Codex, Copilot, Cursor, Antigravity). Retrieve less, read less, edit safer — and version the configs that shape your agent (CLAUDE.md, skills, hooks, MCP).
5
5
  Author-email: Dimitri Tselenchuk <dtselenc@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -25,6 +25,7 @@ cli/hub_server.py
25
25
  cli/hub_ui.html
26
26
  cli/mcp_proxy.py
27
27
  cli/mcp_server.py
28
+ cli/progress.py
28
29
  cli/server.py
29
30
  cli/ui.html
30
31
  cli/ui_legacy.html
@@ -196,6 +197,7 @@ services/retention.py
196
197
  services/retrieval_broker.py
197
198
  services/router.py
198
199
  services/runtime.py
200
+ services/scanner.py
199
201
  services/session_benchmark.py
200
202
  services/session_manager.py
201
203
  services/session_preloader.py
@@ -248,6 +250,7 @@ tests/test_hook_state.py
248
250
  tests/test_hook_utf8_stdio.py
249
251
  tests/test_hub_inspect_api.py
250
252
  tests/test_hub_server_smoke.py
253
+ tests/test_init_scan.py
251
254
  tests/test_install_mcp_entrypoint.py
252
255
  tests/test_lazy_store_init.py
253
256
  tests/test_mcp_host_guard.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "code-context-control"
7
- version = "2.53.0"
7
+ version = "2.54.0"
8
8
  description = "Local code-intelligence layer for AI coding tools (Claude Code, Codex, Copilot, Cursor, Antigravity). Retrieve less, read less, edit safer — and version the configs that shape your agent (CLAUDE.md, skills, hooks, MCP)."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -709,27 +709,19 @@ class CodeCompressor:
709
709
  '.css', '.html', '.json', '.yaml', '.yml', '.md'}
710
710
  allowed = set(extensions) if extensions else default_exts
711
711
 
712
- # Skip common non-essential dirs
713
- skip_dirs = {'node_modules', '.git', '__pycache__', '.c3', 'venv',
714
- 'env', '.venv', 'dist', 'build', '.next', '.cache'}
715
-
716
712
  results = []
717
713
  total_original = 0
718
714
  total_compressed = 0
719
715
  skipped_protected = []
720
716
 
721
- files = sorted(dirpath.rglob('*'))[:max_files * 3] # Pre-limit
722
- count = 0
717
+ # Pruned walk (shared SKIP_DIRS) - never descends into
718
+ # node_modules/.git/etc., stops as soon as the cap is reached.
719
+ from services.scanner import iter_files
723
720
 
724
- for fpath in files:
721
+ count = 0
722
+ for fpath in iter_files(dirpath, exts={e.lower() for e in allowed}):
725
723
  if count >= max_files:
726
724
  break
727
- if not fpath.is_file():
728
- continue
729
- if fpath.suffix.lower() not in allowed:
730
- continue
731
- if any(skip in fpath.parts for skip in skip_dirs):
732
- continue
733
725
  if self.is_protected_file(fpath):
734
726
  skipped_protected.append(self._relative_to_project(fpath))
735
727
  continue
@@ -92,15 +92,26 @@ class DocIndex:
92
92
 
93
93
  # --- Build ---
94
94
 
95
- def build(self, force: bool = False) -> dict:
96
- """Build or incrementally update the doc index."""
95
+ def build(self, force: bool = False, on_progress=None) -> dict:
96
+ """Build or incrementally update the doc index.
97
+
98
+ on_progress: callable(files_done, files_total), invoked per file.
99
+ """
97
100
  stats = {"docs_indexed": 0, "chunks_created": 0, "skipped": 0}
98
101
 
99
102
  files_to_index = self._discover_files()
100
103
  old_hashes = dict(self._file_hashes)
101
104
  new_hashes = {}
105
+ files_total = len(files_to_index)
106
+ files_done = 0
102
107
 
103
108
  for rel_path, fpath in files_to_index:
109
+ files_done += 1
110
+ if on_progress is not None:
111
+ try:
112
+ on_progress(files_done, files_total)
113
+ except Exception:
114
+ pass
104
115
  try:
105
116
  content = fpath.read_text(errors="replace")
106
117
  except Exception:
@@ -154,12 +165,6 @@ class DocIndex:
154
165
 
155
166
  def _discover_files(self) -> list[tuple[str, Path]]:
156
167
  """Find all doc, config, and code files to index."""
157
- skip_dirs = {
158
- "node_modules", ".git", "__pycache__", ".c3", "venv",
159
- "env", ".venv", "dist", "build", ".next", ".cache",
160
- "coverage", ".pytest_cache",
161
- }
162
-
163
168
  # Designated sub-projects keep their own doc index.
164
169
  try:
165
170
  from services.subprojects import make_excluder
@@ -170,15 +175,14 @@ class DocIndex:
170
175
 
171
176
  files = []
172
177
 
173
- # Markdown docs
174
- for ext in ("*.md", "*.mdx", "*.rst", "*.adoc"):
175
- for fpath in self.project_path.rglob(ext):
176
- if any(skip in fpath.parts for skip in skip_dirs):
177
- continue
178
- if _sub_excluded(fpath):
179
- continue
180
- rel = str(fpath.relative_to(self.project_path))
181
- files.append((rel, fpath))
178
+ # Markdown docs - one pruned walk instead of four full rglob passes
179
+ from services.scanner import iter_files
180
+ for fpath in iter_files(self.project_path,
181
+ exts={".md", ".mdx", ".rst", ".adoc"}):
182
+ if _sub_excluded(fpath):
183
+ continue
184
+ rel = str(fpath.relative_to(self.project_path))
185
+ files.append((rel, fpath))
182
186
 
183
187
  # Config files at project root
184
188
  for pattern in _CONFIG_PATTERNS:
@@ -39,6 +39,8 @@ class EmbeddingIndex:
39
39
  self._collection = None
40
40
  self._available = False
41
41
  self._ollama_ok = False
42
+ self._ollama_up = False
43
+ self._model_ok = False
42
44
  self._file_hashes: dict[str, str] = {} # doc_id -> content hash
43
45
  self._lock = threading.Lock()
44
46
  self._chunk_map: dict[str, dict] = {} # chunk_id -> metadata
@@ -101,18 +103,47 @@ class EmbeddingIndex:
101
103
  self._available = False
102
104
 
103
105
  try:
104
- self._ollama_ok = (
105
- self.ollama.is_available(timeout=2)
106
- and self.ollama.has_model(self.embed_model)
106
+ self._ollama_up = self.ollama.is_available(timeout=2)
107
+ self._model_ok = (
108
+ self._ollama_up and self.ollama.has_model(self.embed_model)
107
109
  )
108
110
  except Exception:
109
- self._ollama_ok = False
111
+ self._ollama_up = False
112
+ self._model_ok = False
113
+ self._ollama_ok = self._ollama_up and self._model_ok
110
114
 
111
115
  @property
112
116
  def ready(self) -> bool:
113
117
  """True when both chromadb and Ollama embeddings are available."""
114
118
  return self._available and self._ollama_ok
115
119
 
120
+ def probe(self) -> dict:
121
+ """Explicitly initialize backends and report readiness.
122
+
123
+ ``ready`` alone never triggers backend init (status reporters must
124
+ stay cheap for build_runtime/MCP handshake), so gating a build on a
125
+ fresh instance's ``ready`` always skipped. Init/CLI flows call this
126
+ instead: it pays the one-time backend cost, then reports truthfully.
127
+ """
128
+ self._ensure_ready()
129
+ return {
130
+ "ready": self.ready,
131
+ "chromadb": self._available,
132
+ "ollama": self._ollama_up,
133
+ "model": self._model_ok,
134
+ }
135
+
136
+ def unavailable_reason(self) -> str:
137
+ """Human-readable reason ``ready`` is False (after probe/init)."""
138
+ if not self._available:
139
+ return "chromadb not installed"
140
+ if not self._ollama_up:
141
+ return "Ollama not reachable"
142
+ if not self._model_ok:
143
+ return (f"embed model '{self.embed_model}' not pulled "
144
+ f"(run: ollama pull {self.embed_model})")
145
+ return ""
146
+
116
147
  # ── Hash tracking ─────────────────────────────────────
117
148
 
118
149
  def _load_hashes(self):
@@ -138,12 +169,14 @@ class EmbeddingIndex:
138
169
 
139
170
  # ── Build / Update ────────────────────────────────────
140
171
 
141
- def build(self, code_index, force: bool = False) -> dict:
172
+ def build(self, code_index, force: bool = False, on_progress=None) -> dict:
142
173
  """Build or incrementally update the embedding index from CodeIndex chunks.
143
174
 
144
175
  Args:
145
176
  code_index: A CodeIndex instance with populated chunks/documents.
146
177
  force: If True, re-embed all files regardless of hash.
178
+ on_progress: callable(files_done, files_total, chunks_embedded),
179
+ invoked per file (skipped files count as done).
147
180
 
148
181
  Returns:
149
182
  Stats dict with files_processed, chunks_embedded, chunks_skipped, etc.
@@ -170,6 +203,15 @@ class EmbeddingIndex:
170
203
  files_skipped = 0
171
204
  errors = 0
172
205
  stale_ids = []
206
+ files_total = len(chunks_by_file)
207
+
208
+ def _report():
209
+ if on_progress is not None:
210
+ try:
211
+ on_progress(files_processed + files_skipped, files_total,
212
+ chunks_embedded)
213
+ except Exception:
214
+ pass
173
215
 
174
216
  with self._lock:
175
217
  # Detect deleted files — remove their embeddings
@@ -187,6 +229,7 @@ class EmbeddingIndex:
187
229
  if not force and self._file_hashes.get(doc_id) == new_hash:
188
230
  files_skipped += 1
189
231
  chunks_skipped += len(file_chunks)
232
+ _report()
190
233
  continue
191
234
 
192
235
  # Remove old chunks for this file before re-embedding
@@ -237,6 +280,7 @@ class EmbeddingIndex:
237
280
 
238
281
  self._file_hashes[doc_id] = new_hash
239
282
  files_processed += 1
283
+ _report()
240
284
 
241
285
  self._save_hashes()
242
286
 
@@ -13,6 +13,7 @@ from collections import Counter, OrderedDict
13
13
  from pathlib import Path
14
14
 
15
15
  from core import count_tokens
16
+ from services.scanner import SKIP_DIRS, iter_files
16
17
 
17
18
 
18
19
  class CodeIndex:
@@ -37,10 +38,8 @@ class CodeIndex:
37
38
  self._cooccurrence = {} # term -> {term: count} for auto-synonyms
38
39
  self._file_mtimes = {} # doc_id -> mtime for recency bias
39
40
 
40
- # Config
41
- self.skip_dirs = {'node_modules', '.git', '__pycache__', '.c3', 'venv',
42
- 'env', '.venv', 'dist', 'build', '.next', '.cache',
43
- 'coverage', '.pytest_cache'}
41
+ # Config - shared pruned-walk skip set (services/scanner.py)
42
+ self.skip_dirs = set(SKIP_DIRS)
44
43
  self.code_exts = {
45
44
  # Python
46
45
  '.py', '.pyi', '.pyx',
@@ -87,8 +86,31 @@ class CodeIndex:
87
86
  self.exclude_prefixes = []
88
87
  self._is_excluded = None
89
88
 
90
- def build_index(self, max_files: int = 500) -> dict:
91
- """Build the full code index."""
89
+ _DEFAULT_MAX_FILES = 2000
90
+
91
+ def _configured_max_files(self) -> int:
92
+ """``index_max_files`` from .c3/config.json; default 2000."""
93
+ try:
94
+ cfg = json.loads((self.project_path / '.c3' / 'config.json')
95
+ .read_text(encoding='utf-8'))
96
+ val = int(cfg.get('index_max_files', self._DEFAULT_MAX_FILES))
97
+ return val if val > 0 else self._DEFAULT_MAX_FILES
98
+ except Exception:
99
+ return self._DEFAULT_MAX_FILES
100
+
101
+ def build_index(self, max_files: int = None, on_progress=None) -> dict:
102
+ """Build the full code index.
103
+
104
+ max_files: cap on files indexed. None reads ``index_max_files``
105
+ from .c3/config.json (default 2000). Traversal continues past
106
+ the cap only to count what was left out, so callers can report
107
+ "indexed N of M" instead of silently truncating.
108
+ on_progress: callable(entries_seen, files_indexed, chunks_created),
109
+ invoked during the scan (directory granularity plus per file).
110
+ """
111
+ if max_files is None:
112
+ max_files = self._configured_max_files()
113
+
92
114
  self.documents = {}
93
115
  self.chunks = {}
94
116
  self.symbols = {}
@@ -96,24 +118,35 @@ class CodeIndex:
96
118
 
97
119
  files_indexed = 0
98
120
  chunks_created = 0
121
+ files_capped = 0
122
+ scan_stats = {"entries": 0}
99
123
 
100
- for fpath in sorted(self.project_path.rglob('*')):
101
- if files_indexed >= max_files:
102
- break
103
- if not fpath.is_file():
104
- continue
105
- if fpath.suffix.lower() not in self.code_exts:
106
- continue
107
- if any(skip in fpath.parts for skip in self.skip_dirs):
108
- continue
109
- if self.exclude_prefixes:
124
+ def _report(entries_seen=None, _yielded=None):
125
+ if entries_seen is not None:
126
+ scan_stats["entries"] = entries_seen
127
+ if on_progress is not None:
110
128
  try:
111
- if self._is_excluded(fpath.relative_to(self.project_path).parts,
112
- self.exclude_prefixes):
113
- continue
114
- except ValueError:
129
+ on_progress(scan_stats["entries"], files_indexed,
130
+ chunks_created)
131
+ except Exception:
115
132
  pass
116
133
 
134
+ exclude_parts = None
135
+ if self.exclude_prefixes and self._is_excluded is not None:
136
+ def exclude_parts(parts, _c=self._is_excluded,
137
+ _p=self.exclude_prefixes):
138
+ return _c(parts, _p)
139
+
140
+ for fpath in iter_files(self.project_path, exts=self.code_exts,
141
+ skip_dirs=self.skip_dirs,
142
+ exclude_parts=exclude_parts,
143
+ on_progress=_report):
144
+ if files_indexed >= max_files:
145
+ # Walk on (cheap after pruning) to count coverage;
146
+ # reading and chunking stop at the cap.
147
+ files_capped += 1
148
+ continue
149
+
117
150
  try:
118
151
  content = fpath.read_text(errors='replace')
119
152
  except Exception:
@@ -150,6 +183,7 @@ class CodeIndex:
150
183
  pass
151
184
 
152
185
  files_indexed += 1
186
+ _report()
153
187
 
154
188
  # Build TF-IDF and co-occurrence synonyms
155
189
  self._build_tfidf()
@@ -162,7 +196,10 @@ class CodeIndex:
162
196
  "files_indexed": files_indexed,
163
197
  "chunks_created": chunks_created,
164
198
  "unique_symbols": len(self.symbols),
165
- "index_path": str(self.index_dir)
199
+ "index_path": str(self.index_dir),
200
+ "entries_scanned": scan_stats["entries"],
201
+ "files_capped": files_capped,
202
+ "max_files": max_files,
166
203
  }
167
204
 
168
205
  def _chunk_file(self, content: str, ext: str, doc_id: str) -> list: