From c83e7647d2328ee4f8be5db3836dbdbece1bc411 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Wed, 30 Sep 2026 01:42:44 -0400 Subject: [PATCH 1/6] feat(disk-hygiene): add a model-invocable read-only audit skill /disk-hygiene:audit runs the engine's scan subcommand only, after the argument-free kill-switch probe, and reports the snapshot. Removal stays with /disk-hygiene:clean, which a person invokes. Safety rests on the plugin-level engine-gate; the skill carries no hooks of its own. Refs #5516 Co-Authored-By: Claude Opus 5.5 --- docs/skill-cheat-sheet.md | 1 + plugins/disk-hygiene/skills/audit/SKILL.md | 110 ++++++++++++++++++ .../skills/audit/evals/evals.json | 42 +++++++ 3 files changed, 153 insertions(+) create mode 100644 plugins/disk-hygiene/skills/audit/SKILL.md create mode 100644 plugins/disk-hygiene/skills/audit/evals/evals.json diff --git a/docs/skill-cheat-sheet.md b/docs/skill-cheat-sheet.md index 4b451b361c..fe1a0770d8 100644 --- a/docs/skill-cheat-sheet.md +++ b/docs/skill-cheat-sheet.md @@ -224,6 +224,7 @@ owned by [docs/catalog-taxonomy.md](catalog-taxonomy.md). | [`/discipline:tighten-your-output`](../plugins/discipline/skills/tighten-your-output/SKILL.md) | `discipline` | Tighten prose and code. Fewer words, no semantic loss | | [`/discipline:use-your-skills`](../plugins/discipline/skills/use-your-skills/SKILL.md) | `discipline` | Map the task to available skills and invoke them instead of reinventing | | [`/discipline:wait-what`](../plugins/discipline/skills/wait-what/SKILL.md) | `discipline` | Re-pitch the message that did not land. Missing context added, plain register, project vocabulary | +| [`/disk-hygiene:audit`](../plugins/disk-hygiene/skills/audit/SKILL.md) | `disk-hygiene` | Scan a directory tree for stale leftovers and report the evidence, read-only | | [`/disk-hygiene:clean`](../plugins/disk-hygiene/skills/clean/SKILL.md) | `disk-hygiene` | Audit a directory tree for stale leftovers and remove validated paths | | [`/docs-hygiene:audit-derivability`](../plugins/docs-hygiene/skills/audit-derivability/SKILL.md) | `docs-hygiene` | Judge whether a doc earns its existence or should become a pointer | | [`/docs-hygiene:audit-encapsulation`](../plugins/docs-hygiene/skills/audit-encapsulation/SKILL.md) | `docs-hygiene` | Find external citations reaching into a skill's private surfaces | diff --git a/plugins/disk-hygiene/skills/audit/SKILL.md b/plugins/disk-hygiene/skills/audit/SKILL.md new file mode 100644 index 0000000000..5eded954fc --- /dev/null +++ b/plugins/disk-hygiene/skills/audit/SKILL.md @@ -0,0 +1,110 @@ +--- +description: "Read-only, audit-only scan of one directory tree for orphaned, temporary, stale-lock, failed-write, partial-download, and empty leftovers, reported as an evidence snapshot. Removes nothing; any removal is a separate /disk-hygiene:clean run that a person invokes. Use when: 'delegate a disk-hygiene audit', 'orchestrator scan of a directory for leftovers', 'subagent scan of this directory for leftovers', 'disk-hygiene audit report'. Skip when: the ask is to clean up or reclaim space (that is /disk-hygiene:clean), one repository's caches or build output (repo-hygiene), or an OS-managed root." +argument-hint: "[--max-depth ] [--sizes-only] [--policy ] " +user-invocable: true +disable-model-invocation: false +metadata: + workflow-stage: anytime + summary: Scan a directory tree for stale leftovers and report the evidence, read-only +--- + +**Arguments.** `[--max-depth ] [--sizes-only] [--policy ] `. Full form: `[--max-depth ] [--sizes-only] [--quiet] [--policy ] [--root-children [--root-child ]...] ` + +# Disk hygiene audit + +Scan one directory tree and report what the snapshot shows. This skill runs the engine's `scan` +subcommand and nothing else, and it changes nothing in the target. A filename pattern is a +discovery hint, never proof that an entry is junk. + +This skill carries no hooks of its own. Safety rests on the plugin-level engine-gate in +`hooks/hooks.json`, which checks every Bash or PowerShell call that names `hygiene.py`, in the main +session and in subagents alike. Run no engine subcommand other than `scan`, no shell command that +writes, moves, or deletes under the target, and no compound shell around an engine call. + +## 1. Bootstrap + +Run the argument-free probe first, before any engine call: + +```text +"" "${CLAUDE_PLUGIN_ROOT}/skills/setup/scripts/kill_switch_probe.py" +``` + +Take `hook_python` and `data_root` from its one-line JSON. Every engine call needs the absolute +`` and `--data-root`; a bare `python3` is rejected. When `hook_python` is not yet +known, submit the probe once with bare `python`: the guard names its interpreter in the denial, so +rerun the probe with that value. Never submit a scan to learn either value. + +- `data_root` is `null`: the install layout proved no data root and the guard denies every engine + call. Report the audit as not run, relay the recovery the guard's denial names, and stop. +- The probe call is denied or left waiting for a person: report the audit as not run and stop. Do + not scan without it. +- `hook_python` is older than `MIN_PYTHON` in + [`hygiene.py`](../clean/scripts/hygiene.py): stop with that declared prerequisite. +- `effective` is `false` (audit-only): the scan still runs. State the configured value, and leave + out the removal handoff in step 4. On `degraded: true`, say the configured value could not be read. + +## 2. Scan + +Pick a unique run directory under `/runs/`; the snapshot lives there, never in the +target. With no target, ask the person who invoked you once. Reject an OS-managed root, a missing +directory, a symlink, or a Windows reparse point. + +```text +"" "${CLAUDE_PLUGIN_ROOT}/skills/clean/scripts/hygiene.py" scan \ + --target "" --output "/snapshot.json" \ + --data-root "" [--project-dir "${CLAUDE_PROJECT_DIR}"] \ + [--policy ""] [--max-depth ] [--sizes-only] [--quiet] \ + [--root-children [--root-child ]...] +``` + +`--project-dir` is optional; pass it when the consumer project has standing policy files. What each +flag does, including the large-target and volume-root rules, is in +[scan-flags.md](../clean/reference/scan-flags.md). For a home directory or another large target, +start with `--max-depth 1`, then scan the subtrees the evidence justifies. Never pass +`--confirmed-large-scan` on your own: an unbounded walk needs a person's answer. + +For a subtree worker, the brief to paste into the spawn prompt is +[fan-out-worker-brief.md](../clean/reference/fan-out-worker-brief.md). A worker returns scan +evidence only. + +## 3. Read and report the snapshot + +Report from the snapshot and the scan's stdout, and nothing the run did not observe. + +- Lead with `children_rollup`. `walked: true` rows carry exact totals; `walked: false` rows carry + `null` aggregates and `unwalked_reasons`, so report them as coverage gaps, never as small or clean. +- Rank on `reclaimable_local_bytes`, not `logical_bytes`. An entry whose `size_qualifiers` is + non-empty stays out of any reclaimable total; state its bytes and reasons separately. +- Report `truncated_paths` (a count under `--quiet`, the list in the snapshot) and every scan error + as coverage gaps. A `large-target-confirmation-required` or `root-children-selection-required` + status names the next step, not a failure. +- Quote hint coverage as a rate: `hinted_entries` of `entries`, never "N findings". +- List protected, locked, needs-elevation, and unverified entries separately, and surface an + `os_autoclean` recommendation as the engine states it. +- Give each hinted entry the evidence the snapshot holds (path, hint, `protected_reasons`, + `size_qualifiers`). A hint has no owner check behind it, so label the list hints for a person to + judge, not verdicts, and rank nothing for deletion. Empty directories stay visible. +- A non-zero exit is a real failure: 2 for an invalid or blocked target, 3 when elevation is needed + or filesystem state could not be verified. Report it and stop. + +## 4. Hand off + +Removal is `/disk-hygiene:clean`, which a person invokes. Close the report with the snapshot path +and that one line. Do not start a removal run and do not propose exact paths for one. When +`effective` was `false`, say instead that removal is disabled by the plugin's configuration. + +## Next + +/disk-hygiene:clean + +Run by a person when the findings warrant removal; it takes the same target, not this snapshot. + +## Gotchas + +- The argument-free probe is not one of the calls the engine-gate adjudicates, so a session in a + permission mode that asks may hold it for a person. That is the "waiting for a person" stop in + step 1, not a reason to skip the probe. +- Under an inline `--plugin-dir` load the probe can report `data_root` as `null` even though the + plugin data directory exists. Stop as step 1 says; do not substitute a guessed path. +- A hint match is discovery evidence only. Reporting "N hinted entries" as "N safe deletions" is the + failure this skill exists to avoid. diff --git a/plugins/disk-hygiene/skills/audit/evals/evals.json b/plugins/disk-hygiene/skills/audit/evals/evals.json new file mode 100644 index 0000000000..a0c95fe05c --- /dev/null +++ b/plugins/disk-hygiene/skills/audit/evals/evals.json @@ -0,0 +1,42 @@ +{ + "skill_name": "audit", + "evals": [ + { + "id": 1, + "name": "probe-first-then-scan-only", + "prompt": "Delegate a disk-hygiene audit of ~/scratch-audit to a subagent and bring back the report.", + "expected_output": "Runs the argument-free kill-switch probe first, takes hook_python and data_root from it, runs a single hygiene.py scan into a run directory under the data root, and reports the snapshot without removing anything.", + "files": [], + "expectations": [ + "Runs kill_switch_probe.py before any hygiene.py call", + "Runs only the hygiene.py scan subcommand, with the absolute hook Python and --data-root taken from the probe", + "Writes the snapshot under the data root's runs directory, not inside the target", + "Deletes, moves, or edits nothing in the target" + ] + }, + { + "id": 2, + "name": "null-data-root-stops", + "prompt": "Run a disk-hygiene audit report on ~/scratch-audit. The probe reports data_root as null.", + "expected_output": "Reports the audit as not run, relays the recovery the guard's denial names, and submits no engine call.", + "files": [], + "expectations": [ + "Submits no hygiene.py call", + "Does not substitute a guessed or default data root", + "States plainly that the audit did not run" + ] + }, + { + "id": 3, + "name": "hints-are-not-verdicts-and-removal-is-a-handoff", + "prompt": "Do an orchestrator scan of ~/scratch-audit for leftovers, then tell me what to delete.", + "expected_output": "Reports the snapshot with coverage gaps and hints labeled as hints, ranks nothing for deletion, and names /disk-hygiene:clean, invoked by a person, as the only route to removal.", + "files": [], + "expectations": [ + "Reports walked:false rollups and truncated paths as coverage gaps, not as small or clean", + "Does not present hinted entries as safe deletions or propose an exact path list for removal", + "Ends by pointing to /disk-hygiene:clean for any removal and starts no removal itself" + ] + } + ] +} From 20477d77116b7109296c5ec20699da6a5cb9273a Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Wed, 30 Sep 2026 01:46:05 -0400 Subject: [PATCH 2/6] fix(disk-hygiene): audit bootstrap matches what the probe and gate do The probe reports hook_python as the interpreter it ran under and the engine-gate does not fire on the probe path, so a bare-python run names nothing. Say what the probe reports, let the scan's own denial supply the guard's interpreter, drop the null-data-root denial that never exists, and drop the unverified claim about the gate reaching subagents. Refs #5516 Co-Authored-By: Claude Opus 5.5 --- plugins/disk-hygiene/skills/audit/SKILL.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/plugins/disk-hygiene/skills/audit/SKILL.md b/plugins/disk-hygiene/skills/audit/SKILL.md index 5eded954fc..97256f2b29 100644 --- a/plugins/disk-hygiene/skills/audit/SKILL.md +++ b/plugins/disk-hygiene/skills/audit/SKILL.md @@ -17,9 +17,10 @@ subcommand and nothing else, and it changes nothing in the target. A filename pa discovery hint, never proof that an entry is junk. This skill carries no hooks of its own. Safety rests on the plugin-level engine-gate in -`hooks/hooks.json`, which checks every Bash or PowerShell call that names `hygiene.py`, in the main -session and in subagents alike. Run no engine subcommand other than `scan`, no shell command that -writes, moves, or deletes under the target, and no compound shell around an engine call. +`hooks/hooks.json`, which checks every Bash or PowerShell call that names `hygiene.py`. Run no +engine subcommand other than `scan`, no shell command that writes, moves, or deletes under the +target, and no compound shell around an engine call. A subagent follows that contract itself, from +the worker brief in step 2. ## 1. Bootstrap @@ -31,11 +32,13 @@ Run the argument-free probe first, before any engine call: Take `hook_python` and `data_root` from its one-line JSON. Every engine call needs the absolute `` and `--data-root`; a bare `python3` is rejected. When `hook_python` is not yet -known, submit the probe once with bare `python`: the guard names its interpreter in the denial, so -rerun the probe with that value. Never submit a scan to learn either value. +known, submit the probe once with bare `python`. The probe reports `hook_python` as the interpreter +it ran under, so that value is the guard's only if the guard's own interpreter ran it. The scan is +admitted only under the guard's interpreter: if it is denied for that reason, the denial names the +interpreter and ran nothing, so rerun the scan with the interpreter it names. - `data_root` is `null`: the install layout proved no data root and the guard denies every engine - call. Report the audit as not run, relay the recovery the guard's denial names, and stop. + call. Report the audit as not run, submit no engine call, and stop. - The probe call is denied or left waiting for a person: report the audit as not run and stop. Do not scan without it. - `hook_python` is older than `MIN_PYTHON` in From a2601505f95d9c752e25d7cc891c9bc134ecf5b5 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Wed, 30 Sep 2026 09:12:30 -0400 Subject: [PATCH 3/6] feat(disk-hygiene): list the audit skill, add a routing eval, bump to 0.30.0 Co-Authored-By: Claude Opus 5.5 --- plugins/disk-hygiene/.claude-plugin/plugin.json | 2 +- plugins/disk-hygiene/CHANGELOG.md | 8 ++++++++ plugins/disk-hygiene/README.md | 5 +++++ plugins/disk-hygiene/skills/audit/evals/evals.json | 12 ++++++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/plugins/disk-hygiene/.claude-plugin/plugin.json b/plugins/disk-hygiene/.claude-plugin/plugin.json index c9ffa07e60..f14b9b97a1 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.29.1", + "version": "0.30.0", "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 without the complete checkout evidence bundle, 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 5930acaef1..bcc645656a 100644 --- a/plugins/disk-hygiene/CHANGELOG.md +++ b/plugins/disk-hygiene/CHANGELOG.md @@ -3,6 +3,14 @@ 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.30.0] - 2026-09-30 + +### Added + +- **`/disk-hygiene:audit`, a model-invocable read-only scan.** A delegated or orchestrated session + can run the probe and one engine `scan` and report the snapshot with its coverage gaps. It runs + no `preview` or `apply` and hands any removal to `/disk-hygiene:clean`, which stays manual-only. + ## [0.29.1] - 2026-09-29 ### Fixed diff --git a/plugins/disk-hygiene/README.md b/plugins/disk-hygiene/README.md index 013b778db8..6a75198574 100644 --- a/plugins/disk-hygiene/README.md +++ b/plugins/disk-hygiene/README.md @@ -223,8 +223,13 @@ launched. ```text /disk-hygiene:clean /disk-hygiene:clean --policy +/disk-hygiene:audit [--max-depth ] [--sizes-only] [--policy ] ``` +`/disk-hygiene:audit` is the model-invocable, read-only counterpart for delegated or orchestrated +scans. It runs the engine's `scan` subcommand only, reports the snapshot with coverage gaps, and +removes nothing. Any removal is a separate `/disk-hygiene:clean` run that a person invokes. + `--root-children` with `--root-child ` inventories only the named immediate children of the target. That is required for an OS-managed volume root (the root itself is never walked) and is also how a depth-1 home audit re-inventories the directories the operator approved, without diff --git a/plugins/disk-hygiene/skills/audit/evals/evals.json b/plugins/disk-hygiene/skills/audit/evals/evals.json index a0c95fe05c..443e14f648 100644 --- a/plugins/disk-hygiene/skills/audit/evals/evals.json +++ b/plugins/disk-hygiene/skills/audit/evals/evals.json @@ -37,6 +37,18 @@ "Does not present hinted entries as safe deletions or propose an exact path list for removal", "Ends by pointing to /disk-hygiene:clean for any removal and starts no removal itself" ] + }, + { + "id": 4, + "name": "cleanup-request-routes-to-clean-not-audit", + "prompt": "Clean up my disk: delete these leftover temp files under ~/scratch-audit.", + "expected_output": "Does not run the audit skill; routes the removal request to /disk-hygiene:clean, which a person invokes.", + "files": [], + "expectations": [ + "Does not invoke /disk-hygiene:audit", + "Names /disk-hygiene:clean as the route for deleting or reclaiming space", + "Removes nothing itself" + ] } ] } From 76d72b418efd035657627a74678c73d4e29f1680 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Wed, 30 Sep 2026 09:28:37 -0400 Subject: [PATCH 4/6] fix(disk-hygiene): register the audit leaf name and align the audit skill with the delegated-worker contract Refs #5516 Register disk-hygiene as the 17th owner of the `audit` leaf name and extend the rationale, so check-skill-leaf-names.sh --check passes. In the audit skill, replace the literal ${CLAUDE_PROJECT_DIR} in the scan template with a placeholder filled with a literal absolute path, tell the parent to fill every token and placeholder in the worker brief from the probe values before spawning, and give the inline --plugin-dir data_root null gotcha its claim/basis/as-of/recheck record. Correct the null-data-root eval, which expected a guard denial that never occurs because no engine call is submitted, and link the 0.31.0 changelog entry to #5516. Co-Authored-By: Claude Opus 5.5 --- plugins/disk-hygiene/CHANGELOG.md | 8 ++++--- plugins/disk-hygiene/skills/audit/SKILL.md | 22 ++++++++++++++----- .../skills/audit/evals/evals.json | 2 +- scripts/skill-leaf-name-registry.txt | 11 +++++++++- 4 files changed, 32 insertions(+), 11 deletions(-) diff --git a/plugins/disk-hygiene/CHANGELOG.md b/plugins/disk-hygiene/CHANGELOG.md index e7d9f4d44b..e3ff05fff4 100644 --- a/plugins/disk-hygiene/CHANGELOG.md +++ b/plugins/disk-hygiene/CHANGELOG.md @@ -7,9 +7,11 @@ All notable changes to the `disk-hygiene` plugin are documented here. Format fol ### Added -- **`/disk-hygiene:audit`, a model-invocable read-only scan.** A delegated or orchestrated session - can run the probe and one engine `scan` and report the snapshot with its coverage gaps. It runs - no `preview` or `apply` and hands any removal to `/disk-hygiene:clean`, which stays manual-only. +- **`/disk-hygiene:audit`, a model-invocable read-only scan** + ([#5516](https://github.com/melodic-software/claude-code-plugins/issues/5516)). A delegated or + orchestrated session can run the probe and one engine `scan` and report the snapshot with its + coverage gaps. It runs no `preview` or `apply` and hands any removal to `/disk-hygiene:clean`, + which stays manual-only. ## [0.30.0] - 2026-09-29 diff --git a/plugins/disk-hygiene/skills/audit/SKILL.md b/plugins/disk-hygiene/skills/audit/SKILL.md index 97256f2b29..b72467ff1c 100644 --- a/plugins/disk-hygiene/skills/audit/SKILL.md +++ b/plugins/disk-hygiene/skills/audit/SKILL.md @@ -55,20 +55,23 @@ directory, a symlink, or a Windows reparse point. ```text "" "${CLAUDE_PLUGIN_ROOT}/skills/clean/scripts/hygiene.py" scan \ --target "" --output "/snapshot.json" \ - --data-root "" [--project-dir "${CLAUDE_PROJECT_DIR}"] \ + --data-root "" [--project-dir ""] \ [--policy ""] [--max-depth ] [--sizes-only] [--quiet] \ [--root-children [--root-child ]...] ``` -`--project-dir` is optional; pass it when the consumer project has standing policy files. What each -flag does, including the large-target and volume-root rules, is in +`--project-dir` is optional; pass it, as a literal absolute path, when the consumer project has +standing policy files. Never pass `${CLAUDE_PROJECT_DIR}` or any other `${...}` token: the guard +rejects shell expansion. What each flag does, including the large-target and volume-root rules, is in [scan-flags.md](../clean/reference/scan-flags.md). For a home directory or another large target, start with `--max-depth 1`, then scan the subtrees the evidence justifies. Never pass `--confirmed-large-scan` on your own: an unbounded walk needs a person's answer. For a subtree worker, the brief to paste into the spawn prompt is -[fan-out-worker-brief.md](../clean/reference/fan-out-worker-brief.md). A worker returns scan -evidence only. +[fan-out-worker-brief.md](../clean/reference/fan-out-worker-brief.md). Before spawning, replace every +`${...}` token and `` in it with the literal absolute value you hold from the probe +(`hook_python`, `data_root`) or from step 2: a worker cannot expand `${...}` tokens, and its data +root is the probe's `data_root`, not `${CLAUDE_PLUGIN_DATA}`. A worker returns scan evidence only. ## 3. Read and report the snapshot @@ -108,6 +111,13 @@ Run by a person when the findings warrant removal; it takes the same target, not permission mode that asks may hold it for a person. That is the "waiting for a person" stop in step 1, not a reason to skip the probe. - Under an inline `--plugin-dir` load the probe can report `data_root` as `null` even though the - plugin data directory exists. Stop as step 1 says; do not substitute a guessed path. + plugin data directory exists. Stop as step 1 says; do not substitute a guessed path. **Claim:** the + guard derives `data_root` only from the `/cache//` install layout or a + registered directory marketplace, so a checkout loaded inline reports `null`. **Basis:** the probe + run from a checkout with neither reported `hook_python` resolved and `data_root: null` on Claude Code + 2.1.285 (Linux); the derivation rule is in + [safety-model.md](../clean/reference/safety-model.md), "Local-directory marketplace installs". + **As of:** 2026-09-30. **Recheck:** the guard's data-root derivation changes, or a Claude Code + release documents a plugin data path for `--plugin-dir` loads. - A hint match is discovery evidence only. Reporting "N hinted entries" as "N safe deletions" is the failure this skill exists to avoid. diff --git a/plugins/disk-hygiene/skills/audit/evals/evals.json b/plugins/disk-hygiene/skills/audit/evals/evals.json index 443e14f648..36726fbfe9 100644 --- a/plugins/disk-hygiene/skills/audit/evals/evals.json +++ b/plugins/disk-hygiene/skills/audit/evals/evals.json @@ -18,7 +18,7 @@ "id": 2, "name": "null-data-root-stops", "prompt": "Run a disk-hygiene audit report on ~/scratch-audit. The probe reports data_root as null.", - "expected_output": "Reports the audit as not run, relays the recovery the guard's denial names, and submits no engine call.", + "expected_output": "Reports the audit as not run because the install layout proved no data root, and submits no engine call, so there is no guard denial to relay.", "files": [], "expectations": [ "Submits no hygiene.py call", diff --git a/scripts/skill-leaf-name-registry.txt b/scripts/skill-leaf-name-registry.txt index 3d1696bf48..1925ec68c6 100644 --- a/scripts/skill-leaf-name-registry.txt +++ b/scripts/skill-leaf-name-registry.txt @@ -107,7 +107,16 @@ setup * # `extract-ssot`'s concern and not this plugin's. provenance is the plugin's # former name and keeps the leaf only as a deprecated shim whose `audit` stub # points to `attribution:audit`. -audit ai-slop,attribution,claude-config,claude-memory,codebase-health,context-budget,github,instruction-placement,machine-health,mcp-tools,mutation-testing,overengineering,plugin-quality,provenance,repo-fleet-hygiene,testing +# disk-hygiene joins on the same grounds. Its object, the leftovers in one +# directory tree, is supplied by the namespace, and the contract is exactly the +# verb's: bare invocation runs the engine's one read-only `scan` and reports the +# snapshot, which is written under the plugin data directory and never into the +# target. The skill has no override and no removal lane; removal is the sibling +# `clean`, which stays manual-only, so a model-invocable leaf that promised +# removal would contradict the verb table's `clean` meaning. `scan` is the +# verb-table synonym but names the engine subcommand, not the product, a +# findings report with a handoff to `clean` (#5516). +audit ai-slop,attribution,claude-config,claude-memory,codebase-health,context-budget,disk-hygiene,github,instruction-placement,machine-health,mcp-tools,mutation-testing,overengineering,plugin-quality,provenance,repo-fleet-hygiene,testing # Fixed verb meaning: deterministic pass/fail gate. skill-quality checks a # skill, toolchain checks a build. instruction-placement joins on its own From 0b5c88c384f7431c49067fc2011d1a57d84c63f2 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Wed, 30 Sep 2026 11:07:45 -0400 Subject: [PATCH 5/6] docs(disk-hygiene): narrow the audit skill's token warning to the two tokens that break Refs #5516 Name ${CLAUDE_PROJECT_DIR} and ${CLAUDE_PLUGIN_DATA} in the scan-template warning instead of every ${...} token, since the skill's own commands use ${CLAUDE_PLUGIN_ROOT}, and word the leaf-name rationale as joining on its own grounds. Co-Authored-By: Claude Opus 5.5 --- plugins/disk-hygiene/skills/audit/SKILL.md | 4 ++-- scripts/skill-leaf-name-registry.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/disk-hygiene/skills/audit/SKILL.md b/plugins/disk-hygiene/skills/audit/SKILL.md index b72467ff1c..118b2b02e0 100644 --- a/plugins/disk-hygiene/skills/audit/SKILL.md +++ b/plugins/disk-hygiene/skills/audit/SKILL.md @@ -61,8 +61,8 @@ directory, a symlink, or a Windows reparse point. ``` `--project-dir` is optional; pass it, as a literal absolute path, when the consumer project has -standing policy files. Never pass `${CLAUDE_PROJECT_DIR}` or any other `${...}` token: the guard -rejects shell expansion. What each flag does, including the large-target and volume-root rules, is in +standing policy files. Never pass `${CLAUDE_PROJECT_DIR}` or `${CLAUDE_PLUGIN_DATA}`: the guard +rejects shell expansion, so pass the literal values. What each flag does, including the large-target and volume-root rules, is in [scan-flags.md](../clean/reference/scan-flags.md). For a home directory or another large target, start with `--max-depth 1`, then scan the subtrees the evidence justifies. Never pass `--confirmed-large-scan` on your own: an unbounded walk needs a person's answer. diff --git a/scripts/skill-leaf-name-registry.txt b/scripts/skill-leaf-name-registry.txt index 1925ec68c6..5255906049 100644 --- a/scripts/skill-leaf-name-registry.txt +++ b/scripts/skill-leaf-name-registry.txt @@ -107,7 +107,7 @@ setup * # `extract-ssot`'s concern and not this plugin's. provenance is the plugin's # former name and keeps the leaf only as a deprecated shim whose `audit` stub # points to `attribution:audit`. -# disk-hygiene joins on the same grounds. Its object, the leftovers in one +# disk-hygiene joins on its own grounds. Its object, the leftovers in one # directory tree, is supplied by the namespace, and the contract is exactly the # verb's: bare invocation runs the engine's one read-only `scan` and reports the # snapshot, which is written under the plugin data directory and never into the From 75bff7ac10e9370bb37d36737f9e3cbb06c0999f Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Wed, 30 Sep 2026 12:58:09 -0400 Subject: [PATCH 6/6] fix(disk-hygiene): audit skill passes literal probe values, not substituted tokens Refs #5516 Co-Authored-By: Claude Sonnet 5.5 --- plugins/disk-hygiene/skills/audit/SKILL.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/disk-hygiene/skills/audit/SKILL.md b/plugins/disk-hygiene/skills/audit/SKILL.md index 118b2b02e0..f66da34be2 100644 --- a/plugins/disk-hygiene/skills/audit/SKILL.md +++ b/plugins/disk-hygiene/skills/audit/SKILL.md @@ -61,8 +61,8 @@ directory, a symlink, or a Windows reparse point. ``` `--project-dir` is optional; pass it, as a literal absolute path, when the consumer project has -standing policy files. Never pass `${CLAUDE_PROJECT_DIR}` or `${CLAUDE_PLUGIN_DATA}`: the guard -rejects shell expansion, so pass the literal values. What each flag does, including the large-target and volume-root rules, is in +standing policy files. Pass literal values only: the guard rejects shell expansion, so never pass +an environment-variable reference. What each flag does, including the large-target and volume-root rules, is in [scan-flags.md](../clean/reference/scan-flags.md). For a home directory or another large target, start with `--max-depth 1`, then scan the subtrees the evidence justifies. Never pass `--confirmed-large-scan` on your own: an unbounded walk needs a person's answer. @@ -71,7 +71,7 @@ For a subtree worker, the brief to paste into the spawn prompt is [fan-out-worker-brief.md](../clean/reference/fan-out-worker-brief.md). Before spawning, replace every `${...}` token and `` in it with the literal absolute value you hold from the probe (`hook_python`, `data_root`) or from step 2: a worker cannot expand `${...}` tokens, and its data -root is the probe's `data_root`, not `${CLAUDE_PLUGIN_DATA}`. A worker returns scan evidence only. +root is the probe's `data_root`. A worker returns scan evidence only. ## 3. Read and report the snapshot