Skip to content

fix(ci): arm64 rollback smoke gate + dedicated PowerShell lint workflow#32

Closed
mobileskyfi wants to merge 1 commit into
mainfrom
fix/arm64-snapshot-and-ps-lint
Closed

fix(ci): arm64 rollback smoke gate + dedicated PowerShell lint workflow#32
mobileskyfi wants to merge 1 commit into
mainfrom
fix/arm64-snapshot-and-ps-lint

Conversation

@mobileskyfi

@mobileskyfi mobileskyfi commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Post-merge follow-up to #22. The Extended Verification run on main (28281373854) surfaced two reds — both fixed here.

1. PowerShell lint (underlying fix + #28)

Underlying fix: the $using: change in #22 left a non-ASCII em-dash in a comment in version-matrix.ps1, tripping PSUseBOMForUnicodeEncodedFile — the exact rule examples/PSScriptAnalyzerSettings.psd1 documents as its ASCII-clean guard. Made the file ASCII-clean again (now consistent with the other 9 .ps1 examples).

Closes #28: extracted the PSScriptAnalyzer job into a dedicated, reusable lint-powershell.yml that:

  • runs on its own for any push/PR touching examples/**/*.ps1 (+ the analyzer settings) — so .ps1 regressions surface in normal PR CI instead of hiding behind a manual Extended Verification dispatch;
  • exposes workflow_call, and verify-extended.yml now uses: it — one source of truth, dispatch path still covered.

(This PR touches a .ps1, so the new workflow runs on it — self-verifying.)

2. arm64 rollback example smoke

The rollback example failed on macos/arm64 + linux/aarch64 while passing on every x86 accelerator (KVM/HVF/WHPX):

  • snapshot.save/snapshot.load both return clean — but the post-loadvm waitForBoot(60_000) exhausts its full 60 s and REST never comes back.
  • The only common factor across the two failing platforms is the aarch64 virt guest, not the accelerator and not a too-short timeout.

This is the known QEMU limitation that internal savevm/loadvm snapshots don't restore a working aarch64 guest. Since it's not fixable in quickchr, the smoke matrix now gates the example to arch: ["x64"] (new arch field mirroring the existing os gate). Documented in DESIGN.md, the snapshot API docs (types.ts), and the example header. Real fix tracked in #31.

Verification

bun run check green (biome, tsc, markdownlint, cspell, validate-examples = 12 conform, shellcheck); actionlint clean on both workflows. The arm64 gate needs an Extended Verification dispatch on this branch to confirm green (the arm64 smoke only runs there).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a dedicated PowerShell lint workflow for example scripts, with automatic checks on relevant changes and reusable invocation from verification runs.
  • Bug Fixes
    • Improved example smoke test gating to avoid running the rollback example on unsupported CPU architectures.
    • Clarified rollback example guidance and related documentation to reflect the x64-only limitation.
  • Documentation
    • Updated CI, design, and example notes to better explain workflow behavior and architecture-specific constraints.
  • Chores
    • Minor comment cleanup in the PowerShell version matrix example.

Post-merge Extended Verification (run 28281373854 on main) surfaced two reds.

PowerShell lint: the `$using:` fix from PR #22 left a non-ASCII em-dash in a
comment, tripping PSUseBOMForUnicodeEncodedFile (the rule examples/
PSScriptAnalyzerSettings.psd1 documents as the ASCII-clean guard). Made
version-matrix.ps1 ASCII-clean again. Also closes #28: extracted the
PSScriptAnalyzer job into a reusable lint-powershell.yml that runs on its own
for examples/**/*.ps1 push/PR changes (early signal) and is `uses:`-d by
verify-extended.yml, so .ps1 regressions no longer hide behind a manual dispatch.

arm64 rollback smoke: the rollback example failed on macos/arm64 + linux/aarch64
while passing on every x86 accelerator. QEMU's internal savevm/loadvm snapshots
don't restore a working aarch64 `virt` CHR — loadvm returns clean but the guest
wedges and REST never returns (60s waitForBoot exhausted). Gated the example to
arch: ["x64"] in the smoke matrix (new `arch` field mirroring the existing `os`
gate); documented in DESIGN.md, the snapshot API docs, and the example header.
Real fix tracked in #31.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 27, 2026 14:36
@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Extracts PSScriptAnalyzer linting from verify-extended.yml into a standalone reusable lint-powershell.yml workflow triggered on .ps1 changes. Adds architecture-based gating to the smoke test harness, restricting the rollback example to x64 due to savevm/loadvm failures on aarch64. Documents the aarch64 limitation in types, examples, and design docs.

Changes

PowerShell Lint Workflow Extraction

Layer / File(s) Summary
New lint-powershell.yml workflow
.github/workflows/lint-powershell.yml, examples/version-matrix/version-matrix.ps1
Adds a dedicated Windows workflow with push/pull_request path filters for .ps1 files and a workflow_call trigger; installs PSScriptAnalyzer, runs it over examples/**/*.ps1 with settings from PSScriptAnalyzerSettings.psd1, and exits with code 1 on any issues. Fixes an ASCII comment in version-matrix.ps1 that previously triggered a lint failure.
verify-extended.yml delegation
.github/workflows/verify-extended.yml
Replaces the inline runs-on: windows-latest PSScriptAnalyzer job with uses: ./.github/workflows/lint-powershell.yml, preserving the run-examples condition gate.

arm64 Rollback Gating

Layer / File(s) Summary
Arch-gated smoke test logic
test/integration/examples-smoke.test.ts
Runnable interface gains an optional arch field; rollback entry sets arch: ["x64"]; applies predicate additionally filters by process.arch.
arm64 limitation documentation
src/lib/types.ts, examples/rollback/rollback.ts, DESIGN.md, BACKLOG.md
ChrInstance.snapshot JSDoc, rollback example header, DESIGN.md key decisions, and BACKLOG.md completed items document the aarch64 virt savevm/loadvm wedge behavior and x64 gating, referencing issue #31.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

  • #31: The arch-gating in examples-smoke.test.ts, DESIGN.md, src/lib/types.ts, and examples/rollback/rollback.ts directly implements the aarch64 savevm/loadvm mitigation described in #31.
  • #28: The extraction of PSScriptAnalyzer into lint-powershell.yml with push/pull_request path triggers and workflow_call reuse directly implements the reorganization described in #28.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The arm64 rollback smoke gate, docs, and related test changes are unrelated to the linked #28 PowerShell lint workflow. Split the rollback/arm64 changes into a separate PR or link the relevant issue so this PR stays scoped to #28.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the two main changes: arm64 rollback smoke gating and the dedicated PowerShell lint workflow.
Linked Issues check ✅ Passed The new PowerShell lint workflow is path-triggered and reusable from Extended Verification, matching #28's requirements.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/arm64-snapshot-and-ps-lint

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI 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.

Pull request overview

This PR hardens CI signal for examples and PowerShell scripts by (1) extracting PowerShell linting into a reusable workflow that also runs on normal PRs, and (2) gating the rollback example smoke run to x64-only due to an aarch64 QEMU snapshot/restore limitation (documented across design/API/example docs).

Changes:

  • Add arch gating support to the examples smoke harness and restrict rollback smoke to arch: ["x64"].
  • Introduce a dedicated reusable lint-powershell.yml workflow and switch Extended Verification to call it.
  • Fix version-matrix.ps1 to be ASCII-clean again; document the snapshot limitation in DESIGN.md, types.ts, and the example header; update CI docs and backlog.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
test/integration/examples-smoke.test.ts Adds arch gating and restricts rollback to x64 in smoke runs.
src/lib/types.ts Documents the practical x86-only behavior of internal snapshots for aarch64 virt.
examples/version-matrix/version-matrix.ps1 Removes non-ASCII character to satisfy PSScriptAnalyzer ASCII guard.
examples/rollback/rollback.ts Documents aarch64 snapshot limitation and smoke skip rationale.
DESIGN.md Records the arm64 snapshot caveat as a design constraint.
BACKLOG.md Captures the post-merge fixes and references the tracked follow-up.
.github/workflows/verify-extended.yml Replaces inline PSScriptAnalyzer job with a reusable workflow call.
.github/workflows/lint-powershell.yml New dedicated PSScriptAnalyzer workflow (push/PR paths + workflow_call).
.github/instructions/ci.instructions.md Updates CI docs to include the new PowerShell lint workflow.

Comment on lines 91 to +94
const want = (name: string) => FILTER.length === 0 || FILTER.includes(name);
const applies = (r: Runnable) => !r.os || r.os.includes(process.platform);
const applies = (r: Runnable) =>
(!r.os || r.os.includes(process.platform)) &&
(!r.arch || r.arch.includes(process.arch));

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/lint-powershell.yml:
- Around line 16-33: Add a concurrency guard to the lint workflow so only the
latest run for the same branch or PR stays active; in the workflow defined by
the on/pull_request and workflow_call sections, introduce a concurrency group
based on the ref (or PR head) and enable cancelation of in-progress runs. Keep
the change scoped to this workflow so repeated pushes do not leave older
windows-latest lint jobs running after newer commits.
- Line 40: The workflow currently uses a mutable actions reference for
actions/checkout, so update the checkout step to a full commit SHA and, if this
job does not need git authentication later, disable persisted credentials by
setting persist-credentials to false. Use the existing checkout step in the
workflow to make the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 86d7454d-cb89-451a-8e71-71d0cd579703

📥 Commits

Reviewing files that changed from the base of the PR and between 3f57daf and 70cd851.

📒 Files selected for processing (9)
  • .github/instructions/ci.instructions.md
  • .github/workflows/lint-powershell.yml
  • .github/workflows/verify-extended.yml
  • BACKLOG.md
  • DESIGN.md
  • examples/rollback/rollback.ts
  • examples/version-matrix/version-matrix.ps1
  • src/lib/types.ts
  • test/integration/examples-smoke.test.ts

Comment on lines +16 to +33
on:
push:
branches: [main]
paths:
- "examples/**/*.ps1"
- "examples/PSScriptAnalyzerSettings.psd1"
- ".github/workflows/lint-powershell.yml"
pull_request:
branches: [main]
paths:
- "examples/**/*.ps1"
- "examples/PSScriptAnalyzerSettings.psd1"
- ".github/workflows/lint-powershell.yml"
# Reusable: verify-extended.yml calls this so the dispatch path stays covered.
workflow_call:

permissions:
contents: read

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Cancel stale lint runs for the same ref.

Without a concurrency group, every push to the same PR can queue another full windows-latest lint run, so outdated results can outlive the newest commit. That cuts against the “fast PR feedback” goal of this workflow.

Suggested change
 on:
   push:
     branches: [main]
     paths:
       - "examples/**/*.ps1"
       - "examples/PSScriptAnalyzerSettings.psd1"
       - ".github/workflows/lint-powershell.yml"
   pull_request:
     branches: [main]
     paths:
       - "examples/**/*.ps1"
       - "examples/PSScriptAnalyzerSettings.psd1"
       - ".github/workflows/lint-powershell.yml"
   # Reusable: verify-extended.yml calls this so the dispatch path stays covered.
   workflow_call:
 
+concurrency:
+  group: powershell-lint-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref }}
+  cancel-in-progress: true
+
 permissions:
   contents: read
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
on:
push:
branches: [main]
paths:
- "examples/**/*.ps1"
- "examples/PSScriptAnalyzerSettings.psd1"
- ".github/workflows/lint-powershell.yml"
pull_request:
branches: [main]
paths:
- "examples/**/*.ps1"
- "examples/PSScriptAnalyzerSettings.psd1"
- ".github/workflows/lint-powershell.yml"
# Reusable: verify-extended.yml calls this so the dispatch path stays covered.
workflow_call:
permissions:
contents: read
on:
push:
branches: [main]
paths:
- "examples/**/*.ps1"
- "examples/PSScriptAnalyzerSettings.psd1"
- ".github/workflows/lint-powershell.yml"
pull_request:
branches: [main]
paths:
- "examples/**/*.ps1"
- "examples/PSScriptAnalyzerSettings.psd1"
- ".github/workflows/lint-powershell.yml"
# Reusable: verify-extended.yml calls this so the dispatch path stays covered.
workflow_call:
concurrency:
group: powershell-lint-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
🧰 Tools
🪛 zizmor (1.26.1)

[warning] 16-30: insufficient job-level concurrency limits (concurrency-limits): workflow is missing concurrency setting

(concurrency-limits)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/lint-powershell.yml around lines 16 - 33, Add a
concurrency guard to the lint workflow so only the latest run for the same
branch or PR stays active; in the workflow defined by the on/pull_request and
workflow_call sections, introduce a concurrency group based on the ref (or PR
head) and enable cancelation of in-progress runs. Keep the change scoped to this
workflow so repeated pushes do not leave older windows-latest lint jobs running
after newer commits.

Source: Linters/SAST tools

name: Lint PowerShell examples
runs-on: windows-latest
steps:
- uses: actions/checkout@v5

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Pin actions/checkout to a full commit SHA.
actions/checkout@v5 is a mutable ref. If no later step needs git auth, set persist-credentials: false too.

🧰 Tools
🪛 zizmor (1.26.1)

[warning] 40-40: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 40-40: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/lint-powershell.yml at line 40, The workflow currently
uses a mutable actions reference for actions/checkout, so update the checkout
step to a full commit SHA and, if this job does not need git authentication
later, disable persisted credentials by setting persist-credentials to false.
Use the existing checkout step in the workflow to make the change.

@mobileskyfi mobileskyfi marked this pull request as draft June 27, 2026 15:04
@mobileskyfi

Copy link
Copy Markdown
Contributor Author

On hold. The PowerShell parts (ASCII-clean fix + reusable lint-powershell.yml for #28) are grounded and CI-verified. The arm64 rollback change is not — it masks a real signal. I concluded "QEMU snapshots don't work on aarch64" from a single CI run plus training-data priors, without reproducing locally, even though quickchr runs arm64 CHR under TCG on this Intel host. A failing example is exactly the canary this suite exists to provide; skipping it is the wrong first move. Not merging until the snapshot behaviour is actually reproduced and root-caused (#31).

mobileskyfi added a commit that referenced this pull request Jun 27, 2026
…e skipping (#33)

Codifies the discipline that was missing when a single Extended Verification run
got mistaken for a proven arm64 QEMU limitation and "fixed" by arch-gating the
rollback example (held in #32, real grounding tracked in #31).

The anti-masking rules already existed but were siloed in testing.instructions.md
and framed only around timeout-bumps; the most dangerous masking move — skip /
os-gate / arch-gate — was never named, and nothing required reproducing a claimed
platform limitation locally (which we can: arm64 CHR runs under TCG on Intel).

- examples.instructions.md: examples are canaries; a failing example is a quickchr
  bug until a LOCAL repro proves otherwise; never gate a failure as the first move;
  don't record an unproven cause in DESIGN/API docs/BACKLOG/issues/skills.
- testing.instructions.md: name skip/gating as the worst masking move (worse than a
  timeout-bump); "platform limitation" is a hypothesis until reproduced locally; one
  CI failure must not cascade into doc/skill edits.
- ci.instructions.md: one CI run is a signal, not a fact — reproduce locally, don't
  let one red run cascade.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@mobileskyfi

Copy link
Copy Markdown
Contributor Author

Closing — split and superseded.

This closes the skip, not the question. The actual arm64 + qcow2 snapshot behavior stays open in #31 for a future session to reproduce locally under TCG and root-cause before anything is gated or documented (also tracked as a [ ] in BACKLOG.md).

The branch fix/arm64-snapshot-and-ps-lint is left intact so the first-pass arm64 diff (the arch gate + DESIGN.md/types.ts/rollback.ts notes) remains viewable here as a reference for that work.

mobileskyfi added a commit that referenced this pull request Jun 27, 2026
…ll lint workflow

Post-merge Extended Verification flagged PSUseBOMForUnicodeEncodedFile: the
$using: fix from #22 left a non-ASCII em-dash in a comment in version-matrix.ps1
(the exact case examples/PSScriptAnalyzerSettings.psd1 documents as its
ASCII-clean guard). Made the file ASCII-clean again, matching the other 9 .ps1
examples.

Closes #28: extracted the PSScriptAnalyzer job into a dedicated reusable
lint-powershell.yml that runs on its own for any push/PR touching
examples/**/*.ps1 (early signal in normal PR CI) and is `uses:`-d by
verify-extended.yml, so .ps1 regressions no longer hide behind a manual dispatch.

Split out of the held PR #32; the arm64/snapshot half stays there (#31).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
mobileskyfi added a commit that referenced this pull request Jun 27, 2026
…ll lint workflow (#34)

Post-merge Extended Verification flagged PSUseBOMForUnicodeEncodedFile: the
$using: fix from #22 left a non-ASCII em-dash in a comment in version-matrix.ps1
(the exact case examples/PSScriptAnalyzerSettings.psd1 documents as its
ASCII-clean guard). Made the file ASCII-clean again, matching the other 9 .ps1
examples.

Closes #28: extracted the PSScriptAnalyzer job into a dedicated reusable
lint-powershell.yml that runs on its own for any push/PR touching
examples/**/*.ps1 (early signal in normal PR CI) and is `uses:`-d by
verify-extended.yml, so .ps1 regressions no longer hide behind a manual dispatch.

Split out of the held PR #32; the arm64/snapshot half stays there (#31).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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.

ci: reorganize PowerShell lint into a dedicated *.ps1-triggered workflow

2 participants