feat(route,board): strike the advisor rule, add board.sh --row <repo>

Order 20260912T202210Z-7588027378-from-.claude, operator decision
2026-09-12 (helhetlig vurdering av arbeidssystemet, cut row 3 and the
board.sh --row improvement row). One order, two parts, one version bump.

THE ADVISOR RULE IS STRUCK. route.sh and board.sh --dispatch emit no
--advisor at all. The rule fired per ROW on a need - always on the Sonnet
rows (a capability lift, which is what made the quota fallback safe to
take), and on the Opus rows at reversibility=costly|one-way - and it read
well. It was killed by a MEASUREMENT, not by taste: of 54 dispatches the
PM issued 08.-12.09, ZERO carried the flag, because sessions are started
by hand from the model and effort rather than from the whole emitted
line. A rule nothing honours is not a policy, and an emitted value nobody
acts on is decoration in a field whose only job is to be evidence. The
advisor is now what it already was in practice: an operator decision per
session, said in one sentence in route.sh --help.

The comments that rested on the rule were REWRITTEN, not left standing.
board.sh --dispatch still refuses a --model/--effort pair, but the reason
is no longer "the advisor is a property of the ROW": it is that the rubric
has exactly one copy, and a dispatch taking the model directly would be a
second, unscored way to reach the same decision - recording no traits, no
rationale and no next-cost, so nothing afterwards could say whether the
routing or the scoring was wrong. A comment defending a removed mechanism
is how the next session restores it. Both skills carry the correction.

Pinned as an ABSENCE over the whole trait space - 81 combinations, every
line of output, with a known-positive control proving the sweep's grep
can find a planted advisor - rather than on four sampled rows, because
the claim is that no path emits it. board.sh --dispatch at
reversibility=costly is pinned separately: that is the exact input a
reintroduced rule would fire on. The literal string is absent from
route.sh entirely, including the paragraph recording what was struck (it
says "an opus advisor flag" in words), because a blunt grep cannot tell a
description from a specification. Backward compatibility is pinned rather
than assumed: a route line carrying a legacy advisor= field still parses
and still yields a command - measured, 0 of 48 route lines in ~/repos
carry one, but a reader that broke on an unknown field would turn last
month's STATE.md into "that repo has no route line". The three CLI gates
section 14 carried went with the rule; the suite no longer depends on the
installed claude at all.

board.sh --row <repo> IS THE SEVENTH RENDERING of the same scan, never a
second scan, read-only like every other one. (The order calls it the
sixth; by this file's own numbering --inbox-plan is the fourth and
--dispatch the fifth. Corrected rather than carried wrong.) It exists
because the columns WERE misread: on 11.09 the PM read FLY off the table
by eye and got it wrong, while every other rendering a program consumes
is already key=value. inn, ordre and fly are three separate fields
because they are three separate facts; status is the bare token, never
the table's blocked>target display, with blocked-on beside it; neste is
last and uncut. An unknown repo exits 2 and writes NOTHING to stdout - an
empty block would read as a repo whose every column is blank, which is a
real and different state.

upushet is the ONE field that is not a rendering of the scan, and it is
named rather than blended in: nothing in the scan measures it, so it is
read once, for the named repo only, and never enters the table, the plan
or the briefing. It reads the remote-TRACKING ref, not the remote, so
upushet=N honestly means "the local ref says N"; a repo with no upstream
reports ?, never 0.

The row fixture's three counts are three DIFFERENT integers (3/2/1), and
that is the finding worth recording. Built first with 2/1/1, it was
mutation-tested by making fly read the ORDRE field - the exact 11.09
misreading - and the check stayed GREEN, because the two fields held the
same digit. A fixture that cannot tell two columns apart is the defect
wearing a passing test, inside the section written to prevent it.

Suites under /bin/bash 3.2, before -> after: coord 257 -> 257, board
393 -> 427, route 73 -> 73 (13 advisor checks and 3 CLI gates out, 15
absence/legacy checks in, and it no longer varies with claude being on
PATH), orders 116 -> 116, state-line-guard 54 -> 54. Sum 893 -> 927,
README badge updated to the measured sum. npm test 12/12, fail 0.

Verified live against the real tree, not only fixtures: --row
repo-mailbox reports fly=1 beside ordre=0 (the distinction that was
misread), --row on the nested key from-ai-to-chitta/content-sadhguru
resolves, and an unknown repo exits 2.

No tag, no push, no catalog change - that is the operator's
release-plugin.mjs run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-12 23:45:47 +02:00
commit 5e5bc4a66e
13 changed files with 689 additions and 271 deletions

108
CLAUDE.md
View file

@ -467,7 +467,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` (393 checks).
STATE.md and no mailbox. Pinned by `board-selftest.sh` (427 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
@ -639,13 +639,17 @@ marketplace plugin. Three components, one boundary:
`brief-nightly.sh` already carries for the briefing.
**The cost comes from `route.sh`'s row table, and `--dispatch` deliberately
refuses a `--model`/`--effort` pair.** `--advisor opus` is a property of the
ROW; two rows share a model/effort pair while differing on it, and the CLI
accepts a wrong advisor silently. A dispatch taking the model directly would
have no honest source for that flag, and both available guesses produce the
same failure — a session that looks peer-reviewed without being. A Fable
dispatch is therefore not a `--dispatch` outcome at all, exactly as it is not
a `route.sh` outcome; it is a hand-written override.
refuses a `--model`/`--effort` pair.** Until 2026-09-12 that rested on
`--advisor opus` being a property of the ROW; that rule is struck (see
`route.sh` above) and the argument was REWRITTEN rather than left standing on
a premise the code no longer has — a comment defending a removed mechanism is
how the next session restores it. The reason now: the rubric is a policy with
exactly one copy, and a dispatch accepting the model directly would be a
second, unscored way to reach the same decision — one recording no traits, no
rationale and no `next-cost`, so nothing afterwards could say whether the
ROUTING was wrong or the SCORING was. A Fable dispatch is therefore not a
`--dispatch` outcome at all, exactly as it is not a `route.sh` outcome; it is
a hand-written override.
**`--target-pane yes|no` is REQUIRED, with no default, and that is the same
rule `--last-effort` carries.** It is a measurement of the world — does the
@ -1066,23 +1070,38 @@ marketplace plugin. Three components, one boundary:
and belongs to the skill; turning scores into a row is a lookup and takes zero
model calls.
**`--advisor opus` is emitted per ROW, on a need, never unconditionally.**
Rows 1-2 always carry it (Sonnet main model, so opus is a capability lift —
and since every fallback is one row cheaper and the cheap rows are Sonnet,
this is what makes the quota fallback safe to take); rows 3-4 only at
`reversibility=costly|one-way` (Opus main model, so it buys peer review where
a mistake is not cheap to undo); rows 5-6 never, because the CLI rejects every
advisor for a Fable main model. The alternative — the global `advisorModel`
setting written by `/advisor` — is what this replaces: it applies to every
session in every repo, which is how it burned quota before. The two triggers
are almost disjoint by construction, since `costly` forces row 3 and `one-way`
forces row 4, so a Sonnet row always has `reversibility=cheap`.
`verification=none` is deliberately NOT a third trigger: beyond the stakes
rule it would only add mistakes that are cheap to reverse, docs sessions
(`known/none/cheap/local`) among them. Section 14 pins the rule and gates the
three CLI facts it rests on against the installed `claude` without spending a
token — advisor validation runs before the empty-prompt check, so `-p ""`
reaches the validator and stops there.
**NO `--advisor` is emitted, by this calculator or by `board.sh --dispatch`
(operator decision 2026-09-12, `~/.claude/docs/2026-09-12-helhetlig-vurdering-arbeidssystemet.md`
§ 4, cut row 3).** The struck rule fired per ROW on a need — always on the
Sonnet rows (a capability lift, which is what made the quota fallback safe to
take), and on the Opus rows at `reversibility=costly|one-way` (peer review
where a mistake is not cheap to undo). It read well and it was killed by a
MEASUREMENT, not by taste: of 54 dispatches the PM issued 08.12.09, **zero**
carried the flag, because sessions are started by hand from the model and
effort rather than from the whole emitted line. A rule nothing honours is not
a policy, and an emitted value nobody acts on is decoration in a field whose
only job is to be evidence. The advisor is now what it already was in
practice: **an operator decision per session**, said in one sentence in
`route.sh --help`.
The absence is pinned over the WHOLE trait space — 81 combinations, every
line of output, with a known-positive control proving the sweep's grep can
find a planted advisor — rather than on four sampled rows, because the claim
is that no path emits it. `--dispatch` at `reversibility=costly` is pinned
separately: that is the exact input a reintroduced rule would fire on.
The three CLI gates section 14 used to carry (does `claude` accept
`--advisor`, does it accept opus advising sonnet, does it still reject opus
advising fable) went with the rule — they existed to gate facts the rule
rested on, and the suite no longer depends on the installed `claude` at all.
**The literal string `--advisor opus` is absent from `route.sh` ENTIRELY,
including the paragraph recording what was struck** (it says "an opus advisor
flag" in words): a blunt grep cannot tell a description from a specification,
the same reason coord-selftest's cache assertion runs on an extracted path
rather than the whole file. Do not restore the quote.
Backward compatibility is pinned rather than assumed: a route line carrying a
legacy `advisor=` field still parses and still yields a command. Measured the
same day — **0 of 48** `<!-- route:` lines anywhere in `~/repos` carry one, so
nothing in circulation depends on it, but a reader that broke on an unknown
field would turn last month's STATE.md into "that repo has no route line".
**Rows 5-6 are never a `route.sh` outcome.** Until 2026-08-06 they fired
only from an explicit `--opus-xhigh-failed` flag, mirroring a global
@ -1398,6 +1417,43 @@ marketplace plugin. Three components, one boundary:
phase and age and leaves the judgement to the reader, which is why 51
projects are listed rather than some filtered subset.
- **`--row <repo>` is the SEVENTH rendering: the table's row for ONE repo, as
`field=value` lines** (order 20260912T202210Z-7588027378, operator decision
2026-09-12). Same scan, never a second one, read-only like every other
rendering. **The order calls it the sixth; by this file's own numbering
`--inbox-plan` is the fourth and `--dispatch` the fifth, so it is the
seventh** — corrected here rather than carried wrong.
**It exists because the columns WERE misread.** On 2026-09-11 the PM read the
FLY column off the table by eye and got it wrong. Every other rendering a
program consumes (`--plan`, `--inbox-plan`, `--dispatch`) is already
`key=value`; the default view was the one left out, and the 34-character
nested-repo key already shifts a row two characters right (a stated, unclosed
gap), which makes counting spaces worse than it looks. `inn`, `ordre` and
`fly` are three separate fields because they are three separate facts, and
confusing them is the whole reason this exists. `status` is the bare token,
never the table's `blocked>target` display, with `blocked-on` beside it;
`neste` is last and uncut, for the same reason it is last in the record. An
unknown repo exits **2** and writes NOTHING to stdout — an empty block would
read as a repo whose every column is blank, which is a real and different
state (`?`).
**`upushet` is the one field that is NOT a rendering of the scan, and it is
named rather than blended in.** Nothing in the scan measures it, so it is
read once, for the named repo only, and never enters the table, the plan or
the briefing. It reads the remote-TRACKING ref, not the remote: `upushet=N`
honestly means "the local ref says N", and `git ls-remote` is still what a
claim ABOUT THE WORLD costs. A repo with no upstream reports `?`, never `0`
"nothing is waiting to be pushed" and "nobody looked" are exactly the pair
this engine refuses to render alike.
**The fixture's three counts are three DIFFERENT integers (3/2/1), and that
is the finding worth recording.** Built first with 2/1/1, it was
mutation-tested by making `fly` read the ORDRE field — the exact 11.09
misreading — and the check stayed GREEN, because the two fields held the same
digit. A fixture that cannot tell two columns apart is the defect wearing a
passing test, inside the section written to prevent it.
- **Skills (`skills/coord-send/`, `skills/board/`, `skills/route/`, `skills/dispatch/`):** natural-language front
doors mapping user intent to engine invocations. No mailbox logic lives here
either. `board` additionally owns the *ranking* — which repo wins and why —
@ -1446,7 +1502,7 @@ 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 (257/257),
`bash scripts/board-selftest.sh` must exit 0 (393/393),
`bash scripts/board-selftest.sh` must exit 0 (427/427),
`bash scripts/route-selftest.sh` must exit 0 (73/73),
`bash scripts/orders-selftest.sh` must exit 0 (116/116) and
`bash scripts/state-line-guard-selftest.sh` must exit 0 (54/54).