code-context-control 2.122.0__tar.gz → 2.123.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 (512) hide show
  1. {code_context_control-2.122.0/code_context_control.egg-info → code_context_control-2.123.0}/PKG-INFO +1 -1
  2. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/c3.py +4 -4
  3. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/guide/index.html +1 -1
  4. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/guide/workflow.html +1 -1
  5. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hook_pretool_enforce.py +1 -1
  6. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/read.py +16 -0
  7. {code_context_control-2.122.0 → code_context_control-2.123.0/code_context_control.egg-info}/PKG-INFO +1 -1
  8. {code_context_control-2.122.0 → code_context_control-2.123.0}/code_context_control.egg-info/SOURCES.txt +2 -0
  9. {code_context_control-2.122.0 → code_context_control-2.123.0}/pyproject.toml +1 -1
  10. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/claude_md.py +4 -4
  11. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/codex_integration.py +1 -1
  12. code_context_control-2.123.0/services/dir_map.py +176 -0
  13. code_context_control-2.123.0/tests/test_dir_map_c3.py +176 -0
  14. {code_context_control-2.122.0 → code_context_control-2.123.0}/LICENSE +0 -0
  15. {code_context_control-2.122.0 → code_context_control-2.123.0}/README.md +0 -0
  16. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/__init__.py +0 -0
  17. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/_hook_utils.py +0 -0
  18. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/_shell_writes.py +0 -0
  19. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/commands/__init__.py +0 -0
  20. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/commands/common.py +0 -0
  21. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/commands/parser.py +0 -0
  22. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/docs.html +0 -0
  23. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/edits.html +0 -0
  24. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/guide/access.html +0 -0
  25. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/guide/bitbucket.html +0 -0
  26. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/guide/credentials.html +0 -0
  27. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/guide/getting-started.html +0 -0
  28. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/guide/masking.html +0 -0
  29. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/guide/oracle.html +0 -0
  30. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/guide/shared.css +0 -0
  31. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/guide/tools.html +0 -0
  32. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hook_access_guard.py +0 -0
  33. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hook_artifact.py +0 -0
  34. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hook_auto_snapshot.py +0 -0
  35. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hook_c3_signal.py +0 -0
  36. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hook_c3read.py +0 -0
  37. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hook_codex_lifecycle.py +0 -0
  38. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hook_dispatch.py +0 -0
  39. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hook_edit_ledger.py +0 -0
  40. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hook_edit_unlock.py +0 -0
  41. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hook_filter.py +0 -0
  42. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hook_ghost_files.py +0 -0
  43. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hook_prompt_recall.py +0 -0
  44. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hook_read.py +0 -0
  45. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hook_session_stats.py +0 -0
  46. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hook_terse_advisor.py +0 -0
  47. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_server.py +0 -0
  48. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/app.js +0 -0
  49. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/add_project.js +0 -0
  50. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/config_editor.js +0 -0
  51. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/drill_artifacts.js +0 -0
  52. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/drill_health.js +0 -0
  53. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/drill_panel.js +0 -0
  54. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/drill_subprojects.js +0 -0
  55. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/drill_tasks.js +0 -0
  56. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/drill_views.js +0 -0
  57. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/global_search.js +0 -0
  58. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/hub_access.js +0 -0
  59. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/hub_ci.js +0 -0
  60. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/hub_cred_audit.js +0 -0
  61. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/hub_credentials.js +0 -0
  62. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/hub_enforcement.js +0 -0
  63. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/hub_locks.js +0 -0
  64. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/hub_tokens.js +0 -0
  65. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/mcp_manager.js +0 -0
  66. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/modals.js +0 -0
  67. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/project_card.js +0 -0
  68. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/project_tree.js +0 -0
  69. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/session_drawer.js +0 -0
  70. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/settings_modal.js +0 -0
  71. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/sidebar.js +0 -0
  72. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/summary_bar.js +0 -0
  73. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/task_board.js +0 -0
  74. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/toasts.js +0 -0
  75. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/components/topbar.js +0 -0
  76. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui/state.js +0 -0
  77. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/hub_ui.html +0 -0
  78. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/mcp_proxy.py +0 -0
  79. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/mcp_server.py +0 -0
  80. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/progress.py +0 -0
  81. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/server.py +0 -0
  82. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/__init__.py +0 -0
  83. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/_grants.py +0 -0
  84. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/_helpers.py +0 -0
  85. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/agent.py +0 -0
  86. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/artifacts.py +0 -0
  87. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/bitbucket.py +0 -0
  88. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/ci.py +0 -0
  89. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/compress.py +0 -0
  90. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/credentials.py +0 -0
  91. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/delegate.py +0 -0
  92. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/edit.py +0 -0
  93. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/edit_verify.py +0 -0
  94. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/edits.py +0 -0
  95. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/federate.py +0 -0
  96. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/filter.py +0 -0
  97. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/impact.py +0 -0
  98. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/jira.py +0 -0
  99. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/locks.py +0 -0
  100. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/memory.py +0 -0
  101. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/override.py +0 -0
  102. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/project.py +0 -0
  103. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/search.py +0 -0
  104. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/session.py +0 -0
  105. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/shell.py +0 -0
  106. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/shell_job.py +0 -0
  107. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/shell_nudge.py +0 -0
  108. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/shell_parsers.py +0 -0
  109. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/shell_render.py +0 -0
  110. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/status.py +0 -0
  111. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/tasks.py +0 -0
  112. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/tools/validate.py +0 -0
  113. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/api.js +0 -0
  114. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/app.js +0 -0
  115. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/components/access.js +0 -0
  116. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/components/bitbucket.js +0 -0
  117. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/components/chat.js +0 -0
  118. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/components/credentials.js +0 -0
  119. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/components/dashboard.js +0 -0
  120. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/components/edits.js +0 -0
  121. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/components/enforcement.js +0 -0
  122. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/components/instructions.js +0 -0
  123. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/components/jira.js +0 -0
  124. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/components/memory.js +0 -0
  125. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/components/sessions.js +0 -0
  126. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/components/settings.js +0 -0
  127. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/components/sidebar.js +0 -0
  128. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/components/tasks.js +0 -0
  129. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/icons.js +0 -0
  130. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/pm_shared.js +0 -0
  131. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/shared.js +0 -0
  132. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui/theme.js +0 -0
  133. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui.html +0 -0
  134. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui_legacy.html +0 -0
  135. {code_context_control-2.122.0 → code_context_control-2.123.0}/cli/ui_nano.html +0 -0
  136. {code_context_control-2.122.0 → code_context_control-2.123.0}/code_context_control.egg-info/dependency_links.txt +0 -0
  137. {code_context_control-2.122.0 → code_context_control-2.123.0}/code_context_control.egg-info/entry_points.txt +0 -0
  138. {code_context_control-2.122.0 → code_context_control-2.123.0}/code_context_control.egg-info/requires.txt +0 -0
  139. {code_context_control-2.122.0 → code_context_control-2.123.0}/code_context_control.egg-info/top_level.txt +0 -0
  140. {code_context_control-2.122.0 → code_context_control-2.123.0}/core/__init__.py +0 -0
  141. {code_context_control-2.122.0 → code_context_control-2.123.0}/core/codex_patch.py +0 -0
  142. {code_context_control-2.122.0 → code_context_control-2.123.0}/core/config.py +0 -0
  143. {code_context_control-2.122.0 → code_context_control-2.123.0}/core/host.py +0 -0
  144. {code_context_control-2.122.0 → code_context_control-2.123.0}/core/ide.py +0 -0
  145. {code_context_control-2.122.0 → code_context_control-2.123.0}/core/mcp_toml.py +0 -0
  146. {code_context_control-2.122.0 → code_context_control-2.123.0}/core/web_security.py +0 -0
  147. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/__init__.py +0 -0
  148. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/config.py +0 -0
  149. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/mcp_oracle.py +0 -0
  150. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/oracle_server.py +0 -0
  151. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/oracle_ui.html +0 -0
  152. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/__init__.py +0 -0
  153. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/activity_reporter.py +0 -0
  154. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/api_auth.py +0 -0
  155. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/c3_bridge.py +0 -0
  156. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/chat_engine.py +0 -0
  157. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/chat_poll.py +0 -0
  158. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/chat_store.py +0 -0
  159. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/cross_memory.py +0 -0
  160. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/discovery_audit.py +0 -0
  161. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/federated_graph.py +0 -0
  162. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/health_checker.py +0 -0
  163. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/insight_engine.py +0 -0
  164. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/local_session.py +0 -0
  165. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/memory_reader.py +0 -0
  166. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/memory_writer.py +0 -0
  167. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/mobile_api.py +0 -0
  168. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/project_scanner.py +0 -0
  169. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/review_agent.py +0 -0
  170. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/tool_executor.py +0 -0
  171. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/services/tool_registry.py +0 -0
  172. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/activity.js +0 -0
  173. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/agents.js +0 -0
  174. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/app.js +0 -0
  175. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/busy.js +0 -0
  176. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/chat/conversations.js +0 -0
  177. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/chat/input.js +0 -0
  178. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/chat/markdown.js +0 -0
  179. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/chat/send.js +0 -0
  180. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/chat/stream_renderer.js +0 -0
  181. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/chat/toolbar.js +0 -0
  182. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/core.js +0 -0
  183. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/crossgraph.js +0 -0
  184. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/header.js +0 -0
  185. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/insights.js +0 -0
  186. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/projects.js +0 -0
  187. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/qrcode.js +0 -0
  188. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/settings.js +0 -0
  189. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/suggestions.js +0 -0
  190. {code_context_control-2.122.0 → code_context_control-2.123.0}/oracle/ui/theme_tabs.js +0 -0
  191. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/__init__.py +0 -0
  192. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/access_guard.py +0 -0
  193. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/access_telemetry.py +0 -0
  194. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/activity_log.py +0 -0
  195. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/agent_base.py +0 -0
  196. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/agent_locks.py +0 -0
  197. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/agents.py +0 -0
  198. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/artifact_defs.py +0 -0
  199. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/artifact_store.py +0 -0
  200. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/atomic_json.py +0 -0
  201. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/auto_memory.py +0 -0
  202. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/background_service.py +0 -0
  203. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/bench/__init__.py +0 -0
  204. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/bench/external/__init__.py +0 -0
  205. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/bench/external/aider_polyglot.py +0 -0
  206. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/bench/external/swe_bench.py +0 -0
  207. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/bench/map_eval.py +0 -0
  208. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/bench/search_eval.py +0 -0
  209. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/bench/shell_eval.py +0 -0
  210. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/benchmark_dashboard.py +0 -0
  211. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/bitbucket_client.py +0 -0
  212. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/bitbucket_credentials.py +0 -0
  213. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/ci_act.py +0 -0
  214. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/ci_cache.py +0 -0
  215. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/ci_expr.py +0 -0
  216. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/ci_failures.py +0 -0
  217. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/ci_github.py +0 -0
  218. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/ci_impact.py +0 -0
  219. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/ci_intel.py +0 -0
  220. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/ci_runner.py +0 -0
  221. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/ci_workflow.py +0 -0
  222. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/circuit_breaker.py +0 -0
  223. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/codex_transcript.py +0 -0
  224. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/compressor.py +0 -0
  225. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/context_snapshot.py +0 -0
  226. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/conversation_store.py +0 -0
  227. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/cred_audit.py +0 -0
  228. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/cred_telemetry.py +0 -0
  229. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/credential_store.py +0 -0
  230. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/doc_index.py +0 -0
  231. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/e2e_benchmark.py +0 -0
  232. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/e2e_evaluator.py +0 -0
  233. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/e2e_tasks.py +0 -0
  234. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/edit_ledger.py +0 -0
  235. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/embedding_index.py +0 -0
  236. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/enforcement_policy.py +0 -0
  237. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/error_reporting.py +0 -0
  238. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/file_map.py +0 -0
  239. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/file_memory.py +0 -0
  240. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/git_context.py +0 -0
  241. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/hub_service.py +0 -0
  242. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/index_store.py +0 -0
  243. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/indexer.py +0 -0
  244. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/jira_client.py +0 -0
  245. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/jira_cloud.py +0 -0
  246. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/jira_credentials.py +0 -0
  247. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/jira_data_center.py +0 -0
  248. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/jira_links.py +0 -0
  249. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/lexical_index.py +0 -0
  250. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/mask_activation.py +0 -0
  251. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/mask_mirror.py +0 -0
  252. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/mask_presets.py +0 -0
  253. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/memory.py +0 -0
  254. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/memory_consolidator.py +0 -0
  255. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/memory_distiller.py +0 -0
  256. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/memory_graph.py +0 -0
  257. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/memory_grounder.py +0 -0
  258. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/memory_queue.py +0 -0
  259. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/memory_scorer.py +0 -0
  260. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/metrics.py +0 -0
  261. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/notifications.py +0 -0
  262. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/ollama_bridge.py +0 -0
  263. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/ollama_client.py +0 -0
  264. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/ollama_credentials.py +0 -0
  265. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/oracle_service.py +0 -0
  266. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/output_filter.py +0 -0
  267. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/override_grants.py +0 -0
  268. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/override_policy.py +0 -0
  269. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/override_requests.py +0 -0
  270. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/override_wake.py +0 -0
  271. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/parser.py +0 -0
  272. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/project_manager.py +0 -0
  273. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/project_runtime.py +0 -0
  274. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/protocol.py +0 -0
  275. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/proxy_state.py +0 -0
  276. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/repo_map.py +0 -0
  277. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/repo_shape.py +0 -0
  278. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/reranker.py +0 -0
  279. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/retention.py +0 -0
  280. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/retrieval.py +0 -0
  281. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/retrieval_broker.py +0 -0
  282. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/router.py +0 -0
  283. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/runtime.py +0 -0
  284. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/scanner.py +0 -0
  285. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/session_benchmark.py +0 -0
  286. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/session_manager.py +0 -0
  287. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/session_preloader.py +0 -0
  288. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/shell_jobs.py +0 -0
  289. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/shell_output.py +0 -0
  290. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/subprojects.py +0 -0
  291. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/task_store.py +0 -0
  292. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/telemetry.py +0 -0
  293. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/text_index.py +0 -0
  294. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/time_tracker.py +0 -0
  295. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/tool_classifier.py +0 -0
  296. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/transcript_index.py +0 -0
  297. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/validation_cache.py +0 -0
  298. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/vector_store.py +0 -0
  299. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/watcher.py +0 -0
  300. {code_context_control-2.122.0 → code_context_control-2.123.0}/services/win_subprocess.py +0 -0
  301. {code_context_control-2.122.0 → code_context_control-2.123.0}/setup.cfg +0 -0
  302. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_access_builtin_optout.py +0 -0
  303. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_access_guard.py +0 -0
  304. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_access_guard_meta.py +0 -0
  305. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_access_guard_shell_project.py +0 -0
  306. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_access_guard_surfaces.py +0 -0
  307. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_access_guard_wiring.py +0 -0
  308. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_activity_reporter.py +0 -0
  309. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_agent_locks.py +0 -0
  310. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_aider_polyglot.py +0 -0
  311. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_antigravity_transition.py +0 -0
  312. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_artifact_store.py +0 -0
  313. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_artifact_tool.py +0 -0
  314. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_atomic_json.py +0 -0
  315. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_background_service.py +0 -0
  316. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_bitbucket_cli_smoke.py +0 -0
  317. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_bitbucket_client.py +0 -0
  318. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_bitbucket_config_fallback.py +0 -0
  319. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_bitbucket_credentials.py +0 -0
  320. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_bitbucket_tool.py +0 -0
  321. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_builtin_modes.py +0 -0
  322. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_c3_bridge_project_artifacts.py +0 -0
  323. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_c3_shell.py +0 -0
  324. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_chat_poll.py +0 -0
  325. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_ci_act.py +0 -0
  326. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_ci_cache.py +0 -0
  327. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_ci_expr.py +0 -0
  328. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_ci_impact.py +0 -0
  329. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_ci_intel.py +0 -0
  330. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_ci_runner.py +0 -0
  331. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_ci_workflow.py +0 -0
  332. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_circuit_breaker.py +0 -0
  333. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_claude_md_merge.py +0 -0
  334. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_claude_md_updater.py +0 -0
  335. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_cli_smoke.py +0 -0
  336. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_codex_mcp_transport.py +0 -0
  337. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_codex_native.py +0 -0
  338. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_compressor_large_file.py +0 -0
  339. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_confirm_guard.py +0 -0
  340. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_confirm_guard_wiring.py +0 -0
  341. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_cooccurrence_bounds.py +0 -0
  342. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_cred_audit.py +0 -0
  343. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_cred_telemetry.py +0 -0
  344. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_credential_login_kind.py +0 -0
  345. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_credential_store.py +0 -0
  346. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_credential_ui_parity.py +0 -0
  347. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_credentials_routes.py +0 -0
  348. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_credentials_tool.py +0 -0
  349. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_creds_cli_smoke.py +0 -0
  350. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_delegate_cascade.py +0 -0
  351. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_delegate_version_probe.py +0 -0
  352. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_e2e_benchmark.py +0 -0
  353. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_edit_ledger_deadline.py +0 -0
  354. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_edit_ledger_hook.py +0 -0
  355. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_edit_locking.py +0 -0
  356. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_edit_normalization.py +0 -0
  357. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_edit_verify.py +0 -0
  358. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_embedding_index_deadlock.py +0 -0
  359. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_enforcement_flip.py +0 -0
  360. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_enforcement_policy.py +0 -0
  361. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_enforcement_routes.py +0 -0
  362. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_env_parser.py +0 -0
  363. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_failed_calls_do_not_unlock.py +0 -0
  364. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_federated_graph.py +0 -0
  365. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_file_map_c1.py +0 -0
  366. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_filter_backoff.py +0 -0
  367. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_ghost_files.py +0 -0
  368. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_ghost_generation.py +0 -0
  369. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_git_branch_awareness.py +0 -0
  370. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_hook_access_guard.py +0 -0
  371. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_hook_codex_compat.py +0 -0
  372. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_hook_dispatch.py +0 -0
  373. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_hook_pretool_enforce.py +0 -0
  374. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_hook_prompt_recall.py +0 -0
  375. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_hook_smoke.py +0 -0
  376. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_hook_state.py +0 -0
  377. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_hook_utf8_stdio.py +0 -0
  378. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_hub_credentials_route.py +0 -0
  379. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_hub_credentials_routes_write.py +0 -0
  380. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_hub_enforcement_routes.py +0 -0
  381. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_hub_inspect_api.py +0 -0
  382. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_hub_locks_routes.py +0 -0
  383. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_hub_oracle_service_routes.py +0 -0
  384. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_hub_override_routes.py +0 -0
  385. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_hub_server_smoke.py +0 -0
  386. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_hub_subproject_links.py +0 -0
  387. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_ide_workflow_adaptation.py +0 -0
  388. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_index_cap_not_hardcoded.py +0 -0
  389. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_init_clear_preserves_user_content.py +0 -0
  390. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_init_scan.py +0 -0
  391. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_install_mcp_entrypoint.py +0 -0
  392. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_jira_cli_smoke.py +0 -0
  393. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_jira_client.py +0 -0
  394. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_jira_config_fallback.py +0 -0
  395. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_jira_credentials.py +0 -0
  396. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_jira_links.py +0 -0
  397. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_jira_routes.py +0 -0
  398. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_jira_tool.py +0 -0
  399. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_lazy_store_init.py +0 -0
  400. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_map_eval.py +0 -0
  401. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_map_telemetry_c0.py +0 -0
  402. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_mask_guard.py +0 -0
  403. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_mask_routes.py +0 -0
  404. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_mask_surfaces.py +0 -0
  405. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_mcp_host_guard.py +0 -0
  406. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_mcp_memory_timeout.py +0 -0
  407. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_mcp_server_smoke.py +0 -0
  408. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_mcp_toml.py +0 -0
  409. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_memory_distiller.py +0 -0
  410. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_memory_graph_api.py +0 -0
  411. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_memory_queue.py +0 -0
  412. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_memory_system.py +0 -0
  413. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_mobile_api.py +0 -0
  414. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_mobile_extras.py +0 -0
  415. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_mobile_override_routes.py +0 -0
  416. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_mobile_security_api.py +0 -0
  417. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_no_stale_model_pins.py +0 -0
  418. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_notification_dedup.py +0 -0
  419. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_notification_discipline.py +0 -0
  420. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_ollama_credentials.py +0 -0
  421. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_oracle_api_auth.py +0 -0
  422. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_oracle_apikey_api.py +0 -0
  423. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_oracle_c3_bridge.py +0 -0
  424. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_oracle_chat_engine.py +0 -0
  425. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_oracle_chat_store.py +0 -0
  426. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_oracle_discovery_api.py +0 -0
  427. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_oracle_discovery_audit.py +0 -0
  428. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_oracle_health_probe.py +0 -0
  429. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_oracle_local_auth.py +0 -0
  430. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_oracle_ollama_bridge.py +0 -0
  431. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_oracle_scanner_cache.py +0 -0
  432. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_oracle_security_fixes.py +0 -0
  433. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_oracle_session_bootstrap.py +0 -0
  434. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_oracle_subproject_awareness.py +0 -0
  435. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_oracle_ui_bundle.py +0 -0
  436. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_output_filter.py +0 -0
  437. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_override_grants.py +0 -0
  438. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_override_grants_mcp.py +0 -0
  439. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_override_requests.py +0 -0
  440. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_override_wake.py +0 -0
  441. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_permissions.py +0 -0
  442. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_pm_api.py +0 -0
  443. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_project_manager.py +0 -0
  444. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_project_manager_merge.py +0 -0
  445. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_project_tool.py +0 -0
  446. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_read_coercion.py +0 -0
  447. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_read_edit_parity.py +0 -0
  448. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_related_facts.py +0 -0
  449. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_repo_map.py +0 -0
  450. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_repo_shape.py +0 -0
  451. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_response_boilerplate.py +0 -0
  452. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_retention.py +0 -0
  453. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_review_digest.py +0 -0
  454. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_search_eval.py +0 -0
  455. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_search_p1.py +0 -0
  456. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_search_p2.py +0 -0
  457. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_search_p2b.py +0 -0
  458. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_search_p3.py +0 -0
  459. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_search_p4.py +0 -0
  460. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_search_p5.py +0 -0
  461. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_service_durability.py +0 -0
  462. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_session_benchmark.py +0 -0
  463. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_session_budget.py +0 -0
  464. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_shell_budget_s1.py +0 -0
  465. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_shell_creds.py +0 -0
  466. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_shell_eval.py +0 -0
  467. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_shell_jobs_s3.py +0 -0
  468. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_shell_nudge_s4.py +0 -0
  469. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_shell_output.py +0 -0
  470. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_shell_parsers_s2.py +0 -0
  471. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_shell_robustness.py +0 -0
  472. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_shell_telemetry_s0.py +0 -0
  473. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_shell_write_ledger.py +0 -0
  474. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_shell_writes.py +0 -0
  475. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_subproject_clear_scope.py +0 -0
  476. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_subproject_depth_consumers.py +0 -0
  477. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_subproject_exclusion.py +0 -0
  478. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_subproject_federation.py +0 -0
  479. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_subproject_linkage_api.py +0 -0
  480. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_subprojects.py +0 -0
  481. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_swe_bench.py +0 -0
  482. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_task_store.py +0 -0
  483. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_task_tool.py +0 -0
  484. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_time_tracker.py +0 -0
  485. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_token_telemetry.py +0 -0
  486. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_token_tracking.py +0 -0
  487. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_tool_registry.py +0 -0
  488. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_ui_jsx_syntax.py +0 -0
  489. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_upgrade_and_version.py +0 -0
  490. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_validate.py +0 -0
  491. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_vault_write_guard.py +0 -0
  492. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_version_sync.py +0 -0
  493. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_web_security.py +0 -0
  494. {code_context_control-2.122.0 → code_context_control-2.123.0}/tests/test_windows_reliability.py +0 -0
  495. {code_context_control-2.122.0 → code_context_control-2.123.0}/tui/__init__.py +0 -0
  496. {code_context_control-2.122.0 → code_context_control-2.123.0}/tui/backend.py +0 -0
  497. {code_context_control-2.122.0 → code_context_control-2.123.0}/tui/main.py +0 -0
  498. {code_context_control-2.122.0 → code_context_control-2.123.0}/tui/screens/__init__.py +0 -0
  499. {code_context_control-2.122.0 → code_context_control-2.123.0}/tui/screens/benchmark_view.py +0 -0
  500. {code_context_control-2.122.0 → code_context_control-2.123.0}/tui/screens/claudemd_view.py +0 -0
  501. {code_context_control-2.122.0 → code_context_control-2.123.0}/tui/screens/compress_view.py +0 -0
  502. {code_context_control-2.122.0 → code_context_control-2.123.0}/tui/screens/index_view.py +0 -0
  503. {code_context_control-2.122.0 → code_context_control-2.123.0}/tui/screens/init_view.py +0 -0
  504. {code_context_control-2.122.0 → code_context_control-2.123.0}/tui/screens/mcp_view.py +0 -0
  505. {code_context_control-2.122.0 → code_context_control-2.123.0}/tui/screens/optimize_view.py +0 -0
  506. {code_context_control-2.122.0 → code_context_control-2.123.0}/tui/screens/pipe_view.py +0 -0
  507. {code_context_control-2.122.0 → code_context_control-2.123.0}/tui/screens/projects_view.py +0 -0
  508. {code_context_control-2.122.0 → code_context_control-2.123.0}/tui/screens/search_view.py +0 -0
  509. {code_context_control-2.122.0 → code_context_control-2.123.0}/tui/screens/session_view.py +0 -0
  510. {code_context_control-2.122.0 → code_context_control-2.123.0}/tui/screens/stats.py +0 -0
  511. {code_context_control-2.122.0 → code_context_control-2.123.0}/tui/screens/ui_view.py +0 -0
  512. {code_context_control-2.122.0 → code_context_control-2.123.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.122.0
3
+ Version: 2.123.0
4
4
  Summary: Local MCP code-intelligence for AI coding tools: surgical search/read/edit, agent-config version history, path-level access + masking guards, and a multi-project hub.
5
5
  Author-email: Dimitri Tselenchuk <dtselenc@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -92,7 +92,7 @@ console = Console() if HAS_RICH else None
92
92
  # Config
93
93
  CONFIG_DIR = ".c3"
94
94
  CONFIG_FILE = ".c3/config.json"
95
- __version__ = "2.122.0"
95
+ __version__ = "2.123.0"
96
96
 
97
97
 
98
98
  def _compress_file_cli(compressor, path, mode="smart", **kw):
@@ -271,7 +271,7 @@ _STALE_MCP_TOOLS = {
271
271
  "mcp__c3__c3_remember", # → c3_memory(action='add')
272
272
  "mcp__c3__c3_recall", # → c3_memory(action='recall')
273
273
  "mcp__c3__c3_sltm_add", # → c3_memory(action='add')
274
- "mcp__c3__c3_file_map", # → c3_compress(mode='map')
274
+ "mcp__c3__c3_file_map", # → c3_read(file_path) map
275
275
  "mcp__c3__c3_extract", # → c3_read
276
276
  "mcp__c3__c3_transcript_search", # → c3_search(action='transcript')
277
277
  "mcp__c3__c3_session_log", # → c3_session(action='log')
@@ -3971,7 +3971,7 @@ def cmd_benchmark(args):
3971
3971
  "prompt_budget_multiplier": round(_prompt_gain(comp_comp, comp_orig), 2),
3972
3972
  },
3973
3973
  "file_navigation": {
3974
- "description": "Use c3_compress(mode='map') to choose targeted reads instead of opening whole files blindly.",
3974
+ "description": "Use the c3_read file map to choose targeted reads instead of opening whole files blindly.",
3975
3975
  "performance_metric": "map success rate",
3976
3976
  "with_c3": {"tool": "c3_compress(mode='map')", "total_tokens": file_map_comp, "avg_latency_ms": round(_avg(file_map_c3_latencies), 2), "performance": round((file_map_successes / len(file_map_sample) * 100), 1) if file_map_sample else 0.0},
3977
3977
  "without_c3": {"approach": "read full files into context", "total_tokens": file_map_orig, "avg_latency_ms": round(_avg(file_map_baseline_latencies), 2), "performance": 100.0},
@@ -5005,7 +5005,7 @@ back to native tools as the task progresses.
5005
5005
 
5006
5006
  ## Quick Reference
5007
5007
  - **Search**: `c3_search(query=..., action='code|files|semantic')` — before Grep/Glob
5008
- - **Read**: `c3_compress(mode='map')` then `c3_read(symbols=...)` — before native Read
5008
+ - **Read**: `c3_read(file_path)` maps a file (or directory), then `c3_read(symbols=['Class.method'])` — before native Read
5009
5009
  - **Impact**: `c3_impact(target='symbol')` — blast-radius check before editing shared symbols
5010
5010
  - **Edit**: `c3_edit(file_path=..., old_string=..., new_string=...)` — before Edit/Write
5011
5011
  - **Validate**: `c3_validate(file_path=...)` — after every edit (pyright/tsc type check if installed)
@@ -636,7 +636,7 @@
636
636
  <span>Discover files / content — never start with Grep/Glob</span>
637
637
  </div>
638
638
  <div class="quick-item">
639
- <code>3. c3_compress(mode='map') + c3_read(symbols=…)</code>
639
+ <code>3. c3_read(file_path) + c3_read(symbols=…)</code>
640
640
  <span>Map then surgically read — never start with native Read</span>
641
641
  </div>
642
642
  <div class="quick-item">
@@ -315,7 +315,7 @@
315
315
  <tr>
316
316
  <td><span class="badge badge-blue">3</span></td>
317
317
  <td><strong>Map + Read</strong></td>
318
- <td><code>c3_compress(mode='map')</code> → <code>c3_read(symbols=…)</code></td>
318
+ <td><code>c3_read(file_path)</code> (map) → <code>c3_read(symbols=…)</code></td>
319
319
  <td>Before reading any file content</td>
320
320
  </tr>
321
321
  <tr>
@@ -130,7 +130,7 @@ _VAULT_FILES = frozenset({"config.json", "secrets.enc", "cred_state.json",
130
130
  # Redirect messages per native tool
131
131
  _REDIRECTS = {
132
132
  "Read": (
133
- "Use c3_compress(file_path='...', mode='map') to map the file first, "
133
+ "Use c3_read(file_path='...') to map the file first (one line per symbol), "
134
134
  "then c3_read(file_path='...', symbols=['...']) for surgical extraction."
135
135
  ),
136
136
  "Grep": (
@@ -177,6 +177,22 @@ def handle_read(file_path: str, symbols: Any = None, lines: Any = None,
177
177
 
178
178
  rel_path = str(full.resolve().relative_to(Path(svc.project_path).resolve())).replace("\\", "/")
179
179
 
180
+ if full.is_dir():
181
+ # A directory maps to one line per file, budgeted
182
+ # (docs/file-map.md § Directories). `lines=<int>` sets the budget.
183
+ from services.dir_map import DEFAULT_MAX_TOKENS, render_directory_map
184
+ budget = DEFAULT_MAX_TOKENS
185
+ if isinstance(lines, int) and not isinstance(lines, bool) and lines > 0:
186
+ budget = lines
187
+ text, dir_detail = render_directory_map(svc, rel_path, max_tokens=budget)
188
+ tok = count_tokens(text)
189
+ if finalize is None:
190
+ return text
191
+ return finalize_with_tokens(
192
+ finalize, svc, "c3_read", {"file": file_path}, text,
193
+ f"dir:{dir_detail['files']}files->{tok}tok",
194
+ optimized_tokens=tok, response_tokens=tok, detail=dir_detail)
195
+
180
196
  # Resolve ranges
181
197
  ranges = []
182
198
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-context-control
3
- Version: 2.122.0
3
+ Version: 2.123.0
4
4
  Summary: Local MCP code-intelligence for AI coding tools: surgical search/read/edit, agent-config version history, path-level access + masking guards, and a multi-project hub.
5
5
  Author-email: Dimitri Tselenchuk <dtselenc@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -217,6 +217,7 @@ services/conversation_store.py
217
217
  services/cred_audit.py
218
218
  services/cred_telemetry.py
219
219
  services/credential_store.py
220
+ services/dir_map.py
220
221
  services/doc_index.py
221
222
  services/e2e_benchmark.py
222
223
  services/e2e_evaluator.py
@@ -345,6 +346,7 @@ tests/test_credentials_tool.py
345
346
  tests/test_creds_cli_smoke.py
346
347
  tests/test_delegate_cascade.py
347
348
  tests/test_delegate_version_probe.py
349
+ tests/test_dir_map_c3.py
348
350
  tests/test_e2e_benchmark.py
349
351
  tests/test_edit_ledger_deadline.py
350
352
  tests/test_edit_ledger_hook.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "code-context-control"
7
- version = "2.122.0"
7
+ version = "2.123.0"
8
8
  description = "Local MCP code-intelligence for AI coding tools: surgical search/read/edit, agent-config version history, path-level access + masking guards, and a multi-project hub."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -32,7 +32,7 @@ When falling back, state which c3_* tool was attempted and why it was insufficie
32
32
  ## Workflow (follow this order — do not skip steps)
33
33
  1. **RECALL**: `c3_memory(action='recall')` — before any multi-step or context-dependent task. Large memory stores: use `index` first (compact list), then `fetch` for specific IDs
34
34
  2. **SEARCH FIRST**: `c3_search(action='code|files|semantic')` — before ANY file discovery or content search. Never start with Grep/Glob
35
- 3. **MAP before READ**: `c3_compress(mode='map')` then `c3_read(symbols=...|lines=...)` — for ANY file read. Never start with native Read. Use `mode='ast'` for knowledge-graph overview (requires codebase-memory-mcp)
35
+ 3. **MAP before READ**: `c3_read(file_path)` with no symbols/lines returns the file map (one line per symbol with signature and `[La-Lb]` range, ~10% of the file's tokens; a directory path maps its files), then `c3_read(symbols=['Class.method']|lines=[a,b])` for the source you need. Never start with native Read. `c3_compress` is the same map for a comma-separated batch (legacy; removed in 2.124.0)
36
36
  4. **IMPACT** (shared symbols): `c3_impact(target='symbol')` — blast-radius check before editing any function/class used across files
37
37
  5. **EDIT via C3**: `c3_edit(file_path, old_string, new_string, summary)` — for ALL edits. Parallel across files; `edits=[]` batch for same file
38
38
  6. **FILTER**: `c3_filter(text=...)` — for terminal output >10 lines or log files
@@ -55,7 +55,7 @@ In plan mode, all c3_* read tools (search, read, compress, filter, validate, sta
55
55
  ## Anti-patterns (DO NOT do these)
56
56
  - Starting with native file search/read/grep without a prior c3_* call
57
57
  - Using native Edit when c3_edit is available
58
- - Reading entire files when c3_compress + c3_read would be more surgical
58
+ - Reading entire files when a c3_read map + a symbol read would be more surgical
59
59
  - Skipping c3_validate after making edits"""
60
60
 
61
61
  # Pointer that replaces the embedded Project Context tree (v2.60.0).
@@ -73,14 +73,14 @@ C3_NANO_WORKFLOW = """\
73
73
  ## C3 Tools — MANDATORY
74
74
  Native tools BLOCKED unless c3_* called first. State reason when falling back.
75
75
  1. c3_search(action='code|files|semantic') — BEFORE any search/grep/glob
76
- 2. c3_compress(mode='map') then c3_read(symbols=...|lines=...) — BEFORE any file read
76
+ 2. c3_read(file_path) maps a file (or directory); then c3_read(symbols=['Class.method']|lines=[a,b]) — BEFORE any file read
77
77
  3. c3_edit(file_path, old_string, new_string, summary) — for ALL edits; edits=[{...}] batch
78
78
  4. c3_filter(text='...') — output >10 lines
79
79
  5. c3_validate(file_path) — after edits
80
80
  6. c3_session(action='log'|'snapshot') — decisions / before /clear
81
81
  7. `[c3-access:confirm]` = PAUSE, not block: a human approves this exact write (agent-config files — .mcp.json, instruction docs, .claude bodies — hold by default). Read the S8 tail: wait on the request it names (c3_override(action='wait', request_id='...', timeout_s=180)), then retry once. Never retry early, never route around it.
82
82
  Plan mode: all c3_* read tools work normally — skip edit/delegate steps.
83
- DO NOT: start with native Read/Grep/Glob/Edit, skip c3_validate, read full files without c3_compress."""
83
+ DO NOT: start with native Read/Grep/Glob/Edit, skip c3_validate, read full files without mapping them first."""
84
84
 
85
85
 
86
86
  # --- Per-IDE workflow adaptation ----------------------------------------------
@@ -8,7 +8,7 @@ CODEX_WORKFLOW = """# C3 — Codex workflow
8
8
 
9
9
  Use C3 for repository intelligence and audited changes:
10
10
  1. Recall relevant project facts with c3_memory; inspect .c3/MAP.md.
11
- 2. Find candidates with c3_search; map with c3_compress(mode='map'), then
11
+ 2. Find candidates with c3_search; map with c3_read(file_path) (no symbols), then
12
12
  read exact symbols or lines with c3_read. Check shared changes with c3_impact.
13
13
  3. Edit with c3_edit, validate with c3_validate, and record decisions with
14
14
  c3_session(action='log'). Preserve unrelated work.
@@ -0,0 +1,176 @@
1
+ """Directory maps — one line per file, budgeted, for `c3_read('<dir>')`.
2
+
3
+ # services/ (58 files, 41,203L)
4
+ compressor.py (809L python) — CodeCompressor; compress_file; STRUCTURE_PATTERNS
5
+ file_map.py (280L python) — render_map; parse_signature; parse_map; KINDS
6
+ …
7
+ … 12 more files
8
+
9
+ Files are ranked the way a reader would want them: recently edited first
10
+ (the edit ledger), then by how much structure they hold (symbol count),
11
+ then by path. The map is filled to a token budget and closes with how
12
+ many files it left out. Traversal is bounded — the scanner's SKIP_DIRS
13
+ and .gitignore pruning, never following symlinks, a hard file cap — and
14
+ structure comes from file_memory records, extracting on the fly only
15
+ for a bounded number of code files (docs/file-map.md § Directories).
16
+ """
17
+ from __future__ import annotations
18
+
19
+ import time
20
+ from pathlib import Path
21
+ from typing import Optional
22
+
23
+ from core import count_tokens
24
+ from services.file_memory import CODE_EXTENSIONS, LANG_MAP
25
+ from services.scanner import iter_files
26
+
27
+ DEFAULT_MAX_TOKENS = 1500
28
+ MAX_FILES = 400 # hard traversal cap
29
+ MAX_EXTRACT_FILES = 120 # code files parsed on the fly, per call
30
+ EXTRACT_DEADLINE_S = 3.0 # then the rest show line counts only
31
+ MAX_EXTRACT_BYTES = 200 * 1024
32
+ SYMBOLS_PER_FILE = 6
33
+ LEDGER_LOOKBACK = 300 # recent ledger entries consulted for ranking
34
+
35
+
36
+ def _recent_edit_ranks(svc) -> dict:
37
+ """path -> recency rank (0 = most recent) from the edit ledger."""
38
+ ledger = getattr(svc, "edit_ledger", None)
39
+ if ledger is None:
40
+ return {}
41
+ try:
42
+ entries = ledger.get_history(limit=LEDGER_LOOKBACK)
43
+ except Exception:
44
+ return {}
45
+ ranks: dict = {}
46
+ for entry in entries or []:
47
+ f = str((entry or {}).get("file") or "").replace("\\", "/")
48
+ if f and f not in ranks:
49
+ ranks[f] = len(ranks)
50
+ return ranks
51
+
52
+
53
+ #: What a reader wants to see first on a one-line summary of a file.
54
+ _SYMBOL_PRIORITY = {"class": 0, "interface": 0, "struct": 0, "trait": 0, "enum": 0,
55
+ "function": 1, "method": 1, "type": 2, "heading": 2, "section": 2,
56
+ "constant": 3, "variable": 3}
57
+ _SKIP_SYMBOL_TYPES = {"import", "decorator", "comment", "content", "property", "impl"}
58
+
59
+
60
+ def _structural_sections(record: Optional[dict]) -> list:
61
+ return [s for s in (record or {}).get("sections") or []
62
+ if s.get("type") not in _SKIP_SYMBOL_TYPES
63
+ and str(s.get("name") or "").strip() not in ("", "(full file)")]
64
+
65
+
66
+ def _top_symbols(record: Optional[dict]) -> list:
67
+ """Up to SYMBOLS_PER_FILE names: classes first, then functions, then the
68
+ rest, constants last — each group in source order."""
69
+ picked = sorted(enumerate(_structural_sections(record)),
70
+ key=lambda iv: (_SYMBOL_PRIORITY.get(iv[1].get("type"), 2),
71
+ str(iv[1].get("name") or "").startswith("_"),
72
+ iv[0]))
73
+ names = []
74
+ for _, s in picked[:SYMBOLS_PER_FILE]:
75
+ name = str(s.get("name") or "").strip()
76
+ if s.get("type") == "heading":
77
+ name = name.split(":", 1)[-1].strip()
78
+ names.append(name)
79
+ return names
80
+
81
+
82
+ def _line_count(path: Path) -> int:
83
+ try:
84
+ with open(path, "rb") as fh:
85
+ return sum(1 for _ in fh)
86
+ except OSError:
87
+ return 0
88
+
89
+
90
+ def render_directory_map(svc, rel_dir: str, *, max_tokens: int = DEFAULT_MAX_TOKENS) -> tuple:
91
+ """Return (text, detail) for the directory `rel_dir` (project-relative, posix)."""
92
+ root = Path(svc.project_path).resolve()
93
+ rel_dir = str(rel_dir).replace("\\", "/").strip("/")
94
+ target = (root / rel_dir).resolve() if rel_dir else root
95
+ label = (rel_dir + "/") if rel_dir else "./"
96
+
97
+ files = []
98
+ capped = False
99
+ for fp in iter_files(target, max_files=MAX_FILES + 1):
100
+ if len(files) >= MAX_FILES:
101
+ capped = True
102
+ break
103
+ try:
104
+ files.append(fp.resolve().relative_to(root).as_posix())
105
+ except ValueError:
106
+ continue
107
+
108
+ store = getattr(svc, "file_memory", None)
109
+ recent = _recent_edit_ranks(svc)
110
+ started = time.monotonic()
111
+ extracted = 0
112
+ rows = []
113
+ total_lines = 0
114
+ for rel in files:
115
+ record = None
116
+ if store is not None:
117
+ try:
118
+ record = store.get(rel)
119
+ except Exception:
120
+ record = None
121
+ ext = Path(rel).suffix.lower()
122
+ if (record is None and ext in CODE_EXTENSIONS
123
+ and extracted < MAX_EXTRACT_FILES
124
+ and time.monotonic() - started < EXTRACT_DEADLINE_S):
125
+ try:
126
+ if (root / rel).stat().st_size <= MAX_EXTRACT_BYTES:
127
+ record = store.update(rel)
128
+ extracted += 1
129
+ except Exception:
130
+ record = None
131
+ lines = int((record or {}).get("lines") or 0) or _line_count(root / rel)
132
+ total_lines += lines
133
+ ext = Path(rel).suffix.lower()
134
+ lang = str((record or {}).get("language") or LANG_MAP.get(ext) or ext.lstrip(".") or "")
135
+ symbols = _top_symbols(record)
136
+ rows.append({
137
+ "rel": rel,
138
+ "name": rel[len(rel_dir) + 1:] if rel_dir and rel.startswith(rel_dir + "/") else rel,
139
+ "lines": lines,
140
+ "lang": lang,
141
+ "symbols": symbols,
142
+ "recent": recent.get(rel, 10 ** 6),
143
+ "nsym": len(_structural_sections(record)),
144
+ })
145
+
146
+ rows.sort(key=lambda r: (r["recent"], -r["nsym"], r["rel"]))
147
+
148
+ header = f"# {label} ({len(files)}{'+' if capped else ''} files, {total_lines:,}L)"
149
+ body = []
150
+ for r in rows:
151
+ line = f"{r['name']} ({r['lines']}L {r['lang']})".rstrip()
152
+ if r["symbols"]:
153
+ line += " — " + "; ".join(r["symbols"])
154
+ body.append(line)
155
+
156
+ kept = list(body)
157
+ while kept and count_tokens("\n".join([header] + kept)) > max_tokens:
158
+ kept.pop()
159
+ dropped = len(body) - len(kept)
160
+ parts = [header] + kept
161
+ if dropped:
162
+ parts.append(f"… {dropped} more files")
163
+ if capped:
164
+ parts.append(f"[dir_map] traversal capped at {MAX_FILES} files; map a subdirectory")
165
+ # In source order the reader gets recency first; say so once.
166
+ parts.append("[dir_map] recently edited first, then by structure; "
167
+ "c3_read('<file>') maps one file")
168
+ text = "\n".join(parts)
169
+ detail = {
170
+ "backend": "directory",
171
+ "files": len(files),
172
+ "listed": len(kept),
173
+ "extracted": extracted,
174
+ "capped": capped,
175
+ }
176
+ return text, detail
@@ -0,0 +1,176 @@
1
+ """C3 of the c3_compress remediation: c3_read maps directories too.
2
+
3
+ The one thing c3_read could not do that c3_compress could was a batch,
4
+ and neither could map a directory. Now `c3_read('<dir>')` renders one
5
+ line per file under a token budget, recently edited files first, then the
6
+ ones with the most structure. These tests pin the shape, the ranking, the
7
+ budget and the traversal bounds (docs/file-map.md § Directories), plus the
8
+ instruction surfaces that now teach the c3_read(file_path) form.
9
+ """
10
+ from __future__ import annotations
11
+
12
+ import json
13
+ import sys
14
+ import tempfile
15
+ import unittest
16
+ from pathlib import Path
17
+ from types import SimpleNamespace
18
+
19
+ sys.path.insert(0, str(Path(__file__).parent.parent))
20
+
21
+ from cli.tools.read import handle_read # noqa: E402
22
+ from core import count_tokens # noqa: E402
23
+ from services import dir_map # noqa: E402
24
+ from services.file_memory import FileMemoryStore # noqa: E402
25
+ from services.session_manager import SessionManager # noqa: E402
26
+
27
+
28
+ def _py(n_funcs: int, prefix: str) -> str:
29
+ parts = ["import os\n\n"]
30
+ if n_funcs:
31
+ parts.append(f"class {prefix.title()}Thing:\n def run(self):\n return 1\n\n")
32
+ for i in range(n_funcs):
33
+ parts.append(f"def {prefix}_{i}(x):\n return x + {i}\n\n")
34
+ return "".join(parts)
35
+
36
+
37
+ class _Ledger:
38
+ def __init__(self, files):
39
+ self._files = files
40
+
41
+ def get_history(self, limit=50):
42
+ return [{"file": f} for f in self._files]
43
+
44
+
45
+ def _svc(tmp, ledger=None, session=False):
46
+ sm = None
47
+ if session:
48
+ sm = SessionManager(tmp)
49
+ sm.start_session("t")
50
+ return SimpleNamespace(project_path=tmp, file_memory=FileMemoryStore(tmp),
51
+ edit_ledger=ledger, session_mgr=sm, hybrid_config={})
52
+
53
+
54
+ def _fin(sm):
55
+ def finalize(name, args, resp, summ, **kw):
56
+ sm.log_tool_call(name, args, summ)
57
+ sm.track_response(name, resp, kw.get("response_tokens", 0))
58
+ return resp
59
+ return finalize
60
+
61
+
62
+ class TestDirectoryMap(unittest.TestCase):
63
+ def _tree(self, tmp):
64
+ root = Path(tmp)
65
+ (root / "pkg").mkdir()
66
+ (root / "pkg" / "big.py").write_text(_py(8, "big"), encoding="utf-8")
67
+ (root / "pkg" / "small.py").write_text(_py(1, "small"), encoding="utf-8")
68
+ (root / "pkg" / "notes.md").write_text("# Notes\n\n## Later\n\ntext\n", encoding="utf-8")
69
+ (root / "pkg" / "data.txt").write_text("a\nb\nc\n", encoding="utf-8")
70
+ (root / "pkg" / "node_modules").mkdir()
71
+ (root / "pkg" / "node_modules" / "dep.js").write_text("module.exports = 1;\n", encoding="utf-8")
72
+ return root
73
+
74
+ def test_shape_and_ranking_by_structure(self):
75
+ with tempfile.TemporaryDirectory() as tmp:
76
+ self._tree(tmp)
77
+ out = handle_read("pkg", None, None, True, _svc(tmp), None)
78
+ lines = out.splitlines()
79
+ self.assertEqual(lines[0], "# pkg/ (4 files, 47L)")
80
+ self.assertTrue(lines[1].startswith("big.py (30L python) — BigThing; big_0; big_1; big_2; big_3; big_4"))
81
+ self.assertIn("small.py (9L python) — SmallThing; small_0", lines)
82
+ self.assertIn("notes.md (5L markdown) — Notes; Later", lines)
83
+ self.assertIn("data.txt (3L txt)", lines)
84
+ self.assertNotIn("dep.js", out)
85
+ self.assertTrue(lines[-1].startswith("[dir_map] recently edited first"))
86
+
87
+ def test_recent_edits_rank_first(self):
88
+ with tempfile.TemporaryDirectory() as tmp:
89
+ self._tree(tmp)
90
+ svc = _svc(tmp, ledger=_Ledger(["pkg/small.py", "pkg/data.txt"]))
91
+ lines = handle_read("pkg", None, None, True, svc, None).splitlines()
92
+ self.assertTrue(lines[1].startswith("small.py"))
93
+ self.assertTrue(lines[2].startswith("data.txt"))
94
+ self.assertTrue(lines[3].startswith("big.py"))
95
+
96
+ def test_budget_drops_from_the_end_and_counts(self):
97
+ with tempfile.TemporaryDirectory() as tmp:
98
+ self._tree(tmp)
99
+ out = handle_read("pkg", None, 30, True, _svc(tmp), None)
100
+ self.assertLessEqual(count_tokens("\n".join(out.splitlines()[:-1])),
101
+ 30 + count_tokens("… 3 more files"))
102
+ self.assertIn("… ", out)
103
+ self.assertIn("more files", out)
104
+
105
+ def test_traversal_cap_and_no_symlink_follow(self):
106
+ with tempfile.TemporaryDirectory() as tmp:
107
+ root = self._tree(tmp)
108
+ link = root / "pkg" / "loop"
109
+ try:
110
+ link.symlink_to(root / "pkg", target_is_directory=True)
111
+ linked = True
112
+ except (OSError, NotImplementedError):
113
+ linked = False
114
+ old = dir_map.MAX_FILES
115
+ dir_map.MAX_FILES = 2
116
+ try:
117
+ out = handle_read("pkg", None, None, True, _svc(tmp), None)
118
+ finally:
119
+ dir_map.MAX_FILES = old
120
+ self.assertIn("# pkg/ (2+ files", out)
121
+ self.assertIn("traversal capped at 2 files", out)
122
+ if linked:
123
+ self.assertNotIn("loop/", out)
124
+
125
+ def test_root_directory_and_telemetry_detail(self):
126
+ with tempfile.TemporaryDirectory() as tmp:
127
+ self._tree(tmp)
128
+ svc = _svc(tmp, session=True)
129
+ out = handle_read(".", None, None, True, svc, _fin(svc.session_mgr))
130
+ self.assertTrue(out.startswith("# ./ ("))
131
+ self.assertIn("pkg/big.py (30L python)", out)
132
+ rows = [json.loads(line) for line in
133
+ (Path(tmp) / ".c3" / "tool_telemetry.jsonl").read_text(encoding="utf-8").splitlines()]
134
+ detail = rows[-1]["detail"]
135
+ self.assertEqual(detail["backend"], "directory")
136
+ self.assertEqual(detail["files"], 4)
137
+ self.assertEqual(detail["listed"], 4)
138
+ self.assertGreaterEqual(detail["extracted"], 2)
139
+ self.assertFalse(detail["capped"])
140
+
141
+ def test_extraction_is_bounded(self):
142
+ with tempfile.TemporaryDirectory() as tmp:
143
+ root = Path(tmp)
144
+ (root / "many").mkdir()
145
+ for i in range(6):
146
+ (root / "many" / f"m{i}.py").write_text(_py(1, f"m{i}"), encoding="utf-8")
147
+ old = dir_map.MAX_EXTRACT_FILES
148
+ dir_map.MAX_EXTRACT_FILES = 2
149
+ try:
150
+ text, detail = dir_map.render_directory_map(_svc(tmp), "many")
151
+ finally:
152
+ dir_map.MAX_EXTRACT_FILES = old
153
+ self.assertEqual(detail["extracted"], 2)
154
+ self.assertEqual(detail["files"], 6)
155
+ # Unparsed files still show a line count.
156
+ self.assertEqual(sum(1 for line in text.splitlines() if "(9L python)" in line), 6)
157
+
158
+
159
+ class TestInstructionSurfaces(unittest.TestCase):
160
+ def test_managed_block_teaches_read_first(self):
161
+ from services import claude_md
162
+ text = claude_md.C3_WORKFLOW if hasattr(claude_md, "C3_WORKFLOW") else ""
163
+ src = Path(claude_md.__file__).read_text(encoding="utf-8")
164
+ self.assertIn("`c3_read(file_path)` with no symbols/lines returns the file map", src)
165
+ self.assertNotIn("`c3_compress(mode='map')` then `c3_read(symbols=...|lines=...)`", src)
166
+ self.assertIn("c3_read(file_path) maps a file (or directory)", src)
167
+ del text
168
+
169
+ def test_hook_redirect_names_c3_read(self):
170
+ from cli import hook_pretool_enforce as hook
171
+ self.assertIn("c3_read(file_path='...') to map the file first", hook._REDIRECTS["Read"])
172
+ self.assertNotIn("c3_compress", hook._REDIRECTS["Read"])
173
+
174
+
175
+ if __name__ == "__main__":
176
+ unittest.main()