sourcecode 5.9.26__py3-none-any.whl → 5.9.27__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.26"
7
+ __version__ = "5.9.27"
@@ -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 = '2f283c4d305e2709dc154a4399650c2042b28d68'
3
+ BUILD_COMMIT = '034ad2aa52cd47f3b55a26f58f19536458e15ef3'
4
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
5
  CLOSURE_COVERAGE = {'closed_rows': 169, 'present': 91, 'absent': 0, 'unresolved': 0, 'uncited': 78, 'unknown': 0}
@@ -14,6 +14,61 @@ 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.26`, self-contradictory session (2026-09-02)
18
+
19
+ **The 5.9.26 fix batch did not close the release gate, and new evidence
20
+ narrows the failure to before the guard rather than inside it.** This audit
21
+ round is internally contradictory and both halves are published rather than
22
+ resolved: an initial 129-invocation pass replicating the exact 5.9.25
23
+ methodology found zero empty answers (0/23) and scored 7.4/10; a second,
24
+ larger pass in the same session found zero *successful* answers across 35
25
+ further invocations of the same command family and revised the verdict to
26
+ **3.8/10**, the lowest of four rounds. The auditor's own final position is the
27
+ second number. Full evidence:
28
+ [`AUDIT-2026-09-02-EXTERNAL-5.9.26.md`](AUDIT-2026-09-02-EXTERNAL-5.9.26.md).
29
+
30
+ **New finding, most actionable in four rounds (`R-01`):** across 32 empty
31
+ `exit 0` answers this session, stdout **and** stderr were both empty and no
32
+ `empty_answer_diagnostics` sidecar file exists anywhere on the audited
33
+ machine — the guard that is supposed to write one on every trip did not fire.
34
+ This does not mean the guard added in 5.9.26 is miscalibrated; it means the
35
+ failing runs are not reaching `main_entry`'s wrapper at all, which rules out
36
+ "a caught exception inside command logic" as the mechanism and points instead
37
+ at something that terminates the process before Python's own `try`/`except`
38
+ around `app(prog_name="ask")` ever regains control — an external kill, a
39
+ native crash, or an `os._exit()`-shaped exit somewhere in a dependency. A
40
+ one-line "reached the guard" debug log at the top of `main_entry` would
41
+ confirm this directly without needing native Windows to interpret.
42
+
43
+ Other updates this round: `BUG-17` reconfirmed with a more precise repro
44
+ (no path, a real path, and a nonexistent path are all byte-identical, not
45
+ merely "an extra argument is now accepted"); `ALT-10`/`onboard` got worse (a
46
+ cold run hit the external 200s kill entirely, worse than 5.9.25's 164.9s
47
+ worst case); `ALT-11`/`watch` reconfirmed working, with a correction — the
48
+ 3,342-file audited repository's index warm takes 51.7s before the first
49
+ NDJSON line, real and not a defect, but long enough to still read as hung
50
+ without foreknowledge; and `ask --help` costs 3-4s even warm, which `REG-01`
51
+ never claimed to fix (`REG-01` was specifically the 82-120s hang in a nested
52
+ workspace, now resolved) but is worth its own row if it persists.
53
+
54
+ | ID | Severity | Status | Evidence and required closure |
55
+ |---|---:|---|---|
56
+ | `NEW-01`/`ALT-01`/`ALT-03` | Critical maximum | **open, contradictory session, worst round measured** | 0 of 35 invocations answered in the second pass of this session (vs. 0 of 23 *empty* in the first pass of the same session) — do not average the two into a rate; neither is regime evidence. First round where a single batch of identical `spring-audit . --compact` calls produced both failure shapes (a 200s hang, then a near-instant empty answer) with nothing changed between them. `R-01` above is the actionable lead. |
57
+ | `R-01` | Critical maximum | **instrumented, not yet closed** | The `empty_answer_diagnostics` sidecar added for `ALT-01`/`ALT-03` did not fire in 32 observed empty answers this session — no file, no error envelope. `record_entry_reached` now appends one line to `entry-trace.jsonl` as the very first statement of `main_entry`, argv-gated to `REQUIRED_ANSWER_COMMANDS` so `--help` and other latency-sensitive commands are not charged for it. The next native occurrence answers directly whether the failing run reached this product's own entry point at all, rather than requiring inference from the absence of a failure record. This does not close the row — it is the instrumentation the row asked for, not a fix for whatever is upstream if the trace turns out empty too. |
58
+ | `ALT-10` | Medium | **open, worse** | A cold `onboard .` hit the external 200s kill entirely this session (5.9.25's worst case answered at 164.9s); a second, untouched run answered in 83.5s — still ~120x the 681-780ms historical baseline. Shares `R-01`'s erratic shape, not a simple cold/warm split. |
59
+ | `BUG-17` | Low | **fixed** | `remediation-report` still accepts any `path` value (5.9.24's deliberate CLI-consistency choice, kept — a caller that always passes a repository path needs no special case for the one command with none to say about it), but the payload now carries `path_argument: {given, used: false, note}` whenever one is given, in both JSON and Markdown, whether or not the path exists. `rows.pop("path_argument")` still equals the no-path payload exactly — nothing else changed. |
60
+ | `ALT-09` | Critical | **fixed, reconfirmed** | A piped `n` answer to `ask cache clear .` aborts with `rc=1`, `"Aborted."` on stderr, cache untouched. |
61
+ | `ALT-04` | High | **fixed, reconfirmed** | `impact-chain` gave the same `content_id` across 3 repeated runs again this session. |
62
+ | `BUG-01` | Critical maximum | **fixed, reconfirmed with an independent fixture** | The auditor built their own unbalanced-paren file (not the shipped test fixture) and got the expected `reason: "unbalanced_parens"` gap. The documented residual class (a syntax error that disturbs neither braces nor parens) is unchanged and expected. |
63
+ | `BUG-15` | Low | **fixed, reconfirmed** | 0 Rich-markup occurrences across 3 repeated non-TTY `--help` runs. |
64
+ | `BUG-21` | Low | **fixed, reconfirmed** | `--jobs 0` and `--jobs 999` both rejected with the stated `1<=x<=128` range. |
65
+ | `ALT-11` | Low | **fixed, reconfirmed with a measurement correction** | `watch` emits its `status: "watching"` line at 51.7s on the 3,342-file audited repository — real index-warm cost, not a defect, but long enough that a short observation window (the auditor's own first attempt, 8-20s) reads it as still broken. No further action required by this row; `ALT-10`/onboard shares the same warm-up path and is where the latency itself belongs. |
66
+
67
+ The remaining rows below this section (`BUG-03`, `BUG-09` through `BUG-23`,
68
+ `REG-02`, `REG-03`, `REG-04`, `NEW-02`) were reconfirmed unchanged this round
69
+ or not relaunched for time budget; none regressed. Full detail in the audit
70
+ document.
71
+
17
72
  ## Current Synchronization — Alternative External Audit `5.9.25`, and External Audit `5.9.25` (2026-09-02)
18
73
 
19
74
  **Release `5.9.26` closes eight rows from this round with verified evidence**
@@ -75,7 +130,7 @@ and [`AUDIT-2026-09-02-EXTERNAL-5.9.25.md`](AUDIT-2026-09-02-EXTERNAL-5.9.25.md)
75
130
  | `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. |
76
131
  | `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. |
77
132
  | `BUG-12` | Critical maximum | **open, P0** | Deep `--agent` output construction reaches multi-gigabyte RSS before a small answer. Bound projection while building. |
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. |
133
+ | `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. The 5.9.26 re-audit's own index table still lists this row `abierto` for both 5.9.25 and 5.9.26 without naming which command was tested or a repro that contradicts the fixture above; the fix stands on the passing regression tests until a command-specific repro says otherwise. |
79
134
  | `BUG-04` | High | **open, P1** | `selftest` publishes `complete=true` with five error rows. Derive bounds from actual results. |
80
135
  | `BUG-05` | High | **open, P1** | Overloaded endpoint handlers can receive the wrong declaration line. Resolve by mapping annotation or publish ambiguity. |
81
136
  | `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. |
@@ -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.26
282
+ # ask 5.9.27
283
283
  ```
284
284
 
285
285
  Requires Python 3.9+.
sourcecode/cli.py CHANGED
@@ -17454,7 +17454,6 @@ def remediation_report_cmd(
17454
17454
  copy: bool = _copy_option(),
17455
17455
  ) -> None:
17456
17456
  """Publish a redacted remediation record for this ASK build."""
17457
- del path
17458
17457
  _enforce_format("remediation-report", format)
17459
17458
  from sourcecode import bundled_docs
17460
17459
 
@@ -17473,6 +17472,24 @@ def remediation_report_cmd(
17473
17472
  report = build_report(
17474
17473
  ledger_path.read_text(encoding="utf-8"), build=build_provenance()
17475
17474
  )
17475
+ # BUG-17 (5.9.26 re-audit): a real path, no path and a nonexistent path
17476
+ # all returned byte-identical output with nothing saying the argument was
17477
+ # ignored — read as a confident answer about a repository this command
17478
+ # never opens. This still accepts any value (5.9.24 kept it deliberately,
17479
+ # so scripts that always pass a repository path do not need a special
17480
+ # case for the one command that has none to say about it); what changes
17481
+ # is that the payload now says so, whether the path exists or not.
17482
+ if path is not None:
17483
+ report["path_argument"] = {
17484
+ "given": str(path),
17485
+ "used": False,
17486
+ "note": (
17487
+ "This report always projects the ledger bundled inside this "
17488
+ "build. The path argument is accepted for invocation "
17489
+ "consistency with repository-scoped commands and is never "
17490
+ "read, whether or not it exists."
17491
+ ),
17492
+ }
17476
17493
  output = render_markdown(report) if format == "markdown" else _serialize_dict(report, format)
17477
17494
  _emit_command_output(output, output_path, copy,
17478
17495
  success_msg=f"Remediation report written to {output_path}",
@@ -21676,6 +21693,17 @@ def main_entry() -> None:
21676
21693
  can consume them as positional arguments (which would prevent subcommand
21677
21694
  routing for tokens like 'version' or 'config').
21678
21695
  """
21696
+ # R-01 (5.9.26 re-audit): the earliest possible line in this process, for
21697
+ # the same reason AUD-596-B10 marks the clock here rather than later — a
21698
+ # failure that never reaches this point cannot be told apart, from
21699
+ # outside, from one that reaches it and then goes silent. 32 empty
21700
+ # answers on the audited machine wrote no forensic sidecar at all; this
21701
+ # settles which side of that line they were on. Argv-gated (not every
21702
+ # invocation) so `--help` and other latency-sensitive commands this audit
21703
+ # also flagged are not charged for a trace they were never in question for.
21704
+ if any(tok in REQUIRED_ANSWER_COMMANDS for tok in sys.argv[1:]):
21705
+ from sourcecode import empty_answer_diagnostics as _diag
21706
+ _diag.record_entry_reached(sys.argv[1:])
21679
21707
  # AUD-596-B10: the earliest point in the process that knows a command is
21680
21708
  # starting. `timings.wall_ms` is published under a unit reading "THIS
21681
21709
  # process's wall clock", and until this mark existed it measured from
@@ -19,6 +19,15 @@ for explicitly: capture the process's own state at the exact moment either
19
19
  guard is about to fire, every time it fires, so the next occurrence in the
20
20
  field carries its own forensic record instead of a report written from
21
21
  memory afterward.
22
+
23
+ R-01 (5.9.26 re-audit) sharpened the question: across 32 empty answers on the
24
+ audited machine, `record()` above never fired at all — no sidecar, no error
25
+ envelope. That does not mean the guard mishandled a failure; it means the
26
+ failing runs never reached the guard, which was invisible until something
27
+ recorded whether the process got that far in the first place. `record_entry`
28
+ answers exactly that, for the six audit-family commands, on every invocation
29
+ — reached or not is now a fact this build can be asked for directly, instead
30
+ of inferred from the absence of a failure record.
22
31
  """
23
32
  from __future__ import annotations
24
33
 
@@ -92,3 +101,59 @@ def _prune(directory: Path) -> None:
92
101
  stale.unlink(missing_ok=True)
93
102
  except Exception:
94
103
  pass
104
+
105
+
106
+ #: Filename for the entry-reached trace (R-01). Distinct from `record()`'s
107
+ #: one-file-per-failure snapshots: this is a bounded append log, one line per
108
+ #: invocation of an audit-family command, so a comparison across many
109
+ #: invocations does not depend on `record()` ever having fired.
110
+ _ENTRY_TRACE_NAME = "entry-trace.jsonl"
111
+
112
+ #: Lines to keep once the trace is pruned. Pruning is triggered by file size,
113
+ #: not by line count, so the common case (a small file) costs one `stat`.
114
+ _ENTRY_TRACE_MAX_LINES = 500
115
+ _ENTRY_TRACE_PRUNE_THRESHOLD_BYTES = 512_000
116
+
117
+
118
+ def record_entry_reached(argv: "list[str]") -> None:
119
+ """Append one line: this process reached `main_entry`, with this argv.
120
+
121
+ R-01: called as the very first statement of `main_entry`, before any
122
+ other work, for the audit-family commands only (`REQUIRED_ANSWER_COMMANDS`
123
+ in `cli.py`) — the ones the empty-answer defect affects. A future
124
+ occurrence can then be checked against this trace: a PID with a matching
125
+ timestamp here proves the process reached this product's own entry point
126
+ before it went silent, which narrows the search to after this line; no
127
+ matching entry proves the opposite, that whatever killed the run did so
128
+ before Python's own `main_entry` code could run at all.
129
+
130
+ Best-effort and always cheap: one append, one `stat` call in the common
131
+ case. Never raises — this must not cost, or ever be able to break, the
132
+ invocation it is observing.
133
+ """
134
+ try:
135
+ directory = _diagnostics_dir()
136
+ directory.mkdir(parents=True, exist_ok=True)
137
+ path = directory / _ENTRY_TRACE_NAME
138
+ line = json.dumps(
139
+ {"ts": time.time(), "pid": os.getpid(), "argv": list(argv)},
140
+ ensure_ascii=True, default=str,
141
+ )
142
+ with path.open("a", encoding="utf-8") as fh:
143
+ fh.write(line + "\n")
144
+ try:
145
+ if path.stat().st_size > _ENTRY_TRACE_PRUNE_THRESHOLD_BYTES:
146
+ _prune_entry_trace(path)
147
+ except OSError:
148
+ pass
149
+ except Exception:
150
+ pass
151
+
152
+
153
+ def _prune_entry_trace(path: Path) -> None:
154
+ try:
155
+ lines = path.read_text(encoding="utf-8").splitlines()
156
+ kept = lines[-_ENTRY_TRACE_MAX_LINES:]
157
+ path.write_text("\n".join(kept) + ("\n" if kept else ""), encoding="utf-8")
158
+ except Exception:
159
+ pass
@@ -75,4 +75,7 @@ def render_markdown(report: dict[str, Any]) -> str:
75
75
  lines.extend(f"| {key} | {value} |" for key, value in report["by_severity"].items())
76
76
  lines.extend(["", "## Boundaries", ""])
77
77
  lines.extend(f"- {item}" for item in report["non_coverage"])
78
+ path_argument = report.get("path_argument")
79
+ if path_argument:
80
+ lines.append(f"- {path_argument['note']} (given: `{path_argument['given']}`)")
78
81
  return "\n".join(lines) + "\n"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 5.9.26
3
+ Version: 5.9.27
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.26-blue)
62
+ ![Version](https://img.shields.io/badge/version-5.9.27-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.26 — and, on a build that has aged,
293
+ ask version # ask 5.9.27 — and, on a build that has aged,
294
294
  # how many releases have probably shipped since
295
295
  ```
296
296
 
@@ -1,6 +1,6 @@
1
- sourcecode/__init__.py,sha256=yjkRwJomDMH7QIDQ_QztOQiiuBgCA9f6tISLAKRx-MI,309
1
+ sourcecode/__init__.py,sha256=yNSZAxmGetWKJrYOy3qOjZ2WS4DgS-UQSTopoTwj-UM,309
2
2
  sourcecode/__main__.py,sha256=qDFVkobwsdZrX0B3stiRqsUNivVpybKO-egzAwCW4xw,165
3
- sourcecode/_build_commit.py,sha256=YbiK39JRRfcLPBQ4MwI3XHWbAxoSspOo30E_bkKfgTA,11834
3
+ sourcecode/_build_commit.py,sha256=TpK5atF5POhEEm1OLQUbl_nRWC6HE6FfeAz0-F6N3vE,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
@@ -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=-iHhbHsc0vm8eIuBpGNPm8B3Il92Ynl8azz3HeW8aFw,967004
38
+ sourcecode/cli.py,sha256=bEqB1wkiB-Flhz-UkHZk_UPmOX_Gigkg-IMqFEXaimc,968753
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,7 +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
+ sourcecode/empty_answer_diagnostics.py,sha256=Oe-xzZSYNlG7jqVy2LhXfxO5EZl5E3Xtj_ApDQiJwwg,6822
69
69
  sourcecode/empty_reach.py,sha256=evKK2DyHbjqe_Wimq4-HfgD40Fdk-j6WiZwQaVXQ5t4,15671
70
70
  sourcecode/endpoint_disposition.py,sha256=WXNoHIjQW2uORG54zUygi8LUJKWj6E_y8q9rps2rWoU,9595
71
71
  sourcecode/endpoint_literals.py,sha256=Qf4gTZzvNSFDGDuOvF0YRL9NvaYKKj24klhR5LIOaXc,3263
@@ -145,7 +145,7 @@ sourcecode/release_info.py,sha256=vYe0WiVq1H7D5h07cvTfNRXi_43pJK3SC7lcaTQG6pc,59
145
145
  sourcecode/relevance_scorer.py,sha256=0AgEt4KrV73nioMqBgjhGjtY7L2C7L7cSyKtj3IKcrw,9408
146
146
  sourcecode/remediation_diff.py,sha256=fGYqPmQF7bO54L8ivztX5PgmW4fVu54gNcG6OEQ192U,9730
147
147
  sourcecode/remediation_flow.py,sha256=OFlrNCD2dKw1WlX5cHqVl1yrQZHi2TjCThH8Q3X1PwI,10294
148
- sourcecode/remediation_report.py,sha256=z28x-u618feU2d7ol_FW7IfhUOq6iETCfdpl7zJCKvk,3185
148
+ sourcecode/remediation_report.py,sha256=3B7sFR-guQn6vxAxTRcm7k82mRNPsyj4e9ON_X3FD0Q,3342
149
149
  sourcecode/remedies.py,sha256=V2_cD4pLq8bKRkzF-3RGFoiu1xWYZS384WDVp1MrlZw,10225
150
150
  sourcecode/rename_refactor.py,sha256=oASZIf7TxcOBy3RQ0FuOe-4HlNW_JOu9RW9JqCxGNBE,17225
151
151
  sourcecode/repo_classifier.py,sha256=FG1vaWKdWXsWdl-S8hjVMiTqcwgaRXkDyvK4rPcOGtQ,22681
@@ -276,13 +276,13 @@ sourcecode/telemetry/consent.py,sha256=-Wb8BFGXEexOs8M0Eja7F-T6ZtLNPeRoZnHcHvlP7
276
276
  sourcecode/telemetry/events.py,sha256=l3Z2SQUO4_C2D2ItXOOdVNimAmHedUHnUxqYFTxnsAE,2900
277
277
  sourcecode/telemetry/filters.py,sha256=-lqT2oorECuqEIdeHb--7AZ6BCaUx0bya720a-Z5x6w,7335
278
278
  sourcecode/telemetry/transport.py,sha256=4gGHsq0WeY9VywEZXA3vUxykfiYnw9uuqfjAAec7F8o,1681
279
- sourcecode/_docs/DEFECT-LEDGER.md,sha256=u8hxZPGvCBg2_XHVBgsZFkkiK8XIXaqcd4S2PV3SbYE,1181653
279
+ sourcecode/_docs/DEFECT-LEDGER.md,sha256=kFKWIx8BLvAjyeyUixphfkvvD3J3K4UtfpiGpM1vY-A,1188112
280
280
  sourcecode/_docs/LICENSE,sha256=23-fk61oSWGVmkWyka-FIM0rhAPM2hcYHnsaridL8Uo,1859
281
281
  sourcecode/_docs/NOTICE,sha256=Br-AA8Y3iJo1WXa5uP8QBpzqI5nDu3iGLbFyvDt3BOs,321
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,,
282
+ sourcecode/_docs/USER_GUIDE.md,sha256=eGL9WAygluB8k3EmrHvjaYH_CihlVCMGFB0ue1rL0lE,108622
283
+ sourcecode-5.9.27.dist-info/METADATA,sha256=hJ1slKw0yLLJELTDBBZ5rMRLXmUFwm7d5SVYh4owt6A,67653
284
+ sourcecode-5.9.27.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
285
+ sourcecode-5.9.27.dist-info/entry_points.txt,sha256=-JEAdChrK5We51kZcb7OaDcyil-dHBjBPL-NhuO-QY8,89
286
+ sourcecode-5.9.27.dist-info/licenses/LICENSE,sha256=23-fk61oSWGVmkWyka-FIM0rhAPM2hcYHnsaridL8Uo,1859
287
+ sourcecode-5.9.27.dist-info/licenses/NOTICE,sha256=Br-AA8Y3iJo1WXa5uP8QBpzqI5nDu3iGLbFyvDt3BOs,321
288
+ sourcecode-5.9.27.dist-info/RECORD,,