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>
Bench
A live kanban for coding-agent work: task files in stage directories are the only source of truth; a stdlib-only board narrates everything that happens to them — agents working in git worktrees, PRs opening on review, CI and Copilot state on the cards, drives of the app from a task's own branch, and an archive that is never a delete.
Install into a repo
git clone <this repo> .task-manager && rm -rf .task-manager/.git
./.task-manager/start.sh # wires the project (idempotent) and serves
The first start.sh clears the distribution's own cards from tasks/,
plans/ and reference/ (printing each removal), so a fresh install
starts with an empty board.
Commit .task-manager/ into the host repo — core is vendored on purpose,
so clones work offline and updates show up in the host's own diffs.
Update
# in manager/local/.env: BENCH_SOURCE=<this repo's git url>
./.task-manager/update.sh # latest
BENCH_REF=v1 ./.task-manager/update.sh # a specific release tag
Updates replace manager/core/ and the top-level scripts wholesale and
touch nothing else — tasks, plans, reference, and everything under
manager/local/ (your driver, commands, prompt overrides, settings,
state) survive every update. Then python3 .task-manager/install.py and
restart the board.
The three-layer law
Core knows about tasks, worktrees, PRs and events. It knows nothing about
any particular app (drivers do: local/driver/start), agent vendor
(adapters do: core/adapters/), or project (local/ does). Full docs in
CLAUDE.md; the adapter contract in manager/core/adapters/README.md.