sourcecode 2.5.15__py3-none-any.whl → 2.5.16__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__ = "2.5.15"
7
+ __version__ = "2.5.16"
@@ -967,25 +967,26 @@ def _java_contract_from_graph(rel_path: str, graph: "Any") -> FileContract:
967
967
  nodes/edges instead of re-parsing source. Method signatures are the graph's
968
968
  canonical compact form (`(Type)->Return`); annotations are node-grounded.
969
969
  """
970
- file_syms = [s for s in graph.symbols() if s.source_file == rel_path]
970
+ file_syms = graph.symbols_in_file(rel_path)
971
971
  type_syms = [s for s in file_syms if s.kind in ("class", "interface", "enum", "annotation")]
972
972
  type_fqns = {s.fqn for s in type_syms}
973
973
 
974
974
  # extends / implements edges out of this file's types (targets are simple
975
975
  # names for out-of-repo supertypes, resolved FQNs for in-repo ones — the
976
- # same forms the old regex captured for the unresolved case).
976
+ # same forms the old regex captured for the unresolved case). Only edges
977
+ # sourced at this file's types matter, so index straight to them instead of
978
+ # scanning the whole-repo relation set once per file.
977
979
  extends_of: dict[str, list[str]] = {}
978
980
  implements_of: dict[str, list[str]] = {}
979
981
  import_targets: set[str] = set()
980
- for r in graph.relations():
981
- if r.source not in type_fqns:
982
- continue
983
- if r.kind == "extends":
984
- extends_of.setdefault(r.source, []).append(r.target)
985
- elif r.kind == "implements":
986
- implements_of.setdefault(r.source, []).append(r.target)
987
- elif r.kind == "imports":
988
- import_targets.add(r.target)
982
+ for fqn in type_fqns:
983
+ for r in graph.relations_from(fqn):
984
+ if r.kind == "extends":
985
+ extends_of.setdefault(r.source, []).append(r.target)
986
+ elif r.kind == "implements":
987
+ implements_of.setdefault(r.source, []).append(r.target)
988
+ elif r.kind == "imports":
989
+ import_targets.add(r.target)
989
990
 
990
991
  exports: list[ExportRecord] = []
991
992
  types: list[TypeDefinition] = []
sourcecode/cli.py CHANGED
@@ -15,6 +15,7 @@ from sourcecode import __version__
15
15
  from sourcecode.error_schema import INVALID_INPUT_CODE, build_error_envelope
16
16
  from sourcecode.entrypoint_classifier import is_production_entry_point, normalize_entry_point
17
17
  from sourcecode.progress import Progress
18
+ from sourcecode import perf
18
19
  from sourcecode.caller_metrics import CALLER_METRIC_RECONCILIATION
19
20
  from sourcecode.repository_ir import extract_java_endpoints as _extract_java_endpoints
20
21
 
@@ -1703,6 +1704,7 @@ def main(
1703
1704
  _progress = Progress()
1704
1705
  _progress.start("scanning files")
1705
1706
 
1707
+ _perf_discovery = perf.start()
1706
1708
  scanner = AdaptiveScanner(target, topology=_topology, base_depth=effective_depth,
1707
1709
  extra_excludes=_extra_excludes)
1708
1710
  raw_tree = scanner.scan_tree()
@@ -1710,6 +1712,8 @@ def main(
1710
1712
  _progress.update("parsing manifests")
1711
1713
  # 2. Filter .env and *.secret entries from file tree (SEC-02, all levels)
1712
1714
  file_tree = filter_sensitive_files(raw_tree, redactor)
1715
+ perf.stop("discovery", _perf_discovery)
1716
+ _perf_detection = perf.start()
1713
1717
  detector = ProjectDetector(build_default_detectors())
1714
1718
  workspace_analysis = WorkspaceAnalyzer().analyze(target, manifests)
1715
1719
 
@@ -1951,6 +1955,8 @@ def main(
1951
1955
  else None
1952
1956
  )
1953
1957
 
1958
+ perf.stop("detection", _perf_detection)
1959
+ _perf_analysis = perf.start()
1954
1960
  # 3. Build schema
1955
1961
  # Compute analyzer fingerprints: short hashes of each analyzer's key rule
1956
1962
  # constants so that a rule change is always visible in the output, regardless
@@ -2411,8 +2417,10 @@ def main(
2411
2417
  err=True,
2412
2418
  )
2413
2419
 
2420
+ perf.stop("analysis", _perf_analysis)
2414
2421
  # 4. Serialize
2415
2422
  _progress.update("serializing output")
2423
+ _perf_serialize = perf.start()
2416
2424
  if _is_contract_mode and not agent:
2417
2425
  from sourcecode.serializer import contract_view as _contract_view
2418
2426
  _depth = _CONTRACT_DEPTH.get(mode, "minimal")
@@ -2455,6 +2463,9 @@ def main(
2455
2463
  raw_dict = redact_dict(raw_dict)
2456
2464
  content = _serialize_dict(raw_dict, format)
2457
2465
 
2466
+ perf.stop("serialize", _perf_serialize)
2467
+ perf.flush_recorder()
2468
+
2458
2469
  # 5. Telemetry (fire-and-forget, never blocks)
2459
2470
  try:
2460
2471
  from sourcecode import telemetry as _tel
@@ -408,6 +408,7 @@ class ContextGraph:
408
408
  "_cir", "_nodes_by_fqn", "_nodes", "_build_ms",
409
409
  "_body_index", "_literal_index", "_guard_index", "_span_index",
410
410
  "_class_type_index", "_relations_all", "_symbols_sorted",
411
+ "_symbols_by_file", "_relations_by_source",
411
412
  )
412
413
 
413
414
  def __init__(self, cir: CanonicalRepositoryIR, *, build_ms: float = 0.0) -> None:
@@ -439,6 +440,12 @@ class ContextGraph:
439
440
  # filtered cheaply thereafter.
440
441
  self._relations_all: Optional[tuple[Relation, ...]] = None
441
442
  self._symbols_sorted: Optional[tuple[Symbol, ...]] = None
443
+ # Per-key groupings for per-file consumers (`_java_contract_from_graph`
444
+ # runs once per file). Without these, each file filtered the whole-repo
445
+ # symbol/relation set — the residual O(files × total) scan that the
446
+ # memoized projections above did not remove. Built once, O(1) lookup.
447
+ self._symbols_by_file: Optional[dict[str, list[Symbol]]] = None
448
+ self._relations_by_source: Optional[dict[str, list[Relation]]] = None
442
449
 
443
450
  # -- construction -------------------------------------------------------
444
451
 
@@ -518,6 +525,34 @@ class ContextGraph:
518
525
  and (name_contains is None or name_contains in s.fqn)
519
526
  ]
520
527
 
528
+ def symbols_in_file(self, source_file: str) -> list[Symbol]:
529
+ """All symbols declared in one file, FQN-sorted — the same order and set
530
+ a no-filter ``symbols()`` scan filtered to this file would produce, but
531
+ O(1) after a one-time O(total) grouping instead of O(total) per call.
532
+ """
533
+ if self._symbols_by_file is None:
534
+ if self._symbols_sorted is None:
535
+ self._symbols_sorted = tuple(sorted(self._nodes, key=lambda s: s.fqn))
536
+ idx: dict[str, list[Symbol]] = {}
537
+ for s in self._symbols_sorted:
538
+ idx.setdefault(s.source_file, []).append(s)
539
+ self._symbols_by_file = idx
540
+ return self._symbols_by_file.get(source_file, [])
541
+
542
+ def relations_from(self, source_fqn: str) -> list[Relation]:
543
+ """All relations whose source is ``source_fqn``, in the IR's stable edge
544
+ order. O(1) after a one-time O(edges) grouping — replaces per-file scans
545
+ of the whole relation set.
546
+ """
547
+ if self._relations_by_source is None:
548
+ if self._relations_all is None:
549
+ self._relations_all = tuple(_edge_to_relation(e) for e in self._cir.call_graph)
550
+ idx: dict[str, list[Relation]] = {}
551
+ for r in self._relations_all:
552
+ idx.setdefault(r.source, []).append(r)
553
+ self._relations_by_source = idx
554
+ return self._relations_by_source.get(source_fqn, [])
555
+
521
556
  def types(self) -> list[Symbol]:
522
557
  """All class/interface/enum/annotation symbols, sorted by FQN."""
523
558
  return sorted(
sourcecode/perf.py ADDED
@@ -0,0 +1,268 @@
1
+ """Performance instrumentation and baseline schema — see ADR-0006.
2
+
3
+ Two responsibilities, kept separate:
4
+
5
+ * An **in-process recorder** that times the frozen phase taxonomy (§3). It is
6
+ *zero-cost when disabled* (ADR-0006 §5.5): with ``SOURCECODE_PERF`` unset,
7
+ :func:`span` yields without reading a clock, allocating a span, or writing a
8
+ dict. A production ``ask`` invocation pays nothing for the harness existing.
9
+
10
+ * **Pure functions** — percentiles and the ``perf-baseline-v1`` cell builder —
11
+ that the fleet harness (``scripts/perf_harness.py``) uses to turn a set of raw
12
+ per-run measurements into one frozen-schema artifact.
13
+
14
+ The phase taxonomy and the output schema are the frozen contract; this module is
15
+ the replaceable collector.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import hashlib
21
+ import json
22
+ import os
23
+ import platform
24
+ import socket
25
+ import sys
26
+ import time
27
+ from contextlib import contextmanager
28
+ from datetime import datetime, timezone
29
+ from typing import Iterator, Mapping, Sequence
30
+
31
+ # ── Frozen contract constants (ADR-0006) ────────────────────────────────────
32
+
33
+ SCHEMA_VERSION = "perf-baseline-v1"
34
+
35
+ #: The frozen phase taxonomy. Order is contractual — see ADR-0006 §3.
36
+ #: These are the pipeline's *measured* contiguous seams, not compiler-shaped
37
+ #: guesses: repo discovery, what-is-this-repo detection+enrichment, model
38
+ #: assembly + semantic/contract extraction, and output rendering.
39
+ PHASES: tuple[str, ...] = ("discovery", "detection", "analysis", "serialize")
40
+
41
+ #: Env var that arms the in-process recorder.
42
+ ENV_ENABLE = "SOURCECODE_PERF"
43
+ #: Env var naming the JSONL file the recorder appends its phase timings to.
44
+ ENV_LOG = "SOURCECODE_PERF_LOG"
45
+
46
+
47
+ # ── In-process recorder (zero-cost when disabled) ───────────────────────────
48
+
49
+
50
+ class _Recorder:
51
+ """Accumulates elapsed milliseconds per named phase for one process."""
52
+
53
+ __slots__ = ("_spans",)
54
+
55
+ def __init__(self) -> None:
56
+ self._spans: dict[str, float] = {}
57
+
58
+ def add(self, name: str, ms: float) -> None:
59
+ self._spans[name] = self._spans.get(name, 0.0) + ms
60
+
61
+ def as_dict(self) -> dict[str, float]:
62
+ return dict(self._spans)
63
+
64
+ def flush(self, path: str) -> None:
65
+ """Append the accumulated phase timings as one JSONL record."""
66
+ with open(path, "a", encoding="utf-8") as fh:
67
+ fh.write(json.dumps({"phase_ms": self._spans}) + "\n")
68
+
69
+
70
+ def _resolve_recorder() -> _Recorder | None:
71
+ """Return a recorder iff the environment arms it, else ``None``.
72
+
73
+ Resolved once and cached. Kept out of :func:`span`'s hot path so the
74
+ disabled case is a single ``is None`` check.
75
+ """
76
+ if _resolve_recorder._cached is not _UNSET: # type: ignore[attr-defined]
77
+ return _resolve_recorder._cached # type: ignore[attr-defined]
78
+ rec = _Recorder() if os.environ.get(ENV_ENABLE) == "1" else None
79
+ _resolve_recorder._cached = rec # type: ignore[attr-defined]
80
+ return rec
81
+
82
+
83
+ _UNSET = object()
84
+ _resolve_recorder._cached = _UNSET # type: ignore[attr-defined]
85
+
86
+
87
+ @contextmanager
88
+ def span(name: str) -> Iterator[None]:
89
+ """Time a phase region. No-op (and clock-free) when perf is disabled.
90
+
91
+ ``name`` should be one of :data:`PHASES`, but any name is accepted so the
92
+ caller is never coupled to import order; unknown names simply won't map into
93
+ a baseline cell.
94
+ """
95
+ rec = _resolve_recorder()
96
+ if rec is None:
97
+ # Zero-cost path: no perf_counter, no object, no dict write.
98
+ yield
99
+ return
100
+ t0 = time.perf_counter()
101
+ try:
102
+ yield
103
+ finally:
104
+ rec.add(name, (time.perf_counter() - t0) * 1000.0)
105
+
106
+
107
+ def start() -> float | None:
108
+ """Open a phase measurement without indenting the region it spans.
109
+
110
+ Pairs with :func:`stop`. Returns a start timestamp, or ``None`` when perf is
111
+ disabled — in which case no clock is read. Use this instead of :func:`span`
112
+ to instrument a long, branchy region in place without wrapping it in a
113
+ ``with`` block (which would force a re-indent of hundreds of lines).
114
+ """
115
+ return time.perf_counter() if _resolve_recorder() is not None else None
116
+
117
+
118
+ def stop(name: str, t0: float | None) -> None:
119
+ """Close a :func:`start` measurement, accumulating into phase ``name``.
120
+
121
+ A no-op when perf is disabled (``t0 is None``). Because the recorder sums by
122
+ name, the same phase may be opened and closed at several scattered call
123
+ sites and the times add up.
124
+ """
125
+ if t0 is None:
126
+ return
127
+ rec = _resolve_recorder()
128
+ if rec is not None:
129
+ rec.add(name, (time.perf_counter() - t0) * 1000.0)
130
+
131
+
132
+ def flush_recorder() -> None:
133
+ """Write accumulated phase timings to ``$SOURCECODE_PERF_LOG`` if armed."""
134
+ rec = _resolve_recorder()
135
+ path = os.environ.get(ENV_LOG)
136
+ if rec is not None and path:
137
+ rec.flush(path)
138
+
139
+
140
+ def _reset_for_tests() -> None:
141
+ """Clear the cached recorder so tests can re-resolve after mutating env."""
142
+ _resolve_recorder._cached = _UNSET # type: ignore[attr-defined]
143
+
144
+
145
+ # ── Pure statistics ─────────────────────────────────────────────────────────
146
+
147
+
148
+ def percentile(values: Sequence[float], q: float) -> float:
149
+ """Linear-interpolated percentile, ``q`` in ``[0, 100]``.
150
+
151
+ ``percentile(v, 50)`` is the median. Used for both p50 (central tendency —
152
+ never the mean, ADR-0006 §4) and p95 (tail).
153
+ """
154
+ if not values:
155
+ raise ValueError("percentile of empty sequence")
156
+ if not 0.0 <= q <= 100.0:
157
+ raise ValueError(f"q out of range: {q}")
158
+ s = sorted(values)
159
+ if len(s) == 1:
160
+ return float(s[0])
161
+ rank = (q / 100.0) * (len(s) - 1)
162
+ lo = int(rank)
163
+ hi = min(lo + 1, len(s) - 1)
164
+ frac = rank - lo
165
+ return float(s[lo] + (s[hi] - s[lo]) * frac)
166
+
167
+
168
+ def p50(values: Sequence[float]) -> float:
169
+ return percentile(values, 50.0)
170
+
171
+
172
+ def p95(values: Sequence[float]) -> float:
173
+ return percentile(values, 95.0)
174
+
175
+
176
+ def _stat_block(values: Sequence[float], *, tail: bool = True) -> dict[str, float]:
177
+ block = {"p50": round(p50(values), 3), "p95": round(p95(values), 3)}
178
+ if not tail:
179
+ block.pop("p95")
180
+ return block
181
+
182
+
183
+ # ── Environment fingerprint ─────────────────────────────────────────────────
184
+
185
+
186
+ def collect_env() -> dict[str, object]:
187
+ """Capture the fields that make a baseline comparable only to same-host runs.
188
+
189
+ ``hostname_hash`` (not the raw hostname) groups same-machine runs without
190
+ leaking the machine name. Cross-host absolute numbers are recorded, never
191
+ diffed (ADR-0006 §5.4).
192
+ """
193
+ try:
194
+ host = socket.gethostname()
195
+ except OSError:
196
+ host = "unknown"
197
+ return {
198
+ "python": platform.python_version(),
199
+ "os": sys.platform,
200
+ "cpu": platform.processor() or platform.machine() or "unknown",
201
+ "cores": os.cpu_count() or 0,
202
+ "hostname_hash": hashlib.sha256(host.encode("utf-8")).hexdigest()[:8],
203
+ }
204
+
205
+
206
+ # ── perf-baseline-v1 cell builder ───────────────────────────────────────────
207
+
208
+
209
+ def build_baseline_cell(
210
+ *,
211
+ tool_version: str,
212
+ command: str,
213
+ repo: Mapping[str, object],
214
+ mode: str,
215
+ wall_ms_runs: Sequence[float],
216
+ rss_bytes_runs: Sequence[float],
217
+ phase_ms_runs: Sequence[Mapping[str, float]] | None = None,
218
+ env: Mapping[str, object] | None = None,
219
+ captured_at: str | None = None,
220
+ ) -> dict:
221
+ """Assemble one frozen-schema ``perf-baseline-v1`` cell from raw runs.
222
+
223
+ ``wall_ms_runs`` / ``rss_bytes_runs`` hold one value per run. ``phase_ms_runs``
224
+ is one ``{phase: ms}`` mapping per run; when absent, phase timings are emitted
225
+ as ``null`` with an honest ``instrumentation: "absent"`` marker rather than a
226
+ fabricated zero.
227
+ """
228
+ if not wall_ms_runs:
229
+ raise ValueError("wall_ms_runs must be non-empty")
230
+
231
+ phase_ms: dict[str, object] = {}
232
+ if phase_ms_runs:
233
+ for ph in PHASES:
234
+ series = [float(r[ph]) for r in phase_ms_runs if ph in r]
235
+ phase_ms[ph] = _stat_block(series) if series else None
236
+ # Un-attributed time must stay visible: total minus the sum of phases,
237
+ # never hidden inside a phase (ADR-0006 §3).
238
+ unattributed = []
239
+ for i, wall in enumerate(wall_ms_runs):
240
+ if i < len(phase_ms_runs):
241
+ attributed = sum(float(v) for v in phase_ms_runs[i].values())
242
+ unattributed.append(wall - attributed)
243
+ phase_ms["unattributed_p50"] = (
244
+ round(p50(unattributed), 3) if unattributed else None
245
+ )
246
+ else:
247
+ for ph in PHASES:
248
+ phase_ms[ph] = None
249
+ phase_ms["instrumentation"] = "absent"
250
+
251
+ return {
252
+ "schema_version": SCHEMA_VERSION,
253
+ "tool_version": tool_version,
254
+ "captured_at": captured_at or datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
255
+ "command": command,
256
+ "repo": dict(repo),
257
+ "mode": mode,
258
+ "runs": len(wall_ms_runs),
259
+ "wall_ms": {
260
+ "p50": round(p50(wall_ms_runs), 3),
261
+ "p95": round(p95(wall_ms_runs), 3),
262
+ "min": round(float(min(wall_ms_runs)), 3),
263
+ "max": round(float(max(wall_ms_runs)), 3),
264
+ },
265
+ "phase_ms": phase_ms,
266
+ "rss_peak_bytes": _stat_block(rss_bytes_runs) if rss_bytes_runs else None,
267
+ "env": dict(env) if env is not None else collect_env(),
268
+ }
@@ -5118,11 +5118,23 @@ def build_repo_ir(
5118
5118
  _r["security_annotations"] = {"policy": "xml_or_filter_chain"}
5119
5119
 
5120
5120
  # L-6: inject analysis_meta — files_read, lines_read, symbols_analyzed, token_estimate
5121
+ # symbol_kinds is the deterministic per-kind breakdown; classes/methods are the
5122
+ # two rollups the perf harness consumes for cost-per-symbol (ADR-0006). The IR
5123
+ # owns the taxonomy, so the rollup lives here rather than in the harness.
5124
+ _kind_counts: dict[str, int] = {}
5125
+ for _s in all_symbols:
5126
+ _k = _s.symbol_kind or "unknown"
5127
+ _kind_counts[_k] = _kind_counts.get(_k, 0) + 1
5128
+ _TYPE_KINDS = ("class", "interface", "enum", "annotation", "record")
5129
+ _METHOD_KINDS = ("method", "constructor")
5121
5130
  ir["analysis_meta"] = {
5122
5131
  "files_read": _meta_files_read,
5123
5132
  "lines_read": _meta_lines_read,
5124
5133
  "symbols_analyzed": len(all_symbols),
5125
5134
  "token_estimate": _meta_chars_read // 4, # 4 chars ≈ 1 token (rough approximation)
5135
+ "symbol_kinds": {k: _kind_counts[k] for k in sorted(_kind_counts)},
5136
+ "classes": sum(_kind_counts.get(k, 0) for k in _TYPE_KINDS),
5137
+ "methods": sum(_kind_counts.get(k, 0) for k in _METHOD_KINDS),
5126
5138
  }
5127
5139
  if emit_body_facts:
5128
5140
  # Additive, in-memory only: not a cir_hash input, not serialized by the
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 2.5.15
3
+ Version: 2.5.16
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
@@ -1,20 +1,20 @@
1
- sourcecode/__init__.py,sha256=TA67wvVQzG1GVLowfrLngK0bKQZu-eJyvWrAm5PiAdg,309
1
+ sourcecode/__init__.py,sha256=1AEidIhoB0bOc0Hb9b3t-h8cPmjSPMex9CxZXJhKi98,309
2
2
  sourcecode/adaptive_scanner.py,sha256=XffluXKzJUXrMtjEiAOnSNPZnztdIcts17T9ouHeID0,10521
3
3
  sourcecode/archetype.py,sha256=d7yoN6Tj4OBj-VgSMPEKg4WF9H8FypnZ5A6AkUh5oIE,34484
4
4
  sourcecode/architecture_analyzer.py,sha256=GFc4ek-s1IHWM7pl-0L32WahZ93AmDgrAMcOuBKA5Dk,61463
5
5
  sourcecode/architecture_summary.py,sha256=BVVRHd952cjRhjHnR6CPrvKgaa-tdM16l-pBi1yDCPs,32395
6
- sourcecode/ast_extractor.py,sha256=FEsYTsMCXbJfSYQZRk1k-I-PjUNGnKqO1IxMftsgA5U,51351
6
+ sourcecode/ast_extractor.py,sha256=gBxHVDdmY5o6lcBxawYYA-2CpGbcJ8EEAewGLi5CfQ4,51477
7
7
  sourcecode/cache.py,sha256=1V3vsaODAa2UBJAC0xpvxpmRdriCezQx5Q8JCcfgziE,31892
8
8
  sourcecode/call_surface.py,sha256=fiqYfHooxN1fX9oQoysq1LS3LoZcobhyUNjAGEZKpwk,4148
9
9
  sourcecode/caller_metrics.py,sha256=HG8RCOkpzzsEGdnMRob6byrwjoj5__t0TEsBj4yR7ks,2574
10
10
  sourcecode/canonical_ir.py,sha256=LdP_Ri3rl0M5p-MY0ypVvQwhq1WuUF1FmaHid7zyzEg,29807
11
11
  sourcecode/cir_graphs.py,sha256=9G0HHj1kw2325IDyzo2OpX73BNswEckecf4MZUXB4JM,12078
12
12
  sourcecode/classifier.py,sha256=JBzPwSSrDG-tUHAbcKB678HRbjLpD-ohzbzzO62mgpo,20114
13
- sourcecode/cli.py,sha256=LKK4czUeENVlcxHpSd5xao2HnAgtbRSYo8OoSwcZeZg,324334
13
+ sourcecode/cli.py,sha256=QH7K8Uw19z5o7eXFPvVcC8ZA1KNUHS0bVL_IdOYC2CQ,324702
14
14
  sourcecode/code_notes_analyzer.py,sha256=EJemNCNc9Dn-1RZYu-aNbK0ELzmsyC4s6FdHi3XyNEI,9392
15
15
  sourcecode/confidence_analyzer.py,sha256=vnbPI-20FnHdjO6STxHW8fbaxmB4A7y58io63ibFZjc,21586
16
16
  sourcecode/context_cache.py,sha256=maws79rLKDwyZ7c9Q2LwlIxqZHRFlaKzErtO3mglWoA,25036
17
- sourcecode/context_graph.py,sha256=WFtUvfxoE8XtQxtRJLvaF4SJuS00ICjNoTk0sH2_V5U,44454
17
+ sourcecode/context_graph.py,sha256=i2kOX3XiaCqcR20ojbUnqoX-hJbMyLNYc7rl-n15bwE,46426
18
18
  sourcecode/context_scorer.py,sha256=QpChSpsmaAYz91rXA4Ue5xzQmNz_ZboZN09YOHScq1U,14679
19
19
  sourcecode/context_summarizer.py,sha256=cI2TZMvEhl0BEma12VtPaX6z03ZVBAetVzuK5GaCOvg,6852
20
20
  sourcecode/contract_model.py,sha256=nRxJKPMs1VHwFTa8AVXhGmaLjti3Lr2sjHDpWgv1bfE,3917
@@ -46,6 +46,7 @@ sourcecode/migrate_check.py,sha256=HJhvHuvXDGTJSRQU9_AMx0L94h2TImC1DCGs3m3RTu0,1
46
46
  sourcecode/openapi_surface.py,sha256=BTt0K-woZbkbWTN77IkqeBm_Okag9owR0848fmot8sk,16207
47
47
  sourcecode/output_budget.py,sha256=Js9yUlfQtPhqBl9R6wn_9UHVjjJc3GtLcqyfjf5t50Q,9869
48
48
  sourcecode/path_filters.py,sha256=qPKO7kRmVp2y9zjLNSuAVCbcpZrIInHE4QulLUlzPFI,10412
49
+ sourcecode/perf.py,sha256=GAcEoouPIlPMCQIcHNToxK6K3WdIR-lj9aFg4prOYJI,9743
49
50
  sourcecode/pr_comment_renderer.py,sha256=KmcjMruhR44gjzMDJwjBSkWP9QEvh8xWBLyxzxoRbj0,14542
50
51
  sourcecode/pr_impact.py,sha256=dCDVw83EDbyVf6F9ZmEQmsFz8ruVH7d4mpeKQCIZHM0,16805
51
52
  sourcecode/prepare_context.py,sha256=-Xu33qCETuqw-OFfT3ukvAtxde7krCjQpn7wR3pbdOg,224290
@@ -56,7 +57,7 @@ sourcecode/redactor.py,sha256=SB4hwIvg8h-hvcqKcDWaZvA-aSyn-at-BIRwa0tUv5E,3227
56
57
  sourcecode/relevance_scorer.py,sha256=0AgEt4KrV73nioMqBgjhGjtY7L2C7L7cSyKtj3IKcrw,9408
57
58
  sourcecode/rename_refactor.py,sha256=h6dNFlB9aZ_3q6heeHBkgXQeXaT03nvPSsYH6P8qxFg,12965
58
59
  sourcecode/repo_classifier.py,sha256=FG1vaWKdWXsWdl-S8hjVMiTqcwgaRXkDyvK4rPcOGtQ,22681
59
- sourcecode/repository_ir.py,sha256=3hpxzOrudflSteYDLMQHK7KWdXg6mhhVwG94JSn7FHY,312825
60
+ sourcecode/repository_ir.py,sha256=mLsnKeZkbsEF2Jzl7FOKMtzo4lR9UTyrk2KhbeL4FcE,313566
60
61
  sourcecode/ris.py,sha256=Hw8TakTQ6hku-Abf2k8954NwkrH_sP73_8wVH8x5khc,22079
61
62
  sourcecode/runtime_classifier.py,sha256=uTAD6BDCiBLUZEDRfqk718kM4RTT_vAbfkcOI2_Xx58,18432
62
63
  sourcecode/scanner.py,sha256=WdOQ78mMzjR1NjmKTlbxdgwinnCTfAhxCVLBEFQiFHU,8899
@@ -137,8 +138,8 @@ sourcecode/telemetry/consent.py,sha256=LIAO9ohJZF8OuZwM4u1VWtALlYfTCCKq4wV3Vwc7i
137
138
  sourcecode/telemetry/events.py,sha256=LtzYfaX9Ilckj5PTvAcTpDa9mLqDsYPDUiDkRa58piY,2580
138
139
  sourcecode/telemetry/filters.py,sha256=NHa5T-6DaZduQPFuC34jOqHWQgSizM-Ygq8aZ4j19ng,5834
139
140
  sourcecode/telemetry/transport.py,sha256=4gGHsq0WeY9VywEZXA3vUxykfiYnw9uuqfjAAec7F8o,1681
140
- sourcecode-2.5.15.dist-info/METADATA,sha256=lClKdlUiQRzl134vAQzx_Nvdk0pfm5mGK0pfIT0FIxs,10852
141
- sourcecode-2.5.15.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
142
- sourcecode-2.5.15.dist-info/entry_points.txt,sha256=-JEAdChrK5We51kZcb7OaDcyil-dHBjBPL-NhuO-QY8,89
143
- sourcecode-2.5.15.dist-info/licenses/LICENSE,sha256=7DdHrU9Z_3e7dSvq4ISijZNjnuHo5NIHNiHDouMQ9JU,10491
144
- sourcecode-2.5.15.dist-info/RECORD,,
141
+ sourcecode-2.5.16.dist-info/METADATA,sha256=zog1kb8UlXASniP5jKFyloD-2tLZ-sLMt80zRHaDqo0,10852
142
+ sourcecode-2.5.16.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
143
+ sourcecode-2.5.16.dist-info/entry_points.txt,sha256=-JEAdChrK5We51kZcb7OaDcyil-dHBjBPL-NhuO-QY8,89
144
+ sourcecode-2.5.16.dist-info/licenses/LICENSE,sha256=7DdHrU9Z_3e7dSvq4ISijZNjnuHo5NIHNiHDouMQ9JU,10491
145
+ sourcecode-2.5.16.dist-info/RECORD,,