[P1] Artifact failure JSON hides the effective verdict and recoverable helper copy

#24 · closed · 1 comments

View on GitHub ↗

Azathothas

Tested the published **wsl-toolkit-v1.3.0 Windows amd64** binary on Windows 11/WSL2 on 2026-09-10. SHA-256: `71b2ef9b0cf50da0acda45e7cc9293185a2b18d8aa403812e20ed29222d54424`, matching the release manifest. Follow-up to #8. ## Summary v1.3 correctly makes the CLI exit nonzero when requested artifacts are not delivered, but its structured result still looks successful and can point at no recoverable location. This leaves JSON-only agents unable to determine the effective outcome or retrieve the preserved helper-side copy. ## Reproduction ### Extraction limit ```powershell & $wtk run --image alpine --json --artifacts <empty-dir> --max-bytes 8 -c 'printf 0123456789 > /out/result' ``` Observed: process exit 1, but JSON retained `exit: 0`, a positive `artifacts` count representing entries encountered rather than delivered, and `artifact_error`. A consumer using the result object rather than the surrounding process exit sees a successful command and plausible artifact count. ### Destination is a file ```powershell Set-Content <artifact-path> 'preexisting file' & $wtk run --image alpine --json --artifacts <artifact-path> -c 'printf result > /out/result' ``` Observed: process exit 1 and an artifact mkdir/extraction error, but no usable `guest_dir`/recovery path was reported. The pre-existing host file remained safe. On the helper route, the artifact set is intentionally left unacknowledged in helper state, but the result does not expose its id or a retry/recovery command. ## Cause `JobResult.Exit` remains the container exit while `jobVerdict` separately converts `ArtifactError` to process exit 1. The serialized object has no `effective_exit`/verdict field. `DownloadArtifacts` leaves a failed set unacknowledged, but `helperRunJob` records only the error text; the artifact id is not returned to the user. Human reporting only knows `GuestDir`, which may no longer be the relevant recoverable copy on the helper transfer path. ## Expected Structured results should expose the effective toolkit verdict and distinguish attempted from successfully delivered artifact counts. Every retained recovery copy should be named with a supported retry/retrieve workflow, whether it lives in the guest or helper state. Add JSON-only tests for byte/entry/name/destination failures on both routes.

Comments

Azathothas

Fixed in `wsl-toolkit-v2.0.0`, by `WSL-46` in `TODO/wsl-toolkit-go.md`. The answer carries the effective verdict and where the recoverable copy is. Re-derived against the published v2.0.0 binary, 2026-09-10, on a job whose payload succeeds and whose output cannot be delivered: ```text exit=1 effective_exit=1 artifacts=0 artifacts_attempted=1 artifact_error=<workspace refused: leak points at "/etc/passwd", which is an absolute path and leaves the directory this job delivered. A link out of the tree is refused rather than converted> retained_kind=<guest> retained=</home/toolkit/.wsl-toolkit/jobs/6f1da9fbaf59d7b5> ``` `effective_exit`, `retained_kind` and `retained` are new fields, `artifacts` now counts entries **delivered** and `artifacts_attempted` carries what it used to mean. `artifacts retry` reaches the retained copy without re-running the job. Both changes are breaks and `docs/consumers.md` carries the rows.