dotscope 1.2.0__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.
- {dotscope-1.2.0 → dotscope-1.2.2}/.github/workflows/python-publish.yml +1 -1
- dotscope-1.2.2/CLAUDE.md +10 -0
- dotscope-1.2.2/PKG-INFO +83 -0
- dotscope-1.2.2/README.md +46 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/__init__.py +1 -1
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/cli.py +7 -1
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/constants.py +26 -2
- {dotscope-1.2.0 → dotscope-1.2.2}/dotscope/formatter.py +13 -1
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/generate/engine.py +2 -2
- dotscope-1.2.2/dotscope/ignore.py +59 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/ingest.py +51 -3
- {dotscope-1.2.0 → dotscope-1.2.2}/dotscope/mcp_server.py +121 -1
- {dotscope-1.2.0 → dotscope-1.2.2}/dotscope/models/core.py +4 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/graph_builder.py +13 -2
- {dotscope-1.2.0 → dotscope-1.2.2}/dotscope/scanner.py +18 -1
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/search/retriever.py +21 -3
- {dotscope-1.2.0 → dotscope-1.2.2}/dotscope/search/synthesizer.py +17 -7
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/claude_hooks.py +47 -0
- dotscope-1.2.2/dotscope/swarm/__init__.py +13 -0
- dotscope-1.2.2/dotscope/swarm/merge.py +161 -0
- dotscope-1.2.2/dotscope/swarm/partition.py +236 -0
- dotscope-1.2.2/dotscope/swarm/trace.py +251 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/pyproject.toml +1 -1
- dotscope-1.2.2/tests/test_ignore.py +64 -0
- dotscope-1.2.2/tests/test_swarm.py +300 -0
- dotscope-1.2.0/.claude/settings.local.json +0 -35
- dotscope-1.2.0/.claude/worktrees/hopeful-chatelet/.claude/hooks/pre-commit-check.sh +0 -41
- dotscope-1.2.0/.claude/worktrees/hopeful-chatelet/.claude/settings.json +0 -15
- dotscope-1.2.0/.claude/worktrees/hopeful-chatelet/.claude/settings.local.json +0 -52
- dotscope-1.2.0/.claude/worktrees/hopeful-chatelet/.git +0 -1
- dotscope-1.2.0/.claude/worktrees/hopeful-chatelet/README.md +0 -90
- dotscope-1.2.0/.claude/worktrees/hopeful-chatelet/dotscope/formatter.py +0 -157
- dotscope-1.2.0/.claude/worktrees/hopeful-chatelet/dotscope/mcp_server.py +0 -1457
- dotscope-1.2.0/.claude/worktrees/hopeful-chatelet/dotscope/models/core.py +0 -328
- dotscope-1.2.0/.claude/worktrees/hopeful-chatelet/dotscope/scanner.py +0 -246
- dotscope-1.2.0/.claude/worktrees/hopeful-chatelet/dotscope/search/synthesizer.py +0 -292
- dotscope-1.2.0/.gitignore +0 -10
- dotscope-1.2.0/.mcp.json +0 -9
- dotscope-1.2.0/.scopes +0 -28
- dotscope-1.2.0/AGENT_INSTRUCTIONS.md +0 -129
- dotscope-1.2.0/LICENSE +0 -21
- dotscope-1.2.0/PKG-INFO +0 -127
- dotscope-1.2.0/README.md +0 -90
- dotscope-1.2.0/docs/architecture.md +0 -72
- dotscope-1.2.0/docs/cli-reference.md +0 -67
- dotscope-1.2.0/docs/how-it-works.md +0 -146
- dotscope-1.2.0/docs/mcp-setup.md +0 -255
- dotscope-1.2.0/docs/scope-file.md +0 -285
- dotscope-1.2.0/dotscope/.scope +0 -82
- dotscope-1.2.0/dotscope/__init__.py +0 -3
- dotscope-1.2.0/dotscope/absorber.py +0 -390
- dotscope-1.2.0/dotscope/assertions.py +0 -127
- dotscope-1.2.0/dotscope/ast_analyzer.py +0 -2
- dotscope-1.2.0/dotscope/backtest.py +0 -2
- dotscope-1.2.0/dotscope/bench.py +0 -141
- dotscope-1.2.0/dotscope/budget.py +0 -3
- dotscope-1.2.0/dotscope/cache.py +0 -2
- dotscope-1.2.0/dotscope/check/__init__.py +0 -1
- dotscope-1.2.0/dotscope/check/acknowledge.py +0 -2
- dotscope-1.2.0/dotscope/check/checker.py +0 -3
- dotscope-1.2.0/dotscope/check/checks/__init__.py +0 -1
- dotscope-1.2.0/dotscope/check/checks/antipattern.py +0 -2
- dotscope-1.2.0/dotscope/check/checks/boundary.py +0 -2
- dotscope-1.2.0/dotscope/check/checks/contracts.py +0 -3
- dotscope-1.2.0/dotscope/check/checks/direction.py +0 -2
- dotscope-1.2.0/dotscope/check/checks/intent.py +0 -2
- dotscope-1.2.0/dotscope/check/checks/stability.py +0 -2
- dotscope-1.2.0/dotscope/check/constraints.py +0 -2
- dotscope-1.2.0/dotscope/check/models.py +0 -15
- dotscope-1.2.0/dotscope/cli.py +0 -1561
- dotscope-1.2.0/dotscope/composer.py +0 -229
- dotscope-1.2.0/dotscope/constants.py +0 -45
- dotscope-1.2.0/dotscope/context.py +0 -60
- dotscope-1.2.0/dotscope/counterfactual.py +0 -180
- dotscope-1.2.0/dotscope/debug.py +0 -220
- dotscope-1.2.0/dotscope/discovery.py +0 -138
- dotscope-1.2.0/dotscope/eval/.scope +0 -27
- dotscope-1.2.0/dotscope/eval/__init__.py +0 -18
- dotscope-1.2.0/dotscope/eval/bootstrap.py +0 -231
- dotscope-1.2.0/dotscope/eval/compare.py +0 -147
- dotscope-1.2.0/dotscope/eval/corpus.py +0 -214
- dotscope-1.2.0/dotscope/eval/harness.py +0 -310
- dotscope-1.2.0/dotscope/eval/replay.py +0 -356
- dotscope-1.2.0/dotscope/generate/.scope +0 -24
- dotscope-1.2.0/dotscope/generate/__init__.py +0 -1
- dotscope-1.2.0/dotscope/generate/atlas.py +0 -341
- dotscope-1.2.0/dotscope/generate/contracts.py +0 -296
- dotscope-1.2.0/dotscope/generate/engine.py +0 -189
- dotscope-1.2.0/dotscope/generate/models.py +0 -27
- dotscope-1.2.0/dotscope/generate/network.py +0 -284
- dotscope-1.2.0/dotscope/graph.py +0 -3
- dotscope-1.2.0/dotscope/health.py +0 -272
- dotscope-1.2.0/dotscope/help.py +0 -218
- dotscope-1.2.0/dotscope/history.py +0 -6
- dotscope-1.2.0/dotscope/hooks.py +0 -2
- dotscope-1.2.0/dotscope/ingest.py +0 -972
- dotscope-1.2.0/dotscope/intent.py +0 -614
- dotscope-1.2.0/dotscope/lessons.py +0 -223
- dotscope-1.2.0/dotscope/matcher.py +0 -104
- dotscope-1.2.0/dotscope/merge/.scope +0 -34
- dotscope-1.2.0/dotscope/merge/__init__.py +0 -1
- dotscope-1.2.0/dotscope/merge/classifier.py +0 -83
- dotscope-1.2.0/dotscope/merge/composer.py +0 -210
- dotscope-1.2.0/dotscope/merge/differ.py +0 -178
- dotscope-1.2.0/dotscope/merge/driver.py +0 -147
- dotscope-1.2.0/dotscope/merge/imports.py +0 -114
- dotscope-1.2.0/dotscope/merge/models.py +0 -62
- dotscope-1.2.0/dotscope/merge/swarm.py +0 -336
- dotscope-1.2.0/dotscope/models/.scope +0 -45
- dotscope-1.2.0/dotscope/models/__init__.py +0 -8
- dotscope-1.2.0/dotscope/models/eval.py +0 -96
- dotscope-1.2.0/dotscope/models/history.py +0 -73
- dotscope-1.2.0/dotscope/models/intent.py +0 -214
- dotscope-1.2.0/dotscope/models/passes.py +0 -58
- dotscope-1.2.0/dotscope/models/state.py +0 -251
- dotscope-1.2.0/dotscope/models.py +0 -9
- dotscope-1.2.0/dotscope/near_miss.py +0 -3
- dotscope-1.2.0/dotscope/onboarding.py +0 -2
- dotscope-1.2.0/dotscope/parser.py +0 -395
- dotscope-1.2.0/dotscope/passes/.scope +0 -105
- dotscope-1.2.0/dotscope/passes/__init__.py +0 -1
- dotscope-1.2.0/dotscope/passes/ast_analyzer.py +0 -757
- dotscope-1.2.0/dotscope/passes/backtest.py +0 -198
- dotscope-1.2.0/dotscope/passes/budget_allocator.py +0 -343
- dotscope-1.2.0/dotscope/passes/convention_compliance.py +0 -40
- dotscope-1.2.0/dotscope/passes/convention_discovery.py +0 -345
- dotscope-1.2.0/dotscope/passes/convention_parser.py +0 -235
- dotscope-1.2.0/dotscope/passes/graph_builder.py +0 -437
- dotscope-1.2.0/dotscope/passes/hint_generator.py +0 -128
- dotscope-1.2.0/dotscope/passes/history_miner.py +0 -336
- dotscope-1.2.0/dotscope/passes/incremental.py +0 -221
- dotscope-1.2.0/dotscope/passes/lang/__init__.py +0 -38
- dotscope-1.2.0/dotscope/passes/lang/_base.py +0 -20
- dotscope-1.2.0/dotscope/passes/lang/_treesitter.py +0 -93
- dotscope-1.2.0/dotscope/passes/lang/go.py +0 -334
- dotscope-1.2.0/dotscope/passes/lang/javascript.py +0 -431
- dotscope-1.2.0/dotscope/passes/lazy.py +0 -177
- dotscope-1.2.0/dotscope/passes/preflight.py +0 -117
- dotscope-1.2.0/dotscope/passes/semantic_diff.py +0 -160
- dotscope-1.2.0/dotscope/passes/sentinel/__init__.py +0 -1
- dotscope-1.2.0/dotscope/passes/sentinel/acknowledge.py +0 -222
- dotscope-1.2.0/dotscope/passes/sentinel/checker.py +0 -428
- dotscope-1.2.0/dotscope/passes/sentinel/checks/__init__.py +0 -1
- dotscope-1.2.0/dotscope/passes/sentinel/checks/antipattern.py +0 -84
- dotscope-1.2.0/dotscope/passes/sentinel/checks/boundary.py +0 -46
- dotscope-1.2.0/dotscope/passes/sentinel/checks/contracts.py +0 -148
- dotscope-1.2.0/dotscope/passes/sentinel/checks/convention.py +0 -54
- dotscope-1.2.0/dotscope/passes/sentinel/checks/direction.py +0 -71
- dotscope-1.2.0/dotscope/passes/sentinel/checks/intent.py +0 -207
- dotscope-1.2.0/dotscope/passes/sentinel/checks/network.py +0 -91
- dotscope-1.2.0/dotscope/passes/sentinel/checks/spatial.py +0 -115
- dotscope-1.2.0/dotscope/passes/sentinel/checks/stability.py +0 -66
- dotscope-1.2.0/dotscope/passes/sentinel/checks/voice.py +0 -108
- dotscope-1.2.0/dotscope/passes/sentinel/constraints.py +0 -472
- dotscope-1.2.0/dotscope/passes/sentinel/line_filter.py +0 -88
- dotscope-1.2.0/dotscope/passes/sentinel/models.py +0 -15
- dotscope-1.2.0/dotscope/passes/spatial_autofix.py +0 -206
- dotscope-1.2.0/dotscope/passes/virtual.py +0 -247
- dotscope-1.2.0/dotscope/passes/voice.py +0 -161
- dotscope-1.2.0/dotscope/passes/voice_defaults.py +0 -68
- dotscope-1.2.0/dotscope/passes/voice_discovery.py +0 -245
- dotscope-1.2.0/dotscope/paths.py +0 -83
- dotscope-1.2.0/dotscope/progress.py +0 -44
- dotscope-1.2.0/dotscope/refresh.py +0 -543
- dotscope-1.2.0/dotscope/regression.py +0 -147
- dotscope-1.2.0/dotscope/resolver.py +0 -198
- dotscope-1.2.0/dotscope/runtime_overlay.py +0 -403
- dotscope-1.2.0/dotscope/search/.scope +0 -29
- dotscope-1.2.0/dotscope/search/__init__.py +0 -1
- dotscope-1.2.0/dotscope/search/chunker.py +0 -343
- dotscope-1.2.0/dotscope/search/expander.py +0 -129
- dotscope-1.2.0/dotscope/search/flattener.py +0 -187
- dotscope-1.2.0/dotscope/search/models.py +0 -70
- dotscope-1.2.0/dotscope/search/observation.py +0 -279
- dotscope-1.2.0/dotscope/search/reranker.py +0 -85
- dotscope-1.2.0/dotscope/search/retriever.py +0 -368
- dotscope-1.2.0/dotscope/sessions.py +0 -2
- dotscope-1.2.0/dotscope/storage/.scope +0 -64
- dotscope-1.2.0/dotscope/storage/__init__.py +0 -1
- dotscope-1.2.0/dotscope/storage/cache.py +0 -177
- dotscope-1.2.0/dotscope/storage/claude_hooks.py +0 -119
- dotscope-1.2.0/dotscope/storage/git_hooks.py +0 -500
- dotscope-1.2.0/dotscope/storage/incremental_state.py +0 -124
- dotscope-1.2.0/dotscope/storage/mcp_config.py +0 -98
- dotscope-1.2.0/dotscope/storage/near_miss.py +0 -183
- dotscope-1.2.0/dotscope/storage/onboarding.py +0 -150
- dotscope-1.2.0/dotscope/storage/session_manager.py +0 -195
- dotscope-1.2.0/dotscope/storage/swarm_state.py +0 -144
- dotscope-1.2.0/dotscope/storage/timing.py +0 -84
- dotscope-1.2.0/dotscope/textio.py +0 -122
- dotscope-1.2.0/dotscope/timing.py +0 -2
- dotscope-1.2.0/dotscope/tokens.py +0 -53
- dotscope-1.2.0/dotscope/utility.py +0 -123
- dotscope-1.2.0/dotscope/virtual.py +0 -3
- dotscope-1.2.0/dotscope/visibility.py +0 -687
- dotscope-1.2.0/logo.png +0 -0
- dotscope-1.2.0/pyproject.toml +0 -45
- dotscope-1.2.0/tests/.scope +0 -29
- dotscope-1.2.0/tests/__init__.py +0 -0
- dotscope-1.2.0/tests/conftest.py +0 -152
- dotscope-1.2.0/tests/test_absorber.py +0 -91
- dotscope-1.2.0/tests/test_ast_analyzer.py +0 -168
- dotscope-1.2.0/tests/test_backtest.py +0 -114
- dotscope-1.2.0/tests/test_budget.py +0 -124
- dotscope-1.2.0/tests/test_canonical_snippet.py +0 -70
- dotscope-1.2.0/tests/test_cli.py +0 -122
- dotscope-1.2.0/tests/test_composer.py +0 -125
- dotscope-1.2.0/tests/test_context.py +0 -52
- dotscope-1.2.0/tests/test_enforcement.py +0 -423
- dotscope-1.2.0/tests/test_eval_harness.py +0 -376
- dotscope-1.2.0/tests/test_experience.py +0 -237
- dotscope-1.2.0/tests/test_graph.py +0 -78
- dotscope-1.2.0/tests/test_health.py +0 -142
- dotscope-1.2.0/tests/test_history.py +0 -71
- dotscope-1.2.0/tests/test_ingest.py +0 -319
- dotscope-1.2.0/tests/test_lessons.py +0 -91
- dotscope-1.2.0/tests/test_line_filter.py +0 -67
- dotscope-1.2.0/tests/test_loop.py +0 -384
- dotscope-1.2.0/tests/test_matcher.py +0 -47
- dotscope-1.2.0/tests/test_near_miss.py +0 -161
- dotscope-1.2.0/tests/test_parser.py +0 -180
- dotscope-1.2.0/tests/test_refresh.py +0 -251
- dotscope-1.2.0/tests/test_resolver.py +0 -100
- dotscope-1.2.0/tests/test_rigor.py +0 -223
- dotscope-1.2.0/tests/test_routing.py +0 -207
- dotscope-1.2.0/tests/test_scanner.py +0 -54
- dotscope-1.2.0/tests/test_sessions.py +0 -122
- dotscope-1.2.0/tests/test_textio.py +0 -85
- dotscope-1.2.0/tests/test_treesitter.py +0 -359
- dotscope-1.2.0/tests/test_utility.py +0 -48
- dotscope-1.2.0/tests/test_virtual.py +0 -95
- dotscope-1.2.0/tests/test_visibility.py +0 -417
- dotscope-1.2.0/tests/test_voice_check.py +0 -123
- dotscope-1.2.0/tests/test_voice_discovery.py +0 -143
- dotscope-1.2.0/uv.lock +0 -2375
- {dotscope-1.2.0 → dotscope-1.2.2}/.claude/hooks/pre-commit-check.sh +0 -0
- {dotscope-1.2.0 → dotscope-1.2.2}/.claude/settings.json +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/.gitignore +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/.scopes +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/AGENT_INSTRUCTIONS.md +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/LICENSE +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/docs/architecture.md +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/docs/cli-reference.md +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/docs/how-it-works.md +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/docs/mcp-setup.md +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/docs/scope-file.md +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/.scope +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/absorber.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/assertions.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/ast_analyzer.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/backtest.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/bench.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/budget.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/cache.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/__init__.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/acknowledge.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/checker.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/checks/__init__.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/checks/antipattern.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/checks/boundary.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/checks/contracts.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/checks/direction.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/checks/intent.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/checks/stability.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/constraints.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/check/models.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/composer.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/context.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/counterfactual.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/debug.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/discovery.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/eval/.scope +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/eval/__init__.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/eval/bootstrap.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/eval/compare.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/eval/corpus.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/eval/harness.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/eval/replay.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/generate/.scope +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/generate/__init__.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/generate/atlas.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/generate/contracts.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/generate/models.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/generate/network.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/graph.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/health.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/help.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/history.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/hooks.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/intent.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/lessons.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/matcher.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/merge/.scope +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/merge/__init__.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/merge/classifier.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/merge/composer.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/merge/differ.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/merge/driver.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/merge/imports.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/merge/models.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/merge/swarm.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/models/.scope +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/models/__init__.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/models/eval.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/models/history.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/models/intent.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/models/passes.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/models/state.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/models.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/near_miss.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/onboarding.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/parser.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/.scope +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/__init__.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/ast_analyzer.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/backtest.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/budget_allocator.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/convention_compliance.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/convention_discovery.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/convention_parser.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/hint_generator.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/history_miner.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/incremental.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/lang/__init__.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/lang/_base.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/lang/_treesitter.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/lang/go.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/lang/javascript.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/lazy.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/preflight.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/semantic_diff.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/__init__.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/acknowledge.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checker.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/__init__.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/antipattern.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/boundary.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/contracts.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/convention.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/direction.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/intent.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/network.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/spatial.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/stability.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/checks/voice.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/constraints.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/line_filter.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/sentinel/models.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/spatial_autofix.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/virtual.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/voice.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/voice_defaults.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/passes/voice_discovery.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/paths.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/progress.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/refresh.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/regression.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/resolver.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/runtime_overlay.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/search/.scope +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/search/__init__.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/search/chunker.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/search/expander.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/search/flattener.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/search/models.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/search/observation.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/search/reranker.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/sessions.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/.scope +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/__init__.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/cache.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/git_hooks.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/incremental_state.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/mcp_config.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/near_miss.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/onboarding.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/session_manager.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/swarm_state.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/storage/timing.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/textio.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/timing.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/tokens.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/utility.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/virtual.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/visibility.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/logo.png +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/.scope +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/__init__.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/conftest.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_absorber.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_ast_analyzer.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_backtest.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_budget.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_canonical_snippet.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_cli.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_composer.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_context.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_enforcement.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_eval_harness.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_experience.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_graph.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_health.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_history.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_ingest.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_lessons.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_line_filter.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_loop.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_matcher.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_near_miss.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_parser.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_refresh.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_resolver.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_rigor.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_routing.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_scanner.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_sessions.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_textio.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_treesitter.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_utility.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_virtual.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_visibility.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_voice_check.py +0 -0
- {dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/tests/test_voice_discovery.py +0 -0
- {dotscope-1.2.0/.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:
|
|
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
|
#
|
dotscope-1.2.2/CLAUDE.md
ADDED
|
@@ -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.
|
dotscope-1.2.2/PKG-INFO
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dotscope
|
|
3
|
+
Version: 1.2.2
|
|
4
|
+
Summary: Agents see files. You see architecture. dotscope gives agents the architecture.
|
|
5
|
+
Author: Supremum
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: agents,ai,coding,context,mcp,scope
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Requires-Dist: tree-sitter-go>=0.23.0
|
|
16
|
+
Requires-Dist: tree-sitter-javascript>=0.23.0
|
|
17
|
+
Requires-Dist: tree-sitter-typescript>=0.23.0
|
|
18
|
+
Requires-Dist: tree-sitter>=0.23.0
|
|
19
|
+
Provides-Extra: all
|
|
20
|
+
Requires-Dist: mcp>=1.2.0; extra == 'all'
|
|
21
|
+
Requires-Dist: numpy; extra == 'all'
|
|
22
|
+
Requires-Dist: sentence-transformers; extra == 'all'
|
|
23
|
+
Requires-Dist: tiktoken; extra == 'all'
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
26
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
27
|
+
Provides-Extra: embeddings
|
|
28
|
+
Requires-Dist: sentence-transformers; extra == 'embeddings'
|
|
29
|
+
Provides-Extra: mcp
|
|
30
|
+
Requires-Dist: mcp>=1.2.0; extra == 'mcp'
|
|
31
|
+
Provides-Extra: search
|
|
32
|
+
Requires-Dist: numpy; extra == 'search'
|
|
33
|
+
Requires-Dist: sentence-transformers; extra == 'search'
|
|
34
|
+
Provides-Extra: tokens
|
|
35
|
+
Requires-Dist: tiktoken; extra == 'tokens'
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
|
|
38
|
+
<p align="center">
|
|
39
|
+
<img src="logo.png" alt="dotscope" width="400">
|
|
40
|
+
</p>
|
|
41
|
+
|
|
42
|
+
Your agent writes code that compiles, passes tests, and breaks production.
|
|
43
|
+
|
|
44
|
+
It changed a backend endpoint without touching the frontend that calls it.
|
|
45
|
+
It put a file in `src/helpers/` instead of next to the module that uses it.
|
|
46
|
+
It ignored the convention every other file follows. Two agents working at
|
|
47
|
+
the same time silently overwrote each other.
|
|
48
|
+
|
|
49
|
+
The agent sees files. You see architecture. dotscope closes that gap.
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
$ dotscope ingest
|
|
53
|
+
|
|
54
|
+
Analyzing dependency graph...
|
|
55
|
+
Mining git history...
|
|
56
|
+
Discovering conventions...
|
|
57
|
+
|
|
58
|
+
Discoveries:
|
|
59
|
+
- version.py and environment.prod.ts always change together
|
|
60
|
+
- workflow-edit-dialog.component.ts and models.py are tightly coupled
|
|
61
|
+
|
|
62
|
+
Validation (49 commits backtested):
|
|
63
|
+
- Overall recall: 78%
|
|
64
|
+
- Token reduction: 67% (1.3M → 437K avg)
|
|
65
|
+
|
|
66
|
+
Output: 3 .scope files written.
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
One MCP tool call. The agent gets the relevant code, its dependency
|
|
70
|
+
neighborhood, implicit contracts from git history, convention rules,
|
|
71
|
+
swarm lock status, and action hints. One call, not five.
|
|
72
|
+
|
|
73
|
+
dotscope learns from every commit. Files agents consistently need get
|
|
74
|
+
ranked higher. Conventions that hold get enforced harder. Rules that
|
|
75
|
+
get overridden get quieter. Recall starts at 78% and climbs past 91%.
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
pip install dotscope && dotscope init
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Zero dependencies. Python 3.9+ stdlib only. MIT.
|
|
82
|
+
|
|
83
|
+
[How It Works](docs/how-it-works.md) · [Scope Files](docs/scope-file.md) · [Agent Instructions](AGENT_INSTRUCTIONS.md) · [MIT](LICENSE)
|
dotscope-1.2.2/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="logo.png" alt="dotscope" width="400">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
Your agent writes code that compiles, passes tests, and breaks production.
|
|
6
|
+
|
|
7
|
+
It changed a backend endpoint without touching the frontend that calls it.
|
|
8
|
+
It put a file in `src/helpers/` instead of next to the module that uses it.
|
|
9
|
+
It ignored the convention every other file follows. Two agents working at
|
|
10
|
+
the same time silently overwrote each other.
|
|
11
|
+
|
|
12
|
+
The agent sees files. You see architecture. dotscope closes that gap.
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
$ dotscope ingest
|
|
16
|
+
|
|
17
|
+
Analyzing dependency graph...
|
|
18
|
+
Mining git history...
|
|
19
|
+
Discovering conventions...
|
|
20
|
+
|
|
21
|
+
Discoveries:
|
|
22
|
+
- version.py and environment.prod.ts always change together
|
|
23
|
+
- workflow-edit-dialog.component.ts and models.py are tightly coupled
|
|
24
|
+
|
|
25
|
+
Validation (49 commits backtested):
|
|
26
|
+
- Overall recall: 78%
|
|
27
|
+
- Token reduction: 67% (1.3M → 437K avg)
|
|
28
|
+
|
|
29
|
+
Output: 3 .scope files written.
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
One MCP tool call. The agent gets the relevant code, its dependency
|
|
33
|
+
neighborhood, implicit contracts from git history, convention rules,
|
|
34
|
+
swarm lock status, and action hints. One call, not five.
|
|
35
|
+
|
|
36
|
+
dotscope learns from every commit. Files agents consistently need get
|
|
37
|
+
ranked higher. Conventions that hold get enforced harder. Rules that
|
|
38
|
+
get overridden get quieter. Recall starts at 78% and climbs past 91%.
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
pip install dotscope && dotscope init
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Zero dependencies. Python 3.9+ stdlib only. MIT.
|
|
45
|
+
|
|
46
|
+
[How It Works](docs/how-it-works.md) · [Scope Files](docs/scope-file.md) · [Agent Instructions](AGENT_INSTRUCTIONS.md) · [MIT](LICENSE)
|
|
@@ -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:
|
|
@@ -2,20 +2,44 @@
|
|
|
2
2
|
|
|
3
3
|
# Directories to always skip when walking a codebase
|
|
4
4
|
SKIP_DIRS = frozenset({
|
|
5
|
+
# Version control
|
|
5
6
|
".git",
|
|
7
|
+
# Package managers
|
|
6
8
|
"node_modules",
|
|
9
|
+
"vendor",
|
|
10
|
+
# Python
|
|
7
11
|
"__pycache__",
|
|
8
12
|
"venv",
|
|
9
13
|
".venv",
|
|
10
14
|
"env",
|
|
11
15
|
".env",
|
|
12
|
-
"dist",
|
|
13
|
-
"build",
|
|
14
16
|
".tox",
|
|
15
17
|
".mypy_cache",
|
|
16
18
|
".ruff_cache",
|
|
17
19
|
".eggs",
|
|
18
20
|
".pytest_cache",
|
|
21
|
+
# Build output
|
|
22
|
+
"dist",
|
|
23
|
+
"build",
|
|
24
|
+
"out",
|
|
25
|
+
"target",
|
|
26
|
+
"bin",
|
|
27
|
+
"obj",
|
|
28
|
+
# JS/TS frameworks
|
|
29
|
+
".next",
|
|
30
|
+
".nuxt",
|
|
31
|
+
".output",
|
|
32
|
+
".parcel-cache",
|
|
33
|
+
# Caches
|
|
34
|
+
".cache",
|
|
35
|
+
".gradle",
|
|
36
|
+
".terraform",
|
|
37
|
+
# Test/coverage output
|
|
38
|
+
"coverage",
|
|
39
|
+
"test-results",
|
|
40
|
+
# dotscope / Claude
|
|
41
|
+
".dotscope",
|
|
42
|
+
".claude",
|
|
19
43
|
})
|
|
20
44
|
|
|
21
45
|
# Source file extensions
|
|
@@ -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
|
|
{dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/generate/engine.py
RENAMED
|
@@ -118,8 +118,8 @@ def _load_config(root: str) -> GenerateConfig:
|
|
|
118
118
|
return GenerateConfig()
|
|
119
119
|
|
|
120
120
|
try:
|
|
121
|
-
from ..parser import
|
|
122
|
-
data =
|
|
121
|
+
from ..parser import _parse_yaml
|
|
122
|
+
data = _parse_yaml(config_path.read_text(encoding="utf-8"))
|
|
123
123
|
gen = data.get("generate", {})
|
|
124
124
|
return GenerateConfig(
|
|
125
125
|
output_dir=gen.get("output_dir", "docs/dotscope"),
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
""".dotscopeignore support — gitignore-style exclusion patterns.
|
|
2
|
+
|
|
3
|
+
Loaded once at scan start, passed through the pipeline. No per-file IO.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import fnmatch
|
|
7
|
+
import os
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import List
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def load_ignore_patterns(repo_root: str) -> List[str]:
|
|
13
|
+
"""Load .dotscopeignore patterns. Returns empty list if no file."""
|
|
14
|
+
ignore_path = os.path.join(repo_root, ".dotscopeignore")
|
|
15
|
+
if not os.path.exists(ignore_path):
|
|
16
|
+
return []
|
|
17
|
+
|
|
18
|
+
patterns = []
|
|
19
|
+
try:
|
|
20
|
+
with open(ignore_path, "r", encoding="utf-8") as f:
|
|
21
|
+
for line in f:
|
|
22
|
+
line = line.strip()
|
|
23
|
+
if not line or line.startswith("#"):
|
|
24
|
+
continue
|
|
25
|
+
patterns.append(line)
|
|
26
|
+
except (IOError, OSError):
|
|
27
|
+
return []
|
|
28
|
+
return patterns
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def should_skip(
|
|
32
|
+
path: str,
|
|
33
|
+
skip_dirs: frozenset,
|
|
34
|
+
ignore_patterns: List[str],
|
|
35
|
+
) -> bool:
|
|
36
|
+
"""Check if a path should be skipped.
|
|
37
|
+
|
|
38
|
+
Order: hardcoded skip_dirs first (O(1) lookup),
|
|
39
|
+
then .dotscopeignore patterns (glob matching).
|
|
40
|
+
"""
|
|
41
|
+
parts = Path(path).parts
|
|
42
|
+
for part in parts:
|
|
43
|
+
if part in skip_dirs:
|
|
44
|
+
return True
|
|
45
|
+
|
|
46
|
+
for pattern in ignore_patterns:
|
|
47
|
+
if fnmatch.fnmatch(path, pattern):
|
|
48
|
+
return True
|
|
49
|
+
# Directory patterns: "renderer/target/" matches any file under it
|
|
50
|
+
if pattern.endswith("/"):
|
|
51
|
+
dir_prefix = pattern.rstrip("/")
|
|
52
|
+
if path.startswith(dir_prefix + "/") or path.startswith(dir_prefix + os.sep):
|
|
53
|
+
return True
|
|
54
|
+
# Also match against any path component
|
|
55
|
+
for part in parts:
|
|
56
|
+
if fnmatch.fnmatch(part, dir_prefix):
|
|
57
|
+
return True
|
|
58
|
+
|
|
59
|
+
return False
|
|
@@ -29,6 +29,26 @@ from .paths import (
|
|
|
29
29
|
from .tokens import estimate_scope_tokens
|
|
30
30
|
|
|
31
31
|
|
|
32
|
+
def _safe_print(text, **kwargs):
|
|
33
|
+
"""Print with ASCII fallback for Windows cp1252 terminals."""
|
|
34
|
+
try:
|
|
35
|
+
print(text, **kwargs)
|
|
36
|
+
except UnicodeEncodeError:
|
|
37
|
+
print(text.encode("ascii", errors="replace").decode("ascii"), **kwargs)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _log_ingest_error(root: str, message: str) -> None:
|
|
41
|
+
"""Append error to .dotscope/error.log for debugging."""
|
|
42
|
+
try:
|
|
43
|
+
log_dir = os.path.join(root, ".dotscope")
|
|
44
|
+
os.makedirs(log_dir, exist_ok=True)
|
|
45
|
+
import time
|
|
46
|
+
with open(os.path.join(log_dir, "error.log"), "a", encoding="utf-8") as f:
|
|
47
|
+
f.write(f"[{time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())}] {message}\n")
|
|
48
|
+
except Exception:
|
|
49
|
+
pass # Logging failure should never block ingest
|
|
50
|
+
|
|
51
|
+
|
|
32
52
|
def ingest(
|
|
33
53
|
root: str,
|
|
34
54
|
mine_history: bool = True,
|
|
@@ -168,8 +188,8 @@ def ingest(
|
|
|
168
188
|
artifacts_path = os.path.join(root, ".dotscope_artifacts.yaml")
|
|
169
189
|
if os.path.isfile(artifacts_path):
|
|
170
190
|
try:
|
|
171
|
-
from .parser import
|
|
172
|
-
artifacts_data =
|
|
191
|
+
from .parser import _parse_yaml
|
|
192
|
+
artifacts_data = _parse_yaml(
|
|
173
193
|
open(artifacts_path, "r", encoding="utf-8").read()
|
|
174
194
|
)
|
|
175
195
|
for artifact in artifacts_data.get("artifacts", []):
|
|
@@ -191,13 +211,41 @@ def ingest(
|
|
|
191
211
|
except Exception:
|
|
192
212
|
pass
|
|
193
213
|
|
|
214
|
+
# Cap chunk count to prevent OOM on large repos
|
|
215
|
+
max_chunks = getattr(args, "max_chunks", 50_000) if args else 50_000
|
|
216
|
+
if len(all_chunks) > max_chunks:
|
|
217
|
+
# Prefer source files over tests/configs
|
|
218
|
+
def _chunk_priority(c):
|
|
219
|
+
p = c.file_path.lower()
|
|
220
|
+
if "/test" in p or p.startswith("test"):
|
|
221
|
+
return 2
|
|
222
|
+
if any(p.endswith(e) for e in (".json", ".yaml", ".yml", ".toml")):
|
|
223
|
+
return 1
|
|
224
|
+
return 0
|
|
225
|
+
all_chunks.sort(key=lambda c: (_chunk_priority(c), c.file_path))
|
|
226
|
+
_safe_print(
|
|
227
|
+
f"dotscope: {len(all_chunks)} chunks exceeds limit,"
|
|
228
|
+
f" keeping top {max_chunks}",
|
|
229
|
+
file=sys.stderr,
|
|
230
|
+
)
|
|
231
|
+
all_chunks = all_chunks[:max_chunks]
|
|
232
|
+
|
|
194
233
|
if all_chunks:
|
|
195
234
|
index = build_vector_index(root, all_chunks)
|
|
196
235
|
progress.finish(f"{index.chunk_count} chunks, {index.model_name}")
|
|
197
236
|
else:
|
|
198
237
|
progress.finish("0 chunks")
|
|
199
238
|
except Exception as e:
|
|
200
|
-
|
|
239
|
+
import traceback
|
|
240
|
+
_safe_print(
|
|
241
|
+
f"dotscope: search index failed: {e}\n"
|
|
242
|
+
f" Scopes still work. Search will be unavailable.\n"
|
|
243
|
+
f" Try: dotscope ingest . --max-chunks 25000",
|
|
244
|
+
file=sys.stderr,
|
|
245
|
+
)
|
|
246
|
+
# Log full traceback for debugging
|
|
247
|
+
_log_ingest_error(root, traceback.format_exc())
|
|
248
|
+
progress.finish("failed")
|
|
201
249
|
|
|
202
250
|
# Step 4: Synthesize scope files
|
|
203
251
|
progress.start("generating scopes")
|
|
@@ -1256,7 +1256,20 @@ def main():
|
|
|
1256
1256
|
task_type=task_type,
|
|
1257
1257
|
no_observe=no_observe or False,
|
|
1258
1258
|
)
|
|
1259
|
-
|
|
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
|
|
|
@@ -14,6 +14,7 @@ from ..ast_analyzer import (
|
|
|
14
14
|
resolve_python_import,
|
|
15
15
|
)
|
|
16
16
|
from ..constants import LANG_MAP, SKIP_DIRS
|
|
17
|
+
from ..ignore import load_ignore_patterns, should_skip
|
|
17
18
|
from ..models.core import (
|
|
18
19
|
DependencyGraph,
|
|
19
20
|
FileNode,
|
|
@@ -201,15 +202,25 @@ def transitive_dependents(graph: DependencyGraph, file: str) -> Set[str]:
|
|
|
201
202
|
def _collect_source_files(root: str) -> List[Tuple[str, str]]:
|
|
202
203
|
"""Walk the tree and collect (relative_path, language)."""
|
|
203
204
|
lang_map = {k: v.lower() for k, v in LANG_MAP.items()}
|
|
205
|
+
ignore_patterns = load_ignore_patterns(root)
|
|
204
206
|
results = []
|
|
205
207
|
|
|
206
208
|
for dirpath, dirnames, filenames in os.walk(root):
|
|
207
|
-
dirnames[:] = [
|
|
209
|
+
dirnames[:] = [
|
|
210
|
+
d for d in dirnames
|
|
211
|
+
if d not in SKIP_DIRS
|
|
212
|
+
and not should_skip(
|
|
213
|
+
os.path.relpath(os.path.join(dirpath, d), root),
|
|
214
|
+
SKIP_DIRS,
|
|
215
|
+
ignore_patterns,
|
|
216
|
+
)
|
|
217
|
+
]
|
|
208
218
|
for fn in filenames:
|
|
209
219
|
ext = os.path.splitext(fn)[1].lower()
|
|
210
220
|
if ext in lang_map:
|
|
211
221
|
rel = normalize_relative_path(os.path.relpath(os.path.join(dirpath, fn), root))
|
|
212
|
-
|
|
222
|
+
if not should_skip(rel, frozenset(), ignore_patterns):
|
|
223
|
+
results.append((rel, lang_map[ext]))
|
|
213
224
|
|
|
214
225
|
return sorted(results)
|
|
215
226
|
|
|
@@ -12,6 +12,7 @@ from typing import List, Optional, Set, Tuple
|
|
|
12
12
|
|
|
13
13
|
from .constants import LANG_MAP, SKIP_DIRS
|
|
14
14
|
from .context import parse_context
|
|
15
|
+
from .ignore import load_ignore_patterns, should_skip
|
|
15
16
|
from .models import ScopeConfig
|
|
16
17
|
from .tokens import estimate_file_tokens
|
|
17
18
|
|
|
@@ -100,11 +101,27 @@ def _scan_files(path: str) -> Tuple[List[str], Counter, int]:
|
|
|
100
101
|
lang_counts: Counter = Counter()
|
|
101
102
|
total_tokens = 0
|
|
102
103
|
|
|
104
|
+
# Load .dotscopeignore patterns from the repo root (or nearest parent)
|
|
105
|
+
ignore_patterns = load_ignore_patterns(path)
|
|
106
|
+
|
|
103
107
|
for dirpath, dirnames, filenames in os.walk(path):
|
|
104
|
-
dirnames[:] = [
|
|
108
|
+
dirnames[:] = [
|
|
109
|
+
d for d in dirnames
|
|
110
|
+
if d not in SKIP_DIRS
|
|
111
|
+
and not should_skip(
|
|
112
|
+
os.path.relpath(os.path.join(dirpath, d), path),
|
|
113
|
+
SKIP_DIRS,
|
|
114
|
+
ignore_patterns,
|
|
115
|
+
)
|
|
116
|
+
]
|
|
105
117
|
|
|
106
118
|
for filename in filenames:
|
|
107
119
|
full = os.path.join(dirpath, filename)
|
|
120
|
+
rel = os.path.relpath(full, path)
|
|
121
|
+
|
|
122
|
+
if should_skip(rel, frozenset(), ignore_patterns):
|
|
123
|
+
continue
|
|
124
|
+
|
|
108
125
|
files.append(full)
|
|
109
126
|
|
|
110
127
|
ext = os.path.splitext(filename)[1].lower()
|
{dotscope-1.2.0/.claude/worktrees/hopeful-chatelet → dotscope-1.2.2}/dotscope/search/retriever.py
RENAMED
|
@@ -283,12 +283,30 @@ def _dense_search(query: str, embeddings, limit: int = 50) -> List[Tuple[int, fl
|
|
|
283
283
|
return []
|
|
284
284
|
|
|
285
285
|
|
|
286
|
-
def _embed_texts(texts: List[str]):
|
|
287
|
-
"""Embed texts using sentence-transformers. Returns numpy array or None."""
|
|
286
|
+
def _embed_texts(texts: List[str], batch_size: int = 512):
|
|
287
|
+
"""Embed texts in batches using sentence-transformers. Returns numpy array or None."""
|
|
288
288
|
try:
|
|
289
289
|
from sentence_transformers import SentenceTransformer
|
|
290
|
+
import numpy as np
|
|
291
|
+
|
|
290
292
|
model = SentenceTransformer("all-MiniLM-L6-v2")
|
|
291
|
-
|
|
293
|
+
|
|
294
|
+
if len(texts) <= batch_size:
|
|
295
|
+
return model.encode(texts, show_progress_bar=False, convert_to_numpy=True)
|
|
296
|
+
|
|
297
|
+
# Batch to avoid OOM on large repos
|
|
298
|
+
all_embeddings = []
|
|
299
|
+
for i in range(0, len(texts), batch_size):
|
|
300
|
+
batch = texts[i:i + batch_size]
|
|
301
|
+
try:
|
|
302
|
+
embeddings = model.encode(batch, show_progress_bar=False, convert_to_numpy=True)
|
|
303
|
+
all_embeddings.append(embeddings)
|
|
304
|
+
except Exception:
|
|
305
|
+
continue # Skip failed batch, keep going
|
|
306
|
+
|
|
307
|
+
if not all_embeddings:
|
|
308
|
+
return None
|
|
309
|
+
return np.vstack(all_embeddings)
|
|
292
310
|
except ImportError:
|
|
293
311
|
return None
|
|
294
312
|
|