sourcecode 5.8.31__py3-none-any.whl → 5.8.32__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
sourcecode/__init__.py 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.8.31"
7
+ __version__ = "5.8.32"
@@ -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 = '32e9b630f9276e5e481a33f0232c3a7876cd5751'
3
+ BUILD_COMMIT = '4fcf033d0261c8c67fbce36a70f42a6456f90a69'
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,24 @@ 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.8.31` audit received, 2026-08-26 - `AUD-606`.**
20
+ [`AUDIT-2026-08-26-EXTERNAL-5.8.31.md`](AUDIT-2026-08-26-EXTERNAL-5.8.31.md)
21
+ confirms the new progress and shared-cache controls, and records one actionable
22
+ external-subject follow-up `AUD-606-O01`, where `posture --diff --compact --limit`
23
+ was effectively unchanged on the auditor's nested output; the current checkout
24
+ reproduces no such gap and its bounding batteries pass. It also opens the CLI
25
+ consistency row `AUD-606-R01` for heterogeneous `retrieve` target flags, fixed
26
+ in the current checkout by `be16c04` with help-parity coverage.
27
+ The 137.8s cold run is a single-sample improvement and remains `AUD-606-P01`
28
+ benchmark follow-up, not a parser regression. `AUD-606-P02` (`pack gate` timing)
29
+ and `AUD-606-I01` (`pr-impact --files -` with `/dev/null`) are inconclusive due
30
+ to process contamination and shell-specific stdin behaviour respectively.
31
+
32
+ **Current `5.8.31` queue:** external-subject follow-up `AUD-606-O01`; controlled
33
+ benchmark/portability follow-ups `AUD-606-P01`, `AUD-606-P02` and `AUD-606-I01`.
34
+ The existing `AUD-604-R01` and `AUD-605` release-artifact verification items
35
+ remain unchanged.
36
+
19
37
  **External pack audit received, 2026-08-26 - `AUD-605`.**
20
38
  [`AUDIT-2026-08-26-EXTERNAL-5.8.28-PACK.md`](AUDIT-2026-08-26-EXTERNAL-5.8.28-PACK.md)
21
39
  adds two rows: `AUD-605-G01`, where an unresolved test file broadened pack-gate unknown
@@ -25,7 +43,7 @@ checkout by `52bcc36` and `f89ae18`, with focused regression batteries passing;
25
43
  artefact verification remains pending. The pack's `--since` timing is additional evidence
26
44
  for `AUD-604-P01`, not a duplicate performance finding.
27
45
 
28
- **Current `5.8.31` queue:** artefact verification for `AUD-604-R01`; the two `AUD-605`
46
+ **Previous `5.8.31` pack queue:** artefact verification for `AUD-604-R01`; the two `AUD-605`
29
47
  fixes are included in this release and await release-artefact verification.
30
48
 
31
49
  **External `5.8.28` audit received, 2026-08-26 - `AUD-604`.**
@@ -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.8.31, `validation` enters through that shared CIR and `data-exposure` reuses one semantic
49
+ 5.8.32, `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.8.31, with release-artifact verification
55
+ the two pack fixes are included in release 5.8.32, with release-artifact verification
56
56
  remaining for detached execution and pack evidence.
57
57
 
58
58
  ---
@@ -115,6 +115,8 @@ ask pack list
115
115
  ask pack assessment . --profile prod --output-dir .ask/packs/assessment
116
116
  ask pack gate . --since origin/main --compact --output-dir .ask/packs/gate
117
117
  ask pack assessment . --format markdown -o assessment.md
118
+ ask pack assessment . --only risk,posture --output-dir .ask/packs/assessment
119
+ ask pack gate . --pr 123 --output-dir .ask/packs/gate
118
120
  ```
119
121
 
120
122
  To include deployment evidence, pass the environment artefacts that describe
@@ -129,8 +131,25 @@ The gate can emit native annotations for CI logs:
129
131
  ```bash
130
132
  ask pack gate . --since origin/main --format github-actions
131
133
  ask pack gate . --since origin/main --format gitlab
134
+ ask pack gate . --since origin/main --format sarif -o gate.sarif
132
135
  ```
133
136
 
137
+ `pack assessment --only` selects a comma-separated subset of the declared
138
+ assessment components. The manifest records omitted components;
139
+ `audit-report` may be selected only together with `risk`.
140
+
141
+ MCP `get_assessment_pack` exposes the same capability through its `only`
142
+ `list[str]` input. It uses the declared component order and validation rules;
143
+ the reproducible CLI command in the `mcp` projection includes the selection.
144
+
145
+ `pack gate --pr NUMBER` resolves changed files through the local `gh` CLI and
146
+ uses the pull request's exact base commit. The base commit must already exist
147
+ locally; the command does not fetch or modify the repository and cannot be
148
+ combined with `--since`.
149
+
150
+ The `sarif` gate format is a bounded SARIF 2.1.0 export of ASK-owned gate
151
+ decisions. It does not re-emit findings produced by third-party scanners.
152
+
134
153
  The pack JSON preserves `manifest`, identity, fingerprints, evidence and each
135
154
  component's partial status. `PASS`, `BLOCK` and `UNVERIFIED` are data
136
155
  decisions; the process exit code is the pipeline signal. When `--output-dir` is
@@ -139,6 +158,10 @@ component remains a separate JSON artifact. An explicit `--output FILE` takes
139
158
  precedence. See the
140
159
  [Product Route contract](PRODUCT-ROUTE.md) for the boundaries.
141
160
 
161
+ The MCP `get_change_safety_gate` tool accepts the same two comparison modes:
162
+ `since` for a local Git ref or `pr` for GitHub pull-request resolution through
163
+ the local `gh` CLI. Pass exactly one; PR mode requires the base SHA locally.
164
+
142
165
  See [Product Route](PRODUCT-ROUTE.md) for the evidence contract and scope.
143
166
 
144
167
  A distinct set of commands exists to feed **AI coding agents** rather than to be read by a
@@ -183,7 +206,7 @@ pipx install sourcecode # isolated install, no venv needed
183
206
 
184
207
  # Verify
185
208
  ask version
186
- # ask 5.8.31
209
+ # ask 5.8.32
187
210
  ```
188
211
 
189
212
  Requires Python 3.9+.
@@ -1284,7 +1307,7 @@ explaining. The rest do one thing; `ask <command> --help` is the whole story.
1284
1307
  | `ask rename-class` | supported | Word-boundary Java rename across the repository |
1285
1308
  | `ask schema <name>` | supported | Print a published JSON Schema for this tool's output |
1286
1309
  | `ask archetype` | experimental | Evidence-based architectural archetype across four dimensions |
1287
- | `ask retrieve` | parked | Typed knowledge queries over the model — kept working, no longer developed |
1310
+ | `ask retrieve` | parked | Typed knowledge queries over the model — kept working, no longer developed. Symbol-oriented queries accept `--target/-t`; `--module/-m`, `--subsystem/-s` and `--endpoint/-e` remain compatible domain aliases. |
1288
1311
  | `ask baseline capture\|diff\|trend` | supported | Versioned architectural metrics over time; see [`ask trend`](#ask-trend-dir--how-the-architecture-moved) |
1289
1312
  | `ask cache status\|warm\|model\|clear\|freshness` | supported | Cache inspection; `ask cache model` states what a warm buys each command |
1290
1313
  | `ask config` · `ask version` · `ask activate` · `ask auth` · `ask telemetry` · `ask mcp` | supported | Configuration, version, licence, authentication, telemetry (on by default), MCP integration |
@@ -1443,6 +1466,16 @@ the **RIS**, builds the **shared Canonical IR** and fills the **parse cache**. I
1443
1466
  `--exclude` change *what is analysed*, so they miss the warmed core and rescan — that is the
1444
1467
  171s the field measured after a 103s warm.
1445
1468
 
1469
+ Select the root views needed by a workflow explicitly:
1470
+
1471
+ ```bash
1472
+ ask cache warm . --views compact
1473
+ ask cache warm . --views compact,agent
1474
+ ```
1475
+
1476
+ Without `--views`, all declared root views are warmed. `cache model` reports the
1477
+ same per-view contract and names any view that was skipped.
1478
+
1446
1479
  What invalidates what:
1447
1480
 
1448
1481
  - **Any change to the analysed files** → every layer keys on one signature of the tree state:
sourcecode/cli.py CHANGED
@@ -17511,7 +17511,9 @@ def retrieve_subsystem_inventory_cmd(
17511
17511
 
17512
17512
  @retrieve_app.command("subsystem-members")
17513
17513
  def retrieve_subsystem_members_cmd(
17514
- subsystem: str = typer.Option(..., "--subsystem", "-s", help="Subsystem label or package prefix."),
17514
+ subsystem: str = typer.Option(
17515
+ ..., "--subsystem", "--target", "-s", "-t", help="Subsystem label or package prefix."
17516
+ ),
17515
17517
  path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
17516
17518
  output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
17517
17519
  trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
@@ -17530,7 +17532,9 @@ def retrieve_subsystem_members_cmd(
17530
17532
 
17531
17533
  @retrieve_app.command("module-dependents")
17532
17534
  def retrieve_module_dependents_cmd(
17533
- module: str = typer.Option(..., "--module", "-m", help="Module path or package prefix."),
17535
+ module: str = typer.Option(
17536
+ ..., "--module", "--target", "-m", "-t", help="Module path or package prefix."
17537
+ ),
17534
17538
  path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
17535
17539
  output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
17536
17540
  trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
@@ -17549,7 +17553,9 @@ def retrieve_module_dependents_cmd(
17549
17553
 
17550
17554
  @retrieve_app.command("module-dependencies")
17551
17555
  def retrieve_module_dependencies_cmd(
17552
- module: str = typer.Option(..., "--module", "-m", help="Module path or package prefix."),
17556
+ module: str = typer.Option(
17557
+ ..., "--module", "--target", "-m", "-t", help="Module path or package prefix."
17558
+ ),
17553
17559
  path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
17554
17560
  output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
17555
17561
  trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
@@ -17587,7 +17593,9 @@ def retrieve_type_dependents_cmd(
17587
17593
 
17588
17594
  @retrieve_app.command("endpoint-contract")
17589
17595
  def retrieve_endpoint_contract_cmd(
17590
- ref: str = typer.Option(..., "--endpoint", "-e", help="Endpoint path or handler symbol."),
17596
+ ref: str = typer.Option(
17597
+ ..., "--endpoint", "--target", "-e", "-t", help="Endpoint path or handler symbol."
17598
+ ),
17591
17599
  path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
17592
17600
  output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
17593
17601
  trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
@@ -17606,7 +17614,9 @@ def retrieve_endpoint_contract_cmd(
17606
17614
 
17607
17615
  @retrieve_app.command("endpoint-security")
17608
17616
  def retrieve_endpoint_security_cmd(
17609
- ref: str = typer.Option(..., "--endpoint", "-e", help="Endpoint path or handler symbol."),
17617
+ ref: str = typer.Option(
17618
+ ..., "--endpoint", "--target", "-e", "-t", help="Endpoint path or handler symbol."
17619
+ ),
17610
17620
  path: Path = typer.Argument(Path("."), help="Repository path (default: current directory)"),
17611
17621
  output_path: Optional[Path] = typer.Option(None, "--output", "-o", help="Write output to a file."),
17612
17622
  trace: bool = typer.Option(False, "--trace", help="Include the Query Plan Runtime trace."),
sourcecode/mcp/server.py CHANGED
@@ -300,7 +300,9 @@ def _pack_mcp_projection(
300
300
  *,
301
301
  repo_path: str,
302
302
  compact: bool,
303
+ selected_components: list[str] | None = None,
303
304
  since: str | None = None,
305
+ pr: int | None = None,
304
306
  ) -> dict[str, Any]:
305
307
  """Cap a pack for MCP without dropping its decision or evidence identity."""
306
308
  # MCP adds adapter metadata; never mutate the canonical pack returned by
@@ -310,8 +312,12 @@ def _pack_mcp_projection(
310
312
  return result
311
313
  command = "ask pack assessment" if tool_name == "get_assessment_pack" else "ask pack gate"
312
314
  args = f"{command} <repo>"
315
+ if selected_components:
316
+ args += f" --only {','.join(selected_components)}"
313
317
  if since:
314
318
  args += f" --since {since}"
319
+ elif pr is not None:
320
+ args += f" --pr {pr}"
315
321
  result["mcp"] = {
316
322
  "schema_version": MCP_PACK_PROJECTION_SCHEMA,
317
323
  "compact": compact,
@@ -385,6 +391,7 @@ def get_assessment_pack(
385
391
  repo_path: str = ".",
386
392
  profile: str = "",
387
393
  deployment: list[str] | None = None,
394
+ only: list[str] | None = None,
388
395
  compact: bool = True,
389
396
  ) -> dict:
390
397
  """Modernization and Risk Assessment pack for agents.
@@ -398,6 +405,10 @@ def get_assessment_pack(
398
405
  ``deployment`` is repeatable and names the deployment artefact(s) used to
399
406
  resolve the active profile: Kubernetes, Compose, Dockerfile, WebLogic,
400
407
  dotenv or launch script. It cannot be combined with ``profile``.
408
+
409
+ ``only`` selects a bounded subset of assessment components using the same
410
+ validation and execution order as the CLI ``--only`` option. Omitted
411
+ components are recorded as non-covered in the pack evidence.
401
412
  """
402
413
  _raw = repo_path
403
414
  try:
@@ -414,6 +425,15 @@ def get_assessment_pack(
414
425
  INVALID_INPUT_CODE,
415
426
  expected="list[str]",
416
427
  )
428
+ if only is not None and (
429
+ not isinstance(only, list)
430
+ or any(not isinstance(item, str) or not item.strip() for item in only)
431
+ ):
432
+ return _err(
433
+ "only must be a list of non-empty component names",
434
+ INVALID_INPUT_CODE,
435
+ expected="list[str]",
436
+ )
417
437
  if profile.strip() and deployment:
418
438
  return _err(
419
439
  "profile and deployment cannot be combined",
@@ -424,16 +444,23 @@ def get_assessment_pack(
424
444
  path_err = _check_repo_path(repo_path)
425
445
  if path_err is not None:
426
446
  return path_err
427
- from sourcecode.packs import run_assessment
447
+ from sourcecode.packs import assessment_components, run_assessment
448
+
449
+ try:
450
+ selected_components = assessment_components(only)
451
+ except ValueError as exc:
452
+ return _err(str(exc), INVALID_INPUT_CODE, expected="Declared assessment components.")
428
453
 
429
454
  data = run_assessment(
430
455
  Path(repo_path),
431
456
  profile=profile.strip() or None,
432
457
  deployment=[Path(item) for item in (deployment or [])] or None,
433
458
  compact=compact,
459
+ selected_components=selected_components,
434
460
  )
435
461
  return _ok(_pack_mcp_projection(
436
462
  "get_assessment_pack", data, repo_path=repo_path, compact=compact,
463
+ selected_components=selected_components if only is not None else None,
437
464
  ))
438
465
  except Exception as exc:
439
466
  return _err(
@@ -446,6 +473,7 @@ def get_assessment_pack(
446
473
  def get_change_safety_gate(
447
474
  repo_path: str = ".",
448
475
  since: str = "",
476
+ pr: int | None = None,
449
477
  profile: str = "",
450
478
  allow_unverified: bool = False,
451
479
  compact: bool = True,
@@ -455,18 +483,32 @@ def get_change_safety_gate(
455
483
  Returns the structured ``PASS``, ``BLOCK`` or ``UNVERIFIED`` pack with its
456
484
  component evidence and manifest. The response is report-only for MCP: a
457
485
  blocking or unverified result is data the agent must inspect, not a tool
458
- transport error. ``since`` is required because the gate compares two states.
486
+ transport error. Exactly one of ``since`` or ``pr`` is required. ``pr``
487
+ resolves the GitHub pull request through the local ``gh`` CLI and requires
488
+ its base commit to exist locally.
459
489
  """
460
490
  _raw = repo_path
461
491
  try:
462
492
  if not isinstance(repo_path, str):
463
493
  return _err("repo_path must be a string", INVALID_INPUT_CODE)
464
- if not isinstance(since, str) or not since.strip():
494
+ if not isinstance(since, str):
465
495
  return _err(
466
- "since must be a non-empty git ref",
496
+ "since must be a string",
467
497
  INVALID_INPUT_CODE,
468
- hint="Pass since, for example `origin/main` or `HEAD~1`.",
469
- expected="Non-empty git ref.",
498
+ expected="A git ref string or a pull request number.",
499
+ )
500
+ if pr is not None and (not isinstance(pr, int) or isinstance(pr, bool) or pr <= 0):
501
+ return _err(
502
+ "pr must be a positive pull request number",
503
+ INVALID_INPUT_CODE,
504
+ expected="Positive integer.",
505
+ )
506
+ if bool(since.strip()) == (pr is not None):
507
+ return _err(
508
+ "exactly one of since or pr is required",
509
+ INVALID_INPUT_CODE,
510
+ hint="Pass since for a local ref, or pr for GitHub pull-request mode.",
511
+ expected="One non-empty git ref or one positive pull request number.",
470
512
  )
471
513
  if not isinstance(profile, str):
472
514
  return _err("profile must be a string", INVALID_INPUT_CODE)
@@ -476,16 +518,32 @@ def get_change_safety_gate(
476
518
  return path_err
477
519
  from sourcecode.packs import run_gate
478
520
 
521
+ comparison_ref = since.strip()
522
+ if pr is not None:
523
+ try:
524
+ from sourcecode.github_diff import pull_request_base_ref
525
+
526
+ comparison_ref, _description = pull_request_base_ref(repo_path, pr)
527
+ except Exception as exc:
528
+ return _err(
529
+ str(exc),
530
+ INVALID_INPUT_CODE,
531
+ hint="Ensure gh is installed/authenticated and the PR base commit is local.",
532
+ expected="A resolvable GitHub pull request with a local base commit.",
533
+ )
534
+
479
535
  data = run_gate(
480
536
  Path(repo_path),
481
- since=since.strip(),
537
+ since=comparison_ref,
538
+ pr=pr,
482
539
  profile=profile.strip() or None,
483
540
  allow_unverified=allow_unverified,
484
541
  compact=compact,
485
542
  )
486
543
  return _ok(_pack_mcp_projection(
487
544
  "get_change_safety_gate", data, repo_path=repo_path, compact=compact,
488
- since=since.strip(),
545
+ since=since.strip() or None,
546
+ pr=pr,
489
547
  ))
490
548
  except Exception as exc:
491
549
  return _err(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 5.8.31
3
+ Version: 5.8.32
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.8.31-blue)
62
+ ![Version](https://img.shields.io/badge/version-5.8.32-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
@@ -88,6 +88,8 @@ workflow-shaped packs for users who want one consumable result:
88
88
  ask pack assessment . --profile prod --output-dir .ask/packs/assessment
89
89
  ask pack gate . --since origin/main --output-dir .ask/packs/gate
90
90
  ask pack assessment . --format markdown -o assessment.md
91
+ ask pack assessment . --only risk,posture --output-dir .ask/packs/assessment
92
+ ask pack gate . --pr 123 --output-dir .ask/packs/gate
91
93
  ```
92
94
 
93
95
  For deployment-aware posture evidence, pass the artefacts that describe the
@@ -104,8 +106,17 @@ contract:
104
106
  ```bash
105
107
  ask pack gate . --since origin/main --format github-actions
106
108
  ask pack gate . --since origin/main --format gitlab
109
+ ask pack gate . --since origin/main --format sarif -o gate.sarif
107
110
  ```
108
111
 
112
+ `pack gate --pr NUMBER` uses the local `gh` CLI to resolve changed files and
113
+ the exact base commit; the base SHA must already exist locally. It does not
114
+ fetch or modify the repository. `pack assessment --only` runs named assessment
115
+ components and records omissions in the manifest. MCP's
116
+ `get_assessment_pack` accepts the same selection as `only: list[str]` and
117
+ returns the reproducible CLI command in its `mcp` projection. SARIF is a bounded
118
+ export of ASK-owned gate decisions, not a re-emission of third-party findings.
119
+
109
120
  `PASS`, `BLOCK` and `UNVERIFIED` are data decisions. The process exit code is
110
121
  the CI signal; `--allow-unverified` can change only that exit code, never the
111
122
  reported verdict. Every pack carries a manifest with component invocations,
@@ -177,18 +188,19 @@ set `ASK_MAX_RSS_MB=<megabytes>`; if the process exceeds it, ASK refuses the
177
188
  answer with `MEMORY_TOO_LARGE`, including the observed peak and limit. Leave it
178
189
  unset, or set it to `0`, to disable the ceiling explicitly.
179
190
 
180
- **Current performance status.** Release 5.8.31 retains the shared Canonical IR
191
+ **Current performance status.** Release 5.8.32 retains the shared Canonical IR
181
192
  path used by `validation` and now passes that same CIR into labelled `data-exposure`
182
193
  runs; the no-label path remains parse-free. These are implementation properties,
183
194
  not duration promises. A controlled external warm-path audit has opened performance
184
195
  and bounded-output regressions for this release; use `ask cache model <repo>` and
185
196
  `--progress stderr` for supervised runs, and consult the
186
- [active pack audit intake](docs/AUDIT-2026-08-26-EXTERNAL-5.8.28-PACK.md) before
197
+ [latest external audit intake](docs/AUDIT-2026-08-26-EXTERNAL-5.8.31.md) before
187
198
  treating a historical timing or bounded flag as a current guarantee.
188
199
 
189
- **What a warm actually covers.** `ask cache warm` runs the compact analysis: it rebuilds the
200
+ **What a warm actually covers.** `ask cache warm` rebuilds the declared root views and their
190
201
  shared structural layers (L1/L2 + the Repository Intelligence Snapshot + the shared Canonical
191
- IR) and the **compact view**. Pass `--agent` to warm the agent view as well. Deeper projections
202
+ IR). Pass `--views compact` or `--views compact,agent` to warm only selected views; without
203
+ `--views`, all declared views are warmed. Deeper projections
192
204
  are separate keys and are *not* covered by either — `--full`, `--env-map` and a raised `--depth`
193
205
  recompute on first use, as do most `prepare-context` tasks. Measured on a 3,342-file Spring
194
206
  monolith: `cache warm` 103s → `--compact --git-context` 1s (hit), but `--agent --full --env-map
@@ -210,7 +222,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
210
222
  # pip / pipx
211
223
  pipx install sourcecode # or: pip install sourcecode
212
224
 
213
- ask version # ask 5.8.31 — and, on a build that has aged,
225
+ ask version # ask 5.8.32 — and, on a build that has aged,
214
226
  # how many releases have probably shipped since
215
227
  ```
216
228
 
@@ -479,7 +491,7 @@ from it.
479
491
  | `plan` / `compare` / `delta` / `contract-diff` | supported | what to review for a change; candidates by measured cost; outcome of a change; public-contract break | no verdicts, measured cost only |
480
492
  | `validation` | supported | request-body validation coverage and gaps | |
481
493
  | `baseline capture\|diff` · `trend` | supported | versioned architectural metrics over time; `ask trend .` reads the series (a repository path or a baselines directory), `ask baseline diff .` compares the tree against its newest point | trend reporting, not gating. Baselines land in `.ask/baselines` **inside the repository** — the history travels with the code, not with a vendor; an audit that must not write passes `--dir`. `capture --auto` is the unattended form (one baseline per commit, never rewrites one, never fails the build) — automate it: [baseline-ci.yml](docs/baseline-ci.yml) |
482
- | `retrieve` | parked | typed knowledge queries over the model | |
494
+ | `retrieve` | parked | typed knowledge queries over the model | symbol-oriented queries accept `--target/-t`; domain aliases such as `--module/-m`, `--subsystem/-s` and `--endpoint/-e` remain supported |
483
495
  | `timeline` | experimental | since when a number moved, and in which commit window | walks the commit series and re-runs the shipped analyses (`posture`, `data-exposure`, `endpoints`, `spring-audit`) on a read-only materialisation of each sampled tree; publishes transitions, not a per-commit dump. A sample that could not be analysed is `null` with a reason, never 0, and a transition under sampling carries the window it could have happened in |
484
496
  | `regress` | supported | what moved between two payloads of the same command, and which declaration accounts for it | attributes each delta to a declaration the answers carry (`test_source_excluded`, `symbols_excluded`, `coverage.gaps`, `*_cap`, `waivers`); a delta nothing explains is `unattributed`. Refuses the comparison when `cache_layers`, `base_env` or the analyzer fingerprint differ |
485
497
  | `explain-endpoint` | supported | the derivation behind one route's verdict | six steps — match, declaration, handler, chain, profiles, verdict — each naming the authority that produced it and the file it can be checked against; a step that could not be derived is `undetermined` with the reason, never absent |
@@ -1,6 +1,6 @@
1
- sourcecode/__init__.py,sha256=x6huFekCWuzbMyWgV9DNW6WDTwRfZV3q9UlfspK-7AY,309
1
+ sourcecode/__init__.py,sha256=N1r9fCES7GZKl-MnDEPXkIXKvlci7HGDYyd9T2K3GrQ,309
2
2
  sourcecode/__main__.py,sha256=qDFVkobwsdZrX0B3stiRqsUNivVpybKO-egzAwCW4xw,165
3
- sourcecode/_build_commit.py,sha256=gOxdbVEG8QZSIEAPML8CaTzP3DaBaqHqkVEV25ceY4U,8740
3
+ sourcecode/_build_commit.py,sha256=zfltecl0ZxCjQsc4q7xcTp8qCwPBFSsHSPdUQeKA_u4,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
@@ -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=kA6mou1cf-9nQ90E2K9oGNTFplI2BReBcTPjPUcTDVs,869605
34
+ sourcecode/cli.py,sha256=F32dO1oD7NPdyS6LfkKQhnbjDfYj_VzJknBWjm8joVU,869765
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
@@ -221,7 +221,7 @@ sourcecode/mcp/dependency_import.py,sha256=wfvw1rmDE3n2mHDj-yHnCuy9HZ7TtPqsHG2BU
221
221
  sourcecode/mcp/orchestrator.py,sha256=RUzx2uRfwk-rnEy1RKeXjTBPfUaQiBldo-b2FryL6yI,36826
222
222
  sourcecode/mcp/registry.py,sha256=kydzpUGGKckWM_F_GeGkWG1Z_qU3R8mZSbBWYKtDewU,69326
223
223
  sourcecode/mcp/runner.py,sha256=dRvI0xS2wa8DH0diYjJiAoaGeVdtf389PekWwwh8wRI,3083
224
- sourcecode/mcp/server.py,sha256=rnalEjQ9vcuCiXFekJI4Llx5u9HaBAwXN903NunupP8,73562
224
+ sourcecode/mcp/server.py,sha256=L3xxLaG-bLe3Asr4ZESiEIYldhvKHkfpCMoucndvLvY,76070
225
225
  sourcecode/mcp/onboarding/__init__.py,sha256=sj2PWqEBmMc4zBNkomg89WtL0M6S7A9yb7_wAuSWNP4,66
226
226
  sourcecode/mcp/onboarding/applier.py,sha256=Sx9vHTaXr_M1Bs4uMjO7qa_a2_p4J9oz93oJsKQ7ds4,3298
227
227
  sourcecode/mcp/onboarding/backup.py,sha256=ihqGOR8QTX8HASRSEDyfFyXr5bkXrygPHamv4p9KTmk,1452
@@ -257,13 +257,13 @@ sourcecode/telemetry/consent.py,sha256=-Wb8BFGXEexOs8M0Eja7F-T6ZtLNPeRoZnHcHvlP7
257
257
  sourcecode/telemetry/events.py,sha256=l3Z2SQUO4_C2D2ItXOOdVNimAmHedUHnUxqYFTxnsAE,2900
258
258
  sourcecode/telemetry/filters.py,sha256=-lqT2oorECuqEIdeHb--7AZ6BCaUx0bya720a-Z5x6w,7335
259
259
  sourcecode/telemetry/transport.py,sha256=4gGHsq0WeY9VywEZXA3vUxykfiYnw9uuqfjAAec7F8o,1681
260
- sourcecode/_docs/DEFECT-LEDGER.md,sha256=K5k1J1JDBBeXnB50o9KxIFnFJRHBillTJNoKoiQmLXY,1108377
260
+ sourcecode/_docs/DEFECT-LEDGER.md,sha256=Jux3d0qM_L58-tJZwX6ret7HTK9R7QAVDmfohZfKZUs,1109556
261
261
  sourcecode/_docs/LICENSE,sha256=23-fk61oSWGVmkWyka-FIM0rhAPM2hcYHnsaridL8Uo,1859
262
262
  sourcecode/_docs/NOTICE,sha256=Br-AA8Y3iJo1WXa5uP8QBpzqI5nDu3iGLbFyvDt3BOs,321
263
- sourcecode/_docs/USER_GUIDE.md,sha256=w8YGMcBHQIRLwnFzqodOZhvP5eF8pfYMtw5FyUlRpNk,93284
264
- sourcecode-5.8.31.dist-info/METADATA,sha256=8XTeIYslvJubUEPmt2L6EObS9m9aw4BVKL6BfBDYN0w,55428
265
- sourcecode-5.8.31.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
266
- sourcecode-5.8.31.dist-info/entry_points.txt,sha256=-JEAdChrK5We51kZcb7OaDcyil-dHBjBPL-NhuO-QY8,89
267
- sourcecode-5.8.31.dist-info/licenses/LICENSE,sha256=23-fk61oSWGVmkWyka-FIM0rhAPM2hcYHnsaridL8Uo,1859
268
- sourcecode-5.8.31.dist-info/licenses/NOTICE,sha256=Br-AA8Y3iJo1WXa5uP8QBpzqI5nDu3iGLbFyvDt3BOs,321
269
- sourcecode-5.8.31.dist-info/RECORD,,
263
+ sourcecode/_docs/USER_GUIDE.md,sha256=O5lO0REhpaaC-dfwwkHtfdr4_zrEnXO4eXhBYA00ufI,94962
264
+ sourcecode-5.8.32.dist-info/METADATA,sha256=nWMOqw-qy7BSXhnuO_CWY_xVz_du-216HYbPfE9nvXs,56341
265
+ sourcecode-5.8.32.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
266
+ sourcecode-5.8.32.dist-info/entry_points.txt,sha256=-JEAdChrK5We51kZcb7OaDcyil-dHBjBPL-NhuO-QY8,89
267
+ sourcecode-5.8.32.dist-info/licenses/LICENSE,sha256=23-fk61oSWGVmkWyka-FIM0rhAPM2hcYHnsaridL8Uo,1859
268
+ sourcecode-5.8.32.dist-info/licenses/NOTICE,sha256=Br-AA8Y3iJo1WXa5uP8QBpzqI5nDu3iGLbFyvDt3BOs,321
269
+ sourcecode-5.8.32.dist-info/RECORD,,