dotscope 1.2.1__tar.gz → 1.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (422) hide show
  1. {dotscope-1.2.1 → dotscope-1.2.2}/.github/workflows/python-publish.yml +1 -1
  2. dotscope-1.2.2/CLAUDE.md +10 -0
  3. {dotscope-1.2.1 → dotscope-1.2.2}/PKG-INFO +1 -1
  4. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/__init__.py +1 -1
  5. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/cli.py +7 -1
  6. {dotscope-1.2.1 → dotscope-1.2.2}/dotscope/formatter.py +13 -1
  7. {dotscope-1.2.1 → dotscope-1.2.2}/dotscope/mcp_server.py +121 -1
  8. {dotscope-1.2.1 → dotscope-1.2.2}/dotscope/models/core.py +4 -0
  9. {dotscope-1.2.1 → dotscope-1.2.2}/dotscope/search/synthesizer.py +17 -7
  10. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/claude_hooks.py +47 -0
  11. dotscope-1.2.2/dotscope/swarm/__init__.py +13 -0
  12. dotscope-1.2.2/dotscope/swarm/merge.py +161 -0
  13. dotscope-1.2.2/dotscope/swarm/partition.py +236 -0
  14. dotscope-1.2.2/dotscope/swarm/trace.py +251 -0
  15. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/pyproject.toml +1 -1
  16. dotscope-1.2.2/tests/test_swarm.py +300 -0
  17. dotscope-1.2.1/.claude/settings.local.json +0 -35
  18. dotscope-1.2.1/.claude/worktrees/hopeful-chatelet/.claude/hooks/pre-commit-check.sh +0 -41
  19. dotscope-1.2.1/.claude/worktrees/hopeful-chatelet/.claude/settings.json +0 -15
  20. dotscope-1.2.1/.claude/worktrees/hopeful-chatelet/.claude/settings.local.json +0 -52
  21. dotscope-1.2.1/.claude/worktrees/hopeful-chatelet/.git +0 -1
  22. dotscope-1.2.1/.claude/worktrees/hopeful-chatelet/README.md +0 -90
  23. dotscope-1.2.1/.claude/worktrees/hopeful-chatelet/dotscope/constants.py +0 -45
  24. dotscope-1.2.1/.claude/worktrees/hopeful-chatelet/dotscope/formatter.py +0 -157
  25. dotscope-1.2.1/.claude/worktrees/hopeful-chatelet/dotscope/generate/engine.py +0 -189
  26. dotscope-1.2.1/.claude/worktrees/hopeful-chatelet/dotscope/ingest.py +0 -972
  27. dotscope-1.2.1/.claude/worktrees/hopeful-chatelet/dotscope/mcp_server.py +0 -1457
  28. dotscope-1.2.1/.claude/worktrees/hopeful-chatelet/dotscope/models/core.py +0 -328
  29. dotscope-1.2.1/.claude/worktrees/hopeful-chatelet/dotscope/passes/graph_builder.py +0 -437
  30. dotscope-1.2.1/.claude/worktrees/hopeful-chatelet/dotscope/scanner.py +0 -246
  31. dotscope-1.2.1/.claude/worktrees/hopeful-chatelet/dotscope/search/retriever.py +0 -368
  32. dotscope-1.2.1/.claude/worktrees/hopeful-chatelet/dotscope/search/synthesizer.py +0 -292
  33. dotscope-1.2.1/.gitignore +0 -10
  34. dotscope-1.2.1/.mcp.json +0 -9
  35. dotscope-1.2.1/.scopes +0 -28
  36. dotscope-1.2.1/AGENT_INSTRUCTIONS.md +0 -129
  37. dotscope-1.2.1/LICENSE +0 -21
  38. dotscope-1.2.1/docs/architecture.md +0 -72
  39. dotscope-1.2.1/docs/cli-reference.md +0 -67
  40. dotscope-1.2.1/docs/how-it-works.md +0 -146
  41. dotscope-1.2.1/docs/mcp-setup.md +0 -255
  42. dotscope-1.2.1/docs/scope-file.md +0 -285
  43. dotscope-1.2.1/dotscope/.scope +0 -82
  44. dotscope-1.2.1/dotscope/__init__.py +0 -3
  45. dotscope-1.2.1/dotscope/absorber.py +0 -390
  46. dotscope-1.2.1/dotscope/assertions.py +0 -127
  47. dotscope-1.2.1/dotscope/ast_analyzer.py +0 -2
  48. dotscope-1.2.1/dotscope/backtest.py +0 -2
  49. dotscope-1.2.1/dotscope/bench.py +0 -141
  50. dotscope-1.2.1/dotscope/budget.py +0 -3
  51. dotscope-1.2.1/dotscope/cache.py +0 -2
  52. dotscope-1.2.1/dotscope/check/__init__.py +0 -1
  53. dotscope-1.2.1/dotscope/check/acknowledge.py +0 -2
  54. dotscope-1.2.1/dotscope/check/checker.py +0 -3
  55. dotscope-1.2.1/dotscope/check/checks/__init__.py +0 -1
  56. dotscope-1.2.1/dotscope/check/checks/antipattern.py +0 -2
  57. dotscope-1.2.1/dotscope/check/checks/boundary.py +0 -2
  58. dotscope-1.2.1/dotscope/check/checks/contracts.py +0 -3
  59. dotscope-1.2.1/dotscope/check/checks/direction.py +0 -2
  60. dotscope-1.2.1/dotscope/check/checks/intent.py +0 -2
  61. dotscope-1.2.1/dotscope/check/checks/stability.py +0 -2
  62. dotscope-1.2.1/dotscope/check/constraints.py +0 -2
  63. dotscope-1.2.1/dotscope/check/models.py +0 -15
  64. dotscope-1.2.1/dotscope/cli.py +0 -1561
  65. dotscope-1.2.1/dotscope/composer.py +0 -229
  66. dotscope-1.2.1/dotscope/context.py +0 -60
  67. dotscope-1.2.1/dotscope/counterfactual.py +0 -180
  68. dotscope-1.2.1/dotscope/debug.py +0 -220
  69. dotscope-1.2.1/dotscope/discovery.py +0 -138
  70. dotscope-1.2.1/dotscope/eval/.scope +0 -27
  71. dotscope-1.2.1/dotscope/eval/__init__.py +0 -18
  72. dotscope-1.2.1/dotscope/eval/bootstrap.py +0 -231
  73. dotscope-1.2.1/dotscope/eval/compare.py +0 -147
  74. dotscope-1.2.1/dotscope/eval/corpus.py +0 -214
  75. dotscope-1.2.1/dotscope/eval/harness.py +0 -310
  76. dotscope-1.2.1/dotscope/eval/replay.py +0 -356
  77. dotscope-1.2.1/dotscope/generate/.scope +0 -24
  78. dotscope-1.2.1/dotscope/generate/__init__.py +0 -1
  79. dotscope-1.2.1/dotscope/generate/atlas.py +0 -341
  80. dotscope-1.2.1/dotscope/generate/contracts.py +0 -296
  81. dotscope-1.2.1/dotscope/generate/models.py +0 -27
  82. dotscope-1.2.1/dotscope/generate/network.py +0 -284
  83. dotscope-1.2.1/dotscope/graph.py +0 -3
  84. dotscope-1.2.1/dotscope/health.py +0 -272
  85. dotscope-1.2.1/dotscope/help.py +0 -218
  86. dotscope-1.2.1/dotscope/history.py +0 -6
  87. dotscope-1.2.1/dotscope/hooks.py +0 -2
  88. dotscope-1.2.1/dotscope/intent.py +0 -614
  89. dotscope-1.2.1/dotscope/lessons.py +0 -223
  90. dotscope-1.2.1/dotscope/matcher.py +0 -104
  91. dotscope-1.2.1/dotscope/merge/.scope +0 -34
  92. dotscope-1.2.1/dotscope/merge/__init__.py +0 -1
  93. dotscope-1.2.1/dotscope/merge/classifier.py +0 -83
  94. dotscope-1.2.1/dotscope/merge/composer.py +0 -210
  95. dotscope-1.2.1/dotscope/merge/differ.py +0 -178
  96. dotscope-1.2.1/dotscope/merge/driver.py +0 -147
  97. dotscope-1.2.1/dotscope/merge/imports.py +0 -114
  98. dotscope-1.2.1/dotscope/merge/models.py +0 -62
  99. dotscope-1.2.1/dotscope/merge/swarm.py +0 -336
  100. dotscope-1.2.1/dotscope/models/.scope +0 -45
  101. dotscope-1.2.1/dotscope/models/__init__.py +0 -8
  102. dotscope-1.2.1/dotscope/models/eval.py +0 -96
  103. dotscope-1.2.1/dotscope/models/history.py +0 -73
  104. dotscope-1.2.1/dotscope/models/intent.py +0 -214
  105. dotscope-1.2.1/dotscope/models/passes.py +0 -58
  106. dotscope-1.2.1/dotscope/models/state.py +0 -251
  107. dotscope-1.2.1/dotscope/models.py +0 -9
  108. dotscope-1.2.1/dotscope/near_miss.py +0 -3
  109. dotscope-1.2.1/dotscope/onboarding.py +0 -2
  110. dotscope-1.2.1/dotscope/parser.py +0 -395
  111. dotscope-1.2.1/dotscope/passes/.scope +0 -105
  112. dotscope-1.2.1/dotscope/passes/__init__.py +0 -1
  113. dotscope-1.2.1/dotscope/passes/ast_analyzer.py +0 -757
  114. dotscope-1.2.1/dotscope/passes/backtest.py +0 -198
  115. dotscope-1.2.1/dotscope/passes/budget_allocator.py +0 -343
  116. dotscope-1.2.1/dotscope/passes/convention_compliance.py +0 -40
  117. dotscope-1.2.1/dotscope/passes/convention_discovery.py +0 -345
  118. dotscope-1.2.1/dotscope/passes/convention_parser.py +0 -235
  119. dotscope-1.2.1/dotscope/passes/hint_generator.py +0 -128
  120. dotscope-1.2.1/dotscope/passes/history_miner.py +0 -336
  121. dotscope-1.2.1/dotscope/passes/incremental.py +0 -221
  122. dotscope-1.2.1/dotscope/passes/lang/__init__.py +0 -38
  123. dotscope-1.2.1/dotscope/passes/lang/_base.py +0 -20
  124. dotscope-1.2.1/dotscope/passes/lang/_treesitter.py +0 -93
  125. dotscope-1.2.1/dotscope/passes/lang/go.py +0 -334
  126. dotscope-1.2.1/dotscope/passes/lang/javascript.py +0 -431
  127. dotscope-1.2.1/dotscope/passes/lazy.py +0 -177
  128. dotscope-1.2.1/dotscope/passes/preflight.py +0 -117
  129. dotscope-1.2.1/dotscope/passes/semantic_diff.py +0 -160
  130. dotscope-1.2.1/dotscope/passes/sentinel/__init__.py +0 -1
  131. dotscope-1.2.1/dotscope/passes/sentinel/acknowledge.py +0 -222
  132. dotscope-1.2.1/dotscope/passes/sentinel/checker.py +0 -428
  133. dotscope-1.2.1/dotscope/passes/sentinel/checks/__init__.py +0 -1
  134. dotscope-1.2.1/dotscope/passes/sentinel/checks/antipattern.py +0 -84
  135. dotscope-1.2.1/dotscope/passes/sentinel/checks/boundary.py +0 -46
  136. dotscope-1.2.1/dotscope/passes/sentinel/checks/contracts.py +0 -148
  137. dotscope-1.2.1/dotscope/passes/sentinel/checks/convention.py +0 -54
  138. dotscope-1.2.1/dotscope/passes/sentinel/checks/direction.py +0 -71
  139. dotscope-1.2.1/dotscope/passes/sentinel/checks/intent.py +0 -207
  140. dotscope-1.2.1/dotscope/passes/sentinel/checks/network.py +0 -91
  141. dotscope-1.2.1/dotscope/passes/sentinel/checks/spatial.py +0 -115
  142. dotscope-1.2.1/dotscope/passes/sentinel/checks/stability.py +0 -66
  143. dotscope-1.2.1/dotscope/passes/sentinel/checks/voice.py +0 -108
  144. dotscope-1.2.1/dotscope/passes/sentinel/constraints.py +0 -472
  145. dotscope-1.2.1/dotscope/passes/sentinel/line_filter.py +0 -88
  146. dotscope-1.2.1/dotscope/passes/sentinel/models.py +0 -15
  147. dotscope-1.2.1/dotscope/passes/spatial_autofix.py +0 -206
  148. dotscope-1.2.1/dotscope/passes/virtual.py +0 -247
  149. dotscope-1.2.1/dotscope/passes/voice.py +0 -161
  150. dotscope-1.2.1/dotscope/passes/voice_defaults.py +0 -68
  151. dotscope-1.2.1/dotscope/passes/voice_discovery.py +0 -245
  152. dotscope-1.2.1/dotscope/paths.py +0 -83
  153. dotscope-1.2.1/dotscope/progress.py +0 -44
  154. dotscope-1.2.1/dotscope/refresh.py +0 -543
  155. dotscope-1.2.1/dotscope/regression.py +0 -147
  156. dotscope-1.2.1/dotscope/resolver.py +0 -198
  157. dotscope-1.2.1/dotscope/runtime_overlay.py +0 -403
  158. dotscope-1.2.1/dotscope/search/.scope +0 -29
  159. dotscope-1.2.1/dotscope/search/__init__.py +0 -1
  160. dotscope-1.2.1/dotscope/search/chunker.py +0 -343
  161. dotscope-1.2.1/dotscope/search/expander.py +0 -129
  162. dotscope-1.2.1/dotscope/search/flattener.py +0 -187
  163. dotscope-1.2.1/dotscope/search/models.py +0 -70
  164. dotscope-1.2.1/dotscope/search/observation.py +0 -279
  165. dotscope-1.2.1/dotscope/search/reranker.py +0 -85
  166. dotscope-1.2.1/dotscope/sessions.py +0 -2
  167. dotscope-1.2.1/dotscope/storage/.scope +0 -64
  168. dotscope-1.2.1/dotscope/storage/__init__.py +0 -1
  169. dotscope-1.2.1/dotscope/storage/cache.py +0 -177
  170. dotscope-1.2.1/dotscope/storage/claude_hooks.py +0 -119
  171. dotscope-1.2.1/dotscope/storage/git_hooks.py +0 -500
  172. dotscope-1.2.1/dotscope/storage/incremental_state.py +0 -124
  173. dotscope-1.2.1/dotscope/storage/mcp_config.py +0 -98
  174. dotscope-1.2.1/dotscope/storage/near_miss.py +0 -183
  175. dotscope-1.2.1/dotscope/storage/onboarding.py +0 -150
  176. dotscope-1.2.1/dotscope/storage/session_manager.py +0 -195
  177. dotscope-1.2.1/dotscope/storage/swarm_state.py +0 -144
  178. dotscope-1.2.1/dotscope/storage/timing.py +0 -84
  179. dotscope-1.2.1/dotscope/textio.py +0 -122
  180. dotscope-1.2.1/dotscope/timing.py +0 -2
  181. dotscope-1.2.1/dotscope/tokens.py +0 -53
  182. dotscope-1.2.1/dotscope/utility.py +0 -123
  183. dotscope-1.2.1/dotscope/virtual.py +0 -3
  184. dotscope-1.2.1/dotscope/visibility.py +0 -687
  185. dotscope-1.2.1/logo.png +0 -0
  186. dotscope-1.2.1/pyproject.toml +0 -45
  187. dotscope-1.2.1/tests/.scope +0 -29
  188. dotscope-1.2.1/tests/__init__.py +0 -0
  189. dotscope-1.2.1/tests/conftest.py +0 -152
  190. dotscope-1.2.1/tests/test_absorber.py +0 -91
  191. dotscope-1.2.1/tests/test_ast_analyzer.py +0 -168
  192. dotscope-1.2.1/tests/test_backtest.py +0 -114
  193. dotscope-1.2.1/tests/test_budget.py +0 -124
  194. dotscope-1.2.1/tests/test_canonical_snippet.py +0 -70
  195. dotscope-1.2.1/tests/test_cli.py +0 -122
  196. dotscope-1.2.1/tests/test_composer.py +0 -125
  197. dotscope-1.2.1/tests/test_context.py +0 -52
  198. dotscope-1.2.1/tests/test_enforcement.py +0 -423
  199. dotscope-1.2.1/tests/test_eval_harness.py +0 -376
  200. dotscope-1.2.1/tests/test_experience.py +0 -237
  201. dotscope-1.2.1/tests/test_graph.py +0 -78
  202. dotscope-1.2.1/tests/test_health.py +0 -142
  203. dotscope-1.2.1/tests/test_history.py +0 -71
  204. dotscope-1.2.1/tests/test_ingest.py +0 -319
  205. dotscope-1.2.1/tests/test_lessons.py +0 -91
  206. dotscope-1.2.1/tests/test_line_filter.py +0 -67
  207. dotscope-1.2.1/tests/test_loop.py +0 -384
  208. dotscope-1.2.1/tests/test_matcher.py +0 -47
  209. dotscope-1.2.1/tests/test_near_miss.py +0 -161
  210. dotscope-1.2.1/tests/test_parser.py +0 -180
  211. dotscope-1.2.1/tests/test_refresh.py +0 -251
  212. dotscope-1.2.1/tests/test_resolver.py +0 -100
  213. dotscope-1.2.1/tests/test_rigor.py +0 -223
  214. dotscope-1.2.1/tests/test_routing.py +0 -207
  215. dotscope-1.2.1/tests/test_scanner.py +0 -54
  216. dotscope-1.2.1/tests/test_sessions.py +0 -122
  217. dotscope-1.2.1/tests/test_textio.py +0 -85
  218. dotscope-1.2.1/tests/test_treesitter.py +0 -359
  219. dotscope-1.2.1/tests/test_utility.py +0 -48
  220. dotscope-1.2.1/tests/test_virtual.py +0 -95
  221. dotscope-1.2.1/tests/test_visibility.py +0 -417
  222. dotscope-1.2.1/tests/test_voice_check.py +0 -123
  223. dotscope-1.2.1/tests/test_voice_discovery.py +0 -143
  224. dotscope-1.2.1/uv.lock +0 -2375
  225. {dotscope-1.2.1 → dotscope-1.2.2}/.claude/hooks/pre-commit-check.sh +0 -0
  226. {dotscope-1.2.1 → dotscope-1.2.2}/.claude/settings.json +0 -0
  227. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/.gitignore +0 -0
  228. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/.scopes +0 -0
  229. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/AGENT_INSTRUCTIONS.md +0 -0
  230. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/LICENSE +0 -0
  231. {dotscope-1.2.1 → dotscope-1.2.2}/README.md +0 -0
  232. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/docs/architecture.md +0 -0
  233. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/docs/cli-reference.md +0 -0
  234. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/docs/how-it-works.md +0 -0
  235. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/docs/mcp-setup.md +0 -0
  236. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/docs/scope-file.md +0 -0
  237. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/.scope +0 -0
  238. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/absorber.py +0 -0
  239. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/assertions.py +0 -0
  240. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/ast_analyzer.py +0 -0
  241. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/backtest.py +0 -0
  242. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/bench.py +0 -0
  243. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/budget.py +0 -0
  244. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/cache.py +0 -0
  245. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/__init__.py +0 -0
  246. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/acknowledge.py +0 -0
  247. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/checker.py +0 -0
  248. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/checks/__init__.py +0 -0
  249. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/checks/antipattern.py +0 -0
  250. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/checks/boundary.py +0 -0
  251. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/checks/contracts.py +0 -0
  252. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/checks/direction.py +0 -0
  253. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/checks/intent.py +0 -0
  254. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/checks/stability.py +0 -0
  255. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/constraints.py +0 -0
  256. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/models.py +0 -0
  257. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/composer.py +0 -0
  258. {dotscope-1.2.1 → dotscope-1.2.2}/dotscope/constants.py +0 -0
  259. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/context.py +0 -0
  260. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/counterfactual.py +0 -0
  261. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/debug.py +0 -0
  262. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/discovery.py +0 -0
  263. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/eval/.scope +0 -0
  264. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/eval/__init__.py +0 -0
  265. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/eval/bootstrap.py +0 -0
  266. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/eval/compare.py +0 -0
  267. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/eval/corpus.py +0 -0
  268. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/eval/harness.py +0 -0
  269. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/eval/replay.py +0 -0
  270. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/generate/.scope +0 -0
  271. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/generate/__init__.py +0 -0
  272. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/generate/atlas.py +0 -0
  273. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/generate/contracts.py +0 -0
  274. {dotscope-1.2.1 → dotscope-1.2.2}/dotscope/generate/engine.py +0 -0
  275. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/generate/models.py +0 -0
  276. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/generate/network.py +0 -0
  277. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/graph.py +0 -0
  278. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/health.py +0 -0
  279. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/help.py +0 -0
  280. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/history.py +0 -0
  281. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/hooks.py +0 -0
  282. {dotscope-1.2.1 → dotscope-1.2.2}/dotscope/ignore.py +0 -0
  283. {dotscope-1.2.1 → dotscope-1.2.2}/dotscope/ingest.py +0 -0
  284. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/intent.py +0 -0
  285. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/lessons.py +0 -0
  286. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/matcher.py +0 -0
  287. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/merge/.scope +0 -0
  288. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/merge/__init__.py +0 -0
  289. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/merge/classifier.py +0 -0
  290. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/merge/composer.py +0 -0
  291. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/merge/differ.py +0 -0
  292. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/merge/driver.py +0 -0
  293. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/merge/imports.py +0 -0
  294. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/merge/models.py +0 -0
  295. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/merge/swarm.py +0 -0
  296. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/models/.scope +0 -0
  297. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/models/__init__.py +0 -0
  298. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/models/eval.py +0 -0
  299. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/models/history.py +0 -0
  300. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/models/intent.py +0 -0
  301. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/models/passes.py +0 -0
  302. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/models/state.py +0 -0
  303. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/models.py +0 -0
  304. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/near_miss.py +0 -0
  305. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/onboarding.py +0 -0
  306. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/parser.py +0 -0
  307. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/.scope +0 -0
  308. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/__init__.py +0 -0
  309. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/ast_analyzer.py +0 -0
  310. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/backtest.py +0 -0
  311. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/budget_allocator.py +0 -0
  312. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/convention_compliance.py +0 -0
  313. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/convention_discovery.py +0 -0
  314. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/convention_parser.py +0 -0
  315. {dotscope-1.2.1 → dotscope-1.2.2}/dotscope/passes/graph_builder.py +0 -0
  316. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/hint_generator.py +0 -0
  317. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/history_miner.py +0 -0
  318. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/incremental.py +0 -0
  319. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/lang/__init__.py +0 -0
  320. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/lang/_base.py +0 -0
  321. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/lang/_treesitter.py +0 -0
  322. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/lang/go.py +0 -0
  323. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/lang/javascript.py +0 -0
  324. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/lazy.py +0 -0
  325. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/preflight.py +0 -0
  326. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/semantic_diff.py +0 -0
  327. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/__init__.py +0 -0
  328. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/acknowledge.py +0 -0
  329. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checker.py +0 -0
  330. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/__init__.py +0 -0
  331. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/antipattern.py +0 -0
  332. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/boundary.py +0 -0
  333. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/contracts.py +0 -0
  334. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/convention.py +0 -0
  335. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/direction.py +0 -0
  336. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/intent.py +0 -0
  337. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/network.py +0 -0
  338. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/spatial.py +0 -0
  339. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/stability.py +0 -0
  340. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/voice.py +0 -0
  341. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/constraints.py +0 -0
  342. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/line_filter.py +0 -0
  343. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/models.py +0 -0
  344. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/spatial_autofix.py +0 -0
  345. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/virtual.py +0 -0
  346. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/voice.py +0 -0
  347. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/voice_defaults.py +0 -0
  348. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/voice_discovery.py +0 -0
  349. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/paths.py +0 -0
  350. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/progress.py +0 -0
  351. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/refresh.py +0 -0
  352. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/regression.py +0 -0
  353. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/resolver.py +0 -0
  354. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/runtime_overlay.py +0 -0
  355. {dotscope-1.2.1 → dotscope-1.2.2}/dotscope/scanner.py +0 -0
  356. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/search/.scope +0 -0
  357. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/search/__init__.py +0 -0
  358. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/search/chunker.py +0 -0
  359. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/search/expander.py +0 -0
  360. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/search/flattener.py +0 -0
  361. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/search/models.py +0 -0
  362. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/search/observation.py +0 -0
  363. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/search/reranker.py +0 -0
  364. {dotscope-1.2.1 → dotscope-1.2.2}/dotscope/search/retriever.py +0 -0
  365. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/sessions.py +0 -0
  366. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/.scope +0 -0
  367. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/__init__.py +0 -0
  368. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/cache.py +0 -0
  369. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/git_hooks.py +0 -0
  370. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/incremental_state.py +0 -0
  371. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/mcp_config.py +0 -0
  372. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/near_miss.py +0 -0
  373. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/onboarding.py +0 -0
  374. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/session_manager.py +0 -0
  375. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/swarm_state.py +0 -0
  376. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/timing.py +0 -0
  377. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/textio.py +0 -0
  378. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/timing.py +0 -0
  379. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/tokens.py +0 -0
  380. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/utility.py +0 -0
  381. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/virtual.py +0 -0
  382. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/visibility.py +0 -0
  383. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/logo.png +0 -0
  384. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/.scope +0 -0
  385. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/__init__.py +0 -0
  386. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/conftest.py +0 -0
  387. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_absorber.py +0 -0
  388. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_ast_analyzer.py +0 -0
  389. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_backtest.py +0 -0
  390. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_budget.py +0 -0
  391. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_canonical_snippet.py +0 -0
  392. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_cli.py +0 -0
  393. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_composer.py +0 -0
  394. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_context.py +0 -0
  395. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_enforcement.py +0 -0
  396. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_eval_harness.py +0 -0
  397. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_experience.py +0 -0
  398. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_graph.py +0 -0
  399. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_health.py +0 -0
  400. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_history.py +0 -0
  401. {dotscope-1.2.1 → dotscope-1.2.2}/tests/test_ignore.py +0 -0
  402. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_ingest.py +0 -0
  403. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_lessons.py +0 -0
  404. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_line_filter.py +0 -0
  405. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_loop.py +0 -0
  406. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_matcher.py +0 -0
  407. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_near_miss.py +0 -0
  408. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_parser.py +0 -0
  409. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_refresh.py +0 -0
  410. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_resolver.py +0 -0
  411. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_rigor.py +0 -0
  412. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_routing.py +0 -0
  413. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_scanner.py +0 -0
  414. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_sessions.py +0 -0
  415. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_textio.py +0 -0
  416. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_treesitter.py +0 -0
  417. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_utility.py +0 -0
  418. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_virtual.py +0 -0
  419. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_visibility.py +0 -0
  420. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_voice_check.py +0 -0
  421. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_voice_discovery.py +0 -0
  422. {dotscope-1.2.1/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/uv.lock +0 -0
@@ -49,7 +49,7 @@ jobs:
49
49
  # Dedicated environments with protections for publishing are strongly recommended.
50
50
  # For more information, see: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-protection-rules
51
51
  environment:
52
- name: pypi
52
+ name: dotscope environment
53
53
  # OPTIONAL: uncomment and update to include your PyPI project URL in the deployment status:
54
54
  # url: https://pypi.org/p/YOURPROJECT
55
55
  #
@@ -0,0 +1,10 @@
1
+ # CLAUDE.md
2
+
3
+ This repo uses dotscope. Before touching code:
4
+
5
+ 1. `codebase_search("your task description")` — not manual file reads
6
+ 2. `dotscope_check` before every commit
7
+ 3. If check returns HOLDs, fix them before committing
8
+
9
+ dotscope provides: dependency graph, implicit contracts, conventions,
10
+ and file locks. Use its tools instead of guessing.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dotscope
3
- Version: 1.2.1
3
+ Version: 1.2.2
4
4
  Summary: Agents see files. You see architecture. dotscope gives agents the architecture.
5
5
  Author: Supremum
6
6
  License-Expression: MIT
@@ -1,3 +1,3 @@
1
1
  """dotscope — Directory-scoped context boundaries for AI coding agents."""
2
2
 
3
- __version__ = "0.1.0"
3
+ __version__ = "1.2.2"
@@ -354,12 +354,18 @@ def _cmd_init(args):
354
354
  except Exception as e:
355
355
  print(f"dotscope: MCP config failed: {e}", file=sys.stderr)
356
356
 
357
- # 4. Write AGENT_INSTRUCTIONS.md
357
+ # 4. Write AGENT_INSTRUCTIONS.md + CLAUDE.md
358
358
  try:
359
359
  _write_agent_instructions(root, quiet)
360
360
  except Exception as e:
361
361
  if not quiet:
362
362
  print(f"dotscope: agent instructions failed: {e}", file=sys.stderr)
363
+ try:
364
+ from .storage.claude_hooks import write_claude_md
365
+ write_claude_md(root)
366
+ except Exception as e:
367
+ if not quiet:
368
+ print(f"dotscope: CLAUDE.md failed: {e}", file=sys.stderr)
363
369
 
364
370
  # 5. Backtest as counterfactual demo
365
371
  if not quiet:
@@ -57,7 +57,7 @@ def _format_plain(resolved: ResolvedScope, root: Optional[str], show_tokens: boo
57
57
 
58
58
 
59
59
  def _format_json(resolved: ResolvedScope, root: Optional[str]) -> str:
60
- """JSON format: full object."""
60
+ """JSON format: full object with all compiled retrieval fields."""
61
61
  data = {
62
62
  "files": [make_relative(f, root) for f in resolved.files],
63
63
  "context": resolved.context,
@@ -69,6 +69,18 @@ def _format_json(resolved: ResolvedScope, root: Optional[str]) -> str:
69
69
  if resolved.excluded_files:
70
70
  data["excluded_count"] = len(resolved.excluded_files)
71
71
 
72
+ # Compiled retrieval fields (populated by codebase_search)
73
+ if resolved.flattened_abstractions:
74
+ data["flattened_abstractions"] = resolved.flattened_abstractions
75
+ if resolved.constraints:
76
+ data["constraints"] = resolved.constraints
77
+ if resolved.routing:
78
+ data["routing"] = resolved.routing
79
+ if resolved.action_hints:
80
+ data["action_hints"] = resolved.action_hints
81
+ if resolved.retrieval_metadata:
82
+ data["retrieval_metadata"] = resolved.retrieval_metadata
83
+
72
84
  return json.dumps(data, indent=2)
73
85
 
74
86
 
@@ -1256,7 +1256,20 @@ def main():
1256
1256
  task_type=task_type,
1257
1257
  no_observe=no_observe or False,
1258
1258
  )
1259
- return format_resolved(resolved, fmt="json", root=root)
1259
+ result = json.loads(format_resolved(resolved, fmt="json", root=root))
1260
+
1261
+ # Add next_steps based on what was found
1262
+ next_steps = []
1263
+ if resolved.constraints:
1264
+ next_steps.append("Run dotscope_check before committing.")
1265
+ if any(c.get("severity") == "GUARD" for c in resolved.constraints):
1266
+ next_steps.append("GUARD-level constraints found. These will block your commit.")
1267
+ if result.get("retrieval_metadata", {}).get("index_freshness") == "stale":
1268
+ next_steps.append("Index is stale. Run dotscope ingest to refresh.")
1269
+ if next_steps:
1270
+ result["next_steps"] = next_steps
1271
+
1272
+ return json.dumps(result, indent=2)
1260
1273
 
1261
1274
  # -------------------------------------------------------------------
1262
1275
  # Swarm Lock MCP tools
@@ -1453,5 +1466,112 @@ def _route_by_imports(planned_imports: list, root: str) -> Optional[dict]:
1453
1466
  }
1454
1467
 
1455
1468
 
1469
+ # -------------------------------------------------------------------
1470
+ # Swarm helpers
1471
+ # -------------------------------------------------------------------
1472
+
1473
+ def _find_root():
1474
+ from .discovery import find_repo_root
1475
+ return find_repo_root() or "."
1476
+
1477
+ def _get_graph(root):
1478
+ from .passes.graph_builder import build_graph
1479
+ return build_graph(root)
1480
+
1481
+ def _load_index(root):
1482
+ from .discovery import load_index
1483
+ return load_index(root)
1484
+
1485
+ def _load_invariants(root):
1486
+ inv_path = os.path.join(root, ".dotscope", "invariants.json")
1487
+ if os.path.isfile(inv_path):
1488
+ try:
1489
+ with open(inv_path, "r", encoding="utf-8") as f:
1490
+ return json.load(f)
1491
+ except Exception:
1492
+ pass
1493
+ return {}
1494
+
1495
+ # -------------------------------------------------------------------
1496
+ # Swarm Intelligence MCP tools
1497
+ # -------------------------------------------------------------------
1498
+
1499
+ @mcp.tool()
1500
+ def partition_search_space(
1501
+ intent: str,
1502
+ n_partitions: int = 3,
1503
+ ) -> dict:
1504
+ """Divide an exploratory task into non-overlapping starting points.
1505
+
1506
+ Uses semantic search to find relevant files, then graph analysis
1507
+ to cleave them into decoupled partitions. Scouts assigned to
1508
+ different partitions are guaranteed to start in structurally
1509
+ independent domains.
1510
+
1511
+ Args:
1512
+ intent: Natural language description of what to investigate
1513
+ n_partitions: Number of parallel scouts to support (2-10)
1514
+
1515
+ May return fewer partitions than requested if search results
1516
+ are highly localized. Check len(partitions), not n_partitions.
1517
+ """
1518
+ from .swarm.partition import partition_search_space as _partition
1519
+ root = _root or _find_root()
1520
+ graph = _get_graph(root)
1521
+ index = _load_index(root)
1522
+ invariants = _load_invariants(root)
1523
+ return _partition(intent, n_partitions, root, graph, index, invariants)
1524
+
1525
+ @mcp.tool()
1526
+ def resolve_trace(
1527
+ entry_file: str,
1528
+ max_depth: int = 3,
1529
+ focus: str = "",
1530
+ ) -> dict:
1531
+ """Resolve context along a specific execution path.
1532
+
1533
+ Follows imports from entry_file up to max_depth. Returns unified
1534
+ context covering all scopes crossed, deduplicated, with only the
1535
+ constraints relevant to files in the trace.
1536
+
1537
+ Args:
1538
+ entry_file: Starting point for the trace
1539
+ max_depth: How many import levels to follow (default 3, max 10)
1540
+ focus: Optional keyword to filter context relevance
1541
+ (e.g., "memory" to prioritize memory-related context)
1542
+ """
1543
+ from .swarm.trace import resolve_trace as _trace
1544
+ root = _root or _find_root()
1545
+ graph = _get_graph(root)
1546
+ index = _load_index(root)
1547
+ invariants = _load_invariants(root)
1548
+ return _trace(
1549
+ entry_file, max_depth, focus or None,
1550
+ root, graph, index, invariants,
1551
+ )
1552
+
1553
+ @mcp.tool()
1554
+ def merge_scout_findings(
1555
+ scout_reports: list,
1556
+ ) -> dict:
1557
+ """Cross-reference scout findings against codebase physics.
1558
+
1559
+ Takes raw scout reports (flagged files + notes) and returns
1560
+ structurally validated connections, convergence points,
1561
+ and a unified blast radius.
1562
+
1563
+ Each scout report should contain:
1564
+ scout_id: int
1565
+ flagged_files: List[str]
1566
+ notes: str (natural language findings)
1567
+ confidence: float (0-1, scout's self-assessed confidence)
1568
+ """
1569
+ from .swarm.merge import merge_scout_findings as _merge
1570
+ root = _root or _find_root()
1571
+ graph = _get_graph(root)
1572
+ invariants = _load_invariants(root)
1573
+ return _merge(scout_reports, root, graph, invariants)
1574
+
1575
+
1456
1576
  if __name__ == "__main__":
1457
1577
  main()
@@ -94,6 +94,10 @@ class ResolvedScope:
94
94
  # Compiled Retrieval extensions (populated by codebase_search only)
95
95
  flattened_abstractions: Dict[str, dict] = field(default_factory=dict)
96
96
  retrieval_metadata: Optional[dict] = None
97
+ # Structured constraints (contracts, anti-patterns, conventions, intents)
98
+ constraints: List[dict] = field(default_factory=list)
99
+ # Routing guidance (convention blueprints, voice rules)
100
+ routing: List[dict] = field(default_factory=list)
97
101
  # Action hints: imperative directives derived from constraints and locks
98
102
  action_hints: List[str] = field(default_factory=list)
99
103
 
@@ -131,23 +131,31 @@ def synthesize_search(
131
131
  "scope_crossing": ab.scope_crossing,
132
132
  }
133
133
 
134
- # Build constraints
135
- constraints_text = ""
134
+ # Build constraints (keep structured for JSON response)
135
+ structured_constraints = []
136
136
  try:
137
137
  from ..passes.sentinel.constraints import build_constraints
138
- constraints = build_constraints(root, unique_files, query)
139
- if constraints:
138
+ raw_constraints = build_constraints(root, unique_files, query)
139
+ if raw_constraints:
140
+ structured_constraints = raw_constraints
140
141
  constraint_lines = []
141
- for c in constraints:
142
+ for c in raw_constraints:
142
143
  msg = c.get("message", "")
143
144
  if msg:
144
145
  constraint_lines.append(f"- {msg}")
145
146
  constraints_text = "\n".join(constraint_lines)
147
+ if constraints_text:
148
+ context_parts.append(f"\n## Constraints\n{constraints_text}")
146
149
  except Exception:
147
150
  pass
148
151
 
149
- if constraints_text:
150
- context_parts.append(f"\n## Constraints\n{constraints_text}")
152
+ # Build routing guidance
153
+ structured_routing = []
154
+ try:
155
+ from ..passes.sentinel.constraints import build_routing_guidance
156
+ structured_routing = build_routing_guidance(root, unique_files, query) or []
157
+ except Exception:
158
+ pass
151
159
 
152
160
  # Budget allocation: inside-out truncation
153
161
  from ..tokens import estimate_tokens
@@ -166,6 +174,8 @@ def synthesize_search(
166
174
  context="\n\n".join(context_parts) if context_parts else "",
167
175
  token_estimate=used,
168
176
  truncated=len(budget_files) < len(unique_files),
177
+ constraints=structured_constraints,
178
+ routing=structured_routing,
169
179
  flattened_abstractions=flat_abstractions,
170
180
  retrieval_metadata={
171
181
  "query": query,
@@ -117,3 +117,50 @@ def install_claude_hook(repo_root: str) -> str:
117
117
  f.write("\n")
118
118
 
119
119
  return f"Claude Code hook installed: {script_path}"
120
+
121
+
122
+ _CLAUDE_MD_CONTENT = """\
123
+ # CLAUDE.md
124
+
125
+ This repo uses dotscope. Before touching code:
126
+
127
+ 1. `codebase_search("your task description")` — not manual file reads
128
+ 2. `dotscope_check` before every commit
129
+ 3. If check returns HOLDs, fix them before committing
130
+
131
+ dotscope provides: dependency graph, implicit contracts, conventions,
132
+ and file locks. Use its tools instead of guessing.
133
+ """
134
+
135
+ _CLAUDE_MD_SECTION = """
136
+ ## dotscope
137
+
138
+ This repo uses dotscope. Before touching code:
139
+
140
+ 1. `codebase_search("your task description")` — not manual file reads
141
+ 2. `dotscope_check` before every commit
142
+ 3. If check returns HOLDs, fix them before committing
143
+ """
144
+
145
+
146
+ def write_claude_md(repo_root: str) -> str:
147
+ """Write CLAUDE.md for automatic agent briefing.
148
+
149
+ If CLAUDE.md doesn't exist, creates it with dotscope instructions.
150
+ If it exists but has no dotscope section, appends one.
151
+ If it already has a dotscope section, does nothing.
152
+ """
153
+ claude_md_path = os.path.join(repo_root, "CLAUDE.md")
154
+
155
+ if not os.path.exists(claude_md_path):
156
+ with open(claude_md_path, "w", encoding="utf-8") as f:
157
+ f.write(_CLAUDE_MD_CONTENT)
158
+ return f"Created {claude_md_path}"
159
+
160
+ existing = open(claude_md_path, "r", encoding="utf-8").read()
161
+ if "dotscope" in existing.lower() and "codebase_search" in existing:
162
+ return "CLAUDE.md already has dotscope instructions"
163
+
164
+ with open(claude_md_path, "a", encoding="utf-8") as f:
165
+ f.write(_CLAUDE_MD_SECTION)
166
+ return f"Appended dotscope section to {claude_md_path}"
@@ -0,0 +1,13 @@
1
+ """Swarm-ready primitives for parallel agent coordination.
2
+
3
+ Three read-only tools that make dotscope the sensory layer for agent swarms:
4
+ partition_search_space — divide work into non-overlapping starting points
5
+ resolve_trace — follow an execution path with focused context
6
+ merge_scout_findings — cross-reference parallel findings against codebase structure
7
+ """
8
+
9
+ from .partition import partition_search_space
10
+ from .trace import resolve_trace
11
+ from .merge import merge_scout_findings
12
+
13
+ __all__ = ["partition_search_space", "resolve_trace", "merge_scout_findings"]
@@ -0,0 +1,161 @@
1
+ """Cross-reference scout findings against codebase structure."""
2
+
3
+ from collections import defaultdict
4
+ from typing import Dict, List, Set
5
+
6
+
7
+ def merge_scout_findings(
8
+ scout_reports: List[dict],
9
+ repo_root: str,
10
+ graph,
11
+ invariants: dict,
12
+ ) -> dict:
13
+ """Merge parallel scout findings using codebase structure.
14
+
15
+ Deterministic structural analysis: convergence detection, hidden
16
+ connection discovery via NPMI, blast radius expansion, and
17
+ scout agreement tiers. No LLM calls.
18
+ """
19
+ # Collect all flagged files with attribution
20
+ file_scouts: Dict[str, List[int]] = defaultdict(list)
21
+ all_files: Set[str] = set()
22
+
23
+ for report in scout_reports:
24
+ scout_id = report.get("scout_id", 0)
25
+ for filepath in report.get("flagged_files", []):
26
+ file_scouts[filepath].append(scout_id)
27
+ all_files.add(filepath)
28
+
29
+ n_scouts = len(scout_reports)
30
+
31
+ # 1. Convergence points: files flagged by 2+ scouts
32
+ convergence_points = []
33
+ for filepath, scouts in file_scouts.items():
34
+ if len(scouts) >= 2:
35
+ convergence_points.append({
36
+ "file": filepath,
37
+ "flagged_by": sorted(scouts),
38
+ "significance": (
39
+ f"{len(scouts)} independent traces converged on this file"
40
+ ),
41
+ })
42
+
43
+ convergence_points.sort(key=lambda c: -len(c["flagged_by"]))
44
+
45
+ # 2. Hidden connections: files from different scouts that have
46
+ # structural relationships (contracts, dependencies)
47
+ hidden_connections = []
48
+ scout_file_groups: Dict[int, Set[str]] = defaultdict(set)
49
+ for report in scout_reports:
50
+ scout_id = report.get("scout_id", 0)
51
+ for filepath in report.get("flagged_files", []):
52
+ scout_file_groups[scout_id].add(filepath)
53
+
54
+ # Check NPMI contracts between scout groups
55
+ contracts = invariants.get("contracts", [])
56
+ seen_connections = set()
57
+ for contract in contracts:
58
+ trigger = contract.get("trigger_file", "")
59
+ coupled = contract.get("coupled_file", "")
60
+ confidence = contract.get("confidence", 0)
61
+
62
+ if confidence < 0.5:
63
+ continue
64
+
65
+ trigger_scouts = set(file_scouts.get(trigger, []))
66
+ coupled_scouts = set(file_scouts.get(coupled, []))
67
+
68
+ if (trigger in all_files and coupled in all_files
69
+ and trigger_scouts != coupled_scouts
70
+ and not trigger_scouts & coupled_scouts):
71
+ key = tuple(sorted([trigger, coupled]))
72
+ if key not in seen_connections:
73
+ seen_connections.add(key)
74
+ hidden_connections.append({
75
+ "file_a": trigger,
76
+ "file_b": coupled,
77
+ "relation": "implicit_contract",
78
+ "confidence": confidence,
79
+ "note": (
80
+ f"Co-change rate {confidence:.0%}"
81
+ f" -- flagged by different scouts"
82
+ ),
83
+ })
84
+
85
+ # Check graph edges between scout groups
86
+ graph_files = graph.files if hasattr(graph, 'files') else {}
87
+ for file_a in all_files:
88
+ node = graph_files.get(file_a)
89
+ if not node:
90
+ continue
91
+ imports = getattr(node, 'imports', []) or []
92
+ for dep in imports:
93
+ if dep in all_files:
94
+ scouts_a = set(file_scouts.get(file_a, []))
95
+ scouts_b = set(file_scouts.get(dep, []))
96
+ if scouts_a and scouts_b and not scouts_a & scouts_b:
97
+ key = tuple(sorted([file_a, dep]))
98
+ if key not in seen_connections:
99
+ seen_connections.add(key)
100
+ hidden_connections.append({
101
+ "file_a": file_a,
102
+ "file_b": dep,
103
+ "relation": "direct_dependency",
104
+ "confidence": 1.0,
105
+ "note": f"{file_a} imports {dep}",
106
+ })
107
+
108
+ # 3. Blast radius: expand via NPMI to find strongly coupled files
109
+ proposed_blast_radius = set(all_files)
110
+ npmi_index = invariants.get("npmi_index", {})
111
+ for filepath in list(all_files):
112
+ coupled_files = npmi_index.get(filepath, {})
113
+ for partner, score in coupled_files.items():
114
+ if score >= 0.8 and partner not in all_files:
115
+ proposed_blast_radius.add(partner)
116
+
117
+ # 4. Confidence tiers
118
+ blast_by_confidence: Dict[str, List[str]] = {
119
+ "high": [], "medium": [], "low": [],
120
+ }
121
+ for filepath in proposed_blast_radius:
122
+ scouts = file_scouts.get(filepath, [])
123
+ if len(scouts) >= 2:
124
+ blast_by_confidence["high"].append(filepath)
125
+ elif len(scouts) == 1:
126
+ scout_confidence = next(
127
+ (r.get("confidence", 0.5)
128
+ for r in scout_reports
129
+ if r.get("scout_id") in scouts),
130
+ 0.5,
131
+ )
132
+ if scout_confidence >= 0.7:
133
+ blast_by_confidence["medium"].append(filepath)
134
+ else:
135
+ blast_by_confidence["low"].append(filepath)
136
+ else:
137
+ # NPMI-expanded files (not flagged by any scout)
138
+ blast_by_confidence["low"].append(filepath)
139
+
140
+ for tier in blast_by_confidence.values():
141
+ tier.sort()
142
+
143
+ # 5. Scout agreement
144
+ unanimous = sorted(f for f, s in file_scouts.items() if len(s) == n_scouts and n_scouts > 1)
145
+ majority = sorted(
146
+ f for f, s in file_scouts.items()
147
+ if n_scouts > 1 and len(s) > n_scouts / 2 and len(s) < n_scouts
148
+ )
149
+ single = sorted(f for f, s in file_scouts.items() if len(s) == 1)
150
+
151
+ return {
152
+ "convergence_points": convergence_points,
153
+ "hidden_connections": hidden_connections,
154
+ "proposed_blast_radius": sorted(proposed_blast_radius),
155
+ "blast_radius_by_confidence": blast_by_confidence,
156
+ "scout_agreement": {
157
+ "unanimous": unanimous,
158
+ "majority": majority,
159
+ "single": single,
160
+ },
161
+ }