AGENTS.md (new):
- Environment reference for AI agents: host specs, PS 5.1 constraints,
dir structure, VM templates, transport layer, style rules
- Lessons #9 (snapshot cold state) and #10 (vmrun list vs getGuestIPAddress)
ARCHITECTURE.md:
- Add SSH/SCP transport section (Linux VMs)
- Update system diagram to include _Transport.psm1, SSH transport path
- Network layout: add SSH port 22 for Linux VMs
- Timeline: Linux readiness check phases documented
CI-FLOW.md:
- Prerequisites table: add Template VM (Linux), SSH key row
- Step 6 (readiness): document Windows vs Linux phases
- Step 7 (build) and Step 8 (artifacts): document Linux/SSH paths
- ci-report-ip guestinfo mechanism referenced
HOST-SETUP.md:
- Directory tree: add LinuxBuild2404 template dir and keys/
- Post-setup checklist: add step 5 (SSH key generation + Linux template)
- Fix duplicate step numbering (56, 67)
- Reference Paths table: add Linux template VMX, snapshot, SSH key
LINUX-TEMPLATE-SETUP.md:
- Rewritten as implementation record (no longer a plan)
- Fase A user-data: minimal (user+SSH key only, no packages/runcmd)
- All phases marked complete with actual paths and snapshot names
WINDOWS-TEMPLATE-SETUP.md: minor updates for consistency
TODO.md:
- Summary: update last-updated to 2026-05-11, Sprint 9 description
- Linux Build VM row: all 5 items complete
- Prossimi passi: Test Plan + §6.6 Tier-2 as next priorities
- Updated README.md to reflect the new in-VM git clone feature with `-UseGitClone`.
- Modified Setup-Host.ps1 to correct VMX path references.
- Revised various documentation files (ARCHITECTURE.md, CI-FLOW.md, HOST-SETUP.md, WINDOWS-TEMPLATE-SETUP.md) to include updated paths and features.
- Added Setup-GiteaSSH.md for SSH configuration instructions.
- Archived outdated documentation and updated README.md for clarity on current resources.
Setup-WinBuild2025.ps1: default SevenZipVersion '24.07' → '26.01'
TODO.md: Tier-1 table + bullet list updated to current versions
TEST-PLAN: expected version strings and checklist updated
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Create Test-E2E-Section3.3.ps1 for side-by-side measurement:
- Runs nsis-plugin-nsinnounp with default host-side clone (baseline)
- Runs same build with -UseGitClone flag (target: guest-side git)
- Displays elapsed time, artifact size, performance delta
Usage:
.\scripts\Test-E2E-Section3.3.ps1 # Full comparison
.\scripts\Test-E2E-Section3.3.ps1 -SkipBaseline # Guest-clone only
.\scripts\Test-E2E-Section3.3.ps1 -SkipGuestClone # Baseline only
Prerequisite: Template VM has Git installed (§6.6 Tier-1 Toolchain).
Also: Defer §3.5 (vCPU/RAM tuning) and §3.4 (pre-warm pool) to home lab
section — not required for initial CI operability.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Update TODO.md to reflect §3.3 implementation:
- §3 summary: 4 done (3.1/3.2/3.3/3.6), 1 open (3.5), 1 deferred (3.4)
- §3.3 marked [x] completato 2026-05-10
- Document implementation: Mode 1 (host) vs Mode 2 (guest) clone
- Update recommended next steps: prioritize E2E test §3.3 + full test plan
Next actionable: E2E validation with -UseGitClone flag to measure
host-zip-transfer overhead elimination.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Update TODO.md to reflect progress on §6.6:
- Mark §6 summary: 1 done (6.6 Git+7-Zip), 5 open (6.1 Linux, 6.2-6.5 extensions)
- §6.6 now shows [~] (partially complete) with note on implementation status
- Separate Tier-1 (done: Git, 7-Zip) from Tier-2 backlog (8 tools)
- Update recommended next steps: §3.3 In-VM clone now prioritized (§6.6 prerequisite met)
Next: §3.3 In-VM Git Clone implementation can now proceed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move pre-warm pool (maintaining 2 avviati clones) from main §3 backlog to Deferred section.
Rationale: optimization only valuable if profiling shows New-BuildVM+Wait-VMReady is
bottleneck; with 2-min builds ~40% overhead, but ~0% for 10+ min builds.
Update summary table: §3 now shows 3 done, 2 open, 1 deferred (instead of 3 open).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace "all" with actual count for consistency across table.
Makes progress tracking clearer and quantifiable.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove original §1.2, §1.3, §1.5 entries from main security section since
they are now consolidated in "Deferred (Home Lab)" section with better
organization and context about when to revisit.
Also removed original §1.7, §1.8 entries (was done in previous commit).
Final §1 structure: 1.1, 1.4, 1.6 (done) — 3 items.
All deferred items in separate section with clear criteria for re-enablement.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mark §3.2 (7-Zip compression) and comprehensive test plan as complete.
Defer security tasks to home-lab section (excessive for isolated environment).
Update next steps to prioritize test execution and §6.6 toolchain Tier-1.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
§3.2 — Performance: Implement 7-Zip compression for artifacts with fallback
to Compress-Archive for compatibility. Three call sites updated:
1. Host-side source compression: new Compress-BuildArtifact helper function
2. Guest-side custom build artifacts: inline 7-Zip check in scriptblock
3. Guest-side dotnet build output: inline 7-Zip check in scriptblock
Uses 7z.exe with -mmt=on (multi-threaded) and -mx1 (fast, low ratio impact).
Falls back to Compress-Archive if 7-Zip not found (until §6.6 template update).
Expected 10-20s speedup per build once 7-Zip installed in template.
Also defer all security items (§1.2/1.3/1.5/1.7/1.8) to home-lab section
since environment is isolated and excessive for current use case.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
§1.6 — Threat Model & Hardening Trade-offs: New section in BEST-PRACTICES.md §2.1
explains why Defender/Firewall/UAC are disabled in the template VM:
- Current state: tradeoff table (AV overhead vs attack surface, firewall fragility, UAC blocking elevated WinRM)
- Acceptable conditions: isolated lab, trusted code, no host sharing, VMnet8 not exposed
- Breaking conditions: untrusted code builds, shared host, LAN-exposed network
- Mitigations: how to re-enable each feature with specific cost/benefit trade-offs
Addresses security documentation gap — future modifications to security posture
can now reference this single authoritative source.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Four test files under tests/ using fake vmrun.cmd (exit code via
%FAKE_VMRUN_EXIT% env var) — no VMware or network dependency:
_Common.Tests.ps1 — New-CISessionOption TLS flags, Resolve-VmrunPath
throw/return, Invoke-Vmrun ExitCode/Output/ThrowOnError
New-BuildVM.Tests.ps1 — throw on missing template, throw+cleanup on clone
failure, Clone_{JobId}_{timestamp} name format
Remove-BuildVM.Tests.ps1 — no-op on missing VMX, partial dir cleanup,
-WhatIf preservation, full destroy removes dir
Wait-VMReady.Tests.ps1 — throw on missing vmrun, timeout throw,
IP ValidatePattern accept/reject
Run: Invoke-Pester tests\ -Output Detailed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
§4.1 — Structured JSONL log (Invoke-CIJob.ps1)
Each job now emits a parallel invoke-ci.jsonl alongside the transcript.
Write-JobEvent appends one JSON line per phase transition (ts, jobId,
phase, status, data). Events emitted at: job.start, phase1.clone-repo
start/success, phase2-3b.vm-start start/success, phase4.wait-ready
start/success, phase5.build start/success, phase6.artifacts start/success,
job.success/failure (with elapsedSec and error string).
Silent no-op if $jsonLog is null (log dir setup failed). Errors in
Write-JobEvent are swallowed — logging never breaks the build.
Enables post-hoc per-phase duration analysis with jq or ConvertFrom-Json.
§4.3 — Disk space alert (scripts/Watch-DiskSpace.ps1)
Checks drive free space every 15 min (scheduled by Register-CIScheduledTasks).
Below MinFreeGB (default 50 GB): writes Warning to Windows Application Event Log
(source CI-DiskAlert, EventId 1001) and exits 1 so Task Scheduler flags the run.
Optional -WebhookUrl for Discord/Gitea webhook notification.
Register-CIScheduledTasks.ps1 updated with Task 3: CI-DiskSpaceAlert (every 15 min).
§4.4 — Incident runbook (docs/RUNBOOK.md)
Four scenarios with symptom / triage commands / fix / escalation:
1. Runner offline in Gitea UI
2. All builds fail in Phase 2 (clone/start/IP)
3. Builds are slow (per-phase JSONL analysis, disk/CPU/NAT checks)
4. Template VMX corrupt after host crash (lock removal + backup restore)
Quick-reference table at the end.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
§2.1 — IP race with capacity>1 (Invoke-CIJob.ps1)
Phases 2-3b (clone+start+IP) now run inside a file-based exclusive mutex
(F:\CI\State\vm-start.lock via FileShare.None). Only one job at a time is
in the VM-start phase, preventing concurrent vmrun starts from racing for
the same DHCP lease. After IP is confirmed unique it is written to an IP
lease file (F:\CI\State\ip-leases\<IP>.lease). Lock is released immediately
so build phases run fully in parallel. Lease released in finally block.
Collision detection: if a lease file already exists for the detected IP,
the job fails fast with a clear error rather than silently sharing a WinRM target.
§2.5 — Versioned snapshot (Invoke-CIJob.ps1 + runner/config.yaml)
$SnapshotName now defaults to GITEA_CI_SNAPSHOT_NAME env var, falling back
to 'BaseClean'. config.yaml documents the commented-out variable for snapshot
refresh workflow (BaseClean_<yyyyMMdd> naming convention).
§2.3 — Artifact/log retention (scripts/Invoke-RetentionPolicy.ps1)
Purges per-job subdirs under F:\CI\Artifacts and F:\CI\Logs older than
RetentionDays (default 30). Switches to AggressiveRetentionDays (default 7)
when F: free space drops below MinFreeGB (default 50 GB). Also removes stale
IP lease files older than 12 hours (defensive cleanup for crashed jobs).
SupportsShouldProcess (-WhatIf) for dry-run.
§2.2 — Scheduled task registration (scripts/Register-CIScheduledTasks.ps1)
Registers two tasks under \CI\ task folder as SYSTEM/HighestPrivilege:
CI-CleanupOrphans — every 6h + AtStartup, -MaxAgeHours 4
CI-RetentionPolicy — daily 03:00 (+30min random) + AtStartup (+15min random)
Idempotent (-Force), SupportsShouldProcess (-WhatIf), validates script paths.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Test-WSMan in Windows PowerShell 5.1 does not support -SessionOption (WSManSessionOption),
causing "Cannot find a parameter matching the name 'SessionOption'" at runtime.
Prepare-WinBuild2025.ps1:
- Remove Test-WSMan connectivity check step entirely
- Open New-PSSession directly (handles -SkipCACheck via PSSessionOption)
- Wrap New-PSSession in try/catch with the same actionable error message
- Remove $wsmOpt (WSManSessionOption) — no longer needed
Wait-GuestWinRMReady: replace Test-WSMan probe with New-PSSession probe + Remove-PSSession
Wait-VMReady.ps1:
- Remove $wsmOpt entirely
- Replace Test-WSMan -UseSSL -SessionOption with Test-NetConnection -Port 5986
(TCP open on 5986 = HTTPS listener up = VM ready; credentials not available here)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
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
- 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>