sourcecode 5.8.28__py3-none-any.whl → 5.8.30__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 +1 -1
- sourcecode/_build_commit.py +1 -1
- sourcecode/_docs/DEFECT-LEDGER.md +28 -0
- sourcecode/_docs/USER_GUIDE.md +6 -5
- sourcecode/baseline_autocapture.py +4 -2
- sourcecode/cache_model.py +9 -1
- sourcecode/cli.py +33 -20
- sourcecode/envelope.py +5 -3
- sourcecode/graph_analyzer.py +3 -2
- sourcecode/output_bounds.py +4 -0
- sourcecode/packs.py +9 -3
- sourcecode/path_admission.py +2 -1
- sourcecode/path_display.py +7 -0
- sourcecode/pr_impact.py +28 -3
- sourcecode/repository_ir.py +4 -1
- sourcecode/tree_utils.py +4 -2
- sourcecode/verify_repo.py +5 -4
- {sourcecode-5.8.28.dist-info → sourcecode-5.8.30.dist-info}/METADATA +6 -6
- {sourcecode-5.8.28.dist-info → sourcecode-5.8.30.dist-info}/RECORD +23 -22
- {sourcecode-5.8.28.dist-info → sourcecode-5.8.30.dist-info}/WHEEL +0 -0
- {sourcecode-5.8.28.dist-info → sourcecode-5.8.30.dist-info}/entry_points.txt +0 -0
- {sourcecode-5.8.28.dist-info → sourcecode-5.8.30.dist-info}/licenses/LICENSE +0 -0
- {sourcecode-5.8.28.dist-info → sourcecode-5.8.30.dist-info}/licenses/NOTICE +0 -0
sourcecode/__init__.py
CHANGED
sourcecode/_build_commit.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""Generated at build time by hatch_build.py. Do not edit (AUD-592-D04)."""
|
|
2
2
|
|
|
3
|
-
BUILD_COMMIT = '
|
|
3
|
+
BUILD_COMMIT = 'ab3d2c7736790a32306bd4b1df906f54bb72f5a6'
|
|
4
4
|
CLOSURE_PROVENANCE = {'Window': {'commit': '', 'status': 'uncited'}, '`AUD-588-F05`': {'commit': '470e4a4', 'status': 'present'}, '`AUD-590-B01` / `B-01`, `F-01`': {'commit': '', 'status': 'uncited'}, '`AUD-590-B02` / `B-02`, `F-02`': {'commit': '', 'status': 'uncited'}, '`AUD-590-B03` / `B-03`, `F-03`': {'commit': '', 'status': 'uncited'}, '`AUD-590-B04` / `B-04`, `F-04`': {'commit': '', 'status': 'uncited'}, '`AUD-590-R01` / `R-01`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A01` / `A-1`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A02` / `A-2`, `A-4`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A03` / `A-3`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A05` / `A-5`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A06` / `A-6`, `A-7`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A08` / `A-8`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A09` / `A-9`': {'commit': '', 'status': 'uncited'}, '`AUD-591-A10` / `A-10`': {'commit': '', 'status': 'uncited'}, '`AUD-592-A02` / `A-1` second half, `§12.5`': {'commit': '63f3d61', 'status': 'present'}, '`AUD-592-B01` / `B-8`': {'commit': '8329614', 'status': 'present'}, '`AUD-592-D01` / `D-1`': {'commit': '0f8e03f', 'status': 'present'}, '`AUD-592-D02` / `D-2`': {'commit': '1d3db4d', 'status': 'present'}, '`AUD-592-D03` / `D-3`': {'commit': 'f28fe40', 'status': 'present'}, '`AUD-592-R01` / `A-1`': {'commit': '216025f', 'status': 'present'}, '`AUD-592-R02` / `N-4`, reopens `AUD-513-N04`': {'commit': 'ec3050d', 'status': 'present'}, '`AUD-593-N01` / `N-01`': {'commit': 'dd6a706', 'status': 'present'}, '`AUD-593-N02` / `N-02`': {'commit': 'f539787', 'status': 'present'}, '`AUD-593-N03` / `N-03`': {'commit': '1dd0b1c', 'status': 'present'}, '`AUD-593-N05` / `N-05`': {'commit': 'aa89388', 'status': 'present'}, '`AUD-593-N06` / `N-06`': {'commit': 'aa584a6', 'status': 'present'}, '`AUD-594-N04` / `D-5`, disclosure half of `B-3`': {'commit': 'a0060b7', 'status': 'present'}, '`AUD-594-X01` / `A-1`, residual of `AUD-593-N03`': {'commit': 'dd222b9', 'status': 'present'}, '`AUD-594-X02` / `A-1` second half': {'commit': '1193937', 'status': 'present'}, '`AUD-594-X03` / `X-03`, residual of `AUD-593-N01`': {'commit': 'e89e8f0', 'status': 'present'}, '`AUD-594-X04`': {'commit': '05b8cc9', 'status': 'present'}, '`AUD-595-A02` / `N-5`, advisory half of `AUD-588-B11`': {'commit': '3e15227', 'status': 'present'}, '`AUD-595-A03` / `B-6` exit-code half': {'commit': 'ab7285f', 'status': 'present'}, '`AUD-595-A05`': {'commit': 'e0b3d10', 'status': 'present'}, '`AUD-595-A07`, narrow half of `AUD-592-A02`': {'commit': 'cc15177', 'status': 'present'}, '`AUD-595-B01` / §B': {'commit': 'b77a1ad', 'status': 'present'}, '`AUD-595-Q01`': {'commit': '91a6566', 'status': 'present'}, '`AUD-596-A01` / `ASK-DET-001`': {'commit': 'fa508b4', 'status': 'present'}, '`AUD-596-A02` / `ASK-SELF-001`': {'commit': '4dfadc8', 'status': 'present'}, '`AUD-596-A03` / `ASK-C1-001`': {'commit': 'bffa3a6', 'status': 'present'}, '`AUD-596-A04` / `ASK-UX-003` + `ASK-UX-004`': {'commit': 'f0aac3c', 'status': 'present'}, '`AUD-596-B01` / `B-01`, harder witness for `BUG-6`': {'commit': '567d09d', 'status': 'present'}, '`AUD-596-B02` / `B-02`, class residual of `R2`': {'commit': '', 'status': 'uncited'}, '`AUD-596-B03` / `B-03`': {'commit': 'a8cb814', 'status': 'present'}, '`AUD-596-B06` / `B-06`': {'commit': '8107927', 'status': 'present'}, '`AUD-596-B07` / `B-07`, class residual of `AUD-592-R02`': {'commit': 'e060485', 'status': 'present'}, '`AUD-596-B09` / `B-09`': {'commit': '5b8146c', 'status': 'present'}, '`AUD-596-B10` / `B-10`': {'commit': '5cb994d', 'status': 'present'}, '`AUD-596-B16` / `B-16`': {'commit': '1507f69', 'status': 'present'}, '`AUD-596-D01` / `B-13` + `B-14`': {'commit': '0b1bdf0', 'status': 'present'}, '`AUD-596-D02` / `B-08`, residual of `AUD-594-N04`': {'commit': 'e7f73c3', 'status': 'present'}, '`AUD-596-D03` / `ASK-AGT-001`': {'commit': '8c46967', 'status': 'present'}, '`AUD-596-D04` / `B-18`': {'commit': '040f027', 'status': 'present'}, '`AUD-596-D05` / `B-19`': {'commit': 'fd2bf68', 'status': 'present'}, '`AUD-596-D06` / `B-20`': {'commit': '784cd83', 'status': 'present'}, '`AUD-596-D07` / `B-17`, half refuted': {'commit': 'c3ff822', 'status': 'present'}, '`AUD-596-D08` / `B-22`, class residual of `AUD-591-A06`': {'commit': 'b396c6a', 'status': 'present'}, '`AUD-596-D09` / `B-23`, surviving half of `B26`': {'commit': 'fd3d63f', 'status': 'present'}, '`AUD-596-D10` / `B-29`': {'commit': '', 'status': 'uncited'}, '`AUD-596-D11` / `ASK-UX-005`': {'commit': 'f4b4f77', 'status': 'present'}, '`AUD-596-D12` — six hints that send the reader back to the error': {'commit': '498df44', 'status': 'present'}, '`AUD-596-D13` / `B-28`': {'commit': '1014c72', 'status': 'present'}, '`AUD-596-D14` / `B-15`, narrow half of `B20`': {'commit': '10f2827', 'status': 'present'}, '`AUD-596-R01` / `B-05`': {'commit': '', 'status': 'uncited'}, '`AUD-596-X01` / `ASK-GATE-001`, gating half of `B24`': {'commit': 'e59c655', 'status': 'present'}, '`AUD-596-X02` / `ASK-UX-001` + `ASK-UX-002` + `B-21`': {'commit': 'f6ebf50', 'status': 'present'}, '`AUD-597-A01` / `ASK-UX-001` + `N-01`': {'commit': 'f8cf061', 'status': 'present'}, '`AUD-597-A02` / `ASK-UX-008` + `ASK-DOC-002`': {'commit': '9d47a4c', 'status': 'present'}, '`AUD-597-A03` / `ASK-DET-001`': {'commit': '4c7622a', 'status': 'present'}, '`AUD-597-A04` / `ASK-LEDGER-001`': {'commit': '46fb870', 'status': 'present'}, '`AUD-597-D01` / `B-04`': {'commit': '1094e6a', 'status': 'present'}, '`AUD-597-D02` / `ASK-DOC-001`': {'commit': 'ecb1bb7', 'status': 'present'}, '`AUD-597-D03` / `N-06`': {'commit': '9784333', 'status': 'present'}, '`AUD-597-D04` / `N-05`': {'commit': 'e51c087', 'status': 'present'}, '`AUD-597-D05` / `N-04`, fourth appearance of `C4-27`': {'commit': '9cccc15', 'status': 'present'}, '`AUD-597-D06` / `ASK-CLI-001`': {'commit': '178aa6d', 'status': 'present'}, '`AUD-597-D07` / `N-03`': {'commit': '9245e35', 'status': 'present'}, '`AUD-597-R01` / `ASK-PERF-001`': {'commit': '6910054', 'status': 'present'}, '`AUD-597-R02` / `ASK-ENC-001`': {'commit': 'ce6dac1', 'status': 'present'}, '`AUD-597-R03` / `ASK-UX-002`': {'commit': 'c57e50b', 'status': 'present'}, '`AUD-597-X01` / `ASK-BUILD-001` + `ASK-META-001` / `B-12`': {'commit': '354338b', 'status': 'present'}, '`AUD-598-B01` / `ASK-META-001`': {'commit': 'b2f7c65', 'status': 'present'}, '`AUD-598-B02` / `ASK-UX-002`': {'commit': '56a4bf7', 'status': 'present'}, '`AUD-598-B03` / `B-11`': {'commit': 'c63cb24', 'status': 'present'}, '`AUD-598-B04` / `N-02`': {'commit': '187937f', 'status': 'present'}, '`AUD-598-R01` / `ASK-PERF-002`': {'commit': '', 'status': 'uncited'}, '`AUD-598-X01` / `N-01` + `B-13` + `B-14` + `B-29` + `N-06`': {'commit': '6f2f5a4', 'status': 'present'}, '`AUD-600-B01` / `P-01`': {'commit': '366ffed', 'status': 'present'}, '`AUD-600-B02` / `P-02` + `ASK-PACK-002`': {'commit': '2a814c3', 'status': 'present'}, '`AUD-600-B03` / `ASK-PACK-001`': {'commit': '452f2a0', 'status': 'present'}, '`AUD-600-D01`': {'commit': '1224e1b', 'status': 'present'}, '`AUD-600-D02`': {'commit': 'eab8172', 'status': 'present'}, '`AUD-600-R01` / `R-01`': {'commit': '88add64', 'status': 'present'}, '`AUD-601-B01` / `N-02`, 5th round': {'commit': '', 'status': 'uncited'}, '`AUD-601-B02` / `ASK-PACK-004`': {'commit': '', 'status': 'uncited'}, '`AUD-601-D01` / `N-01`, `ASK-UX-001`, 5th round': {'commit': '', 'status': 'uncited'}, '`AUD-601-D02` / `B-13`, `B-14`, 5th round': {'commit': '', 'status': 'uncited'}, '`AUD-601-M01` / `B-26`, `B-27` retracted': {'commit': '', 'status': 'uncited'}, '`AUD-601-R01` / `R-02`': {'commit': '', 'status': 'uncited'}, '`B-3`': {'commit': '773268d', 'status': 'present'}, '`B-6`': {'commit': '17c6e06', 'status': 'present'}, '`B-8`': {'commit': '8329614', 'status': 'present'}, '`BUG-3` / `443b345`': {'commit': '', 'status': 'uncited'}, '`BUG-4a` / `AUD-588-B11` residual': {'commit': '24b4185', 'status': 'present'}, '`BUG-4b` / `AUD-588-B11` residual': {'commit': '0376350', 'status': 'present'}, '`E-39`, class residual of `AUD-593-N06`': {'commit': '25fc11f', 'status': 'present'}, '`N-5`': {'commit': 'c68083f', 'status': 'present'}, '`N-7`': {'commit': '082e9de', 'status': 'present'}, '`R-1`': {'commit': '424fb1c', 'status': 'present'}, '`R-2`': {'commit': '5158b92', 'status': 'present'}, '`R-3`': {'commit': '88aec04', 'status': 'present'}, '`R-4`': {'commit': '04fd04f', 'status': 'present'}}
|
|
5
5
|
CLOSURE_COVERAGE = {'closed_rows': 113, 'present': 88, 'absent': 0, 'unresolved': 0, 'uncited': 25, 'unknown': 0}
|
|
@@ -16,6 +16,34 @@ The facts these rows are keyed to are published: `ask schema facts-v1` prints th
|
|
|
16
16
|
|
|
17
17
|
## Current Synchronization
|
|
18
18
|
|
|
19
|
+
**External pack audit received, 2026-08-26 - `AUD-605`.**
|
|
20
|
+
[`AUDIT-2026-08-26-EXTERNAL-5.8.28-PACK.md`](AUDIT-2026-08-26-EXTERNAL-5.8.28-PACK.md)
|
|
21
|
+
adds two rows: `AUD-605-G01`, where an unresolved test file broadened pack-gate unknown
|
|
22
|
+
endpoints beyond its real production reach, and `AUD-605-U01`, where foreground `pack
|
|
23
|
+
assessment` did not forward component progress. Both are implemented in the current
|
|
24
|
+
checkout by `52bcc36` and `f89ae18`, with focused regression batteries passing; release
|
|
25
|
+
artefact verification remains pending. The pack's `--since` timing is additional evidence
|
|
26
|
+
for `AUD-604-P01`, not a duplicate performance finding.
|
|
27
|
+
|
|
28
|
+
**Current `5.8.30` queue:** artefact verification for `AUD-604-R01`; the two `AUD-605`
|
|
29
|
+
fixes are included in this release and await release-artefact verification.
|
|
30
|
+
|
|
31
|
+
**External `5.8.28` audit received, 2026-08-26 - `AUD-604`.**
|
|
32
|
+
[`AUDIT-2026-08-26-EXTERNAL-5.8.28.md`](AUDIT-2026-08-26-EXTERNAL-5.8.28.md) confirms the
|
|
33
|
+
semantic fixes from the previous round and adds three actionable rows: `AUD-604-O01`
|
|
34
|
+
(`posture --diff --compact --limit` is effectively a no-op on nested output),
|
|
35
|
+
`AUD-604-P01` (cold-cost regression signal requiring controlled profiling), and
|
|
36
|
+
`AUD-604-U01` (stale root-help timing headline). Detached execution remains implemented
|
|
37
|
+
in the current source, with native Windows artefact verification still pending. The audit's
|
|
38
|
+
duplicated claim about `python -m sourcecode.cli` is historical and does not describe the
|
|
39
|
+
current `python -m sourcecode` plus `__main__.py` implementation.
|
|
40
|
+
|
|
41
|
+
**Current `5.8.29` queue:** artefact verification for `AUD-604-R01`. `AUD-604-S01`,
|
|
42
|
+
`AUD-604-D01`, `AUD-604-U02`, `AUD-604-O01` and `AUD-604-U01` are closed in `5.8.28`.
|
|
43
|
+
`AUD-604-P01` is closed as an unconfirmed, non-attributable performance signal after
|
|
44
|
+
controlled profiling; it remains a benchmark follow-up, not a parser fix. WebScripts and
|
|
45
|
+
root-only subcommand `--compact` remain excluded.
|
|
46
|
+
|
|
19
47
|
**External `5.8.27` audit received, 2026-08-26 — `AUD-603`.** [`AUDIT-2026-08-26-EXTERNAL-5.8.27.md`](AUDIT-2026-08-26-EXTERNAL-5.8.27.md) confirms the SEC-004 and Boot 3 fixes, but reopens detached execution because the direct `python -m sourcecode.cli` worker exits without invoking `main_entry`. It adds a DEAD-001 comment-prose false positive, a `posture --diff --compact` output-ceiling contract defect, and a cold-performance regression signal requiring controlled profiling. The stale timing headline and non-interactive selftest scope warning remain open. WebScripts remains unconfirmed and root-only subcommand `--compact` remains by design.
|
|
20
48
|
|
|
21
49
|
**Current `5.8.27` queue:** `AUD-603-R01` · `AUD-603-S01` · `AUD-603-O01` · `AUD-603-P01` · `AUD-603-U01` · `AUD-603-U02`. This supersedes the earlier AUD-602 implementation-status note for the reopened rows; its historical commits remain evidence, not closure.
|
sourcecode/_docs/USER_GUIDE.md
CHANGED
|
@@ -46,13 +46,14 @@ CLI commands — impact, endpoints, spring-audit, explain, … each a pro
|
|
|
46
46
|
The key idea: the extraction is **content-addressed**. Commands reuse the parse cache and,
|
|
47
47
|
where their analysed scope matches, the shared Canonical IR; `ask cache model` names what a
|
|
48
48
|
warm buys for each command rather than implying that every projection costs the same. In
|
|
49
|
-
5.8.
|
|
49
|
+
5.8.30, `validation` enters through that shared CIR and `data-exposure` reuses one semantic
|
|
50
50
|
model across all declared label seeds. (The extraction and consumption contract is fixed in
|
|
51
51
|
the architecture ADRs 0001–0004 under `docs/architecture/`.)
|
|
52
52
|
|
|
53
|
-
The current external audit intake is tracked in
|
|
54
|
-
[`AUDIT-2026-08-26-EXTERNAL-5.8.
|
|
55
|
-
|
|
53
|
+
The current external pack audit intake is tracked in
|
|
54
|
+
[`AUDIT-2026-08-26-EXTERNAL-5.8.28-PACK.md`](AUDIT-2026-08-26-EXTERNAL-5.8.28-PACK.md);
|
|
55
|
+
the two pack fixes are included in release 5.8.30, with release-artifact verification
|
|
56
|
+
remaining for detached execution and pack evidence.
|
|
56
57
|
|
|
57
58
|
---
|
|
58
59
|
|
|
@@ -182,7 +183,7 @@ pipx install sourcecode # isolated install, no venv needed
|
|
|
182
183
|
|
|
183
184
|
# Verify
|
|
184
185
|
ask version
|
|
185
|
-
# ask 5.8.
|
|
186
|
+
# ask 5.8.30
|
|
186
187
|
```
|
|
187
188
|
|
|
188
189
|
Requires Python 3.9+.
|
|
@@ -38,6 +38,8 @@ from dataclasses import dataclass
|
|
|
38
38
|
from pathlib import Path
|
|
39
39
|
from typing import TYPE_CHECKING, Any, Iterable, Optional
|
|
40
40
|
|
|
41
|
+
from sourcecode.path_display import portable_path
|
|
42
|
+
|
|
41
43
|
if TYPE_CHECKING: # pragma: no cover - typing only
|
|
42
44
|
from sourcecode.canonical_ir import CanonicalRepositoryIR
|
|
43
45
|
|
|
@@ -55,7 +57,7 @@ _FALSE = frozenset({"0", "false", "no", "off"})
|
|
|
55
57
|
|
|
56
58
|
def _published_path(path: Path) -> str:
|
|
57
59
|
"""Serialize a filesystem path with the stable separator used by payloads."""
|
|
58
|
-
return path
|
|
60
|
+
return portable_path(path)
|
|
59
61
|
|
|
60
62
|
# Actions.
|
|
61
63
|
CAPTURED: str = "captured"
|
|
@@ -396,7 +398,7 @@ def decide(
|
|
|
396
398
|
attribution, then idempotency.
|
|
397
399
|
"""
|
|
398
400
|
common = {
|
|
399
|
-
"history_dir":
|
|
401
|
+
"history_dir": _published_path(history_dir),
|
|
400
402
|
"commit": commit,
|
|
401
403
|
"history_size": size,
|
|
402
404
|
}
|
sourcecode/cache_model.py
CHANGED
|
@@ -829,13 +829,21 @@ def cost_sentence() -> str:
|
|
|
829
829
|
f"{_thousands(int(_gate_cell['java_files']))}-file repository "
|
|
830
830
|
f"({_gate_cell['cache_state']} cache, {_gate_cell['host_class']})."
|
|
831
831
|
)
|
|
832
|
+
# AUD-604-U01: the external 5.8.28 review observed ~184 s for the root
|
|
833
|
+
# cold path at the same scale. It is useful context, but not a replacement
|
|
834
|
+
# for the spring-audit field anchor because the command and protocol differ.
|
|
835
|
+
current_observation = (
|
|
836
|
+
" The latest external review also observed about 184 s for the root "
|
|
837
|
+
"cold path at this scale on 5.8.28; that figure is provisional until "
|
|
838
|
+
"the controlled release benchmark is reproduced."
|
|
839
|
+
)
|
|
832
840
|
return (
|
|
833
841
|
f"Historical field anchor only: cost tracks the command class and the build, "
|
|
834
842
|
f"not the file count: "
|
|
835
843
|
f"per-symbol queries are the fast path, inventory commands scale with "
|
|
836
844
|
f"files, and a repository-wide audit measured {seconds:g} s on a "
|
|
837
845
|
f"{_thousands(FIELD_ANCHOR_JAVA_FILES)}-file repository "
|
|
838
|
-
f"({FIELD_ANCHOR_MEASURED_VERSION}{stale}).{gate} `ask cache model` prints "
|
|
846
|
+
f"({FIELD_ANCHOR_MEASURED_VERSION}{stale}).{current_observation}{gate} `ask cache model` prints "
|
|
839
847
|
f"the figure and the build behind it for every command; ASK_PROGRESS "
|
|
840
848
|
f"narrates supervised work, while ASK_MAX_ANALYSIS_SECONDS bounds "
|
|
841
849
|
f"{budget_tiers_phrase()}."
|
sourcecode/cli.py
CHANGED
|
@@ -49,6 +49,7 @@ from sourcecode.caller_metrics import (
|
|
|
49
49
|
CYCLE_METRIC_RECONCILIATION,
|
|
50
50
|
)
|
|
51
51
|
from sourcecode.repository_ir import extract_java_endpoints as _extract_java_endpoints
|
|
52
|
+
from sourcecode.path_display import portable_path
|
|
52
53
|
|
|
53
54
|
|
|
54
55
|
# ---------------------------------------------------------------------------
|
|
@@ -1842,7 +1843,7 @@ def _write_root_partial_stub(output: "Path", target: "Path") -> None:
|
|
|
1842
1843
|
"schema_version": "partial-analysis-v1",
|
|
1843
1844
|
"partial": True,
|
|
1844
1845
|
"command": "ask",
|
|
1845
|
-
"scope": {"path":
|
|
1846
|
+
"scope": {"path": portable_path(target)},
|
|
1846
1847
|
"started_at": _dt.datetime.now(_dt.timezone.utc).isoformat(),
|
|
1847
1848
|
"status": "running",
|
|
1848
1849
|
"reason": (
|
|
@@ -4356,22 +4357,34 @@ def pack_assessment_cmd(
|
|
|
4356
4357
|
)
|
|
4357
4358
|
raise typer.Exit(code=2)
|
|
4358
4359
|
_enforce_format("pack-assessment", format)
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4360
|
+
_progress = Progress().start("pack assessment")
|
|
4361
|
+
try:
|
|
4362
|
+
data = run_assessment(
|
|
4363
|
+
root, profile=profile, deployment=deployment, compact=compact, output_dir=output_dir,
|
|
4364
|
+
progress=lambda done, total, component: _progress.work(
|
|
4365
|
+
done, total, stage=f"pack assessment: {component}",
|
|
4366
|
+
unit="components", estimate=False,
|
|
4367
|
+
),
|
|
4368
|
+
)
|
|
4369
|
+
except BaseException:
|
|
4370
|
+
_progress.stop()
|
|
4371
|
+
raise
|
|
4362
4372
|
output = render_assessment_markdown(data) if format == "markdown" else _serialize_dict(data, format)
|
|
4363
4373
|
# AUD-600-D01: when the pack decided at t=0 that it may not write into the
|
|
4364
4374
|
# analysed tree, the aggregate must not be routed there either — the same
|
|
4365
4375
|
# decision, one destination later.
|
|
4366
4376
|
_dir = None if data.get("no_write_substitution") else output_dir
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4377
|
+
try:
|
|
4378
|
+
_emit_command_output(
|
|
4379
|
+
output,
|
|
4380
|
+
_pack_output_path(_dir, output_path, format),
|
|
4381
|
+
copy,
|
|
4382
|
+
stamp_envelope=(format != "markdown"),
|
|
4383
|
+
)
|
|
4384
|
+
if data["verdict"] == "UNVERIFIED":
|
|
4385
|
+
raise typer.Exit(code=2)
|
|
4386
|
+
finally:
|
|
4387
|
+
_progress.finish()
|
|
4375
4388
|
|
|
4376
4389
|
|
|
4377
4390
|
@pack_app.command("gate")
|
|
@@ -10110,7 +10123,7 @@ def plan_cmd(
|
|
|
10110
10123
|
data["scan_truncated"] = _plan_scan_trunc
|
|
10111
10124
|
# The tree these components and candidates came from: `--path` defaults to
|
|
10112
10125
|
# `.`, so a run from the wrong directory answers about another repository.
|
|
10113
|
-
data.setdefault("scope", {"path":
|
|
10126
|
+
data.setdefault("scope", {"path": portable_path(target_dir)})
|
|
10114
10127
|
_prog.finish()
|
|
10115
10128
|
|
|
10116
10129
|
output = _serialize_dict(data, format)
|
|
@@ -10231,7 +10244,7 @@ def compare_cmd(
|
|
|
10231
10244
|
# The tree these candidates came from. `--path` defaults to `.`, so a run
|
|
10232
10245
|
# from the wrong directory offered candidates from a different repository
|
|
10233
10246
|
# with nothing naming the repository they belonged to.
|
|
10234
|
-
data.setdefault("scope", {"path":
|
|
10247
|
+
data.setdefault("scope", {"path": portable_path(target_dir)})
|
|
10235
10248
|
_prog.finish()
|
|
10236
10249
|
|
|
10237
10250
|
_unresolved = [c["target"] for c in data["candidates"] if not c["resolved"]]
|
|
@@ -14187,7 +14200,7 @@ def posture_cmd(
|
|
|
14187
14200
|
# than that individual cut, leaving a large diff above the ceiling.
|
|
14188
14201
|
# An explicit --limit remains a precise shape request; compact must
|
|
14189
14202
|
# actually remove every registered body.
|
|
14190
|
-
monotone=
|
|
14203
|
+
monotone=(limit is None and compact),
|
|
14191
14204
|
)
|
|
14192
14205
|
|
|
14193
14206
|
_emit_command_output(
|
|
@@ -15897,7 +15910,7 @@ def modernize_cmd(
|
|
|
15897
15910
|
result = {
|
|
15898
15911
|
"schema_version": _MODERNIZE_SCHEMA,
|
|
15899
15912
|
"workflow": "modernize",
|
|
15900
|
-
"path":
|
|
15913
|
+
"path": portable_path(root),
|
|
15901
15914
|
"tier": "free",
|
|
15902
15915
|
"tier_note": (
|
|
15903
15916
|
"This repository exceeds the free-tier size limit. "
|
|
@@ -15923,7 +15936,7 @@ def modernize_cmd(
|
|
|
15923
15936
|
result = {
|
|
15924
15937
|
"schema_version": _MODERNIZE_SCHEMA,
|
|
15925
15938
|
"workflow": "modernize",
|
|
15926
|
-
"path":
|
|
15939
|
+
"path": portable_path(root),
|
|
15927
15940
|
"summary": _summary,
|
|
15928
15941
|
"hotspot_candidates": hotspots,
|
|
15929
15942
|
"high_coupling_nodes": [
|
|
@@ -18288,9 +18301,9 @@ def cache_status_cmd(
|
|
|
18288
18301
|
target = Path(path).resolve()
|
|
18289
18302
|
_git_root = _resolve_repo_root(Path(path))
|
|
18290
18303
|
stats = _cm.status(target)
|
|
18291
|
-
stats["scope"] =
|
|
18304
|
+
stats["scope"] = portable_path(target)
|
|
18292
18305
|
if _git_root != target:
|
|
18293
|
-
stats["git_root"] =
|
|
18306
|
+
stats["git_root"] = portable_path(_git_root)
|
|
18294
18307
|
if json_output:
|
|
18295
18308
|
import json as _j
|
|
18296
18309
|
_emit_text_output(_j.dumps(stats, indent=2, ensure_ascii=False), copy, output_path)
|
|
@@ -18928,7 +18941,7 @@ def cache_model_cmd(
|
|
|
18928
18941
|
if json_output:
|
|
18929
18942
|
import json as _j
|
|
18930
18943
|
_payload = _cmodel.as_dict(_here)
|
|
18931
|
-
_payload["scope"] =
|
|
18944
|
+
_payload["scope"] = portable_path(Path(path).resolve())
|
|
18932
18945
|
_payload["scope_note"] = (
|
|
18933
18946
|
"The cache model is global; this path is accepted so cache model, "
|
|
18934
18947
|
"cache status and cache freshness share one path grammar."
|
sourcecode/envelope.py
CHANGED
|
@@ -31,6 +31,8 @@ import subprocess
|
|
|
31
31
|
from pathlib import Path
|
|
32
32
|
from typing import Any, Optional
|
|
33
33
|
|
|
34
|
+
from sourcecode.path_display import portable_path
|
|
35
|
+
|
|
34
36
|
#: Shape of the `_meta` block itself. Bump when a field's meaning changes.
|
|
35
37
|
ENVELOPE_VERSION = "1"
|
|
36
38
|
|
|
@@ -104,9 +106,9 @@ def repository_identity(target: "Path | str") -> "dict[str, Any]":
|
|
|
104
106
|
try:
|
|
105
107
|
resolved = Path(target).resolve()
|
|
106
108
|
except Exception:
|
|
107
|
-
return {"path":
|
|
109
|
+
return {"path": portable_path(target), "is_git_repository": False,
|
|
108
110
|
"tree_state": "unknown", "git_head": None, "tree_id": None}
|
|
109
|
-
block: dict[str, Any] = {"path":
|
|
111
|
+
block: dict[str, Any] = {"path": portable_path(resolved), "is_git_repository": False,
|
|
110
112
|
"tree_state": "not-a-git-repository",
|
|
111
113
|
"git_head": None, "tree_id": None}
|
|
112
114
|
try:
|
|
@@ -203,7 +205,7 @@ def build_meta(
|
|
|
203
205
|
if target is not None:
|
|
204
206
|
try:
|
|
205
207
|
resolved = Path(target).resolve()
|
|
206
|
-
scope: dict[str, Any] = {"path":
|
|
208
|
+
scope: dict[str, Any] = {"path": portable_path(resolved)}
|
|
207
209
|
if resolved.is_dir():
|
|
208
210
|
# AUD-601-D02: one authority for repository identity. This block
|
|
209
211
|
# read the tree once for `run_id` and then asked git for HEAD a
|
sourcecode/graph_analyzer.py
CHANGED
|
@@ -8,6 +8,7 @@ from pathlib import Path, PurePosixPath
|
|
|
8
8
|
from typing import Any, Literal, Optional
|
|
9
9
|
|
|
10
10
|
from sourcecode.detectors.parsers import load_json_file, load_toml_file
|
|
11
|
+
from sourcecode.path_display import portable_path
|
|
11
12
|
from sourcecode.schema import EntryPoint, GraphEdge, GraphNode, ModuleGraph, ModuleGraphSummary
|
|
12
13
|
from sourcecode.tree_utils import flatten_file_tree
|
|
13
14
|
|
|
@@ -186,7 +187,7 @@ class GraphAnalyzer:
|
|
|
186
187
|
workspace: str | None,
|
|
187
188
|
) -> ModuleGraph:
|
|
188
189
|
source_files = [
|
|
189
|
-
path
|
|
190
|
+
portable_path(path)
|
|
190
191
|
for path in flatten_file_tree(file_tree)
|
|
191
192
|
if Path(path).suffix in self._SUPPORTED_EXTENSIONS and (root / path).is_file()
|
|
192
193
|
]
|
|
@@ -213,7 +214,7 @@ class GraphAnalyzer:
|
|
|
213
214
|
java_import_edges = self._build_jvm_java_import_edges(root, source_files, jvm_types)
|
|
214
215
|
|
|
215
216
|
# .NET: project-level graph from .csproj/.fsproj/.vbproj manifests
|
|
216
|
-
all_tree_paths = [p for p in flatten_file_tree(file_tree)]
|
|
217
|
+
all_tree_paths = [portable_path(p) for p in flatten_file_tree(file_tree)]
|
|
217
218
|
dotnet_project_paths = [
|
|
218
219
|
p for p in all_tree_paths
|
|
219
220
|
if Path(p).suffix.lower() in self._DOTNET_PROJECT_EXTENSIONS
|
sourcecode/output_bounds.py
CHANGED
|
@@ -68,6 +68,10 @@ POSTURE_BOUNDED_LISTS: "tuple[str, ...]" = (
|
|
|
68
68
|
"only_in_right",
|
|
69
69
|
"left_active",
|
|
70
70
|
"right_active",
|
|
71
|
+
# AUD-604-O01. The real diff projection publishes endpoint rows under
|
|
72
|
+
# `endpoint_access.endpoints`; registering only the synthetic `changed`
|
|
73
|
+
# shape left the largest nested list untouched by `--limit`.
|
|
74
|
+
"endpoints",
|
|
71
75
|
# AUD-602-R02. `posture --diff` caps the per-profile bean and security
|
|
72
76
|
# lists, but the actionable delta is `endpoint_access.changed`: one row per
|
|
73
77
|
# request whose decision moves between the two profile sets. Omitting it
|
sourcecode/packs.py
CHANGED
|
@@ -24,7 +24,7 @@ import sys
|
|
|
24
24
|
import tempfile
|
|
25
25
|
import time
|
|
26
26
|
from pathlib import Path
|
|
27
|
-
from typing import Any, Optional
|
|
27
|
+
from typing import Any, Callable, Optional
|
|
28
28
|
|
|
29
29
|
from sourcecode import pack_manifest
|
|
30
30
|
from sourcecode.partial_contract import PARTIAL_EXIT_CODE
|
|
@@ -771,7 +771,8 @@ def _carrier(result: "dict[str, Any]") -> "dict[str, Any]":
|
|
|
771
771
|
def run_assessment(root: Path, *, profile: Optional[str] = None,
|
|
772
772
|
deployment: Optional[list[Path]] = None,
|
|
773
773
|
compact: bool = False,
|
|
774
|
-
output_dir: Optional[Path] = None
|
|
774
|
+
output_dir: Optional[Path] = None,
|
|
775
|
+
progress: Optional[Callable[[int, int, str], None]] = None) -> dict[str, Any]:
|
|
775
776
|
"""Build the assessment pack from existing analysis commands."""
|
|
776
777
|
no_write = _no_write_substitution("assessment", output_dir)
|
|
777
778
|
if no_write is not None:
|
|
@@ -781,7 +782,10 @@ def run_assessment(root: Path, *, profile: Optional[str] = None,
|
|
|
781
782
|
artifacts: dict[str, Optional[str]] = {}
|
|
782
783
|
with tempfile.TemporaryDirectory(prefix="ask-assessment-") as temp:
|
|
783
784
|
temp_root = Path(temp)
|
|
784
|
-
|
|
785
|
+
total_components = len(commands) + 1 # the aggregate audit-report is a component too
|
|
786
|
+
for index, command in enumerate(commands, start=1):
|
|
787
|
+
if progress:
|
|
788
|
+
progress(index, total_components, command)
|
|
785
789
|
extra: list[str] = []
|
|
786
790
|
if compact and command in {"migrate-check", "posture", "endpoints", "spring-audit"}:
|
|
787
791
|
extra.append("--compact")
|
|
@@ -800,6 +804,8 @@ def run_assessment(root: Path, *, profile: Optional[str] = None,
|
|
|
800
804
|
report_extra = ["--from-risk", str(temp_root / "risk.json")]
|
|
801
805
|
if profile:
|
|
802
806
|
report_extra.extend(["--profile", profile])
|
|
807
|
+
if progress:
|
|
808
|
+
progress(total_components, total_components, "audit-report")
|
|
803
809
|
report = _run_command("audit-report", root, temp_root / "audit-report.json", report_extra)
|
|
804
810
|
# The composed `--from-risk` path is a temporary file; what the manifest
|
|
805
811
|
# publishes is the reproducible form, which is `risk`'s own artifact.
|
sourcecode/path_admission.py
CHANGED
|
@@ -24,6 +24,7 @@ from dataclasses import dataclass
|
|
|
24
24
|
from pathlib import Path
|
|
25
25
|
|
|
26
26
|
from sourcecode.error_schema import INVALID_INPUT_CODE
|
|
27
|
+
from sourcecode.path_display import portable_path
|
|
27
28
|
|
|
28
29
|
#: Why a path was refused. ``None`` on an admitted path.
|
|
29
30
|
MISSING = "missing"
|
|
@@ -56,7 +57,7 @@ def admit_repo_path(raw: Path | str) -> PathAdmission:
|
|
|
56
57
|
path, and an error message quoting that rewrite sends the user hunting for
|
|
57
58
|
a directory they never named.
|
|
58
59
|
"""
|
|
59
|
-
raw_text =
|
|
60
|
+
raw_text = portable_path(raw)
|
|
60
61
|
try:
|
|
61
62
|
resolved = Path(raw_text).resolve()
|
|
62
63
|
except OSError:
|
sourcecode/pr_impact.py
CHANGED
|
@@ -43,6 +43,15 @@ _RISK_LABEL: dict[int, str] = {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
|
|
46
|
+
def _split_unresolved_files(paths: list[str]) -> tuple[list[str], list[str]]:
|
|
47
|
+
"""Separate unresolved production files from test-only evidence."""
|
|
48
|
+
from sourcecode.repository_ir import is_test_source_file
|
|
49
|
+
|
|
50
|
+
productive = [path for path in paths if not is_test_source_file(path)]
|
|
51
|
+
test_sources = [path for path in paths if is_test_source_file(path)]
|
|
52
|
+
return productive, test_sources
|
|
53
|
+
|
|
54
|
+
|
|
46
55
|
# ---------------------------------------------------------------------------
|
|
47
56
|
# Output model
|
|
48
57
|
# ---------------------------------------------------------------------------
|
|
@@ -669,6 +678,17 @@ def _run_pr_impact_internal(
|
|
|
669
678
|
changed_files, file_class_index, root
|
|
670
679
|
)
|
|
671
680
|
warnings.extend(file_warnings)
|
|
681
|
+
# A changed test source can be absent from the production CIR by design. It
|
|
682
|
+
# remains evidence in `unresolved_files`, but it must not turn every
|
|
683
|
+
# production endpoint into `unknown` or inflate the blast-radius verdict.
|
|
684
|
+
# Keep the classification in the same authority used by the source walk.
|
|
685
|
+
unresolved_productive, unresolved_excluded = _split_unresolved_files(unresolved_java)
|
|
686
|
+
if unresolved_excluded:
|
|
687
|
+
warnings.append(
|
|
688
|
+
f"{len(unresolved_excluded)} changed test-source file(s) were not mapped "
|
|
689
|
+
"to production classes by design; they do not broaden endpoint "
|
|
690
|
+
"uncertainty."
|
|
691
|
+
)
|
|
672
692
|
non_java_changes = _classify_non_java(non_java)
|
|
673
693
|
|
|
674
694
|
if not class_fqns:
|
|
@@ -694,6 +714,8 @@ def _run_pr_impact_internal(
|
|
|
694
714
|
"changed_files_count": len(changed_files),
|
|
695
715
|
"classes_analyzed": 0,
|
|
696
716
|
"unresolved_java_count": len(unresolved_java),
|
|
717
|
+
"unresolved_productive_count": len(unresolved_productive),
|
|
718
|
+
"unresolved_test_source_count": len(unresolved_excluded),
|
|
697
719
|
"non_java_count": len(non_java_changes),
|
|
698
720
|
},
|
|
699
721
|
)
|
|
@@ -785,7 +807,7 @@ def _run_pr_impact_internal(
|
|
|
785
807
|
event_consumers,
|
|
786
808
|
tx_methods,
|
|
787
809
|
individual_risks,
|
|
788
|
-
|
|
810
|
+
unresolved_productive,
|
|
789
811
|
container_wired=wired,
|
|
790
812
|
risk_by_class=risk_by_class,
|
|
791
813
|
)
|
|
@@ -841,11 +863,12 @@ def _run_pr_impact_internal(
|
|
|
841
863
|
"outside it is undetermined rather than excluded"
|
|
842
864
|
),
|
|
843
865
|
))
|
|
844
|
-
if
|
|
866
|
+
if unresolved_productive:
|
|
845
867
|
disposition_blockers.append(_disposition.Blocker(
|
|
846
868
|
reason=_disposition.REASON_UNRESOLVED_CHANGED_FILE,
|
|
847
869
|
detail=(
|
|
848
|
-
f"{len(
|
|
870
|
+
f"{len(unresolved_productive)} changed production Java file(s) mapped "
|
|
871
|
+
"to no class, "
|
|
849
872
|
"so part of the diff was never analysed and the surface it might "
|
|
850
873
|
"reach is unknown by construction"
|
|
851
874
|
),
|
|
@@ -904,6 +927,8 @@ def _run_pr_impact_internal(
|
|
|
904
927
|
"route population (`endpoints.total`)"
|
|
905
928
|
),
|
|
906
929
|
"unresolved_java_count": len(unresolved_java),
|
|
930
|
+
"unresolved_productive_count": len(unresolved_productive),
|
|
931
|
+
"unresolved_test_source_count": len(unresolved_excluded),
|
|
907
932
|
"non_java_count": len(non_java_changes),
|
|
908
933
|
"analysis_time_ms": elapsed_ms,
|
|
909
934
|
},
|
sourcecode/repository_ir.py
CHANGED
|
@@ -26,6 +26,7 @@ from pathlib import Path
|
|
|
26
26
|
from typing import Any, Callable, Iterable, Iterator, Optional
|
|
27
27
|
|
|
28
28
|
from sourcecode.cache import repo_id as _cache_repo_id
|
|
29
|
+
from sourcecode.path_display import portable_path
|
|
29
30
|
from sourcecode.caller_metrics import CALLER_METRIC_RECONCILIATION, caller_classes
|
|
30
31
|
from sourcecode.caller_metrics import declared_tags as _caller_declared_tags
|
|
31
32
|
from sourcecode.degradation import cap_effect as _cap_effect
|
|
@@ -6623,6 +6624,8 @@ def build_repo_ir(
|
|
|
6623
6624
|
|
|
6624
6625
|
Returns aggregated deterministic IR dict (schema_version=final-v1).
|
|
6625
6626
|
"""
|
|
6627
|
+
# Relative paths are part of the IR contract, not OS-specific display text.
|
|
6628
|
+
file_paths = [portable_path(path) for path in file_paths]
|
|
6626
6629
|
if custom_security is None:
|
|
6627
6630
|
custom_security = _load_custom_security(root)
|
|
6628
6631
|
_custom_sec_tuple = tuple(custom_security)
|
|
@@ -7803,7 +7806,7 @@ def analysed_tree_scope(root: Path) -> "dict[str, Any]":
|
|
|
7803
7806
|
except OSError:
|
|
7804
7807
|
pass
|
|
7805
7808
|
return {
|
|
7806
|
-
"path":
|
|
7809
|
+
"path": portable_path(resolved),
|
|
7807
7810
|
"is_repository_root": is_repo,
|
|
7808
7811
|
"nested_repositories": len(nested),
|
|
7809
7812
|
"basis": (
|
sourcecode/tree_utils.py
CHANGED
|
@@ -3,6 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from typing import Any
|
|
5
5
|
|
|
6
|
+
from sourcecode.path_display import portable_path
|
|
7
|
+
|
|
6
8
|
|
|
7
9
|
def safe_read_text(path: Path) -> str:
|
|
8
10
|
"""Read a text file with encoding fallback to handle Latin-1 / UTF-8 ambiguity.
|
|
@@ -26,7 +28,7 @@ def flatten_file_tree(file_tree: dict[str, Any], prefix: str = "") -> list[str]:
|
|
|
26
28
|
"""Aplana el file_tree jerarquico a paths relativos."""
|
|
27
29
|
paths: list[str] = []
|
|
28
30
|
for name, value in file_tree.items():
|
|
29
|
-
current = f"{prefix}/{name}" if prefix else name
|
|
31
|
+
current = portable_path(f"{prefix}/{name}" if prefix else name)
|
|
30
32
|
paths.append(current)
|
|
31
33
|
if isinstance(value, dict):
|
|
32
34
|
paths.extend(flatten_file_tree(value, current))
|
|
@@ -39,7 +41,7 @@ def find_files_by_name(
|
|
|
39
41
|
"""Return all paths in the tree whose filename matches `filename`."""
|
|
40
42
|
paths: list[str] = []
|
|
41
43
|
for key, value in file_tree.items():
|
|
42
|
-
current = f"{prefix}/{key}" if prefix else key
|
|
44
|
+
current = portable_path(f"{prefix}/{key}" if prefix else key)
|
|
43
45
|
if isinstance(value, dict):
|
|
44
46
|
paths.extend(find_files_by_name(value, filename, current))
|
|
45
47
|
elif key == filename:
|
sourcecode/verify_repo.py
CHANGED
|
@@ -43,6 +43,7 @@ from pathlib import Path
|
|
|
43
43
|
from typing import Any, Optional
|
|
44
44
|
|
|
45
45
|
from sourcecode.remedies import remedy
|
|
46
|
+
from sourcecode.path_display import portable_path
|
|
46
47
|
|
|
47
48
|
VERIFY_SCHEMA = "verify-v1"
|
|
48
49
|
|
|
@@ -270,7 +271,7 @@ def verify_repo(
|
|
|
270
271
|
verdict="unverified",
|
|
271
272
|
exit_code=EXIT_PASS if allow_unverified else EXIT_UNVERIFIED,
|
|
272
273
|
fail_on=fail_on,
|
|
273
|
-
contracts_file=
|
|
274
|
+
contracts_file=portable_path(contracts_file) if contracts_file else None,
|
|
274
275
|
contract_count=0,
|
|
275
276
|
baseline_file=str(resolved_baseline) if resolved_baseline.is_file() else None,
|
|
276
277
|
unverified_reason=UNVERIFIED_NO_CONTRACTS,
|
|
@@ -333,7 +334,7 @@ def verify_repo(
|
|
|
333
334
|
new_violations=tuple(_violation_dict(v) for v in new),
|
|
334
335
|
baselined_violations=tuple(_violation_dict(v) for v in baselined),
|
|
335
336
|
resolved_violations=tuple(resolved),
|
|
336
|
-
contracts_file=
|
|
337
|
+
contracts_file=portable_path(contracts_file) if contracts_file else None,
|
|
337
338
|
contract_count=contract_count,
|
|
338
339
|
baseline_file=str(resolved_baseline) if resolved_baseline.is_file() else None,
|
|
339
340
|
reasons=tuple(reasons),
|
|
@@ -361,12 +362,12 @@ def capture_baseline(
|
|
|
361
362
|
if dry_run:
|
|
362
363
|
return {
|
|
363
364
|
"baseline_file": None,
|
|
364
|
-
"would_write":
|
|
365
|
+
"would_write": portable_path(target),
|
|
365
366
|
"schema_version": BASELINE_SCHEMA,
|
|
366
367
|
"head_sha": _head_sha(root),
|
|
367
368
|
"violations": [_violation_dict(v) for v in violations],
|
|
368
369
|
}
|
|
369
370
|
return {
|
|
370
|
-
"baseline_file":
|
|
371
|
+
"baseline_file": portable_path(target),
|
|
371
372
|
**write_baseline(target, violations, head_sha=_head_sha(root)),
|
|
372
373
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version: 5.8.
|
|
3
|
+
Version: 5.8.30
|
|
4
4
|
Summary: Persistent structural context and ultra-fast repeated analysis for AI coding agents
|
|
5
5
|
Project-URL: Homepage, https://github.com/HarounDominique/sourcecode
|
|
6
6
|
Project-URL: Repository, https://github.com/HarounDominique/sourcecode
|
|
@@ -59,7 +59,7 @@ Description-Content-Type: text/markdown
|
|
|
59
59
|
> question. All analysis is local and deterministic; see [Privacy](#configuration--privacy)
|
|
60
60
|
> before inspecting a repository whose telemetry policy you need to control.
|
|
61
61
|
|
|
62
|
-

|
|
63
63
|

|
|
64
64
|
|
|
65
65
|
Copyright (c) 2026 Dominique Haroun. All rights reserved. ASK Engine 5.7.0 and
|
|
@@ -177,14 +177,14 @@ set `ASK_MAX_RSS_MB=<megabytes>`; if the process exceeds it, ASK refuses the
|
|
|
177
177
|
answer with `MEMORY_TOO_LARGE`, including the observed peak and limit. Leave it
|
|
178
178
|
unset, or set it to `0`, to disable the ceiling explicitly.
|
|
179
179
|
|
|
180
|
-
**Current performance status.** Release 5.8.
|
|
180
|
+
**Current performance status.** Release 5.8.30 retains the shared Canonical IR
|
|
181
181
|
path used by `validation` and now passes that same CIR into labelled `data-exposure`
|
|
182
182
|
runs; the no-label path remains parse-free. These are implementation properties,
|
|
183
183
|
not duration promises. A controlled external warm-path audit has opened performance
|
|
184
184
|
and bounded-output regressions for this release; use `ask cache model <repo>` and
|
|
185
185
|
`--progress stderr` for supervised runs, and consult the
|
|
186
|
-
[active audit intake](docs/AUDIT-2026-08-26-EXTERNAL-5.8.
|
|
187
|
-
historical timing or bounded flag as a current guarantee.
|
|
186
|
+
[active pack audit intake](docs/AUDIT-2026-08-26-EXTERNAL-5.8.28-PACK.md) before
|
|
187
|
+
treating a historical timing or bounded flag as a current guarantee.
|
|
188
188
|
|
|
189
189
|
**What a warm actually covers.** `ask cache warm` runs the compact analysis: it rebuilds the
|
|
190
190
|
shared structural layers (L1/L2 + the Repository Intelligence Snapshot + the shared Canonical
|
|
@@ -210,7 +210,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
|
|
|
210
210
|
# pip / pipx
|
|
211
211
|
pipx install sourcecode # or: pip install sourcecode
|
|
212
212
|
|
|
213
|
-
ask version # ask 5.8.
|
|
213
|
+
ask version # ask 5.8.30 — and, on a build that has aged,
|
|
214
214
|
# how many releases have probably shipped since
|
|
215
215
|
```
|
|
216
216
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
sourcecode/__init__.py,sha256=
|
|
1
|
+
sourcecode/__init__.py,sha256=ZtJO4wGTOdXFDoPlFpOvl25Gw0oliGFJ-_kFgOT_Qr8,309
|
|
2
2
|
sourcecode/__main__.py,sha256=qDFVkobwsdZrX0B3stiRqsUNivVpybKO-egzAwCW4xw,165
|
|
3
|
-
sourcecode/_build_commit.py,sha256=
|
|
3
|
+
sourcecode/_build_commit.py,sha256=X3yn3fg6SQXQ5Ac9CFyu16QI9RSVRvLOe79xSYeftVw,8740
|
|
4
4
|
sourcecode/adaptive_scanner.py,sha256=yJBKjNpkY6bpueYJ2YnRezen3sYZDecEt7WaaNWdqug,9466
|
|
5
5
|
sourcecode/analysis_budget.py,sha256=ZuNEboPF8A6GK-_V7WNt92ezgriga7_Rbr-vvSN4UEE,4183
|
|
6
6
|
sourcecode/answer_bounds.py,sha256=_51_DCuYEUmI_xwUFxDMiprSavkNakkLiIBbPjevQ3M,9793
|
|
@@ -14,13 +14,13 @@ sourcecode/audit_clusters.py,sha256=9uqUh8x2qlsqD0eiXdtu7RQEtFBCiC254xustlCcK40,
|
|
|
14
14
|
sourcecode/audit_recipe.py,sha256=bpFqKuf84SSZAjtTnfFsLUz_20SXx-B_ggppdXedNwY,12817
|
|
15
15
|
sourcecode/audit_report.py,sha256=tsx9lmxEenu_JZ0bSpX5ufhGH3ThNo2luj6a4N5DrHg,14240
|
|
16
16
|
sourcecode/audit_since.py,sha256=bkl2tUuYcmS0epvKR9SltXMYx7RSoWedJL0zDGe8xGI,9601
|
|
17
|
-
sourcecode/baseline_autocapture.py,sha256=
|
|
17
|
+
sourcecode/baseline_autocapture.py,sha256=B8xmKedSmStiFJOmC2i2o_2_nlgA91ClOQVeZ_zSsKQ,21134
|
|
18
18
|
sourcecode/breaking_changes.py,sha256=iaTEkegVGnR_DEQP45U66GQKMkq-_qNM60nv7XEPm7k,17504
|
|
19
19
|
sourcecode/build_modules.py,sha256=rsT8reXoeOGztX28SNwem3yGdBhAC5VJx9RL2vRp_d0,15935
|
|
20
20
|
sourcecode/build_stamp.py,sha256=YWlnT8CEFzMre5pacRQkc244BfZNG5owySIyP9Dq4pw,7677
|
|
21
21
|
sourcecode/bundled_docs.py,sha256=KymEkB7P8oeg0-PjcD8eRSDhqQbwQxDUbHv1i00LQOc,2663
|
|
22
22
|
sourcecode/cache.py,sha256=z_1T0ClTbC3DaG_Fo-6_HKRUdBXHbwNoVvj8gZmQVGo,45591
|
|
23
|
-
sourcecode/cache_model.py,sha256=
|
|
23
|
+
sourcecode/cache_model.py,sha256=fI5dEvK2-dA246a_-DHyq8zumBPR0rjYvyxx397SNW4,73716
|
|
24
24
|
sourcecode/cache_observation.py,sha256=5E2BeqiYE5wBCbvDglkc5A9fTNhXkT_OhcDuuCqRu4Q,5622
|
|
25
25
|
sourcecode/call_surface.py,sha256=fiqYfHooxN1fX9oQoysq1LS3LoZcobhyUNjAGEZKpwk,4148
|
|
26
26
|
sourcecode/caller_metrics.py,sha256=zGc3sHRRwEJgAGmyfqEiH69mD9w5rOqMUhzby8Vmm_w,12599
|
|
@@ -31,7 +31,7 @@ sourcecode/change_plan.py,sha256=drAoDsqFplutCLc6Y0xue7sYkTls0SpYh7aOXvttv3I,129
|
|
|
31
31
|
sourcecode/ci_output.py,sha256=X4NRokWWMRF9Ex8OQrEO2g04GzJ00GDP5zYIoqI9YCc,4625
|
|
32
32
|
sourcecode/cir_graphs.py,sha256=RytqSv1WF8kdlfXj2fPQz16LY4akS2kyThbdWL8beCQ,14835
|
|
33
33
|
sourcecode/classifier.py,sha256=JBzPwSSrDG-tUHAbcKB678HRbjLpD-ohzbzzO62mgpo,20114
|
|
34
|
-
sourcecode/cli.py,sha256=
|
|
34
|
+
sourcecode/cli.py,sha256=PK-DWNQw58k-SYybYv9lMziIulPJeB2rQ86FZiuo8J0,867520
|
|
35
35
|
sourcecode/client_calls.py,sha256=YOPnfRZzRyqmdHvXSVeiunW8cuiuCuWXacNIQRgKMCw,22640
|
|
36
36
|
sourcecode/code_notes_analyzer.py,sha256=EJemNCNc9Dn-1RZYu-aNbK0ELzmsyC4s6FdHi3XyNEI,9392
|
|
37
37
|
sourcecode/compare.py,sha256=Lnfmm9I3k0H1jP1tV6ZJ-R7znjQPLPLCe5TzV1Jb_PM,15323
|
|
@@ -64,7 +64,7 @@ sourcecode/endpoint_literals.py,sha256=Qf4gTZzvNSFDGDuOvF0YRL9NvaYKKj24klhR5LIOa
|
|
|
64
64
|
sourcecode/endpoint_metrics.py,sha256=sLSLUIgiIyvNdOynaxVgHd9SjRF_DbN3QxevaquykaU,2840
|
|
65
65
|
sourcecode/entrypoint_classifier.py,sha256=jhTYlyqDJH2AtdEcLVaRU3lYRTJuF8DkxVzl4-W3zWE,5322
|
|
66
66
|
sourcecode/env_analyzer.py,sha256=tU2CcW-Lkl__60DMd4ibYnXnxfmPbV5Z9GrToSWLdSA,22029
|
|
67
|
-
sourcecode/envelope.py,sha256=
|
|
67
|
+
sourcecode/envelope.py,sha256=gAvGZrH2Q1ovfDdqjuvx5gIc31zUNAJLVCHu6pMxAnI,17397
|
|
68
68
|
sourcecode/environment_resolution.py,sha256=e86HT3RNbIIUIRChvz1Pu9Um81UvYu22BkpHNnwbUQI,30650
|
|
69
69
|
sourcecode/error_schema.py,sha256=uAWEknt3Z-6pNoNaiaSVeiDHdBe-bmt08BDlkS1YaAs,2951
|
|
70
70
|
sourcecode/evidence_provider.py,sha256=GSSL44JEaouO5AHks2sB3d1YvC9xIKIld1yBYxZpXxo,4277
|
|
@@ -82,7 +82,7 @@ sourcecode/gate_anchors.py,sha256=26v8wUtzOk1K1Un5uXdUxAu20mqSPX3jo82zuM05ByE,20
|
|
|
82
82
|
sourcecode/git_analyzer.py,sha256=irvEwddbd5_tbA_eYUZebf4mH7_nFhpjwaWAV1f7jUY,15755
|
|
83
83
|
sourcecode/git_checkout.py,sha256=gCnkMwHpU6yLyc10FoGzE8W9-tI8KyYxKTgpbWPjayo,6009
|
|
84
84
|
sourcecode/github_diff.py,sha256=EVjSR853IoEuKUn10lDjpqw2a6r0-jM_xsxwEOS-Wzs,1399
|
|
85
|
-
sourcecode/graph_analyzer.py,sha256=
|
|
85
|
+
sourcecode/graph_analyzer.py,sha256=Gw2MzLp0P990TGx6D6Ie-WIPnjWVE6X6dNBQnoM9xPU,65857
|
|
86
86
|
sourcecode/graph_evidence.py,sha256=rENNsYRZeNstX_ExNCLlbHJAruFQwxo5d00x6wO3xwI,15030
|
|
87
87
|
sourcecode/hibernate_strat.py,sha256=kLAa5GMwYFZgOI7edl-nDcJTr4SFVYAoxtMy-fj2BsA,77954
|
|
88
88
|
sourcecode/identity_fallback.py,sha256=uRC_j_80uaI4Ue4tf-OhKX4h472dmufYcjEFGSxY2jk,9190
|
|
@@ -98,24 +98,25 @@ sourcecode/migration_blast.py,sha256=OPryWkM6-PbvcG3eJFdcWUnlpXBje41nu2BkrZnE2hg
|
|
|
98
98
|
sourcecode/non_coverage.py,sha256=x-P6nRWc3cfUgHLUjjFWkxiyENASlksUhVHJYwd-a_8,30024
|
|
99
99
|
sourcecode/openapi_surface.py,sha256=BTt0K-woZbkbWTN77IkqeBm_Okag9owR0848fmot8sk,16207
|
|
100
100
|
sourcecode/openrewrite_recipe.py,sha256=0pS-61falE6rSfkos2MPnmoDamvoeTT-8Kmj7smj_DI,12987
|
|
101
|
-
sourcecode/output_bounds.py,sha256=
|
|
101
|
+
sourcecode/output_bounds.py,sha256=909Wu4qlLqHGa4fgQAsDhSBBi0lL8MQnrXv0gxZM2u8,14051
|
|
102
102
|
sourcecode/output_budget.py,sha256=AHwxnfToUk9a3MJdcq0WDUiFbyNla9VWxdE0pC7UWfY,15617
|
|
103
103
|
sourcecode/output_ceiling.py,sha256=rMLDHbXeC6C_uP8iQSVbbCGiJ_n0gMr2YI9zt5nltFA,33201
|
|
104
104
|
sourcecode/output_encoding.py,sha256=OxiZQtr7uWBDUtblNQviNHsTH1Xo9AZEpsegPlQWKFk,2139
|
|
105
105
|
sourcecode/output_sink.py,sha256=Eya-PnXxqc3RGulJoLhuC9LUF73SZD0aO5O2B0xAMXU,8762
|
|
106
106
|
sourcecode/pack_manifest.py,sha256=Qm6et6SQsFCLc-HJ-Uhz1XlcOa77ZDHgks4JVDEENss,20820
|
|
107
|
-
sourcecode/packs.py,sha256=
|
|
107
|
+
sourcecode/packs.py,sha256=BudazaJg2Xd1UwVmWYxVuf5XxsLiN05iS0yEQn94Sgk,46151
|
|
108
108
|
sourcecode/parallel.py,sha256=QocwdZoUabdxzd_jEz7f6B2XMsYWFaCFaIl0tIEQs3g,10546
|
|
109
109
|
sourcecode/parse_cache.py,sha256=BaPzh-KygmY4OpJQm2YGh6PWztYsj58vHWTu2eSF4s8,38769
|
|
110
110
|
sourcecode/partial_contract.py,sha256=FZUBACkClvRAmPeYVjxNWeQmP6Y22KW4fPeeTfmT80A,5951
|
|
111
|
-
sourcecode/path_admission.py,sha256=
|
|
111
|
+
sourcecode/path_admission.py,sha256=5IBfmHvOrSwrVLlXXwj9KAEg-ciVaHYHjcpAS8mriPg,5898
|
|
112
|
+
sourcecode/path_display.py,sha256=ikro7EBSzoZAx7lkmKuDYM3Ykh5NefkjM2Mmp_iOp-w,257
|
|
112
113
|
sourcecode/path_filters.py,sha256=YWhiy6mARZ8QPDMA6O274jbjHSk6pKE_LMvj8ge_Nbs,15658
|
|
113
114
|
sourcecode/perf.py,sha256=hB0LE0fhH_TwePXmIdtxhTyol6GBTwVBkAcxJa7MYpg,67254
|
|
114
115
|
sourcecode/phased_run.py,sha256=MOLH5f3ZMyfpSQ-tLGRy1qzL4ETE_46qaS3G0O2QsPM,23471
|
|
115
116
|
sourcecode/pipe_contract.py,sha256=PML0Er5d8uDyec4OrdUXuyqHbGPUYndjeaKUjkFz2u4,8369
|
|
116
117
|
sourcecode/posture.py,sha256=OQX3r0wBzdRNwMs6fuJcpFKPuyoC_uAkAVoKsYuwqgE,87190
|
|
117
118
|
sourcecode/pr_comment_renderer.py,sha256=239PmJdf95av_ZW236C7_tvq_ahECeuF9AZxrheJ4OQ,15573
|
|
118
|
-
sourcecode/pr_impact.py,sha256=
|
|
119
|
+
sourcecode/pr_impact.py,sha256=8RgTJgvEThezh-Vm65eiFvJBdb45VjcbewEk5P144-0,39184
|
|
119
120
|
sourcecode/prepare_context.py,sha256=U-iAQaLDc7qSjf2IKM4IznZFFZBDwWlFTRp_MBaALXQ,245016
|
|
120
121
|
sourcecode/product_info.py,sha256=rpuCDf0KM2SD-WP8vw2tjdcbhWPsOGEVjSWqS8fkzlo,4966
|
|
121
122
|
sourcecode/progress.py,sha256=naKbWFqf-eTE3vtLsi-eHYILz0p3pxCASAzMmvxUIAI,21643
|
|
@@ -133,7 +134,7 @@ sourcecode/remediation_diff.py,sha256=fGYqPmQF7bO54L8ivztX5PgmW4fVu54gNcG6OEQ192
|
|
|
133
134
|
sourcecode/remedies.py,sha256=V2_cD4pLq8bKRkzF-3RGFoiu1xWYZS384WDVp1MrlZw,10225
|
|
134
135
|
sourcecode/rename_refactor.py,sha256=oASZIf7TxcOBy3RQ0FuOe-4HlNW_JOu9RW9JqCxGNBE,17225
|
|
135
136
|
sourcecode/repo_classifier.py,sha256=FG1vaWKdWXsWdl-S8hjVMiTqcwgaRXkDyvK4rPcOGtQ,22681
|
|
136
|
-
sourcecode/repository_ir.py,sha256=
|
|
137
|
+
sourcecode/repository_ir.py,sha256=xW3ahhhejolAaQL-EMEjOPYmrxhEx5S_3BNGxTEX56U,523074
|
|
137
138
|
sourcecode/resource_budget.py,sha256=Bo-XMvVK9XyHY_S06fVirZrhXgwmnr3XI38-Li55NWY,7767
|
|
138
139
|
sourcecode/ris.py,sha256=zlns4esv1tK8VDIYzOzRmw5yM6VLx7oxaPNB_kN3it4,28617
|
|
139
140
|
sourcecode/risk.py,sha256=uwKSK5BLNVXaSnRDEmepmFGXODppGmzwS0c-yCEwKrc,100319
|
|
@@ -179,12 +180,12 @@ sourcecode/text_input.py,sha256=3pL8DxR_DMI3ece-B70DnppvrEaLh4R17Pp8dK9G_hc,3596
|
|
|
179
180
|
sourcecode/timeline.py,sha256=3S2Kgh0wDaq3H4bgPskWDKX-tDE74RZZ_1RRNu7Id3Y,22284
|
|
180
181
|
sourcecode/timeline_cache.py,sha256=99RQ-MW3wqxjtuHcVB_k83USsxWP6DqzeupfSzKR_CE,8277
|
|
181
182
|
sourcecode/token_estimate.py,sha256=_2cworfPkfP2ZxVcwX_Ltu0vFdMvK-FMuTY3qJAqI5M,9415
|
|
182
|
-
sourcecode/tree_utils.py,sha256=
|
|
183
|
+
sourcecode/tree_utils.py,sha256=oAwkGyrixO2VMX4ZMIDzg9V2oBxt3KIxFN3ahVMxKJo,2174
|
|
183
184
|
sourcecode/type_usage_surface.py,sha256=51IrKRQoIoRnlsiDjHnqpJBn2rc6E59aRhgS0HTzAF0,4428
|
|
184
185
|
sourcecode/validation_inference.py,sha256=-oWJqE6PqkqcZbCFDJeWCQHgI9Dbuv5ggJWD3LE_2IU,20817
|
|
185
186
|
sourcecode/validation_surface.py,sha256=LeoOeZfTZmz5l4f2EDXNlOlzoTlL3EMVrYY8HEKGEg0,36716
|
|
186
187
|
sourcecode/verify_edit.py,sha256=Ha0JNsC6CYHjtbetVZurLetqBNjriykYJ8ITDUMuNVY,63479
|
|
187
|
-
sourcecode/verify_repo.py,sha256=
|
|
188
|
+
sourcecode/verify_repo.py,sha256=svwc66w55bkeRfO_W7wOI9b27bM7SBVqr7NGX7jrQxg,16342
|
|
188
189
|
sourcecode/verify_rules.py,sha256=R3l6nLT6WQzUNBzxtmnxyGZcKj9qMDW38Y0c0gNdCGk,19973
|
|
189
190
|
sourcecode/version_check.py,sha256=CHp6ZxTIfo8kyHPCBgJA1uFC0xQCoXMuuOfrW8QTL8o,4942
|
|
190
191
|
sourcecode/waivers.py,sha256=VlGsvpGt9K5ih3q7P5-co1ob2IROyZDSlVLMZyLbLJU,14874
|
|
@@ -256,13 +257,13 @@ sourcecode/telemetry/consent.py,sha256=-Wb8BFGXEexOs8M0Eja7F-T6ZtLNPeRoZnHcHvlP7
|
|
|
256
257
|
sourcecode/telemetry/events.py,sha256=l3Z2SQUO4_C2D2ItXOOdVNimAmHedUHnUxqYFTxnsAE,2900
|
|
257
258
|
sourcecode/telemetry/filters.py,sha256=-lqT2oorECuqEIdeHb--7AZ6BCaUx0bya720a-Z5x6w,7335
|
|
258
259
|
sourcecode/telemetry/transport.py,sha256=4gGHsq0WeY9VywEZXA3vUxykfiYnw9uuqfjAAec7F8o,1681
|
|
259
|
-
sourcecode/_docs/DEFECT-LEDGER.md,sha256=
|
|
260
|
+
sourcecode/_docs/DEFECT-LEDGER.md,sha256=3xTXcOm_zn2Ty597MG3fUOSAjCgDZL3nuh_cuRY5Y4M,1108377
|
|
260
261
|
sourcecode/_docs/LICENSE,sha256=23-fk61oSWGVmkWyka-FIM0rhAPM2hcYHnsaridL8Uo,1859
|
|
261
262
|
sourcecode/_docs/NOTICE,sha256=Br-AA8Y3iJo1WXa5uP8QBpzqI5nDu3iGLbFyvDt3BOs,321
|
|
262
|
-
sourcecode/_docs/USER_GUIDE.md,sha256=
|
|
263
|
-
sourcecode-5.8.
|
|
264
|
-
sourcecode-5.8.
|
|
265
|
-
sourcecode-5.8.
|
|
266
|
-
sourcecode-5.8.
|
|
267
|
-
sourcecode-5.8.
|
|
268
|
-
sourcecode-5.8.
|
|
263
|
+
sourcecode/_docs/USER_GUIDE.md,sha256=91R8fih4OvBvzpZ0UvhbHek7gg0RoIZK8apLUmH9ar0,93284
|
|
264
|
+
sourcecode-5.8.30.dist-info/METADATA,sha256=feREJq3ivFy-CBGFs8SDUAX-nlQDVEByROi2VJxqd5c,55428
|
|
265
|
+
sourcecode-5.8.30.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
266
|
+
sourcecode-5.8.30.dist-info/entry_points.txt,sha256=-JEAdChrK5We51kZcb7OaDcyil-dHBjBPL-NhuO-QY8,89
|
|
267
|
+
sourcecode-5.8.30.dist-info/licenses/LICENSE,sha256=23-fk61oSWGVmkWyka-FIM0rhAPM2hcYHnsaridL8Uo,1859
|
|
268
|
+
sourcecode-5.8.30.dist-info/licenses/NOTICE,sha256=Br-AA8Y3iJo1WXa5uP8QBpzqI5nDu3iGLbFyvDt3BOs,321
|
|
269
|
+
sourcecode-5.8.30.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|