dotscope 1.2.0__tar.gz → 1.2.1__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.1/PKG-INFO +83 -0
- dotscope-1.2.1/README.md +46 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/__init__.py +1 -1
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/constants.py +26 -2
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/generate/engine.py +2 -2
- dotscope-1.2.1/dotscope/ignore.py +59 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/ingest.py +51 -3
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/graph_builder.py +13 -2
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/scanner.py +18 -1
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/search/retriever.py +21 -3
- {dotscope-1.2.0 → dotscope-1.2.1}/pyproject.toml +1 -1
- dotscope-1.2.1/tests/test_ignore.py +64 -0
- dotscope-1.2.0/PKG-INFO +0 -127
- dotscope-1.2.0/README.md +0 -90
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/hooks/pre-commit-check.sh +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/settings.json +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/settings.local.json +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/.claude/hooks/pre-commit-check.sh +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/.claude/settings.json +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/.claude/settings.local.json +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/.git +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/.gitignore +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/.scopes +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/AGENT_INSTRUCTIONS.md +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/LICENSE +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/README.md +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/docs/architecture.md +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/docs/cli-reference.md +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/docs/how-it-works.md +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/docs/mcp-setup.md +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/docs/scope-file.md +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/.scope +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/absorber.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/assertions.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/ast_analyzer.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/backtest.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/bench.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/budget.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/cache.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/check/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/check/acknowledge.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/check/checker.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/check/checks/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/check/checks/antipattern.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/check/checks/boundary.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/check/checks/contracts.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/check/checks/direction.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/check/checks/intent.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/check/checks/stability.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/check/constraints.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/check/models.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/cli.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/composer.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/constants.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/context.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/counterfactual.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/debug.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/discovery.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/eval/.scope +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/eval/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/eval/bootstrap.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/eval/compare.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/eval/corpus.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/eval/harness.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/eval/replay.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/formatter.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/generate/.scope +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/generate/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/generate/atlas.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/generate/contracts.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/generate/engine.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/generate/models.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/generate/network.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/graph.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/health.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/help.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/history.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/hooks.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/ingest.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/intent.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/lessons.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/matcher.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/mcp_server.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/merge/.scope +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/merge/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/merge/classifier.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/merge/composer.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/merge/differ.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/merge/driver.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/merge/imports.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/merge/models.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/merge/swarm.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/models/.scope +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/models/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/models/core.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/models/eval.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/models/history.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/models/intent.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/models/passes.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/models/state.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/models.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/near_miss.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/onboarding.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/parser.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/.scope +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/ast_analyzer.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/backtest.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/budget_allocator.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/convention_compliance.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/convention_discovery.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/convention_parser.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/graph_builder.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/hint_generator.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/history_miner.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/incremental.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/lang/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/lang/_base.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/lang/_treesitter.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/lang/go.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/lang/javascript.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/lazy.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/preflight.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/semantic_diff.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/sentinel/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/sentinel/acknowledge.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/sentinel/checker.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/sentinel/checks/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/sentinel/checks/antipattern.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/sentinel/checks/boundary.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/sentinel/checks/contracts.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/sentinel/checks/convention.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/sentinel/checks/direction.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/sentinel/checks/intent.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/sentinel/checks/network.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/sentinel/checks/spatial.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/sentinel/checks/stability.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/sentinel/checks/voice.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/sentinel/constraints.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/sentinel/line_filter.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/sentinel/models.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/spatial_autofix.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/virtual.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/voice.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/voice_defaults.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/passes/voice_discovery.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/paths.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/progress.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/refresh.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/regression.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/resolver.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/runtime_overlay.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/scanner.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/search/.scope +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/search/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/search/chunker.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/search/expander.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/search/flattener.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/search/models.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/search/observation.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/search/reranker.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/search/retriever.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/search/synthesizer.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/sessions.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/storage/.scope +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/storage/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/storage/cache.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/storage/claude_hooks.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/storage/git_hooks.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/storage/incremental_state.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/storage/mcp_config.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/storage/near_miss.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/storage/onboarding.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/storage/session_manager.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/storage/swarm_state.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/storage/timing.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/textio.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/timing.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/tokens.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/utility.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/virtual.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/dotscope/visibility.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/logo.png +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/pyproject.toml +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/.scope +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/conftest.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_absorber.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_ast_analyzer.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_backtest.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_budget.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_canonical_snippet.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_cli.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_composer.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_context.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_enforcement.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_eval_harness.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_experience.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_graph.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_health.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_history.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_ingest.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_lessons.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_line_filter.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_loop.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_matcher.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_near_miss.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_parser.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_refresh.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_resolver.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_rigor.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_routing.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_scanner.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_sessions.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_textio.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_treesitter.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_utility.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_virtual.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_visibility.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_voice_check.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/tests/test_voice_discovery.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.claude/worktrees/hopeful-chatelet/uv.lock +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.github/workflows/python-publish.yml +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.gitignore +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.mcp.json +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/.scopes +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/AGENT_INSTRUCTIONS.md +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/LICENSE +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/docs/architecture.md +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/docs/cli-reference.md +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/docs/how-it-works.md +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/docs/mcp-setup.md +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/docs/scope-file.md +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/.scope +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/absorber.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/assertions.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/ast_analyzer.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/backtest.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/bench.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/budget.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/cache.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/check/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/check/acknowledge.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/check/checker.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/check/checks/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/check/checks/antipattern.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/check/checks/boundary.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/check/checks/contracts.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/check/checks/direction.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/check/checks/intent.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/check/checks/stability.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/check/constraints.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/check/models.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/cli.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/composer.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/context.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/counterfactual.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/debug.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/discovery.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/eval/.scope +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/eval/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/eval/bootstrap.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/eval/compare.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/eval/corpus.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/eval/harness.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/eval/replay.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/formatter.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/generate/.scope +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/generate/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/generate/atlas.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/generate/contracts.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/generate/models.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/generate/network.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/graph.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/health.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/help.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/history.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/hooks.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/intent.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/lessons.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/matcher.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/mcp_server.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/merge/.scope +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/merge/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/merge/classifier.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/merge/composer.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/merge/differ.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/merge/driver.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/merge/imports.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/merge/models.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/merge/swarm.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/models/.scope +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/models/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/models/core.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/models/eval.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/models/history.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/models/intent.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/models/passes.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/models/state.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/models.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/near_miss.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/onboarding.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/parser.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/.scope +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/ast_analyzer.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/backtest.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/budget_allocator.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/convention_compliance.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/convention_discovery.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/convention_parser.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/hint_generator.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/history_miner.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/incremental.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/lang/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/lang/_base.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/lang/_treesitter.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/lang/go.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/lang/javascript.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/lazy.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/preflight.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/semantic_diff.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/sentinel/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/sentinel/acknowledge.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/sentinel/checker.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/sentinel/checks/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/sentinel/checks/antipattern.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/sentinel/checks/boundary.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/sentinel/checks/contracts.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/sentinel/checks/convention.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/sentinel/checks/direction.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/sentinel/checks/intent.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/sentinel/checks/network.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/sentinel/checks/spatial.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/sentinel/checks/stability.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/sentinel/checks/voice.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/sentinel/constraints.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/sentinel/line_filter.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/sentinel/models.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/spatial_autofix.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/virtual.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/voice.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/voice_defaults.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/passes/voice_discovery.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/paths.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/progress.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/refresh.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/regression.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/resolver.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/runtime_overlay.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/search/.scope +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/search/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/search/chunker.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/search/expander.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/search/flattener.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/search/models.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/search/observation.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/search/reranker.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/search/synthesizer.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/sessions.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/storage/.scope +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/storage/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/storage/cache.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/storage/claude_hooks.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/storage/git_hooks.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/storage/incremental_state.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/storage/mcp_config.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/storage/near_miss.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/storage/onboarding.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/storage/session_manager.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/storage/swarm_state.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/storage/timing.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/textio.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/timing.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/tokens.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/utility.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/virtual.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/dotscope/visibility.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/logo.png +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/.scope +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/__init__.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/conftest.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_absorber.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_ast_analyzer.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_backtest.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_budget.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_canonical_snippet.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_cli.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_composer.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_context.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_enforcement.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_eval_harness.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_experience.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_graph.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_health.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_history.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_ingest.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_lessons.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_line_filter.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_loop.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_matcher.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_near_miss.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_parser.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_refresh.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_resolver.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_rigor.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_routing.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_scanner.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_sessions.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_textio.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_treesitter.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_utility.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_virtual.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_visibility.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_voice_check.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/tests/test_voice_discovery.py +0 -0
- {dotscope-1.2.0 → dotscope-1.2.1}/uv.lock +0 -0
dotscope-1.2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dotscope
|
|
3
|
+
Version: 1.2.1
|
|
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.1/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)
|
|
@@ -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
|
|
@@ -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")
|
|
@@ -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()
|
|
@@ -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
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""Tests for .dotscopeignore pattern matching."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import tempfile
|
|
5
|
+
|
|
6
|
+
from dotscope.ignore import load_ignore_patterns, should_skip
|
|
7
|
+
from dotscope.constants import SKIP_DIRS
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestLoadIgnorePatterns:
|
|
11
|
+
def test_no_file(self, tmp_path):
|
|
12
|
+
assert load_ignore_patterns(str(tmp_path)) == []
|
|
13
|
+
|
|
14
|
+
def test_empty_file(self, tmp_path):
|
|
15
|
+
(tmp_path / ".dotscopeignore").write_text("")
|
|
16
|
+
assert load_ignore_patterns(str(tmp_path)) == []
|
|
17
|
+
|
|
18
|
+
def test_comments_skipped(self, tmp_path):
|
|
19
|
+
(tmp_path / ".dotscopeignore").write_text("# comment\n\n# another\n")
|
|
20
|
+
assert load_ignore_patterns(str(tmp_path)) == []
|
|
21
|
+
|
|
22
|
+
def test_patterns_loaded(self, tmp_path):
|
|
23
|
+
(tmp_path / ".dotscopeignore").write_text(
|
|
24
|
+
"renderer/target/\n*.fbx\n# comment\nassets/raw/\n"
|
|
25
|
+
)
|
|
26
|
+
patterns = load_ignore_patterns(str(tmp_path))
|
|
27
|
+
assert patterns == ["renderer/target/", "*.fbx", "assets/raw/"]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class TestShouldSkip:
|
|
31
|
+
def test_skip_dirs_match(self):
|
|
32
|
+
assert should_skip("node_modules/foo.js", SKIP_DIRS, [])
|
|
33
|
+
assert should_skip("src/node_modules/bar.js", SKIP_DIRS, [])
|
|
34
|
+
|
|
35
|
+
def test_skip_dirs_no_match(self):
|
|
36
|
+
assert not should_skip("src/handler.py", SKIP_DIRS, [])
|
|
37
|
+
|
|
38
|
+
def test_glob_pattern(self):
|
|
39
|
+
assert should_skip("model.fbx", frozenset(), ["*.fbx"])
|
|
40
|
+
assert should_skip("assets/scene.fbx", frozenset(), ["*.fbx"])
|
|
41
|
+
assert not should_skip("handler.py", frozenset(), ["*.fbx"])
|
|
42
|
+
|
|
43
|
+
def test_directory_pattern(self):
|
|
44
|
+
patterns = ["renderer/target/"]
|
|
45
|
+
assert should_skip("renderer/target/debug/main.rs", frozenset(), patterns)
|
|
46
|
+
assert not should_skip("renderer/src/main.rs", frozenset(), patterns)
|
|
47
|
+
|
|
48
|
+
def test_combined(self):
|
|
49
|
+
patterns = ["*.wav", "build_output/"]
|
|
50
|
+
assert should_skip("node_modules/pkg.js", SKIP_DIRS, patterns)
|
|
51
|
+
assert should_skip("audio/effect.wav", SKIP_DIRS, patterns)
|
|
52
|
+
assert should_skip("build_output/release/app", SKIP_DIRS, patterns)
|
|
53
|
+
assert not should_skip("src/main.py", SKIP_DIRS, patterns)
|
|
54
|
+
|
|
55
|
+
def test_new_skip_dirs(self):
|
|
56
|
+
"""Verify the expanded SKIP_DIRS covers common build dirs."""
|
|
57
|
+
assert should_skip("target/debug/main", SKIP_DIRS, [])
|
|
58
|
+
assert should_skip("src/target/release/bin", SKIP_DIRS, [])
|
|
59
|
+
assert should_skip(".next/cache/foo", SKIP_DIRS, [])
|
|
60
|
+
assert should_skip(".dotscope/sessions/abc.json", SKIP_DIRS, [])
|
|
61
|
+
assert should_skip(".claude/settings.json", SKIP_DIRS, [])
|
|
62
|
+
assert should_skip("out/compiled.js", SKIP_DIRS, [])
|
|
63
|
+
assert should_skip("obj/Debug/net6.0/app.dll", SKIP_DIRS, [])
|
|
64
|
+
assert should_skip("coverage/lcov.info", SKIP_DIRS, [])
|
dotscope-1.2.0/PKG-INFO
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: dotscope
|
|
3
|
-
Version: 1.2.0
|
|
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
|
-
You give an agent a task. It searches your codebase, finds the files,
|
|
43
|
-
writes the code, runs the tests, and ships. Sounds fine until you
|
|
44
|
-
realize it changed a backend endpoint without touching the frontend
|
|
45
|
-
that calls it. It put a utility function in `src/helpers/` instead of
|
|
46
|
-
next to the module that uses it. It ignored the naming convention every
|
|
47
|
-
other file follows. And when two agents worked at the same time, they
|
|
48
|
-
silently overwrote each other's changes.
|
|
49
|
-
|
|
50
|
-
The code compiled. The tests passed. Production broke.
|
|
51
|
-
|
|
52
|
-
This happens because agents don't have what you have — the full
|
|
53
|
-
picture. They see files. You see architecture.
|
|
54
|
-
|
|
55
|
-
**dotscope is the operating system for agent-driven codebases.**
|
|
56
|
-
|
|
57
|
-
One command scans your project and learns the architecture: which files
|
|
58
|
-
depend on which, what patterns your code follows, how your backend
|
|
59
|
-
talks to your frontend, and what breaks when something changes. From
|
|
60
|
-
that point on, every agent gets the full picture before it writes a
|
|
61
|
-
line.
|
|
62
|
-
|
|
63
|
-
It does five things:
|
|
64
|
-
|
|
65
|
-
1. **One search, everything you need.** An agent describes what it
|
|
66
|
-
wants to do. dotscope returns the relevant files, the functions
|
|
67
|
-
they call, the contracts they must honor, the conventions they must
|
|
68
|
-
follow, and which files are locked by other agents. One call. Not
|
|
69
|
-
five.
|
|
70
|
-
|
|
71
|
-
2. **Enforces contracts across languages.** Your Python backend and
|
|
72
|
-
TypeScript frontend share an invisible API contract. dotscope
|
|
73
|
-
extracts routes from FastAPI, Flask, and DRF. It extracts fetch
|
|
74
|
-
calls from React and Angular. It links them automatically. Change
|
|
75
|
-
a Django ViewSet without updating the Angular component? Blocked.
|
|
76
|
-
|
|
77
|
-
3. **Routes files to the right place.** Before an agent creates a
|
|
78
|
-
file, it asks dotscope where it should go. dotscope reads the
|
|
79
|
-
dependency graph and routes the file there. No more `src/utils/`
|
|
80
|
-
graveyards.
|
|
81
|
-
|
|
82
|
-
4. **Coordinates multiple agents.** When Agent A starts working on
|
|
83
|
-
billing, dotscope locks the blast radius. Agent B works on auth
|
|
84
|
-
without collision. If they touch the same function, the AST merge
|
|
85
|
-
driver resolves it semantically — not with conflict markers.
|
|
86
|
-
|
|
87
|
-
5. **Gets smarter with every commit.** Which search results did agents
|
|
88
|
-
actually use? Which did they ignore? dotscope tracks this and
|
|
89
|
-
adjusts. Conventions that hold up get enforced harder. Rules that
|
|
90
|
-
get overridden get quieter.
|
|
91
|
-
|
|
92
|
-
Here's what it looks like on a real codebase:
|
|
93
|
-
|
|
94
|
-
```
|
|
95
|
-
$ dotscope ingest
|
|
96
|
-
|
|
97
|
-
Analyzing dependency graph...
|
|
98
|
-
Mining git history...
|
|
99
|
-
Discovering conventions...
|
|
100
|
-
|
|
101
|
-
Discoveries:
|
|
102
|
-
- version.py and environment.prod.ts always change together
|
|
103
|
-
- workflow-edit-dialog.component.ts and models.py are tightly coupled
|
|
104
|
-
|
|
105
|
-
Validation (49 commits backtested):
|
|
106
|
-
- Overall recall: 78%
|
|
107
|
-
- Token reduction: 67% (1.3M → 437K avg)
|
|
108
|
-
|
|
109
|
-
Output: 3 .scope files written.
|
|
110
|
-
|
|
111
|
-
$ dotscope check --backtest
|
|
112
|
-
|
|
113
|
-
13 issues flagged across 7 commits:
|
|
114
|
-
- models.py changes need the Angular component updated
|
|
115
|
-
- consumer.py changes need matching parser test updates
|
|
116
|
-
- views.py changes typically need test_api_search.py updated
|
|
117
|
-
|
|
118
|
-
3 commits were clean.
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
One command. Point it at anything.
|
|
122
|
-
|
|
123
|
-
```
|
|
124
|
-
pip install dotscope && dotscope init
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
[How It Works](docs/how-it-works.md) · [Scope Files](docs/scope-file.md) · [Agent Instructions](AGENT_INSTRUCTIONS.md) · [MIT](LICENSE)
|