docs(coord): measure the debt, and record why no second mechanism was built
WP5 asked for one of two candidate mechanisms, chosen by measurement. The measurement chose neither. coord-sweep.sh already IS the bulk-ack for pure notices, and it has never run: no _sweep.log at the default path, and none anywhere under ~/.claude (stated that way because --log can override the default, so an absent default-path log alone would not prove it). Its own dry-run agrees exactly with an independent classification of the same inboxes - 0 at 30 days, 7 at 14, 13 at 7 - so the gap is invocation, not mechanism. The broadcast class converges on its own: reading records a broadcast as seen, so a mailbox clears its backlog on its next session. 263 of 884 pairs are unread, but 34 of those belong to two mailboxes no session can hold - one a documented retired --to address, one with no checkout anywhere under /Users/ktg (known-positive control: llm-ingestion-okf resolves). A TTL would close those rather than reduce them. What remains is running coord-sweep --write unattended, which closes mail in 51 other repos' inboxes unread. That is a decision on another repo's behalf and a policy constant of the same class as the STATE.md line limit, so it is left to the operator rather than shipped. No version bump: nothing here changes behaviour. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
39cb6538e3
commit
a2019d44f7
1 changed files with 103 additions and 0 deletions
103
docs/2026-09-03-coordination-debt-measurement.md
Normal file
103
docs/2026-09-03-coordination-debt-measurement.md
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
# Coordination debt: what does not converge, and why building a second
|
||||
# mechanism would have been wrong
|
||||
|
||||
Measured 2026-09-03 against the live mailbox, for order
|
||||
`20260902T113745Z-1254925290-from-.claude` (WP5). Every number below was
|
||||
produced by a command, and every negative result carries the control that
|
||||
proves the query could have found something.
|
||||
|
||||
The order offered two candidate mechanisms and said to choose by measurement,
|
||||
not taste: a broadcast TTL, or a bulk-ack for pure notices. The measurement
|
||||
chose neither. One of them is already built and has never been run; the other
|
||||
addresses the class that converges on its own.
|
||||
|
||||
## Denominators
|
||||
|
||||
| population | count |
|
||||
|---|---|
|
||||
| mailbox directories under the coord root | 55 |
|
||||
| of those, holding an `inbox/` | 52 |
|
||||
| pending directed messages across all inboxes | 27 |
|
||||
| broadcasts in `_broadcast/inbox/` | 17 |
|
||||
| (mailbox x broadcast) delivery pairs | 884 |
|
||||
|
||||
The three directories with no `inbox/` are named rather than silently dropped:
|
||||
`jobbsok`, `mediemon`, `medieovervaaking`. 55 - 3 = 52 is the reconciliation,
|
||||
stated because an unreconciled pair of denominators in one report is the same
|
||||
positive-looking null this engine refuses everywhere else.
|
||||
|
||||
## The two classes behave in opposite directions
|
||||
|
||||
**Directed messages do not converge.** They are re-injected at every session
|
||||
start until a session closes them by hand. Of the 27 pending, 4 owe a reply and
|
||||
23 are pure notices (`reply-expected: no`). By age:
|
||||
|
||||
| class | <7d | 7-13d | 14-29d | >=30d |
|
||||
|---|---|---|---|---|
|
||||
| owes a reply | 0 | 3 | 1 | 0 |
|
||||
| pure notice | 10 | 6 | 7 | 0 |
|
||||
|
||||
**Broadcasts converge on their own.** Reading one records it as seen, so a
|
||||
mailbox clears its whole backlog on its next session. 263 of the 884 pairs are
|
||||
unread (29.8%), and the distribution shows the self-clearing: 10 mailboxes are
|
||||
fully current, 26 sit at exactly 6 unread (the newest announcements), and the
|
||||
tail is short.
|
||||
|
||||
## The floor under the broadcast number, which strengthens the case
|
||||
|
||||
Two mailboxes hold all 17 broadcasts unread, and neither can ever read them:
|
||||
|
||||
- `ktg-plugin-marketplace` is a **retired `--to` address**. It is a polyrepo
|
||||
directory, not a git repo, so `basename(git toplevel)` can never resolve to
|
||||
it and no session can hold that identity. This is already documented as
|
||||
engine behaviour; the 17 unread are its permanent consequence.
|
||||
- `llm-ingestion-guard` has no checkout anywhere under `/Users/ktg`
|
||||
(`find -maxdepth 4`, with `llm-ingestion-okf` as the known-positive control
|
||||
proving the query finds a real one) and no `.origin`. It also holds the
|
||||
single oldest pending notice, 24 days.
|
||||
|
||||
So **34 of 263 unread pairs (12.9%) are a permanent floor no TTL would reduce
|
||||
to zero** - it would close them, but it would be closing announcements for
|
||||
mailboxes that were never going to read anything. `.origin` absence alone is
|
||||
NOT a proxy for unholdable: `repos` also lacks one, yet sits at 2 unread of 17,
|
||||
which is only possible if something reads it.
|
||||
|
||||
## Why no second mechanism was built
|
||||
|
||||
`coord-sweep.sh` already **is** the bulk-ack for pure notices: machine-wide,
|
||||
one mechanically decidable class (`reply-expected: no`, older than a grace
|
||||
window), dry-run by default, closing through `coord-done.sh`, logging sender
|
||||
and subject for every closure. Building the order's second candidate would have
|
||||
been a second copy of a shipped policy - the defect class this repo names
|
||||
repeatedly.
|
||||
|
||||
Its own dry-run reports what it would close today, and the figures agree
|
||||
exactly with the independent classification above:
|
||||
|
||||
--days 30 -> 0 messages
|
||||
--days 14 -> 7 messages
|
||||
--days 7 -> 13 messages
|
||||
|
||||
**The gap is invocation, not mechanism.** No `_sweep.log` exists at the default
|
||||
path, and no sweep log exists anywhere under `~/.claude` (the one `*sweep*` hit
|
||||
is an unrelated plugin file) - stated that way because `--log` can override the
|
||||
default, so an absent default-path log alone would not prove it never ran.
|
||||
|
||||
## What remains, and why it is not this repo's call
|
||||
|
||||
Making the notice class converge without opening each repo means running
|
||||
`coord-sweep.sh --write` unattended. That closes mail in 51 other repos'
|
||||
inboxes, unread, and the script's own design says so in as many words: a notice
|
||||
to a repo left unopened for the whole window is closed unread, and the log is
|
||||
the only thing standing between that and a silent disappearance.
|
||||
|
||||
Deciding that on another repo's behalf is the one anti-pattern with no
|
||||
exception clause, and the grace window is a policy constant of the same class
|
||||
as the STATE.md line limit, which was an operator decision both times it moved.
|
||||
Dry-run is the default precisely because this is the script that destroys
|
||||
pending state; flipping that to a schedule is the operator's act, not a
|
||||
plugin's.
|
||||
|
||||
The messages that owe a reply are untouched by any of this, at any age, with
|
||||
any flag. That is not a gap to close later - it is the rule that keeps a
|
||||
procedural duty from becoming a substantive one.
|
||||
Loading…
Add table
Add a link
Reference in a new issue