mirror of
https://github.com/anthropics/claude-plugins-official.git
synced 2026-06-13 22:26:03 -03:00
Enable agentic commit reviewer on Windows
The agentic reviewer is silently no-op on Windows today. SessionStart bootstrap (ensure_agent_sdk.py) short-circuits with SKIP_WIN32 because the consumer glob in llm.py only matches POSIX venv layout (lib/pythonX.Y/site-packages). On Windows, venvs use Lib/site-packages (capital L, no pythonX.Y subdir), so even if a venv got built the glob wouldn't find its contents. Result: Windows users on default installs (no system-wide claude_agent_sdk) get layer 1 (pattern warnings) and layer 2 (single- shot LLM diff review) but not layer 3 — the cross-file agentic review that catches IDOR, auth-bypass, cross-file SSRF, and other things that need to read related files. Plugin description claims layer 3 but it silently doesn't run. Three changes: 1. llm.py — extend the consumer glob (2 sites: 3P SDK fallback at ~L297, agentic_review fallback at ~L1090) to also match the Windows Lib/site-packages layout, so a venv built on Windows is actually discoverable. 2. ensure_agent_sdk.py — remove the sys.platform == 'win32' early-exit so the SessionStart bootstrap builds the venv on Windows too. Outcome code 4 (formerly SKIP_WIN32) is retired but not reused so pre-fix telemetry rows still decode correctly. 3. ensure_agent_sdk.py — venv_py path now branches on sys.platform: Windows venvs put the interpreter at Scripts\python.exe; POSIX uses bin/python. Previously assumed POSIX, so even with the glob fix, the post-build SDK-importability probe would fail on Windows. Verified locally on macOS: - glob test: both layouts now match (POSIX venv detected, simulated Windows venv also detected via the new Lib/site-packages branch) - both files pass py_compile - POSIX path unchanged (sys.platform != 'win32' so old branch runs) Not verified on Windows in this commit — needs an actual Windows runner to confirm the venv build + SDK import + subprocess plumbing all work end-to-end. The SDK spawns a child claude.exe; Windows process plumbing has its own quirks (shell semantics, path escaping) that may surface separately. Worth a controlled rollout (one-week soak under env-var opt-in before flipping default). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e77ff913ad
commit
4decd2e3b2
@ -28,7 +28,9 @@ NOOP_SYSTEM = 0 # claude_agent_sdk already importable in system python
|
|||||||
NOOP_VENV = 1 # venv already built and SDK imports from it
|
NOOP_VENV = 1 # venv already built and SDK imports from it
|
||||||
BUILT = 2 # venv created + SDK pip-installed this run
|
BUILT = 2 # venv created + SDK pip-installed this run
|
||||||
BUILD_FAILED = 3 # venv create or pip install raised/timed out
|
BUILD_FAILED = 3 # venv create or pip install raised/timed out
|
||||||
SKIP_WIN32 = 4 # Windows; consumer glob doesn't handle Lib/ layout
|
# Outcome 4 was previously SKIP_WIN32; retired now that the consumer glob in
|
||||||
|
# llm.py also matches Windows venv layout (Lib/site-packages). Don't reuse the
|
||||||
|
# value — telemetry rows from older plugin builds still emit 4.
|
||||||
SKIP_SENTINEL = 5 # another SessionStart is currently building
|
SKIP_SENTINEL = 5 # another SessionStart is currently building
|
||||||
|
|
||||||
|
|
||||||
@ -60,13 +62,6 @@ def main() -> tuple[int, str, str]:
|
|||||||
err_phase / err_kind are non-empty only on BUILD_FAILED — they let
|
err_phase / err_kind are non-empty only on BUILD_FAILED — they let
|
||||||
telemetry split bootstrap failures by root cause.
|
telemetry split bootstrap failures by root cause.
|
||||||
"""
|
"""
|
||||||
# Windows venv layout (Lib/site-packages, no python* subdir) isn't
|
|
||||||
# handled by the consumer's glob in security_reminder_hook.py; skip the
|
|
||||||
# bootstrap entirely rather than build a venv that's never read.
|
|
||||||
if sys.platform == "win32":
|
|
||||||
return SKIP_WIN32, "", ""
|
|
||||||
|
|
||||||
|
|
||||||
if _sdk_on_syspath():
|
if _sdk_on_syspath():
|
||||||
return NOOP_SYSTEM, "", ""
|
return NOOP_SYSTEM, "", ""
|
||||||
|
|
||||||
@ -75,7 +70,11 @@ def main() -> tuple[int, str, str]:
|
|||||||
or os.path.expanduser("~/.claude/security")
|
or os.path.expanduser("~/.claude/security")
|
||||||
)
|
)
|
||||||
venv = state_dir / "agent-sdk-venv"
|
venv = state_dir / "agent-sdk-venv"
|
||||||
venv_py = venv / "bin" / "python"
|
# Windows venvs put the interpreter at Scripts\python.exe; POSIX uses bin/python.
|
||||||
|
if sys.platform == "win32":
|
||||||
|
venv_py = venv / "Scripts" / "python.exe"
|
||||||
|
else:
|
||||||
|
venv_py = venv / "bin" / "python"
|
||||||
|
|
||||||
# Another SessionStart (concurrent CC instance, same plugin) may already
|
# Another SessionStart (concurrent CC instance, same plugin) may already
|
||||||
# be building. The sentinel lives NEXT TO the venv, not inside it —
|
# be building. The sentinel lives NEXT TO the venv, not inside it —
|
||||||
|
|||||||
@ -298,9 +298,12 @@ def _call_claude_via_sdk(prompt, output_schema, *, max_tokens=16000, model=None)
|
|||||||
"SECURITY_WARNINGS_STATE_DIR",
|
"SECURITY_WARNINGS_STATE_DIR",
|
||||||
os.path.expanduser("~/.claude/security"),
|
os.path.expanduser("~/.claude/security"),
|
||||||
)
|
)
|
||||||
for _sp in glob.glob(
|
# POSIX venv: lib/pythonX.Y/site-packages
|
||||||
os.path.join(_state_dir, "agent-sdk-venv", "lib",
|
# Windows venv: Lib/site-packages (capital L, no pythonX.Y subdir)
|
||||||
"python*", "site-packages")
|
_venv_root = os.path.join(_state_dir, "agent-sdk-venv")
|
||||||
|
for _sp in (
|
||||||
|
glob.glob(os.path.join(_venv_root, "lib", "python*", "site-packages"))
|
||||||
|
+ glob.glob(os.path.join(_venv_root, "Lib", "site-packages"))
|
||||||
):
|
):
|
||||||
if os.path.isdir(_sp) and _sp not in sys.path:
|
if os.path.isdir(_sp) and _sp not in sys.path:
|
||||||
sys.path.insert(0, _sp)
|
sys.path.insert(0, _sp)
|
||||||
@ -1094,9 +1097,12 @@ def agentic_review(
|
|||||||
"SECURITY_WARNINGS_STATE_DIR",
|
"SECURITY_WARNINGS_STATE_DIR",
|
||||||
os.path.expanduser("~/.claude/security"),
|
os.path.expanduser("~/.claude/security"),
|
||||||
)
|
)
|
||||||
for _sp in glob.glob(
|
# POSIX venv: lib/pythonX.Y/site-packages
|
||||||
os.path.join(_state_dir, "agent-sdk-venv", "lib",
|
# Windows venv: Lib/site-packages (capital L, no pythonX.Y subdir)
|
||||||
"python*", "site-packages")
|
_venv_root = os.path.join(_state_dir, "agent-sdk-venv")
|
||||||
|
for _sp in (
|
||||||
|
glob.glob(os.path.join(_venv_root, "lib", "python*", "site-packages"))
|
||||||
|
+ glob.glob(os.path.join(_venv_root, "Lib", "site-packages"))
|
||||||
):
|
):
|
||||||
if os.path.isdir(_sp) and _sp not in sys.path:
|
if os.path.isdir(_sp) and _sp not in sys.path:
|
||||||
sys.path.insert(0, _sp)
|
sys.path.insert(0, _sp)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user