sourcecode 4.3.0__py3-none-any.whl → 4.5.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 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__ = "4.3.0"
7
+ __version__ = "4.5.0"
sourcecode/cli.py CHANGED
@@ -4885,6 +4885,12 @@ def endpoints_cmd(
4885
4885
  False, "--by-controller",
4886
4886
  help="Group endpoints by controller class (structured API surface for C4/Container synthesis).",
4887
4887
  ),
4888
+ servlets: bool = typer.Option(
4889
+ False, "--servlets",
4890
+ help="Also list the HTTP surface mounted as a servlet — `web.xml` mappings "
4891
+ "and ServletRegistrationBean registrations (NC-007). Published as a "
4892
+ "population of its own; never merged into the endpoint count.",
4893
+ ),
4888
4894
  client_usage: bool = typer.Option(
4889
4895
  False, "--client-usage",
4890
4896
  help="Join the routes against the HTTP calls written in the TypeScript/"
@@ -5001,6 +5007,14 @@ def endpoints_cmd(
5001
5007
  # exists to remove, one line into its own implementation (R5-R8).
5002
5008
  data["exposure"] = _endpoint_exposure_summary(_selected)
5003
5009
 
5010
+ # CL-12 admission half. NC-007 declared this population in 4.2.0; this lists it,
5011
+ # under its own name and its own total, because the two things counted are not the
5012
+ # same kind of thing and `endpoints.total` is a published figure.
5013
+ if servlets:
5014
+ from sourcecode.servlet_surface import build_servlet_surface
5015
+
5016
+ data["servlet_surface"] = build_servlet_surface(target)
5017
+
5004
5018
  # M10.5 item 4. On a large surface the cheapest reduction of exposure is
5005
5019
  # deleting API nobody calls, and in a monorepo the caller is checked in next
5006
5020
  # to the callee. Joined over the population the filters chose, for the same
sourcecode/envelope.py CHANGED
@@ -201,3 +201,38 @@ def attach_meta(payload: "dict[str, Any]", meta: "dict[str, Any]") -> "dict[str,
201
201
  else:
202
202
  payload[_META_KEY] = dict(meta)
203
203
  return payload
204
+
205
+
206
+ #: The specification document is *rendered* from the schema, never written beside it.
207
+ #: Audit #8 called the envelope "el activo estratégico más subestimado del producto" and
208
+ #: the asymmetry is the point: a format that makes `basis`, `limitations` and `unit`
209
+ #: mandatory is one an incumbent cannot adopt without confessing. A spec that drifts from
210
+ #: the implementation is worth nothing to the people asked to adopt it, so the document
211
+ #: below is generated from the same JSON Schema `ask schema envelope-v1` prints, and the
212
+ #: battery fails when the published copy no longer matches.
213
+ SPEC_BEGIN = "<!-- BEGIN GENERATED: ask schema envelope-v1 -->"
214
+ SPEC_END = "<!-- END GENERATED -->"
215
+
216
+
217
+ def render_spec_markdown(name: str = "envelope-v1") -> str:
218
+ """The field table of a published schema, as Markdown."""
219
+ schema = load_schema(name)
220
+ required = set(schema.get("required", ()))
221
+ lines = [
222
+ f"**Schema id:** `{schema.get('$id', name)}`",
223
+ "",
224
+ schema.get("description", "").strip(),
225
+ "",
226
+ "| Field | Required | Type | Meaning |",
227
+ "|---|---|---|---|",
228
+ ]
229
+ for field, spec in schema.get("properties", {}).items():
230
+ kind = spec.get("type", "")
231
+ if isinstance(kind, list):
232
+ kind = " \\| ".join(kind)
233
+ meaning = " ".join(str(spec.get("description", "")).split())
234
+ lines.append(
235
+ f"| `{field}` | {'yes' if field in required else 'no'} | "
236
+ f"{kind or '—'} | {meaning} |"
237
+ )
238
+ return "\n".join(lines) + "\n"
@@ -172,11 +172,12 @@ NON_COVERAGE: tuple[NonCoverage, ...] = (
172
172
  "declared before it is widened."
173
173
  ),
174
174
  instead=(
175
- "Read the deployment descriptors for `<servlet-mapping>` entries and "
176
- "the Spring configuration for `ServletRegistrationBean` beans. Field "
177
- "evaluation #9 found a monitoring console mounted this way, behind a "
178
- "credential `ask spring-audit` did report (SEC-007) at a path nothing "
179
- "here listed."
175
+ "`ask endpoints --servlets` lists that surface as a population of its "
176
+ "own — `<servlet-mapping>` entries and `ServletRegistrationBean` "
177
+ "registrations, with the declaring file — and never merges it into the "
178
+ "endpoint count. Field evaluation #9 found a monitoring console mounted "
179
+ "this way, behind a credential `ask spring-audit` did report (SEC-007) "
180
+ "at a path nothing here listed."
180
181
  ),
181
182
  ),
182
183
  NonCoverage(
@@ -23,6 +23,14 @@ _TEST_MODULE_SEGMENTS = frozenset({
23
23
  "test-support", "testsupport",
24
24
  })
25
25
 
26
+ #: `spec/` means a test suite in the RSpec/Jasmine sense — and it means the opposite
27
+ #: under a documentation root, where a *specification* lives. Found in this repository:
28
+ #: `docs/spec/envelope-v1.md`, the published output-format specification, was classified
29
+ #: as a test file and counted in the test population of the tool's own metrics. The
30
+ #: segment keeps its meaning everywhere else; only these parents disarm it.
31
+ _DOC_ROOT_SEGMENTS = frozenset({"docs", "doc", "documentation"})
32
+ _AMBIGUOUS_TEST_SEGMENTS = frozenset({"spec", "specs"})
33
+
26
34
  _VENDOR_SEGMENTS = frozenset({
27
35
  "vendor", "vendors",
28
36
  "third_party", "thirdparty",
@@ -73,10 +81,15 @@ def is_test_path(path: str) -> bool:
73
81
 
74
82
  # Segment-based check – any directory component is a test segment
75
83
  parts = norm.split("/")
84
+ seen: set[str] = set()
76
85
  for part in parts[:-1]: # skip filename itself
77
86
  bare = part.rstrip("/")
87
+ if bare in _AMBIGUOUS_TEST_SEGMENTS and seen & _DOC_ROOT_SEGMENTS:
88
+ seen.add(bare)
89
+ continue # a specification under `docs/`, not a spec suite
78
90
  if bare in _TEST_SEGMENTS:
79
91
  return True
92
+ seen.add(bare)
80
93
 
81
94
  # File-name conventions
82
95
  name = parts[-1]
sourcecode/remedies.py CHANGED
@@ -97,6 +97,18 @@ REMEDIES: "dict[str, Remedy]" = {
97
97
  ),
98
98
  headline="derive contracts, write nothing",
99
99
  ),
100
+ Remedy(
101
+ key="http_surface_that_is_not_a_handler_mapping",
102
+ command="endpoints",
103
+ option="--servlets",
104
+ answers=(
105
+ "the endpoint population is Spring handler mappings; to list the HTTP "
106
+ "surface mounted as a servlet instead — `web.xml` mappings and "
107
+ "`ServletRegistrationBean` registrations — as its own population, never "
108
+ "merged into the endpoint count"
109
+ ),
110
+ headline="servlet-mounted HTTP surface",
111
+ ),
100
112
  )
101
113
  }
102
114
 
@@ -0,0 +1,194 @@
1
+ """servlet_surface.py — HTTP surface that is not a Spring handler mapping.
2
+
3
+ Field evaluation #9's second finding was a monitoring console mounted at
4
+ `/panel-de-control` through a `<servlet-mapping>` in `web.xml`, behind a credential
5
+ `spring-audit` did report (SEC-007) at a path **nothing in this product listed**. The
6
+ endpoint population is projected from the Spring route model — one entry per handler
7
+ mapping — and a servlet is reachable over HTTP without being in that model.
8
+
9
+ `NC-007` (4.2.0) declared that gap. This module is its admission half, and the rule
10
+ that shaped it is the reason the declaration came first: **this population is never
11
+ merged into `endpoints.total`**. That count, and every ratio keyed on it, is published
12
+ and read; widening it silently would move numbers a reader has already acted on, and
13
+ the two things counted are not the same kind of thing — a Spring handler has a
14
+ controller, a handler symbol and a security verdict derived from the filter chain; a
15
+ servlet mapping has a URL pattern and a class name, and nothing here resolves what
16
+ guards it.
17
+
18
+ So the answer is a second, named population beside the first, with its own total.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import re
24
+ from dataclasses import dataclass
25
+ from pathlib import Path
26
+ from typing import Optional
27
+ from xml.etree import ElementTree as ET
28
+
29
+ SCHEMA_VERSION = "servlet-surface-v1"
30
+
31
+ _SKIP_DIRS = frozenset({".git", "target", "build", "out", "node_modules", "dist"})
32
+
33
+ #: `new ServletRegistrationBean<>(new Foo(), "/path/*")` and the `addUrlMappings` form.
34
+ _REGISTRATION_BEAN = re.compile(
35
+ r"""ServletRegistrationBean\s*(?:<[^>]*>)?\s*\(\s*(?P<args>[^;]{0,400}?)\)\s*;""",
36
+ re.DOTALL,
37
+ )
38
+ _URL_MAPPINGS = re.compile(
39
+ r"""(?:addUrlMappings|setUrlMappings)\s*\(\s*(?P<args>[^;]{0,300}?)\)""", re.DOTALL
40
+ )
41
+ _STRING_LITERAL = re.compile(r"""["']([^"']{1,200})["']""")
42
+
43
+
44
+ @dataclass(frozen=True)
45
+ class ServletMapping:
46
+ """One servlet reachable over HTTP, and where it was declared."""
47
+
48
+ url_pattern: str
49
+ servlet_name: str
50
+ servlet_class: str
51
+ source_file: str
52
+ source: str # "web.xml" | "servlet_registration_bean"
53
+
54
+ def to_dict(self) -> dict:
55
+ return {
56
+ "url_pattern": self.url_pattern,
57
+ "servlet_name": self.servlet_name,
58
+ "servlet_class": self.servlet_class,
59
+ "source_file": self.source_file,
60
+ "source": self.source,
61
+ }
62
+
63
+
64
+ def _local(tag: str) -> str:
65
+ return tag.rsplit("}", 1)[-1]
66
+
67
+
68
+ def _child_text(elem: "ET.Element", name: str) -> str:
69
+ for child in elem.iter():
70
+ if _local(child.tag) == name and (child.text or "").strip():
71
+ return child.text.strip()
72
+ return ""
73
+
74
+
75
+ def _from_web_xml(xml_path: Path, relative: str) -> "list[ServletMapping]":
76
+ try:
77
+ root = ET.parse(str(xml_path)).getroot()
78
+ except Exception:
79
+ return []
80
+ classes: "dict[str, str]" = {}
81
+ for elem in root.iter():
82
+ if _local(elem.tag) != "servlet":
83
+ continue
84
+ name = _child_text(elem, "servlet-name")
85
+ klass = _child_text(elem, "servlet-class")
86
+ if name:
87
+ classes[name] = klass
88
+ out: "list[ServletMapping]" = []
89
+ for elem in root.iter():
90
+ if _local(elem.tag) != "servlet-mapping":
91
+ continue
92
+ name = _child_text(elem, "servlet-name")
93
+ for child in elem.iter():
94
+ if _local(child.tag) != "url-pattern" or not (child.text or "").strip():
95
+ continue
96
+ out.append(ServletMapping(
97
+ url_pattern=child.text.strip(),
98
+ servlet_name=name,
99
+ servlet_class=classes.get(name, ""),
100
+ source_file=relative,
101
+ source="web.xml",
102
+ ))
103
+ return out
104
+
105
+
106
+ def _from_registration_beans(java_path: Path, relative: str) -> "list[ServletMapping]":
107
+ try:
108
+ text = java_path.read_text(encoding="utf-8", errors="replace")
109
+ except OSError:
110
+ return []
111
+ if "ServletRegistrationBean" not in text:
112
+ return []
113
+ out: "list[ServletMapping]" = []
114
+ for match in _REGISTRATION_BEAN.finditer(text):
115
+ args = match.group("args")
116
+ literals = _STRING_LITERAL.findall(args)
117
+ patterns = [lit for lit in literals if lit.startswith("/")]
118
+ klass = ""
119
+ new_call = re.search(r"new\s+([A-Z][\w.]*)\s*\(", args)
120
+ if new_call:
121
+ klass = new_call.group(1)
122
+ for pattern in patterns:
123
+ out.append(ServletMapping(
124
+ url_pattern=pattern, servlet_name="", servlet_class=klass,
125
+ source_file=relative, source="servlet_registration_bean",
126
+ ))
127
+ for match in _URL_MAPPINGS.finditer(text):
128
+ for literal in _STRING_LITERAL.findall(match.group("args")):
129
+ if literal.startswith("/"):
130
+ out.append(ServletMapping(
131
+ url_pattern=literal, servlet_name="", servlet_class="",
132
+ source_file=relative, source="servlet_registration_bean",
133
+ ))
134
+ return out
135
+
136
+
137
+ def build_servlet_surface(root: Path, *, limit: Optional[int] = None) -> dict:
138
+ """Every servlet-mapped URL pattern under `root`, as a population of its own."""
139
+ from sourcecode import non_coverage
140
+
141
+ root = Path(root)
142
+ mappings: "list[ServletMapping]" = []
143
+ for path in sorted(root.rglob("*")):
144
+ if any(part in _SKIP_DIRS for part in path.parts) or not path.is_file():
145
+ continue
146
+ try:
147
+ relative = str(path.relative_to(root))
148
+ except ValueError:
149
+ relative = str(path)
150
+ if path.name == "web.xml":
151
+ mappings.extend(_from_web_xml(path, relative))
152
+ elif path.suffix == ".java":
153
+ mappings.extend(_from_registration_beans(path, relative))
154
+
155
+ # One URL pattern declared twice is two declarations of one reachable path; the
156
+ # census counts patterns, the rows keep every declaration.
157
+ patterns = sorted({m.url_pattern for m in mappings})
158
+ by_source: "dict[str, int]" = {}
159
+ for mapping in mappings:
160
+ by_source[mapping.source] = by_source.get(mapping.source, 0) + 1
161
+
162
+ rows = [m.to_dict() for m in sorted(
163
+ mappings, key=lambda m: (m.url_pattern, m.source_file)
164
+ )]
165
+ shown = rows if limit is None else rows[:limit]
166
+
167
+ return {
168
+ "schema_version": SCHEMA_VERSION,
169
+ "total_url_patterns": len(patterns),
170
+ "declarations": len(mappings),
171
+ "by_source": dict(sorted(by_source.items())),
172
+ "url_patterns": patterns,
173
+ "mappings": shown,
174
+ "mappings_omitted": len(rows) - len(shown),
175
+ "population": (
176
+ "servlet mappings declared in `web.xml` or registered as a "
177
+ "`ServletRegistrationBean` — HTTP surface that is NOT a Spring handler "
178
+ "mapping and is therefore in none of the endpoint counts"
179
+ ),
180
+ "never_merged": (
181
+ "This total is deliberately separate from `endpoints.total`. The two count "
182
+ "different things — a handler mapping has a controller, a handler symbol "
183
+ "and a security verdict derived from the chain; a servlet mapping has a URL "
184
+ "pattern and a class — and merging them would move a published count and "
185
+ "every ratio keyed on it."
186
+ ),
187
+ "access": (
188
+ "Nothing here resolves what guards these patterns. A servlet is matched by "
189
+ "the same filter chain as everything else, so a filter pattern that covers "
190
+ "it may or may not authenticate it; `ask spring-audit` reports credentials "
191
+ "found in the same descriptors (SEC-007)."
192
+ ),
193
+ "non_coverage": non_coverage.block("endpoints"),
194
+ }
@@ -52,6 +52,14 @@ _TEST_DIR_NAMES: frozenset[str] = frozenset(
52
52
  {"test", "tests", "spec", "specs", "__tests__"}
53
53
  )
54
54
 
55
+ #: `spec/` is a test suite in the RSpec/Jasmine sense — and the opposite under a
56
+ #: documentation root, where a *specification* lives. Found by this project's own suite
57
+ #: when `docs/spec/envelope-v1.md` (the published output-format specification) landed in
58
+ #: the test population of the tool's own metrics. Only these parents disarm the segment;
59
+ #: `spec/` keeps its meaning everywhere else, and `docs/tests/` is still tests.
60
+ _DOC_ROOT_NAMES: frozenset[str] = frozenset({"docs", "doc", "documentation"})
61
+ _AMBIGUOUS_TEST_DIR_NAMES: frozenset[str] = frozenset({"spec", "specs"})
62
+
55
63
  # A directory named `test` under one of these is production code, not a test.
56
64
  _MAIN_ROOT_SEGMENTS: tuple[tuple[str, ...], ...] = (
57
65
  ("src", "main"),
@@ -99,8 +107,13 @@ def declared_test_root(path: str) -> "str | None":
99
107
  # A `test` package inside a main source root is production code.
100
108
  return None
101
109
  for i, part in enumerate(parts[:-1]):
102
- if part in _TEST_DIR_NAMES:
103
- return "/".join(parts[:i + 1])
110
+ if part not in _TEST_DIR_NAMES:
111
+ continue
112
+ if part in _AMBIGUOUS_TEST_DIR_NAMES and (
113
+ set(parts[:i]) & _DOC_ROOT_NAMES
114
+ ):
115
+ continue # a specification under `docs/`, not a spec suite
116
+ return "/".join(parts[:i + 1])
104
117
  return None
105
118
 
106
119
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 4.3.0
3
+ Version: 4.5.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
@@ -387,6 +387,12 @@ And one about who calls a route:
387
387
  |---|---|---|
388
388
  | **Whether a route is called from outside this repository — another service, a mobile app, a partner, a cron job, or a client whose URL is assembled at run time.** | The join reads the TypeScript/JavaScript checked in beside the server and only the call shapes whose verb and path are written at the call site. That is a floor on who calls a route and can never be a ceiling: the repository cannot observe consumers it does not contain. So a route with no call site here is published as a candidate for deletion, never as dead API. | Access logs or an API gateway answer who really calls a route. The opposite direction is decisive without them: a client call matching no route is a request this repository's own front end makes and its server does not serve. |
389
389
 
390
+ The one row above with a remedy in this build: `ask endpoints /path/to/repo --servlets`
391
+ lists the servlet-mounted HTTP surface as a population of its own — `web.xml` mappings and
392
+ `ServletRegistrationBean` registrations, with the file that declares each — and never merges
393
+ it into `endpoints.total`. Measured: openmrs-core 7 patterns, alfresco-community-repo 11,
394
+ including `/api/*` served by a WebScript servlet.
395
+
390
396
  **Positioning.** Until an executor ships, this is the **diagnosis layer**: it measures what
391
397
  must change, what each change reaches, and what a gate should block — and it removes none of
392
398
  it. Field evaluation scored it 7/10 as a report generator and 5.5/10 as a development tool,
@@ -479,3 +485,4 @@ Matching endpoints report `policy: "custom"` and drop out of the `no_security_si
479
485
  | [PRODUCT_IDENTITY.md](docs/PRODUCT_IDENTITY.md) | `ask` (command) vs `sourcecode` (package/alias) |
480
486
  | [privacy.md](docs/privacy.md) | Telemetry and data-handling policy |
481
487
  | [DEFECT-LEDGER.md](docs/DEFECT-LEDGER.md) | Every defect found in the field, its class, and which release closed it — published on purpose |
488
+ | [spec/envelope-v1.md](docs/spec/envelope-v1.md) | The output format as an **open specification** — provenance, a named unit, a stated basis, declared non-coverage. Implementable by tools that are not this one; the field table is generated from the schema `ask schema envelope-v1` prints |
@@ -1,4 +1,4 @@
1
- sourcecode/__init__.py,sha256=VzE3y83kXkJoA93WrV4CYV_6qTGSQOQGTFSYee-Wiz8,308
1
+ sourcecode/__init__.py,sha256=GuicP24rR0BJLjvNn6DvgAV9JfkUtm-vrQYsnQfw6NM,308
2
2
  sourcecode/adaptive_scanner.py,sha256=yJBKjNpkY6bpueYJ2YnRezen3sYZDecEt7WaaNWdqug,9466
3
3
  sourcecode/archetype.py,sha256=HBGTTaS-bVHS6pdacPUMKcMxklkDEKnZMgz48Kc3yec,37630
4
4
  sourcecode/architectural_baseline.py,sha256=agDSwGEakdkgLLh5xnd3hiD_TC6pRujWt4klnuYF1wo,18689
@@ -17,7 +17,7 @@ sourcecode/chain_rules.py,sha256=Bi6UHfgd-GxWswmnHRcPz5jdbAuqka3Zkz_P-MTvqhw,127
17
17
  sourcecode/change_plan.py,sha256=kFjjp16XYbupgkv1CPkfqo39_SiZPMRQ8OOfC-Vy9eg,7929
18
18
  sourcecode/cir_graphs.py,sha256=9G0HHj1kw2325IDyzo2OpX73BNswEckecf4MZUXB4JM,12078
19
19
  sourcecode/classifier.py,sha256=JBzPwSSrDG-tUHAbcKB678HRbjLpD-ohzbzzO62mgpo,20114
20
- sourcecode/cli.py,sha256=1iYGmrAvmN3lW1gWL3xVLo-tTj2VR92Sqa_k7rmuejA,482834
20
+ sourcecode/cli.py,sha256=PGcg9XkNh4D52gvoXaAlTLa5G-HWGmVfXyS3w9tG05k,483546
21
21
  sourcecode/client_calls.py,sha256=fb5fvmryrBQlly2ETyLcjoQcyzQTPxZ38jYx47V_yqs,13293
22
22
  sourcecode/code_notes_analyzer.py,sha256=EJemNCNc9Dn-1RZYu-aNbK0ELzmsyC4s6FdHi3XyNEI,9392
23
23
  sourcecode/compare.py,sha256=xq3zsqAOAw4AWkoD9khb9xDP_O3KvwqO9k-pf8sbi3g,10951
@@ -44,7 +44,7 @@ sourcecode/endpoint_literals.py,sha256=Qf4gTZzvNSFDGDuOvF0YRL9NvaYKKj24klhR5LIOa
44
44
  sourcecode/endpoint_metrics.py,sha256=sLSLUIgiIyvNdOynaxVgHd9SjRF_DbN3QxevaquykaU,2840
45
45
  sourcecode/entrypoint_classifier.py,sha256=jhTYlyqDJH2AtdEcLVaRU3lYRTJuF8DkxVzl4-W3zWE,5322
46
46
  sourcecode/env_analyzer.py,sha256=oLz4gDUE3BHlRRn6Qj4rnbjwyYjIZ0nlqO_SBQwL_H8,21999
47
- sourcecode/envelope.py,sha256=IIUY6q_VPGsDfmlZri1GORXcYiAKvQepGoI-B0N0orE,7372
47
+ sourcecode/envelope.py,sha256=fpF_8znvPqGXKZb0UPYcCYjm27yO7Pr-WsdXNE-tEoY,8911
48
48
  sourcecode/environment_resolution.py,sha256=2cEsF741-Cb6PR9Hiv57BpOTWl4gEnHMQsiRzcNcjJM,18872
49
49
  sourcecode/error_schema.py,sha256=uwosfNaSujtYm11_732Hu92z5ITV040fQDaIyefSvR4,1683
50
50
  sourcecode/evidence_provider.py,sha256=GSSL44JEaouO5AHks2sB3d1YvC9xIKIld1yBYxZpXxo,4277
@@ -67,13 +67,13 @@ sourcecode/mcp_nudge.py,sha256=lKemOqK_wny2u7Ymcr2Idi5Kx8pXY02jCi-_nJYLGMg,2992
67
67
  sourcecode/metrics_analyzer.py,sha256=gLoRWKygF18jLgwsqmGXSWopw-f5iO1VbM7Jjdif6ag,22809
68
68
  sourcecode/migrate_check.py,sha256=jMv1GMhMthpHCnoEtkKWHiIC2Not2kdbU4UaA9sWX7I,134643
69
69
  sourcecode/migration_blast.py,sha256=OPryWkM6-PbvcG3eJFdcWUnlpXBje41nu2BkrZnE2hg,9359
70
- sourcecode/non_coverage.py,sha256=W2q9-T6wXwCuKK2nVrcJ1lRVqzIKWDQtIZworGdFI_c,11715
70
+ sourcecode/non_coverage.py,sha256=lQZCdvHz4c_Gr0PIugkybOvSVwiaWvpCesq2p_9HtNk,11823
71
71
  sourcecode/openapi_surface.py,sha256=BTt0K-woZbkbWTN77IkqeBm_Okag9owR0848fmot8sk,16207
72
72
  sourcecode/openrewrite_recipe.py,sha256=4dyY5twRB6Xew-G9Zy5FafNZwlMU1S7DnRa2FqPkhpQ,12233
73
73
  sourcecode/output_budget.py,sha256=__DQrIg7MGsYrd0_S3lyd3AG0a0jWNGr55v5Gg9kK0U,12347
74
74
  sourcecode/parse_cache.py,sha256=SnHOhNTvAqHm_PXImPVBuj7NEoOQRn8dfIZHEqOFENs,7565
75
75
  sourcecode/path_admission.py,sha256=OGNSoluhVh8YYOBZBnACUrkmH4Tp_yxjGLifkcsxQpo,5838
76
- sourcecode/path_filters.py,sha256=qPKO7kRmVp2y9zjLNSuAVCbcpZrIInHE4QulLUlzPFI,10412
76
+ sourcecode/path_filters.py,sha256=9yk8fA29sZSPyvI8UjF6fIOY37Hd3hs8txUiNXsQGwg,11182
77
77
  sourcecode/perf.py,sha256=GAcEoouPIlPMCQIcHNToxK6K3WdIR-lj9aFg4prOYJI,9743
78
78
  sourcecode/pipe_contract.py,sha256=PML0Er5d8uDyec4OrdUXuyqHbGPUYndjeaKUjkFz2u4,8369
79
79
  sourcecode/posture.py,sha256=x1LY98XSjZzG4xThZYJYK3e5BTYDmJhyg5eqJ5KquNk,72999
@@ -88,7 +88,7 @@ sourcecode/redactor.py,sha256=SB4hwIvg8h-hvcqKcDWaZvA-aSyn-at-BIRwa0tUv5E,3227
88
88
  sourcecode/reference_facts.py,sha256=Ns495c6eTmq2SrqPkcUrJUJru4_wj_yRWm4YDeJwves,13440
89
89
  sourcecode/release_info.py,sha256=r8GlRnraTQH_olGkdpbCAzBb0B_Js1cRBPaRe7IUoyU,5378
90
90
  sourcecode/relevance_scorer.py,sha256=0AgEt4KrV73nioMqBgjhGjtY7L2C7L7cSyKtj3IKcrw,9408
91
- sourcecode/remedies.py,sha256=-zvOeVllMqhSVT3BzXmSLDwDNrPEv-VJsEzNtMKJ4WI,5034
91
+ sourcecode/remedies.py,sha256=TIYeWD8gFsG_69CF2Qjxgbcx6mivf9TVTm1GqevASWM,5591
92
92
  sourcecode/rename_refactor.py,sha256=h6dNFlB9aZ_3q6heeHBkgXQeXaT03nvPSsYH6P8qxFg,12965
93
93
  sourcecode/repo_classifier.py,sha256=FG1vaWKdWXsWdl-S8hjVMiTqcwgaRXkDyvK4rPcOGtQ,22681
94
94
  sourcecode/repository_ir.py,sha256=uuJsPmtgSEi4MKVKJEiZl8bpvU1QFU2Oslxn96p5xi8,356849
@@ -107,6 +107,7 @@ sourcecode/semantic_impact_engine.py,sha256=t09IirGC3JjQDy33JZd1_WKzQVKXkoNl3-XE
107
107
  sourcecode/semantic_integration_engine.py,sha256=7a0WqAInOv39f0Yr_94TYo_JP_8QpeI9KGaknpzAyQU,18899
108
108
  sourcecode/semantic_services.py,sha256=nbUuPv-F01USTt_9CHT8iy_ucCIw3fz4W3Aquea_pd4,10782
109
109
  sourcecode/serializer.py,sha256=T1-Ybi6aPczxiz11N_nfuZ_jUMQVBMExeWuYHCUjKPc,139222
110
+ sourcecode/servlet_surface.py,sha256=XokdtUFeqCpFfD1nZHJSnJsDgrQMuVOYzM72eoaAHpM,7708
110
111
  sourcecode/spring_event_topology.py,sha256=5_ON_21Le5zbG-1GRc5GLIi5HJfy_QjcXLVPC5WeUGQ,18055
111
112
  sourcecode/spring_findings.py,sha256=qgWz4LLL5TFe3eG-mTttlrDTx-6ps3EOuLA-S2HvQCM,16945
112
113
  sourcecode/spring_impact.py,sha256=KkThpPmBbBJk_1H8f0cVWOuz6vBN-yX5qcTQ3Sjmjnk,74797
@@ -119,7 +120,7 @@ sourcecode/spring_tx_analyzer.py,sha256=_wqjRktqdPS6PiXXxtTkCD1t6BaE2uhqx6ioYY-U
119
120
  sourcecode/summarizer.py,sha256=0aD4x3vgPngqBCEBKGuES1J2Vk5f7mqCm_ZWErwm3js,27025
120
121
  sourcecode/target_admission.py,sha256=wFZ4pzlxhiF6Q6s2lEAZEzcCfj1Y6xNvujjt8MdO0Qo,7154
121
122
  sourcecode/test_gap_ranking.py,sha256=hl-tTyQUXZGJycG1b6npbLeE_DaVHaOsvPwG9qqC5y8,15711
122
- sourcecode/test_sources.py,sha256=2O7LXF-M-CQ0DwEF3B7BfWE6IWmHJngSOES5aRz6WR4,6205
123
+ sourcecode/test_sources.py,sha256=cMGVNLbYZZ2yt2PVcySK4scbjKpCLDAKhIViyWN_pRM,6986
123
124
  sourcecode/token_estimate.py,sha256=RBXCGnF20jMzAeU0rUuf22Ol6y2wdf9q6nfs2sXIn4k,9262
124
125
  sourcecode/tree_utils.py,sha256=8GAkIfQAsvtEudIeW1l4ooH_oRtrWR8cpJQJsEa_Pfw,2093
125
126
  sourcecode/type_usage_surface.py,sha256=51IrKRQoIoRnlsiDjHnqpJBn2rc6E59aRhgS0HTzAF0,4428
@@ -188,8 +189,8 @@ sourcecode/telemetry/consent.py,sha256=pQdl-QeLl6Gcibn0eWHSKZrm-HYSsjpVqOnjrgFp8
188
189
  sourcecode/telemetry/events.py,sha256=4_yeO58U-Cwc1Qb27VB0_EjhmroY0k91n3_VGxeALB8,2776
189
190
  sourcecode/telemetry/filters.py,sha256=RzxauTz8HliO4BllQnXEXc7zTeqdCZi5MgqGEDuW7OQ,6570
190
191
  sourcecode/telemetry/transport.py,sha256=4gGHsq0WeY9VywEZXA3vUxykfiYnw9uuqfjAAec7F8o,1681
191
- sourcecode-4.3.0.dist-info/METADATA,sha256=T75swzEAj9oh9i0jR206k-oOMYRnilGJS2qlTY5gcgY,33052
192
- sourcecode-4.3.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
193
- sourcecode-4.3.0.dist-info/entry_points.txt,sha256=-JEAdChrK5We51kZcb7OaDcyil-dHBjBPL-NhuO-QY8,89
194
- sourcecode-4.3.0.dist-info/licenses/LICENSE,sha256=7DdHrU9Z_3e7dSvq4ISijZNjnuHo5NIHNiHDouMQ9JU,10491
195
- sourcecode-4.3.0.dist-info/RECORD,,
192
+ sourcecode-4.5.0.dist-info/METADATA,sha256=HAJ1Mhhiaf1DpQLb5vLP57WwPBy5t3x-SutNNG4vAkE,33762
193
+ sourcecode-4.5.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
194
+ sourcecode-4.5.0.dist-info/entry_points.txt,sha256=-JEAdChrK5We51kZcb7OaDcyil-dHBjBPL-NhuO-QY8,89
195
+ sourcecode-4.5.0.dist-info/licenses/LICENSE,sha256=7DdHrU9Z_3e7dSvq4ISijZNjnuHo5NIHNiHDouMQ9JU,10491
196
+ sourcecode-4.5.0.dist-info/RECORD,,