* fix(packaging): accept Windows-style absolute output paths in build-zip.sh
On Git Bash, `scripts/build-zip.sh C:\path\out.zip` (or `C:/...`) exited
with ENOENT: the script treated any path not starting with `/` as relative
and prepended `$(pwd)/`, and MSYS then handed Node a mixed path such as
`D:\repo\C;C:\Program Files\Git\Users\...`. Skip the prefix for drive paths,
which Node resolves natively, and add a win32-only regression test.
The repository's own package-gate tests pass os.tmpdir() paths, so on a
clean Windows checkout two of them failed before building anything.
* fix(packaging): record Git index modes so archify.zip reproduces on Windows
scripts/write-deterministic-zip.mjs derived each entry's mode from
fs.stat(), but NTFS cannot store an executable bit: after the stager's
chmod(0o755), stat() still reports 0o666 on Windows, so
archify/bin/archify.mjs (index mode 100755) was written as 0644 and the
archive differed from the committed bytes in four central-directory
bytes while every payload matched.
The stager now records every staged file's Git index mode in a manifest
outside the staged tree (--mode-manifest), the writer requires that
manifest and fails closed when it disagrees with the staged files, and
build-zip.sh passes it between them. Linux bytes are unchanged; together
with the output-path fix in the previous commit, a Windows rebuild is now
byte-identical to archify.zip.
Refs #384
* fix(packaging): harden output-path and mode-manifest handling from review
- build-zip.sh also passes \\-prefixed absolute paths (UNC shares, the
device namespace) through untouched instead of prefixing the cwd.
- stage-clean-skill.mjs compares the manifest and destination by their
physical locations (existing ancestors resolved through symlinks),
refuses a manifest path that already exists, creates the manifest
exclusively, and removes it on failure only when this invocation
created it.
- Tests: the Windows path regression also builds through a \\.\ device
path; the stager suite covers an existing manifest path and a
symlinked-ancestor alias on both sides.
Addresses the CodeRabbit findings on #385.
Refs #384