sourcecode 5.8.17__tar.gz → 5.8.18__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.

Potentially problematic release.


This version of sourcecode might be problematic. Click here for more details.

Files changed (388) hide show
  1. {sourcecode-5.8.17 → sourcecode-5.8.18}/CHANGELOG.md +19 -0
  2. {sourcecode-5.8.17 → sourcecode-5.8.18}/PKG-INFO +4 -4
  3. {sourcecode-5.8.17 → sourcecode-5.8.18}/README.md +3 -3
  4. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/DEFECT-LEDGER.md +140 -10
  5. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/DEVELOPMENT-ROADMAP.md +102 -50
  6. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/EXECUTIVE-ROADMAP.md +84 -42
  7. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/MANUAL-USUARIO.md +1 -1
  8. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/USER_GUIDE.md +7 -7
  9. {sourcecode-5.8.17 → sourcecode-5.8.18}/pyproject.toml +1 -1
  10. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/__init__.py +1 -1
  11. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/caller_metrics.py +45 -3
  12. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/cli.py +59 -14
  13. sourcecode-5.8.18/src/sourcecode/product_info.py +44 -0
  14. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/repository_ir.py +30 -0
  15. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/sarif.py +2 -0
  16. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/spring_impact.py +20 -0
  17. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/summarizer.py +58 -4
  18. sourcecode-5.8.17/src/sourcecode/product_info.py +0 -22
  19. {sourcecode-5.8.17 → sourcecode-5.8.18}/.github/workflows/build-windows.yml +0 -0
  20. {sourcecode-5.8.17 → sourcecode-5.8.18}/.github/workflows/perf-gate.yml +0 -0
  21. {sourcecode-5.8.17 → sourcecode-5.8.18}/.gitignore +0 -0
  22. {sourcecode-5.8.17 → sourcecode-5.8.18}/.ruff.toml +0 -0
  23. {sourcecode-5.8.17 → sourcecode-5.8.18}/CLAUDE.md +0 -0
  24. {sourcecode-5.8.17 → sourcecode-5.8.18}/CONTRIBUTING.md +0 -0
  25. {sourcecode-5.8.17 → sourcecode-5.8.18}/LICENSE +0 -0
  26. {sourcecode-5.8.17 → sourcecode-5.8.18}/NOTICE +0 -0
  27. {sourcecode-5.8.17 → sourcecode-5.8.18}/SECURITY.md +0 -0
  28. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/CACHE.md +0 -0
  29. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/COMMERCIAL-OFFER.md +0 -0
  30. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/CUSTOMER-VALIDATION.md +0 -0
  31. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/DEMO-5MIN.md +0 -0
  32. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/EXECUTION-PLAN-12MO.md +0 -0
  33. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/MODERNIZATION.md +0 -0
  34. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/PRODUCT_AUDIT.md +0 -0
  35. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/PRODUCT_IDENTITY.md +0 -0
  36. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/PRODUCT_TIERS.md +0 -0
  37. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/RC1-CHECKLIST.md +0 -0
  38. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/RELEASE-CHECKLIST.md +0 -0
  39. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/CATALOG-retrieval-intents.md +0 -0
  40. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/DESIGN-knowledge-provider-integration.md +0 -0
  41. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/DESIGN-p5.3b-statement-surface.md +0 -0
  42. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/DESIGN-p5.5-span-index.md +0 -0
  43. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/DESIGN-p6-semantic-impact-engine.md +0 -0
  44. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/DESIGN-p6-semantic-integration-engine.md +0 -0
  45. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/DESIGN-p7-semantic-services.md +0 -0
  46. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/DESIGN-robustness-security-inference.md +0 -0
  47. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/DESIGN-semantic-retrieval.md +0 -0
  48. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/EPV-p6-class-typeref.md +0 -0
  49. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/REPORT-p6-flow-analyzer-comparison.md +0 -0
  50. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/REPORT-p6-integration-detector-comparison.md +0 -0
  51. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/REPORT-p8-flow-analyzer-migration.md +0 -0
  52. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/REPORT-p9-integration-detector-migration.md +0 -0
  53. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/adr/0001-semantic-ir.md +0 -0
  54. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/adr/0002-source-evidence-boundary.md +0 -0
  55. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/adr/0003-architectural-characterization.md +0 -0
  56. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/adr/0004-semantic-retrieval.md +0 -0
  57. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/adr/0005-evidence-reconciliation.md +0 -0
  58. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/adr/0006-performance-harness.md +0 -0
  59. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/adr/0007-composition-semantics.md +0 -0
  60. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/adr/0008-answer-coherence.md +0 -0
  61. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/consumer-disposition-inventory.md +0 -0
  62. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/overview.md +0 -0
  63. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/product-architecture-review.md +0 -0
  64. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/product-strategy-layering.md +0 -0
  65. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/semantic-ir-consumer-matrix.md +0 -0
  66. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/architecture/semantic-ir-roadmap.md +0 -0
  67. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/baseline-ci.yml +0 -0
  68. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/commercial-pipeline-audit.md +0 -0
  69. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/contracts-ci.yml +0 -0
  70. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/contracts.md +0 -0
  71. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/eval/2026-06-15-petclinic-rest-issue11-vets-pagination.md +0 -0
  72. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/eval/2026-06-15-petclinic-rest-issue147-validation.md +0 -0
  73. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/eval/2026-06-15-petclinic-rest-workflow.md +0 -0
  74. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/eval/2026-06-15-phase18-openapi-surface.md +0 -0
  75. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/eval/2026-06-15-phase20-validation-surface.md +0 -0
  76. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/eval/2026-06-16-broadleaf-checkout-impact-fieldtest.md +0 -0
  77. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/eval/2026-06-16-petclinic-rest-issue11-weakness2-closed.md +0 -0
  78. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/eval/2026-06-16-spring-petclinic-issue2333-dead-vets.md +0 -0
  79. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/licensing-schema.md +0 -0
  80. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/migrate-check.md +0 -0
  81. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/README.md +0 -0
  82. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/REGRESSION-GATE.md +0 -0
  83. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/SUMMARY.md +0 -0
  84. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/alfresco__ask__cold.json +0 -0
  85. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/alfresco__ask__warm.json +0 -0
  86. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/broadleaf__ask__cold.json +0 -0
  87. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/broadleaf__ask__warm.json +0 -0
  88. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/eureka__ask__cold.json +0 -0
  89. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/eureka__ask__warm.json +0 -0
  90. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/jenkins__ask__cold.json +0 -0
  91. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/jenkins__ask__warm.json +0 -0
  92. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/jobrunr__ask__cold.json +0 -0
  93. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/jobrunr__ask__warm.json +0 -0
  94. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/keycloak__ask__cold.json +0 -0
  95. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/keycloak__ask__warm.json +0 -0
  96. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/neo4j__ask__cold.json +0 -0
  97. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/neo4j__ask__warm.json +0 -0
  98. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/ofbiz__ask__cold.json +0 -0
  99. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/ofbiz__ask__warm.json +0 -0
  100. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/openmrs__ask__cold.json +0 -0
  101. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/openmrs__ask__warm.json +0 -0
  102. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/petclinic__ask__cold.json +0 -0
  103. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.15/petclinic__ask__warm.json +0 -0
  104. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/SUMMARY.md +0 -0
  105. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/alfresco__ask__cold.json +0 -0
  106. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/alfresco__ask__warm.json +0 -0
  107. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/broadleaf__ask__cold.json +0 -0
  108. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/broadleaf__ask__warm.json +0 -0
  109. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/eureka__ask__cold.json +0 -0
  110. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/eureka__ask__warm.json +0 -0
  111. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/jenkins__ask__cold.json +0 -0
  112. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/jenkins__ask__warm.json +0 -0
  113. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/jobrunr__ask__cold.json +0 -0
  114. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/jobrunr__ask__warm.json +0 -0
  115. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/keycloak__ask__cold.json +0 -0
  116. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/keycloak__ask__warm.json +0 -0
  117. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/neo4j__ask__cold.json +0 -0
  118. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/neo4j__ask__warm.json +0 -0
  119. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/ofbiz__ask__cold.json +0 -0
  120. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/ofbiz__ask__warm.json +0 -0
  121. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/openmrs__ask__cold.json +0 -0
  122. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/openmrs__ask__warm.json +0 -0
  123. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/petclinic__ask__cold.json +0 -0
  124. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/2.5.16/petclinic__ask__warm.json +0 -0
  125. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/gate-latest/README.md +0 -0
  126. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/gate-latest/broadleaf__ask__warm.json +0 -0
  127. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/gate-latest/broadleaf__endpoints__warm.json +0 -0
  128. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/gate-latest/broadleaf__migrate-check__warm.json +0 -0
  129. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/gate-latest/broadleaf__posture__warm.json +0 -0
  130. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/gate-latest/broadleaf__spring-audit__warm.json +0 -0
  131. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/gate-latest/broadleaf__validation__warm.json +0 -0
  132. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/perf/baselines/reference-best/README.md +0 -0
  133. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/posture.md +0 -0
  134. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/privacy.md +0 -0
  135. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/pro-experience-audit.md +0 -0
  136. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/schema.md +0 -0
  137. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/spec/envelope-v1.md +0 -0
  138. {sourcecode-5.8.17 → sourcecode-5.8.18}/docs/spring-audit-ci.yml +0 -0
  139. {sourcecode-5.8.17 → sourcecode-5.8.18}/scripts/compare_integration_engines.py +0 -0
  140. {sourcecode-5.8.17 → sourcecode-5.8.18}/scripts/customer_smoke_test.sh +0 -0
  141. {sourcecode-5.8.17 → sourcecode-5.8.18}/scripts/generate_jdk_exports.py +0 -0
  142. {sourcecode-5.8.17 → sourcecode-5.8.18}/scripts/perf_gate.py +0 -0
  143. {sourcecode-5.8.17 → sourcecode-5.8.18}/scripts/perf_harness.py +0 -0
  144. {sourcecode-5.8.17 → sourcecode-5.8.18}/scripts/sync_gate_anchors.py +0 -0
  145. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/adaptive_scanner.py +0 -0
  146. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/answer_bounds.py +0 -0
  147. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/archetype.py +0 -0
  148. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/architectural_baseline.py +0 -0
  149. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/architectural_delta.py +0 -0
  150. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/architecture_analyzer.py +0 -0
  151. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/architecture_summary.py +0 -0
  152. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/ast_extractor.py +0 -0
  153. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/audit_clusters.py +0 -0
  154. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/audit_recipe.py +0 -0
  155. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/audit_report.py +0 -0
  156. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/audit_since.py +0 -0
  157. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/baseline_autocapture.py +0 -0
  158. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/breaking_changes.py +0 -0
  159. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/build_modules.py +0 -0
  160. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/bundled_docs.py +0 -0
  161. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/cache.py +0 -0
  162. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/cache_model.py +0 -0
  163. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/call_surface.py +0 -0
  164. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/caller_reach.py +0 -0
  165. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/canonical_ir.py +0 -0
  166. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/chain_rules.py +0 -0
  167. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/change_plan.py +0 -0
  168. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/ci_output.py +0 -0
  169. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/cir_graphs.py +0 -0
  170. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/classifier.py +0 -0
  171. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/client_calls.py +0 -0
  172. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/code_notes_analyzer.py +0 -0
  173. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/compare.py +0 -0
  174. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/confidence_analyzer.py +0 -0
  175. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/constraint_diff.py +0 -0
  176. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/consumer_join.py +0 -0
  177. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/container_wiring.py +0 -0
  178. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/context_cache.py +0 -0
  179. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/context_graph.py +0 -0
  180. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/context_scorer.py +0 -0
  181. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/context_summarizer.py +0 -0
  182. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/contract_diff.py +0 -0
  183. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/contract_init.py +0 -0
  184. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/contract_model.py +0 -0
  185. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/contract_pipeline.py +0 -0
  186. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/coverage_parser.py +0 -0
  187. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/data_exposure.py +0 -0
  188. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/data_labels.py +0 -0
  189. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/declarations.py +0 -0
  190. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/defect_identity.py +0 -0
  191. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/degradation.py +0 -0
  192. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/dependency_analyzer.py +0 -0
  193. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/deployment_prefix.py +0 -0
  194. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detach.py +0 -0
  195. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/__init__.py +0 -0
  196. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/base.py +0 -0
  197. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/csproj_parser.py +0 -0
  198. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/dart.py +0 -0
  199. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/dotnet.py +0 -0
  200. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/elixir.py +0 -0
  201. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/go.py +0 -0
  202. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/heuristic.py +0 -0
  203. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/hybrid.py +0 -0
  204. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/java.py +0 -0
  205. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/jvm_ext.py +0 -0
  206. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/nodejs.py +0 -0
  207. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/parsers.py +0 -0
  208. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/php.py +0 -0
  209. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/project.py +0 -0
  210. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/python.py +0 -0
  211. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/ruby.py +0 -0
  212. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/rust.py +0 -0
  213. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/systems.py +0 -0
  214. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/terraform.py +0 -0
  215. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/detectors/tooling.py +0 -0
  216. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/doc_analyzer.py +0 -0
  217. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/dynamic_argument_surface.py +0 -0
  218. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/empty_reach.py +0 -0
  219. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/endpoint_disposition.py +0 -0
  220. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/endpoint_literals.py +0 -0
  221. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/endpoint_metrics.py +0 -0
  222. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/entrypoint_classifier.py +0 -0
  223. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/env_analyzer.py +0 -0
  224. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/envelope.py +0 -0
  225. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/environment_resolution.py +0 -0
  226. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/error_schema.py +0 -0
  227. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/evidence_provider.py +0 -0
  228. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/execution_plan.py +0 -0
  229. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/explain.py +0 -0
  230. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/explain_endpoint.py +0 -0
  231. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/facts/__init__.py +0 -0
  232. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/facts/registry.json +0 -0
  233. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/field_deprecations.py +0 -0
  234. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/file_chunker.py +0 -0
  235. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/file_classifier.py +0 -0
  236. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/filter_surface.py +0 -0
  237. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/format_contract.py +0 -0
  238. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/fqn_utils.py +0 -0
  239. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/functional_routes.py +0 -0
  240. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/gate_anchors.py +0 -0
  241. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/git_analyzer.py +0 -0
  242. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/git_checkout.py +0 -0
  243. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/github_diff.py +0 -0
  244. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/graph_analyzer.py +0 -0
  245. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/graph_evidence.py +0 -0
  246. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/hibernate_strat.py +0 -0
  247. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/identity_fallback.py +0 -0
  248. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/integration_coordinates.py +0 -0
  249. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/jdk_exports.py +0 -0
  250. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/license.py +0 -0
  251. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/manifest_cache.py +0 -0
  252. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/mcp/__init__.py +0 -0
  253. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/mcp/dependency_import.py +0 -0
  254. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
  255. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/mcp/onboarding/applier.py +0 -0
  256. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/mcp/onboarding/backup.py +0 -0
  257. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/mcp/onboarding/detector.py +0 -0
  258. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/mcp/onboarding/planner.py +0 -0
  259. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/mcp/orchestrator.py +0 -0
  260. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/mcp/registry.py +0 -0
  261. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/mcp/runner.py +0 -0
  262. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/mcp/server.py +0 -0
  263. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/mcp_nudge.py +0 -0
  264. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/metrics_analyzer.py +0 -0
  265. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/migrate_check.py +0 -0
  266. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/migration_apply.py +0 -0
  267. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/migration_blast.py +0 -0
  268. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/non_coverage.py +0 -0
  269. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/openapi_surface.py +0 -0
  270. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/openrewrite_recipe.py +0 -0
  271. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/output_bounds.py +0 -0
  272. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/output_budget.py +0 -0
  273. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/output_ceiling.py +0 -0
  274. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/output_encoding.py +0 -0
  275. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/output_sink.py +0 -0
  276. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/parallel.py +0 -0
  277. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/parse_cache.py +0 -0
  278. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/partial_contract.py +0 -0
  279. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/path_admission.py +0 -0
  280. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/path_filters.py +0 -0
  281. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/perf.py +0 -0
  282. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/phased_run.py +0 -0
  283. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/pipe_contract.py +0 -0
  284. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/posture.py +0 -0
  285. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/pr_comment_renderer.py +0 -0
  286. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/pr_impact.py +0 -0
  287. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/prepare_context.py +0 -0
  288. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/progress.py +0 -0
  289. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/provenance.py +0 -0
  290. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/ranking_engine.py +0 -0
  291. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/readiness_timeline.py +0 -0
  292. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/readonly.py +0 -0
  293. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/reconciliation.py +0 -0
  294. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/redactor.py +0 -0
  295. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/reference_facts.py +0 -0
  296. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/regress.py +0 -0
  297. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/release_info.py +0 -0
  298. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/relevance_scorer.py +0 -0
  299. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/remediation_diff.py +0 -0
  300. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/remedies.py +0 -0
  301. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/rename_refactor.py +0 -0
  302. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/repo_classifier.py +0 -0
  303. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/retrieval/__init__.py +0 -0
  304. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/retrieval/context.py +0 -0
  305. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/retrieval/errors.py +0 -0
  306. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/retrieval/executor.py +0 -0
  307. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/retrieval/planner.py +0 -0
  308. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/retrieval/query.py +0 -0
  309. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/retrieval/request.py +0 -0
  310. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/retrieval/resolution.py +0 -0
  311. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/retrieval/result.py +0 -0
  312. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/retrieval/retriever.py +0 -0
  313. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/retrieval/runtime.py +0 -0
  314. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/retrieval/steps.py +0 -0
  315. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/retrieval/steps_endpoint.py +0 -0
  316. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/retrieval/steps_graph.py +0 -0
  317. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/retrieval/steps_impact.py +0 -0
  318. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/retrieval/steps_intf.py +0 -0
  319. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/retrieval/steps_struct.py +0 -0
  320. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/retrieval/steps_txsec.py +0 -0
  321. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/ris.py +0 -0
  322. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/risk.py +0 -0
  323. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/risk_model.py +0 -0
  324. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/rule_catalog.py +0 -0
  325. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/rule_pass.py +0 -0
  326. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/runs.py +0 -0
  327. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/runtime_classifier.py +0 -0
  328. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/scanner.py +0 -0
  329. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/schema.py +0 -0
  330. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/schema_producers.py +0 -0
  331. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/schema_registry.py +0 -0
  332. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/schemas/core-analysis-v1.schema.json +0 -0
  333. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/schemas/endpoints-v1.schema.json +0 -0
  334. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/schemas/envelope-v1.schema.json +0 -0
  335. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/schemas/pr-impact-v1.schema.json +0 -0
  336. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/schemas/verify-edit-v1.schema.json +0 -0
  337. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/schemas/verify-v1.schema.json +0 -0
  338. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/security_chain.py +0 -0
  339. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/security_config.py +0 -0
  340. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/security_config_scan.py +0 -0
  341. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/security_posture.py +0 -0
  342. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/selftest.py +0 -0
  343. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/semantic_analyzer.py +0 -0
  344. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/semantic_impact_engine.py +0 -0
  345. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/semantic_integration_engine.py +0 -0
  346. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/semantic_services.py +0 -0
  347. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/serializer.py +0 -0
  348. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/servlet_surface.py +0 -0
  349. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/source_text.py +0 -0
  350. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/spring_event_topology.py +0 -0
  351. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/spring_findings.py +0 -0
  352. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/spring_model.py +0 -0
  353. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/spring_profiles.py +0 -0
  354. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/spring_properties.py +0 -0
  355. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/spring_security_audit.py +0 -0
  356. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/spring_semantic.py +0 -0
  357. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/spring_tx_analyzer.py +0 -0
  358. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/sql_taint.py +0 -0
  359. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/target_admission.py +0 -0
  360. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/telemetry/__init__.py +0 -0
  361. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/telemetry/config.py +0 -0
  362. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/telemetry/consent.py +0 -0
  363. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/telemetry/events.py +0 -0
  364. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/telemetry/filters.py +0 -0
  365. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/telemetry/transport.py +0 -0
  366. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/test_gap_ranking.py +0 -0
  367. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/test_sources.py +0 -0
  368. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/text_input.py +0 -0
  369. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/timeline.py +0 -0
  370. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/timeline_cache.py +0 -0
  371. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/token_estimate.py +0 -0
  372. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/tree_utils.py +0 -0
  373. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/type_usage_surface.py +0 -0
  374. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/validation_inference.py +0 -0
  375. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/validation_surface.py +0 -0
  376. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/verify_edit.py +0 -0
  377. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/verify_repo.py +0 -0
  378. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/verify_rules.py +0 -0
  379. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/version_check.py +0 -0
  380. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/waivers.py +0 -0
  381. {sourcecode-5.8.17 → sourcecode-5.8.18}/src/sourcecode/workspace.py +0 -0
  382. {sourcecode-5.8.17 → sourcecode-5.8.18}/supabase/functions/README.md +0 -0
  383. {sourcecode-5.8.17 → sourcecode-5.8.18}/supabase/functions/get-license/index.ts +0 -0
  384. {sourcecode-5.8.17 → sourcecode-5.8.18}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
  385. {sourcecode-5.8.17 → sourcecode-5.8.18}/supabase/functions/telemetry/index.ts +0 -0
  386. {sourcecode-5.8.17 → sourcecode-5.8.18}/supabase/sql/license_event_ordering.sql +0 -0
  387. {sourcecode-5.8.17 → sourcecode-5.8.18}/supabase/sql/licensing_schema.sql +0 -0
  388. {sourcecode-5.8.17 → sourcecode-5.8.18}/supabase/sql/telemetry_events.sql +0 -0
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## [5.8.18] — 2026-08-21
4
+
5
+ *The eighth audit pass is closed. Every reported fix in that queue is shipped in
6
+ an atomic commit with a focused regression assertion; the release battery passes
7
+ except for the pre-existing RIS B11 test failure documented in the release check.*
8
+
9
+ ### Eighth audit pass closure
10
+
11
+ - Fixed caller-count authority drift, compact unresolved samples, scan-truncation
12
+ disclosure, and the meta-annotation route prefix. (`AUD-593-N01`, `AUD-592-B01`,
13
+ `AUD-592-A02`, `E-38`)
14
+ - Reconciled the compact budget across help and documentation, and corrected the
15
+ budget scope, interface-count metadata, and caller-list cap disclosures.
16
+ (`AUD-593-N02`, `AUD-593-N03`, `AUD-593-N05`, `AUD-593-N06`)
17
+ - Corrected write-inventory wording, min-band filter disclosure, unknown enrich
18
+ rule handling, and build-commit provenance. (`AUD-592-D01`–`D04`)
19
+ - Isolated the compact-cache test so the CLI regression battery is deterministic.
20
+ (`B29`)
21
+
3
22
  ## [5.8.17] — 2026-08-21
4
23
 
5
24
  *The seventh audit pass, closed end to end: eleven rows from P0 to P3 plus the
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 5.8.17
3
+ Version: 5.8.18
4
4
  Summary: Persistent structural context and ultra-fast repeated analysis for AI coding agents
5
5
  Project-URL: Homepage, https://github.com/HarounDominique/sourcecode
6
6
  Project-URL: Repository, https://github.com/HarounDominique/sourcecode
@@ -55,7 +55,7 @@ Description-Content-Type: text/markdown
55
55
  > question. All analysis is local and deterministic; see [Privacy](#configuration--privacy)
56
56
  > before inspecting a repository whose telemetry policy you need to control.
57
57
 
58
- ![Version](https://img.shields.io/badge/version-5.8.17-blue)
58
+ ![Version](https://img.shields.io/badge/version-5.8.18-blue)
59
59
  ![Python](https://img.shields.io/badge/python-3.9%2B-green)
60
60
 
61
61
  Copyright (c) 2026 Dominique Haroun. All rights reserved. ASK Engine 5.7.0 and
@@ -125,7 +125,7 @@ stops at 1 408 files and ends at 5.1s. Commands outside that phase-runner set
125
125
  must not be gated on this variable; their budget applicability remains visible in
126
126
  the [defect ledger](docs/DEFECT-LEDGER.md).
127
127
 
128
- **Current performance status.** Release 5.8.17 retains the shared Canonical IR
128
+ **Current performance status.** Release 5.8.18 retains the shared Canonical IR
129
129
  path used by `validation` and now passes that same CIR into labelled `data-exposure`
130
130
  runs; the no-label path remains parse-free. The one-model-per-declared-label path is
131
131
  also retained. These are implementation properties, not duration promises:
@@ -159,7 +159,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
159
159
  # pip / pipx
160
160
  pipx install sourcecode # or: pip install sourcecode
161
161
 
162
- ask version # ask 5.8.17 — and, on a build that has aged,
162
+ ask version # ask 5.8.18 — and, on a build that has aged,
163
163
  # how many releases have probably shipped since
164
164
  ```
165
165
 
@@ -10,7 +10,7 @@
10
10
  > question. All analysis is local and deterministic; see [Privacy](#configuration--privacy)
11
11
  > before inspecting a repository whose telemetry policy you need to control.
12
12
 
13
- ![Version](https://img.shields.io/badge/version-5.8.17-blue)
13
+ ![Version](https://img.shields.io/badge/version-5.8.18-blue)
14
14
  ![Python](https://img.shields.io/badge/python-3.9%2B-green)
15
15
 
16
16
  Copyright (c) 2026 Dominique Haroun. All rights reserved. ASK Engine 5.7.0 and
@@ -80,7 +80,7 @@ stops at 1 408 files and ends at 5.1s. Commands outside that phase-runner set
80
80
  must not be gated on this variable; their budget applicability remains visible in
81
81
  the [defect ledger](docs/DEFECT-LEDGER.md).
82
82
 
83
- **Current performance status.** Release 5.8.17 retains the shared Canonical IR
83
+ **Current performance status.** Release 5.8.18 retains the shared Canonical IR
84
84
  path used by `validation` and now passes that same CIR into labelled `data-exposure`
85
85
  runs; the no-label path remains parse-free. The one-model-per-declared-label path is
86
86
  also retained. These are implementation properties, not duration promises:
@@ -114,7 +114,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
114
114
  # pip / pipx
115
115
  pipx install sourcecode # or: pip install sourcecode
116
116
 
117
- ask version # ask 5.8.17 — and, on a build that has aged,
117
+ ask version # ask 5.8.18 — and, on a build that has aged,
118
118
  # how many releases have probably shipped since
119
119
  ```
120
120
 
@@ -16,7 +16,30 @@ The facts these rows are keyed to are published: `ask schema facts-v1` prints th
16
16
 
17
17
  ## Current Synchronization
18
18
 
19
- **Latest attached audits — release `5.8.16`, 2026-08-21, two independent rounds.**
19
+ **Latest attached audits — release `5.8.18`, 2026-08-21, two independent rounds, and the
20
+ first pass since 5.8.2 that opens with a regression.** Round A (`saint-server`/MSAS,
21
+ 3 342 Java files, 17 commands, 29 invocations, same HEAD as the previous round bit for
22
+ bit) scores **8.77/10** — up from 8.21 — with **zero false statements about the
23
+ repository for the second consecutive run**, 6 of 6 reported defects closed and verified
24
+ from outside, and **five new contract defects, four of them the same class as the fix that
25
+ preceded them**. Round B (a 12-repository bank, ~150 invocations, the §7 measurement
26
+ protocol applied: idle host, interleaved, ×3, median, cache state declared per row) closes
27
+ **8 of the 10 new rows and 2 of the 9 inherited ones**, records **zero content regressions
28
+ and no performance row above the ×1.25 threshold**, and finds **two regressions, one of
29
+ them a P0**: `compare` is dead in every valid invocation with an unhandled `NameError`,
30
+ and `project_summary` publishes an Apache licence header as the description of the project
31
+ on 3 of 8 repositories.
32
+
33
+ **The two rounds agree on the shape of what is left, and it has moved again.** The
34
+ previous pass ended with contracts that were *absent*; this one ends with contracts that
35
+ *contradict each other across authorities*: two homonymous fields declaring the same unit
36
+ and the same population and differing 16×, one budget published three times with three
37
+ values, a help page denying a scope the fix beside it granted, and two ledger rows marked
38
+ `closed` that do not reproduce as closed in the field. **A row marked closed that is not
39
+ closed is worse than an open one — nobody looks at it again** — so those are carried at P1
40
+ below rather than left in their original sections.
41
+
42
+ **Previous attached audits — release `5.8.16`, 2026-08-21, two independent rounds.**
20
43
  Round A (`saint-server`, 3 342 Java files, 17 commands, 25 invocations) scores **8.21/10**
21
44
  with **zero false statements about the repository** and two contract defects. Round B (a
22
45
  16-repository bank, 49 to 24 073 Java files, **240 invocations, 0 crashes, 0 tracebacks**)
@@ -28,10 +51,11 @@ previously open defects by correction with **zero regressions among the inherite
28
51
 
29
52
  Both rounds agree on where the product now fails, and it is not the Java/Spring analysis:
30
53
  it is the contract an agent consumes programmatically — the write guard, repository
31
- identity, list units, flag scope, and published budgets. The seventh-pass section below is
32
- the only current queue; older rounds remain for traceability.
54
+ identity, list units, flag scope, and published budgets. Its queue is closed in `5.8.17`;
55
+ **the eighth-pass section below is the only current queue**, and older rounds remain for
56
+ traceability.
33
57
 
34
- **Mechanisms confirmed in source during intake** (not taken on the reports' word):
58
+ **Mechanisms confirmed in source during the seventh-pass intake** (not taken on the reports' word):
35
59
  `verify --init` writes with no `readonly.guard` (`cli.py:10706-10708`) while five sibling
36
60
  writers guard; `spring-audit` derives `repo_id` from the CIR content hash
37
61
  (`spring_security_audit.py:1416`, `spring_tx_analyzer.py:1081`) while every other surface
@@ -52,10 +76,13 @@ itself rather than merely under-declaring.
52
76
  **Release status:** entries marked “pending `5.8.14`” in their historical wording are
53
77
  shipped in `5.8.14`; the correction battery fixes listed above are included in `5.8.15`.
54
78
 
55
- **Current release:** `5.8.16` includes two post-audit corrections: compact cold-start
56
- identity is preserved for `no_ris`, and manifest-cache keys include Python requirements
57
- files. The testing-repository hygiene exercise changed no external repository; it
58
- completed 108/108 read-only workflow runs with valid JSON and exit code 0.
79
+ **Current release:** `5.8.18` closes the whole eighth-pass queue, one commit per row, and
80
+ includes the targeted release battery. `5.8.17` before it carried the seventh-pass queue;
81
+ `5.8.16` before that carried two post-audit
82
+ corrections: compact cold-start identity is preserved for `no_ris`, and manifest-cache keys
83
+ include Python requirements files. The testing-repository hygiene exercise changed no
84
+ external repository; it completed 108/108 read-only workflow runs with valid JSON and exit
85
+ code 0.
59
86
 
60
87
  The battery also closed the following reproducible contract defects in `5.8.15`:
61
88
  `migrate-apply` is registered across help, progress, path-admission, output-purity,
@@ -73,6 +100,107 @@ with neither parseable stdout nor its requested artifact) or `BUG-6`
73
100
  queue position. `BUG-1` and `BUG-5` gain witnesses on public OSS repositories, recorded
74
101
  under their own rows rather than as new ones.
75
102
 
103
+ ### Eighth Audit Pass: `5.8.17` findings, closed in `5.8.18` / MSAS + 12-repository bank / 2026-08-21
104
+
105
+ The current queue. Ordered as the correction order: **regressions first, then the rows a
106
+ previous pass marked closed that the field does not reproduce as closed, then new contract
107
+ defects, then residuals.** Canonical IDs are `AUD-592-*` (bank round, reporter IDs `A-*`,
108
+ `B-*`, `N-*`, `D-*`) and `AUD-593-*` (MSAS round, reporter IDs `N-0*`). Rows held elsewhere
109
+ in this ledger are listed after the table as mappings, not as new defects.
110
+
111
+ | ID | Severity | Current status | Required direction |
112
+ |---|---|---|---|
113
+ | `AUD-592-R01` / `A-1` | **P0 — regression** | **open, confirmed in source, and it is two defects from one error.** `compare` raises `NameError: name '_compare_scan_trunc' is not defined` on **5 of 5 valid invocations** — Rich traceback on stderr, zero bytes on stdout, no error envelope, exit 1 — ending a 240-invocation streak with no traceback. The assignment introduced by `AUD-591-A06` landed **inside `plan_cmd`** (`cli.py:8874`, beside `plan`'s own `find_java_files` at `:8873`) while the read is in `compare_cmd` (`cli.py:8972`); the two functions are `8818-8901` and `8903-9002`. Verified by reading the source at HEAD, not from the report. Second effect: `plan` computes its truncation state and **discards it** — nothing in the payload carries it, so `plan` answers `resolution: not_found` over a walk that stopped at its cap, offering candidates from a different repository. Third effect: `compare`'s other `AUD-591-A06` fix, `data.setdefault("scope", ...)` at `cli.py:8975`, is **after the line that raises** and has never executed, so the cross-repository candidate leak is still undeclared. | Read `_last_scan_truncation()` at `compare`'s own call site, immediately after `cli.py:8965`; rename the `plan_cmd` variable to `_plan_scan_trunc` and **bind it to the payload** — an unused walk-state variable is the defect, not the fix. Regression: an AST assertion that no `_*_scan_trunc` name is read in a `FunctionDef` that does not assign it, plus one execution test per command that owns a walk. A unit test that imported `compare_cmd` would not have caught this; one that *calls* it would. |
114
+ | `AUD-592-R02` / `N-4`, reopens `AUD-513-N04` | **P1 — regression** | **open, confirmed in source, on 3 of 8 repositories (37,5 %), in `--compact` and `--agent` alike.** `project_summary` publishes an Apache-2.0 licence header as the description of the project (struts), a 30-character horizontal rule (halo) and a setext underline (shopizer) — and `summary_basis` asserts `"README descriptive prose"` over all three. In 5.8.16 this field was `null` with `"no descriptive section found in README"`, the literal acceptance text of `AUD-513-N04`; the field went from honest to false. Mechanism, four separate holes, all read at HEAD: HTML comments are detected **only on their opening line** (`summarizer.py:335-337`) with no `in_html_comment` state — three lines above, `in_code_block` does exactly that for fences (`:326-330`) — so `<!---` on line 1 flushes and lines 2-15 of the licence become the first paragraph; headings are ATX-only (`:331`), so setext titles underlined with `===` are content; the short-fragment floor is `len(paragraph) < 30` **strictly** (`:359`), so a rule of exactly 30 dashes survives; `_LICENSE_MARKETING_RE` (`:266-281`) matches product-tier and marketing phrasing and **carries no Apache/MIT/GPL/BSD boilerplate pattern at all**; and `summary_basis` is assigned unconditionally to whatever paragraph survives the filters (`:382-385`) — a restatement of the code path, not a property that was checked. | Add `in_html_comment` symmetric to `in_code_block`; recognise setext underlines as headings, not content; extend the licence regex with the four standard boilerplates; and make `summary_basis` describe the path actually taken — where nothing is verifiably descriptive, `null` plus the 5.8.14 text. **The mechanical cause of the reopening is that no README fixtures exist**: add the three witnesses from the bank as fixtures (HTML licence comment, 30-character rule, setext `===`) in the same commit as the fix. |
115
+ | `AUD-593-N01` / `N-01` | **P1** | **open, and it falsifies the closure assertion of `AUD-590-B02`.** For one symbol, one tree, one HEAD, consecutive invocations, both at `depth=4`: `impact` publishes `direct_caller_count: 34` (210 reference sites) and `impact-chain` publishes `554` (3 103), both under the literal unit `"distinct caller classes"`. The product's own comparability rule (`CALLER_METRIC_RECONCILIATION`) is *"two figures are comparable only when both match"* — they match, and differ 16×. **The authority is what is wrong, not only the number**: `FAN_IN_FIGURES` (`caller_metrics.py:80-110`) declares both rows `unit=distinct_classes, population=references_excluding_imports`, and the populations are not the same. Measured mechanism: `impact-chain` expands the seed set with every member of the interfaces the target implements (CH-001b, `spring_impact.py:1110-1135`) and then takes depth 1 **from the expanded seeds** (`caller_reach.py:309-336`), so its "direct" includes callers that name a sibling implementation; `impact` admits only references that name the target and keeps interface-mediated callers on a separate axis (`repository_ir.py:9263`, `:9596-9606`). Corroborating symptom: `chain_classes_total`, declared *"unbounded above by any direct-caller count"*, equals `direct_caller_count` exactly (554), and `indirect_callers` is `[]` — that emptiness is the hub guard capping the walk to depth 1 (`caller_reach.py:319-321`) and **is** declared, so it is not a confident zero. The published closure assertion `len(impact.direct_callers) == chain.metadata.direct_caller_count` measures 30 (list, capped from 34) against 554: it passes on a fixture where the two coincide by accident. | Decide which figure the `direct_caller_*` namespace owns, and fix the **catalogue** either way: either `impact-chain` measures depth-1 fan-in on the unexpanded seed (≈34), or the figure is renamed out of that namespace and its `population` becomes its own tag — an interface-expanded seed set is not `references_excluding_imports`. Regression is parametric over the catalogue, not over `CommonService`: for every pair of `FAN_IN_FIGURES` rows sharing `(unit, population)`, the emitted values must be equal, run over ≥3 symbols of different fan-in **including one that trips the hub guard** — the condition under which the divergence appears, and the reason two previous corrections of this class (`callers_total`, `P0-2`) closed a name and left the divergence. `chain_classes_total ≥ direct_caller_count` with strict inequality wherever uncapped transitive reach exists. |
116
+ | `AUD-592-B01` / `B-8` | **P1 — closed row that does not reproduce as closed** | **open; the ledger row overstates its own fix.** `B-8` is recorded as *"compact posture retains one unresolved sample when the total is non-zero"* (`52593b6`). The code retains a sample only when the total is **exactly one**: `_posture_limit = 1 if summary["unresolved"] == 1 else 0` (`cli.py:12653-12654`). Field measurement on `mall`: `summary.unresolved: 3`, `unresolved: []`, `unresolved_cap: {total: 3, shown: 0, omitted: 3, limit: 0}` — and it is the only cap in that payload with `limit: 0` while `undecided_cap` and `evidence_cap` carry 200. `--limit 10` returns all three, so the analysis is intact and only the compact contract is wrong. | Either make the code do what the row says (retain ≥1 sample whenever `summary.unresolved > 0`) or correct the row to the narrower promise and reopen the defect it leaves. Do not leave `closed` standing over `shown: 0`. Add an assertion that no `cap_effect` receives `limit=0` by default on a path where `--limit 0` is published as *"no cap"* (`AUD-513-N08`), so the published semantics and the internal default cannot invert each other. |
117
+ | `AUD-592-A02` / `A-1` second half, `§12.5` | **P2** | **open — scan truncation is declared by 1 of 4 commands that own a walk.** Over a truncated scan (cap observed at **8 000 files**), `impact` publishes `scan_truncated`; `plan` and `impact-chain` answer `not_found` with `scan_truncated: null`, and `endpoints` exits 1 with no payload — every one of them an exclusion derived from an incomplete population. `compare` cannot be measured (`AUD-592-R01`). Second, narrower defect in the same row: the root `--help` describes the cap as *"the scan stopped at 25 000 directory entries"* — a different limit in a different unit from the 8 000-file cap the field observes. | Publish the truncation beside every walk that can end in `not_found`, `candidates` or a census — the seventh pass already recorded that `extract_java_endpoints` does its own uncapped `rglob`, so this must be read at each call site, never centrally. Reconcile the two caps in the help text or declare both with their units. |
118
+ | `AUD-593-N02` / `N-02` | **P2** | **open — the `--compact` budget is published three times, in two shipped authorities, with three values.** `ask --help` generates *"~7K tokens (30 KB, chars/4)"* from `output_budget`, the module that enforces the limit — this half is the `AUD-590-B03` fix and it is correct. The packaged `docs/USER_GUIDE.md` is still hand-maintained and disagrees with it twice: `:111` *"A ~10K-token subset"* and `:243` / `:1366` *"~2,500–4,000 tokens"*; `--agent` carries a fourth figure at `:254` / `:1367` (*4,500–5,500*). Measured payload: 22 390 B ≈ 5 597 est. tokens — inside the help ceiling, **+40 % over the guide's table**. `grep '7K tokens' *.py` finds no literal: the help is generated and the guide is not, and that asymmetry is the defect. | Generate every token figure in the packaged docs from `output_budget.token_estimate`, or delete them and point at `--help`. Extend the existing release assertion (today help ↔ payload ↔ section registry) to cover `docs/*.md`: a token band in a shipped `.md` that does not come from that module fails the battery. Packaged documentation is a published authority and belongs inside the same assertion as the help text. |
119
+ | `AUD-593-N03` / `N-03` | **P2** | **open — `--help` denies the scope that `AUD-590-B04` had just granted.** With `ASK_MAX_ANALYSIS_SECONDS=90` the root analysis prints *"ask is a repo-wide analysis and the configured budget is 90s. Budget read from ASK_MAX_ANALYSIS_SECONDS=90 (process environment)"* — the fix works. The help page beside it still reads *"deadline only for spring-audit, risk, audit-report"* and *"Other commands are not time-bounded by this variable"* (`cli.py:621-622`). The root analysis is the most expensive command in the product and the one an agent most needs to bound; a reader of the help will not set the variable there. | Generate that line from the same registry `_build_analysis_classes` populates (the root is keyed there as `B14`), never by hand. Assertion: the set of commands the help names equals the set the preamble emitter covers. |
120
+ | `AUD-593-N05` / `N-05` | **P3** | **open — a figure emitted outside the catalogue that forbids it.** `via_interface_resolution[].caller_count` publishes 37 where every other surface of the same fact says 23 (`interface_mediated_caller_count`, the list length, and the `explanation` prose), and it carries no `_unit` while the rest of the payload does. Both are legitimate and neither is declared: `caller_count` is `len(_iface_callers)` — raw caller symbols of the interface, before the `not in all_affected` filter and before normalisation to classes (`repository_ir.py:9248-9251`); the 23 is `caller_classes(_iface_mediated_callers, ...)` (`:9603`, `:10173`). It is also **not in `FAN_IN_FIGURES`**, which states that a figure absent from it may not be emitted — so `tests/test_fan_in_authority.py` did not catch a fan-in figure added in this release. | Give it a unit and a `FAN_IN_FIGURES` row, or rename it to `interface_caller_symbols`. Make the authority test sweep the **emitted** keys against the catalogue rather than the catalogue against itself; a catalogue that only validates its own rows cannot see an unregistered emission. |
121
+ | `AUD-593-N06` / `N-06` | **P3** | **open, latent — a silent `[:30]` where every sibling list declares its cap.** `out["interface_mediated_callers"] = _iface_mediated_classes[:30]` (`repository_ir.py:10172`) with no `*_cap` block, in a payload where `direct_callers_cap`, `indirect_callers_cap` and `security_surface_affected_omitted` all carry `total`/`shown`/`omitted`/`direction`/`how_to_read`. On MSAS the list is 23, so nothing is visible; the first repository with more than 30 interface-mediated callers loses the excess without a word. | Route it through the same `_cap_effect(...)` used 27 lines above (`repository_ir.py:10145`). |
122
+ | `AUD-592-D01` / `D-1` | **P3 — residual of `AUD-591-A08`** | **open, confirmed in source.** The write inventory in the root help says `migrate-check` writes *"only with `--history-dir`"* (`cli.py:296`). `--history-dir` only relocates the destination; the flag that writes is `--snapshot`, as `migrate-check --help` states correctly and as the code comment at `cli.py:12980-12986` states explicitly. Verified in the field: `migrate-check --history-dir <path>` exits 0 with zero writes and no guard message, while `--snapshot` fires the guard correctly. `AUD-591-A08`'s assertion checks that each cited flag **exists** in that command's parser — `--history-dir` does — not that it is the flag that triggers the write. | Key the inventory on `(command, triggering flag, path)` taken from the guard site itself, as `AUD-591-A08`'s own acceptance text required. An auditor tests what the inventory lists: this is the same mechanism by which `AUD-591-A01` went unfound. |
123
+ | `AUD-592-D02` / `D-2` | **P3 — residual of `AUD-591-A02`** | **open.** `--min-band` filters and validates (`cli.py:11294-11308` in `risk`, `:11563-11568` in `enrich`) but publishes no `_filter` block, while its sibling `--band` publishes one through `_apply_selection`. A consumer cannot tell a filtered answer from a small one. | Route `--min-band` through `_apply_selection` like every other selection flag, or publish the same `_filter` shape from wherever it is applied. |
124
+ | `AUD-592-D03` / `D-3` | **P3 — residual of `AUD-591-A02`** | **open.** `enrich --rule NOPE-999` exits 0 with an empty result; `spring-audit --rule NOPE-999` exits 1 against the rule catalogue. One flag name, two contracts. Measured with a synthetic SARIF 2.1.0 (2 results): `--rule`, `--band` and an invalid `--band` all behave correctly in `enrich`; only unknown-rule validation is missing. | Validate against the same catalogue in both commands. `enrich` is experimental-tier, which sets the severity, not the contract. |
125
+ | `AUD-592-D04` / `build_commit` | **P3 — process** | **open, fourth consecutive report.** `ask version` publishes `build_commit: unrecorded`, so no measurement in these ~150 invocations is attributable to a commit and *"fixed in 5.8.17"* is not falsifiable from outside. | Stamp the commit at build time. It is the cheapest row in this table and it is the precondition for every other row's verification. |
126
+
127
+ **Mapped, not new — inherited rows this pass re-witnesses.** `B-6` (partial answers exit 0)
128
+ keeps its row and gains its best measurement yet: overrun ×5.4 → ×4.2 → **×1.39** (median
129
+ 20.90 s of 70.74/20.90/19.70 against a 15 s budget), with a `_partial` block that is
130
+ exemplary (`phases_completed`, `phases_pending`, `why_stopped`, and *"every count here is a
131
+ FLOOR"*) — and `exit 0` on all three runs, so a pipeline reading `$?` passes with two of
132
+ three phases unexecuted. **`AUD-591-A09` is the template**: `exit_code` / `gate_exit_code` /
133
+ `gate_exit_code_basis`, or an explicit `--allow-partial`. `B-3` (`--agent` versus
134
+ `--compact`) gains a witness at 3 342 files: 35 357 B ≈ 8 839 est. tokens, **+61 % over the
135
+ only published band**, 16 blocks present in `--compact` and absent from `--agent`
136
+ (`transactional_boundaries`, `mybatis`, `spring_profiles`, `deployment`, `env_map`,
137
+ `stacks` among them), and `sibling_view` still names no block; on the bank round the two
138
+ views are no longer a subset relation at all (9 blocks agent-only, 15 compact-only) and the
139
+ ×2.25 time overhead is gone (×1.02). Substantively, `security_surface` is absent from
140
+ **both** channels on a repository with 368 security findings and 725 routes open by rule —
141
+ the predicate is disclosed under `AUD-590-B03`, not closed. `N-5` (an advisory saying
142
+ *"8 372 Java files"* with no population label while the progress line says
143
+ `[population=production_java_sources]`) remains the unclosed half of `AUD-588-B11`; the
144
+ label exists (`cli.py:10278-10280`) and reaches the progress lines and the payload but not
145
+ the advisory emitted from `phased_run.py:367`. `D-09` (cost anchors stamped *"on 5.1.0"* in
146
+ a 5.8.17 build — now counted: **17 anchors on 5.1.0, one each on 4.18.0, 5.0.0 and 3.2.2**,
147
+ in a `cache model` output presented as operational guidance) belongs to `BUG-5`. `N-6`
148
+ (cold `spring-audit` on `openmrs-core`) belongs to `BUG-1` and **improved**: 8.86 s → 8.06 s.
149
+
150
+ **Closed by correction and re-verified from outside in this pass — do not re-derive.**
151
+ `AUD-591-A01` (8 of 8 write paths refuse, verified by filesystem footprint rather than
152
+ `git status`, `ASK_RUNS_IN_REPO=1` included), `AUD-591-A02`, `AUD-591-A03` (and the
153
+ proposed highest-priority probe is retired: `rename-class --from O` exits 1, as the seventh
154
+ pass had already established), `AUD-591-A05`, `AUD-591-A06` (50.30 s → 0.43 s, and the
155
+ sweep it asked for holds: **6 of 6 error paths ≤0.54 s**), `AUD-591-A08` (modulo
156
+ `AUD-592-D01`), `AUD-591-A09`, `AUD-591-A10`, `AUD-590-B01` (`repo_id` cardinality 1 with
157
+ `repo_id_basis`; the content hash lives on as `content_id`), `AUD-590-B02` (the *lists* —
158
+ the counters above it are `AUD-593-N01`), `AUD-590-B03` (in `--help`; the packaged guide is
159
+ `AUD-593-N02`), `AUD-590-B04` (both halves: a `partial-analysis-v1` stub with `partial:
160
+ true` where 5.8.16 left zero bytes, and an 807 B preamble byte-compatible with
161
+ `spring-audit`'s 813 B), `AUD-590-R01` (`route_census` — and it **refuted the auditor's own
162
+ double-counting hypothesis with the product's data**: `mappings 3763` against
163
+ `on_rows 1120`, with `distinct_routes ≥ mappings`), `AUD-591-Q01`, `B-7` (closed by
164
+ deletion, which was the right answer: `total_ms` is gone, replaced by
165
+ `wall_ms`/`measured_ms`/`unaccounted_ms`/`unaccounted_pct` with arithmetic exact to the
166
+ decimal and a `unit` explaining why the remainder is published rather than distributed).
167
+
168
+ **Verified and not defects — do not spend effort.** `posture --profile` accepting an
169
+ undeclared profile is **by design and correctly declared**: it is a hypothesis input, not a
170
+ catalogue name, and the payload publishes `profiles_requested` beside `profiles_declared`
171
+ (the bank round withdrew this finding itself after reading the payload). `pr-impact` on a
172
+ clean tree exits 1 with a typed `INVALID_INPUT` naming the empty diff. `pr-impact` over
173
+ three classes refuses with `OUTPUT_TOO_LARGE` and names `--output` — a ceiling as contract,
174
+ not a truncation. `verify` publishes `exit_code: 2` matching the process (`AUD-591-A09`).
175
+ `data-exposure` still answers `answered: false` rather than inferring labels. Cache
176
+ freshness reporting `STALE` at delta 0 commits is `Uncommitted: True` over the auditor's own
177
+ untracked files. `repo_id` absent from `endpoints`, `posture` and `--compact` is coverage,
178
+ not a defect — the criterion was cardinality 1 among emitters, and the help no longer
179
+ promises it.
180
+
181
+ **Process findings of this pass, and they are the same finding twice.**
182
+
183
+ 1. **The class survives the fix, four times out of five.** `AUD-590-B02` (unit absent from
184
+ the lists) returned as `AUD-593-N01` (unit present and false in the counters) and
185
+ `AUD-593-N05` (a new field shipped without one); `AUD-590-B03` (two figures in one help
186
+ page) returned as `AUD-593-N02` (three figures once the packaged guide is counted) and
187
+ as the `--agent` band in `B-3`; `AUD-590-B04` (a variable invisible to the root) returned
188
+ as `AUD-593-N03` (a help page denying the scope the fix granted). The seventh pass named
189
+ this pattern its highest-value finding and wrote the rule — *every acceptance criterion
190
+ carrying a sweep clause is closed with a parametric test over the catalogue* — and the
191
+ two classes closed **as sweeps** in that pass (write guards 8/8, numeric bounds 7/7, and
192
+ now error-path cost 6/6) did not recur, while three of three closed by instance did.
193
+ `FAN_IN_FIGURES`, `COMMANDS_THAT_WRITE` and the serializer's section registry are already
194
+ catalogues: the test goes over the catalogue, never over the reported symbol.
195
+ 2. **Two rows in this ledger were marked `closed` while the field reproduces them open**
196
+ (`AUD-592-B01`, and `AUD-588-B11`'s advisory half). Both were closed against a surface
197
+ narrower than the row's own wording. A closure whose assertion cannot fail on the tree
198
+ that produced the defect is not a closure: `AUD-593-N01`'s assertion passes today only
199
+ because the fixture makes both figures coincide.
200
+ 3. **Packaged documentation is a published authority.** `AUD-593-N02` exists because the
201
+ release assertion covers help ↔ payload and stops at the package boundary. Two stale
202
+ figures in a shipped `.md` are enough to contradict the correct one in the help.
203
+
76
204
  ### Seventh Audit Pass: `5.8.16` / 16-repository bank + `saint-server` / 2026-08-21
77
205
 
78
206
  Ordered as the correction queue, regressions and permissive-direction failures first. Each
@@ -184,7 +312,7 @@ partial, `F03` open, `F04` explicit opt-in and `F05` locally verified only.
184
312
  | `N-6` | Medium | **not reproduced after cache fixes** | Isolated cold `openmrs-core`: 5.18 s wall / 4.76 s internal, all four layers cold. Retain the field report as an environment-specific reproduction request. |
185
313
  | `B-3` | Medium, core/supported | **closed by `773268d`** | Help no longer claims maximum signal; `sibling_view` points to compact. |
186
314
  | `B-6` | Medium, core | **closed by `17c6e06`** | Partial answers publish `overrun_bound` and its wall-clock basis. |
187
- | `B-8` | Low | **closed by `52593b6`** | Compact posture retains one unresolved sample when the total is non-zero. |
315
+ | `B-8` | Low | **reopened 5.8.17 — see `AUD-592-B01`** (was: closed by `52593b6`) | The fix retains a sample only when the total is exactly 1, not whenever it is non-zero, so `total: 3, shown: 0` still reproduces. |
188
316
  | `N-5` | Low, core | **closed by `c68083f`** | Progress and payload name the Java population. |
189
317
  | `N-7` | Low, core | **closed by `082e9de`** | Bounded fuzzy candidates and matching message hints handle close typos. |
190
318
 
@@ -207,7 +335,7 @@ automation remains deferred; provider non-coverage is the current product behavi
207
335
  | `AUD-513-N01` (`N-1`) | **closed in 5.8.14** | `rename-class` rewrote three Petclinic files under both `ASK_READONLY=1` and `--no-write`, then exited 0. The audit restored the tree; this is a write-policy breach, not an artifact-directory exception. `readonly.guard_mutation()` now refuses before any planned source write or physical rename; help names the command as mutating and regressions cover both readonly controls plus `--dry-run`. |
208
336
  | `AUD-513-N02` / `B-4` / `N-5` | **N02/B-4 implemented in 5.8.14; N-5 open** | `posture.summary.unconditional` counted 1,697 on a non-Spring Struts tree and 1,573 on Mall, and `security` was `0/0/0` with no population. The posture projection now uses the canonical Spring IoC bean population, publishes its population/unit and separates unconditional security beans. Regressions cover non-Spring, mixed-bean and conditional/unconditional security fixtures. Progress/advice still use incompatible “Java files” scopes (`N-5`), so the `AUD-588-F02` family remains open. |
209
337
  | `AUD-513-B01` / `B-3` / `B-5` | **B01/B-5 implemented in 5.8.14; B-3 closed as revalidated** | A MyBatis XML paired with a `*Mapper.java` interface now takes precedence over an absent `@Mapper` annotation, preserving XML-backed/`@MapperScan` interfaces in `mapper_interfaces` rather than misclassifying them as DTO mappers. `imports_found` now contains only actual Java imports; code, XML and build matches are emitted as `evidence`, including in compact output. `B-3` was stale against the current source: both views consume `JAVA_SPRING_SECTIONS`; a real MyBatis Mapper/XML regression proves the section is retained by `--agent`. |
210
- | `AUD-513-N03/N04/N07/N08/N09`, `B-6/B-7/B-8`, `D-09` | **N03/N04/N07/N08/N09 implemented in 5.8.14; remainder open** | `impact` now always publishes the `candidates` field its not-found message names, including `[]` when no close symbol exists. Budget advice no longer calls partial snapshot/RIS evidence a warm cache: it identifies that presence and says context/parse are unknown before analysis, whose payload then reports all four actual layers. README operational sections (`clone`, install, build, getting started, troubleshooting and related headings) are never promoted into a project summary; with no descriptive prose compact output publishes `project_summary: null` and `summary_basis`. `security_posture.limitations` is now cache-state invariant; dynamic execution advice travels in `security_posture.operational_hints`. Every numeric output bound rejects negative values at parse time with a structured `INVALID_INPUT` envelope (`flag`, `value`, `expected`); `--limit 0` still means no cap wherever that behavior was published. Budgets overrun, timing coverage is inconsistent, compact hides unresolved identities and cost anchors remain stale. |
338
+ | `AUD-513-N03/N04/N07/N08/N09`, `B-6/B-7/B-8`, `D-09` | **N03/N04/N07/N08/N09 implemented in 5.8.14; remainder open** | `impact` now always publishes the `candidates` field its not-found message names, including `[]` when no close symbol exists. Budget advice no longer calls partial snapshot/RIS evidence a warm cache: it identifies that presence and says context/parse are unknown before analysis, whose payload then reports all four actual layers. README operational sections (`clone`, install, build, getting started, troubleshooting and related headings) are never promoted into a project summary; with no descriptive prose compact output publishes `project_summary: null` and `summary_basis` — **`N04` regressed in 5.8.17 and is `AUD-592-R02`: licence headers and layout rules are promoted again, under a basis that asserts they are prose.** `security_posture.limitations` is now cache-state invariant; dynamic execution advice travels in `security_posture.operational_hints`. Every numeric output bound rejects negative values at parse time with a structured `INVALID_INPUT` envelope (`flag`, `value`, `expected`); `--limit 0` still means no cap wherever that behavior was published. Budgets overrun, timing coverage is inconsistent, compact hides unresolved identities and cost anchors remain stale. |
211
339
  | `AUD-588-B11` (container/units subset) | **partially implemented in 5.8.14** | `d745d31` discovers nested Maven modules; `273ae8e` suppresses unsupported `pr-impact.unaffected_basis`. `e53507d` separates direct impact matches from analysis seeds and implementation classes; `8386744` carries the established container-wiring fact into plan checklists and compare cost dimensions. Source population units and risk-tier wording remain open. |
212
340
  | `AUD-511-R02` / `AUD-589-B02` / `AUD-513-N06` | **partially corrected; `data-exposure` open, P1** | Nine of ten measured commands recovered, many to their best historical timings. `data-exposure --config` did not: 42.7 s versus 16.2 s in 5.8.8 and a 28.9 s model, with byte-equivalent output. Measure it with the idle-host, isolated-cache, interleaved-control protocol before changing code, then compare its reuse path with `validation`. |
213
341
  | `AUD-588-B02`, `B06`, B11 residuals, `B12` | **B02/B06 closed; B11/B12 open, P2** | `3869c87` excludes explicit EclipseLink from Hibernate applicability and effort; `037223e` publishes provider non-coverage. The re-audit verifies both and the payload reduction; `cf57457` makes aggregate wording name only applicable dimensions. Complete B11 consumer parity and calibrate B12 only from provenance-bearing controlled samples. |
@@ -407,6 +535,8 @@ retained only as evidence of what the auditor observed before the fix.
407
535
  | ASK-17 | **The parse store's default budget cannot hold a multi-repository workspace warm, and the cold cost of the largest repository is 7,6 minutes.** Measured on the 8-repo corpus (43 986 `.java`): `cache status` reports 56 730 entries at **511,12 MB against a 512 MB budget** — i.e. permanently sweeping by LRU — so `tutorials` (24 073 `.java`, the largest contributor) is the first candidate for eviction. Cold `--compact` on it: **457,6 s**, independently reproduced at 449 s, against 2,0 s on the second pass. | 5.8.4 corpus re-audit | Medium — warm plus `--compact` is still the answer (2,0 s), but a workspace this size cannot keep every repository warm at the default budget, and nothing tells the caller which repository is cold before it pays for it | **closed 5.8.5 — the disclosure shipped and the owed measurement taken, under our own control.** ⚠ **The +66 % does not reproduce, and the mechanism the row suspected is worth ~3 %, not 66 %.** Protocol: `tutorials` (24 073 `.java`), root `--compact`, both cache bases isolated **and emptied between runs** (`SOURCECODE_CONTEXT_CACHE_DIR` *and* `SOURCECODE_CACHE_DIR` — the first attempt isolated only the first, and the second pass of each version answered from the L2 view its own first pass had written: 2,4 s with an empty parse store, which is how a measurement of a cold path becomes a measurement of a warm one), `ASK_PARSE_CACHE_MAX_MB` fixed at 4 096 MB so no sweep can confound the comparison, 2 passes per version. **5.7.2 (`e803c8b`): 112,0 s / 112,6 s. This tree: 113,8 s / 115,2 s — +2,3 %**, with per-version dispersion of 1,005× and 1,012× and a payload 2,2 % larger. Then the audit's own condition, isolated as the only variable — the store pre-filled to 489 MB against the **default** 512 MB budget, so every 32 MB written sweeps: **117,0 s, +2,7 %.** So the LRU sweep is not where 457,6 s comes from, and neither is the analysis path: the auditor was right to hold the regression, and the held figure is now retracted **with a number** rather than on suspicion. ⚠ Scope, stated because the difference is unexplained rather than explained away: 457,6 s on Windows 11 / pipx is **not reproduced here** (113 s on 20 cores), and that gap is not assertable in either direction from this measurement — what is assertable is that 5.7.2 → this tree did not get slower and that a saturated store costs ~3 %. ✅ **What the measurement does confirm is the row's own claim, with our number: one repository of 24 073 `.java` leaves 46 840 entries and 470 MB in the store — 92 % of the 512 MB default budget** — so a workspace with a second repository of any size is permanently sweeping by construction, exactly as reported. Sizing rule, measured rather than guessed: ~20 KB of store per Java file, so ~500 MB per 24 000-file repository. Collateral confirmation of `AS-18`: after the saturated run the store rests at 669 MB — 157 MB over the budget and **under** the 736 MB effective ceiling it publishes at 7 writers — so the ceiling holds under the condition that produced the complaint. **The disclosure half:** `cache status` now publishes **coverage per repository**, which is the half the row itself recommended and the half that changes a decision: *«tutorials: 3 100 of 24 073 files cached (13 %)»* replaces a blind guess about whether to raise the budget, and an LRU eviction becomes visible **before** somebody pays 457,6 s to discover it. Both halves of the attribution were already held and thrown away — the walk knows the repository and it computes the store key for every file — so the run records the pairs (`parse_cache.record_repository_index`, from **both** readers of the store: `build_repo_ir` and the route-surface extractor, so the figure does not depend on which command was typed) and `store_stats` intersects them with the keys it collects **in the entry walk it already performs**: coverage costs an intersection, never a second scan of the store and never a scan of the repository. Three rules keep it honest. The index is **merged, never replaced**, because a `--changed-only` or `--since` run would otherwise shrink a 24 000-file population to the twelve files it read and publish *«12 of 12 cached (100 %)»* about a repository that is cold. The number travels with its **basis** — a file deleted since its last analysis still counts as recorded and reads as uncached, which errs toward *colder than it is* and says so. And the index is **neither an entry nor evictable**: the entry walk, the byte accounting and the LRU sweep all glob `*.json`, so its bytes are published under their own name (`repository_index_bytes`) rather than folded into a total that means entries — an index swept away with the entries it describes cannot report the eviction, which is the one moment it exists for. It lives inside the generation root, so retiring a generation retires its indexes with it: the keys are only readable by the build that wrote them. Regression `tests/test_parse_store_repository_coverage_ask17.py`, 11 assertions, including the one the row is about — entries deleted underneath a recorded repository make coverage **fall** while the population holds. ⚠ **Still owed, and unchanged:** the controlled cold measurement (5.7.2 against this tree, `ASK_PARSE_CACHE_MAX_MB` fixed, store emptied between runs, on a >20 000-file repository). Until it exists neither the +66 % nor its absence is assertable, and the row stays open on that half alone. **History:** **open** — ⚠ **not filed as a regression, deliberately**: the same cold figure was 274,8 s in 5.7.2 (+66 %), and the auditor refuses to call it one because the conditions are not comparable — in 5.7.2 the store had been retired by a version change, here it was mid-LRU-sweep. Seven false positives of exactly this class have been retracted over seven cycles; this is the eighth candidate and it is being held. What is owed is a measurement **we** control: cold `--compact` on a >20 000-file repository, 5.7.2 against 5.8.4, with `ASK_PARSE_CACHE_MAX_MB` fixed and the store emptied between runs — until that exists, neither the +66 % nor its absence is assertable. Recommended beside it, and cheap because both halves already exist: `cache status` should publish **coverage per repository** — how many entries belong to each analysed repository and what fraction of its files are covered — so *tutorials: 3 100 of 24 073 files cached (13 %)* replaces a blind decision about whether to raise the budget. Entries are content-addressed and the walk knows the repository, so this is a projection of facts we hold, not new analysis. **Refutation reproduced independently in cycle 8, under the reporter's own protocol**: both stores isolated and emptied, `ASK_PARSE_CACHE_MAX_MB=4096`, 2 passes per version — 5.7.2 at 112,0 / 112,6 s against 5.8.5 at 113,8 / 115,2 s (~3 %), and an A/B of the budget itself (512 MB sweeping by LRU against 4 096 MB that cannot sweep) at 9,1–10,1 s against 9,0–9,7 s: **the LRU sweep costs nothing measurable**. The +66 % is retired as the reporter's eighth false positive, with `E-37` named as its confounder. |
408
536
  | C3-128 | **`timeline` is the only gate-shaped command above 120 s, and it has not come back to its record.** Steady state, 4 runs, audited corpus: `timeline --since HEAD~5` costs **198 469 ms**, +27,3 % over its 5.7.2 record of 155 950 ms. The two other commands over 120 s are there structurally — `delta` (234 s) and `contract-diff` (136 s) analyse two whole trees — while `timeline` analyses **five** and costs less than `delta` does with two, so its cost is not explained by the number of trees it walks. | 5.8.2 → 5.8.4 re-audits | Low-Medium — an investigation command rather than a gate, and the last performance figure of the round sitting outside its own best | **closed 5.8.5 by measurement — the clock is attributed, and there is nothing left unaccounted to tune against.** The row's own instruction was ASK-16's: instrument before tuning. `timeline` published a per-sample total over what is really four costs — materialising a tree, measuring each watched metric, releasing the tree, and the remainder — so *«198 469 ms»* named a command rather than a phase. `perf.PhaseTimings` (the ASK-16 authority, always on) now splits it, with the phase names taken from `--watch` so the split cannot drift from the population, and the tree materialisation kept as its own phase because git's work must not be attributed to an analysis. **Measured, BroadleafCommerce (2 985 `.java`), `--since HEAD~5 --watch posture`, 5 samples: wall 38 921 ms — `measure:posture` 32 273 (82,9 %), `materialise_tree` 5 376 (13,8 %, ~1 075 ms per tree), `release_tree` 1 272 (3,3 %), unaccounted 0,45 ms (0,0 %).** So the answer to the row's premise — *«it analyses five trees and costs less than `delta` does with two»* — is that five sixths of the cost **is** the analysis, re-run per tree by construction, and the git work is a sixth of it: `timeline` is N × one analysis and there is no timeline-specific overhead to remove. Any future gain belongs to the metric being sampled (`C3-84`, `C3-127`), which is where it would also help every other command, and the payload now says so per run instead of per audit. Regression `tests/test_timeline_timings_c3_128.py`, 9 assertions, including that the series itself is byte-identical across two runs once the clock readings are removed — instrumentation that moved an answer would be a worse defect than the row. **Original note:** **open** — ⚠ the cache-reuse half of `B7` must **not** be reopened on this evidence: the v3 assertion (`max(sample) < 8 × posture_warm`) passes at 6,8 in both 5.8.2 and 5.8.4, against 14,8 / 13,4 / 12,4 / 8,5 in the four versions that genuinely failed it. What has not returned is the absolute cost. Attribution comes before tuning and is now cheap: `metadata.timings` (`ASK-16`) exists, so the per-phase split across the five trees can be published before anything is changed. |
409
537
  | B20 | **Thirteen declared renames with no cut-off date, and two distinct `1.0` identifiers meanwhile.** The registry publishes `pending_renames` for the 13 non-conforming `schema_version` values with their canonical name — exactly the policy `ASK-11` exists to enforce: the rename is an incompatible change, declared before it is made, never applied in silence. The consequence is published by the registry itself as `ambiguous_identifiers: 1` — `spring-audit` emits `1.0` for `core-analysis-v1` and `impact-chain` emits `1.0` for `impact-chain-v1`, so a consumer dispatching on the emitted version cannot tell them apart. | 5.8.4 re-audit (residual of `B19` / `B6`) | Low — declared debt rather than a defect, and the audit says so in as many words | **closed 5.8.5 — the window is declared where every other incompatible change is, and the reported ambiguity was understated by five shapes.** `BC-002` in `sourcecode.breaking_changes`: **announced 5.8.5, takes effect 6.0.0**, printed by `ask schema breaking-changes-v1`, carried in the CHANGELOG's `## Upgrading` section above the release history, and projected into `ask schema schemas-v1` as `pending_renames_window` — **one fact, two surfaces**, with a structural assertion that the registry source holds no second copy of the date. The registry's policy is generalised rather than loosened: a declared change is now `kind: exit_code` (must move an exit code) **or** `kind: contract` (must move a **published value** *and* name the version it takes effect in), because a rename breaks a consumer with every exit code still 0 and a registry that only knew about exit codes had nowhere to put it. A contract change publishes no `exit_code_before`/`after` at all — inviting a reader to check a field that cannot move is how a disclosure becomes noise. The 13 affected shapes are **read from `schema_registry.canonical_migrations()` at call time**, never copied: a shape that starts conforming leaves the declaration by itself (asserted by swapping the registry for a conforming one and watching the list empty). ⚠ **Correction to the reported cause, measured**: the audit named *two* shapes spelling their version `1.0`; there are **seven** — `core-analysis-v1`, `impact-chain-v1`, `pr-impact-v1`, `migration-blast-v1`, `spring-impact-v1`, `event-topology-v1`, `test-gap-ranking-v1` — so `ambiguous_identifiers: 1` was counting one *identifier* over seven shapes, not two. `ask schema 1.0` already resolved to all seven with each canonical name; the count is now asserted from the registry so it cannot be quoted from prose again. The rename itself is deliberately **not** made early: that is the incompatible change this policy exists to prevent. Regression `tests/test_schema_rename_window_b20.py`, 11 assertions, plus the ASK-11 battery generalised to both kinds. **Original note:** **open** — the missing half is a date, not a decision. Announce the cut-off window in `breaking-changes-v1` with the target version, the way every other incompatible change is announced, so a consumer can pin `core-analysis-v1` today and know when the bare `1.0` stops being emitted. Until then `ask schema 1.0` resolving to all seven shapes, each offering its canonical name, is the correct behaviour and must not be *fixed* by renaming an emitted value early — that is the incompatible change this policy exists to prevent. ⚠ **Round 10 ran on the 5.8.5 build and still reports the renames as *«deuda bien declarada, pero sin fecha»*, asking for precisely what `BC-002` already ships.** The row stays closed — the window exists, is announced 5.8.5 / effective 6.0.0, and is printed by `ask schema breaking-changes-v1`, carried in the CHANGELOG's `## Upgrading` and projected into `schemas-v1` as `pending_renames_window`. What it leaves behind is a **discoverability check, not a defect**: the reporter quoted `pending_renames` and `counts` out of the registry payload and did not see the window beside them, so verify that `pending_renames_window` travels in the same payload those two keys do — and if it does not, that is where it belongs. A declaration a ten-round auditor cannot find is not yet declared to a consumer. |
538
+ | E-38 | **A class-level route prefix carried by a meta-annotation is dropped, and the route is published without it.** `_build_route_surface` reads the class prefix only when the class symbol carries `@RequestMapping` or `@Path` **literally** (`repository_ir.py:5882-5887`); a repository that declares its own composed annotation gets `prefixes = [""]`, and the published `path` is the method suffix alone. **Measured on shenyu (5.8.17): 35 of 365 published routes — 9,6 %, over 21 controllers — carry `path: "/"`.** `AiProxyApiKeyController` is annotated `@RestApi("/selector/{selectorId}/ai-proxy-apikey")`, a Shenyu annotation meta-annotated with `@RestController` + `@RequestMapping`; its five handlers are published at `/`, `/`, `/batchDelete`, `/{id}`, `/page`. The served URLs do not exist as published. This is a **confident falsehood**, not a gap: no `path_resolution: "unresolved"`, no `path_expression`, no warning, and `route_census.distinct_routes` (316 of 365) reads the collisions as if two controllers genuinely shared a path. It also propagates to every consumer keyed on route text — `explain-endpoint`, `data-exposure --path-prefix`, `validation --path-prefix`, `pr-impact` route matching — where a correct query returns nothing. **The machinery already exists on the other axis**: `E-12`/`5.7.1` closed exactly this class for *beans* by resolving the spelling against the graph's `imports` edges, and `BeanGraph.build` already builds a meta-annotation map in its first pass. The route axis never asked. Vendor-agnostic by construction: the rule is "an annotation this repository declares that itself carries `@RequestMapping`/`@Path`", never a proprietary name. | found 2026-08-21 during the `AUD-590-R01` census triage, on the corrected 5.8.17 build; **not part of the seventh-pass queue and deliberately not fixed in it** — it moves route counts on any repository using composed annotations and needs its own measured pass with the golden set re-baselined | **High** — it is the rule this repository enforces most loudly, inverted on the route axis: a published route that is not served, with no affordance saying so. Blast radius is every repository with a framework-level or in-house composed controller annotation; shenyu is the witness, dubbo/sa-token/halo are unmeasured | **open** — direction: resolve the class-level prefix through the meta-annotation map `BeanGraph.build` already computes, in the order `E-12` established (explicit single-type import decides; wildcard leaves it admissible; a repository-declared annotation in the owner's package is the owner's own; **nothing resolved stays unresolved rather than acquiring a verdict from silence**). Where it cannot be resolved, publish `path_resolution: "unresolved"` with the annotation as `path_expression` — the contract the method-level path already honours — never a bare `/`. Regression on a fixture declaring its own composed annotation, plus a shenyu assertion that no published route is `/` |
539
+ | B29 | **A cache-freshness test asserts a cold cache without ensuring one, so it fails on every run but the first after a purge.** `tests/test_cli.py::test_compact` asserts `_meta.timing_ms.served_from_cache is False` and does nothing to make that true: the first `--compact` run over its fixture populates the cache the second one then hits. Verified symmetrically at `d9071d4` (clean) and at every commit of the seventh-pass queue — purge, run, pass; run again, fail — so it is **state-dependent, not a regression**, and it has been reported as "1 pre-existing failure" for the whole pass. It is still a red line in a suite whose value is that red means something. | found 2026-08-21 while establishing the baseline for the seventh-pass queue | **Low** as a defect, **medium** as an eroder — a permanently-red test trains a reader to skip the summary line, which is how a real regression gets shipped | **open** — direction: the test must create the state it asserts (purge this fixture's cache dir in the fixture, or assert the *transition* cold→warm across two runs rather than the absolute). Do not "fix" it by deleting the assertion: `served_from_cache` is the field `is_stale`/cache-freshness rows are keyed to, and a cold-start claim is worth holding |
410
540
  | E-37 | **Two environment variables move three cache stores, and no surface said which moves which.** `SOURCECODE_CACHE_DIR` relocates the per-repository snapshot store (core snapshots, the rendered L2 view, the RIS); `SOURCECODE_CONTEXT_CACHE_DIR` relocates the shared ones (the Canonical IR and the per-file parse store). Their defaults are siblings under `~/.sourcecode`, so the split is not derivable from the paths, and `cache status` published a path per store with no variable beside it while `docs/CACHE.md` named both variables in one sentence after the table. | found here 2026-08-18 while taking the controlled A/B `ASK-17` owed, not reported by the field | Medium — it does not make an answer wrong, it makes a **measurement** wrong, silently: an operator who redirects or empties *the cache* moves one store and is served answers out of the other | **closed 5.8.5** — measured first: with only `SOURCECODE_CONTEXT_CACHE_DIR` redirected, the second cold pass of each version answered from the L2 view its own first pass had written — **2,4 s against 113 s, with an empty parse store** — and the run reported `cache_source: L2_view` without anything naming the store it came out of. Now every store in `cache status` publishes `base_env`, from one authority (`cache._STORE_BASE_ENV`), the text answer prints *«<path> ($VAR moves it)»* beside each one, `stores.base_env_note` states the consequence rather than the layout, and `docs/CACHE.md` carries a **column** instead of a sentence covering both. Regression `tests/test_cache_store_base_env_e37.py`, 8 assertions, and the ones that matter are **behavioural**: setting the variable a store names moves *that* store and leaves the others where they were — a published mapping nobody exercises is the class of claim this repository refuses everywhere else. The CLI is forbidden a second copy of the mapping (structural assertion). **Confirmed from the outside in cycle 8, by the reporter falling into it first**: isolating only `SOURCECODE_CONTEXT_CACHE_DIR`, their second *cold* pass answered from the L2 view their first pass had written — **2,4 s against 113 s with an empty parse store** — and their write-up now quotes the shipped `base_env` mapping back as the fix (*"dos variables mueven tres almacenes y ninguna superficie decía cuál"*). A defect found while measuring, that was itself corrupting the measurement. |
411
541
  | B21 | **Six of the thirteen shapes being renamed name no command that emits them.** `schemas-v1` publishes `emitted_by` per shape; for `migration-blast-v1`, `spring-impact-v1`, `event-topology-v1`, `test-gap-ranking-v1`, `canonical-ir-v1` and `hibernate-strategy-v2` it is `[]`, beside seven shapes where it is populated. Read the way a consumer reads a list, an empty `emitted_by` says *nothing emits this shape* — which tells the one consumer that **is** affected by `BC-002` that it is not. | found here while declaring `BC-002` (5.8.5), not reported by the field | Low — a disclosure gap in a declaration whose whole purpose is to let a consumer decide whether it is affected | **closed 5.8.6 — derived, not typed out.** `schema_producers` reads the two authorities the CLI already holds — the registered command tree and the import graph of the module that defines each callback — and answers with the evidence it derived on: `command_import` (the command's own body imports the producing module), `module_import` (one hop, through an intermediate narrow enough to attribute), `substrate` (reached from more commands than a producer would be) or `unresolved` (nothing found, said in a sentence). Five of the six now name a command — `migration-blast-v1` → `migrate-check`, `spring-impact-v1` and `event-topology-v1` → `impact-chain`, `test-gap-ranking-v1` → `impact`, `hibernate-strategy-v2` → `migrate-check`/`migrate-recipe` — and the sixth, `canonical-ir-v1`, is reached from **28 modules**: naming every command would be less true than naming none, so it publishes `substrate` with the count and the instruction to match on `subject`. A declared producer still wins, because some producers are not one registered command (`ask (root)`, `baseline capture`). Regression `tests/test_schema_producers_derived_b21.py`, 33 assertions, parametrised by the registry so a fourteenth unnamed shape fails the battery. **History:** open, and named rather than shipped as a fact: every `BC-002` row with an empty producer list carries `emitted_by_basis` — *«not declared in the registry: this shape's producing command is not named yet, so match on `subject`»* — so the gap is visible instead of being read as a negative claim. What remains is to fill the six, and the honest way is derivation rather than six more hand-written strings: the producer is discoverable from the command that constructs each payload, which is the same authority every other population in this repository comes from. Until then the assertion in `tests/test_schema_rename_window_b20.py` holds the weaker invariant a reader can rely on: a row either names its emitters or says why it cannot. |
412
542
  | C3-129 | **`timeline`'s absolute cost, now fully attributed and still 27 % above its own record.** `C3-128` closed by instrumenting rather than tuning, which was the right order and left this behind: the clock is split, nothing is unaccounted, and the number has not moved. Round 10 on 5.8.5 measures `timeline --since HEAD~5` at **~198 000 ms against the 5.7.2 record of 155 950 ms (+27 %)** — the only gate-shaped command over 120 s that is not there structurally (`delta` 191 s and `contract-diff` 115 s walk two whole trees, `compare` 46 s walks N candidates; `timeline` walks **five** trees and costs more than `delta` does with two). | 5.8.2 → 5.8.5 re-audits (residual of `C3-128`, which closed the attribution half in 5.8.5) | Low-Medium — an investigation command rather than a CI gate, and the last performance figure of the round sitting outside its own best | **closed 5.8.6 — by not paying twice for what does not change.** A metric at a commit is a pure function of that tree, and the tree at a sha never changes: the only cache in this product whose key can be exact rather than heuristic (analyzer fingerprint + metric + commit sha). `timeline_cache.SampleCache` stores measured values under the per-repository core store, and when every watched metric for a sample is a hit the tree is **never materialised**, which is the 13,8 % the split attributes to git. Measured on BroadleafCommerce over the same range: **26 845 ms → 12 ms**, samples and transitions byte-identical. What makes it admissible rather than merely fast, all asserted: a failed sample is never stored (one bad run cannot become permanent), the fingerprint is in the key (corrected analysis is never served from a previous release), the hit is published (`sample_cache`, `from_cache` per sample, and `cost` separates the cached population from the measured one instead of reporting a median over both), and `--no-cache` / `ASK_TIMELINE_NO_SAMPLE_CACHE=1` measure everything again so the command stays measurable without emptying a store (E-37). `cache_model` carries the layer, so `cache model` and `docs/CACHE.md` state it from one authority. Regression `tests/test_timeline_sample_cache_c3_129.py`, 11 assertions. **History:** open — and it opened with the answer already published, which is why it is cheap to attack and expensive to leave: `timeline`'s own `timings` say **82,9 % `measure:posture`, 13,8 % `materialise_tree`, 3,3 % `release_tree`, 0,0 % unattributed**. So this is not a `timeline` defect at all: it is `posture` paid five times over five materialised trees, and it makes the same substrate question `C3-127` asks — with the difference that here the five payers are one command, so the cache is intra-invocation and needs no cross-command contract. ⚠ **Do not reopen `B7`**: cross-tree cache reuse is healthy, the v3 assertion passes at 6,8×. Acceptance: `timeline --since HEAD~5` back inside +10 % of 155 950 ms on the audited corpus with `timings` still summing to 100 %, and `measure:posture` falling as a share rather than the total falling for an unnamed reason. |
@@ -3,62 +3,114 @@
3
3
  *Chief-engineer development record. This is the internal, dev-facing counterpart to the
4
4
  customer-facing `docs/EXECUTIVE-ROADMAP.md`.*
5
5
 
6
- > **CURRENT STATE — seventh audit pass CLOSED, released as `5.8.17`, 2026-08-21**
6
+ > **CURRENT STATE — eighth audit pass CLOSED and shipped as `5.8.18`, 2026-08-21**
7
7
  >
8
- > The queue below is empty. All eleven rows of the seventh pass `AUD-591-A01`,
9
- > `AUD-590-R01`, `AUD-591-A03`, `AUD-591-A10`, `AUD-590-B01`, `AUD-591-A02`,
10
- > `AUD-590-B02`, `AUD-590-B04`, `AUD-590-B03`, `AUD-591-A06`, `AUD-591-A09` /
11
- > `A-08` / `A-05` are closed by correction, one commit per row, and the open
12
- > question `AUD-591-Q01` is answered. Full evidence per row: `docs/DEFECT-LEDGER.md`,
13
- > *Seventh Audit Pass*.
8
+ > The seventh-pass queue was closed and shipped as `5.8.17`; the eighth-pass queue is now
9
+ > closed and shipped as `5.8.18`, one fix per atomic commit with a focused regression
10
+ > assertion. Round A (MSAS, 3 342 files, 29 invocations,
11
+ > same HEAD as the previous round bit for bit) scores **8.77/10**, up from 8.21, with zero
12
+ > false statements about the repository for the second consecutive run. Round B (12-repo
13
+ > bank, ~150 invocations, §7 protocol) records **zero content regressions and no timing row
14
+ > above the ×1.25 threshold** — and both rounds together open **two regressions and eleven
15
+ > defects**. Full evidence per row: `docs/DEFECT-LEDGER.md`, *Eighth Audit Pass*. What is
16
+ > below is the attack order and the mechanism, not a second copy of the evidence.
14
17
  >
15
- > **What the pass found that the reports did not, and what it refuted:**
18
+ > **Release result all reported rows in this pass are closed:**
16
19
  >
17
- > - The `AUD-591-A01` sweep found **two further unguarded write paths**, and one of
18
- > them explains why a guard audit by module could not see them: `verify-edit
19
- > --install-hook` guarded the *hooks directory*, and `guard()` deliberately never
20
- > refuses a path that already exists `git init` always creates `hooks/`, so that
21
- > guard could not fire on any repository in the world.
22
- > - **The acceptance criterion proposed for `AUD-591-A01` cannot see the defect.**
23
- > `git status --porcelain == ""` is blind here: the first thing written into
24
- > `.ask/` is a `.gitignore` containing `*`. The sweep compares a filesystem
25
- > footprint of the whole tree, `.git/hooks/` included.
26
- > - **`AUD-591-A03` is wrong about its blast radius.** `rename-class --from` does
27
- > *not* share `_resolve_target`; it requires a file declaring the class and
28
- > refuses `--from O` outright. The one path that rewrites source was never
29
- > reachable from the substring match. `compute_blast_radius` is reached by
30
- > `impact`, `plan` and `compare`; `impact-chain` resolves separately.
31
- > - **`AUD-590-R01`'s hypothesis was half right and the sign was wrong.** Annotation
32
- > handling *is* the mechanism, but the census was **under**-counting: a
33
- > method-level `@GetMapping({"/a","/b"})` published `/a` and dropped `/b`, while
34
- > the class-level array had expanded correctly since always. Its other half
35
- > `no_security_signal` and `undocumented` is one number under two names, in both
36
- > authorities.
37
- > - **`AUD-590-B03`'s open question has the feared answer.** The predicate emitting
38
- > `security_surface` in `--compact` requires an annotation that *names a resource*;
39
- > `GATE-001..004` fire on any custom authorization mechanism. A gate with no
40
- > resource argument produces audit findings and no section. Disclosed in the
41
- > section's own `basis` rather than re-implemented.
42
- > - **`AUD-591-Q01` answered:** the snapshot layer is reachable and only the root
43
- > analysis writes it. All 240 invocations were of other commands, so `cold` was
44
- > correct on every one and said nothing about the cache.
20
+ > 1. **`AUD-592-R01` (P0, regression)** closed in the fix sequence; `compare` now owns
21
+ > and publishes its scan state.
22
+ >
23
+ > 2. **`AUD-592-R02` (P1, regression)**closed in the fix sequence; project summaries no
24
+ > longer promote licence/layout boilerplate as descriptive prose.
25
+ >
26
+ > 3. **`AUD-593-N01` through `AUD-593-N06`, `AUD-592-B01`, `AUD-592-A02`, `AUD-592-D01`
27
+ > through `AUD-592-D04`, `E-38`, and `B29`** closed in `5.8.18`; see the changelog
28
+ > and atomic commits for the authority, consumer, and regression evidence.
29
+ >
30
+ > The following material is the **historical attack-order record** from before `5.8.18`:
31
+ >
32
+ > 1. **`AUD-592-R01` (P0, historical regression)** — `compare` was dead on 5 of 5 valid
33
+ > invocations: `NameError: _compare_scan_trunc`, Rich traceback, no envelope, zero bytes
34
+ > of payload. The `AUD-591-A06` assignment landed in `plan_cmd` (`cli.py:8874`) and the
35
+ > read is in `compare_cmd` (`cli.py:8972`); the functions are `8818-8901` and `8903-9002`.
36
+ > **Confirmed by reading HEAD, not from the report.** Two more defects fall out of the
37
+ > same error: `plan` computes its truncation state and binds it to nothing, and
38
+ > `compare`'s `scope` fix at `:8975` sits after the raising line and has never run.
39
+ > 2. **`AUD-592-R02` (P1, regression of `AUD-513-N04`)** — `project_summary` publishes an
40
+ > Apache licence header as the project description on 3 of 8 repositories, with
41
+ > `summary_basis: "README descriptive prose"` asserting it is prose. Four holes in
42
+ > `summarizer.py`, all read at HEAD: HTML comments detected only on their opening line
43
+ > (`:335-337`) where `in_code_block` three lines above (`:326-330`) is the correct
44
+ > pattern; ATX-only headings (`:331`), so setext titles are content; a strict `< 30`
45
+ > floor (`:359`), so a 30-dash rule survives; `_LICENSE_MARKETING_RE` (`:266-281`) with
46
+ > no Apache/MIT/GPL/BSD pattern in it; and an unconditional `summary_basis` (`:382-385`).
47
+ > 3. **`AUD-593-N01` (P1)** `direct_caller_count` is 34 in `impact` and 554 in
48
+ > `impact-chain` for one symbol at one HEAD, both under `"distinct caller classes"`, and
49
+ > `FAN_IN_FIGURES` (`caller_metrics.py:80-110`) declares both rows the same `unit` **and**
50
+ > the same `population`. The populations are in fact different: `impact-chain` takes
51
+ > depth 1 from a seed set expanded with interface members (`spring_impact.py:1110-1135`,
52
+ > `caller_reach.py:309-336`), `impact` admits only references naming the target. **It
53
+ > falsifies the assertion `AUD-590-B02` was closed with** — that assertion passes on a
54
+ > fixture where the two coincide.
55
+ > 4. **`AUD-592-B01` (P1)** — `B-8` is marked `closed` and does not reproduce as closed:
56
+ > the code keeps a sample only when `unresolved == 1` (`cli.py:12653-12654`), the row
57
+ > promises it whenever the total is non-zero, and the field measures `total: 3, shown: 0`.
58
+ > 5. **P2 contract rows** — `AUD-592-A02` (scan truncation declared by 1 of 4 commands that
59
+ > own a walk; `plan` computes it and drops it; the root help still cites a 25 000
60
+ > directory-entry cap against an 8 000-file cap observed), `AUD-593-N02` (the `--compact`
61
+ > budget published three times in two shipped authorities: `--help` generates it from
62
+ > `output_budget`, the packaged `docs/USER_GUIDE.md` does not — `:111`, `:243`/`:1366`,
63
+ > `:254`/`:1367`), `AUD-593-N03` (`cli.py:621-622` still says the budget variable bounds
64
+ > only three commands, after `AUD-590-B04` extended it to the root — the command that
65
+ > most needs it).
66
+ > 6. **P3 residuals** — `AUD-593-N05` (a fan-in figure emitted outside `FAN_IN_FIGURES`,
67
+ > which forbids exactly that), `AUD-593-N06` (a silent `[:30]` at `repository_ir.py:10172`
68
+ > where every sibling list declares its cap), `AUD-592-D01` (the write inventory names
69
+ > `--history-dir` where `--snapshot` writes — `cli.py:296` against the code's own comment
70
+ > at `:12980-12986`), `AUD-592-D02`/`D03` (`--min-band` publishes no `_filter`; `enrich
71
+ > --rule` accepts an unknown id where `spring-audit` rejects it), `AUD-592-D04`
72
+ > (`build_commit: unrecorded`, fourth consecutive report — the precondition for every
73
+ > other row being falsifiable from outside).
74
+ >
75
+ > **Carried, unchanged, from the seventh pass:** **`E-38`** (High) — a class-level route
76
+ > prefix carried by a meta-annotation is dropped; 35 of 365 shenyu routes published as
77
+ > `path: "/"`; the machinery exists on the bean axis (`E-12`) and the route axis never asked
78
+ > for it. **`B29`** (Low) — `tests/test_cli.py::test_compact` asserts a cold cache without
79
+ > making one, so it fails on every run but the first after a purge.
80
+ >
81
+ > **What the pass refuted, and what it corrected about itself** — do not re-derive:
82
+ >
83
+ > - `posture --profile` accepting an undeclared profile is **by design**: a hypothesis
84
+ > input, not a catalogue name, and `profiles_requested` is published beside
85
+ > `profiles_declared`. The bank round withdrew the finding after reading the payload.
86
+ > - The MSAS round's first mechanism for `AUD-593-N01` — *"the `direct_caller_*` fields are
87
+ > wired to the chain totals"* — is **wrong**, and it corrected itself: the count does
88
+ > derive from `direct_callers`, and the empty `indirect_callers` is the hub guard capping
89
+ > the walk to depth 1, which **is** declared. The defect is one layer up, in what each
90
+ > command admits as *direct*.
91
+ > - `AUD-590-R01`'s double-counting hypothesis was **refuted with the product's own data**:
92
+ > `route_census` shows `mappings 3763` against `on_rows 1120` with `distinct_routes ≥
93
+ > mappings`, so the total is not an expansion inflating a smaller surface.
45
94
  >
46
95
  > **Traps this pass leaves for the next one:**
47
96
  >
48
- > - `last_scan_truncation()` is ambient by design and must be read *at the call
49
- > site*, immediately after the walk that produced the file list. Several paths do
50
- > their own uncapped `rglob` `extract_java_endpoints` among them and reading it
51
- > there attaches a previous walk's warning to a complete answer. A test holds that.
52
- > - `_build_help_text()` runs at import (`_HELP = _build_help_text()`), so any helper
53
- > it interpolates must be defined **above** it, not merely before use.
54
- > - Four ledger/registry batteries caught new work before it was committed and are
55
- > worth trusting: the `SpringAuditResult.merge` field guard, the schema registry's
56
- > emitted-literal check, the `docs/CACHE.md` drift check, and `N-3`'s advisory
57
- > assertion.
58
- > - `test_cli.py::test_compact` asserts a cold cache without ensuring one. It fails
59
- > on the second run at any HEAD and passes on the first after a purge — identical
60
- > before and after every commit in this pass. It is not a regression and it is not
61
- > yet a row.
97
+ > - `last_scan_truncation()` is ambient by design and must be read **at the call site**,
98
+ > right after the walk that produced the file list. `AUD-592-R01` is what happens when
99
+ > that reading is a free-floating local: it compiled, it imported, and it died on every
100
+ > call. A test that *imports* a command cannot see this; one that *calls* it can.
101
+ > - `_build_help_text()` runs at import (`_HELP = _build_help_text()`), so any helper it
102
+ > interpolates must be defined **above** it, not merely before use.
103
+ > - The four ledger/registry batteries from the previous pass remain worth trusting: the
104
+ > `SpringAuditResult.merge` field guard, the schema registry's emitted-literal check, the
105
+ > `docs/CACHE.md` drift check, and `N-3`'s advisory assertion.
106
+ >
107
+ > **The three process rules this pass makes non-optional** (the ledger carries the evidence):
108
+ > close a class with a parametric test over the catalogue that already exists
109
+ > (`FAN_IN_FIGURES`, `COMMANDS_THAT_WRITE`, the section registry), never over the reported
110
+ > symbol — the three classes closed as sweeps did not recur and three of three closed by
111
+ > instance did; never leave `closed` standing on a row whose assertion cannot fail on the
112
+ > tree that produced the defect; and treat every packaged `.md` as a published authority
113
+ > inside the same release assertion as `--help`.
62
114
 
63
115
  ---
64
116