chore(release): bump to 0.32.0

Ships two things that belong in one bump because they are one plugin.

`board.sh --voyage` (85cd628, 2026-08-31) sat one commit past v0.31.0,
unreleased and unpushed. Every entry point on this machine runs the
version-pinned plugin cache, so the feature existed in git and did not
exist for anyone using it.

`route.sh --last-model` learned "Fable 5.1" (2bec7fe) with both boundary
decisions taken and written down: "Fable 5" is kept because the row table
itself spells rows 5-6 with it, and the set was widened rather than
replaced by form validation because only a closed set catches a version
that never shipped.

Version sites, enumerated rather than swept - a blank sed would rewrite
the historical prose in CLAUDE.md that deliberately keeps its old number:
plugin.json, package.json, the README badge, and four SKILL.md
(coord-send, board, route, dispatch). CHANGELOG entry added.

Selftest counts corrected where they are asserted as prose: route 69 ->
73 in CLAUDE.md and README.

npm test: 11/11. coord 242, board 360, route 73, orders 110, guard 54.

Order: 20260901T185028Z-3612729538-from-.claude

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-01 21:47:33 +02:00
commit 39cb6538e3
9 changed files with 121 additions and 10 deletions

View file

@ -1,6 +1,6 @@
{
"name": "repo-mailbox",
"version": "0.31.0",
"version": "0.32.0",
"description": "Local mailbox for coordination between Claude Code sessions in different repositories. Directed messages and broadcasts as plain Markdown files on your own disk, injected as context at session start. Local, private, no network.",
"author": {
"name": "Kjell Tore Guttormsen"

View file

@ -5,6 +5,70 @@ 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.32.0] - 2026-09-01
Two commits, and the first of them was already written when this release
started: `board.sh --voyage` landed on 2026-08-31 and then sat one step past
`v0.31.0`, unreleased AND unpushed. Every entry point on this machine runs the
version-pinned plugin cache, so the feature existed in git and did not exist
for anyone using it. That gap is the reason both changes ship together - they
are the same plugin and the same bump.
### Added
- **`board.sh --voyage` reports the Voyage briefs in flight** (committed
2026-08-31, released here). A sixth rendering of the same read-only scan.
`board` reads STATE lines, which say nothing about a brief, so a programme
running Voyage across several repos had no shared surface at all: nobody
could answer which briefs were running, in what phase, and who was waiting on
whom. Detection is by PROPERTY, never by directory name - a directory counts
only if it holds `brief.md` or `brief.md.draft` under one of the three
planning locations the convention recognises - and it walks the FILESYSTEM,
never the git index: `llm-ingestion-okf` gitignores `.claude/projects/`, so
`git ls-files` would have reported zero briefs in the one repo actually
running one. The phase ladder measures ARTIFACTS, not sessions, and says so
in its legend; three fields refuse to let an absence borrow the shape of a
measurement (`kvalitet=-` is never `complete`, `research=-` is not
`research=0`, and the rendering always prints its own denominator). A
matching `VOY` column sits beside `ORDRE` and `FLY`, never summed with them.
### Fixed
- **`route.sh --last-model` now accepts `Fable 5.1`, and the set stays
CLOSED.** Fable 5.1 shipped 2026-09-01 and the three-value set refused it, so
a session that actually ran it could not record what it ran: the record was
either omitted or written as a name already in the set. A lied record reads
back months later as a measurement rather than as the gap it is, which is the
failure mode of the one field whose entire purpose is to be believed later.
Two boundary decisions were taken rather than deferred. `Fable 5` is KEPT -
not for backward compatibility (measured: exactly 1 of 45 `route-last` lines
on this machine carries it) but because `route.sh`'s own row table spells
rows 5-6 `Fable 5/high` and `Fable 5/xhigh`, so dropping it would make the
script refuse to record a name its own spec writes. And the set was WIDENED
rather than replaced by form validation: a `<family> <digits>[.<digits>]`
pattern would still catch a misspelled family, but would stop catching a
version that does not exist, letting `Fable 5.2` and `Opus 7` read back as
evidence that a model ran when it never shipped. The selftest pins that
choice - `Fable 5.2` / `Fable 6` / `Fable 5.10` are rejected beside the new
accept case - so a later switch to form validation fails there instead of
quietly widening what the record can claim. The die message now names the
repair, since the cost of a hand-maintained list is exactly what was paid
here.
Not touched: the row table (still six rows, still emitting only 1-4, Fable
still a hand-written override) and the note that a Fable session runs without
an advisor because the CLI does not enforce it.
Known gap, stated rather than closed: `Fable 5.1/xhigh` is 15 characters and
overflows `board.sh`'s `%-14s` KOST column, shifting the rest of that row one
column right. Parsing is unaffected and is now pinned by the round-trip
section. Widening the column was not ordered in this session and is reported
rather than made.
`route-selftest.sh`: 69 -> 73 checks. The other four suites are unchanged
(coord 242, board 360, orders 110, state-line-guard 54).
## [0.31.0] - 2026-08-29
Two commits landed after `v0.30.0` and, as with that release, neither reaches

View file

@ -897,7 +897,7 @@ marketplace plugin. Three components, one boundary:
rationale, and prints one block of `key=value` lines: the rubric row, the rule
that fired, the `next-cost` value, a pasteable startup command, the one-row
cheaper fallback, and the STATE.md comment lines. Pinned by
`route-selftest.sh` (69 checks).
`route-selftest.sh` (73 checks).
**It is here because it is the WRITER for the field `board.sh` already reads.**
`next-cost` had a reader and no writer, so it was hand-typed every session and
@ -957,6 +957,53 @@ marketplace plugin. Three components, one boundary:
startup command. Corollary pinned by section 13: `skills/route/SKILL.md` must
never declare an `effort:` frontmatter field, because frontmatter overrides the
session effort and the reading would then measure the skill, not the session.
**Order 20260901T185028Z-3612729538 (2026-09-01): `--last-model` was a closed
set of three, Fable 5.1 shipped that day, and the refusal turned a
measurement into a lie.** A session that genuinely ran Fable 5.1 could not
record what it ran, so its record was either omitted or written as a name
already in the set - and a lied record reads back months later as a
measurement rather than as the gap it is. The whole point of the four
`--last-*` fields is to be readable evidence, so this is the field's own
failure mode, not a cosmetic one. Both edit sites moved, never one: the usage
block and the validating case, because fixing the case alone is the
two-copies-of-one-policy defect this file names repeatedly.
**"Fable 5" is KEPT, and the reason is NOT backward compatibility.** The
nevner was measured rather than assumed - exactly 1 of 45 `route-last` lines
across the machine carries it - which is thin enough that a future session
would happily "clean up" the one stale line and then drop the value. The
load-bearing reason is that `route.sh`'s own row table spells rows 5-6
`Fable 5/high` and `Fable 5/xhigh`. Dropping the value would make the script
refuse to record a name its own spec writes.
**The set is WIDENED, never replaced by form validation, and the selftest is
what makes that a fact rather than a paragraph.** A pattern like
`<family> <digits>[.<digits>]` would still catch a misspelled family and a
drifted case (`opus 5`), and would stop catching **a version that does not
exist**: `Fable 5.2` and `Opus 7` would both pass and read back as evidence
that a model ran when it never shipped - the positive-looking null this repo
refuses everywhere else, in the one field whose entire purpose is to be
believed later. Section 8b therefore rejects `Fable 5.2` / `Fable 6` /
`Fable 5.10` beside the accept case, so a later switch to form validation
fails here instead of silently widening what the record can claim. The cost
of the closed set is real and was paid before the choice was made, so the die
message now names the repair - a newly shipped model is ADDED to the list,
never approximated to a value already in it.
Untouched, deliberately: the row table (still six rows; `route.sh` still
emits only 1-4, and Fable remains a hand-written override), and the note that
a Fable session runs without an advisor because the CLI does not enforce it.
**Bounded gap, stated rather than closed:** `Fable 5.1/xhigh` is 15
characters and overflows `board.sh`'s `%-14s` KOST column, shifting the rest
of that row one column right. Parsing is unaffected - `next-cost` extraction
is free text, and selftest section 6 now pins that the point release survives
the round trip - so this is alignment, not data. Widening the column is a
`board.sh` rendering change nobody ordered in this session, which is also why
the value is deliberately ABSENT from section 6's widest-value loop: adding
it there would go red, and the red would be the unfixed gap wearing a broken
test's clothes. Reported to `.claude` instead.
- **Board's ORDRE column** counts PENDING orders per repo with the identical
idiom as INN, and the two are never summed: INN is "others are waiting on
YOU" (outgoing obligation), ORDRE is "authorized work is waiting on this
@ -1215,7 +1262,7 @@ obligations in another repo.
- TDD: no behavior change without a failing selftest check first.
`bash scripts/coord-selftest.sh` must exit 0 (242/242),
`bash scripts/board-selftest.sh` must exit 0 (360/360),
`bash scripts/route-selftest.sh` must exit 0 (69/69),
`bash scripts/route-selftest.sh` must exit 0 (73/73),
`bash scripts/orders-selftest.sh` must exit 0 (110/110) and
`bash scripts/state-line-guard-selftest.sh` must exit 0 (54/54).
- English for all code, docs, and commit messages (public repo). Norwegian

View file

@ -10,7 +10,7 @@ Session A in repo X leaves a message for repo Y; the next session in repo Y gets
*AI-generated: all code produced by Claude Code through dialog-driven development.*
![Version](https://img.shields.io/badge/version-0.31.0-blue)
![Version](https://img.shields.io/badge/version-0.32.0-blue)
![Hooks](https://img.shields.io/badge/hooks-1-green)
![Skills](https://img.shields.io/badge/skills-4-orange)
![CLI scripts](https://img.shields.io/badge/CLI_scripts-8-blue)
@ -184,7 +184,7 @@ Note that raising the inbox's priority (Rule 7) deliberately does **not** widen
bash scripts/coord-selftest.sh # 220 checks against a throwaway mailbox
bash scripts/board-selftest.sh # 360 checks against a throwaway repo tree
bash scripts/route-selftest.sh # 69 checks, incl. the route->board round trip
bash scripts/route-selftest.sh # 73 checks, incl. the route->board round trip
bash scripts/orders-selftest.sh # 99 checks, incl. the 20-way barriered claim race
bash scripts/state-line-guard-selftest.sh # 40 checks, incl. the Edit replace_all projection and the ratchet
npm test # all five selftests plus the hook tests, via node --test

View file

@ -1,6 +1,6 @@
{
"name": "repo-mailbox",
"version": "0.31.0",
"version": "0.32.0",
"private": true,
"type": "module",
"engines": {

View file

@ -23,7 +23,7 @@ description: >-
user names no repo and no tool — choosing *between* repos is this skill. Not for
"where were we" inside the current repo: that is this repo's own STATE.md,
already injected at session start.
version: "0.31.0"
version: "0.32.0"
---
# board — which repo deserves the next session

View file

@ -15,7 +15,7 @@ description: >-
covers retiring a broadcast that has become wrong or obsolete: "retract that
broadcast", "that announcement is outdated, pull it", "trekk tilbake kringkastingen",
"den broadcasten er utdatert".
version: "0.31.0"
version: "0.32.0"
---
# coord-send — natural-language front door for inter-repo messages

View file

@ -17,7 +17,7 @@ description: >-
skill. Not for choosing WHICH repo deserves the next session (that is `board`),
not for scoring model and effort alone (that is `route`), and not for sending a
message to another repo (that is `coord-send`).
version: "0.31.0"
version: "0.32.0"
---
# dispatch — hand a session a task it can actually start on

View file

@ -14,7 +14,7 @@ description: >-
the operator names no model and no tool — choosing the model for the next
session IS this skill. Not for choosing which REPO gets the next session:
that is the `board` skill.
version: "0.31.0"
version: "0.32.0"
---
# route — what the next session should run with