Repository navigation
[Hackathon] fix(test): the documented --out ./.testsprite/… bundle commands exit 5 in a fresh project, including the verify skill's step 5 #654
Description
Verified against (commit SHA or released version)
commit a18d37c (v0.15.0; testsprite --version → 0.15.0), built from source. Reproduced on Linux (WSL2, Node 24) on 2026-10-23.
Discord Username / User ID
npall_805
What does this improvement do?
The failure-bundle commands that the shipped agent skill and the README tell you to run are refused with exit 5 the first time they run in a project, before any request is sent, because ./.testsprite/ doesn't exist yet:
| Where | Command | In a project with no .testsprite/ folder |
|---|---|---|
Verify skill, step "5. On failure → download the artifact" (skill.md#L543, codex.md#L99). agent install writes it for all 8 targets: claude, cursor, cline, antigravity, kiro, windsurf, copilot, and the codex section of AGENTS.md |
testsprite test artifact get <run-id> --out ./.testsprite/runs/<run-id>/ |
exit 5: parent directory does not exist: …/.testsprite/runs |
| README loop, step 2 (README.md#L87), and "The complete agent loop" (DOCUMENTATION.md#L122) | testsprite test failure get <test-id> --out ./.testsprite/failure |
exit 5: parent directory does not exist: …/.testsprite |
| Command reference (DOCUMENTATION.md#L334, #L976) | --out ./.testsprite/failure/<test-id>, --out ./.testsprite/runs/<run-id> |
exit 5, same reason |
Nothing in the CLI creates a project's .testsprite/ except test artifact get without --out, and that default is exactly the directory the skill spells out. So the same directory is created when it is implied and refused when it is named:
testsprite test artifact get run_abc # default ./.testsprite/runs/run_abc/: created, proceeds
testsprite test artifact get run_abc --out ./.testsprite/runs/run_abc/ # the verify skill's command: exit 5Who hits it: every coding agent that follows the verify skill, on the first failed run it investigates in a repo (.testsprite/runs/ only appears after a default-path artifact get), and anyone following the README loop. Under --output json the agent gets a VALIDATION_ERROR envelope instead of the bundle, and has to work out that it should mkdir -p and retry.
Reproduction. Offline: the refusal happens before any request, and the dummy key only lets the client be built.
npm ci && npm run build # in a checkout of a18d37c
cd "$(mktemp -d)" && git init -q
export TESTSPRITE_API_KEY=sk-user-dummy
node <checkout>/dist/index.js test artifact get run_abc --out ./.testsprite/runs/run_abc/; echo "exit $?"
node <checkout>/dist/index.js test failure get test_abc --out ./.testsprite/failure; echo "exit $?"Error: Invalid request.
Flag `--out` is invalid: parent directory does not exist: …/.testsprite/runs.
exit 5
Error: Invalid request.
Flag `--out` is invalid: parent directory does not exist: …/.testsprite.
exit 5
Expected: an --out inside the project's own .testsprite/ folder behaves like the default. Missing parents are created and the bundle is written.
Cause: assertOutDirParentExists requires the parent of --out to exist before the fetch (test artifact get --help: "Parent must exist"). The writer has no such limit: writeBundle runs mkdir(dir, { recursive: true }) once the response passes its integrity checks, which is how the default path gets created. So only the pre-check is in the way, and the commands in the docs and the skill don't satisfy it.
Details / implementation notes
Proposed fix: keep the guard, since it catches a mistyped --out before anything is sent, but scope it.
- In
assertOutDirParentExists, when the resolved--outlies inside<cwd>/.testsprite/, require only that the closest existing ancestor is a directory.writeBundlecreates the rest, exactly as it does for the default. Every other path is checked as today, so--out ./typo/bundlestill exits 5 and creates nothing. - That function serves both
test failure getandtest artifact get, so both commands are fixed, andfailure get --dry-run --out ./.testsprite/…stops refusing too. - The
--outhelp of both commands says "Parent must exist, except under ./.testsprite/, which is created as needed." Todaytest failure get --helpdoesn't mention the rule at all. - No docs or skill text has to change, and skills already installed in users' repos start working as soon as the CLI is upgraded.
Tests:
- In a fresh temp project, the skill's exact spelling (
./.testsprite/runs/<run-id>/, trailing slash included) and the README's./.testsprite/failureboth write a bundle. - A missing parent outside
.testsprite/is still refused (testsprite/…,.testsprite-old/…,.testsprite/../elsewhere/…). - A
.testspritefile in the way is reported as "not a directory". - The pre-check itself creates nothing.
I have this ready on a branch.
- The 4 new tests fail on a18d37c and pass with the change.
- On Linux, the full suite (4,803 tests) and the coverage gate pass.
- On Windows (Node 24), the spec and the help snapshots pass.
I'll open the PR as soon as this is accepted.
Not included: test scaffold --help's own example, --out tests/health.py, hits the same rule in a repo without tests/. That one is a single-file --out with its own semantics, so I can file it separately if you want it.
Confirmations
- I have searched existing issues and this is not a duplicate.
- I have provided my Discord identity above for reward coordination.
Activity