A shebang means executable: test the invariant, cut the patch

install.py shipped mode 644 in v0.1-alpha, so the README one-liner's
./install.py was permission-denied on every install. The repo modes and
update.sh's repair line were hotfixed already (all 14 shebang'd tracked
files are 100755; update.sh:165 names install.py) — this is the guard
that keeps them that way, and the patch release that heals the field.

- tests/test_release_artifact.py: the invariant, read from the tar
  header rather than the repo — every member whose content starts `#!`
  must carry the exec bit, failing by name. No exception list: there is
  no shipped file that legitimately may not be run, and gaining one
  means editing the test with a reason. Two tests keep it honest: the
  guard is proven to bite by repacking the real artifact with
  install.py's mode stripped, and an unpacked release must run
  ./install.py as a program, not via python3.
- tests/test_update_from_release.py: an install whose install.py is
  mode 644 — the shape v0.1-alpha left in the field — is executable
  again after any update. `cp` onto an existing file keeps the
  destination's mode, so the chmod line is the only thing healing it;
  removing that line fails this test.
- manager/core/VERSION → 0.1-alpha.1: cutting the patch is the honest
  move over a release note telling users to work around it.
- manager/core/release-manifest: the invariant, stated where the
  shipping list lives.

Verified: python3 -m unittest discover -s tests (267 tests, OK). Both
new assertions were watched failing first — a build-side `chmod -x` on
the staged install.py, and update.sh with install.py dropped from its
chmod list — then restored.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
istos
2026-07-30 12:00:01 +02:00
co-authored by Claude Opus 5
parent 39ab96d81b
commit eec69ba575
4 changed files with 92 additions and 5 deletions
+1 -1
View File
@@ -1 +1 @@
0.1-alpha
0.1-alpha.1
+5
View File
@@ -20,6 +20,11 @@
#
# Anything not listed here does not ship: bench's own task cards, its
# manager/local/ content, local/state/, .claude/, tests/, release.sh.
#
# Modes ship too, and one invariant is absolute: any shipped file whose
# first two bytes are `#!` carries the executable bit in the tarball.
# The artifact test enforces it with no exception list — a shebang is a
# promise the file can be run.
copy AGENTS.md
copy CLAUDE.md
copy README.md