name: solve-challenge
description: Applies a scripted solution to a running challenge (single- or multi-VM) and verifies every non-helper task completes. Use to validate a .solution.sh / .solution-NN.sh end-to-end.
argument-hint: [solution-file]
Validate the scripted solution(s) for challenge $0 against fresh challenge attempts. Always do this with the CI helper tests/challenges/main.go — it runs the exact CI chunk-execution semantics (multi-VM # session: chunks, retry=N reboot handling, init-task waiting, the authoritative completion check) and captures rich per-solution artifacts. Do not hand-roll the chunk runner.
Resolve the bare challenge name from $0 (strip any https://labs.iximiuz.com/challenges/ prefix). Refer to it as <name>.
Locating the challenge and its solution scripts
Find the challenge folder: 3rd-party/challenges/<name> for community submissions, otherwise challenges/<name> (use the detect-local-content-folder skill to resolve hex suffixes for first-party content). The helper auto-discovers every solution file in that folder whose basename matches ^\.solution(-\d+)?\.sh$ (.solution.sh, .solution-01.sh, …); .solution-NN.md files are human-facing and ignored. Each solution is run against its own fresh attempt and all must pass.
Run the CI helper
Build once, then run with --skip-auth (mandatory — without it the helper calls labctl auth login and logs you out / replaces your session):
cd tests
go build -o challenge-tester ./challenges
./challenge-tester --skip-auth -v -d "$(pwd)/../challenges" -c "<name>" --test-timeout <dur>
- Point
-dat3rd-party/challengesinstead for community submissions. --skip-authreuses the current session and treats it as premium-capable (premium challenges are not skipped).- Bump
--test-timeout(default 5m) for slow/reboot challenges. - The
challenge-testerbinary is a build artifact — delete it when done, don't commit it.
The helper prints SOLUTION ... SUCCESS/FAIL per solution file and a final TEST RESULTS summary; a non-zero exit means at least one solution failed.
Debugging a failing run
Two signals, both available while the helper is still running (it leaves its challenge playground up for the whole attempt):
- Artifacts (primary). At the start of each solution the helper prints the absolute artifacts directory (default
$TMPDIR/challenge-tester-artifacts/<challenge>/challenge-tester-artifacts.<solution>/). Files are written and appended dynamically as the attempt proceeds — tail them live, don't wait for the run to end:chunk-NN[.retry-MM].{stdout,stderr}.log— per-chunk SSH output (NN= 0-based chunk index,MM= retry attempt); a failing chunk's error lands here.tasks-NNNN.txt+tasks-final.txt— periodiclabctl playground tasks -o yamlsnapshots (every 15s; final one taken right before exit) — shows which task never reached40and its last-run output.journal-<machine>.examiner[.err].log— streamed examiner journal per machine.
- Live
labctlagainst the same playground. Find its ID withlabctl playground list --filter challenge=<name>(orlist-running-playgrounds), then inspect:labctl playground tasks <id> -o yaml, orlabctl ssh <id> [--machine <m>] -- <diagnostic>. Keep SSH foreground and one at a time (tunnel-pool discipline).
Notes
- Tasks are edge-activated and never regress — once a task shows
completed(40) it stays there. A task that has passed cannot later fail, so the artifacts' final task snapshot is authoritative. - A flakiness check = run the helper twice (e.g.
vet-challengedoes this); both runs must pass. - Never run
labctl auth login/labctl auth logout— use the inherited session only (logging out invalidates it irrecoverably without an interactive browser flow); this is exactly why--skip-authis mandatory. - In challenges with VM reboots, the VM comes back in a few seconds; the helper's
retry=Nchunks handle the reconnect. Cap any manual post-reboot wait at ~20s.