sourcecode 5.9.0__py3-none-any.whl → 5.9.1__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 +17 -0
- sourcecode/_docs/USER_GUIDE.md +3 -3
- sourcecode/cli.py +65 -16
- sourcecode/cve_reachability.py +27 -1
- sourcecode/output_bounds.py +34 -8
- {sourcecode-5.9.0.dist-info → sourcecode-5.9.1.dist-info}/METADATA +5 -5
- {sourcecode-5.9.0.dist-info → sourcecode-5.9.1.dist-info}/RECORD +13 -13
- {sourcecode-5.9.0.dist-info → sourcecode-5.9.1.dist-info}/WHEEL +0 -0
- {sourcecode-5.9.0.dist-info → sourcecode-5.9.1.dist-info}/entry_points.txt +0 -0
- {sourcecode-5.9.0.dist-info → sourcecode-5.9.1.dist-info}/licenses/LICENSE +0 -0
- {sourcecode-5.9.0.dist-info → sourcecode-5.9.1.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 = '48f4057a9c265d73e61f76f00b41cd011a2e0031'
|
|
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,23 @@ 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 `5.9.0` audit received, 2026-08-26 - `AUD-608`; corrections shipped in `5.9.1`.** The audited
|
|
20
|
+
revision is the released `5.9.0` commit. The three confirmed corrections are
|
|
21
|
+
closed: `AUD-608-C01` (P1, `cve` now declares its static inventory scope,
|
|
22
|
+
`fe1f624`), `AUD-608-P01` (P1, `pr-risk --since` returns structured base-ref
|
|
23
|
+
errors, `b479465`), and `AUD-608-O01` (P2, `posture --diff --limit` bounds
|
|
24
|
+
`permit_all` plus effective-access evidence maps, `5f8a50b`). `AUD-607-U01`
|
|
25
|
+
is also closed (`19811ac`): the seven new command helps state budget-policy
|
|
26
|
+
non-applicability. `AUD-607-U02` is
|
|
27
|
+
withdrawn after controlled runs showed an external 120-second timeout;
|
|
28
|
+
`AUD-608-C02` (reported UTF-8 mojibake in `chunk-file`) remains a platform
|
|
29
|
+
reproduction follow-up because the released reader is explicitly UTF-8.
|
|
30
|
+
|
|
31
|
+
The new effective-access evidence supersedes the prior `AUD-607-O01`
|
|
32
|
+
non-reproduction: that check did not exercise the payload shape now identified.
|
|
33
|
+
Historical records below remain snapshots. Full evidence is in
|
|
34
|
+
[`AUDIT-2026-08-26-EXTERNAL-5.9.0.md`](AUDIT-2026-08-26-EXTERNAL-5.9.0.md).
|
|
35
|
+
|
|
19
36
|
**External `5.8.32` audit received, 2026-08-26 — `AUD-607`.** Two independent
|
|
20
37
|
reports ([`AUDIT-2026-08-26-EXTERNAL-5.8.32.md`](AUDIT-2026-08-26-EXTERNAL-5.8.32.md)):
|
|
21
38
|
a reverification round (9.7/10) and a comparison round against `5.8.31` (8/10).
|
sourcecode/_docs/USER_GUIDE.md
CHANGED
|
@@ -46,13 +46,13 @@ 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.9.
|
|
49
|
+
5.9.1, `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
53
|
The current external pack audit intake is tracked in
|
|
54
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.9.
|
|
55
|
+
the two pack fixes are included in release 5.9.1, with release-artifact verification
|
|
56
56
|
remaining for detached execution and pack evidence.
|
|
57
57
|
|
|
58
58
|
---
|
|
@@ -206,7 +206,7 @@ pipx install sourcecode # isolated install, no venv needed
|
|
|
206
206
|
|
|
207
207
|
# Verify
|
|
208
208
|
ask version
|
|
209
|
-
# ask 5.9.
|
|
209
|
+
# ask 5.9.1
|
|
210
210
|
```
|
|
211
211
|
|
|
212
212
|
Requires Python 3.9+.
|
sourcecode/cli.py
CHANGED
|
@@ -826,6 +826,31 @@ from sourcecode.analysis_budget import ( # noqa: E402
|
|
|
826
826
|
)
|
|
827
827
|
|
|
828
828
|
|
|
829
|
+
def _command_budget_help(command: str) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
|
|
830
|
+
"""Append the command-level budget contract derived from the shared registry."""
|
|
831
|
+
from sourcecode.analysis_budget import budget_registry_name
|
|
832
|
+
|
|
833
|
+
if budget_registry_name(command) is not None:
|
|
834
|
+
policy = (
|
|
835
|
+
"\n\b\nBudget policy: this command is registered for "
|
|
836
|
+
"`ASK_MAX_ANALYSIS_SECONDS`; its result publishes the applicable "
|
|
837
|
+
"analysis-budget and memory contract."
|
|
838
|
+
)
|
|
839
|
+
else:
|
|
840
|
+
policy = (
|
|
841
|
+
"\n\b\nBudget policy: this command does not consume "
|
|
842
|
+
"`ASK_MAX_ANALYSIS_SECONDS` and does not create a command-level "
|
|
843
|
+
"`ASK_MAX_RSS_MB` enforcement scope. A delegated analysis, if any, "
|
|
844
|
+
"publishes its own budget contract."
|
|
845
|
+
)
|
|
846
|
+
|
|
847
|
+
def decorate(command_fn: Callable[..., Any]) -> Callable[..., Any]:
|
|
848
|
+
command_fn.__doc__ = (command_fn.__doc__ or "") + policy
|
|
849
|
+
return command_fn
|
|
850
|
+
|
|
851
|
+
return decorate
|
|
852
|
+
|
|
853
|
+
|
|
829
854
|
def _build_help_text(scope: "Optional[Any]" = None) -> str:
|
|
830
855
|
"""Build --help text dynamically based on current license state."""
|
|
831
856
|
try:
|
|
@@ -14508,7 +14533,12 @@ def posture_cmd(
|
|
|
14508
14533
|
# answered in — a `--diff` carries a bean list per profile set and a
|
|
14509
14534
|
# `--diff-ref` one per ref, so the bound has to reach every depth or the
|
|
14510
14535
|
# caller believes they bounded something they did not.
|
|
14511
|
-
from sourcecode.output_bounds import
|
|
14536
|
+
from sourcecode.output_bounds import (
|
|
14537
|
+
POSTURE_BOUNDED_LISTS,
|
|
14538
|
+
POSTURE_BOUNDED_MAPS,
|
|
14539
|
+
bound_lists,
|
|
14540
|
+
resolve_limit,
|
|
14541
|
+
)
|
|
14512
14542
|
|
|
14513
14543
|
_posture_limit = resolve_limit(limit, compact)
|
|
14514
14544
|
# B-8 / AUD-592-B01. A compact answer must retain one actionable unresolved
|
|
@@ -14518,6 +14548,7 @@ def posture_cmd(
|
|
|
14518
14548
|
_posture_limit = 1 if data.get("summary", {}).get("unresolved", 0) else 0
|
|
14519
14549
|
bound_lists(
|
|
14520
14550
|
data, POSTURE_BOUNDED_LISTS, _posture_limit,
|
|
14551
|
+
map_keys=POSTURE_BOUNDED_MAPS,
|
|
14521
14552
|
# `--compact` is a size contract for agent output. The monotone
|
|
14522
14553
|
# optimisation may keep a list whole when its disclosure costs more
|
|
14523
14554
|
# than that individual cut, leaving a large diff above the ceiling.
|
|
@@ -16543,6 +16574,7 @@ def _audit_population_for(root: "Path", *, progress: "Any" = None):
|
|
|
16543
16574
|
# ── self-audit (what this build can say about itself, and what it cannot) ────
|
|
16544
16575
|
|
|
16545
16576
|
@app.command("self-audit")
|
|
16577
|
+
@_command_budget_help("self-audit")
|
|
16546
16578
|
def self_audit_cmd(
|
|
16547
16579
|
fail_on: Optional[str] = typer.Option(
|
|
16548
16580
|
None, "--fail-on",
|
|
@@ -16619,6 +16651,7 @@ def self_audit_cmd(
|
|
|
16619
16651
|
# ── drift (what changed in the effective access, and when) ───────────────────
|
|
16620
16652
|
|
|
16621
16653
|
@app.command("drift")
|
|
16654
|
+
@_command_budget_help("drift")
|
|
16622
16655
|
def drift_cmd(
|
|
16623
16656
|
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
16624
16657
|
profile: Optional[str] = typer.Option(
|
|
@@ -16759,6 +16792,7 @@ def drift_cmd(
|
|
|
16759
16792
|
# ── watch (re-answer only what changed, while you are still editing) ─────────
|
|
16760
16793
|
|
|
16761
16794
|
@app.command("watch")
|
|
16795
|
+
@_command_budget_help("watch")
|
|
16762
16796
|
def watch_cmd(
|
|
16763
16797
|
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
16764
16798
|
once: bool = typer.Option(
|
|
@@ -16858,6 +16892,7 @@ def watch_cmd(
|
|
|
16858
16892
|
# ── pr-risk (the risk of THIS change, not the state of the repository) ───────
|
|
16859
16893
|
|
|
16860
16894
|
@app.command("pr-risk")
|
|
16895
|
+
@_command_budget_help("pr-risk")
|
|
16861
16896
|
def pr_risk_cmd(
|
|
16862
16897
|
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
16863
16898
|
files: Optional[str] = typer.Option(
|
|
@@ -16901,6 +16936,7 @@ def pr_risk_cmd(
|
|
|
16901
16936
|
ask pr-risk . --files changed.txt --since origin/main --fail-on block
|
|
16902
16937
|
"""
|
|
16903
16938
|
from sourcecode.pr_risk import assess, VERDICT_BLOCK, VERDICT_REVIEW, VERDICT_UNKNOWN
|
|
16939
|
+
from sourcecode.context_graph import ContextGraph
|
|
16904
16940
|
from sourcecode.repository_ir import find_java_files
|
|
16905
16941
|
from sourcecode.spring_model import SpringSemanticModel
|
|
16906
16942
|
|
|
@@ -16939,7 +16975,7 @@ def pr_risk_cmd(
|
|
|
16939
16975
|
base_routes = None
|
|
16940
16976
|
if since:
|
|
16941
16977
|
_prog.start(f"differencing routes against {since}")
|
|
16942
|
-
from sourcecode.git_checkout import materialize_ref
|
|
16978
|
+
from sourcecode.git_checkout import RefError, materialize_ref
|
|
16943
16979
|
from sourcecode.pr_risk import _routes_of
|
|
16944
16980
|
|
|
16945
16981
|
try:
|
|
@@ -16947,14 +16983,24 @@ def pr_risk_cmd(
|
|
|
16947
16983
|
base_files = find_java_files(base_tree)
|
|
16948
16984
|
base_cir = ContextGraph.build(base_files, base_tree).cir
|
|
16949
16985
|
base_routes = _routes_of(base_cir)
|
|
16950
|
-
except
|
|
16951
|
-
|
|
16952
|
-
|
|
16953
|
-
|
|
16954
|
-
|
|
16955
|
-
|
|
16956
|
-
|
|
16957
|
-
|
|
16986
|
+
except RefError as exc:
|
|
16987
|
+
_emit_error_json(
|
|
16988
|
+
exc.code,
|
|
16989
|
+
exc.message,
|
|
16990
|
+
ref=since,
|
|
16991
|
+
hint="Pass a commit available in this repository; no ref is fetched or substituted.",
|
|
16992
|
+
)
|
|
16993
|
+
raise typer.Exit(code=1)
|
|
16994
|
+
except Exception as exc:
|
|
16995
|
+
_emit_error_json(
|
|
16996
|
+
EXECUTION_FAILED_CODE,
|
|
16997
|
+
f"Could not build the base route inventory for {since!r}: "
|
|
16998
|
+
f"{type(exc).__name__}: {exc}",
|
|
16999
|
+
ref=since,
|
|
17000
|
+
stage="base_route_inventory",
|
|
17001
|
+
hint="Fix the base tree or retry with a readable local ref; no comparison was produced.",
|
|
17002
|
+
)
|
|
17003
|
+
raise typer.Exit(code=1)
|
|
16958
17004
|
|
|
16959
17005
|
_prog.start("scoring the change")
|
|
16960
17006
|
result = assess(
|
|
@@ -16968,12 +17014,6 @@ def pr_risk_cmd(
|
|
|
16968
17014
|
finally:
|
|
16969
17015
|
_prog.stop()
|
|
16970
17016
|
|
|
16971
|
-
if since and base_routes is None:
|
|
16972
|
-
result.non_coverage.append(
|
|
16973
|
-
f"the base ref `{since}` could not be read, so no route was reported "
|
|
16974
|
-
f"as newly added: {_base_error}"
|
|
16975
|
-
)
|
|
16976
|
-
|
|
16977
17017
|
data = result.to_dict()
|
|
16978
17018
|
_emit_command_output(
|
|
16979
17019
|
_serialize_dict(data, format),
|
|
@@ -16998,6 +17038,7 @@ def pr_risk_cmd(
|
|
|
16998
17038
|
# ── remediate (finding → recipe → apply → verify, as one loop) ───────────────
|
|
16999
17039
|
|
|
17000
17040
|
@app.command("remediate")
|
|
17041
|
+
@_command_budget_help("remediate")
|
|
17001
17042
|
def remediate_cmd(
|
|
17002
17043
|
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
17003
17044
|
write: bool = typer.Option(
|
|
@@ -17101,6 +17142,7 @@ def remediate_cmd(
|
|
|
17101
17142
|
# ── intent (natural language → a typed query this CLI already answers) ───────
|
|
17102
17143
|
|
|
17103
17144
|
@app.command("intent")
|
|
17145
|
+
@_command_budget_help("intent")
|
|
17104
17146
|
def intent_cmd(
|
|
17105
17147
|
question: str = typer.Argument(..., help="The question, in plain language."),
|
|
17106
17148
|
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
@@ -17179,6 +17221,7 @@ def intent_cmd(
|
|
|
17179
17221
|
# ── cve (dependency advisories, gated on reachability) ───────────────────────
|
|
17180
17222
|
|
|
17181
17223
|
@app.command("cve")
|
|
17224
|
+
@_command_budget_help("cve")
|
|
17182
17225
|
def cve_cmd(
|
|
17183
17226
|
path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
|
|
17184
17227
|
feed: Optional[Path] = typer.Option(
|
|
@@ -17231,6 +17274,12 @@ def cve_cmd(
|
|
|
17231
17274
|
Nothing here answers "not reachable": reflection, SPI loading and container
|
|
17232
17275
|
wiring reach code no import statement names.
|
|
17233
17276
|
|
|
17277
|
+
\b
|
|
17278
|
+
Dependency coverage is the static manifest and supported-lockfile inventory.
|
|
17279
|
+
This command does not execute Maven or Gradle, so a transitive dependency
|
|
17280
|
+
absent from that inventory is not assessed. The JSON result publishes this
|
|
17281
|
+
coverage explicitly; it never treats an unobserved coordinate as safe.
|
|
17282
|
+
|
|
17234
17283
|
\b
|
|
17235
17284
|
ask cve . --feed ./osv-maven.json
|
|
17236
17285
|
ask cve . --feed ./feeds/ --reachable-only --fail-on reachable
|
sourcecode/cve_reachability.py
CHANGED
|
@@ -371,6 +371,29 @@ def assess(
|
|
|
371
371
|
}
|
|
372
372
|
non_coverage: list[str] = []
|
|
373
373
|
|
|
374
|
+
# DependencyAnalyzer reads manifests and the lockfiles it understands. It
|
|
375
|
+
# deliberately does not execute Maven or Gradle, so a missing record cannot
|
|
376
|
+
# mean a dependency resolver proved the coordinate absent.
|
|
377
|
+
java_records = [
|
|
378
|
+
record for record in dependencies
|
|
379
|
+
if str(getattr(record, "ecosystem", "")).lower() == "java"
|
|
380
|
+
]
|
|
381
|
+
scopes_observed: dict[str, int] = {}
|
|
382
|
+
for record in java_records:
|
|
383
|
+
scope = str(getattr(record, "scope", None) or "unknown")
|
|
384
|
+
scopes_observed[scope] = scopes_observed.get(scope, 0) + 1
|
|
385
|
+
dependency_inventory = {
|
|
386
|
+
"basis": "static_manifests_and_supported_lockfiles",
|
|
387
|
+
"dependency_resolution": "not_performed",
|
|
388
|
+
"java_records_observed": len(java_records),
|
|
389
|
+
"scopes_observed": dict(sorted(scopes_observed.items())),
|
|
390
|
+
"non_coverage": (
|
|
391
|
+
"Maven and Gradle are not executed. Dependencies absent from the "
|
|
392
|
+
"static manifest or supported lockfile inventory, including "
|
|
393
|
+
"tool-resolved transitive dependencies, are not assessed."
|
|
394
|
+
),
|
|
395
|
+
}
|
|
396
|
+
|
|
374
397
|
if not feed.loaded:
|
|
375
398
|
# A refusal, not a clean scan. The caller turns this into an exit code.
|
|
376
399
|
return {
|
|
@@ -378,6 +401,7 @@ def assess(
|
|
|
378
401
|
"schema": SCHEMA_ID,
|
|
379
402
|
"status": "no_feed",
|
|
380
403
|
"feed": feed.to_dict(),
|
|
404
|
+
"dependency_inventory": dependency_inventory,
|
|
381
405
|
"dependencies_examined": 0,
|
|
382
406
|
"matches": [],
|
|
383
407
|
"counts": counts,
|
|
@@ -490,8 +514,10 @@ def assess(
|
|
|
490
514
|
"schema": SCHEMA_ID,
|
|
491
515
|
"status": "ok",
|
|
492
516
|
"feed": feed.to_dict(),
|
|
517
|
+
"dependency_inventory": dependency_inventory,
|
|
493
518
|
"dependencies_examined": examined,
|
|
494
519
|
"matches": matches,
|
|
495
520
|
"counts": counts,
|
|
496
|
-
"non_coverage": non_coverage
|
|
521
|
+
"non_coverage": [dependency_inventory["non_coverage"]]
|
|
522
|
+
+ non_coverage + list(feed.limitations),
|
|
497
523
|
}
|
sourcecode/output_bounds.py
CHANGED
|
@@ -72,6 +72,9 @@ POSTURE_BOUNDED_LISTS: "tuple[str, ...]" = (
|
|
|
72
72
|
# `endpoint_access.endpoints`; registering only the synthetic `changed`
|
|
73
73
|
# shape left the largest nested list untouched by `--limit`.
|
|
74
74
|
"endpoints",
|
|
75
|
+
# AUD-608-O01. Effective access publishes this as one endpoint id per open
|
|
76
|
+
# decision. Omitting it made `posture --diff --limit` leave a full branch.
|
|
77
|
+
"permit_all",
|
|
75
78
|
# AUD-602-R02. `posture --diff` caps the per-profile bean and security
|
|
76
79
|
# lists, but the actionable delta is `endpoint_access.changed`: one row per
|
|
77
80
|
# request whose decision moves between the two profile sets. Omitting it
|
|
@@ -79,6 +82,11 @@ POSTURE_BOUNDED_LISTS: "tuple[str, ...]" = (
|
|
|
79
82
|
"changed",
|
|
80
83
|
)
|
|
81
84
|
|
|
85
|
+
#: AUD-608-O01. `effective_access.evidence` is an endpoint-id map rather than a
|
|
86
|
+
#: list. It has a separate registry because `evidence` is deliberately a common
|
|
87
|
+
#: name in unrelated payloads and must not become a global truncation rule.
|
|
88
|
+
POSTURE_BOUNDED_MAPS: "tuple[str, ...]" = ("evidence",)
|
|
89
|
+
|
|
82
90
|
#: The same for `validation`: one row per endpoint and one per gap, both of which
|
|
83
91
|
#: scale with the repository rather than with the question.
|
|
84
92
|
VALIDATION_BOUNDED_LISTS: "tuple[str, ...]" = (
|
|
@@ -141,6 +149,7 @@ def bound_lists(
|
|
|
141
149
|
keys: "Iterable[str]",
|
|
142
150
|
limit: "int | None",
|
|
143
151
|
*,
|
|
152
|
+
map_keys: "Iterable[str]" = (),
|
|
144
153
|
monotone: bool = False,
|
|
145
154
|
) -> Any:
|
|
146
155
|
"""Cap every list named in *keys*, anywhere in *payload*, and declare the cut.
|
|
@@ -151,8 +160,12 @@ def bound_lists(
|
|
|
151
160
|
level and misses one level down is worse than no flag, because the caller
|
|
152
161
|
believes they bounded it.
|
|
153
162
|
|
|
154
|
-
|
|
155
|
-
|
|
163
|
+
Named list values are touched. Named maps are touched only when their
|
|
164
|
+
parent is `effective_access`: `evidence` is a deliberately generic key in
|
|
165
|
+
other answer shapes. `summary.unresolved` is an int under the same name,
|
|
166
|
+
and a count is not a body. Maps retain their published insertion order:
|
|
167
|
+
their keys are endpoint identifiers, so sorting again here would make the
|
|
168
|
+
limit a second, inconsistent ranking policy.
|
|
156
169
|
|
|
157
170
|
**A bounded payload is never larger than the unbounded one it replaces.**
|
|
158
171
|
AUD-597-R03: `posture . --diff dev:prod` estimated 284 464 B and the same
|
|
@@ -182,6 +195,7 @@ def bound_lists(
|
|
|
182
195
|
if limit is None:
|
|
183
196
|
return payload
|
|
184
197
|
bounded = set(keys)
|
|
198
|
+
bounded_maps = set(map_keys)
|
|
185
199
|
limit = max(0, int(limit))
|
|
186
200
|
#: Bytes the accepted cuts freed, net of what they had to say about
|
|
187
201
|
#: themselves. The declaration below is paid for out of this and nothing
|
|
@@ -189,16 +203,25 @@ def bound_lists(
|
|
|
189
203
|
saved = 0
|
|
190
204
|
declined: "set[str]" = set()
|
|
191
205
|
|
|
192
|
-
def walk(node: Any) -> Any:
|
|
206
|
+
def walk(node: Any, parent_key: "str | None" = None) -> Any:
|
|
193
207
|
nonlocal saved
|
|
194
208
|
if isinstance(node, dict):
|
|
195
209
|
for key in list(node):
|
|
196
210
|
value = node[key]
|
|
197
|
-
|
|
211
|
+
is_bounded_list = key in bounded and isinstance(value, list)
|
|
212
|
+
is_bounded_map = (
|
|
213
|
+
key in bounded_maps
|
|
214
|
+
and parent_key == "effective_access"
|
|
215
|
+
and isinstance(value, dict)
|
|
216
|
+
)
|
|
217
|
+
if is_bounded_list or is_bounded_map:
|
|
198
218
|
total = len(value)
|
|
199
219
|
if total <= limit:
|
|
200
220
|
continue # nothing cut, and `declare_cap` says nothing
|
|
201
|
-
|
|
221
|
+
if isinstance(value, list):
|
|
222
|
+
node[key] = value[:limit]
|
|
223
|
+
else:
|
|
224
|
+
node[key] = dict(list(value.items())[:limit])
|
|
202
225
|
declare_cap(node, key, total, limit)
|
|
203
226
|
if not monotone:
|
|
204
227
|
continue
|
|
@@ -206,7 +229,10 @@ def bound_lists(
|
|
|
206
229
|
# `[limit:]` weighed as a list is the separators the removed
|
|
207
230
|
# rows carried with them, which is what the emit actually
|
|
208
231
|
# stops writing.
|
|
209
|
-
|
|
232
|
+
removed = value[limit:] if isinstance(value, list) else dict(
|
|
233
|
+
list(value.items())[limit:]
|
|
234
|
+
)
|
|
235
|
+
freed = payload_bytes(removed)
|
|
210
236
|
spent = payload_bytes({cap_key: node.get(cap_key)})
|
|
211
237
|
if freed > spent:
|
|
212
238
|
saved += freed - spent
|
|
@@ -215,10 +241,10 @@ def bound_lists(
|
|
|
215
241
|
node.pop(cap_key, None)
|
|
216
242
|
declined.add(key)
|
|
217
243
|
else:
|
|
218
|
-
walk(value)
|
|
244
|
+
walk(value, key)
|
|
219
245
|
elif isinstance(node, list):
|
|
220
246
|
for item in node:
|
|
221
|
-
walk(item)
|
|
247
|
+
walk(item, parent_key)
|
|
222
248
|
return node
|
|
223
249
|
|
|
224
250
|
result = walk(payload)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version: 5.9.
|
|
3
|
+
Version: 5.9.1
|
|
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
|
|
@@ -188,13 +188,13 @@ set `ASK_MAX_RSS_MB=<megabytes>`; if the process exceeds it, ASK refuses the
|
|
|
188
188
|
answer with `MEMORY_TOO_LARGE`, including the observed peak and limit. Leave it
|
|
189
189
|
unset, or set it to `0`, to disable the ceiling explicitly.
|
|
190
190
|
|
|
191
|
-
**Current performance status.** Release 5.9.
|
|
191
|
+
**Current performance status.** Release 5.9.1 retains the shared Canonical IR
|
|
192
192
|
path used by `validation` and now passes that same CIR into labelled `data-exposure`
|
|
193
193
|
runs; the no-label path remains parse-free. These are implementation properties,
|
|
194
194
|
not duration promises. A controlled external warm-path audit has opened performance
|
|
195
195
|
and bounded-output regressions for this release; use `ask cache model <repo>` and
|
|
196
196
|
`--progress stderr` for supervised runs, and consult the
|
|
197
|
-
[latest external audit intake](docs/AUDIT-2026-08-26-EXTERNAL-5.
|
|
197
|
+
[latest external audit intake](docs/AUDIT-2026-08-26-EXTERNAL-5.9.0.md) before
|
|
198
198
|
treating a historical timing or bounded flag as a current guarantee.
|
|
199
199
|
|
|
200
200
|
**What a warm actually covers.** `ask cache warm` rebuilds the declared root views and their
|
|
@@ -222,7 +222,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
|
|
|
222
222
|
# pip / pipx
|
|
223
223
|
pipx install sourcecode # or: pip install sourcecode
|
|
224
224
|
|
|
225
|
-
ask version # ask 5.9.
|
|
225
|
+
ask version # ask 5.9.1 — and, on a build that has aged,
|
|
226
226
|
# how many releases have probably shipped since
|
|
227
227
|
```
|
|
228
228
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
sourcecode/__init__.py,sha256=
|
|
1
|
+
sourcecode/__init__.py,sha256=_2HX1Q37i7qsrKVEti8GzYH5VTQN_ceb00JMLUsgPq0,308
|
|
2
2
|
sourcecode/__main__.py,sha256=qDFVkobwsdZrX0B3stiRqsUNivVpybKO-egzAwCW4xw,165
|
|
3
|
-
sourcecode/_build_commit.py,sha256=
|
|
3
|
+
sourcecode/_build_commit.py,sha256=fE28IwhQeKoWSX5Qk5TSlP6pkTSAKn0o7s1E1NiL5N0,8740
|
|
4
4
|
sourcecode/access_drift.py,sha256=1R7_fiAPvKNOnxc9uxkH3JH-k8MiAuyE7FwWUX1r4Fg,8995
|
|
5
5
|
sourcecode/adaptive_scanner.py,sha256=yJBKjNpkY6bpueYJ2YnRezen3sYZDecEt7WaaNWdqug,9466
|
|
6
6
|
sourcecode/analysis_budget.py,sha256=ZuNEboPF8A6GK-_V7WNt92ezgriga7_Rbr-vvSN4UEE,4183
|
|
@@ -33,7 +33,7 @@ sourcecode/change_plan.py,sha256=drAoDsqFplutCLc6Y0xue7sYkTls0SpYh7aOXvttv3I,129
|
|
|
33
33
|
sourcecode/ci_output.py,sha256=X4NRokWWMRF9Ex8OQrEO2g04GzJ00GDP5zYIoqI9YCc,4625
|
|
34
34
|
sourcecode/cir_graphs.py,sha256=RytqSv1WF8kdlfXj2fPQz16LY4akS2kyThbdWL8beCQ,14835
|
|
35
35
|
sourcecode/classifier.py,sha256=JBzPwSSrDG-tUHAbcKB678HRbjLpD-ohzbzzO62mgpo,20114
|
|
36
|
-
sourcecode/cli.py,sha256=
|
|
36
|
+
sourcecode/cli.py,sha256=kdXkygV9OTy5lAHLx730GkUuAzYvYfMZxeqmbd6Q0iI,918522
|
|
37
37
|
sourcecode/client_calls.py,sha256=YOPnfRZzRyqmdHvXSVeiunW8cuiuCuWXacNIQRgKMCw,22640
|
|
38
38
|
sourcecode/code_notes_analyzer.py,sha256=EJemNCNc9Dn-1RZYu-aNbK0ELzmsyC4s6FdHi3XyNEI,9392
|
|
39
39
|
sourcecode/compare.py,sha256=Lnfmm9I3k0H1jP1tV6ZJ-R7znjQPLPLCe5TzV1Jb_PM,15323
|
|
@@ -51,7 +51,7 @@ sourcecode/contract_model.py,sha256=nRxJKPMs1VHwFTa8AVXhGmaLjti3Lr2sjHDpWgv1bfE,
|
|
|
51
51
|
sourcecode/contract_pipeline.py,sha256=4XE-xhab7ysdExXyUOBl2hAH4MABo7moKnT9V4XcEwQ,30243
|
|
52
52
|
sourcecode/coverage_parser.py,sha256=X9scuUWxacahYTrTBGea2Ku-sf-WCVcnc9OEB35_3IU,19340
|
|
53
53
|
sourcecode/cve_feed.py,sha256=t93Ofu0uxB3zyI8W9nUKmH4Ljbt4qZpGIg68IP_aTrY,10749
|
|
54
|
-
sourcecode/cve_reachability.py,sha256=
|
|
54
|
+
sourcecode/cve_reachability.py,sha256=aEHkG3IaeLxgekK79cz07QTcv9LZHEqEYqyLGjwjzSE,20409
|
|
55
55
|
sourcecode/data_exposure.py,sha256=73EcuHsN3ESKdSvSj1B2FzD1myGJqzlNJpYO1NpI5WM,19963
|
|
56
56
|
sourcecode/data_labels.py,sha256=9v0JaICRH7jIZ015T1_DuT5E0MFfeL-Wcq1WOPE0Fe0,10965
|
|
57
57
|
sourcecode/declarations.py,sha256=Jr7oJDg004sFw0TvJySNVggXFT2jB6hQgbeQK2qreVo,7000
|
|
@@ -104,7 +104,7 @@ sourcecode/migration_blast.py,sha256=OPryWkM6-PbvcG3eJFdcWUnlpXBje41nu2BkrZnE2hg
|
|
|
104
104
|
sourcecode/non_coverage.py,sha256=Tl04OemPnxnOuWISMF6gAhDYx-P0LP6_l-PbpyvBJb4,30634
|
|
105
105
|
sourcecode/openapi_surface.py,sha256=BTt0K-woZbkbWTN77IkqeBm_Okag9owR0848fmot8sk,16207
|
|
106
106
|
sourcecode/openrewrite_recipe.py,sha256=0pS-61falE6rSfkos2MPnmoDamvoeTT-8Kmj7smj_DI,12987
|
|
107
|
-
sourcecode/output_bounds.py,sha256=
|
|
107
|
+
sourcecode/output_bounds.py,sha256=BvaRQY5nuytgfNUJHyO7JDLOHuSy0vdjqasISxmxLxI,15516
|
|
108
108
|
sourcecode/output_budget.py,sha256=AHwxnfToUk9a3MJdcq0WDUiFbyNla9VWxdE0pC7UWfY,15617
|
|
109
109
|
sourcecode/output_ceiling.py,sha256=rMLDHbXeC6C_uP8iQSVbbCGiJ_n0gMr2YI9zt5nltFA,33201
|
|
110
110
|
sourcecode/output_encoding.py,sha256=OxiZQtr7uWBDUtblNQviNHsTH1Xo9AZEpsegPlQWKFk,2139
|
|
@@ -268,13 +268,13 @@ sourcecode/telemetry/consent.py,sha256=-Wb8BFGXEexOs8M0Eja7F-T6ZtLNPeRoZnHcHvlP7
|
|
|
268
268
|
sourcecode/telemetry/events.py,sha256=l3Z2SQUO4_C2D2ItXOOdVNimAmHedUHnUxqYFTxnsAE,2900
|
|
269
269
|
sourcecode/telemetry/filters.py,sha256=-lqT2oorECuqEIdeHb--7AZ6BCaUx0bya720a-Z5x6w,7335
|
|
270
270
|
sourcecode/telemetry/transport.py,sha256=4gGHsq0WeY9VywEZXA3vUxykfiYnw9uuqfjAAec7F8o,1681
|
|
271
|
-
sourcecode/_docs/DEFECT-LEDGER.md,sha256=
|
|
271
|
+
sourcecode/_docs/DEFECT-LEDGER.md,sha256=EkYSJieDrazfADCZ8tsCsybyW9U0nAzWDQ8rS4KmGTU,1115164
|
|
272
272
|
sourcecode/_docs/LICENSE,sha256=23-fk61oSWGVmkWyka-FIM0rhAPM2hcYHnsaridL8Uo,1859
|
|
273
273
|
sourcecode/_docs/NOTICE,sha256=Br-AA8Y3iJo1WXa5uP8QBpzqI5nDu3iGLbFyvDt3BOs,321
|
|
274
|
-
sourcecode/_docs/USER_GUIDE.md,sha256=
|
|
275
|
-
sourcecode-5.9.
|
|
276
|
-
sourcecode-5.9.
|
|
277
|
-
sourcecode-5.9.
|
|
278
|
-
sourcecode-5.9.
|
|
279
|
-
sourcecode-5.9.
|
|
280
|
-
sourcecode-5.9.
|
|
274
|
+
sourcecode/_docs/USER_GUIDE.md,sha256=VtJs2r3hnqZ93vLpP92tFKgoPZ2VScoiBse1y01a0s4,99674
|
|
275
|
+
sourcecode-5.9.1.dist-info/METADATA,sha256=0K__BP-Li6SKHaPzMyNvNbz3EuqckTJsNp6R7j-xMUo,63167
|
|
276
|
+
sourcecode-5.9.1.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
277
|
+
sourcecode-5.9.1.dist-info/entry_points.txt,sha256=-JEAdChrK5We51kZcb7OaDcyil-dHBjBPL-NhuO-QY8,89
|
|
278
|
+
sourcecode-5.9.1.dist-info/licenses/LICENSE,sha256=23-fk61oSWGVmkWyka-FIM0rhAPM2hcYHnsaridL8Uo,1859
|
|
279
|
+
sourcecode-5.9.1.dist-info/licenses/NOTICE,sha256=Br-AA8Y3iJo1WXa5uP8QBpzqI5nDu3iGLbFyvDt3BOs,321
|
|
280
|
+
sourcecode-5.9.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|