chore(release): 0.26.0

The done-guard (d16a3f5) landed after 0.25.0 was already tagged and published
on 95ac710, with the catalog ref pinned to it (catalog 01161f0). Moving a
published tag would swap content under a name consumers may already have
fetched, so the guard gets its own release instead.

Version bumped in all seven places: plugin.json, package.json, the README
badge, and the coord-send / board / route / dispatch skill frontmatters.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P4LMWBQGmufmBU6UdvJZ2E
This commit is contained in:
Kjell Tore Guttormsen 2026-08-16 22:19:08 +02:00
commit 165385be5f
8 changed files with 45 additions and 7 deletions

View file

@ -5,6 +5,44 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.26.0] - 2026-08-16
### Added
- **`status=done` can no longer be written into a board line while the repo
holds unpushed commits.** Measured that day: two sessions had their push
refused by the UFW rate limit on port 22, reported that honestly in the coord
inbox, and wrote `status=done` regardless — board line green, one commit
unpushed, published surface 404. `done` meant "the session finished" where
every reader takes it to mean "the work landed", and because `done` drops a
repo from the board plan, `morning --say <repo>` could not reach either of
them: one defect hid the other. `pre-state-line-guard.mjs` now denies that
write (stderr + exit 2), naming the unpushed commits, the branch and its
upstream, and the three ways out.
The deny sits on the WRITE rather than at session end, measured against the
official hooks docs instead of assumed: `Stop` fires "once per turn", not
once when the session ends, with no signal marking the last turn, and its
exit 2 "prevents Claude from stopping, continues the conversation" — so a
repo that genuinely cannot push would get a session that will not end.
`SessionEnd` is the once-per-session event and cannot block at all
("Can block? No" — exit 2 "shows stderr to user only").
It fails OPEN on every git uncertainty (no upstream, detached HEAD, missing
remote-tracking ref, not a repo): 8 of the 44 repos carrying a STATE.md on
the real tree have no upstream at all, one of them already `status=done`.
The comparison is against the branch's own upstream, never a hardcoded
`origin/main..main` (three repos sit on `master`), and the board line is
selected with `board.sh`'s own anchor, so prose containing `status=done`
never triggers it. `status=blocked` and `status=in-progress` stay writable in
the same single edit, so the guard can never wedge a session that cannot
push — it only stops it claiming otherwise.
`state-line-guard-selftest.sh` grows 23 → 40 checks (section 10), including
the mandatory known-positive: a `status=done` with everything pushed must
still go through, or the guard would be a gate that denies everything and
proves nothing. Both outcomes were also verified against real repos.
## [0.25.0] - 2026-08-16
### Added