fix(orders): a pending order's age comes from the filename, not the mtime

`coord-order-done --return` rewrites the order file's mtime, and both age
surfaces read mtime, so putting an order back reset the very reading that
says how long it has waited. An order returned three times could never look
old - on the one surface that exists precisely so a repo nobody opens still
shows something.

Found by reading the board right after this repo returned an order of its
own, not by looking for it: a file whose name says 2026-09-02 rendered
`ORDRE 1:0d` and `pending, 0d old` minutes later. Verified live after the
fix: the same order now reads 1d.

Two questions, two sources, and only one of them moved. A PENDING order's
age is "how long has this sat with no owner" = now - delivery time, which
only the filename carries and nothing rewrites. A CLAIMED order's age is
"how long has it been in flight", which is the claim's own mtime and was
already right. So oldest_pending_age() sits BESIDE oldest_order_age(), and
pending_age_of() beside age_of() - switching FLY to the filename would
answer the delivery question in the column that asks the flight question.
An unparseable filename yields "?" for the whole reading, never a
fabricated 0, because an unmeasured order could be the oldest one.

TDD, red first: orders-selftest section 11 (110 -> 116) and board-selftest
section 30 (360 -> 368), each asserting its own ground truth before
anything depends on it, with controls that a freshly delivered order still
reads 0d and that FLY did not move. Mutation-verified in both files:
restoring the mtime read turns exactly the defect checks red and leaves
every control green.

Section 28's fixtures were rewritten as part of this rather than
incidentally: they encoded their ages in `touch -t` while their filenames
held fixed 2026-01/2026-08 dates, which a filename-based reading makes both
wrong and time-dependent. They now compute their stems from `date -v` and
the section asserts two ground truths, the filename for ORDRE and the mtime
for FLY.

Order 20260903T185736Z-1290610855 (.claude). Version 0.32.1 across all
seven files; no catalog change in this session.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-03 22:17:26 +02:00
commit 5316688844
13 changed files with 332 additions and 24 deletions

View file

@ -146,7 +146,7 @@ marketplace plugin. Three components, one boundary:
mailbox, `~/.claude/coord/<repo>/orders/`, with four one-verb scripts —
`coord-order-send.sh` (write), `coord-order-inbox.sh` (read for injection),
`coord-order-claim.sh` (claim), `coord-order-done.sh` (terminal state).
Pinned by `orders-selftest.sh` (110 checks).
Pinned by `orders-selftest.sh` (116 checks).
**It is a separate CHANNEL, not more mail, and the axis is authorization.**
Inbox content is untrusted cross-repo data that may never instruct a session
@ -411,7 +411,7 @@ marketplace plugin. Three components, one boundary:
- **Board (`scripts/board.sh`):** cross-repo attention board. Reads STATE.md
next-step blocks + board lines, `git status`, and mailbox pending counts, and
prints one line per repo. Read-only by construction: it writes to no repo, no
STATE.md and no mailbox. Pinned by `board-selftest.sh` (360 checks).
STATE.md and no mailbox. Pinned by `board-selftest.sh` (368 checks).
**It lives here because the mailbox is one of its three inputs, and it carries
the same axis distinction the mailbox does.** A pending count means *others
@ -1080,6 +1080,40 @@ marketplace plugin. Three components, one boundary:
broken `touch -t` fails there rather than turning the section into a test of
nothing.
**Order 20260903T185736Z-1290610855 (2026-09-03): the PENDING age read the
mtime, and `coord-order-done --return` rewrites it - so putting an order back
reset the very reading that says how long it has waited.** An order returned
three times could never look old, on the one surface that exists precisely so
a repo nobody opens still shows something. Found by reading the board right
after this repo returned an order of its own, not by looking for it: a file
whose name says 2026-09-02 rendered `ORDRE 1:0d` minutes later. It is the
same class as every other reading hardened here - a failed or reset
measurement rendering as a reassuring value - with the twist that the reset
was performed by the engine itself.
**Two questions, two sources, and only one of them moved.** A PENDING order's
age is "how long has this sat with no owner" = now - DELIVERY time, and only
the filename carries that; it is written once and nothing rewrites it. A
CLAIMED order's age is "how long has it been in flight", which is the claim's
own mtime and was already right - so `oldest_pending_age()` sits BESIDE
`oldest_order_age()` rather than replacing it, and `coord-order-inbox.sh`
keeps `age_of` for the claim marker next to a new `pending_age_of`. Switching
FLY to the filename would answer the delivery question in the column that
asks the flight question. An unparseable filename yields `?` for the whole
reading, never a fabricated `0`, because an unmeasured order could be the
oldest one - the same rule the mtime path already carried.
**Section 28's fixtures had to be rewritten, and that is the finding worth
recording.** They encoded their intended ages in `touch -t` while their
filenames held fixed 2026-01/2026-08 dates, which a filename-based reading
makes both wrong and time-dependent - the checks would have started failing
on their own as the wall clock moved past them. They now compute their stems
from `date -v`, and the section asserts TWO ground truths, the filename for
ORDRE and the mtime for FLY, because a fixture check guarding only one source
leaves the other assertion resting on nothing. Mutation-verified in both
files: restoring the mtime read turns exactly the defect checks red with
every control green.
**There is deliberately NO process inspection, and the selftest asserts it
structurally** (no live `pgrep`/`pkill`/`lsof` in `board.sh`, with a
known-positive control proving the grep can find a planted call). Four
@ -1261,9 +1295,9 @@ obligations in another repo.
builtins only in hook and tests.
- 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/board-selftest.sh` must exit 0 (368/368),
`bash scripts/route-selftest.sh` must exit 0 (73/73),
`bash scripts/orders-selftest.sh` must exit 0 (110/110) and
`bash scripts/orders-selftest.sh` must exit 0 (116/116) and
`bash scripts/state-line-guard-selftest.sh` must exit 0 (54/54).
- English for all code, docs, and commit messages (public repo). Norwegian
trigger aliases in the skill description are deliberate.