attocode-code-intel 0.1.0__py3-none-any.whl
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.
- attocode_code_intel-0.1.0.dist-info/METADATA +221 -0
- attocode_code_intel-0.1.0.dist-info/RECORD +345 -0
- attocode_code_intel-0.1.0.dist-info/WHEEL +4 -0
- attocode_code_intel-0.1.0.dist-info/entry_points.txt +2 -0
- attocode_code_intel-0.1.0.dist-info/licenses/LICENSE +21 -0
- attocode_intel/GUIDELINES.md +432 -0
- attocode_intel/__init__.py +52 -0
- attocode_intel/_internal/__init__.py +1 -0
- attocode_intel/_internal/errors/__init__.py +126 -0
- attocode_intel/_internal/integrations/__init__.py +1 -0
- attocode_intel/_internal/integrations/context/__init__.py +1 -0
- attocode_intel/_internal/integrations/context/architecture_drift.py +354 -0
- attocode_intel/_internal/integrations/context/ast_chunker.py +202 -0
- attocode_intel/_internal/integrations/context/ast_service.py +1483 -0
- attocode_intel/_internal/integrations/context/blob_oid.py +423 -0
- attocode_intel/_internal/integrations/context/cache_manifest.py +221 -0
- attocode_intel/_internal/integrations/context/cas.py +466 -0
- attocode_intel/_internal/integrations/context/code_analyzer.py +528 -0
- attocode_intel/_internal/integrations/context/codebase_ast.py +1461 -0
- attocode_intel/_internal/integrations/context/codebase_context.py +1736 -0
- attocode_intel/_internal/integrations/context/cross_mode.py +263 -0
- attocode_intel/_internal/integrations/context/cross_references.py +616 -0
- attocode_intel/_internal/integrations/context/embedding_rotation.py +597 -0
- attocode_intel/_internal/integrations/context/embeddings.py +282 -0
- attocode_intel/_internal/integrations/context/frecency.py +427 -0
- attocode_intel/_internal/integrations/context/fuzzy.py +320 -0
- attocode_intel/_internal/integrations/context/hierarchical_explorer.py +331 -0
- attocode_intel/_internal/integrations/context/hydration.py +90 -0
- attocode_intel/_internal/integrations/context/index_repair.py +87 -0
- attocode_intel/_internal/integrations/context/index_store.py +586 -0
- attocode_intel/_internal/integrations/context/memory_store.py +602 -0
- attocode_intel/_internal/integrations/context/module_resolution.py +52 -0
- attocode_intel/_internal/integrations/context/query_constraints.py +361 -0
- attocode_intel/_internal/integrations/context/query_history.py +417 -0
- attocode_intel/_internal/integrations/context/reranker.py +351 -0
- attocode_intel/_internal/integrations/context/semantic_search.py +2931 -0
- attocode_intel/_internal/integrations/context/syntax_evidence.py +94 -0
- attocode_intel/_internal/integrations/context/systemone_ranker.py +245 -0
- attocode_intel/_internal/integrations/context/temporal_coupling.py +411 -0
- attocode_intel/_internal/integrations/context/trigram_index.py +820 -0
- attocode_intel/_internal/integrations/context/trigram_regex.py +171 -0
- attocode_intel/_internal/integrations/context/ts_parser.py +2199 -0
- attocode_intel/_internal/integrations/context/vector_store.py +795 -0
- attocode_intel/_internal/integrations/feature_flags/__init__.py +357 -0
- attocode_intel/_internal/integrations/lsp/__init__.py +1 -0
- attocode_intel/_internal/integrations/lsp/client.py +1140 -0
- attocode_intel/_internal/integrations/mcp/__init__.py +1 -0
- attocode_intel/_internal/integrations/mcp/client.py +253 -0
- attocode_intel/_internal/integrations/security/__init__.py +1 -0
- attocode_intel/_internal/integrations/security/custom_rules.py +176 -0
- attocode_intel/_internal/integrations/security/dataflow.py +522 -0
- attocode_intel/_internal/integrations/security/dependency_audit.py +303 -0
- attocode_intel/_internal/integrations/security/matcher.py +44 -0
- attocode_intel/_internal/integrations/security/patterns.py +724 -0
- attocode_intel/_internal/integrations/security/scanner.py +351 -0
- attocode_intel/_internal/integrations/utilities/__init__.py +1 -0
- attocode_intel/_internal/integrations/utilities/ignore.py +64 -0
- attocode_intel/_internal/integrations/utilities/token_estimate.py +51 -0
- attocode_intel/_internal/tricks/__init__.py +1 -0
- attocode_intel/_internal/tricks/recursive_context.py +357 -0
- attocode_intel/_internal/types/__init__.py +1 -0
- attocode_intel/_internal/types/events.py +289 -0
- attocode_intel/_internal/types/severity.py +15 -0
- attocode_intel/_shared.py +341 -0
- attocode_intel/analysis_coverage.py +56 -0
- attocode_intel/api/__init__.py +1 -0
- attocode_intel/api/access.py +32 -0
- attocode_intel/api/app.py +247 -0
- attocode_intel/api/auth/__init__.py +128 -0
- attocode_intel/api/auth/api_keys.py +61 -0
- attocode_intel/api/auth/context.py +34 -0
- attocode_intel/api/auth/jwt.py +66 -0
- attocode_intel/api/auth/oauth.py +146 -0
- attocode_intel/api/auth/passwords.py +15 -0
- attocode_intel/api/deps.py +351 -0
- attocode_intel/api/knowledge_bridge.py +13 -0
- attocode_intel/api/mcp_transport.py +51 -0
- attocode_intel/api/middleware.py +411 -0
- attocode_intel/api/models.py +698 -0
- attocode_intel/api/providers/__init__.py +1 -0
- attocode_intel/api/providers/db_provider.py +1106 -0
- attocode_intel/api/providers/local_provider.py +476 -0
- attocode_intel/api/providers/remote_provider.py +740 -0
- attocode_intel/api/repository_source.py +21 -0
- attocode_intel/api/routes/__init__.py +1 -0
- attocode_intel/api/routes/_pin_helper.py +158 -0
- attocode_intel/api/routes/activity.py +148 -0
- attocode_intel/api/routes/adr.py +102 -0
- attocode_intel/api/routes/analysis.py +515 -0
- attocode_intel/api/routes/api_keys.py +170 -0
- attocode_intel/api/routes/auth.py +428 -0
- attocode_intel/api/routes/branches.py +262 -0
- attocode_intel/api/routes/cross_repo_search.py +198 -0
- attocode_intel/api/routes/embeddings.py +386 -0
- attocode_intel/api/routes/files.py +132 -0
- attocode_intel/api/routes/files_v2.py +388 -0
- attocode_intel/api/routes/gc.py +322 -0
- attocode_intel/api/routes/git_v2.py +433 -0
- attocode_intel/api/routes/graph.py +174 -0
- attocode_intel/api/routes/graph_viz.py +160 -0
- attocode_intel/api/routes/health.py +62 -0
- attocode_intel/api/routes/history.py +175 -0
- attocode_intel/api/routes/jobs.py +84 -0
- attocode_intel/api/routes/learning.py +205 -0
- attocode_intel/api/routes/lsp.py +272 -0
- attocode_intel/api/routes/notify.py +623 -0
- attocode_intel/api/routes/operations.py +27 -0
- attocode_intel/api/routes/orgs.py +924 -0
- attocode_intel/api/routes/preferences.py +100 -0
- attocode_intel/api/routes/presence.py +42 -0
- attocode_intel/api/routes/projects.py +116 -0
- attocode_intel/api/routes/repos.py +47 -0
- attocode_intel/api/routes/search.py +180 -0
- attocode_intel/api/routes/snapshots.py +614 -0
- attocode_intel/api/routes/webhooks.py +313 -0
- attocode_intel/api/routes/websocket.py +116 -0
- attocode_intel/api/static/graph.html +239 -0
- attocode_intel/api/utils.py +96 -0
- attocode_intel/artifacts/__init__.py +45 -0
- attocode_intel/artifacts/hashing.py +230 -0
- attocode_intel/artifacts/provenance.py +190 -0
- attocode_intel/artifacts/retrieval_pin.py +159 -0
- attocode_intel/audit.py +59 -0
- attocode_intel/bug_finder.py +206 -0
- attocode_intel/bundle.py +80 -0
- attocode_intel/catalog.py +242 -0
- attocode_intel/change_review.py +75 -0
- attocode_intel/cli.py +3062 -0
- attocode_intel/community.py +63 -0
- attocode_intel/confidence/__init__.py +144 -0
- attocode_intel/confidence/jev.py +234 -0
- attocode_intel/confidence/llm.py +330 -0
- attocode_intel/confidence/redact.py +44 -0
- attocode_intel/confidence/settings.py +74 -0
- attocode_intel/config.py +256 -0
- attocode_intel/crypto.py +31 -0
- attocode_intel/db/__init__.py +7 -0
- attocode_intel/db/base.py +33 -0
- attocode_intel/db/engine.py +61 -0
- attocode_intel/db/models.py +529 -0
- attocode_intel/entrypoint.py +185 -0
- attocode_intel/focused_evidence.py +130 -0
- attocode_intel/freshness.py +154 -0
- attocode_intel/gateway.py +734 -0
- attocode_intel/git/__init__.py +7 -0
- attocode_intel/git/credentials.py +75 -0
- attocode_intel/git/manager.py +493 -0
- attocode_intel/git/models.py +96 -0
- attocode_intel/git/storage.py +98 -0
- attocode_intel/graph_query_parser.py +761 -0
- attocode_intel/helpers.py +712 -0
- attocode_intel/indexing/__init__.py +29 -0
- attocode_intel/indexing/debouncer.py +136 -0
- attocode_intel/indexing/delta_indexer.py +151 -0
- attocode_intel/indexing/full_indexer.py +323 -0
- attocode_intel/indexing/incremental.py +240 -0
- attocode_intel/indexing/parser.py +403 -0
- attocode_intel/indexing/summarizer.py +264 -0
- attocode_intel/installer.py +1896 -0
- attocode_intel/knowledge.py +269 -0
- attocode_intel/local_knowledge.py +77 -0
- attocode_intel/migrations/alembic.ini +36 -0
- attocode_intel/migrations/env.py +71 -0
- attocode_intel/migrations/script.py.mako +27 -0
- attocode_intel/migrations/versions/001_initial_schema.py +219 -0
- attocode_intel/migrations/versions/002_branch_version_and_embeddings.py +61 -0
- attocode_intel/migrations/versions/003_embedding_uniqueness_and_cascade.py +51 -0
- attocode_intel/migrations/versions/004_audit_events.py +38 -0
- attocode_intel/migrations/versions/005_user_preferences.py +30 -0
- attocode_intel/migrations/versions/006_google_oauth.py +27 -0
- attocode_intel/migrations/versions/007_pgvector_embeddings.py +28 -0
- attocode_intel/migrations/versions/008_symbol_references.py +37 -0
- attocode_intel/migrations/versions/009_webhook_secret_encryption.py +25 -0
- attocode_intel/migrations/versions/010_add_commits_table.py +40 -0
- attocode_intel/migrations/versions/011_commit_changed_files.py +25 -0
- attocode_intel/migrations/versions/012_branch_merged_at.py +25 -0
- attocode_intel/migrations/versions/013_revoked_tokens.py +32 -0
- attocode_intel/migrations/versions/014_blame_hunks.py +40 -0
- attocode_intel/migrations/versions/015_commit_file_stats.py +40 -0
- attocode_intel/migrations/versions/016_embedding_provenance_columns.py +179 -0
- attocode_intel/migrations/versions/017_provenance_table.py +102 -0
- attocode_intel/migrations/versions/018_repo_snapshots.py +178 -0
- attocode_intel/migrations/versions/019_symref_caller.py +42 -0
- attocode_intel/migrations/versions/020_shared_knowledge.py +29 -0
- attocode_intel/onboarding.py +258 -0
- attocode_intel/output.py +178 -0
- attocode_intel/precision.py +133 -0
- attocode_intel/presence.py +160 -0
- attocode_intel/probe.py +110 -0
- attocode_intel/project_dir.py +97 -0
- attocode_intel/pubsub.py +113 -0
- attocode_intel/query_ranking.py +242 -0
- attocode_intel/readiness.py +972 -0
- attocode_intel/redis.py +51 -0
- attocode_intel/reference_pages.py +60 -0
- attocode_intel/remote.py +131 -0
- attocode_intel/repo_ranker.py +246 -0
- attocode_intel/request_context.py +82 -0
- attocode_intel/rules/__init__.py +28 -0
- attocode_intel/rules/ci.py +320 -0
- attocode_intel/rules/combinators.py +293 -0
- attocode_intel/rules/enricher.py +127 -0
- attocode_intel/rules/evolution.py +452 -0
- attocode_intel/rules/executor.py +531 -0
- attocode_intel/rules/filters/__init__.py +5 -0
- attocode_intel/rules/filters/pipeline.py +151 -0
- attocode_intel/rules/formatter.py +198 -0
- attocode_intel/rules/hygiene.py +242 -0
- attocode_intel/rules/importers/__init__.py +1 -0
- attocode_intel/rules/importers/semgrep.py +382 -0
- attocode_intel/rules/loader.py +292 -0
- attocode_intel/rules/marketplace.py +375 -0
- attocode_intel/rules/metavar.py +181 -0
- attocode_intel/rules/model.py +317 -0
- attocode_intel/rules/packs/__init__.py +1 -0
- attocode_intel/rules/packs/community/_license_templates/Apache-2.0.txt +176 -0
- attocode_intel/rules/packs/community/_license_templates/MIT.txt +21 -0
- attocode_intel/rules/packs/community/bandit-python/LICENSE +176 -0
- attocode_intel/rules/packs/community/bandit-python/NOTICE +13 -0
- attocode_intel/rules/packs/community/bandit-python/PORTING.md +23 -0
- attocode_intel/rules/packs/community/bandit-python/manifest.yaml +14 -0
- attocode_intel/rules/packs/community/bandit-python/rules/B105-hardcoded-password.yaml +23 -0
- attocode_intel/rules/packs/community/bandit-python/rules/B303-weak-md5.yaml +21 -0
- attocode_intel/rules/packs/community/bandit-python/rules/B304-weak-des.yaml +20 -0
- attocode_intel/rules/packs/community/bandit-python/rules/B307-use-of-eval.yaml +22 -0
- attocode_intel/rules/packs/community/bandit-python/rules/B324-weak-sha1.yaml +21 -0
- attocode_intel/rules/packs/community/bandit-python/rules/B501-no-cert-validation.yaml +23 -0
- attocode_intel/rules/packs/community/bandit-python/rules/B602-shell-true.yaml +22 -0
- attocode_intel/rules/packs/community/bandit-python/rules/B608-sqli.yaml +22 -0
- attocode_intel/rules/packs/community/eslint-typescript/LICENSE +21 -0
- attocode_intel/rules/packs/community/eslint-typescript/NOTICE +13 -0
- attocode_intel/rules/packs/community/eslint-typescript/PORTING.md +23 -0
- attocode_intel/rules/packs/community/eslint-typescript/manifest.yaml +14 -0
- attocode_intel/rules/packs/community/eslint-typescript/rules/eqeqeq.yaml +20 -0
- attocode_intel/rules/packs/community/eslint-typescript/rules/no-eval.yaml +22 -0
- attocode_intel/rules/packs/community/eslint-typescript/rules/no-implied-eval.yaml +20 -0
- attocode_intel/rules/packs/community/eslint-typescript/rules/no-new-func.yaml +21 -0
- attocode_intel/rules/packs/community/eslint-typescript/rules/no-throw-literal.yaml +19 -0
- attocode_intel/rules/packs/community/eslint-typescript/rules/no-var.yaml +20 -0
- attocode_intel/rules/packs/community/eslint-typescript/rules/no-with.yaml +18 -0
- attocode_intel/rules/packs/community/gosec-go/LICENSE +176 -0
- attocode_intel/rules/packs/community/gosec-go/NOTICE +13 -0
- attocode_intel/rules/packs/community/gosec-go/PORTING.md +23 -0
- attocode_intel/rules/packs/community/gosec-go/manifest.yaml +14 -0
- attocode_intel/rules/packs/community/gosec-go/rules/G101-hardcoded-credentials.yaml +22 -0
- attocode_intel/rules/packs/community/gosec-go/rules/G102-bind-all-interfaces.yaml +21 -0
- attocode_intel/rules/packs/community/gosec-go/rules/G103-unsafe-block.yaml +21 -0
- attocode_intel/rules/packs/community/gosec-go/rules/G201-sql-format.yaml +21 -0
- attocode_intel/rules/packs/community/gosec-go/rules/G304-file-inclusion.yaml +23 -0
- attocode_intel/rules/packs/community/gosec-go/rules/G401-weak-cipher.yaml +20 -0
- attocode_intel/rules/packs/community/gosec-go/rules/G402-tls-min-version.yaml +20 -0
- attocode_intel/rules/packs/community/gosec-go/rules/G501-md5-import.yaml +21 -0
- attocode_intel/rules/packs/examples/cpp/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/cpp/rules/security.yaml +90 -0
- attocode_intel/rules/packs/examples/cpp/rules/structural.yaml +42 -0
- attocode_intel/rules/packs/examples/csharp/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/csharp/rules/security.yaml +69 -0
- attocode_intel/rules/packs/examples/csharp/rules/structural.yaml +42 -0
- attocode_intel/rules/packs/examples/go/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/go/rules/performance.yaml +136 -0
- attocode_intel/rules/packs/examples/go/rules/security.yaml +48 -0
- attocode_intel/rules/packs/examples/go/rules/structural.yaml +58 -0
- attocode_intel/rules/packs/examples/go/taint/sanitizers.yaml +24 -0
- attocode_intel/rules/packs/examples/go/taint/sinks.yaml +51 -0
- attocode_intel/rules/packs/examples/go/taint/sources.yaml +26 -0
- attocode_intel/rules/packs/examples/java/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/java/rules/correctness.yaml +55 -0
- attocode_intel/rules/packs/examples/java/rules/structural.yaml +48 -0
- attocode_intel/rules/packs/examples/java/taint/sinks.yaml +37 -0
- attocode_intel/rules/packs/examples/java/taint/sources.yaml +21 -0
- attocode_intel/rules/packs/examples/kotlin/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/kotlin/rules/correctness.yaml +50 -0
- attocode_intel/rules/packs/examples/kotlin/rules/structural.yaml +38 -0
- attocode_intel/rules/packs/examples/php/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/php/rules/security.yaml +66 -0
- attocode_intel/rules/packs/examples/php/rules/structural.yaml +41 -0
- attocode_intel/rules/packs/examples/python/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/python/rules/performance.yaml +90 -0
- attocode_intel/rules/packs/examples/python/rules/structural.yaml +55 -0
- attocode_intel/rules/packs/examples/ruby/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/ruby/rules/security.yaml +73 -0
- attocode_intel/rules/packs/examples/ruby/rules/structural.yaml +41 -0
- attocode_intel/rules/packs/examples/rust/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/rust/rules/correctness.yaml +51 -0
- attocode_intel/rules/packs/examples/rust/rules/structural.yaml +49 -0
- attocode_intel/rules/packs/examples/typescript/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/typescript/rules/performance.yaml +70 -0
- attocode_intel/rules/packs/examples/typescript/rules/structural.yaml +48 -0
- attocode_intel/rules/packs/pack_loader.py +244 -0
- attocode_intel/rules/plugins/__init__.py +1 -0
- attocode_intel/rules/plugins/plugin_loader.py +132 -0
- attocode_intel/rules/profiling.py +332 -0
- attocode_intel/rules/registry.py +213 -0
- attocode_intel/rules/sarif.py +187 -0
- attocode_intel/rules/synthesis.py +420 -0
- attocode_intel/rules/testing.py +326 -0
- attocode_intel/server.py +734 -0
- attocode_intel/service.py +3416 -0
- attocode_intel/sharing.py +57 -0
- attocode_intel/storage/__init__.py +6 -0
- attocode_intel/storage/branch_overlay.py +352 -0
- attocode_intel/storage/content_store.py +220 -0
- attocode_intel/storage/dependency_store.py +143 -0
- attocode_intel/storage/diff_engine.py +187 -0
- attocode_intel/storage/embedding_store.py +594 -0
- attocode_intel/storage/provenance_store.py +137 -0
- attocode_intel/storage/security_scanner_db.py +164 -0
- attocode_intel/storage/symbol_store.py +160 -0
- attocode_intel/structural_evidence.py +144 -0
- attocode_intel/symbol_inspection.py +141 -0
- attocode_intel/symbol_links.py +167 -0
- attocode_intel/telemetry.py +42 -0
- attocode_intel/test_ranking.py +73 -0
- attocode_intel/testing/__init__.py +43 -0
- attocode_intel/testing/fixtures.py +122 -0
- attocode_intel/testing/helpers.py +75 -0
- attocode_intel/testing/mocks.py +99 -0
- attocode_intel/tools/__init__.py +2 -0
- attocode_intel/tools/adr_tools.py +628 -0
- attocode_intel/tools/analysis_tools.py +382 -0
- attocode_intel/tools/composite_tools.py +695 -0
- attocode_intel/tools/cross_mode_tools.py +173 -0
- attocode_intel/tools/dead_code_tools.py +582 -0
- attocode_intel/tools/distill_tools.py +353 -0
- attocode_intel/tools/frecency_tools.py +220 -0
- attocode_intel/tools/fuzzy_tools.py +255 -0
- attocode_intel/tools/history_tools.py +486 -0
- attocode_intel/tools/learning_tools.py +222 -0
- attocode_intel/tools/lsp_tools.py +218 -0
- attocode_intel/tools/maintenance_tools.py +1662 -0
- attocode_intel/tools/navigation_tools.py +220 -0
- attocode_intel/tools/overlay_tools.py +540 -0
- attocode_intel/tools/pin_store.py +432 -0
- attocode_intel/tools/pin_tools.py +266 -0
- attocode_intel/tools/query_constraints_tools.py +262 -0
- attocode_intel/tools/query_history_tools.py +158 -0
- attocode_intel/tools/readiness_tools.py +44 -0
- attocode_intel/tools/rule_tools.py +992 -0
- attocode_intel/tools/search_tools.py +770 -0
- attocode_intel/tools/snapshot_tools.py +624 -0
- attocode_intel/workers/__init__.py +1 -0
- attocode_intel/workers/job_utils.py +111 -0
- attocode_intel/workers/jobs.py +573 -0
- attocode_intel/workers/run.py +30 -0
- attocode_intel/workers/settings.py +61 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
"""One catalog for protocol schemas, profiles, and documentation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from copy import deepcopy
|
|
6
|
+
|
|
7
|
+
from mcp.types import Tool, ToolAnnotations
|
|
8
|
+
|
|
9
|
+
INSTRUCTIONS = (
|
|
10
|
+
"If these tools are deferred (for example in Claude Code), load them with ToolSearch, for example "
|
|
11
|
+
"'attocode-code-intel inspect_symbol'. For a known symbol, call inspect_symbol. For unfamiliar behavior, "
|
|
12
|
+
"call bootstrap with a task_hint. Use search_symbols to find names, and impact_analysis and suggest_tests "
|
|
13
|
+
"to plan and check a change. Grep stays useful for literal text. Cite each excerpt range separately. "
|
|
14
|
+
"An incomplete index does not prove that a dependency is absent. {watch} Keep uncommitted code local."
|
|
15
|
+
)
|
|
16
|
+
# ponytail: two variants of one sentence; the server knows whether it watches files.
|
|
17
|
+
WATCHING = "The server watches the project, so it indexes your edits without a call."
|
|
18
|
+
NOT_WATCHING = "This server does not watch files: after edits, call notify_file_changed."
|
|
19
|
+
INSTRUCTIONS, INSTRUCTIONS_NO_WATCH = INSTRUCTIONS.format(watch=WATCHING), INSTRUCTIONS.format(watch=NOT_WATCHING)
|
|
20
|
+
DAILY = frozenset(
|
|
21
|
+
{
|
|
22
|
+
"bootstrap",
|
|
23
|
+
"project_summary",
|
|
24
|
+
"explore_codebase",
|
|
25
|
+
"search_symbols",
|
|
26
|
+
"inspect_symbol",
|
|
27
|
+
"semantic_search",
|
|
28
|
+
"fast_search",
|
|
29
|
+
"symbols",
|
|
30
|
+
"relevant_context",
|
|
31
|
+
"cross_references",
|
|
32
|
+
"dependencies",
|
|
33
|
+
"call_graph",
|
|
34
|
+
"impact_analysis",
|
|
35
|
+
"suggest_tests",
|
|
36
|
+
"review_change",
|
|
37
|
+
"notify_file_changed",
|
|
38
|
+
"hydration_status",
|
|
39
|
+
"recall",
|
|
40
|
+
"record_learning",
|
|
41
|
+
"list_learnings",
|
|
42
|
+
"learning_feedback",
|
|
43
|
+
}
|
|
44
|
+
)
|
|
45
|
+
# Remote daily keeps the learnings for team knowledge. A local daily session leaves them out:
|
|
46
|
+
# their schemas cost about 1,600 tokens in every model request.
|
|
47
|
+
LEARNING = frozenset({"recall", "record_learning", "list_learnings", "learning_feedback", "update_learning"})
|
|
48
|
+
WRITES = frozenset(
|
|
49
|
+
[
|
|
50
|
+
"notify_file_changed",
|
|
51
|
+
"record_adr",
|
|
52
|
+
"update_adr_status",
|
|
53
|
+
"pin_current",
|
|
54
|
+
"pin_delete",
|
|
55
|
+
"track_file_access",
|
|
56
|
+
"clear_frecency",
|
|
57
|
+
"record_learning",
|
|
58
|
+
"learning_feedback",
|
|
59
|
+
"update_learning",
|
|
60
|
+
"reindex",
|
|
61
|
+
"track_query_result",
|
|
62
|
+
"clear_query_history",
|
|
63
|
+
"migrate_cache",
|
|
64
|
+
"clear_symbols",
|
|
65
|
+
"clear_embeddings",
|
|
66
|
+
"clear_trigrams",
|
|
67
|
+
"clear_kw_index",
|
|
68
|
+
"clear_learnings",
|
|
69
|
+
"clear_adrs",
|
|
70
|
+
"clear_all",
|
|
71
|
+
"cas_clear",
|
|
72
|
+
"export_learnings",
|
|
73
|
+
"import_learnings",
|
|
74
|
+
"export_adrs_markdown",
|
|
75
|
+
"import_adrs_markdown",
|
|
76
|
+
"gc_run",
|
|
77
|
+
"embeddings_rotate_start",
|
|
78
|
+
"embeddings_rotate_step",
|
|
79
|
+
"embeddings_rotate_cutover",
|
|
80
|
+
"embeddings_rotate_gc_old",
|
|
81
|
+
"embeddings_rotate_abort",
|
|
82
|
+
"snapshot_create",
|
|
83
|
+
"snapshot_delete",
|
|
84
|
+
"snapshot_restore",
|
|
85
|
+
"overlay_create",
|
|
86
|
+
"overlay_activate",
|
|
87
|
+
"overlay_delete",
|
|
88
|
+
"install_pack",
|
|
89
|
+
"register_rule",
|
|
90
|
+
"rule_feedback",
|
|
91
|
+
"evolve_rules",
|
|
92
|
+
"synthesize_rule",
|
|
93
|
+
"rule_hygiene",
|
|
94
|
+
"install_community_pack",
|
|
95
|
+
"import_rules",
|
|
96
|
+
]
|
|
97
|
+
)
|
|
98
|
+
REMOTE_WRITES = frozenset(
|
|
99
|
+
{"record_learning", "learning_feedback", "record_adr", "update_adr_status", "update_learning"}
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def compact_schema(node, names=False):
|
|
104
|
+
"""The input schema that a model reads: no pydantic titles, and no null branch for an optional argument.
|
|
105
|
+
|
|
106
|
+
NAMES marks a map of property names, whose keys are not schema keywords. Validation keeps the full
|
|
107
|
+
schema, so an explicit null stays valid.
|
|
108
|
+
"""
|
|
109
|
+
if isinstance(node, list):
|
|
110
|
+
return [compact_schema(item) for item in node]
|
|
111
|
+
if not isinstance(node, dict):
|
|
112
|
+
return node
|
|
113
|
+
if names:
|
|
114
|
+
return {key: compact_schema(value) for key, value in node.items()}
|
|
115
|
+
node = {key: compact_schema(value, key in ("properties", "$defs", "definitions"))
|
|
116
|
+
for key, value in node.items() if key != "title"}
|
|
117
|
+
options = node.get("anyOf")
|
|
118
|
+
if (isinstance(options, list) and len(options) == 2 and {"type": "null"} in options
|
|
119
|
+
and "default" in node and node["default"] is None):
|
|
120
|
+
del node["anyOf"], node["default"]
|
|
121
|
+
node.update(next(option for option in options if option != {"type": "null"}))
|
|
122
|
+
return node
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def remote_available(name):
|
|
126
|
+
return not is_write(name) or name in REMOTE_WRITES
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def registered_tools():
|
|
130
|
+
from attocode_intel.server import mcp
|
|
131
|
+
|
|
132
|
+
return mcp._tool_manager._tools
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def is_write(name: str) -> bool:
|
|
136
|
+
return name in WRITES
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def tool_catalog(profile: str = "full", *, remote: bool = False) -> list[Tool]:
|
|
140
|
+
if profile not in ("daily", "full"):
|
|
141
|
+
raise ValueError("profile must be daily or full")
|
|
142
|
+
result = []
|
|
143
|
+
for name, tool in registered_tools().items():
|
|
144
|
+
if profile == "daily" and name not in DAILY:
|
|
145
|
+
continue
|
|
146
|
+
if remote and not remote_available(name):
|
|
147
|
+
continue
|
|
148
|
+
schema = deepcopy(tool.parameters)
|
|
149
|
+
schema.setdefault("properties", {}).update(
|
|
150
|
+
{
|
|
151
|
+
"workspace": {
|
|
152
|
+
"type": "string",
|
|
153
|
+
"description": "Local project path or authorized remote repository ID.",
|
|
154
|
+
},
|
|
155
|
+
"revision": {
|
|
156
|
+
"type": "string",
|
|
157
|
+
"description": "Remote branch or commit; omitted uses the default branch.",
|
|
158
|
+
},
|
|
159
|
+
}
|
|
160
|
+
)
|
|
161
|
+
schema["properties"]["max_tokens"] = {
|
|
162
|
+
"type": "integer",
|
|
163
|
+
"minimum": 1,
|
|
164
|
+
"maximum": 32000,
|
|
165
|
+
"default": 8000,
|
|
166
|
+
"description": "Maximum tokens in the complete readable response, including provenance.",
|
|
167
|
+
}
|
|
168
|
+
result.append(
|
|
169
|
+
Tool(
|
|
170
|
+
name=name,
|
|
171
|
+
description=tool.description,
|
|
172
|
+
inputSchema=schema,
|
|
173
|
+
annotations=ToolAnnotations(
|
|
174
|
+
readOnlyHint=not is_write(name),
|
|
175
|
+
destructiveHint=name.startswith(("clear_", "delete_"))
|
|
176
|
+
or name
|
|
177
|
+
in {"snapshot_delete", "snapshot_restore", "overlay_delete", "pin_delete"},
|
|
178
|
+
),
|
|
179
|
+
)
|
|
180
|
+
)
|
|
181
|
+
result.extend(
|
|
182
|
+
[
|
|
183
|
+
Tool(
|
|
184
|
+
name="update_learning",
|
|
185
|
+
description="Edit or archive a repository learning.",
|
|
186
|
+
inputSchema={
|
|
187
|
+
"type": "object",
|
|
188
|
+
"required": ["learning_id"],
|
|
189
|
+
"properties": {
|
|
190
|
+
"learning_id": {"type": "integer"},
|
|
191
|
+
"description": {"type": "string"},
|
|
192
|
+
"details": {"type": "string"},
|
|
193
|
+
"status": {"type": "string", "enum": ["active", "archived"]},
|
|
194
|
+
"confidence": {"type": "number", "minimum": 0, "maximum": 1},
|
|
195
|
+
"workspace": {"type": "string"},
|
|
196
|
+
"revision": {"type": "string"},
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
annotations=ToolAnnotations(readOnlyHint=False),
|
|
200
|
+
),
|
|
201
|
+
Tool(
|
|
202
|
+
name="cross_repo_search",
|
|
203
|
+
description="Search explicitly selected authorized repositories; results retain repository and commit provenance.",
|
|
204
|
+
inputSchema={
|
|
205
|
+
"type": "object",
|
|
206
|
+
"required": ["query", "workspaces"],
|
|
207
|
+
"properties": {
|
|
208
|
+
"query": {"type": "string"},
|
|
209
|
+
"workspaces": {
|
|
210
|
+
"type": "array",
|
|
211
|
+
"items": {"type": "string"},
|
|
212
|
+
"minItems": 1,
|
|
213
|
+
"maxItems": 20,
|
|
214
|
+
},
|
|
215
|
+
"top_k": {"type": "integer", "minimum": 1, "maximum": 50},
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
annotations=ToolAnnotations(readOnlyHint=True),
|
|
219
|
+
),
|
|
220
|
+
]
|
|
221
|
+
)
|
|
222
|
+
result.append(
|
|
223
|
+
Tool(
|
|
224
|
+
name="capabilities",
|
|
225
|
+
description="Available tools, profiles, workspace selection, and optional enhancements.",
|
|
226
|
+
inputSchema={
|
|
227
|
+
"type": "object",
|
|
228
|
+
"properties": {"workspace": {"type": "string"}, "revision": {"type": "string"}},
|
|
229
|
+
},
|
|
230
|
+
annotations=ToolAnnotations(readOnlyHint=True),
|
|
231
|
+
)
|
|
232
|
+
)
|
|
233
|
+
# Apply common arguments to synthetic tools too (knowledge and cross-repo search).
|
|
234
|
+
for tool in result:
|
|
235
|
+
tool.inputSchema.setdefault("properties", {}).setdefault("max_tokens", {
|
|
236
|
+
"type": "integer", "minimum": 1, "maximum": 32000, "default": 8000,
|
|
237
|
+
"description": "Readable response budget; daily MCP budgets the entire serialized result.",
|
|
238
|
+
})
|
|
239
|
+
if not remote: # local analysis always reads the working tree
|
|
240
|
+
tool.inputSchema["properties"].pop("revision", None)
|
|
241
|
+
local_daily = profile == "daily" and not remote
|
|
242
|
+
return [tool for tool in result if not (local_daily and tool.name in LEARNING)]
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Compose findings as data so incomplete passes cannot become a clean review."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import asdict
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def review(service, files, mode="full"):
|
|
10
|
+
from attocode_intel.tools.composite_tools import _git_modified_files
|
|
11
|
+
|
|
12
|
+
files = files if files is not None else _git_modified_files(service.project_dir)
|
|
13
|
+
if mode not in {"quick", "full"}:
|
|
14
|
+
raise ValueError("mode must be quick or full")
|
|
15
|
+
root = Path(service.project_dir)
|
|
16
|
+
selected = {str((root / path).resolve().relative_to(root)) for path in files}
|
|
17
|
+
findings, passes = [], []
|
|
18
|
+
if not selected:
|
|
19
|
+
return {
|
|
20
|
+
"files": [],
|
|
21
|
+
"findings": [],
|
|
22
|
+
"passes": [],
|
|
23
|
+
"complete": False,
|
|
24
|
+
"assessment": "No files selected; review did not run.",
|
|
25
|
+
}
|
|
26
|
+
try:
|
|
27
|
+
report = service.security_scan_data(mode="full")
|
|
28
|
+
for finding in report["findings"]:
|
|
29
|
+
path = str((root / finding["file_path"]).resolve().relative_to(root))
|
|
30
|
+
if path in selected:
|
|
31
|
+
findings.append({**finding, "file_path": path, "pass": "security"})
|
|
32
|
+
passes.append({"name": "security", "status": "completed"})
|
|
33
|
+
except Exception as exc:
|
|
34
|
+
passes.append({"name": "security", "status": "failed", "error": str(exc)})
|
|
35
|
+
if mode == "full":
|
|
36
|
+
try:
|
|
37
|
+
from attocode_intel import confidence
|
|
38
|
+
from attocode_intel.confidence.settings import workspace
|
|
39
|
+
from attocode_intel.rules.enricher import enrich_findings
|
|
40
|
+
from attocode_intel.rules.executor import execute_rules
|
|
41
|
+
from attocode_intel.rules.filters.pipeline import run_pipeline
|
|
42
|
+
from attocode_intel.tools.rule_tools import _collect_files, _get_registry
|
|
43
|
+
|
|
44
|
+
with workspace(service.project_dir):
|
|
45
|
+
rules = _get_registry().query(min_confidence=confidence.rule_threshold(0.5))
|
|
46
|
+
scanned = _collect_files(sorted(selected), "", service.project_dir)
|
|
47
|
+
result = run_pipeline(
|
|
48
|
+
execute_rules(scanned, rules, project_dir=service.project_dir), min_confidence=0.5,
|
|
49
|
+
project_dir=service.project_dir,
|
|
50
|
+
)
|
|
51
|
+
enrich_findings(result, project_dir=service.project_dir)
|
|
52
|
+
findings.extend(
|
|
53
|
+
{**asdict(finding), "file_path": finding.file, "pass": "rules"}
|
|
54
|
+
for finding in result
|
|
55
|
+
)
|
|
56
|
+
passes.append(
|
|
57
|
+
{
|
|
58
|
+
"name": "rules",
|
|
59
|
+
"status": "completed" if rules and scanned else "unavailable",
|
|
60
|
+
"files_scanned": len(scanned),
|
|
61
|
+
"confidence": {k: v for k, v in confidence.last_report().items() if k != "findings"},
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
except Exception as exc:
|
|
65
|
+
passes.append({"name": "rules", "status": "failed", "error": str(exc)})
|
|
66
|
+
complete = all(item["status"] == "completed" for item in passes)
|
|
67
|
+
return {
|
|
68
|
+
"files": sorted(selected),
|
|
69
|
+
"findings": findings,
|
|
70
|
+
"passes": passes,
|
|
71
|
+
"complete": complete,
|
|
72
|
+
"assessment": f"{len(findings)} findings from completed checks."
|
|
73
|
+
if complete
|
|
74
|
+
else "Review incomplete. Inspect the failed or unavailable passes.",
|
|
75
|
+
}
|