- CLAUDE.md: Linux host no longer runs pwsh; PS 5.1 constraints scoped to
Windows guests + Windows runner.
- RUNBOOK: add "Phase C — Python equivalents" table; §6-§13 benchmark records
kept as historical provenance.
- TODO §3.7: close $IsWindows shim bug (resolved-by-replacement — bench run
bypasses the shim).
- plans: mark C1-C8 done + docs C9; flag operational cutover/uninstall pending.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
RUNBOOK §15: dual-boot operation — Linux⇄Windows switch procedure, per-OS
CI-stack table (roots/runner/vmrun), current GRUB behaviour (DEFAULT=0,
TIMEOUT=0 hidden → boots straight to Linux), post-boot verification commands
for both OSes, and an optional GRUB tweak (left unapplied — boot-to-Linux is
intentional so the box returns as the Linux CI host after any unattended
reboot).
Checklist: Passo 9 done; fixed the stale global tracking table (Passi 6–9
were still [ ] despite being complete). Phase B is now fully closed (1–9 [x]).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
§11 Win-guest static (boot 29.75s, +24% vs Linux-host §8; static-IP floor
~22s confirmed host-independent), §12 Lin-guest DHCP (13.51s, +53%), §13
burn-in 4×10 (Win 36/40 — transient WinRM faults under 4× concurrency,
self-recovered; Lin 40/40). §14 adds the full host×guest×IP-mode matrix.
Plan checkboxes filled with results and the template-parity pre-req note.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
§10: single-job Measure-CIBenchmark on LinuxBuild2404 (DHCP, 10 iter) on the
Linux host — boot total 8.82s avg, near-deterministic even on DHCP (IP-acquire
7.45s, σ≈0.01). Guest-vs-guest table: Linux guest ~63% faster boot total than
the Windows static-IP guest (§8) on the same host.
plans/benchmark-windows-host.md: dual-boot plan to collect the symmetric
Windows-host numbers (§11 Win static, §12 Linux DHCP, §13 concurrent burn-in)
so the host×guest×IP-mode matrix is complete and Linux-vs-Windows is a
column-for-column comparison. Includes Windows paths, Credential Manager
prereqs, and the BaseClean-Linux snapshot caveat.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Concurrent capacity burn-in run on the Linux host as ci-runner with the
static-IP pool: WinBuild2025 40/40 PASS (~78.6s/round) and LinuxBuild2404
40/40 PASS (~70.2s/round) — 80/80 jobs, 20/20 rounds, near-deterministic
(static IP eliminates the DHCP IP-acquire variance of the §6/§7 baselines).
- RUNBOOK §9: concurrent burn-in result + ip-pool reset/recovery note.
- PhaseB-user-checklist Passo 7/8 marked done; fixed two checklist bugs:
run as ci-runner (the simone path needs g+w on the /var/lib/ci root for
ip-pool.tmp, not just the sub-dirs), and the Linux command was missing
-SnapshotName BaseClean-Linux (default BaseClean is Windows-only).
- idea-2-linux-host §8 DoD: Phase B complete (B1–B7 + >2 weeks stability).
- TODO §2.8 [P2]: ip-pool is not reconciled against live clones; a killed
job leaks its lease permanently and exhausts the 4-IP pool. Proposed fix.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Postmortem of the Linux template deploy/prepare 'no IP' investigation:
separates the three distinct causes (apt index stale from --skip-update,
deploy --force snapshot-chain, wedged host vmnet-dhcpd) and documents the
recovery (restart vmware-networks). Changelog entry summarising the
toolchain, xvfb, --force cleanup and cloud-init seal changes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add an --xvfb switch to 'build run' and 'job' that wraps the Linux build
command in 'xvfb-run -a sh -c ...', giving GUI toolkits (GTK4/PyGObject)
a headless $DISPLAY. Exported env vars precede xvfb-run so they
propagate into the virtual-display session. No-op (with a notice) for
Windows guests.
The local-ci-build composite action exposes it as the 'xvfb' input
(default false), forwarded as INPUT_XVFB -> --xvfb, mirroring the
use-shared-cache/skip-artifact wiring.
Docs: WORKFLOW-AUTHORING.md parameter table + Linux example note;
LINUX-TEMPLATE-SETUP.md Step 4a (the template ships python3-gi
gir1.2-gtk-4.0 xvfb). Adds build-run unit tests (wrap, plain, Windows
no-op).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Static IP via ip_pool: 24 s boot-to-ready vs 102 s DHCP (4x faster),
IP acquire now deterministic (σ < 0.03 s vs σ ≈ 57 s with DHCP).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the abandoned PSWSMan approach (New-PSSession hangs on Linux)
with a Python-native implementation using the proven pypsrp WinRmTransport.
- New `template prepare-win` command in commands/template.py: starts VM,
waits for WinRM, uploads and runs Install-CIToolchain-*.ps1, handles
Windows Update 3010 reboot loop (max 10 iterations), installs CI-StaticIp
scheduled task, runs post-setup validation, graceful shutdown, snapshot.
- Helpers: _ps_escape, _wait_tcp, _parse_exit_marker, _wait_winrm.
- 40 new tests in test_commands_template.py covering all major branches.
- Fix test_commands_job.py: patch load_config in _patch_common so tests
don't pick up live /var/lib/ci/config.toml ip_pool and fail on lock.
- Coverage gate: 90.06% (was 88.95% before fix).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4-iteration run on Linux Mint host, WinBuild2025/BaseClean.
Clone/Start/Ready/Destroy within ±20% of Windows baseline.
IP-acquire avg 99.7 s vs 58.2 s Windows — high variance (39–177 s),
attributed to VMware Tools reporting latency, not orchestrator regression.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Data from Measure-CIBenchmark.ps1 × 4 (2026-05-17, commit 36913ab):
avg boot 60.6s, IP-acquire dominant (20–85s, σ≈26s). Adds ±20% ranges
for B7 comparison and guidance on sample size given IP-phase variance.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Parallel MSBuild fan-out (e.g. ns7zip x86/x64/x86-ansi) over pypsrp
Linux→Win fails with MSBuild MSB6003 / Win32 1816 'Not enough quota'
because two default guest limits are too tight for concurrent native
processes via WinRM:
- Plugin Microsoft.PowerShell MaxMemoryPerShellMB = 150 MB
(pypsrp uses the plugin endpoint, not the Shell endpoint that
Deploy was previously bumping)
- Non-interactive desktop heap SharedSection 3rd field = 768 KB
(Session 0 csrss; CreateProcess fails when 3+ cl.exe spawn)
Pre-migration Win→Win went through Invoke-Command on PSSession with
quotas inherited from the local process, so the limits never bit.
Changes:
- Deploy-WinBuild2025.ps1 / Deploy-WinBuild2022.ps1: also set the
plugin-level MaxMemoryPerShellMB=2048, bump MaxProcessesPerShell
25→100, patch SharedSection 3rd field 768→4096 (reboot needed for
csrss to pick up, applied by post-install shutdown).
- Install-CIToolchain-WinBuild2025/2022.ps1: add Assert-Step for
plugin quota, MaxProcessesPerShell≥100, SharedSection≥4096; fail
hard if any are under threshold.
- docs/WINDOWS-TEMPLATE-SETUP.md: new "WinRM quotas e desktop heap"
section explaining the diagnosis + one-shot patch for legacy
templates; updated Step 3 validation row + troubleshooting entry.
- AGENTS.md: error #13 with symptom, root cause, and pointer to docs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Workflow now targets Simone/nsis-plugin-ns7zip. Renamed the file and
the workflow `name:`, and updated all references in active docs
(plans/archived and docs/archived left as frozen history).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Reconcile docs with the end-to-end pipeline fixes:
- upload/download-artifact @v4 -> @v3 (Gitea GHES) in WORKFLOW-AUTHORING
and workflow-example.yml; add Common Mistakes rows (v4, action ref
form + DEFAULT_ACTIONS_URL, public action repo).
- BEST-PRACTICES / README / HOST-SETUP: guest credential must live in
the LocalSystem vault with a host-qualified username; document
Set-CIGuestCredential.ps1 / Test-CIGuestWinRM.ps1 and auth=ntlm.
- README / AGENTS / HOST-SETUP: production venv install is NON-editable
(LocalSystem); no CI workflow may install into it.
- HOST-SETUP: add DEFAULT_ACTIONS_URL=github + full-URL uses: + public
repo + @main requirements discovered during validation.
- Correct stale repo name local-ci-system -> local-ci-cd-system.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Update --cov-fail-under in lint workflow + docs (AGENTS, README, ARCHITECTURE). Note: A5 closeout reported 80.10%% so this run will likely fail until additional tests are added.
AGENTS.md: new 'Python development' section (venv paths, install/lint/typecheck/test commands, conventions, full PS->Python sub-command mapping, list of PS scripts that stay PowerShell, link to phase closeouts). README.md: expand 'Python orchestrator' with examples for all 10 sub-commands (wait-ready, vm new/remove/cleanup, build run, artifacts collect, monitor disk/runner, report job, job), local validation gates with 80% coverage gate, link to test_agents_errors.py. docs/ARCHITECTURE.md: new 'Python orchestrator (Phase A)' section with package layout tree, VmBackend Protocol contract, load_backend(config) factory, Phase C ESXi extension recipe, transport selection note, and CI validation gates.
- Updated the final master plan to improve clarity and consistency in the status of various capabilities, including fixes and enhancements made as of 2026-05-12.
- Revised the opus47 analysis to provide a more structured overview of the system's production readiness, including detailed coverage of OWASP Top 10 risks and operational gaps.
- Enhanced the opus47 review of GPT-5.5 by clarifying severity ratings and rationales for various items, while adding new high-severity items that were previously overlooked.
- All 3 workflows: pwsh -> powershell (host requires PS 5.1, not Core 7+)
- workflow-example.yml: replace GITHUB_WORKSPACE-relative ciScriptsDir with
hardcoded host path; use SSH alias URL (host-clone mode) instead of HTTP
- docs: add WORKFLOW-AUTHORING.md reference for AI and developers
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.
- Overview table: mark partial vs done (VM-dependent items noted)
- Success Criteria: check all validated items, mark VM-only as [skip]
- Session results: 22/22 Pester, PSScriptAnalyzer 0 errors, IP validation,
disk watch, retention policy, orphan cleanup, runbook, threat model all pass
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>
§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>
§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>
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>