docs(a5): mark A5 as code-complete; add A5-closeout.md

Master checklist + step A5 attivita + 'definizione di fatto' updated; A5-closeout.md added (116 pytest, coverage 80.10% total, gate raised to 80%). Hardware validation (burn-in 4x10 + workflow matrix end-to-end) deferred to user. Shim PS removal deferred to B5 (systemd timers): all 10 shims still referenced by Register-CIScheduledTasks.ps1 / docs / Test-*.ps1.
This commit is contained in:
2026-05-14 17:39:47 +02:00
parent 4d9c6d07ba
commit a658f4ed3b
2 changed files with 118 additions and 18 deletions
+100
View File
@@ -0,0 +1,100 @@
# A5 — Closeout
Fase A5 di `plans/implementation-plan-A-B.md`: polish, regression test
per gli errori frequenti `AGENTS.md` #9-#12, documentazione Python
allineata, gate coverage alzato a 80%.
Branch: `feature/python-rewrite-phase-a`.
## Stato attuale
- [x] `tests/python/test_agents_errors.py` aggiunto: 12 test dedicati che
coprono regressioni per `AGENTS.md` "Errori frequenti da evitare"
#9, #10, #11, #12.
- **#9** (snapshot template con VM accesa): `clone_linked` propaga
"should not be powered on" come `BackendOperationFailed` (subclass
di `BackendError`) con `operation == "clone"` e `output` che
contiene il messaggio originale di `vmrun`.
- **#10** (`vmrun getGuestIPAddress` lento): `is_running` usa solo
`vmrun list`. Tre asserzioni — happy path, VM non listata, errore
di `vmrun list` — verificano che `getGuestIPAddress` non venga MAI
chiamato come fallback.
- **#11** (machine-id duplicato → DHCP collision): la safety net
orchestrator-side è che `vm new` non riusi mai un clone-name
(timestamp suffix); il test invoca `vm new` due volte con lo stesso
`--job-id` e verifica che `clone_linked` riceva due
`name`/`destination` distinti. Il fix template-side
(`truncate -s 0 /etc/machine-id`) resta documentato in
`template/Prepare-LinuxBuild2404.ps1`.
- **#12** (`& nativecmd 2>$null` non sopprime stderr in PS 5.1):
`SshTransport` usa `paramiko.AutoAddPolicy` di default con
`known_hosts=None`, non chiama mai `subprocess.run`/`Popen`
(incluso `ssh-keygen`/`ssh.exe`/`scp.exe`), e wrappa errori
paramiko (import mancante, `exec_command` exception, SFTP
`put`/`get`) come `TransportConnectError` invece di propagare
eccezioni nude.
- [x] `AGENTS.md` aggiornato: nuova sezione "Python development" subito
dopo "PowerShell 5.1 — Vincoli critici", con tabella parametri,
convenzioni (type hints, no `Any`/globali/`print`/`shell=True`),
mappatura completa PS → Python sub-command, elenco PS che restano
e gate coverage 80%.
- [x] `docs/ARCHITECTURE.md` esteso con sezione "Python orchestrator
(Phase A)": layout package, `VmBackend` Protocol, factory
`load_backend(config)`, ricetta Phase C per backend ESXi
(`backends/esxi.py` + selettore `[backend]` in `config.toml`),
transport selection, gate CI.
- [x] `README.md` ampliato: setup venv produzione + dev, esempi CLI per
tutti i 10 sub-comandi (`wait-ready`, `vm new/remove/cleanup`,
`build run`, `artifacts collect`, `monitor disk/runner`,
`report job`, `job`), comandi validazione locale con gate 80%,
link a `test_agents_errors.py` e `pyproject.toml`.
- [x] Suite completa: ruff clean, mypy --strict clean, **116 pytest
PASS**, coverage totale **80.10%** (gate 80% raggiunto).
- [ ] Burn-in 4 job concorrenti × 10 round (versione Python di
`Test-CapacityBurnIn`) — **richiede VM reali, lasciato a carico
utente**.
- [ ] Workflow `build-nsInnoUnp.yml` matrix (Win + Linux) end-to-end
PASS — eredita pendenza da A4 (richiede runner registrato).
## Definizione di "fatto" A5
| Criterio | Stato |
| ----------------------------------------------------- | -------------------------------- |
| Errori #9#12 coperti da test pytest | ✅ |
| `AGENTS.md` ha sezione "Python development" | ✅ |
| `docs/ARCHITECTURE.md` aggiornato (layout + hook C) | ✅ |
| `README.md` aggiornato (setup + esempi CLI) | ✅ |
| Coverage globale ≥80% (gate alzato in pyproject) | ✅ 80.10% |
| Shim PS non referenziati rimossi | ⏭️ nessuno candidato (vedi nota) |
| Burn-in 4×10 PASS | ⏳ utente — richiede VM reali |
**Nota shim PS**: tutti i 10 shim (`Wait-VMReady.ps1`, `New-BuildVM.ps1`,
`Remove-BuildVM.ps1`, `Cleanup-OrphanedBuildVMs.ps1`,
`Invoke-RemoteBuild.ps1`, `Get-BuildArtifacts.ps1`, `Watch-DiskSpace.ps1`,
`Watch-RunnerHealth.ps1`, `Get-CIJobSummary.ps1`, `Invoke-CIJob.ps1`)
sono ancora referenziati: `Register-CIScheduledTasks.ps1` registra
scheduled task che invocano `Watch-DiskSpace.ps1`,
`Watch-RunnerHealth.ps1`, `Cleanup-OrphanedBuildVMs.ps1`; `README.md`
documenta `Invoke-CIJob.ps1` per uso manuale; `Test-*.ps1` di smoke
chiamano gli shim. Nessuno shim è candidato a rimozione in A5 senza
prima migrare anche `Register-CIScheduledTasks.ps1` (Fase B5 lo
sostituirà con `*.service` + `*.timer` su systemd).
## Cosa resta a carico utente
1. Eseguire un burn-in concorrente (4 job × 10 round) usando il workflow
`build-nsInnoUnp.yml` matrix o `scripts/Test-CapacityBurnIn.ps1` (che
ora delega via shim alla CLI Python `job`) e verificare:
- PASS senza VM orfane (`vm cleanup` non rimuove nulla a fine round).
- Wall-clock entro ±20% del baseline pre-Python (`Measure-CIBenchmark.ps1`).
2. Validare `build-nsInnoUnp.yml` matrix (Win + Linux) end-to-end PASS
sul runner reale — pendenza ereditata da A4.
3. Validare `self-test.yml` e `lint.yml` post-switch.
## Riferimenti commit
- `test(a5): add pytest regression tests for AGENTS.md errors #9-#12`
`tests/python/test_agents_errors.py`
- `docs(a5): document Python orchestrator in AGENTS.md, ARCHITECTURE.md, README.md`
`AGENTS.md`, `docs/ARCHITECTURE.md`, `README.md`
- `docs(a5): mark A5 as code-complete; add A5-closeout.md`
`plans/implementation-plan-A-B.md`, `plans/A5-closeout.md`