sourcecode 1.31.28__py3-none-any.whl → 1.31.29__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
@@ -1,3 +1,3 @@
1
1
  """sourcecode — Deterministic codebase context maps for AI coding agents."""
2
2
 
3
- __version__ = "1.31.28"
3
+ __version__ = "1.31.29"
sourcecode/cli.py CHANGED
@@ -1952,6 +1952,10 @@ def main(
1952
1952
  if _copy_to_clipboard(content):
1953
1953
  typer.echo("✓ copied to clipboard", err=True)
1954
1954
 
1955
+ # 8. One-time MCP setup nudge (stderr only — does not affect exit code or stdout)
1956
+ from sourcecode.mcp_nudge import nudge_mcp_if_needed as _nudge
1957
+ _nudge()
1958
+
1955
1959
 
1956
1960
  # ── prepare-context output helpers ────────────────────────────────────────────
1957
1961
 
@@ -2554,6 +2558,9 @@ def prepare_context_cmd(
2554
2558
  if _copy_to_clipboard(_pc_content):
2555
2559
  typer.echo("✓ copied to clipboard", err=True)
2556
2560
 
2561
+ from sourcecode.mcp_nudge import nudge_mcp_if_needed as _nudge
2562
+ _nudge()
2563
+
2557
2564
 
2558
2565
  # ── Telemetry commands ────────────────────────────────────────────────────────
2559
2566
 
@@ -2899,6 +2906,9 @@ def impact_cmd(
2899
2906
  if result.get("resolution") == "not_found":
2900
2907
  raise typer.Exit(code=1)
2901
2908
 
2909
+ from sourcecode.mcp_nudge import nudge_mcp_if_needed as _nudge
2910
+ _nudge()
2911
+
2902
2912
 
2903
2913
  # ── endpoints ─────────────────────────────────────────────────────────────────
2904
2914
 
@@ -2969,6 +2979,9 @@ def endpoints_cmd(
2969
2979
  if _copy_to_clipboard(output):
2970
2980
  typer.echo("✓ copied to clipboard", err=True)
2971
2981
 
2982
+ from sourcecode.mcp_nudge import nudge_mcp_if_needed as _nudge
2983
+ _nudge()
2984
+
2972
2985
 
2973
2986
  # ── Enterprise Workflow Commands ──────────────────────────────────────────────
2974
2987
  #
@@ -3574,6 +3587,10 @@ def mcp_init(
3574
3587
  typer.echo("")
3575
3588
  typer.echo(" Remove: sourcecode mcp remove")
3576
3589
 
3590
+ # Clear nudge flag: next run finds is_installed=True → no nudge.
3591
+ from sourcecode.mcp_nudge import clear_nudge_flag as _clear_nudge
3592
+ _clear_nudge()
3593
+
3577
3594
 
3578
3595
  @mcp_app.command("status")
3579
3596
  def mcp_status() -> None:
@@ -0,0 +1,84 @@
1
+ """MCP setup nudge — one-time stderr hint after successful analysis commands.
2
+
3
+ Fires when:
4
+ 1. At least one known MCP client (Claude Desktop, Cursor) is installed
5
+ 2. sourcecode is NOT yet registered in that client's config
6
+ 3. The nudge hasn't been shown this session (~/.sourcecode/nudge_shown flag)
7
+
8
+ Cleared by: a successful `sourcecode mcp init` (deletes the flag so the
9
+ post-init detection finds is_installed=True and never nudges again).
10
+
11
+ Side effects: writes only to stderr — stdout (JSON/YAML output) is untouched.
12
+ Exit code of the calling command is unaffected.
13
+ """
14
+ from __future__ import annotations
15
+
16
+ import sys
17
+ from pathlib import Path
18
+
19
+ # Stable path used as a session-level "already shown" sentinel.
20
+ _FLAG: Path = Path.home() / ".sourcecode" / "nudge_shown"
21
+
22
+ _MSG = (
23
+ "→ Claude Desktop detected. "
24
+ "Run `sourcecode mcp init` to enable agent integration.\n"
25
+ )
26
+
27
+ # Module-level imports so names are patchable in tests.
28
+ # Falls back to no-op stubs if onboarding package is unavailable.
29
+ try:
30
+ from sourcecode.mcp.onboarding.detector import detect_clients # noqa: PLC0415
31
+ from sourcecode.mcp.onboarding.applier import is_installed, read_config # noqa: PLC0415
32
+ _IMPORTS_OK = True
33
+ except Exception: # pragma: no cover
34
+ _IMPORTS_OK = False
35
+
36
+ def detect_clients() -> list: # type: ignore[misc]
37
+ return []
38
+
39
+ def is_installed(config: dict) -> bool: # type: ignore[misc]
40
+ return False
41
+
42
+ def read_config(path: Path) -> dict: # type: ignore[misc]
43
+ return {}
44
+
45
+
46
+ def nudge_mcp_if_needed() -> None:
47
+ """Print MCP setup nudge to stderr at most once (until mcp init succeeds)."""
48
+ # Fast path: already shown this session.
49
+ if _FLAG.exists():
50
+ return
51
+
52
+ try:
53
+ clients = detect_clients()
54
+ except Exception: # pragma: no cover
55
+ return
56
+
57
+ needs_nudge = any(
58
+ c.app_installed and not is_installed(read_config(c.config_path))
59
+ for c in clients
60
+ )
61
+
62
+ if not needs_nudge:
63
+ return
64
+
65
+ # Write nudge and persist flag.
66
+ sys.stderr.write(_MSG)
67
+ sys.stderr.flush()
68
+ try:
69
+ _FLAG.parent.mkdir(parents=True, exist_ok=True)
70
+ _FLAG.touch()
71
+ except OSError:
72
+ pass # Non-fatal: nudge will fire again next run, which is acceptable.
73
+
74
+
75
+ def clear_nudge_flag() -> None:
76
+ """Delete the session flag so post-mcp-init runs don't re-show the nudge.
77
+
78
+ Called by `mcp init` after a successful installation. On the next run,
79
+ detection finds is_installed=True → needs_nudge=False → no nudge shown.
80
+ """
81
+ try:
82
+ _FLAG.unlink(missing_ok=True)
83
+ except OSError:
84
+ pass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 1.31.28
3
+ Version: 1.31.29
4
4
  Summary: Deterministic codebase context for AI coding agents
5
5
  License: Apache License
6
6
  Version 2.0, January 2004
@@ -225,7 +225,7 @@ Description-Content-Type: text/markdown
225
225
 
226
226
  **AI-ready change intelligence for Java/Spring enterprise monoliths.**
227
227
 
228
- ![Version](https://img.shields.io/badge/version-1.31.28-blue)
228
+ ![Version](https://img.shields.io/badge/version-1.31.29-blue)
229
229
  ![Python](https://img.shields.io/badge/python-3.10%2B-green)
230
230
 
231
231
  ---
@@ -263,7 +263,7 @@ pipx install sourcecode
263
263
 
264
264
  ```bash
265
265
  sourcecode version
266
- # sourcecode 1.31.28
266
+ # sourcecode 1.31.29
267
267
  ```
268
268
 
269
269
  ---
@@ -1,4 +1,4 @@
1
- sourcecode/__init__.py,sha256=u-6FWeYcsHBD4kgFtNzOZPQeoIf-YlQrC_JzWDvNiaA,104
1
+ sourcecode/__init__.py,sha256=SBMk4PWIR6gOyohinC11lw1mhLWB_AxkxfACQb9B_zk,104
2
2
  sourcecode/adaptive_scanner.py,sha256=XffluXKzJUXrMtjEiAOnSNPZnztdIcts17T9ouHeID0,10521
3
3
  sourcecode/architecture_analyzer.py,sha256=Ry3aYT9dc7XuLmWLT5IZ93RkCf_P14Qtew0nGPvUl_8,42184
4
4
  sourcecode/architecture_summary.py,sha256=z34_6v7cSwy98cof2UVciGho7SCrZ93tiqMmq5WNzRQ,20405
@@ -6,7 +6,7 @@ sourcecode/ast_extractor.py,sha256=_btmeOJIe3t-NicF94D5ZAesa2YIJ0_QNExGnbHxGFE,5
6
6
  sourcecode/cache.py,sha256=TiYa3ECjBKtvlfCk7GvQ9v6gZkAITpH3ow9PubA7sUo,22946
7
7
  sourcecode/canonical_ir.py,sha256=_HM3AUmKSdna9u4dCoU6rpgSA6HdF8gzOKZykIUCNGY,23277
8
8
  sourcecode/classifier.py,sha256=yWeq6agTjkFa3zuNa-gdVIHtjoBoPoVlJnX-b7tdVJs,7851
9
- sourcecode/cli.py,sha256=YRHo7R58Nf-NYASQNCW39AjsJnOi5mrl5iziaPdMUxk,152204
9
+ sourcecode/cli.py,sha256=KhYORJEuswP5T6Dn3bzIYATa01eHzUXmJjIMb5ZOBf4,152777
10
10
  sourcecode/code_notes_analyzer.py,sha256=EJemNCNc9Dn-1RZYu-aNbK0ELzmsyC4s6FdHi3XyNEI,9392
11
11
  sourcecode/confidence_analyzer.py,sha256=_jckZSxksV-OU38vbkxfVNBnWCtlCq8Vwfg23x1uspA,19054
12
12
  sourcecode/context_scorer.py,sha256=QpChSpsmaAYz91rXA4Ue5xzQmNz_ZboZN09YOHScq1U,14679
@@ -22,6 +22,7 @@ sourcecode/file_classifier.py,sha256=QrYm7MlG29HQdAR1WOfpnIIBysAz62c5coz9eQ76meo
22
22
  sourcecode/flow_analyzer.py,sha256=dSiuY4w49k29jW_EPXUOND9B5uVbuCA7kjnuHi-pIWA,28781
23
23
  sourcecode/git_analyzer.py,sha256=0Gyj-vMpIIN4nfriKXVRouNYBeJ59s6pQDX2Xu9Pq-U,13177
24
24
  sourcecode/graph_analyzer.py,sha256=iUK-7pSV-cvGqqD2hENdYmhnm0wcXFEyK-xnu5ul8OU,62515
25
+ sourcecode/mcp_nudge.py,sha256=rJzr_dirC6L3VMsUBmzsSSJb-j-nphZy-qq7i2JPjEQ,2625
25
26
  sourcecode/metrics_analyzer.py,sha256=m0ENgtqKeBL17kUIK3fmGkgo7UfXBNHxCMj0H_Y5K7c,22750
26
27
  sourcecode/output_budget.py,sha256=43307mJEyUPU3MI-QEQoVxrcAvNyUzdzF_SAPgisBQE,6603
27
28
  sourcecode/path_filters.py,sha256=ROFRQ8eSLBEMiixK9f45-RO7um4VEEcjoD5AA4I427I,3739
@@ -76,8 +77,8 @@ sourcecode/telemetry/consent.py,sha256=wLMvGNJeSSyZoNkQXpoUioY6mMv4Qdvuw7S9jAEWn
76
77
  sourcecode/telemetry/events.py,sha256=oEvvulfsv5GIDWG2174gSS6tNB95w38AIYiYeifGKlE,2294
77
78
  sourcecode/telemetry/filters.py,sha256=Asa71oRl7q3Wt_FMwuufIZJFzSYdgRNKS8LHCIyFeYE,4805
78
79
  sourcecode/telemetry/transport.py,sha256=KJeIPCPWMdmbCP3ySGs2iUlia34U6vWne2dZsUezesw,1560
79
- sourcecode-1.31.28.dist-info/METADATA,sha256=IopWHYcmGBKmum7GTpRUesF4DHPc1bSC4kVW3-BDYuU,31103
80
- sourcecode-1.31.28.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
81
- sourcecode-1.31.28.dist-info/entry_points.txt,sha256=ex3F9rmbXeyDIoFQHtkEqTsKSaJow8F0LrVu8XfIktQ,57
82
- sourcecode-1.31.28.dist-info/licenses/LICENSE,sha256=7DdHrU9Z_3e7dSvq4ISijZNjnuHo5NIHNiHDouMQ9JU,10491
83
- sourcecode-1.31.28.dist-info/RECORD,,
80
+ sourcecode-1.31.29.dist-info/METADATA,sha256=x4Y5nAbzj_7MpUG9XvQFjbFIO0imXHfJWD1EjJ_Rkhc,31103
81
+ sourcecode-1.31.29.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
82
+ sourcecode-1.31.29.dist-info/entry_points.txt,sha256=ex3F9rmbXeyDIoFQHtkEqTsKSaJow8F0LrVu8XfIktQ,57
83
+ sourcecode-1.31.29.dist-info/licenses/LICENSE,sha256=7DdHrU9Z_3e7dSvq4ISijZNjnuHo5NIHNiHDouMQ9JU,10491
84
+ sourcecode-1.31.29.dist-info/RECORD,,