The first real 0.2.0 publish failed on its first package with ENOENT:
"Publishing ekklesia-contracts-0.2.0.tgz failed: npm error code ENOENT".
The publish workflow passes a relative release path,
--release "$(find package-train …)", which is
package-train/ekklesia-packages-0.2.0. The tool validated the artifacts
relative to the job's working directory, but ran npm in its own
temporary home (cwd /tmp/ekklesia-publish-XXXXXX) with the same relative
path, package-train/ekklesia-packages-0.2.0/ekklesia-contracts-0.2.0.tgz,
which there names nothing. The disposable-registry suite always passed
an absolute path, so it never saw this.
- loadReleaseTrain resolves the release directory once; every artifact
path is absolute from validation on, and npm is given only that exact
file's absolute path (anything else is refused at the npm boundary).
- Just before each upload the file is checked against the validated
bytes once more; the tool logs the absolute path it publishes, and a
failure names it with npm's path/syscall lines (npm's temporary home
masked, the token never shown).
- Regression tests: unit tests with a recording npm (relative nested
release from another cwd; npm's argv, cwd, and the file's existence; a
changed artifact refused before npm runs), which fail on the previous
tool; and a disposable-Gitea test that runs the CLI exactly as the
workflow does, from the Actions artifact layout, round-tripping all
nine packages byte for byte.
Co-Authored-By: Claude Opus 5.5 <[email protected]>