sourcecode 5.9.22__py3-none-any.whl → 5.9.24__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 +39 -0
- sourcecode/_docs/USER_GUIDE.md +8 -5
- sourcecode/answer_bounds.py +27 -10
- sourcecode/canonical_ir.py +1 -0
- sourcecode/cli.py +116 -13
- sourcecode/migrate_check.py +14 -0
- sourcecode/non_coverage.py +17 -0
- sourcecode/output_budget.py +18 -4
- sourcecode/release_info.py +1 -1
- sourcecode/repository_ir.py +46 -1
- sourcecode/resource_budget.py +10 -5
- sourcecode/rule_catalog.py +1 -0
- sourcecode/spring_findings.py +4 -3
- sourcecode/spring_security_audit.py +57 -0
- {sourcecode-5.9.22.dist-info → sourcecode-5.9.24.dist-info}/METADATA +16 -6
- {sourcecode-5.9.22.dist-info → sourcecode-5.9.24.dist-info}/RECORD +22 -22
- {sourcecode-5.9.22.dist-info → sourcecode-5.9.24.dist-info}/WHEEL +0 -0
- {sourcecode-5.9.22.dist-info → sourcecode-5.9.24.dist-info}/entry_points.txt +0 -0
- {sourcecode-5.9.22.dist-info → sourcecode-5.9.24.dist-info}/licenses/LICENSE +0 -0
- {sourcecode-5.9.22.dist-info → sourcecode-5.9.24.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 = {'AUD-611-B05': {'commit': '', 'status': 'uncited'}, 'AUD-611-B06': {'commit': '', 'status': 'uncited'}, 'AUD-611-B07': {'commit': '', 'status': 'uncited'}, 'AUD-611-B08': {'commit': '', 'status': 'uncited'}, 'AUD-611-B09': {'commit': '', 'status': 'uncited'}, 'AUD-611-B10': {'commit': '', 'status': 'uncited'}, 'AUD-611-B11': {'commit': '', 'status': 'uncited'}, 'AUD-612-07': {'commit': '', 'status': 'uncited'}, 'AUD-612-09': {'commit': '', 'status': 'uncited'}, 'AUD-612-14': {'commit': '', 'status': 'uncited'}, 'AUD-612-B03': {'commit': '', 'status': 'uncited'}, 'AUD-612-B07': {'commit': '', 'status': 'uncited'}, 'AUD-612-B13': {'commit': '', 'status': 'uncited'}, 'AUD-612-E': {'commit': '', 'status': 'uncited'}, 'AUD-612-G': {'commit': '', 'status': 'uncited'}, 'AUD-612-I': {'commit': '', 'status': 'uncited'}, 'AUD-612-K': {'commit': '', 'status': 'uncited'}, 'AUD-612-M': {'commit': '', 'status': 'uncited'}, 'AUD-612-R': {'commit': '', 'status': 'uncited'}, 'AUD-613-ROOT': {'commit': '', 'status': 'uncited'}, 'AUD-614-07': {'commit': '', 'status': 'uncited'}, 'AUD-614-E': {'commit': '', 'status': 'uncited'}, 'AUD-614-F': {'commit': '', 'status': 'uncited'}, 'AUD-614-G': {'commit': '', 'status': 'uncited'}, 'AUD-614-I': {'commit': '', 'status': 'uncited'}, 'AUD-614-INTENT-TIE': {'commit': '', 'status': 'uncited'}, 'AUD-614-JUNIT4': {'commit': '', 'status': 'uncited'}, 'AUD-614-RISK-L0': {'commit': '', 'status': 'uncited'}, 'AUD-614-SELFTEST-TIMEOUT': {'commit': '', 'status': 'uncited'}, 'AUD-615-07': {'commit': '', 'status': 'uncited'}, 'AUD-615-COLD-COMPACT': {'commit': '', 'status': 'uncited'}, 'AUD-615-DRIFT': {'commit': '', 'status': 'uncited'}, 'AUD-615-E': {'commit': '', 'status': 'uncited'}, 'AUD-615-F': {'commit': '', 'status': 'uncited'}, 'AUD-615-INTENT-TIE': {'commit': '', 'status': 'uncited'}, 'AUD-615-JUNIT4': {'commit': '', 'status': 'uncited'}, 'AUD-615-RISK-L0': {'commit': '', 'status': 'uncited'}, 'AUD-615-SELFTEST-TIMEOUT': {'commit': '', 'status': 'uncited'}, 'AUD-616-E-PROV': {'commit': '', 'status': 'uncited'}, 'AUD-616-F, -RISK-L0, -SELFTEST-TIMEOUT, -INTENT-TIE, -DRIFT, -COLD-COMPACT, -E, -07': {'commit': '', 'status': 'uncited'}, 'AUD-616-INTENT-TIE-COV': {'commit': '', 'status': 'uncited'}, 'AUD-616-JUNIT4-SELF': {'commit': '', 'status': 'uncited'}, 'AUD-616-KOTLIN': {'commit': '', 'status': 'uncited'}, 'AUD-616-O': {'commit': '', 'status': 'uncited'}, 'AUD-616-P': {'commit': '', 'status': 'uncited'}, 'Window': {'commit': '', 'status': 'uncited'}, '`ASK-FIELD-01`': {'commit': '829f9fa', 'status': 'present'}, '`ASK-FIELD-02`': {'commit': '6a659fa', 'status': 'present'}, '`ASK-FIELD-03`': {'commit': '55b0d51', 'status': 'present'}, '`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'}, '`AUD-619-WATCH`': {'commit': '', 'status': 'uncited'}, '`AUD-620-COMMAND-SURFACE`': {'commit': '', 'status': 'uncited'}, '`AUD-620-REVIEW-PR`': {'commit': '', 'status': 'uncited'}, '`AUD-621-REVIEW-PR`': {'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':
|
|
3
|
+
BUILD_COMMIT = 'f13c91f463a7cd885eacc9befd93c8fe4009c29e'
|
|
4
|
+
CLOSURE_PROVENANCE = {'AUD-611-B05': {'commit': '', 'status': 'uncited'}, 'AUD-611-B06': {'commit': '', 'status': 'uncited'}, 'AUD-611-B07': {'commit': '', 'status': 'uncited'}, 'AUD-611-B08': {'commit': '', 'status': 'uncited'}, 'AUD-611-B09': {'commit': '', 'status': 'uncited'}, 'AUD-611-B10': {'commit': '', 'status': 'uncited'}, 'AUD-611-B11': {'commit': '', 'status': 'uncited'}, 'AUD-612-07': {'commit': '', 'status': 'uncited'}, 'AUD-612-09': {'commit': '', 'status': 'uncited'}, 'AUD-612-14': {'commit': '', 'status': 'uncited'}, 'AUD-612-B03': {'commit': '', 'status': 'uncited'}, 'AUD-612-B07': {'commit': '', 'status': 'uncited'}, 'AUD-612-B13': {'commit': '', 'status': 'uncited'}, 'AUD-612-E': {'commit': '', 'status': 'uncited'}, 'AUD-612-G': {'commit': '', 'status': 'uncited'}, 'AUD-612-I': {'commit': '', 'status': 'uncited'}, 'AUD-612-K': {'commit': '', 'status': 'uncited'}, 'AUD-612-M': {'commit': '', 'status': 'uncited'}, 'AUD-612-R': {'commit': '', 'status': 'uncited'}, 'AUD-613-ROOT': {'commit': '', 'status': 'uncited'}, 'AUD-614-07': {'commit': '', 'status': 'uncited'}, 'AUD-614-E': {'commit': '', 'status': 'uncited'}, 'AUD-614-F': {'commit': '', 'status': 'uncited'}, 'AUD-614-G': {'commit': '', 'status': 'uncited'}, 'AUD-614-I': {'commit': '', 'status': 'uncited'}, 'AUD-614-INTENT-TIE': {'commit': '', 'status': 'uncited'}, 'AUD-614-JUNIT4': {'commit': '', 'status': 'uncited'}, 'AUD-614-RISK-L0': {'commit': '', 'status': 'uncited'}, 'AUD-614-SELFTEST-TIMEOUT': {'commit': '', 'status': 'uncited'}, 'AUD-615-07': {'commit': '', 'status': 'uncited'}, 'AUD-615-COLD-COMPACT': {'commit': '', 'status': 'uncited'}, 'AUD-615-DRIFT': {'commit': '', 'status': 'uncited'}, 'AUD-615-E': {'commit': '', 'status': 'uncited'}, 'AUD-615-F': {'commit': '', 'status': 'uncited'}, 'AUD-615-INTENT-TIE': {'commit': '', 'status': 'uncited'}, 'AUD-615-JUNIT4': {'commit': '', 'status': 'uncited'}, 'AUD-615-RISK-L0': {'commit': '', 'status': 'uncited'}, 'AUD-615-SELFTEST-TIMEOUT': {'commit': '', 'status': 'uncited'}, 'AUD-616-E-PROV': {'commit': '', 'status': 'uncited'}, 'AUD-616-F, -RISK-L0, -SELFTEST-TIMEOUT, -INTENT-TIE, -DRIFT, -COLD-COMPACT, -E, -07': {'commit': '', 'status': 'uncited'}, 'AUD-616-INTENT-TIE-COV': {'commit': '', 'status': 'uncited'}, 'AUD-616-JUNIT4-SELF': {'commit': '', 'status': 'uncited'}, 'AUD-616-KOTLIN': {'commit': '', 'status': 'uncited'}, 'AUD-616-O': {'commit': '', 'status': 'uncited'}, 'AUD-616-P': {'commit': '', 'status': 'uncited'}, 'Window': {'commit': '', 'status': 'uncited'}, '`ASK-FIELD-01`': {'commit': '829f9fa', 'status': 'present'}, '`ASK-FIELD-02`': {'commit': '6a659fa', 'status': 'present'}, '`ASK-FIELD-03`': {'commit': '55b0d51', 'status': 'present'}, '`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'}, '`AUD-619-WATCH`': {'commit': '', 'status': 'uncited'}, '`AUD-620-COMMAND-SURFACE`': {'commit': '', 'status': 'uncited'}, '`AUD-620-REVIEW-PR`': {'commit': '', 'status': 'uncited'}, '`AUD-621-REVIEW-PR`': {'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'}, '`REG-04`': {'commit': '', 'status': 'uncited'}}
|
|
5
|
+
CLOSURE_COVERAGE = {'closed_rows': 166, 'present': 91, 'absent': 0, 'unresolved': 0, 'uncited': 75, 'unknown': 0}
|
|
@@ -14,6 +14,45 @@ Status values: `open` · `in-progress` · `closed <version>` · `by-design` (wit
|
|
|
14
14
|
The facts these rows are keyed to are published: `ask schema facts-v1` prints the registry
|
|
15
15
|
(authority, definition, consumers, parity test) that the release battery enforces.
|
|
16
16
|
|
|
17
|
+
## Current Synchronization — External Audit `5.9.23`, carried into `5.9.24` (2026-09-01)
|
|
18
|
+
|
|
19
|
+
**Release gate: do not use 5.9.24 as a CI decision gate for these surfaces.** The audit measured
|
|
20
|
+
three `rc=0`, zero-byte answers across `risk` and Markdown `audit-report`.
|
|
21
|
+
The trigger is not yet established; warm-cache and contention hypotheses were
|
|
22
|
+
explicitly tested and did not reproduce it. A global non-empty-output invariant
|
|
23
|
+
is therefore the P0 containment work, not a claim that the root cause is known.
|
|
24
|
+
|
|
25
|
+
Priority order is: `NEW-01` empty successful output; `REG-02` default agent
|
|
26
|
+
memory rejection and post-hoc RSS enforcement; `BUG-01` undeclared parse loss;
|
|
27
|
+
`REG-03` warm-path slowdown; `NEW-02` overloaded endpoint anchors; then
|
|
28
|
+
workspace-help/selftest/plan and output-contract regressions. Full evidence:
|
|
29
|
+
[`AUDIT-2026-09-01-EXTERNAL-5.9.23.md`](AUDIT-2026-09-01-EXTERNAL-5.9.23.md).
|
|
30
|
+
|
|
31
|
+
| ID | Severity | Status | Evidence and required closure |
|
|
32
|
+
|---|---:|---|---|
|
|
33
|
+
| `NEW-01` | Critical maximum | **open, P0 / CI blocker** | `risk` and Markdown `audit-report` can exit `0` with zero bytes on stdout and stderr. The measured rate was 3/47 byte-counted runs; root cause is unknown. Enforce `EMPTY_ANSWER` globally and add byte-counted background-process coverage. |
|
|
34
|
+
| `REG-02` | Critical | **open, regression** | The 1,536 MB default `--agent` ceiling rejects valid large repositories only after spending minutes; it is not published in successful default-agent metadata. Bound projection during construction, sample RSS periodically, and publish the effective ceiling. |
|
|
35
|
+
| `REG-03` | High | **open, regression** | Warm `spring-audit` was measured 2.1–3.8x slower despite a fully reused CIR. Attribute the warm pass before claiming cache benefit. |
|
|
36
|
+
| `REG-01` | High | **open, regression** | Root `ask --help` took 83–86 seconds in a workspace with nested repositories. Help must not perform unbounded repository/profile analysis. |
|
|
37
|
+
| `REG-04` | Medium | **closed 5.9.24** | `_meta.answer_bounds.capped` now aggregates nested cap contracts, so compact answers disclose rows omitted below nested payloads. Regression coverage includes nested dictionaries and lists. |
|
|
38
|
+
| `NEW-02` | High | **open** | Overloaded endpoint handlers can all inherit the final overload's `declaration_line`. Resolve by mapping annotation/signature or publish ambiguity. |
|
|
39
|
+
| `BUG-01` | Critical maximum | **open, P0** | A malformed Java file can disappear without a file-specific declaration. Publish parse failure/recovery in the answer bounds and preserve any affected endpoint gap. |
|
|
40
|
+
| `BUG-02` | Critical maximum | **open, P0** | Large `risk` ended `rc=127` with no output or structured failure. Add fail-fast resource/process handling and durable partial checkpoints. |
|
|
41
|
+
| `BUG-12` | Critical maximum | **open, P0** | Deep `--agent` output construction reaches multi-gigabyte RSS before a small answer. Bound projection while building. |
|
|
42
|
+
| `BUG-03` | High | **open, P1** | Marginal Spring detection can overstate what a zero-finding result covers. Publish Spring footprint/coverage with the stack-fit claim. |
|
|
43
|
+
| `BUG-04` | High | **open, P1** | `selftest` publishes `complete=true` with five error rows. Derive bounds from actual results. |
|
|
44
|
+
| `BUG-05` | High | **open, P1** | Overloaded endpoint handlers can receive the wrong declaration line. Resolve by mapping annotation or publish ambiguity. |
|
|
45
|
+
| `BUG-07` | Closed 5.9.23, verification gap | Compact JVM inventory is bounded, but the audit notes no selftest row protects the correction. Add release-battery coverage before treating it as durable closure. |
|
|
46
|
+
| `BUG-10` | High | **open, P1** | Unsupported routing styles can produce empty coverage gaps. Publish detected-but-unmodeled routing gaps. |
|
|
47
|
+
| `BUG-11` | High | **open, P1** | Default `pack assessment` can fail on a small Spring repository. Use a bounded default or explicit full mode. |
|
|
48
|
+
| `BUG-13` | High | **open, P1** | Unscoped `selftest` starts over nested repositories after warning. Refuse and require an explicit path. |
|
|
49
|
+
| `BUG-16` | High | **open, P1** | Context-cache growth has no published budget or eviction contract; about 1.5 GB was measured. |
|
|
50
|
+
| `BUG-22` | High | **open, P1** | RSS ceilings are checked post-hoc. Add periodic sampling and orderly abort. |
|
|
51
|
+
|
|
52
|
+
The remaining `BUG-04b`, `BUG-06`, `BUG-08`, `BUG-09`, `BUG-15`, `BUG-19`,
|
|
53
|
+
`BUG-20`, `BUG-21` and `BUG-23` findings are open P2/coverage follow-ups in
|
|
54
|
+
the audit document. None is closed by documentation alone.
|
|
55
|
+
|
|
17
56
|
## Current Synchronization — External Audit `AUD-621`
|
|
18
57
|
|
|
19
58
|
**Release `5.9.19` remediation.** The stderr-decoding fix for `AUD-621-PACK-STDERR` remains in code, and the distinct `pack gate --since` crash found by the post-remediation re-audit is corrected with a Python 3.9–3.11-compatible tar extraction path. `AUD-621-R` has a second Windows barrier at process-pool construction, complementing the sequential fallback. The broader findings remain open until their required native Windows evidence is recorded; `AUD-621-CONTEXT` and `AUD-621-WIN-PROC` are unchanged.
|
sourcecode/_docs/USER_GUIDE.md
CHANGED
|
@@ -382,6 +382,9 @@ Output: detected stacks, entry points, dependencies, transactional boundaries (S
|
|
|
382
382
|
### `ask --agent`
|
|
383
383
|
|
|
384
384
|
More structured version of `--compact`. Designed for AI agent system prompt injection.
|
|
385
|
+
It is bounded to 40 KB on stdout and admits repositories up to 10,000 Java files;
|
|
386
|
+
larger repositories return `AGENT_SCOPE_TOO_LARGE` before expensive analysis. Use
|
|
387
|
+
`--compact` or narrow the path in that case.
|
|
385
388
|
|
|
386
389
|
```bash
|
|
387
390
|
ask /repo --agent --output context.json
|
|
@@ -528,7 +531,7 @@ disabled changes runtime behaviour nobody measured; a diff is how a person makes
|
|
|
528
531
|
call with the evidence in front of them.
|
|
529
532
|
|
|
530
533
|
**TX patterns (TX-001..TX-006):** proxy bypass, nested transactions, readOnly propagation, NOT_SUPPORTED in active TX, exception swallowing, self-invocation of a `@Transactional` sibling.
|
|
531
|
-
**SEC patterns (SEC-001..SEC-
|
|
534
|
+
**SEC patterns (SEC-001..SEC-010):** unsecured endpoints, CVE-2025-41248 `@PreAuthorize` inheritance bypass, `@Transactional` on controllers, passwords stored under a fast unsalted digest, CSRF disabled under session-bearing authentication, cookies created without the Secure attribute, credentials stored in a deployment descriptor, SQL built by MyBatis string interpolation, anonymous request-chain exceptions, and HTTP input reaching a concatenated known query sink through bounded positional in-repository calls. **DEAD-001** reports a security control that is present only in comments and therefore disabled.
|
|
532
535
|
**GATE patterns (GATE-001..GATE-004):** custom AOP/security-gate risks over the same custom-gate authority published in `security_posture`: proxy bypass (`private`/`final`/self-invocation), advice that appears to fail open, disabled or tautological annotation attributes, and fragile `args[0]`/reflection binding.
|
|
533
536
|
|
|
534
537
|
Each finding includes `severity`, `confidence`, `symbol`, `source_file`, `evidence`, `explanation`, and `fix_hint`. JAVA/SPRING ONLY.
|
|
@@ -1812,10 +1815,10 @@ stops at 1 408 files inside the `SEC-004` group and ends at 5.1s.
|
|
|
1812
1815
|
**Memory budget.** Repository-scoped JSON answers include `_meta.memory` with
|
|
1813
1816
|
`unit: "MB"`, the observed `peak_rss_mb`, the `peak_rss_basis` it was sampled
|
|
1814
1817
|
from, `configured_max_rss_mb`, and `ceiling_enforceable`. To bound long analyses
|
|
1815
|
-
on a CI or supervised runner, set `ASK_MAX_RSS_MB=<megabytes>`.
|
|
1816
|
-
ceiling produces exit code `1`
|
|
1817
|
-
|
|
1818
|
-
|
|
1818
|
+
on a CI or supervised runner, set `ASK_MAX_RSS_MB=<megabytes>`. `--agent` uses
|
|
1819
|
+
1,536 MB when the variable is unset. Exceeding the ceiling produces exit code `1`
|
|
1820
|
+
and a structured `MEMORY_TOO_LARGE` error with the peak and configured limit; no
|
|
1821
|
+
partial answer is published. Set the variable to `0` to disable this ceiling.
|
|
1819
1822
|
|
|
1820
1823
|
Where the platform exposes no footprint sample, `peak_rss_mb` is `null` and
|
|
1821
1824
|
`peak_rss_basis` says why — never `0`, which would read as a measured floor. A
|
sourcecode/answer_bounds.py
CHANGED
|
@@ -99,6 +99,16 @@ def _gaps(payload: "dict[str, Any]") -> "list[dict[str, Any]]":
|
|
|
99
99
|
found.append({"field": "non_coverage", "what": _summarise(entry)})
|
|
100
100
|
elif non_coverage:
|
|
101
101
|
found.append({"field": "non_coverage", "what": _summarise(non_coverage)})
|
|
102
|
+
populations = [payload.get("population")]
|
|
103
|
+
metadata = payload.get("metadata")
|
|
104
|
+
if isinstance(metadata, dict):
|
|
105
|
+
populations.append(metadata.get("population"))
|
|
106
|
+
for population in populations:
|
|
107
|
+
if not isinstance(population, dict):
|
|
108
|
+
continue
|
|
109
|
+
for failure in _as_list(population.get("parse_failures")):
|
|
110
|
+
if failure:
|
|
111
|
+
found.append({"field": "population.parse_failures", "what": _summarise(failure)})
|
|
102
112
|
for prefix, block in _blocks(payload):
|
|
103
113
|
for field in _GAP_FIELDS:
|
|
104
114
|
value = block.get(field)
|
|
@@ -160,17 +170,24 @@ def _exclusions(payload: "dict[str, Any]") -> "list[dict[str, Any]]":
|
|
|
160
170
|
|
|
161
171
|
def _caps(payload: "dict[str, Any]") -> "list[dict[str, Any]]":
|
|
162
172
|
found: "list[dict[str, Any]]" = []
|
|
173
|
+
def walk(value: Any, prefix: str) -> None:
|
|
174
|
+
if isinstance(value, dict):
|
|
175
|
+
for key, child in value.items():
|
|
176
|
+
path = f"{prefix}{key}"
|
|
177
|
+
if key.endswith(_CAP_SUFFIX) and isinstance(child, dict):
|
|
178
|
+
omitted = child.get("omitted")
|
|
179
|
+
if omitted not in (None, 0):
|
|
180
|
+
found.append({"field": path, **{
|
|
181
|
+
axis: child[axis] for axis in ("total", "shown", "omitted")
|
|
182
|
+
if axis in child
|
|
183
|
+
}})
|
|
184
|
+
walk(child, f"{path}.")
|
|
185
|
+
elif isinstance(value, list):
|
|
186
|
+
for index, child in enumerate(value):
|
|
187
|
+
walk(child, f"{prefix}{index}.")
|
|
188
|
+
|
|
163
189
|
for prefix, block in _blocks(payload):
|
|
164
|
-
|
|
165
|
-
if not key.endswith(_CAP_SUFFIX) or not isinstance(value, dict):
|
|
166
|
-
continue
|
|
167
|
-
omitted = value.get("omitted")
|
|
168
|
-
if omitted in (None, 0):
|
|
169
|
-
continue
|
|
170
|
-
found.append({"field": f"{prefix}{key}", **{
|
|
171
|
-
axis: value[axis] for axis in ("total", "shown", "omitted")
|
|
172
|
-
if axis in value
|
|
173
|
-
}})
|
|
190
|
+
walk(block, prefix)
|
|
174
191
|
return found
|
|
175
192
|
|
|
176
193
|
|
sourcecode/canonical_ir.py
CHANGED
|
@@ -594,6 +594,7 @@ def ir_dict_to_canonical(
|
|
|
594
594
|
"edge_count": len(call_graph),
|
|
595
595
|
"subsystems": ir.get("subsystems") or [],
|
|
596
596
|
"analysis_gaps": ir.get("analysis_gaps") or [],
|
|
597
|
+
"population": ir.get("population") or {},
|
|
597
598
|
"spring_events": ir.get("spring_events") or {},
|
|
598
599
|
"score_basis": (ir.get("impact") or {}).get("score_basis", "none"),
|
|
599
600
|
"reverse_graph_size": len(ir.get("reverse_graph") or {}),
|
sourcecode/cli.py
CHANGED
|
@@ -513,6 +513,28 @@ _START_HERE: "tuple[tuple[str, str], ...]" = (
|
|
|
513
513
|
)
|
|
514
514
|
|
|
515
515
|
|
|
516
|
+
def _start_here_entries(root: "Optional[Path]") -> "tuple[tuple[str, str], ...]":
|
|
517
|
+
"""Return pasteable first steps that the measured repository can accept."""
|
|
518
|
+
if root is None:
|
|
519
|
+
return _START_HERE
|
|
520
|
+
try:
|
|
521
|
+
from sourcecode.spring_profiles import profile_population
|
|
522
|
+
|
|
523
|
+
profiles = profile_population(root).names
|
|
524
|
+
except Exception:
|
|
525
|
+
# Help must remain available if a repository cannot be read.
|
|
526
|
+
return _START_HERE
|
|
527
|
+
if len(profiles) < 2:
|
|
528
|
+
# `posture --diff` rejects undeclared profile names. Do not publish an
|
|
529
|
+
# example that cannot run on this repository.
|
|
530
|
+
return tuple(entry for entry in _START_HERE if not entry[0].startswith("posture "))
|
|
531
|
+
diff = f"posture . --diff {profiles[0]}:{profiles[1]}"
|
|
532
|
+
return tuple(
|
|
533
|
+
(diff, answers) if invocation.startswith("posture ") else (invocation, answers)
|
|
534
|
+
for invocation, answers in _START_HERE
|
|
535
|
+
)
|
|
536
|
+
|
|
537
|
+
|
|
516
538
|
#: Resolved bounding flags, by invocation. Deliberately **not** an `lru_cache`:
|
|
517
539
|
#: only a resolution that found the command is stored. AUD-601-D01 — the front
|
|
518
540
|
#: page is composed while this module is still being imported, so the first
|
|
@@ -637,6 +659,8 @@ def _start_here_block(scope: "Optional[Any]" = None) -> str:
|
|
|
637
659
|
BUCKET_ORDER, BUCKET_TITLE, BUDGETED, DETACH, RUNS_NOW, UNKNOWN, plan,
|
|
638
660
|
)
|
|
639
661
|
|
|
662
|
+
root = getattr(scope, "root", None) if scope is not None else None
|
|
663
|
+
entries = _start_here_entries(root)
|
|
640
664
|
if scope is None or not scope.measured:
|
|
641
665
|
# AUD-601-D01. The ceiling is a property of the **command**, not of the
|
|
642
666
|
# repository, so the bounding flag must not depend on measuring one.
|
|
@@ -647,13 +671,13 @@ def _start_here_block(scope: "Optional[Any]" = None) -> str:
|
|
|
647
671
|
# the generator covers them, and this rendering never called it.
|
|
648
672
|
static = [
|
|
649
673
|
(_bounded_invocation(invocation), answers)
|
|
650
|
-
for invocation, answers in
|
|
674
|
+
for invocation, answers in entries
|
|
651
675
|
]
|
|
652
676
|
width = max([29] + [len(invocation) + 1 for invocation, _ in static])
|
|
653
677
|
lines = ["[bold]Start here — Java/Spring analysis:[/bold]"]
|
|
654
678
|
for invocation, answers in static:
|
|
655
679
|
lines.append(f" {invocation:<{width}}[dim]# {answers}[/dim]")
|
|
656
|
-
if any(bounded != raw for (bounded, _), (raw, _) in zip(static,
|
|
680
|
+
if any(bounded != raw for (bounded, _), (raw, _) in zip(static, entries)):
|
|
657
681
|
lines.append(
|
|
658
682
|
" [dim]Bounded for a first look: each line above carries the "
|
|
659
683
|
"flag its command declares against the output ceiling. Drop it, "
|
|
@@ -661,7 +685,7 @@ def _start_here_block(scope: "Optional[Any]" = None) -> str:
|
|
|
661
685
|
)
|
|
662
686
|
return "\n".join(lines)
|
|
663
687
|
|
|
664
|
-
answers = dict(
|
|
688
|
+
answers = dict(entries)
|
|
665
689
|
# AUD-596-X02: this block sold three commands under "Runs now" and two of
|
|
666
690
|
# them exited 1 here, both with `OUTPUT_TOO_LARGE` — `posture . --diff
|
|
667
691
|
# dev:prod` at ~71K estimated tokens over a 50K ceiling, and `endpoints .`
|
|
@@ -672,12 +696,12 @@ def _start_here_block(scope: "Optional[Any]" = None) -> str:
|
|
|
672
696
|
# it from an error.
|
|
673
697
|
bounded = {
|
|
674
698
|
invocation: _bounded_invocation(invocation)
|
|
675
|
-
for invocation, _ in
|
|
699
|
+
for invocation, _ in entries
|
|
676
700
|
}
|
|
677
701
|
for invocation, bounded_form in bounded.items():
|
|
678
702
|
if bounded_form != invocation:
|
|
679
703
|
answers[bounded_form] = answers[invocation]
|
|
680
|
-
grouped = plan([bounded[invocation] for invocation, _ in
|
|
704
|
+
grouped = plan([bounded[invocation] for invocation, _ in entries], scope)
|
|
681
705
|
|
|
682
706
|
# AUD-597-A01. The plan orders by *time* and the ceiling refuses by *size*,
|
|
683
707
|
# so a command that is seconds away from an answer it cannot print is not a
|
|
@@ -729,7 +753,7 @@ def _start_here_block(scope: "Optional[Any]" = None) -> str:
|
|
|
729
753
|
" [dim]…each of these answers into a file and survives the shell:"
|
|
730
754
|
" add --output <file> --detach[/dim]"
|
|
731
755
|
)
|
|
732
|
-
if any(bounded[invocation] != invocation for invocation, _ in
|
|
756
|
+
if any(bounded[invocation] != invocation for invocation, _ in entries):
|
|
733
757
|
lines.append(
|
|
734
758
|
" [dim]Bounded for a first look: each line above carries the flag "
|
|
735
759
|
"its command declares against the output ceiling. Drop it, or add "
|
|
@@ -888,12 +912,12 @@ scope matches; `ask cache model` says exactly what a warm buys per command.
|
|
|
888
912
|
data-exposure . [dim]# one semantic model is shared across declared label seeds[/dim]
|
|
889
913
|
repo-ir . --since main --budget-tokens 12000 [dim]# bounded agent context[/dim]
|
|
890
914
|
migrate-check . --format sarif -o migration.sarif [dim]# located migration findings[/dim]
|
|
891
|
-
[dim]
|
|
892
|
-
|
|
915
|
+
[dim]Repository paths are normally positional. Commands that publish --path, --repo
|
|
916
|
+
or --dir accept that documented spelling; use each command's --help for its grammar.[/dim]
|
|
893
917
|
|
|
894
918
|
ASK_MAX_ANALYSIS_SECONDS=N [dim]# deadline for {_budget_tiers_phrase()}[/dim]
|
|
895
919
|
[dim]Other commands do not consume this budget; use `--progress` or `--detach` where offered.[/dim]
|
|
896
|
-
ASK_MAX_RSS_MB=N [dim]# peak resident-memory ceiling
|
|
920
|
+
ASK_MAX_RSS_MB=N [dim]# peak resident-memory ceiling; --agent defaults to 1536 MB, 0 disables[/dim]
|
|
897
921
|
[dim]Repository JSON answers publish `_meta.memory.peak_rss_mb` with its basis; exceeding the ceiling
|
|
898
922
|
returns MEMORY_TOO_LARGE, and a platform that exposes no sample returns MEMORY_CEILING_UNAVAILABLE
|
|
899
923
|
rather than passing a ceiling nothing measured.[/dim]
|
|
@@ -969,6 +993,9 @@ scope matches; `ask cache model` says exactly what a warm buys per command.
|
|
|
969
993
|
[dim cyan]→ ask activate <key>[/dim cyan]
|
|
970
994
|
"""
|
|
971
995
|
|
|
996
|
+
if not getattr(sys.stdout, "isatty", lambda: False)():
|
|
997
|
+
# Rich markup is useful interactively but corrupts piped help output.
|
|
998
|
+
return re.sub(r"\[/?(?:bold(?: green)?|dim(?: bold)?|yellow|cyan)\]", "", text)
|
|
972
999
|
return text
|
|
973
1000
|
|
|
974
1001
|
|
|
@@ -1796,7 +1823,12 @@ def _apply_budget(
|
|
|
1796
1823
|
|
|
1797
1824
|
to_file = output_path is not None
|
|
1798
1825
|
return _trim(
|
|
1799
|
-
data,
|
|
1826
|
+
data,
|
|
1827
|
+
budget_bytes,
|
|
1828
|
+
label=label,
|
|
1829
|
+
skip=to_file,
|
|
1830
|
+
warn_stderr=not to_file,
|
|
1831
|
+
strict=(label in {"agent", "compact"}),
|
|
1800
1832
|
)
|
|
1801
1833
|
|
|
1802
1834
|
|
|
@@ -3140,6 +3172,18 @@ def _emit_command_output(
|
|
|
3140
3172
|
not about the encoding. A command that already serialized its own YAML passes
|
|
3141
3173
|
the default and is untouched: the conversion only fires on a JSON object.
|
|
3142
3174
|
"""
|
|
3175
|
+
# A completed analysis with no payload is never a successful answer. The
|
|
3176
|
+
# process-level guard also catches this for the production entry point, but
|
|
3177
|
+
# rejecting it here protects every direct Typer invocation and prevents an
|
|
3178
|
+
# empty file from being published as an artefact.
|
|
3179
|
+
if not content.strip():
|
|
3180
|
+
_emit_error_json(
|
|
3181
|
+
EXECUTION_FAILED_CODE,
|
|
3182
|
+
"The command finished without publishing an answer.",
|
|
3183
|
+
command=_ANSWER_REQUIRED_BY or "unknown",
|
|
3184
|
+
expected="a non-empty parseable answer or report",
|
|
3185
|
+
)
|
|
3186
|
+
raise typer.Exit(code=1)
|
|
3143
3187
|
if stamp_envelope:
|
|
3144
3188
|
content = _stamp_envelope(content)
|
|
3145
3189
|
if fmt == "yaml":
|
|
@@ -4095,7 +4139,14 @@ def _jobs_option() -> Any:
|
|
|
4095
4139
|
capability that makes the rule pass parallel is F-AT, and no help text is a
|
|
4096
4140
|
substitute for it.
|
|
4097
4141
|
"""
|
|
4098
|
-
return typer.Option(
|
|
4142
|
+
return typer.Option(
|
|
4143
|
+
None,
|
|
4144
|
+
"--jobs",
|
|
4145
|
+
"-j",
|
|
4146
|
+
min=1,
|
|
4147
|
+
max=128,
|
|
4148
|
+
help=JOBS_OPTION_HELP + " Maximum accepted value: 128.",
|
|
4149
|
+
)
|
|
4099
4150
|
|
|
4100
4151
|
|
|
4101
4152
|
def _invoke_command(ctx: typer.Context, command: Any, **named: Any) -> Any:
|
|
@@ -4906,6 +4957,24 @@ DOCS_DEPTH_CHOICES = ["module", "symbols", "full"]
|
|
|
4906
4957
|
_FREE_TIER_NODE_CAP: int = 50 # graph/semantic node cap — applies only to large repos on free tier
|
|
4907
4958
|
_JAVA_MIN_SCAN_DEPTH: int = 12 # Maven src/main/java/<pkg>/<module>/File depth floor
|
|
4908
4959
|
_LARGE_REPO_ADVISORY_FILES: int = 3000 # cold-scan advisory threshold (files); honest expectation-setting, not a speed claim
|
|
4960
|
+
_AGENT_JAVA_FILE_CAP: int = 10_000
|
|
4961
|
+
|
|
4962
|
+
|
|
4963
|
+
def _agent_scope_error(root: Path) -> "Optional[dict[str, Any]]":
|
|
4964
|
+
"""Refuse an agent run that cannot stay inside its memory contract."""
|
|
4965
|
+
try:
|
|
4966
|
+
java_files = sum(1 for _ in root.rglob("*.java"))
|
|
4967
|
+
except OSError:
|
|
4968
|
+
return None
|
|
4969
|
+
if java_files <= _AGENT_JAVA_FILE_CAP:
|
|
4970
|
+
return None
|
|
4971
|
+
return {
|
|
4972
|
+
"code": "AGENT_SCOPE_TOO_LARGE",
|
|
4973
|
+
"message": f"--agent is limited to {_AGENT_JAVA_FILE_CAP:,} Java files by default; this repository has {java_files:,}.",
|
|
4974
|
+
"hint": "Use --compact for the bounded summary, or narrow the repository path.",
|
|
4975
|
+
"java_files": java_files,
|
|
4976
|
+
"max_java_files": _AGENT_JAVA_FILE_CAP,
|
|
4977
|
+
}
|
|
4909
4978
|
|
|
4910
4979
|
#: What one Java file costs in serialized `repo-ir` output, measured across five
|
|
4911
4980
|
#: repositories (C3-18): spring-petclinic 30 files/318 KB (10.8 KB/file),
|
|
@@ -5769,7 +5838,14 @@ def main(
|
|
|
5769
5838
|
code_notes = True
|
|
5770
5839
|
no_tree = True # agents never need the raw file tree
|
|
5771
5840
|
architecture = True # agents need full architectural signal (M4)
|
|
5772
|
-
|
|
5841
|
+
# Module graphs are quadratic on large import populations and are not
|
|
5842
|
+
# required by agent_view. Keep them opt-in via --graph-modules.
|
|
5843
|
+
_agent_error = _agent_scope_error(target)
|
|
5844
|
+
if _agent_error is not None:
|
|
5845
|
+
_emit_error_json(
|
|
5846
|
+
_agent_error.pop("code"), _agent_error.pop("message"), **_agent_error
|
|
5847
|
+
)
|
|
5848
|
+
raise typer.Exit(code=2)
|
|
5773
5849
|
|
|
5774
5850
|
# --compact implicitly enables lightweight analysis passes so that
|
|
5775
5851
|
# dependency_summary, env_summary and code_notes_summary are never null.
|
|
@@ -6351,6 +6427,7 @@ def main(
|
|
|
6351
6427
|
"""Close a phase and stop the run if the operator's budget is spent."""
|
|
6352
6428
|
_root_run.completed.append(phase)
|
|
6353
6429
|
if not _root_run.exhausted():
|
|
6430
|
+
_root_memory_seam()
|
|
6354
6431
|
return
|
|
6355
6432
|
_progress.stop()
|
|
6356
6433
|
_block = _root_run.status(_WHY_BUDGET)
|
|
@@ -6362,6 +6439,26 @@ def main(
|
|
|
6362
6439
|
_emit_command_output(_serialize_dict(_block, format), output, copy)
|
|
6363
6440
|
raise typer.Exit(code=_exit)
|
|
6364
6441
|
|
|
6442
|
+
def _root_memory_seam() -> None:
|
|
6443
|
+
"""Enforce the agent's protective RSS ceiling at every root boundary."""
|
|
6444
|
+
if not agent:
|
|
6445
|
+
return
|
|
6446
|
+
from sourcecode import resource_budget
|
|
6447
|
+
|
|
6448
|
+
memory_error = resource_budget.exceeded(
|
|
6449
|
+
"ask --agent",
|
|
6450
|
+
default_ceiling_mb=resource_budget.DEFAULT_AGENT_RSS_CEILING_MB,
|
|
6451
|
+
)
|
|
6452
|
+
if memory_error is None:
|
|
6453
|
+
return
|
|
6454
|
+
_progress.stop()
|
|
6455
|
+
_emit_error_json(
|
|
6456
|
+
memory_error.pop("code"),
|
|
6457
|
+
memory_error.pop("message"),
|
|
6458
|
+
**memory_error,
|
|
6459
|
+
)
|
|
6460
|
+
raise typer.Exit(code=1)
|
|
6461
|
+
|
|
6365
6462
|
_perf_discovery = perf.start()
|
|
6366
6463
|
scanner = AdaptiveScanner(target, topology=_topology, base_depth=effective_depth,
|
|
6367
6464
|
extra_excludes=_extra_excludes)
|
|
@@ -7099,7 +7196,7 @@ def main(
|
|
|
7099
7196
|
_root_timing.setdefault("ris_ms", 0.0)
|
|
7100
7197
|
_root_timing.setdefault("snapshot_ms", 0.0)
|
|
7101
7198
|
# 4. Serialize
|
|
7102
|
-
_progress.update("serializing output")
|
|
7199
|
+
_progress.update("building bounded agent context" if agent else "serializing output")
|
|
7103
7200
|
_perf_serialize = perf.start()
|
|
7104
7201
|
if _is_contract_mode and not agent:
|
|
7105
7202
|
from sourcecode.serializer import contract_view as _contract_view
|
|
@@ -7156,6 +7253,7 @@ def main(
|
|
|
7156
7253
|
content = _serialize_dict(data, format)
|
|
7157
7254
|
|
|
7158
7255
|
perf.stop("serialize", _perf_serialize)
|
|
7256
|
+
_root_seam("serialize")
|
|
7159
7257
|
perf.flush_recorder()
|
|
7160
7258
|
|
|
7161
7259
|
# 5. Write output (CLI-04)
|
|
@@ -17237,6 +17335,10 @@ def _audit_population_for(root: "Path", *, progress: "Any" = None):
|
|
|
17237
17335
|
|
|
17238
17336
|
@app.command("remediation-report")
|
|
17239
17337
|
def remediation_report_cmd(
|
|
17338
|
+
path: Optional[Path] = typer.Argument(
|
|
17339
|
+
None,
|
|
17340
|
+
help="Optional repository path accepted for CLI consistency; the bundled ledger is used.",
|
|
17341
|
+
),
|
|
17240
17342
|
output_path: Optional[Path] = typer.Option(
|
|
17241
17343
|
None, "--output", "-o", help="Write output to a file instead of stdout.",
|
|
17242
17344
|
),
|
|
@@ -17244,6 +17346,7 @@ def remediation_report_cmd(
|
|
|
17244
17346
|
copy: bool = _copy_option(),
|
|
17245
17347
|
) -> None:
|
|
17246
17348
|
"""Publish a redacted remediation record for this ASK build."""
|
|
17349
|
+
del path
|
|
17247
17350
|
_enforce_format("remediation-report", format)
|
|
17248
17351
|
from sourcecode import bundled_docs
|
|
17249
17352
|
|
sourcecode/migrate_check.py
CHANGED
|
@@ -2673,6 +2673,20 @@ class MigrationReport:
|
|
|
2673
2673
|
for _col in ("evidence", "target_lts_blockers"):
|
|
2674
2674
|
_cap_into(_l, _col, top_n)
|
|
2675
2675
|
compact["java_lts_inventory"] = _l
|
|
2676
|
+
inventory = full.get("jvm_inventory")
|
|
2677
|
+
if isinstance(inventory, dict) and isinstance(inventory.get("frameworks"), dict):
|
|
2678
|
+
_inventory = dict(inventory)
|
|
2679
|
+
_frameworks: dict[str, dict] = {}
|
|
2680
|
+
for _name, _framework in inventory["frameworks"].items():
|
|
2681
|
+
if not isinstance(_framework, dict):
|
|
2682
|
+
_frameworks[_name] = _framework
|
|
2683
|
+
continue
|
|
2684
|
+
_bounded = dict(_framework)
|
|
2685
|
+
for _collection in ("declared", "observed"):
|
|
2686
|
+
_cap_into(_bounded, _collection, top_n)
|
|
2687
|
+
_frameworks[_name] = _bounded
|
|
2688
|
+
_inventory["frameworks"] = _frameworks
|
|
2689
|
+
compact["jvm_inventory"] = _inventory
|
|
2676
2690
|
return compact
|
|
2677
2691
|
|
|
2678
2692
|
def to_text(self, min_severity: str = "low") -> str:
|
sourcecode/non_coverage.py
CHANGED
|
@@ -487,6 +487,7 @@ _STACK_INDEPENDENT_AXES: "tuple[str, ...]" = (
|
|
|
487
487
|
def stack_fit(
|
|
488
488
|
spring_detected: bool,
|
|
489
489
|
security_frameworks: "tuple[str, ...] | list[str]" = (),
|
|
490
|
+
spring_footprint: "Optional[dict[str, int]]" = None,
|
|
490
491
|
) -> dict:
|
|
491
492
|
"""Whether this product's Spring-shaped axes model the repository. (CL-19)
|
|
492
493
|
|
|
@@ -553,6 +554,22 @@ def stack_fit(
|
|
|
553
554
|
"Spring Security result must not be read as public access."
|
|
554
555
|
),
|
|
555
556
|
}
|
|
557
|
+
footprint = spring_footprint or {}
|
|
558
|
+
beans = int(footprint.get("spring_beans") or 0)
|
|
559
|
+
java_files = int(footprint.get("java_files") or 0)
|
|
560
|
+
if spring_detected and java_files and beans / java_files < 0.1:
|
|
561
|
+
return {
|
|
562
|
+
"schema_version": STACK_FIT_SCHEMA,
|
|
563
|
+
"spring_detected": True,
|
|
564
|
+
"fit": "partial",
|
|
565
|
+
"spring_footprint": {"spring_beans": beans, "java_files": java_files},
|
|
566
|
+
"statement": (
|
|
567
|
+
"Spring is present but marginal in this scope, so Spring-shaped axes "
|
|
568
|
+
"model only the detected Spring population. Do not read their absence "
|
|
569
|
+
"of findings as coverage of the remaining repository."
|
|
570
|
+
),
|
|
571
|
+
"how_to_read": "Use Spring results for the detected Spring population only.",
|
|
572
|
+
}
|
|
556
573
|
if spring_detected:
|
|
557
574
|
return {
|
|
558
575
|
"schema_version": STACK_FIT_SCHEMA,
|
sourcecode/output_budget.py
CHANGED
|
@@ -74,6 +74,11 @@ _TRIM_SCHEDULE: list[tuple[str, str | None, int]] = [
|
|
|
74
74
|
]
|
|
75
75
|
|
|
76
76
|
|
|
77
|
+
# The root CLI adds cache, timing and envelope records after view trimming.
|
|
78
|
+
# This is the measured upper bound needed to keep its published ceilings true.
|
|
79
|
+
_STRICT_POSTPROCESSING_RESERVE = 12_288
|
|
80
|
+
|
|
81
|
+
|
|
77
82
|
def _serialized_size(data: Any) -> int:
|
|
78
83
|
"""Byte size of JSON-serialized data (UTF-8)."""
|
|
79
84
|
return len(json.dumps(data, ensure_ascii=False).encode("utf-8"))
|
|
@@ -86,6 +91,7 @@ def trim_to_budget(
|
|
|
86
91
|
label: str = "",
|
|
87
92
|
skip: bool = False,
|
|
88
93
|
warn_stderr: bool = False,
|
|
94
|
+
strict: bool = False,
|
|
89
95
|
) -> dict:
|
|
90
96
|
"""Progressively trim *data* to fit within *budget_bytes*.
|
|
91
97
|
|
|
@@ -101,17 +107,26 @@ def trim_to_budget(
|
|
|
101
107
|
|
|
102
108
|
Returns data unchanged if already within budget or ``skip=True``.
|
|
103
109
|
"""
|
|
104
|
-
|
|
110
|
+
# The strict caller needs space for metadata added after this return.
|
|
111
|
+
target_budget = (
|
|
112
|
+
max(0, budget_bytes - _STRICT_POSTPROCESSING_RESERVE)
|
|
113
|
+
if strict else budget_bytes
|
|
114
|
+
)
|
|
115
|
+
if skip or _serialized_size(data) <= target_budget:
|
|
105
116
|
return data
|
|
106
117
|
|
|
107
118
|
result: dict = dict(data)
|
|
108
119
|
original_size = _serialized_size(result)
|
|
120
|
+
# Truncation metadata is added after content is reduced. Agent output
|
|
121
|
+
# publishes a hard byte ceiling, so reserve room for that metadata first.
|
|
122
|
+
# The CLI appends envelope, timing and cache metadata after this function.
|
|
123
|
+
# Reserve their worst observed footprint for every published hard ceiling.
|
|
109
124
|
trimmed_sections: list[str] = []
|
|
110
125
|
# Track original counts for total_omitted_items calculation.
|
|
111
126
|
_original_counts: dict[str, int] = {}
|
|
112
127
|
|
|
113
128
|
for top_key, inner_key, max_items in _TRIM_SCHEDULE:
|
|
114
|
-
if _serialized_size(result) <=
|
|
129
|
+
if _serialized_size(result) <= target_budget:
|
|
115
130
|
break
|
|
116
131
|
|
|
117
132
|
if top_key not in result or result[top_key] is None:
|
|
@@ -163,7 +178,7 @@ def trim_to_budget(
|
|
|
163
178
|
# again — so when the schedule is exhausted and the payload is still over,
|
|
164
179
|
# the remaining cut is chosen by *measuring* what is actually large.
|
|
165
180
|
_MEASURED_FLOOR = 5 # never cut a list below this: a sample of 0 is not a sample
|
|
166
|
-
while _serialized_size(result) >
|
|
181
|
+
while _serialized_size(result) > target_budget:
|
|
167
182
|
_candidates = [
|
|
168
183
|
(_serialized_size(v), k, len(v))
|
|
169
184
|
for k, v in result.items()
|
|
@@ -337,4 +352,3 @@ def compact_budget_phrase() -> str:
|
|
|
337
352
|
context window needs.
|
|
338
353
|
"""
|
|
339
354
|
return _budget_phrase(BUDGET_COMPACT)
|
|
340
|
-
|
sourcecode/release_info.py
CHANGED
|
@@ -27,7 +27,7 @@ from typing import Any, Optional
|
|
|
27
27
|
#: The date `__version__` was released, from that version's CHANGELOG entry.
|
|
28
28
|
#: `tests/test_release_info.py` fails the build if the two disagree, so this is
|
|
29
29
|
#: a copy of a fact rather than a second authority for it.
|
|
30
|
-
RELEASE_DATE = "2026-
|
|
30
|
+
RELEASE_DATE = "2026-09-01"
|
|
31
31
|
|
|
32
32
|
#: Releases per day, measured over the latest 30 CHANGELOG releases (the same
|
|
33
33
|
#: computation the test re-runs). The nine-day interval before 5.9.0 lowers
|
sourcecode/repository_ir.py
CHANGED
|
@@ -5151,6 +5151,7 @@ def _compute_analysis_gaps(
|
|
|
5151
5151
|
relations: list[RelationEdge],
|
|
5152
5152
|
unparsed_type_files: Optional[list[str]] = None,
|
|
5153
5153
|
unbalanced_files: Optional[list[str]] = None,
|
|
5154
|
+
parse_failures: Optional[list[dict]] = None,
|
|
5154
5155
|
) -> list[dict]:
|
|
5155
5156
|
"""Compute structural analysis gaps — real system failures, not cosmetic issues."""
|
|
5156
5157
|
gaps: list[dict] = []
|
|
@@ -5199,6 +5200,20 @@ def _compute_analysis_gaps(
|
|
|
5199
5200
|
"files": list(rf.symbols),
|
|
5200
5201
|
})
|
|
5201
5202
|
|
|
5203
|
+
if parse_failures:
|
|
5204
|
+
failed_files = [row["path"] for row in parse_failures if row.get("status") == "failed"]
|
|
5205
|
+
recovered_files = [row["path"] for row in parse_failures if row.get("status") == "recovered"]
|
|
5206
|
+
gaps.append({
|
|
5207
|
+
"area": "parse_failures",
|
|
5208
|
+
"reason": (
|
|
5209
|
+
f"{len(failed_files)} Java file(s) could not be parsed and "
|
|
5210
|
+
f"{len(recovered_files)} were only partially recovered. Their "
|
|
5211
|
+
"absence or recovered symbols must not be read as complete coverage."
|
|
5212
|
+
),
|
|
5213
|
+
"impact": "high" if failed_files else "medium",
|
|
5214
|
+
"files": [row["path"] for row in parse_failures],
|
|
5215
|
+
})
|
|
5216
|
+
|
|
5202
5217
|
controllers = spring_summary.get("controllers", [])
|
|
5203
5218
|
if controllers and not route_surface:
|
|
5204
5219
|
gaps.append({
|
|
@@ -5251,6 +5266,7 @@ def _assemble(
|
|
|
5251
5266
|
custom_security: "tuple[CustomSecuritySpec, ...]" = (),
|
|
5252
5267
|
unparsed_type_files: Optional[list[str]] = None,
|
|
5253
5268
|
unbalanced_files: Optional[list[str]] = None,
|
|
5269
|
+
parse_failures: Optional[list[dict]] = None,
|
|
5254
5270
|
constants: "Optional[dict[str, str]]" = None,
|
|
5255
5271
|
root: "Optional[Path]" = None,
|
|
5256
5272
|
) -> dict:
|
|
@@ -5548,6 +5564,7 @@ def _assemble(
|
|
|
5548
5564
|
sorted_syms, spring_summary, _route_surface, sorted_rels,
|
|
5549
5565
|
unparsed_type_files=unparsed_type_files,
|
|
5550
5566
|
unbalanced_files=unbalanced_files,
|
|
5567
|
+
parse_failures=parse_failures,
|
|
5551
5568
|
)
|
|
5552
5569
|
|
|
5553
5570
|
# Detect filter-based security model for the assembled IR.
|
|
@@ -6717,6 +6734,9 @@ def build_repo_ir(
|
|
|
6717
6734
|
# for the rare file that already looks unbalanced, exactly as the
|
|
6718
6735
|
# zero-symbol probe below does.
|
|
6719
6736
|
_unbalanced_files: list[str] = []
|
|
6737
|
+
# BUG-01: a tolerant extractor may recover useful symbols, but it must never
|
|
6738
|
+
# make a malformed or non-text Java file disappear from the population.
|
|
6739
|
+
_parse_failures: dict[str, dict[str, str]] = {}
|
|
6720
6740
|
_total_files = len(file_paths)
|
|
6721
6741
|
|
|
6722
6742
|
# F-AQ. Before the loop below runs, hand the same files to a pool of worker
|
|
@@ -6746,9 +6766,19 @@ def build_repo_ir(
|
|
|
6746
6766
|
progress(_file_index, _total_files, "parsing")
|
|
6747
6767
|
abs_path = root / rel_path
|
|
6748
6768
|
try:
|
|
6749
|
-
|
|
6769
|
+
raw_source = abs_path.read_bytes()
|
|
6750
6770
|
except OSError:
|
|
6771
|
+
_parse_failures[rel_path] = {
|
|
6772
|
+
"path": rel_path, "status": "failed", "reason": "unreadable_file",
|
|
6773
|
+
}
|
|
6751
6774
|
continue
|
|
6775
|
+
try:
|
|
6776
|
+
source = raw_source.decode("utf-8")
|
|
6777
|
+
except UnicodeDecodeError:
|
|
6778
|
+
source = raw_source.decode("utf-8", errors="replace")
|
|
6779
|
+
_parse_failures[rel_path] = {
|
|
6780
|
+
"path": rel_path, "status": "failed", "reason": "invalid_utf8",
|
|
6781
|
+
}
|
|
6752
6782
|
_meta_files_read += 1
|
|
6753
6783
|
_meta_lines_read += source.count("\n") + (1 if source and not source.endswith("\n") else 0)
|
|
6754
6784
|
_meta_chars_read += len(source)
|
|
@@ -6787,12 +6817,22 @@ def build_repo_ir(
|
|
|
6787
6817
|
from sourcecode.reconciliation import declares_java_type
|
|
6788
6818
|
if declares_java_type(_mask_java(source)):
|
|
6789
6819
|
_unparsed_type_files.append(rel_path)
|
|
6820
|
+
_parse_failures.setdefault(rel_path, {
|
|
6821
|
+
"path": rel_path,
|
|
6822
|
+
"status": "failed",
|
|
6823
|
+
"reason": "type_declaration_produced_no_symbols",
|
|
6824
|
+
})
|
|
6790
6825
|
# E-10: a brace that never closes is not a style question — it means the
|
|
6791
6826
|
# symbols recovered from this file stop somewhere the reader cannot see.
|
|
6792
6827
|
elif symbols and source.count("{") != source.count("}"):
|
|
6793
6828
|
_masked_src = _mask_java(source)
|
|
6794
6829
|
if _masked_src.count("{") != _masked_src.count("}"):
|
|
6795
6830
|
_unbalanced_files.append(rel_path)
|
|
6831
|
+
_parse_failures.setdefault(rel_path, {
|
|
6832
|
+
"path": rel_path,
|
|
6833
|
+
"status": "recovered",
|
|
6834
|
+
"reason": "unbalanced_braces",
|
|
6835
|
+
})
|
|
6796
6836
|
_per_file.append((rel_path, package, raw_imports, symbols))
|
|
6797
6837
|
if "@" in source:
|
|
6798
6838
|
_parsed_refs = _extract_annotation_type_refs(source, package)
|
|
@@ -7014,6 +7054,7 @@ def build_repo_ir(
|
|
|
7014
7054
|
custom_security=_custom_sec_tuple,
|
|
7015
7055
|
unparsed_type_files=_unparsed_type_files,
|
|
7016
7056
|
unbalanced_files=_unbalanced_files,
|
|
7057
|
+
parse_failures=[_parse_failures[path] for path in sorted(_parse_failures)],
|
|
7017
7058
|
# Cross-file constant folding for annotation paths: per-file folding only
|
|
7018
7059
|
# sees constants declared in the same file (see _collect_repo_constants).
|
|
7019
7060
|
constants=_repo_constants,
|
|
@@ -7117,6 +7158,10 @@ def build_repo_ir(
|
|
|
7117
7158
|
"methods": sum(_kind_counts.get(k, 0) for k in _METHOD_KINDS),
|
|
7118
7159
|
"symbols_excluded": symbols_excluded_disclosure(_meta_symbols_excluded),
|
|
7119
7160
|
}
|
|
7161
|
+
ir["population"] = {
|
|
7162
|
+
"java_files": len(file_paths),
|
|
7163
|
+
"parse_failures": [_parse_failures[path] for path in sorted(_parse_failures)],
|
|
7164
|
+
}
|
|
7120
7165
|
if emit_body_facts:
|
|
7121
7166
|
# Additive, in-memory only: not a cir_hash input, not serialized by the
|
|
7122
7167
|
# repo-ir command (which builds without this flag). Sorted for determinism.
|
sourcecode/resource_budget.py
CHANGED
|
@@ -12,6 +12,7 @@ except ImportError: # pragma: no cover - exercised on Windows
|
|
|
12
12
|
_resource = None
|
|
13
13
|
|
|
14
14
|
ENV_RSS_CEILING = "ASK_MAX_RSS_MB"
|
|
15
|
+
DEFAULT_AGENT_RSS_CEILING_MB = 1_536.0
|
|
15
16
|
ERROR_CODE = "MEMORY_TOO_LARGE"
|
|
16
17
|
UNAVAILABLE_CODE = "MEMORY_CEILING_UNAVAILABLE"
|
|
17
18
|
|
|
@@ -121,11 +122,11 @@ def peak_rss_mb() -> Optional[float]:
|
|
|
121
122
|
return peak_rss_sample()[0]
|
|
122
123
|
|
|
123
124
|
|
|
124
|
-
def configured_ceiling_mb() -> Optional[float]:
|
|
125
|
-
"""Read the positive RSS ceiling;
|
|
125
|
+
def configured_ceiling_mb(*, default: Optional[float] = None) -> Optional[float]:
|
|
126
|
+
"""Read the positive RSS ceiling; an explicit zero disables any default."""
|
|
126
127
|
raw = os.environ.get(ENV_RSS_CEILING)
|
|
127
128
|
if raw is None or not raw.strip():
|
|
128
|
-
return
|
|
129
|
+
return default
|
|
129
130
|
try:
|
|
130
131
|
value = float(raw.strip())
|
|
131
132
|
except ValueError:
|
|
@@ -173,7 +174,11 @@ def _unavailable(command: str, ceiling: float, basis: str) -> dict[str, Any]:
|
|
|
173
174
|
}
|
|
174
175
|
|
|
175
176
|
|
|
176
|
-
def exceeded(
|
|
177
|
+
def exceeded(
|
|
178
|
+
command: str,
|
|
179
|
+
*,
|
|
180
|
+
default_ceiling_mb: Optional[float] = None,
|
|
181
|
+
) -> Optional[dict[str, Any]]:
|
|
177
182
|
"""Build the refusal payload when the ceiling was exceeded — or unusable.
|
|
178
183
|
|
|
179
184
|
Three outcomes, and the middle one is `AUD-601-R01`'s: no ceiling asked for
|
|
@@ -182,7 +187,7 @@ def exceeded(command: str) -> Optional[dict[str, Any]]:
|
|
|
182
187
|
A gate that was requested and cannot be run must say so; passing it in
|
|
183
188
|
silence is the failure mode the row was filed for.
|
|
184
189
|
"""
|
|
185
|
-
ceiling = configured_ceiling_mb()
|
|
190
|
+
ceiling = configured_ceiling_mb(default=default_ceiling_mb)
|
|
186
191
|
if ceiling is None:
|
|
187
192
|
return None
|
|
188
193
|
peak, basis = peak_rss_sample()
|
sourcecode/rule_catalog.py
CHANGED
|
@@ -57,6 +57,7 @@ RULES: tuple[Rule, ...] = (
|
|
|
57
57
|
Rule("SEC-007", "SEC", "Credential stored in a deployment descriptor"),
|
|
58
58
|
Rule("SEC-008", "SEC", "SQL built by MyBatis string interpolation"),
|
|
59
59
|
Rule("SEC-009", "SEC", "Anonymous request-chain exception"),
|
|
60
|
+
Rule("SEC-010", "SEC", "HTTP input reaches a concatenated SQL query sink"),
|
|
60
61
|
Rule("DEAD-001", "DEAD", "Security control present but disabled"),
|
|
61
62
|
Rule("GATE-001", "GATE", "Custom AOP/security gate can be bypassed by proxy limits"),
|
|
62
63
|
Rule("GATE-002", "GATE", "Custom gate advice appears to fail open"),
|
sourcecode/spring_findings.py
CHANGED
|
@@ -143,11 +143,11 @@ def _non_coverage_block() -> dict:
|
|
|
143
143
|
return block("security_surface")
|
|
144
144
|
|
|
145
145
|
|
|
146
|
-
def _stack_fit_block(spring_detected: bool) -> dict:
|
|
146
|
+
def _stack_fit_block(spring_detected: bool, spring_footprint: Optional[dict] = None) -> dict:
|
|
147
147
|
"""Whether this report's Spring-shaped axes model the repository (CL-19)."""
|
|
148
148
|
from sourcecode.non_coverage import stack_fit
|
|
149
149
|
|
|
150
|
-
return stack_fit(spring_detected)
|
|
150
|
+
return stack_fit(spring_detected, spring_footprint=spring_footprint)
|
|
151
151
|
|
|
152
152
|
|
|
153
153
|
@dataclass
|
|
@@ -168,6 +168,7 @@ class SpringAuditResult:
|
|
|
168
168
|
git_head: str = ""
|
|
169
169
|
generated_at: str = ""
|
|
170
170
|
spring_detected: bool = False
|
|
171
|
+
spring_footprint: dict = field(default_factory=dict)
|
|
171
172
|
scope: str = "all" # "all" | "tx" | "security"
|
|
172
173
|
findings: list[SpringFinding] = field(default_factory=list)
|
|
173
174
|
limitations: list[str] = field(default_factory=list)
|
|
@@ -469,7 +470,7 @@ class SpringAuditResult:
|
|
|
469
470
|
# consumer reading a missing key on every repository the case was
|
|
470
471
|
# written for, unable to tell "this build does not publish it" from
|
|
471
472
|
# "your stack is modelled".
|
|
472
|
-
"stack_fit": _stack_fit_block(self.spring_detected),
|
|
473
|
+
"stack_fit": _stack_fit_block(self.spring_detected, self.spring_footprint),
|
|
473
474
|
}
|
|
474
475
|
|
|
475
476
|
def to_compact_dict(self, top_n: int = COMPACT_TOP_N) -> dict:
|
|
@@ -480,6 +480,55 @@ def _controller_source_file(cir: "CanonicalRepositoryIR", controller_fqn: str) -
|
|
|
480
480
|
return ""
|
|
481
481
|
|
|
482
482
|
|
|
483
|
+
class _SEC010HttpInputConcatenatedQuery:
|
|
484
|
+
"""Bounded HTTP-input flow into a known concatenated SQL sink."""
|
|
485
|
+
|
|
486
|
+
pattern_id = "SEC-010"
|
|
487
|
+
severity = "high"
|
|
488
|
+
|
|
489
|
+
def analyze(
|
|
490
|
+
self,
|
|
491
|
+
cir: "CanonicalRepositoryIR",
|
|
492
|
+
tx_index: Optional[TransactionBoundaryIndex],
|
|
493
|
+
root: Optional[Path],
|
|
494
|
+
*,
|
|
495
|
+
model: Optional[SpringSemanticModel] = None,
|
|
496
|
+
) -> list[SpringFinding]:
|
|
497
|
+
if root is None:
|
|
498
|
+
return []
|
|
499
|
+
# Reuse risk's bounded propagation rather than inventing a second taint
|
|
500
|
+
# analysis. It follows annotated HTTP parameters through positional
|
|
501
|
+
# in-repository calls to the published query-sink vocabulary only.
|
|
502
|
+
from sourcecode.risk import _http_input_query_sinks
|
|
503
|
+
|
|
504
|
+
sinks = _http_input_query_sinks(root, cir)
|
|
505
|
+
findings: list[SpringFinding] = []
|
|
506
|
+
for symbol, trace in sorted(sinks.items()):
|
|
507
|
+
owner = symbol.split("#", 1)[0]
|
|
508
|
+
findings.append(SpringFinding(
|
|
509
|
+
id=SpringFinding.make_id(self.pattern_id, symbol),
|
|
510
|
+
pattern_id=self.pattern_id,
|
|
511
|
+
category="security",
|
|
512
|
+
severity=self.severity,
|
|
513
|
+
confidence="medium",
|
|
514
|
+
title="HTTP input reaches a concatenated SQL query sink",
|
|
515
|
+
symbol=symbol,
|
|
516
|
+
source_file=_controller_source_file(cir, owner),
|
|
517
|
+
evidence={"flow": trace, "scope": "bounded_http_input_to_known_query_sink"},
|
|
518
|
+
explanation=(
|
|
519
|
+
"An annotated HTTP input reaches a query argument constructed by "
|
|
520
|
+
"concatenation. The observed flow is limited to positional calls "
|
|
521
|
+
"inside this repository and the documented query-sink vocabulary."
|
|
522
|
+
),
|
|
523
|
+
fix_hint="Use a parameterized query and bind the request value instead of concatenating SQL.",
|
|
524
|
+
limitations=[
|
|
525
|
+
"This is not general taint analysis; see the published query-sink vocabulary.",
|
|
526
|
+
],
|
|
527
|
+
related_symbols=[owner],
|
|
528
|
+
))
|
|
529
|
+
return findings
|
|
530
|
+
|
|
531
|
+
|
|
483
532
|
# ---------------------------------------------------------------------------
|
|
484
533
|
# Default pattern registry
|
|
485
534
|
# ---------------------------------------------------------------------------
|
|
@@ -1130,6 +1179,7 @@ _DEFAULT_SECURITY_PATTERNS: list[SecurityPattern] = [
|
|
|
1130
1179
|
_SEC002PreAuthorizeGenericInheritance(), # type: ignore[list-item]
|
|
1131
1180
|
_SEC003TransactionalOnController(), # type: ignore[list-item]
|
|
1132
1181
|
_SEC00XConfigurationWeaknesses(), # type: ignore[list-item]
|
|
1182
|
+
_SEC010HttpInputConcatenatedQuery(), # type: ignore[list-item]
|
|
1133
1183
|
_GATE00XCustomGateAudit(), # type: ignore[list-item]
|
|
1134
1184
|
]
|
|
1135
1185
|
|
|
@@ -1321,6 +1371,12 @@ def run_security_audit(
|
|
|
1321
1371
|
_spring_detected = _detect_spring(
|
|
1322
1372
|
cir, model=model, tx_total=tx_index.stats()["total"]
|
|
1323
1373
|
)
|
|
1374
|
+
from sourcecode.spring_model import BeanGraph
|
|
1375
|
+
_beans = (model.bean_graph if model is not None else BeanGraph.build(cir)).beans
|
|
1376
|
+
_spring_footprint = {
|
|
1377
|
+
"spring_beans": sum(1 for bean in _beans.values() if bean.spring),
|
|
1378
|
+
"java_files": len(cir.files),
|
|
1379
|
+
}
|
|
1324
1380
|
|
|
1325
1381
|
_profile_state: dict[str, Any] = {
|
|
1326
1382
|
"selected": [],
|
|
@@ -1421,6 +1477,7 @@ def run_security_audit(
|
|
|
1421
1477
|
repo_id=_cache_repo_id(Path(root)) if root is not None else "",
|
|
1422
1478
|
content_id=getattr(cir, "cir_hash", "")[:16],
|
|
1423
1479
|
spring_detected=_spring_detected,
|
|
1480
|
+
spring_footprint=_spring_footprint,
|
|
1424
1481
|
scope="security",
|
|
1425
1482
|
findings=findings,
|
|
1426
1483
|
limitations=_sec_limitations,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version: 5.9.
|
|
3
|
+
Version: 5.9.24
|
|
4
4
|
Summary: Persistent structural context and ultra-fast repeated analysis for AI coding agents
|
|
5
5
|
Project-URL: Homepage, https://github.com/HarounDominique/sourcecode
|
|
6
6
|
Project-URL: Repository, https://github.com/HarounDominique/sourcecode
|
|
@@ -59,7 +59,7 @@ Description-Content-Type: text/markdown
|
|
|
59
59
|
> question. All analysis is local and deterministic; see [Privacy](#configuration--privacy)
|
|
60
60
|
> before inspecting a repository whose telemetry policy you need to control.
|
|
61
61
|
|
|
62
|
-

|
|
63
63
|

|
|
64
64
|
|
|
65
65
|
Copyright (c) 2026 Dominique Haroun. All rights reserved. ASK Engine 5.7.0 and
|
|
@@ -191,10 +191,10 @@ must not be gated on this variable; their budget applicability remains visible i
|
|
|
191
191
|
the [defect ledger](docs/DEFECT-LEDGER.md).
|
|
192
192
|
|
|
193
193
|
**Memory is measurable and bounded.** Repository-scoped JSON answers publish
|
|
194
|
-
`_meta.memory.peak_rss_mb` and the configured ceiling.
|
|
195
|
-
set `ASK_MAX_RSS_MB=<megabytes
|
|
196
|
-
|
|
197
|
-
|
|
194
|
+
`_meta.memory.peak_rss_mb` and the configured ceiling. `--agent` applies a
|
|
195
|
+
1,536 MB ceiling by default; set `ASK_MAX_RSS_MB=<megabytes>` to override it or
|
|
196
|
+
`ASK_MAX_RSS_MB=0` to disable it explicitly. If the process exceeds the ceiling,
|
|
197
|
+
ASK refuses the answer with `MEMORY_TOO_LARGE`, including the observed peak and limit.
|
|
198
198
|
|
|
199
199
|
**Current performance status.** Release 5.9.22 retains the shared Canonical IR
|
|
200
200
|
path used by `validation` and now passes that same CIR into labelled `data-exposure`
|
|
@@ -212,6 +212,16 @@ exit 75 (`--allow-partial` accepts one deliberately). The long-run progress
|
|
|
212
212
|
message names the phase it is in and whether that phase has changed, so a slow run
|
|
213
213
|
is distinguishable from a blocked one.
|
|
214
214
|
|
|
215
|
+
**External audit boundary (2026-09-01).** The latest Windows audit rates the
|
|
216
|
+
large-repository experience at **6.9/10** and reports open P0/P1 issues: empty
|
|
217
|
+
successful Markdown `audit-report`, silent `risk` termination, multi-gigabyte
|
|
218
|
+
deep-agent RSS, incomplete parse/coverage disclosure and oversized compact
|
|
219
|
+
surfaces. The 5.9.23 audit found a CI-blocking empty-output regression that
|
|
220
|
+
remains open in 5.9.24; do not use `risk` or Markdown `audit-report` as
|
|
221
|
+
unattended gates until it is fixed. Findings are tracked in the [external audit](docs/AUDIT-2026-09-01-EXTERNAL-5.9.23.md)
|
|
222
|
+
and [defect ledger](docs/DEFECT-LEDGER.md); they are not closed by the existing
|
|
223
|
+
engineering-host measurements.
|
|
224
|
+
|
|
215
225
|
The current external audit still records two open availability limits, and they
|
|
216
226
|
are held open deliberately: `audit-report --format markdown` under contention, and
|
|
217
227
|
the root compact flow under strict timeouts on very large monorepos. Neither
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
sourcecode/__init__.py,sha256=
|
|
1
|
+
sourcecode/__init__.py,sha256=DmdoBkg7zSAuttoatvcjQ1nmlJsaijqlJo8Ms_tsSmU,309
|
|
2
2
|
sourcecode/__main__.py,sha256=qDFVkobwsdZrX0B3stiRqsUNivVpybKO-egzAwCW4xw,165
|
|
3
|
-
sourcecode/_build_commit.py,sha256=
|
|
3
|
+
sourcecode/_build_commit.py,sha256=28jSOZra1ccdR4xN0zOzZhAxzeVx3Ftn7uRKazqc68k,11687
|
|
4
4
|
sourcecode/access_drift.py,sha256=uYD8ipiEAaTnkz0IhG6ujU_KI3LghdY-6ycurs-BZnc,9355
|
|
5
5
|
sourcecode/adaptive_scanner.py,sha256=yJBKjNpkY6bpueYJ2YnRezen3sYZDecEt7WaaNWdqug,9466
|
|
6
6
|
sourcecode/analysis_budget.py,sha256=ZuNEboPF8A6GK-_V7WNt92ezgriga7_Rbr-vvSN4UEE,4183
|
|
7
|
-
sourcecode/answer_bounds.py,sha256=
|
|
7
|
+
sourcecode/answer_bounds.py,sha256=uFgsOLAb2REVgM5-3DLxk3IgnTs2g8vujEANuzj4Xa8,11225
|
|
8
8
|
sourcecode/archetype.py,sha256=V_s5grgpbanrXb8qGEQb73W5Cg5iKW9FQHWKgg5KM8Y,41201
|
|
9
9
|
sourcecode/architectural_baseline.py,sha256=9ds-ZYw4dEJUKWZSdq_ufHq7d2AXnMbEHteSQlT7iu8,26468
|
|
10
10
|
sourcecode/architectural_delta.py,sha256=JhZVmA0gYUryt4x4ieVuxPbcvoBygHgADZaYJ_o4gdk,15142
|
|
@@ -29,13 +29,13 @@ sourcecode/cache_observation.py,sha256=5E2BeqiYE5wBCbvDglkc5A9fTNhXkT_OhcDuuCqRu
|
|
|
29
29
|
sourcecode/call_surface.py,sha256=fiqYfHooxN1fX9oQoysq1LS3LoZcobhyUNjAGEZKpwk,4148
|
|
30
30
|
sourcecode/caller_metrics.py,sha256=zGc3sHRRwEJgAGmyfqEiH69mD9w5rOqMUhzby8Vmm_w,12599
|
|
31
31
|
sourcecode/caller_reach.py,sha256=M7Ffs5CtlimihfdSy3HtC4WpDP97bRFX15QYOlOfMJw,16626
|
|
32
|
-
sourcecode/canonical_ir.py,sha256=
|
|
32
|
+
sourcecode/canonical_ir.py,sha256=H28TJOG75IMHEkY_YkbJ9LBz2YzgTcNipp2LnYbTYOc,38829
|
|
33
33
|
sourcecode/chain_rules.py,sha256=Bi6UHfgd-GxWswmnHRcPz5jdbAuqka3Zkz_P-MTvqhw,12767
|
|
34
34
|
sourcecode/change_plan.py,sha256=drAoDsqFplutCLc6Y0xue7sYkTls0SpYh7aOXvttv3I,12934
|
|
35
35
|
sourcecode/ci_output.py,sha256=X4NRokWWMRF9Ex8OQrEO2g04GzJ00GDP5zYIoqI9YCc,4625
|
|
36
36
|
sourcecode/cir_graphs.py,sha256=RytqSv1WF8kdlfXj2fPQz16LY4akS2kyThbdWL8beCQ,14835
|
|
37
37
|
sourcecode/classifier.py,sha256=ft1RGPIChvO84q2QMrEH93x1J15AXNWMh26lnxvoRao,26476
|
|
38
|
-
sourcecode/cli.py,sha256=
|
|
38
|
+
sourcecode/cli.py,sha256=b53LxwWjOsbkJui7GXD8HBTbEKgZA3hwkN10xXFNS54,960661
|
|
39
39
|
sourcecode/click_runtime.py,sha256=K2cUdzFhbd6uEUpucWptXE89_z-ZNZGsqgd-34usUXk,1890
|
|
40
40
|
sourcecode/client_calls.py,sha256=YOPnfRZzRyqmdHvXSVeiunW8cuiuCuWXacNIQRgKMCw,22640
|
|
41
41
|
sourcecode/code_notes_analyzer.py,sha256=EJemNCNc9Dn-1RZYu-aNbK0ELzmsyC4s6FdHi3XyNEI,9392
|
|
@@ -102,14 +102,14 @@ sourcecode/license.py,sha256=eIEuIVQXywl_S9LOIACOEpJ4M5RyaPvWrqg_jSNOrXA,31088
|
|
|
102
102
|
sourcecode/manifest_cache.py,sha256=qoBn7hPeaMjLHi3higfxsjo7oS7noommRqDnpKP0Ya8,4124
|
|
103
103
|
sourcecode/mcp_nudge.py,sha256=beNjfyb7z09T1rnS4t6Q4qfbLzZQNaP6ddCA4XpmV0s,3256
|
|
104
104
|
sourcecode/metrics_analyzer.py,sha256=gLoRWKygF18jLgwsqmGXSWopw-f5iO1VbM7Jjdif6ag,22809
|
|
105
|
-
sourcecode/migrate_check.py,sha256=
|
|
105
|
+
sourcecode/migrate_check.py,sha256=OvJ51zcnxYTnPoCAPk63ua4En8qdGpvbU8HHDeQT4H4,172215
|
|
106
106
|
sourcecode/migration_apply.py,sha256=36E9IUq7RbpGVt6RZ8PlSZKgDoEMHorZrXw6UVWPnpw,8692
|
|
107
107
|
sourcecode/migration_blast.py,sha256=OPryWkM6-PbvcG3eJFdcWUnlpXBje41nu2BkrZnE2hg,9359
|
|
108
|
-
sourcecode/non_coverage.py,sha256=
|
|
108
|
+
sourcecode/non_coverage.py,sha256=0voxV7GdEZBaDHKDaw9RjHeb2qH-8ZdAUAOiu71vd8I,31508
|
|
109
109
|
sourcecode/openapi_surface.py,sha256=BTt0K-woZbkbWTN77IkqeBm_Okag9owR0848fmot8sk,16207
|
|
110
110
|
sourcecode/openrewrite_recipe.py,sha256=0pS-61falE6rSfkos2MPnmoDamvoeTT-8Kmj7smj_DI,12987
|
|
111
111
|
sourcecode/output_bounds.py,sha256=BvaRQY5nuytgfNUJHyO7JDLOHuSy0vdjqasISxmxLxI,15516
|
|
112
|
-
sourcecode/output_budget.py,sha256=
|
|
112
|
+
sourcecode/output_budget.py,sha256=aiIsX7sefUB1CHiBTt-SskCcdxcbczYC8LdD6ppvSPA,16352
|
|
113
113
|
sourcecode/output_ceiling.py,sha256=dY007vP4V3T9AI09EIz_W36A3FWARQiege_BZ72uMs0,34757
|
|
114
114
|
sourcecode/output_encoding.py,sha256=OxiZQtr7uWBDUtblNQviNHsTH1Xo9AZEpsegPlQWKFk,2139
|
|
115
115
|
sourcecode/output_sink.py,sha256=Eya-PnXxqc3RGulJoLhuC9LUF73SZD0aO5O2B0xAMXU,8762
|
|
@@ -140,7 +140,7 @@ sourcecode/redactor.py,sha256=SB4hwIvg8h-hvcqKcDWaZvA-aSyn-at-BIRwa0tUv5E,3227
|
|
|
140
140
|
sourcecode/reference_facts.py,sha256=mx7H-Ax5y8sKAQHrnJCXlgjkUzqZtQTByv9Zy2lxKQQ,15500
|
|
141
141
|
sourcecode/regress.py,sha256=6rlFP2rsIzVKAA0spJ66To528GyBtnRI2Zg9vAGq8kQ,13264
|
|
142
142
|
sourcecode/regulatory_pack.py,sha256=xVWd8hYg6MjGfkFP8UWcYeLmNMxEk8k2uSbTcnGMbhg,3421
|
|
143
|
-
sourcecode/release_info.py,sha256=
|
|
143
|
+
sourcecode/release_info.py,sha256=deK17VdMaSvMYhwjpfotdnNyorDbhfRU0pZKks1NRgk,5918
|
|
144
144
|
sourcecode/relevance_scorer.py,sha256=0AgEt4KrV73nioMqBgjhGjtY7L2C7L7cSyKtj3IKcrw,9408
|
|
145
145
|
sourcecode/remediation_diff.py,sha256=fGYqPmQF7bO54L8ivztX5PgmW4fVu54gNcG6OEQ192U,9730
|
|
146
146
|
sourcecode/remediation_flow.py,sha256=OFlrNCD2dKw1WlX5cHqVl1yrQZHi2TjCThH8Q3X1PwI,10294
|
|
@@ -148,12 +148,12 @@ sourcecode/remediation_report.py,sha256=z28x-u618feU2d7ol_FW7IfhUOq6iETCfdpl7zJC
|
|
|
148
148
|
sourcecode/remedies.py,sha256=V2_cD4pLq8bKRkzF-3RGFoiu1xWYZS384WDVp1MrlZw,10225
|
|
149
149
|
sourcecode/rename_refactor.py,sha256=oASZIf7TxcOBy3RQ0FuOe-4HlNW_JOu9RW9JqCxGNBE,17225
|
|
150
150
|
sourcecode/repo_classifier.py,sha256=FG1vaWKdWXsWdl-S8hjVMiTqcwgaRXkDyvK4rPcOGtQ,22681
|
|
151
|
-
sourcecode/repository_ir.py,sha256=
|
|
152
|
-
sourcecode/resource_budget.py,sha256=
|
|
151
|
+
sourcecode/repository_ir.py,sha256=O6d1IWp0-RlJyx4OHBGcflvNA0CgsTS7td7UlI9t7S8,528687
|
|
152
|
+
sourcecode/resource_budget.py,sha256=wqe6WuXlEfxAgBGLj0QX47HmV8WldaYWQjLe-TMR6hk,7938
|
|
153
153
|
sourcecode/ris.py,sha256=HsLVHZfseEHNqMyxrj8SvrzUK7jE_85lsWjHtsEw9ik,29196
|
|
154
154
|
sourcecode/risk.py,sha256=rG7fqDIjyhtvB0Qje0d2ZEUl5kemMBwbuOJG8ZJxqrQ,102552
|
|
155
155
|
sourcecode/risk_model.py,sha256=RoC-G15qZP5BLEwwmcr4eJ0APgvIbh1WTqhTVT-5YFE,10895
|
|
156
|
-
sourcecode/rule_catalog.py,sha256=
|
|
156
|
+
sourcecode/rule_catalog.py,sha256=7lwyNe_sA7M9KtoKXVf9qQYBlo7VEPQ3IK1KiGSqTts,5408
|
|
157
157
|
sourcecode/rule_pass.py,sha256=DTNxD-nAecMJhIzI1LCd9FyRumInQSZjitacNh4Zoc8,14671
|
|
158
158
|
sourcecode/runs.py,sha256=o4oXkB3WFJGScbK_C10OAWzsE18B9Zc55u_IE8_yl4M,6291
|
|
159
159
|
sourcecode/runtime_classifier.py,sha256=uTAD6BDCiBLUZEDRfqk718kM4RTT_vAbfkcOI2_Xx58,18432
|
|
@@ -178,12 +178,12 @@ sourcecode/serializer.py,sha256=zcwsbkC84XKhoDEMv5YR4pP_CnH9iSB1_GlUUvfF8es,1598
|
|
|
178
178
|
sourcecode/servlet_surface.py,sha256=CeiebkxLXKojUQxIf7HV7tdQAwLM32ggDUwBnVQIjdo,13499
|
|
179
179
|
sourcecode/source_text.py,sha256=R52gmSljz7L6YVPbixv5W-LOZ5eKUVvSUP3S-QH_IWc,9047
|
|
180
180
|
sourcecode/spring_event_topology.py,sha256=gm_1J7Dj9JQ1tXnkOzIfjPNFxPLmSN56Vcj8RisqB5I,18093
|
|
181
|
-
sourcecode/spring_findings.py,sha256=
|
|
181
|
+
sourcecode/spring_findings.py,sha256=pvH7Qg7MHv_6m1QyxoVBppCceK_U4P_MKbU6YdQivUM,27922
|
|
182
182
|
sourcecode/spring_impact.py,sha256=7gcP4MJcRl8SF5UjYnZXsvtwvIollUtYXlUn08q-JMM,98677
|
|
183
183
|
sourcecode/spring_model.py,sha256=MBUKR1tes5UVGxtYiv4J2WrydgOp_zReek7P7hO50hA,28962
|
|
184
184
|
sourcecode/spring_profiles.py,sha256=jDNBVhEZQAZXrpqt85FkP2URsMw4YWhQo3W3SLHuwpM,19617
|
|
185
185
|
sourcecode/spring_properties.py,sha256=kPTk5qAJxdbHc1hclhHAP0O-hCIzBn8PTh3lzl-I4a4,8400
|
|
186
|
-
sourcecode/spring_security_audit.py,sha256=
|
|
186
|
+
sourcecode/spring_security_audit.py,sha256=uEAuHGcPYbmhHeL4k5sDqBvUs5RaN6j-zM6oJqv1yrk,73734
|
|
187
187
|
sourcecode/spring_semantic.py,sha256=zrUYWF7Gnz6hpP_3hRveHmGEntT95WpgXt6u7PzLSGg,16835
|
|
188
188
|
sourcecode/spring_tx_analyzer.py,sha256=cFK9M3madb7dKbJ_d97cO-1fGMUPDOwB8KoJ-oocMeY,50951
|
|
189
189
|
sourcecode/sql_taint.py,sha256=As1DbEdjXMBFjCTXU5ojksOzuKkP6LmnuMVnzzmckzc,26998
|
|
@@ -275,13 +275,13 @@ sourcecode/telemetry/consent.py,sha256=-Wb8BFGXEexOs8M0Eja7F-T6ZtLNPeRoZnHcHvlP7
|
|
|
275
275
|
sourcecode/telemetry/events.py,sha256=l3Z2SQUO4_C2D2ItXOOdVNimAmHedUHnUxqYFTxnsAE,2900
|
|
276
276
|
sourcecode/telemetry/filters.py,sha256=-lqT2oorECuqEIdeHb--7AZ6BCaUx0bya720a-Z5x6w,7335
|
|
277
277
|
sourcecode/telemetry/transport.py,sha256=4gGHsq0WeY9VywEZXA3vUxykfiYnw9uuqfjAAec7F8o,1681
|
|
278
|
-
sourcecode/_docs/DEFECT-LEDGER.md,sha256=
|
|
278
|
+
sourcecode/_docs/DEFECT-LEDGER.md,sha256=jtnqqp59cBGmCsM9tdLH3hybKhMRs8_h6XW5OWu77VE,1172054
|
|
279
279
|
sourcecode/_docs/LICENSE,sha256=23-fk61oSWGVmkWyka-FIM0rhAPM2hcYHnsaridL8Uo,1859
|
|
280
280
|
sourcecode/_docs/NOTICE,sha256=Br-AA8Y3iJo1WXa5uP8QBpzqI5nDu3iGLbFyvDt3BOs,321
|
|
281
|
-
sourcecode/_docs/USER_GUIDE.md,sha256=
|
|
282
|
-
sourcecode-5.9.
|
|
283
|
-
sourcecode-5.9.
|
|
284
|
-
sourcecode-5.9.
|
|
285
|
-
sourcecode-5.9.
|
|
286
|
-
sourcecode-5.9.
|
|
287
|
-
sourcecode-5.9.
|
|
281
|
+
sourcecode/_docs/USER_GUIDE.md,sha256=5gVJnyzQHCNyJ3DgIU6VOJZCrjs9l7CQCrd9NLKcm2Y,108622
|
|
282
|
+
sourcecode-5.9.24.dist-info/METADATA,sha256=q0KEBFlKjiFJYo9Rm70yw5wVAw-NMQqZWgphjEOieu8,67389
|
|
283
|
+
sourcecode-5.9.24.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
284
|
+
sourcecode-5.9.24.dist-info/entry_points.txt,sha256=-JEAdChrK5We51kZcb7OaDcyil-dHBjBPL-NhuO-QY8,89
|
|
285
|
+
sourcecode-5.9.24.dist-info/licenses/LICENSE,sha256=23-fk61oSWGVmkWyka-FIM0rhAPM2hcYHnsaridL8Uo,1859
|
|
286
|
+
sourcecode-5.9.24.dist-info/licenses/NOTICE,sha256=Br-AA8Y3iJo1WXa5uP8QBpzqI5nDu3iGLbFyvDt3BOs,321
|
|
287
|
+
sourcecode-5.9.24.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|