The guard packs the tree twice in its `beforeAll`. The `pnpm` arm ran the
root `prepack` — a full clean-dist + tsc + copy-templates — because
`pnpm pack` has no `--ignore-scripts` flag. Measured: 26s with the build,
**4s** with `npm_config_ignore_scripts=true`, and the tarball is
**identical** either way (2958 files, 0 fixtures, 25 SKILL.md).
The build does not affect what this file measures. The fixtures it hunts
are TRACKED IN GIT, not produced by the build, and the build's copy step
writes into `dist/` only. What the file measures is the two packers'
file-collection semantics against the tracked tree.
AND THE 26s WAS NOT FREE — it was breaking another test. The unit suite
runs this alongside `tests/unit/code/orchestrator-can-do.test.ts`, whose
Q4 probe spawns the CLI with a 10-second budget and falls back to
`source:'unavailable'` when it overruns. The guard's packing added
contention to the same run, and that test went red in two of three
whole-tree runs. QA classified it as a load flake — it was one — but the
guard was a contributor and the cause was removable.
It was also a live CI risk: the guard packs on EVERY OS in the matrix
(ubuntu, windows, macos), and a 4-core `windows-latest` runner could
exceed the `beforeAll`'s 300s budget and go red with `Hook timed out`.
Cutting 22s removes most of that margin.
The guarantee the skipping rests on is now PINNED rather than assumed: a
new assertion reads `scripts/copy-templates.mjs`'s SOURCE and extracts
its `dest:` literals, asserting that none is under `skills/`. The
published tarball is packed WITHOUT the build being skipped —
`scripts/release-pack.mjs` calls `pnpm pack` with no
`npm_config_ignore_scripts` — so the two tarballs agree about `skills/`
ONLY if the build cannot write into it. The extraction reads the source
rather than running the copy step, because running it would reintroduce
the cost this change exists to remove, and an EMPTY extraction is a RED
rather than a pass: "none of zero destinations is under skills/" is true
for the wrong reason.
Also adds the 4.1.25 changelog's honest note that `resolvePnpmInvocation`
in `scripts/_release-shared.mjs` still falls back to a bare `pnpm` on
Windows where `resolveNpmInvocation` refuses loudly — the defect is in
the PUBLISH path, CI publishes on ubuntu so this release is unaffected,
and it is recorded in backlog §23.22 rather than fixed here.