hypergumbo-core 2.7.0__tar.gz → 3.0.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 (406) hide show
  1. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/.gitignore +1 -0
  2. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/PKG-INFO +1 -1
  3. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/pyproject.toml +1 -1
  4. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/__init__.py +1 -1
  5. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/analyze/all_analyzers.py +11 -0
  6. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/analyze/base.py +225 -0
  7. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/cli.py +207 -29
  8. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/compact.py +51 -18
  9. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow.py +14 -2
  10. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/framework_patterns.py +36 -7
  11. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/io_boundary.py +397 -29
  12. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/io_primitives/c.yaml +4 -0
  13. hypergumbo_core-3.0.0/src/hypergumbo_core/io_primitives/cpp.yaml +38 -0
  14. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/io_primitives/elixir.yaml +4 -0
  15. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/io_primitives/erlang.yaml +4 -0
  16. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/io_primitives/go.yaml +4 -0
  17. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/io_primitives/haskell.yaml +4 -0
  18. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/io_primitives/java.yaml +26 -102
  19. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/io_primitives/javascript.yaml +35 -53
  20. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/io_primitives/kotlin.yaml +20 -70
  21. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/io_primitives/objc.yaml +4 -0
  22. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/io_primitives/python.yaml +44 -17
  23. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/io_primitives/rust.yaml +14 -41
  24. hypergumbo_core-3.0.0/src/hypergumbo_core/io_primitives/scala.yaml +137 -0
  25. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/io_primitives/swift.yaml +4 -0
  26. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/ir.py +284 -53
  27. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/build_target.py +8 -1
  28. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/subprocess_cli.py +12 -8
  29. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/vue_component.py +5 -2
  30. hypergumbo_core-3.0.0/src/hypergumbo_core/name_matcher.py +122 -0
  31. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/profile.py +34 -0
  32. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/ranking.py +175 -31
  33. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/schema.py +1 -1
  34. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/sketch.py +9 -19
  35. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/sketch_embeddings.py +34 -3
  36. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/taint.py +250 -15
  37. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/taxonomy.py +10 -0
  38. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/verify_claims.py +51 -0
  39. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_analyzer_registry.py +112 -0
  40. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_base.py +573 -1
  41. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_cli_dead_code.py +1 -1
  42. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_cli_io_boundaries.py +303 -0
  43. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_cli_run_behavior_map.py +52 -0
  44. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_cli_search.py +56 -0
  45. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_cli_verify_claims.py +198 -0
  46. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_compact.py +482 -0
  47. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_dataflow.py +131 -2
  48. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_framework_patterns.py +245 -0
  49. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_io_boundary.py +1096 -134
  50. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_ir.py +325 -22
  51. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_max_tier.py +90 -0
  52. hypergumbo_core-3.0.0/tests/test_name_matcher.py +113 -0
  53. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_profile.py +106 -0
  54. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_ranking.py +193 -0
  55. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_schema.py +28 -0
  56. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_sketch.py +287 -2
  57. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_taint.py +428 -0
  58. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_taxonomy.py +14 -0
  59. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_verify_claims.py +68 -0
  60. hypergumbo_core-2.7.0/src/hypergumbo_core/io_primitives/scala.yaml +0 -295
  61. hypergumbo_core-2.7.0/src/hypergumbo_core/taint_sinks/host_filesystem.yaml +0 -45
  62. hypergumbo_core-2.7.0/src/hypergumbo_core/taint_sinks/network_send.yaml +0 -47
  63. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/README.md +0 -0
  64. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/__main__.py +0 -0
  65. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/_embedding_data.py +0 -0
  66. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/_hf_noise.py +0 -0
  67. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/analyze/__init__.py +0 -0
  68. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/analyze/registry.py +0 -0
  69. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/build_grammars.py +0 -0
  70. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/catalog.py +0 -0
  71. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/cfg.py +0 -0
  72. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/cfg_nodes/go.yaml +0 -0
  73. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/cfg_nodes/java.yaml +0 -0
  74. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/cfg_nodes/python.yaml +0 -0
  75. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/cfg_nodes/rust.yaml +0 -0
  76. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/cfg_nodes/typescript.yaml +0 -0
  77. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/c.yaml +0 -0
  78. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/cpp.yaml +0 -0
  79. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/csharp.yaml +0 -0
  80. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/dart.yaml +0 -0
  81. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/elixir.yaml +0 -0
  82. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/erlang.yaml +0 -0
  83. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/go.yaml +0 -0
  84. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/haskell.yaml +0 -0
  85. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/java.yaml +0 -0
  86. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/javascript.yaml +0 -0
  87. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/kotlin.yaml +0 -0
  88. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/lua.yaml +0 -0
  89. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/perl.yaml +0 -0
  90. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/php.yaml +0 -0
  91. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/python.yaml +0 -0
  92. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/ruby.yaml +0 -0
  93. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/rust.yaml +0 -0
  94. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/scala.yaml +0 -0
  95. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/swift.yaml +0 -0
  96. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/dataflow_patterns/typescript.yaml +0 -0
  97. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/datamodels.py +0 -0
  98. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/discovery.py +0 -0
  99. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/entrypoints.py +0 -0
  100. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/adonisjs.yaml +0 -0
  101. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/aiohttp.yaml +0 -0
  102. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/akka-http.yaml +0 -0
  103. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/android.yaml +0 -0
  104. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/aspnet.yaml +0 -0
  105. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/bottle.yaml +0 -0
  106. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/cakephp.yaml +0 -0
  107. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/celery.yaml +0 -0
  108. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/cli-go.yaml +0 -0
  109. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/cli-js.yaml +0 -0
  110. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/cli-ruby.yaml +0 -0
  111. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/cli-rust.yaml +0 -0
  112. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/cli.yaml +0 -0
  113. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/cocoa.yaml +0 -0
  114. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/codeigniter.yaml +0 -0
  115. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/config-conventions.yaml +0 -0
  116. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/cowboy.yaml +0 -0
  117. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/django.yaml +0 -0
  118. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/electron.yaml +0 -0
  119. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/express.yaml +0 -0
  120. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/falcon.yaml +0 -0
  121. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/fastapi.yaml +0 -0
  122. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/fastify.yaml +0 -0
  123. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/feathers.yaml +0 -0
  124. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/flask-appbuilder.yaml +0 -0
  125. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/flask-restful.yaml +0 -0
  126. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/flask.yaml +0 -0
  127. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/fuelphp.yaml +0 -0
  128. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/giraffe.yaml +0 -0
  129. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/go-encoding-callbacks.yaml +0 -0
  130. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/go-web.yaml +0 -0
  131. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/grape.yaml +0 -0
  132. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/graphql-python.yaml +0 -0
  133. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/graphql-ruby.yaml +0 -0
  134. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/graphql.yaml +0 -0
  135. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/guice.yaml +0 -0
  136. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/hanami.yaml +0 -0
  137. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/hapi.yaml +0 -0
  138. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/http4k.yaml +0 -0
  139. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/http4s.yaml +0 -0
  140. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/hummingbird.yaml +0 -0
  141. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/jakarta-cdi.yaml +0 -0
  142. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/javalin.yaml +0 -0
  143. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/jax-rs.yaml +0 -0
  144. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/kafka-connect.yaml +0 -0
  145. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/koa.yaml +0 -0
  146. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/ktor.yaml +0 -0
  147. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/laminas.yaml +0 -0
  148. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/language-conventions.yaml +0 -0
  149. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/laravel.yaml +0 -0
  150. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/library-exports.yaml +0 -0
  151. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/lit.yaml +0 -0
  152. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/litestar.yaml +0 -0
  153. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/logging-conventions.yaml +0 -0
  154. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/lumen.yaml +0 -0
  155. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/main-functions.yaml +0 -0
  156. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/masonite.yaml +0 -0
  157. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/mcp-python.yaml +0 -0
  158. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/mcp.yaml +0 -0
  159. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/micronaut.yaml +0 -0
  160. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/naming-conventions.yaml +0 -0
  161. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/nestjs.yaml +0 -0
  162. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/nex.yaml +0 -0
  163. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/nextjs.yaml +0 -0
  164. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/nuxt.yaml +0 -0
  165. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/openresty.yaml +0 -0
  166. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/padrino.yaml +0 -0
  167. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/pedestal.yaml +0 -0
  168. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/phoenix.yaml +0 -0
  169. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/play.yaml +0 -0
  170. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/plug.yaml +0 -0
  171. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/plumber.yaml +0 -0
  172. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/pyramid.yaml +0 -0
  173. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/qt.yaml +0 -0
  174. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/quarkus.yaml +0 -0
  175. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/quart.yaml +0 -0
  176. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/rails.yaml +0 -0
  177. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/react.yaml +0 -0
  178. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/remix.yaml +0 -0
  179. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/restify.yaml +0 -0
  180. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/ring-compojure.yaml +0 -0
  181. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/roda.yaml +0 -0
  182. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/rust-web.yaml +0 -0
  183. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/sanic.yaml +0 -0
  184. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/scalatra.yaml +0 -0
  185. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/scotty.yaml +0 -0
  186. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/servant.yaml +0 -0
  187. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/shiny.yaml +0 -0
  188. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/sinatra.yaml +0 -0
  189. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/slim.yaml +0 -0
  190. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/solid.yaml +0 -0
  191. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/spring-boot.yaml +0 -0
  192. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/stapler.yaml +0 -0
  193. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/sveltekit.yaml +0 -0
  194. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/swiftui.yaml +0 -0
  195. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/symfony.yaml +0 -0
  196. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/tauri.yaml +0 -0
  197. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/test-frameworks.yaml +0 -0
  198. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/tornado.yaml +0 -0
  199. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/vapor.yaml +0 -0
  200. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/vertx.yaml +0 -0
  201. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/web_audio.yaml +0 -0
  202. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/yesod.yaml +0 -0
  203. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/yii.yaml +0 -0
  204. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/frameworks/zio.yaml +0 -0
  205. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/function_summaries/__init__.py +0 -0
  206. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/function_summaries/rust_stdlib.yaml +0 -0
  207. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/function_summaries/typescript_stdlib.yaml +0 -0
  208. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/gitleaks.py +0 -0
  209. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/limits.py +0 -0
  210. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/__init__.py +0 -0
  211. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/_concept_utils.py +0 -0
  212. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/airflow_framework_dispatch.py +0 -0
  213. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/annotation_convention.py +0 -0
  214. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/cgo.py +0 -0
  215. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/containment.py +0 -0
  216. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/controller_routes.py +0 -0
  217. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/crypto_flow.py +0 -0
  218. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/database_query.py +0 -0
  219. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/decorator_dispatch.py +0 -0
  220. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/dependency.py +0 -0
  221. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/di_resolution.py +0 -0
  222. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/django_orm_dispatch.py +0 -0
  223. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/event_sourcing.py +0 -0
  224. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/go_cobra.py +0 -0
  225. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/go_memberlist.py +0 -0
  226. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/graphql.py +0 -0
  227. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/graphql_resolver.py +0 -0
  228. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/grpc.py +0 -0
  229. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/http.py +0 -0
  230. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/inheritance.py +0 -0
  231. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/ipc.py +0 -0
  232. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/jackson_dispatch.py +0 -0
  233. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/jni.py +0 -0
  234. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/js_module.py +0 -0
  235. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/kafka_streams_dispatch.py +0 -0
  236. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/lua_ffi.py +0 -0
  237. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/message_dispatch.py +0 -0
  238. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/message_queue.py +0 -0
  239. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/method_call_recovery.py +0 -0
  240. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/middleware_chain.py +0 -0
  241. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/napi.py +0 -0
  242. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/openapi.py +0 -0
  243. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/orm.py +0 -0
  244. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/otp.py +0 -0
  245. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/phoenix_ipc.py +0 -0
  246. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/pyffi.py +0 -0
  247. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/react_component.py +0 -0
  248. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/registry.py +0 -0
  249. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/route_handler.py +0 -0
  250. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/router_routes.py +0 -0
  251. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/ruby_ffi.py +0 -0
  252. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/rust_trait_dispatch.py +0 -0
  253. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/solidity_abi.py +0 -0
  254. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/swift_objc.py +0 -0
  255. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/tauri_ipc.py +0 -0
  256. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/type_hierarchy.py +0 -0
  257. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/view_template.py +0 -0
  258. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/vue_template_method.py +0 -0
  259. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/wasm_bindgen.py +0 -0
  260. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/websocket.py +0 -0
  261. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/linkers/yjs_crdt.py +0 -0
  262. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/metrics.py +0 -0
  263. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/partial_install_warnings.py +0 -0
  264. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/paths.py +0 -0
  265. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/rust_analyzer_install.py +0 -0
  266. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/scip/__init__.py +0 -0
  267. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/scip/_generated/SOURCE_COMMIT.txt +0 -0
  268. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/scip/_generated/__init__.py +0 -0
  269. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/scip/_generated/scip_pb2.py +0 -0
  270. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/scip/calls.py +0 -0
  271. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/scip/descriptor.py +0 -0
  272. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/scip/edges.py +0 -0
  273. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/scip/index.py +0 -0
  274. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/selection/__init__.py +0 -0
  275. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/selection/filters.py +0 -0
  276. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/selection/language_proportional.py +0 -0
  277. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/selection/token_budget.py +0 -0
  278. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/slice.py +0 -0
  279. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/supply_chain.py +0 -0
  280. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/symbol_resolution.py +0 -0
  281. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/taint_sanitizers/encryption.yaml +0 -0
  282. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/taint_sources/crypto.yaml +0 -0
  283. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/taint_sources/key_material.yaml +0 -0
  284. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/src/hypergumbo_core/test_masking.py +0 -0
  285. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/BRANCHES_test_compact.py +0 -0
  286. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/BRANCHES_test_database_query.py +0 -0
  287. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/BRANCHES_test_framework_patterns.py +0 -0
  288. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/BRANCHES_test_graphql.py +0 -0
  289. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/BRANCHES_test_graphql_resolver.py +0 -0
  290. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/BRANCHES_test_http.py +0 -0
  291. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/BRANCHES_test_ipc.py +0 -0
  292. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/BRANCHES_test_openapi.py +0 -0
  293. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/BRANCHES_test_phoenix_ipc.py +0 -0
  294. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/BRANCHES_test_route_handler.py +0 -0
  295. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/BRANCHES_test_slice.py +0 -0
  296. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/BRANCHES_test_subprocess_cli.py +0 -0
  297. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/conftest.py +0 -0
  298. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_airflow_framework_dispatch_linker.py +0 -0
  299. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_annotation_convention_linker.py +0 -0
  300. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_backend_cli_flag.py +0 -0
  301. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_behavior_map_schema.py +0 -0
  302. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_build_grammars.py +0 -0
  303. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_build_target_linker.py +0 -0
  304. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_catalog.py +0 -0
  305. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_cfg.py +0 -0
  306. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_cgo_linker.py +0 -0
  307. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_cli_basic.py +0 -0
  308. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_cli_cache.py +0 -0
  309. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_cli_commands.py +0 -0
  310. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_cli_config.py +0 -0
  311. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_cli_explain.py +0 -0
  312. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_cli_relativize_paths.py +0 -0
  313. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_cli_routes.py +0 -0
  314. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_cli_symbols.py +0 -0
  315. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_cli_test_coverage.py +0 -0
  316. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_concept_utils.py +0 -0
  317. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_containment_linker.py +0 -0
  318. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_controller_routes_linker.py +0 -0
  319. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_crypto_flow_linker.py +0 -0
  320. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_database_query_linker.py +0 -0
  321. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_datamodels.py +0 -0
  322. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_decorator_dispatch_linker.py +0 -0
  323. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_dependency_linker.py +0 -0
  324. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_discovery.py +0 -0
  325. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_django_orm_dispatch_linker.py +0 -0
  326. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_entrypoints.py +0 -0
  327. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_event_sourcing_linker.py +0 -0
  328. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_fastapi_patterns.py +0 -0
  329. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_file_excludes.py +0 -0
  330. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_frameworks_flag.py +0 -0
  331. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_function_summaries.py +0 -0
  332. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_generate_concepts.py +0 -0
  333. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_gitleaks.py +0 -0
  334. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_go_cobra_linker.py +0 -0
  335. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_go_memberlist_linker.py +0 -0
  336. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_graphql_linker.py +0 -0
  337. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_graphql_resolver_linker.py +0 -0
  338. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_grpc_linker.py +0 -0
  339. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_handler_slices.py +0 -0
  340. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_hf_noise.py +0 -0
  341. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_http_linker.py +0 -0
  342. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_inheritance_linker.py +0 -0
  343. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_install_extras.py +0 -0
  344. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_ipc_linker.py +0 -0
  345. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_jackson_dispatch_linker.py +0 -0
  346. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_jni_linker.py +0 -0
  347. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_js_module_linker.py +0 -0
  348. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_kafka_streams_dispatch_linker.py +0 -0
  349. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_limits.py +0 -0
  350. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_linker_activation.py +0 -0
  351. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_linker_di_resolution.py +0 -0
  352. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_linker_filtering.py +0 -0
  353. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_linker_registry.py +0 -0
  354. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_locale.py +0 -0
  355. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_lua_ffi_linker.py +0 -0
  356. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_main_module.py +0 -0
  357. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_memory_guard.py +0 -0
  358. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_message_dispatch_linker.py +0 -0
  359. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_message_queue_linker.py +0 -0
  360. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_method_call_recovery_linker.py +0 -0
  361. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_metrics.py +0 -0
  362. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_middleware_chain_linker.py +0 -0
  363. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_napi_linker.py +0 -0
  364. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_no_first_party_priority.py +0 -0
  365. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_openapi_linker.py +0 -0
  366. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_orm_linker.py +0 -0
  367. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_otp_linker.py +0 -0
  368. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_partial_install_warnings.py +0 -0
  369. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_paths.py +0 -0
  370. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_phoenix_ipc_linker.py +0 -0
  371. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_pyffi_linker.py +0 -0
  372. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_react_component_linker.py +0 -0
  373. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_route_handler_linker.py +0 -0
  374. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_router_routes_linker.py +0 -0
  375. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_rubyffi_linker.py +0 -0
  376. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_run_behavior_map.py +0 -0
  377. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_rust_analyzer_install.py +0 -0
  378. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_rust_trait_dispatch_linker.py +0 -0
  379. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_schema_compliance.py +0 -0
  380. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_scip_calls.py +0 -0
  381. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_scip_descriptor.py +0 -0
  382. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_scip_edges.py +0 -0
  383. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_scip_generated.py +0 -0
  384. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_scip_index.py +0 -0
  385. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_selection_filters.py +0 -0
  386. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_selection_language_proportional.py +0 -0
  387. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_selection_token_budget.py +0 -0
  388. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_sketch_sanity.py +0 -0
  389. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_slice.py +0 -0
  390. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_slice_tier_filter.py +0 -0
  391. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_solidity_abi_linker.py +0 -0
  392. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_stable_shape_ids.py +0 -0
  393. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_subprocess_linker.py +0 -0
  394. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_supply_chain.py +0 -0
  395. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_swift_objc_linker.py +0 -0
  396. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_symbol_resolution.py +0 -0
  397. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_tauri_ipc_linker.py +0 -0
  398. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_test_masking.py +0 -0
  399. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_tree_sitter_analyzer.py +0 -0
  400. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_type_hierarchy_linker.py +0 -0
  401. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_view_template_linker.py +0 -0
  402. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_vue_component_linker.py +0 -0
  403. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_vue_template_method_linker.py +0 -0
  404. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_wasm_bindgen_linker.py +0 -0
  405. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_websocket.py +0 -0
  406. {hypergumbo_core-2.7.0 → hypergumbo_core-3.0.0}/tests/test_yjs_crdt_linker.py +0 -0
@@ -42,6 +42,7 @@ autonomous_intent.txt
42
42
  .agent/.transcript-sync-state.*.json
43
43
  .agent/.transcript-poll-state.*
44
44
  .agent/.transcript-injection-state.*.json
45
+ .agent/.transcript-injection-state.*.lock
45
46
  .agent/.last_session_transcript.jsonl
46
47
  .agent/.second_to_last_transcript.jsonl
47
48
  .agent/.last_injection_history.jsonl
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hypergumbo-core
3
- Version: 2.7.0
3
+ Version: 3.0.0
4
4
  Summary: Core infrastructure for hypergumbo repo behavior map generator
5
5
  Author: Hypergumbo contributors
6
6
  License: AGPL-3.0-or-later
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "hypergumbo-core"
7
- version = "2.7.0"
7
+ version = "3.0.0"
8
8
  description = "Core infrastructure for hypergumbo repo behavior map generator"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -23,6 +23,6 @@ format has breaking changes, while the tool version changes with any release.
23
23
  See ADR-0010 for the modular package architecture.
24
24
  """
25
25
  __all__ = ["PASS_VERSION", "__version__", "make_pass_id"]
26
- __version__ = "2.7.0"
26
+ __version__ = "3.0.0"
27
27
 
28
28
  from .ir import PASS_VERSION, make_pass_id
@@ -21,6 +21,7 @@ from ..discovery import set_global_on_file_skipped
21
21
  from ..ir import Edge, Symbol, UsageContext
22
22
  from ..limits import Limits
23
23
  from ..paths import normalize_path
24
+ from .base import synthesize_file_symbols_for_dangling_edges
24
25
  from .registry import (
25
26
  RegisteredAnalyzer,
26
27
  clear_registry,
@@ -174,6 +175,16 @@ def run_all_analyzers(
174
175
  deduped_edges.append(edge)
175
176
  all_edges = deduped_edges
176
177
 
178
+ # WI-ramuv: synthesize real file Symbols for any edge endpoint matching
179
+ # ``make_file_id`` shape that has no producer-side Symbol. Without this,
180
+ # ``ir.create_boundary_nodes`` would treat these dangling endpoints as
181
+ # external boundaries even though the file is first-party. Doing it
182
+ # here at the orchestrator chokepoint covers every analyzer in one
183
+ # place and obviates per-analyzer fixes.
184
+ all_symbols.extend(
185
+ synthesize_file_symbols_for_dangling_edges(all_symbols, all_edges)
186
+ )
187
+
177
188
  # Normalize paths: some analyzers produce absolute paths instead of
178
189
  # paths relative to repo_root. Stripping the repo_root prefix ensures
179
190
  # consistent tier classification, test-file detection, and
@@ -306,6 +306,73 @@ def make_file_id(lang: str, path: str) -> str:
306
306
  return f"{lang}:{path}:1-1:file:file"
307
307
 
308
308
 
309
+ _FILE_ID_SUFFIX = ":1-1:file:file"
310
+
311
+
312
+ def synthesize_file_symbols_for_dangling_edges(
313
+ symbols: list[Symbol],
314
+ edges: list[Edge],
315
+ ) -> list[Symbol]:
316
+ """Synthesize real file Symbols for any ``make_file_id``-shape dangling edge endpoint.
317
+
318
+ WI-ramuv chokepoint: many analyzers emit import / module-level edges
319
+ whose ``src`` (and occasionally ``dst``) is :func:`make_file_id` shape
320
+ (``{lang}:{path}:1-1:file:file``) without emitting a matching producer-
321
+ side ``kind="file"`` Symbol. ``ir.create_boundary_nodes`` then turns
322
+ every such dangling endpoint into an external boundary node, which is
323
+ structurally wrong (the file IS first-party) and forces Plan A
324
+ canonical-id collapsing as a band-aid.
325
+
326
+ This helper runs at the orchestrator (after analyzer result
327
+ aggregation, before boundary-node synthesis) and emits one real
328
+ ``kind="file"`` Symbol per distinct dangling ``make_file_id`` id, so
329
+ those edges land on real producer-side Symbols and never enter the
330
+ boundary pipeline.
331
+
332
+ Args:
333
+ symbols: All Symbols collected from analyzers (mutated only via
334
+ return value — this function is non-destructive).
335
+ edges: All Edges collected from analyzers.
336
+
337
+ Returns:
338
+ List of new Symbols (one per previously-dangling
339
+ ``make_file_id`` id). The caller appends these to the global
340
+ Symbol list.
341
+ """
342
+ existing_ids = {s.id for s in symbols}
343
+ synthesized: dict[str, Symbol] = {}
344
+
345
+ for edge in edges:
346
+ for endpoint in (edge.src, edge.dst):
347
+ if not endpoint.endswith(_FILE_ID_SUFFIX):
348
+ continue
349
+ if endpoint in existing_ids or endpoint in synthesized:
350
+ continue
351
+ # Canonical make_file_id shape is "{lang}:{path}:1-1:file:file".
352
+ # path may itself contain colons (e.g. dart "dart:io"), so we
353
+ # split off the language at the first colon and strip the
354
+ # fixed suffix. Anything that doesn't match this shape was
355
+ # filtered above.
356
+ head = endpoint[: -len(_FILE_ID_SUFFIX)]
357
+ colon = head.find(":")
358
+ if colon < 0: # pragma: no cover
359
+ continue
360
+ language = head[:colon]
361
+ path = head[colon + 1 :]
362
+ synthesized[endpoint] = Symbol(
363
+ id=endpoint,
364
+ name=path,
365
+ kind="file",
366
+ language=language,
367
+ path=path,
368
+ span=Span(start_line=1, start_col=0, end_line=1, end_col=0),
369
+ origin="orchestrator_file_symbol_synthesis",
370
+ origin_run_id="",
371
+ )
372
+
373
+ return list(synthesized.values())
374
+
375
+
309
376
  def make_unresolved_edge(
310
377
  lang: str,
311
378
  src_id: str,
@@ -1079,6 +1146,164 @@ def iter_tree_with_context(
1079
1146
  # ---------------------------------------------------------------------------
1080
1147
 
1081
1148
 
1149
+ def emit_module_attribute_refs(
1150
+ root: "tree_sitter.Node",
1151
+ source: bytes,
1152
+ imports: dict[str, str],
1153
+ caller_symbol: Symbol,
1154
+ lang: str,
1155
+ edges_out: list[Edge],
1156
+ *,
1157
+ node_kinds: tuple[str, ...],
1158
+ object_field_names: tuple[str, ...],
1159
+ property_field_names: tuple[str, ...],
1160
+ call_node_kinds: tuple[str, ...] = ("call_expression", "call",),
1161
+ call_function_field_names: tuple[str, ...] = ("function", "callee",),
1162
+ scoped_path: bool = False,
1163
+ ) -> None:
1164
+ """Emit ``module_attr_ref`` edges for attribute reads on imported modules.
1165
+
1166
+ This is the tree-sitter counterpart of the per-language helper that
1167
+ ships inside ``py.py`` (see WI-guhok). It targets bare attribute
1168
+ accesses like ``process.env.PATH`` (JS), ``System.out`` (Java), or
1169
+ ``os.Stdout`` (Go) — an imported-or-global module name followed by
1170
+ one or more attribute accesses whose leftmost access is NOT itself
1171
+ the callee of a function call. Callee attribute accesses such as
1172
+ ``os.getenv("X")`` or ``System.out.println("x")`` already produce
1173
+ ``calls`` edges and would be double-counted if emitted here.
1174
+
1175
+ The emission pairs with ``attributes:`` entries in
1176
+ ``io_primitives/*.yaml`` (WI-guhok for Python; this helper extends
1177
+ the same mechanism to all tree-sitter-based analyzers — WI-gapam).
1178
+ Without an edge to match, ``io-boundaries`` silently under-reports
1179
+ ``env_read`` / ``ipc_send`` / ``ipc_recv`` chains on any attribute
1180
+ primitive.
1181
+
1182
+ Args:
1183
+ root: The tree-sitter node to walk. Pass the file root for
1184
+ module-level reads, or a function body for per-function
1185
+ emission.
1186
+ source: Raw source bytes used for ``node_text``.
1187
+ imports: Map of local-alias name to the fully-qualified module
1188
+ name (e.g. ``{"process": "process"}`` in JS,
1189
+ ``{"os": "os"}`` in Go). Base names that are not in this
1190
+ map are skipped.
1191
+ caller_symbol: The symbol containing the attribute read (used
1192
+ as the edge ``src``).
1193
+ lang: Language tag for the synthetic edge destination
1194
+ (e.g. ``"javascript"`` / ``"java"`` / ``"go"``) — matches
1195
+ the ``language`` field of module-attribute sink IDs.
1196
+ edges_out: The edge list to append to — mutated in place.
1197
+ node_kinds: Tree-sitter node types that represent
1198
+ attribute-access nodes in this language. Tuple because
1199
+ some languages use more than one (e.g. JS ``member_expression``
1200
+ handles both ``a.b`` and ``a["b"]`` via an ``index_expression``
1201
+ sibling that the caller may also want to include).
1202
+ object_field_names: Child-field names to try for the base
1203
+ (receiver) of the attribute access, in order. Some grammars
1204
+ expose ``object``, others ``value`` or ``operand``.
1205
+ property_field_names: Child-field names to try for the attribute
1206
+ name.
1207
+ call_node_kinds: Tree-sitter node types that represent function
1208
+ calls; the helper excludes attribute-access nodes that are
1209
+ the callee of such a call so ``calls`` edges are not
1210
+ duplicated.
1211
+ call_function_field_names: Child-field names to try for the
1212
+ callee of a call node.
1213
+ scoped_path: When True, switches the helper to a left-recursive
1214
+ path-walk model used by languages whose scoped access is
1215
+ not a binary ``object`` / ``property`` pair. Rust's
1216
+ ``scoped_identifier`` and C++'s ``qualified_identifier``
1217
+ parse ``std::env::consts::OS`` as a nested chain of
1218
+ ``path`` + ``name`` children — the helper walks left via
1219
+ the path field to find the leftmost identifier, checks it
1220
+ against the imports map, and emits edges using
1221
+ dot-normalized module paths (``::`` replaced with ``.``)
1222
+ so the resulting edge ID survives downstream ``:``-split
1223
+ parsing. Catalog matching still works because
1224
+ ``IoBoundaryCatalog`` registers both ``::`` and ``.``
1225
+ forms in its qualified-name index.
1226
+ """
1227
+ # tree-sitter's Python bindings return a fresh wrapper object on each
1228
+ # accessor call, so `id()` is unstable across two walks of the same
1229
+ # tree. The underlying node carries a stable integer ``.id`` — use
1230
+ # that as the key for the callee-detection set.
1231
+ callee_attr_ids: set[int] = set()
1232
+ for node in iter_tree(root):
1233
+ if node.type not in call_node_kinds:
1234
+ continue
1235
+ callee = None
1236
+ for fname in call_function_field_names:
1237
+ callee = node.child_by_field_name(fname)
1238
+ if callee is not None:
1239
+ break
1240
+ if callee is None:
1241
+ continue
1242
+ if callee.type in node_kinds:
1243
+ callee_attr_ids.add(callee.id)
1244
+
1245
+ for node in iter_tree(root):
1246
+ if node.type not in node_kinds:
1247
+ continue
1248
+ if node.id in callee_attr_ids:
1249
+ continue
1250
+ base = None
1251
+ for fname in object_field_names:
1252
+ base = node.child_by_field_name(fname)
1253
+ if base is not None:
1254
+ break
1255
+ prop = None
1256
+ for fname in property_field_names:
1257
+ prop = node.child_by_field_name(fname)
1258
+ if prop is not None:
1259
+ break
1260
+ if base is None or prop is None:
1261
+ continue
1262
+ base_text = node_text(base, source)
1263
+ attr_name = node_text(prop, source)
1264
+ if scoped_path:
1265
+ # Left-recursive walk: the base may itself be a scoped_identifier
1266
+ # (``std::env`` inside ``std::env::consts``). Walk left via the
1267
+ # first object_field_name until we bottom out at a terminal
1268
+ # identifier — that's the alias we check against imports.
1269
+ leftmost = base
1270
+ while leftmost.type in node_kinds:
1271
+ inner = None
1272
+ for fname in object_field_names:
1273
+ inner = leftmost.child_by_field_name(fname)
1274
+ if inner is not None:
1275
+ break
1276
+ if inner is None: # pragma: no cover
1277
+ # Grammar variation guard: a node whose type is in
1278
+ # node_kinds but whose ``object_field_names`` resolve
1279
+ # to nothing is malformed — the outer node check would
1280
+ # have failed too. Break to avoid an infinite loop.
1281
+ break
1282
+ leftmost = inner
1283
+ leftmost_text = node_text(leftmost, source)
1284
+ if leftmost_text not in imports:
1285
+ continue
1286
+ # Replace the leftmost alias with its real module, then
1287
+ # dot-normalize ``::`` to ``.`` so the resulting edge ID
1288
+ # survives ``:``-split parsing in io_boundary.
1289
+ real_leftmost = imports[leftmost_text]
1290
+ real_module_raw = real_leftmost + base_text[len(leftmost_text):]
1291
+ real_module = real_module_raw.replace("::", ".")
1292
+ else:
1293
+ if base_text not in imports:
1294
+ continue
1295
+ real_module = imports[base_text]
1296
+ qname = f"{real_module}.{attr_name}"
1297
+ edges_out.append(Edge.create(
1298
+ src=caller_symbol.id,
1299
+ dst=f"{lang}:{real_module}:0-0:{qname}:attribute",
1300
+ edge_type="module_attr_ref",
1301
+ line=node.start_point[0] + 1,
1302
+ confidence=0.85,
1303
+ evidence_type="module_attribute_reference",
1304
+ ))
1305
+
1306
+
1082
1307
  def make_file_finder(patterns: list[str]) -> Callable[[Path], Iterator[Path]]: # pragma: no cover
1083
1308
  """Create a file finder function for specific patterns.
1084
1309
 
@@ -105,7 +105,11 @@ import hypergumbo_core.linkers.kafka_streams_dispatch as _kafka_streams_dispatch
105
105
  import hypergumbo_core.linkers.django_orm_dispatch as _django_orm_dispatch_linker # noqa: F401
106
106
  import hypergumbo_core.linkers.rust_trait_dispatch as _rust_trait_dispatch_linker # noqa: F401
107
107
  from .entrypoints import EntrypointKind, detect_entrypoints
108
- from .ir import Symbol, Edge, UsageContext, create_boundary_nodes, deduplicate_edges
108
+ from .ir import (
109
+ Symbol, Edge, UsageContext, apply_external_id_remap, create_boundary_nodes,
110
+ deduplicate_edges,
111
+ is_external_boundary,
112
+ )
109
113
  from .metrics import compute_metrics
110
114
  from .profile import detect_profile
111
115
  from .schema import new_behavior_map
@@ -1524,6 +1528,11 @@ def cmd_search(args: argparse.Namespace) -> int:
1524
1528
  matches = []
1525
1529
 
1526
1530
  for node in nodes:
1531
+ # Skip synthetic boundary nodes — they have no source location
1532
+ # and would surface as confusing "<external>" rows. Users searching
1533
+ # for `urlopen` want their fetch() call site, not the placeholder.
1534
+ if is_external_boundary(node):
1535
+ continue
1527
1536
  name = node.get("name", "")
1528
1537
  # Check if pattern matches name (fuzzy substring match)
1529
1538
  if pattern in name.lower():
@@ -3094,9 +3103,13 @@ def cmd_compact(args: argparse.Namespace) -> int:
3094
3103
  def cmd_io_boundaries(args: argparse.Namespace) -> int:
3095
3104
  """Display I/O boundary map for a repository (ADR-0016).
3096
3105
 
3097
- Identifies call edges that reach I/O primitives (filesystem, network,
3098
- subprocess, environment) and groups them by boundary type. Loads a
3099
- cached behavior map or auto-runs analysis if needed.
3106
+ Identifies call edges that reach I/O primitives and groups them by
3107
+ boundary type: ``fs_read``, ``fs_write``, ``net_send``, ``net_recv``,
3108
+ ``subprocess``, ``env_read``, ``env_write``, ``ipc_send``, ``ipc_recv``,
3109
+ ``browser_storage_write``, ``browser_storage_read``, ``db_read``,
3110
+ ``db_write``, ``process_send``, ``logging``. Attribute-style primitives
3111
+ (``os.environ``, ``sys.argv``) are included via ``module_attr_ref``
3112
+ edges. Loads a cached behavior map or auto-runs analysis if needed.
3100
3113
  """
3101
3114
  repo_root = Path(args.path).resolve()
3102
3115
 
@@ -3169,12 +3182,21 @@ def cmd_io_boundaries(args: argparse.Namespace) -> int:
3169
3182
  for ep in behavior_map.get("entrypoints", [])
3170
3183
  }
3171
3184
 
3172
- # Compute boundary map with entrypoint tracing
3173
- bmap = compute_boundary_map(edges, catalogs, entrypoint_ids=entrypoint_ids or None)
3174
-
3175
- # Build node lookup for human-readable caller names
3185
+ # Build node lookup for human-readable caller names AND for IoChain
3186
+ # tier surfacing passing nodes_by_id into compute_boundary_map lets
3187
+ # each chain carry its dst's supply_chain.tier so verify-claims /
3188
+ # sketch / external consumers can distinguish "first-party calls
3189
+ # first-party I/O" from "first-party calls tier-3 wrapper that may
3190
+ # reach the network" without per-library catalog growth.
3176
3191
  nodes_by_id: Dict[str, Any] = {n["id"]: n for n in behavior_map.get("nodes", [])}
3177
3192
 
3193
+ # Compute boundary map with entrypoint tracing AND tier lookup
3194
+ bmap = compute_boundary_map(
3195
+ edges, catalogs,
3196
+ entrypoint_ids=entrypoint_ids or None,
3197
+ nodes_by_id=nodes_by_id,
3198
+ )
3199
+
3178
3200
  # Apply boundary/primitive/exclude-tests filters
3179
3201
  boundary_filter = getattr(args, "boundary", None)
3180
3202
  primitive_filter = getattr(args, "primitive", None)
@@ -3183,7 +3205,25 @@ def cmd_io_boundaries(args: argparse.Namespace) -> int:
3183
3205
  # CLI users do the same via --include-tests.
3184
3206
  exclude_tests = getattr(args, "exclude_tests", True)
3185
3207
 
3186
- from .io_boundary import BoundaryMapEntry
3208
+ from .io_boundary import (
3209
+ BoundaryMapEntry,
3210
+ _build_reverse_graph,
3211
+ compute_leaf_rollups,
3212
+ )
3213
+
3214
+ # WI-rubir: when the filter path rebuilds BoundaryMapEntry it must
3215
+ # also recompute the WI-darad leaf-caller roll-ups for the surviving
3216
+ # chain subset; otherwise leaf_callers / entry_points_per_leaf are
3217
+ # silently dropped (they default to empty on the dataclass), and
3218
+ # because exclude_tests=True is the default, every normal CLI
3219
+ # invocation hits this path.
3220
+ reverse_graph_for_filter: Optional[Dict[str, set[str]]] = None
3221
+
3222
+ def _ensure_reverse_graph() -> Dict[str, set[str]]:
3223
+ nonlocal reverse_graph_for_filter
3224
+ if reverse_graph_for_filter is None:
3225
+ reverse_graph_for_filter = _build_reverse_graph(edges)
3226
+ return reverse_graph_for_filter
3187
3227
 
3188
3228
  filtered_entries: Dict[str, BoundaryMapEntry] = {}
3189
3229
  for btype, entry in bmap.entries.items():
@@ -3209,11 +3249,18 @@ def cmd_io_boundaries(args: argparse.Namespace) -> int:
3209
3249
  continue
3210
3250
 
3211
3251
  if primitive_filter or exclude_tests:
3252
+ leaf_callers, entry_points_per_leaf = compute_leaf_rollups(
3253
+ chains,
3254
+ _ensure_reverse_graph(),
3255
+ entrypoint_ids or None,
3256
+ )
3212
3257
  filtered_entries[btype] = BoundaryMapEntry(
3213
3258
  boundary=entry.boundary,
3214
3259
  chains=chains,
3215
3260
  entry_points=sorted({ep for c in chains for ep in c.entry_points}),
3216
3261
  primitives_used=sorted({c.primitive for c in chains}),
3262
+ leaf_callers=leaf_callers,
3263
+ entry_points_per_leaf=entry_points_per_leaf,
3217
3264
  )
3218
3265
  else:
3219
3266
  filtered_entries[btype] = entry
@@ -3351,7 +3398,24 @@ def _print_io_boundaries_by_type(
3351
3398
  print(f" {prim} ({count}){risk_flag}")
3352
3399
  for chain in chains_by_prim[prim]:
3353
3400
  caller = _format_io_caller(chain.io_edge_src, nodes_by_id, repo_root)
3354
- print(f" <- {caller}")
3401
+ # Surface dst supply-chain tier so the user can tell apart
3402
+ # "first-party calls first-party I/O" from "first-party
3403
+ # calls a tier-3 wrapper that may reach the network."
3404
+ # Only annotate when the dst is an external boundary —
3405
+ # the common case for stdlib / npm / third-party deps.
3406
+ tier_tag = ""
3407
+ if chain.dst_external_boundary and chain.dst_tier_name:
3408
+ tier_tag = f" [tier-{chain.dst_tier} {chain.dst_tier_name}]"
3409
+ # Plan C, PR C: external_potential chains for in_progress
3410
+ # source languages flag the absence-of-catalog-hit as
3411
+ # unreliable so the user knows the language's stdlib is
3412
+ # not yet provenance-validated.
3413
+ unreliable_tag = (
3414
+ " [unreliable]"
3415
+ if chain.dst_classification_unreliable
3416
+ else ""
3417
+ )
3418
+ print(f" <- {caller}{tier_tag}{unreliable_tag}")
3355
3419
  if chain.entry_points:
3356
3420
  ep_names = [
3357
3421
  _format_io_caller(ep, nodes_by_id, repo_root)
@@ -3414,6 +3478,28 @@ def cmd_verify_claims(args: argparse.Namespace) -> int:
3414
3478
  taint-flow analysis if needed, and checks each claim. Returns exit
3415
3479
  code 1 if any claim is violated. Supports boundary constraints
3416
3480
  (ADR-0016) and taint-flow constraints (ADR-0017).
3481
+
3482
+ Trust zones checked: ``host_fs``, ``network``, ``host_env``, ``ipc``,
3483
+ ``browser_storage``, ``relay``. Built-in taint labels: ``host_secret``,
3484
+ ``untrusted_input``, ``plaintext``, ``key_material``, ``ciphertext``,
3485
+ ``derived_key``. The source and sink catalogs are derived automatically
3486
+ from ``io_primitives/*.yaml`` (every write-side primitive is a sink at
3487
+ ``trust_level=untrusted``; ``env_read``, ``net_recv``, and ``ipc_recv``
3488
+ primitives are sources). YAML files under ``taint_sources/``,
3489
+ ``taint_sinks/``, ``taint_sanitizers/`` contribute cryptographic labels
3490
+ and sanitizer transforms that the auto-layer cannot express.
3491
+
3492
+ Project-local catalogs (WI-votan): the ``--taint-sources``,
3493
+ ``--taint-sinks``, and ``--taint-sanitizers`` flags each accept a YAML
3494
+ file or a directory of YAMLs and are repeatable; the claims YAML may
3495
+ carry the same paths under a top-level ``extra_catalogs:`` key with
3496
+ ``sources``/``sinks``/``sanitizers`` sub-lists (paths resolve relative
3497
+ to the claims-file directory). User entries whose
3498
+ ``(module, name, kind)`` triple matches an auto-derived or built-in
3499
+ source/sink replace it; user sanitizers concatenate. This is the
3500
+ supported extension point for declaring project-specific trust zones,
3501
+ raising ``trust_level`` on a sink that is safe in context, or adding
3502
+ a domain-specific taint source label.
3417
3503
  """
3418
3504
  repo_root = Path(args.path).resolve()
3419
3505
  claims_path = Path(args.claims)
@@ -3497,11 +3583,51 @@ def cmd_verify_claims(args: argparse.Namespace) -> int:
3497
3583
  unsupported_taint_languages: list[str] = []
3498
3584
  has_taint_claims = any(c.constraint_taint_flow is not None for c in claims)
3499
3585
  if has_taint_claims:
3500
- from .taint import load_builtin_taint_catalog, propagate_taint_structural
3501
- taint_catalog = load_builtin_taint_catalog()
3586
+ from .taint import load_full_taint_catalog, propagate_taint_structural
3587
+ from .verify_claims import load_extra_catalog_paths
3588
+
3589
+ # Assemble project-local taint catalog paths from CLI flags and the
3590
+ # ``extra_catalogs:`` key in the claims YAML (WI-votan). CLI paths
3591
+ # come first so users invoking on the command line keep control
3592
+ # even when a claims file declares its own defaults; merge
3593
+ # semantics are order-independent because (module, name, kind)
3594
+ # conflicts between two user entries would be a bug regardless.
3595
+ cli_sources = [Path(p) for p in (getattr(args, "taint_sources", None) or [])]
3596
+ cli_sinks = [Path(p) for p in (getattr(args, "taint_sinks", None) or [])]
3597
+ cli_sanitizers = [
3598
+ Path(p) for p in (getattr(args, "taint_sanitizers", None) or [])
3599
+ ]
3600
+ claims_sources, claims_sinks, claims_sanitizers = (
3601
+ load_extra_catalog_paths(claims_path)
3602
+ )
3603
+ extra_source_paths = cli_sources + claims_sources
3604
+ extra_sink_paths = cli_sinks + claims_sinks
3605
+ extra_sanitizer_paths = cli_sanitizers + claims_sanitizers
3606
+
3607
+ try:
3608
+ taint_catalog = load_full_taint_catalog(
3609
+ extra_source_paths=extra_source_paths,
3610
+ extra_sink_paths=extra_sink_paths,
3611
+ extra_sanitizer_paths=extra_sanitizer_paths,
3612
+ )
3613
+ except FileNotFoundError as exc:
3614
+ print(f"Error: {exc}", file=sys.stderr)
3615
+ return 1
3502
3616
 
3503
- # Also load project-local taint catalogs if specified in claims file
3504
- # (future: --taint-sources, --taint-sinks, --taint-sanitizers args)
3617
+ if (
3618
+ extra_source_paths
3619
+ or extra_sink_paths
3620
+ or extra_sanitizer_paths
3621
+ ):
3622
+ print(
3623
+ "Loaded project-local taint catalog: "
3624
+ f"{len(extra_source_paths)} source path(s), "
3625
+ f"{len(extra_sink_paths)} sink path(s), "
3626
+ f"{len(extra_sanitizer_paths)} sanitizer path(s). "
3627
+ "User entries override auto-derived defaults on "
3628
+ "(module, name, kind) match.",
3629
+ file=sys.stderr,
3630
+ )
3505
3631
 
3506
3632
  # Collect all sources, sinks, sanitizers across languages
3507
3633
  all_sources = []
@@ -5823,6 +5949,39 @@ are excluded by default — pass --include-tests to see them. See ADR-0016."""
5823
5949
  dest="json_output",
5824
5950
  help="Output as JSON",
5825
5951
  )
5952
+ p_vc.add_argument(
5953
+ "--taint-sources",
5954
+ action="append",
5955
+ default=None,
5956
+ metavar="PATH",
5957
+ help=(
5958
+ "Project-local taint source YAML file or directory. "
5959
+ "Repeatable. Entries whose (module, name, kind) matches an "
5960
+ "auto-derived or built-in source are overridden. (WI-votan)"
5961
+ ),
5962
+ )
5963
+ p_vc.add_argument(
5964
+ "--taint-sinks",
5965
+ action="append",
5966
+ default=None,
5967
+ metavar="PATH",
5968
+ help=(
5969
+ "Project-local taint sink YAML file or directory. "
5970
+ "Repeatable. Entries whose (module, name, kind) matches an "
5971
+ "auto-derived or built-in sink are overridden. (WI-votan)"
5972
+ ),
5973
+ )
5974
+ p_vc.add_argument(
5975
+ "--taint-sanitizers",
5976
+ action="append",
5977
+ default=None,
5978
+ metavar="PATH",
5979
+ help=(
5980
+ "Project-local taint sanitizer YAML file or directory. "
5981
+ "Repeatable. User sanitizers concatenate onto the built-in "
5982
+ "list. (WI-votan)"
5983
+ ),
5984
+ )
5826
5985
  p_vc.set_defaults(func=cmd_verify_claims)
5827
5986
 
5828
5987
  # Assign subcommands to groups for help formatting
@@ -6491,11 +6650,17 @@ def run_behavior_map(
6491
6650
  # Create boundary nodes for dangling edge endpoints (WI-sikur / INV-miniz).
6492
6651
  # Edges to external functions (stdlib, npm packages, etc.) would otherwise
6493
6652
  # break slice traversal by pointing to nonexistent nodes.
6494
- boundary = create_boundary_nodes(
6653
+ # WI-fozoh: synthesizer collapses dangling refs by (lang, name, kind) and
6654
+ # returns an id_remap so we can rewrite edges to point at the canonical
6655
+ # boundary Symbols. Without this rewrite, edges would still reference the
6656
+ # original (now-absent) per-reference dangling ids.
6657
+ boundary, id_remap = create_boundary_nodes(
6495
6658
  all_symbols, all_edges, dependency_manifest=dependency_manifest,
6496
6659
  )
6497
6660
  if boundary:
6498
6661
  all_symbols.extend(boundary)
6662
+ if id_remap:
6663
+ all_edges = apply_external_id_remap(all_edges, id_remap)
6499
6664
  _log_memory("after boundary nodes")
6500
6665
 
6501
6666
  # Apply supply chain classification to all symbols
@@ -6539,7 +6704,7 @@ def run_behavior_map(
6539
6704
  removed_symbol_ids = {
6540
6705
  s.id for s in all_symbols
6541
6706
  if s.id not in filtered_symbol_ids
6542
- and not (s.meta and s.meta.get("external_boundary"))
6707
+ and not is_external_boundary(s)
6543
6708
  }
6544
6709
 
6545
6710
  def _is_valid_edge_src(src: str) -> bool:
@@ -6578,14 +6743,28 @@ def run_behavior_map(
6578
6743
  # CSS structural (degree-0 in behavior maps)
6579
6744
  "class_selector", "id_selector", "rule_set",
6580
6745
  "property", "media", "keyframes", "font_face",
6581
- "variable", # CSS custom properties / SCSS variables (zero edges)
6582
6746
  # Config metadata (degree-0 across all tested repos)
6583
6747
  "pattern", # .gitignore entries
6584
6748
  "script", # npm scripts / pyproject.toml entry points
6585
6749
  "requirement", # pip requirements.txt entries
6586
6750
  })
6587
- noise_ids = {s.id for s in all_symbols if s.kind in _NOISE_KINDS}
6588
- all_symbols = [s for s in all_symbols if s.kind not in _NOISE_KINDS]
6751
+ # CSS-family `variable` (custom properties, SCSS / Sass variables) is
6752
+ # zero-edge noise and stays excluded. WI-gafog E2: in any other
6753
+ # language, `variable` is a real top-level binding (Python module
6754
+ # constants, Go top-level `var`, YAML / Make variables) and must
6755
+ # remain in the output for cross-file `from <mod> import NAME`
6756
+ # resolution.
6757
+ _CSS_LANGUAGES = frozenset({"css", "scss", "sass", "less"})
6758
+
6759
+ def _is_noise(sym: "Symbol") -> bool:
6760
+ if sym.kind in _NOISE_KINDS:
6761
+ return True
6762
+ if sym.kind == "variable" and sym.language in _CSS_LANGUAGES:
6763
+ return True
6764
+ return False
6765
+
6766
+ noise_ids = {s.id for s in all_symbols if _is_noise(s)}
6767
+ all_symbols = [s for s in all_symbols if not _is_noise(s)]
6589
6768
  all_edges = [
6590
6769
  e for e in all_edges
6591
6770
  if e.src not in noise_ids and e.dst not in noise_ids
@@ -6601,16 +6780,15 @@ def run_behavior_map(
6601
6780
  ranked_symbols = [r.symbol for r in ranked]
6602
6781
  del ranked # Free RankedSymbol wrappers
6603
6782
 
6604
- # Filter boundary nodes from output. They exist in `all_symbols` to make
6605
- # edge endpoints resolvable for slice traversal, but shouldn't appear in
6606
- # the behavior map output they're synthetic, have no source code, and
6607
- # would inflate node counts. Edges pointing to boundary node IDs are
6608
- # retained (consumers can detect them by the "<external>" path or
6609
- # external_boundary meta flag).
6610
- ranked_symbols = [
6611
- s for s in ranked_symbols
6612
- if not (s.meta and s.meta.get("external_boundary"))
6613
- ]
6783
+ # Boundary nodes (synthetic Symbols for unresolved external edge endpoints
6784
+ # created by ir.create_boundary_nodes per WI-sikur / INV-miniz) are kept
6785
+ # in the output. Display surfaces (sketch / compact / search /
6786
+ # dead-code / explain) filter them via ir.is_external_boundary so the
6787
+ # presentation stays focused on first-party code, but the JSON exposes
6788
+ # them so disk-load consumers (slice / verify-claims / test-coverage)
6789
+ # can resolve every edge endpoint to a node and reason over the
6790
+ # boundary's supply_chain.tier (e.g., tier-3 wrappers that may reach
6791
+ # the network).
6614
6792
 
6615
6793
  # Convert to dicts for output (in ranked order)
6616
6794
  all_nodes = [s.to_dict() for s in ranked_symbols]