attocode-code-intel 0.1.2__tar.gz → 0.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (415) hide show
  1. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/PKG-INFO +1 -1
  2. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/results/2026-10-11-agent-r4-stage0.md +59 -7
  3. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/pyproject.toml +1 -1
  4. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/__init__.py +1 -1
  5. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/codebase_context.py +40 -16
  6. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/index_store.py +1 -1
  7. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/providers/db_provider.py +6 -1
  8. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/indexing/full_indexer.py +17 -6
  9. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/indexing/incremental.py +7 -1
  10. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/test_ranking.py +71 -1
  11. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/composite_tools.py +38 -2
  12. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_focused_inspection.py +50 -0
  13. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_navigation_evidence.py +12 -0
  14. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/.gitignore +0 -0
  15. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/LICENSE +0 -0
  16. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/README.md +0 -0
  17. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/README.md +0 -0
  18. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/broad_candidate_audit.yaml +0 -0
  19. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/broad_query_cases.yaml +0 -0
  20. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/broad_query_external_cases.yaml +0 -0
  21. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/broad_query_final_holdout.yaml +0 -0
  22. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/client_comparison.py +0 -0
  23. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/client_responses.py +0 -0
  24. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/daily.py +0 -0
  25. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/external_benchmarks.py +0 -0
  26. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/external_study.py +0 -0
  27. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/graded_blind_pack.yaml +0 -0
  28. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/localize_study.py +0 -0
  29. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/locbench_title_pack.yaml +0 -0
  30. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/onboarding_study.py +0 -0
  31. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/pilot.py +0 -0
  32. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/quality_scoring.py +0 -0
  33. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/quality_tasks.py +0 -0
  34. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/release_gate.py +0 -0
  35. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/responses.py +0 -0
  36. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/results/2026-09-05-macos.json +0 -0
  37. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/results/2026-10-04-broad-query-ranking.md +0 -0
  38. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/results/2026-10-04-decision-reranker-trial.md +0 -0
  39. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/results/2026-10-04-systemone-http-local-trial.md +0 -0
  40. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/results/2026-10-05-broad-candidate-audit.md +0 -0
  41. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/results/2026-10-05-source-view-transfer.md +0 -0
  42. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/results/2026-10-08-blind-graded-rerank.md +0 -0
  43. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/results/2026-10-08-locbench-560.md +0 -0
  44. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/results/2026-10-09-locbench-560-first-stage.md +0 -0
  45. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/results/2026-10-10-agent-pilot.md +0 -0
  46. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/results/2026-10-10-agent-r3.md +0 -0
  47. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/results/2026-10-10-matrix-r1.md +0 -0
  48. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/results/README.md +0 -0
  49. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/source_view_transfer.yaml +0 -0
  50. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/study.py +0 -0
  51. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/study_clients.py +0 -0
  52. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/study_events.py +0 -0
  53. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/study_tasks.py +0 -0
  54. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/token_overhead.py +0 -0
  55. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/understanding_scoring.py +0 -0
  56. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/understanding_study.py +0 -0
  57. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/warm_cache.py +0 -0
  58. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/evals/workflows.py +0 -0
  59. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/GUIDELINES.md +0 -0
  60. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/__init__.py +0 -0
  61. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/errors/__init__.py +0 -0
  62. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/__init__.py +0 -0
  63. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/__init__.py +0 -0
  64. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/architecture_drift.py +0 -0
  65. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/ast_chunker.py +0 -0
  66. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/ast_service.py +0 -0
  67. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/blob_oid.py +0 -0
  68. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/cache_manifest.py +0 -0
  69. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/cas.py +0 -0
  70. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/code_analyzer.py +0 -0
  71. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/codebase_ast.py +0 -0
  72. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/cross_mode.py +0 -0
  73. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/cross_references.py +0 -0
  74. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/embedding_rotation.py +0 -0
  75. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/embeddings.py +0 -0
  76. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/frecency.py +0 -0
  77. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/fuzzy.py +0 -0
  78. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/hierarchical_explorer.py +0 -0
  79. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/hydration.py +0 -0
  80. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/index_repair.py +0 -0
  81. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/memory_store.py +0 -0
  82. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/module_resolution.py +0 -0
  83. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/query_constraints.py +0 -0
  84. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/query_history.py +0 -0
  85. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/reranker.py +0 -0
  86. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/semantic_search.py +0 -0
  87. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/syntax_evidence.py +0 -0
  88. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/systemone_ranker.py +0 -0
  89. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/temporal_coupling.py +0 -0
  90. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/trigram_index.py +0 -0
  91. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/trigram_regex.py +0 -0
  92. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/ts_parser.py +0 -0
  93. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/context/vector_store.py +0 -0
  94. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/feature_flags/__init__.py +0 -0
  95. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/lsp/__init__.py +0 -0
  96. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/lsp/client.py +0 -0
  97. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/mcp/__init__.py +0 -0
  98. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/mcp/client.py +0 -0
  99. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/security/__init__.py +0 -0
  100. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/security/custom_rules.py +0 -0
  101. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/security/dataflow.py +0 -0
  102. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/security/dependency_audit.py +0 -0
  103. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/security/matcher.py +0 -0
  104. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/security/patterns.py +0 -0
  105. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/security/scanner.py +0 -0
  106. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/utilities/__init__.py +0 -0
  107. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/utilities/ignore.py +0 -0
  108. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/integrations/utilities/token_estimate.py +0 -0
  109. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/tricks/__init__.py +0 -0
  110. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/tricks/recursive_context.py +0 -0
  111. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/types/__init__.py +0 -0
  112. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/types/events.py +0 -0
  113. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_internal/types/severity.py +0 -0
  114. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/_shared.py +0 -0
  115. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/analysis_coverage.py +0 -0
  116. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/__init__.py +0 -0
  117. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/access.py +0 -0
  118. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/app.py +0 -0
  119. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/auth/__init__.py +0 -0
  120. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/auth/api_keys.py +0 -0
  121. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/auth/context.py +0 -0
  122. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/auth/jwt.py +0 -0
  123. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/auth/oauth.py +0 -0
  124. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/auth/passwords.py +0 -0
  125. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/deps.py +0 -0
  126. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/knowledge_bridge.py +0 -0
  127. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/mcp_transport.py +0 -0
  128. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/middleware.py +0 -0
  129. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/models.py +0 -0
  130. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/providers/__init__.py +0 -0
  131. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/providers/local_provider.py +0 -0
  132. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/providers/remote_provider.py +0 -0
  133. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/repository_source.py +0 -0
  134. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/__init__.py +0 -0
  135. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/_pin_helper.py +0 -0
  136. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/activity.py +0 -0
  137. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/adr.py +0 -0
  138. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/analysis.py +0 -0
  139. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/api_keys.py +0 -0
  140. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/auth.py +0 -0
  141. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/branches.py +0 -0
  142. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/cross_repo_search.py +0 -0
  143. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/embeddings.py +0 -0
  144. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/files.py +0 -0
  145. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/files_v2.py +0 -0
  146. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/gc.py +0 -0
  147. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/git_v2.py +0 -0
  148. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/graph.py +0 -0
  149. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/graph_viz.py +0 -0
  150. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/health.py +0 -0
  151. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/history.py +0 -0
  152. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/jobs.py +0 -0
  153. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/learning.py +0 -0
  154. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/lsp.py +0 -0
  155. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/notify.py +0 -0
  156. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/operations.py +0 -0
  157. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/orgs.py +0 -0
  158. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/preferences.py +0 -0
  159. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/presence.py +0 -0
  160. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/projects.py +0 -0
  161. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/repos.py +0 -0
  162. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/search.py +0 -0
  163. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/snapshots.py +0 -0
  164. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/webhooks.py +0 -0
  165. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/routes/websocket.py +0 -0
  166. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/static/graph.html +0 -0
  167. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/api/utils.py +0 -0
  168. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/artifacts/__init__.py +0 -0
  169. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/artifacts/hashing.py +0 -0
  170. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/artifacts/provenance.py +0 -0
  171. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/artifacts/retrieval_pin.py +0 -0
  172. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/audit.py +0 -0
  173. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/bug_finder.py +0 -0
  174. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/bundle.py +0 -0
  175. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/catalog.py +0 -0
  176. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/change_review.py +0 -0
  177. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/cli.py +0 -0
  178. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/community.py +0 -0
  179. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/confidence/__init__.py +0 -0
  180. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/confidence/jev.py +0 -0
  181. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/confidence/llm.py +0 -0
  182. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/confidence/redact.py +0 -0
  183. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/confidence/settings.py +0 -0
  184. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/config.py +0 -0
  185. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/crypto.py +0 -0
  186. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/db/__init__.py +0 -0
  187. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/db/base.py +0 -0
  188. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/db/engine.py +0 -0
  189. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/db/models.py +0 -0
  190. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/entrypoint.py +0 -0
  191. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/focused_evidence.py +0 -0
  192. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/freshness.py +0 -0
  193. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/gateway.py +0 -0
  194. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/git/__init__.py +0 -0
  195. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/git/credentials.py +0 -0
  196. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/git/manager.py +0 -0
  197. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/git/models.py +0 -0
  198. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/git/storage.py +0 -0
  199. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/graph_query_parser.py +0 -0
  200. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/helpers.py +0 -0
  201. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/indexing/__init__.py +0 -0
  202. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/indexing/debouncer.py +0 -0
  203. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/indexing/delta_indexer.py +0 -0
  204. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/indexing/parser.py +0 -0
  205. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/indexing/summarizer.py +0 -0
  206. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/installer.py +0 -0
  207. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/knowledge.py +0 -0
  208. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/local_knowledge.py +0 -0
  209. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/alembic.ini +0 -0
  210. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/env.py +0 -0
  211. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/script.py.mako +0 -0
  212. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/001_initial_schema.py +0 -0
  213. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/002_branch_version_and_embeddings.py +0 -0
  214. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/003_embedding_uniqueness_and_cascade.py +0 -0
  215. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/004_audit_events.py +0 -0
  216. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/005_user_preferences.py +0 -0
  217. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/006_google_oauth.py +0 -0
  218. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/007_pgvector_embeddings.py +0 -0
  219. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/008_symbol_references.py +0 -0
  220. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/009_webhook_secret_encryption.py +0 -0
  221. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/010_add_commits_table.py +0 -0
  222. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/011_commit_changed_files.py +0 -0
  223. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/012_branch_merged_at.py +0 -0
  224. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/013_revoked_tokens.py +0 -0
  225. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/014_blame_hunks.py +0 -0
  226. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/015_commit_file_stats.py +0 -0
  227. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/016_embedding_provenance_columns.py +0 -0
  228. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/017_provenance_table.py +0 -0
  229. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/018_repo_snapshots.py +0 -0
  230. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/019_symref_caller.py +0 -0
  231. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/migrations/versions/020_shared_knowledge.py +0 -0
  232. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/onboarding.py +0 -0
  233. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/output.py +0 -0
  234. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/precision.py +0 -0
  235. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/presence.py +0 -0
  236. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/probe.py +0 -0
  237. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/project_dir.py +0 -0
  238. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/pubsub.py +0 -0
  239. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/query_ranking.py +0 -0
  240. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/readiness.py +0 -0
  241. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/redis.py +0 -0
  242. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/reference_pages.py +0 -0
  243. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/remote.py +0 -0
  244. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/repo_ranker.py +0 -0
  245. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/request_context.py +0 -0
  246. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/__init__.py +0 -0
  247. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/ci.py +0 -0
  248. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/combinators.py +0 -0
  249. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/enricher.py +0 -0
  250. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/evolution.py +0 -0
  251. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/executor.py +0 -0
  252. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/filters/__init__.py +0 -0
  253. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/filters/pipeline.py +0 -0
  254. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/formatter.py +0 -0
  255. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/hygiene.py +0 -0
  256. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/importers/__init__.py +0 -0
  257. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/importers/semgrep.py +0 -0
  258. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/loader.py +0 -0
  259. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/marketplace.py +0 -0
  260. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/metavar.py +0 -0
  261. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/model.py +0 -0
  262. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/__init__.py +0 -0
  263. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/_license_templates/Apache-2.0.txt +0 -0
  264. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/_license_templates/MIT.txt +0 -0
  265. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/bandit-python/LICENSE +0 -0
  266. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/bandit-python/NOTICE +0 -0
  267. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/bandit-python/PORTING.md +0 -0
  268. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/bandit-python/manifest.yaml +0 -0
  269. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/bandit-python/rules/B105-hardcoded-password.yaml +0 -0
  270. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/bandit-python/rules/B303-weak-md5.yaml +0 -0
  271. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/bandit-python/rules/B304-weak-des.yaml +0 -0
  272. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/bandit-python/rules/B307-use-of-eval.yaml +0 -0
  273. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/bandit-python/rules/B324-weak-sha1.yaml +0 -0
  274. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/bandit-python/rules/B501-no-cert-validation.yaml +0 -0
  275. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/bandit-python/rules/B602-shell-true.yaml +0 -0
  276. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/bandit-python/rules/B608-sqli.yaml +0 -0
  277. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/eslint-typescript/LICENSE +0 -0
  278. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/eslint-typescript/NOTICE +0 -0
  279. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/eslint-typescript/PORTING.md +0 -0
  280. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/eslint-typescript/manifest.yaml +0 -0
  281. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/eslint-typescript/rules/eqeqeq.yaml +0 -0
  282. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/eslint-typescript/rules/no-eval.yaml +0 -0
  283. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/eslint-typescript/rules/no-implied-eval.yaml +0 -0
  284. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/eslint-typescript/rules/no-new-func.yaml +0 -0
  285. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/eslint-typescript/rules/no-throw-literal.yaml +0 -0
  286. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/eslint-typescript/rules/no-var.yaml +0 -0
  287. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/eslint-typescript/rules/no-with.yaml +0 -0
  288. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/gosec-go/LICENSE +0 -0
  289. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/gosec-go/NOTICE +0 -0
  290. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/gosec-go/PORTING.md +0 -0
  291. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/gosec-go/manifest.yaml +0 -0
  292. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/gosec-go/rules/G101-hardcoded-credentials.yaml +0 -0
  293. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/gosec-go/rules/G102-bind-all-interfaces.yaml +0 -0
  294. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/gosec-go/rules/G103-unsafe-block.yaml +0 -0
  295. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/gosec-go/rules/G201-sql-format.yaml +0 -0
  296. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/gosec-go/rules/G304-file-inclusion.yaml +0 -0
  297. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/gosec-go/rules/G401-weak-cipher.yaml +0 -0
  298. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/gosec-go/rules/G402-tls-min-version.yaml +0 -0
  299. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/community/gosec-go/rules/G501-md5-import.yaml +0 -0
  300. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/cpp/manifest.yaml +0 -0
  301. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/cpp/rules/security.yaml +0 -0
  302. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/cpp/rules/structural.yaml +0 -0
  303. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/csharp/manifest.yaml +0 -0
  304. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/csharp/rules/security.yaml +0 -0
  305. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/csharp/rules/structural.yaml +0 -0
  306. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/go/manifest.yaml +0 -0
  307. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/go/rules/performance.yaml +0 -0
  308. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/go/rules/security.yaml +0 -0
  309. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/go/rules/structural.yaml +0 -0
  310. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/go/taint/sanitizers.yaml +0 -0
  311. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/go/taint/sinks.yaml +0 -0
  312. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/go/taint/sources.yaml +0 -0
  313. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/java/manifest.yaml +0 -0
  314. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/java/rules/correctness.yaml +0 -0
  315. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/java/rules/structural.yaml +0 -0
  316. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/java/taint/sinks.yaml +0 -0
  317. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/java/taint/sources.yaml +0 -0
  318. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/kotlin/manifest.yaml +0 -0
  319. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/kotlin/rules/correctness.yaml +0 -0
  320. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/kotlin/rules/structural.yaml +0 -0
  321. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/php/manifest.yaml +0 -0
  322. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/php/rules/security.yaml +0 -0
  323. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/php/rules/structural.yaml +0 -0
  324. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/python/manifest.yaml +0 -0
  325. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/python/rules/performance.yaml +0 -0
  326. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/python/rules/structural.yaml +0 -0
  327. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/ruby/manifest.yaml +0 -0
  328. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/ruby/rules/security.yaml +0 -0
  329. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/ruby/rules/structural.yaml +0 -0
  330. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/rust/manifest.yaml +0 -0
  331. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/rust/rules/correctness.yaml +0 -0
  332. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/rust/rules/structural.yaml +0 -0
  333. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/typescript/manifest.yaml +0 -0
  334. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/typescript/rules/performance.yaml +0 -0
  335. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/examples/typescript/rules/structural.yaml +0 -0
  336. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/packs/pack_loader.py +0 -0
  337. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/plugins/__init__.py +0 -0
  338. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/plugins/plugin_loader.py +0 -0
  339. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/profiling.py +0 -0
  340. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/registry.py +0 -0
  341. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/sarif.py +0 -0
  342. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/synthesis.py +0 -0
  343. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/rules/testing.py +0 -0
  344. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/server.py +0 -0
  345. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/service.py +0 -0
  346. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/sharing.py +0 -0
  347. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/storage/__init__.py +0 -0
  348. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/storage/branch_overlay.py +0 -0
  349. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/storage/content_store.py +0 -0
  350. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/storage/dependency_store.py +0 -0
  351. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/storage/diff_engine.py +0 -0
  352. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/storage/embedding_store.py +0 -0
  353. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/storage/provenance_store.py +0 -0
  354. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/storage/security_scanner_db.py +0 -0
  355. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/storage/symbol_store.py +0 -0
  356. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/structural_evidence.py +0 -0
  357. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/symbol_inspection.py +0 -0
  358. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/symbol_links.py +0 -0
  359. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/telemetry.py +0 -0
  360. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/testing/__init__.py +0 -0
  361. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/testing/fixtures.py +0 -0
  362. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/testing/helpers.py +0 -0
  363. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/testing/mocks.py +0 -0
  364. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/__init__.py +0 -0
  365. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/adr_tools.py +0 -0
  366. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/analysis_tools.py +0 -0
  367. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/cross_mode_tools.py +0 -0
  368. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/dead_code_tools.py +0 -0
  369. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/distill_tools.py +0 -0
  370. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/frecency_tools.py +0 -0
  371. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/fuzzy_tools.py +0 -0
  372. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/history_tools.py +0 -0
  373. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/learning_tools.py +0 -0
  374. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/lsp_tools.py +0 -0
  375. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/maintenance_tools.py +0 -0
  376. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/navigation_tools.py +0 -0
  377. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/overlay_tools.py +0 -0
  378. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/pin_store.py +0 -0
  379. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/pin_tools.py +0 -0
  380. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/query_constraints_tools.py +0 -0
  381. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/query_history_tools.py +0 -0
  382. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/readiness_tools.py +0 -0
  383. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/rule_tools.py +0 -0
  384. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/search_tools.py +0 -0
  385. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/tools/snapshot_tools.py +0 -0
  386. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/workers/__init__.py +0 -0
  387. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/workers/job_utils.py +0 -0
  388. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/workers/jobs.py +0 -0
  389. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/workers/run.py +0 -0
  390. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/src/attocode_intel/workers/settings.py +0 -0
  391. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_cold_discovery.py +0 -0
  392. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_compact_inspection.py +0 -0
  393. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_daily_workflows.py +0 -0
  394. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_doctor.py +0 -0
  395. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_edit_restart.py +0 -0
  396. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_external_study.py +0 -0
  397. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_index_reuse.py +0 -0
  398. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_language_capabilities.py +0 -0
  399. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_local_reranker.py +0 -0
  400. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_localize_study.py +0 -0
  401. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_onboarding_study.py +0 -0
  402. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_pilot.py +0 -0
  403. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_precision_protocol.py +0 -0
  404. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_product.py +0 -0
  405. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_quality_evaluation.py +0 -0
  406. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_query_ranking.py +0 -0
  407. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_ranking_intent.py +0 -0
  408. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_remote.py +0 -0
  409. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_structural_evidence.py +0 -0
  410. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_study.py +0 -0
  411. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_systemone_ranker.py +0 -0
  412. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_token_overhead.py +0 -0
  413. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_understanding_evaluation.py +0 -0
  414. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_walk_order.py +0 -0
  415. {attocode_code_intel-0.1.2 → attocode_code_intel-0.1.3}/tests/test_warm_cache.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: attocode-code-intel
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: Local code search and navigation for coding agents and people
5
5
  Project-URL: Homepage, https://github.com/eren23/attocode
6
6
  Project-URL: Repository, https://github.com/eren23/attocode
@@ -9,6 +9,13 @@ and Recall@5 was 0.545 against 0.477 (Δ +0.068, range -0.020 to +0.158).
9
9
  That is also below the rule. By the rule, the next work is better test
10
10
  ranking, not agent runs.
11
11
 
12
+ **Update after the ranking change (#164): the holdout check also does not
13
+ meet the rule.** On the 56 holdout tasks, `suggest_tests` had Recall@5
14
+ 0.640 and the name grep 0.586 (Δ +0.054, range -0.047 to +0.167). On the
15
+ dev tasks, which we used to make the change, Δ was +0.213. Thus no agent
16
+ runs. The section [After the ranking change](#after-the-ranking-change)
17
+ gives the details.
18
+
12
19
  R4 follows the R3 rule: after the localization studies, test a review
13
20
  task. The [R3 results](2026-10-10-agent-r3.md) give the background.
14
21
 
@@ -123,12 +130,57 @@ for the ranking work, not results of the rule.
123
130
  - We now know the dev tasks. A ranking change that we tune on them needs
124
131
  a check on tasks that we did not look at.
125
132
 
133
+ ## After the ranking change
134
+
135
+ The user approved these steps on 2026-10-11 (`studies/r4-addendum.md` in
136
+ the evals store). Because we used the dev results to make the change, the
137
+ holdout tasks decide. Each holdout task ran once, with the final version.
138
+
139
+ - **Change.** PR #164 at commit `381ece4`. `suggest_tests` finds tests by
140
+ name in the whole repository, and any folder that holds a top-level
141
+ Python package is an import root.
142
+ - **Setup.** The same script, arms and metric, on a new RunPod CPU pod
143
+ (128 CPUs). Dev and holdout ran at the same time, with 12 workers each.
144
+ The pod ran for about 0.5 hours and cost about USD 0.45.
145
+ - **Two record-only fields.** `product_detail` holds the priority of each
146
+ candidate. `name_v011` is the name grep with the test detector of 0.1.1.
147
+ The `name` arm uses the detector of the installed version, and #164 adds
148
+ .NET, C# and C/C++ test names to it.
149
+
150
+ | Set | Tasks | Failed | `product` R@5 | `name` R@5 | Δ | Range of Δ (95%) | `product` Hit@5 | `name` Hit@5 | Higher / lower | Rule met |
151
+ |---|---:|---:|---:|---:|---:|---|---:|---:|---:|---|
152
+ | Dev (tuning) | 123 | 1 | 0.694 | 0.481 | +0.213 | +0.139 to +0.286 | 0.740 | 0.520 | 33 / 1 | Yes |
153
+ | Holdout (decides) | 56 | 1 | 0.640 | 0.586 | +0.054 | -0.047 to +0.167 | 0.696 | 0.625 | 6 / 3 | No |
154
+
155
+ With the 0.1.1 detector, the name grep had 0.477 on dev and 0.580 on the
156
+ holdout. The Δ changes by less than 0.01. Each set has one task whose
157
+ patch does not apply at the base commit (dubbo-3317 and dubbo-4678).
158
+
159
+ **Reading.** On dev, `suggest_tests` improved on 21 tasks against the fix
160
+ view, and no task got worse. All 7 matplotlib tasks had no test before.
161
+ After the change, their Recall@5 is 0.50. On the holdout, the gain is
162
+ small, and the range includes 0. By the rule, this is no evidence that
163
+ the product names the tests for a change better than a file-name grep.
164
+ The name grep is strong on the holdout. Both arms had a Hit@5 on 33 of
165
+ 55 tasks, because the developers changed the test that has the name of
166
+ the source file.
167
+
168
+ **Holdout misses.** These are leads only. The holdout tasks cannot check
169
+ a fix for them.
170
+
171
+ - `suggest_tests` found no test on 8 tasks.
172
+ - In coreutils, the changed file is `src/uu/cp/src/cp.rs`. The name
173
+ finder skips names with fewer than 3 letters, so it did not find
174
+ `tests/by-util/test_cp.rs`.
175
+ - In grommet and decap-cms, the gold set holds a Jest snapshot file
176
+ (`.snap`). `suggest_tests` gives only test source files, and the name
177
+ grep also gives data files.
178
+
126
179
  ## Next
127
180
 
128
- 1. Release the race fix (#161) as code intel 0.1.2.
129
- 2. Improve test ranking. Close the name-rule gaps above: a `tests/`
130
- folder next to the source, Java packages and modules, C# and C/C++.
131
- When the graph gives no test, use file-name matches as a fallback.
132
- 3. Measure the change on the dev tasks, then once on the 56 holdout
133
- tasks. The holdout tasks have not run yet, so they stay a clean check.
134
- Stage 1 runs only if the change meets the rule.
181
+ 1. Merge #164 as a product change. Its claims are the numbers above, not
182
+ a measured gain on new tasks.
183
+ 2. No R4 agent runs. This also gives no new evidence for the cut of the
184
+ daily tool list.
185
+ 3. Any new test-ranking study needs new tasks, because we know the results
186
+ of all 179 tasks now.
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
6
6
 
7
7
  [project]
8
8
  name = "attocode-code-intel"
9
- version = "0.1.2"
9
+ version = "0.1.3"
10
10
  description = "Local code search and navigation for coding agents and people"
11
11
  readme = "README.md"
12
12
  requires-python = ">=3.12"
@@ -49,4 +49,4 @@ def __getattr__(name: str) -> Any:
49
49
  raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
50
50
 
51
51
  # The other copy is packages/code-intel/pyproject.toml. A test checks that both match.
52
- __version__ = "0.1.2"
52
+ __version__ = "0.1.3"
@@ -366,28 +366,52 @@ def _build_file_index(
366
366
  normalized = f.relative_path.replace(os.sep, "/")
367
367
  file_index[normalized] = f.relative_path
368
368
 
369
- # Detect source prefixes and add stripped alternate keys. A package below
370
- # any src/ folder adds that folder too, as in packages/<name>/src/ of a monorepo.
371
- source_prefixes = set(_detect_source_prefixes(root_dir))
372
- for normalized in file_index:
373
- path = "/" + normalized
374
- if normalized.endswith("/__init__.py") and "/src/" in path:
375
- source_prefixes.add(path[1:path.index("/src/") + 5])
369
+ # Detect source prefixes and add stripped alternate keys.
370
+ source_prefixes = set(_detect_source_prefixes(root_dir)) | _python_import_roots(file_index)
376
371
  if source_prefixes:
377
- extra: dict[str, str] = {}
378
- for normalized, rel_path in file_index.items():
379
- for prefix in sorted(source_prefixes):
380
- if normalized.startswith(prefix):
381
- stripped = normalized[len(prefix):]
382
- # Don't override direct matches
383
- if stripped not in file_index:
384
- extra[stripped] = rel_path
385
- file_index.update(extra)
372
+ _add_root_keys(file_index, source_prefixes)
386
373
 
387
374
  file_index.configure_javascript(root_dir)
388
375
  return file_index
389
376
 
390
377
 
378
+ def _python_import_roots(paths) -> set[str]:
379
+ """Folders that hold a top-level Python package, as ``lib/`` for ``lib/pkg/__init__.py``.
380
+
381
+ Such a folder is an import root: src/, packages/<name>/src/ of a monorepo,
382
+ lib/ of matplotlib or python/ of ray.
383
+ """
384
+ roots: set[str] = set()
385
+ for path in paths:
386
+ package, _, name = path.rpartition("/")
387
+ parent = package.rpartition("/")[0]
388
+ if name == "__init__.py" and parent and parent + "/__init__.py" not in paths:
389
+ roots.add(parent + "/")
390
+ return roots
391
+
392
+
393
+ def _add_root_keys(file_index: dict[str, str], roots: set[str]) -> None:
394
+ """Add a key without the root prefix for each file below an import root."""
395
+ extra: dict[str, str] = {}
396
+ for normalized, rel_path in file_index.items():
397
+ parts = normalized.split("/")
398
+ # Shallow roots first, so a deeper root wins, as in sorted prefix order.
399
+ for depth in range(1, len(parts)):
400
+ prefix = "/".join(parts[:depth]) + "/"
401
+ stripped = normalized[len(prefix):]
402
+ # Don't override direct matches
403
+ if prefix in roots and stripped not in file_index:
404
+ extra[stripped] = rel_path
405
+ file_index.update(extra)
406
+
407
+
408
+ def python_module_index(paths) -> dict[str, str]:
409
+ """Module-path keys for ``_resolve_python_import`` from repository paths alone."""
410
+ file_index = {path: path for path in paths}
411
+ _add_root_keys(file_index, _python_import_roots(file_index))
412
+ return file_index
413
+
414
+
391
415
  def _resolve_python_import(module: str, source_file: str, file_index: dict[str, str]) -> str | None:
392
416
  """Resolve a Python import module name to a relative file path.
393
417
 
@@ -23,7 +23,7 @@ logger = logging.getLogger(__name__)
23
23
  SCHEMA_VERSION = "6"
24
24
  # Bump the suffix when a change alters the saved graph edges, for example import resolution.
25
25
  # Stores keep their tables, and the next start rebuilds the index once.
26
- SNAPSHOT_KEY = "structural_snapshot_v2"
26
+ SNAPSHOT_KEY = "structural_snapshot_v3"
27
27
  SQLITE_BUSY_TIMEOUT_MS = 30_000
28
28
  INDEX_INIT_LOCK_TIMEOUT_SECONDS = 30
29
29
 
@@ -340,6 +340,9 @@ class DbAnalysisProvider:
340
340
 
341
341
  from sqlalchemy import select
342
342
 
343
+ from attocode_intel._internal.integrations.context.codebase_context import (
344
+ python_module_index,
345
+ )
343
346
  from attocode_intel.db.models import FileContent
344
347
  from attocode_intel.indexing.full_indexer import _resolve_import_path
345
348
  from attocode_intel.indexing.parser import detect_language, extract_imports
@@ -347,6 +350,7 @@ class DbAnalysisProvider:
347
350
  logger = logging.getLogger(__name__)
348
351
  manifest = branch_ctx.manifest # path -> sha
349
352
  known_paths = set(manifest.keys())
353
+ python_index = python_module_index(known_paths)
350
354
  sha_to_path = {sha: path for path, sha in manifest.items()}
351
355
  content_shas = list(set(manifest.values()))
352
356
 
@@ -378,7 +382,8 @@ class DbAnalysisProvider:
378
382
  raw_content = content if isinstance(content, bytes) else content.encode("utf-8")
379
383
  imports = extract_imports(raw_content, source_path, language)
380
384
  for imp in imports:
381
- target = _resolve_import_path(imp, source_path, known_paths, language)
385
+ target = _resolve_import_path(imp, source_path, known_paths, language,
386
+ python_index=python_index)
382
387
  if target and target != source_path:
383
388
  edges.append({
384
389
  "source": source_path,
@@ -69,18 +69,23 @@ def _resolve_import_path(
69
69
  known_paths: set[str],
70
70
  language: str | None,
71
71
  aliases: dict[str, str] | None = None,
72
+ python_index: dict[str, str] | None = None,
72
73
  ) -> str | None:
73
74
  """Resolve an import string to a file path in the repo.
74
75
 
75
- Returns the matching path or None if unresolvable.
76
+ Returns the matching path or None if unresolvable. For Python, pass
77
+ ``python_index = python_module_index(known_paths)`` when resolving many imports.
76
78
  """
77
79
  from pathlib import PurePosixPath
78
80
 
79
81
  if language == "python":
80
- # foo.bar -> foo/bar.py or foo/bar/__init__.py
81
- parts = import_name.replace(".", "/")
82
- candidates = [f"{parts}.py", f"{parts}/__init__.py"]
83
- elif language in ("javascript", "typescript"):
82
+ # The resolver of the local index: relative imports and import roots such as src/ or lib/.
83
+ from attocode_intel._internal.integrations.context.codebase_context import (
84
+ _resolve_python_import,
85
+ python_module_index,
86
+ )
87
+ return _resolve_python_import(import_name, source_path, python_index or python_module_index(known_paths))
88
+ if language in ("javascript", "typescript"):
84
89
  if import_name.startswith("."):
85
90
  # Relative import — resolve against source dir
86
91
  source_dir = str(PurePosixPath(source_path).parent)
@@ -249,8 +254,13 @@ class FullIndexer:
249
254
  if overlay_updates:
250
255
  await overlay.set_files_batch(branch_id, overlay_updates)
251
256
 
257
+ from attocode_intel._internal.integrations.context.codebase_context import (
258
+ python_module_index,
259
+ )
260
+
252
261
  # Resolve path aliases from tsconfig/jsconfig
253
262
  aliases = _load_path_aliases(known_paths, config_contents)
263
+ python_index = python_module_index(known_paths)
254
264
 
255
265
  # Second pass: resolve imports to dependencies
256
266
  self._progress({"phase": "resolving_dependencies", "total": len(deferred_deps), "current": 0})
@@ -260,7 +270,8 @@ class FullIndexer:
260
270
  continue
261
271
  deps: list[dict] = []
262
272
  for imp in imports:
263
- target_path = _resolve_import_path(imp, source_path, known_paths, language, aliases=aliases)
273
+ target_path = _resolve_import_path(imp, source_path, known_paths, language, aliases=aliases,
274
+ python_index=python_index)
264
275
  if target_path and target_path in path_to_sha:
265
276
  deps.append({
266
277
  "target_sha": path_to_sha[target_path],
@@ -159,9 +159,15 @@ class IncrementalPipeline:
159
159
  for u_path, u_sha, _ in overlay_updates:
160
160
  path_to_sha[u_path] = u_sha
161
161
 
162
+ python_index = None
163
+ if language == "python":
164
+ from attocode_intel._internal.integrations.context.codebase_context import (
165
+ python_module_index,
166
+ )
167
+ python_index = python_module_index(known_paths)
162
168
  deps = []
163
169
  for imp in imports:
164
- target = _resolve_import_path(imp, path, known_paths, language)
170
+ target = _resolve_import_path(imp, path, known_paths, language, python_index=python_index)
165
171
  if target and target in path_to_sha:
166
172
  deps.append({
167
173
  "target_sha": path_to_sha[target],
@@ -1,6 +1,7 @@
1
1
  """Symbol-focused test evidence, reusing the parsed index instead of scanning file bodies."""
2
2
  from __future__ import annotations
3
3
 
4
+ import re
4
5
  from pathlib import PurePosixPath
5
6
 
6
7
  from attocode_intel.focused_evidence import task_terms, terms
@@ -10,8 +11,77 @@ def is_test_path(path):
10
11
  parts = PurePosixPath(path).parts
11
12
  name = parts[-1] if parts else ""
12
13
  return (any(p in {"test", "tests", "__tests__", "spec", "specs"} for p in parts)
14
+ # .NET test projects: UnitsNet.Tests/, Kavita.Services.Tests/
15
+ or any(p.endswith((".Tests", ".Test", ".UnitTests", ".IntegrationTests")) for p in parts[:-1])
13
16
  or name.startswith("test_") or ".test." in name or ".spec." in name
14
- or name.endswith(("_test.py", "_test.go", "Test.java", "Test.kt")))
17
+ or name.endswith(("_test.py", "_test.go", "Test.java", "Test.kt", "Tests.java", "Tests.kt",
18
+ "Test.cs", "Tests.cs", "_test.c", "_test.cc", "_test.cpp", "_unittest.cc")))
19
+
20
+
21
+ _TEST_PREFIX = re.compile(r"^(?:unit)?tests?[_-]|^Tests?(?=[A-Z])")
22
+ _TEST_SUFFIX = re.compile(r"(?:[_-](?:unit)?(?:tests?|spec)|Tests?|Spec)$")
23
+ # These names say little; the folder names the module (pkg/__init__.py, src/index.ts).
24
+ _GENERIC_STEMS = {"__init__", "index", "mod", "lib", "main"}
25
+
26
+
27
+ def _plain(name):
28
+ return name.lower().replace("_", "").replace("-", "")
29
+
30
+
31
+ def file_subject(path):
32
+ """The name that a test for this file would carry: lib/pkg/figure.py -> figure."""
33
+ p = PurePosixPath(path)
34
+ stem = p.name.split(".")[0]
35
+ if stem in _GENERIC_STEMS and p.parent.name:
36
+ stem = p.parent.name
37
+ return _plain(stem)
38
+
39
+
40
+ def test_subject(path):
41
+ """The name that a test file is for: test_figure.py, FigureTest.java, figure.test.ts -> figure.
42
+
43
+ None when the name has no test affix: a fixture or generated file in a test folder.
44
+ """
45
+ p = PurePosixPath(path)
46
+ stem = p.name.split(".")[0]
47
+ core = _TEST_SUFFIX.sub("", _TEST_PREFIX.sub("", stem))
48
+ if core == stem and ".test." not in p.name and ".spec." not in p.name and "__tests__" not in p.parts:
49
+ return None
50
+ return _plain(core)
51
+
52
+
53
+ def folder_overlap(path, other):
54
+ """The number of folder names that two paths share, in any position."""
55
+ return len(set(PurePosixPath(path).parent.parts) & set(PurePosixPath(other).parent.parts))
56
+
57
+
58
+ def name_matched_tests(changed_file, test_paths, limit=10):
59
+ """Test files named for ``changed_file``, best first, as (path, priority, reason).
60
+
61
+ Priority 1: the nearest tests whose name without the test affix is the file name, if
62
+ they share a folder name with it. Priority 3: the same name farther away. Priority 4: the test file name only
63
+ contains the file name, as a plain file-name search finds it. Nearest means the most
64
+ folder names in common, so src/test/java/org/x mirrors src/main/java/org/x.
65
+ """
66
+ subject = file_subject(changed_file)
67
+ if len(subject) < 2:
68
+ return []
69
+
70
+ def shared(path):
71
+ return folder_overlap(path, changed_file)
72
+
73
+ exact = [path for path in test_paths if test_subject(path) == subject]
74
+ named = set(exact)
75
+ # A short name is part of too many file names: cp.rs gets test_cp.rs, not every *cp* file.
76
+ loose = [path for path in test_paths if len(subject) >= 3 and path not in named
77
+ and subject in _plain(PurePosixPath(path).name)]
78
+ exact.sort(key=lambda path: (-shared(path), len(path), path))
79
+ loose.sort(key=lambda path: (-shared(path), len(path), path))
80
+ nearest = shared(exact[0]) if exact else 0
81
+ rows = [(path, 1 if nearest and shared(path) == nearest else 3, f"Test file named for `{changed_file}`")
82
+ for path in exact]
83
+ rows += [(path, 4, f"Test file name contains `{PurePosixPath(changed_file).stem}`") for path in loose]
84
+ return rows[:limit]
15
85
 
16
86
 
17
87
  def rank_symbol_tests(ast, suggestions, files, symbol_name, task_hint, distances,
@@ -123,6 +123,30 @@ def _find_test_files_by_convention(file_path: str, project_dir: str) -> list[str
123
123
  return existing
124
124
 
125
125
 
126
+ def _test_paths(project_dir: str) -> list[str]:
127
+ """Tracked test source files. The index can leave out tests of a large repository."""
128
+ from pathlib import PurePosixPath
129
+
130
+ from attocode_intel._internal.integrations.context.codebase_context import EXTENSION_LANGUAGES
131
+ from attocode_intel.test_ranking import is_test_path
132
+
133
+ try:
134
+ listed = subprocess.run(
135
+ ["git", "ls-files", "-z"],
136
+ cwd=project_dir, capture_output=True, text=True, timeout=30, check=True,
137
+ ).stdout.split("\0")
138
+ except (OSError, subprocess.SubprocessError):
139
+ listed = []
140
+ if not any(listed): # Not a git repository, or nothing tracked yet.
141
+ try:
142
+ listed = [f.relative_path for f in _get_context_mgr()._files]
143
+ except Exception:
144
+ return []
145
+ data = {"data", "yaml", "json", "toml", "markdown", "html", "css", "scss"}
146
+ return [path for path in listed if path
147
+ and EXTENSION_LANGUAGES.get(PurePosixPath(path).suffix, "data") not in data and is_test_path(path)]
148
+
149
+
126
150
  # ---------------------------------------------------------------------------
127
151
  # Tools
128
152
  # ---------------------------------------------------------------------------
@@ -429,6 +453,13 @@ def suggest_tests_data(files: list[str], *, symbol_name: str | None = None,
429
453
  reason=f"Direct test file for `{f}`",
430
454
  )
431
455
 
456
+ # Test files named for a changed file, anywhere in the repository.
457
+ from attocode_intel.test_ranking import folder_overlap, name_matched_tests
458
+ test_paths = _test_paths(project_dir)
459
+ for f in files:
460
+ for test_file, priority, reason in name_matched_tests(f, test_paths):
461
+ _add_suggestion(test_file, priority, reason)
462
+
432
463
  # --- Priority 2: Import-based discovery ---
433
464
  try:
434
465
  ctx = _get_context_mgr()
@@ -558,10 +589,14 @@ def suggest_tests_data(files: list[str], *, symbol_name: str | None = None,
558
589
  except (AttributeError, OSError) as exc:
559
590
  logger.debug("Test reference ranking incomplete: %s", exc)
560
591
 
561
- # Sort by evidence, then put repository tests before documentation examples.
592
+ # Sort by evidence, then put repository tests before documentation examples, then nearest first.
593
+ def nearness(path):
594
+ return max(folder_overlap(path, changed) for changed in files) if files else 0
595
+
562
596
  sorted_suggestions = sorted(
563
597
  suggestions.items(),
564
- key=lambda kv: (kv[1]["priority"], kv[0] not in representatives, -symbol_hits.get(kv[0], 0), kv[0].startswith("docs"), kv[0]),
598
+ key=lambda kv: (kv[1]["priority"], kv[0] not in representatives, -symbol_hits.get(kv[0], 0),
599
+ kv[0].startswith("docs"), -nearness(kv[0]), kv[0]),
565
600
  )
566
601
 
567
602
  return {"files": files, "candidates": [
@@ -598,6 +633,7 @@ def format_test_suggestions(data: dict) -> str:
598
633
  1: "DIRECT",
599
634
  2: "IMPORTS",
600
635
  3: "INDIRECT",
636
+ 4: "NAME",
601
637
  }
602
638
 
603
639
  lines = [
@@ -307,3 +307,53 @@ async def test_workspace_member_src_layout_links_its_tests(tmp_path, monkeypatch
307
307
  assert bundle["tests"][0]["evidence"]["selected_symbol_reference"]
308
308
  finally:
309
309
  await gateway.close()
310
+
311
+
312
+ def test_name_matched_tests_prefer_the_nearest_test_for_the_file():
313
+ from attocode_intel.test_ranking import is_test_path, name_matched_tests
314
+
315
+ tests = ["lib/pkg/tests/test_figure.py", "lib/other/tests/test_figure.py", "lib/pkg/tests/test_figure_legend.py"]
316
+ assert name_matched_tests("lib/pkg/figure.py", tests) == [
317
+ ("lib/pkg/tests/test_figure.py", 1, "Test file named for `lib/pkg/figure.py`"),
318
+ ("lib/other/tests/test_figure.py", 3, "Test file named for `lib/pkg/figure.py`"),
319
+ ("lib/pkg/tests/test_figure_legend.py", 4, "Test file name contains `figure`"),
320
+ ]
321
+ # Java tests in another package or module, and .NET test projects.
322
+ java = "core/src/main/java/org/x/Version.java"
323
+ assert name_matched_tests(java, ["core-testing/src/test/java/org/x/v/VersionTest.java"])[0][1] == 1
324
+ assert is_test_path("App.Tests/Parsing/ParserTests.cs")
325
+ assert name_matched_tests("App/Parsing/Parser.cs", ["App.Tests/Parsing/ParserTests.cs"])[0][1] == 1
326
+ # A word that ends in "test" is not a test affix.
327
+ assert name_matched_tests("src/latest.py", ["tests/contest.py"]) == []
328
+ # A fixture in a test folder has no test affix, and a test with no shared folder is far.
329
+ assert [row[1] for row in name_matched_tests("lib/pkg/figure.py", ["lib/pkg/tests/data/figure.py"])] == [4]
330
+ assert [row[1] for row in name_matched_tests("kernel/core.c", ["tools/selftests/test_core.c"])] == [3]
331
+ # A two-letter name matches its test exactly, but a name that only contains it is noise.
332
+ assert [row[0] for row in name_matched_tests("src/uu/cp/src/cp.rs", ["tests/test_cp.rs", "tests/test_scp.rs"])] == [
333
+ "tests/test_cp.rs"]
334
+
335
+
336
+ async def test_lib_layout_links_tests_by_name_and_by_import(tmp_path, monkeypatch):
337
+ # matplotlib keeps its package in lib/, and its tests in a tests/ folder next to the source.
338
+ import subprocess
339
+
340
+ monkeypatch.setenv("ATTOCODE_INTEL_PRECISION", "off")
341
+ (tmp_path / "lib/pkg/tests").mkdir(parents=True)
342
+ (tmp_path / "lib/pkg/__init__.py").write_text("")
343
+ (tmp_path / "lib/pkg/figure.py").write_text("class Figure:\n pass\n")
344
+ (tmp_path / "lib/pkg/tests/__init__.py").write_text("")
345
+ (tmp_path / "lib/pkg/tests/test_figure.py").write_text("def test_figure(): assert True\n")
346
+ (tmp_path / "lib/pkg/tests/test_layout.py").write_text(
347
+ "from pkg.figure import Figure\ndef test_layout(): assert Figure()\n")
348
+ (tmp_path / "lib/pkg/tests/test_text.py").write_text("def test_text(): assert True\n")
349
+ subprocess.run(["git", "init", "-q"], cwd=tmp_path, check=True)
350
+ subprocess.run(["git", "add", "-A"], cwd=tmp_path, check=True)
351
+ gateway = OperationGateway(str(tmp_path), "daily", watch=False)
352
+ try:
353
+ result = await gateway.execute_mcp("suggest_tests", {"files": ["lib/pkg/figure.py"]})
354
+ paths = [row["file_path"] for row in decode(result)["candidates"]]
355
+ assert paths[:2] == ["lib/pkg/tests/test_figure.py", "lib/pkg/tests/test_layout.py"]
356
+ assert "lib/pkg/tests/test_text.py" not in paths
357
+ finally:
358
+ await gateway.close()
359
+
@@ -196,3 +196,15 @@ def test_index_lookups_wait_for_a_background_writer():
196
196
  assert reader.is_alive()
197
197
  reader.join(5)
198
198
  assert not reader.is_alive()
199
+
200
+
201
+ def test_http_indexer_resolves_relative_imports_and_import_roots():
202
+ from attocode_intel.indexing.full_indexer import _resolve_import_path
203
+
204
+ paths = {"lib/pkg/__init__.py", "lib/pkg/utils.py", "lib/pkg/sub/__init__.py", "lib/pkg/sub/f.py", "utils.py"}
205
+ resolve = lambda name: _resolve_import_path(name, "lib/pkg/sub/f.py", paths, "python") # noqa: E731
206
+ assert resolve("..utils") == "lib/pkg/utils.py"
207
+ assert resolve("pkg.utils") == "lib/pkg/utils.py" # lib/ holds the top-level package.
208
+ assert resolve(".") == "lib/pkg/sub/__init__.py"
209
+ # Before, the dots were dropped and .utils linked the unrelated top-level utils.py.
210
+ assert resolve(".utils") is None