Skip to content

feat(machine-health): add the top-processes and backup-status checks - #8935

Merged
kyle-sexton merged 14 commits into
mainfrom
feat/machine-health-top-processes-backup
Oct 22, 2026
Merged

kyle-sexton merged 14 commits into
mainfrom
feat/machine-health-top-processes-backup

Conversation

@kyle-sexton

Copy link
Copy Markdown
Member

No related issue: Phase 8 of the owner-approved machine-health PC-checkup plan (ADR 0081, #8906).

Summary

This adds two checks:

  • top-processes answers "what's slowing this computer down". It samples processes over a window and grades CPU, memory, processor queue and disk latency against the Microsoft Learn bands for Windows Server, and the output says those bands are for Windows Server.
  • backup-status answers "is this computer backed up". It reads every backup signal: system image, restore points, File History, Windows Backup, and OneDrive folder backup.

It also adds a generic appendix arm, so every list-style check's items now appear in the markdown report.

Fix

  • Adapters:
    • Get-ProcessSample takes two process snapshots -SampleSeconds apart, with the counters sampled in between. CPU % is delta / (interval × logical CPUs) × 100. The counter paths are held once and also build the reproduction command.
    • Get-BackupSignal reads the Backup channel by numeric event id and never reads localized labels. wbadmin runs only when elevated, and only its exit code and version-id count are used. Its sources, ids, paths and keys are held once and build $commands.
  • The two checks:
    • Test-TopProcesses items are FindingItems of a new process kind (identity: the lowercased image name), so they can be muted. Disk latency is graded only on a window of at least the sustained window. sample_seconds is reported.
    • Test-BackupStatus is WARN when no source is present and UNKNOWN when any source needs admin. The System Image Backup deprecation note is always in the detail.
  • Orchestrator: a new -SampleSeconds parameter, validated 5-60 with a default of 15, is passed to checks that declare it. The per-check timeout is now Get-CheckTimeoutSec: max(90, window + 30).
  • Generic appendix arm in ConvertTo-AppendixMarkdown: it renders items[] for any check, and it never prints an exclusion item's title or value.
  • Catalog and elevation matrix: a backup-status row in the elevation matrix. Catalog entries for top-processes and backup-status, both reliability with no cadence, and sections 26 and 27. Sections and entries 20-27 are positions assigned across the sibling PRs.
  • Changelog fragment (minor).

Verification

  • run-tests.ps1 exits 0: 789 passed, 0 failed, 1 skipped.
  • Each filtered suite exits 0. The named test "an exclusion item through the generic arm emits neither its title nor its value" passes.
  • Host smoke with -SampleSeconds 60 exits 0: top-processes 62768 ms and storage-top-n 39683 ms, both under 75,000 ms. The default 15 s run also passes.
  • A no-events Backup channel returns system-image as unknown.
  • typos, machine-paths, the TODO lint and the changelog check all pass.
  • Code-design review: 4 CRITICAL findings, all fixed. Three were reproduction commands and source ids retyped instead of built from one source. The fourth was the sample window, the sustained window and the dispatch timeout depending on each other with nothing tying them together.
  • A fresh-context phase verifier passed 11 of 11 criteria.

Related

backup-status reads UNKNOWN on standard runs until the elevated pass lands, because restore points need admin.

🤖 Generated with Claude Code

kyle-sexton and others added 6 commits October 21, 2026 16:33
top-processes samples process CPU deltas and system counters over the
orchestrator's new -SampleSeconds window (passed through Get-CheckArgument)
and grades them against Microsoft Learn's Windows Server bands, labeled as
such; disk latency is graded only on a sustained window.

backup-status reads every backup signal through Get-BackupSignal (Backup
channel by event id, wbadmin and restore points elevated only, File
History, Windows Backup log, OneDrive Known Folder Move policy) and adds
its elevation-matrix row.

The report appendix gains a generic arm that lists any check's items[] by
title, severity and muted state, withholding exclusion values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Basis strings and docs say "version id" rather than the wbadmin label,
and the deprecation sentence is held at script scope so the failure
summary carries it too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Get-FindingKey gains a process kind whose identity is the lowercased
image file name, never the PID, so top-processes items carry a key and
can be muted; a muted process stays listed and never raises severity.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Counter paths, backup channel, class, path, log, policy keys and source
ids are named once in their adapters and the checks build commands from
them. The dispatch timeout covers the sampling window through
Get-CheckTimeoutSec, and a test ties the -SampleSeconds maximum to the
sustained window. Catalog records take the Pointer / As of / Recheck
trigger form and hold the rationale the scripts now cite. The System
Image Backup deprecation rides on the summary only when a system image
is the present source.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…test headers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 21, 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-10-21T21:14:15.683392Z dcc25e1 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.

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

claude-security-review reviewed 389adcf43c0a79dfae60fb28625ea9265a9bd738: 0 finding(s), 0 as inline comments.

Security review: PR #8935 (head 389adcf)

Result: no security findings reported, no inline comments posted.

Scope. The PR adds the top-processes and backup-status checks to the Windows machine-health audit. No plugin manifest (plugin.json / marketplace.json) changed, so there are no manifest <field> lines.

I read these files in full: Test-TopProcesses.ps1, Get-ProcessSample.ps1, Get-BackupSignal.ps1, Get-CheckArgument.ps1, New-FindingItem.ps1, ConvertTo-AppendixMarkdown.ps1.

Not covered. I could not run git diff against the base (the command was blocked), so the other changed files were not diffed line by line. I did not read Test-BackupStatus.ps1, Get-ElevationMatrix.ps1, Invoke-MachineHealthCheck.ps1, Invoke-NativeCommand.ps1, the catalog or the tests.

Why nothing was reported:

  • Read-only access. The checks only read: Get-Process, Get-Counter, Get-WinEvent, Get-CimInstance, registry reads, and a Get-ChildItem on the File History folder. Nothing in what I read writes, deletes, installs or makes network calls.
  • Fixed command line. wbadmin runs only when elevated and with the constant arguments get versions. No machine-derived value reaches a command line.
  • Backup event text. Event message text is never read, only event ids, the BackupTime XML field (parsed with TryParse) and counts.
  • Paths and registry keys. All come from constants and use -LiteralPath. The OneDrive redirect test is a prefix match on a \-terminated root, so a sibling folder does not match.
  • Argument splatting. Get-CheckArgument passes only parameters the check script declares. SampleSeconds is an [int] that sets the sampling window and the dispatch timeout. Its upper bound is enforced in the orchestrator, which I did not read.
  • Mute keys. They are a SHA-256 prefix of the lowercased image file name, compared with -cin. Muting only hides one item from the severity fold and gives no new access.
  • Report text. The item title goes through Format-MachineText (control and bidi characters replaced, length capped), and the appendix renders it with Format-MarkdownCell.

Instruction-surface lens. The diff deletes or narrows no standing instruction, so the exception register was not consulted.

Note below the reporting bar (not counted). Test-TopProcesses.ps1 puts raw process names into the summary string ($top) and into the item fields name and path. Those bypass Format-MachineText, which cleans only the title. A local user could launch a process whose file name carries a bidi-override character or instruction-like text. Windows file names cannot contain newlines and the summary is capped at 240 characters, so the effect is limited to cosmetic misdirection in a report about that same machine. Running the top-3 list through Format-MachineText would match the file's own untrusted-display-data policy.

@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: dcc25e1536

ℹ️ 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".

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

claude-review reviewed 389adcf43c0a79dfae60fb28625ea9265a9bd738: 0 finding(s), 0 as inline comments.

Code review of PR #8935 at head 389adcf: no findings.

I read the full diff (20 files) and the PR context. I did not run the Pester suite or any script. The author's "789 passed" claim is author-claimed and unverified by me.

What I checked

  • Helper dependencies: Test-TopProcesses.ps1 uses Get-WorstSeverity and Get-UnmutedSeverity without dot-sourcing them itself. New-FindingItem.ps1 defines the latter and dot-sources the former, so both resolve.
  • Generic appendix arm: I checked every existing check that emits detail.items (app-last-use, browser-extensions, defender, firewall-rules, network-listeners, startup-items, storage-top-n). All build their items with New-FindingItem, so each item carries title, severity and muted. The new Get-ItemsAppendix cannot fail on a missing property under StrictMode. Defender exclusion items are always keyed exclusion:…, so the placeholder fires for them.
  • Timeout and window wiring: Get-CheckTimeoutSec returns max(90, window + 30), which is 90 s at the 60 s maximum. The sustained window is 60 s and equals the [ValidateRange(5, 60)] maximum, and a test pins that relation.
  • Summary truncation arithmetic: Test-TopProcesses cuts the summary only when it is over 240 characters, so the Substring length cannot exceed the body's length.
  • Process and event handling: Get-ProcessSample has no divide-by-zero or reused-pid path, and the median and counter-matching logic is sound. The Get-BackupSignal event handling is sound, as are the KFM redirect and policy rules.
  • Manifests, closing issue, rules: No plugin.json or marketplace.json changed, so there are no manifest lines to report. The PR states "No related issue", so there are no closing-issue criteria. The skill-bodies-state-current-rules rule covers the new catalog sections. They carry pointers, as-of dates and recheck triggers, and restate no band values.

Design note, not a finding: backup-status reads UNKNOWN on every non-elevated run, even when a source such as OneDrive Known Folder Move is present. That follows the documented rubric and a dedicated test. The PR's Related section says so openly, so I left it unflagged.

kyle-sexton and others added 4 commits October 21, 2026 17:24
…sions

onedrive-kfm reads present when a known folder resolves under a OneDrive
root, or when a Known Folder Move policy names a tenant and moves a
folder; zero folder values and notification or prompt policies are not
evidence. A positive wbadmin version count keeps system-image present
when the retained channel holds only failed runs. The top-processes
summary says when system counters were unreadable instead of printing
blank readings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…op-processes-backup

# Conflicts:
#	plugins/machine-health/skills/audit/catalog/checks.jsonc
#	plugins/machine-health/skills/audit/reference/windows/check-catalog.md
#	plugins/machine-health/skills/audit/scripts/windows/lib/Get-ElevationMatrix.ps1
#	plugins/machine-health/skills/audit/tests/windows/lib/Get-ElevationMatrix.Tests.ps1
Lane-Activity: pr-unblock/resolve-conflicts
…s-backup' into feat/machine-health-top-processes-backup

# Conflicts:
#	plugins/machine-health/skills/audit/catalog/checks.jsonc
#	plugins/machine-health/skills/audit/reference/windows/check-catalog.md
kyle-sexton and others added 4 commits October 21, 2026 17:44
…ary is capped

The summary drops the process list first, then cuts the rest of the
body, so the label naming which bands apply always survives the cap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…op-processes-backup

# Conflicts:
#	plugins/machine-health/skills/audit/catalog/checks.jsonc
#	plugins/machine-health/skills/audit/reference/windows/check-catalog.md
Lane-Activity: pr-unblock/resolve-conflicts
…s-backup' into feat/machine-health-top-processes-backup
@kyle-sexton
kyle-sexton added this pull request to the merge queue Oct 22, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 22, 2026
@kyle-sexton
kyle-sexton added this pull request to the merge queue Oct 22, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 22, 2026
@kyle-sexton
kyle-sexton added this pull request to the merge queue Oct 22, 2026
Merged via the queue into main with commit fa38e99 Oct 22, 2026
27 checks passed
@kyle-sexton
kyle-sexton deleted the feat/machine-health-top-processes-backup branch October 22, 2026 03:34
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.

1 participant