From c2aeae81afff8a62f6e10e79a39743a2fd29c16c Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Wed, 22 Jul 2026 05:23:43 -0400 Subject: [PATCH] test(disk-hygiene): mock sys.argv in run_guard* helpers to seal the kill-switch argv seam MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `resolve_disk_hygiene_enabled()` reads `--disk-hygiene-enabled` from `sys.argv[1:]` before the environment fallback (#382). The `run_guard`, `run_guard_disabled`, and `run_guard_powershell_disabled` helpers in `test_hygiene.py` patched `os.environ` to drive the kill switch but left `sys.argv` unpatched, so a test runner whose real invocation argv carried that flag could override the env-var mock and flip an expected `deny` to `ask`. Each helper now patches `guard.sys.argv` to a clean, flag-free argv alongside its existing environment mock — matching the `run_guard_enabled_argv` helper already in the file — so the environment variable stays the sole channel under test. Test-only isolation seal; no production logic changes. Standard `unittest`/`pytest` invocations never produced such argv, so this closes latent fragility rather than a live failure. Closes #970 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) --- plugins/disk-hygiene/.claude-plugin/plugin.json | 2 +- plugins/disk-hygiene/CHANGELOG.md | 14 ++++++++++++++ .../skills/clean/scripts/test_hygiene.py | 3 +++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/plugins/disk-hygiene/.claude-plugin/plugin.json b/plugins/disk-hygiene/.claude-plugin/plugin.json index 25b35f1b42..0eba0ecfe2 100644 --- a/plugins/disk-hygiene/.claude-plugin/plugin.json +++ b/plugins/disk-hygiene/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "disk-hygiene", - "version": "0.4.4", + "version": "0.4.5", "description": "Context-aware disk hygiene for arbitrary directory trees: inventories orphaned and temporary artifacts, classifies evidence into review tiers, and offers exact-path cleanup only after a fresh safety preview and explicit per-tier approval. The target is read-only by default; OS-managed paths, links and mount points, VCS-tracked content, changed entries, and live-handle uncertainty fail closed.", "author": { "name": "Melodic Software", diff --git a/plugins/disk-hygiene/CHANGELOG.md b/plugins/disk-hygiene/CHANGELOG.md index 10978e78fa..b6a6d80b1a 100644 --- a/plugins/disk-hygiene/CHANGELOG.md +++ b/plugins/disk-hygiene/CHANGELOG.md @@ -3,6 +3,20 @@ All notable changes to the `disk-hygiene` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.4.5] + +### Changed + +- **Test isolation only — no runtime behavior change.** The `run_guard`, `run_guard_disabled`, and + `run_guard_powershell_disabled` helpers in `test_hygiene.py` mocked `os.environ` to exercise the + kill switch but left `sys.argv` unpatched. Since the guard reads `--disk-hygiene-enabled` from + `sys.argv[1:]` before the environment fallback, a test runner whose real invocation argv happened + to carry that flag could override the env-var mock and flip an expected `deny` to `ask`. Each + helper now patches `guard.sys.argv` to a clean, flag-free argv alongside its existing environment + mock — matching the pattern the `run_guard_enabled_argv` helper already established — so the + environment variable stays the sole channel under test. Standard `unittest`/`pytest` invocations + never produced such argv, so this seals latent fragility rather than a live failure. + ## [0.4.4] ### Fixed diff --git a/plugins/disk-hygiene/skills/clean/scripts/test_hygiene.py b/plugins/disk-hygiene/skills/clean/scripts/test_hygiene.py index 6a777b1f2f..94598e947b 100755 --- a/plugins/disk-hygiene/skills/clean/scripts/test_hygiene.py +++ b/plugins/disk-hygiene/skills/clean/scripts/test_hygiene.py @@ -1064,6 +1064,7 @@ def run_guard(self, command: str) -> dict[str, object]: with ( mock.patch("sys.stdin", stdin), redirect_stdout(stdout), + mock.patch.object(guard.sys, "argv", [str(SCRIPT_DIR / "destructive_guard.py")]), mock.patch.dict( "os.environ", {"CLAUDE_PLUGIN_OPTION_DISK_HYGIENE_ENABLED": "true"}, clear=False ), @@ -1077,6 +1078,7 @@ def run_guard_disabled(self, command: str) -> dict[str, object]: with ( mock.patch("sys.stdin", stdin), redirect_stdout(stdout), + mock.patch.object(guard.sys, "argv", [str(SCRIPT_DIR / "destructive_guard.py")]), mock.patch.dict( "os.environ", {"CLAUDE_PLUGIN_OPTION_DISK_HYGIENE_ENABLED": "false"}, clear=False ), @@ -1319,6 +1321,7 @@ def run_guard_powershell_disabled( with ( mock.patch("sys.stdin", stdin), redirect_stdout(stdout), + mock.patch.object(guard.sys, "argv", [str(SCRIPT_DIR / "destructive_guard.py")]), mock.patch.dict( "os.environ", {"CLAUDE_PLUGIN_OPTION_DISK_HYGIENE_ENABLED": "false"},