sourcecode 5.1.0__py3-none-any.whl → 5.2.0__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/architectural_delta.py +57 -0
- sourcecode/cache_model.py +92 -29
- sourcecode/cli.py +110 -32
- sourcecode/contract_diff.py +27 -0
- sourcecode/execution_plan.py +41 -2
- sourcecode/perf.py +102 -5
- sourcecode/verify_edit.py +70 -24
- {sourcecode-5.1.0.dist-info → sourcecode-5.2.0.dist-info}/METADATA +3 -3
- {sourcecode-5.1.0.dist-info → sourcecode-5.2.0.dist-info}/RECORD +13 -13
- {sourcecode-5.1.0.dist-info → sourcecode-5.2.0.dist-info}/WHEEL +0 -0
- {sourcecode-5.1.0.dist-info → sourcecode-5.2.0.dist-info}/entry_points.txt +0 -0
- {sourcecode-5.1.0.dist-info → sourcecode-5.2.0.dist-info}/licenses/LICENSE +0 -0
sourcecode/__init__.py
CHANGED
|
@@ -235,6 +235,63 @@ def diff_metrics(base: ArchMetrics, head: ArchMetrics) -> dict:
|
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
|
|
238
|
+
#: The one sentence both identical-state payloads are derived from (C3-107).
|
|
239
|
+
#: It is an argument, not an assumption, and it rests on a property this product
|
|
240
|
+
#: publishes and asserts every release: the analysis is a pure function of the
|
|
241
|
+
#: tree state, byte-identical across eleven field rounds and two major jumps.
|
|
242
|
+
IDENTICAL_STATE_BASIS = (
|
|
243
|
+
"The two states are one tree, and the analysis is a deterministic function of "
|
|
244
|
+
"the tree state, so every delta is zero without reading the tree. What is "
|
|
245
|
+
"*not* claimed is anything about the tree itself: the per-side totals were "
|
|
246
|
+
"not measured and are `null`, never 0 — pass two different states, or run "
|
|
247
|
+
"`ask <repo>` on one of them, to measure the repository rather than the diff."
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def identical_state_delta() -> dict:
|
|
252
|
+
"""The `architectural-delta-v1` payload for two states that are one state.
|
|
253
|
+
|
|
254
|
+
C3-107 closed the second build; the eleventh round measured what was left —
|
|
255
|
+
`delta` 24,6 s and `contract-diff` 59,9 s to conclude that a tree does not
|
|
256
|
+
differ from itself, from a purged cache. Building one side to diff it against
|
|
257
|
+
itself is a measurement of the *repository*, and this command's answer is the
|
|
258
|
+
*difference*: with one tree state the difference is empty by construction.
|
|
259
|
+
|
|
260
|
+
So the deltas are published as the zeroes they provably are, and every figure
|
|
261
|
+
that would require an analysis is `null` with the reason attached — the rule
|
|
262
|
+
this product applies everywhere else (an axis that was not measured is
|
|
263
|
+
`unknown`, never `0`).
|
|
264
|
+
"""
|
|
265
|
+
empty_counts = {"base": None, "head": None, "delta": 0}
|
|
266
|
+
return {
|
|
267
|
+
"schema": ARCH_DELTA_SCHEMA,
|
|
268
|
+
"base_cir_hash": None,
|
|
269
|
+
"head_cir_hash": None,
|
|
270
|
+
"totals": {
|
|
271
|
+
"files": dict(empty_counts),
|
|
272
|
+
"symbols": dict(empty_counts),
|
|
273
|
+
"endpoints": dict(empty_counts),
|
|
274
|
+
"dependency_edges": dict(empty_counts),
|
|
275
|
+
"import_cycles": dict(empty_counts),
|
|
276
|
+
},
|
|
277
|
+
"endpoint_surface": {
|
|
278
|
+
"added_count": 0, "removed_count": 0, "added": [], "removed": [],
|
|
279
|
+
},
|
|
280
|
+
"fan_in_shifts": {"changed_count": 0, "shifts": []},
|
|
281
|
+
"import_cycle_shifts": {
|
|
282
|
+
"added_count": 0, "removed_count": 0, "added": [], "removed": [],
|
|
283
|
+
},
|
|
284
|
+
"blast_radius_shifts": {
|
|
285
|
+
"scope": "fan_in_shift_symbols", "changed_count": 0, "shifts": [],
|
|
286
|
+
},
|
|
287
|
+
"analysis": {"performed": False, "basis": IDENTICAL_STATE_BASIS},
|
|
288
|
+
"provenance": (
|
|
289
|
+
"architectural_delta (D1), identical states: no repository was read. "
|
|
290
|
+
+ IDENTICAL_STATE_BASIS
|
|
291
|
+
),
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
|
|
238
295
|
def _transitive_reach(fqn: str, reverse_graph: dict, node_cap: int) -> int:
|
|
239
296
|
"""Size of the transitive reverse-dependency set of `fqn` (its blast radius).
|
|
240
297
|
|
sourcecode/cache_model.py
CHANGED
|
@@ -141,10 +141,11 @@ REFERENCE_JAVA_FILES = 2000
|
|
|
141
141
|
REFERENCE_MEASURED_VERSION = "3.2.2"
|
|
142
142
|
|
|
143
143
|
#: The other end of the measured range, and the reason this module publishes a
|
|
144
|
-
#: *class* rather than a projected duration (C4-19). Field evaluation #
|
|
145
|
-
#: Windows 11 / PowerShell 5.1 / pipx / Python 3.10
|
|
146
|
-
#: 3 342-file repository ran **
|
|
147
|
-
#: 2 000-file reference, for a repository 1,7× the size
|
|
144
|
+
#: *class* rather than a projected duration (C4-19). Field evaluation #26, on
|
|
145
|
+
#: Windows 11 / PowerShell 5.1 / pipx / Python 3.10, every cache purged first:
|
|
146
|
+
#: `spring-audit` on a 3 342-file repository ran **31,0 s** — the same command
|
|
147
|
+
#: takes 8.8 s on the 2 000-file reference, for a repository 1,7× the size, and it
|
|
148
|
+
#: ran 8,4 s on the same subject two releases earlier.
|
|
148
149
|
#:
|
|
149
150
|
#: **The refusal to project stands, and this evaluation strengthened it** (C3-97).
|
|
150
151
|
#: For eight releases the pair of anchors said *cost does not track file count*;
|
|
@@ -159,9 +160,11 @@ REFERENCE_MEASURED_VERSION = "3.2.2"
|
|
|
159
160
|
#: each was measured on**, and how to run it.
|
|
160
161
|
#:
|
|
161
162
|
#: History of the anchor, kept because it is the measurement C3-76 exists for:
|
|
162
|
-
#: 408 s (#13) → 2 351 s (#16, C3-72) → 8,4 s (#22, C3-97)
|
|
163
|
-
#: quoted as an operational anchor for four releases after
|
|
164
|
-
#: it, and told operators to detach commands that finish in
|
|
163
|
+
#: 408 s (#13) → 2 351 s (#16, C3-72) → 8,4 s (#22, C3-97) → 31,0 s (#26, C3-110).
|
|
164
|
+
#: The middle figure was quoted as an operational anchor for four releases after
|
|
165
|
+
#: the build that produced it, and told operators to detach commands that finish in
|
|
166
|
+
#: seconds; the last one moved 3,7× in two releases with byte-identical payloads,
|
|
167
|
+
#: which is the movement the release gate exists to catch and did not.
|
|
165
168
|
#:
|
|
166
169
|
#: ⚠ `FIELD_ANCHOR`, `FIELD_ANCHOR_SECONDS` and `FIELD_ANCHOR_MEASURED_VERSION`
|
|
167
170
|
#: are **derived from the `spring-audit` row**, below `COMMANDS`. They used to be
|
|
@@ -242,12 +245,12 @@ COMMANDS: tuple[CommandCache, ...] = (
|
|
|
242
245
|
"71,7 s again for `--agent` on the state it had just analysed (C3-103).",
|
|
243
246
|
"--compact 13.3 s cold → 0.3 s warm (cold re-measured on 3.7.0: was 19.3 s, C3-6); "
|
|
244
247
|
"--agent --full --env-map --depth 20 34.7 s → 33.9 s (no gain)", analysis_class="repo-wide", cold_seconds=13.3, warm_seconds=0.3,
|
|
245
|
-
field_seconds=
|
|
248
|
+
field_seconds=166.7, field_cache_state="cold", field_measured_version="5.1.0"),
|
|
246
249
|
CommandCache("posture", ("cir", "parse"), "shared", False,
|
|
247
250
|
"Resolves the conditional bean graph on every run, over the shared CIR a warm "
|
|
248
251
|
"builds — the parse it used to repeat for itself. `--diff` compares two profile "
|
|
249
252
|
"sets over that one IR, so the second side costs the resolution only.",
|
|
250
|
-
"10.1 s → 1.6 s", analysis_class="repo-wide", cold_seconds=10.1, warm_seconds=1.6, field_seconds=8.
|
|
253
|
+
"10.1 s → 1.6 s", analysis_class="repo-wide", cold_seconds=10.1, warm_seconds=1.6, field_seconds=8.3, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
251
254
|
CommandCache("risk", ("cir", "parse"), "shared", False,
|
|
252
255
|
"Composes what the audit, impact-chain and the posture already answer, so it "
|
|
253
256
|
"pays each of their costs once over the shared CIR a warm builds — one parse "
|
|
@@ -255,7 +258,7 @@ COMMANDS: tuple[CommandCache, ...] = (
|
|
|
255
258
|
"within the run.",
|
|
256
259
|
"not measured on the battery yet — the composition is bounded by the "
|
|
257
260
|
"`spring-audit` + `impact-chain` costs listed here, not by new analysis",
|
|
258
|
-
analysis_class="deep", field_seconds=
|
|
261
|
+
analysis_class="deep", field_seconds=77.2, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
259
262
|
CommandCache("enrich", ("cir", "parse"), "shared", False,
|
|
260
263
|
"Runs the same composition as `risk` over the repository, then joins a SARIF "
|
|
261
264
|
"log to it. Reading the log is negligible; everything a warm helps with is the "
|
|
@@ -280,30 +283,31 @@ COMMANDS: tuple[CommandCache, ...] = (
|
|
|
280
283
|
"builds. Cost scales with the number of declared types, not with the "
|
|
281
284
|
"size of the label.",
|
|
282
285
|
"not measured on the battery yet — one `impact-chain` traversal per "
|
|
283
|
-
"declared seed type over a CIR the warm already paid for", analysis_class="repo-wide"
|
|
286
|
+
"declared seed type over a CIR the warm already paid for", analysis_class="repo-wide",
|
|
287
|
+
field_seconds=28.9, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
284
288
|
CommandCache("endpoints", ("ris", "parse"), "shared", False,
|
|
285
289
|
"Recomputes the endpoint surface on every run, over a parse a warm has already "
|
|
286
290
|
"paid for. Until 3.7.0 the extractor parsed every file itself instead of reading "
|
|
287
291
|
"the shared parse cache, and a warm measurably bought it nothing (C3-6).",
|
|
288
|
-
"3.3 s → 1.4 s (re-measured on 3.7.0; was 2.8 s → 2.9 s)", analysis_class="repo-wide", cold_seconds=3.3, warm_seconds=1.4, field_seconds=
|
|
292
|
+
"3.3 s → 1.4 s (re-measured on 3.7.0; was 2.8 s → 2.9 s)", analysis_class="repo-wide", cold_seconds=3.3, warm_seconds=1.4, field_seconds=5.6, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
289
293
|
CommandCache("spring-audit", ("ris", "parse"), "shared", False,
|
|
290
294
|
"Recomputes every run, but over a parse a warm has already paid for.",
|
|
291
|
-
"8.8 s → 3.7 s", analysis_class="repo-wide", cold_seconds=8.8, warm_seconds=3.7, field_seconds=
|
|
295
|
+
"8.8 s → 3.7 s", analysis_class="repo-wide", cold_seconds=8.8, warm_seconds=3.7, field_seconds=31.0, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
292
296
|
CommandCache("migrate-check", ("cir",), "none", False,
|
|
293
297
|
"Computes its own inventory and shares nothing a warm builds. Only `--blast-radius` "
|
|
294
298
|
"reuses the shared CIR.",
|
|
295
|
-
"4.8 s → 4.8 s", analysis_class="repo-wide", cold_seconds=4.8, warm_seconds=4.8, field_seconds=
|
|
299
|
+
"4.8 s → 4.8 s", analysis_class="repo-wide", cold_seconds=4.8, warm_seconds=4.8, field_seconds=11.3, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
296
300
|
CommandCache("impact-chain", ("cir", "parse"), "shared", False,
|
|
297
301
|
"The CIR is the expensive half — this is where a warm pays most.",
|
|
298
302
|
"9.9 s → 1.7 s", analysis_class="core", cold_seconds=9.9, warm_seconds=1.7,
|
|
299
|
-
field_seconds=
|
|
303
|
+
field_seconds=16.1, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
300
304
|
CommandCache("impact", ("parse",), "shared", False, "", "4.9 s → 2.8 s", analysis_class="core", cold_seconds=4.9, warm_seconds=2.8,
|
|
301
305
|
field_seconds=7.7, field_measured_version="4.18.0"),
|
|
302
306
|
CommandCache("pr-impact", ("parse",), "shared", False,
|
|
303
307
|
"Diff-dependent: the answer itself is never stored. What it costs follows the "
|
|
304
308
|
"diff, not the repository: 12,5 s on an ordinary one and 11,8 s on a diff of "
|
|
305
309
|
"security configuration, measured at field scale.", analysis_class="core",
|
|
306
|
-
field_seconds=
|
|
310
|
+
field_seconds=25.7, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
307
311
|
CommandCache("verify", (), "none", False, "Runs the contracts against a fresh reading.", analysis_class="core"),
|
|
308
312
|
CommandCache("verify-edit", ("parse",), "shared", True,
|
|
309
313
|
"Built for the edit loop: the parse cache is what keeps an unchanged file out of the "
|
|
@@ -311,15 +315,17 @@ COMMANDS: tuple[CommandCache, ...] = (
|
|
|
311
315
|
"yet: eval #23 measured 76,6 s on a tree with no edits, because the HEAD side is "
|
|
312
316
|
"still built in a throwaway worktree instead of reusing the shared CIR (C3-102).",
|
|
313
317
|
"14.6 s → 9.6 s → 5.6 s on repeat", analysis_class="repo-wide", cold_seconds=14.6, warm_seconds=9.6,
|
|
314
|
-
field_seconds=
|
|
318
|
+
field_seconds=119.5, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
315
319
|
CommandCache("review-pr", ("cir",), "none", False,
|
|
316
320
|
"Diff-dependent, and it reuses the CIR only if one exists. On a small diff, loading "
|
|
317
321
|
"the warmed CIR costs more than the work it saves.",
|
|
318
322
|
"1.1 s → 2.3 s (slower)", analysis_class="core", cold_seconds=1.1, warm_seconds=2.3),
|
|
319
323
|
CommandCache("plan", ("parse",), "shared", False, "", "9.3 s → 3.8 s", analysis_class="core", cold_seconds=9.3, warm_seconds=3.8),
|
|
320
324
|
CommandCache("compare", ("parse",), "shared", False, "", analysis_class="core"),
|
|
321
|
-
CommandCache("delta", (), "none", False, "Analyses two states — two checkouts, or two refs materialised into temporary trees; neither is the tree the cache describes.", analysis_class="repo-wide"
|
|
322
|
-
|
|
325
|
+
CommandCache("delta", (), "none", False, "Analyses two states — two checkouts, or two refs materialised into temporary trees; neither is the tree the cache describes.", analysis_class="repo-wide",
|
|
326
|
+
field_seconds=24.6, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
327
|
+
CommandCache("contract-diff", (), "none", False, "Analyses two states (checkouts or refs); neither is the tree the cache describes.", analysis_class="repo-wide",
|
|
328
|
+
field_seconds=59.9, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
323
329
|
CommandCache("fix-bug", ("task",), "none", True,
|
|
324
330
|
"Shorthand for `prepare-context fix-bug`; caches its own answer, which a warm never runs.", analysis_class="core"),
|
|
325
331
|
CommandCache("rename-class", (), "none", False, "", analysis_class="core"),
|
|
@@ -341,26 +347,27 @@ COMMANDS: tuple[CommandCache, ...] = (
|
|
|
341
347
|
"no answer hit", analysis_class="repo-wide", cold_seconds=6.5, warm_seconds=0.3),
|
|
342
348
|
CommandCache("explain", ("cir",), "shared", False, "Serves from the shared CIR a warm builds.",
|
|
343
349
|
"9.8 s → 1.6 s", analysis_class="core", cold_seconds=9.8, warm_seconds=1.6,
|
|
344
|
-
field_seconds=
|
|
350
|
+
field_seconds=6.3, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
345
351
|
CommandCache("export", ("parse",), "shared", False, "", "8.8 s → 3.7 s", analysis_class="repo-wide", cold_seconds=8.8, warm_seconds=3.7),
|
|
346
352
|
CommandCache("repo-ir", ("parse",), "shared", False,
|
|
347
353
|
"Carried as *did not finish* from 4.10.4 until eval #23 ran it at field size in "
|
|
348
354
|
"9,8 s — a run that did not finish once is not a command that cannot finish "
|
|
349
355
|
"(C3-100, and the same correction `modernize` needed).",
|
|
350
356
|
"5.1 s → 2.9 s", analysis_class="repo-wide", cold_seconds=5.1, warm_seconds=2.9,
|
|
351
|
-
field_seconds=
|
|
357
|
+
field_seconds=19.2, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
352
358
|
CommandCache("validation", ("parse",), "shared", False, "", "11.6 s → 6.4 s", analysis_class="repo-wide", cold_seconds=11.6, warm_seconds=6.4,
|
|
353
|
-
field_seconds=
|
|
359
|
+
field_seconds=39.5, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
354
360
|
CommandCache("modernize", ("parse",), "shared", False,
|
|
355
361
|
"Blocked in the session that recorded C3-53 and measured since: a run that did "
|
|
356
362
|
"not finish once is not a command that cannot finish.",
|
|
357
363
|
"5.2 s → 3.0 s", analysis_class="repo-wide", cold_seconds=5.2, warm_seconds=3.0,
|
|
358
|
-
field_seconds=
|
|
364
|
+
field_seconds=17.1, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
359
365
|
CommandCache("chunk-file", (), "none", False, "Reads one file; nothing to cache.", analysis_class="core"),
|
|
360
366
|
CommandCache("cold-start", ("ris",), "answer", True,
|
|
361
367
|
"Reads the RIS a warm rebuilds — that is all it does. Without one it answers "
|
|
362
368
|
"`no_ris` instead of a snapshot.",
|
|
363
|
-
"0.2 s either way", analysis_class="core", cold_seconds=0.2, warm_seconds=0.2
|
|
369
|
+
"0.2 s either way", analysis_class="core", cold_seconds=0.2, warm_seconds=0.2,
|
|
370
|
+
field_seconds=0.4, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
364
371
|
CommandCache("trend", (), "none", False, "Reads stored baseline artifacts from disk; analyses no source, so no cache layer applies. Same command as `baseline trend`.", analysis_class="none"),
|
|
365
372
|
CommandCache("baseline", ("parse",), "shared", False,
|
|
366
373
|
"`capture`/`diff`/`trend` over architectural metrics. The field figure is `capture`, "
|
|
@@ -405,13 +412,15 @@ def _row(command: str) -> "CommandCache":
|
|
|
405
412
|
|
|
406
413
|
#: The headline anchor, read off the table rather than written twice (C3-100).
|
|
407
414
|
#: `spring-audit` is the command the whole series measured — 408 s (#13), 2 351 s
|
|
408
|
-
#: (#16), 8,4 s (#22) — so it is the row the front page quotes, and
|
|
409
|
-
#: means reading it, not copying it.
|
|
415
|
+
#: (#16), 8,4 s (#22), 31,0 s (#26) — so it is the row the front page quotes, and
|
|
416
|
+
#: quoting it means reading it, not copying it. The figure moving *up* between two
|
|
417
|
+
#: rounds with byte-identical payloads is the reason C3-110 exists: nothing in this
|
|
418
|
+
#: repository measured the direction, and the anchor is the only place it shows.
|
|
410
419
|
_FIELD_ANCHOR_ROW = _row("spring-audit")
|
|
411
420
|
FIELD_ANCHOR_SECONDS = _FIELD_ANCHOR_ROW.field_seconds
|
|
412
421
|
FIELD_ANCHOR_MEASURED_VERSION = _FIELD_ANCHOR_ROW.field_measured_version
|
|
413
422
|
FIELD_ANCHOR = (
|
|
414
|
-
f"field evaluation #
|
|
423
|
+
f"field evaluation #26: spring-audit on {_thousands(FIELD_ANCHOR_JAVA_FILES)} "
|
|
415
424
|
f"Java files took {FIELD_ANCHOR_SECONDS:g} s (Windows, pipx, "
|
|
416
425
|
f"{_FIELD_ANCHOR_ROW.field_cache_state} cache) against "
|
|
417
426
|
f"{_FIELD_ANCHOR_ROW.cold_seconds:g} s on the "
|
|
@@ -532,6 +541,37 @@ def field_anchor_note(row: "Optional[CommandCache]") -> "Optional[str]":
|
|
|
532
541
|
return f"on {measured_on}"
|
|
533
542
|
|
|
534
543
|
|
|
544
|
+
def field_anchor_currency_clause(row: "Optional[CommandCache]") -> "Optional[str]":
|
|
545
|
+
"""The same fact as :func:`field_anchor_note`, said where it is *acted on* (C3-110).
|
|
546
|
+
|
|
547
|
+
C3-109 made every field figure carry its build, and the eleventh round confirms
|
|
548
|
+
the label is read and believed — and then reports the gap it does not close:
|
|
549
|
+
`spring-audit` publishes *"8,4 s … (4.18.0)"* while the same command measures
|
|
550
|
+
31,0 s on the build the reader is running. `(on 4.18.0)` is the right label for
|
|
551
|
+
a **row in a table**, where the reader is comparing figures; it is not enough
|
|
552
|
+
on a line that tells somebody how to run something, because there the figure is
|
|
553
|
+
being used as advice about the build in hand.
|
|
554
|
+
|
|
555
|
+
So the same fact gets a longer form for the surfaces that advise: the build,
|
|
556
|
+
and the admission that nothing has re-measured it here. That admission is the
|
|
557
|
+
registry this product applies everywhere else (`counts_are_floor`,
|
|
558
|
+
`unchanged_for`, `confidence_basis`) and the one place it had not applied to
|
|
559
|
+
itself.
|
|
560
|
+
|
|
561
|
+
``None`` when the figure was taken on the running build — there is nothing to
|
|
562
|
+
admit — or when there is no figure at all.
|
|
563
|
+
"""
|
|
564
|
+
if row is None or (row.field_seconds is None and not row.field_blocked):
|
|
565
|
+
return None
|
|
566
|
+
from sourcecode import __version__
|
|
567
|
+
|
|
568
|
+
measured_on = row.field_measured_version
|
|
569
|
+
if measured_on == __version__:
|
|
570
|
+
return None
|
|
571
|
+
where = f"measured on {measured_on}" if measured_on else "build not recorded"
|
|
572
|
+
return f"{where}; this build has not been re-measured at that scale"
|
|
573
|
+
|
|
574
|
+
|
|
535
575
|
def cost_sentence() -> str:
|
|
536
576
|
"""The one paragraph the front page says about cost, derived here (CL-21).
|
|
537
577
|
|
|
@@ -544,15 +584,38 @@ def cost_sentence() -> str:
|
|
|
544
584
|
with. It is generated from the anchors instead, so refreshing them refreshes
|
|
545
585
|
the prose.
|
|
546
586
|
"""
|
|
587
|
+
from sourcecode import __version__
|
|
588
|
+
|
|
547
589
|
audit = next((r for r in COMMANDS if r.command == "spring-audit"), None)
|
|
548
590
|
seconds = FIELD_ANCHOR_SECONDS if audit is None or audit.field_seconds is None else audit.field_seconds
|
|
591
|
+
# C3-110: the figure is history the moment it is published, and this sentence
|
|
592
|
+
# is the surface a reader budgets against. The field measured 31,0 s where this
|
|
593
|
+
# line said 8,4 s, and the line was not wrong — it named 4.18.0 — it just left
|
|
594
|
+
# the reader to notice that 4.18.0 is not the build they are running. Said
|
|
595
|
+
# outright, and paired with the one figure this project *can* refresh: the gate
|
|
596
|
+
# measurement of the build in hand, when there is one.
|
|
597
|
+
stale = (
|
|
598
|
+
""
|
|
599
|
+
if FIELD_ANCHOR_MEASURED_VERSION == __version__
|
|
600
|
+
else f", and {__version__} has not been re-measured at that scale"
|
|
601
|
+
)
|
|
602
|
+
gate = ""
|
|
603
|
+
_gate_cell = gate_anchor("spring-audit")
|
|
604
|
+
_gate_state = gate_currency()
|
|
605
|
+
if _gate_cell and _gate_state.get("current"):
|
|
606
|
+
gate = (
|
|
607
|
+
f" On this build the release gate measured the same command at "
|
|
608
|
+
f"{_gate_cell['seconds']:g} s on a "
|
|
609
|
+
f"{_thousands(int(_gate_cell['java_files']))}-file repository "
|
|
610
|
+
f"({_gate_cell['cache_state']} cache, {_gate_cell['host_class']})."
|
|
611
|
+
)
|
|
549
612
|
return (
|
|
550
613
|
f"Cost tracks the command class and the build, not the file count: "
|
|
551
614
|
f"per-symbol queries are the fast path, inventory commands scale with "
|
|
552
615
|
f"files, and a repository-wide audit measured {seconds:g} s on a "
|
|
553
616
|
f"{_thousands(FIELD_ANCHOR_JAVA_FILES)}-file repository "
|
|
554
|
-
f"({FIELD_ANCHOR_MEASURED_VERSION}). `ask cache model` prints
|
|
555
|
-
f"and the build behind it for every command; "
|
|
617
|
+
f"({FIELD_ANCHOR_MEASURED_VERSION}{stale}).{gate} `ask cache model` prints "
|
|
618
|
+
f"the figure and the build behind it for every command; "
|
|
556
619
|
f"ASK_MAX_ANALYSIS_SECONDS/ASK_PROGRESS bound and narrate a run where CI "
|
|
557
620
|
f"wants an explicit budget."
|
|
558
621
|
)
|
sourcecode/cli.py
CHANGED
|
@@ -403,7 +403,7 @@ def _start_here_block(scope: "Optional[Any]" = None) -> str:
|
|
|
403
403
|
not would be worse than the one this replaces.
|
|
404
404
|
"""
|
|
405
405
|
from sourcecode.execution_plan import (
|
|
406
|
-
BUCKET_ORDER, BUCKET_TITLE, DETACH, RUNS_NOW, UNKNOWN, plan,
|
|
406
|
+
BUCKET_ORDER, BUCKET_TITLE, BUDGETED, DETACH, RUNS_NOW, UNKNOWN, plan,
|
|
407
407
|
)
|
|
408
408
|
|
|
409
409
|
if scope is None or not scope.measured:
|
|
@@ -430,7 +430,7 @@ def _start_here_block(scope: "Optional[Any]" = None) -> str:
|
|
|
430
430
|
" [dim]…each of these answers into a file and survives the shell:"
|
|
431
431
|
" add --output <file> --detach[/dim]"
|
|
432
432
|
)
|
|
433
|
-
if not (grouped.get(RUNS_NOW) or grouped.get(UNKNOWN)):
|
|
433
|
+
if not (grouped.get(RUNS_NOW) or grouped.get(BUDGETED) or grouped.get(UNKNOWN)):
|
|
434
434
|
lines.append(
|
|
435
435
|
" [dim]Nothing here runs in seconds on a repository this size. "
|
|
436
436
|
"`ask cache warm .` first, or start with `ask endpoints . -o endpoints.json`.[/dim]"
|
|
@@ -2559,6 +2559,20 @@ _IR_BYTES_PER_FILE_HIGH: int = 30_300
|
|
|
2559
2559
|
_IR_BYTES_PER_FILE_SAMPLES: int = 5
|
|
2560
2560
|
_IR_SIZE_WARN_MB: int = 10 # advise above this; below it the write is not worth a sentence
|
|
2561
2561
|
|
|
2562
|
+
#: **C3-111.** The ceiling on the `-o` path, which had none. `--output FILE skips
|
|
2563
|
+
#: the payload budget entirely` is right about a *budget* — a file has no context
|
|
2564
|
+
#: window — and it was read as *no limit of any kind*: the field's run wrote
|
|
2565
|
+
#: **101 254 852 B**, byte-identical across three releases, with no line anywhere,
|
|
2566
|
+
#: because the pre-build band travels through `_notice`, which is silent off-TTY
|
|
2567
|
+
#: by contract (C3-26) and every `-o` run is a scripted one.
|
|
2568
|
+
#:
|
|
2569
|
+
#: 50 MB is where a projection or compression stops being optional: nothing in
|
|
2570
|
+
#: this catalogue reads a file that size in one piece, and `--gzip` cuts it by
|
|
2571
|
+
#: ~70-80 %. The guard fires *before* the build, so refusing costs the reader a
|
|
2572
|
+
#: third of a second rather than the whole analysis, and `--force` keeps the door
|
|
2573
|
+
#: open for somebody who means it.
|
|
2574
|
+
_IR_FILE_CEILING_MB: int = 50
|
|
2575
|
+
|
|
2562
2576
|
#: What `--no-cache` means on a subcommand (C3-5). The old text — "this command
|
|
2563
2577
|
#: always reads fresh source (no snapshot cache)" — was false: `cache model`, the
|
|
2564
2578
|
#: authority, records these commands reading the `ris`, `cir` and `parse` layers.
|
|
@@ -2579,6 +2593,21 @@ _NO_CACHE_SUBCOMMAND_HELP = (
|
|
|
2579
2593
|
)
|
|
2580
2594
|
|
|
2581
2595
|
|
|
2596
|
+
def _ir_size_estimate_mb(file_count: int) -> "tuple[float, float, float]":
|
|
2597
|
+
"""The `repo-ir` size band for *file_count*, as ``(low, high, midpoint)`` MB.
|
|
2598
|
+
|
|
2599
|
+
One authority for the estimate (C3-111): the advisory printed it and the
|
|
2600
|
+
guard needed it, and two derivations of one band drift the way the band and
|
|
2601
|
+
the field's measurement drifted in C3-105. The midpoint is what the ceiling
|
|
2602
|
+
is compared against — the low end would have let the field's 101 MB through
|
|
2603
|
+
(34 MB estimated) and the high end refuses repositories whose real output is
|
|
2604
|
+
half of it.
|
|
2605
|
+
"""
|
|
2606
|
+
low = file_count * _IR_BYTES_PER_FILE_LOW / (1024 * 1024)
|
|
2607
|
+
high = file_count * _IR_BYTES_PER_FILE_HIGH / (1024 * 1024)
|
|
2608
|
+
return low, high, (low + high) / 2
|
|
2609
|
+
|
|
2610
|
+
|
|
2582
2611
|
def _ir_size_advisory_message(file_count: int) -> "Optional[str]":
|
|
2583
2612
|
"""Return the `repo-ir` output-size advisory, or ``None`` below the threshold.
|
|
2584
2613
|
|
|
@@ -2604,8 +2633,7 @@ def _ir_size_advisory_message(file_count: int) -> "Optional[str]":
|
|
|
2604
2633
|
Pure and TTY-agnostic: the caller owns the terminal gate, so this never
|
|
2605
2634
|
reaches stdout or a pipeline (C3-26).
|
|
2606
2635
|
"""
|
|
2607
|
-
est_low_mb
|
|
2608
|
-
est_high_mb = file_count * _IR_BYTES_PER_FILE_HIGH / (1024 * 1024)
|
|
2636
|
+
est_low_mb, est_high_mb, _ = _ir_size_estimate_mb(file_count)
|
|
2609
2637
|
if est_high_mb <= _IR_SIZE_WARN_MB:
|
|
2610
2638
|
return None
|
|
2611
2639
|
return (
|
|
@@ -5809,6 +5837,39 @@ def repo_ir_cmd(
|
|
|
5809
5837
|
if _notice_msg:
|
|
5810
5838
|
_notice(_notice_msg)
|
|
5811
5839
|
|
|
5840
|
+
# C3-111: and the notice above is the half that does not reach a script.
|
|
5841
|
+
# `-o` is a scripted run by construction, `_notice` is silent off-TTY by
|
|
5842
|
+
# contract (C3-26), and the write had no ceiling of any kind — which is
|
|
5843
|
+
# how 101 254 852 B arrived three releases running with no line anywhere.
|
|
5844
|
+
# An error envelope reaches every consumer, and this one is raised before
|
|
5845
|
+
# the analysis rather than after the file is on disk.
|
|
5846
|
+
_est_low, _est_high, _est_mid = _ir_size_estimate_mb(len(file_list))
|
|
5847
|
+
_bounded = summary_only or max_nodes is not None or max_edges is not None
|
|
5848
|
+
if _est_mid > _IR_FILE_CEILING_MB and not force and not _bounded:
|
|
5849
|
+
_emit_error_json(
|
|
5850
|
+
"OUTPUT_TOO_LARGE",
|
|
5851
|
+
f"Estimated output is {_est_low:.0f}-{_est_high:.0f}MB for "
|
|
5852
|
+
f"{len(file_list)} files, above the {_IR_FILE_CEILING_MB}MB "
|
|
5853
|
+
f"ceiling for a written IR.",
|
|
5854
|
+
hint=(
|
|
5855
|
+
"Choose the size deliberately: --summary-only (~5K tokens), "
|
|
5856
|
+
"--max-nodes N --max-edges N, --gzip (70-80% smaller), or "
|
|
5857
|
+
"--force to write it in full."
|
|
5858
|
+
),
|
|
5859
|
+
expected=(
|
|
5860
|
+
f"An estimate under {_IR_FILE_CEILING_MB}MB, or one of "
|
|
5861
|
+
f"--summary-only / --max-nodes / --max-edges / --gzip / --force"
|
|
5862
|
+
),
|
|
5863
|
+
estimate_mb={"low": round(_est_low, 1), "high": round(_est_high, 1)},
|
|
5864
|
+
estimate_basis=(
|
|
5865
|
+
f"{_IR_BYTES_PER_FILE_LOW}-{_IR_BYTES_PER_FILE_HIGH} bytes per "
|
|
5866
|
+
f"Java file, sampled across {_IR_BYTES_PER_FILE_SAMPLES} "
|
|
5867
|
+
f"repositories; the top of the band under-states, since its "
|
|
5868
|
+
f"sample counted tests among its files and this run does not"
|
|
5869
|
+
),
|
|
5870
|
+
)
|
|
5871
|
+
raise typer.Exit(1)
|
|
5872
|
+
|
|
5812
5873
|
_ir_phase = f"extracting IR ({len(file_list)} files)"
|
|
5813
5874
|
if since:
|
|
5814
5875
|
_ir_phase += f" since {since}"
|
|
@@ -7103,12 +7164,13 @@ def _two_states(
|
|
|
7103
7164
|
f"--base-ref and --head-ref resolve to the same commit ({base_sha})",
|
|
7104
7165
|
)
|
|
7105
7166
|
if _identical:
|
|
7106
|
-
# C3-107
|
|
7107
|
-
#
|
|
7108
|
-
#
|
|
7109
|
-
#
|
|
7110
|
-
|
|
7111
|
-
|
|
7167
|
+
# C3-107: two refs that name one commit are one tree. The first
|
|
7168
|
+
# half of the row stopped the second `git archive`; the second
|
|
7169
|
+
# half stops the first one too, because a caller that reads
|
|
7170
|
+
# `identical_states` analyses neither side — there is no
|
|
7171
|
+
# difference to measure, and materialising a tree nobody opens is
|
|
7172
|
+
# the whole cost on a large repository.
|
|
7173
|
+
yield root, root, block
|
|
7112
7174
|
return
|
|
7113
7175
|
with materialize_ref(target, base_ref) as base_tree, \
|
|
7114
7176
|
materialize_ref(target, head_ref) as head_tree:
|
|
@@ -7233,7 +7295,10 @@ def delta_cmd(
|
|
|
7233
7295
|
_enforce_format("delta", format)
|
|
7234
7296
|
|
|
7235
7297
|
from sourcecode.context_graph import ContextGraph
|
|
7236
|
-
from sourcecode.architectural_delta import
|
|
7298
|
+
from sourcecode.architectural_delta import (
|
|
7299
|
+
architectural_delta,
|
|
7300
|
+
identical_state_delta as _identical_state_delta,
|
|
7301
|
+
)
|
|
7237
7302
|
|
|
7238
7303
|
_prog = Progress()
|
|
7239
7304
|
with _two_states(
|
|
@@ -7242,15 +7307,18 @@ def delta_cmd(
|
|
|
7242
7307
|
# C3-107: `_two_states` has already decided this, from the commit on the
|
|
7243
7308
|
# ref path and from the tree signature on the checkout path.
|
|
7244
7309
|
_same = bool(_comparison.get("identical_states"))
|
|
7245
|
-
_prog.start("building base IR")
|
|
7246
|
-
_base_cir = ContextGraph.build_from_root(_base_root).cir
|
|
7247
7310
|
if _same:
|
|
7248
|
-
|
|
7311
|
+
# C3-107, second half: one tree state has no difference to measure, so
|
|
7312
|
+
# nothing is read. Eval #26 measured 24,6 s here to conclude that a
|
|
7313
|
+
# tree does not differ from itself.
|
|
7314
|
+
data = _identical_state_delta()
|
|
7249
7315
|
else:
|
|
7316
|
+
_prog.start("building base IR")
|
|
7317
|
+
_base_cir = ContextGraph.build_from_root(_base_root).cir
|
|
7250
7318
|
_prog.update("building head IR")
|
|
7251
7319
|
_head_cir = ContextGraph.build_from_root(_head_root).cir
|
|
7252
|
-
|
|
7253
|
-
|
|
7320
|
+
_prog.update("diffing snapshots")
|
|
7321
|
+
data = architectural_delta(_base_cir, _head_cir)
|
|
7254
7322
|
data["comparison"] = _comparison
|
|
7255
7323
|
_prog.finish()
|
|
7256
7324
|
|
|
@@ -7328,7 +7396,10 @@ def contract_diff_cmd(
|
|
|
7328
7396
|
_enforce_format("contract-diff", format)
|
|
7329
7397
|
|
|
7330
7398
|
from sourcecode.context_graph import ContextGraph
|
|
7331
|
-
from sourcecode.contract_diff import
|
|
7399
|
+
from sourcecode.contract_diff import (
|
|
7400
|
+
contract_diff as _contract_diff,
|
|
7401
|
+
identical_state_contract_diff as _identical_state_contract_diff,
|
|
7402
|
+
)
|
|
7332
7403
|
from sourcecode.constraint_diff import constraint_findings as _constraint_findings
|
|
7333
7404
|
from sourcecode.validation_surface import build_validation_surface
|
|
7334
7405
|
|
|
@@ -7339,24 +7410,26 @@ def contract_diff_cmd(
|
|
|
7339
7410
|
# C3-107: `_two_states` has already decided this, from the commit on the
|
|
7340
7411
|
# ref path and from the tree signature on the checkout path.
|
|
7341
7412
|
_same = bool(_comparison.get("identical_states"))
|
|
7342
|
-
_prog.start("building base IR")
|
|
7343
|
-
_base_cir = ContextGraph.build_from_root(_base_root).cir
|
|
7344
7413
|
if _same:
|
|
7345
|
-
|
|
7414
|
+
# C3-107, second half. This is the command the round measured at
|
|
7415
|
+
# **59,9 s** on one tree — two CIRs and two validation surfaces, all
|
|
7416
|
+
# four of them projections of the same bytes.
|
|
7417
|
+
data = _identical_state_contract_diff()
|
|
7346
7418
|
else:
|
|
7419
|
+
_prog.start("building base IR")
|
|
7420
|
+
_base_cir = ContextGraph.build_from_root(_base_root).cir
|
|
7347
7421
|
_prog.update("building head IR")
|
|
7348
7422
|
_head_cir = ContextGraph.build_from_root(_head_root).cir
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7353
|
-
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
data = _contract_diff(_base_cir, _head_cir, constraint_findings=_cfindings)
|
|
7423
|
+
# D2-b: proven request-constraint loosenings fill the non_breaking bucket. The
|
|
7424
|
+
# validation surface needs the repo roots (it discovers specs/DTOs), not just the
|
|
7425
|
+
# CIR — build it per side and diff the constraint contracts.
|
|
7426
|
+
_prog.update("projecting validation constraints")
|
|
7427
|
+
_cfindings = _constraint_findings(
|
|
7428
|
+
build_validation_surface(_base_root),
|
|
7429
|
+
build_validation_surface(_head_root),
|
|
7430
|
+
)
|
|
7431
|
+
_prog.update("diffing contracts")
|
|
7432
|
+
data = _contract_diff(_base_cir, _head_cir, constraint_findings=_cfindings)
|
|
7360
7433
|
data["comparison"] = _comparison
|
|
7361
7434
|
_prog.finish()
|
|
7362
7435
|
|
|
@@ -13810,7 +13883,7 @@ def _cache_model_conditioning(path: Path) -> Any:
|
|
|
13810
13883
|
try:
|
|
13811
13884
|
from sourcecode import cache_model as _cmodel
|
|
13812
13885
|
from sourcecode.execution_plan import (
|
|
13813
|
-
DETACH, RUNS_NOW, UNKNOWN, WARM_FIRST, scope_for, verdict,
|
|
13886
|
+
BUDGETED, DETACH, RUNS_NOW, UNKNOWN, WARM_FIRST, scope_for, verdict,
|
|
13814
13887
|
)
|
|
13815
13888
|
|
|
13816
13889
|
scope = scope_for(path)
|
|
@@ -13820,6 +13893,11 @@ def _cache_model_conditioning(path: Path) -> Any:
|
|
|
13820
13893
|
phrasing = {
|
|
13821
13894
|
RUNS_NOW: "runs in the foreground here",
|
|
13822
13895
|
WARM_FIRST: "run `ask cache warm .` first; it pays once for every command after it",
|
|
13896
|
+
# C3-110: a minute of foreground work is a budget line, not a refusal.
|
|
13897
|
+
# This line said *"not a foreground run here — a nightly job"* about a
|
|
13898
|
+
# command the field had just run in the foreground, off a figure taken
|
|
13899
|
+
# on another build.
|
|
13900
|
+
BUDGETED: "a foreground run to budget for here — keep the answer with `--output <file>`",
|
|
13823
13901
|
DETACH: "not a foreground run here — `--output <file> --detach`, or a nightly job",
|
|
13824
13902
|
UNKNOWN: "not measured at this size",
|
|
13825
13903
|
}
|
sourcecode/contract_diff.py
CHANGED
|
@@ -206,6 +206,33 @@ def diff_contract(
|
|
|
206
206
|
}
|
|
207
207
|
|
|
208
208
|
|
|
209
|
+
def identical_state_contract_diff() -> dict:
|
|
210
|
+
"""The `contract-diff-v1` payload for two states that are one state (C3-107).
|
|
211
|
+
|
|
212
|
+
Same argument as `architectural_delta.identical_state_delta`, and the same
|
|
213
|
+
care about what it does not say: `unchanged` here is a statement about the
|
|
214
|
+
*difference* between the two states, which is empty because there is only one
|
|
215
|
+
state. It is not a statement that the contract is sound, and the payload says
|
|
216
|
+
so rather than leaving a reader to infer it from a green word.
|
|
217
|
+
"""
|
|
218
|
+
from sourcecode.architectural_delta import IDENTICAL_STATE_BASIS
|
|
219
|
+
|
|
220
|
+
return {
|
|
221
|
+
"schema": CONTRACT_DIFF_SCHEMA,
|
|
222
|
+
"contract_status": "unchanged",
|
|
223
|
+
"summary": {"breaking": 0, "additive": 0, "non_breaking": 0},
|
|
224
|
+
"breaking": [],
|
|
225
|
+
"additive": [],
|
|
226
|
+
"non_breaking": [],
|
|
227
|
+
"analysis": {"performed": False, "basis": IDENTICAL_STATE_BASIS},
|
|
228
|
+
"provenance": (
|
|
229
|
+
"contract_diff (D2), identical states: no repository was read, and "
|
|
230
|
+
"`unchanged` describes the difference between the two states, not the "
|
|
231
|
+
"health of the contract in either. " + IDENTICAL_STATE_BASIS
|
|
232
|
+
),
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
|
|
209
236
|
def contract_diff(
|
|
210
237
|
base_cir: "CanonicalRepositoryIR",
|
|
211
238
|
head_cir: "CanonicalRepositoryIR",
|
sourcecode/execution_plan.py
CHANGED
|
@@ -38,12 +38,14 @@ from sourcecode.cache_model import (
|
|
|
38
38
|
FIELD_ANCHOR_JAVA_FILES,
|
|
39
39
|
REFERENCE_JAVA_FILES,
|
|
40
40
|
REFERENCE_REPOSITORY,
|
|
41
|
+
field_anchor_currency_clause,
|
|
41
42
|
field_anchor_note,
|
|
42
43
|
)
|
|
43
44
|
|
|
44
45
|
#: How a command can be run on the scope in hand.
|
|
45
46
|
RUNS_NOW = "runs_now" # foreground, seconds — the fast path
|
|
46
47
|
WARM_FIRST = "warm_first" # foreground, after `cache warm`, which pays once
|
|
48
|
+
BUDGETED = "budgeted" # foreground, but long enough to plan for (C3-110)
|
|
47
49
|
DETACH = "detach" # `--output` + `--detach`, or a nightly job
|
|
48
50
|
UNKNOWN = "unknown" # not measured on this axis; never guessed
|
|
49
51
|
|
|
@@ -257,6 +259,17 @@ class Verdict:
|
|
|
257
259
|
#: session (C3-53). Commands measured under it at field size are still offered.
|
|
258
260
|
FOREGROUND_SECONDS = 30.0
|
|
259
261
|
|
|
262
|
+
#: **C3-110.** Above this, and only above it, the product says *"not a foreground
|
|
263
|
+
#: run"*. Between the two thresholds a command is offered with its measured cost
|
|
264
|
+
#: attached, because those two sentences are different claims and the product was
|
|
265
|
+
#: making the stronger one on the weaker evidence: `risk` carried *"not a
|
|
266
|
+
#: foreground run here — `--output <file> --detach`, or a nightly job"* off a
|
|
267
|
+
#: 73,3 s anchor taken on another build, and the field — who had just run it in
|
|
268
|
+
#: 77,2 s in the foreground — read that as the product refusing work it does
|
|
269
|
+
#: nightly. Their number, and they are the ones holding the stopwatch: *"umbral
|
|
270
|
+
#: para `not a foreground run`: no emitirlo por debajo de ~120 s"*.
|
|
271
|
+
DETACH_SECONDS = 120.0
|
|
272
|
+
|
|
260
273
|
|
|
261
274
|
def _reference(row) -> Optional[str]:
|
|
262
275
|
if row is None:
|
|
@@ -360,8 +373,13 @@ def verdict(command: str, scope: Scope) -> Verdict:
|
|
|
360
373
|
# row this matters most on — 72,3 s from a purged cache against 0,3 s
|
|
361
374
|
# warm on the reference — and the honest thing to publish is the
|
|
362
375
|
# measurement's conditions, not a warm figure nobody took at this size.
|
|
376
|
+
# C3-110: on the surfaces that *advise*, the build the figure belongs
|
|
377
|
+
# to is not a parenthetical — it is the reason the advice may be wrong
|
|
378
|
+
# here, so it is said in full.
|
|
379
|
+
currency = field_anchor_currency_clause(row)
|
|
363
380
|
qualifiers = ", ".join(
|
|
364
|
-
[f"{row.field_cache_state} cache"]
|
|
381
|
+
[f"{row.field_cache_state} cache"]
|
|
382
|
+
+ ([currency] if currency else ([note] if note else []))
|
|
365
383
|
)
|
|
366
384
|
dated = f" ({qualifiers})"
|
|
367
385
|
if row.field_seconds <= FOREGROUND_SECONDS:
|
|
@@ -370,6 +388,19 @@ def verdict(command: str, scope: Scope) -> Verdict:
|
|
|
370
388
|
f"measured at {row.field_seconds:g} s on a repository this size{dated}",
|
|
371
389
|
cls, reference,
|
|
372
390
|
)
|
|
391
|
+
if row.field_seconds <= DETACH_SECONDS:
|
|
392
|
+
# C3-110: a minute is a cost, not a prohibition. The figure decides
|
|
393
|
+
# as it always did; what changes is that it stops being read as a
|
|
394
|
+
# refusal on the strength of a measurement from another build.
|
|
395
|
+
return Verdict(
|
|
396
|
+
command, BUDGETED,
|
|
397
|
+
(
|
|
398
|
+
f"measured at {row.field_seconds:g} s on a repository this "
|
|
399
|
+
f"size{dated} — a foreground run to budget for, or "
|
|
400
|
+
f"`--output <file>` to keep the answer"
|
|
401
|
+
),
|
|
402
|
+
cls, reference,
|
|
403
|
+
)
|
|
373
404
|
return Verdict(
|
|
374
405
|
command, DETACH,
|
|
375
406
|
(
|
|
@@ -454,6 +485,10 @@ def advice(invocation: str, root: "Optional[Path]") -> str:
|
|
|
454
485
|
found = verdict(invocation, scope)
|
|
455
486
|
if found.how == DETACH:
|
|
456
487
|
return f"Not a foreground run on this repository ({scope.describe()}): {found.why}."
|
|
488
|
+
if found.how == BUDGETED:
|
|
489
|
+
# C3-110: stated as a cost, never as a refusal — the distinction the
|
|
490
|
+
# threshold above exists to keep.
|
|
491
|
+
return f"A run to budget for on this repository ({scope.describe()}): {found.why}."
|
|
457
492
|
if found.how == WARM_FIRST:
|
|
458
493
|
return (
|
|
459
494
|
f"The cache for this repository is cold ({scope.describe()}); "
|
|
@@ -464,11 +499,15 @@ def advice(invocation: str, root: "Optional[Path]") -> str:
|
|
|
464
499
|
|
|
465
500
|
#: The order the front page lists the buckets in: what the reader can do now
|
|
466
501
|
#: first, what costs one warm next, what needs a plan last.
|
|
467
|
-
BUCKET_ORDER = (RUNS_NOW, WARM_FIRST, DETACH, UNKNOWN)
|
|
502
|
+
BUCKET_ORDER = (RUNS_NOW, WARM_FIRST, BUDGETED, DETACH, UNKNOWN)
|
|
468
503
|
|
|
469
504
|
BUCKET_TITLE = {
|
|
470
505
|
RUNS_NOW: "Runs now",
|
|
471
506
|
WARM_FIRST: "Warm the cache first — `ask cache warm .` pays once",
|
|
507
|
+
BUDGETED: (
|
|
508
|
+
f"Foreground, with a budget — measured between {FOREGROUND_SECONDS:g} s "
|
|
509
|
+
f"and {DETACH_SECONDS:g} s at this size"
|
|
510
|
+
),
|
|
472
511
|
DETACH: "Too big for this session — `--output <file> --detach`, or nightly",
|
|
473
512
|
UNKNOWN: "Cost not measured on this repository",
|
|
474
513
|
}
|
sourcecode/perf.py
CHANGED
|
@@ -452,24 +452,121 @@ RELEASE_GATE_MIN_RUNS = 5
|
|
|
452
452
|
#: The gated population: repository-wide commands that take only a path, so the
|
|
453
453
|
#: gate never depends on a symbol that exists in one revision and not the next.
|
|
454
454
|
#: `""` is the root analysis (`ask <repo>`).
|
|
455
|
+
#:
|
|
456
|
+
#: **C3-110.** Six commands for five releases, against the eighteen the field
|
|
457
|
+
#: measures every round — so `validation` could oscillate 2,9× four times, `risk`
|
|
458
|
+
#: could cross two orders of magnitude, and the gate could stay green throughout
|
|
459
|
+
#: because neither was in it. Every path-only command the field times is here now;
|
|
460
|
+
#: what is left out is left out for a reason, and the reason is published below.
|
|
455
461
|
RELEASE_GATE_COMMANDS: tuple[str, ...] = (
|
|
456
462
|
"", "endpoints", "spring-audit", "migrate-check", "validation", "posture",
|
|
463
|
+
"risk", "modernize", "repo-ir", "data-exposure",
|
|
457
464
|
)
|
|
458
465
|
|
|
466
|
+
#: Extra arguments a gated command needs to be measured at all — one authority,
|
|
467
|
+
#: read by the harness and published by `--print-config`, because a flag typed
|
|
468
|
+
#: into a workflow is a second copy of a decision.
|
|
469
|
+
#:
|
|
470
|
+
#: `repo-ir` writes its whole IR by default, which C3-111 now refuses above 50 MB
|
|
471
|
+
#: on the gate repository. `--summary-only` measures the half that is analysis
|
|
472
|
+
#: (build the IR) without the half that is serialisation of ~80 MB, and it is the
|
|
473
|
+
#: form the harness already uses to count symbols.
|
|
474
|
+
RELEASE_GATE_COMMAND_ARGS: dict[str, tuple[str, ...]] = {
|
|
475
|
+
"repo-ir": ("--summary-only",),
|
|
476
|
+
}
|
|
477
|
+
|
|
459
478
|
#: What the gate does **not** cover, and why — published rather than omitted, so
|
|
460
479
|
#: "the gate is green" is never read as "every command was measured".
|
|
461
480
|
RELEASE_GATE_EXCLUSIONS: tuple[tuple[str, str], ...] = (
|
|
462
|
-
("risk", "68 s on the gate repository since C3-96 deleted the catastrophic "
|
|
463
|
-
"backtracking that made it 54 minutes (F-AQ) — no longer excluded for "
|
|
464
|
-
"cost, only until a baseline cell exists for it; the first capture "
|
|
465
|
-
"that includes it makes it gated (C3-99)"),
|
|
466
481
|
("impact-chain", "takes a symbol, not a repository — its cost is the audit "
|
|
467
482
|
"`risk` and `spring-audit` already gate"),
|
|
483
|
+
("explain", "takes a symbol, same reason"),
|
|
468
484
|
("verify-edit", "measures an edit loop, which needs a working-tree mutation "
|
|
469
|
-
"the gate would have to fabricate"
|
|
485
|
+
"the gate would have to fabricate. Its clean-tree path builds "
|
|
486
|
+
"no model at all since C3-102, so the figure a gate could take "
|
|
487
|
+
"here would not be the figure a user pays"),
|
|
488
|
+
("delta / contract-diff", "take two tree states; on one state they read "
|
|
489
|
+
"nothing at all (C3-107), and on two they measure "
|
|
490
|
+
"the same build the gated commands already cover"),
|
|
491
|
+
("pr-impact / review-pr", "diff-dependent — their cost follows a diff the "
|
|
492
|
+
"gate would have to invent, and an invented diff "
|
|
493
|
+
"measures the invention"),
|
|
470
494
|
)
|
|
471
495
|
|
|
472
496
|
|
|
497
|
+
#: **C3-110.** The second comparison, and the one that would have caught the
|
|
498
|
+
#: series the field prints. A release compared only against the release before it
|
|
499
|
+
#: passes every step of a staircase: `validation` went 13,8 → 34,1 → 39,5 s in
|
|
500
|
+
#: three releases and no single step is 20 %. The reference build is the best
|
|
501
|
+
#: measurement this product has taken, kept as its own baseline directory, and a
|
|
502
|
+
#: release states its distance from it.
|
|
503
|
+
#:
|
|
504
|
+
#: Drift is **measured and published, never deciding** — the same separation
|
|
505
|
+
#: C3-108 drew for cold cells, and for a stronger reason: some of the distance
|
|
506
|
+
#: from the best build is deliberate (work that was added), and a gate that
|
|
507
|
+
#: cannot tell deliberate from accidental must not hold the release. What it must
|
|
508
|
+
#: do is make the number impossible to not know.
|
|
509
|
+
RELEASE_GATE_DRIFT_BASELINE = "reference-best"
|
|
510
|
+
#: The distance at which drift is reported as `drifted` rather than `within`.
|
|
511
|
+
#: Same 20 % as the release threshold: one number for "this is a lot", so a reader
|
|
512
|
+
#: never has to hold two.
|
|
513
|
+
RELEASE_GATE_DRIFT_THRESHOLD = RELEASE_GATE_THRESHOLD
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
def drift_report(
|
|
517
|
+
reference_cells: Mapping[str, Mapping[str, object]],
|
|
518
|
+
current_cells: Mapping[str, Mapping[str, object]],
|
|
519
|
+
*,
|
|
520
|
+
threshold: float = RELEASE_GATE_DRIFT_THRESHOLD,
|
|
521
|
+
) -> dict[str, object]:
|
|
522
|
+
"""How far this run is from the best build ever measured, cell by cell.
|
|
523
|
+
|
|
524
|
+
Never a verdict: every entry is a ratio and a label, `passed` is not part of
|
|
525
|
+
the shape, and the caller cannot accidentally gate on it. The one thing this
|
|
526
|
+
fails at is silence.
|
|
527
|
+
"""
|
|
528
|
+
cells: list[dict[str, object]] = []
|
|
529
|
+
drifted: list[str] = []
|
|
530
|
+
for cid in sorted(set(reference_cells) & set(current_cells)):
|
|
531
|
+
base = reference_cells[cid]
|
|
532
|
+
head = current_cells[cid]
|
|
533
|
+
b_wall = base.get("wall_ms") if isinstance(base.get("wall_ms"), Mapping) else {}
|
|
534
|
+
h_wall = head.get("wall_ms") if isinstance(head.get("wall_ms"), Mapping) else {}
|
|
535
|
+
b50, h50 = b_wall.get("p50"), h_wall.get("p50")
|
|
536
|
+
if not isinstance(b50, (int, float)) or not isinstance(h50, (int, float)) or b50 <= 0:
|
|
537
|
+
cells.append({"cell": cid, "status": "unmeasured"})
|
|
538
|
+
continue
|
|
539
|
+
ratio = float(h50) / float(b50)
|
|
540
|
+
status = "drifted" if (ratio - 1.0) > threshold else "within"
|
|
541
|
+
if status == "drifted":
|
|
542
|
+
drifted.append(cid)
|
|
543
|
+
cells.append({
|
|
544
|
+
"cell": cid,
|
|
545
|
+
"status": status,
|
|
546
|
+
"reference_p50_ms": round(float(b50), 3),
|
|
547
|
+
"current_p50_ms": round(float(h50), 3),
|
|
548
|
+
"ratio": round(ratio, 3),
|
|
549
|
+
})
|
|
550
|
+
unmeasured = sorted(set(reference_cells) - set(current_cells))
|
|
551
|
+
return {
|
|
552
|
+
"schema_version": GATE_SCHEMA_VERSION,
|
|
553
|
+
"comparison": "drift_against_reference_best",
|
|
554
|
+
"reference": RELEASE_GATE_DRIFT_BASELINE,
|
|
555
|
+
"threshold": threshold,
|
|
556
|
+
"cells": cells,
|
|
557
|
+
"drifted": drifted,
|
|
558
|
+
"not_measured_here": unmeasured,
|
|
559
|
+
"basis": (
|
|
560
|
+
"Distance from the best measurement this product has taken, not from "
|
|
561
|
+
"the previous release. A staircase of steps under the release "
|
|
562
|
+
"threshold is invisible to a release-to-release gate and visible "
|
|
563
|
+
"here. Measured and published; never a verdict, because some of the "
|
|
564
|
+
"distance is work that was deliberately added and this comparison "
|
|
565
|
+
"cannot tell which."
|
|
566
|
+
),
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
|
|
473
570
|
def cell_id(cell: Mapping[str, object]) -> str:
|
|
474
571
|
"""The identity two runs are matched on: ``<repo>__<command>__<mode>``.
|
|
475
572
|
|
sourcecode/verify_edit.py
CHANGED
|
@@ -56,6 +56,15 @@ class HeadVsWorking:
|
|
|
56
56
|
#: True when the working CIR *is* the HEAD CIR because git reported an
|
|
57
57
|
#: unmodified tree, so it was never built a second time (C3-32).
|
|
58
58
|
working_cir_reused: bool = False
|
|
59
|
+
#: **C3-102.** False when no model was built at all, which is the only
|
|
60
|
+
#: honest answer to *"what did you analyse?"* on a tree git reports as
|
|
61
|
+
#: unmodified: nothing, because there is nothing to diff. `cir_head` and
|
|
62
|
+
#: `cir_working` are then the cached model if one already existed for this
|
|
63
|
+
#: exact tree state — free — and ``None`` otherwise. Every axis diffs the two
|
|
64
|
+
#: CIRs, so an empty change set has one answer that no analysis can alter;
|
|
65
|
+
#: paying 119,5 s to reach it is what put this command outside the loop it
|
|
66
|
+
#: was built for.
|
|
67
|
+
model_built: bool = True
|
|
59
68
|
|
|
60
69
|
|
|
61
70
|
# Git env vars that REDIRECT git at where it operates. When verify-edit runs INSIDE a
|
|
@@ -218,34 +227,33 @@ def _build_head_cir_via_worktree(root: Path) -> Any:
|
|
|
218
227
|
|
|
219
228
|
|
|
220
229
|
def _clean_tree_cir(root: Path) -> tuple[Any, bool]:
|
|
221
|
-
"""The CIR
|
|
222
|
-
|
|
223
|
-
C3-102
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
not edited anything"
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
230
|
+
"""The cached CIR for a tree git reports identical to HEAD, or ``(None, False)``.
|
|
231
|
+
|
|
232
|
+
**C3-102, second half.** The first half stopped the throwaway worktree: on a
|
|
233
|
+
clean tree the HEAD tree *is* the working tree, so it was read through the
|
|
234
|
+
shared entry instead of being copied and re-parsed. What that left is the
|
|
235
|
+
build itself — 119,5 s on the field's repository, from a purged cache, to
|
|
236
|
+
produce 807 bytes saying *"you have not edited anything"* — and the eleventh
|
|
237
|
+
round is the third to report it.
|
|
238
|
+
|
|
239
|
+
The build is not needed. `verdict()` short-circuits an empty change set
|
|
240
|
+
because every axis is a diff of the two CIRs and here they are the same
|
|
241
|
+
object: no analysis can change the answer, only the time it takes to give it.
|
|
242
|
+
So a clean run takes the model if one is already cached for exactly this tree
|
|
243
|
+
state (free, and it keeps `--compact`-style consumers whole) and builds
|
|
244
|
+
nothing when there is not.
|
|
236
245
|
|
|
237
246
|
The shortcut is reached only through `git_answered` (C3-32's guard): a failed
|
|
238
247
|
`git diff` also returns an empty change set, and mistaking that for a clean
|
|
239
248
|
tree would turn an unknown into a confident *"nothing changed"*.
|
|
240
249
|
"""
|
|
241
250
|
from sourcecode import context_cache as _ctx
|
|
242
|
-
from sourcecode.repository_ir import find_java_files
|
|
243
251
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
return
|
|
248
|
-
return
|
|
252
|
+
try:
|
|
253
|
+
cached = _ctx.peek_cir(_ctx.repo_root_of(root))
|
|
254
|
+
except Exception:
|
|
255
|
+
return None, False
|
|
256
|
+
return (cached, True) if cached is not None else (None, False)
|
|
249
257
|
|
|
250
258
|
|
|
251
259
|
def _head_cir(root: Path, head_sha: str) -> tuple[Any, bool]:
|
|
@@ -347,11 +355,14 @@ def head_vs_working(path: Path) -> HeadVsWorking:
|
|
|
347
355
|
# before the build rather than after it. A clean tree needs no worktree
|
|
348
356
|
# checkout: the tree on disk is HEAD, and its CIR is the shared one.
|
|
349
357
|
t1 = time.perf_counter()
|
|
358
|
+
model_built = True
|
|
350
359
|
if reused:
|
|
360
|
+
# C3-102: nothing to diff, so nothing is built. A model already cached for
|
|
361
|
+
# this exact tree state is taken because it costs a lookup; its absence is
|
|
362
|
+
# not a reason to spend a repository-wide parse on an answer that cannot
|
|
363
|
+
# depend on it.
|
|
351
364
|
cir_head, hit = _clean_tree_cir(root)
|
|
352
|
-
|
|
353
|
-
# Keep the edit lane warm: the next run is the one with an edit in it.
|
|
354
|
-
_store_head_cir(root, head_sha, cir_head)
|
|
365
|
+
model_built = False
|
|
355
366
|
else:
|
|
356
367
|
cir_head, hit = _head_cir(root, head_sha)
|
|
357
368
|
timings["head_cir_ms"] = (time.perf_counter() - t1) * 1000.0
|
|
@@ -369,6 +380,7 @@ def head_vs_working(path: Path) -> HeadVsWorking:
|
|
|
369
380
|
timings_ms=timings,
|
|
370
381
|
changed_build_files=changed_build,
|
|
371
382
|
working_cir_reused=reused,
|
|
383
|
+
model_built=model_built,
|
|
372
384
|
)
|
|
373
385
|
|
|
374
386
|
|
|
@@ -424,6 +436,11 @@ class VerifyVerdict:
|
|
|
424
436
|
reasons: tuple[str, ...]
|
|
425
437
|
exit_code: int
|
|
426
438
|
head_sha: str
|
|
439
|
+
#: **C3-102.** What was read to produce this verdict. Always present, because
|
|
440
|
+
#: its absence would be the answer: a `pass` that analysed nothing and a `pass`
|
|
441
|
+
#: that diffed two models are the same verdict on different evidence, and a
|
|
442
|
+
#: consumer gating on this is owed the difference.
|
|
443
|
+
analysis: dict = field(default_factory=lambda: {"model_built": True})
|
|
427
444
|
|
|
428
445
|
def to_dict(self) -> dict:
|
|
429
446
|
return {
|
|
@@ -436,6 +453,7 @@ class VerifyVerdict:
|
|
|
436
453
|
"blast_radius": self.blast_radius,
|
|
437
454
|
"reasons": list(self.reasons),
|
|
438
455
|
"exit_code": self.exit_code,
|
|
456
|
+
"analysis": dict(self.analysis),
|
|
439
457
|
}
|
|
440
458
|
|
|
441
459
|
|
|
@@ -775,6 +793,25 @@ def verdict(hvw: HeadVsWorking, root: Path) -> VerifyVerdict:
|
|
|
775
793
|
reasons=(),
|
|
776
794
|
exit_code=0,
|
|
777
795
|
head_sha=hvw.head_sha,
|
|
796
|
+
analysis={
|
|
797
|
+
"model_built": hvw.model_built,
|
|
798
|
+
"basis": (
|
|
799
|
+
"git reports no file differing from HEAD, so the working tree "
|
|
800
|
+
"is HEAD and every axis diffs a state against itself"
|
|
801
|
+
),
|
|
802
|
+
"what_was_read": (
|
|
803
|
+
"the git change set, and a model already cached for this tree "
|
|
804
|
+
"state" if hvw.cir_head is not None else "the git change set"
|
|
805
|
+
),
|
|
806
|
+
# The claim this verdict does NOT make, said outright: nothing was
|
|
807
|
+
# analysed, so nothing is asserted about the code beyond identity
|
|
808
|
+
# with HEAD.
|
|
809
|
+
"scope_note": (
|
|
810
|
+
"`pass` here means the working tree does not differ from HEAD, "
|
|
811
|
+
"not that HEAD was audited — that is `ask spring-audit` / "
|
|
812
|
+
"`ask verify`."
|
|
813
|
+
),
|
|
814
|
+
},
|
|
778
815
|
)
|
|
779
816
|
|
|
780
817
|
axes: dict[str, AxisResult] = {
|
|
@@ -815,6 +852,15 @@ def verdict(hvw: HeadVsWorking, root: Path) -> VerifyVerdict:
|
|
|
815
852
|
reasons=tuple(reasons),
|
|
816
853
|
exit_code=code,
|
|
817
854
|
head_sha=hvw.head_sha,
|
|
855
|
+
analysis={
|
|
856
|
+
"model_built": True,
|
|
857
|
+
"basis": (
|
|
858
|
+
f"{len(hvw.changed_files)} changed .java file(s) and "
|
|
859
|
+
f"{len(hvw.changed_build_files)} changed build file(s): HEAD and "
|
|
860
|
+
f"the working tree were both modelled and diffed"
|
|
861
|
+
),
|
|
862
|
+
"head_model_cache_hit": hvw.head_cache_hit,
|
|
863
|
+
},
|
|
818
864
|
)
|
|
819
865
|
|
|
820
866
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.2.0
|
|
4
4
|
Summary: Persistent structural context and ultra-fast repeated analysis for AI coding agents
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Keywords: agents,ai,codebase,context,developer-tools,llm
|
|
@@ -42,7 +42,7 @@ Description-Content-Type: text/markdown
|
|
|
42
42
|
|
|
43
43
|
**Context · Impact · Migration · Architecture · Review — everything from one structural model.**
|
|
44
44
|
|
|
45
|
-

|
|
46
46
|

|
|
47
47
|
|
|
48
48
|
> **ASK Engine** is the product. The CLI command is **`ask`**. The legacy **`sourcecode`**
|
|
@@ -126,7 +126,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
|
|
|
126
126
|
# pip / pipx
|
|
127
127
|
pipx install sourcecode # or: pip install sourcecode
|
|
128
128
|
|
|
129
|
-
ask version # ask 5.
|
|
129
|
+
ask version # ask 5.2.0 — and, on a build that has aged,
|
|
130
130
|
# how many releases have probably shipped since
|
|
131
131
|
```
|
|
132
132
|
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
sourcecode/__init__.py,sha256=
|
|
1
|
+
sourcecode/__init__.py,sha256=ceBAMIauSu1eUdUEkTRgsDTDWiSm1LutxpbiBjjoS-Y,308
|
|
2
2
|
sourcecode/adaptive_scanner.py,sha256=yJBKjNpkY6bpueYJ2YnRezen3sYZDecEt7WaaNWdqug,9466
|
|
3
3
|
sourcecode/archetype.py,sha256=CZvRLpkHot_D8D3JFQVorr-EHDJyh0BbS7RnSTqBigM,40499
|
|
4
4
|
sourcecode/architectural_baseline.py,sha256=4GiMVBLJVHvRKSWQGf2ZVurI1-R0qk5pmaevgvGSgVA,26325
|
|
5
|
-
sourcecode/architectural_delta.py,sha256=
|
|
5
|
+
sourcecode/architectural_delta.py,sha256=JhZVmA0gYUryt4x4ieVuxPbcvoBygHgADZaYJ_o4gdk,15142
|
|
6
6
|
sourcecode/architecture_analyzer.py,sha256=GFc4ek-s1IHWM7pl-0L32WahZ93AmDgrAMcOuBKA5Dk,61463
|
|
7
7
|
sourcecode/architecture_summary.py,sha256=BVVRHd952cjRhjHnR6CPrvKgaa-tdM16l-pBi1yDCPs,32395
|
|
8
8
|
sourcecode/ast_extractor.py,sha256=aXJjZ7XjAdxa99hWNm4SyzPqx4gNWiTbUYjNWGNl-Vc,51213
|
|
9
9
|
sourcecode/audit_report.py,sha256=CLvvlQH2oA6Qj4UADUWhNwSsp1OcyzwXXey5DN_IiWI,8660
|
|
10
10
|
sourcecode/baseline_autocapture.py,sha256=tmMLexQSeaQRRbqxAd7walvGQqnF0mdpxQmkL40rlhI,15623
|
|
11
11
|
sourcecode/cache.py,sha256=CK_J8NqyaTNZ57KQT-R4puqI8yYlzG5WL7uLFRbzods,41727
|
|
12
|
-
sourcecode/cache_model.py,sha256=
|
|
12
|
+
sourcecode/cache_model.py,sha256=EqsVZ9U2f5Yd1A1RuBp9CBWyMh-mHpFDBOA3aSCmU74,56721
|
|
13
13
|
sourcecode/call_surface.py,sha256=fiqYfHooxN1fX9oQoysq1LS3LoZcobhyUNjAGEZKpwk,4148
|
|
14
14
|
sourcecode/caller_metrics.py,sha256=--sFGDnIog_YGu9xZHMcB91F5xZakfaAKvy15xU54hg,7904
|
|
15
15
|
sourcecode/caller_reach.py,sha256=RRF49tv4-QswraJ2vsZ89VAMOj7BmYXlAdXr-tLP_CA,9483
|
|
@@ -18,7 +18,7 @@ sourcecode/chain_rules.py,sha256=Bi6UHfgd-GxWswmnHRcPz5jdbAuqka3Zkz_P-MTvqhw,127
|
|
|
18
18
|
sourcecode/change_plan.py,sha256=aX1mp2XnlDN-8R2BcTiu8HlkDwQ_4fN1ZLckj0VMXHM,9945
|
|
19
19
|
sourcecode/cir_graphs.py,sha256=9G0HHj1kw2325IDyzo2OpX73BNswEckecf4MZUXB4JM,12078
|
|
20
20
|
sourcecode/classifier.py,sha256=JBzPwSSrDG-tUHAbcKB678HRbjLpD-ohzbzzO62mgpo,20114
|
|
21
|
-
sourcecode/cli.py,sha256=
|
|
21
|
+
sourcecode/cli.py,sha256=_dDEE_2pyD4d0VD6WR2KDVKeCVFH6pHToUMEhdd_T4I,622141
|
|
22
22
|
sourcecode/client_calls.py,sha256=daRTgbXNUOfkzGXJpVb6A737R_Thhka8vw1_YgxCaLg,13548
|
|
23
23
|
sourcecode/code_notes_analyzer.py,sha256=EJemNCNc9Dn-1RZYu-aNbK0ELzmsyC4s6FdHi3XyNEI,9392
|
|
24
24
|
sourcecode/compare.py,sha256=2GdDy0qkDSgmkkpgvoCHitoLj3mt30EeFgJ8PGEXJng,14712
|
|
@@ -29,7 +29,7 @@ sourcecode/context_cache.py,sha256=xfS0GpWG8MpHwqgw61tp3IR7jZ2IdG1j-v_HoIiSx7o,3
|
|
|
29
29
|
sourcecode/context_graph.py,sha256=a6v2lgl2DxDnPAWE59K3yg6L5YFDak0LIUff3pi9p0c,47327
|
|
30
30
|
sourcecode/context_scorer.py,sha256=QpChSpsmaAYz91rXA4Ue5xzQmNz_ZboZN09YOHScq1U,14679
|
|
31
31
|
sourcecode/context_summarizer.py,sha256=cI2TZMvEhl0BEma12VtPaX6z03ZVBAetVzuK5GaCOvg,6852
|
|
32
|
-
sourcecode/contract_diff.py,sha256=
|
|
32
|
+
sourcecode/contract_diff.py,sha256=skND-oDmLyMDW5Qdvz-yDh7VyisikBCm5fvmLP7Q1xE,10618
|
|
33
33
|
sourcecode/contract_init.py,sha256=bXRCqWM9tvrDLeT8j7ea6IWf87jB4VJxnlSzGBsRRXo,19582
|
|
34
34
|
sourcecode/contract_model.py,sha256=nRxJKPMs1VHwFTa8AVXhGmaLjti3Lr2sjHDpWgv1bfE,3917
|
|
35
35
|
sourcecode/contract_pipeline.py,sha256=4XE-xhab7ysdExXyUOBl2hAH4MABo7moKnT9V4XcEwQ,30243
|
|
@@ -52,7 +52,7 @@ sourcecode/envelope.py,sha256=fpF_8znvPqGXKZb0UPYcCYjm27yO7Pr-WsdXNE-tEoY,8911
|
|
|
52
52
|
sourcecode/environment_resolution.py,sha256=bfhkM0RGSyLwzFvfi-YhHjU1cy2ufA_WIkXBVeHs9y8,22130
|
|
53
53
|
sourcecode/error_schema.py,sha256=uwosfNaSujtYm11_732Hu92z5ITV040fQDaIyefSvR4,1683
|
|
54
54
|
sourcecode/evidence_provider.py,sha256=GSSL44JEaouO5AHks2sB3d1YvC9xIKIld1yBYxZpXxo,4277
|
|
55
|
-
sourcecode/execution_plan.py,sha256=
|
|
55
|
+
sourcecode/execution_plan.py,sha256=sV2VrR60XxdzM58SwI577kucLBqCVNQFbDGmA-x9Mvo,22655
|
|
56
56
|
sourcecode/explain.py,sha256=yqxvKiLF0XMMg11PdgqMFrsim5SXuEKM1U2cLvCLspM,29935
|
|
57
57
|
sourcecode/file_chunker.py,sha256=3vkM3mDQ5eE_yTPvUgjyjpGFBIjkW6_mrBmIbrylnA8,16444
|
|
58
58
|
sourcecode/file_classifier.py,sha256=pJCeN9KqWpAwKMCgGP4KDsBjuWMeo4zlbj5fv3hk9dA,15587
|
|
@@ -83,7 +83,7 @@ sourcecode/parse_cache.py,sha256=TpIoSeNUba4Aoaz5o5SmgAc0Tz02OKq1Du4Hw7HyJfg,225
|
|
|
83
83
|
sourcecode/partial_contract.py,sha256=x_N_0bF3mpNNjXd7JFB1zr6LSIroo2zN5GCz14GXvXQ,3510
|
|
84
84
|
sourcecode/path_admission.py,sha256=OGNSoluhVh8YYOBZBnACUrkmH4Tp_yxjGLifkcsxQpo,5838
|
|
85
85
|
sourcecode/path_filters.py,sha256=LmTYq735orssKTIuxTX1mE1FHAXF7dVEJEse35xE1RA,12371
|
|
86
|
-
sourcecode/perf.py,sha256=
|
|
86
|
+
sourcecode/perf.py,sha256=Zipl5Wveolrl5xsDzHtlX7q0WYGQLfKlGX1m6__AkWA,34232
|
|
87
87
|
sourcecode/phased_run.py,sha256=cFd0Lxfc8XL-XkCVCCzcjd9bZbtgkJkGZAHfmJ6dBJ4,16542
|
|
88
88
|
sourcecode/pipe_contract.py,sha256=PML0Er5d8uDyec4OrdUXuyqHbGPUYndjeaKUjkFz2u4,8369
|
|
89
89
|
sourcecode/posture.py,sha256=7d3zM4ExrSXVKrWNTlXQ0fUQNqDdl1LOuKwRVaXdRss,76574
|
|
@@ -143,7 +143,7 @@ sourcecode/tree_utils.py,sha256=8GAkIfQAsvtEudIeW1l4ooH_oRtrWR8cpJQJsEa_Pfw,2093
|
|
|
143
143
|
sourcecode/type_usage_surface.py,sha256=51IrKRQoIoRnlsiDjHnqpJBn2rc6E59aRhgS0HTzAF0,4428
|
|
144
144
|
sourcecode/validation_inference.py,sha256=-oWJqE6PqkqcZbCFDJeWCQHgI9Dbuv5ggJWD3LE_2IU,20817
|
|
145
145
|
sourcecode/validation_surface.py,sha256=jYL-hkDjaaRKkAt7ZUcbxm3Dydl8o6KVRhTkuPXKPVc,31460
|
|
146
|
-
sourcecode/verify_edit.py,sha256=
|
|
146
|
+
sourcecode/verify_edit.py,sha256=SUaJeH5Icc54mutQx3-gh7i8U6d50cb_oxYc9SDUnHs,42757
|
|
147
147
|
sourcecode/verify_repo.py,sha256=aHlNIUfoVVUxTXTNtSFryP4dOFBOvCfdyC31fFRXU6s,15346
|
|
148
148
|
sourcecode/verify_rules.py,sha256=YxG5JkDXBVpwbU1_tIKVtU8_eaF3zjpsq05tjpN4Z7Y,19401
|
|
149
149
|
sourcecode/version_check.py,sha256=CHp6ZxTIfo8kyHPCBgJA1uFC0xQCoXMuuOfrW8QTL8o,4942
|
|
@@ -207,8 +207,8 @@ sourcecode/telemetry/consent.py,sha256=pQdl-QeLl6Gcibn0eWHSKZrm-HYSsjpVqOnjrgFp8
|
|
|
207
207
|
sourcecode/telemetry/events.py,sha256=4_yeO58U-Cwc1Qb27VB0_EjhmroY0k91n3_VGxeALB8,2776
|
|
208
208
|
sourcecode/telemetry/filters.py,sha256=RzxauTz8HliO4BllQnXEXc7zTeqdCZi5MgqGEDuW7OQ,6570
|
|
209
209
|
sourcecode/telemetry/transport.py,sha256=4gGHsq0WeY9VywEZXA3vUxykfiYnw9uuqfjAAec7F8o,1681
|
|
210
|
-
sourcecode-5.
|
|
211
|
-
sourcecode-5.
|
|
212
|
-
sourcecode-5.
|
|
213
|
-
sourcecode-5.
|
|
214
|
-
sourcecode-5.
|
|
210
|
+
sourcecode-5.2.0.dist-info/METADATA,sha256=5c5Xukk2etIZwtrijfL2_Hya7h1a08S-MyOD0s7EX8U,42410
|
|
211
|
+
sourcecode-5.2.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
212
|
+
sourcecode-5.2.0.dist-info/entry_points.txt,sha256=-JEAdChrK5We51kZcb7OaDcyil-dHBjBPL-NhuO-QY8,89
|
|
213
|
+
sourcecode-5.2.0.dist-info/licenses/LICENSE,sha256=7DdHrU9Z_3e7dSvq4ISijZNjnuHo5NIHNiHDouMQ9JU,10491
|
|
214
|
+
sourcecode-5.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|