descry-codegraph 0.3.4__tar.gz → 1.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/.github/workflows/ci.yml +7 -1
  2. descry_codegraph-0.3.4/CLAUDE.md → descry_codegraph-1.0.1/AGENTS.md +14 -13
  3. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/CHANGELOG.md +492 -2
  4. descry_codegraph-1.0.1/CONTRACT.md +93 -0
  5. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/PKG-INFO +64 -29
  6. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/README.md +59 -20
  7. descry_codegraph-1.0.1/SECURITY.md +66 -0
  8. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/claude-skill/README.md +1 -1
  9. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/claude-skill/descry/SKILL.md +21 -16
  10. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/claude-skill/descry/references/cli-reference.md +9 -8
  11. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/claude-skill/descry/references/mcp-tools.md +7 -7
  12. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/claude-skill/descry/references/recipes.md +9 -6
  13. descry_codegraph-1.0.1/docs/CERTAINTY.md +61 -0
  14. descry_codegraph-1.0.1/docs/TOOLS.md +659 -0
  15. descry_codegraph-1.0.1/docs/UPGRADING.md +301 -0
  16. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/justfile +9 -5
  17. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/pi-extension/descry-cli.py +8 -8
  18. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/pi-extension/descry-tools.ts +12 -12
  19. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/pyproject.toml +4 -4
  20. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/__init__.py +1 -1
  21. descry_codegraph-1.0.1/src/descry/_answers.py +7 -0
  22. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/_comments.py +6 -12
  23. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/_files.py +19 -0
  24. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/_graph.py +18 -6
  25. descry_codegraph-1.0.1/src/descry/_parse_cache.py +209 -0
  26. descry_codegraph-1.0.1/src/descry/_parsing.py +3161 -0
  27. descry_codegraph-1.0.1/src/descry/_reads.py +287 -0
  28. descry_codegraph-1.0.1/src/descry/_stdlib.py +110 -0
  29. descry_codegraph-1.0.1/src/descry/_streams.py +11 -0
  30. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/clang_parser.py +241 -80
  31. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/cli.py +199 -156
  32. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/cross_lang.py +17 -77
  33. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/dart_parser.py +27 -36
  34. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/dotnet_parser.py +176 -108
  35. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/embeddings.py +122 -87
  36. descry_codegraph-1.0.1/src/descry/generate.py +1470 -0
  37. descry_codegraph-1.0.1/src/descry/git_history.py +1517 -0
  38. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/go_parser.py +83 -73
  39. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/handlers.py +1390 -971
  40. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/java_parser.py +30 -45
  41. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/mcp_server.py +171 -165
  42. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/php_parser.py +55 -48
  43. descry_codegraph-1.0.1/src/descry/proto_parser.py +66 -0
  44. descry_codegraph-1.0.1/src/descry/python_parser.py +1030 -0
  45. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/query.py +666 -848
  46. descry_codegraph-1.0.1/src/descry/resolver.py +10074 -0
  47. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/ruby_parser.py +126 -92
  48. descry_codegraph-1.0.1/src/descry/rust_parser.py +2195 -0
  49. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/scip/adapter.py +52 -38
  50. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/scip/adapters/clang.py +6 -30
  51. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/scip/adapters/dart.py +7 -58
  52. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/scip/adapters/dotnet.py +15 -70
  53. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/scip/adapters/go.py +19 -53
  54. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/scip/adapters/java.py +18 -73
  55. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/scip/adapters/php.py +18 -63
  56. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/scip/adapters/python.py +27 -43
  57. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/scip/adapters/ruby.py +5 -33
  58. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/scip/adapters/rust.py +12 -50
  59. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/scip/adapters/typescript.py +9 -55
  60. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/scip/cache.py +77 -219
  61. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/scip/parser.py +102 -194
  62. descry_codegraph-1.0.1/src/descry/scip/support.py +40 -0
  63. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/stdlib/cpp.json +99 -141
  64. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/stdlib/dotnet.json +652 -1
  65. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/stdlib/go.json +49 -1
  66. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/stdlib/python.json +60 -14
  67. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/stdlib/ruby.json +649 -414
  68. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/stdlib/rust.json +2714 -0
  69. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/stdlib/typescript.json +6 -1
  70. descry_codegraph-1.0.1/src/descry/ts_parser.py +6089 -0
  71. descry_codegraph-1.0.1/src/descry/web/server.py +803 -0
  72. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/web/web/index.html +188 -282
  73. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/web/web/style.css +1 -70
  74. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/conftest.py +12 -0
  75. descry_codegraph-1.0.1/tests/ground_truth/c/Makefile +2 -0
  76. descry_codegraph-1.0.1/tests/ground_truth/c/expected.json +14 -0
  77. descry_codegraph-1.0.1/tests/ground_truth/c/io.c +7 -0
  78. descry_codegraph-1.0.1/tests/ground_truth/c/io.h +2 -0
  79. descry_codegraph-1.0.1/tests/ground_truth/c/main.c +3 -0
  80. descry_codegraph-1.0.1/tests/ground_truth/c/order.c +5 -0
  81. descry_codegraph-1.0.1/tests/ground_truth/cpp/Makefile +2 -0
  82. descry_codegraph-1.0.1/tests/ground_truth/cpp/expected.json +17 -0
  83. descry_codegraph-1.0.1/tests/ground_truth/cpp/main.cpp +9 -0
  84. descry_codegraph-1.0.1/tests/ground_truth/cpp/models.hpp +25 -0
  85. descry_codegraph-1.0.1/tests/ground_truth/cpp/reader.hpp +9 -0
  86. descry_codegraph-1.0.1/tests/ground_truth/csharp/Gt.csproj +6 -0
  87. descry_codegraph-1.0.1/tests/ground_truth/csharp/Io.cs +15 -0
  88. descry_codegraph-1.0.1/tests/ground_truth/csharp/Models.cs +36 -0
  89. descry_codegraph-1.0.1/tests/ground_truth/csharp/Program.cs +9 -0
  90. descry_codegraph-1.0.1/tests/ground_truth/csharp/expected.json +17 -0
  91. descry_codegraph-1.0.1/tests/ground_truth/dart/bin/main.dart +8 -0
  92. descry_codegraph-1.0.1/tests/ground_truth/dart/expected.json +78 -0
  93. descry_codegraph-1.0.1/tests/ground_truth/dart/lib/io.dart +9 -0
  94. descry_codegraph-1.0.1/tests/ground_truth/dart/lib/models.dart +21 -0
  95. descry_codegraph-1.0.1/tests/ground_truth/dart/pubspec.yaml +3 -0
  96. descry_codegraph-1.0.1/tests/ground_truth/go/expected.json +17 -0
  97. descry_codegraph-1.0.1/tests/ground_truth/go/go.mod +3 -0
  98. descry_codegraph-1.0.1/tests/ground_truth/go/io.go +13 -0
  99. descry_codegraph-1.0.1/tests/ground_truth/go/main.go +7 -0
  100. descry_codegraph-1.0.1/tests/ground_truth/go/models.go +20 -0
  101. descry_codegraph-1.0.1/tests/ground_truth/java/expected.json +19 -0
  102. descry_codegraph-1.0.1/tests/ground_truth/java/src/gt/Base.java +11 -0
  103. descry_codegraph-1.0.1/tests/ground_truth/java/src/gt/Io.java +7 -0
  104. descry_codegraph-1.0.1/tests/ground_truth/java/src/gt/Main.java +9 -0
  105. descry_codegraph-1.0.1/tests/ground_truth/java/src/gt/Order.java +7 -0
  106. descry_codegraph-1.0.1/tests/ground_truth/java/src/gt/Reader.java +7 -0
  107. descry_codegraph-1.0.1/tests/ground_truth/java/src/gt/User.java +15 -0
  108. descry_codegraph-1.0.1/tests/ground_truth/javascript/expected.json +91 -0
  109. descry_codegraph-1.0.1/tests/ground_truth/javascript/package.json +1 -0
  110. descry_codegraph-1.0.1/tests/ground_truth/javascript/src/io.js +14 -0
  111. descry_codegraph-1.0.1/tests/ground_truth/javascript/src/main.js +13 -0
  112. descry_codegraph-1.0.1/tests/ground_truth/javascript/src/models.js +28 -0
  113. descry_codegraph-1.0.1/tests/ground_truth/php/composer.json +1 -0
  114. descry_codegraph-1.0.1/tests/ground_truth/php/expected.json +86 -0
  115. descry_codegraph-1.0.1/tests/ground_truth/php/src/Io.php +19 -0
  116. descry_codegraph-1.0.1/tests/ground_truth/php/src/Models.php +38 -0
  117. descry_codegraph-1.0.1/tests/ground_truth/php/src/main.php +17 -0
  118. descry_codegraph-1.0.1/tests/ground_truth/python/app/__init__.py +0 -0
  119. descry_codegraph-1.0.1/tests/ground_truth/python/app/io.py +14 -0
  120. descry_codegraph-1.0.1/tests/ground_truth/python/app/main.py +13 -0
  121. descry_codegraph-1.0.1/tests/ground_truth/python/app/models.py +20 -0
  122. descry_codegraph-1.0.1/tests/ground_truth/python/expected.json +90 -0
  123. descry_codegraph-1.0.1/tests/ground_truth/python/pyproject.toml +2 -0
  124. descry_codegraph-1.0.1/tests/ground_truth/ruby/Gemfile +1 -0
  125. descry_codegraph-1.0.1/tests/ground_truth/ruby/expected.json +85 -0
  126. descry_codegraph-1.0.1/tests/ground_truth/ruby/lib/io.rb +16 -0
  127. descry_codegraph-1.0.1/tests/ground_truth/ruby/lib/main.rb +13 -0
  128. descry_codegraph-1.0.1/tests/ground_truth/ruby/lib/models.rb +26 -0
  129. descry_codegraph-1.0.1/tests/ground_truth/rust/Cargo.toml +4 -0
  130. descry_codegraph-1.0.1/tests/ground_truth/rust/expected.json +77 -0
  131. descry_codegraph-1.0.1/tests/ground_truth/rust/src/io.rs +11 -0
  132. descry_codegraph-1.0.1/tests/ground_truth/rust/src/main.rs +11 -0
  133. descry_codegraph-1.0.1/tests/ground_truth/rust/src/models.rs +42 -0
  134. descry_codegraph-1.0.1/tests/ground_truth/typescript/expected.json +87 -0
  135. descry_codegraph-1.0.1/tests/ground_truth/typescript/package.json +1 -0
  136. descry_codegraph-1.0.1/tests/ground_truth/typescript/src/io.ts +13 -0
  137. descry_codegraph-1.0.1/tests/ground_truth/typescript/src/main.ts +14 -0
  138. descry_codegraph-1.0.1/tests/ground_truth/typescript/src/models.ts +28 -0
  139. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_backtracking.py +101 -67
  140. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_clang_parser.py +1 -2
  141. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_cli.py +63 -46
  142. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_config.py +63 -17
  143. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_cross_lang.py +63 -33
  144. descry_codegraph-1.0.1/tests/test_docs.py +22 -0
  145. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_dotnet_parser.py +7 -7
  146. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_embeddings.py +94 -8
  147. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_generate.py +26499 -21437
  148. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_git_history.py +511 -122
  149. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_go_parser.py +16 -30
  150. descry_codegraph-1.0.1/tests/test_ground_truth.py +174 -0
  151. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_handlers.py +502 -111
  152. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_hardening.py +151 -26
  153. descry_codegraph-1.0.1/tests/test_interfaces.py +581 -0
  154. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_mcp.py +99 -13
  155. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_non_regular_files.py +2 -2
  156. descry_codegraph-1.0.1/tests/test_parse_cache.py +227 -0
  157. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_query.py +383 -379
  158. descry_codegraph-1.0.1/tests/test_resolve_cache.py +233 -0
  159. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_ruby_parser.py +1 -0
  160. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_scip.py +136 -59
  161. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_scip_cache.py +120 -32
  162. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_scip_clang.py +10 -11
  163. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_scip_dart.py +7 -9
  164. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_scip_dotnet.py +3 -12
  165. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_scip_go.py +1 -8
  166. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_scip_java.py +16 -25
  167. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_scip_php.py +1 -10
  168. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_scip_ruby.py +1 -10
  169. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_stdlib.py +126 -7
  170. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_web_server.py +268 -267
  171. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_written_through.py +5 -5
  172. descry_codegraph-1.0.1/tools/docs/gen_tools.py +167 -0
  173. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tools/stdlib/README.md +58 -22
  174. descry_codegraph-1.0.1/tools/stdlib/common.py +171 -0
  175. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tools/stdlib/gen_c.py +31 -58
  176. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tools/stdlib/gen_cpp.py +188 -125
  177. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tools/stdlib/gen_dart.py +25 -33
  178. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tools/stdlib/gen_dotnet.py +113 -32
  179. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tools/stdlib/gen_go.py +27 -20
  180. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tools/stdlib/gen_java.py +8 -1
  181. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tools/stdlib/gen_node.py +2 -2
  182. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tools/stdlib/gen_php.py +6 -1
  183. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tools/stdlib/gen_python.py +175 -50
  184. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tools/stdlib/gen_ruby.py +89 -60
  185. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tools/stdlib/gen_rust.py +208 -3
  186. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tools/stdlib/gen_typescript.py +48 -33
  187. descry_codegraph-0.3.4/SECURITY.md +0 -27
  188. descry_codegraph-0.3.4/src/descry/_stdlib.py +0 -71
  189. descry_codegraph-0.3.4/src/descry/generate.py +0 -25636
  190. descry_codegraph-0.3.4/src/descry/git_history.py +0 -1771
  191. descry_codegraph-0.3.4/src/descry/scip/support.py +0 -70
  192. descry_codegraph-0.3.4/src/descry/web/server.py +0 -1089
  193. descry_codegraph-0.3.4/tests/test_interfaces.py +0 -296
  194. descry_codegraph-0.3.4/tools/stdlib/common.py +0 -76
  195. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/.github/assets/01-landing.png +0 -0
  196. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/.github/workflows/release.yml +0 -0
  197. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/.gitignore +0 -0
  198. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/LICENSE +0 -0
  199. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/THIRD-PARTY-NOTICES.md +0 -0
  200. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/pi-extension/README.md +0 -0
  201. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/_env.py +0 -0
  202. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/scip/__init__.py +0 -0
  203. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/scip/adapters/__init__.py +0 -0
  204. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/scip/adapters/_empty_environment.json +0 -0
  205. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/scip/adapters/_java_compat.init.gradle +0 -0
  206. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/scip/pb2.py +0 -0
  207. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/stdlib/c.json +0 -0
  208. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/stdlib/dart.json +0 -0
  209. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/stdlib/java.json +0 -0
  210. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/stdlib/node.json +0 -0
  211. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/stdlib/php.json +0 -0
  212. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/src/descry/web/__init__.py +0 -0
  213. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/__init__.py +0 -0
  214. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/eval/README.md +0 -0
  215. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/eval/__init__.py +0 -0
  216. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/eval/compare.py +0 -0
  217. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/eval/corpus.py +0 -0
  218. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/eval/metrics.py +0 -0
  219. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/eval/registry.py +0 -0
  220. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/eval/results/results-descry.json +0 -0
  221. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/eval/results/results-ripgrep.json +0 -0
  222. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/fixtures/small_graph.json +0 -0
  223. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_dart_parser.py +0 -0
  224. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_java_parser.py +0 -0
  225. {descry_codegraph-0.3.4 → descry_codegraph-1.0.1}/tests/test_php_parser.py +0 -0
@@ -24,10 +24,16 @@ jobs:
24
24
  - run: ruff format --check src/ tests/ tools/
25
25
 
26
26
  test:
27
- runs-on: ubuntu-latest
27
+ runs-on: ${{ matrix.os }}
28
28
  strategy:
29
29
  matrix:
30
+ os: [ubuntu-latest]
30
31
  python-version: ["3.11", "3.12", "3.13"]
32
+ # The unit suite and the interface tests on macOS too; Windows is
33
+ # best-effort, kept from regressing on a local VM.
34
+ include:
35
+ - os: macos-latest
36
+ python-version: "3.13"
31
37
  steps:
32
38
  - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
33
39
  - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
@@ -1,6 +1,6 @@
1
- # CLAUDE.md
1
+ # AGENTS.md
2
2
 
3
- This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
3
+ This file provides guidance to coding agents when working with code in this repository.
4
4
 
5
5
  ## Commands
6
6
 
@@ -18,12 +18,12 @@ just clean # remove .descry_cache, dist, caches, __pycache__
18
18
  Run a single test or filter:
19
19
 
20
20
  ```bash
21
- just test tests/test_handlers.py # one file
22
- just test tests/test_handlers.py::test_index # one test
23
- just test -k "cross_lang and not slow" # by expression
21
+ just test tests/test_handlers.py # one file
22
+ just test tests/test_config.py::TestFromToml::test_from_toml_basic # one test
23
+ just test -k "cross_lang and not slow" # by expression
24
24
  ```
25
25
 
26
- Python 3.11+ required (enforced by `pyproject.toml`). Pre-commit gate: `just lint && just fmt && just test` all pass (2822 tests currently — a drop is a regression signal).
26
+ Python 3.11+ required (enforced by `pyproject.toml`). Pre-commit gate: `just lint && just fmt && just test` all pass (3343 tests pass; a handful more are skipped where the environment lacks their fixture — a drop is a regression signal).
27
27
 
28
28
  Invoke the tool while developing:
29
29
 
@@ -43,14 +43,14 @@ Packaging: `pyproject.toml` defines four console scripts — `descry`, `descry-m
43
43
 
44
44
  **Two graph phases:**
45
45
 
46
- 1. **Generate** (`generate.py`, invoked via `descry index` or `descry-generate`) — walks the project, parses source files with regex + AST, resolves calls (`CallResolver`) from imports, declared and returned types, scope and the class hierarchy, optionally runs SCIP indexers (rust-analyzer, scip-typescript) for type-aware call resolution, optionally builds embeddings. Writes `.descry_cache/codebase_graph.json`. A call is resolved, left unresolved with the definitions that fit recorded as `candidates`, or dropped as external. Never resolve by name alone when more than one definition fits, never by file path, and never guess the type of a receiver: an unknown receiver stays unresolved.
46
+ 1. **Generate** (`generate.py`, invoked via `descry index` or `descry-generate`) — walks the project, parses source files with regex + AST (`_parsing.py` holds what every parser shares; each language has its `<lang>_parser.py`), resolves calls (`CallResolver` in `resolver.py`) from imports, declared and returned types, scope and the class hierarchy, optionally runs SCIP indexers (rust-analyzer, scip-typescript) for type-aware call resolution, optionally builds embeddings. Writes `.descry_cache/codebase_graph.json`. A call is resolved, left unresolved with the definitions that fit recorded as `candidates`, or dropped as external. Never resolve by name alone when more than one definition fits, never by file path, and never guess the type of a receiver: an unknown receiver stays unresolved.
47
47
  2. **Query** (`query.py` → `GraphQuerier`) — loads the cached graph and answers callers/callees/flow/path/context queries. All service methods lazy-load the querier; freshness is tracked by graph file mtime.
48
48
 
49
49
  **Graph schema is versioned.** `src/descry/_graph.py` exports `CURRENT_SCHEMA` (currently `2`) and `load_graph_with_schema()`. Every graph-consuming code path must load via this helper — it raises `GraphSchemaError` on mismatch so stale graphs are rejected rather than silently producing wrong results. If you change the graph shape in a breaking way, bump `CURRENT_SCHEMA`.
50
50
 
51
- **Standard-library knowledge is generated.** `src/descry/stdlib/<lang>.json` (format in `src/descry/_stdlib.py`, loaded lazily per language) is written by `tools/stdlib/gen_<lang>.py` from the language's own machine-readable description and never edited by hand. `class StandardLibrary` in `generate.py` is the one lookup every language plugs into, by supplying how it writes a type and how a name in source maps to the data. Do not add lists of library types, functions or members to a parser or the resolver — extend the generator. `tests/test_stdlib.py` regenerates each file when its source is present (`$DESCRY_STDLIB_SOURCES`, `$JAVA_HOME`).
51
+ **Standard-library knowledge is generated.** `src/descry/stdlib/<lang>.json` (format in `src/descry/_stdlib.py`, loaded lazily per language) is written by `tools/stdlib/gen_<lang>.py` from the language's own machine-readable description and never edited by hand. `class StandardLibrary` in `resolver.py` is the one lookup every language plugs into, by supplying how it writes a type and how a name in source maps to the data. Do not add lists of library types, functions or members to a parser or the resolver — extend the generator. `tests/test_stdlib.py` regenerates each file when its source is present (`$DESCRY_STDLIB_SOURCES`, `$JAVA_HOME`).
52
52
 
53
- **Owners are named as source names them.** A parser files members under the type that source names. A block for no type source can name (an anonymous class, a Rust `impl` for a tuple or a type parameter, an unnamed extension) gets an owner whose name no source can write (`class@12`, `object@12`, `<Trait for (A, B)>`, `extension on String`), never the name of a trait, a base or the enclosing type, so no lookup of a type lands on it. An accessor is filed as source writes it (`get size`), a name no method can have. `TestOwnersSourceCannotName` in `tests/test_generate.py` holds a fixture per language; a new parser adds one.
53
+ **Owners are named as source names them.** A parser files members under the type that source names. A block for no type source can name (an anonymous class, a Rust `impl` for a tuple or a type parameter, an unnamed extension) gets an owner whose name no source can write (`class@12`, `object@12`, `<Trait for (A, B)>`, `extension on String`), never the name of a trait, a base or the enclosing type, so no lookup of a type lands on it. An accessor is filed as source writes it (`get size`), a name no method can have. `TestOwnersSourceCannotName` in `tests/test_generate.py` holds a fixture for every parser that files members under an owner source cannot name (Rust, TS/JS, Java, PHP, Dart, Ruby, C/C++); a new such parser adds one.
54
54
 
55
55
  **Resolution changes need numbers.** Measure a resolver or parser change on public repositories before and after (`DESCRY_NO_SCIP=1 DESCRY_NO_EMBEDDINGS=1`, cache outside the repository), compare the graphs edge by edge, and read a random sample of the moved edges against the source. A wrong edge is worse than an unresolved one; a rule must be the language's, never tuned to one repository.
56
56
 
@@ -67,11 +67,12 @@ These are load-bearing — see the `### Security` sections of `CHANGELOG.md`. Do
67
67
  - **The indexer child is isolated from the repository it indexes.** It is spawned with `python -P`, so a `descry/` package inside the repository cannot shadow the installed one.
68
68
  - **Git runs with the repository's config neutralised.** `_run_git` in `git_history.py` disables hooks, fsmonitor, signature display, external diff, textconv and filter drivers, never lazily fetches (`GIT_NO_LAZY_FETCH`), forces the plain uncoloured `a/` `b/` diff format, and frames log output with NUL bytes. Arguments from callers go through the `_validate_git_*` helpers. New git calls go through `_run_git`.
69
69
  - **Source is only read from inside the project root.** Graph node paths are untrusted (a graph file can be hand-edited or shipped by a repository); every read goes through `source_path()` in `query.py`, which refuses anything that resolves outside the root or is not a regular file.
70
- - **The default cache directory stays inside the project.** A repository can ship `.descry_cache`, or its `scip` subdirectory, as a symlink to another directory; `DescryConfig.cache_dir_error()` refuses indexing and embedding there, and only `DESCRY_CACHE_DIR` names a cache outside the project.
70
+ - **The default cache directory stays inside the project.** A repository can ship `.descry_cache`, or its `scip` or `parse` subdirectory, as a symlink to another directory; `DescryConfig.cache_dir_error()` refuses indexing and embedding there, and only `DESCRY_CACHE_DIR` names a cache outside the project.
71
+ - **A parse is reused only from an entry descry wrote.** Each file's parse is kept in `<cache>/parse` as JSON, never pickle, with an HMAC of the entry's name and content under a key in the user's state directory (`$XDG_STATE_HOME/descry/parse.key` when that is absolute, else `~/.local/state`; `%LOCALAPPDATA%` on Windows); where the key would be inside the project, no entry is read or kept. An entry a repository ships, or one moved to another file's name, fails the check and the file is parsed again; restoring an entry cannot stop an index.
71
72
  - **TOML-sourced subprocess args are validated.** `_validate_toolchain`, `_validate_scip_extra_arg`, `_validate_embedding_model` in `handlers.py` reject short flags, shell metacharacters, and out-of-root local paths. New TOML → subprocess plumbing must validate.
72
- - **Web UI is local-only by design.** `descry-web` binds `127.0.0.1`, has no auth, and deliberately omits `CORSMiddleware` so browsers enforce same-origin — a tab on `evil.com` cannot read `/api/source`. State-changing requests are refused unless same-origin (`Origin` / `Sec-Fetch-Site`), so it cannot trigger `/api/index` either. The host middleware rejects non-loopback `Host` headers to defeat DNS-rebinding that would otherwise bypass the 127.0.0.1 bind. `/api/source` enforces project-root containment, rejects non-regular files / non-text content / >10 MiB, and opens every path component with `O_NOFOLLOW`. `/api/index` (and `/api/index/stream`) take no path parameter (always indexes the configured root). `DescryService` runs one index at a time for every interface and stops the indexer's whole process tree when a run ends early. The page's remote scripts carry SRI hashes and every response carries the Content-Security-Policy that `web/server.py` builds from the page's own tags, allowing exactly those asset URLs; a new remote script needs an SRI hash. Don't add a `--host 0.0.0.0` flag, don't add `CORSMiddleware`, and don't expose network listeners.
73
+ - **Web UI is local-only by design.** `descry-web` binds `127.0.0.1`, has no auth, and deliberately omits `CORSMiddleware` so browsers enforce same-origin — a tab on `evil.com` cannot read `/api/source`. State-changing requests are refused unless same-origin (`Origin` / `Sec-Fetch-Site`), so it cannot trigger `/api/index` either. The host middleware rejects non-loopback `Host` headers to defeat DNS-rebinding that would otherwise bypass the 127.0.0.1 bind. `/api/source` enforces project-root containment, rejects non-regular files, files over `[code_files] max_file_mb` (10 by default; 0, which a repository's `.descry.toml` can set, lifts the cap) and files with a NUL byte in their first 8 KiB, and opens every path component with `O_NOFOLLOW` (on Windows, which has no `openat`, it checks after opening that the file opened is the one the path resolves to, inside the root). `/api/index` (and `/api/index/stream`) take no path parameter (always indexes the configured root). `DescryService` runs one index at a time for every interface and stops the indexer's whole process tree when a run ends early. The page's remote scripts carry SRI hashes and every response carries the Content-Security-Policy that `web/server.py` builds from the page's own tags, allowing exactly those asset URLs; a new remote script needs an SRI hash. Don't add a `--host 0.0.0.0` flag, don't add `CORSMiddleware`, and don't expose network listeners.
73
74
  - **MCP `index(path=...)`** is restricted to the configured project root; a path below it narrows the walk but still writes the root's graph.
74
- - **Embedding cache** uses numpy safe-mode load + JSON sidecar + atomic writes + content-addressed keys. `MODEL_REGISTRY` in `embeddings.py` is the single source of truth for which models descry ships pinned configurations for — each entry carries its revision and its task prompts. **`trust_remote_code` is always `False`**: there is no registry field, loader parameter or config key that enables it, so descry never executes code from a model repository — do not add one. A model named in `.descry.toml` that is not registered is loaded unpinned. Adding a model means adding a registry entry, not editing the loader.
75
+ - **Embedding cache** uses numpy safe-mode load + JSON sidecar + atomic writes, keyed by the graph's bytes and time and the recipe. A rebuild reuses a node's vector, by the digest of its text, only from a cache descry signed with the key in the user's state directory (`signing_key()` in `_parse_cache.py`), so a shipped cache is never reused. `MODEL_REGISTRY` in `embeddings.py` is the single source of truth for which models descry ships pinned configurations for — each entry carries its revision and its task prompts. **`trust_remote_code` is always `False`**: there is no registry field, loader parameter or config key that enables it, so descry never executes code from a model repository — do not add one. A model named in `.descry.toml` that is not registered is loaded unpinned. Adding a model means adding a registry entry, not editing the loader.
75
76
  - **The cache key is the embedding recipe's identity.** `_recipe_fingerprint()` folds in the resolved repo id, the pinned revision, `RECIPE_VERSION`, `DOCSTRING_CHAR_LIMIT`, the prompt names, the entry's loading options, and whether source code is embedded (`CODE_CHAR_LIMIT`). Anything that changes the vectors without changing the graph must be added there and `RECIPE_VERSION` bumped, or a stale cache is served against freshly-encoded queries — comparing two different embedding spaces.
76
77
  - **`node_text()` and `code_excerpt()` are shared with the eval harness.** `tests/eval/corpus.doc_text` delegates to them so the harness's leave-one-out substitute cannot drift from the index rows it replaces. Change the text assembly there, not in a copy, and bump `RECIPE_VERSION`.
77
78
  - **The default model has a fallback.** With no model configured, `SemanticSearcher` uses `DEFAULT_MODEL_ALIAS` and, when HuggingFace refuses it as gated, builds with `FALLBACK_MODEL_ALIAS` and warns. Searches use whichever model built the index; only a rebuild retries the default. A model named explicitly never falls back.
@@ -79,4 +80,4 @@ These are load-bearing — see the `### Security` sections of `CHANGELOG.md`. Do
79
80
 
80
81
  ## Versioning
81
82
 
82
- Pre-1.0. The only stable public API is `descry.__version__`. Submodules (`descry.handlers`, `descry.query`, etc.) are **not** stable — refactor freely. Minor bumps (`0.1.x` → `0.2.x`) may break the library API, graph schema, CLI, or MCP tool signatures; patch bumps won't.
83
+ From 1.0.0 semver holds. The only stable public API is `descry.__version__`. Submodules (`descry.handlers`, `descry.query`, etc.) are **not** stable — refactor freely. A breaking change to the library API, graph schema, CLI, or MCP tool signatures comes with a major bump; minor and patch releases don't.
@@ -2,9 +2,499 @@
2
2
 
3
3
  All notable changes to Descry will be documented in this file.
4
4
 
5
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to pre-1.0 semver (minor-version bumps may include breaking changes; see README versioning stance).
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [semver](https://semver.org/) from 1.0.0.
6
6
 
7
- ## [Unreleased]
7
+ ## [1.0.1] — 2026-10-30
8
+
9
+ ### Fixed
10
+
11
+ - On macOS, stopping `descry index` (Ctrl-C, `SIGINT`) stops the run as
12
+ `SIGTERM` and `SIGHUP` do; it reported "Index error: Operation not
13
+ permitted" and exited 2.
14
+
15
+ ### Changed
16
+
17
+ - `CLAUDE.md` is `AGENTS.md`.
18
+
19
+ ## [1.0.0] — 2026-10-29
20
+
21
+ ### Breaking
22
+
23
+ - Every symbol-taking tool asks for `symbol` (a node ID or a name), where
24
+ some asked for `name` or `node_id`: MCP `descry_callers`, `descry_callees`,
25
+ `descry_quick`, `descry_evolution`, `descry_context`, `descry_flatten`; the
26
+ web's `?name=` / `?node_id=` / `?class_node_id=`; the CLI's positional
27
+ argument names. `docs/UPGRADING.md` lists the interface changes in full.
28
+ - Every failure is `{error, reason}` (and `choices` for a shared name) in
29
+ every interface, with `reason` one of `invalid`, `ambiguous`, `not_found`,
30
+ `busy`, `no_graph`, `unavailable`, `loading`, `failed`. Arguments an
31
+ interface cannot read as their type (the CLI's too, with `--json`),
32
+ unknown search languages and types (lower case, aliases such as `ts`
33
+ taken everywhere), an HTTP method no OpenAPI operation can be under, a
34
+ date git cannot read, and an empty symbol, search, query, file or method
35
+ name are `invalid` in every interface where some silently answered. The
36
+ web's own refusals (host, origin, `/api/source`) carry `reason` too.
37
+ - A name several definitions share is refused with every node ID to choose
38
+ from, by every tool but `search` and `impls`; a name no definition has is
39
+ `not_found` naming close matches. `callers` and `callees` no longer answer
40
+ for one close match, and their `fuzzy` field is removed.
41
+ - Structured answers carry IDs, counts and kinds — and an import line, a
42
+ file path, or an OpenAPI tag, path or operation ID where the answer names
43
+ one; other repository text stays in the MCP fence. MCP tools return structured content beside the markdown,
44
+ the web API the same object, and the CLI prints it with `--json`.
45
+ - `search --type` is lower case in every interface; the CLI no longer
46
+ lowercases it.
47
+ - A C# overload's node ID is `Type::Name#2`, `#3` and on, where it was
48
+ `Type::overload2_Name`, a name C# source could write.
49
+ - `DESCRY_SCIP_WORKERS` is removed: SCIP indexers run one at a time, and
50
+ the variable set nothing.
51
+
52
+ ### Security
53
+
54
+ - `status` and `health` count an embeddings cache only where descry
55
+ signed it, as the searcher does.
56
+ - A model that fails to load, when the index is built or at the first
57
+ search, is reported by the kind of its error; its message, which may
58
+ name what `.descry.toml` configured, goes to the log rather than into an
59
+ answer.
60
+ - The incremental parse cache is signed: entries carry an HMAC over their
61
+ content, and an entry descry did not sign is ignored, never run. The key
62
+ is made in the user's state directory, `descry/parse.key`
63
+ (`XDG_STATE_HOME`, or `~/.local/state` where that is unset), and never
64
+ leaves it.
65
+ - A submodule's own config runs no program: its diff stays inline and a
66
+ working-tree diff starts no git inside it.
67
+ - `.descry.toml` values are type-checked before use: a quoted boolean, a
68
+ fractional depth, a string where a list belongs, a list entry that is not
69
+ a string or a number too large to use is ignored with a warning, where it
70
+ once crashed or silently took effect. A model path written as prose is
71
+ refused.
72
+ - The web's own refusals (host, origin, `/api/source`) answer the
73
+ contract's failure shape.
74
+
75
+ ### Added
76
+
77
+ - Incremental indexing: unchanged files are not re-parsed, and their
78
+ resolutions are kept with the keys of the tables they read, a node by
79
+ the fields read of it, so an edit that moves lines re-resolves only the
80
+ files that read where something is, and an MSBuild `Exists()` or
81
+ `GetPathOfFileAbove` condition is asked again; a cache entry of another descry
82
+ version, or one descry did not sign, is re-parsed. A rebuild whose
83
+ embeddings are all kept loads no model.
84
+ - `descry embedding-models --json`; with `--json`, an argument the CLI
85
+ cannot read answers `{error, reason}`.
86
+ - C#: a project's `<ImplicitUsings>` and `<Using>` items put their
87
+ namespaces in scope, read from its `.csproj` and the nearest
88
+ `Directory.Build.props` and `Directory.Build.targets` at or above it as
89
+ MSBuild evaluates them: every property first, the files they `<Import>`
90
+ (an `<ImportGroup>`'s too) in place, then the items in import order
91
+ (the props file's, the SDK's usings, the project's, the targets file's);
92
+ `;`-separated lists, nested `<Choose>`, item metadata as attributes or
93
+ elements, `Static` and `Alias` items as `using static` and aliases,
94
+ conditions of `==`, `!=`, `<`, `<=`, `>`, `>=`, `Exists()` (compared
95
+ on either side), string methods, `[MSBuild]::Version…` comparisons and
96
+ `GetPathOfFileAbove` and `GetDirectoryNameOfFileAbove` (arguments
97
+ quoted or a bare `$(Name)`), `$(Name)` with the reserved properties
98
+ (`MSBuildProjectDirectory`, `MSBuildThisFile…` and the like) and the
99
+ SDK-default ones (`Configuration`, `TargetFrameworkIdentifier`,
100
+ `RootNamespace`, `AssemblyName`); a project of several target
101
+ frameworks has what any of its builds has; what a `<Target>` sets is
102
+ left out, as it is set only when the target runs. A condition of a
103
+ function it does not read holds for no `Include` and every `Remove`,
104
+ and an `<Import>` of such a path is not followed; a file that is no XML,
105
+ or declares a DTD, is not read. The SDK is the `<Project Sdk>` or
106
+ `<Sdk Name>` one, and its list is generated from the SDK that bundles
107
+ the pinned runtime.
108
+
109
+ ### Changed
110
+
111
+ - Resolution: a local declaration shadows an import only over its block,
112
+ by line and column, whether a `const`, `let`, `function` or `class`, a
113
+ sibling block's its own (TS/JS); a method of the class or of a base
114
+ shadows a static import, and a nested class's inherited method comes
115
+ before its enclosing class's (Java); a Python import after a definition
116
+ rebinds it, a star import binding only what the module's `__all__`
117
+ lists (assigned, annotated, `+=`, `append`, `extend`; any name where it
118
+ is not written out, or is written in a function, deleted, or written
119
+ through a subscript or by name), and an awaitable is its own type until `await`,
120
+ `async for` or `async with` takes what it hands on (`awaited`, read from
121
+ typeshed's `__await__`), a project `async def`'s call a coroutine; the
122
+ `typing` aliases (`List`) are read from CPython's `typing.py`; a C# type
123
+ name is looked up namespace by namespace, a namespace's types before the
124
+ `using`s and aliases of the declaration of it around the code (another
125
+ declaration of the namespace has its own), a nested type in the class
126
+ and the types it derives from, a `global using` in its project's files,
127
+ and one no namespace or `using` reaches is not the project's, an alias
128
+ of the compilation unit names a path from the global namespace, one in
129
+ a namespace is read from there, and a dotted path reaches a type
130
+ through the namespaces around the code; a Java member type, own or
131
+ inherited (a base's `private` one is not), comes before a single-type
132
+ import of its name, a qualified call's too; Ruby's `::Name` is the
133
+ top-level constant, a constant is looked up by `Module.nesting`, then
134
+ the ancestors, prepended modules first, then `Object`, which a
135
+ `BasicObject` subclass does not have, and a `class A::B` body looks
136
+ names up in `A::B` and where it is written, not in `A`; C#
137
+ overload resolution follows the most derived type that declares an
138
+ applicable method (by the language's conversions and the library's
139
+ declared implicit conversions), a protobuf type is found as protoc finds it, Rust
140
+ match and `matches!` patterns are never calls while guards and
141
+ `select!` futures stay calls, and a call a receiver cannot reach stays
142
+ unresolved with its candidates rather than being dropped. A JavaScript
143
+ call of a name a local of a block or function around binds is no
144
+ import's, and a local binds no call past its block; a plain function
145
+ declared in a block of sloppy code is its function's variable too
146
+ (Annex B: not an `async` or generator one, not in a module, by its
147
+ syntax or its package's `"type": "module"`, a class body or under a
148
+ `"use strict"` prologue, nor where a parameter or a `let` of the name
149
+ around would clash); a named class expression's name is bound in its
150
+ body; a call of a class without `new`, or of a name before its `let`,
151
+ `const` or `class` runs, reaches nothing. A JavaScript file importing a
152
+ package by its name gets what Node's `exports` give it (its subpath's
153
+ own key, else the longest pattern; the `node`, `module-sync`, `import`
154
+ or `require` and `default` conditions; a `null` target, or one not
155
+ found as written, gives nothing), a TypeScript file `types` and its
156
+ tsconfig's `customConditions` too, as `require` from a CommonJS-format
157
+ file under node16, node18, node20 and nodenext (a dynamic `import()` as
158
+ `import`), without `node` under bundler resolution and without
159
+ `exports` under node10, the default resolution by the TypeScript
160
+ version where the tsconfig sets neither, and unknown where it extends
161
+ a config descry does not read. A C or C++ call of the one macro of its
162
+ name in reach, defined at the call (by the last `#define` or `#undef`
163
+ of the name above it, an included file read where it is included,
164
+ once where an include guard around every directive or a `#pragma once`
165
+ outside any conditional keeps it, a directive or code in an arm no
166
+ build compiles none: `#if 0`, `#elif 0`, `#if 0 && …`, `#if 1-1`, an
167
+ arm after one that always holds; a condition's integer arithmetic and
168
+ comparisons are evaluated as the preprocessor does, each operator at C's
169
+ precedence and octal, hex and binary literals read as C reads them, and one with an operator descry does
170
+ not read is left to the macros), is that macro, before any name is looked up, where every
171
+ build of the call defines it or every other definition of the name is
172
+ built only where it does; else the call keeps both as candidates. An
173
+ `#if A || B` arm is one condition, its `#else` the other. A function
174
+ of a macro's name has its own body; an out-of-line member is one
175
+ of a class of the namespace it is written in. C++ `->` reaches what a
176
+ type's `operator->` points at: a library template's first argument only
177
+ where the data's `pointers` say so, so a `vector`'s or `weak_ptr`'s no
178
+ longer does, and a project template's member with its arguments. A Rust
179
+ bare name is looked up block by block, then in its module: an item,
180
+ then a `use`, then what the scope's globs bring that the caller can
181
+ see; a path's first name is first an item a function around declares,
182
+ and may be a module the function or its module declares, a file one
183
+ (`mod m;`, `#[path]`) too; a module a function declares sees no other
184
+ item of that function.
185
+ An impl block holds a type's members where its `use` of the name leads
186
+ to the type, or the crate has one type of the name; another type of
187
+ the name lends it none. A `use` path follows every module's `use`s and
188
+ globs, `extern crate a as b` at a crate root, and of the files
189
+ `#[cfg]`s declare one module as, the writing file's own; where a
190
+ `#[cfg]` alternative or another crate's glob may bind the name
191
+ elsewhere, or the module tree leads to the module but not the item,
192
+ the name stays unresolved, never chosen by its file's path.
193
+ - `cross_lang` reads every OpenAPI operation method (`head`, `options`
194
+ and `trace` too), under its lower-case field name only. `evolution --crate` is the first directory of a
195
+ definition's path, as `search --crate` is, and a crate no definition is
196
+ in finds none.
197
+ - The C++ standard-library data reads a class's or a method's template
198
+ parameter as the parameter, not as an alias of its name elsewhere
199
+ (`basic_string::front` returns `_Traits::char_type`), and its generator
200
+ reads Clang's AST one declaration at a time without the parts it never
201
+ reads (peak memory about 1.5 GB, from over 20).
202
+ - C#'s implicit usings hold where the SDK's conditions do: a WPF project
203
+ has no `System.IO`, a Windows Forms one has `System.Windows.Forms`.
204
+ - `index(path)` reads the path from the project root; `status` tells the
205
+ SCIP state (`enabled`/`disabled`/`unavailable`/`not_loaded`) and
206
+ embeddings switched off as `disabled`; `changes` counts and diffs the
207
+ commits of its range from their merge base. `status` and `health` list
208
+ the languages a `lang` filter names; a `[syntax.lang_map]` name of none
209
+ only tags fences.
210
+ - What the library has comes from the generated standard-library data:
211
+ `_library.py`, the lists of library names the parsers skipped, and the
212
+ resolver's lists are gone. Read from the data instead: Ruby's
213
+ never-returning methods (`-> bot`) and its type makers (`Class.new`,
214
+ `Struct.new`, `Data.define`, from RBS; a maker whose name a project
215
+ constant shadows, own or a base's, makes nothing: the constant holds
216
+ what that constant's `new` gives, and a class that derives from
217
+ `BasicObject` has no Kernel methods), Dart's lower-case core types, Go's
218
+ GOOS and GOARCH values (`platforms`, from `internal/syslist`, a file
219
+ name constraining its build as go/build reads it),
220
+ C++'s pointer-like templates (`pointers`: those whose `->` the compiler,
221
+ asked, finds reaching their first type argument), and the JavaScript
222
+ functions that write members onto `exports` (`writers`: `Object.assign`
223
+ and the like, by their signatures). A base is dropped as the library's where the
224
+ data has it as written (a `typing` special form, `IOError`,
225
+ `fmt::Display` through a `use` in an inner module, a C# type of an
226
+ enclosing namespace, from `global::` or generic, a C++ typedef of
227
+ `std`, a class of a Node module). A base the language's lookup leaves
228
+ unknown is never taken as a project type of its name that the lookup
229
+ does not reach (a Java class of another package not imported, a C++
230
+ type of a file not compiled with the subtype's); one from another
231
+ package stays a reference. The data gains `qualifiers`,
232
+ `evaluators` (read from RBS `[self: self]`), `attributes` and
233
+ `context_managers` (Python's data descriptors and context-manager
234
+ decorators, read from typeshed), `implicit`, `implicit_usings` and
235
+ `platforms`; a
236
+ Rust method that hands on what a standard type wraps is read from the
237
+ type's own return types; the .NET data is read from the 10.0.14 runtime.
238
+ - Ruby's `puts`, `require`, `raise` and the other Kernel and Module
239
+ methods, Dart's `print` and Go's built-ins are calls like any other: the
240
+ project's own method or function of the name where scope reaches one,
241
+ the library's otherwise.
242
+ - A Rust `use` path starts at a crate unless the scope it is written in,
243
+ or a module a glob `use` brings, has a module or item of its first name
244
+ (`use util::read_all` with a `mod util`, `use Kind::Alpha` with an
245
+ `enum Kind`): a module named `std` (or `glob`) elsewhere in the project
246
+ no longer hides the crate. A glob `use` brings what the `use`s of the
247
+ modules it reaches bind, renamed ones and their globs too, and a `use`
248
+ in a body on a function's own line is the function's. A Rust base
249
+ is looked up by the path it is written with. A Rust bare name
250
+ reaches a variant or associated function only under a glob import of
251
+ its type; a call on a standard type that holds a project
252
+ type (`Option<T>`, `Arc<T>`) is answered by that type's data.
253
+ - `0` lifts `[timeouts] query_ms` and `[query] max_nodes`.
254
+
255
+ ### Fixed
256
+
257
+ - A PHP `new class` reaches its anonymous class where the parser moved
258
+ lines; it named a class that did not exist.
259
+ - TypeScript parameter types of function types (`f: () => void`) and of
260
+ parameters with defaults are read; the list was split at `=>`. A
261
+ `for await (const x of xs)` head binds nothing, and an interceptor whose
262
+ callback closes on its line ends there.
263
+ - A Python class's decorators are calls, as a function's are.
264
+ - A Rust type alias whose parameter's bound returns a type
265
+ (`type A<F: Fn() -> u8> = B<F>;`) is read.
266
+ - Git failures other than "not a repository" (git missing, a timeout) are
267
+ reported as what they are.
268
+ - SCIP honours the configured `excluded_dirs` when it finds projects and
269
+ hashes their sources, and sees edits to a Rust project under a directory
270
+ named `target`.
271
+ - The Ruby standard library data keeps the type arguments of a type
272
+ written from the root (`::Array[Integer]`); the Dart generator reads a
273
+ libraries directory given itself.
274
+ - The web UI colours the flow tree's type badges.
275
+ - `context` finds the tests of a name with an acronym (`HTTPServer` →
276
+ `test_http_server`).
277
+ - The MCP server no longer builds embeddings for a graph indexed without
278
+ them, and pre-warms a graph's own ready embeddings.
279
+ - A deeply nested graph or embeddings sidecar, or a sidecar that is not
280
+ text, is reported unusable instead of crashing.
281
+ - A `.descry_cache` shipped as a file, or a graph shipped as a directory,
282
+ is refused with an error.
283
+ - Parser misses: one-line Java anonymous classes hold their methods, Go
284
+ statements on a `case` line, protobuf package-qualified names, the
285
+ members and lines of an unnamed C++ struct, and Rust enum variants named
286
+ as the prelude's (`None`, `Ok`) or written below a variant's opening
287
+ bracket.
288
+ - The Ruby data has the module functions RBS declares with `self?.`
289
+ (`Kernel#puts`) and the singleton aliases; the C++ data gives a method
290
+ the return of its overloads that return a value, written as the public
291
+ type the library's own typedefs name (`ostringstream::str` is
292
+ `basic_string`, where it was `void`).
293
+ - `this` inside a nested non-arrow function is the function's own; a
294
+ relative local embedding model has one cache key, and is loaded, from
295
+ the project root whatever the cwd; `context.tests` entries are node
296
+ IDs of test code as `[test_detection]` marks it: of the test files named
297
+ after the symbol's file (without the `[test_detection]` suffix or the
298
+ `test_` prefix that makes them tests), the `test_<name>` functions, and
299
+ the symbol's file's own tests that name it. `examples` and the usage examples of
300
+ `context` tell tests as `[test_detection]` does.
301
+ - `descry-web` starts when `DESCRY_LOG_LEVEL` names no level
302
+ (`basic_format`), at WARNING, as the CLI does.
303
+ - A Rust guard whose `if` ends its line or meets `(` keeps its calls, in a
304
+ `match` or a `matches!`; a
305
+ function a type has from a trait it derives (`H::default()`) gives that
306
+ type; a variant a glob `use` brings (`Ok` under `use Outcome::*`) is
307
+ that variant, before the prelude's. A Ruby call of a Kernel name in a
308
+ class's method, outside a block, is Kernel's where neither the class's
309
+ ancestry nor the project's own `Object`, `Kernel` or `BasicObject` has
310
+ it.
311
+ - `churn` counts a commit for the symbols its lines were in at that
312
+ commit, as `git log -L` follows a range: today's spans carried back
313
+ through the file's own history, each side of a merge in its own lines
314
+ and past one that left the file alone, across renames whatever
315
+ `log.follow` says, the path read as written, never as a pattern, lines
316
+ counted at `\n` as git counts them, a `\r` before one kept, today's file
317
+ matched to the last commit's without the `\r` a checkout writes (Windows'
318
+ `core.autocrlf`), added lines by
319
+ the commit's spans and removed ones by its parent's, a merge where it
320
+ changed a symbol against every parent. It read them against today's
321
+ lines, so a function added above shifted history onto its neighbours.
322
+ `changes` reads its range's lines against the symbols as they stood at
323
+ its ends. A file whose history cannot be read is counted in the
324
+ partial-results note.
325
+ - `evolution` lists the commits that changed a symbol's own lines, those no
326
+ definition inside it holds, followed through history as `churn` follows
327
+ them, so the two count alike; it read `git log -L`, which counted a nested
328
+ function's changes for the function around it and a merge for neither.
329
+ - `churn --mode files` counts every commit that changed a file, through
330
+ each parent of a merge, with the generated-file exclusions or without.
331
+ - `flow`'s tree nodes give the node type (`Function`), not its first
332
+ three letters. The web page's "Show callers" asks for none when
333
+ unticked, and an unresolved callee opens no context.
334
+ - With SCIP, a Python call scip-python records to a method of a package
335
+ the project defines nothing of (`pathlib.Path.resolve`) leaves the
336
+ project, unless a project class overrides that method; it is no
337
+ possible caller of a project method of its name.
338
+ - An empty `churn`, `changes` or `evolution` names what narrowed it; a
339
+ failed git step is named without its arguments run into the range, and
340
+ what git wrote is kept for the text.
341
+ - A JavaScript or TypeScript call of a constant that names a function
342
+ (`const x = helper`, `const make = Shape.create`, `const y = x`) calls
343
+ that function; it reached the constant.
344
+ - A Rust trait's path (`Ex::extra(&v)`) calls that trait's method for the
345
+ receiver's type, the trait's own body where the impl leaves it; it took
346
+ any method of the name the type had. A method call of a name two traits
347
+ give the type is the in-scope trait's, so it keeps both as candidates;
348
+ an inherent method of the name comes first. Where the type has no impl
349
+ of the trait, the path reaches the blanket impl it meets; the path of a
350
+ trait from outside (`Display::fmt(&self.inner, f)`) reaches the type's
351
+ impl, where it was dropped; a trait function without `self`
352
+ (`Build::build(1)`) keeps the impls as candidates, where it reached the
353
+ trait's declaration. A Rust argument dereferenced twice (`&**self`) is
354
+ of a type not known, as a `Deref` impl gives it; it was taken as the
355
+ type of what it dereferences.
356
+ - A Rust unit struct or unit variant written by its path (`net::Inner`,
357
+ `Kind::Unit`), passed, bound by `let` or called on (`m::Kind::A.tick()`),
358
+ is a value of its type, and so is a struct literal written after its
359
+ modules (`net::Big { a: 1 }`), passed or called on; a call written
360
+ inside another's arguments gives what it returns to the call around it.
361
+ Calls on them were unresolved or dropped. A `use` in a block names the
362
+ first name of such a path, where the path was left unknown; a glob
363
+ `use` there still leaves it unknown. A tuple struct or variant written
364
+ bare is its constructor, not a value of its type, where `let f = Tup;`
365
+ took it as one, and a name bound to such a constructor or to a function
366
+ (`let make = Kind::Held; make(1)`, `let f = net::make; f()`) calls it, as
367
+ does a variant called directly (`Kind::Held(1).tick()`); the call was
368
+ dropped and what it returned unknown. A constant by its path
369
+ (`Ready::ALL`, `Self::LIST`) is a value of the type it declares, `Self`
370
+ in it the impl's type. A call reaches no
371
+ struct but a tuple struct (`m::Same()` beside `struct Same { .. }` is
372
+ the function).
373
+ - A Rust method called on an element by index (`xs[0].go()`,
374
+ `self.items[i].go()`, `let x = &xs[i];`) is of what indexing gives: a
375
+ `Vec`'s, slice's or array's element, a map's value, a project type's
376
+ `index`; it was unresolved. A method returning `&Self::Output` returns
377
+ the impl's associated type, as `Self::Output` did. An index of an index
378
+ (`m["k"][0]`), and one bound by `let` from a project type's `index`,
379
+ read each in turn. A range index gives a slice, not an element, and the
380
+ slice's own elements by index; a range inside the index, `xs[at(0..1)]`,
381
+ does not make it one. An index of what a call returns
382
+ (`m.get(&1).unwrap()[0]`, `m.get_mut(&1)?[0]`, or `[0]` on a line of its
383
+ own after one) is of the call's type.
384
+ - A Rust tuple struct's field, `self.0`, is of the type its declaration
385
+ writes at that position; it had none. In a block for one instantiation,
386
+ `impl Named<Own>`, a type parameter is the type the block gives it.
387
+ - A Rust `let` with a pattern that ends with `;` before more code on its
388
+ line, `{ let Pair(x) = p; x.id() }`, and each later one, and a `let ..
389
+ else { .. };`, binds its names there; the pattern was taken for a call,
390
+ an edge to `Pair` nothing constructs. A `match` arm's guard,
391
+ `Some(x) if x.ok() =>`, binds no name: the arm's `x` read the guard's
392
+ as of no type, on the arm's own line as on the `match`'s. A `match`
393
+ whose arms are on its own line binds each arm's names, and a `let x = t`
394
+ of a name the line binds just before (a `for` or a closure on one line)
395
+ holds what the name does.
396
+ - What a Rust standard method returns where an argument's type decides it
397
+ (`v.get(0)`, `v.get(0usize)`, `v.get(i as usize)`, `v.get(0..1)`) is
398
+ known: the generated
399
+ data's new `by_argument` table holds, for each such method, what each
400
+ impl of the bound trait gives (`SliceIndex` for `usize` the element, for
401
+ a range a slice), and an integer literal without a suffix reads as the
402
+ integer type, a range as the language item its syntax makes (the data's
403
+ new `lang` table, read from rustdoc's `#[lang]`). `v.get(0).unwrap().id()`
404
+ was unresolved. An argument of a standard type fits a parameter of an
405
+ alias of it, `i32` a `RawFd` (the data's new `same`, the type each other
406
+ path and argument-free alias names).
407
+ - A Rust value is read by one model of Rust's expressions, wherever it is
408
+ written (a `let`, an argument, a receiver, a field, a pattern's value, a
409
+ closure's body), over lines too: a `match` or an `if` is what the arms
410
+ that do not diverge agree on (arms of different types give none), a
411
+ `loop` what its `break`s give (those naming its label from an inner
412
+ loop too), a labelled block its own and its `break`s', an `unsafe` block or a block its last expression's, behind
413
+ `&`, `*`, `?` or `as`. `let x = match ..` and a multi-line `if` were
414
+ read as of no type.
415
+ - A Rust value's type arguments pick between blocks for one
416
+ instantiation each (`impl NamedT for Named<Own>` beside `Named<Pair<T>>`),
417
+ as written on a parameter or in a turbofish literal, `Named::<Own> { .. }`,
418
+ or made by a tuple struct's call from what it is passed, `Pair(Own)`; the
419
+ call was unresolved with every block's method; a struct literal's type
420
+ arguments are those its fields' values give, `Named { t: Own }`, bound
421
+ by a `let` or not, a field's value a call too (`Named { t: Pair(Own) }`
422
+ is a `Named<Pair<Own>>`), written over lines as rustfmt writes it, with
423
+ a method on the line after its `}`; a struct update, `Named { ..base }`,
424
+ is of its base's type. A Rust block of one expression, `let u = { o };`,
425
+ is that expression's value. A
426
+ struct's fields written
427
+ on its own line, `struct Named<T> { pub t: T }`, have their types.
428
+ - A Rust closure whose block is one expression, `map(|t| { t })`, returns
429
+ it; what it returned was not known.
430
+ - A Rust block a crate writes for a type of another crate of the project
431
+ (`impl Wipe for Buf` after `use olib::buffer::Buffer as Buf`) holds that
432
+ type's methods: `self.clear()` in it and `b.wipe()` on the type were
433
+ dropped or unresolved.
434
+ - A path whose fields, indexed or not, go on below with their `.` leading
435
+ (`self` / `.items` / `.iter()`, `this` / `.items[0]` / `.size()`), as
436
+ rustfmt and prettier write long chains, keeps its receiver, and a Rust
437
+ `for` whose value is written so binds its pattern; the receiver was
438
+ lost. So does a line of `?` alone or an index alone between them, a
439
+ `for` whose value passes a closure with braces, and in TypeScript a
440
+ field with `?.` leading or after a non-null `!` (`this.deep!.leaf`), one
441
+ a line ends with too.
442
+ - A method called with its type arguments on what a call returns,
443
+ `registry().get<S>()`, is its type's member; it was unresolved with no
444
+ candidates.
445
+ - A TypeScript object type an exported alias writes on one line, `export
446
+ type Deep = { leaf: Leaf }`, has its fields, as an interface written so
447
+ has; a value's field of it was of no type.
448
+ - A value of a Rust type alias is of the type it stands for; where another
449
+ module declared a type of the alias's name, the alias was taken for that
450
+ type, and calls on its values reached that type's methods. A type and
451
+ an alias of one name in one module, each under its own `#[cfg]`, are
452
+ either, so calls on a value of the name keep both as candidates.
453
+ - Rust and TypeScript types of one name in one file (a struct a function
454
+ declares, in each of two functions) keep their own fields; each took
455
+ the other's, and none had a type for a field both declare. A Rust
456
+ `const` or `static` a function declares is seen in that function's body,
457
+ nested items too, where it was seen in the whole file.
458
+ - A Rust `impl` block is for the type the path in its header names, read
459
+ from the module the block is in and through its `use`s (`impl Trait for
460
+ crate::a::Error` beside another `Error`, `impl F` after `use
461
+ crate::a::Foo as F`), where only the last name was read: calls of its
462
+ methods reached another type's or none. A block written beside the type's module, `impl
463
+ T for m::Unit` beside `mod m`, files its methods under the type
464
+ (`m::Unit::talk`, where they were `Unit::talk`); one written in another
465
+ module keeps its own node, `Foo::extra`, as a block in another file
466
+ does.
467
+ - A Rust dependency renamed in its manifest, `tui = { path = "../core",
468
+ package = "core" }`, or taken with `workspace = true` from a renamed
469
+ `[workspace.dependencies]` entry, is that project crate; paths through
470
+ the name were read as an outside crate's and their calls dropped.
471
+ - A Rust block for a standard type a `use` names, `impl Wait for
472
+ StdChild` after `use std::process::Child as StdChild`, keeps the name
473
+ written. A value of a standard type the project implements a trait for
474
+ is of that type, not of the project's blocks for it, and a method of
475
+ the type's own of the name a trait gives too, which rustc picks by how
476
+ each takes the receiver, leaves the call unresolved with the trait's
477
+ as the candidate; the trait's was taken.
478
+ - A Rust trait's path on a type whose impl of the trait is not in the
479
+ source read (a macro writes it, and may override the trait's body) is
480
+ unresolved with the impls as candidates; it reached the trait's
481
+ declaration. A receiver of the trait's own type, as a bound gives it,
482
+ still reads the trait's function.
483
+ - A call resolved while another is (what a function returns, a call in
484
+ the arguments) leaves the other as it was; it changed whether the
485
+ other was written as a path and what it passed, so a Rust call could
486
+ keep an impl that cannot take its arguments.
487
+ - A JavaScript or TypeScript `#` specifier resolves through the `imports`
488
+ of the nearest package.json, as Node's do; it was left unresolved.
489
+ - A PHP method called on a property declared no type is one of the methods
490
+ of its name, as on an undeclared one; it was unresolved with none.
491
+ - C# files keep their resolution from one index to the next.
492
+ - An index with SCIP switched off no longer probes every indexer.
493
+ - `[test_detection] file_suffixes = []` (or `path_patterns = []`) is the
494
+ list used; it no longer falls back to a third, different list.
495
+ - `[embeddings] model = "./models/x"` is read as a local path.
496
+ - `semantic` with embeddings switched off says so, not that the
497
+ dependencies are missing.
8
498
 
9
499
  ## [0.3.4] — 2026-10-23
10
500