ai-codeindex 0.26.2__tar.gz → 0.27.0__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 (446) hide show
  1. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/CHANGELOG.md +21 -0
  2. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/PKG-INFO +1 -1
  3. ai_codeindex-0.27.0/docs/guides/graph-export.md +128 -0
  4. ai_codeindex-0.27.0/docs/releases/RELEASE_NOTES_v0.27.0.md +60 -0
  5. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/pyproject.toml +1 -1
  6. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/README_AI.md +13 -12
  7. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/cli.py +2 -0
  8. ai_codeindex-0.27.0/src/codeindex/cli_graph_export.py +65 -0
  9. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/cli_scan.py +8 -3
  10. ai_codeindex-0.27.0/src/codeindex/graph_buffer.py +116 -0
  11. ai_codeindex-0.27.0/src/codeindex/graph_export.py +269 -0
  12. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/invoker.py +103 -34
  13. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parser.py +2 -0
  14. ai_codeindex-0.27.0/src/codeindex/parsers/README_AI.md +325 -0
  15. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/base.py +13 -7
  16. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/java/README_AI.md +1 -1
  17. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/java/__init__.py +13 -7
  18. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/objc/README_AI.md +1 -1
  19. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/objc/__init__.py +13 -7
  20. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/php/README_AI.md +1 -1
  21. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/php/__init__.py +13 -7
  22. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/python/README_AI.md +1 -1
  23. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/python/__init__.py +13 -7
  24. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/typescript/README_AI.md +1 -1
  25. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/typescript/__init__.py +24 -14
  26. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/README_AI.md +102 -73
  27. ai_codeindex-0.27.0/tests/characterization/test_graphbuffer_baseline.py +147 -0
  28. ai_codeindex-0.27.0/tests/characterization/test_graphbuffer_equivalence.py +120 -0
  29. ai_codeindex-0.27.0/tests/fixtures/char_graphbuffer/golden/enrich_prompts.txt +19 -0
  30. ai_codeindex-0.27.0/tests/fixtures/char_graphbuffer/golden/frozen_ai_readmes.txt +120 -0
  31. ai_codeindex-0.27.0/tests/fixtures/char_graphbuffer/golden/project_symbols.md +37 -0
  32. ai_codeindex-0.27.0/tests/fixtures/char_graphbuffer/golden/structural_readmes.txt +114 -0
  33. ai_codeindex-0.27.0/tests/fixtures/char_graphbuffer/project/pysrc/models.py +16 -0
  34. ai_codeindex-0.27.0/tests/fixtures/char_graphbuffer/project/pysrc/service.py +45 -0
  35. ai_codeindex-0.27.0/tests/fixtures/char_graphbuffer/project/pysrc/util/helpers.py +13 -0
  36. ai_codeindex-0.27.0/tests/fixtures/char_graphbuffer/project/tssrc/api.ts +19 -0
  37. ai_codeindex-0.27.0/tests/fixtures/char_graphbuffer/project/tssrc/broken.ts +18 -0
  38. ai_codeindex-0.27.0/tests/fixtures/char_graphbuffer/project/tssrc/index.ts +29 -0
  39. ai_codeindex-0.27.0/tests/fixtures/char_graphbuffer/project/tssrc/nested/deep.ts +7 -0
  40. ai_codeindex-0.27.0/tests/fixtures/graph_export/export.ndjson +23 -0
  41. ai_codeindex-0.27.0/tests/fixtures/graph_export/project/app/service.py +22 -0
  42. ai_codeindex-0.27.0/tests/fixtures/graph_export/project/app/validators.py +6 -0
  43. ai_codeindex-0.27.0/tests/fixtures/graph_export/project/app/workers.py +15 -0
  44. ai_codeindex-0.27.0/tests/fixtures/graph_export/project/web/api.ts +9 -0
  45. ai_codeindex-0.27.0/tests/fixtures/graph_export/project/web/index.ts +7 -0
  46. ai_codeindex-0.27.0/tests/test_graph_export.py +158 -0
  47. ai_codeindex-0.27.0/tests/test_invoker_retry.py +91 -0
  48. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_java_error_recovery.py +12 -4
  49. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_java_parser.py +4 -2
  50. ai_codeindex-0.27.0/tests/test_parser_partial_recovery.py +66 -0
  51. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_typescript_parser.py +56 -0
  52. ai_codeindex-0.26.2/src/codeindex/parsers/README_AI.md +0 -59
  53. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/.editorconfig +0 -0
  54. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/.github/ISSUE_TEMPLATE/bug.md +0 -0
  55. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  56. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/.github/ISSUE_TEMPLATE/enhancement.md +0 -0
  57. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/.github/ISSUE_TEMPLATE/epic.md +0 -0
  58. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/.github/ISSUE_TEMPLATE/feature.md +0 -0
  59. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/.github/workflows/ci.yml +0 -0
  60. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/.github/workflows/publish.yml +0 -0
  61. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/.gitignore +0 -0
  62. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/.serena/.gitignore +0 -0
  63. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/.serena/memories/design_philosophy.md +0 -0
  64. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/.serena/memories/development_workflow.md +0 -0
  65. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/.serena/memories/project_overview.md +0 -0
  66. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/.serena/memories/release_automation.md +0 -0
  67. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/.serena/memories/suggested_commands.md +0 -0
  68. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/CLAUDE.md +0 -0
  69. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/CODE_OF_CONDUCT.md +0 -0
  70. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/CONTRIBUTING.md +0 -0
  71. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/FOR_LOOMGRAPH.md +0 -0
  72. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/LICENSE +0 -0
  73. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/Makefile +0 -0
  74. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/PROJECT_SYMBOLS.md +0 -0
  75. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/README.md +0 -0
  76. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/README_AI.md +0 -0
  77. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/README_zh.md +0 -0
  78. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/SECURITY.md +0 -0
  79. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/bench/.gitignore +0 -0
  80. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/bench/Makefile +0 -0
  81. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/bench/README.md +0 -0
  82. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/bench/grade.py +0 -0
  83. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/bench/questions.yaml.example +0 -0
  84. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/bench/report.py +0 -0
  85. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/bench/run_bench.py +0 -0
  86. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/bench/targets.yaml.example +0 -0
  87. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/README.md +0 -0
  88. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/architecture/adr/001-use-tree-sitter-for-parsing.md +0 -0
  89. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/architecture/adr/002-external-ai-cli-integration.md +0 -0
  90. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/architecture/adr/003-add-swift-objc-support.md +0 -0
  91. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/architecture/adr/004-automatic-claude-md-update.md +0 -0
  92. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/architecture/adr/005-navigation-disclaimer-and-readme-size-cap.md +0 -0
  93. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/architecture/adr/006-distribution-architecture-split.md +0 -0
  94. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/architecture/design/document-aggregation.md +0 -0
  95. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/architecture/design/initial-design.md +0 -0
  96. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/architecture/design/kiss-universal-description.md +0 -0
  97. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/architecture/design/parallel-strategy.md +0 -0
  98. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/architecture/design-philosophy.md +0 -0
  99. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/benchmark/2026-05-readme-impact.md +0 -0
  100. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/development/QUICK_START_RELEASE.md +0 -0
  101. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/development/claude-code-adoption-guide.md +0 -0
  102. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/development/claude-code-adoption-guide.zh.md +0 -0
  103. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/development/gitflow-workflow.md +0 -0
  104. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/development/github-issue-quick-reference.md +0 -0
  105. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/development/package-naming.md +0 -0
  106. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/development/pre-release-checklist.md +0 -0
  107. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/development/setup.md +0 -0
  108. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/development/team-workflow-guide.md +0 -0
  109. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/development/test-architecture.md +0 -0
  110. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/evaluation/before-after/README.md +0 -0
  111. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/evaluation/case-studies/php-payment-project.md +0 -0
  112. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/evaluation/loomgraph-efficiency-comparison.md +0 -0
  113. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/guides/advanced-usage.md +0 -0
  114. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/guides/claude-code-integration.md +0 -0
  115. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/guides/configuration.md +0 -0
  116. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/guides/contributing.md +0 -0
  117. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/guides/getting-started.md +0 -0
  118. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/guides/git-hooks-integration.md +0 -0
  119. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/guides/json-output-integration.md +0 -0
  120. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/guides/loomgraph-integration.md +0 -0
  121. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/planning/README.md +0 -0
  122. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/planning/ROADMAP.md +0 -0
  123. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/planning/executive-summary.md +0 -0
  124. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/README.md +0 -0
  125. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.10.0.md +0 -0
  126. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.12.0.md +0 -0
  127. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.12.1.md +0 -0
  128. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.14.0.md +0 -0
  129. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.15.0.md +0 -0
  130. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.17.0.md +0 -0
  131. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.17.2.md +0 -0
  132. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.17.3.md +0 -0
  133. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.18.0.md +0 -0
  134. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.19.0.md +0 -0
  135. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.2.0.md +0 -0
  136. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.20.0.md +0 -0
  137. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.23.1.md +0 -0
  138. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.23.2.md +0 -0
  139. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.24.0.md +0 -0
  140. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.25.0.md +0 -0
  141. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.3.0.md +0 -0
  142. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.3.1.md +0 -0
  143. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.3.2.md +0 -0
  144. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.4.0.md +0 -0
  145. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.5.0-beta1.md +0 -0
  146. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.7.0.md +0 -0
  147. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.8.0.md +0 -0
  148. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/docs/releases/RELEASE_NOTES_v0.9.0.md +0 -0
  149. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/examples/CLAUDE.md.php-project +0 -0
  150. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/examples/CLAUDE.md.template +0 -0
  151. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/examples/README.md +0 -0
  152. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/examples/README_AI.md +0 -0
  153. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/examples/ai-integration-guide.md +0 -0
  154. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/examples/frameworks/README_AI.md +0 -0
  155. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/examples/frameworks/template/README.md +0 -0
  156. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/examples/frameworks/template/README_AI.md +0 -0
  157. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/examples/frameworks/template/test_template_extractor.py +0 -0
  158. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/examples/frameworks/template/yourframework_extractor.py +0 -0
  159. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/examples/loomgraph_output.json +0 -0
  160. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/examples/loomgraph_php_output.json +0 -0
  161. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/examples/loomgraph_sample.php +0 -0
  162. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/examples/loomgraph_sample.py +0 -0
  163. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/examples/parse_integration_example.sh +0 -0
  164. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/examples/print_env.py +0 -0
  165. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/hooks/README.md +0 -0
  166. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/hooks/templates/post-commit-update-logic.sh +0 -0
  167. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/hooks/templates/post-commit-v4 +0 -0
  168. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/reports/swift-objc-support-analysis.md +0 -0
  169. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/reports/swift-poc-summary.md +0 -0
  170. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/reports/tech-debt-codeindex-v2.md +0 -0
  171. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/reports/tech-debt-codeindex.md +0 -0
  172. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/reports/tech-debt-loomgraph-v2.md +0 -0
  173. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/reports/tech-debt-loomgraph.md +0 -0
  174. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/reports/workflow-comparison.md +0 -0
  175. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/scripts/README.md +0 -0
  176. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/scripts/README_AI.md +0 -0
  177. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/scripts/bump_version.sh +0 -0
  178. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/scripts/check_docs_release.py +0 -0
  179. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/scripts/check_version_consistency.py +0 -0
  180. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/scripts/close-epic9-issues.sh +0 -0
  181. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/scripts/diagnose_ai_failures.py +0 -0
  182. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/scripts/hooks/hook-common.sh +0 -0
  183. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/scripts/hooks/pre-push +0 -0
  184. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/scripts/legacy/PROJECT_INDEX.json +0 -0
  185. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/scripts/legacy/README.md +0 -0
  186. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/scripts/legacy/hierarchical_strategy.py +0 -0
  187. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/scripts/pre_release_check.sh +0 -0
  188. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/scripts/release.sh +0 -0
  189. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/scripts/test_hook_e2e.sh +0 -0
  190. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/scripts/validate_php_project.py +0 -0
  191. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/skills/README.md +0 -0
  192. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/skills/create.sh +0 -0
  193. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/skills/install.sh +0 -0
  194. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/skills/src/mo-arch/SKILL.md +0 -0
  195. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/skills/src/mo-index/SKILL.md +0 -0
  196. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/README_AI.md +0 -0
  197. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/__init__.py +0 -0
  198. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/adaptive_config.py +0 -0
  199. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/adaptive_selector.py +0 -0
  200. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/ai_helper.py +0 -0
  201. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/claude_md.py +0 -0
  202. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/cli_claude_md.py +0 -0
  203. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/cli_common.py +0 -0
  204. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/cli_config.py +0 -0
  205. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/cli_config_commands.py +0 -0
  206. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/cli_docs.py +0 -0
  207. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/cli_hooks.py +0 -0
  208. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/cli_parse.py +0 -0
  209. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/cli_symbols.py +0 -0
  210. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/cli_tech_debt.py +0 -0
  211. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/config.py +0 -0
  212. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/config_help.py +0 -0
  213. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/directory_tree.py +0 -0
  214. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/docstring_processor.py +0 -0
  215. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/doctor.py +0 -0
  216. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/enricher.py +0 -0
  217. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/errors.py +0 -0
  218. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/extractors/README_AI.md +0 -0
  219. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/extractors/__init__.py +0 -0
  220. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/extractors/spring.py +0 -0
  221. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/extractors/thinkphp.py +0 -0
  222. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/file_classifier.py +0 -0
  223. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/framework_detect.py +0 -0
  224. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/hierarchical.py +0 -0
  225. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/hooks.py +0 -0
  226. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/incremental.py +0 -0
  227. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/init_wizard.py +0 -0
  228. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/objc_association.py +0 -0
  229. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parallel.py +0 -0
  230. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/__init__.py +0 -0
  231. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/java/calls.py +0 -0
  232. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/java/imports.py +0 -0
  233. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/java/inheritance.py +0 -0
  234. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/java/symbols.py +0 -0
  235. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/java_parser.py +0 -0
  236. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/objc/calls.py +0 -0
  237. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/objc/imports.py +0 -0
  238. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/objc/inheritance.py +0 -0
  239. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/objc/symbols.py +0 -0
  240. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/php/calls.py +0 -0
  241. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/php/imports.py +0 -0
  242. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/php/inheritance.py +0 -0
  243. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/php/symbols.py +0 -0
  244. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/python/calls.py +0 -0
  245. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/python/imports.py +0 -0
  246. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/python/inheritance.py +0 -0
  247. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/python/symbols.py +0 -0
  248. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/swift/README_AI.md +0 -0
  249. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/swift/__init__.py +0 -0
  250. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/swift/calls.py +0 -0
  251. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/swift/imports.py +0 -0
  252. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/swift/inheritance.py +0 -0
  253. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/swift/symbols.py +0 -0
  254. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/typescript/calls.py +0 -0
  255. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/typescript/imports.py +0 -0
  256. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/typescript/inheritance.py +0 -0
  257. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/typescript/symbols.py +0 -0
  258. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/parsers/utils.py +0 -0
  259. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/route_extractor.py +0 -0
  260. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/route_registry.py +0 -0
  261. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/scanner.py +0 -0
  262. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/semantic_extractor.py +0 -0
  263. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/skill_helpers.py +0 -0
  264. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/smart_writer.py +0 -0
  265. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/symbol_index.py +0 -0
  266. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/symbol_scorer.py +0 -0
  267. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/tech_debt.py +0 -0
  268. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/tech_debt_formatters.py +0 -0
  269. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/templates/README_AI.md +0 -0
  270. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/templates/__init__.py +0 -0
  271. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/templates/claude_md_core.md +0 -0
  272. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/test_smells.py +0 -0
  273. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/writer.py +0 -0
  274. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/writers/README_AI.md +0 -0
  275. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/writers/__init__.py +0 -0
  276. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/writers/core.py +0 -0
  277. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/writers/detailed_generator.py +0 -0
  278. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/writers/navigation_generator.py +0 -0
  279. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/writers/overview_generator.py +0 -0
  280. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/src/codeindex/writers/utils.py +0 -0
  281. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/test_generator/generator.py +0 -0
  282. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/test_generator/scripts/analyze_legacy_tests.py +0 -0
  283. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/test_generator/scripts/compare_coverage.py +0 -0
  284. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/test_generator/scripts/compare_test_results.py +0 -0
  285. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/test_generator/specs/java.yaml +0 -0
  286. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/test_generator/specs/php.yaml +0 -0
  287. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/test_generator/specs/python.yaml +0 -0
  288. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/test_generator/templates/inheritance_test.py.j2 +0 -0
  289. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/__init__.py +0 -0
  290. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/conftest.py +0 -0
  291. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/extractors/README_AI.md +0 -0
  292. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/extractors/__init__.py +0 -0
  293. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/extractors/test_spring.py +0 -0
  294. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/extractors/test_thinkphp.py +0 -0
  295. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/extractors/test_thinkphp_description.py +0 -0
  296. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/features/README.md +0 -0
  297. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/features/cli_scan_defaults.feature +0 -0
  298. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/features/help_system.feature +0 -0
  299. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/features/init_wizard.feature +0 -0
  300. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/features/symbol_overload_detection.feature +0 -0
  301. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/features/tech_debt_detection.feature +0 -0
  302. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/features/tech_debt_reporting.feature +0 -0
  303. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/README_AI.md +0 -0
  304. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/cli_parse/Controller.php +0 -0
  305. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/cli_parse/README_AI.md +0 -0
  306. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/cli_parse/Service.java +0 -0
  307. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/cli_parse/Simple.java +0 -0
  308. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/cli_parse/broken.py +0 -0
  309. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/cli_parse/complete.py +0 -0
  310. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/cli_parse/service.ts +0 -0
  311. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/cli_parse/simple.php +0 -0
  312. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/cli_parse/simple.py +0 -0
  313. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/cli_parse/unsupported.txt +0 -0
  314. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/java/enum.java +0 -0
  315. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/java/generics.java +0 -0
  316. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/java/imports.java +0 -0
  317. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/java/interface.java +0 -0
  318. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/java/record.java +0 -0
  319. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/java/sealed_class.java +0 -0
  320. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/java/simple_class.java +0 -0
  321. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/java/spring/Application.java +0 -0
  322. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/java/spring/User.java +0 -0
  323. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/java/spring/UserController.java +0 -0
  324. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/java/spring/UserRepository.java +0 -0
  325. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/java/spring/UserService.java +0 -0
  326. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/java/spring_controller.java +0 -0
  327. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/typescript/app.js +0 -0
  328. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/typescript/component.tsx +0 -0
  329. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/fixtures/typescript/service.ts +0 -0
  330. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/legacy/README.md +0 -0
  331. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/legacy/README_AI.md +0 -0
  332. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/legacy/test_hierarchical_test/level1/file1.py +0 -0
  333. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/legacy/test_hierarchical_test/level1/level2a/file2.py +0 -0
  334. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/legacy/test_hierarchical_test/level1/level2a/level3/file4.py +0 -0
  335. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/legacy/test_hierarchical_test/level1/level2b/file3.py +0 -0
  336. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/legacy/test_hierarchy_simple.py +0 -0
  337. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_adaptive_config.py +0 -0
  338. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_adaptive_selector.py +0 -0
  339. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_ai_helper.py +0 -0
  340. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_backward_compatibility.py +0 -0
  341. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_call_integration.py +0 -0
  342. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_claude_md.py +0 -0
  343. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_claude_md_injection.py +0 -0
  344. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_cli_config_gitignore.py +0 -0
  345. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_cli_debt_scan.py +0 -0
  346. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_cli_docstring_options.py +0 -0
  347. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_cli_hooks.py +0 -0
  348. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_cli_json.py +0 -0
  349. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_cli_parse.py +0 -0
  350. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_cli_scan_defaults_bdd.py +0 -0
  351. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_cli_tech_debt.py +0 -0
  352. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_config_adaptive.py +0 -0
  353. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_dataclass_structure.py +0 -0
  354. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_directory_tree.py +0 -0
  355. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_docstring_config.py +0 -0
  356. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_docstring_processor.py +0 -0
  357. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_doctor.py +0 -0
  358. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_enricher.py +0 -0
  359. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_enricher_integration.py +0 -0
  360. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_error_handling.py +0 -0
  361. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_file_classifier.py +0 -0
  362. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_help_system_bdd.py +0 -0
  363. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_hook_post_commit.py +0 -0
  364. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_hooks.py +0 -0
  365. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_hooks_config.py +0 -0
  366. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_hooks_integration.py +0 -0
  367. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_init_minimal_scope.py +0 -0
  368. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_init_wizard_bdd.py +0 -0
  369. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_integration_swift_objc.py +0 -0
  370. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_java_annotations.py +0 -0
  371. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_java_calls.py +0 -0
  372. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_java_edge_cases.py +0 -0
  373. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_java_generic_bounds.py +0 -0
  374. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_java_inheritance.py +0 -0
  375. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_java_lambda.py +0 -0
  376. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_java_lombok.py +0 -0
  377. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_java_module.py +0 -0
  378. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_java_spring.py +0 -0
  379. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_java_throws.py +0 -0
  380. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_json_output.py +0 -0
  381. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_lazy_loading.py +0 -0
  382. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_list_dirs_diagnostic.py +0 -0
  383. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_loomgraph_integration.py +0 -0
  384. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_objc_association_utils.py +0 -0
  385. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_parallel_scan.py +0 -0
  386. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_parser.py +0 -0
  387. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_parser_detection.py +0 -0
  388. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_parser_objc_association.py +0 -0
  389. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_parser_objc_basic.py +0 -0
  390. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_parser_objc_bridging.py +0 -0
  391. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_parser_objc_categories.py +0 -0
  392. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_parser_swift_docstrings.py +0 -0
  393. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_parser_swift_extensions.py +0 -0
  394. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_parser_swift_generics.py +0 -0
  395. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_parser_swift_inheritance.py +0 -0
  396. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_parser_swift_integration.py +0 -0
  397. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_parser_swift_poc.py +0 -0
  398. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_parser_swift_properties.py +0 -0
  399. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_parser_swift_property_wrappers.py +0 -0
  400. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_parser_swift_protocols.py +0 -0
  401. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_parser_swift_signatures.py +0 -0
  402. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_php_calls.py +0 -0
  403. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_php_comment_extraction.py +0 -0
  404. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_php_docstring_extraction.py +0 -0
  405. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_php_import_alias.py +0 -0
  406. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_php_inheritance.py +0 -0
  407. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_php_loomgraph_integration.py +0 -0
  408. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_project_index_semantic.py +0 -0
  409. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_python_calls.py +0 -0
  410. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_python_docstring_description.py +0 -0
  411. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_python_import_alias.py +0 -0
  412. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_python_inheritance.py +0 -0
  413. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_route_extractor.py +0 -0
  414. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_route_info.py +0 -0
  415. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_route_registry.py +0 -0
  416. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_route_table_description.py +0 -0
  417. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_route_table_display.py +0 -0
  418. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_scanall_auto_ai.py +0 -0
  419. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_scanner_passthrough.py +0 -0
  420. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_semantic_extractor.py +0 -0
  421. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_skill_helpers.py +0 -0
  422. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_smart_writer.py +0 -0
  423. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_smart_writer_adaptive.py +0 -0
  424. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_smart_writer_docstring.py +0 -0
  425. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_smart_writer_enriched.py +0 -0
  426. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_smart_writer_integration.py +0 -0
  427. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_smart_writer_semantic.py +0 -0
  428. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_story_4_4_integration.py +0 -0
  429. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_symbol_overload.py +0 -0
  430. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_symbol_scorer.py +0 -0
  431. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_tech_debt_bdd.py +0 -0
  432. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_tech_debt_detector.py +0 -0
  433. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_tech_debt_formatters.py +0 -0
  434. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_tech_debt_ios.py +0 -0
  435. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_tech_debt_java.py +0 -0
  436. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_tech_debt_reporter.py +0 -0
  437. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_test_smells.py +0 -0
  438. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_thinkphp_route_extractor.py +0 -0
  439. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_typescript_integration.py +0 -0
  440. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_windows_path_optimization.py +0 -0
  441. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/test_writer_preserves_enrichment.py +0 -0
  442. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/writers/README_AI.md +0 -0
  443. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/writers/__init__.py +0 -0
  444. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/writers/test_generators.py +0 -0
  445. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/tests/writers/test_utils.py +0 -0
  446. {ai_codeindex-0.26.2 → ai_codeindex-0.27.0}/uv.lock +0 -0
@@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.27.0] - 2026-06-28
11
+
12
+ **Theme**: graph-export + parser robustness. Ships the new `codeindex
13
+ graph-export` command — codeindex's write-once data contract with loomgraph
14
+ (ADR-007, gated GREEN/YELLOW by the LoomGraph#30 consumption spike) — plus
15
+ the in-run AI retry (#97) and the cross-language partial-parse recovery (#95)
16
+ that were sitting unreleased on master. graph-export is **additive**: it is a
17
+ standalone command, the new `GraphBuffer` IR (#101) it reuses is dormant
18
+ (unwired into `scan-all`), and existing `scan-all` / `parse` / `symbols`
19
+ output is unchanged. No migration needed.
20
+
21
+ ### Added
22
+
23
+ - **`codeindex graph-export` — write-once graph artifact for loomgraph** (GH #102, ADR-007, **experimental schema_version 0**): a standalone command that does its own clean whole-tree parse and dumps NDJSON of code entities (`class`/`function`/`method`, module-qualified id + `source_id` + first-line description + `provenance`) and `CALLS`/`INHERITS` edges. It is **decoupled from `scan-all`/README render** — the LoomGraph#30 consumption spike (verdict 🟡 YELLOW) justified the export but not the #101 render-flip, and the two are architecturally independent (export needs the buffer *populated*, not the render path *flipped*). The parser emits *file-local* names, so the export performs the only cross-file resolution pass: every edge carries a **`resolution_qualifier`** (`resolved` / `ambiguous` / `unresolved`, with `candidates` on ambiguous) so a consumer never reads an unresolved edge as real, plus **`dst_raw`** (the original best-effort name) so a consumer can still synthesise an external stub or filter framework noise when `dst` is null, and the meta header carries **`provenance_completeness`** flagging that AST extraction misses dynamic dispatch / reflection (the spike's E-class finding — an absent edge means "not statically resolvable", not "none"). Schema is experimental and Python-validated; a TS spot-check precedes any stable-contract promise. Reuses the #101 `GraphBuffer` purely as the parsed-data container; ships no persistent/mutable state (ADR-007).
24
+ - **`scan-all --ai` retries transient AI failures in-run** (GH #97): a serial enrichment pass that hit a one-off haiku timeout / rate-limit / 5xx previously lost that directory until a manual re-run (observed 12/50 transient failures in the GH #94 A/B). `invoke_ai_cli` now takes `max_attempts` (scan paths use 3) and retries with exponential backoff, but **only** on recognised-transient signals (`_is_transient`: timeout, rate-limit, 429, 502/503/529, overload, connection reset, …). Permanent failures — a misconfigured `ai_command` (`command not found`, exit 127) or any unlabeled non-zero exit — **fail fast** (single attempt) so they are not hammered N× across every directory. Not a backend/direct-API change: the agent-CLI invocation stays the only transport. Default `max_attempts=1` preserves single-shot behavior for every other caller.
25
+
26
+ ### Fixed
27
+
28
+ - **TypeScript parser no longer zeroes out a whole file on one unsupported construct** (GH #95): the bundled `tree-sitter-typescript` grammar (0.23.2 — the latest published, so this is *not* a stale pin but upstream grammar lag) does not parse some modern-TS constructs, e.g. `export type *` (TS 5.0) and generic-typed tagged templates like Prisma `$queryRaw<{...}[]>`...``. The parser bailed the moment `tree.root_node.has_error` was true, returning `symbols: []` — so a single unparseable line dropped the file's entire class/method set from `PROJECT_SYMBOLS.md` and its directory `README_AI.md` (hit 2/608 `.ts` files on a real monorepo, silently). tree-sitter error recovery is *local*, so the surrounding symbols are still in the tree. `TypeScriptParser.parse` now extracts symbols regardless of `has_error`, returns whatever is recoverable flagged with a new `ParseResult.partial=True`, and only surfaces the hard `error="Syntax error in source file"` when nothing at all could be recovered. Consumers that branch on `result.error` (enrichment, tech-debt, error counts) are unaffected — a partial file has `error=None` so its recovered symbols flow through. Verified: `LockController.ts` with a `$queryRaw<T>` line went from `symbols: []` to recovering its class + all 4 members.
29
+ - **Same partial-parse recovery applied to all remaining parsers** (GH #95 fast-follow): the identical `has_error` early-bail existed in `base` (used by Swift), `python`, `java`, `php`, and `objc`. All now extract regardless of `has_error`, return recoverable symbols flagged `partial=True`, and only emit the hard error when nothing is recoverable — so a single malformed construct no longer zeroes a whole file in any supported language. Cross-language regression test (`tests/test_parser_partial_recovery.py`) covers python/java/php/swift/objc; two Java tests that asserted the old all-or-nothing contract were updated to the graceful-degradation contract.
30
+
10
31
  ## [0.26.2] - 2026-06-22
11
32
 
12
33
  **Theme**: enrichment-quality patch. `scan-all --ai` was silently writing punt
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ai-codeindex
3
- Version: 0.26.2
3
+ Version: 0.27.0
4
4
  Summary: AI-native code indexing tool for large codebases
5
5
  Project-URL: Homepage, https://github.com/dreamlx/codeindex
6
6
  Project-URL: Documentation, https://github.com/dreamlx/codeindex
@@ -0,0 +1,128 @@
1
+ # graph-export — codeindex → loomgraph data contract
2
+
3
+ > **Status: EXPERIMENTAL (`schema_version: 0`).** Validated on Python; a
4
+ > TypeScript spot-check precedes any stable-contract promise. Fields and
5
+ > format may change without deprecation while at version 0.
6
+
7
+ `codeindex graph-export` dumps a **write-once** NDJSON graph of the codebase
8
+ for downstream consumers (loomgraph) to read. Per [ADR-007](../architecture/adr/007-codeindex-stateless-graph-ownership.md)
9
+ codeindex stays a stateless emitter: this command holds **no** persistent or
10
+ mutable state — no `.db`, no incremental sync, no vector index.
11
+
12
+ ## Usage
13
+
14
+ ```bash
15
+ codeindex graph-export --root . -o graph-export.ndjson
16
+ codeindex graph-export --root . -o - # stdout
17
+ ```
18
+
19
+ It does its **own clean whole-tree parse** (every source file exactly once)
20
+ and is fully decoupled from `scan-all` / README rendering — running it never
21
+ touches `README_AI.md`.
22
+
23
+ ## Format
24
+
25
+ NDJSON. Line 1 is the `meta` record; then `entity` records; then `edge`
26
+ records. All records carry a `type` tag.
27
+
28
+ ```jsonc
29
+ {"type":"meta","schema_version":0,"generator":"codeindex","provenance_completeness":"ast-only: ..."}
30
+ {"type":"entity","id":"app.service.AuthService","entity_type":"class","source_id":"app/service.py:8","description":"Authenticates users.","provenance":"ast"}
31
+ {"type":"edge","kind":"CALLS","src":"app.service.AuthService.login","dst":"app.service.AuthService.authenticate","resolution_qualifier":"resolved","source_id":"app/service.py:15"}
32
+ {"type":"edge","kind":"CALLS","src":"app.workers.kickoff","dst":null,"resolution_qualifier":"ambiguous","candidates":["app.workers.Builder.run","app.workers.Packer.run"],"source_id":"app/workers.py:15"}
33
+ ```
34
+
35
+ ### Naming convention (`id`)
36
+
37
+ Entity ids are **fully-qualified and path-derived**: the module is the file
38
+ path *relative to the scan root* with the extension dropped and `/` → `.`,
39
+ then the file-local symbol name appended. So `src/loomgraph/cli/_common.py`'s
40
+ `prepare_workspace_store` becomes `src.loomgraph.cli._common.prepare_workspace_store`.
41
+
42
+ Fully-qualified is deliberate — it resolves same-name collisions across
43
+ sibling classes/modules (the spike's F-class) and makes ownership explicit.
44
+
45
+ > **src-layout caveat.** Because the module is *path*-derived, not
46
+ > *import*-derived, a `src/`-layout project carries the layout dir in the id
47
+ > (`src.loomgraph.…`, where the real Python import path is `loomgraph.…`).
48
+ > codeindex does **not** strip it in v0 — there is no robust, config-free way
49
+ > to tell a layout dir (`src/`, strip) from a genuine top package (`app/`,
50
+ > keep). A consumer that maintains its own import-path index should normalise
51
+ > the layout prefix when ingesting these ids (it knows the project layout;
52
+ > codeindex, scanning a bare tree, does not). A codeindex-side `module_root` option is a
53
+ > possible v1 addition if multiple consumers need it.
54
+
55
+ ### Entity
56
+
57
+ | field | meaning |
58
+ |---|---|
59
+ | `id` | fully-qualified, path-derived name (see above), e.g. `app.service.AuthService.login` |
60
+ | `entity_type` | `class` \| `function` \| `method` |
61
+ | `source_id` | `relpath:line` |
62
+ | `description` | first line of the docstring (may be empty) |
63
+ | `provenance` | `ast` (L1 structural) |
64
+
65
+ ### Edge
66
+
67
+ | field | meaning |
68
+ |---|---|
69
+ | `kind` | `CALLS` \| `INHERITS` |
70
+ | `src` | resolved entity id of the caller / child class |
71
+ | `dst` | resolved entity id of the callee / parent, or `null` if not resolved |
72
+ | `dst_raw` | the original best-effort name the resolver tried (file-local). Always present; **load-bearing when `dst` is null** — it is the only record of *what* was called, so a consumer can synthesise an external stub or filter framework noise (e.g. `expect`, `Date.now`) |
73
+ | `resolution_qualifier` | `resolved` \| `ambiguous` \| `unresolved` |
74
+ | `candidates` | (ambiguous only) the entity ids the name could refer to |
75
+ | `source_id` | `relpath:line` of the call / class definition |
76
+
77
+ ## Scope — a structural slice, not a full graph index
78
+
79
+ The export is codeindex's **structural slice** (L1+L2): real code symbols
80
+ (`class` / `function` / `method`) and their `CALLS` / `INHERITS` edges. It is
81
+ **not** a complete graph index and is **not** meant to replace a consumer's
82
+ own index.
83
+
84
+ Deliberately **not** emitted (the consumer synthesises these around the
85
+ slice during ingestion, per ADR-007):
86
+
87
+ - **file / module container nodes** — derivable from each entity's `source_id`.
88
+ Consequence: a `<module>`-level call has a `src` (the dotted module path)
89
+ with no backing `entity` record; that's expected, the consumer materialises
90
+ the container if it wants one. (`entity_type: "module"` may be added in v1
91
+ if synthesising modules proves painful downstream.)
92
+ - **external / stdlib stubs** — these are exactly where `unresolved` edges
93
+ point (see below); the consumer decides whether to materialise stub nodes.
94
+
95
+ This matches the LoomGraph#30 GREEN field set (which contained no module/file
96
+ nodes) and keeps the codeindex/loomgraph division clean: codeindex emits the
97
+ symbol-level truth, loomgraph builds the container + external + semantic
98
+ scaffolding on top.
99
+
100
+ ## Consumer contract — read these two caveats
101
+
102
+ The parser emits **file-local** names; the export runs the only cross-file
103
+ resolution pass. Two metadata mechanisms exist because that resolution and
104
+ the underlying AST extraction are lossy — **a consumer that ignores them will
105
+ draw wrong conclusions**:
106
+
107
+ 1. **`resolution_qualifier`** — never treat an `unresolved` or `ambiguous`
108
+ edge as a confirmed relationship. `unresolved` usually means external /
109
+ stdlib or a name not in the tree (with `dst: null`); `ambiguous` means the
110
+ name matched several entities (see `candidates`, `dst: null`). A **high
111
+ unresolved fraction is normal** — most calls in real code go to stdlib /
112
+ third-party / methods AST cannot statically resolve (≈59% on a real
113
+ loomgraph round-trip). The consumer owns the dangling-edge policy: drop,
114
+ keep as dangling, or materialise an external stub node as the `dst`.
115
+ codeindex emits no sentinel/placeholder entity — the entity set contains
116
+ only real code symbols.
117
+ 2. **`provenance_completeness`** (meta) — extraction is AST-only. Dynamic
118
+ dispatch (`getattr` / duck-typing / event handlers), reflection /
119
+ metaclasses, and decorator wiring are **not** captured. An **absent edge
120
+ means "not statically resolvable", not "none"** — this was the decisive
121
+ finding of the LoomGraph#30 consumption spike.
122
+
123
+ ## What this is NOT
124
+
125
+ Per ADR-007, codeindex does not own a persistent graph. No mutable `.db`,
126
+ incremental sync, corruption recovery, or `sqlite-vec` index — those, plus L3
127
+ (design-doc LLM extraction), are loomgraph's. This artifact is a one-shot
128
+ snapshot loomgraph reads (process-decoupled, decision (a)).
@@ -0,0 +1,60 @@
1
+ # Release Notes - v0.27.0
2
+
3
+ **Theme**: graph-export + parser robustness.
4
+
5
+ This release ships codeindex's first **write-once graph artifact** — the data
6
+ contract with loomgraph (per [ADR-007](../architecture/adr/007-codeindex-stateless-graph-ownership.md)) —
7
+ alongside the AI-retry and partial-parse robustness fixes that were sitting
8
+ unreleased on master.
9
+
10
+ > **Upgrade is safe and additive.** `graph-export` is a brand-new standalone
11
+ > command; the `GraphBuffer` IR it reuses is dormant (not wired into
12
+ > `scan-all`); and existing `scan-all` / `parse` / `symbols` output is
13
+ > unchanged. No migration, no cache flush needed.
14
+
15
+ ## New: `codeindex graph-export`
16
+
17
+ A standalone command that does its own clean whole-tree parse and emits a
18
+ **write-once NDJSON** graph for downstream consumers (loomgraph):
19
+
20
+ ```bash
21
+ codeindex graph-export --root . -o graph-export.ndjson
22
+ codeindex graph-export --root . -o - # stdout
23
+ ```
24
+
25
+ - **Entities** — `class` / `function` / `method`, module-qualified id,
26
+ `source_id` (`relpath:line`), first-line description, `provenance`.
27
+ - **Edges** — `CALLS` / `INHERITS`, each carrying a `resolution_qualifier`
28
+ (`resolved` / `ambiguous` / `unresolved`) plus `dst_raw` (the original
29
+ name, load-bearing when `dst` is null) and `candidates` on ambiguous.
30
+ - **Meta** — `schema_version` + `provenance_completeness` flagging that AST
31
+ extraction does not capture dynamic dispatch / reflection.
32
+
33
+ **Status: experimental (`schema_version: 0`).** The schema may change without
34
+ deprecation while at version 0; validated on Python with a TypeScript
35
+ spot-check. Full contract + consumer caveats: [docs/guides/graph-export.md](../guides/graph-export.md).
36
+
37
+ Decoupling note: the LoomGraph#30 consumption spike (verdict 🟡 YELLOW)
38
+ justified this export but **not** an internal render-flip (#101 Phase 2);
39
+ the two are architecturally independent and the flip is deferred.
40
+
41
+ ## Robustness (previously unreleased on master)
42
+
43
+ - **In-run AI retry/backoff** (#97): `scan-all --ai` now retries
44
+ *recognised-transient* failures (timeout / rate-limit / 5xx) with
45
+ exponential backoff (scan paths use 3 attempts); permanent failures
46
+ (e.g. misconfigured `ai_command`) still fail fast. Agent-CLI stays the
47
+ only transport.
48
+ - **Cross-language partial-parse recovery** (#95): a single unparseable
49
+ construct no longer zeroes a whole file's symbols. All parsers
50
+ (python / typescript / java / php / swift / objc) now return recoverable
51
+ symbols flagged `partial=True`, surfacing a hard error only when nothing
52
+ is recoverable.
53
+
54
+ ## Internal
55
+
56
+ - **GraphBuffer IR** (#101): a per-run in-memory IR between parse and render,
57
+ shipped dormant (unwired) with a characterization safety net. Reused by
58
+ `graph-export`; no user-facing behavior change.
59
+
60
+ See [CHANGELOG.md](../../CHANGELOG.md) for the full entry list.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ai-codeindex"
3
- version = "0.26.2"
3
+ version = "0.27.0"
4
4
  description = "AI-native code indexing tool for large codebases"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -1,12 +1,12 @@
1
1
  <!-- codeindex navigation index — agent: drill into source via Read/Grep for precise mechanism; do not treat this as final word. -->
2
- <!-- Generated by codeindex (detailed) at 2026-06-21T23:56:14.087118 -->
2
+ <!-- Generated by codeindex (detailed) at 2026-06-27T20:08:49.478875 -->
3
3
 
4
4
  # codeindex
5
5
 
6
6
  ## Overview
7
7
 
8
- - **Files**: 89
9
- - **Symbols**: 574
8
+ - **Files**: 92
9
+ - **Symbols**: 599
10
10
 
11
11
  ## Files
12
12
 
@@ -125,6 +125,15 @@ _Documentation CLI commands for codeindex._
125
125
  - `def docs()`
126
126
  - `def show_ai_guide()`
127
127
 
128
+ ### cli_graph_export.py
129
+ _CLI graph-export command — write-once graph artifact for loomgraph (GH #102).
130
+
131
+ Standalone (Path A): does its own clean whole-tree parse and dumps a
132
+ wr_
133
+
134
+ **Functions:**
135
+ - `def graph_export(root: Path, output: str, quiet: bool)`
136
+
128
137
  ### cli_hooks.py
129
138
  _Git Hooks management module for codeindex.
130
139
 
@@ -337,15 +346,7 @@ _Configuration management for codeindex._
337
346
  ### config_help.py
338
347
  _Configuration help documentation for codeindex (Epic 15 Story 15.3).
339
348
 
340
- This module provides comprehensive help documentation for all .codeindex.yaml
341
- co_
342
-
343
- **Functions:**
344
- - `def show_full_config_help() -> None`
345
- - `def _show_param_section(param_name: str) -> None`
346
- - `def explain_parameter(
347
- param_name: str, current_value: Optional[any] = None, cpu_count: Optional[int] = None
348
-
349
+ This module provides comprehensive help documentatio
349
350
 
350
351
  ---
351
352
  _Content truncated due to size limit. See individual module README files for details._
@@ -12,6 +12,7 @@ from .cli_claude_md import claude_md, print_outdated_warning
12
12
  from .cli_config import doctor, init, list_dirs, status
13
13
  from .cli_config_commands import config
14
14
  from .cli_docs import docs
15
+ from .cli_graph_export import graph_export
15
16
  from .cli_hooks import hooks
16
17
  from .cli_parse import parse
17
18
  from .cli_scan import scan, scan_all
@@ -44,6 +45,7 @@ main.add_command(affected)
44
45
  main.add_command(tech_debt)
45
46
  main.add_command(tech_debt, name="debt-scan") # Alias for backward compatibility (v0.22.0+)
46
47
  main.add_command(hooks)
48
+ main.add_command(graph_export)
47
49
  main.add_command(docs)
48
50
  main.add_command(claude_md)
49
51
 
@@ -0,0 +1,65 @@
1
+ """CLI graph-export command — write-once graph artifact for loomgraph (GH #102).
2
+
3
+ Standalone (Path A): does its own clean whole-tree parse and dumps a
4
+ write-once NDJSON graph. Does not touch scan-all / README render.
5
+ See ``codeindex.graph_export`` and ADR-007.
6
+ """
7
+
8
+ from pathlib import Path
9
+
10
+ import click
11
+
12
+ from .cli_common import console
13
+ from .config import Config
14
+ from .graph_export import build_export, dump_ndjson, walk_and_parse
15
+
16
+
17
+ @click.command(name="graph-export")
18
+ @click.option(
19
+ "--root",
20
+ type=click.Path(exists=True, file_okay=False, path_type=Path),
21
+ default=Path("."),
22
+ help="Project root to export (default: current directory).",
23
+ )
24
+ @click.option(
25
+ "--output",
26
+ "-o",
27
+ default="graph-export.ndjson",
28
+ help="Output NDJSON path, or '-' for stdout (default: graph-export.ndjson).",
29
+ )
30
+ @click.option("--quiet", "-q", is_flag=True, help="Minimal output.")
31
+ def graph_export(root: Path, output: str, quiet: bool):
32
+ """Export the code graph (entities + CALLS/INHERITS edges) as write-once NDJSON.
33
+
34
+ EXPERIMENTAL (schema_version 0): the contract with loomgraph per ADR-007.
35
+ Each edge carries a resolution_qualifier (resolved / ambiguous / unresolved)
36
+ so a consumer never mistakes an unresolved edge for a real one.
37
+ """
38
+ config_path = root / ".codeindex.yaml"
39
+ config = Config.load(config_path if config_path.exists() else None)
40
+
41
+ buffer = walk_and_parse(root, config)
42
+ model = build_export(buffer, root)
43
+ text = dump_ndjson(model)
44
+
45
+ if output == "-":
46
+ click.echo(text, nl=False)
47
+ return
48
+
49
+ out_path = Path(output)
50
+ if not out_path.is_absolute():
51
+ out_path = root / out_path
52
+ out_path.write_text(text, encoding="utf-8")
53
+
54
+ if not quiet:
55
+ n_amb = sum(
56
+ 1 for e in model.edges if e.resolution_qualifier == "ambiguous"
57
+ )
58
+ n_unres = sum(
59
+ 1 for e in model.edges if e.resolution_qualifier == "unresolved"
60
+ )
61
+ console.print(
62
+ f"[green]✓[/green] graph-export → {out_path} "
63
+ f"[dim]({len(model.entities)} entities, {len(model.edges)} edges; "
64
+ f"{n_amb} ambiguous, {n_unres} unresolved)[/dim]"
65
+ )
@@ -14,6 +14,7 @@ from .config import Config
14
14
  from .directory_tree import DirectoryTree
15
15
  from .docstring_processor import DocstringProcessor
16
16
  from .invoker import (
17
+ AI_SCAN_MAX_ATTEMPTS,
17
18
  clean_ai_output,
18
19
  format_prompt,
19
20
  invoke_ai_cli,
@@ -331,7 +332,9 @@ def _generate_ai_readme(
331
332
  console.print(f" [dim]→ Invoking AI CLI (timeout: {timeout}s)...[/dim]")
332
333
  console.print(f" [dim] Command: {config.ai_command[:50]}...[/dim]")
333
334
 
334
- invoke_result = invoke_ai_cli(config.ai_command, prompt, timeout=timeout)
335
+ invoke_result = invoke_ai_cli(
336
+ config.ai_command, prompt, timeout=timeout, max_attempts=AI_SCAN_MAX_ATTEMPTS
337
+ )
335
338
 
336
339
  if not invoke_result.success:
337
340
  console.print(f"[red]✗ AI CLI error:[/red] {invoke_result.error}")
@@ -775,8 +778,10 @@ def _enrich_directories_with_ai(
775
778
  parent_name = dir_path.parent.name if dir_path.parent != dir_path else ""
776
779
  prompt = build_enrich_prompt(dir_path.name, summary, parent_name)
777
780
 
778
- # Invoke AI CLI
779
- invoke_result = invoke_ai_cli(config.ai_command, prompt, timeout=timeout)
781
+ # Invoke AI CLI (retry transient timeout / rate-limit in-run, GH #97)
782
+ invoke_result = invoke_ai_cli(
783
+ config.ai_command, prompt, timeout=timeout, max_attempts=AI_SCAN_MAX_ATTEMPTS
784
+ )
780
785
 
781
786
  if not invoke_result.success:
782
787
  reason = (invoke_result.error or "unknown").strip().split("\n")[0][:200]
@@ -0,0 +1,116 @@
1
+ """In-memory IR between parse and render (GH #101, ADR-007).
2
+
3
+ ``GraphBuffer`` is a per-run, in-memory intermediate representation of a
4
+ scanned project. It sits between the *parse* stage and the README *render*
5
+ stage, decoupling :class:`~codeindex.writers.SmartWriter` from the live
6
+ scan/parse loop.
7
+
8
+ Scope — Phase 1 (strangler step), deliberately minimal:
9
+
10
+ * Holds one :class:`DirNode` per indexed directory: the render inputs
11
+ (``level``, ``parse_results``, ``child_dirs``) the renderer currently
12
+ consumes.
13
+ * Provides :func:`render_directory` — the seam the eventual SmartWriter flip
14
+ will call. Rendering *from* the buffer must stay byte-identical to the
15
+ direct ``parse -> write_readme`` path (proven by
16
+ ``tests/characterization/test_graphbuffer_equivalence.py``).
17
+
18
+ Deliberately **out of scope** for Phase 1:
19
+
20
+ * The global call / inheritance graph and the write-once graph-export
21
+ artifact. Per ADR-007 that substrate is gated on LoomGraph#30 and is not
22
+ built until that consumption spike comes back GREEN.
23
+ * Wiring into the production ``scan-all`` loop (the flip). Until the buffer
24
+ is the renderer's source of truth, paying its RAM cost in production buys
25
+ nothing, so it stays test-only for now.
26
+
27
+ This module is pure data plus a thin adapter: no AI, no I/O of its own beyond
28
+ what :meth:`SmartWriter.write_readme` already performs.
29
+ """
30
+
31
+ from __future__ import annotations
32
+
33
+ from dataclasses import dataclass, field
34
+ from pathlib import Path
35
+
36
+ from .parser import ParseResult
37
+ from .writers import LevelType, SmartWriter, WriteResult
38
+
39
+
40
+ @dataclass
41
+ class DirNode:
42
+ """One indexed directory's render inputs, captured in the buffer.
43
+
44
+ Attributes mirror exactly the arguments
45
+ :meth:`SmartWriter.write_readme` consumes, so the buffer is a faithful,
46
+ lossless capture of the renderer's input at the moment of the scan.
47
+ """
48
+
49
+ path: Path
50
+ level: LevelType
51
+ parse_results: list[ParseResult] = field(default_factory=list)
52
+ child_dirs: list[Path] = field(default_factory=list)
53
+
54
+
55
+ class GraphBuffer:
56
+ """Per-run, in-memory map of directory -> :class:`DirNode`.
57
+
58
+ Insertion is single-threaded *by contract*: callers may produce
59
+ ``parse_results`` with a parallel pool, but each directory is recorded
60
+ once from a single collecting thread. The buffer performs no locking.
61
+ """
62
+
63
+ def __init__(self) -> None:
64
+ self._dirs: dict[Path, DirNode] = {}
65
+
66
+ def record_directory(
67
+ self,
68
+ dir_path: Path,
69
+ level: LevelType,
70
+ parse_results: list[ParseResult],
71
+ child_dirs: list[Path],
72
+ ) -> DirNode:
73
+ """Capture one directory's render inputs and return the node."""
74
+ node = DirNode(
75
+ path=dir_path,
76
+ level=level,
77
+ parse_results=list(parse_results),
78
+ child_dirs=list(child_dirs),
79
+ )
80
+ self._dirs[dir_path] = node
81
+ return node
82
+
83
+ def get(self, dir_path: Path) -> DirNode | None:
84
+ """Return the buffered node for ``dir_path`` (or ``None``)."""
85
+ return self._dirs.get(dir_path)
86
+
87
+ def directories(self) -> list[DirNode]:
88
+ """Return all buffered nodes (insertion order)."""
89
+ return list(self._dirs.values())
90
+
91
+ def __len__(self) -> int:
92
+ return len(self._dirs)
93
+
94
+ def __contains__(self, dir_path: object) -> bool:
95
+ return dir_path in self._dirs
96
+
97
+
98
+ def render_directory(
99
+ writer: SmartWriter,
100
+ node: DirNode,
101
+ output_file: str = "README_AI.md",
102
+ ) -> WriteResult:
103
+ """Render one directory's README from a buffered :class:`DirNode`.
104
+
105
+ This is the seam the eventual SmartWriter flip will use: the renderer's
106
+ inputs come from the buffer, not from a fresh inline parse. It must stay
107
+ byte-identical to ``writer.write_readme(... parse_results ...)`` on the
108
+ same inputs.
109
+ """
110
+ return writer.write_readme(
111
+ dir_path=node.path,
112
+ parse_results=node.parse_results,
113
+ level=node.level,
114
+ child_dirs=node.child_dirs,
115
+ output_file=output_file,
116
+ )