First field bug of v0.1-alpha: install.py was committed 100644, so
every install shipped it permission-denied for direct ./install.py use
(start.sh's python3 invocation masked it). Exec bit set on all four
shebang'd files (install.py, board.py, hook_settings.py,
permission_config.py) and install.py added to update.sh's post-update
chmod line so already-broken installs heal on their next update. The
artifact-side invariant test — every shipped #! file executable — is
card 21.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Refuse assets whose tar members or manifest copy paths reach outside
their root, checked before anything is replaced; create parent dirs for
future nested copy entries. Test both refusals hermetically. Replace
setUpClass bare asserts with explicit checks that survive python -O.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The repo is two things at once — bench-the-project and bench-the-
distribution — and install/update conflated them by cloning the repo
and subtracting what should not have come along. Invert it: one
curated artifact, correct by construction.
- manager/core/release-manifest: the whole shipping list in one place
(copy/tree/once/keep/seed classes). update.sh's hardcoded top-level
file list, promoted.
- release.sh: builds bench.tar.gz from the manifest (contents at the
tarball root, stable asset name — the tokenless latest-release URL
depends on both), stamps the source repo into the shipped update.sh,
refuses on dirty tree or existing tag, tags v<VERSION> and publishes
via gh release create. Never ships in the artifact.
- update.sh: downloads the latest release (BENCH_REF pins a tag) via
gh with an anonymous curl fallback; refuses when the asset's VERSION
disagrees with its tag; replaces manager/core/ wholesale plus the
artifact manifest's `copy` files; touches nothing else. No release
published -> says so and changes nothing; no silent git fallback.
- tests: the tarball equals exactly the manifest (no cards, no local/
content beyond the generated starter, no state/tests/.claude), the
artifact installs pristine and boots the board, and update.sh's
replace/survive/refuse paths run hermetically against PATH-stubbed
gh and curl.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Everything core from cicero-pas's .task-manager, with instance data
reduced to skeleton: empty stage directories, the task template, empty
local/ scaffolding, and a README covering install (clone into
.task-manager/, vendored on purpose) and update (update.sh replaces core
wholesale; local/ and tasks/ survive).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>