code-context-control 2.120.0__tar.gz → 2.121.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 (510) hide show
  1. {code_context_control-2.120.0/code_context_control.egg-info → code_context_control-2.121.0}/PKG-INFO +1 -1
  2. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/c3.py +1 -1
  3. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/mcp_server.py +10 -7
  4. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/agent.py +6 -8
  5. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/compress.py +11 -3
  6. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/read.py +5 -0
  7. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/search.py +14 -17
  8. {code_context_control-2.120.0 → code_context_control-2.121.0/code_context_control.egg-info}/PKG-INFO +1 -1
  9. {code_context_control-2.120.0 → code_context_control-2.121.0}/code_context_control.egg-info/SOURCES.txt +2 -0
  10. {code_context_control-2.120.0 → code_context_control-2.121.0}/pyproject.toml +1 -1
  11. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/agents.py +4 -23
  12. code_context_control-2.121.0/services/file_map.py +353 -0
  13. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/file_memory.py +89 -151
  14. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/parser.py +134 -36
  15. code_context_control-2.121.0/tests/test_file_map_c1.py +266 -0
  16. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_map_eval.py +5 -3
  17. {code_context_control-2.120.0 → code_context_control-2.121.0}/LICENSE +0 -0
  18. {code_context_control-2.120.0 → code_context_control-2.121.0}/README.md +0 -0
  19. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/__init__.py +0 -0
  20. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/_hook_utils.py +0 -0
  21. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/_shell_writes.py +0 -0
  22. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/commands/__init__.py +0 -0
  23. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/commands/common.py +0 -0
  24. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/commands/parser.py +0 -0
  25. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/docs.html +0 -0
  26. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/edits.html +0 -0
  27. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/guide/access.html +0 -0
  28. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/guide/bitbucket.html +0 -0
  29. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/guide/credentials.html +0 -0
  30. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/guide/getting-started.html +0 -0
  31. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/guide/index.html +0 -0
  32. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/guide/masking.html +0 -0
  33. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/guide/oracle.html +0 -0
  34. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/guide/shared.css +0 -0
  35. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/guide/tools.html +0 -0
  36. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/guide/workflow.html +0 -0
  37. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hook_access_guard.py +0 -0
  38. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hook_artifact.py +0 -0
  39. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hook_auto_snapshot.py +0 -0
  40. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hook_c3_signal.py +0 -0
  41. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hook_c3read.py +0 -0
  42. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hook_codex_lifecycle.py +0 -0
  43. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hook_dispatch.py +0 -0
  44. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hook_edit_ledger.py +0 -0
  45. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hook_edit_unlock.py +0 -0
  46. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hook_filter.py +0 -0
  47. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hook_ghost_files.py +0 -0
  48. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hook_pretool_enforce.py +0 -0
  49. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hook_prompt_recall.py +0 -0
  50. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hook_read.py +0 -0
  51. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hook_session_stats.py +0 -0
  52. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hook_terse_advisor.py +0 -0
  53. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_server.py +0 -0
  54. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/app.js +0 -0
  55. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/add_project.js +0 -0
  56. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/config_editor.js +0 -0
  57. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/drill_artifacts.js +0 -0
  58. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/drill_health.js +0 -0
  59. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/drill_panel.js +0 -0
  60. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/drill_subprojects.js +0 -0
  61. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/drill_tasks.js +0 -0
  62. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/drill_views.js +0 -0
  63. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/global_search.js +0 -0
  64. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/hub_access.js +0 -0
  65. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/hub_ci.js +0 -0
  66. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/hub_cred_audit.js +0 -0
  67. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/hub_credentials.js +0 -0
  68. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/hub_enforcement.js +0 -0
  69. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/hub_locks.js +0 -0
  70. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/hub_tokens.js +0 -0
  71. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/mcp_manager.js +0 -0
  72. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/modals.js +0 -0
  73. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/project_card.js +0 -0
  74. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/project_tree.js +0 -0
  75. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/session_drawer.js +0 -0
  76. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/settings_modal.js +0 -0
  77. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/sidebar.js +0 -0
  78. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/summary_bar.js +0 -0
  79. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/task_board.js +0 -0
  80. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/toasts.js +0 -0
  81. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/components/topbar.js +0 -0
  82. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui/state.js +0 -0
  83. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/hub_ui.html +0 -0
  84. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/mcp_proxy.py +0 -0
  85. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/progress.py +0 -0
  86. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/server.py +0 -0
  87. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/__init__.py +0 -0
  88. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/_grants.py +0 -0
  89. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/_helpers.py +0 -0
  90. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/artifacts.py +0 -0
  91. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/bitbucket.py +0 -0
  92. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/ci.py +0 -0
  93. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/credentials.py +0 -0
  94. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/delegate.py +0 -0
  95. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/edit.py +0 -0
  96. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/edit_verify.py +0 -0
  97. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/edits.py +0 -0
  98. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/federate.py +0 -0
  99. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/filter.py +0 -0
  100. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/impact.py +0 -0
  101. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/jira.py +0 -0
  102. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/locks.py +0 -0
  103. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/memory.py +0 -0
  104. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/override.py +0 -0
  105. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/project.py +0 -0
  106. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/session.py +0 -0
  107. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/shell.py +0 -0
  108. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/shell_job.py +0 -0
  109. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/shell_nudge.py +0 -0
  110. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/shell_parsers.py +0 -0
  111. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/shell_render.py +0 -0
  112. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/status.py +0 -0
  113. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/tasks.py +0 -0
  114. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/tools/validate.py +0 -0
  115. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/api.js +0 -0
  116. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/app.js +0 -0
  117. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/components/access.js +0 -0
  118. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/components/bitbucket.js +0 -0
  119. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/components/chat.js +0 -0
  120. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/components/credentials.js +0 -0
  121. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/components/dashboard.js +0 -0
  122. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/components/edits.js +0 -0
  123. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/components/enforcement.js +0 -0
  124. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/components/instructions.js +0 -0
  125. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/components/jira.js +0 -0
  126. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/components/memory.js +0 -0
  127. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/components/sessions.js +0 -0
  128. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/components/settings.js +0 -0
  129. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/components/sidebar.js +0 -0
  130. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/components/tasks.js +0 -0
  131. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/icons.js +0 -0
  132. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/pm_shared.js +0 -0
  133. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/shared.js +0 -0
  134. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui/theme.js +0 -0
  135. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui.html +0 -0
  136. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui_legacy.html +0 -0
  137. {code_context_control-2.120.0 → code_context_control-2.121.0}/cli/ui_nano.html +0 -0
  138. {code_context_control-2.120.0 → code_context_control-2.121.0}/code_context_control.egg-info/dependency_links.txt +0 -0
  139. {code_context_control-2.120.0 → code_context_control-2.121.0}/code_context_control.egg-info/entry_points.txt +0 -0
  140. {code_context_control-2.120.0 → code_context_control-2.121.0}/code_context_control.egg-info/requires.txt +0 -0
  141. {code_context_control-2.120.0 → code_context_control-2.121.0}/code_context_control.egg-info/top_level.txt +0 -0
  142. {code_context_control-2.120.0 → code_context_control-2.121.0}/core/__init__.py +0 -0
  143. {code_context_control-2.120.0 → code_context_control-2.121.0}/core/codex_patch.py +0 -0
  144. {code_context_control-2.120.0 → code_context_control-2.121.0}/core/config.py +0 -0
  145. {code_context_control-2.120.0 → code_context_control-2.121.0}/core/host.py +0 -0
  146. {code_context_control-2.120.0 → code_context_control-2.121.0}/core/ide.py +0 -0
  147. {code_context_control-2.120.0 → code_context_control-2.121.0}/core/mcp_toml.py +0 -0
  148. {code_context_control-2.120.0 → code_context_control-2.121.0}/core/web_security.py +0 -0
  149. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/__init__.py +0 -0
  150. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/config.py +0 -0
  151. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/mcp_oracle.py +0 -0
  152. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/oracle_server.py +0 -0
  153. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/oracle_ui.html +0 -0
  154. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/__init__.py +0 -0
  155. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/activity_reporter.py +0 -0
  156. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/api_auth.py +0 -0
  157. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/c3_bridge.py +0 -0
  158. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/chat_engine.py +0 -0
  159. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/chat_poll.py +0 -0
  160. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/chat_store.py +0 -0
  161. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/cross_memory.py +0 -0
  162. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/discovery_audit.py +0 -0
  163. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/federated_graph.py +0 -0
  164. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/health_checker.py +0 -0
  165. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/insight_engine.py +0 -0
  166. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/local_session.py +0 -0
  167. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/memory_reader.py +0 -0
  168. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/memory_writer.py +0 -0
  169. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/mobile_api.py +0 -0
  170. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/project_scanner.py +0 -0
  171. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/review_agent.py +0 -0
  172. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/tool_executor.py +0 -0
  173. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/services/tool_registry.py +0 -0
  174. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/activity.js +0 -0
  175. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/agents.js +0 -0
  176. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/app.js +0 -0
  177. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/busy.js +0 -0
  178. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/chat/conversations.js +0 -0
  179. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/chat/input.js +0 -0
  180. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/chat/markdown.js +0 -0
  181. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/chat/send.js +0 -0
  182. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/chat/stream_renderer.js +0 -0
  183. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/chat/toolbar.js +0 -0
  184. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/core.js +0 -0
  185. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/crossgraph.js +0 -0
  186. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/header.js +0 -0
  187. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/insights.js +0 -0
  188. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/projects.js +0 -0
  189. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/qrcode.js +0 -0
  190. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/settings.js +0 -0
  191. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/suggestions.js +0 -0
  192. {code_context_control-2.120.0 → code_context_control-2.121.0}/oracle/ui/theme_tabs.js +0 -0
  193. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/__init__.py +0 -0
  194. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/access_guard.py +0 -0
  195. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/access_telemetry.py +0 -0
  196. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/activity_log.py +0 -0
  197. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/agent_base.py +0 -0
  198. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/agent_locks.py +0 -0
  199. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/artifact_defs.py +0 -0
  200. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/artifact_store.py +0 -0
  201. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/atomic_json.py +0 -0
  202. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/auto_memory.py +0 -0
  203. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/background_service.py +0 -0
  204. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/bench/__init__.py +0 -0
  205. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/bench/external/__init__.py +0 -0
  206. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/bench/external/aider_polyglot.py +0 -0
  207. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/bench/external/swe_bench.py +0 -0
  208. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/bench/map_eval.py +0 -0
  209. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/bench/search_eval.py +0 -0
  210. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/bench/shell_eval.py +0 -0
  211. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/benchmark_dashboard.py +0 -0
  212. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/bitbucket_client.py +0 -0
  213. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/bitbucket_credentials.py +0 -0
  214. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/ci_act.py +0 -0
  215. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/ci_cache.py +0 -0
  216. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/ci_expr.py +0 -0
  217. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/ci_failures.py +0 -0
  218. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/ci_github.py +0 -0
  219. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/ci_impact.py +0 -0
  220. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/ci_intel.py +0 -0
  221. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/ci_runner.py +0 -0
  222. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/ci_workflow.py +0 -0
  223. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/circuit_breaker.py +0 -0
  224. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/claude_md.py +0 -0
  225. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/codex_integration.py +0 -0
  226. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/codex_transcript.py +0 -0
  227. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/compressor.py +0 -0
  228. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/context_snapshot.py +0 -0
  229. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/conversation_store.py +0 -0
  230. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/cred_audit.py +0 -0
  231. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/cred_telemetry.py +0 -0
  232. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/credential_store.py +0 -0
  233. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/doc_index.py +0 -0
  234. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/e2e_benchmark.py +0 -0
  235. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/e2e_evaluator.py +0 -0
  236. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/e2e_tasks.py +0 -0
  237. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/edit_ledger.py +0 -0
  238. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/embedding_index.py +0 -0
  239. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/enforcement_policy.py +0 -0
  240. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/error_reporting.py +0 -0
  241. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/git_context.py +0 -0
  242. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/hub_service.py +0 -0
  243. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/index_store.py +0 -0
  244. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/indexer.py +0 -0
  245. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/jira_client.py +0 -0
  246. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/jira_cloud.py +0 -0
  247. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/jira_credentials.py +0 -0
  248. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/jira_data_center.py +0 -0
  249. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/jira_links.py +0 -0
  250. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/lexical_index.py +0 -0
  251. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/mask_activation.py +0 -0
  252. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/mask_mirror.py +0 -0
  253. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/mask_presets.py +0 -0
  254. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/memory.py +0 -0
  255. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/memory_consolidator.py +0 -0
  256. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/memory_distiller.py +0 -0
  257. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/memory_graph.py +0 -0
  258. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/memory_grounder.py +0 -0
  259. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/memory_queue.py +0 -0
  260. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/memory_scorer.py +0 -0
  261. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/metrics.py +0 -0
  262. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/notifications.py +0 -0
  263. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/ollama_bridge.py +0 -0
  264. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/ollama_client.py +0 -0
  265. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/ollama_credentials.py +0 -0
  266. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/oracle_service.py +0 -0
  267. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/output_filter.py +0 -0
  268. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/override_grants.py +0 -0
  269. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/override_policy.py +0 -0
  270. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/override_requests.py +0 -0
  271. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/override_wake.py +0 -0
  272. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/project_manager.py +0 -0
  273. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/project_runtime.py +0 -0
  274. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/protocol.py +0 -0
  275. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/proxy_state.py +0 -0
  276. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/repo_map.py +0 -0
  277. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/repo_shape.py +0 -0
  278. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/reranker.py +0 -0
  279. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/retention.py +0 -0
  280. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/retrieval.py +0 -0
  281. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/retrieval_broker.py +0 -0
  282. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/router.py +0 -0
  283. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/runtime.py +0 -0
  284. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/scanner.py +0 -0
  285. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/session_benchmark.py +0 -0
  286. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/session_manager.py +0 -0
  287. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/session_preloader.py +0 -0
  288. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/shell_jobs.py +0 -0
  289. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/shell_output.py +0 -0
  290. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/subprojects.py +0 -0
  291. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/task_store.py +0 -0
  292. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/telemetry.py +0 -0
  293. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/text_index.py +0 -0
  294. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/time_tracker.py +0 -0
  295. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/tool_classifier.py +0 -0
  296. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/transcript_index.py +0 -0
  297. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/validation_cache.py +0 -0
  298. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/vector_store.py +0 -0
  299. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/watcher.py +0 -0
  300. {code_context_control-2.120.0 → code_context_control-2.121.0}/services/win_subprocess.py +0 -0
  301. {code_context_control-2.120.0 → code_context_control-2.121.0}/setup.cfg +0 -0
  302. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_access_builtin_optout.py +0 -0
  303. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_access_guard.py +0 -0
  304. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_access_guard_meta.py +0 -0
  305. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_access_guard_shell_project.py +0 -0
  306. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_access_guard_surfaces.py +0 -0
  307. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_access_guard_wiring.py +0 -0
  308. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_activity_reporter.py +0 -0
  309. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_agent_locks.py +0 -0
  310. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_aider_polyglot.py +0 -0
  311. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_antigravity_transition.py +0 -0
  312. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_artifact_store.py +0 -0
  313. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_artifact_tool.py +0 -0
  314. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_atomic_json.py +0 -0
  315. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_background_service.py +0 -0
  316. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_bitbucket_cli_smoke.py +0 -0
  317. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_bitbucket_client.py +0 -0
  318. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_bitbucket_config_fallback.py +0 -0
  319. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_bitbucket_credentials.py +0 -0
  320. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_bitbucket_tool.py +0 -0
  321. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_builtin_modes.py +0 -0
  322. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_c3_bridge_project_artifacts.py +0 -0
  323. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_c3_shell.py +0 -0
  324. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_chat_poll.py +0 -0
  325. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_ci_act.py +0 -0
  326. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_ci_cache.py +0 -0
  327. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_ci_expr.py +0 -0
  328. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_ci_impact.py +0 -0
  329. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_ci_intel.py +0 -0
  330. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_ci_runner.py +0 -0
  331. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_ci_workflow.py +0 -0
  332. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_circuit_breaker.py +0 -0
  333. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_claude_md_merge.py +0 -0
  334. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_claude_md_updater.py +0 -0
  335. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_cli_smoke.py +0 -0
  336. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_codex_mcp_transport.py +0 -0
  337. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_codex_native.py +0 -0
  338. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_compressor_large_file.py +0 -0
  339. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_confirm_guard.py +0 -0
  340. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_confirm_guard_wiring.py +0 -0
  341. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_cooccurrence_bounds.py +0 -0
  342. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_cred_audit.py +0 -0
  343. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_cred_telemetry.py +0 -0
  344. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_credential_login_kind.py +0 -0
  345. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_credential_store.py +0 -0
  346. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_credential_ui_parity.py +0 -0
  347. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_credentials_routes.py +0 -0
  348. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_credentials_tool.py +0 -0
  349. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_creds_cli_smoke.py +0 -0
  350. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_delegate_cascade.py +0 -0
  351. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_delegate_version_probe.py +0 -0
  352. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_e2e_benchmark.py +0 -0
  353. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_edit_ledger_deadline.py +0 -0
  354. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_edit_ledger_hook.py +0 -0
  355. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_edit_locking.py +0 -0
  356. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_edit_normalization.py +0 -0
  357. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_edit_verify.py +0 -0
  358. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_embedding_index_deadlock.py +0 -0
  359. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_enforcement_flip.py +0 -0
  360. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_enforcement_policy.py +0 -0
  361. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_enforcement_routes.py +0 -0
  362. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_env_parser.py +0 -0
  363. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_failed_calls_do_not_unlock.py +0 -0
  364. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_federated_graph.py +0 -0
  365. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_filter_backoff.py +0 -0
  366. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_ghost_files.py +0 -0
  367. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_ghost_generation.py +0 -0
  368. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_git_branch_awareness.py +0 -0
  369. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_hook_access_guard.py +0 -0
  370. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_hook_codex_compat.py +0 -0
  371. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_hook_dispatch.py +0 -0
  372. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_hook_pretool_enforce.py +0 -0
  373. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_hook_prompt_recall.py +0 -0
  374. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_hook_smoke.py +0 -0
  375. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_hook_state.py +0 -0
  376. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_hook_utf8_stdio.py +0 -0
  377. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_hub_credentials_route.py +0 -0
  378. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_hub_credentials_routes_write.py +0 -0
  379. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_hub_enforcement_routes.py +0 -0
  380. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_hub_inspect_api.py +0 -0
  381. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_hub_locks_routes.py +0 -0
  382. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_hub_oracle_service_routes.py +0 -0
  383. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_hub_override_routes.py +0 -0
  384. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_hub_server_smoke.py +0 -0
  385. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_hub_subproject_links.py +0 -0
  386. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_ide_workflow_adaptation.py +0 -0
  387. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_index_cap_not_hardcoded.py +0 -0
  388. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_init_clear_preserves_user_content.py +0 -0
  389. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_init_scan.py +0 -0
  390. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_install_mcp_entrypoint.py +0 -0
  391. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_jira_cli_smoke.py +0 -0
  392. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_jira_client.py +0 -0
  393. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_jira_config_fallback.py +0 -0
  394. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_jira_credentials.py +0 -0
  395. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_jira_links.py +0 -0
  396. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_jira_routes.py +0 -0
  397. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_jira_tool.py +0 -0
  398. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_lazy_store_init.py +0 -0
  399. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_map_telemetry_c0.py +0 -0
  400. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_mask_guard.py +0 -0
  401. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_mask_routes.py +0 -0
  402. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_mask_surfaces.py +0 -0
  403. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_mcp_host_guard.py +0 -0
  404. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_mcp_memory_timeout.py +0 -0
  405. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_mcp_server_smoke.py +0 -0
  406. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_mcp_toml.py +0 -0
  407. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_memory_distiller.py +0 -0
  408. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_memory_graph_api.py +0 -0
  409. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_memory_queue.py +0 -0
  410. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_memory_system.py +0 -0
  411. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_mobile_api.py +0 -0
  412. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_mobile_extras.py +0 -0
  413. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_mobile_override_routes.py +0 -0
  414. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_mobile_security_api.py +0 -0
  415. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_no_stale_model_pins.py +0 -0
  416. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_notification_dedup.py +0 -0
  417. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_notification_discipline.py +0 -0
  418. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_ollama_credentials.py +0 -0
  419. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_oracle_api_auth.py +0 -0
  420. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_oracle_apikey_api.py +0 -0
  421. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_oracle_c3_bridge.py +0 -0
  422. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_oracle_chat_engine.py +0 -0
  423. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_oracle_chat_store.py +0 -0
  424. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_oracle_discovery_api.py +0 -0
  425. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_oracle_discovery_audit.py +0 -0
  426. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_oracle_health_probe.py +0 -0
  427. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_oracle_local_auth.py +0 -0
  428. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_oracle_ollama_bridge.py +0 -0
  429. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_oracle_scanner_cache.py +0 -0
  430. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_oracle_security_fixes.py +0 -0
  431. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_oracle_session_bootstrap.py +0 -0
  432. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_oracle_subproject_awareness.py +0 -0
  433. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_oracle_ui_bundle.py +0 -0
  434. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_output_filter.py +0 -0
  435. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_override_grants.py +0 -0
  436. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_override_grants_mcp.py +0 -0
  437. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_override_requests.py +0 -0
  438. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_override_wake.py +0 -0
  439. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_permissions.py +0 -0
  440. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_pm_api.py +0 -0
  441. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_project_manager.py +0 -0
  442. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_project_manager_merge.py +0 -0
  443. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_project_tool.py +0 -0
  444. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_read_coercion.py +0 -0
  445. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_read_edit_parity.py +0 -0
  446. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_related_facts.py +0 -0
  447. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_repo_map.py +0 -0
  448. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_repo_shape.py +0 -0
  449. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_response_boilerplate.py +0 -0
  450. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_retention.py +0 -0
  451. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_review_digest.py +0 -0
  452. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_search_eval.py +0 -0
  453. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_search_p1.py +0 -0
  454. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_search_p2.py +0 -0
  455. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_search_p2b.py +0 -0
  456. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_search_p3.py +0 -0
  457. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_search_p4.py +0 -0
  458. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_search_p5.py +0 -0
  459. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_service_durability.py +0 -0
  460. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_session_benchmark.py +0 -0
  461. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_session_budget.py +0 -0
  462. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_shell_budget_s1.py +0 -0
  463. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_shell_creds.py +0 -0
  464. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_shell_eval.py +0 -0
  465. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_shell_jobs_s3.py +0 -0
  466. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_shell_nudge_s4.py +0 -0
  467. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_shell_output.py +0 -0
  468. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_shell_parsers_s2.py +0 -0
  469. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_shell_robustness.py +0 -0
  470. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_shell_telemetry_s0.py +0 -0
  471. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_shell_write_ledger.py +0 -0
  472. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_shell_writes.py +0 -0
  473. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_subproject_clear_scope.py +0 -0
  474. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_subproject_depth_consumers.py +0 -0
  475. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_subproject_exclusion.py +0 -0
  476. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_subproject_federation.py +0 -0
  477. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_subproject_linkage_api.py +0 -0
  478. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_subprojects.py +0 -0
  479. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_swe_bench.py +0 -0
  480. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_task_store.py +0 -0
  481. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_task_tool.py +0 -0
  482. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_time_tracker.py +0 -0
  483. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_token_telemetry.py +0 -0
  484. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_token_tracking.py +0 -0
  485. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_tool_registry.py +0 -0
  486. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_ui_jsx_syntax.py +0 -0
  487. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_upgrade_and_version.py +0 -0
  488. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_validate.py +0 -0
  489. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_vault_write_guard.py +0 -0
  490. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_version_sync.py +0 -0
  491. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_web_security.py +0 -0
  492. {code_context_control-2.120.0 → code_context_control-2.121.0}/tests/test_windows_reliability.py +0 -0
  493. {code_context_control-2.120.0 → code_context_control-2.121.0}/tui/__init__.py +0 -0
  494. {code_context_control-2.120.0 → code_context_control-2.121.0}/tui/backend.py +0 -0
  495. {code_context_control-2.120.0 → code_context_control-2.121.0}/tui/main.py +0 -0
  496. {code_context_control-2.120.0 → code_context_control-2.121.0}/tui/screens/__init__.py +0 -0
  497. {code_context_control-2.120.0 → code_context_control-2.121.0}/tui/screens/benchmark_view.py +0 -0
  498. {code_context_control-2.120.0 → code_context_control-2.121.0}/tui/screens/claudemd_view.py +0 -0
  499. {code_context_control-2.120.0 → code_context_control-2.121.0}/tui/screens/compress_view.py +0 -0
  500. {code_context_control-2.120.0 → code_context_control-2.121.0}/tui/screens/index_view.py +0 -0
  501. {code_context_control-2.120.0 → code_context_control-2.121.0}/tui/screens/init_view.py +0 -0
  502. {code_context_control-2.120.0 → code_context_control-2.121.0}/tui/screens/mcp_view.py +0 -0
  503. {code_context_control-2.120.0 → code_context_control-2.121.0}/tui/screens/optimize_view.py +0 -0
  504. {code_context_control-2.120.0 → code_context_control-2.121.0}/tui/screens/pipe_view.py +0 -0
  505. {code_context_control-2.120.0 → code_context_control-2.121.0}/tui/screens/projects_view.py +0 -0
  506. {code_context_control-2.120.0 → code_context_control-2.121.0}/tui/screens/search_view.py +0 -0
  507. {code_context_control-2.120.0 → code_context_control-2.121.0}/tui/screens/session_view.py +0 -0
  508. {code_context_control-2.120.0 → code_context_control-2.121.0}/tui/screens/stats.py +0 -0
  509. {code_context_control-2.120.0 → code_context_control-2.121.0}/tui/screens/ui_view.py +0 -0
  510. {code_context_control-2.120.0 → code_context_control-2.121.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.120.0
3
+ Version: 2.121.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.120.0"
95
+ __version__ = "2.121.0"
96
96
 
97
97
 
98
98
  def _compress_file_cli(compressor, path, mode="smart", **kw):
@@ -85,7 +85,7 @@ def _build_instructions(ide_name: str) -> str:
85
85
  return (
86
86
  "C3 — local code intelligence. Route by goal:\n"
87
87
  " FIND candidates → c3_search\n"
88
- " MAP file shape → c3_compress(mode='map') then READ content → c3_read(symbols=…)\n"
88
+ " MAP a file → c3_read(file_path) with no symbols, then READ → c3_read(symbols=…); batch maps → c3_compress\n"
89
89
  " EDIT code → c3_edit (always; it logs to the ledger automatically)\n"
90
90
  " VALIDATE after every edit → c3_validate\n"
91
91
  " BLAST RADIUS before shared-symbol edits → c3_impact\n"
@@ -583,8 +583,10 @@ async def c3_memory(action: str, query: str = "", fact: str = "",
583
583
  @mcp.tool()
584
584
  async def c3_read(file_path: str, symbols: Any = None, lines: Any = None,
585
585
  include_docstrings: bool = True, ctx: Context = None) -> str:
586
- """READ exact content. Use after c3_compress when you need real source (read-only, plan-mode safe).
587
- file_path: single or comma-separated. symbols: function/class names. lines: int, [start,end], or list of ranges."""
586
+ """READ source, or MAP a file when called with only file_path (read-only, plan-mode safe).
587
+ file_path: single or comma-separated. symbols: names as the map prints them (Class.method ok).
588
+ lines: int, [start,end], or list of ranges. No symbols/lines = one line per symbol with
589
+ signature and [La-Lb] range at ~10% of the file's tokens; then read the symbols you need."""
588
590
  path_err = validate_file_path(file_path)
589
591
  if path_err:
590
592
  return f"[c3_read:error] {path_err}"
@@ -597,10 +599,11 @@ async def c3_read(file_path: str, symbols: Any = None, lines: Any = None,
597
599
 
598
600
 
599
601
  @mcp.tool()
600
- async def c3_compress(file_path: str, mode: str = "smart", ctx: Context = None) -> str:
601
- """MAP file shape — classes/functions/imports at 40-70% tokens (read-only, plan-mode safe).
602
- Use before c3_read to know which symbols to fetch. Modes: map, dense_map, smart, diff, bug_scan, ast.
603
- file_path: single or comma-separated."""
602
+ async def c3_compress(file_path: str, mode: str = "map", ctx: Context = None) -> str:
603
+ """MAP a file — one line per symbol with full signature and [La-Lb] range, ~10% of the
604
+ file's tokens (read-only, plan-mode safe). Same map as c3_read(file_path) with no symbols;
605
+ use this form for a comma-separated batch (up to 10). mode: map (default); other modes
606
+ are legacy."""
604
607
  path_err = validate_file_path(file_path)
605
608
  if path_err:
606
609
  return f"[c3_compress:error] {path_err}"
@@ -877,11 +877,10 @@ def _parallel_compress(files: list, svc, steps_log: list,
877
877
  maps = {}
878
878
 
879
879
  def compress_one(fp):
880
- full_path = str(Path(svc.project_path) / fp)
881
880
  try:
882
- res = svc.compressor.compress_file(full_path, "map")
883
- if isinstance(res, dict) and res.get("compressed"):
884
- return fp, res["compressed"]
881
+ fmap = svc.file_memory.get_or_build_map(fp.replace("\\", "/"))
882
+ if fmap and not fmap.startswith("[file_map]"):
883
+ return fp, fmap
885
884
  except Exception:
886
885
  pass
887
886
  return fp, None
@@ -936,11 +935,10 @@ def _parallel_validate_and_compress(files: list, svc, steps_log: list):
936
935
  return "validate", fp, "ERROR", str(e)
937
936
 
938
937
  def compress_one(fp):
939
- full_path = str(Path(svc.project_path) / fp)
940
938
  try:
941
- res = svc.compressor.compress_file(full_path, "map")
942
- if isinstance(res, dict) and res.get("compressed"):
943
- return "compress", fp, res["compressed"]
939
+ fmap = svc.file_memory.get_or_build_map(fp.replace("\\", "/"))
940
+ if fmap and not fmap.startswith("[file_map]"):
941
+ return "compress", fp, fmap
944
942
  except Exception:
945
943
  pass
946
944
  return "compress", fp, None
@@ -1,5 +1,7 @@
1
- """c3_compress — Token-efficient file summaries (6 modes: map, dense_map, smart, diff, bug_scan, ast).
2
- Supports comma-separated paths for batch compression with parallel execution."""
1
+ """c3_compress — the canonical file map (services/file_map.render_map), one file or a batch.
2
+
3
+ mode='map' (default) is the same text c3_read(file_path) serves. The other
4
+ modes (dense_map, smart, diff, bug_scan, ast) are legacy and retire in 2.122.0."""
3
5
 
4
6
  import json
5
7
  import shutil
@@ -218,8 +220,14 @@ def _compress_single(file_path: str, mode: str, svc, finalize, maybe_facts) -> s
218
220
  raw_tokens = None
219
221
  map_tokens = 0
220
222
  try:
221
- raw_tokens = count_tokens(full.read_text(encoding="utf-8", errors="replace"))
223
+ raw_text = full.read_text(encoding="utf-8", errors="replace")
224
+ raw_tokens = count_tokens(raw_text)
222
225
  map_tokens = count_tokens(res)
226
+ if map_tokens >= raw_tokens and not res.startswith("[file_map]"):
227
+ # A map that costs more than the file is worth nothing
228
+ # (docs/file-map.md § Small files).
229
+ res = f"[compress:{file_path}] whole file — smaller than its map\n" + raw_text
230
+ map_tokens = count_tokens(res)
223
231
  summary = mode
224
232
  except Exception:
225
233
  summary = "mapped"
@@ -316,6 +316,11 @@ def handle_read(file_path: str, symbols: Any = None, lines: Any = None,
316
316
  if not ranges:
317
317
  map_cached = not svc.file_memory.needs_update(rel_path)
318
318
  file_map = svc.file_memory.get_or_build_map(rel_path)
319
+ if count_tokens(file_map) >= full_file_tokens():
320
+ # A map that costs more than the file is worth nothing: serve the
321
+ # file (docs/file-map.md § Small files).
322
+ file_map = (f"[read:{file_path}] whole file — smaller than its map\n"
323
+ + raw_text)
319
324
  resp = (file_map
320
325
  + "\n[map only — pass lines=[start,end] or symbols=[...] for exact source]"
321
326
  + maybe_related_facts(svc, rel_path, top_k=3, context="read"))
@@ -13,6 +13,7 @@ from pathlib import Path
13
13
  from cli.tools._helpers import finalize_with_tokens, show_token_ratios
14
14
  from core import count_tokens
15
15
  from services import access_guard
16
+ from services.file_map import render_map
16
17
  from services.indexer import DEFAULT_CODE_EXTS
17
18
  from services.lexical_index import Filters, doc_kind
18
19
  from services.scanner import SKIP_DIRS, iter_files
@@ -473,21 +474,15 @@ def _first_file_map(rel: str, svc) -> str:
473
474
  watcher_active = (hasattr(svc, "watcher") and svc.watcher._observer.is_alive())
474
475
  if not watcher_active and svc.file_memory.needs_update(rel):
475
476
  svc.file_memory.update(rel)
476
- fmap = svc.file_memory.get_or_build_map(rel)
477
+ record = svc.file_memory.get(rel)
478
+ if not record:
479
+ return ""
480
+ # Same renderer as c3_read/c3_compress, shortened to the cap by
481
+ # dropping symbol lines from the end (docs/file-map.md).
482
+ fmap = render_map(record, max_tokens=_MAP_TOKEN_CAP)
477
483
  if not fmap:
478
484
  return ""
479
- if count_tokens(fmap) <= _MAP_TOKEN_CAP:
480
- return f"\n {fmap.replace(chr(10), chr(10) + ' ')}"
481
- # Truncate large maps: keep first N lines
482
- truncated = []
483
- tok = 0
484
- for fl in fmap.split("\n"):
485
- tok += count_tokens(fl)
486
- if tok > _MAP_TOKEN_CAP:
487
- break
488
- truncated.append(fl)
489
- truncated.append(" [map truncated]")
490
- return f"\n {chr(10).join(truncated).replace(chr(10), chr(10) + ' ')}"
485
+ return f"\n {fmap.replace(chr(10), chr(10) + ' ')}"
491
486
  except Exception:
492
487
  return ""
493
488
 
@@ -720,11 +715,13 @@ def _append_prefetch(resp: str, query: str, top_k: int, svc) -> str:
720
715
  uncached.append(fp)
721
716
 
722
717
  def compress_one(fp):
718
+ # The canonical map from file_memory — the same text c3_read serves
719
+ # (compressor.compress_file never had a "map" mode; it rendered a
720
+ # structure-only summary under that name).
723
721
  try:
724
- full = str(Path(svc.project_path) / fp)
725
- result = svc.compressor.compress_file(full, "map")
726
- if isinstance(result, dict) and result.get("compressed"):
727
- return fp, result["compressed"]
722
+ fmap = svc.file_memory.get_or_build_map(fp.replace("\\", "/"))
723
+ if fmap and not fmap.startswith("[file_map]"):
724
+ return fp, fmap
728
725
  except Exception:
729
726
  pass
730
727
  return fp, None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-context-control
3
- Version: 2.120.0
3
+ Version: 2.121.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
@@ -225,6 +225,7 @@ services/edit_ledger.py
225
225
  services/embedding_index.py
226
226
  services/enforcement_policy.py
227
227
  services/error_reporting.py
228
+ services/file_map.py
228
229
  services/file_memory.py
229
230
  services/git_context.py
230
231
  services/hub_service.py
@@ -357,6 +358,7 @@ tests/test_enforcement_routes.py
357
358
  tests/test_env_parser.py
358
359
  tests/test_failed_calls_do_not_unlock.py
359
360
  tests/test_federated_graph.py
361
+ tests/test_file_map_c1.py
360
362
  tests/test_filter_backoff.py
361
363
  tests/test_ghost_files.py
362
364
  tests/test_ghost_generation.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "code-context-control"
7
- version = "2.120.0"
7
+ version = "2.121.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"
@@ -923,29 +923,10 @@ class FileMemoryAgent(BackgroundAgent):
923
923
  completed = []
924
924
  failed = []
925
925
  for rel_path in files_to_process:
926
- ai_summary = None
927
-
928
- # Generate AI summary if available
929
- if self.ai_available:
930
- record = self.file_memory.get(rel_path)
931
- section_names = ""
932
- if record:
933
- names = [s.get("name", "") for s in record.get("sections", [])
934
- if s.get("type") not in ("import", "decorator")]
935
- section_names = ", ".join(names[:10])
936
-
937
- if section_names:
938
- ai_summary = self._ai_generate(
939
- f"File: {rel_path}\n"
940
- f"Symbols: {section_names}\n\n"
941
- f"Describe the purpose of this file and its main symbols in 1-2 concise sentences. "
942
- f"Focus on what they do, not how they are implemented.",
943
- system="You are a senior architect summarizing code for an AI assistant. "
944
- "Be technical, concise, and highlight the main responsibilities of the symbols.",
945
- max_tokens=100,
946
- )
947
-
948
- result = self.file_memory.update(rel_path, ai_summary=ai_summary)
926
+ # No generated summary: it was produced from symbol names alone
927
+ # and half of the stored ones were cut mid-sentence (2026-09-06).
928
+ # The map carries symbols and ranges only (docs/file-map.md).
929
+ result = self.file_memory.update(rel_path)
949
930
  if result:
950
931
  updated_count += 1
951
932
  completed.append(rel_path)
@@ -0,0 +1,353 @@
1
+ """The canonical file map — ONE renderer for every map C3 serves.
2
+
3
+ A map is what the model reads to choose a `c3_read` target: one line per
4
+ symbol carrying kind, qualified name, the complete signature, the return
5
+ type when the source has one, and the exact line range. Nothing else — no
6
+ emoji, no column padding, no AI summary, no docstrings unless asked
7
+ (docs/file-map.md, C1 of the c3_compress remediation).
8
+
9
+ # services/compressor.py (806L python)
10
+ I 12 imports
11
+ K LARGE_FILE_LINE_THRESHOLD [L77-L77]
12
+ C CodeCompressor [L130-L806]
13
+ M CodeCompressor.compress_file(self, filepath: str, mode: str = "structure") -> dict [L166-L188]
14
+ F handle_compress(file_path: str, mode: str, svc, finalize, maybe_facts) -> str [L94-L114]
15
+
16
+ Every symbol line matches SYMBOL_LINE_RE, so a harness, a test, or the
17
+ model can parse the map back without knowing the language. Renders from a
18
+ FileMemoryStore record (the `sections` tree the parsers produce); parsers
19
+ that emit a flat list (Rust, Go) are nested here by line containment so an
20
+ impl's methods still read as `Type.method`.
21
+ """
22
+ from __future__ import annotations
23
+
24
+ import re
25
+ from typing import Any, Optional
26
+
27
+ from core import count_tokens
28
+
29
+ # Section type (as the parsers emit it) -> kind letter in the map.
30
+ KINDS = {
31
+ "class": "C", "function": "F", "method": "M", "property": "P",
32
+ "constant": "K", "variable": "V", "interface": "IF", "type": "T",
33
+ "enum": "E", "struct": "S", "trait": "TR", "impl": "IM",
34
+ "heading": "H", "section": "SEC", "import": "I",
35
+ }
36
+ # Section types that are never a symbol line of their own.
37
+ SKIP_TYPES = {"decorator", "comment", "content"}
38
+ # Kinds whose line carries a parameter list when the signature has one.
39
+ CALLABLE_KINDS = {"F", "M"}
40
+ # Container kinds: children (explicit or by containment) nest under them.
41
+ CONTAINER_KINDS = {"C", "IM", "TR", "S", "E", "IF"}
42
+ # More imports than this collapse to one count line.
43
+ IMPORTS_INLINE_MAX = 6
44
+ # Docstring excerpt cap when include_docs=True.
45
+ DOC_MAX_CHARS = 120
46
+
47
+ SYMBOL_LINE_RE = re.compile(
48
+ r"^(?P<indent> *)(?P<kind>I|K|V|C|M|P|F|IF|T|E|S|TR|IM|H|SEC) "
49
+ r"(?P<async>async )?(?P<name>.+?)(?:\((?P<params>.*)\))?"
50
+ r"(?: -> (?P<ret>.+?))? \[L(?P<a>\d+)-L(?P<b>\d+)\]$")
51
+
52
+ _WS = re.compile(r"\s+")
53
+
54
+ # Signature grammars, most specific first. Each yields (params, ret, receiver).
55
+ _PY_DEF = re.compile(r"^(?:async\s+)?def\s+[\w.]+\s*\((?P<params>.*)\)\s*(?:->\s*(?P<ret>.+?))?\s*:?$")
56
+ _PY_CLASS = re.compile(r"^class\s+\w+\s*(?:\((?P<bases>.*)\))?\s*:?$")
57
+ _GO_FUNC = re.compile(r"^func\s+(?:\((?P<recv>[^)]*)\)\s*)?\w+\s*\((?P<params>.*?)\)\s*(?P<ret>[^{]*?)\s*\{?$")
58
+ _RS_FN = re.compile(r"^(?:pub(?:\([^)]*\))?\s+)?(?:async\s+|const\s+|unsafe\s+)*fn\s+\w+(?:<[^>]*>)?\s*\((?P<params>.*)\)\s*(?:->\s*(?P<ret>[^{]+?))?\s*(?:where\b.*)?\{?$")
59
+ _JS_FUNC = re.compile(r"^(?:export\s+)?(?:default\s+)?(?:async\s+)?function\s*\*?\s*\w*\s*(?:<[^>]*>)?\s*\((?P<params>.*)\)\s*(?::\s*(?P<ret>[^{]+?))?\s*\{?$")
60
+ _JS_ARROW = re.compile(r"^(?:export\s+)?(?:const|let|var)\s+\w+\s*(?::[^=]+)?=\s*(?:async\s+)?\((?P<params>.*)\)\s*(?::\s*(?P<ret>[^=]+?))?\s*=>")
61
+ _JS_ARROW1 = re.compile(r"^(?:export\s+)?(?:const|let|var)\s+\w+\s*=\s*(?:async\s+)?(?P<params>\w+)\s*=>")
62
+ _JS_CLASS = re.compile(r"^(?:export\s+)?(?:default\s+)?(?:abstract\s+)?class\s+\w+(?:<[^>]*>)?\s*(?:extends\s+(?P<base>[\w.<>, ]+?))?\s*(?:implements\s+(?P<impl>[\w.<>, ]+?))?\s*\{?$")
63
+ _JS_METHOD = re.compile(r"^(?:(?:public|private|protected|static|readonly|async|get|set|override)\s+)*[\w$#]+\s*(?:<[^>]*>)?\s*\((?P<params>.*)\)\s*(?::\s*(?P<ret>[^{]+?))?\s*\{?$")
64
+
65
+
66
+ def _norm(text: str) -> str:
67
+ return _WS.sub(" ", str(text or "")).strip()
68
+
69
+
70
+ def parse_signature(signature: str, language: str) -> dict:
71
+ """Split a raw signature into params / ret / receiver / bases.
72
+
73
+ Whitespace-normalized (a multi-line def becomes one line); nothing is
74
+ truncated. Returns {} when the text has no recognisable parameter list
75
+ so the caller renders the bare name.
76
+ """
77
+ sig = _norm(signature)
78
+ if not sig:
79
+ return {}
80
+ lang = (language or "").lower()
81
+ out: dict = {}
82
+ if lang == "python":
83
+ m = _PY_DEF.match(sig)
84
+ if m:
85
+ out["params"] = _norm(m.group("params"))
86
+ if m.group("ret"):
87
+ out["ret"] = _norm(m.group("ret"))
88
+ return out
89
+ m = _PY_CLASS.match(sig)
90
+ if m and m.group("bases"):
91
+ out["bases"] = _norm(m.group("bases"))
92
+ return out
93
+ if lang == "go":
94
+ m = _GO_FUNC.match(sig)
95
+ if m:
96
+ out["params"] = _norm(m.group("params"))
97
+ ret = _norm(m.group("ret") or "")
98
+ if ret:
99
+ out["ret"] = ret.strip("()") if ret.startswith("(") and "," not in ret else ret
100
+ recv = _norm(m.group("recv") or "")
101
+ if recv:
102
+ # `s *Server` / `Server` -> Server
103
+ out["receiver"] = recv.split()[-1].lstrip("*")
104
+ return out
105
+ if lang == "rust":
106
+ m = _RS_FN.match(sig)
107
+ if m:
108
+ out["params"] = _norm(m.group("params"))
109
+ if m.group("ret"):
110
+ out["ret"] = _norm(m.group("ret"))
111
+ return out
112
+ if lang in ("javascript", "typescript"):
113
+ m = _JS_CLASS.match(sig)
114
+ if m:
115
+ bases = [b.strip() for b in (m.group("base") or "").split(",") if b.strip()]
116
+ if bases:
117
+ out["bases"] = ", ".join(bases)
118
+ return out
119
+ for rx in (_JS_FUNC, _JS_ARROW, _JS_METHOD):
120
+ m = rx.match(sig)
121
+ if m:
122
+ out["params"] = _norm(m.group("params"))
123
+ if m.groupdict().get("ret"):
124
+ out["ret"] = _norm(m.group("ret"))
125
+ return out
126
+ m = _JS_ARROW1.match(sig)
127
+ if m:
128
+ out["params"] = m.group("params")
129
+ return out
130
+ # Unknown language: a single balanced parenthesised group is a param list.
131
+ m = re.match(r"^[^()]*\((?P<params>.*)\)[^()]*$", sig)
132
+ if m and not sig.lstrip().startswith(("class ", "struct ", "enum ")):
133
+ out["params"] = _norm(m.group("params"))
134
+ return out
135
+
136
+
137
+ #: Languages whose `property` sections are top-level keys, not members.
138
+ DATA_LANGUAGES = {"json", "yaml", "toml", "ini"}
139
+
140
+
141
+ def _kind_for(section: dict, language: str) -> Optional[str]:
142
+ stype = str(section.get("type") or "")
143
+ if stype in SKIP_TYPES:
144
+ return None
145
+ if stype == "property" and (language or "").lower() in DATA_LANGUAGES:
146
+ return "SEC"
147
+ kind = KINDS.get(stype)
148
+ if kind is None:
149
+ return None
150
+ if kind == "M" and _is_property(section):
151
+ return "P"
152
+ if kind == "F" and _is_property(section):
153
+ return "P"
154
+ return kind
155
+
156
+
157
+ def _is_property(section: dict) -> bool:
158
+ decos = section.get("decorators") or []
159
+ if any(d == "property" or d.endswith(".setter") or d.endswith(".getter")
160
+ or d == "cached_property" or d.endswith(".cached_property") for d in decos):
161
+ return True
162
+ sig = str(section.get("signature") or "")
163
+ return bool(re.match(r"^\s*(?:get|set)\s+[\w$#]+\s*\(", sig))
164
+
165
+
166
+ def _heading_level(section: dict) -> int:
167
+ name = str(section.get("name") or "")
168
+ m = re.match(r"^h([1-6]):", name)
169
+ if m:
170
+ return int(m.group(1))
171
+ sig = str(section.get("signature") or "").lstrip()
172
+ if sig.startswith("#"):
173
+ return len(sig) - len(sig.lstrip("#"))
174
+ return 1
175
+
176
+
177
+ def _heading_text(section: dict) -> str:
178
+ name = str(section.get("name") or "")
179
+ name = re.sub(r"^h[1-6]:\s*", "", name)
180
+ return _norm(name)
181
+
182
+
183
+ def _first_sentence(doc: str) -> str:
184
+ text = _norm(doc)
185
+ if not text:
186
+ return ""
187
+ m = re.match(r"(.+?[.!?])(?:\s|$)", text)
188
+ sent = m.group(1) if m else text
189
+ if len(sent) > DOC_MAX_CHARS:
190
+ sent = sent[:DOC_MAX_CHARS - 1].rstrip() + "…"
191
+ return sent
192
+
193
+
194
+ def _nest_by_containment(sections: list) -> list:
195
+ """Turn a flat section list into a tree by line containment.
196
+
197
+ Parsers that never populate `children` (Rust, Go, the regex fallback)
198
+ emit an impl/trait/class followed by its methods as siblings. A
199
+ callable whose range lies inside the nearest preceding container becomes
200
+ that container's child, so it renders qualified. Sections that already
201
+ carry children are left as they are.
202
+ """
203
+ out: list = []
204
+ stack: list = [] # open containers (dicts with a synthetic "_kids" list)
205
+ for sec in sections:
206
+ ls, le = int(sec.get("line_start") or 0), int(sec.get("line_end") or 0)
207
+ while stack and not (stack[-1]["line_start"] <= ls and le <= stack[-1]["line_end"]):
208
+ stack.pop()
209
+ node = dict(sec)
210
+ node["_kids"] = list(sec.get("children") or [])
211
+ if stack and not sec.get("children") and node.get("type") in (
212
+ "function", "method", "property", "constant", "variable", "class", "struct",
213
+ "enum", "type", "interface"):
214
+ stack[-1]["_kids"].append(node)
215
+ else:
216
+ out.append(node)
217
+ if node.get("type") in ("class", "impl", "trait", "struct", "enum", "interface") \
218
+ and le > ls:
219
+ stack.append(node)
220
+ return out
221
+
222
+
223
+ def _display_name(section: dict, kind: str, parent_name: str, language: str,
224
+ parsed: dict) -> str:
225
+ name = _norm(section.get("name") or "")
226
+ if kind == "IM":
227
+ name = re.sub(r"^impl\s+", "", name)
228
+ # `impl Trait for Type` -> Type
229
+ m = re.match(r"^(?:<[^>]*>\s*)?(?:.+?\s+for\s+)?(?P<t>[\w:<>]+)", name)
230
+ if m:
231
+ name = m.group("t")
232
+ if kind == "H":
233
+ return _heading_text(section)
234
+ if parent_name and kind in ("M", "P", "F", "K", "V", "C", "S", "E", "T", "IF") \
235
+ and not name.startswith(parent_name + "."):
236
+ return f"{parent_name}.{name}"
237
+ if not parent_name and parsed.get("receiver") and kind in ("M", "F"):
238
+ return f"{parsed['receiver']}.{name}"
239
+ return name
240
+
241
+
242
+ def _render_symbol(section: dict, language: str, indent: int, parent_name: str,
243
+ include_docs: bool, lines: list) -> Optional[str]:
244
+ kind = _kind_for(section, language)
245
+ if kind is None:
246
+ return None
247
+ ls = int(section.get("line_start") or 0)
248
+ le = int(section.get("line_end") or ls)
249
+ if le < ls:
250
+ le = ls
251
+ sig = str(section.get("signature") or "")
252
+ parsed = parse_signature(sig, language) if kind in CALLABLE_KINDS | {"C", "P"} else {}
253
+ # Go: a receiver method is emitted flat; the receiver is the parent.
254
+ if kind == "M" and not parent_name and parsed.get("receiver"):
255
+ pass
256
+ name = _display_name(section, kind, parent_name, language, parsed)
257
+ is_async = bool(section.get("async")) or bool(re.match(r"^\s*(?:export\s+)?async\b", sig)) \
258
+ or bool(re.match(r"^\s*(?:pub\s+)?async\b", sig)) \
259
+ or (language == "python" and bool(re.match(r"^\s*(?:@.*\n)*\s*async\s+def", sig)))
260
+ pad = " " * indent
261
+ parts = [pad + kind + " " + ("async " if is_async else "") + name]
262
+ if kind in CALLABLE_KINDS and "params" in parsed:
263
+ parts[0] += f"({parsed['params']})"
264
+ if parsed.get("ret"):
265
+ parts[0] += f" -> {parsed['ret']}"
266
+ elif kind == "C" and parsed.get("bases"):
267
+ parts[0] += f"({parsed['bases']})"
268
+ parts[0] += f" [L{ls}-L{le}]"
269
+ lines.append(parts[0])
270
+ if include_docs and section.get("doc"):
271
+ sent = _first_sentence(str(section["doc"]))
272
+ if sent:
273
+ lines.append(f'{pad} "{sent}"')
274
+ return name
275
+
276
+
277
+ def render_map(record: dict, *, include_docs: bool = False,
278
+ max_tokens: Optional[int] = None) -> str:
279
+ """Render a FileMemoryStore record as the canonical map.
280
+
281
+ `max_tokens` (search prefetch's inline cap) drops symbol lines from the
282
+ END and appends `… <k> more symbols` — the renderer never changes shape
283
+ to fit, it only shortens.
284
+ """
285
+ path = str(record.get("path") or "").replace("\\", "/")
286
+ total_lines = int(record.get("lines") or 0)
287
+ language = str(record.get("language") or "")
288
+ sections = list(record.get("sections") or [])
289
+
290
+ header = f"# {path} ({total_lines}L {language})".rstrip()
291
+ body: list = []
292
+
293
+ imports = [s for s in sections if s.get("type") == "import"]
294
+ others = [s for s in sections if s.get("type") != "import"]
295
+ if imports:
296
+ if len(imports) > IMPORTS_INLINE_MAX:
297
+ body.append(f"I {len(imports)} imports")
298
+ else:
299
+ for imp in imports:
300
+ ls = int(imp.get("line_start") or 0)
301
+ le = int(imp.get("line_end") or ls)
302
+ body.append(f"I {_norm(imp.get('signature') or imp.get('name'))} [L{ls}-L{le}]")
303
+
304
+ tree = _nest_by_containment(others)
305
+
306
+ def _walk(nodes: list, indent: int, parent_name: str) -> None:
307
+ for node in nodes:
308
+ kind = _kind_for(node, language)
309
+ if kind is None:
310
+ continue
311
+ if kind == "H":
312
+ level = max(1, _heading_level(node))
313
+ name = _render_symbol(node, language, (level - 1) * 2, "", include_docs, body)
314
+ continue
315
+ name = _render_symbol(node, language, indent, parent_name, include_docs, body)
316
+ kids = node.get("_kids")
317
+ if kids is None:
318
+ kids = list(node.get("children") or [])
319
+ if kids and kind in CONTAINER_KINDS:
320
+ _walk(kids, indent + 2, name or "")
321
+ elif kids:
322
+ _walk(kids, indent + 2, parent_name)
323
+
324
+ _walk(tree, 0, "")
325
+
326
+ text = "\n".join([header] + body)
327
+ if max_tokens is not None and count_tokens(text) > max_tokens:
328
+ kept = list(body)
329
+ while kept and count_tokens("\n".join([header] + kept)) > max_tokens:
330
+ kept.pop()
331
+ dropped = len(body) - len(kept)
332
+ text = "\n".join([header] + kept + [f"… {dropped} more symbols"])
333
+ return text
334
+
335
+
336
+ def parse_map(text: str) -> list[dict[str, Any]]:
337
+ """Parse a canonical map back into symbol dicts (name, kind, a, b, params, ret, async)."""
338
+ out = []
339
+ for line in text.splitlines():
340
+ m = SYMBOL_LINE_RE.match(line)
341
+ if not m:
342
+ continue
343
+ out.append({
344
+ "kind": m.group("kind"),
345
+ "name": m.group("name"),
346
+ "params": m.group("params"),
347
+ "ret": m.group("ret"),
348
+ "async": bool(m.group("async")),
349
+ "a": int(m.group("a")),
350
+ "b": int(m.group("b")),
351
+ "depth": len(m.group("indent")) // 2,
352
+ })
353
+ return out