Skip to content

feat(machine-health): add drive-root-litter check surfacing stray volume-root entries - #3498

Open
kyle-sexton wants to merge 2 commits into
mainfrom
feat/machine-health-drive-root-litter
Open

feat(machine-health): add drive-root-litter check surfacing stray volume-root entries#3498
kyle-sexton wants to merge 2 commits into
mainfrom
feat/machine-health-drive-root-litter

Conversation

@kyle-sexton

@kyle-sexton kyle-sexton commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds machine-health catalog check #19, drive-root-litter, so stray files and directories at fixed-volume roots surface on a routine health run instead of only during a manual disk audit. The audit that prompted this found an empty C:\tmp path-translation artifact and a 0-byte C:\log.txt owned by BUILTIN\Administrators — neither visible to any existing check.

Closes #3499

Fix

  • New check scripts/windows/checks/Test-DriveRootLitter.ps1: lists each fixed-volume root non-recursively and diffs it against an expected-entry baseline. Read-only; unelevated; Windows-only.
  • Baseline is data, not logic: references/windows/drive-root-baseline.jsonc holds the expected sets (any-volume housekeeping / system-drive-only / known litter-name shapes) as type-aware, case-insensitive -like patterns. Admitting a newly legitimate entry is a data edit, never a script change.
  • Per-volume posture: system drive gets the full baseline diff; non-system fixed volumes (data drives, Dev Drives) legitimately hold arbitrary user content, so only litter-name shapes (tmp, temp, tmp.*, log.txt, *.tmp) are reported there. Removable/network drives never scanned.
  • Proportionate severity: OK / INFO (1–9 residue) / WARN (≥10, something actively dumping) / UNKNOWN (baseline unreadable or a root unlistable). Never CRIT, and excluded from the trend engine's generic upward upgrade (Invoke-TrendAnalysis.ps1 maps it to residue_count for history only).
  • Trend-aware: deterministic output (sorted residue, day-granularity created dates) so an unchanged dropping feeds identical_streak demotion instead of reading as news weekly.
  • Catalog entry in checks.jsonc, rubric §19 in references/windows/check-catalog.md, plugin bumped to 0.12.0 with changelog entry. Owner and directory-emptiness probes are best-effort (try/catchnull) so a denied ACL read degrades instead of erroring.

Verification

  • Real C:\ acceptance run (unelevated): the manual audit's ground truth was exactly three unexpected entries, and the check reported exactly those three — C:\symbols (directory, SymSrv store), C:\tmp (directory, path-translation artifact), C:\log.txt (0-byte file, owner BUILTIN\Administrators read without elevation) — plus one entry that postdates the audit: C:\worktrees, an empty user-owned directory created 2026-08-30 14:24:32 and registered to no worktree in either repo's git worktree list — a second instance of the same leak CLASS from a different producer, not a recurrence of the same artifact. The C:\tmp leak itself fired once, at 2026-08-30 14:15:56, from the mktemp -d path in plugins/source-control/skills/worktree/context/create.md (addressed separately in PR fix(source-control): convert the mktemp path to Windows mixed form before it feeds the Write tool #3497); it was never deleted or re-created. Zero false positives: 16 of 20 C:\ root entries matched baseline, all stock names (Windows, Program Files, ProgramData, Users, PerfLogs, Recovery, $Recycle.Bin, System Volume Information, pagefile.sys, swapfile.sys, DumpStack.log.tmp, Documents and Settings, OneDriveTemp, Config.Msi, …) suppressed. D:\tmp reported on the data volume via the litter-name posture.
  • New Pester suite Test-DriveRootLitter.Tests.ps1: 16/16 — clean baseline-only root, stray file, stray directory, type-aware matching, severity ladder (never CRIT), non-system posture, UNKNOWN degradations, mutation-free assertion, deterministic ordering.
  • Invoke-TrendAnalysis suite extended for the new mapping: 12/12.
  • Full machine-health suite: 440 passed; the single failure (Test-EnvironmentHealth %VAR% expansion) is machine-environment-dependent and fails identically on an untouched main checkout.
  • scripts/affected-tests.sh: every changed file maps (--explain exit 0); --run exit 3 as documented (all selected suites are Pester, covered above).
  • markdownlint-cli2 clean on changed markdown; PSScriptAnalyzer clean on the check script (test helper carries the same accepted warning as its siblings).
  • Independent fresh-context verifier passed all 11 acceptance criteria (catalog shape, rubric anchor, data-only baseline, zero stock false positives, file+dir reporting, severity vocabulary, no mutation, honest needs_admin, windows-only os, Pester, determinism) with no defects.

Related

Closes #3499. The repo-tooling scripts/check-drive-root-litter.sh is intentionally untouched — it is CI tooling being widened separately, not a machine-health check.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Egdf11hXdBch1HTFmjB8FV

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-31T01:53:28.419020Z 6bffa36 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6bffa36e7d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/machine-health/skills/audit/catalog/checks.jsonc
@kyle-sexton
kyle-sexton force-pushed the feat/machine-health-drive-root-litter branch from 6bffa36 to e4757f8 Compare August 31, 2026 03:29
@claude

claude Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 2m 24s —— View job


CI code review — complete

  • Gather context (PR body, diff, comments, CLAUDE.md/AGENTS.md)
  • Run skip-gate checks (PR open, not draft, substantive change — proceeded with full review)
  • Review changed files for correctness/maintainability findings
  • Post inline findings (none anchor to a changed line — see below)
  • Post final summary

I read all 9 changed files in full: Test-DriveRootLitter.ps1, drive-root-baseline.jsonc, checks.jsonc, check-catalog.md §19, the Invoke-TrendAnalysis.ps1 mapping + its test, Test-DriveRootLitter.Tests.ps1, plugin.json, and CHANGELOG.md.

Correctness: traced the residue-diffing logic (Get-RootResidue, Test-NameMatchesAny, type-aware directory/file matching, system vs. non-system posture), the severity ladder, the UNKNOWN degradation paths (missing/malformed baseline, unlistable root), the deterministic-ordering guarantee, and the trend-engine exclusion (drive-root-litter is mapped to residue_count for history but correctly left out of $upwardWorsens in Invoke-TrendAnalysis.ps1:183-187, matching the PR's "never CRIT" claim). All of it holds up — I didn't find a bug. The 240-char summary-truncation fallback (Test-DriveRootLitter.ps1:239-265) is also safe: the fallback string is small and fixed-length, so it can't itself exceed the cap.

Tests: Test-DriveRootLitter.Tests.ps1 exercises the cases that matter — case-insensitive/type-aware matching, both severity boundaries (9→INFO, 10→WARN, never CRIT), non-system litter-name posture, both UNKNOWN degradation paths, no-mutation, and deterministic ordering. The Invoke-TrendAnalysis addition correctly asserts no upward-worsening upgrade.

One finding — no changed line to anchor it to, so it's here instead of inline:

No other high-signal correctness or maintainability issues found. I did not run the PowerShell/Pester suites myself (no PowerShell available in this environment) — the PR body's test results are author-claimed and unverified by me; my review is based on static reading of the diff and surrounding code.

@claude

claude Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 53s —— View job


Security review (/review:security-review)

  • Gather context (PR diff, changed files)
  • Invoke /review:security-review skill and follow its instructions
  • Post findings/results

Skip gate: no security-relevant surface. Per the skill's skip gate, I'm stopping early and posting nothing else.

This PR adds a new machine-health check (Test-DriveRootLitter.ps1) plus a data-only JSONC baseline, catalog entry, docs, and tests. Reviewed every changed file in the diff (git diff origin/main...HEAD):

  • The script is read-only: it lists volume roots non-recursively (Get-ChildItem -Force), reads owner via Get-Acl (best-effort, try/catchnull), and checks directory emptiness. It never deletes, moves, writes, or executes anything it finds.
  • No command construction from untrusted input — no Invoke-Expression, no string-built commands, no shell-outs.
  • Name matching against the baseline uses PowerShell -like on a static, checked-in pattern list (drive-root-baseline.jsonc), not a regex or code-eval path — no injection surface.
  • -SystemRootPath / -DataRootPath / -BaselinePath are test/manual-scratch overrides on a locally-invoked diagnostic tool, not attacker-reachable input.
  • Invoke-TrendAnalysis.ps1 change is a one-line switch-mapping addition ('drive-root-litter' { return 'residue_count' }), no logic change to trust boundaries.
  • No GitHub Actions/workflow files touched, no dependency or permission changes, no secrets/token handling anywhere in the diff.

No CRITICAL, IMPORTANT, or SUGGESTION findings.

@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown

Last security-reviewed head: 033af5e832497ba9cca89025e5f983bacf161855. On the next push, the relevance gate compares only the commits since this SHA; delete this comment to force a full re-review.

@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown

Claude has reviewed this PR 3 times. The lane skips further automatic reviews after 5; deleting this comment resets the count.

@claude

claude Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 52s —— View job


CI code review — complete

  • Gather context (PR body, diff since last code-review pass, comments, CLAUDE.md/AGENTS.md)
  • Apply skip gate
  • Post summary

Skip gate: trivial change, no new review surface. This lane already reviewed the substantive diff (commit e4757f8) and found one finding: plugins/machine-health/README.md line 9 still advertised "18 checks" after the catalog grew to 19.

The only commit added since that review is c136d66, and it does exactly that fix — a one-line doc correction, 18 checks19 checks, addressing the finding both this lane and Codex raised. No script, test, catalog, or baseline logic changed. Per the skip gate ("change is trivial... / this head already has a successful review from this lane that still applies"), I'm stopping here rather than re-reviewing the already-reviewed feature code.

plugins/machine-health/README.md#L9 — confirmed now reads "19 checks", matches checks.jsonc's 19 enabled Windows entries.

No findings on this pass.
· branch feat/machine-health-drive-root-litter

kyle-sexton and others added 2 commits August 31, 2026 02:15
…ume-root entries

A disk audit found an empty C:\tmp path-translation artifact and a 0-byte
C:\log.txt at the volume root; no existing check would ever have reported
either. The new catalog entry #19 lists each fixed-volume root non-recursively
and diffs it against an expected-entry baseline that is data
(references/windows/drive-root-baseline.jsonc), not script logic: the system
drive gets the full baseline diff, non-system volumes report only known
litter-name shapes, and admitting a legitimate entry is a data edit. Severity
caps at WARN (>=10 residue entries), INFO below, no CRIT, and the check is
excluded from the trend engine's generic upward upgrade; output is
deterministic so an unchanged dropping feeds identical_streak demotion instead
of reading as news. Read-only, unelevated, Windows-only; removal routes to
disk-hygiene:clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Egdf11hXdBch1HTFmjB8FV
The drive-root-litter addition brings the shipped catalog to 19 enabled
Windows checks; README.md still advertised 18. Plugin-wide grep found no
other stale count (CHANGELOG and check-catalog '18' hits are section
references, sdk-eol-table's is Node 18).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Egdf11hXdBch1HTFmjB8FV
@kyle-sexton
kyle-sexton force-pushed the feat/machine-health-drive-root-litter branch from c136d66 to 033af5e Compare August 31, 2026 06:36
@claude

claude Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 1m 24s —— View job


CI code review — complete

  • Gather context (PR body, diff since last code-review pass, comments, CLAUDE.md/AGENTS.md)
  • Apply skip gate
  • Post summary

Skip gate: this head already has a successful review from this lane that still applies. I compared git diff origin/main...HEAD at the current head (033af5e832497ba9cca89025e5f983bacf161855) against what this lane already reviewed:

  • File list and diff stat are identical to the original review pass (10 files, 729 insertions / 2 deletions) — same content as commit 6bffa36 reviewed at 2026-08-31T01:53:28Z.
  • The one finding from that pass (plugins/machine-health/README.md advertising "18 checks" instead of 19) is present and fixed at README.md#L9 — confirmed it reads "19 checks", matching checks.jsonc's 19 enabled Windows entries. This was already re-confirmed by this lane at 2026-08-31T05:06:01Z against commit c136d66.
  • The difference between c136d66 and the current head 033af5e is a rebase onto an updated main (the unrelated refactor: batch-simplify sweep commit landed underneath), not a content change to this PR's diff — git diff c136d66 033af5e --stat shows 85 files touched, all outside plugins/machine-health/ except plugins/machine-health/CHANGELOG.md's date/version stamps picked up from the rebase; git diff origin/main...HEAD for this PR's own content is byte-for-byte the same shape as before.

No new review surface. No findings.
· branch feat/machine-health-drive-root-litter

@claude

claude Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 1m 11s —— View job


Security review (/review:security-review)

  • Gather context (PR body, diff, comments, CLAUDE.md/AGENTS.md)
  • Invoke /review:security-review skill and follow its instructions exactly
  • Post findings/results

Skip gate: this head already has a successful security review that still applies. Per the skill's skip gate, I'm stopping early and posting nothing else.

The security lane's prior pass (03:29:58Z) reviewed the substantive commit and found no findings — the check script is read-only, does no command construction from untrusted input, and matches names only via -like against a static checked-in baseline file. The only commit added since that review is a one-line docs fix (plugins/machine-health/README.md line 9, "18 checks" → "19 checks"), confirmed by diffing the current PR content (git diff origin/main...HEAD, still exactly the same 10 files / +729/-2 as the code-review lane already catalogued) against the previously-reviewed tree. No script, test, catalog, or baseline logic changed since the last security pass.

No CRITICAL, IMPORTANT, or SUGGESTION findings.
· branch feat/machine-health-drive-root-litter

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

machine-health: no check notices stray files or directories at a volume root

1 participant