sourcecode 5.8.24__py3-none-any.whl → 5.8.26__py3-none-any.whl
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.
- sourcecode/__init__.py +1 -1
- sourcecode/_build_commit.py +3 -3
- sourcecode/_docs/DEFECT-LEDGER.md +317 -1
- sourcecode/_docs/USER_GUIDE.md +16 -7
- sourcecode/analysis_budget.py +26 -0
- sourcecode/audit_report.py +43 -0
- sourcecode/baseline_autocapture.py +9 -4
- sourcecode/cache.py +67 -1
- sourcecode/cache_model.py +8 -5
- sourcecode/cache_observation.py +148 -0
- sourcecode/cli.py +230 -29
- sourcecode/context_cache.py +11 -0
- sourcecode/envelope.py +21 -4
- sourcecode/explain.py +43 -1
- sourcecode/format_contract.py +3 -3
- sourcecode/migrate_check.py +21 -2
- sourcecode/non_coverage.py +46 -1
- sourcecode/output_ceiling.py +59 -4
- sourcecode/packs.py +85 -1
- sourcecode/parse_cache.py +16 -0
- sourcecode/posture.py +17 -1
- sourcecode/product_info.py +25 -1
- sourcecode/regress.py +38 -0
- sourcecode/release_info.py +1 -1
- sourcecode/repository_ir.py +118 -50
- sourcecode/resource_budget.py +137 -9
- sourcecode/sarif_emit.py +156 -0
- sourcecode/schema_registry.py +5 -0
- sourcecode/security_posture.py +12 -0
- sourcecode/selftest.py +8 -2
- sourcecode/serializer.py +21 -2
- sourcecode/spring_impact.py +101 -0
- sourcecode/spring_tx_analyzer.py +8 -0
- sourcecode/timeline_cache.py +24 -4
- sourcecode/workspace.py +1 -1
- {sourcecode-5.8.24.dist-info → sourcecode-5.8.26.dist-info}/METADATA +4 -4
- {sourcecode-5.8.24.dist-info → sourcecode-5.8.26.dist-info}/RECORD +41 -39
- {sourcecode-5.8.24.dist-info → sourcecode-5.8.26.dist-info}/WHEEL +0 -0
- {sourcecode-5.8.24.dist-info → sourcecode-5.8.26.dist-info}/entry_points.txt +0 -0
- {sourcecode-5.8.24.dist-info → sourcecode-5.8.26.dist-info}/licenses/LICENSE +0 -0
- {sourcecode-5.8.24.dist-info → sourcecode-5.8.26.dist-info}/licenses/NOTICE +0 -0
sourcecode/__init__.py
CHANGED
sourcecode/_build_commit.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""Generated at build time by hatch_build.py. Do not edit (AUD-592-D04)."""
|
|
2
2
|
|
|
3
|
-
BUILD_COMMIT = '
|
|
4
|
-
CLOSURE_PROVENANCE = {'Window': {'commit': '', 'status': 'uncited'}, '`AUD-588-F05`': {'commit': '470e4a4', 'status': 'present'}, '`AUD-590-B01` / `B-01`, `F-01`': {'commit': '', 'status': 'uncited'}, '`AUD-590-B02` / `B-02`, `F-02`': {'commit': '', 'status': 'uncited'}, '`AUD-590-B03` / `B-03`, `F-03`': {'commit': '', 'status': 'uncited'}, '`AUD-590-B04` / `B-04`, `F-04`': {'commit': '', 'status': 'uncited'}, '`AUD-590-R01` / `R-01`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A01` / `A-1`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A02` / `A-2`, `A-4`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A03` / `A-3`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A05` / `A-5`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A06` / `A-6`, `A-7`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A08` / `A-8`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A09` / `A-9`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A10` / `A-10`': {'commit': '', 'status': 'uncited'}, '`AUD-592-A02` / `A-1` second half, `§12.5`': {'commit': '63f3d61', 'status': 'present'}, '`AUD-592-B01` / `B-8`': {'commit': '8329614', 'status': 'present'}, '`AUD-592-D01` / `D-1`': {'commit': '0f8e03f', 'status': 'present'}, '`AUD-592-D02` / `D-2`': {'commit': '1d3db4d', 'status': 'present'}, '`AUD-592-D03` / `D-3`': {'commit': 'f28fe40', 'status': 'present'}, '`AUD-592-R01` / `A-1`': {'commit': '216025f', 'status': 'present'}, '`AUD-592-R02` / `N-4`, reopens `AUD-513-N04`': {'commit': 'ec3050d', 'status': 'present'}, '`AUD-593-N01` / `N-01`': {'commit': 'dd6a706', 'status': 'present'}, '`AUD-593-N02` / `N-02`': {'commit': 'f539787', 'status': 'present'}, '`AUD-593-N03` / `N-03`': {'commit': '1dd0b1c', 'status': 'present'}, '`AUD-593-N05` / `N-05`': {'commit': 'aa89388', 'status': 'present'}, '`AUD-593-N06` / `N-06`': {'commit': 'aa584a6', 'status': 'present'}, '`AUD-594-N04` / `D-5`, disclosure half of `B-3`': {'commit': 'a0060b7', 'status': 'present'}, '`AUD-594-X01` / `A-1`, residual of `AUD-593-N03`': {'commit': 'dd222b9', 'status': 'present'}, '`AUD-594-X02` / `A-1` second half': {'commit': '1193937', 'status': 'present'}, '`AUD-594-X03` / `X-03`, residual of `AUD-593-N01`': {'commit': 'e89e8f0', 'status': 'present'}, '`AUD-594-X04`': {'commit': '05b8cc9', 'status': 'present'}, '`AUD-595-A02` / `N-5`, advisory half of `AUD-588-B11`': {'commit': '3e15227', 'status': 'present'}, '`AUD-595-A03` / `B-6` exit-code half': {'commit': 'ab7285f', 'status': 'present'}, '`AUD-595-A05`': {'commit': 'e0b3d10', 'status': 'present'}, '`AUD-595-A07`, narrow half of `AUD-592-A02`': {'commit': 'cc15177', 'status': 'present'}, '`AUD-595-B01` / §B': {'commit': 'b77a1ad', 'status': 'present'}, '`AUD-595-Q01`': {'commit': '91a6566', 'status': 'present'}, '`AUD-596-A01` / `ASK-DET-001`': {'commit': 'fa508b4', 'status': 'present'}, '`AUD-596-A02` / `ASK-SELF-001`': {'commit': '4dfadc8', 'status': 'present'}, '`AUD-596-A03` / `ASK-C1-001`': {'commit': 'bffa3a6', 'status': 'present'}, '`AUD-596-A04` / `ASK-UX-003` + `ASK-UX-004`': {'commit': 'f0aac3c', 'status': 'present'}, '`AUD-596-B01` / `B-01`, harder witness for `BUG-6`': {'commit': '567d09d', 'status': 'present'}, '`AUD-596-B02` / `B-02`, class residual of `R2`': {'commit': '', 'status': 'uncited'}, '`AUD-596-B03` / `B-03`': {'commit': 'a8cb814', 'status': 'present'}, '`AUD-596-B06` / `B-06`': {'commit': '8107927', 'status': 'present'}, '`AUD-596-B07` / `B-07`, class residual of `AUD-592-R02`': {'commit': 'e060485', 'status': 'present'}, '`AUD-596-B09` / `B-09`': {'commit': '5b8146c', 'status': 'present'}, '`AUD-596-B10` / `B-10`': {'commit': '5cb994d', 'status': 'present'}, '`AUD-596-B16` / `B-16`': {'commit': '1507f69', 'status': 'present'}, '`AUD-596-D01` / `B-13` + `B-14`': {'commit': '0b1bdf0', 'status': 'present'}, '`AUD-596-D02` / `B-08`, residual of `AUD-594-N04`': {'commit': 'e7f73c3', 'status': 'present'}, '`AUD-596-D03` / `ASK-AGT-001`': {'commit': '8c46967', 'status': 'present'}, '`AUD-596-D04` / `B-18`': {'commit': '040f027', 'status': 'present'}, '`AUD-596-D05` / `B-19`': {'commit': 'fd2bf68', 'status': 'present'}, '`AUD-596-D06` / `B-20`': {'commit': '784cd83', 'status': 'present'}, '`AUD-596-D07` / `B-17`, half refuted': {'commit': 'c3ff822', 'status': 'present'}, '`AUD-596-D08` / `B-22`, class residual of `AUD-591-A06`': {'commit': 'b396c6a', 'status': 'present'}, '`AUD-596-D09` / `B-23`, surviving half of `B26`': {'commit': 'fd3d63f', 'status': 'present'}, '`AUD-596-D10` / `B-29`': {'commit': '', 'status': 'uncited'}, '`AUD-596-D11` / `ASK-UX-005`': {'commit': 'f4b4f77', 'status': 'present'}, '`AUD-596-D12` — six hints that send the reader back to the error': {'commit': '498df44', 'status': 'present'}, '`AUD-596-D13` / `B-28`': {'commit': '1014c72', 'status': 'present'}, '`AUD-596-D14` / `B-15`, narrow half of `B20`': {'commit': '10f2827', 'status': 'present'}, '`AUD-596-R01` / `B-05`': {'commit': '', 'status': 'uncited'}, '`AUD-596-X01` / `ASK-GATE-001`, gating half of `B24`': {'commit': 'e59c655', 'status': 'present'}, '`AUD-596-X02` / `ASK-UX-001` + `ASK-UX-002` + `B-21`': {'commit': 'f6ebf50', 'status': 'present'}, '`AUD-597-A01` / `ASK-UX-001` + `N-01`': {'commit': 'f8cf061', 'status': 'present'}, '`AUD-597-A02` / `ASK-UX-008` + `ASK-DOC-002`': {'commit': '9d47a4c', 'status': 'present'}, '`AUD-597-A03` / `ASK-DET-001`': {'commit': '4c7622a', 'status': 'present'}, '`AUD-597-A04` / `ASK-LEDGER-001`': {'commit': '46fb870', 'status': 'present'}, '`AUD-597-D01` / `B-04`': {'commit': '1094e6a', 'status': 'present'}, '`AUD-597-D02` / `ASK-DOC-001`': {'commit': 'ecb1bb7', 'status': 'present'}, '`AUD-597-D03` / `N-06`': {'commit': '9784333', 'status': 'present'}, '`AUD-597-D04` / `N-05`': {'commit': 'e51c087', 'status': 'present'}, '`AUD-597-D05` / `N-04`, fourth appearance of `C4-27`': {'commit': '9cccc15', 'status': 'present'}, '`AUD-597-D06` / `ASK-CLI-001`': {'commit': '178aa6d', 'status': 'present'}, '`AUD-597-D07` / `N-03`': {'commit': '9245e35', 'status': 'present'}, '`AUD-597-R01` / `ASK-PERF-001`': {'commit': '6910054', 'status': 'present'}, '`AUD-597-R02` / `ASK-ENC-001`': {'commit': 'ce6dac1', 'status': 'present'}, '`AUD-597-R03` / `ASK-UX-002`': {'commit': 'c57e50b', 'status': 'present'}, '`AUD-597-X01` / `ASK-BUILD-001` + `ASK-META-001` / `B-12`': {'commit': '354338b', 'status': 'present'}, '`AUD-598-B01` / `ASK-META-001`': {'commit': 'b2f7c65', 'status': 'present'}, '`AUD-598-B02` / `ASK-UX-002`': {'commit': '56a4bf7', 'status': 'present'}, '`AUD-598-B03` / `B-11`': {'commit': 'c63cb24', 'status': 'present'}, '`AUD-598-B04` / `N-02`': {'commit': '187937f', 'status': 'present'}, '`AUD-598-R01` / `ASK-PERF-002`': {'commit': '', 'status': 'uncited'}, '`AUD-598-X01` / `N-01` + `B-13` + `B-14` + `B-29` + `N-06`': {'commit': '6f2f5a4', 'status': 'present'}, '`AUD-600-B01` / `P-01`': {'commit': '366ffed', 'status': 'present'}, '`AUD-600-B02` / `P-02` + `ASK-PACK-002`': {'commit': '2a814c3', 'status': 'present'}, '`AUD-600-B03` / `ASK-PACK-001`': {'commit': '452f2a0', 'status': 'present'}, '`AUD-600-D01`': {'commit': '1224e1b', 'status': 'present'}, '`AUD-600-D02`': {'commit': 'eab8172', 'status': 'present'}, '`AUD-600-R01` / `R-01`': {'commit': '88add64', 'status': 'present'}, '`B-3`': {'commit': '773268d', 'status': 'present'}, '`B-6`': {'commit': '17c6e06', 'status': 'present'}, '`B-8`': {'commit': '8329614', 'status': 'present'}, '`BUG-3` / `443b345`': {'commit': '', 'status': 'uncited'}, '`BUG-4a` / `AUD-588-B11` residual': {'commit': '24b4185', 'status': 'present'}, '`BUG-4b` / `AUD-588-B11` residual': {'commit': '0376350', 'status': 'present'}, '`E-39`, class residual of `AUD-593-N06`': {'commit': '25fc11f', 'status': 'present'}, '`N-5`': {'commit': 'c68083f', 'status': 'present'}, '`N-7`': {'commit': '082e9de', 'status': 'present'}, '`R-1`': {'commit': '424fb1c', 'status': 'present'}, '`R-2`': {'commit': '5158b92', 'status': 'present'}, '`R-3`': {'commit': '88aec04', 'status': 'present'}, '`R-4`': {'commit': '04fd04f', 'status': 'present'}}
|
|
5
|
-
CLOSURE_COVERAGE = {'closed_rows':
|
|
3
|
+
BUILD_COMMIT = 'e2da5d84a30bc2e8c60325e1e2d48a8d736b8ad7'
|
|
4
|
+
CLOSURE_PROVENANCE = {'Window': {'commit': '', 'status': 'uncited'}, '`AUD-588-F05`': {'commit': '470e4a4', 'status': 'present'}, '`AUD-590-B01` / `B-01`, `F-01`': {'commit': '', 'status': 'uncited'}, '`AUD-590-B02` / `B-02`, `F-02`': {'commit': '', 'status': 'uncited'}, '`AUD-590-B03` / `B-03`, `F-03`': {'commit': '', 'status': 'uncited'}, '`AUD-590-B04` / `B-04`, `F-04`': {'commit': '', 'status': 'uncited'}, '`AUD-590-R01` / `R-01`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A01` / `A-1`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A02` / `A-2`, `A-4`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A03` / `A-3`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A05` / `A-5`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A06` / `A-6`, `A-7`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A08` / `A-8`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A09` / `A-9`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A10` / `A-10`': {'commit': '', 'status': 'uncited'}, '`AUD-592-A02` / `A-1` second half, `§12.5`': {'commit': '63f3d61', 'status': 'present'}, '`AUD-592-B01` / `B-8`': {'commit': '8329614', 'status': 'present'}, '`AUD-592-D01` / `D-1`': {'commit': '0f8e03f', 'status': 'present'}, '`AUD-592-D02` / `D-2`': {'commit': '1d3db4d', 'status': 'present'}, '`AUD-592-D03` / `D-3`': {'commit': 'f28fe40', 'status': 'present'}, '`AUD-592-R01` / `A-1`': {'commit': '216025f', 'status': 'present'}, '`AUD-592-R02` / `N-4`, reopens `AUD-513-N04`': {'commit': 'ec3050d', 'status': 'present'}, '`AUD-593-N01` / `N-01`': {'commit': 'dd6a706', 'status': 'present'}, '`AUD-593-N02` / `N-02`': {'commit': 'f539787', 'status': 'present'}, '`AUD-593-N03` / `N-03`': {'commit': '1dd0b1c', 'status': 'present'}, '`AUD-593-N05` / `N-05`': {'commit': 'aa89388', 'status': 'present'}, '`AUD-593-N06` / `N-06`': {'commit': 'aa584a6', 'status': 'present'}, '`AUD-594-N04` / `D-5`, disclosure half of `B-3`': {'commit': 'a0060b7', 'status': 'present'}, '`AUD-594-X01` / `A-1`, residual of `AUD-593-N03`': {'commit': 'dd222b9', 'status': 'present'}, '`AUD-594-X02` / `A-1` second half': {'commit': '1193937', 'status': 'present'}, '`AUD-594-X03` / `X-03`, residual of `AUD-593-N01`': {'commit': 'e89e8f0', 'status': 'present'}, '`AUD-594-X04`': {'commit': '05b8cc9', 'status': 'present'}, '`AUD-595-A02` / `N-5`, advisory half of `AUD-588-B11`': {'commit': '3e15227', 'status': 'present'}, '`AUD-595-A03` / `B-6` exit-code half': {'commit': 'ab7285f', 'status': 'present'}, '`AUD-595-A05`': {'commit': 'e0b3d10', 'status': 'present'}, '`AUD-595-A07`, narrow half of `AUD-592-A02`': {'commit': 'cc15177', 'status': 'present'}, '`AUD-595-B01` / §B': {'commit': 'b77a1ad', 'status': 'present'}, '`AUD-595-Q01`': {'commit': '91a6566', 'status': 'present'}, '`AUD-596-A01` / `ASK-DET-001`': {'commit': 'fa508b4', 'status': 'present'}, '`AUD-596-A02` / `ASK-SELF-001`': {'commit': '4dfadc8', 'status': 'present'}, '`AUD-596-A03` / `ASK-C1-001`': {'commit': 'bffa3a6', 'status': 'present'}, '`AUD-596-A04` / `ASK-UX-003` + `ASK-UX-004`': {'commit': 'f0aac3c', 'status': 'present'}, '`AUD-596-B01` / `B-01`, harder witness for `BUG-6`': {'commit': '567d09d', 'status': 'present'}, '`AUD-596-B02` / `B-02`, class residual of `R2`': {'commit': '', 'status': 'uncited'}, '`AUD-596-B03` / `B-03`': {'commit': 'a8cb814', 'status': 'present'}, '`AUD-596-B06` / `B-06`': {'commit': '8107927', 'status': 'present'}, '`AUD-596-B07` / `B-07`, class residual of `AUD-592-R02`': {'commit': 'e060485', 'status': 'present'}, '`AUD-596-B09` / `B-09`': {'commit': '5b8146c', 'status': 'present'}, '`AUD-596-B10` / `B-10`': {'commit': '5cb994d', 'status': 'present'}, '`AUD-596-B16` / `B-16`': {'commit': '1507f69', 'status': 'present'}, '`AUD-596-D01` / `B-13` + `B-14`': {'commit': '0b1bdf0', 'status': 'present'}, '`AUD-596-D02` / `B-08`, residual of `AUD-594-N04`': {'commit': 'e7f73c3', 'status': 'present'}, '`AUD-596-D03` / `ASK-AGT-001`': {'commit': '8c46967', 'status': 'present'}, '`AUD-596-D04` / `B-18`': {'commit': '040f027', 'status': 'present'}, '`AUD-596-D05` / `B-19`': {'commit': 'fd2bf68', 'status': 'present'}, '`AUD-596-D06` / `B-20`': {'commit': '784cd83', 'status': 'present'}, '`AUD-596-D07` / `B-17`, half refuted': {'commit': 'c3ff822', 'status': 'present'}, '`AUD-596-D08` / `B-22`, class residual of `AUD-591-A06`': {'commit': 'b396c6a', 'status': 'present'}, '`AUD-596-D09` / `B-23`, surviving half of `B26`': {'commit': 'fd3d63f', 'status': 'present'}, '`AUD-596-D10` / `B-29`': {'commit': '', 'status': 'uncited'}, '`AUD-596-D11` / `ASK-UX-005`': {'commit': 'f4b4f77', 'status': 'present'}, '`AUD-596-D12` — six hints that send the reader back to the error': {'commit': '498df44', 'status': 'present'}, '`AUD-596-D13` / `B-28`': {'commit': '1014c72', 'status': 'present'}, '`AUD-596-D14` / `B-15`, narrow half of `B20`': {'commit': '10f2827', 'status': 'present'}, '`AUD-596-R01` / `B-05`': {'commit': '', 'status': 'uncited'}, '`AUD-596-X01` / `ASK-GATE-001`, gating half of `B24`': {'commit': 'e59c655', 'status': 'present'}, '`AUD-596-X02` / `ASK-UX-001` + `ASK-UX-002` + `B-21`': {'commit': 'f6ebf50', 'status': 'present'}, '`AUD-597-A01` / `ASK-UX-001` + `N-01`': {'commit': 'f8cf061', 'status': 'present'}, '`AUD-597-A02` / `ASK-UX-008` + `ASK-DOC-002`': {'commit': '9d47a4c', 'status': 'present'}, '`AUD-597-A03` / `ASK-DET-001`': {'commit': '4c7622a', 'status': 'present'}, '`AUD-597-A04` / `ASK-LEDGER-001`': {'commit': '46fb870', 'status': 'present'}, '`AUD-597-D01` / `B-04`': {'commit': '1094e6a', 'status': 'present'}, '`AUD-597-D02` / `ASK-DOC-001`': {'commit': 'ecb1bb7', 'status': 'present'}, '`AUD-597-D03` / `N-06`': {'commit': '9784333', 'status': 'present'}, '`AUD-597-D04` / `N-05`': {'commit': 'e51c087', 'status': 'present'}, '`AUD-597-D05` / `N-04`, fourth appearance of `C4-27`': {'commit': '9cccc15', 'status': 'present'}, '`AUD-597-D06` / `ASK-CLI-001`': {'commit': '178aa6d', 'status': 'present'}, '`AUD-597-D07` / `N-03`': {'commit': '9245e35', 'status': 'present'}, '`AUD-597-R01` / `ASK-PERF-001`': {'commit': '6910054', 'status': 'present'}, '`AUD-597-R02` / `ASK-ENC-001`': {'commit': 'ce6dac1', 'status': 'present'}, '`AUD-597-R03` / `ASK-UX-002`': {'commit': 'c57e50b', 'status': 'present'}, '`AUD-597-X01` / `ASK-BUILD-001` + `ASK-META-001` / `B-12`': {'commit': '354338b', 'status': 'present'}, '`AUD-598-B01` / `ASK-META-001`': {'commit': 'b2f7c65', 'status': 'present'}, '`AUD-598-B02` / `ASK-UX-002`': {'commit': '56a4bf7', 'status': 'present'}, '`AUD-598-B03` / `B-11`': {'commit': 'c63cb24', 'status': 'present'}, '`AUD-598-B04` / `N-02`': {'commit': '187937f', 'status': 'present'}, '`AUD-598-R01` / `ASK-PERF-002`': {'commit': '', 'status': 'uncited'}, '`AUD-598-X01` / `N-01` + `B-13` + `B-14` + `B-29` + `N-06`': {'commit': '6f2f5a4', 'status': 'present'}, '`AUD-600-B01` / `P-01`': {'commit': '366ffed', 'status': 'present'}, '`AUD-600-B02` / `P-02` + `ASK-PACK-002`': {'commit': '2a814c3', 'status': 'present'}, '`AUD-600-B03` / `ASK-PACK-001`': {'commit': '452f2a0', 'status': 'present'}, '`AUD-600-D01`': {'commit': '1224e1b', 'status': 'present'}, '`AUD-600-D02`': {'commit': 'eab8172', 'status': 'present'}, '`AUD-600-R01` / `R-01`': {'commit': '88add64', 'status': 'present'}, '`AUD-601-B01` / `N-02`, 5th round': {'commit': '', 'status': 'uncited'}, '`AUD-601-B02` / `ASK-PACK-004`': {'commit': '', 'status': 'uncited'}, '`AUD-601-D01` / `N-01`, `ASK-UX-001`, 5th round': {'commit': '', 'status': 'uncited'}, '`AUD-601-D02` / `B-13`, `B-14`, 5th round': {'commit': '', 'status': 'uncited'}, '`AUD-601-M01` / `B-26`, `B-27` retracted': {'commit': '', 'status': 'uncited'}, '`AUD-601-R01` / `R-02`': {'commit': '', 'status': 'uncited'}, '`B-3`': {'commit': '773268d', 'status': 'present'}, '`B-6`': {'commit': '17c6e06', 'status': 'present'}, '`B-8`': {'commit': '8329614', 'status': 'present'}, '`BUG-3` / `443b345`': {'commit': '', 'status': 'uncited'}, '`BUG-4a` / `AUD-588-B11` residual': {'commit': '24b4185', 'status': 'present'}, '`BUG-4b` / `AUD-588-B11` residual': {'commit': '0376350', 'status': 'present'}, '`E-39`, class residual of `AUD-593-N06`': {'commit': '25fc11f', 'status': 'present'}, '`N-5`': {'commit': 'c68083f', 'status': 'present'}, '`N-7`': {'commit': '082e9de', 'status': 'present'}, '`R-1`': {'commit': '424fb1c', 'status': 'present'}, '`R-2`': {'commit': '5158b92', 'status': 'present'}, '`R-3`': {'commit': '88aec04', 'status': 'present'}, '`R-4`': {'commit': '04fd04f', 'status': 'present'}}
|
|
5
|
+
CLOSURE_COVERAGE = {'closed_rows': 113, 'present': 88, 'absent': 0, 'unresolved': 0, 'uncited': 25, 'unknown': 0}
|
|
@@ -16,6 +16,105 @@ The facts these rows are keyed to are published: `ask schema facts-v1` prints th
|
|
|
16
16
|
|
|
17
17
|
## Current Synchronization
|
|
18
18
|
|
|
19
|
+
**Corpus ampliado recibido, 2026-08-23 — 17 hallazgos nuevos en intake.**
|
|
20
|
+
[`AUDIT-2026-08-23-CORPUS-AMPLIADO.md`](AUDIT-2026-08-23-CORPUS-AMPLIADO.md) registra cuatro
|
|
21
|
+
P0 (`AUD-CA-001`, `002`, `003`, `014`), ocho P1, cuatro P2 y un P3. La evidencia externa
|
|
22
|
+
aporta reproducción y contraste manual, pero estas filas permanecen **pendientes de
|
|
23
|
+
reproducción contra checkout/wheel**: no se declaran corregidas ni se atribuyen al código
|
|
24
|
+
auditado. La prioridad inmediata es seguridad no modelada, colisiones de FQN y superficie
|
|
25
|
+
HTTP Micronaut; después siguen contratos de inventario, cobertura y precisión de salida.
|
|
26
|
+
|
|
27
|
+
**Correcciones iniciadas, 2026-08-23.** `AUD-CA-001` (declaración segura de Shiro),
|
|
28
|
+
`AUD-CA-005` (autoridad de `src/main`), `AUD-CA-013` (sobrecargas y anclas de
|
|
29
|
+
`explain`) y `AUD-CA-017` (contador estructurado) están corregidos en commits atómicos
|
|
30
|
+
de `5.8.25`. `AUD-CA-014` tiene una corrección parcial: Micronaut ya aparece como
|
|
31
|
+
superficie detectada-no-modelada y cuantificada, pero el soporte HTTP sigue pendiente.
|
|
32
|
+
Los restantes hallazgos permanecen abiertos hasta reproducirlos y cubrirlos con pruebas.
|
|
33
|
+
|
|
34
|
+
**Estado autoritativo del repositorio, 2026-08-23 — `5.8.25`, `HEAD 3d56d11`.** Este
|
|
35
|
+
snapshot supersede cualquier estado de release indicado en las secciones históricas de
|
|
36
|
+
este ledger. La batería completa pasa en verde cuando se configuran ambos almacenes
|
|
37
|
+
temporales: `SOURCECODE_CONTEXT_CACHE_DIR` para CIR/parse y `SOURCECODE_CACHE_DIR` para
|
|
38
|
+
snapshots/RIS. Usar sólo el primer directorio produce falsos fallos de persistencia.
|
|
39
|
+
|
|
40
|
+
Los commits `125e486`, `735d766`, `434d0e2`, `cd3f8f1`, `e9f5861`, `49187f9` y `3d56d11` están incluidos
|
|
41
|
+
en el checkout actual. Cubren rutas
|
|
42
|
+
Windows, selftest con `ask.exe`, resolución bounded de comandos y flags, fallback de
|
|
43
|
+
contexto, rutas POSIX del workspace, salida estable del job Windows, fingerprint sin estado
|
|
44
|
+
runtime de caché, sweep final del parse cache, gate CI de migraciones, trazabilidad explícita
|
|
45
|
+
de benchmarks históricos y aislamiento de observabilidad por invocación. Por tanto,
|
|
46
|
+
`ASK-UX-001`, `ASK-UX-002` y `ASK-ENV-001` ya no deben describirse como fallos sin
|
|
47
|
+
corrección: quedan **pendientes de verificación contra el wheel publicado y de confirmación
|
|
48
|
+
en GitHub Windows**.
|
|
49
|
+
|
|
50
|
+
La cola abierta actual es: validación externa de `ASK-DET-002`, `B-26` y `ASK-GATE-001`,
|
|
51
|
+
regeneración reproducible de cifras `B-11`, `ASK-PERF-003` (medición aislada aún
|
|
52
|
+
necesaria), `B-13`/`B-14` (reconciliación contra artefacto exacto), y la deuda P3 de filas
|
|
53
|
+
sin cita y `B-30`. No quedan fallos locales reproducidos pendientes en esta batería.
|
|
54
|
+
|
|
55
|
+
Las menciones posteriores a `5.8.24`, “release/commit pending” o “no audit, no release”
|
|
56
|
+
son fotografías históricas de sus respectivas iteraciones. Se mantienen para trazabilidad,
|
|
57
|
+
pero no representan el estado vigente ni deben usarse para decidir el siguiente release.
|
|
58
|
+
|
|
59
|
+
**External `5.8.25` regression audit received, 2026-08-23 — triage recorded.**
|
|
60
|
+
[`AUDIT-2026-08-23-EXTERNAL-5.8.25.md`](AUDIT-2026-08-23-EXTERNAL-5.8.25.md) separates the
|
|
61
|
+
Windows/MSAS wheel evidence from this checkout. The only new confirmed product defect is
|
|
62
|
+
`ASK-DET-002`: root `content_id` changes between cold and warm runs because `_cache` runtime
|
|
63
|
+
state is included in the answer fingerprint. `ASK-UX-001`/`ASK-UX-002` and
|
|
64
|
+
`ASK-GATE-001` remain actionable contract residues in the audited artefact; `ASK-ENV-001`
|
|
65
|
+
is a Windows-specific witness still requiring reproduction. `B-26` is recorded as a fleet
|
|
66
|
+
capacity issue (559.48 MB against 512 MB), not as a finding-analysis error. The reported
|
|
67
|
+
performance deltas are not accepted as regressions until isolated measurements control cache
|
|
68
|
+
state and concurrency. `B-13`/`B-14` require reconciliation against the exact wheel and
|
|
69
|
+
repository pair because the source re-audit disagrees with the external field result.
|
|
70
|
+
|
|
71
|
+
The validated commercial queue is now: deterministic/provenance envelope, bounded UX and
|
|
72
|
+
hint correctness, coherent CI gates, Windows envelope verification, then PR semantic gate,
|
|
73
|
+
bounded agent context, Java/Spring migration inventory, HTTP exposure provenance and SARIF
|
|
74
|
+
enrichment. The complete CTO assessment and acceptance criteria are in the linked audit;
|
|
75
|
+
they are not a claim that every auditor suggestion is a next-iteration fix.
|
|
76
|
+
|
|
77
|
+
**ThingsBoard field audit, 2026-08-23 — five findings documented and corrected in the
|
|
78
|
+
working tree; included in `5.8.25` and commit `2c551db`.**
|
|
79
|
+
[`AUDIT-2026-08-23-THINGSBOARD-FINDINGS.md`](AUDIT-2026-08-23-THINGSBOARD-FINDINGS.md)
|
|
80
|
+
records the evidence and acceptance tests for the missing negative scope (`AUD-THB-001`),
|
|
81
|
+
TX-006 precision (`AUD-THB-002`), ambiguous `none_detected` exposure semantics
|
|
82
|
+
(`AUD-THB-003`), incomplete evidence bounds in the generated report (`AUD-THB-004`) and
|
|
83
|
+
contradictory migration summary wording (`AUD-THB-005`). The audit found no runtime
|
|
84
|
+
regression, crash, write leakage or mutation of the audited checkout. The five authorities
|
|
85
|
+
and focused regression tests were updated and released; these rows are product gaps/defects, not
|
|
86
|
+
claims that ThingsBoard itself is broken.
|
|
87
|
+
|
|
88
|
+
**`AUD-601` queue closed, 2026-08-23 — seven rows, one commit each, no release.** Six closed
|
|
89
|
+
and one (`AUD-601-X01`) held with the half it was owed. Suite **12 702 / 0 red**,
|
|
90
|
+
`__version__` unchanged at `5.8.24`. ⚠ **Three more reported mechanisms are corrected by the
|
|
91
|
+
reproduction, on top of the three corrected at triage.** `D01`: the AUD-597-A01 generator does
|
|
92
|
+
cover the two lines the field read as bare — the *unmeasured* rendering never called it, and
|
|
93
|
+
underneath was an `lru_cache` that pins *"this command declares nothing"* whenever the front
|
|
94
|
+
page is composed before the command is registered. `D02`: `data-exposure` is **not**
|
|
95
|
+
byte-identical across two repositories (measured `mall` against `nacos`); what is real is that
|
|
96
|
+
`build_meta` derived repository identity a second time and published no tree state. `D01`'s
|
|
97
|
+
second half does not reproduce either: `posture . --diff dev:prod --compact` is
|
|
98
|
+
124 268 B → 10 955 B on BroadleafCommerce, **×11.3**, not the 71 483 tokens under every flag
|
|
99
|
+
the report reads.
|
|
100
|
+
|
|
101
|
+
**The head of the queue was the method row, and it is the one that changes how the next round
|
|
102
|
+
is measured.** `AUD-601-M01`: four retracted performance findings in six rounds were all
|
|
103
|
+
measured honestly against a cache state nobody could establish. Every timed answer now
|
|
104
|
+
publishes `_meta.cache_state` — `cold` / `seeded` / `warm`, from the lookups each layer
|
|
105
|
+
actually **served**, never from files on disk — and `cache clear <repo>` stops leaving
|
|
106
|
+
`timeline-samples-v1/` standing in silence, which is the layer that produced the retraction.
|
|
107
|
+
`cache_state` is a `regress` condition field, so two cache states can no longer be compared as
|
|
108
|
+
if they were two versions. ⚠ **`peak_rss_mb` was reaching the determinism batteries as an
|
|
109
|
+
answer**: it is monotonic within a process, so two runs of an unchanged tree disagree on it by
|
|
110
|
+
construction — the `duration_ms` shape again, now in `_CLOCK_KEYS`, with
|
|
111
|
+
`regress.without_run_conditions()` replacing three hand-maintained pop-lists.
|
|
112
|
+
|
|
113
|
+
**`AUD-601-X01` is held, not closed, and `S-10` shipped instead.** It still does not reproduce
|
|
114
|
+
here through any entry path. The platform that produces it now runs the whole suite on every
|
|
115
|
+
push (`.github/workflows/windows-battery.yml`) plus named cases for what the field says is
|
|
116
|
+
broken, so the sixth witness arrives as a red build rather than as a sixth round of a held row.
|
|
117
|
+
|
|
19
118
|
**Backlog sweep after `5.8.24`, 2026-08-23 — no audit, no release: the rows left open across
|
|
20
119
|
the older passes, re-read against HEAD one by one.** Twelve rows closed. Five needed a fix and
|
|
21
120
|
got one: `B25` (a declaration that parsed to nothing said *"no labels declared"*), `B27` (the
|
|
@@ -40,6 +139,45 @@ unreachable by construction. The same sentinels ran the delegated tasks as if
|
|
|
40
139
|
`--all --include-config` had been typed. Suite **12 606 / 0 red**, `__version__` unchanged at
|
|
41
140
|
`5.8.24`.
|
|
42
141
|
|
|
142
|
+
**Fourteenth audit pass, 2026-08-23 — two independent rounds on `5.8.24`, and the first
|
|
143
|
+
pass in the series whose subject is verifiable.** Round A (16-repository bank, Windows 11 Pro,
|
|
144
|
+
~145 invocations) scores **8.7/10**, verdict *adopt*; Round B (MSAS `3dde0376`, eighth round on
|
|
145
|
+
the same tree, ~55 invocations) scores **8.88/10**, verdict *buy and upgrade*, with its
|
|
146
|
+
performance axis marked provisional by its own author. Both read
|
|
147
|
+
`build_commit 61b9c12b0e35…` and both read the same `closure_coverage` (107 closed rows, 88
|
|
148
|
+
`present`, 19 `uncited`), which this checkout reproduces exactly — `AUD-597-X01` and
|
|
149
|
+
`AUD-598-X01` paying out together. `AUD-600-R01` is **closed without residue** (`struts`
|
|
150
|
+
40 911 → 688 ms on the first `--agent` call after a warm, ×59), and `AUD-600-B01` and
|
|
151
|
+
`AUD-600-B02` are confirmed from outside. The queue is `AUD-601-M01` · `AUD-601-R01` ·
|
|
152
|
+
`AUD-601-B01` · `AUD-601-B02` · `AUD-601-X01` · `AUD-601-D01` · `AUD-601-D02`, detailed in
|
|
153
|
+
*Fourteenth Audit Pass* below. **Three of the reported mechanisms are corrected by the
|
|
154
|
+
reproduction**: the memory zero is a written-down decision and it also makes `ASK_MAX_RSS_MB`
|
|
155
|
+
unreachable on Windows (P1, not P2); the budget advisory *works* and shipped on the one command
|
|
156
|
+
where the budget cannot bind, while the three that enforce publish nothing; and the pack's
|
|
157
|
+
futility hint fails because `bounded_floor` models list truncation where `--compact` on a pack
|
|
158
|
+
is a substitution. **One row is retracted by its own reporter after four reports** — `C3-128`
|
|
159
|
+
(`timeline` above 120 s) is a per-commit sampling layer, not a command cost — and the method
|
|
160
|
+
row it produced (`AUD-601-M01`) is the head of the queue. No code changed and no release:
|
|
161
|
+
`__version__` stays `5.8.24`.
|
|
162
|
+
|
|
163
|
+
**Third strategy memo, 2026-08-23 — commercial, not a defect pass, and it produced two
|
|
164
|
+
ledger rows anyway.** A third external memo audited positioning, unit of sale and price
|
|
165
|
+
ceiling from six rounds against the binary. Its verdict row by row is
|
|
166
|
+
[`docs/AUDIT-2026-08-23-COMMERCIAL.md`](AUDIT-2026-08-23-COMMERCIAL.md); the strategy it
|
|
167
|
+
changes is in `EXECUTION-PLAN-12MO.md` and the four rows it opened are `S-27`…`S-30`.
|
|
168
|
+
**Six of its claims changed state when measured against HEAD**, and three of those changed
|
|
169
|
+
the priority of the proposal they supported: the parse store is not the fleet blocker
|
|
170
|
+
(`ASK-17` measured the LRU sweep at ~3 % and retracted the 66 % with a number), `pack` runs
|
|
171
|
+
its components in **subprocesses** and not in memory (`packs.py:555`) so the intersection
|
|
172
|
+
block is a join over published artefacts rather than a shared-process recomputation — which
|
|
173
|
+
is the cheaper *and* the architecturally correct half — and `verify --init` derives all
|
|
174
|
+
three of `verify_rules._KINDS`, so the observed 20/20 is its thresholds degenerating in
|
|
175
|
+
silence rather than a missing rule kind. `cache clear --global` already does what the memo
|
|
176
|
+
said no flag did. **What the reproduction found that no memo did is `P-13`**: `is_large_repo()`
|
|
177
|
+
counts Java files per repository, so the 40-microservice organisation the product route
|
|
178
|
+
names as its buyer pays nothing. `P-14` records why the ledger cannot be published raw.
|
|
179
|
+
No code changed and no release: `__version__` stays `5.8.24`.
|
|
180
|
+
|
|
43
181
|
**Latest attached audits — audit of release `5.8.23`, 2026-08-22, two independent rounds, and
|
|
44
182
|
the first pass whose queue is led by a regression that four previous protocols could not have
|
|
45
183
|
seen.** Round A (MSAS, `banyan-v2` @ `3dde0376`, the same subject bit for bit for the seventh
|
|
@@ -439,6 +577,182 @@ with neither parseable stdout nor its requested artifact) or `BUG-6`
|
|
|
439
577
|
queue position. `BUG-1` and `BUG-5` gain witnesses on public OSS repositories, recorded
|
|
440
578
|
under their own rows rather than as new ones.
|
|
441
579
|
|
|
580
|
+
### Fourteenth Audit Pass: `5.8.24` findings / 16-repository bank (round A) + MSAS (round B) / 2026-08-23
|
|
581
|
+
|
|
582
|
+
**Both rounds audited the same artefact and it is verifiable for the first time in the
|
|
583
|
+
series.** `build_commit` reads `61b9c12b0e354cda157038bc8be6e19384a42368` in both reports and
|
|
584
|
+
in this checkout, and `version.provenance.closure_coverage` agrees to the row: **107 closed
|
|
585
|
+
rows, 88 `present`, 19 `uncited`, 0 `absent`, 0 `unresolved`**. That is `AUD-597-X01` and
|
|
586
|
+
`AUD-598-X01` paying out together — the seven-report question *"does the binary carry the
|
|
587
|
+
fix"* is now answered by the binary, and the third state `uncited` distinguishes *not tracked*
|
|
588
|
+
from *tracked and missing* rather than flattering the total. Round B says the consequence
|
|
589
|
+
plainly: two previous rounds concluded *"the fix did not reach the artefact"* about
|
|
590
|
+
`ASK-UX-001`; the artefact now declares it present, the help block demonstrably changed, and
|
|
591
|
+
the two broken lines are still there — so the correct reading became **the fix is in and does
|
|
592
|
+
not cover these two cases**, which is a different row.
|
|
593
|
+
|
|
594
|
+
Round A (the 16-repository bank, ~145 invocations, Windows 11 Pro) scores **8.7/10** against
|
|
595
|
+
8.3, verdict **adopt**. Round B (MSAS, `3dde0376`, eighth consecutive round on the same tree
|
|
596
|
+
bit for bit, ~55 invocations, `ASK_READONLY=1` and an explicit ceiling on every one, 0
|
|
597
|
+
tracebacks, 0 writes) scores **8.88/10** against 8.84, verdict **buy and upgrade with one
|
|
598
|
+
operating reservation**, and marks its own performance axis **provisional**.
|
|
599
|
+
|
|
600
|
+
**`AUD-600-R01` is closed without residue and the closure is the most consequential
|
|
601
|
+
measurement of the cycle.** Round A re-ran its own protocol (`cache clear -y` → `cache warm`
|
|
602
|
+
→ 1st → 2nd): `struts` (~3 000 Java files) goes **40 911 ms → 688 ms** on the first `--agent`
|
|
603
|
+
invocation after the warm, a **×59 improvement**, with the second at 674 ms — ratio 1.0 where
|
|
604
|
+
it was ×49.2. `mall` 12 487 → 665 ms (was ×16.6), `spring-petclinic` 1 615 → 683 ms (was
|
|
605
|
+
×1.9). `AUD-600-B01` and `AUD-600-B02` are confirmed closed from outside as well: the gate
|
|
606
|
+
composes `verify-edit` and answers `UNVERIFIED` / exit 2 on a working tree that gained
|
|
607
|
+
`GET /internal/dump-config`, and `pack assessment --compact` goes 1 901 108 B → 35 619 B
|
|
608
|
+
(**×53**) where it previously refused with `OUTPUT_TOO_LARGE` after ~52 s.
|
|
609
|
+
|
|
610
|
+
**Four rows come out of this pass, and three of them correct the report's own mechanism.**
|
|
611
|
+
The queue is `AUD-601-R01` · `AUD-601-B01` · `AUD-601-B02` · `AUD-601-X01`, with `AUD-601-M01`
|
|
612
|
+
recording the method finding that outranks all of them.
|
|
613
|
+
|
|
614
|
+
**`AUD-601-R01` — the memory disclosure publishes a confident zero, and the ceiling above it
|
|
615
|
+
cannot fire.** Round A found `_meta.memory.peak_rss_mb: 0.0` on four loads spanning 49 → 3 000
|
|
616
|
+
Java files including the agent view, against its own independent `tasklist` sampling of ~1.4 GB
|
|
617
|
+
on `thingsboard`, and filed it P2 as *"the product's doctrine inverted where it applies it
|
|
618
|
+
best"*. Reproduced in source and it is **worse than reported, in two ways**. First, the zero is
|
|
619
|
+
not an oversight: `resource_budget.peak_rss_mb()` returns `0.0` when the `resource` module is
|
|
620
|
+
absent with the comment *"the zero value explicitly means the platform did not expose a
|
|
621
|
+
sample"* — a confident falsehood written down as a decision, in the axis this product exists
|
|
622
|
+
to refuse. Second, and unreported: `resource_budget.exceeded()` computes the refusal as
|
|
623
|
+
`peak <= ceiling → None`, so with `peak` pinned at 0.0 **`ASK_MAX_RSS_MB` can never fire and
|
|
624
|
+
`MEMORY_TOO_LARGE` is unreachable on Windows** — the declared platform. That is a gate that
|
|
625
|
+
cannot fail, which is the exact shape `AUD-597` refused once already when it declined `--ci`
|
|
626
|
+
on `migrate-check`, and the root help promises the opposite in writing (`cli.py:805`).
|
|
627
|
+
Verified on this host for contrast: `peak_rss_mb: 54.69` on `posture ./spring-petclinic`,
|
|
628
|
+
so the fault is the platform branch and nothing else. **P1, not P2.**
|
|
629
|
+
|
|
630
|
+
**`AUD-601-B01` — the budget disclosure shipped on the one command where the budget cannot
|
|
631
|
+
bind, and is absent on the three where it does.** Round A reproduces `N-02` for the fifth time
|
|
632
|
+
(`ASK_MAX_ANALYSIS_SECONDS=1e9` and `=1_000` → rc 0, 0 bytes of stderr, no advisory) and reads
|
|
633
|
+
it as the row `AUD-598-B04` refused. Measured here, the report is looking at the wrong surface
|
|
634
|
+
and the real defect is underneath it: `budget_binds` **works exactly as `AUD-598-B04` closed
|
|
635
|
+
it** — `migrate-check` publishes *"1e+09s is more than 100x the 11.3s this product has measured
|
|
636
|
+
for `migrate-check`, so no run of it reaches that deadline"* with `measured_anchor_seconds:
|
|
637
|
+
11.3` — and `_budget_disclosure()` has **exactly one call site** (`cli.py:14437`,
|
|
638
|
+
`migrate-check`, whose scope is `advisory_only`). The three members of
|
|
639
|
+
`phased_run.BUDGET_RUNNER_COMMANDS` — `spring-audit`, `risk`, `audit-report`, the only commands
|
|
640
|
+
where a deadline can actually stop anything — publish **no `analysis_budget` block at all**
|
|
641
|
+
(measured: `spring-audit ./spring-petclinic` with the budget set carries no key containing
|
|
642
|
+
*budget* anywhere in its payload). A caller who sets a deadline on a command that enforces one
|
|
643
|
+
learns nothing; a caller who sets it on the command that ignores it gets the full advisory.
|
|
644
|
+
This is this ledger's most repeated class — a correct fix that stopped at one call site — and
|
|
645
|
+
the population it owes is `BUDGET_RUNNER_COMMANDS ∪ {migrate-check}`, read off the registry.
|
|
646
|
+
|
|
647
|
+
**`AUD-601-B02` — the ceiling hint's futility model does not know what `--compact` does to a
|
|
648
|
+
pack.** Round B files `ASK-PACK-004` (minor): `pack assessment .` refuses with *"No flag this
|
|
649
|
+
command declares can bring this answer under the ceiling"* while `--compact` brings the same
|
|
650
|
+
answer from 2 094 023 to ~8 800 estimated tokens, so *"an agent that reads the hint will never
|
|
651
|
+
try `--compact`"*. Reproduced here with the ceiling forced
|
|
652
|
+
(`ASK_MAX_OUTPUT_TOKENS=2000 ask pack assessment ./spring-petclinic`) and the mechanism is
|
|
653
|
+
precise and published in the refusal itself: `bounded_floor_tokens: 18201` with
|
|
654
|
+
`bounded_floor_basis` = *"this payload with every list emptied — the smallest answer any
|
|
655
|
+
list-bounding flag can produce"*. **The floor models list truncation, and `--compact` on a pack
|
|
656
|
+
is not a truncation — it is a substitution**: it replaces each component's body with that
|
|
657
|
+
component's own decision summary (`S-21` / `AUD-600-B02`, as shipped). So the hint is honest
|
|
658
|
+
against a model that does not describe the flag it is deciding about, and `hint_basis` even
|
|
659
|
+
prints `declared_flags: ["--compact"]` beside the sentence saying no declared flag helps. The
|
|
660
|
+
row is the model, not the sentence: `bounded_floor` must be measured for a pack the way the
|
|
661
|
+
pack bounds itself, or the futility claim must be withheld for surfaces whose bounding flag is
|
|
662
|
+
a substitution. Note for whoever takes it: `bounding_is_futile` has **no production call site**
|
|
663
|
+
(only `output_ceiling.py` and one test), so this hint arrives through the `nothing_smaller`
|
|
664
|
+
branch, not through the measured one `AUD-598-B02` built.
|
|
665
|
+
|
|
666
|
+
**`AUD-601-X01` — the envelope declares itself degraded in the field and does not reproduce
|
|
667
|
+
here; the platform is the only variable, and it is held rather than closed.** Round B measures
|
|
668
|
+
`_meta.envelope_status: "degraded"`, `envelope_status_reason: "the running command could not be
|
|
669
|
+
named"` and `command: "unknown"` on **13 of 13 payloads**, filed `ASK-ENV-001` (moderate,
|
|
670
|
+
precisely because the field self-declares instead of failing silently, which is the
|
|
671
|
+
observability the same auditor asked for). Measured on this checkout at the **same
|
|
672
|
+
`build_commit`**, through four entry paths — `run_cli.py`, `python -c "from sourcecode.cli
|
|
673
|
+
import main_entry"` (the path `packs.py:555` uses), the installed `ask` console script, and
|
|
674
|
+
each of those under `ASK_READONLY=1` and an explicit budget — `command` resolves to `posture`
|
|
675
|
+
every time, `envelope_status` is absent, and `peak_rss_mb` is real. So the degradation is
|
|
676
|
+
environmental, `_active_command_context()` returns `""` only where Click has no current context
|
|
677
|
+
at emit time, and **nothing here can name which environment does that**. Held with its
|
|
678
|
+
measurement in both directions rather than closed, the way `ASK-17`'s 457.6 s Windows figure
|
|
679
|
+
was held: it binds to `S-10` (a Windows runner in CI), which now has **five** defect witnesses
|
|
680
|
+
and zero reproductions, and that is what the row is for.
|
|
681
|
+
|
|
682
|
+
**`AUD-601-M01` — the method row, and it outranks the defects.** Round A **retracts `B-27` /
|
|
683
|
+
`C3-128`** after four consecutive reports: *"`timeline` is the only gate-shaped command above
|
|
684
|
+
120 s with no possible ceiling"*, published at 198 s, 163.9 s, 75.2 s and 161.6 s, is a cache
|
|
685
|
+
artefact. Its own control, same command, same session: **161 641 ms** on the first pass over an
|
|
686
|
+
unsampled commit range, then **547 / 509 / 505 ms** on repeats, and **512 ms** after
|
|
687
|
+
`cache clear ./spring-security -y` — because the layer is per sampled commit and a repository
|
|
688
|
+
clear does not invalidate it, which `ask cache model` declares in writing
|
|
689
|
+
(*"timeline · nothing (repeat cached) · [timeline-samples]"*). The cost belongs to seeding a
|
|
690
|
+
layer the product documents as seeded once. That is the **fourth** false finding cache state
|
|
691
|
+
has produced on that bank in six rounds (×10.4 in `5.8.16`, ×2.42 and ×1.39 in `5.8.18`, ×1.93
|
|
692
|
+
in `5.8.20`, and this), so Round A raises `B-26` / `ASK-17` to the **head of its queue as a
|
|
693
|
+
P1 of method**: at 559.95 MB against a 512 MB budget, with `cache clear --all` leaving the
|
|
694
|
+
shared store at 25 095 entries before and after, *neither the maintainer nor an auditor can
|
|
695
|
+
attribute a cost figure to a version*. Two more figures go unattributed for the same reason
|
|
696
|
+
this pass — `B-21` (`posture ./thingsboard` at 59.7 s interleaved against 4.9 / 4.3 s isolated)
|
|
697
|
+
and `migrate-check ./spring-security` (×1.59, published as **not attributable** rather than as
|
|
698
|
+
a regression, with the six-round series 6.02 → 11.60 → 11.30 → 10.66 → 6.81 → 10.82 s showing
|
|
699
|
+
the 6.81 as the outlier and three controlled passes at 10 365 / 10 400 / 10 825 ms). ⚠ **One
|
|
700
|
+
correction this ledger owes the row**: `cache clear --global` exists and empties the shared
|
|
701
|
+
parse and CIR stores (`cli.py:18213`); `--all` preserving them is declared behaviour, not the
|
|
702
|
+
defect. What survives is the budget, and it is real.
|
|
703
|
+
|
|
704
|
+
**The two rounds disagree on performance, and the disagreement is the finding.** Round A, on
|
|
705
|
+
its own protocol (explicit `cache warm` of five repositories, settled host, interleaved ×4,
|
|
706
|
+
median, first pass discarded), measures **eight of nine anchors improving 4–17 %** and every
|
|
707
|
+
one of the six that rose in `5.8.23` back inside its band or below — `ask --help` at 1.74 s,
|
|
708
|
+
under the ×1.25 watch this ledger set. Round B, on MSAS, measures `posture` +55 %,
|
|
709
|
+
`spring-audit` ×2.1, `migrate-check` ×2.2, `selftest` +45 %, `compare` +39 % and `export --c4`
|
|
710
|
+
worse, while `ask . --compact` improves 1.3× (94.6 → 74.9 s), `validation` 1.5× and
|
|
711
|
+
`verify --init` 1.3×. **Round B marks its own axis provisional and names the confound**: its
|
|
712
|
+
first invocation of the session cost 94.9 s against 8.9 s on the second, so the session started
|
|
713
|
+
cold, and its parse store fell 28 106 → 22 491 entries. Neither round is discarded and no
|
|
714
|
+
regression is filed: the two protocols differ in exactly the variable `AUD-601-M01` is about.
|
|
715
|
+
Round B's own reservation is the publishable operating advice, because it comes from the
|
|
716
|
+
product's own numbers rather than from a stopwatch — `pack gate --compact` went 45.6 → 127.9 s
|
|
717
|
+
and `manifest.timing` attributes it: `verify` 566 ms, `verify-edit` **2 854 ms**, `posture`
|
|
718
|
+
**99 539 ms (78 %)**, `pr-impact` 24 175 ms. The new component is not the cost; comparative
|
|
719
|
+
`posture` is. That is `S-22` paying out in the first round that could attribute a composed cost
|
|
720
|
+
without an external clock.
|
|
721
|
+
|
|
722
|
+
**Two design suggestions of the previous round shipped and both rounds verify them.**
|
|
723
|
+
`non_coverage` per pack with its own ids (`NC-PACK-001`, `NC-PACK-003`) and the `packs-v1`
|
|
724
|
+
registry with the aggregation rule published rather than inferable (*"BLOCK wins over
|
|
725
|
+
UNVERIFIED, and UNVERIFIED over PASS"*, `verdict_vocabulary`, `exit_codes`, `formats`,
|
|
726
|
+
`artifacts_written`), whose `basis` reads *"Generated from the pack declarations in `packs.py`
|
|
727
|
+
and the format registry. Nothing here is maintained by hand beside the code it describes."* —
|
|
728
|
+
which is the doctrine whose breach produced `AUD-598-X01`. Not taken, and both rounds say so
|
|
729
|
+
without prompting: the `intersections` block (`S-23`) and `--format sarif` (`S-28`), the latter
|
|
730
|
+
refusing with `INVALID_USAGE` and listing the four valid formats, so there is no ambiguity.
|
|
731
|
+
|
|
732
|
+
**Movement on three long rows, recorded so nobody re-derives them.** `B-11` / `AUD-598-B03`:
|
|
733
|
+
19 anchors, **16 still reading `5.1.0` and one regenerated on `5.8.23`** — the first movement in
|
|
734
|
+
ten reports, consistent with that row closing on the falsifiability half and owing the 16 field
|
|
735
|
+
figures. `B-13`: `validation` gains `schema_version: validation-v1`; repository identity is
|
|
736
|
+
still absent from `posture`, `validation` and `data-exposure`, and `data-exposure` is
|
|
737
|
+
**byte-identical between `mall` and `struts`**, which is `B-14`'s identical-refusal shape and
|
|
738
|
+
the reason the two rows travel together. `N-06` / `AUD-597-D03`: the confident empty string is
|
|
739
|
+
gone and the absence is `null`, exactly as closed; the file itself is still unpopulated, which
|
|
740
|
+
is the half that row published as owed.
|
|
741
|
+
|
|
742
|
+
**Open queue of the fourteenth pass.** Ordered by what it costs to leave open: the method row
|
|
743
|
+
first, because while it stands no cost figure from that bank is attributable to a version;
|
|
744
|
+
then the confident zero, which is the doctrine broken in the axis that sells it.
|
|
745
|
+
|
|
746
|
+
| ID | Severity | Current status | Required direction |
|
|
747
|
+
| --- | --- | --- | --- |
|
|
748
|
+
| `AUD-601-M01` / `B-26`, `B-27` retracted | **P1 of method — it is not an analysis defect and it outranks them** | **closed on `fix/aud600-queue`, unreleased — `__version__` stays `5.8.24`.** The fix is not a faster command: a timed answer now declares the state it was measured in. `cache_observation` collects what each layer **served** this run — never what exists on disk, which `AUD-595-B01` already established costs like a cold store — and the envelope publishes `_meta.cache_state`: `cold` when every lookup missed, `warm` when every one hit, `seeded` when both, and **absent** where the command consulted no layer (`cold` for a layer nobody reads is `AUD-591-Q01` read the other way). `cir`, `snapshot` and `timeline-samples` report their lookups; `parse` keeps its own tally and is read at disclosure. Measured end to end: `posture ./spring-petclinic` cold declares `cir 0/1, parse 0/30`, the immediate repeat declares `warm`. ⚠ **The second half is the one that produced the retractions**: `cache.clear()` removed `core-*`, `snapshot-*`, `view-*` and the CAS directory and **never touched `timeline-samples-v1/`** — the key carries no tree state — and said nothing about it. `--all` now empties it and a plain clear names the samples it left standing, so `cache clear --all -y` is what makes one repository genuinely cold. `cache_state` joins `regress._CONDITION_FIELDS` (a comparison across two cache states is disqualified, not reported as drift) and `peak_rss_mb` joins `_CLOCK_KEYS`. `regress.without_run_conditions()` is now the single authority the three determinism batteries read, replacing three hand-maintained pop-lists that each learned about `cache_layers`, then `timings`, then this, one red run at a time. Commit `17915f0`. *Previous verdict:* **open.** Round A retracts `B-27` / `C3-128` after four reports with its own control (161 641 ms first pass over an unsampled commit range; 547 / 509 / 505 ms on repeats; 512 ms after `cache clear ./spring-security -y`, because the layer is per sampled commit and the product declares it: *"timeline · nothing (repeat cached) · [timeline-samples]"*). Fourth false finding cache state has produced on that bank in six rounds (×10.4 in `5.8.16`, ×2.42 and ×1.39 in `5.8.18`, ×1.93 in `5.8.20`, this). Two more figures unattributed this pass: `B-21` (`posture ./thingsboard` 59.7 s interleaved against 4.9 / 4.3 s isolated) and `migrate-check ./spring-security` (×1.59, published as **not attributable** with its six-round series and three controlled passes at 10 365 / 10 400 / 10 825 ms). Store at **559.95 MB against 512 MB**, `cache clear --all` leaving 25 095 entries either side. ⚠ **One half of the row is answered already and the report did not see it**: `cache clear --global` empties the shared parse and CIR stores (`cli.py:18213`); `--all` preserving them is declared, not the defect | The budget, and a way for an auditor to establish cache state as an input rather than infer it. `cache status` already publishes per-repository coverage (`ASK-17`, `5.8.5`); what is missing is a stated protocol the product itself can assert — a documented *cold / seeded / warm* declaration in the payload of a timed command, so a figure carries the state it was taken in. Until then this ledger publishes bank figures as **not attributable**, which is what Round A did with `migrate-check` and is the correct behaviour |
|
|
749
|
+
| `AUD-601-R01` / `R-02` | **P1 — a confident zero, and a ceiling that cannot fire on the declared platform** (the report filed P2) | **closed on `fix/aud600-queue`, unreleased — `__version__` stays `5.8.24`.** Reproduced exactly as triaged, and both halves are fixed. `peak_rss_sample()` is the single authority and returns `(value, basis)`: `resource` where it exists, then `psutil`, then `GetProcessMemoryInfo`, and `(None, why)` where none answer. The disclosure publishes `peak_rss_mb: null` with `peak_rss_basis` and `ceiling_enforceable`, and **no `*_mb` key is ever a bare `0.0`**. The unreported half — the P1 — is closed too: a ceiling configured on a platform that cannot be sampled ends in a structured `MEMORY_CEILING_UNAVAILABLE` instead of passing in silence, so `ASK_MAX_RSS_MB` can no longer be a gate that cannot fail. Where no ceiling was asked for, nothing changed. `cli.py:805`, the user guide and the manual say what the payload does. Commit `9c763f3`. *Previous verdict:* **open.** `_meta.memory.peak_rss_mb: 0.0` on four loads spanning 49 → 3 000 Java files including `--agent`, against the reporter's own `tasklist` control of ~1.4 GB on `thingsboard`. Reproduced in source and **wider than reported**: `resource_budget.peak_rss_mb()` returns `0.0` when the `resource` module is absent, with the comment *"the zero value explicitly means the platform did not expose a sample"* — the confident falsehood written down as a decision, in the one axis this product exists to refuse. Unreported half: `resource_budget.exceeded()` refuses only when `peak > ceiling`, so with `peak` pinned at 0.0 **`ASK_MAX_RSS_MB` can never fire and `MEMORY_TOO_LARGE` is unreachable on Windows**, while the root help promises the opposite (`cli.py:805`). A gate that cannot fail is the shape `AUD-597` already refused once. Contrast measured here: `peak_rss_mb: 54.69` on `posture ./spring-petclinic`, so the branch is the whole fault | `peak_rss_mb: null` with `peak_rss_basis: "not measurable on this platform (<reason>)"` where the platform does not expose it, and a real sample via `psutil` or `GetProcessMemoryInfo` where it does — the reporter's own acceptance criterion, and it is the right one. Second half, which the report did not ask for and which is the P1: where the sample is `null`, `exceeded()` must **refuse to answer** rather than return `None`, and `MEMORY_TOO_LARGE` must be declared unavailable instead of silently unreachable. Assertion: no `*_mb` key may be `0.0` in an invocation that completed an analysis, and no ceiling may be published as enforced on a platform where its input is `null` |
|
|
750
|
+
| `AUD-601-B01` / `N-02`, 5th round | **P2 — the fix landed on the one command where the budget cannot bind** | **closed on `fix/aud600-queue`, unreleased — `__version__` stays `5.8.24`.** The triage was right and the fix is the population. The envelope now publishes `analysis_budget` for **every command that reads `ASK_MAX_ANALYSIS_SECONDS`**, resolved through `analysis_budget.BUDGETED_ANALYSIS_COMMANDS` — a superset of `BUDGET_RUNNER_COMMANDS ∪ {migrate-check}`, because a caller who set a deadline on `verify` was equally uninformed. A command that never consults the variable carries **no block**, never one saying the budget does not apply. Measured: `spring-audit ./spring-petclinic` with the budget at `1e9` answers `budget_binds: false` against its 31 s anchor where it published nothing at all; `audit-report` has no measured anchor and answers `null` with the reason said out loud rather than a bound it cannot demonstrate. The battery is parametric over the registry, which is what this class keeps returning for. Commit `eb6e013`. *Previous verdict:* **open, and the report is looking at the wrong surface.** `AUD-598-B04`'s `budget_binds` **works**: `migrate-check` with `ASK_MAX_ANALYSIS_SECONDS=1e9` publishes *"1e+09s is more than 100x the 11.3s this product has measured for `migrate-check`, so no run of it reaches that deadline"* with `measured_anchor_seconds: 11.3`. But `_budget_disclosure()` has **exactly one call site** (`cli.py:14437`), and it is that command — whose scope is `advisory_only`. The three members of `phased_run.BUDGET_RUNNER_COMMANDS` (`spring-audit`, `risk`, `audit-report`), the only ones where a deadline can stop anything, publish **no `analysis_budget` block at all**: measured on `spring-audit ./spring-petclinic` with the budget set, no key containing *budget* appears anywhere in the payload. So a caller who sets a deadline on a command that enforces one learns nothing, and a caller who sets it on the command that ignores it gets the full advisory. Round A reads *"rc 0, 0 bytes of stderr, no advisory"* and is right about stderr and wrong about the payload | Publish `_budget_disclosure()` over the population, not over the command that happened to get it: `BUDGET_RUNNER_COMMANDS ∪ {migrate-check}`, read off `phased_run` rather than from a list. The assertion is parametric over that registry — every member publishes `analysis_budget` with `applies`, `budget_binds` and its basis — which is the same sweep shape `S-01` established and the reason this class keeps returning when it is closed by instance |
|
|
751
|
+
| `AUD-601-B02` / `ASK-PACK-004` | **P3 — the futility model does not describe the flag it is deciding about** | **closed on `fix/aud600-queue`, unreleased — `__version__` stays `5.8.24`.** The mechanism identified at triage is the one that was fixed, and the contradiction is gone. The vocabulary now declares which options `bounded_floor` actually models — the ones that only shorten lists (`--limit`, `--top-n`, `--min-severity`, `--max-nodes`, `--max-edges`) — and a command still holding an unmodelled option keeps its futility claim **withheld**, with the flag still offered and the payload naming what its floor is silent about (`bounded_floor_does_not_model`). Measured: `ASK_MAX_OUTPUT_TOKENS=2000 pack assessment ./spring-petclinic` now opens *"Use --compact (bounded decision summary, same report)"* where it opened with *"No flag this command declares…"* beside `declared_flags: ["--compact"]`. Where the model covers everything a command can do to its own answer, `AUD-598-B02`'s measurement is untouched. Nothing branches on a command name. Commit `a5fdc4a`. *Previous verdict:* **open, mechanism identified here and different from the report's.** `pack assessment .` refuses with *"No flag this command declares can bring this answer under the ceiling"* while `--compact` takes the same answer to ~8 800 estimated tokens. Reproduced with the ceiling forced (`ASK_MAX_OUTPUT_TOKENS=2000 ask pack assessment ./spring-petclinic`): the refusal publishes `bounded_floor_tokens: 18201` and `bounded_floor_basis` = *"this payload with every list emptied — the smallest answer any list-bounding flag can produce"*, and prints `hint_basis.declared_flags: ["--compact"]` beside the sentence saying no declared flag helps. **The floor models list truncation; `--compact` on a pack is a substitution** — it replaces each component's body with that component's own decision summary (`S-21` / `AUD-600-B02`, as shipped). The hint is honest against a model that does not fit the surface. Note for whoever takes it: `bounding_is_futile` has **no production call site** (only `output_ceiling.py` and one test), so this arrives through the `nothing_smaller` branch and not through the measured one `AUD-598-B02` built | Measure the floor the way the surface bounds itself, or withhold the futility claim where the bounding flag is a substitution rather than a truncation. A refusal that names a flag as declared and in the same breath says no declared flag helps is the contradiction to remove first — cheapest correct fix is to compute `bounded_floor` by applying the surface's own bounding transform, which for a pack is the `--compact` renderer it already has |
|
|
752
|
+
| `AUD-601-X01` / `ASK-ENV-001` | **P3 — held, not closed: it does not reproduce here and the platform is the only variable** | **held, and the half that was missing has shipped — `__version__` stays `5.8.24`.** Still not reproduced: through `run_cli.py` and the `from sourcecode.cli import main_entry` path `packs.py:555` uses, each plain, under `ASK_READONLY=1` and under an explicit budget, `command` resolves every time and `envelope_status` is absent. Asserting it away would be the confident answer the row is about. What ships is `S-10`: the platform lived in a report and not in the battery, which is why it has **five defect witnesses and zero reproductions**. `tests/test_the_envelope_names_its_command_on_every_entry_path_aud601_x01.py` asserts what the field says is broken — the envelope names its running command on each entry path, the footprint sample is a number or a stated null and never `0.0`, and a ceiling that cannot be evaluated refuses instead of passing — and `.github/workflows/windows-battery.yml` runs the whole suite on `windows-latest` on every push. The next witness arrives as a red build, not as a sixth round. Commit `07560b2`. *Previous verdict:* **open.** Round B measures `_meta.envelope_status: "degraded"`, `envelope_status_reason: "the running command could not be named"` and `command: "unknown"` on **13 of 13 payloads**, and grades it moderate rather than severe precisely because the field now self-declares instead of failing silently — the observability the same reporter asked for. Measured on this checkout at the **same `build_commit`** through four entry paths (`run_cli.py`; `python -c "from sourcecode.cli import main_entry"`, the path `packs.py:555` uses; the installed `ask` console script; each under `ASK_READONLY=1` and an explicit budget): `command` resolves to `posture` every time, `envelope_status` is absent, `peak_rss_mb` is real. `_active_command_context()` returns `""` only where Click has no current context at emit time, and nothing here can name the environment that produces it | Held with its measurement in both directions, the way `ASK-17`'s 457.6 s Windows figure was held — asserting it away would be the confident answer this row is about. It binds to `S-10` (a Windows runner in CI), which now has **five** defect witnesses and zero reproductions, and that is the fix: the platform that produces these needs to be in the battery, not in a report |
|
|
753
|
+
| `AUD-601-D01` / `N-01`, `ASK-UX-001`, 5th round | **P2 — declaration, and the closure reading changed** | **closed on `fix/aud600-queue`, unreleased — `__version__` stays `5.8.24`.** ⚠ **the reported mechanism is corrected: the generator covers those two lines, and the rendering the field read never called it.** With no measured scope, `_start_here_block` printed `_START_HERE` verbatim — so `posture . --diff dev:prod` and `endpoints .` appeared bare and `migrate-check . --compact` showed a flag only because that line carries one in the tuple, which is the reported symptom word for word. The output ceiling is a property of the **command**, not of the repository, so both renderings now bound the whole block; the static path still declines to claim an order it could not measure, which is what `AUD-596-X02` actually asked of it. ⚠ **Underneath was a memo that pins a wrong answer**: `_bounded_invocation` was an `lru_cache` and the front page is composed while `cli` is still importing, so a caller arriving before a command is registered gets *"declares nothing"* and every later render in that process is served it. Only resolutions that found the command are stored now. ⚠ **The second half does not reproduce**: the report reads `posture . --diff dev:prod` at 71 483 tokens with no flag, with `--compact` and with `--limit 20` alike; measured on BroadleafCommerce (2 985 Java files), `--compact` takes it 124 268 B → 10 955 B, **×11.3**. Commit `a6c93eb`. *Previous verdict:* **open, and for the first time the diagnosis is not *"the fix did not ship"*.** `CLOSURE_PROVENANCE` reports `AUD-597-A01` (commit `f8cf061`) as `present`, the help block demonstrably changed — `risk .` moved into a new category *"Too big for this session — `--output <file> --detach`, or nightly"* — and the two broken lines are still there: *"Runs now"* still carries `posture . --diff dev:prod` and `endpoints .` with no bounding flag, and only `migrate-check . --compact` shows one. So the generator does consult cost now and does not cover those two lines. Same correction for `AUD-598-B02` (`ASK-UX-002`, commit `56a4bf7`, `present`) with the payload not moving a byte: no flag / `--compact` / `--limit 20` all return exactly 71 483 tokens / 285 935 B | Sweep the five lines of the block, not the one that was fixed — the population is the block, which is `S-01`'s rule applied to a generator. And the sentence that closes `ASK-UX-002` already exists in the product: the honest-ceiling hint *"the weight is not in the lists they bound"* shipped for packs and was not applied to `posture --diff`, where the hint still offers `--compact` over an answer `--compact` does not move |
|
|
754
|
+
| `AUD-601-D02` / `B-13`, `B-14`, 5th round | **P3 — identity, and an identical refusal that proves it matters** | **closed on `fix/aud600-queue`, unreleased — `__version__` stays `5.8.24`.** ⚠ **the reported symptom does not reproduce**: measured on `mall` against `nacos`, the two `data-exposure` payloads differ in `repo_id`, `git_head`, `scope.path`, `scope.repo_root` and `inputs.tree` — the envelope has carried identity on all three surfaces since `B14`. What the reproduction found is the mechanism the row is really about: `build_meta` assembled that identity **a second time**, reading the tree once for `run_id` and then asking git for HEAD again, and it published neither the tree state nor whether the target is a checkout at all — so an answer about a dirty tree could not be told from an answer about the clean one. `build_meta` now derives the whole block from `envelope.repository_identity()`, the authority `pack_manifest` is already bound to: one git read instead of two, and `scope` publishes `is_git_repository` and `tree_state` (`clean` / `dirty` / `not-a-git-repository` — a state, never a silence that reads as clean). The battery asserts the two agree field by field, that a dirty tree says so, and — `B-14`'s shape — that one refusal about two repositories is two payloads. Commit `fbb259d`. *Previous verdict:* **open, with movement.** `validation` gains `schema_version: validation-v1`. Repository identity is still absent from `posture`, `validation` and `data-exposure`, and `data-exposure` is **byte-identical between `mall` and `struts`** — two different repositories, one answer, nothing in it naming either. That is `B-14`'s identical-refusal shape and the reason the two rows travel together: without identity in the envelope, a refusal cannot be told from a refusal about something else | The envelope block on the three payloads, from `envelope.repository_identity()`, which exists and is already the authority for `pack_manifest`. Assertion over the population that publishes answers about a repository, not over the three named here — closing this by instance is how it reached a fifth round |
|
|
755
|
+
|
|
442
756
|
### Thirteenth Audit Pass: `5.8.23` findings / MSAS (round A) + 16-repository bank (round B) / 2026-08-22
|
|
443
757
|
|
|
444
758
|
**Verdicts first. Round A: buy and upgrade — 8.84/10 against 8.58, the maximum of the
|
|
@@ -1435,7 +1749,7 @@ retained only as evidence of what the auditor observed before the fix.
|
|
|
1435
1749
|
| C3-127 | **`validation` is the only command with sustained monotonic degradation.** Steady-state, three consecutive versions worsening: 17 268 → 18 273 → 21 337 ms, **+23,6 % over the record**, while every other command returned to record level or better after the cache converged. `ASK_PROGRESS=1` attributes 100 % of it to one phase, `mapping validation surface`. | 5.8.2 re-audit | Medium | **closed 5.8.6 — by refuting the premise the row carried, with the measurement inside the phase.** Instrumented on BroadleafCommerce: of the 10 126 ms the phase costs, **14,0 s is method extraction over 2 766 files** and the walk it feeds runs in **0,01 s** and finds nothing. So the cost was never the analysis: it was parsing a universe the walk cannot reach. The walk starts at parameters annotated as HTTP inputs (18 of 2 766 files on that repository) and resolves callees **by name**, and a file whose text does not contain that name followed by `(` cannot declare it — the same regex that finds methods says so, which makes the pruning an equivalence and not a heuristic, the shape of the C3-88 guard one level up. `_DemandParsedMethods` parses the seeds first and then only what the walk asks for, transitively; in the worst case that is every file, which is exactly the old cost and never more. Measured end to end through the CLI: **`risk` 13 396 → 5 722 ms (−57 %)**, the phase 10 126 → 526 ms, with findings, defects and every row byte-identical (only clocks and run ids move). Also identical on keycloak-config-cli, spring-petclinic and jobrunr — whose 12,7 s of parse for zero seeds the C3-88 comment already recorded. One extractor (`_methods_in_text`) serves both universes, the demand-driven one never publishes itself onto the CIR (a partial universe cached as the complete one is the failure the eager path's own comment warns about), and the C3-121 budget check still runs per file inside the parse. Regression `tests/test_http_input_walk_demand_parse_c3_127.py`, 9 assertions, including a positive chain asserted equal to the eager reference. **History:** open, premise corrected by measurement (5.8.3, `e57f3e7`). `risk` publishes `timings` now, and on BroadleafCommerce the two substrates this row is about are **2,6 s of 13,5 s (19 %)** — `indexing the validation surface` 2 103 ms, `resolving the conditional bean graph` 525 ms — while **75 % of the clock is `reading HTTP-input query sinks` (10 051 ms)**, a phase the row does not mention. Two consequences: the ~27 s figure is a property of the audited corpus, not of the command; and within a single `risk` invocation each substrate already runs exactly once, so the saving this row imagines is a **cross-command** cache — a feature with its own contract, not a patch. What stays open is the real one: the query-sink walk. ⚠ **The drift half resolved itself in 5.8.4, measured**: `validation` returns to **18 068 ms** on the audited corpus — −15,3 % against 5.8.2 and +4,6 % over its 5.7.2 record — so the monotonic series (17 268 → 18 273 → 21 337) is broken without the cross-command cache having been built, and the row is now only about the substrate. The corpus divergence is two-sided and stays: the same audit measures the two substrates at ~24 s inside `risk`'s 40 554 ms there (`posture` 5 842 ms and `validation` 18 068 ms as standalone commands, both announced as stages of `risk` by `ASK_PROGRESS=1`), against 19 % on BroadleafCommerce. A cross-command cache must therefore publish its measured saving per corpus rather than inherit the ~24 s figure. ⚠ **Re-profiled by the field on 5.8.5, and the reporter retires half of their own premise**: in `risk`'s trace at 43,7 s on the audited corpus, `resolving the conditional bean graph` **no longer appears as a stage at all** (*"o lo habéis cacheado ya, o cae por debajo del muestreo de 5 s. Retiro esa mitad de mi propuesta"*), which agrees with our own 525 ms measurement. What is left is one substrate and one hot spot: `indexing the validation surface` ~10 s of the 43,7 s (against `validation` standalone at 19,6 s), so a cross-command cache is worth ~−22 % of `risk` here and makes `validation` free once `risk` has run; and **`composing risk factors (reading HTTP-input query sinks)` at ~15 s of 43,7 s (34 %)**, unchanged since round 4 and the same phase our BroadleafCommerce run puts at 75 % — **two corpora now name the same walk as the largest single cost in the CLI**, which makes it the profiling target with the best return and outranks the cache. The parallel lever above both stays `C3-84`: the rule pass is serial on a 20-core host |
|
|
1436
1750
|
| P1-proc | **A performance regression battery still does not exist, and the sixth request now arrives with a validated protocol.** `R6` (the parse cache never converging, so timings were irreproducible) was a real defect, was fixed well in 5.8.2 — dispersion between consecutive warm runs fell from 2,81× to a median of 1,04×, and `cache status` no longer prints its `over by N MB` line — and **was found only because an auditor happened to be measuring**. The same auditor then reported a 43 % regression that did not exist, and retracted it: a 2-run protocol produces artefacts up to **2,8×**. | 5.5.6 → 5.8.2, sixth request | Medium — process, not code | **closed 5.8.6 — the harness ships, and the protocol with it.** `perf.steady_verdict` (six runs, not four; an unconverged sample publishes **no** figure), `perf.contention_verdict` (the control command interleaved: `clean` / `host` / `command`, and only the last is about the product), `perf.host_verdict` (another `ask` process disqualifies the host before anything is measured) and `perf.measurement_protocol()`, with `scripts/perf_harness.py --steady` running them — warm-up discarded, control interleaved between every target pass, both cache bases isolated (E-37) and `ASK_PARSE_CACHE_MAX_MB` pinned. It exits non-zero when a cell did not converge **or** when the session is not attributable to the build. The field's three sessions are replayed as data the way `ANCHOR_MULTIPLE_VALIDATION` replays the six measured releases — the 5.8.5 round-10 session (control 1,29× beside target 1,25×) must classify as `host`, round 9 as `clean`, and a held control beside a moving target as `command` — so a later change to either threshold that stops classifying them correctly fails in the battery instead of in a round. `docs/perf/REGRESSION-GATE.md` §5.1 publishes the protocol. Regression `tests/test_measurement_protocol_p1proc.py`, 15 assertions. **History:** open — 5.8.2 shipped the *assertions* (`P1 / F-BR`: absolute ceilings and `max(sample) < 8 × posture_warm`, whose validation table the audit independently reproduces and extends with 5.8.2 at 6,8× ✅). What is still missing is the **harness that runs them**, and the audit supplies the missing half — a measurement protocol this ledger should treat as binding: `wall_steady()` = one discarded warm-up, then **4 runs**, report the **minimum**, and fail the measurement itself when `max/min ≥ 1,25` because at that point the cache is still evicting and no number is comparable. **Two independent corpora now report the same confounder**: 5 of 7 false positives in one audit and 4 of 7 in the other came from cache state or CPU contention — a competing `ask` process took `spring-audit` from 11,0 s to 71,4 s (+549 %), and `analysis_time_ms` inherits the bias (2 454 → 8 109 ms), so it is not an independent metric either. Acceptance: the battery runs `wall_steady`, asserts the reproducibility gate first, and no performance figure enters this ledger without a clean-CPU check. ⚠ **The cheap half closed 5.8.4, and the cause was not `endpoints`**: it was instrumented all along — one `Progress()`, started and finished — but a phase was announced by the *heartbeat*, which only fires once the interval has elapsed, so a run that finished inside 5 s printed nothing and an instrumented fast command was indistinguishable from an uninstrumented one. The counts the audit reported (posture 1 · spring-audit 2 · validation 3 · risk 5) were measuring how slow each command was, not how well it reports. Entering a phase is now announced whether or not the interval has passed, at `start()` and at every `update()`; the `_last_emit` stamp is still taken there, so the timed loop waits a full interval behind it and the two cannot double-print, and a counted stage is still rate-limited (asserted). `endpoints` also names the snapshot write as its own phase rather than charging that time to the scan. Measured: `endpoints` **0 → 2** phase lines on a 3-file repository, and on `tutorials` the first line arrives at `elapsed=0.0s` instead of after five seconds of silence. Battery `tests/test_phase_boundaries_are_announced_p1proc.py`, 8 assertions. ⚠ **Seventh request, 5.8.4, and the reproducibility gate now passes on everything measured**: `posture` 1,02× · `impact-chain` 1,05× · `impact` 1,08× (1,56× in 5.8.2) · `spring-audit` / `endpoints` / `validation` 1,09× · `risk` 1,23× — seven of seven under the 1,25× gate for the first time, with `cache status` at 293,65 MB of a 512 MB budget and no `over by` line. The absolute ceilings the harness should assert, from 5.8.4 steady state on the audited corpus (3 342 `.java`): `impact` < 5 000 ms (measured 4 192) · `endpoints -o f` < 6 000 (5 166) · `posture` < 6 500 (5 842) · `impact-chain` < 7 000 (6 460) · `spring-audit -o f` < 11 000 (9 716) · `validation -o f` < 19 000 (18 068) · `risk -o f` < 42 000 (40 554), plus the short-circuit `verify-edit` on a genuinely clean tree < 6 000 (4 848). The reuse assertion stays the **v3** formulation — `max(sample) < 8 × posture_warm` — whose validation table extends with 5.8.4 at 6,8 ✅; the two earlier formulations are recorded here as invalid so nobody re-derives them: extremes-only (`samples[0]/samples[-1] > 1.5`) passes 5.6.1 at 2,95 with reuse almost gone, and flatness (`median/min < 1.5`) passes 5.5.5 at 1,00 with reuse broken, because flat at 80 s and flat at 30 s score identically. Population and staleness assertions to carry with them: `symbols_analyzed == PREVIOUS or "symbols_excluded" in metadata`, and no `unchanged_for` line in the progress output. What is still missing is only the harness that runs them. ⚠ **Seventh request, and the protocol is amended by its own author after a ninth false positive — caught before it was reported, which is the point.** Four amendments, all binding here: **(1) four runs are not enough.** A transient survived four passes and died on six: `endpoints` measured 21–28 s (a reported +141 %/+250 %) against a steady state of 7,7–8,0 s, and `spring-audit` 22,9 s against 9,2 s. The minimum is now **6 runs to convergence**, minimum reported. **(2) A control command is mandatory, and it is the piece that was missing for six rounds.** Interleave a cheap, stable command with the expensive one in the same session — `impact <Class> .` (~4,2 s, the most stable in the CLI) against `risk . -o f` — and fail the measurement if the *cheap* one disperses: `assert dispersion(control) < 1.15`. This is what stopped round 10 from reporting a 5.8.5 regression: `spring-audit` at 1,39× and `risk` at 1,49× (both over the 1,25× gate, where all seven were under it in 5.8.4) sat beside a control that dispersed 1,29× when it had measured 1,08× in the same round — proportional movement is the signature of host contention, not of a degraded command. **(3) Host hygiene is asserted, not assumed**: `ask` processes = 0 before measuring (cross-session contention has produced +300 % to +549 % in this ledger), and the round-10 host was carrying 404 active processes. **(4) Isolate *both* cache bases (`E-37`) and pin `ASK_PARSE_CACHE_MAX_MB`; read `metadata.timings`, never `analysis_time_ms`**, which inherits the contention bias it is being used to detect. The one figure round 10 leaves unresolved — that dispersion — is explicitly **not attributed to 5.8.5** and is exactly what this harness, run on a verified-idle host, settles in a single run instead of a round of argument. Of the reporter's nine retired false positives, **eight are of one family (cache state or contention)**, which is the strongest argument this row has ever carried |
|
|
1437
1751
|
| 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. |
|
|
1438
|
-
| 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. |
|
|
1752
|
+
| 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 | **RETRACTED 2026-08-23 by its own reporter, after four reports — it is a cache artefact, not a command cost.** Control, same command, same session: **161 641 ms** on the first pass over an unsampled commit range, then **547 / 509 / 505 ms** on repeats, and **512 ms** after `cache clear ./spring-security -y` — the repository clear does not invalidate it because the layer is **per sampled commit**, which `ask cache model` declares in writing (*"timeline · nothing (repeat cached) · [timeline-samples]"*). The 198 s, 163.9 s, 75.2 s and 161.6 s of four rounds are the price of seeding a layer the product documents as seeded once, paid by a protocol that did not establish cache state as an input. What survives is **not** a `timeline` row: it is `AUD-601-M01`, the method row this retraction opened — the fourth false finding cache state has produced on that bank in six rounds. *Previous verdict:* **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. |
|
|
1439
1753
|
| 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. |
|
|
1440
1754
|
| E-40 | **Three commands delegate to a fourth and hand it `typer.Option` objects instead of values, so the cache they are sold on can never hit.** `onboard`, `review-pr` and `fix-bug` are `prepare-context` under three names and delegated with `ctx.invoke(prepare_context_cmd, ...)`. Click fills declared defaults only for a `click.Command`; handed the *function* Typer decorated it calls it directly, so every parameter the caller did not name kept its `typer.Option(...)` sentinel — an object that is **truthy** and whose `repr` carries its own address. Measured on `ask fix-bug <repo> -o out.json`, three identical invocations: the task cache key is built from `sym=;all=;cfg=;timeout=` and read `all=<typer.models.OptionInfo object at 0x10b5a82d0>`, so each run wrote a **new** entry (`…-fb09db5a-json`, `…-6d3c8370-json`, `…-52f29d3c-json`) and never read one — the warm path was unreachable by construction on the three commands whose sub-second re-run is the claim. Two more from the same sentinel: `include_config` and `all_gaps` reached `builder.build(...)` truthy, so the delegated tasks ran as if `--all --include-config` had been typed, and `_apply_jobs` raised inside its own `except`, leaving `--jobs` unapplied | found here while closing `C4-28`'s residual (the silent warm write is only reachable once the cache can hit), not reported by the field | Medium-High — a published performance claim that cannot be true, and two flag defaults inverted on the product's primary agent surface | **closed after `5.8.24` (`2317af7`).** `_invoke_command` is the one delegation seam: a parameter the caller names wins, every other one gets the value the callee declares, read from the callee's own signature. After it the key is stable (`pctx-fix-bug-d5b9a77-21a8847c-json`) and the second run is a hit. Regression `tests/test_delegated_command_defaults_e40.py`, 15 assertions parametrised over the three delegating commands, including an AST assertion that no `ctx.invoke(<command function>)` returns to `cli.py` and an end-to-end witness that two identical runs share one cache key. The affordance battery follows the new seam (`3f5b0e7`), so the spinner check still sees through the delegation. |
|
|
1441
1755
|
| 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 | **closed `5.8.18`** (`096c7c3`) — direction taken as written: 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 `/` |
|
|
@@ -1835,6 +2149,8 @@ class's subject, not its provenance.
|
|
|
1835
2149
|
| P-10 | **A sixth pass, and the first to move a band on remediation rather than on capability.** Eval #12 raises the fair band to **€1 400–1 800** (from €1 200–1 500) for one stated reason: *"ahora con la evidencia de que los fallos que reportes se corrigen en días"* — 5 of 9 complaints closed in hours, verified against the source from outside. Floor **€400/seat/year** and ceiling **€2 500** are unchanged, and so is the ceiling's condition: performance resolved **and** `posture`/`risk` promoted out of `experimental`. *"Hoy no lo pagaría."* The new datum is that this pass argues **back toward the seat** — *"si el modelo fuese por repo/CI, hoy no pagaría por el pipeline: a 35–45 min por comando no hay pipeline. Pagaría por asiento de auditor"* — which is the first time the per-repository axis (P-5 → P-9) has been talked out of, and it was talked out of by C3-42, not by the model. The free gate (500 Java files against 3 342) is judged correctly placed | 4.6.0 (eval #12) | Pricing decision. **Remediation speed is now a priced property** — the ledger's original thesis, arriving from outside — and the performance row is now what stands between the fair band and the ceiling, **and** between the seat model and the pipeline model that prices higher |
|
|
1836
2150
|
| P-11 | **A seventh pass at the price, and the first where a band is set by reliability rather than by capability.** Eval #13 prices **€9/dev/month** (*"lo que yo pagaría hoy por 4.10.3 en un repo de este tamaño: 16 de 43 comandos inalcanzables, incluidos los 4 Start here"*), **€22 recommended** (*"refleja lo que hoy funciona de verdad: el fast path"* — ~€2 600/year for a team of 10, *"se amortiza con un solo `impact-chain` que evite un despliegue roto"*), and a **€45 maximum conditional on C3-53/C3-54/C3-55/C3-57 being closed and `spring-audit`/`posture` running under 2 minutes with checkpointing** — above which *"compites de frente con Semgrep+CodeScene juntos y pierdes en detección"*. Then, for the fifth time, it argues off the seat axis: **per repository analysed, €150–300/repo/year, or per CI execution** — *"la herramienta es un servicio de análisis, no un IDE; cobrar por asiento castiga justo al equipo grande con el repo grande, que es donde aporta más"*. Its recommendation is explicit: *"cómpralo por el fast path, a precio de fast path, y no montes ningún gate de CI sobre `spring-audit`, `posture` ni `pr-impact` en Windows"* | 4.10.3 (eval #13) | — | **open** — pricing, not engineering, but it carries the sharpest engineering signal in the ledger: this is the first evaluation whose **floor** is set by what will not run rather than by what is missing, and its market references are named (DeepSource ~€8, Codacy ~€15–21, CodeScene ~€25–40, Snyk Code ~€25–57, Semgrep Code ~€40, NDepend ~€450 perpetual/seat). Read against P-9/P-10: the fair band did not move, the **floor collapsed** — €400/seat/year became €9/dev/month — and the whole difference is C3-53's class. Fifth independent arrival at the per-repository unit (P-5 → P-6 → P-8 → P-9 → here) |
|
|
1837
2151
|
| P-12 | **An eighth and a ninth pass at the price, four days apart, on two consecutive builds — and the first pair to agree on both the floor and the condition attached to the ceiling.** Eval #14 (4.10.4, 7/10) prices **€20/seat/month** minimum (*"solo por `endpoints` + `endpoints --servlets` + `validation`; tres comandos, ~20 s, dan un inventario de superficie que no tiene sustituto barato"*), **€45 fair today** (*"el fast path completo… y valoro también la honestidad epistémica: puedo citar sus cifras en un informe sin cubrirme las espaldas, y eso tiene valor material"*), **€90 maximum** — explicitly conditional: *"solo con los repo-wide operables y BUG-1 corregido… hoy no lo pagaría"*. Eval #15 (4.10.5, 6,5/10) lands on the same shape from a different repo state: **€15–20** floor, **€40–50** *"con B3 y B4 resueltos"*, **€90–110** *"además, B5 arreglado y `pr-impact` fiable como gate bloqueante"*, with a ceiling argument that is new: above ~€110 *"compite con SAST enterprise que tiene 10 años más de madurez operativa"*. Both add a **CI licence on a separate axis: €150–300 per repo per month** for nightly runs — eval #14 conditions it precisely: *"depende de que la escritura de `-o` deje de perderse"*. Eval #14 also rules out one model outright: *"lo que no pagaría en ningún caso: precio por LOC o por endpoint analizado. En un repo de 3 574 endpoints donde la mitad del catálogo no ejecuta, un modelo por volumen cobra por capacidad que no se entrega"* | 4.10.4 (eval #14), 4.10.5 (eval #15) | — | **open** — pricing, not engineering, but read against P-11 it is the signal that matters: the floor **recovered from €9 to €15–20** in one release, and the whole difference is remediation of the execution rows, not new capability. Both ceilings are gated by the same two things: C1-36 (the gate must stop lying green) and C3-53/C3-54 (repo-wide runs must survive and keep their output). Sixth and seventh independent arrival at a per-repository unit |
|
|
2152
|
+
| P-13 | **The licence axis cannot charge the buyer the product route is built for.** `is_large_repo()` counts Java source files **per repository path** against `_FREE_REPO_JAVA_FILE_LIMIT = 500` (`license.py:121`, `:521`); the only other axis is the `delta` automation quota (`:267`). An organisation of 40 microservices at ~300 Java files each crosses no threshold on any repository and pays nothing, while `PRODUCT-ROUTE.md` and the third strategy memo both name that organisation as the buyer. The gate in `license.py` and the route contradict each other, and the contradiction favours not charging | third strategy memo, 2026-08-23 — found in the reproduction, **not reported by any of the three memos** | **High (product)** — it is not a pricing preference: the product's own gate excludes the segment its route targets, so `fleet` (`S-18`) has no axis to be sold on and the per-developer price is the ceiling by construction | **open** — `S-27`. Remedy: an axis that can charge an organisation (repository count, a fleet manifest, or seats over a workspace) declared in `license.entitlement()` with `when_it_changes` stating what it costs, exactly as `P-2` established for the existing axis. **Not** by lowering the per-repository threshold — that would start charging the users the current rule deliberately leaves free, and `is_large_repo()`'s docstring says so. Acceptance: a fixture workspace of N small repositories reaches the same entitlement decision as one repository of the same total size, or the difference ships as a stated product decision rather than as an artefact of the counter |
|
|
2153
|
+
| P-14 | **The remediation record is the strongest sales asset in the product and cannot be published as it stands.** `docs/DEFECT-LEDGER.md` carries absolute maintainer paths (`/Users/user/Documents/workspace/testing`), third-party repositories named as evaluation subjects, and self-criticism at a density a buyer can read as instability rather than as rigour. It ships inside the wheel and nowhere else | third strategy memo, 2026-08-23 — the memo proposed publishing it and did not evaluate the publication risk | **Medium (procurement)** — publishing the raw file leaks local paths and implies those third-party projects were audited by this product; not publishing it leaves the answer to *"what if the maintainer disappears"* as a promise instead of a number | **open** — `S-29`. Remedy: publish a **generated projection**, never the file — rows open and closed per version, median days to closure, declined rows with their reason — derived from the ledger plus `build_commit` so the page cannot drift from what shipped. Redaction is part of the acceptance criterion and not a follow-up. The assertion goes on the generator, not on its output, which is the same rule the doc batteries already apply |
|
|
1838
2154
|
|
|
1839
2155
|
## Claims to correct (not defects, but they cost trust)
|
|
1840
2156
|
|
sourcecode/_docs/USER_GUIDE.md
CHANGED
|
@@ -46,7 +46,7 @@ CLI commands — impact, endpoints, spring-audit, explain, … each a pro
|
|
|
46
46
|
The key idea: the extraction is **content-addressed**. Commands reuse the parse cache and,
|
|
47
47
|
where their analysed scope matches, the shared Canonical IR; `ask cache model` names what a
|
|
48
48
|
warm buys for each command rather than implying that every projection costs the same. In
|
|
49
|
-
5.8.
|
|
49
|
+
5.8.25, `validation` enters through that shared CIR and `data-exposure` reuses one semantic
|
|
50
50
|
model across all declared label seeds. (The extraction and consumption contract is fixed in
|
|
51
51
|
the architecture ADRs 0001–0004 under `docs/architecture/`.)
|
|
52
52
|
|
|
@@ -178,7 +178,7 @@ pipx install sourcecode # isolated install, no venv needed
|
|
|
178
178
|
|
|
179
179
|
# Verify
|
|
180
180
|
ask version
|
|
181
|
-
# ask 5.8.
|
|
181
|
+
# ask 5.8.25
|
|
182
182
|
```
|
|
183
183
|
|
|
184
184
|
Requires Python 3.9+.
|
|
@@ -1592,11 +1592,20 @@ inventories `rules_run` / `rules_not_run` with `rules_run_count` and
|
|
|
1592
1592
|
stops at 1 408 files inside the `SEC-004` group and ends at 5.1s.
|
|
1593
1593
|
|
|
1594
1594
|
**Memory budget.** Repository-scoped JSON answers include `_meta.memory` with
|
|
1595
|
-
`unit: "MB"`, the observed `peak_rss_mb`,
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1595
|
+
`unit: "MB"`, the observed `peak_rss_mb`, the `peak_rss_basis` it was sampled
|
|
1596
|
+
from, `configured_max_rss_mb`, and `ceiling_enforceable`. To bound long analyses
|
|
1597
|
+
on a CI or supervised runner, set `ASK_MAX_RSS_MB=<megabytes>`. Exceeding the
|
|
1598
|
+
ceiling produces exit code `1` and a structured `MEMORY_TOO_LARGE` error with the
|
|
1599
|
+
peak and configured limit; no partial answer is published. Unset the variable, or
|
|
1600
|
+
set it to `0`, to disable this ceiling.
|
|
1601
|
+
|
|
1602
|
+
Where the platform exposes no footprint sample, `peak_rss_mb` is `null` and
|
|
1603
|
+
`peak_rss_basis` says why — never `0`, which would read as a measured floor. A
|
|
1604
|
+
ceiling set on such a platform is **refused, not passed**:
|
|
1605
|
+
`ceiling_enforceable: false` and the run ends in a structured
|
|
1606
|
+
`MEMORY_CEILING_UNAVAILABLE` rather than reporting itself under a limit nothing
|
|
1607
|
+
measured. Installing `psutil` gives the sample where the standard library has
|
|
1608
|
+
none.
|
|
1600
1609
|
|
|
1601
1610
|
Every count in such an answer is a floor over what ran — a family or phase that
|
|
1602
1611
|
never ran is named, never reported as an absence of findings. A command outside
|