Repository navigation
feat(machine-health): add finding items and the read-only mute path - #8917
Conversation
The Start-Job dispatcher moves unchanged from the orchestrator into scripts/windows/lib so its own suite can run it. The suite covers the parsed result, a string[] argument crossing the job boundary, and the timeout, no_output and invalid_json reasons. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New-FindingItem.ps1 builds the FindingKey (<kind>:<first 16 hex of the SHA-256 of the lowercased kind and identity fields>), the FindingItem shape, the ReadState closed set, and the unmuted severity fold over Get-WorstSeverity. A read state other than ok or absent never folds to OK. Mutes live in their own state/mutes.json with a new mutes.schema.json at 1.0; approvals.json and its schema are unchanged. Get-MuteState reads it with FileShare.ReadWrite | Delete and creates, migrates and logs nothing. The orchestrator reads it before dispatch and Get-CheckArgument passes -MutedKeys as a string[] to the eight list-style check ids only. Get-ApprovalState now reads with the same shared open. An end-to-end case runs a mute for startup-items through Get-MuteState, Get-MutedFindingKey, Get-CheckArgument and the Start-Job dispatcher. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Get-CheckArgument takes the check's -ScriptPath and returns only the candidate arguments the script declares, read from its parameter metadata, in place of a fixed list of eight check ids. A check that declares -MutedKeys now receives it with no per-id edit, and a list-style check can also take -ReportPath or -LogPath. The share-delete read moves into one helper, Read-SharedText, used by Get-ApprovalState and Get-MuteState and covered by its own suite. Get-MuteState finds its schema through Resolve-SkillRoot. The golden FindingKey tests validate each key inside a mutes.json against mutes.schema.json, and every accepted kind is checked the same way. The ReadState set is held in one variable. output-schema.md documents the FindingItem shape once; approvals.md points to it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
claude-security-review reviewed No security issues in the incremental change (2ca2f2a..8bb4760).
The change touches no instruction surface, so the instruction-surface lens did not apply. I did not re-review the other files, which are unchanged since the last review. |
|
claude-review reviewed No findings. I reviewed only the incremental change since
The incremental change touched no other files. The rest of the PR was reviewed at |
Use -cin for the case-sensitive mute lookup and a non-word accented test string, so the repository's typos check passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No related issue: Phase 2 of the owner-approved machine-health PC-checkup plan; implements ADR 0081 (#8906).
Summary
Adds the integration slice that every new list-style check builds on:
state/mutes.jsonwith its own schema;A mute keeps an item listed but stops it from raising the check's severity.
Fix
lib/New-FindingItem.ps1adds:Get-FindingKey:<kind>:<first 16 hex of SHA-256(lower(kind|identity))>, over 9 kinds;New-FindingItem;Assert-ReadState;okorabsentnever folds to OK).catalog/schemas/mutes.schema.jsonat 1.0.approvals.schema.jsonis unchanged byte for byte.lib/Get-MutedFindingKey.ps1addsGet-MuteState, which is read-only: it creates no folder or file and never migrates TODO.md. It also addsGet-MutedFindingKey.lib/Read-SharedText.ps1is the one share-delete reader (FileShare ReadWrite|Delete).Get-ApprovalStateandGet-MuteStateboth use it.Get-CheckArgumenttakes-ScriptPathand returns only the arguments the check script declares. A new check that declares-MutedKeysreceives it without a per-id edit, and a check that doesn't declare it is never handed it.Invoke-CheckWithTimeoutmoves to its own lib file in a separate commit, with its behavior unchanged.output-schema.mddocuments the FindingItemdetailshape, andapprovals.mddocuments mutes.json.minor): a downgraded plugin ignores mutes.json, so muted items raise severity again until the upgrade. Nothing FAILs and nothing is stripped.Consumers found by grep:
Assert-ApprovalState(approvals only, unchanged);Get-ApprovalState(now reads throughRead-SharedText);checkstep 3 andapprove=(approvals only, unchanged);approvals.md;Verification
run-tests.ps1exits 0: 622 passed, 0 failed, 1 skipped.New-FindingItem,Get-MutedFindingKey,Get-ApprovalState,Get-CheckArgument,Invoke-CheckWithTimeoutandRead-SharedText.Start-Job: a mute for one item returnsmuted: true, the item's WARN is ignored by the check severity, anditems_countis 2 withmuted_count1.sha256sumand with .NET.-DryRun) exits 0: 19 checks ok, 0 failed.Related
Next phases: the state writer, run lock and sync-root guard; then the storage top-N check, the first check to emit FindingItems.
🤖 Generated with Claude Code