Skip to content

feat(machine-health): refresh a stale monthly wrapper copy from setup check - #10419

Merged
melodic-automation-lanes[bot] merged 1 commit into
mainfrom
work-resolve-issue/issue-9253-40441497330-1
Oct 27, 2026
Merged

melodic-automation-lanes[bot] merged 1 commit into
mainfrom
work-resolve-issue/issue-9253-40441497330-1

Conversation

@melodic-automation-lanes

Copy link
Copy Markdown
Contributor

Closes #9253

Summary

Opened by the work-resolve-issue lane. The run's own summary:

Builds the decision recorded on #9253, which rescoped the issue to the wrapper copy only. Install-MonthlyRun now writes the wrapper through the existing Write-StateFile recipe (temp file in the same folder, then a swap) instead of Copy-Item in place. When setup check step 6 finds WrapperCurrent false, it now offers the refresh: only on the owner's yes it runs Install-MonthlyRun alone (never schtasks), then Test-MonthlyRunCurrent, and reports the result. The skill description, the check heading and the README name that one write.

Not verified

  • Pester suites (Install-MonthlyRun.Tests.ps1, SkillCommands.Tests.ps1) were not run: this lane's Bash runs only the named wrappers, so no pwsh. They are left to the PR's Windows test CI.
  • typos and the changed-skills skill-quality check were skipped by check-affected (typos not installed; changed-skills runs the checked tree's own code). They are left to CI.
  • The 35-day never-fired verdict in check step 6 still measures from the copy's write time, so a refresh restarts that clock. The prose now sequences around this, but measuring from the task's registration time instead would need its own change.
  • Untracked dotfiles (.bash_profile, .bashrc, .gitconfig, .idea, .mcp.json, .profile, .ripgreprc, .vscode, .zprofile, .zshrc) are in the checkout root. This run did not create them and they are not part of this change; leave them out of the patch.

Fix

  • plugins/machine-health/skills/setup/scripts/Install-MonthlyRun.ps1: dot-sources the audit lib's Write-StateFile.ps1 and writes the template text through Write-StateFile instead of Copy-Item; synopsis and description updated
  • plugins/machine-health/skills/setup/SKILL.md: description and check heading name the one write (a stale wrapper copy, only on the owner's yes); step 6 offers the refresh with its command, says it never touches the task, and says to report the no-status-file 35-day verdict before offering because the
  • plugins/machine-health/skills/audit/tests/windows/scheduler/Install-MonthlyRun.Tests.ps1: new case where a stale copy, after Install-MonthlyRun, reports current and the scheduler folder holds only monthly-run.ps1 (no temp file)
  • plugins/machine-health/skills/audit/tests/windows/SkillCommands.Tests.ps1: setup now has 10 PowerShell fences; adds the 'check wrapper refresh' command case (Index 2) and moves the later indexes down by one
  • plugins/machine-health/skills/audit/scripts/windows/lib/Write-StateFile.ps1: synopsis lists the monthly wrapper copy among the files it replaces
  • plugins/machine-health/README.md: setup row says check (default) has one write, refreshing a stale wrapper copy on the owner's yes
  • .changes/machine-health/feat-9253-refresh-monthly-wrapper-4b8e2c71.md: minor changelog fragment (Changed: check offers the refresh; Fixed: atomic wrapper write)

Verification

The runner ran each check from the base copy against 5817a8b:

  • scripts/check-changelog-fragments.sh --check: passed

The run reports:

  • check-changelog-fragments: all 11 fragments under .changes/ valid
  • check-affected: 10 passed, 7 skipped over the changed files, with no failures
  • cant-fail-scan --file Install-MonthlyRun.Tests.ps1 --check: PASS, 5 test blocks, no gating findings
  • cant-fail-scan --file SkillCommands.Tests.ps1 --check: PASS, 9 test blocks, no gating findings
  • fresh-context subagent review of the whole diff: two findings, both fixed. (1) SkillCommands.Tests.ps1 indexes setup's PowerShell fences by position, so the new fence broke the count and every later index; fixed. (2) A refresh resets the copy's LastWriteTime, which the no-status-file 35-day never-fi
  • The lane run: https://github.com/melodic-software/claude-code-plugins/actions/runs/40441497330

Left out: the items under Not verified.

Related

#9253

Lane-Activity: work-resolve-issue/resolve-issue
@github-actions

Copy link
Copy Markdown
Contributor

claude-review reviewed 5817a8ba2f301a0d05a3ab3e93435774da78ffd3: 0 finding(s), 0 as inline comments.

No blocking findings on #10419.

Reviewed: all 7 files in the diff, the closing issue #9253, and the existing Write-StateFile.ps1 and Install-MonthlyRun.ps1 code. No file in the diff matches the trusted-path globs. I could not run pwsh, so I ran no tests. The Pester results are unverified here, and the PR body says the author did not run them either.

Closing issue #9253, acceptance criteria:

  • Install-MonthlyRun writes through Write-StateFile, not Copy-Item: met. Install-MonthlyRun.ps1:28-29 reads the template and calls Write-StateFile -Update { $text }.GetNewClosure(). The closure is needed, and Write-StateFile passes the current text to -Update, which the block ignores.
  • Step 6 offers the refresh, and runs only Install-MonthlyRun then Test-MonthlyRunCurrent on the owner's yes: met. SKILL.md adds the command, says it never touches the task, and says to write nothing without a yes. SkillCommands.Tests.ps1 covers the new fence: its count goes to 10 and the later indexes shift by one.
  • The check heading and skill description name the one write: met in the SKILL.md heading, the description, the Output section and the README.
  • A test where a stale copy becomes current and leaves no temp file: met. The new case in Install-MonthlyRun.Tests.ps1 appends to the copy, reinstalls, asserts WrapperCurrent is true, and asserts the scheduler folder holds only monthly-run.ps1. It can fail if Write-StateFile leaves its .tmp file or the content differs.

Correctness checks:

  • Comparison: Test-MonthlyRunCurrent compares ReadAllText output, which strips a BOM. Write-StateFile writes UTF-8 without a BOM, so a refreshed copy compares equal to the template.
  • Dependencies: Write-StateFile.ps1 dot-sources its own helpers using $PSScriptRoot, so the nested dot-source resolves. $script:SharingViolationHResult is defined in Get-InnerHResult.ps1.
  • First install: Write-StateFile handles the missing-destination case through File.Move.

Fragment and manifest: the changelog fragment is bump: minor, which fits a new owner-gated write path in check. No plugin.json or marketplace.json change, so no manifest lines apply.

Known trade-off, not counted as a finding: a refresh resets the copy's write time, which restarts the 35-day clock that SKILL.md:139 uses for the no-status-file verdict. The PR discloses this under "Not verified". The added prose at SKILL.md:168 tells the agent to report that verdict before offering the refresh, which is reasonable mitigation. Measuring from the task's registration time would be a separate change.

Spend: no billed resources or paid plan changes. No hold.

@github-actions

Copy link
Copy Markdown
Contributor

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

No security issues found in this pull request.

I read the full diff, the PR context and the unchanged Write-StateFile.ps1 and Install-MonthlyRun.ps1 that it changes.

  • Trusted paths and trust controls: none of the seven changed files match a TRUSTED PATHS glob, and none changes a trust control (trusted-trigger list, lane token scope, kill switch, merge holds, broker rules). There is no plugin manifest change, so there are no manifest <field> lines.
  • Refresh write: Install-MonthlyRun now writes the wrapper through Write-StateFile (temp file in the same folder, then File.Replace or File.Move) instead of Copy-Item. The content is the plugin's own template, read with ReadAllText. The destination is fixed as <StateBase>/scheduler/monthly-run.ps1, and no caller-supplied text reaches the path or the content. The .GetNewClosure() call captures only $text. The temp file name is a GUID, and the lib never moves over an existing file. Same write target, same trust level, and a more robust write than before.
  • Owner-consent gate: the new check step 6 refresh is gated on the owner's own yes in the conversation. The skill is disable-model-invocation: true, as schedule already was. The refresh command runs Install-MonthlyRun only, never schtasks, so the task definition and what it launches are unchanged. The gate is prose, as it already was for schedule, and this change adds no new bypass. The step reads as stronger than the old schedule-only path, not weaker.
  • Instruction surface: the "read-only" wording of check is narrowed to name this single owner-approved write. No rule is deleted or softened without a replacement. The write still needs the owner's yes, which the skill text states in the description, heading, step 6 and Output.
  • Tests and docs: the Pester index shifts and the new refresh case are consistent with the added fence. The README and changelog edits are inert.

Spend: none. No paid plan, billing setting or billed resource changes.

critical-findings: 0

@melodic-automation-lanes

Copy link
Copy Markdown
Contributor Author

The unattended merge path armed native auto-merge at head 5817a8ba2f301a0d05a3ab3e93435774da78ffd3.

@melodic-automation-lanes
melodic-automation-lanes Bot added this pull request to the merge queue Oct 27, 2026
Merged via the queue into main with commit 778a729 Oct 27, 2026
43 checks passed
@melodic-automation-lanes
melodic-automation-lanes Bot deleted the work-resolve-issue/issue-9253-40441497330-1 branch October 27, 2026 05:38
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: keep the installed monthly wrapper current

0 participants