sourcecode 5.9.25__py3-none-any.whl → 5.9.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.

Potentially problematic release.


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

sourcecode/__init__.py CHANGED
@@ -4,4 +4,4 @@ ASK Engine is the product. ``ask`` is the canonical CLI command; ``sourcecode``
4
4
  the legacy compatibility alias and the Python/PyPI package name. See
5
5
  docs/PRODUCT_IDENTITY.md (normative)."""
6
6
 
7
- __version__ = "5.9.25"
7
+ __version__ = "5.9.26"
@@ -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 = 'd28b0cc19426b100d47381ab842d291860c6c3a2'
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}
3
+ BUILD_COMMIT = '2f283c4d305e2709dc154a4399650c2042b28d68'
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-15`': {'commit': '', 'status': 'uncited'}, '`BUG-21`': {'commit': '', 'status': 'uncited'}, '`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-01`': {'commit': '', 'status': 'uncited'}, '`REG-04`': {'commit': '', 'status': 'uncited'}}
5
+ CLOSURE_COVERAGE = {'closed_rows': 169, 'present': 91, 'absent': 0, 'unresolved': 0, 'uncited': 78, 'unknown': 0}
@@ -14,57 +14,82 @@ 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 — Alternative External Audit `5.9.23`, carried into `5.9.25` (2026-09-01)
18
-
19
- **Release gate: do not use 5.9.25 to gate unattended CI through the audit-command
20
- family.** A native-Windows alternative audit of the 5.9.23 build measured 55
21
- `rc=0`, zero-byte answers and eight timeouts in 84 runs. The failures include
22
- `spring-audit`, `verify`, `risk`, Markdown `audit-report`, `migrate-check`, and
23
- `migrate-apply`; the prior 3/47 observation was materially incomplete. The
24
- cause remains unproven. A security-rules phase is a supported hypothesis, not a
25
- closure claim. `exit 0` is valid only for a non-empty stdout answer or a verified
26
- `--output` artifact; a missing phase result must be structured failure, never an
27
- empty finding set.
28
-
29
- Priority order is: `ALT-01` silent success and unkept output promises;
30
- `ALT-02` budget/partial-result failure; `ALT-03` security-rules phase bisection;
31
- `ALT-04` content-id instability; `ALT-05` contradictory migration totals;
32
- `ALT-06` false-complete selftest; then remediation, context bounds and CLI
33
- ergonomics. Full evidence: [`AUDIT-2026-09-01-ALTERNATIVE-5.9.23.md`](AUDIT-2026-09-01-ALTERNATIVE-5.9.23.md)
34
- and [`AUDIT-2026-09-01-EXTERNAL-5.9.23.md`](AUDIT-2026-09-01-EXTERNAL-5.9.23.md).
17
+ ## Current Synchronization — Alternative External Audit `5.9.25`, and External Audit `5.9.25` (2026-09-02)
18
+
19
+ **Release `5.9.26` closes eight rows from this round with verified evidence**
20
+ (`ALT-09`, `ALT-11`, `BUG-01`, `BUG-03`, `REG-02`'s disclosure half, `ALT-06`'s
21
+ itemization half, plus the `remediation-report` path-admission coverage gap
22
+ and the `ALT-01`/`ALT-03` forensic sidecar) — see each row below for the
23
+ commit-level detail, and `CHANGELOG.md` for the release note. It does **not**
24
+ close the release gate: `ALT-01`/`ALT-03` were investigated and instrumented,
25
+ not fixed, because the failure did not reproduce outside native Windows.
26
+
27
+ **Release gate unchanged and now more urgent: do not use 5.9.25 or 5.9.26 to
28
+ gate unattended CI through the audit-command family.** Two independent re-audits of
29
+ 5.9.25 agree the empty-`exit 0` defect did not shrink. The multi-repository
30
+ audit measured it at 18.4% (9/49, byte-counted) and, for the first time, in
31
+ `spring-audit` itself — the command the tool's own help recommends first. The
32
+ native-Windows audit found the same failure has gone from a hang to something
33
+ **erratic**: the identical `migrate-apply .` invocation gave 8/8 empty answers
34
+ in one batch and 3/3 full answers minutes later with nothing else changed, and
35
+ the failure spread to `migrate-check` and `onboard`, both reliable in 5.9.23.
36
+ `ALT-01` is **reopened**: the commit cited as closing it does not hold under
37
+ native re-test — `risk . -o FILE` still returns `rc=0`, zero bytes, and no
38
+ file in 4/4 runs.
39
+
40
+ Three rows are genuinely closed with verified evidence this round: `ALT-04`
41
+ (content-id clock exclusion, 3/3 stable hashes), `ALT-05` (findings-population
42
+ reconciliation, exact arithmetic), and `REG-01` (root `ask --help` no longer
43
+ hangs — sub-linear cost curve up to 4,772 files; the original 31-repo extreme
44
+ case was not re-confirmed). `BUG-15` (Rich markup leak) and `BUG-21`
45
+ (`--jobs` range validation) also close cleanly.
46
+
47
+ Priority order is: `ALT-01` reopened silent success and unkept output
48
+ promises; `ALT-03` security/audit-phase bisection, now with an erratic rather
49
+ than hang-only signature; `ALT-09` (new) `cache clear` ignoring a piped `n`
50
+ answer; `REG-02` agent memory ceiling; `BUG-01` silent malformed-file
51
+ disappearance; then `ALT-07` remediate hang, `ALT-10`/`ALT-11` new latency and
52
+ ergonomics findings, and remaining CLI ergonomics. Full evidence:
53
+ [`AUDIT-2026-09-02-ALTERNATIVE-5.9.25.md`](AUDIT-2026-09-02-ALTERNATIVE-5.9.25.md)
54
+ and [`AUDIT-2026-09-02-EXTERNAL-5.9.25.md`](AUDIT-2026-09-02-EXTERNAL-5.9.25.md).
35
55
 
36
56
  | ID | Severity | Status | Evidence and required closure |
37
57
  |---|---:|---|---|
38
- | `ALT-01` | Critical maximum | **fixed, pending native-Windows repetition** | `a7ad44b` hardens the required-answer and output-artifact guards: `exit 0` now requires delivered stdout or a verified requested artifact. Native 30-run repetition remains the release closure evidence. |
58
+ | `ALT-01` | Critical maximum | **reopened, contradicted by native re-test** | `risk . -o FILE` returned `rc=0`, 0 bytes, no file in 4/4 native runs. Source review of the guard (`_fail_on_missing_required_answer`, `_fail_on_unkept_output_promise`, armed for `risk`/`spring-audit`/`verify`/`audit-report`/`migrate-check`/`migrate-apply` via `REQUIRED_ANSWER_COMMANDS`) finds it correctly wired end to end on this platform; the field failure is not reproducible outside native Windows. Both guards now write a forensic sidecar (`empty_answer_diagnostics.record`, referenced as `diagnostics_path` in the error envelope) capturing phase/RSS/argv/pid at the exact moment either fires, so the next occurrence carries evidence instead of a report written from memory. This does not close the row — it makes the next native reproduction diagnosable. |
39
59
  | `ALT-02` | Critical maximum | **fixed, bounded-phase follow-up** | `aab1e8b` propagates deadline checks into security posture and publishes omitted stages and partial coverage. A small-repository budget can still finish its coarse earlier phases before the deadline is observed; `ALT-03` owns reducing that phase granularity. |
40
- | `ALT-03` | High | **open, investigation** | The security-rules phase is the common evidence-backed suspect: all affected audit flows consume security findings, security `retrieve` queries timed out, and `remediate` stalled in the same phase. Bisect the known working small subtree against the 3,342-file root; do not assert causality before reproducing it. |
41
- | `ALT-04` | High | **fixed** | `36e3893` excludes every nested `*_time_ms` execution clock from `content_id`; parametric tests retain semantic-field sensitivity. |
42
- | `ALT-05` | High | **fixed** | `b12c8f1` publishes `population_total` and `excluded_before_cap` beside the compact findings cap, reconciling it with the summary population. |
43
- | `ALT-06` | High | **fixed** | `6d0889e` publishes structured limitations for failed, unrun and unknown ledger rows; `5620864` also makes generic task `gaps` invalidate envelope completeness. |
60
+ | `ALT-03` | High | **open, investigation, sharper signature** | Failures are now mostly near-instant (1-2s) empty success rather than multi-minute hangs on the same commands — consistent with a phase being *skipped*, not *stuck*. The audit could not isolate a trigger below three concurrent heavy ASK processes. Bisect the known working small subtree against the 3,342-file root; do not assert causality before reproducing it. The `ALT-01` diagnostic sidecar now records the last known phase and peak RSS at the moment of every occurrence, closing the evidence gap the audits both named. |
61
+ | `ALT-04` | High | **fixed, confirmed** | `36e3893` excludes every nested `*_time_ms` execution clock from `content_id`. Re-confirmed: `impact-chain` gave the same hash across 3 repeated native runs (was 3 different hashes in 5.9.23). |
62
+ | `ALT-05` | High | **fixed, confirmed** | `b12c8f1` publishes `population_total` and `excluded_before_cap` beside the compact findings cap. Re-confirmed with exact arithmetic: `1526 - 593 = 933 = by_rule.MIG-016`. |
63
+ | `ALT-06` | High | **fixed** | `complete` is correctly `false` when rows fail. The itemization half is also closed: `answer_bounds._summarise` picked a dict's `id` before its `reason`/`what`, so `selftest`'s per-category `limitations` entries rendered as the bare slug (`selftest_rows_failed`) with the actual failing row IDs dropped even though `reason` and the new `rows` field named them. `_summarise` now prefers the descriptive text; no other producer in this codebase pairs `id` with `what`/`reason` on the same dict, so nothing else changes. |
44
64
  | `ALT-07` | Medium | **open** | `remediate` regressed from a 23.6-second answer to hangs beyond 400 seconds in `auditing for repairable findings`; it shares the `ALT-03` investigation until separated by evidence. |
45
- | `ALT-08` | Medium | **fixed** | `15d77d2` publishes the effective per-task stdout budget and the full-artifact path; bounded output remains skipped only for explicit `--output` artifacts. |
46
- | `NEW-01` | Critical maximum | **superseded by ALT-01** | The earlier 3/47 `risk` and Markdown `audit-report` observation undercounted the native-Windows audit-family failure. |
47
- | `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. |
48
- | `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. |
49
- | `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. |
50
- | `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. |
51
- | `NEW-02` | High | **open** | Overloaded endpoint handlers can all inherit the final overload's `declaration_line`. Resolve by mapping annotation/signature or publish ambiguity. |
52
- | `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. |
65
+ | `ALT-08` | Medium | **fixed, confirmed** | `15d77d2` publishes the effective per-task stdout budget and the full-artifact path; confirmed functioning, with a minor arithmetic mismatch in `prepare-context review-pr`'s `_truncation_summary` noted as low-severity follow-up. |
66
+ | `ALT-09` | Critical | **open, new** | `ask cache clear .` deletes cache entries even when piped stdin answers `n`; only true EOF (`< /dev/null`) correctly refuses. The non-interactivity detector appears to treat "stdin has bytes" as "proceed" instead of reading and comparing them against `y`/`yes`. Low blast radius today (cache is rebuildable); fix the detection to use `isatty()` plus an actual answer comparison before any future destructive command reuses the same pattern. |
67
+ | `ALT-10` | Medium | **open, new** | `onboard .` took 164.9s cold in one native session versus a consistent 681-780ms in every prior round on the same repository (~240x). Delivered a full answer, so not release-blocking alone; profile for a shared warm-up path with the `ALT-01`/`ALT-03` commands. |
68
+ | `ALT-11` | Low | **fixed** | `watch` now emits a `{"tick": 0, "status": "watching", "elapsed_ms": …}` NDJSON line on stdout immediately after the index warms and before the tick loop begins — the channel `watch` already promises a consumer is reading, unlike stderr, whose silence on a non-TTY stream is a deliberate, tested invariant elsewhere in the CLI. Written to `--output` too. |
69
+ | `NEW-01` | Critical maximum | **escalated** | Now measured at 18.4% (9/49, byte-counted) and reaches `spring-audit --compact` in addition to `risk` and Markdown `audit-report`. Two identical back-to-back `spring-audit thingsboard --compact` runs (46,596 bytes/69.7s, then 0 bytes/57.2s) refute the earlier "only on abnormally fast runs" hypothesis. `BUG-17` (`remediation-report` silently empty on an unexpected positional, rather than `INVALID_USAGE`) does not reproduce as described here: the command returns its normal, non-empty bundled-ledger report regardless of the path given, by design (`del path` — "the bundled ledger is used"), so it is not the same failure class as `NEW-01`. What is real and now fixed is narrower: `path_admission`'s own coverage battery had a gap for exactly this command — `remediation-report`'s `path` parameter matched the battery's repo-path discovery heuristic with no invocation row, a pre-existing red independent of this audit. Closed by documenting the exclusion inline (`PATH_NOT_READ_BY_DESIGN` in `tests/test_path_admission.py`), the same "opt-out is a decision, not an omission" convention `cli.py` already uses for `--copy`/`Progress`. |
70
+ | `REG-02` | Critical | **partially fixed: disclosure half closed, enforcement-timing half open** | Reproduced and fixed the specific gap named in both audits: a successful `--agent` run published `_meta.memory.configured_max_rss_mb: null` even though `_root_memory_seam` was actively enforcing the 1,536 MB default at every phase boundary for that same run. `disclosure()` now takes the same `default_ceiling_mb` `exceeded()` already did, and the root command threads whether `--agent` is active through a per-invocation flag (`_AGENT_MODE_ACTIVE`) so a successful run says what protected it. The still-open half — the ceiling rejecting large repositories only after minutes of work, and a higher observed peak than 5.9.23 (2,029.92 MB vs 1,552.45 MB) — needs periodic RSS sampling with early abort inside the expensive phases themselves (`BUG-22`'s row), which cannot be validated without the field's own large repository. |
71
+ | `REG-03` | High | **open, regression, unchanged** | Warm `spring-audit` still shows no reliable time or reliability benefit over cold; the `NEW-01` back-to-back pair is itself the sharpest evidence, since the "warm" run was proportionally slower and the one that came back empty. |
72
+ | `REG-01` | High | **closed, resolved on measured range** | Root `ask --help` no longer hangs in a nested-repository workspace: cost now scales sub-linearly (49 files: 608ms; 4,772 files: 13.6s), against 82-86s trending to 120s+/`rc=124` in 5.9.23. The original 31-repo/8,322-file extreme case was not re-confirmed — the audit's own 110s harness cutoff interrupted it. Re-run that specific extreme case before treating the ceiling as proven. |
73
+ | `REG-04` | Medium | **closed 5.9.24, reconfirmed** | `_meta.answer_bounds.capped` aggregation re-verified in `migrate-check --compact`: all 5 nested cap contracts listed, 268 omitted values disclosed. |
74
+ | `NEW-02` | High | **open, unchanged** | Overloaded endpoint handlers can all inherit the final overload's `declaration_line`; the `anchor_ambiguity`/`overload_count` fields expected from this row are still absent from the payload. Resolve by mapping annotation/signature or publish ambiguity. |
75
+ | `BUG-01` | Critical maximum | **fixed, mechanism narrowed, not eliminated** | Reproduced directly: a missing `;` or a missing `)` on a method signature both extract a clean class+method symbol pair with balanced braces, so the E-10 brace-only check (`unbalanced_braces`) never fired and the file passed as clean. `repository_ir.py` now also masks and checks paren balance (`unbalanced_parens`), publishing the same `parse_structure` gap for that shape. This is a heuristic extractor without a real Java grammar, so a syntax error that disturbs neither braces nor parens (for example a missing operand with balanced punctuation on both sides) remains undetectable by construction — the row stays open at lower severity for that residual class, not closed. |
53
76
  | `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. |
54
77
  | `BUG-12` | Critical maximum | **open, P0** | Deep `--agent` output construction reaches multi-gigabyte RSS before a small answer. Bound projection while building. |
55
- | `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. |
78
+ | `BUG-03` | High | **fixed** | `non_coverage.stack_fit`'s marginal-detection disclosure (`fit: "partial"`, below 10% Spring-bean density) has existed since AUD-596-D13 but was unreachable from `risk` and `posture`: neither call site passed `spring_footprint`, so `java_files` stayed 0 and the branch that reads it could never fire regardless of the real ratio. Both now compute it the same way `spring-audit`'s own call already did (`sum(bean.spring for bean in graph.beans.values())` over `len(cir.files)`); verified end to end on a 1-bean/16-file fixture. |
56
79
  | `BUG-04` | High | **open, P1** | `selftest` publishes `complete=true` with five error rows. Derive bounds from actual results. |
57
80
  | `BUG-05` | High | **open, P1** | Overloaded endpoint handlers can receive the wrong declaration line. Resolve by mapping annotation or publish ambiguity. |
58
81
  | `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. |
59
- | `BUG-10` | High | **open, P1** | Unsupported routing styles can produce empty coverage gaps. Publish detected-but-unmodeled routing gaps. |
60
- | `BUG-11` | High | **open, P1** | Default `pack assessment` can fail on a small Spring repository. Use a bounded default or explicit full mode. |
61
- | `BUG-13` | High | **open, P1** | Unscoped `selftest` starts over nested repositories after warning. Refuse and require an explicit path. |
62
- | `BUG-16` | High | **open, P1** | Context-cache growth has no published budget or eviction contract; about 1.5 GB was measured. |
82
+ | `BUG-10` | High | **open, P1, unchanged** | Unsupported routing styles can produce empty coverage gaps. Publish detected-but-unmodeled routing gaps. |
83
+ | `BUG-11` | High | **open, P1, now hangs instead of failing fast** | Default `pack assessment` and `pack gate --since` now hang to their external kill (300s/200s) instead of the legitimate `INVALID_INPUT`/`INVALID_USAGE` they gave in 5.9.23 — both compose the audit-family commands affected by `ALT-01`/`ALT-03` and inherit the failure. |
84
+ | `BUG-13` | High | **open, P1, unchanged** | Unscoped `selftest` starts over nested repositories after warning. Refuse and require an explicit path. |
85
+ | `BUG-15` | Low | **closed 5.9.25** | Non-TTY `ask --help` no longer emits Rich markup: 0 occurrences of `[bold]`/`[dim]`/`[bold green]`, down from 208 (5.9.22) and 202 (5.9.23). |
86
+ | `BUG-16` | High | **open, P1, unchanged** | Context-cache growth has no published budget or eviction contract; ~1.7 GB was measured (was ~1.6 GB in 5.9.23). |
87
+ | `BUG-21` | Low | **closed 5.9.25** | `--jobs` now rejects out-of-range values with `INVALID_USAGE` stating the `1<=x<=128` bound, replacing silent acceptance. |
63
88
  | `BUG-22` | High | **open, P1** | RSS ceilings are checked post-hoc. Add periodic sampling and orderly abort. |
64
89
 
65
- The remaining `BUG-04b`, `BUG-06`, `BUG-08`, `BUG-09`, `BUG-15`, `BUG-19`,
66
- `BUG-20`, `BUG-21` and `BUG-23` findings are open P2/coverage follow-ups in
67
- the audit document. None is closed by documentation alone.
90
+ The remaining `BUG-04b`, `BUG-06`, `BUG-08`, `BUG-09`, `BUG-19`, `BUG-20` and
91
+ `BUG-23` findings are open P2/coverage follow-ups in the audit document. None
92
+ is closed by documentation alone.
68
93
 
69
94
  ## Current Synchronization — External Audit `AUD-621`
70
95
 
@@ -279,7 +279,7 @@ pipx install sourcecode # isolated install, no venv needed
279
279
 
280
280
  # Verify
281
281
  ask version
282
- # ask 5.9.25
282
+ # ask 5.9.26
283
283
  ```
284
284
 
285
285
  Requires Python 3.9+.
@@ -77,7 +77,16 @@ def _summarise(value: Any) -> Any:
77
77
  payloads would see the same fact move twice.
78
78
  """
79
79
  if isinstance(value, dict):
80
- for key in ("id", "what", "reason", "not_covered", "message", "title"):
80
+ # R-05 (5.9.25 alternative audit): `reason`/`what` are the producer's
81
+ # own descriptive sentence about the gap; `id` is a stable category
82
+ # slug meant for a consumer that filters programmatically, not for a
83
+ # human reading `gaps`. `id` used to be checked first, so a producer
84
+ # that published both (selftest's `limitations`) had its actual
85
+ # itemized detail — which rows, not just how many — silently dropped
86
+ # in favor of the bare slug. No other producer in this codebase pairs
87
+ # `id` with `what`/`reason` on the same dict, so this reorder changes
88
+ # nothing for any of them.
89
+ for key in ("what", "reason", "not_covered", "message", "title", "id"):
81
90
  if key in value and isinstance(value[key], str):
82
91
  return value[key][:200]
83
92
  return {k: v for k, v in list(value.items())[:3] if not isinstance(v, (dict, list))}
sourcecode/cli.py CHANGED
@@ -1746,6 +1746,44 @@ def _stdin_is_interactive() -> bool:
1746
1746
  return False
1747
1747
 
1748
1748
 
1749
+ def _read_piped_answer(*, timeout: float = 0.2) -> Optional[str]:
1750
+ """Best-effort read of a non-interactive stdin's actual content.
1751
+
1752
+ ALT-09 (5.9.25 alternative audit): the non-interactive branch of a
1753
+ destructive prompt treated *any* redirected stdin as an implicit "yes" —
1754
+ `echo n | ask cache clear .` deleted cache files despite the piped answer
1755
+ being an explicit refusal, and only true immediate EOF (`< /dev/null`)
1756
+ happened to refuse, by accident of `_confirm`'s own EOF handling on a
1757
+ different path. A non-interactive caller can still mean to answer.
1758
+
1759
+ This reads one line on a background thread and gives it `timeout` seconds
1760
+ to arrive. A pipe with data (or a closed pipe with none) resolves almost
1761
+ immediately either way. A stdin that is open but never closed — an
1762
+ inherited terminal fd, an MCP session — resolves neither within the
1763
+ window, and this returns `None` rather than block: the caller falls back
1764
+ to its prior default-confirm behavior in that case, unchanged.
1765
+ """
1766
+ import threading
1767
+
1768
+ result: list = [None]
1769
+
1770
+ def _reader() -> None:
1771
+ try:
1772
+ result[0] = sys.stdin.readline()
1773
+ except Exception:
1774
+ result[0] = None
1775
+
1776
+ reader = threading.Thread(target=_reader, daemon=True)
1777
+ reader.start()
1778
+ reader.join(timeout)
1779
+ if reader.is_alive():
1780
+ return None
1781
+ line = result[0]
1782
+ if not line:
1783
+ return None
1784
+ return line.strip()
1785
+
1786
+
1749
1787
  def _confirm(question: str, *, command: str, default: bool = False, err: bool = False) -> bool:
1750
1788
  """Ask a yes/no question, and diagnose a prompt that cannot be answered.
1751
1789
 
@@ -2160,7 +2198,16 @@ def _stamp_envelope(content: str) -> str:
2160
2198
  try:
2161
2199
  from sourcecode import resource_budget
2162
2200
 
2163
- extra["memory"] = resource_budget.disclosure()
2201
+ # REG-02: `--agent` enforces `DEFAULT_AGENT_RSS_CEILING_MB` at every
2202
+ # phase boundary (`_root_memory_seam`) whether or not `ASK_MAX_RSS_MB`
2203
+ # was set, so a successful run under it must not disclose "no ceiling
2204
+ # configured" — that was the exact gap the field measured.
2205
+ extra["memory"] = resource_budget.disclosure(
2206
+ default_ceiling_mb=(
2207
+ resource_budget.DEFAULT_AGENT_RSS_CEILING_MB
2208
+ if _AGENT_MODE_ACTIVE else None
2209
+ ),
2210
+ )
2164
2211
  except Exception as _exc: # a footprint sample is not the envelope
2165
2212
  degraded = degraded or f"memory disclosure unavailable: {type(_exc).__name__}"
2166
2213
 
@@ -3000,6 +3047,12 @@ _OUTPUT_PROMISED: "Optional[str]" = None
3000
3047
  _OUTPUT_DELIVERED: bool = False
3001
3048
  _ANSWER_REQUIRED_BY: "Optional[str]" = None
3002
3049
 
3050
+ #: REG-02. Whether the running root invocation set `--agent`, so the envelope
3051
+ #: builder can disclose the mode-specific RSS default `_root_memory_seam`
3052
+ #: actually enforces — set at the same point that seam is armed, and reset at
3053
+ #: the top of `main()` like every other per-invocation global here.
3054
+ _AGENT_MODE_ACTIVE: bool = False
3055
+
3003
3056
  # ALT-01. These commands publish repository-analysis answers. A successful
3004
3057
  # process with neither stdout nor a verified output artifact is never valid.
3005
3058
  # Kept as one authority so the entry point can arm the guard before Click enters
@@ -3094,6 +3147,9 @@ def _fail_on_missing_required_answer(exit_code: object) -> None:
3094
3147
  """Turn a silent successful composed run into a typed failure (C3-122)."""
3095
3148
  if exit_code not in (0, None) or _OUTPUT_DELIVERED or not _ANSWER_REQUIRED_BY:
3096
3149
  return
3150
+ from sourcecode import empty_answer_diagnostics as _diag
3151
+
3152
+ _diag_path = _diag.record(_ANSWER_REQUIRED_BY, "missing_required_answer")
3097
3153
  _emit_error_json(
3098
3154
  EXECUTION_FAILED_CODE,
3099
3155
  f"{_ANSWER_REQUIRED_BY} finished without publishing an answer.",
@@ -3104,6 +3160,10 @@ def _fail_on_missing_required_answer(exit_code: object) -> None:
3104
3160
  ),
3105
3161
  command=_ANSWER_REQUIRED_BY,
3106
3162
  expected="parseable stdout or the requested output artifact",
3163
+ # ALT-03/NEW-01: two audits measured this outcome without pinning a
3164
+ # mechanism. This sidecar captures phase/RSS/argv at the moment of
3165
+ # failure so the next occurrence carries its own forensic record.
3166
+ diagnostics_path=_diag_path,
3107
3167
  )
3108
3168
  raise SystemExit(1)
3109
3169
 
@@ -3122,6 +3182,11 @@ def _fail_on_unkept_output_promise(exit_code: object) -> None:
3122
3182
  missing = _unkept_output_promise()
3123
3183
  if missing is None:
3124
3184
  return
3185
+ from sourcecode import empty_answer_diagnostics as _diag
3186
+
3187
+ _diag_path = _diag.record(
3188
+ _ANSWER_REQUIRED_BY, "unkept_output_promise", promised_path=str(missing),
3189
+ )
3125
3190
  _emit_error_json(
3126
3191
  EXECUTION_FAILED_CODE,
3127
3192
  f"The run finished without producing '{missing}'.",
@@ -3133,6 +3198,9 @@ def _fail_on_unkept_output_promise(exit_code: object) -> None:
3133
3198
  ),
3134
3199
  expected="The file named by --output.",
3135
3200
  path=str(missing),
3201
+ # ALT-01: the guard closing on paper did not close it in the field.
3202
+ # This sidecar captures phase/RSS/argv at the moment of failure.
3203
+ diagnostics_path=_diag_path,
3136
3204
  )
3137
3205
  raise SystemExit(1)
3138
3206
 
@@ -5547,6 +5615,8 @@ def main(
5547
5615
  cache_observation.reset()
5548
5616
  except Exception:
5549
5617
  pass
5618
+ global _AGENT_MODE_ACTIVE
5619
+ _AGENT_MODE_ACTIVE = False
5550
5620
  _apply_jobs(jobs)
5551
5621
  # A root option so the ceiling is one policy rather than sixty flags, and an
5552
5622
  # environment variable so it survives into a subcommand's own parse: Click
@@ -5858,6 +5928,7 @@ def main(
5858
5928
 
5859
5929
  # --agent: enable signal analyzers; output via agent_view (not compact)
5860
5930
  if agent:
5931
+ _AGENT_MODE_ACTIVE = True
5861
5932
  dependencies = True
5862
5933
  env_map = True
5863
5934
  code_notes = True
@@ -17684,6 +17755,7 @@ def watch_cmd(
17684
17755
 
17685
17756
  _prog = Progress()
17686
17757
  _prog.start("warming the index")
17758
+ _warm_t0 = time.monotonic()
17687
17759
  try:
17688
17760
  from sourcecode import context_cache as _ctxcache
17689
17761
 
@@ -17700,6 +17772,24 @@ def watch_cmd(
17700
17772
  try:
17701
17773
  if output_path is not None:
17702
17774
  _sink = open(output_path, "w", encoding="utf-8")
17775
+ # ALT-11 (5.9.25 audit): a non-TTY `watch` gave no output at all until
17776
+ # its first change or its external timeout — indistinguishable from
17777
+ # hung. The `Progress` spinner above stays correctly silent there by
17778
+ # design (a non-interactive command's stderr is a byte-identical
17779
+ # contract), so the confirmation belongs in the one channel `watch`
17780
+ # already promises a consumer is reading: its own NDJSON stdout.
17781
+ from sourcecode.watch_loop import WatchEvent
17782
+
17783
+ _warming_event = WatchEvent(
17784
+ tick=0, status="watching",
17785
+ elapsed_ms=int((time.monotonic() - _warm_t0) * 1000),
17786
+ )
17787
+ _warming_line = _json.dumps(_warming_event.to_dict(), ensure_ascii=False)
17788
+ lines.append(_warming_line)
17789
+ typer.echo(_warming_line)
17790
+ if _sink is not None:
17791
+ _sink.write(_warming_line + "\n")
17792
+ _sink.flush()
17703
17793
  for event in watch(
17704
17794
  target,
17705
17795
  analyse=analyse_with_pr_impact(target, cir, model),
@@ -20695,6 +20785,12 @@ def cache_clear_cmd(
20695
20785
  typer.echo("Aborted.", err=True)
20696
20786
  raise typer.Exit(code=1)
20697
20787
  else:
20788
+ # ALT-09: a piped answer is read and honored before falling back
20789
+ # to the idempotent-cleanup default; see `_read_piped_answer`.
20790
+ _answer = _read_piped_answer()
20791
+ if _answer is not None and _answer.lower() in ("n", "no"):
20792
+ typer.echo("Aborted.", err=True)
20793
+ raise typer.Exit(code=1)
20698
20794
  typer.echo(
20699
20795
  f"Non-interactive: clearing cache for {target}{_ris_note}. "
20700
20796
  "Pass --yes to silence this notice.",
@@ -21364,14 +21460,21 @@ def cache_context_clear_cmd(
21364
21460
  """Delete the AI Context Cache for a repository (structured context + stats)."""
21365
21461
  from sourcecode import context_cache as _ctxcache
21366
21462
  target = _resolve_repo_root(Path(path))
21367
- if not yes and _stdin_is_interactive():
21368
- if not _confirm(
21369
- f"Delete AI context cache for {target}?",
21370
- command="ask cache context-clear",
21371
- err=True,
21372
- ):
21373
- typer.echo("Aborted.", err=True)
21374
- raise typer.Exit(code=1)
21463
+ if not yes:
21464
+ if _stdin_is_interactive():
21465
+ if not _confirm(
21466
+ f"Delete AI context cache for {target}?",
21467
+ command="ask cache context-clear",
21468
+ err=True,
21469
+ ):
21470
+ typer.echo("Aborted.", err=True)
21471
+ raise typer.Exit(code=1)
21472
+ else:
21473
+ # ALT-09: same piped-answer read as `cache clear`.
21474
+ _answer = _read_piped_answer()
21475
+ if _answer is not None and _answer.lower() in ("n", "no"):
21476
+ typer.echo("Aborted.", err=True)
21477
+ raise typer.Exit(code=1)
21375
21478
  removed = _ctxcache.clear_for_repo(target)
21376
21479
  typer.echo(f"Removed {removed} context file(s).")
21377
21480
 
@@ -0,0 +1,94 @@
1
+ """Forensic snapshot for the unproven empty-`exit 0` field defect (ALT-01/ALT-03/NEW-01).
2
+
3
+ Two independent 5.9.25 audits measured `spring-audit`, `verify`, `risk`,
4
+ `audit-report`, `migrate-check` and `migrate-apply` returning `exit 0` with an
5
+ empty answer — from 3/47 to 18.4% of runs — and neither could pin a
6
+ mechanism: a directed 2-concurrent-process contention test reproduced 5/5
7
+ with a full answer, the empty runs ranged from near-instant to a multi-minute
8
+ hang, and a correlation with 3+ concurrent heavy processes is explicitly
9
+ unconfirmed, not established. Every guard already in `cli.py`
10
+ (`_fail_on_missing_required_answer`, `_fail_on_unkept_output_promise`) turns
11
+ this into a typed failure instead of a false `exit 0` — but neither guard,
12
+ nor static reading of the code they protect, can explain *why* the answer was
13
+ missing on an unreproduced Windows race. Shipping a guess at that mechanism
14
+ without evidence is how a real defect gets marked closed on a plausible
15
+ story instead of a fact (the house rule this ledger is built on).
16
+
17
+ What is directly actionable without a Windows repro is what both audits asked
18
+ for explicitly: capture the process's own state at the exact moment either
19
+ guard is about to fire, every time it fires, so the next occurrence in the
20
+ field carries its own forensic record instead of a report written from
21
+ memory afterward.
22
+ """
23
+ from __future__ import annotations
24
+
25
+ import json
26
+ import os
27
+ import sys
28
+ import time
29
+ import uuid
30
+ from pathlib import Path
31
+ from typing import Any, Optional
32
+
33
+ #: Override for the diagnostics directory, mirroring `SOURCECODE_CACHE_DIR`'s
34
+ #: shape. Independent of the per-repository cache: this fires exactly when a
35
+ #: repository-scoped cache directory may not have been resolved yet.
36
+ ENV_DIAGNOSTICS_DIR = "SOURCECODE_DIAGNOSTICS_DIR"
37
+
38
+ #: Diagnostics are capped so a genuinely recurring failure cannot grow this
39
+ #: directory without bound; the newest snapshots are what a bisection needs.
40
+ _MAX_SNAPSHOTS = 200
41
+
42
+
43
+ def _diagnostics_dir() -> Path:
44
+ from sourcecode.cache import _user_home
45
+
46
+ override = os.environ.get(ENV_DIAGNOSTICS_DIR, "")
47
+ return Path(override) if override else _user_home() / ".sourcecode" / "diagnostics"
48
+
49
+
50
+ def record(command: Optional[str], reason: str, **extra: Any) -> Optional[str]:
51
+ """Write a best-effort snapshot of process state; return its path or None.
52
+
53
+ Never raises and never blocks meaningfully: this runs on the failure path
54
+ of a command that is already about to report a typed error, so a
55
+ diagnostics write must not become a second failure, mask the first one,
56
+ or cost the caller real latency.
57
+ """
58
+ try:
59
+ from sourcecode import resource_budget as _rb
60
+ from sourcecode.progress import last_known_phase
61
+
62
+ snapshot: dict = {
63
+ "recorded_at": time.time(),
64
+ "command": command,
65
+ "reason": reason,
66
+ "pid": os.getpid(),
67
+ "argv": sys.argv[1:],
68
+ "phase": last_known_phase(),
69
+ "peak_rss_mb": _rb.peak_rss_mb(),
70
+ "python": sys.version.split()[0],
71
+ "platform": sys.platform,
72
+ }
73
+ snapshot.update(extra)
74
+ directory = _diagnostics_dir()
75
+ directory.mkdir(parents=True, exist_ok=True)
76
+ name = f"{int(snapshot['recorded_at'])}-{os.getpid()}-{uuid.uuid4().hex[:8]}.json"
77
+ path = directory / name
78
+ path.write_text(
79
+ json.dumps(snapshot, indent=2, sort_keys=True, ensure_ascii=True, default=str),
80
+ encoding="utf-8",
81
+ )
82
+ _prune(directory)
83
+ return str(path)
84
+ except Exception:
85
+ return None
86
+
87
+
88
+ def _prune(directory: Path) -> None:
89
+ try:
90
+ files = sorted(directory.glob("*.json"), key=lambda p: p.stat().st_mtime)
91
+ for stale in files[: max(0, len(files) - _MAX_SNAPSHOTS)]:
92
+ stale.unlink(missing_ok=True)
93
+ except Exception:
94
+ pass
sourcecode/posture.py CHANGED
@@ -1424,10 +1424,19 @@ def _posture(
1424
1424
  # stack IS modelled cannot be told apart from a build that does not publish
1425
1425
  # it at all, and the catalogue promises it.
1426
1426
  from sourcecode.non_coverage import stack_fit as _stack_fit
1427
+ from sourcecode.spring_model import BeanGraph as _BeanGraph
1427
1428
  from sourcecode.spring_model import spring_detected as _detect_spring
1428
1429
 
1430
+ # BUG-03 (5.9.25 audit): same gap as `risk`'s call — `stack_fit`'s
1431
+ # marginal-detection disclosure was unreachable here without a footprint.
1432
+ _beans = _BeanGraph.build(cir).beans
1429
1433
  payload["stack_fit"] = _stack_fit(
1430
- _detect_spring(cir), security_frameworks=_security_frameworks(cir)
1434
+ _detect_spring(cir),
1435
+ security_frameworks=_security_frameworks(cir),
1436
+ spring_footprint={
1437
+ "spring_beans": sum(1 for bean in _beans.values() if bean.spring),
1438
+ "java_files": len(cir.files),
1439
+ },
1431
1440
  )
1432
1441
  # Which chain is wired is a fact about a bean; what that chain permits is the
1433
1442
  # fact about the request, and it is the one a reviewer asked for.
sourcecode/progress.py CHANGED
@@ -136,6 +136,25 @@ def _terminal_capable() -> bool:
136
136
  return True
137
137
 
138
138
 
139
+ #: The most recent phase any `Progress` in this process entered, and when.
140
+ #: Module-level rather than per-instance so the ALT-03/NEW-01 diagnostic dump
141
+ #: (fired from the top-level exit guard in `cli.py`, which holds no reference
142
+ #: to the command's own `Progress` object) can report what phase a run was in
143
+ #: when it turned out to have produced nothing — the one fact every affected
144
+ #: audit run recorded manually and this product did not.
145
+ _LAST_PHASE: "Optional[dict]" = None
146
+
147
+
148
+ def last_known_phase() -> "Optional[dict]":
149
+ """The last `(phase, entered_at)` recorded by any `Progress` here, or None."""
150
+ return _LAST_PHASE
151
+
152
+
153
+ def _record_phase(phase: str) -> None:
154
+ global _LAST_PHASE
155
+ _LAST_PHASE = {"phase": phase, "entered_at": time.time()}
156
+
157
+
139
158
  class Progress:
140
159
  """In-place spinner on stderr.
141
160
 
@@ -229,6 +248,7 @@ class Progress:
229
248
 
230
249
  def start(self, phase: str = "initializing") -> "Progress":
231
250
  self._t0 = time.monotonic()
251
+ _record_phase(phase)
232
252
  with self._lock:
233
253
  self._phase = phase
234
254
  self._phase_t0 = self._t0
@@ -254,6 +274,7 @@ class Progress:
254
274
  return self
255
275
 
256
276
  def update(self, phase: str) -> None:
277
+ _record_phase(phase)
257
278
  with self._lock:
258
279
  self._phase = phase
259
280
  self._phase_t0 = time.monotonic()
@@ -259,7 +259,8 @@ def _rule_parse_coverage(
259
259
  def parse_structure_findings(
260
260
  unbalanced_files: "frozenset[str]",
261
261
  ) -> list[ReconciliationFinding]:
262
- """Files whose braces do not balance once comments and strings are masked.
262
+ """Files whose braces or parentheses do not balance once comments and
263
+ strings are masked.
263
264
 
264
265
  **E-10.** `BrokenSyntax.java` on spaghetti-api has two opening braces and no
265
266
  closing one — invalid Java by any compiler — and the extractor recovered a
@@ -268,6 +269,13 @@ def parse_structure_findings(
268
269
  indefensible is that the payload said nothing, so a consumer read those
269
270
  symbols with the same confidence as symbols from a file that parses.
270
271
 
272
+ **BUG-01 (5.9.25 audit).** Brace balance alone is a narrow net: `int x = 5`
273
+ missing its `;`, or `void broken( {` missing its `)`, both extract a clean
274
+ class+method pair with balanced braces, so the file passed as clean with no
275
+ disclosure. A masked paren-balance check catches that second shape — a
276
+ parameter or argument list that never closes is invalid Java regardless of
277
+ the braces around it — without a real Java grammar.
278
+
271
279
  Distinct from `parse_coverage`, which fires on *total* extraction absence.
272
280
  This rule fires when extraction succeeded over source that cannot be
273
281
  complete, so what it qualifies is confidence, not presence.
@@ -280,10 +288,11 @@ def parse_structure_findings(
280
288
  rule="parse_structure",
281
289
  symbols=tuple(lost),
282
290
  detail=(
283
- f"{len(lost)} Java file(s) do not have balanced braces once comments "
284
- "and strings are masked — they cannot be valid Java. Symbols "
285
- "recovered from them are a partial reading: members after the "
286
- "unclosed block, and the type's own end, are not modelled."
291
+ f"{len(lost)} Java file(s) do not have balanced braces or "
292
+ "parentheses once comments and strings are masked — they "
293
+ "cannot be valid Java. Symbols recovered from them are a "
294
+ "partial reading: content after the unclosed block or "
295
+ "argument list, and the type's own end, are not modelled."
287
296
  ),
288
297
  )
289
298
  ]
@@ -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-09-01"
30
+ RELEASE_DATE = "2026-09-02"
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
@@ -6824,7 +6824,19 @@ def build_repo_ir(
6824
6824
  })
6825
6825
  # E-10: a brace that never closes is not a style question — it means the
6826
6826
  # symbols recovered from this file stop somewhere the reader cannot see.
6827
- elif symbols and source.count("{") != source.count("}"):
6827
+ #
6828
+ # BUG-01 (5.9.25 audit): brace balance alone missed most real syntax
6829
+ # errors — `int x = 5` with a missing `;`, or `void broken( {` with a
6830
+ # missing `)`, both extract a clean class+method symbol pair with
6831
+ # balanced braces, so the file vanished with no disclosure at all. An
6832
+ # unbalanced *paren* count, masked the same way, catches the second
6833
+ # shape cheaply without a real Java grammar: a method or call whose
6834
+ # parameter/argument list never closes is invalid Java regardless of
6835
+ # what its braces do.
6836
+ elif symbols and (
6837
+ source.count("{") != source.count("}")
6838
+ or source.count("(") != source.count(")")
6839
+ ):
6828
6840
  _masked_src = _mask_java(source)
6829
6841
  if _masked_src.count("{") != _masked_src.count("}"):
6830
6842
  _unbalanced_files.append(rel_path)
@@ -6833,6 +6845,13 @@ def build_repo_ir(
6833
6845
  "status": "recovered",
6834
6846
  "reason": "unbalanced_braces",
6835
6847
  })
6848
+ elif _masked_src.count("(") != _masked_src.count(")"):
6849
+ _unbalanced_files.append(rel_path)
6850
+ _parse_failures.setdefault(rel_path, {
6851
+ "path": rel_path,
6852
+ "status": "recovered",
6853
+ "reason": "unbalanced_parens",
6854
+ })
6836
6855
  _per_file.append((rel_path, package, raw_imports, symbols))
6837
6856
  if "@" in source:
6838
6857
  _parsed_refs = _extract_annotation_type_refs(source, package)
@@ -136,9 +136,18 @@ def configured_ceiling_mb(*, default: Optional[float] = None) -> Optional[float]
136
136
  return value
137
137
 
138
138
 
139
- def disclosure() -> dict[str, Any]:
140
- """Return stable metadata describing the observed process footprint."""
141
- ceiling = configured_ceiling_mb()
139
+ def disclosure(*, default_ceiling_mb: Optional[float] = None) -> dict[str, Any]:
140
+ """Return stable metadata describing the observed process footprint.
141
+
142
+ REG-02 (5.9.25 audit): a successful `--agent` run published
143
+ `configured_max_rss_mb: null` even though `_root_memory_seam` was
144
+ actively enforcing `DEFAULT_AGENT_RSS_CEILING_MB` at every phase boundary
145
+ for that same run — this function had no way to know the mode-specific
146
+ default applied. `default_ceiling_mb` lets a caller that knows which
147
+ default is in force for the active command say so; `exceeded()` already
148
+ takes the same parameter for the enforcement side of this exact fact.
149
+ """
150
+ ceiling = configured_ceiling_mb(default=default_ceiling_mb)
142
151
  peak, basis = peak_rss_sample()
143
152
  return {
144
153
  "unit": "MB",
sourcecode/risk.py CHANGED
@@ -1957,8 +1957,23 @@ def _assemble_payload(
1957
1957
  # rather than by measurement. AUD-596-D13: published in both cases — the
1958
1958
  # model is already built, so it costs nothing, and a catalogued sub-schema
1959
1959
  # that appears only on the repositories nobody asked about is not published.
1960
+ # BUG-03 (5.9.25 audit): `stack_fit`'s marginal-detection disclosure
1961
+ # (`fit: "partial"`, published when Spring beans are under 10% of the
1962
+ # scope) has existed since AUD-596-D13 but was unreachable here — this
1963
+ # call never passed `spring_footprint`, so `java_files` stayed 0 and the
1964
+ # branch that reads it could never fire, regardless of how marginal the
1965
+ # detection actually was. `spring-audit`'s own call
1966
+ # (`spring_security_audit.py`) already computes this the same way.
1967
+ from sourcecode.spring_model import BeanGraph as _BeanGraph
1968
+
1969
+ _model = getattr(composer, "model", None)
1970
+ _beans = (_model.bean_graph if _model is not None else _BeanGraph.build(composer.cir)).beans
1960
1971
  payload["stack_fit"] = non_coverage.stack_fit(
1961
- spring_detected(composer.cir, model=getattr(composer, "model", None))
1972
+ spring_detected(composer.cir, model=_model),
1973
+ spring_footprint={
1974
+ "spring_beans": sum(1 for bean in _beans.values() if bean.spring),
1975
+ "java_files": len(composer.cir.files),
1976
+ },
1962
1977
  )
1963
1978
  # C3-87 (and C2-31's rule, applied to the second consumer): the counts above
1964
1979
  # are arithmetic over what was composed, and on a cut run that is a truncated
sourcecode/selftest.py CHANGED
@@ -954,23 +954,36 @@ def run_selftest(
954
954
  counts = {status: 0 for status in (PASS, FAIL, NOT_APPLICABLE, ERROR)}
955
955
  for result in results:
956
956
  counts[result["status"]] = counts.get(result["status"], 0) + 1
957
+ # R-05 (5.9.25 alternative audit): `answer_bounds.derive` renders each
958
+ # limitation by picking `id` first, and `id` here was a fixed category
959
+ # slug — so a `selftest` payload that failed on ten named rows carried
960
+ # exactly one generic sentence in `_meta.answer_bounds.gaps`, with the
961
+ # actual `rows[]` this payload already publishes never referenced. Each
962
+ # entry now names which rows, in `reason` (what `_summarise` now prefers)
963
+ # and in `rows` (for a consumer that wants the list itself).
964
+ errored_rows = [r["row"] for r in results if r["status"] == ERROR]
965
+ failed_rows = [r["row"] for r in results if r["status"] == FAIL]
957
966
  limitations: list[dict[str, Any]] = []
958
967
  if counts[ERROR]:
959
968
  limitations.append({
960
969
  "id": "selftest_rows_not_run",
961
- "reason": f"{counts[ERROR]} ledger row(s) could not run",
970
+ "reason": f"{counts[ERROR]} ledger row(s) could not run: "
971
+ f"{', '.join(errored_rows)}",
962
972
  "count": counts[ERROR],
973
+ "rows": errored_rows,
963
974
  })
964
975
  if counts[FAIL]:
965
976
  limitations.append({
966
977
  "id": "selftest_rows_failed",
967
- "reason": f"{counts[FAIL]} ledger assertion(s) did not hold",
978
+ "reason": f"{counts[FAIL]} ledger assertion(s) did not hold: "
979
+ f"{', '.join(failed_rows)}",
968
980
  "count": counts[FAIL],
981
+ "rows": failed_rows,
969
982
  })
970
983
  if unknown:
971
984
  limitations.append({
972
985
  "id": "selftest_unknown_rows",
973
- "reason": "requested ledger rows do not exist",
986
+ "reason": f"requested ledger rows do not exist: {', '.join(unknown)}",
974
987
  "rows": unknown,
975
988
  })
976
989
  return {
sourcecode/watch_loop.py CHANGED
@@ -101,7 +101,7 @@ class WatchEvent:
101
101
  """One tick's answer."""
102
102
 
103
103
  tick: int = 0
104
- status: str = "idle" # idle | changed | error
104
+ status: str = "idle" # watching | idle | changed | error
105
105
  changes: Changes = field(default_factory=Changes)
106
106
  analysis: "Optional[dict]" = None
107
107
  error: str = ""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 5.9.25
3
+ Version: 5.9.26
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
- ![Version](https://img.shields.io/badge/version-5.9.25-blue)
62
+ ![Version](https://img.shields.io/badge/version-5.9.26-blue)
63
63
  ![Python](https://img.shields.io/badge/python-3.9%2B-green)
64
64
 
65
65
  Copyright (c) 2026 Dominique Haroun. All rights reserved. ASK Engine 5.7.0 and
@@ -290,7 +290,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
290
290
  # pip / pipx
291
291
  pipx install sourcecode # or: pip install sourcecode
292
292
 
293
- ask version # ask 5.9.25 — and, on a build that has aged,
293
+ ask version # ask 5.9.26 — and, on a build that has aged,
294
294
  # how many releases have probably shipped since
295
295
  ```
296
296
 
@@ -1,10 +1,10 @@
1
- sourcecode/__init__.py,sha256=MtlfIgDZzDrOnmDuTETquhbQ9yFiHFleLZ9oUJXeyhc,309
1
+ sourcecode/__init__.py,sha256=yjkRwJomDMH7QIDQ_QztOQiiuBgCA9f6tISLAKRx-MI,309
2
2
  sourcecode/__main__.py,sha256=qDFVkobwsdZrX0B3stiRqsUNivVpybKO-egzAwCW4xw,165
3
- sourcecode/_build_commit.py,sha256=lOLiVZBzoZPQ5WEGzYe1auvTEGaaZpO4xh_-E6axm2s,11687
3
+ sourcecode/_build_commit.py,sha256=YbiK39JRRfcLPBQ4MwI3XHWbAxoSspOo30E_bkKfgTA,11834
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=mZHTO41wgzq4o6jk1X4QuqOv788rE208AFDvcE0JUz4,11569
7
+ sourcecode/answer_bounds.py,sha256=1okgQxXSz8Tjl5X54Jg9bVL0u1MvmrMCdM1BO_gscf0,12221
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
@@ -35,7 +35,7 @@ sourcecode/change_plan.py,sha256=drAoDsqFplutCLc6Y0xue7sYkTls0SpYh7aOXvttv3I,129
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=NVh5xaPvG4woswb_pM-O7EmpN6tmiQQyV7kscgARZYA,962254
38
+ sourcecode/cli.py,sha256=-iHhbHsc0vm8eIuBpGNPm8B3Il92Ynl8azz3HeW8aFw,967004
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
@@ -65,6 +65,7 @@ sourcecode/deployment_prefix.py,sha256=kPHPT6ZLg6CnMqCp9QwhbNNjDyS0sXAfKlPtSHUMg
65
65
  sourcecode/detach.py,sha256=Otoe7Egcn5Mcl_cRAstXLyDWA5D7dPAhOv39T5fJYpo,8257
66
66
  sourcecode/doc_analyzer.py,sha256=05bjTUbDbmnbajD_cgRnACzS8T7xxBKVX4CjkJlhZg8,24411
67
67
  sourcecode/dynamic_argument_surface.py,sha256=u6zJoY-zChYVw1-SrgiyAq-rUwqMZ5ZqBwLfbPJ_8ng,2960
68
+ sourcecode/empty_answer_diagnostics.py,sha256=bNi4rc0ZK6rK8WzbNXYzVSVbgm8h6z9gGI9OF1K503o,3891
68
69
  sourcecode/empty_reach.py,sha256=evKK2DyHbjqe_Wimq4-HfgD40Fdk-j6WiZwQaVXQ5t4,15671
69
70
  sourcecode/endpoint_disposition.py,sha256=WXNoHIjQW2uORG54zUygi8LUJKWj6E_y8q9rps2rWoU,9595
70
71
  sourcecode/endpoint_literals.py,sha256=Qf4gTZzvNSFDGDuOvF0YRL9NvaYKKj24klhR5LIOaXc,3263
@@ -124,23 +125,23 @@ sourcecode/path_filters.py,sha256=YWhiy6mARZ8QPDMA6O274jbjHSk6pKE_LMvj8ge_Nbs,15
124
125
  sourcecode/perf.py,sha256=hB0LE0fhH_TwePXmIdtxhTyol6GBTwVBkAcxJa7MYpg,67254
125
126
  sourcecode/phased_run.py,sha256=vvLUUZkt4jfvzLsPBwqjgoiSXeahVnDhzbBWTQt6dDk,24972
126
127
  sourcecode/pipe_contract.py,sha256=PML0Er5d8uDyec4OrdUXuyqHbGPUYndjeaKUjkFz2u4,8369
127
- sourcecode/posture.py,sha256=OQX3r0wBzdRNwMs6fuJcpFKPuyoC_uAkAVoKsYuwqgE,87190
128
+ sourcecode/posture.py,sha256=5vJNIzuj9iWWuyJ0EPEcMkGtILfYXNrFsr1S4pA6tyg,87614
128
129
  sourcecode/pr_comment_renderer.py,sha256=239PmJdf95av_ZW236C7_tvq_ahECeuF9AZxrheJ4OQ,15573
129
130
  sourcecode/pr_impact.py,sha256=8RgTJgvEThezh-Vm65eiFvJBdb45VjcbewEk5P144-0,39184
130
131
  sourcecode/pr_risk.py,sha256=Qbj1aK-JsdTQd_nji_-RaZAL3WUbwqDg9aH-cHQkoog,11354
131
132
  sourcecode/prepare_context.py,sha256=QsJiKoJRNn5_1adyBbKguH_wiaM8hpPLE0fLG9J4ilU,245016
132
133
  sourcecode/product_info.py,sha256=rpuCDf0KM2SD-WP8vw2tjdcbhWPsOGEVjSWqS8fkzlo,4966
133
- sourcecode/progress.py,sha256=qA21SmbPoruAvulSsyYwIU75tIx0-iBpNxqFaYzPlo4,27625
134
+ sourcecode/progress.py,sha256=00PJTq1yoZQt4JNQFtxLEuyO0Hq4zL5OYbb214Iw9Tc,28445
134
135
  sourcecode/provenance.py,sha256=gLbsLv0gze7k7ChM4i5M3MwKfFPzs8wzM72rUd2C5sM,7342
135
136
  sourcecode/ranking_engine.py,sha256=ZAucq_YX2KkWUuAZf4P0lhtQ_38vEFnUhuGtSZd1S0E,12970
136
137
  sourcecode/readiness_timeline.py,sha256=KjghC1MWH7Tzto97TBR3N0F8FkR87w5z7lZ1QsWvAQE,8506
137
138
  sourcecode/readonly.py,sha256=8MJfg5E5gjwHN2f2qw0RM7fdzxTFeOsdGwLNKHCh-xc,7462
138
- sourcecode/reconciliation.py,sha256=pmqc0JNcAagKGWDcjH2rLDlKlAbfJCVUj86vV--YEXQ,35689
139
+ sourcecode/reconciliation.py,sha256=EtYzWaYN7Nng-lfL6jNVqlZl6CL6QvEi0xf8xYQYGfg,36213
139
140
  sourcecode/redactor.py,sha256=SB4hwIvg8h-hvcqKcDWaZvA-aSyn-at-BIRwa0tUv5E,3227
140
141
  sourcecode/reference_facts.py,sha256=mx7H-Ax5y8sKAQHrnJCXlgjkUzqZtQTByv9Zy2lxKQQ,15500
141
142
  sourcecode/regress.py,sha256=6rlFP2rsIzVKAA0spJ66To528GyBtnRI2Zg9vAGq8kQ,13264
142
143
  sourcecode/regulatory_pack.py,sha256=xVWd8hYg6MjGfkFP8UWcYeLmNMxEk8k2uSbTcnGMbhg,3421
143
- sourcecode/release_info.py,sha256=deK17VdMaSvMYhwjpfotdnNyorDbhfRU0pZKks1NRgk,5918
144
+ sourcecode/release_info.py,sha256=vYe0WiVq1H7D5h07cvTfNRXi_43pJK3SC7lcaTQG6pc,5918
144
145
  sourcecode/relevance_scorer.py,sha256=0AgEt4KrV73nioMqBgjhGjtY7L2C7L7cSyKtj3IKcrw,9408
145
146
  sourcecode/remediation_diff.py,sha256=fGYqPmQF7bO54L8ivztX5PgmW4fVu54gNcG6OEQ192U,9730
146
147
  sourcecode/remediation_flow.py,sha256=OFlrNCD2dKw1WlX5cHqVl1yrQZHi2TjCThH8Q3X1PwI,10294
@@ -148,10 +149,10 @@ sourcecode/remediation_report.py,sha256=z28x-u618feU2d7ol_FW7IfhUOq6iETCfdpl7zJC
148
149
  sourcecode/remedies.py,sha256=V2_cD4pLq8bKRkzF-3RGFoiu1xWYZS384WDVp1MrlZw,10225
149
150
  sourcecode/rename_refactor.py,sha256=oASZIf7TxcOBy3RQ0FuOe-4HlNW_JOu9RW9JqCxGNBE,17225
150
151
  sourcecode/repo_classifier.py,sha256=FG1vaWKdWXsWdl-S8hjVMiTqcwgaRXkDyvK4rPcOGtQ,22681
151
- sourcecode/repository_ir.py,sha256=O6d1IWp0-RlJyx4OHBGcflvNA0CgsTS7td7UlI9t7S8,528687
152
- sourcecode/resource_budget.py,sha256=wqe6WuXlEfxAgBGLj0QX47HmV8WldaYWQjLe-TMR6hk,7938
152
+ sourcecode/repository_ir.py,sha256=iDPcbQ3S17td_b9l2oS-p2vUnt-tov83f8I60Tx1bxE,529667
153
+ sourcecode/resource_budget.py,sha256=gVPjiMlTB9jWR2zbZIuyWma15ccSNqHXwWb6Rwd_HmQ,8527
153
154
  sourcecode/ris.py,sha256=HsLVHZfseEHNqMyxrj8SvrzUK7jE_85lsWjHtsEw9ik,29196
154
- sourcecode/risk.py,sha256=rG7fqDIjyhtvB0Qje0d2ZEUl5kemMBwbuOJG8ZJxqrQ,102552
155
+ sourcecode/risk.py,sha256=I9nPKLI0C9EL2gZdRoPDSLK8FuLLBtu4EFzGP1xWK70,103407
155
156
  sourcecode/risk_model.py,sha256=RoC-G15qZP5BLEwwmcr4eJ0APgvIbh1WTqhTVT-5YFE,10895
156
157
  sourcecode/rule_catalog.py,sha256=7lwyNe_sA7M9KtoKXVf9qQYBlo7VEPQ3IK1KiGSqTts,5408
157
158
  sourcecode/rule_pass.py,sha256=Z1UBe0y4WOokGVeOfn325jlphdEdarM_oGNQ9sHzcrY,15157
@@ -169,7 +170,7 @@ sourcecode/security_config_scan.py,sha256=LU8gfNUBB6wjKR8jkK-qRKtUrbkHZ301_Xsk6h
169
170
  sourcecode/security_posture.py,sha256=FS3WYU9C2_KP4aO0SdkFZ808CMWIvKYyTMcCE9UaSWw,57984
170
171
  sourcecode/selection_contract.py,sha256=O3q_zHBgUsp1SDukqmH9nOUO6HxLFH_7fAqVL7JMV_A,1974
171
172
  sourcecode/self_audit.py,sha256=ZK6VZwbkTL66f4Q4U_JD6sdl6KjQ4DvtPcn5XqGcZDY,11541
172
- sourcecode/selftest.py,sha256=Ci7hF2khCxcw0pSVKMh7DlrYuutU9ojt31IWAsMzdlg,42461
173
+ sourcecode/selftest.py,sha256=hQA4SwOhikeetesHMzDWPl1izdEsrT4MaUfmcvlCCX0,43317
173
174
  sourcecode/semantic_analyzer.py,sha256=xGwQvhU9xeOlZ4N-TPXFZT8HBHx4Rg0nPwu8nDFl00Y,95621
174
175
  sourcecode/semantic_impact_engine.py,sha256=t09IirGC3JjQDy33JZd1_WKzQVKXkoNl3-XEUr5kjis,20563
175
176
  sourcecode/semantic_integration_engine.py,sha256=ZjyKJKOj-adScWlYBuWx8Ee_P0F4_OImUJVnCYgopuU,20952
@@ -205,7 +206,7 @@ sourcecode/verify_rules.py,sha256=R3l6nLT6WQzUNBzxtmnxyGZcKj9qMDW38Y0c0gNdCGk,19
205
206
  sourcecode/version_check.py,sha256=CHp6ZxTIfo8kyHPCBgJA1uFC0xQCoXMuuOfrW8QTL8o,4942
206
207
  sourcecode/vex.py,sha256=0-gdUPbKD9XgA3y_ASc_DE-TaHKzruA5znRsMYUeAoY,3399
207
208
  sourcecode/waivers.py,sha256=VlGsvpGt9K5ih3q7P5-co1ob2IROyZDSlVLMZyLbLJU,14874
208
- sourcecode/watch_loop.py,sha256=Zj8yBJOnkyJSL41JeXjkakAZy9vD3y-lX2wDOPS6o7c,7770
209
+ sourcecode/watch_loop.py,sha256=yL3XRmCxN_enaG-2GyuTzp_c1Uma2HkGeo7njg1IhQA,7781
209
210
  sourcecode/wired_surface.py,sha256=M5m2gDufCA4xUlU9z6CRSJeJBfbMeedkSXpvJGKnPT8,12066
210
211
  sourcecode/workspace.py,sha256=H2X1GkIIYqiODJsTu8aLIi2RceuXHYdzwgGrYf92DZU,8277
211
212
  sourcecode/defect_classes/__init__.py,sha256=Y_8W7fnchyFWkR4yB_PE1q8b5-JxF3kEH3EiihSI4eg,8038
@@ -275,13 +276,13 @@ sourcecode/telemetry/consent.py,sha256=-Wb8BFGXEexOs8M0Eja7F-T6ZtLNPeRoZnHcHvlP7
275
276
  sourcecode/telemetry/events.py,sha256=l3Z2SQUO4_C2D2ItXOOdVNimAmHedUHnUxqYFTxnsAE,2900
276
277
  sourcecode/telemetry/filters.py,sha256=-lqT2oorECuqEIdeHb--7AZ6BCaUx0bya720a-Z5x6w,7335
277
278
  sourcecode/telemetry/transport.py,sha256=4gGHsq0WeY9VywEZXA3vUxykfiYnw9uuqfjAAec7F8o,1681
278
- sourcecode/_docs/DEFECT-LEDGER.md,sha256=JyRLeRBjV5luaHrh2w1U2TdK6l3erTRwrCS9kB8wxco,1174219
279
+ sourcecode/_docs/DEFECT-LEDGER.md,sha256=u8hxZPGvCBg2_XHVBgsZFkkiK8XIXaqcd4S2PV3SbYE,1181653
279
280
  sourcecode/_docs/LICENSE,sha256=23-fk61oSWGVmkWyka-FIM0rhAPM2hcYHnsaridL8Uo,1859
280
281
  sourcecode/_docs/NOTICE,sha256=Br-AA8Y3iJo1WXa5uP8QBpzqI5nDu3iGLbFyvDt3BOs,321
281
- sourcecode/_docs/USER_GUIDE.md,sha256=s4H1q5ADDn0IYDzTyXFFQSojOH7ko8clwhNU0CKfcTk,108622
282
- sourcecode-5.9.25.dist-info/METADATA,sha256=UtJhhuSIbv7yKfhmeQvvy1-kq6gMqjoCMEVAlPLr8W0,67653
283
- sourcecode-5.9.25.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
284
- sourcecode-5.9.25.dist-info/entry_points.txt,sha256=-JEAdChrK5We51kZcb7OaDcyil-dHBjBPL-NhuO-QY8,89
285
- sourcecode-5.9.25.dist-info/licenses/LICENSE,sha256=23-fk61oSWGVmkWyka-FIM0rhAPM2hcYHnsaridL8Uo,1859
286
- sourcecode-5.9.25.dist-info/licenses/NOTICE,sha256=Br-AA8Y3iJo1WXa5uP8QBpzqI5nDu3iGLbFyvDt3BOs,321
287
- sourcecode-5.9.25.dist-info/RECORD,,
282
+ sourcecode/_docs/USER_GUIDE.md,sha256=kNvyTAwgllFoFE-8FP9UnLF1SYuBXLkQKWiwa8HL-Ug,108622
283
+ sourcecode-5.9.26.dist-info/METADATA,sha256=iTQwypyGJ6UIq6q8qhBKPcAtUYECrpKwY-EAHfiGxo0,67653
284
+ sourcecode-5.9.26.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
285
+ sourcecode-5.9.26.dist-info/entry_points.txt,sha256=-JEAdChrK5We51kZcb7OaDcyil-dHBjBPL-NhuO-QY8,89
286
+ sourcecode-5.9.26.dist-info/licenses/LICENSE,sha256=23-fk61oSWGVmkWyka-FIM0rhAPM2hcYHnsaridL8Uo,1859
287
+ sourcecode-5.9.26.dist-info/licenses/NOTICE,sha256=Br-AA8Y3iJo1WXa5uP8QBpzqI5nDu3iGLbFyvDt3BOs,321
288
+ sourcecode-5.9.26.dist-info/RECORD,,