Fix emerged during §7.4 e2e test run (2026-05-10):
- Deploy: set UsoSvc to Manual explicitly (Server 2025 default = Automatic)
- Setup cleanup: re-apply Set-Service Disabled on wuauserv/UsoSvc after DISM
StartComponentCleanup (WaaSMedicSvc resets StartType during component store cleanup)
- Deploy + Setup: add Administrator autologin (AutoAdminLogon, DefaultUserName,
DefaultPassword, DefaultDomainName) in post-install.ps1; Assert-Step 5c validates it
- Add Validate-DeployState.ps1: standalone host-side check of all Deploy-set state
- Add Validate-SetupState.ps1: standalone host-side check of full post-Setup state
- Mark §7.4, §7.1 and §7.2 e2e validation items as complete in TODO.md
- Update docs: WINDOWS-TEMPLATE-SETUP.md (arch table, validation scripts section,
autologin in confine Deploy/Setup); TEST-7.4-e2e.md checklist marked done
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Step-by-step guide to validate §7 refactor on a real VM:
Deploy stand-alone, state verification, Prepare with/without -SkipWindowsUpdate,
snapshot promotion. Includes expected values table and checklist.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Convert §7.1/7.2/7.3 from emoji ✅ + prose into standard [x] checkbox lists.
§7.4 items converted to [ ] open checkboxes. Consistent with rest of TODO.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
template/Deploy-WinBuild2025.ps1:
New host-side script that drives the unattended Windows install phase:
creates the VM, injects autounattend.xml (disabling Defender/firewall/UAC
before Setup-WinBuild2025.ps1 runs), boots from ISO, waits for first-boot.
template/autounattend.template.xml:
WiM-based answer file template for Windows Server 2025 unattended install.
Sets DisableAntiSpyware GPO + RTP off so Defender is fully off at first
logon (prerequisite for Setup-WinBuild2025.ps1 Step-2 validation-only path).
TODO.md:
- Date + wording updated (2026-05-10)
- §1.1: file refs updated to post-refactor line numbers (Step 3 WinRM,
Deploy-WinBuild2025 Enable-PSRemoting, Invoke-RemoteBuild, Get-BuildArtifacts)
- §1.2: TrustedHosts audit status corrected (Setup-Host.ps1 never sets '*';
Prepare appends IP and restores in finally)
- §1.3: Python/dotnet/VS Build Tools line refs updated
- §1.5: PAT security constraints expanded with grep-on-log safety net rule
- §1.6: Defender/Firewall/UAC state updated to reflect Deploy vs Setup split
- §3.3 deploy reference: VMX path corrected to CI-WinBuild.vmx
- §3.3 doc ref: WINDOWS-TEMPLATE-SETUP updated to list Deploy step
Setup-WinBuild2025.ps1 (Step 2):
- Defender is now disabled at deploy time by Deploy-WinBuild2025.ps1 via
DisableAntiSpyware=1 GPO + RTP off during unattended install.
- Step 2 reduced to a single Assert-Step sanity check (GPO key present = 1).
Exclusion paths removed: scanner is not running, they would be moot.
Prepare-WinBuild2025.ps1 (Setup invocation):
- Replace one-shot Invoke-Command + manual 're-run with -SkipWindowsUpdate'
message with an automated loop (max 10 iterations):
* Invoke-GuestSetup helper runs Setup inside the VM and returns exit code.
* Exit 3010 (ERROR_SUCCESS_REBOOT_REQUIRED) triggers Restart-Computer on
the guest, waits for WinRM via Wait-GuestWinRMReady (20 min timeout),
reopens PSSession and loops.
* Exit 0 breaks the loop; any other code throws immediately.
* Hard cap prevents infinite loops if WU never converges.
- Unified TODO.md + CONSIGLI.md into single working document
- Added priority levels P0 (security/reliability) through P3 (nice-to-have)
- Added references to new docs/HOST-SETUP.md, WINDOWS-TEMPLATE-SETUP.md,
LINUX-TEMPLATE-SETUP.md
- Documented Assert-Step validation flow in Fase B
- Updated open items with rationale and priority tagging
Restore full reference-style TODO (setup phases, commands, e2e log).
Add new entries from FIX-TODO that were dropped in the compact merge:
- Scripts Verification: Cleanup-OrphanedBuildVMs + Remove-BuildVM fix
- Performance & Maintenance: scheduled task for Cleanup
- New "Open Bug Fixes" section: IP octet validation, SHA256 installer
- Reference Paths: add Log dir row
- Gitea Workflow: mark lint.yml done
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Collapse completed setup history into a single summary block.
Absorb FIX-TODO open items (IP octet validation, SHA256 installer
check, Cleanup scheduled task) into the appropriate TODO sections.
Remove FIX-TODO.md — single source of truth restored.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
After hard stop, vmware-vmx.exe briefly holds file locks causing
deleteVM to fail with "Insufficient permissions". Replace the fixed
3s sleep with a vmrun-list poll loop (up to 20s) that waits until
the VMX is no longer registered as running, then retry deleteVM up
to 3x with 0/3/6s backoff before falling back to directory removal.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Wraps Invoke-CIJob.ps1 with nsinnounp params, verifies artifact exists.
Optional -VerifyArtifact flag expands zip and checks for expected
DLL/EXE names. Supports -Commit for pinned SHA testing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previous fix removed --depth 1 entirely when $Commit was set, causing
full clones on every workflow run (github.sha is always non-empty).
Better approach: keep --depth 1 (fast path), detect checkout failure,
then fetch --unshallow and retry. Only pays full-clone cost when the
requested commit is actually older than HEAD.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Invoke-RemoteBuild.ps1:
- Custom build command: replace buffered collect-then-print with
Write-Host streaming inside Invoke-Command (WinRM forwards Write-Host
in real-time to the host console)
- Set PYTHONUNBUFFERED=1 in the remote session to prevent Python from
holding lines in its internal buffer
- Same streaming approach for dotnet restore and dotnet build paths
- Return value is now just int exit code instead of hashtable
Invoke-CIJob.ps1:
- Add -LogDir parameter (default F:\CI\Logs)
- Add -LogRetentionDays parameter (default 30)
- Start-Transcript at job start -> F:\CI\Logs\<JobId>\invoke-ci.log
- Stop-Transcript in finally block (guaranteed execution)
- Auto-purge log directories older than LogRetentionDays after each job