sourcecode 2.0.1__py3-none-any.whl → 2.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.
@@ -176,6 +176,28 @@ class JavaDetector(AbstractDetector):
176
176
  frameworks = [f for f in frameworks if f.name != "MyBatis"]
177
177
 
178
178
  entry_points = self._collect_entry_points(context)
179
+
180
+ # C1 (Eureka field test): a repo whose REST surface is JAX-RS / Jakarta
181
+ # REST — declared on the source via @Path/@GET, not through a web framework
182
+ # coordinate in the build manifest — must still surface that in the headline
183
+ # stack. Eureka wires JAX-RS through Jersey 1.x (com.sun.jersey) + jsr311-api
184
+ # + Guice, none of which the manifest-coordinate scan models, and its child
185
+ # build.gradle files are not scanned at all — yet it ships 18 @Path resource
186
+ # classes. Without this the headline read "Java library / package" while the
187
+ # endpoints command listed a full JAX-RS API. When the annotation scan found
188
+ # JAX-RS entry points and no Jakarta-EE framework was inferred from the
189
+ # manifest, surface it so the stack (and project_type) reflect the REST API
190
+ # the endpoints already prove. Structural (VAI): reasons from the JAX-RS
191
+ # entry points found in source, not from a vendor dependency-name allowlist.
192
+ # detected_via carries no path form, so it is treated as repo-wide evidence
193
+ # (never localized to an adapter submodule).
194
+ if not any(f.name == "Jakarta EE" for f in frameworks) and any(
195
+ ep.kind in ("jax_rs_controller", "jax_rs_provider") for ep in entry_points
196
+ ):
197
+ frameworks.append(FrameworkDetection(
198
+ name="Jakarta EE", source="annotation", detected_via=["jax_rs_endpoints"],
199
+ ))
200
+
179
201
  transactional_classes = self._collect_transactional_classes(context, all_paths)
180
202
  stack = StackDetection(
181
203
  stack="java",
@@ -459,7 +481,13 @@ class JavaDetector(AbstractDetector):
459
481
  # 1. @SpringBootApplication entry: Application.java / Main.java by name
460
482
  # Exclude test trees: test helpers like AdminApplication.java in
461
483
  # integration/src/test/java/ must not be treated as production entrypoints.
462
- from sourcecode.path_filters import is_test_path as _is_test_path
484
+ # B2 (openmrs field test): exclude not just src/test/ trees but whole
485
+ # test-harness MODULES whose sources sit under src/main — e.g. openmrs'
486
+ # `test-suite/module/omod/src/main/java/.../TestModuleController.java`, a
487
+ # scaffolding @Controller (`GET /module/testmodule/hello`) that a narrow
488
+ # src/test/ check misses, so it surfaced as a production entry point. The
489
+ # broader is_test_or_fixture_path catches test-suite / *-test / *-it modules.
490
+ from sourcecode.path_filters import is_test_or_fixture_path as _is_test_path
463
491
  # BUG #3 (Alfresco field test): a `*Application.java` / `*Main.java` NAME does
464
492
  # not make a file a bootstrap entry point. Alfresco has XSD-generated JAXB
465
493
  # `Application.java` model classes (no main(), no bootstrap annotation) in a
@@ -0,0 +1,42 @@
1
+ """Single source of truth for the endpoint / route-surface reconciliation note.
2
+
3
+ Three commands report an endpoint count, each from a different point in the
4
+ pipeline. Read side by side they look contradictory (e.g. 245 vs 225 vs 220 for
5
+ one repo) — they are not. Expected ordering for a single repo:
6
+
7
+ repo-ir.route_surface >= endpoints.total >= spring-audit.endpoints_analyzed
8
+
9
+ - ``repo-ir.route_surface`` is the RAW structural surface (every @RequestMapping /
10
+ @Path handler after inheritance projection and JAX-RS sub-resource-locator
11
+ composition). It still contains framework dynamic-admin routes whose path is a
12
+ Java FQN (e.g. ``/org.broadleafcommerce.core.search.domain.FieldImpl``), which
13
+ the ``endpoints`` command filters out — so it is NOT the canonical API surface.
14
+ - ``endpoints.total`` is the canonical REST/API surface (FQN-shaped framework
15
+ routes removed). This is the number to cite for "how many endpoints".
16
+ - ``spring-audit.endpoints_analyzed`` is that canonical surface further deduplicated
17
+ by (method, path, controller, handler) for security analysis.
18
+
19
+ The exact arithmetic between the three is intentionally NOT asserted (the pipelines
20
+ differ in dedup/expansion, so route_surface minus FQN-paths does not equal
21
+ endpoints.total). Only the robust ordering and the population of each are stated.
22
+
23
+ ``spring-audit`` already documents its own count inline; this note gives repo-ir's
24
+ raw ``route_surface`` the same self-description so no reader mistakes it for the
25
+ canonical endpoint total.
26
+ """
27
+
28
+ ENDPOINT_SURFACE_RECONCILIATION: str = (
29
+ "route_surface is the RAW structural route surface: every @RequestMapping/@Path "
30
+ "handler after inheritance projection and JAX-RS sub-resource-locator composition. "
31
+ "It is NOT the canonical API surface — it still contains framework dynamic-admin "
32
+ "routes whose path is a Java FQN (e.g. /org.broadleafcommerce...), which the "
33
+ "`endpoints` command excludes. Endpoint counts differ across commands BY DESIGN "
34
+ "and are not contradictory; expected ordering for one repo is "
35
+ "repo-ir.route_surface (raw, includes FQN-shaped framework routes) >= "
36
+ "endpoints.total (canonical REST/API surface, FQN-shaped routes filtered out) >= "
37
+ "spring-audit.metadata.endpoints_analyzed (canonical surface further deduplicated "
38
+ "by (method, path, controller, handler) for security analysis). Cite "
39
+ "endpoints.total for the real API surface; the pipelines differ in dedup and "
40
+ "prefix expansion, so the three counts are related by this ordering, not by exact "
41
+ "arithmetic."
42
+ )
sourcecode/explain.py CHANGED
@@ -17,6 +17,7 @@ from __future__ import annotations
17
17
  from dataclasses import dataclass, field
18
18
  from typing import TYPE_CHECKING, Optional
19
19
 
20
+ from sourcecode.caller_metrics import CALLER_METRIC_RECONCILIATION
20
21
  from sourcecode.fqn_utils import normalize_owner_fqn
21
22
 
22
23
  if TYPE_CHECKING:
@@ -121,6 +122,7 @@ class ClassExplanation:
121
122
  "purpose": self.purpose,
122
123
  "public_methods": self.public_methods,
123
124
  "incoming_callers": self.incoming_callers,
125
+ "incoming_callers_note": CALLER_METRIC_RECONCILIATION,
124
126
  "outgoing_deps": self.outgoing_deps,
125
127
  "events_published": self.events_published,
126
128
  "events_consumed": self.events_consumed,
sourcecode/license.py CHANGED
@@ -89,9 +89,25 @@ if _SUPABASE_URL != _DEFAULT_SUPABASE_URL:
89
89
  # which case prompts point to the documented Pro plans instead of a placeholder link.
90
90
  _PURCHASE_URL: str = os.environ.get("SOURCECODE_PURCHASE_URL", "").strip()
91
91
 
92
- _LICENSE_DIR: Path = Path.home() / ".sourcecode"
92
+ # Config home: ~/.ask is canonical (product = ASK Engine). The legacy ~/.sourcecode
93
+ # stays READABLE so no existing user loses their license — reads prefer ~/.ask and
94
+ # fall back to ~/.sourcecode; writes always land in ~/.ask. Backward-compatible.
95
+ _LICENSE_DIR: Path = Path.home() / ".ask"
96
+ _LEGACY_LICENSE_DIR: Path = Path.home() / ".sourcecode"
93
97
  _LICENSE_FILE: Path = _LICENSE_DIR / "license.json"
94
98
  _DELTA_RUNS_FILE: Path = _LICENSE_DIR / "delta_runs.json"
99
+
100
+
101
+ def _read_config_path(name: str) -> Path:
102
+ """Existing config file for `name`, preferring ~/.ask, else legacy ~/.sourcecode.
103
+ Returns the canonical ~/.ask path when neither exists (write target)."""
104
+ new = _LICENSE_DIR / name
105
+ if new.exists():
106
+ return new
107
+ legacy = _LEGACY_LICENSE_DIR / name
108
+ if legacy.exists():
109
+ return legacy
110
+ return new
95
111
  _CACHE_TTL_SECONDS: int = 1800 # 30 minutes default; CI env overrides to 24h (see _get_cache_ttl)
96
112
  _CACHE_TTL_CI_SECONDS: int = 86400 # 24 hours — CI containers must not re-validate mid-run
97
113
 
@@ -196,7 +212,7 @@ _PRO_UNLOCK_ALL = os.environ.get("SOURCECODE_PRO_UNLOCK", "1") != "0"
196
212
 
197
213
 
198
214
  def _secure_dir() -> None:
199
- """Create ~/.sourcecode owner-only (0700). Holds the license secret.
215
+ """Create ~/.ask owner-only (0700). Holds the license secret.
200
216
 
201
217
  ``mkdir(mode=...)`` is ignored when the dir already exists, so chmod
202
218
  unconditionally. Best-effort: a chmod failure (e.g. Windows) is non-fatal.
@@ -235,8 +251,9 @@ def _write_license_file(data: dict) -> None:
235
251
 
236
252
  def _read_delta_runs() -> dict:
237
253
  try:
238
- if _DELTA_RUNS_FILE.exists():
239
- return json.loads(_DELTA_RUNS_FILE.read_text(encoding="utf-8"))
254
+ src = _read_config_path("delta_runs.json")
255
+ if src.exists():
256
+ return json.loads(src.read_text(encoding="utf-8"))
240
257
  except Exception:
241
258
  pass
242
259
  return {}
@@ -268,11 +285,12 @@ def check_delta_free_tier(repo_path: str) -> "tuple[bool, int, int]":
268
285
 
269
286
 
270
287
  def _load_license_file() -> Optional[dict]:
271
- """Read ~/.sourcecode/license.json. Returns parsed dict or None."""
288
+ """Read the license file, preferring ~/.ask and falling back to the legacy
289
+ ~/.sourcecode. Returns parsed dict or None."""
272
290
  try:
273
- if _LICENSE_FILE.exists():
274
- raw = _LICENSE_FILE.read_text(encoding="utf-8")
275
- return json.loads(raw)
291
+ src = _read_config_path("license.json")
292
+ if src.exists():
293
+ return json.loads(src.read_text(encoding="utf-8"))
276
294
  except Exception:
277
295
  pass
278
296
  return None
@@ -409,7 +427,7 @@ def _emit_upgrade_and_exit(headline: str, body_lines: list[str], payload: dict)
409
427
  lines.append(" Unlock Pro:")
410
428
  where = _PURCHASE_URL or "see Pro plans (docs/PRODUCT_TIERS.md)"
411
429
  lines.append(f" 1. Get a license: {where}")
412
- lines.append(" 2. Activate: sourcecode activate <license_key>")
430
+ lines.append(" 2. Activate: ask activate <license_key>")
413
431
  lines.append("")
414
432
  sys.stderr.write("\n".join(lines) + "\n")
415
433
  sys.stderr.flush()
@@ -479,9 +497,9 @@ def require_feature(
479
497
  "feature": feature_name,
480
498
  "message": (
481
499
  f"'{display}' requires a Pro license. "
482
- "Run: sourcecode activate <license_key>"
500
+ "Run: ask activate <license_key>"
483
501
  ),
484
- "upgrade_hint": "sourcecode activate <license_key>",
502
+ "upgrade_hint": "ask activate <license_key>",
485
503
  }
486
504
  if extra_fields:
487
505
  payload.update(extra_fields)
@@ -530,9 +548,9 @@ def require_repo_or_pro(
530
548
  f"This repository exceeds the free-tier limit of "
531
549
  f"{_FREE_REPO_JAVA_FILE_LIMIT} Java source files. "
532
550
  "Pro unlocks enterprise-scale monoliths. "
533
- "Run: sourcecode activate <license_key>"
551
+ "Run: ask activate <license_key>"
534
552
  ),
535
- "upgrade_hint": "sourcecode activate <license_key>",
553
+ "upgrade_hint": "ask activate <license_key>",
536
554
  }
537
555
  if extra_fields:
538
556
  payload.update(extra_fields)
@@ -6,9 +6,10 @@ import os
6
6
  from pathlib import Path
7
7
 
8
8
  _MCP_SERVERS_KEY = "mcpServers"
9
- _ENTRY_NAME = "sourcecode"
9
+ _ENTRY_NAME = "ask" # canonical (product = ASK Engine)
10
+ _LEGACY_ENTRY_NAME = "sourcecode" # deprecated alias — still recognized/cleaned
10
11
  _ENTRY_VALUE: dict[str, object] = {
11
- "command": "sourcecode",
12
+ "command": "ask",
12
13
  "args": ["mcp", "serve"],
13
14
  }
14
15
 
@@ -25,24 +26,31 @@ def read_config(path: Path) -> dict:
25
26
 
26
27
 
27
28
  def is_installed(config: dict) -> bool:
28
- """True if sourcecode entry already present in mcpServers."""
29
- return _ENTRY_NAME in config.get(_MCP_SERVERS_KEY, {})
29
+ """True if the ASK Engine entry (canonical `ask` or legacy `sourcecode`) is
30
+ already present in mcpServers."""
31
+ servers = config.get(_MCP_SERVERS_KEY, {})
32
+ return _ENTRY_NAME in servers or _LEGACY_ENTRY_NAME in servers
30
33
 
31
34
 
32
35
  def apply_entry(config: dict) -> dict:
33
- """Return new config dict with sourcecode merged into mcpServers."""
36
+ """Return new config dict with the canonical `ask` entry merged into mcpServers.
37
+ Any legacy `sourcecode` entry is migrated away (removed) so the client launches
38
+ a single server."""
34
39
  config = dict(config)
35
40
  servers: dict = dict(config.get(_MCP_SERVERS_KEY, {}))
41
+ servers.pop(_LEGACY_ENTRY_NAME, None)
36
42
  servers[_ENTRY_NAME] = _ENTRY_VALUE
37
43
  config[_MCP_SERVERS_KEY] = servers
38
44
  return config
39
45
 
40
46
 
41
47
  def remove_entry(config: dict) -> dict:
42
- """Return new config dict with sourcecode removed from mcpServers."""
48
+ """Return new config dict with the ASK Engine entry removed both the canonical
49
+ `ask` key and any legacy `sourcecode` key."""
43
50
  config = dict(config)
44
51
  servers: dict = dict(config.get(_MCP_SERVERS_KEY, {}))
45
52
  servers.pop(_ENTRY_NAME, None)
53
+ servers.pop(_LEGACY_ENTRY_NAME, None)
46
54
  if servers:
47
55
  config[_MCP_SERVERS_KEY] = servers
48
56
  elif _MCP_SERVERS_KEY in config:
@@ -416,7 +416,7 @@ def make_tool_callable(spec: ToolSpec) -> Callable[..., Any]:
416
416
 
417
417
  def _canonical_spec_for_runtime_command(runtime: RuntimeCommand) -> ToolSpec:
418
418
  params = tuple(_click_to_param_spec(param) for param in runtime.command.params)
419
- runtime_command = " ".join(runtime.path) if runtime.path else "sourcecode"
419
+ runtime_command = " ".join(runtime.path) if runtime.path else "ask"
420
420
  name = _tool_name_for_path(runtime.path)
421
421
  doc = runtime.docstring or runtime.help or ""
422
422
  description = _first_doc_line(doc) or f"CLI command: {runtime_command}"
@@ -510,7 +510,7 @@ def _alias_spec(
510
510
  not_exposed_to_cli=not_exposed_to_cli,
511
511
  mcp_hidden=mcp_hidden,
512
512
  docstring=doc,
513
- runtime_command=" ".join(cli_path) if cli_path else "sourcecode",
513
+ runtime_command=" ".join(cli_path) if cli_path else "ask",
514
514
  _argv_builder=argv_builder,
515
515
  validator=validator,
516
516
  )
@@ -552,7 +552,7 @@ Returns: stacks, entry points, dependency summary, architecture summary, confide
552
552
  Includes security_surface, mybatis, and transactional_boundaries for Java/Spring projects.
553
553
  For richer machine-oriented detail (deeper signals, more sections), use get_agent_context.
554
554
 
555
- Maps to: sourcecode <repo_path> --compact [--git-context]
555
+ Maps to: ask <repo_path> --compact [--git-context]
556
556
  repo_path: absolute path to the repository (default: current working directory).
557
557
  git_context: include git log and branch context in the analysis.
558
558
  """
@@ -565,7 +565,7 @@ lacks sufficient detail. Includes all compact fields plus: env_map, code_notes,
565
565
  architecture layers, security surface, transactional boundaries, module graph summary.
566
566
  Prefer get_compact_context for quick orientation or token-constrained workflows.
567
567
 
568
- Maps to: sourcecode <repo_path> --agent [--git-context]
568
+ Maps to: ask <repo_path> --agent [--git-context]
569
569
  repo_path: absolute path to the repository (default: current working directory).
570
570
  git_context: include git log and branch context in the analysis.
571
571
  """
@@ -573,7 +573,7 @@ git_context: include git log and branch context in the analysis.
573
573
  _GET_MODULE_DOC = """\
574
574
  Compact analysis of a specific module or subdirectory within a repository.
575
575
 
576
- Maps to: sourcecode <repo_path>/<module> --compact
576
+ Maps to: ask <repo_path>/<module> --compact
577
577
  repo_path: absolute path to the repository root.
578
578
  module: subdirectory name relative to repo_path (e.g. 'src/auth', 'api', 'core').
579
579
  Returns: same fields as get_compact_context but scoped to the module subtree.
@@ -582,7 +582,7 @@ Returns: same fields as get_compact_context but scoped to the module subtree.
582
582
  _TELEMETRY_DOC = """\
583
583
  Manage telemetry settings.
584
584
 
585
- Maps to: sourcecode telemetry <action>
585
+ Maps to: ask telemetry <action>
586
586
  action: one of "status" (show current state), "enable" (opt in), "disable" (opt out).
587
587
  Valid values: "status" | "enable" | "disable"
588
588
  """
@@ -689,7 +689,7 @@ def _prepare_context_aliases() -> list[ToolSpec]:
689
689
  _GET_DELTA_DOC = """\
690
690
  Incremental context: git-changed files since a reference commit.
691
691
 
692
- Maps to: sourcecode prepare-context delta <repo_path> --since <since>
692
+ Maps to: ask prepare-context delta <repo_path> --since <since>
693
693
  repo_path: absolute path to the repository (default: current working directory).
694
694
  since: git ref to diff against (e.g. HEAD~3, main, origin/main).
695
695
  If empty or omitted, auto-detects merge-base with origin/main (or
@@ -700,7 +700,7 @@ since: git ref to diff against (e.g. HEAD~3, main, origin/main).
700
700
  _REVIEW_PR_DOC = """\
701
701
  Execution paths and risk analysis for changed files in a pull request.
702
702
 
703
- Maps to: sourcecode prepare-context review-pr <repo_path> [--since <since>]
703
+ Maps to: ask prepare-context review-pr <repo_path> [--since <since>]
704
704
  Returns: compact_base + execution_paths (diff-scoped) + hotspots for changed files.
705
705
  repo_path: absolute path to the repository (default: current working directory).
706
706
  since: git ref to diff against (e.g. HEAD~3, main, origin/main).
@@ -710,7 +710,7 @@ since: git ref to diff against (e.g. HEAD~3, main, origin/main).
710
710
  _FIX_BUG_DOC = """\
711
711
  Risk-ranked files for bug investigation, optionally focused by symptom.
712
712
 
713
- Maps to: sourcecode prepare-context fix-bug <repo_path> [--symptom <symptom>]
713
+ Maps to: ask prepare-context fix-bug <repo_path> [--symptom <symptom>]
714
714
  Includes compact_base: security_surface, transactional_boundaries, spring_profiles.
715
715
  repo_path: absolute path to the repository (default: current working directory).
716
716
  symptom: optional error message or class name to focus the file ranking
@@ -722,7 +722,7 @@ symptom: optional error message or class name to focus the file ranking
722
722
  _ONBOARD_DOC = """\
723
723
  Onboarding context: structured overview for new contributors.
724
724
 
725
- Maps to: sourcecode prepare-context onboard <repo_path>
725
+ Maps to: ask prepare-context onboard <repo_path>
726
726
  Returns: project structure, key entry points, architectural patterns, getting-started guide.
727
727
  repo_path: absolute path to the repository (default: current working directory).
728
728
  """
@@ -730,7 +730,7 @@ repo_path: absolute path to the repository (default: current working directory).
730
730
  _EXPLAIN_DOC = """\
731
731
  Architecture and entry-point explanation for a repository.
732
732
 
733
- Maps to: sourcecode prepare-context explain <repo_path>
733
+ Maps to: ask prepare-context explain <repo_path>
734
734
  Returns: project summary, architecture overview, entry points, key dependencies.
735
735
  repo_path: absolute path to the repository (default: current working directory).
736
736
  """
@@ -738,7 +738,7 @@ repo_path: absolute path to the repository (default: current working directory).
738
738
  _REFACTOR_DOC = """\
739
739
  Structural issues and refactor opportunities for a repository.
740
740
 
741
- Maps to: sourcecode prepare-context refactor <repo_path>
741
+ Maps to: ask prepare-context refactor <repo_path>
742
742
  Returns: structural issues, coupling hotspots, high-churn files, improvement opportunities.
743
743
  repo_path: absolute path to the repository (default: current working directory).
744
744
  """
@@ -746,7 +746,7 @@ repo_path: absolute path to the repository (default: current working directory).
746
746
  _GENERATE_TESTS_DOC = """\
747
747
  Untested source files and test gap analysis for a repository.
748
748
 
749
- Maps to: sourcecode prepare-context generate-tests <repo_path> [--all]
749
+ Maps to: ask prepare-context generate-tests <repo_path> [--all]
750
750
  Returns: test_gaps list of untested files ranked by risk.
751
751
  On large repos (>2000 classes) analysis is bounded by SOURCECODE_TESTS_TIMEOUT_MS
752
752
  (default: 15000 ms). If timeout elapses, returns truncated=true with partial results.
@@ -757,7 +757,7 @@ include_all: return full test_gaps list without truncating to top 20.
757
757
  _IR_SUMMARY_DOC = """\
758
758
  Deterministic symbol-level IR summary for Java repositories. Java only.
759
759
 
760
- Maps to: sourcecode repo-ir <repo_path> --summary-only
760
+ Maps to: ask repo-ir <repo_path> --summary-only
761
761
  Returns: reverse_graph, route_surface (top 50 endpoints),
762
762
  subsystems (top 15), impact, analysis. Full graph nodes/edges omitted.
763
763
 
@@ -770,7 +770,7 @@ subsystems: list of detected subsystem cluster dicts.
770
770
  analysis: metadata — total_classes, total_edges, analysis_ms.
771
771
 
772
772
  Output is bounded to ~100 KB for LLM safety. For full IR (can exceed 10 MB
773
- on large repos), use the CLI: sourcecode repo-ir <path> --output ir.json
773
+ on large repos), use the CLI: ask repo-ir <path> --output ir.json
774
774
  Use get_compact_context or get_agent_context for non-Java repos.
775
775
 
776
776
  repo_path: absolute path to the Java repository (default: current working directory).
@@ -779,7 +779,7 @@ repo_path: absolute path to the Java repository (default: current working direct
779
779
  _IMPACT_CONTEXT_DOC = """\
780
780
  Blast-radius analysis: who calls a class and what breaks if it changes? Java only.
781
781
 
782
- Maps to: sourcecode impact <target> <repo_path> [--depth <depth>]
782
+ Maps to: ask impact <target> <repo_path> [--depth <depth>]
783
783
  Returns: direct_callers, indirect_callers, endpoints_affected,
784
784
  transactional_boundaries_touched, risk_score, risk_level, stats.
785
785
 
@@ -797,7 +797,7 @@ depth: BFS depth for indirect caller traversal (1–8, default: 4).
797
797
  _MODERNIZE_DOC = """\
798
798
  Analyzes codebase for modernization opportunities: dead zones, hotspot scores, upgrade candidates.
799
799
 
800
- Maps to: sourcecode modernize <repo_path>
800
+ Maps to: ask modernize <repo_path>
801
801
  Returns: hotspot_candidates (high fan-in + git churn), statically_unreferenced (zero-caller classes — NOT confirmed dead; verify no framework dispatch) + framework_dispatched,
802
802
  high_coupling_nodes, subsystem_summary, cross_module_tangles, recommendation.
803
803
 
@@ -852,7 +852,7 @@ REST API endpoint surface extraction from Java source files. JAVA ONLY.
852
852
  Do NOT call this on non-Java repositories — it will return empty results.
853
853
  Use get_compact_context or get_agent_context for non-Java repos.
854
854
 
855
- Maps to: sourcecode endpoints <repo_path>
855
+ Maps to: ask endpoints <repo_path>
856
856
  Returns: endpoints list with method, path, controller, handler fields;
857
857
  security dict always present (policy: roles_allowed|permit_all|deny_all|
858
858
  authenticated|...|none_detected); none_detected = no auth annotation found.
@@ -879,7 +879,7 @@ must satisfy before generating a payload, a test, or reasoning about a 400:
879
879
  * hand-written custom validators (@Constraint + ConstraintValidator, e.g.
880
880
  PetAgeValidator), linked to fields via x-field-extra-annotation.
881
881
 
882
- Maps to: sourcecode validation <repo_path>
882
+ Maps to: ask validation <repo_path>
883
883
  Returns: endpoints[] (method, path, controller, handler, schema, validatedFields[
884
884
  {name, rules[{kind,value}], customValidators[{annotation,validators,message,resolved}]}]),
885
885
  custom_validators[] (catalog: annotation, validators, message, validatedTypes, targets),
@@ -894,7 +894,7 @@ gaps_only: when true, return only the gaps section (endpoints lacking validation
894
894
  _CACHE_STATUS_DOC = """\
895
895
  Report cache metadata for a repository.
896
896
 
897
- Maps to: sourcecode cache status <repo_path> --json
897
+ Maps to: ask cache status <repo_path> --json
898
898
  Returns: cache entries with git_head, timestamps, size info.
899
899
  Use check_freshness for RIS-specific freshness checking (faster, richer).
900
900
  repo_path: absolute path to the repository (default: current working directory).
@@ -903,7 +903,7 @@ repo_path: absolute path to the repository (default: current working directory).
903
903
  _CACHE_WARM_DOC = """\
904
904
  Warm the cache for a repository (builds compact and agent analysis snapshots).
905
905
 
906
- Maps to: sourcecode cache warm <repo_path>
906
+ Maps to: ask cache warm <repo_path>
907
907
  Builds or refreshes the Repository Intelligence Snapshot (RIS).
908
908
  Use before analytical workflows to ensure fast subsequent tool calls (~8s first run,
909
909
  instant after).
@@ -913,7 +913,7 @@ repo_path: absolute path to the repository (default: current working directory).
913
913
  _CACHE_CLEAR_DOC = """\
914
914
  Clear cached analysis for a repository.
915
915
 
916
- Maps to: sourcecode cache clear <repo_path> [--include-ris]
916
+ Maps to: ask cache clear <repo_path> [--include-ris]
917
917
  Removes cached context files. After clearing, run get_compact_context or cache_warm to rebuild.
918
918
  include_ris: also remove the RIS snapshot in addition to analysis cache (default: False).
919
919
  repo_path: absolute path to the repository (default: current working directory).
sourcecode/mcp/runner.py CHANGED
@@ -66,7 +66,7 @@ def run_command(args: list[str]) -> Any:
66
66
  payload = _parsed
67
67
  break
68
68
  raise CommandError(
69
- f"sourcecode command failed (exit {result.exit_code}). Args: {args}",
69
+ f"ask command failed (exit {result.exit_code}). Args: {args}",
70
70
  exit_code=result.exit_code,
71
71
  stdout=stdout,
72
72
  stderr=stderr,
@@ -76,7 +76,7 @@ def run_command(args: list[str]) -> Any:
76
76
  output = (result.output or "").strip()
77
77
  if not output:
78
78
  raise RuntimeError(
79
- f"sourcecode command produced no output.\n"
79
+ f"ask command produced no output.\n"
80
80
  f"Args: {args}"
81
81
  )
82
82