sourcecode 5.5.2__tar.gz → 5.5.4__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 (357) hide show
  1. {sourcecode-5.5.2 → sourcecode-5.5.4}/CHANGELOG.md +36 -0
  2. {sourcecode-5.5.2 → sourcecode-5.5.4}/PKG-INFO +3 -3
  3. {sourcecode-5.5.2 → sourcecode-5.5.4}/README.md +2 -2
  4. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/DEFECT-LEDGER.md +11 -0
  5. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/USER_GUIDE.md +8 -2
  6. {sourcecode-5.5.2 → sourcecode-5.5.4}/pyproject.toml +1 -1
  7. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/__init__.py +1 -1
  8. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/cli.py +21 -1
  9. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/deployment_prefix.py +18 -12
  10. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/repository_ir.py +91 -28
  11. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/servlet_surface.py +50 -5
  12. {sourcecode-5.5.2 → sourcecode-5.5.4}/.github/workflows/build-windows.yml +0 -0
  13. {sourcecode-5.5.2 → sourcecode-5.5.4}/.github/workflows/perf-gate.yml +0 -0
  14. {sourcecode-5.5.2 → sourcecode-5.5.4}/.gitignore +0 -0
  15. {sourcecode-5.5.2 → sourcecode-5.5.4}/.ruff.toml +0 -0
  16. {sourcecode-5.5.2 → sourcecode-5.5.4}/CLAUDE.md +0 -0
  17. {sourcecode-5.5.2 → sourcecode-5.5.4}/CONTRIBUTING.md +0 -0
  18. {sourcecode-5.5.2 → sourcecode-5.5.4}/LICENSE +0 -0
  19. {sourcecode-5.5.2 → sourcecode-5.5.4}/SECURITY.md +0 -0
  20. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/CACHE.md +0 -0
  21. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/COMMERCIAL-OFFER.md +0 -0
  22. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/CUSTOMER-VALIDATION.md +0 -0
  23. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/DEMO-5MIN.md +0 -0
  24. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/DEVELOPMENT-ROADMAP.md +0 -0
  25. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/EXECUTION-PLAN-12MO.md +0 -0
  26. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/EXECUTIVE-ROADMAP.md +0 -0
  27. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/MANUAL-USUARIO.md +0 -0
  28. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/MODERNIZATION.md +0 -0
  29. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/PRODUCT_AUDIT.md +0 -0
  30. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/PRODUCT_IDENTITY.md +0 -0
  31. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/PRODUCT_TIERS.md +0 -0
  32. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/RC1-CHECKLIST.md +0 -0
  33. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/RELEASE-CHECKLIST.md +0 -0
  34. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/CATALOG-retrieval-intents.md +0 -0
  35. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/DESIGN-knowledge-provider-integration.md +0 -0
  36. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/DESIGN-p5.3b-statement-surface.md +0 -0
  37. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/DESIGN-p5.5-span-index.md +0 -0
  38. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/DESIGN-p6-semantic-impact-engine.md +0 -0
  39. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/DESIGN-p6-semantic-integration-engine.md +0 -0
  40. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/DESIGN-p7-semantic-services.md +0 -0
  41. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/DESIGN-robustness-security-inference.md +0 -0
  42. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/DESIGN-semantic-retrieval.md +0 -0
  43. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/EPV-p6-class-typeref.md +0 -0
  44. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/REPORT-p6-flow-analyzer-comparison.md +0 -0
  45. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/REPORT-p6-integration-detector-comparison.md +0 -0
  46. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/REPORT-p8-flow-analyzer-migration.md +0 -0
  47. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/REPORT-p9-integration-detector-migration.md +0 -0
  48. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/adr/0001-semantic-ir.md +0 -0
  49. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/adr/0002-source-evidence-boundary.md +0 -0
  50. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/adr/0003-architectural-characterization.md +0 -0
  51. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/adr/0004-semantic-retrieval.md +0 -0
  52. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/adr/0005-evidence-reconciliation.md +0 -0
  53. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/adr/0006-performance-harness.md +0 -0
  54. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/adr/0007-composition-semantics.md +0 -0
  55. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/adr/0008-answer-coherence.md +0 -0
  56. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/consumer-disposition-inventory.md +0 -0
  57. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/overview.md +0 -0
  58. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/product-architecture-review.md +0 -0
  59. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/product-strategy-layering.md +0 -0
  60. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/semantic-ir-consumer-matrix.md +0 -0
  61. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/architecture/semantic-ir-roadmap.md +0 -0
  62. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/baseline-ci.yml +0 -0
  63. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/commercial-pipeline-audit.md +0 -0
  64. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/contracts-ci.yml +0 -0
  65. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/contracts.md +0 -0
  66. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/eval/2026-06-15-petclinic-rest-issue11-vets-pagination.md +0 -0
  67. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/eval/2026-06-15-petclinic-rest-issue147-validation.md +0 -0
  68. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/eval/2026-06-15-petclinic-rest-workflow.md +0 -0
  69. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/eval/2026-06-15-phase18-openapi-surface.md +0 -0
  70. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/eval/2026-06-15-phase20-validation-surface.md +0 -0
  71. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/eval/2026-06-16-broadleaf-checkout-impact-fieldtest.md +0 -0
  72. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/eval/2026-06-16-petclinic-rest-issue11-weakness2-closed.md +0 -0
  73. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/eval/2026-06-16-spring-petclinic-issue2333-dead-vets.md +0 -0
  74. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/licensing-schema.md +0 -0
  75. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/migrate-check.md +0 -0
  76. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/README.md +0 -0
  77. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/REGRESSION-GATE.md +0 -0
  78. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/SUMMARY.md +0 -0
  79. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/alfresco__ask__cold.json +0 -0
  80. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/alfresco__ask__warm.json +0 -0
  81. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/broadleaf__ask__cold.json +0 -0
  82. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/broadleaf__ask__warm.json +0 -0
  83. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/eureka__ask__cold.json +0 -0
  84. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/eureka__ask__warm.json +0 -0
  85. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/jenkins__ask__cold.json +0 -0
  86. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/jenkins__ask__warm.json +0 -0
  87. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/jobrunr__ask__cold.json +0 -0
  88. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/jobrunr__ask__warm.json +0 -0
  89. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/keycloak__ask__cold.json +0 -0
  90. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/keycloak__ask__warm.json +0 -0
  91. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/neo4j__ask__cold.json +0 -0
  92. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/neo4j__ask__warm.json +0 -0
  93. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/ofbiz__ask__cold.json +0 -0
  94. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/ofbiz__ask__warm.json +0 -0
  95. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/openmrs__ask__cold.json +0 -0
  96. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/openmrs__ask__warm.json +0 -0
  97. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/petclinic__ask__cold.json +0 -0
  98. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.15/petclinic__ask__warm.json +0 -0
  99. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/SUMMARY.md +0 -0
  100. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/alfresco__ask__cold.json +0 -0
  101. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/alfresco__ask__warm.json +0 -0
  102. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/broadleaf__ask__cold.json +0 -0
  103. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/broadleaf__ask__warm.json +0 -0
  104. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/eureka__ask__cold.json +0 -0
  105. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/eureka__ask__warm.json +0 -0
  106. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/jenkins__ask__cold.json +0 -0
  107. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/jenkins__ask__warm.json +0 -0
  108. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/jobrunr__ask__cold.json +0 -0
  109. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/jobrunr__ask__warm.json +0 -0
  110. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/keycloak__ask__cold.json +0 -0
  111. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/keycloak__ask__warm.json +0 -0
  112. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/neo4j__ask__cold.json +0 -0
  113. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/neo4j__ask__warm.json +0 -0
  114. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/ofbiz__ask__cold.json +0 -0
  115. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/ofbiz__ask__warm.json +0 -0
  116. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/openmrs__ask__cold.json +0 -0
  117. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/openmrs__ask__warm.json +0 -0
  118. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/petclinic__ask__cold.json +0 -0
  119. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/2.5.16/petclinic__ask__warm.json +0 -0
  120. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/gate-latest/README.md +0 -0
  121. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/gate-latest/broadleaf__ask__warm.json +0 -0
  122. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/gate-latest/broadleaf__endpoints__warm.json +0 -0
  123. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/gate-latest/broadleaf__migrate-check__warm.json +0 -0
  124. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/gate-latest/broadleaf__posture__warm.json +0 -0
  125. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/gate-latest/broadleaf__spring-audit__warm.json +0 -0
  126. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/gate-latest/broadleaf__validation__warm.json +0 -0
  127. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/perf/baselines/reference-best/README.md +0 -0
  128. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/posture.md +0 -0
  129. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/privacy.md +0 -0
  130. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/pro-experience-audit.md +0 -0
  131. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/schema.md +0 -0
  132. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/spec/envelope-v1.md +0 -0
  133. {sourcecode-5.5.2 → sourcecode-5.5.4}/docs/spring-audit-ci.yml +0 -0
  134. {sourcecode-5.5.2 → sourcecode-5.5.4}/raw +0 -0
  135. {sourcecode-5.5.2 → sourcecode-5.5.4}/scripts/compare_integration_engines.py +0 -0
  136. {sourcecode-5.5.2 → sourcecode-5.5.4}/scripts/customer_smoke_test.sh +0 -0
  137. {sourcecode-5.5.2 → sourcecode-5.5.4}/scripts/generate_jdk_exports.py +0 -0
  138. {sourcecode-5.5.2 → sourcecode-5.5.4}/scripts/perf_gate.py +0 -0
  139. {sourcecode-5.5.2 → sourcecode-5.5.4}/scripts/perf_harness.py +0 -0
  140. {sourcecode-5.5.2 → sourcecode-5.5.4}/scripts/sync_gate_anchors.py +0 -0
  141. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/adaptive_scanner.py +0 -0
  142. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/archetype.py +0 -0
  143. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/architectural_baseline.py +0 -0
  144. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/architectural_delta.py +0 -0
  145. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/architecture_analyzer.py +0 -0
  146. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/architecture_summary.py +0 -0
  147. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/ast_extractor.py +0 -0
  148. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/audit_report.py +0 -0
  149. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/baseline_autocapture.py +0 -0
  150. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/bundled_docs.py +0 -0
  151. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/cache.py +0 -0
  152. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/cache_model.py +0 -0
  153. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/call_surface.py +0 -0
  154. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/caller_metrics.py +0 -0
  155. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/caller_reach.py +0 -0
  156. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/canonical_ir.py +0 -0
  157. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/chain_rules.py +0 -0
  158. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/change_plan.py +0 -0
  159. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/cir_graphs.py +0 -0
  160. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/classifier.py +0 -0
  161. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/client_calls.py +0 -0
  162. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/code_notes_analyzer.py +0 -0
  163. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/compare.py +0 -0
  164. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/confidence_analyzer.py +0 -0
  165. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/constraint_diff.py +0 -0
  166. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/consumer_join.py +0 -0
  167. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/container_wiring.py +0 -0
  168. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/context_cache.py +0 -0
  169. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/context_graph.py +0 -0
  170. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/context_scorer.py +0 -0
  171. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/context_summarizer.py +0 -0
  172. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/contract_diff.py +0 -0
  173. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/contract_init.py +0 -0
  174. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/contract_model.py +0 -0
  175. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/contract_pipeline.py +0 -0
  176. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/coverage_parser.py +0 -0
  177. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/data_exposure.py +0 -0
  178. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/data_labels.py +0 -0
  179. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/declarations.py +0 -0
  180. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/defect_identity.py +0 -0
  181. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/degradation.py +0 -0
  182. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/dependency_analyzer.py +0 -0
  183. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detach.py +0 -0
  184. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/__init__.py +0 -0
  185. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/base.py +0 -0
  186. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/csproj_parser.py +0 -0
  187. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/dart.py +0 -0
  188. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/dotnet.py +0 -0
  189. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/elixir.py +0 -0
  190. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/go.py +0 -0
  191. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/heuristic.py +0 -0
  192. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/hybrid.py +0 -0
  193. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/java.py +0 -0
  194. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/jvm_ext.py +0 -0
  195. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/nodejs.py +0 -0
  196. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/parsers.py +0 -0
  197. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/php.py +0 -0
  198. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/project.py +0 -0
  199. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/python.py +0 -0
  200. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/ruby.py +0 -0
  201. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/rust.py +0 -0
  202. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/systems.py +0 -0
  203. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/terraform.py +0 -0
  204. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/detectors/tooling.py +0 -0
  205. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/doc_analyzer.py +0 -0
  206. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/dynamic_argument_surface.py +0 -0
  207. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/endpoint_literals.py +0 -0
  208. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/endpoint_metrics.py +0 -0
  209. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/entrypoint_classifier.py +0 -0
  210. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/env_analyzer.py +0 -0
  211. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/envelope.py +0 -0
  212. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/environment_resolution.py +0 -0
  213. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/error_schema.py +0 -0
  214. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/evidence_provider.py +0 -0
  215. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/execution_plan.py +0 -0
  216. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/explain.py +0 -0
  217. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/facts/__init__.py +0 -0
  218. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/facts/registry.json +0 -0
  219. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/file_chunker.py +0 -0
  220. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/file_classifier.py +0 -0
  221. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/filter_surface.py +0 -0
  222. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/format_contract.py +0 -0
  223. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/fqn_utils.py +0 -0
  224. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/gate_anchors.py +0 -0
  225. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/git_analyzer.py +0 -0
  226. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/git_checkout.py +0 -0
  227. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/graph_analyzer.py +0 -0
  228. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/graph_evidence.py +0 -0
  229. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/hibernate_strat.py +0 -0
  230. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/identity_fallback.py +0 -0
  231. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/integration_coordinates.py +0 -0
  232. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/jdk_exports.py +0 -0
  233. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/license.py +0 -0
  234. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/manifest_cache.py +0 -0
  235. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/mcp/__init__.py +0 -0
  236. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/mcp/dependency_import.py +0 -0
  237. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
  238. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/mcp/onboarding/applier.py +0 -0
  239. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/mcp/onboarding/backup.py +0 -0
  240. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/mcp/onboarding/detector.py +0 -0
  241. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/mcp/onboarding/planner.py +0 -0
  242. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/mcp/orchestrator.py +0 -0
  243. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/mcp/registry.py +0 -0
  244. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/mcp/runner.py +0 -0
  245. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/mcp/server.py +0 -0
  246. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/mcp_nudge.py +0 -0
  247. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/metrics_analyzer.py +0 -0
  248. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/migrate_check.py +0 -0
  249. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/migration_blast.py +0 -0
  250. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/non_coverage.py +0 -0
  251. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/openapi_surface.py +0 -0
  252. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/openrewrite_recipe.py +0 -0
  253. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/output_budget.py +0 -0
  254. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/output_encoding.py +0 -0
  255. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/parallel.py +0 -0
  256. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/parse_cache.py +0 -0
  257. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/partial_contract.py +0 -0
  258. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/path_admission.py +0 -0
  259. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/path_filters.py +0 -0
  260. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/perf.py +0 -0
  261. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/phased_run.py +0 -0
  262. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/pipe_contract.py +0 -0
  263. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/posture.py +0 -0
  264. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/pr_comment_renderer.py +0 -0
  265. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/pr_impact.py +0 -0
  266. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/prepare_context.py +0 -0
  267. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/progress.py +0 -0
  268. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/provenance.py +0 -0
  269. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/ranking_engine.py +0 -0
  270. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/readiness_timeline.py +0 -0
  271. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/readonly.py +0 -0
  272. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/reconciliation.py +0 -0
  273. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/redactor.py +0 -0
  274. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/reference_facts.py +0 -0
  275. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/release_info.py +0 -0
  276. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/relevance_scorer.py +0 -0
  277. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/remedies.py +0 -0
  278. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/rename_refactor.py +0 -0
  279. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/repo_classifier.py +0 -0
  280. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/retrieval/__init__.py +0 -0
  281. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/retrieval/context.py +0 -0
  282. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/retrieval/errors.py +0 -0
  283. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/retrieval/executor.py +0 -0
  284. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/retrieval/planner.py +0 -0
  285. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/retrieval/query.py +0 -0
  286. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/retrieval/request.py +0 -0
  287. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/retrieval/resolution.py +0 -0
  288. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/retrieval/result.py +0 -0
  289. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/retrieval/retriever.py +0 -0
  290. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/retrieval/runtime.py +0 -0
  291. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/retrieval/steps.py +0 -0
  292. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/retrieval/steps_endpoint.py +0 -0
  293. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/retrieval/steps_graph.py +0 -0
  294. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/retrieval/steps_impact.py +0 -0
  295. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/retrieval/steps_intf.py +0 -0
  296. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/retrieval/steps_struct.py +0 -0
  297. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/retrieval/steps_txsec.py +0 -0
  298. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/ris.py +0 -0
  299. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/risk.py +0 -0
  300. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/rule_catalog.py +0 -0
  301. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/rule_pass.py +0 -0
  302. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/runs.py +0 -0
  303. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/runtime_classifier.py +0 -0
  304. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/sarif.py +0 -0
  305. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/scanner.py +0 -0
  306. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/schema.py +0 -0
  307. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/schemas/envelope-v1.schema.json +0 -0
  308. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/security_chain.py +0 -0
  309. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/security_config.py +0 -0
  310. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/security_config_scan.py +0 -0
  311. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/security_posture.py +0 -0
  312. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/semantic_analyzer.py +0 -0
  313. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/semantic_impact_engine.py +0 -0
  314. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/semantic_integration_engine.py +0 -0
  315. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/semantic_services.py +0 -0
  316. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/serializer.py +0 -0
  317. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/source_text.py +0 -0
  318. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/spring_event_topology.py +0 -0
  319. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/spring_findings.py +0 -0
  320. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/spring_impact.py +0 -0
  321. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/spring_model.py +0 -0
  322. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/spring_profiles.py +0 -0
  323. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/spring_properties.py +0 -0
  324. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/spring_security_audit.py +0 -0
  325. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/spring_semantic.py +0 -0
  326. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/spring_tx_analyzer.py +0 -0
  327. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/sql_taint.py +0 -0
  328. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/summarizer.py +0 -0
  329. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/target_admission.py +0 -0
  330. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/telemetry/__init__.py +0 -0
  331. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/telemetry/config.py +0 -0
  332. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/telemetry/consent.py +0 -0
  333. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/telemetry/events.py +0 -0
  334. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/telemetry/filters.py +0 -0
  335. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/telemetry/transport.py +0 -0
  336. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/test_gap_ranking.py +0 -0
  337. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/test_sources.py +0 -0
  338. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/text_input.py +0 -0
  339. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/timeline.py +0 -0
  340. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/token_estimate.py +0 -0
  341. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/tree_utils.py +0 -0
  342. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/type_usage_surface.py +0 -0
  343. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/validation_inference.py +0 -0
  344. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/validation_surface.py +0 -0
  345. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/verify_edit.py +0 -0
  346. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/verify_repo.py +0 -0
  347. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/verify_rules.py +0 -0
  348. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/version_check.py +0 -0
  349. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/waivers.py +0 -0
  350. {sourcecode-5.5.2 → sourcecode-5.5.4}/src/sourcecode/workspace.py +0 -0
  351. {sourcecode-5.5.2 → sourcecode-5.5.4}/supabase/functions/README.md +0 -0
  352. {sourcecode-5.5.2 → sourcecode-5.5.4}/supabase/functions/get-license/index.ts +0 -0
  353. {sourcecode-5.5.2 → sourcecode-5.5.4}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
  354. {sourcecode-5.5.2 → sourcecode-5.5.4}/supabase/functions/telemetry/index.ts +0 -0
  355. {sourcecode-5.5.2 → sourcecode-5.5.4}/supabase/sql/license_event_ordering.sql +0 -0
  356. {sourcecode-5.5.2 → sourcecode-5.5.4}/supabase/sql/licensing_schema.sql +0 -0
  357. {sourcecode-5.5.2 → sourcecode-5.5.4}/supabase/sql/telemetry_events.sql +0 -0
@@ -2,6 +2,42 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [5.5.4] — 2026-08-13
6
+
7
+ **Re-audit performance and HTTP contract corrections.**
8
+
9
+ ### Fixed
10
+ - Consolidated repeated XML and configuration traversals in `endpoints`; servlet
11
+ discovery now uses a pruned walk or the inventories already computed by the
12
+ endpoint analysis.
13
+ - Parsed braced Spring `RequestMethod` declarations and expose complete
14
+ `methods` lists while retaining the backwards-compatible primary `method`.
15
+ - Verified that atomic `--output` replacement produced the requested destination
16
+ before recording the run as successful.
17
+
18
+ ### Documentation
19
+ - Documented `ANY` semantics and synchronized the defect ledger, roadmap, and
20
+ atomic audit-fix commits. The reported CLI alias discrepancy was not
21
+ reproducible against the public command signatures.
22
+
23
+ ## [5.5.3] — 2026-08-13
24
+
25
+ **Audit regression fixes and diagnostic output.**
26
+
27
+ ### Fixed
28
+ - Restored bounded default `spring-audit` stdout while preserving complete
29
+ reports through `--output`.
30
+ - Added depth, provenance, unit declarations, and hub-excluded reach to
31
+ `impact` for service-locator architectures.
32
+ - Hardened `web.xml` mapping extraction for legacy descriptors and consecutive
33
+ mappings, without activating commented mappings.
34
+ - Published root timing metadata and reused content-addressed manifest analysis.
35
+ - Made excluded test-source route counts explicit in endpoint output.
36
+
37
+ ### Documentation
38
+ - Updated the roadmap with the 5.5.2 audit follow-up, deduplicated against
39
+ previous defect entries and linked to atomic fix commits.
40
+
5
41
  ## [5.5.2] — 2026-08-13
6
42
 
7
43
  **Follow-up audit corrections and performance visibility.**
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 5.5.2
3
+ Version: 5.5.4
4
4
  Summary: Persistent structural context and ultra-fast repeated analysis for AI coding agents
5
5
  License-File: LICENSE
6
6
  Keywords: agents,ai,codebase,context,developer-tools,llm
@@ -42,7 +42,7 @@ Description-Content-Type: text/markdown
42
42
 
43
43
  **Context · Impact · Migration · Architecture · Review — everything from one structural model.**
44
44
 
45
- ![Version](https://img.shields.io/badge/version-5.5.2-blue)
45
+ ![Version](https://img.shields.io/badge/version-5.5.4-blue)
46
46
  ![Python](https://img.shields.io/badge/python-3.9%2B-green)
47
47
 
48
48
  > **ASK Engine** is the product. The CLI command is **`ask`**. The legacy **`sourcecode`**
@@ -126,7 +126,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
126
126
  # pip / pipx
127
127
  pipx install sourcecode # or: pip install sourcecode
128
128
 
129
- ask version # ask 5.5.2 — and, on a build that has aged,
129
+ ask version # ask 5.5.4 — and, on a build that has aged,
130
130
  # how many releases have probably shipped since
131
131
  ```
132
132
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  **Context · Impact · Migration · Architecture · Review — everything from one structural model.**
6
6
 
7
- ![Version](https://img.shields.io/badge/version-5.5.2-blue)
7
+ ![Version](https://img.shields.io/badge/version-5.5.4-blue)
8
8
  ![Python](https://img.shields.io/badge/python-3.9%2B-green)
9
9
 
10
10
  > **ASK Engine** is the product. The CLI command is **`ask`**. The legacy **`sourcecode`**
@@ -88,7 +88,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
88
88
  # pip / pipx
89
89
  pipx install sourcecode # or: pip install sourcecode
90
90
 
91
- ask version # ask 5.5.2 — and, on a build that has aged,
91
+ ask version # ask 5.5.4 — and, on a build that has aged,
92
92
  # how many releases have probably shipped since
93
93
  ```
94
94
 
@@ -16,6 +16,17 @@ The facts these rows are keyed to are published: `ask schema facts-v1` prints th
16
16
 
17
17
  ---
18
18
 
19
+ ## Audit synchronization
20
+
21
+ | ID | Defect | Found | Severity | Status |
22
+ |---|---|---|---|---|
23
+ | AS-01 | `risk`/`enrich` could omit `sql_taint.bounded_interpolations`, making `sinks_total` impossible to audit against its bounded evidence. | 5.4.2 re-audit | Medium | **closed 5.4.2** — both projections preserve the bounded rows; the paired fixture asserts the sink total and the retained bounded interpolation. |
24
+ | AS-02 | Route projection emitted declarations from abstract Spring controllers, creating phantom routes and inflating the unprotected census. | 5.4.2 re-audit | Low | **closed 5.4.2** — abstract declarers are excluded while concrete subtype projection remains admitted; the route-surface regression covers both sides. |
25
+ | AS-03 | The distributed ledger could leave `C3-123` open after the 5.4.1 build already excluded static assets. | 5.4.2 re-audit | Informational | **closed 5.4.2** — the stale state was synchronized to the wheel it documents. |
26
+ | AS-04 | An unconstrained `@RequestMapping` was described by consumers as GET although Spring admits every verb. | 5.5.1 audit | Medium | **closed 5.5.1** — primary `method` is `ANY`; 5.5.4 adds the concrete `methods` list so consumers do not need to infer its expansion. |
27
+
28
+ ---
29
+
19
30
  ## Class C1 — One fact, two authorities
20
31
 
21
32
  | ID | Defect | Found | Severity | Status |
@@ -136,7 +136,7 @@ pipx install sourcecode # isolated install, no venv needed
136
136
 
137
137
  # Verify
138
138
  ask version
139
- # ask 5.5.2
139
+ # ask 5.5.4
140
140
  ```
141
141
 
142
142
  Requires Python 3.9+.
@@ -261,7 +261,13 @@ ask endpoints /path/to/repo
261
261
  ask endpoints . --format yaml
262
262
  ```
263
263
 
264
- Output: list of `{method, path, controller, handler}`. Covers `@GetMapping`, `@PostMapping`, `@PutMapping`, `@DeleteMapping`, `@PatchMapping`, `@RequestMapping`, `@GET`, `@POST`, `@PUT`, `@DELETE`, `@PATCH` + `@Path`.
264
+ Output: list of `{method, methods, path, controller, handler}`. `method` remains
265
+ the backwards-compatible primary verb; `methods` is the complete declared set.
266
+ An unconstrained `@RequestMapping` reports `method: "ANY"` and
267
+ `methods: ["GET", "POST", "PUT", "DELETE", "PATCH"]`, because it accepts all
268
+ of those verbs rather than defaulting to GET. Covers `@GetMapping`, `@PostMapping`,
269
+ `@PutMapping`, `@DeleteMapping`, `@PatchMapping`, `@RequestMapping`, `@GET`,
270
+ `@POST`, `@PUT`, `@DELETE`, `@PATCH` + `@Path`.
265
271
 
266
272
  Each endpoint carries a `security` policy. Standard annotations (`@PreAuthorize`, `@Secured`, `@RolesAllowed`, …) are recognized automatically; a custom authorization annotation reports `policy: "none_detected"` until declared in a `sourcecode.config.json` at the repo root:
267
273
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "5.5.2"
7
+ version = "5.5.4"
8
8
  description = "Persistent structural context and ultra-fast repeated analysis for AI coding agents"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -4,4 +4,4 @@ ASK Engine is the product. ``ask`` is the canonical CLI command; ``sourcecode``
4
4
  the legacy compatibility alias and the Python/PyPI package name. See
5
5
  docs/PRODUCT_IDENTITY.md (normative)."""
6
6
 
7
- __version__ = "5.5.2"
7
+ __version__ = "5.5.4"
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import contextlib
4
+ import errno
4
5
  import hashlib
5
6
  import json
6
7
  import difflib
@@ -1196,6 +1197,15 @@ def _safe_write_file(path: "Path", content: str) -> None:
1196
1197
  fh.flush()
1197
1198
  os.fsync(fh.fileno())
1198
1199
  tmp.replace(path)
1200
+ # Atomic replacement alone does not prove that the destination is the
1201
+ # requested artifact. Verify the postcondition before reporting a run
1202
+ # output path, especially for non-empty JSON reports.
1203
+ if not path.is_file() or (content and path.stat().st_size == 0):
1204
+ raise OSError(
1205
+ errno.EIO,
1206
+ "atomic output replacement did not produce the requested file",
1207
+ str(path),
1208
+ )
1199
1209
  try:
1200
1210
  dir_fd = os.open(str(path.parent), os.O_RDONLY)
1201
1211
  try:
@@ -9239,7 +9249,17 @@ def spring_audit_cmd(
9239
9249
  elif format == "github-comment":
9240
9250
  output = _render_spring_audit_github_comment(combined, min_severity)
9241
9251
  else:
9242
- data = combined.to_compact_dict() if compact else combined.to_dict()
9252
+ _bounded_default = (
9253
+ not compact and output_path is None and format == "json" and not table
9254
+ )
9255
+ data = (
9256
+ combined.to_compact_dict()
9257
+ if compact or _bounded_default
9258
+ else combined.to_dict()
9259
+ )
9260
+ if _bounded_default:
9261
+ data.pop("mode", None)
9262
+ data["default_output"] = "bounded"
9243
9263
  output = _serialize_dict(data, format)
9244
9264
 
9245
9265
  # F-AV: our own readers ask for the count under either spelling — the break
@@ -23,7 +23,7 @@ from __future__ import annotations
23
23
  import re
24
24
  from dataclasses import dataclass, field
25
25
  from pathlib import Path
26
- from typing import Any, Optional
26
+ from typing import Any, Iterable, Optional
27
27
 
28
28
  # Published Spring Boot property keys (DATA — never a predicate on a repo name).
29
29
  _CONTEXT_PATH_KEYS: tuple[str, ...] = (
@@ -163,25 +163,31 @@ def _profile_of_document(flat: "dict[str, str]", file_profile: Optional[str]) ->
163
163
  return file_profile
164
164
 
165
165
 
166
- def _config_files(root: Path) -> "list[Path]":
166
+ def _config_files(root: Path, files: Optional[Iterable[Path]] = None) -> "list[Path]":
167
167
  """Spring config files under conventional resource directories.
168
168
 
169
169
  Bounded and sorted for determinism; test resources are excluded because a
170
170
  prefix declared for tests is not the deployed one.
171
171
  """
172
+ candidates = files if files is not None else root.rglob("application*.*")
172
173
  found: list[Path] = []
173
- for pattern in ("**/src/main/resources/**/application*.*", "**/config/application*.*"):
174
- for path in root.glob(pattern):
175
- name = path.name
176
- if name in _CONFIG_BASENAMES or _PROFILE_FILE_RE.match(name):
177
- text = str(path).replace("\\", "/")
178
- if "/src/test/" in text or "/target/" in text:
179
- continue
180
- found.append(path)
174
+ for path in candidates:
175
+ path = Path(path)
176
+ name = path.name
177
+ if name not in _CONFIG_BASENAMES and not _PROFILE_FILE_RE.match(name):
178
+ continue
179
+ text = str(path).replace("\\", "/")
180
+ in_resources = "/src/main/resources/" in text
181
+ in_config = "/config/" in text
182
+ if not (in_resources or in_config) or "/src/test/" in text or "/target/" in text:
183
+ continue
184
+ found.append(path)
181
185
  return sorted(set(found))[:60]
182
186
 
183
187
 
184
- def detect_deployment_prefix(root: Path) -> DeploymentPrefix:
188
+ def detect_deployment_prefix(
189
+ root: Path, *, files: Optional[Iterable[Path]] = None
190
+ ) -> DeploymentPrefix:
185
191
  """Read the deployment prefix from the repo's Spring configuration.
186
192
 
187
193
  Best effort and never raises: an unreadable or malformed config yields an
@@ -190,7 +196,7 @@ def detect_deployment_prefix(root: Path) -> DeploymentPrefix:
190
196
  """
191
197
  result = DeploymentPrefix()
192
198
  try:
193
- candidates = _config_files(Path(root))
199
+ candidates = _config_files(Path(root), files)
194
200
  except Exception:
195
201
  return result
196
202
 
@@ -3772,17 +3772,40 @@ def _route_path_expression(args_str: str, constants: "Optional[dict[str, str]]")
3772
3772
  return args_str.strip()
3773
3773
 
3774
3774
 
3775
- def _parse_route_http_method(ann_name: str, args_str: str) -> str:
3776
- """Derive HTTP method from annotation name or explicit method= arg."""
3775
+ _ANY_HTTP_METHODS = ("GET", "POST", "PUT", "DELETE", "PATCH")
3776
+
3777
+
3778
+ def _parse_route_http_methods(ann_name: str, args_str: str) -> tuple[str, ...]:
3779
+ """Derive every declared HTTP method, preserving annotation order."""
3777
3780
  explicit = _HTTP_METHOD_MAP.get(ann_name)
3778
3781
  if explicit:
3779
- return explicit
3780
- m = re.search(r'method\s*=\s*(?:RequestMethod\.)?(\w+)', args_str or "")
3782
+ return (explicit,)
3783
+ # Spring accepts both `method=RequestMethod.GET` and the array spelling
3784
+ # `method={RequestMethod.GET, RequestMethod.POST}`. The old expression
3785
+ # expected the token immediately after `=`, so the braces form fell through
3786
+ # to ANY and overstated the reachable verb surface.
3787
+ m = re.search(
3788
+ r'\bmethod\s*=\s*\{?\s*((?:RequestMethod\.)?\w+(?:\s*,\s*(?:RequestMethod\.)?\w+)*)',
3789
+ args_str or "",
3790
+ )
3781
3791
  if m:
3782
- return m.group(1).upper()
3792
+ methods = re.findall(r'(?:RequestMethod\.)?(\w+)', m.group(1))
3793
+ if methods:
3794
+ return tuple(dict.fromkeys(method.upper() for method in methods))
3783
3795
  if ann_name == "@RequestMapping":
3784
- return "ANY"
3785
- return ""
3796
+ return ("ANY",)
3797
+ return ()
3798
+
3799
+
3800
+ def _parse_route_http_method(ann_name: str, args_str: str) -> str:
3801
+ """Backward-compatible primary HTTP method for a route."""
3802
+ methods = _parse_route_http_methods(ann_name, args_str)
3803
+ return methods[0] if methods else ""
3804
+
3805
+
3806
+ def _published_http_methods(method: str) -> list[str]:
3807
+ """Concrete verbs a consumer must consider for a route's method label."""
3808
+ return list(_ANY_HTTP_METHODS if method == "ANY" else (method,))
3786
3809
 
3787
3810
 
3788
3811
  def _parse_route_extras(args_str: str) -> dict:
@@ -5014,7 +5037,8 @@ def _build_route_surface(
5014
5037
  _suffix_expr = _route_path_expression(args, constants)
5015
5038
  effective_prefixes = class_info.get(cls_simple, {}).get("prefixes", [""])
5016
5039
 
5017
- method = _parse_route_http_method(ann_name, args) or "GET"
5040
+ route_methods = _parse_route_http_methods(ann_name, args) or ("GET",)
5041
+ method = route_methods[0]
5018
5042
 
5019
5043
  if cls_simple in class_info:
5020
5044
  class_info[cls_simple]["own_endpoints"].append(
@@ -5070,6 +5094,7 @@ def _build_route_surface(
5070
5094
  "effective_class": cls_fqn,
5071
5095
  "path": full_path,
5072
5096
  "method": method,
5097
+ "methods": _published_http_methods(method) if method == "ANY" else list(route_methods),
5073
5098
  "return_type": (sym.return_type.strip() if sym.return_type else "void"),
5074
5099
  "stable_id": sym.stable_id,
5075
5100
  "inheritance_depth": 0,
@@ -5175,6 +5200,7 @@ def _build_route_surface(
5175
5200
  "effective_class": data["fqn"],
5176
5201
  "path": full_path,
5177
5202
  "method": verb,
5203
+ "methods": _published_http_methods(verb),
5178
5204
  "return_type": _parent_rt_by_sym.get(declaring_sym, "void"),
5179
5205
  "stable_id": stable_id,
5180
5206
  "inheritance_depth": depth,
@@ -6415,6 +6441,27 @@ def extract_java_endpoints(
6415
6441
  and "target/" not in str(p).replace("\\", "/")
6416
6442
  and not any(f in str(p).replace("\\", "/") for f in _CLIENT_PATH_FRAGMENTS)
6417
6443
  )
6444
+ # `endpoints` needs XML both for Spring Security and WebScript detection.
6445
+ # One inventory avoids seven name-specific walks plus a later desc.xml walk.
6446
+ _xml_files = sorted(root.rglob("*.xml"))
6447
+ # Deployment-prefix resolution formerly ran two independent `root.glob()`
6448
+ # calls. One candidate list keeps that work bounded and reusable below.
6449
+ _config_files = sorted(root.rglob("application*.*"))
6450
+ _excluded_test_source_routes = 0
6451
+ if not include_tests:
6452
+ _route_marker = _re.compile(
6453
+ r"@(GetMapping|PostMapping|PutMapping|DeleteMapping|PatchMapping|RequestMapping|GET|POST|PUT|DELETE|PATCH|Path)\b"
6454
+ )
6455
+ for _candidate in root.rglob("*.java"):
6456
+ _candidate_rel = _rel(_candidate)
6457
+ if not is_test_source_file(_candidate_rel):
6458
+ continue
6459
+ try:
6460
+ _excluded_test_source_routes += len(
6461
+ _route_marker.findall(_candidate.read_text(encoding="utf-8", errors="replace"))
6462
+ )
6463
+ except OSError:
6464
+ continue
6418
6465
 
6419
6466
  all_symbols: list[SymbolRecord] = []
6420
6467
  extends_map: dict[str, str] = {}
@@ -6620,6 +6667,7 @@ def extract_java_endpoints(
6620
6667
 
6621
6668
  entry: dict = {
6622
6669
  "method": route["method"],
6670
+ "methods": route.get("methods", _published_http_methods(route["method"])),
6623
6671
  "path": route["path"],
6624
6672
  "controller": controller,
6625
6673
  # Two controllers can share a simple name across packages: keycloak
@@ -6776,23 +6824,23 @@ def extract_java_endpoints(
6776
6824
  re.IGNORECASE,
6777
6825
  )
6778
6826
  _xml_security_detected = False
6779
- _XML_GLOBS = (
6780
- "*security*.xml", "*Security*.xml",
6781
- "*applicationContext*.xml", "*-context.xml", "*Context.xml",
6782
- "*spring*.xml", "*Spring*.xml",
6783
- )
6784
- for _glob in _XML_GLOBS:
6785
- for _xf in root.rglob(_glob):
6786
- if "target/" in str(_xf).replace("\\", "/"):
6787
- continue
6788
- try:
6789
- _xt = _xf.read_text(encoding="utf-8", errors="replace")
6790
- except OSError:
6791
- continue
6792
- if _XML_SECURITY_RE.search(_xt):
6793
- _xml_security_detected = True
6794
- break
6795
- if _xml_security_detected:
6827
+ for _xf in _xml_files:
6828
+ _xml_name = _xf.name.lower()
6829
+ if not (
6830
+ "security" in _xml_name
6831
+ or "spring" in _xml_name
6832
+ or _xml_name.endswith("-context.xml")
6833
+ or _xml_name.endswith("context.xml")
6834
+ ):
6835
+ continue
6836
+ if "target/" in str(_xf).replace("\\", "/"):
6837
+ continue
6838
+ try:
6839
+ _xt = _xf.read_text(encoding="utf-8", errors="replace")
6840
+ except OSError:
6841
+ continue
6842
+ if _XML_SECURITY_RE.search(_xt):
6843
+ _xml_security_detected = True
6796
6844
  break
6797
6845
 
6798
6846
  if _xml_security_detected:
@@ -6892,7 +6940,7 @@ def extract_java_endpoints(
6892
6940
  try:
6893
6941
  from sourcecode.deployment_prefix import detect_deployment_prefix
6894
6942
 
6895
- _prefix = detect_deployment_prefix(root)
6943
+ _prefix = detect_deployment_prefix(root, files=_config_files)
6896
6944
  if _prefix.sources:
6897
6945
  result["deployment_prefix"] = _prefix.to_dict()
6898
6946
  if _prefix.prefix:
@@ -6912,6 +6960,12 @@ def extract_java_endpoints(
6912
6960
  )
6913
6961
  elif _test_util_endpoints:
6914
6962
  result["test_util_included"] = len(_test_util_endpoints)
6963
+ if _excluded_test_source_routes:
6964
+ result["test_source_excluded"] = _excluded_test_source_routes
6965
+ result.setdefault("notes", []).append(
6966
+ f"{_excluded_test_source_routes} route annotation(s) from test source trees "
6967
+ "were excluded; use --include-tests to include them."
6968
+ )
6915
6969
  # Surface incomplete-endpoint warnings (interface-defined controllers) only when
6916
6970
  # present, to keep output backward-compatible for the common case.
6917
6971
  if endpoint_warnings:
@@ -6949,7 +7003,9 @@ def extract_java_endpoints(
6949
7003
  # (*.desc.xml: <url>/<authentication>/<transaction>) in addition to the Java
6950
7004
  # signals gathered above.
6951
7005
  _webscript_descriptors = 0
6952
- for _df in root.rglob("*.desc.xml"):
7006
+ for _df in _xml_files:
7007
+ if not _df.name.endswith(".desc.xml"):
7008
+ continue
6953
7009
  if "target/" in str(_df).replace("\\", "/"):
6954
7010
  continue
6955
7011
  try:
@@ -6977,7 +7033,7 @@ def extract_java_endpoints(
6977
7033
  from sourcecode.servlet_surface import build_servlet_surface
6978
7034
 
6979
7035
  _nonspring["servlets"] = int(
6980
- build_servlet_surface(root).get("declarations", 0)
7036
+ build_servlet_surface(root, files=[*java_files, *_xml_files]).get("declarations", 0)
6981
7037
  )
6982
7038
  except Exception:
6983
7039
  pass
@@ -7853,6 +7909,10 @@ def compute_blast_radius(
7853
7909
  _indirect_summary = (
7854
7910
  _indirect_ordered if _indirect_cap is None else _indirect_ordered[:_indirect_cap]
7855
7911
  )
7912
+ _indirect_by_depth: dict[str, int] = {}
7913
+ for _node in indirect_callers:
7914
+ _depth_key = str(all_affected.get(_node, 0))
7915
+ _indirect_by_depth[_depth_key] = _indirect_by_depth.get(_depth_key, 0) + 1
7856
7916
  def _via_hub(_node: str) -> bool:
7857
7917
  _seen_path: set[str] = set()
7858
7918
  _cursor = _node
@@ -7914,6 +7974,9 @@ def compute_blast_radius(
7914
7974
  ),
7915
7975
  "indirect_callers": _indirect_summary,
7916
7976
  "indirect_caller_details": _indirect_details,
7977
+ "indirect_callers_unit": "reference symbols (methods or classes)",
7978
+ "indirect_callers_by_depth": _indirect_by_depth,
7979
+ "indirect_callers_without_hubs": _without_hubs,
7917
7980
  "container_wired": [w.to_dict() for w in _container_wired],
7918
7981
  "endpoints_affected": endpoints_affected,
7919
7982
  "mappers_affected": mappers_affected,
@@ -20,10 +20,11 @@ So the answer is a second, named population beside the first, with its own total
20
20
 
21
21
  from __future__ import annotations
22
22
 
23
+ import os
23
24
  import re
24
25
  from dataclasses import dataclass
25
26
  from pathlib import Path
26
- from typing import Optional
27
+ from typing import Iterable, Optional
27
28
  from xml.etree import ElementTree as ET
28
29
 
29
30
  POPULATION = "servlet"
@@ -84,7 +85,8 @@ def _child_text(elem: "ET.Element", name: str) -> str:
84
85
 
85
86
  def _from_web_xml(xml_path: Path, relative: str) -> "list[ServletMapping]":
86
87
  try:
87
- root = ET.parse(str(xml_path)).getroot()
88
+ text = xml_path.read_text(encoding="utf-8", errors="replace")
89
+ root = ET.fromstring(text)
88
90
  except Exception:
89
91
  return []
90
92
  classes: "dict[str, str]" = {}
@@ -110,6 +112,27 @@ def _from_web_xml(xml_path: Path, relative: str) -> "list[ServletMapping]":
110
112
  source_file=relative,
111
113
  source="web.xml",
112
114
  ))
115
+ # Keep a tolerant lexical fallback for descriptors containing legacy XML
116
+ # constructs that ElementTree rejects or partially normalizes. Comments are
117
+ # removed first so commented deployment examples never become live routes.
118
+ try:
119
+ active = re.sub(r"<!--.*?-->", "", text, flags=re.DOTALL)
120
+ for block in re.findall(r"<servlet-mapping\b[^>]*>(.*?)</servlet-mapping>", active, re.DOTALL | re.IGNORECASE):
121
+ name_match = re.search(r"<servlet-name\b[^>]*>\s*([^<]+?)\s*</servlet-name>", block, re.DOTALL | re.IGNORECASE)
122
+ pattern_match = re.search(r"<url-pattern\b[^>]*>\s*([^<]+?)\s*</url-pattern>", block, re.DOTALL | re.IGNORECASE)
123
+ if not pattern_match:
124
+ continue
125
+ candidate = ServletMapping(
126
+ url_pattern=pattern_match.group(1).strip(),
127
+ servlet_name=name_match.group(1).strip() if name_match else "",
128
+ servlet_class=classes.get(name_match.group(1).strip(), "") if name_match else "",
129
+ source_file=relative,
130
+ source="web.xml",
131
+ )
132
+ if candidate not in out:
133
+ out.append(candidate)
134
+ except Exception:
135
+ pass
113
136
  return out
114
137
 
115
138
 
@@ -144,14 +167,36 @@ def _from_registration_beans(java_path: Path, relative: str) -> "list[ServletMap
144
167
  return out
145
168
 
146
169
 
147
- def build_servlet_surface(root: Path, *, limit: Optional[int] = None) -> dict:
170
+ def build_servlet_surface(
171
+ root: Path,
172
+ *,
173
+ limit: Optional[int] = None,
174
+ files: Optional[Iterable[Path]] = None,
175
+ ) -> dict:
148
176
  """Every servlet-mapped URL pattern under `root`, as a population of its own."""
149
177
  from sourcecode import non_coverage
150
178
 
151
179
  root = Path(root)
152
180
  mappings: "list[ServletMapping]" = []
153
- for path in sorted(root.rglob("*")):
154
- if any(part in _SKIP_DIRS for part in path.parts) or not path.is_file():
181
+ if files is None:
182
+ candidates: list[Path] = []
183
+ for directory, dirs, names in os.walk(root):
184
+ dirs[:] = sorted(name for name in dirs if name not in _SKIP_DIRS)
185
+ candidates.extend(
186
+ Path(directory) / name
187
+ for name in sorted(names)
188
+ if name == "web.xml" or name.endswith(".java")
189
+ )
190
+ else:
191
+ candidates = sorted(
192
+ {
193
+ Path(path)
194
+ for path in files
195
+ if Path(path).name == "web.xml" or Path(path).suffix == ".java"
196
+ }
197
+ )
198
+ for path in candidates:
199
+ if not path.is_file():
155
200
  continue
156
201
  try:
157
202
  # POSIX, like every other path this CLI publishes. C2-18 fixed this
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes