Skip to content

✨ feat: make AutoUnattend-minimal and defer setup OOBE#14

Merged
Timpan4 merged 4 commits intomainfrom
ta-branch-1
Apr 7, 2026
Merged

✨ feat: make AutoUnattend-minimal and defer setup OOBE#14
Timpan4 merged 4 commits intomainfrom
ta-branch-1

Conversation

@Timpan4
Copy link
Copy Markdown
Owner

@Timpan4 Timpan4 commented Mar 28, 2026

Summary by CodeRabbit

  • Documentation

    • Updated installation and ISO layout docs to reflect an ultra-minimal, OOBE-only setup and the new location where payload files are staged for installation.
    • Clarified post-install responsibilities and reboot/failure guidance now centralized under the bootstrap step.
  • Configuration

    • Simplified OOBE to keep installation fully manual with fewer automated tweaks; adjusted which setup screens and wireless prompts are shown during first run.
  • Tests

    • Static checks updated to enforce minimal initial logon activity and to validate staged payload references before ISO build.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 28, 2026

📝 Walkthrough

Walkthrough

The PR converts the installer to an oobeSystem-only flow, removes the windowsPE pass and its bypasses, moves OEM payload into sources\$OEM$, adds build-time staged-layout validation (cross-checking C:\Setup\... references), and defers all post-install actions to C:\Setup\bootstrap.ps1 launched at first logon.

Changes

Cohort / File(s) Summary
Documentation
AUTOUNATTEND.md, CLAUDE.md, docs/ISO-GENERATION.md
Update examples and instructions: OEM payload is now under sources\$OEM$; document oobeSystem-only workflow and FirstLogon bootstrap responsibilities.
Unattend / Configuration
autounattend.xml
Removed windowsPE pass and WinPE bypass registry commands; simplified oobeSystem to expose wireless/OOBE screens, keep ProtectYourPC=3 and HideEULAPage=true, and leave only FirstLogonCommands to run C:\Setup\bootstrap.ps1.
ISO build & staging
build-iso.ps1, docs/..., tests/BuildIso.Tests.ps1
Stage payload under sources\$OEM$\..., make IsoLabel optional, add Get-UnattendSetupFileReferences, add Validate-StagedIsoLayout to ensure all C:\Setup\... refs are staged (fail early), and adjust UEFI boot image selection fallback.
Tests / Static checks
tests/Autounattend.Tests.ps1, tests/BuildIso.Tests.ps1
Replace checks for execution-policy/network-wait strings with assertion for single FirstLogon bootstrap invocation; tighten patterns to require sources\$OEM$\$1\Setup; add tests asserting staged-layout validation and ordering before oscdimg.

Sequence Diagram(s)

sequenceDiagram
    participant Dev as "Developer / CI"
    participant Builder as "build-iso.ps1"
    participant StagedISO as "Staged ISO (sources\\$OEM$)"
    participant Installer as "Windows Setup (autounattend)"
    participant User as "First User Logon"
    participant Bootstrap as "C:\\Setup\\bootstrap.ps1"

    rect rgba(200,200,255,0.5)
    Dev->>Builder: provide staged payload (sources\\$OEM$)
    Builder->>Builder: Get-UnattendSetupFileReferences -> Validate-StagedIsoLayout
    Builder->>StagedISO: produce ISO (oscdimg)
    end

    rect rgba(200,255,200,0.5)
    StagedISO->>Installer: boot / run Setup (oobeSystem-only)
    Installer->>User: present OOBE / sign-in screens
    User->>Installer: complete first logon
    Installer->>Bootstrap: FirstLogonCommands -> powershell -File C:\\Setup\\bootstrap.ps1
    Bootstrap->>Bootstrap: perform installs, debloat, customize
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

"I hopped through trees and through the code,
Moved payloads where the installers go.
One small bootstrap at first sign-on,
Then apps and tweaks hop merrily on. 🐇"

🚥 Pre-merge checks | ✅ 3
✅ 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 and specifically describes the main changes: making AutoUnattend minimal and deferring setup to OOBE, which is the core focus across all modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ta-branch-1

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 and usage tips.

Copy link
Copy Markdown

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

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: c8e5fad956

ℹ️ 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 autounattend.xml
Comment on lines 11 to 12
<settings pass="oobeSystem">
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Restore windowsPE hardware bypass commands

Removing the entire windowsPE pass drops the LabConfig registry writes that bypass TPM/Secure Boot/RAM checks, so on unsupported hardware (especially many default VirtualBox/VMware test VMs) Windows 11 setup fails before OOBE with “This PC can’t run Windows 11.” In that scenario FirstLogonCommands never execute and bootstrap.ps1 cannot run, which regresses the repo’s VM-first installation workflow unless those bypasses are preserved or TPM-capable VMs are made an explicit requirement.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
AUTOUNATTEND.md (1)

31-33: Mention the desktop shortcut method first for re-running bootstrap.

Line 33 should guide users to "Run Windows Setup.lnk" on the desktop as the primary option, with manual script execution (C:\Setup\bootstrap.ps1) as a fallback for advanced users. This aligns with the desktop shortcuts that bootstrap.ps1 actually creates.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@AUTOUNATTEND.md` around lines 31 - 33, Update the AUTOUNATTEND.md text so the
primary guidance for re-running bootstrap points users to the desktop shortcut
"Windows Setup.lnk" (created by bootstrap.ps1) and list running
C:\Setup\bootstrap.ps1 manually only as an advanced fallback; specifically
change the sentence that currently says “Just run C:\Setup\bootstrap.ps1
manually” to first instruct users to click "Run Windows Setup.lnk" on the
desktop and then note the manual bootstrap.ps1 invocation as an alternative for
advanced users.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@AUTOUNATTEND.md`:
- Around line 7-10: Update the opening sentence in AUTOUNATTEND.md that states
"The file runs in three phases during Windows installation" to correctly reflect
the current content which documents only the single unattended phase
"oobeSystem"; locate the phrase near the start of the document and change it to
indicate a single phase (e.g., "The file runs in a single phase during Windows
installation: oobeSystem") and ensure any subsequent references to multiple
phases are adjusted or removed to avoid confusion about "oobeSystem".
- Line 3: The intro of AUTOUNATTEND.md lacks an explicit platform target; update
the top of AUTOUNATTEND.md to state the repository policy that the document and
associated scripts target Windows 11 (24H2+) only (e.g., add a one-line header
or note: "Target platform: Windows 11 (24H2+)") so the file unambiguously
enforces the Windows 11-only requirement referenced by the guidelines; ensure
this one-line callout appears at the very top of the file and that no other
lines in AUTOUNATTEND.md imply Windows 10 compatibility.

---

Nitpick comments:
In `@AUTOUNATTEND.md`:
- Around line 31-33: Update the AUTOUNATTEND.md text so the primary guidance for
re-running bootstrap points users to the desktop shortcut "Windows Setup.lnk"
(created by bootstrap.ps1) and list running C:\Setup\bootstrap.ps1 manually only
as an advanced fallback; specifically change the sentence that currently says
“Just run C:\Setup\bootstrap.ps1 manually” to first instruct users to click "Run
Windows Setup.lnk" on the desktop and then note the manual bootstrap.ps1
invocation as an alternative for advanced users.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 497ff9dc-06c2-455f-a69b-ec8d94ca3484

📥 Commits

Reviewing files that changed from the base of the PR and between d8822a4 and c8e5fad.

📒 Files selected for processing (2)
  • AUTOUNATTEND.md
  • autounattend.xml

Comment thread AUTOUNATTEND.md
# AutoUnattend.xml Explained

This file automates only the minimal parts of Windows 11 setup needed for this repo. It intentionally avoids aggressive install-time customization so Windows Setup stays as reliable as possible.
This file is now intentionally ultra-minimal. It avoids changing Windows Setup itself and only kicks off post-install automation after first login.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Call out Windows 11 (24H2+) explicitly in the intro.

Please make the platform target explicit at the top so the doc enforces the repo policy unambiguously.

✏️ Suggested doc fix
-This file is now intentionally ultra-minimal. It avoids changing Windows Setup itself and only kicks off post-install automation after first login.
+This file is now intentionally ultra-minimal and targets **Windows 11 (24H2+) only**. It avoids changing Windows Setup itself and only kicks off post-install automation after first login.

As per coding guidelines: "**/*.{md,ps1}: Ensure all documentation, scripts, and configurations assume Windows 11 as the target platform and do not include references to Windows 10 compatibility".

📝 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
This file is now intentionally ultra-minimal. It avoids changing Windows Setup itself and only kicks off post-install automation after first login.
This file is now intentionally ultra-minimal and targets **Windows 11 (24H2+) only**. It avoids changing Windows Setup itself and only kicks off post-install automation after first login.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@AUTOUNATTEND.md` at line 3, The intro of AUTOUNATTEND.md lacks an explicit
platform target; update the top of AUTOUNATTEND.md to state the repository
policy that the document and associated scripts target Windows 11 (24H2+) only
(e.g., add a one-line header or note: "Target platform: Windows 11 (24H2+)") so
the file unambiguously enforces the Windows 11-only requirement referenced by
the guidelines; ensure this one-line callout appears at the very top of the file
and that no other lines in AUTOUNATTEND.md imply Windows 10 compatibility.

Comment thread AUTOUNATTEND.md
Comment on lines 7 to 10
The file runs in three phases during Windows installation:

### 1. windowsPE (Installation Phase)

Runs while Windows is being installed to the disk.

- Bypasses TPM/Secure Boot/RAM checks (helpful for VMs)
- Leaves disk and partition selection to the user in Windows Setup
- Configures language/locale to en-US

### 2. oobeSystem (First Boot)
### 1. oobeSystem (First Boot)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix stale phase count in setup flow description.

Line 7 says “three phases,” but the updated content now documents a single unattended phase (oobeSystem). This is confusing for readers following the new model.

✏️ Suggested doc fix
-The file runs in three phases during Windows installation:
+The file now runs in a single unattended phase during Windows installation:
📝 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
The file runs in three phases during Windows installation:
### 1. windowsPE (Installation Phase)
Runs while Windows is being installed to the disk.
- Bypasses TPM/Secure Boot/RAM checks (helpful for VMs)
- Leaves disk and partition selection to the user in Windows Setup
- Configures language/locale to en-US
### 2. oobeSystem (First Boot)
### 1. oobeSystem (First Boot)
The file now runs in a single unattended phase during Windows installation:
### 1. oobeSystem (First Boot)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@AUTOUNATTEND.md` around lines 7 - 10, Update the opening sentence in
AUTOUNATTEND.md that states "The file runs in three phases during Windows
installation" to correctly reflect the current content which documents only the
single unattended phase "oobeSystem"; locate the phrase near the start of the
document and change it to indicate a single phase (e.g., "The file runs in a
single phase during Windows installation: oobeSystem") and ensure any subsequent
references to multiple phases are adjusted or removed to avoid confusion about
"oobeSystem".

Copy link
Copy Markdown

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

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: 4a4b63d1eb

ℹ️ 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 build-iso.ps1 Outdated
[bool]$HasOptionalApps
)

$stagedSetupRoot = Join-Path $WorkRoot 'sources\`$OEM`$\`$1\Setup'
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Build staged setup path without literal backticks

In Validate-StagedIsoLayout, $stagedSetupRoot is defined with a single-quoted string ('sources\$OEM$\$1\Setup'). In PowerShell single-quoted strings are literal, so the backticks are kept in the path instead of escaping $, which makes this value differ from the directory actually created earlier (sources$OEM$$1\Setup). This causes Test-Path` checks to fail and the ISO build to abort during staged layout validation in normal runs.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/Autounattend.Tests.ps1 (1)

23-27: Assert the XML shape, not just a few strings.

This still passes if another SynchronousCommand gets added or if the bootstrap command moves out of oobeSystem. Parsing the XML and asserting exactly one FirstLogonCommands/SynchronousCommand would make the “minimal” contract much harder to regress.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/Autounattend.Tests.ps1` around lines 23 - 27, The test currently checks
for a few strings but not the XML structure; update the test to parse the
Autounattend XML ($fileContent) and assert the exact shape: locate the
oobeSystem pass, then the FirstLogonCommands element and verify there is exactly
one SynchronousCommand element (and that it contains the expected bootstrap
command text), and also assert that forbidden commands like
"Set-ExecutionPolicy" and "Wait for Network Connectivity" are not present; use
XML parsing APIs to count FirstLogonCommands/SynchronousCommand nodes and
validate their content instead of relying on regex matches.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/BuildIso.Tests.ps1`:
- Around line 45-64: The order-check is anchored to the function declaration
because IndexOf('Validate-StagedIsoLayout') returns the first match; change the
lookup to target the actual invocation by using
IndexOf('Validate-StagedIsoLayout -WorkRoot') when computing $validationIndex so
it compares the real call site against the build step (Write-Step "Building
custom ISO with oscdimg") ensuring the validation runs before the ISO build.

---

Nitpick comments:
In `@tests/Autounattend.Tests.ps1`:
- Around line 23-27: The test currently checks for a few strings but not the XML
structure; update the test to parse the Autounattend XML ($fileContent) and
assert the exact shape: locate the oobeSystem pass, then the FirstLogonCommands
element and verify there is exactly one SynchronousCommand element (and that it
contains the expected bootstrap command text), and also assert that forbidden
commands like "Set-ExecutionPolicy" and "Wait for Network Connectivity" are not
present; use XML parsing APIs to count FirstLogonCommands/SynchronousCommand
nodes and validate their content instead of relying on regex matches.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 15966adf-c844-4aad-9c74-e2de1478ef88

📥 Commits

Reviewing files that changed from the base of the PR and between c8e5fad and 6841479.

📒 Files selected for processing (6)
  • CLAUDE.md
  • autounattend.xml
  • build-iso.ps1
  • docs/ISO-GENERATION.md
  • tests/Autounattend.Tests.ps1
  • tests/BuildIso.Tests.ps1
✅ Files skipped from review due to trivial changes (2)
  • CLAUDE.md
  • docs/ISO-GENERATION.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • autounattend.xml

Comment thread tests/BuildIso.Tests.ps1
Comment on lines +45 to +64
It "validates the staged ISO layout before oscdimg" {
$scriptContent | Should -Match "Validate-StagedIsoLayout"
$scriptContent | Should -Match "Validating staged ISO layout"
$scriptContent | Should -Match "Staged ISO layout validation passed"
}

It "checks unattend C:\\Setup references against the staged OEM payload" {
$scriptContent | Should -Match "Get-UnattendSetupFileReferences"
$scriptContent | Should -Match "C:\\Setup\\"
$scriptContent | Should -Match "autounattend\.xml references .* staged ISO is missing"
}

It "runs staged layout validation before building the ISO" {
$validationIndex = $scriptContent.IndexOf('Validate-StagedIsoLayout')
$buildIndex = $scriptContent.IndexOf('Write-Step "Building custom ISO with oscdimg"')

$validationIndex | Should -BeGreaterThan -1
$buildIndex | Should -BeGreaterThan -1
$validationIndex | Should -BeLessThan $buildIndex
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
python - <<'PY'
from pathlib import Path

text = Path("build-iso.ps1").read_text(encoding="utf-8")
needle = "Validate-StagedIsoLayout"

positions = []
start = 0
while True:
    idx = text.find(needle, start)
    if idx == -1:
        break
    positions.append(idx)
    start = idx + 1

print("All 'Validate-StagedIsoLayout' positions:", positions)
print("Call-site index:", text.find("Validate-StagedIsoLayout -WorkRoot"))
print('Build-step index:', text.find('Write-Step "Building custom ISO with oscdimg"'))
PY

Repository: Timpan4/declarative-windows

Length of output: 173


Anchor the order check on the actual call site, not the function declaration.

Line 58 uses the first occurrence of Validate-StagedIsoLayout, which is the function declaration at byte position 3415. The actual invocation (Validate-StagedIsoLayout -WorkRoot) is at position 13851. Since .IndexOf() finds the first match, this test can pass even if the real call site comes after the build step. Anchor on "Validate-StagedIsoLayout -WorkRoot" instead to validate the actual call order.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/BuildIso.Tests.ps1` around lines 45 - 64, The order-check is anchored
to the function declaration because IndexOf('Validate-StagedIsoLayout') returns
the first match; change the lookup to target the actual invocation by using
IndexOf('Validate-StagedIsoLayout -WorkRoot') when computing $validationIndex so
it compares the real call site against the build step (Write-Step "Building
custom ISO with oscdimg") ensuring the validation runs before the ISO build.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
build-iso.ps1 (3)

103-103: Optional: Use approved PowerShell verb and singular noun.

PSScriptAnalyzer flags two naming convention issues:

  • Validate-StagedIsoLayout → prefer Test-StagedIsoLayout (approved verb)
  • Get-UnattendSetupFileReferences → prefer Get-UnattendSetupFileReference (singular noun)

These are internal functions so the impact is minimal, but following conventions improves consistency with the PowerShell ecosystem.

Also applies to: 125-125

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@build-iso.ps1` at line 103, Rename the two internal functions to follow
PowerShell approved verb/noun conventions: change Validate-StagedIsoLayout to
Test-StagedIsoLayout and change Get-UnattendSetupFileReferences to
Get-UnattendSetupFileReference; update every reference to those symbols (calls,
splatting, tests, comment/docs, and any exported/function lists) to the new
names and run PSScriptAnalyzer to confirm the warnings are resolved.

117-119: Regex may truncate paths containing spaces.

The pattern [^\s"'';]+ stops at whitespace, so a quoted path like "C:\Setup\My Script.ps1" would extract C:\Setup\My instead of the full filename. Current staged files don't have spaces, but this could cause silent validation misses if such files are added later.

Consider using a more robust pattern that handles quoted paths:

💡 Optional: Handle quoted paths
-        foreach ($match in [regex]::Matches($commandNode.InnerText, '(?i)\bC:\\Setup\\[^\s"'';]+')) {
+        # Match both quoted and unquoted C:\Setup paths
+        foreach ($match in [regex]::Matches($commandNode.InnerText, '(?i)(?:"(C:\\Setup\\[^"]+)"|''(C:\\Setup\\[^'']+)''|\b(C:\\Setup\\[^\s"'';]+))')) {
+            $capturedPath = $match.Groups[1].Value, $match.Groups[2].Value, $match.Groups[3].Value | Where-Object { $_ } | Select-Object -First 1
             $references.Add($match.Value)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@build-iso.ps1` around lines 117 - 119, The regex used in the foreach over
$commandNode.InnerText currently stops at whitespace and will truncate quoted
paths; update the pattern in that foreach (the [regex]::Matches call) to accept
either a quoted path (allowing spaces inside the quotes) or an unquoted token,
and when adding to $references strip any surrounding quotes; i.e., replace the
single-token pattern with an alternation that captures quoted "C:\Setup\..."
entries as well as unquoted paths so $match.Value yields the full filename for
both cases.

66-74: Consider adding UTF-8 BOM for Unicode characters.

The file contains Unicode symbols (✓, ✗, box-drawing characters) but lacks a BOM. While modern editors handle BOM-less UTF-8 fine, some Windows tools (including older PowerShell hosts) may misinterpret these characters. Saving with UTF-8 BOM ensures consistent rendering.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@build-iso.ps1` around lines 66 - 74, The script uses Unicode glyphs in
Write-Success and Write-ErrorMessage (the ✓ and ✗ characters) but the file lacks
a UTF-8 BOM; re-save the file encoded as "UTF-8 with BOM" so Windows PowerShell
hosts render these characters reliably (or alternatively replace the literal
glyphs in Write-Success/Write-ErrorMessage with explicit Unicode escapes if BOM
cannot be used), ensuring the change is applied to build-iso.ps1 so the
functions Write-Success and Write-ErrorMessage display correctly across Windows
tools.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@build-iso.ps1`:
- Line 103: Rename the two internal functions to follow PowerShell approved
verb/noun conventions: change Validate-StagedIsoLayout to Test-StagedIsoLayout
and change Get-UnattendSetupFileReferences to Get-UnattendSetupFileReference;
update every reference to those symbols (calls, splatting, tests, comment/docs,
and any exported/function lists) to the new names and run PSScriptAnalyzer to
confirm the warnings are resolved.
- Around line 117-119: The regex used in the foreach over $commandNode.InnerText
currently stops at whitespace and will truncate quoted paths; update the pattern
in that foreach (the [regex]::Matches call) to accept either a quoted path
(allowing spaces inside the quotes) or an unquoted token, and when adding to
$references strip any surrounding quotes; i.e., replace the single-token pattern
with an alternation that captures quoted "C:\Setup\..." entries as well as
unquoted paths so $match.Value yields the full filename for both cases.
- Around line 66-74: The script uses Unicode glyphs in Write-Success and
Write-ErrorMessage (the ✓ and ✗ characters) but the file lacks a UTF-8 BOM;
re-save the file encoded as "UTF-8 with BOM" so Windows PowerShell hosts render
these characters reliably (or alternatively replace the literal glyphs in
Write-Success/Write-ErrorMessage with explicit Unicode escapes if BOM cannot be
used), ensuring the change is applied to build-iso.ps1 so the functions
Write-Success and Write-ErrorMessage display correctly across Windows tools.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 98649814-f514-412c-9684-08919ee647cd

📥 Commits

Reviewing files that changed from the base of the PR and between 6841479 and cbf63f7.

📒 Files selected for processing (2)
  • build-iso.ps1
  • tests/BuildIso.Tests.ps1
✅ Files skipped from review due to trivial changes (1)
  • tests/BuildIso.Tests.ps1

@Timpan4 Timpan4 merged commit ad8bbe5 into main Apr 7, 2026
3 checks passed
@Timpan4 Timpan4 deleted the ta-branch-1 branch April 7, 2026 13:22
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