feat(board): nested repos enter on a STATE.md, and the scan reports its nevner

Order 20260903T190201Z-238406410-from-.claude (.claude, operator decision
2026-09-03). A git repo nested under a depth-1 REPO was invisible: discovery
adds a depth-1 repo and stops, and the else-branch container scan - the only
place children are ever looked at - is unreachable for an entry that is itself
a repo. Measured before writing anything: 12 nested repos across the real tree,
exactly 1 with a STATE.md (from-ai-to-chitta/content-sadhguru), which had been
running work and reporting to nobody.

Admission is criterion (a) and nothing wider. add_nested_repos() sits beside
add_dot_repos(), never a widening of the `*` loops - the same argument ordre
20260818T124828Z made for dot repos, and the order made it again before this
repo wrote a line: routing a depth-1 repo into the container branch would admit
every vendored clone under claude-code-100x/. One level only; depth 3 is pinned
as NOT admitted. A dot-prefixed depth-1 repo gets the same nested scan, since
nothing in the criterion distinguishes it.

A nested repo now carries TWO names. The board KEY is <parent>/<child> as the
order specifies. The MAILBOX name is not that key: a mailbox is addressed by
basename(git toplevel), so $COORD/<parent>/<child>/inbox finds no directory and
INN/ORDRE/FLY would print 0 for a repo that may have mail - a failed
measurement wearing the reassuring value, in three columns at once. The record
loop carries `mbox` beside `name`; --voyage's order lookup takes
basename($vy_dir) for the same reason. Which dirs are nested is RECORDED by
discovery (NESTED_LIST), not re-derived from "is my parent a repo?", which
would prefix every depth-1 repo if a scan root were ever a checkout.

The denominator line is independent of all of that and went in regardless:
"undersoekt: N katalog(er) depth 1, M polyrepo-container(e), K nestede repo
(J med STATE.md tatt med)". The header count answers how many were found and
nothing about how many were looked at, so a criterion excluding 11 of 12 was
invisible at the surface built to show it. Real tree 2026-09-04: 43 / 5 / 12
(1 tatt med). A non-repo dot-dir counts in N and never in M - it is a
denominator, not a partition.

Its wording broke an existing check: "polyrepo container itself is not listed
as a repo" grepped the whole output for `polyrepo` and matched the footer's own
`polyrepo-container(e)` - the same class as a grep reading a comment that
EXPLAINS a pattern as an instance of it. Now anchored at column 1, which is
what it always meant.

Verified with board.sh, not from memory: from-ai-to-chitta/content-sadhguru
in-progress, Sonnet 5/high, and --plan gives it a real tab with paste=.
Mutation-verified: reverting the eight $COORD/$mbox reads turns exactly the
three mailbox checks red with the rest of the section green.

Bounded gaps, stated rather than closed: the mailbox-keyed JOINS ($OWED,
brief_orphans, --inbox-plan) still key on the board name - neither created nor
worsened here, since the repo was previously absent from RECORDS entirely; a
34-char key overflows the table's %-32s REPO column (same class as Fable
5.1/xhigh in KOST, and widening moves three cut -c89- helpers); a dot-prefixed
NESTED repo is not looked for.

board-selftest 368 -> 393. Suites: coord 257, board 393, route 73, orders 116,
guard 54 = 893. npm test 11/11.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-04 21:35:55 +02:00
commit cde185979c
10 changed files with 428 additions and 23 deletions

View file

@ -1,6 +1,6 @@
{ {
"name": "repo-mailbox", "name": "repo-mailbox",
"version": "0.33.0", "version": "0.33.1",
"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.", "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": { "author": {
"name": "Kjell Tore Guttormsen" "name": "Kjell Tore Guttormsen"

View file

@ -467,7 +467,7 @@ marketplace plugin. Three components, one boundary:
- **Board (`scripts/board.sh`):** cross-repo attention board. Reads STATE.md - **Board (`scripts/board.sh`):** cross-repo attention board. Reads STATE.md
next-step blocks + board lines, `git status`, and mailbox pending counts, and 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 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` (368 checks). STATE.md and no mailbox. Pinned by `board-selftest.sh` (393 checks).
**It lives here because the mailbox is one of its three inputs, and it carries **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 the same axis distinction the mailbox does.** A pending count means *others
@ -902,6 +902,101 @@ marketplace plugin. Three components, one boundary:
it was exactly the unmeasured side effect the order flagged, and nothing it was exactly the unmeasured side effect the order flagged, and nothing
in `~/repos` currently needs it (`.claude` has no repo children today). in `~/repos` currently needs it (`.claude` has no repo children today).
**Ordre 20260903T190201Z-238406410 (2026-09-03, operator decision the same
day): a git repo nested under a depth-1 REPO was invisible to the board, and
the admission that closes it is criterion (a) - a STATE.md - never "all
nested repos".** Discovery adds a depth-1 repo and stops; the else-branch
container scan is the only place children are ever looked at, and it is
unreachable for an entry that is itself a repo. Measured on the real tree
before anything was written: **12 nested repos across the tree, exactly 1
with a STATE.md** (`from-ai-to-chitta/content-sadhguru`, which had been
running work and reporting to nobody). The other 11 are vendored or
experimental checkouts under `claude-code-100x/`; the operator's decision is
that they stay invisible ON PURPOSE - they do not even reach the `UTEN
STATE.md` bucket, because that bucket is for repos someone opens. Verified
after the fix with `board.sh`, not from memory:
`from-ai-to-chitta/content-sadhguru in-progress ... Sonnet 5/high`, and
`--plan` gives it a real tab with a `paste=` line.
**`add_nested_repos()` beside `add_dot_repos()`, never a widening of the `*`
loops - the same argument ordre 20260818T124828Z made for dot repos, and the
order made it again before this repo wrote a line.** Routing a depth-1 repo
into the container branch would admit every nested checkout, which is exactly
what criterion (a) declines. One level only: a repo inside a nested repo is a
checkout of a checkout, and the selftest pins that depth 3 is NOT admitted. A
dot-prefixed depth-1 repo gets the same nested scan an ordinary one gets
(`add_dot_repos` takes a `d1` flag for it) - the asymmetry would otherwise be
arbitrary, and nothing in the criterion distinguishes them.
**A nested repo now has TWO names, and conflating them would have put a
fabricated 0 in three columns.** The board KEY is `<parent>/<child>` as the
order specifies - a bare basename says nothing about where the checkout lives
and would collide with a same-named depth-1 repo. The MAILBOX name is not
that key: a mailbox is addressed by `basename(git toplevel)`, which is
`coord-send.sh`'s own rule and the only name a session in that repo can hold,
so `$COORD/<parent>/<child>/inbox` finds no directory and INN/ORDRE/FLY print
0 for a repo that may have mail. That is the failed measurement wearing the
reassuring value, in three columns at once. The record loop therefore carries
`mbox` beside `name`, and `--voyage`'s order lookup takes `basename($vy_dir)`
for the same reason. Mutation-verified: reverting the eight `$COORD/$mbox`
reads to `$COORD/$name` turns exactly the three mailbox checks red with every
other check in the section green.
**Which nested dirs those are is RECORDED by discovery, not re-derived.** The
obvious re-derivation ("is my parent directory a git repo?") answers a
slightly different question and would prefix every depth-1 repo if a scan
root ever happened to be a checkout; `NESTED_LIST` cannot drift from the
criterion because discovery is what writes it.
**The denominator line is independent of all of that and went in regardless,
because the order said so and because it is ansikt 4 pointed at the board's
own reading.** `undersoekt: N katalog(er) depth 1, M polyrepo-container(e),
K nestede repo (J med STATE.md tatt med).` The header's repo count answers
"how many were found"; nothing answered "how many were looked at", so a
criterion excluding 11 of 12 nested repos was invisible at the surface built
to show it. Real tree, 2026-09-04: `43 katalog(er) depth 1, 5
polyrepo-container(e), 12 nestede repo (1 med STATE.md tatt med)`. A
non-repo dot-dir counts in N (it WAS examined) and never in M (it is
deliberately not a container - ordre 20260818's decision), so the line is a
denominator, not a partition. Selftest section 32 pins each number against a
fixture, then changes the tree and asserts the numbers move, so a hardcoded
constant cannot pass.
**The line's own wording broke an existing check, and that is the finding
worth recording.** `check "polyrepo container itself is not listed as a
repo"` grepped the WHOLE output for `polyrepo`, so the footer's
`polyrepo-container(e)` matched and the check went red on a board that was
behaving correctly - the same defect class as coord-selftest section 38's
cache grep reading a comment that EXPLAINS a pattern as an instance of it,
and as the done-guard's rule that prose saying `status=done` must not trigger
it. The check is now anchored at column 1, which is what it always meant: a
container has no ROW.
**Bounded gap, stated rather than closed (1): the mailbox-keyed JOINS still
key on the board name.** `--brief`/`--plan`'s `$OWED` join, `brief_orphans`
and `--inbox-plan` match `coord-count.sh`'s mailbox names against RECORDS
field 3, so a nested repo owing a reply would not get a debt tab and would be
listed under `UTENFOR REPO-SKANNEN`. This change neither creates nor worsens
that: before it, the repo was not in RECORDS at all, so both readings were
already exactly as wrong. Closing it means threading a mailbox key through
six awk programs, which was not ordered and is not a discovery change.
Reported to `.claude` for its own order.
**Bounded gap, stated rather than closed (2): a 34-character key overflows
the table's `%-32s` REPO column**, shifting `from-ai-to-chitta/content-sadhguru`'s
row two characters right. Same class as `Fable 5.1/xhigh` overflowing the
`%-14s` KOST column, and handled the same way: parsing is unaffected (every
rendering that a driver reads is `key=value`), widening the column moves every
fixed offset including three `cut -c89-` selftest helpers, and it is a
rendering change nobody ordered. Truncating instead would be worse - it would
destroy the very identity the compound key exists to carry, and break
copy-paste into `--dispatch --repo`.
**Bounded gap, stated rather than closed (3):** a DOT-prefixed *nested* repo
is not looked for. The `*` glob in `add_nested_repos()` has no dotglob, the
combination was neither measured nor ordered, and `add_dot_repos` exists for
the depth-1 and container cases only because those were.
**Ordre 20260820T204409Z (2026-08-20): `route_cmd_for()`'s four trait **Ordre 20260820T204409Z (2026-08-20): `route_cmd_for()`'s four trait
extractions searched the WHOLE route line, and `.*trait=` is greedy, so a extractions searched the WHOLE route line, and `.*trait=` is greedy, so a
rationale that names a trait won the match over the field itself.** rationale that names a trait won the match over the field itself.**
@ -1351,7 +1446,7 @@ obligations in another repo.
builtins only in hook and tests. builtins only in hook and tests.
- TDD: no behavior change without a failing selftest check first. - TDD: no behavior change without a failing selftest check first.
`bash scripts/coord-selftest.sh` must exit 0 (257/257), `bash scripts/coord-selftest.sh` must exit 0 (257/257),
`bash scripts/board-selftest.sh` must exit 0 (368/368), `bash scripts/board-selftest.sh` must exit 0 (393/393),
`bash scripts/route-selftest.sh` must exit 0 (73/73), `bash scripts/route-selftest.sh` must exit 0 (73/73),
`bash scripts/orders-selftest.sh` must exit 0 (116/116) and `bash scripts/orders-selftest.sh` must exit 0 (116/116) and
`bash scripts/state-line-guard-selftest.sh` must exit 0 (54/54). `bash scripts/state-line-guard-selftest.sh` must exit 0 (54/54).

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.* *AI-generated: all code produced by Claude Code through dialog-driven development.*
![Version](https://img.shields.io/badge/version-0.33.0-blue) ![Version](https://img.shields.io/badge/version-0.33.1-blue)
![Hooks](https://img.shields.io/badge/hooks-1-green) ![Hooks](https://img.shields.io/badge/hooks-1-green)
![Skills](https://img.shields.io/badge/skills-4-orange) ![Skills](https://img.shields.io/badge/skills-4-orange)
![CLI scripts](https://img.shields.io/badge/CLI_scripts-8-blue) ![CLI scripts](https://img.shields.io/badge/CLI_scripts-8-blue)
@ -86,7 +86,7 @@ The plugin ships empty: your mailbox is created lazily on first send, on your ma
Since v0.8.0 it closes with one aggregate line about mail pending in *other* mailboxes, so an empty inbox no longer reads as "all clear" while messages sit unanswered elsewhere. Two integers, never a roster: naming the other mailboxes would put their situation inside your repo's injection, and the line explicitly disclaims the obligation it sits beneath — those counts are not yours to handle, and counting them delivered nothing. Since v0.8.0 it closes with one aggregate line about mail pending in *other* mailboxes, so an empty inbox no longer reads as "all clear" while messages sit unanswered elsewhere. Two integers, never a roster: naming the other mailboxes would put their situation inside your repo's injection, and the line explicitly disclaims the obligation it sits beneath — those counts are not yours to handle, and counting them delivered nothing.
**Choosing between repos (the `board` skill).** "What should I work on?", "who is waiting on me?", "what unblocks the most?" — `board.sh` scans every repo it can find and reads three sources per repo: the STATE.md next-step block and its optional board line, `git status`, and the pending count in that repo's mailbox. The skill runs it, ranks by leverage (what unblocks the most, cheapest first) and answers with one repo and the rule that fired, never the table. Read-only: it writes to no repo, no STATE.md, and no mailbox. The board is deliberately *not* wired into session start — it runs when asked. **Choosing between repos (the `board` skill).** "What should I work on?", "who is waiting on me?", "what unblocks the most?" — `board.sh` scans every repo it can find and reads three sources per repo: the STATE.md next-step block and its optional board line, `git status`, and the pending count in that repo's mailbox. The skill runs it, ranks by leverage (what unblocks the most, cheapest first) and answers with one repo and the rule that fired, never the table. Read-only: it writes to no repo, no STATE.md, and no mailbox. The board is deliberately *not* wired into session start — it runs when asked. Discovery takes git repos at depth 1, the children of a polyrepo container, and — since 0.33.1 — a repo nested under a depth-1 repo **only when it carries a `STATE.md`**: measured on the real tree, 12 such checkouts existed and exactly 1 had one, so admitting all of them would have buried the board in vendored clones. Every run prints its own denominator (`undersoekt: N katalog(er) depth 1, M polyrepo-container(e), K nestede repo (J med STATE.md tatt med)`), because a repo count alone says how many were found and nothing about how many were looked at.
The mailbox is one of its three inputs, which is why the board lives here. Note the axis: a repo's pending count means *others are waiting on it*, an obligation it owes outward. Who a repo waits *on* comes only from its own board line, because the message format has no reply-to field. The mailbox is one of its three inputs, which is why the board lives here. Note the axis: a repo's pending count means *others are waiting on it*, an obligation it owes outward. Who a repo waits *on* comes only from its own board line, because the message format has no reply-to field.

View file

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

View file

@ -355,7 +355,13 @@ printf '%s' "$OUT" | grep -q 'repo-a'; check "discovers top-level git repo" $?
printf '%s' "$OUT" | grep -q 'plug-x'; check "discovers nested polyrepo git repo (depth 2)" $? printf '%s' "$OUT" | grep -q 'plug-x'; check "discovers nested polyrepo git repo (depth 2)" $?
printf '%s' "$OUT" | grep -q 'repo-c'; check "lists git repo without STATE.md" $? printf '%s' "$OUT" | grep -q 'repo-c'; check "lists git repo without STATE.md" $?
printf '%s' "$OUT" | grep -q 'plain-dir'; [ $? -ne 0 ]; check "ignores non-git directory tree" $? printf '%s' "$OUT" | grep -q 'plain-dir'; [ $? -ne 0 ]; check "ignores non-git directory tree" $?
printf '%s' "$OUT" | grep -q 'polyrepo'; [ $? -ne 0 ]; check "polyrepo container itself is not listed as a repo" $? # Anchored at column 1, and the anchor is load-bearing: the claim is "the
# container has no ROW", and a row starts with the repo name. Unanchored, this
# check now matches the denominator line's own word "polyrepo-container(e)" -
# the same defect class as a file-wide grep reading a comment that EXPLAINS a
# pattern as an instance of it (coord-selftest section 38's cache assertion,
# and the done-guard's rule that prose saying status=done must not trigger it).
printf '%s' "$OUT" | grep -q '^polyrepo'; [ $? -ne 0 ]; check "polyrepo container itself is not listed as a repo" $?
# Guard the fixture itself: if git ever stops writing a .git FILE for # Guard the fixture itself: if git ever stops writing a .git FILE for
# worktrees, the next two checks would pass for the wrong reason. # worktrees, the next two checks would pass for the wrong reason.
[ -f "$ROOT/wt-feature/.git" ]; check "fixture: worktree .git is a FILE, not a dir" $? [ -f "$ROOT/wt-feature/.git" ]; check "fixture: worktree .git is a FILE, not a dir" $?
@ -3044,6 +3050,208 @@ PAOUT2="$(CLAUDE_COORD_DIR="$PACOORD" "$BOARD" --roots "$PAROOT" 2>/dev/null)"
check "pendingage: an unparseable filename reads ?, never a fabricated 0" $? check "pendingage: an unparseable filename reads ?, never a fabricated 0" $?
/bin/rm -rf "$PAROOT" "$PACOORD" 2>/dev/null /bin/rm -rf "$PAROOT" "$PACOORD" 2>/dev/null
# --- 31. Nested git repos with a STATE.md (admission a) ---------------------
# Operator decision 2026-09-03, order 20260903T190201Z-238406410-from-.claude:
# a git repo nested at depth 2 UNDER a directory that is itself a git repo
# (claude-code-100x/*, from-ai-to-chitta/*) was invisible to the board - the
# discovery loop adds a depth-1 repo and never looks inside it, and the
# else-branch container scan is reached only when the depth-1 entry is NOT a
# repo. Admission is criterion (a) and nothing wider: such a repo enters the
# board ONLY when it carries a STATE.md. A nested repo without one stays
# invisible ON PURPOSE - it does not even reach the UTEN STATE.md bucket,
# because that bucket is for repos the operator opens, and these are vendored
# or experimental checkouts nobody has declared a next step for. Measured on
# the real tree the day the order was written: 12 nested repos, exactly 1 with
# a STATE.md (from-ai-to-chitta/content-sadhguru).
#
# A dedicated add_nested_repos() beside add_dot_repos(), never a widening of
# the `*` loops: the same argument ordre 20260818T124828Z made for dot repos.
# Turning the depth-1 repo branch into a container scan would admit every
# nested checkout, which is precisely what criterion (a) declines.
NEST_ROOT="$(mktemp -d)"
NEST_COORD="$(mktemp -d)"
mk_nest_state() {
{
echo "# STATE - $2"
printf '## %s NESTE %s START HER\n' "$HAND" "$EMDASH"
echo "<!-- board: status=$3; blocked-on=-; next-cost=Sonnet 5/high -->"
echo "Next step for $2."
} > "$1/STATE.md"
}
# A depth-1 repo holding THREE nested repos, exactly one with a STATE.md.
mkrepo "$NEST_ROOT/parent-repo"
mk_nest_state "$NEST_ROOT/parent-repo" parent-repo in-progress
mkrepo "$NEST_ROOT/parent-repo/nest-with-state"
mk_nest_state "$NEST_ROOT/parent-repo/nest-with-state" nest-with-state planned
mkrepo "$NEST_ROOT/parent-repo/nest-no-state-1"
mkrepo "$NEST_ROOT/parent-repo/nest-no-state-2"
# Known-positive control: an ordinary depth-1 repo must still be found, so a
# green section cannot come from a fix that broke the case that already worked.
mkrepo "$NEST_ROOT/plain-repo"
mk_nest_state "$NEST_ROOT/plain-repo" plain-repo planned
# Known-negative control: a depth-1 repo whose nested repos carry NO STATE.md
# must contribute exactly zero extra rows.
mkrepo "$NEST_ROOT/barren-parent"
mk_nest_state "$NEST_ROOT/barren-parent" barren-parent done
mkrepo "$NEST_ROOT/barren-parent/nest-barren"
NEST_OUT="$(CLAUDE_COORD_DIR="$NEST_COORD" "$BOARD" --roots "$NEST_ROOT" 2>/dev/null)"
# Ground truth for the fixture itself, before anything depends on it: the
# nested checkout really is a git repo and really does carry a STATE.md.
[ -e "$NEST_ROOT/parent-repo/nest-with-state/.git" ] && \
[ -f "$NEST_ROOT/parent-repo/nest-with-state/STATE.md" ]
check "nested: ground truth - the fixture nested repo has .git AND STATE.md" $?
[ -e "$NEST_ROOT/parent-repo/nest-no-state-1/.git" ] && \
[ ! -f "$NEST_ROOT/parent-repo/nest-no-state-1/STATE.md" ]
check "nested: ground truth - the excluded fixture has .git and NO STATE.md" $?
printf '%s' "$NEST_OUT" | grep -q 'parent-repo/nest-with-state'
check "nested: a nested repo with STATE.md is on the board, keyed <parent>/<child>" $?
printf '%s' "$NEST_OUT" | grep -q 'nest-no-state-1'; [ $? -ne 0 ]
check "nested: a nested repo WITHOUT STATE.md stays invisible (criterion a)" $?
printf '%s' "$NEST_OUT" | grep -q 'nest-no-state-2'; [ $? -ne 0 ]
check "nested: the second STATE-less nested repo is invisible too" $?
printf '%s' "$NEST_OUT" | grep -q 'nest-barren'; [ $? -ne 0 ]
check "nested: known-negative - a parent with no STATE-carrying child adds 0 rows" $?
printf '%s' "$NEST_OUT" | grep -q '^plain-repo '
check "nested: known-positive - the ordinary depth-1 repo is still found" $?
printf '%s' "$NEST_OUT" | grep -q '(4 repo'
check "nested: exactly one row is added (4 = parent + plain + barren + nested)" $?
# The nested row is a repo like any other: its status comes from its OWN
# STATE.md, not the parent's.
printf '%s' "$NEST_OUT" | grep '^parent-repo/nest-with-state ' | grep -q 'planned'
check "nested: the nested row reads its own STATE.md board line" $?
printf '%s' "$NEST_OUT" | grep '^parent-repo ' | grep -q 'in-progress'
check "nested: the parent keeps its own status (known-positive)" $?
# The display key is <parent>/<child>; the MAILBOX name is not. A mailbox is
# addressed by basename(git toplevel) - coord-send.sh's own rule - so a repo
# named parent-repo/nest-with-state on the board still counts its mail under
# <coord>/nest-with-state. Reading the compound name against $COORD would find
# no directory and print INN 0, which is a failed measurement wearing the
# reassuring value - the one thing this file refuses everywhere.
mkdir -p "$NEST_COORD/nest-with-state/inbox" "$NEST_COORD/nest-with-state/orders/claimed"
: > "$NEST_COORD/nest-with-state/inbox/20260101T000000Z-1-from-x.md"
: > "$NEST_COORD/nest-with-state/inbox/20260101T000000Z-2-from-x.md"
: > "$NEST_COORD/nest-with-state/orders/$(date -u +%Y%m%dT%H%M%SZ)-3-from-x.md"
: > "$NEST_COORD/nest-with-state/orders/claimed/20260101T000000Z-4-from-x.md"
NEST_OUT2="$(CLAUDE_COORD_DIR="$NEST_COORD" "$BOARD" --roots "$NEST_ROOT" 2>/dev/null)"
nest_cells="$(printf '%s' "$NEST_OUT2" | grep '^parent-repo/nest-with-state ' | cut -c89-)"
# Exact values, never "not 0": before the fix the row did not exist at all, so
# `awk '{print $1}'` on an empty string is "" - which is not "0" and would have
# passed these two checks while measuring nothing. That is state-line-guard
# section 11's vacuously-green defect, and it was observed here on the red run.
[ -n "$nest_cells" ]
check "nested: ground truth - the nested row exists before its cells are read" $?
# A today-stamped filename, because a PENDING order's age is read from the
# FILENAME, not the mtime (0.32.1) - a fixed 2026-01 stem would date this cell
# to whenever the suite happens to run.
[ "$(printf '%s' "$nest_cells" | awk '{print $1}')" = "1:0d" ]
check "nested: ORDRE is counted under the mailbox BASENAME, not the compound key" $?
[ "$(printf '%s' "$nest_cells" | awk '{print $2}')" = "1:0d" ]
check "nested: FLY likewise reads <coord>/<basename>" $?
printf '%s' "$NEST_OUT2" | grep '^parent-repo/nest-with-state ' | grep -q ' 2 '
check "nested: INN reads the basename mailbox, never a fabricated 0" $?
# Depth 3 is NOT admitted: the order says depth 2 under a depth-1 repo, and a
# repo nested inside a nested repo is a checkout of a checkout. Widening was
# not ordered, and an unmeasured widening is the defect ordre 20260818 flagged.
mkrepo "$NEST_ROOT/parent-repo/nest-with-state/deeper"
mk_nest_state "$NEST_ROOT/parent-repo/nest-with-state/deeper" deeper planned
NEST_OUT3="$(CLAUDE_COORD_DIR="$NEST_COORD" "$BOARD" --roots "$NEST_ROOT" 2>/dev/null)"
printf '%s' "$NEST_OUT3" | grep -q 'deeper'; [ $? -ne 0 ]
check "nested: depth 3 is not admitted (one level under a depth-1 repo only)" $?
/bin/rm -rf "$NEST_ROOT/parent-repo/nest-with-state/deeper"
# A polyrepo container's children are UNCHANGED - their parent is not a repo,
# so they keep their bare basename and never grow a <parent>/ prefix.
mkdir -p "$NEST_ROOT/container-dir"
mkrepo "$NEST_ROOT/container-dir/child-repo"
mk_nest_state "$NEST_ROOT/container-dir/child-repo" child-repo planned
NEST_OUT4="$(CLAUDE_COORD_DIR="$NEST_COORD" "$BOARD" --roots "$NEST_ROOT" 2>/dev/null)"
printf '%s' "$NEST_OUT4" | grep -q '^child-repo '
check "nested: a polyrepo container's child keeps its bare name (known-positive)" $?
printf '%s' "$NEST_OUT4" | grep -q 'container-dir/child-repo'; [ $? -ne 0 ]
check "nested: container children are NOT renamed to <parent>/<child>" $?
# Same rule under a dot-prefixed depth-1 repo: it is a depth-1 repo, so its
# STATE-carrying nested repo is admitted on exactly the same criterion. The
# asymmetry would otherwise be arbitrary - ordinary parents scanned, dot ones
# not - and nothing in the order distinguishes them.
mkrepo "$NEST_ROOT/.dotparent"
mk_nest_state "$NEST_ROOT/.dotparent" .dotparent planned
mkrepo "$NEST_ROOT/.dotparent/dotnest"
mk_nest_state "$NEST_ROOT/.dotparent/dotnest" dotnest planned
NEST_OUT5="$(CLAUDE_COORD_DIR="$NEST_COORD" "$BOARD" --roots "$NEST_ROOT" 2>/dev/null)"
printf '%s' "$NEST_OUT5" | grep -q '\.dotparent/dotnest'
check "nested: a dot-prefixed depth-1 repo's nested repo is admitted too" $?
/bin/rm -rf "$NEST_ROOT" "$NEST_COORD" 2>/dev/null
# --- 32. The scan reports its own denominator -------------------------------
# Independent of section 31 and required regardless (the order says so in as
# many words). Verifiseringsloven ansikt 4 applied to the board's own reading:
# a repo count alone answers "how many were found" and says nothing about how
# many directories were LOOKED AT, so a criterion that silently excludes 11 of
# 12 nested repos is invisible at the surface that is supposed to show it.
# The line names all four quantities, including the excluded ones.
DEN_ROOT="$(mktemp -d)"
DEN_COORD="$(mktemp -d)"
mk_den_state() {
{
echo "# STATE - $2"
printf '## %s NESTE %s START HER\n' "$HAND" "$EMDASH"
echo "<!-- board: status=planned; blocked-on=-; next-cost=Sonnet 5/high -->"
echo "Next step for $2."
} > "$1/STATE.md"
}
# Depth-1 directories: 4 (two repos, one polyrepo container, one plain dir).
mkrepo "$DEN_ROOT/d1-repo-a"
mk_den_state "$DEN_ROOT/d1-repo-a" d1-repo-a
mkrepo "$DEN_ROOT/d1-repo-b"
mk_den_state "$DEN_ROOT/d1-repo-b" d1-repo-b
mkdir -p "$DEN_ROOT/d1-container"
mkrepo "$DEN_ROOT/d1-container/contained"
mk_den_state "$DEN_ROOT/d1-container/contained" contained
mkdir -p "$DEN_ROOT/d1-emptydir"
# Nested repos: 3 under d1-repo-a, of which 2 carry a STATE.md.
mkrepo "$DEN_ROOT/d1-repo-a/n1"; mk_den_state "$DEN_ROOT/d1-repo-a/n1" n1
mkrepo "$DEN_ROOT/d1-repo-a/n2"; mk_den_state "$DEN_ROOT/d1-repo-a/n2" n2
mkrepo "$DEN_ROOT/d1-repo-a/n3"
DEN_OUT="$(CLAUDE_COORD_DIR="$DEN_COORD" "$BOARD" --roots "$DEN_ROOT" 2>/dev/null)"
DEN_LINE="$(printf '%s\n' "$DEN_OUT" | grep '^undersoekt:')"
[ -n "$DEN_LINE" ]
check "denominator: the board prints an 'undersoekt:' line" $?
printf '%s' "$DEN_LINE" | grep -q '4 katalog(er) depth 1'
check "denominator: depth-1 directory count matches the fixture (4)" $?
printf '%s' "$DEN_LINE" | grep -q '2 polyrepo-container(e)'
check "denominator: container count matches the fixture (2: one with a repo, one empty)" $?
printf '%s' "$DEN_LINE" | grep -q '3 nestede repo'
check "denominator: nested-repo count matches the fixture (3)" $?
printf '%s' "$DEN_LINE" | grep -q '2 med STATE.md tatt med'
check "denominator: admitted-nested count matches the fixture (2 of 3)" $?
# The line must be a real reading, not a constant: change the tree and it moves.
mkrepo "$DEN_ROOT/d1-repo-a/n4"; mk_den_state "$DEN_ROOT/d1-repo-a/n4" n4
DEN_OUT2="$(CLAUDE_COORD_DIR="$DEN_COORD" "$BOARD" --roots "$DEN_ROOT" 2>/dev/null)"
printf '%s\n' "$DEN_OUT2" | grep '^undersoekt:' | grep -q '4 nestede repo (3 med STATE.md tatt med)'
check "denominator: the counts follow the tree, they are not hardcoded" $?
# A root that does not exist contributes nothing and must not silently inflate
# the denominator - F10's rule, applied to the new counters.
DEN_OUT3="$(CLAUDE_COORD_DIR="$DEN_COORD" "$BOARD" --roots "$DEN_ROOT,/nonexistent-root-$$" 2>/dev/null)"
printf '%s\n' "$DEN_OUT3" | grep '^undersoekt:' | grep -q '4 katalog(er) depth 1'
check "denominator: a missing scan root adds nothing to the counts" $?
/bin/rm -rf "$DEN_ROOT" "$DEN_COORD" 2>/dev/null
echo "" echo ""
echo "board-selftest: $PASS passed, $FAIL failed" echo "board-selftest: $PASS passed, $FAIL failed"
[ "$FAIL" -eq 0 ] || exit 1 [ "$FAIL" -eq 0 ] || exit 1

View file

@ -284,13 +284,67 @@ trunc() { printf '%s' "$1" | LC_ALL=en_US.UTF-8 cut -c1-"$2"; }
# --- Discovery: git repos at depth 1, plus depth 2 under polyrepo dirs ------ # --- Discovery: git repos at depth 1, plus depth 2 under polyrepo dirs ------
# A directory that is itself a git repo is one repo; a directory that is not # A directory that is itself a git repo is one repo; a directory that is not
# but contains git repos is a polyrepo container (the plugin marketplace) and # but contains git repos is a polyrepo container (the plugin marketplace) and
# contributes its children, never itself. # contributes its children, never itself. A repo nested under a depth-1 REPO is
# a third case, admitted on criterion (a) only - see add_nested_repos() below.
# #
# "Is a repo" tests .git with -e, not -d: a worktree or submodule has .git as a # "Is a repo" tests .git with -e, not -d: a worktree or submodule has .git as a
# FILE. A plain `git worktree add <root>/feature-x` lands a depth-1 sibling that # FILE. A plain `git worktree add <root>/feature-x` lands a depth-1 sibling that
# can CARRY its own STATE.md - a -d test drops it silently. Kept identical in # can CARRY its own STATE.md - a -d test drops it silently. Kept identical in
# the rollup builder (catalog) on purpose: two readers, one name. # the rollup builder (catalog) on purpose: two readers, one name.
REPOS="" REPOS=""
# Dirs admitted by add_nested_repos(), recorded rather than re-derived. The
# record loop needs to know which entries are nested so it can build the
# <parent>/<child> key, and the obvious re-derivation ("is my parent dir a git
# repo?") answers a slightly different question: it would also fire for every
# depth-1 repo if a SCAN ROOT ever happened to be a git checkout. Discovery
# already knows the answer exactly; storing it cannot drift from the criterion.
NESTED_LIST=""
# --- Denominator counters (order 20260903T190201Z-238406410, .claude) -------
# A repo COUNT alone answers "how many were found" and is silent about how many
# directories were looked at, so an admission criterion that excludes 11 of 12
# nested repos is invisible at the very surface meant to show it - ansikt 4
# turned on the board's own reading. These four are printed as one line under
# the table (see UNDERSOEKT below) and are independent of the nested-repo
# admission itself: the line goes in whether or not anything is admitted.
N_DEPTH1=0 # directories examined at depth 1, dot-entries included
N_CONTAINER=0 # of those, entered as polyrepo containers (not themselves repos)
N_NESTED=0 # git repos found one level under a depth-1 repo
N_NESTED_IN=0 # of those, admitted because they carry a STATE.md
# Admission criterion (a), operator decision 2026-09-03: a git repo nested
# under a directory that is ITSELF a git repo enters the board only when it
# carries a STATE.md. Measured on the real tree that day: 12 nested repos,
# exactly 1 with a STATE.md (from-ai-to-chitta/content-sadhguru). The other 11
# are vendored or experimental checkouts with no declared next step, and they
# stay invisible ON PURPOSE - they do not even reach the UTEN STATE.md bucket,
# which is for repos the operator opens.
#
# A dedicated function beside add_dot_repos(), never a widening of the `*`
# loops below, for the identical reason ordre 20260818T124828Z gave for dot
# repos: routing a depth-1 REPO into the else-branch container scan would admit
# every nested checkout, which is exactly what criterion (a) declines. One
# level only - a repo nested inside a nested repo is a checkout of a checkout,
# and widening past what was ordered is the unmeasured scope creep that order
# flagged.
#
# Bounded gap, stated rather than closed: a DOT-prefixed nested repo is not
# looked for (the `*` glob here has no dotglob, same as everywhere else in this
# file). The combination was not measured and not ordered; add_dot_repos exists
# for the depth-1 and container cases because those were.
add_nested_repos() {
for nested in "$1"/*; do
[ -d "$nested" ] || continue
[ -e "$nested/.git" ] || continue
N_NESTED=$((N_NESTED + 1))
[ -f "$nested/STATE.md" ] || continue
N_NESTED_IN=$((N_NESTED_IN + 1))
REPOS="$REPOS
$nested"
NESTED_LIST="$NESTED_LIST
$nested"
done
}
# Picks up dot-prefixed git repos directly under $1 - the Forgejo/GitHub # Picks up dot-prefixed git repos directly under $1 - the Forgejo/GitHub
# `.profile` org-profile convention, measured invisible to the loops below # `.profile` org-profile convention, measured invisible to the loops below
@ -304,16 +358,29 @@ REPOS=""
# a bare `*` needs dotglob to see them), so no shopt toggle is needed here. # a bare `*` needs dotglob to see them), so no shopt toggle is needed here.
# Only a dot-entry that IS itself a repo is ever added; one that is not is # Only a dot-entry that IS itself a repo is ever added; one that is not is
# silently skipped, never recursed into as a container. # silently skipped, never recursed into as a container.
#
# $2 = "d1" when this is the depth-1 scan of a root. A dot-prefixed depth-1
# repo IS a depth-1 repo, so it gets the same nested scan an ordinary one gets
# - the asymmetry would otherwise be arbitrary, and nothing in the admission
# criterion distinguishes them. Under a polyrepo container the flag is absent:
# those entries are already at depth 2, and their children would be depth 3.
add_dot_repos() { add_dot_repos() {
for dotentry in "$1"/.*; do for dotentry in "$1"/.*; do
dotbase="$(basename "$dotentry")" dotbase="$(basename "$dotentry")"
[ "$dotbase" = "." ] && continue [ "$dotbase" = "." ] && continue
[ "$dotbase" = ".." ] && continue [ "$dotbase" = ".." ] && continue
[ -d "$dotentry" ] || continue [ -d "$dotentry" ] || continue
# Counted as a depth-1 directory that was LOOKED AT even when it is not a
# repo: the denominator reports what was examined, not what was admitted.
# It is deliberately never counted as a polyrepo container - a dot-dir that
# is not a repo is skipped outright, which is ordre 20260818's decision.
[ "${2:-}" = "d1" ] && N_DEPTH1=$((N_DEPTH1 + 1))
[ -e "$dotentry/.git" ] || continue [ -e "$dotentry/.git" ] || continue
REPOS="$REPOS REPOS="$REPOS
$dotentry" $dotentry"
[ "${2:-}" = "d1" ] && add_nested_repos "$dotentry"
done done
return 0
} }
# Split on comma via IFS + `set --` rather than an unquoted $(...) expansion: # Split on comma via IFS + `set --` rather than an unquoted $(...) expansion:
@ -336,13 +403,20 @@ for root in "$@"; do
continue continue
fi fi
ROOTS_OK=$((ROOTS_OK + 1)) ROOTS_OK=$((ROOTS_OK + 1))
add_dot_repos "$root" add_dot_repos "$root" d1
for entry in "$root"/*; do for entry in "$root"/*; do
[ -d "$entry" ] || continue [ -d "$entry" ] || continue
N_DEPTH1=$((N_DEPTH1 + 1))
if [ -e "$entry/.git" ]; then if [ -e "$entry/.git" ]; then
REPOS="$REPOS REPOS="$REPOS
$entry" $entry"
# A depth-1 repo used to end the walk here: the else-branch below is the
# only place children are ever looked at, and it is unreachable for an
# entry that is itself a repo. That is what made every nested repo
# invisible.
add_nested_repos "$entry"
else else
N_CONTAINER=$((N_CONTAINER + 1))
for child in "$entry"/*; do for child in "$entry"/*; do
[ -e "$child/.git" ] || continue [ -e "$child/.git" ] || continue
REPOS="$REPOS REPOS="$REPOS
@ -613,7 +687,24 @@ VOYAGE_CELL_EOF
printf '%s\n' "$REPOS" | while IFS= read -r d; do printf '%s\n' "$REPOS" | while IFS= read -r d; do
[ -n "$d" ] || continue [ -n "$d" ] || continue
name="$(basename "$d")" # Two names, deliberately: the KEY the board shows and the MAILBOX the coord
# columns read. For every repo but a nested one they are the same string.
#
# A nested repo is keyed <parent>/<child> (operator decision 2026-09-03): the
# bare basename would render a row that says nothing about where the checkout
# lives, and two repos of the same name - one depth-1, one nested - would
# collide into indistinguishable rows.
#
# The mailbox name is NOT that key. A mailbox is addressed by
# basename(git toplevel), which is coord-send.sh's own rule and the only name
# a session in that repo can hold; reading $COORD/<parent>/<child>/inbox would
# find no directory and print INN 0 - a failed measurement wearing the
# reassuring value, which is the one thing this file refuses everywhere.
mbox="$(basename "$d")"
name="$mbox"
if printf '%s\n' "$NESTED_LIST" | grep -qxF "$d"; then
name="$(basename "$(dirname "$d")")/$mbox"
fi
state="$d/STATE.md" state="$d/STATE.md"
# F6: `git status | wc -l` yields 0 lines whether the tree is CLEAN or git # F6: `git status | wc -l` yields 0 lines whether the tree is CLEAN or git
@ -640,8 +731,8 @@ printf '%s\n' "$REPOS" | while IFS= read -r d; do
fi fi
inbox=0 inbox=0
if [ -d "$COORD/$name/inbox" ]; then if [ -d "$COORD/$mbox/inbox" ]; then
inbox="$(ls "$COORD/$name/inbox"/*.md 2>/dev/null | wc -l | tr -d ' ')" inbox="$(ls "$COORD/$mbox/inbox"/*.md 2>/dev/null | wc -l | tr -d ' ')"
[ -n "$inbox" ] || inbox=0 [ -n "$inbox" ] || inbox=0
fi fi
@ -657,8 +748,8 @@ printf '%s\n' "$REPOS" | while IFS= read -r d; do
# as mail to such a name is invisible in INN. coord-count.sh is the cross- # as mail to such a name is invisible in INN. coord-count.sh is the cross-
# check for the mail half; there is deliberately no join built for orders. # check for the mail half; there is deliberately no join built for orders.
orders=0 orders=0
if [ -d "$COORD/$name/orders" ]; then if [ -d "$COORD/$mbox/orders" ]; then
orders="$(ls "$COORD/$name/orders"/*.md 2>/dev/null | wc -l | tr -d ' ')" orders="$(ls "$COORD/$mbox/orders"/*.md 2>/dev/null | wc -l | tr -d ' ')"
[ -n "$orders" ] || orders=0 [ -n "$orders" ] || orders=0
fi fi
@ -681,8 +772,8 @@ printf '%s\n' "$REPOS" | while IFS= read -r d; do
# read as "a session is running here" would be the process axis smuggled in # read as "a session is running here" would be the process axis smuggled in
# as a file count. # as a file count.
claimed=0 claimed=0
if [ -d "$COORD/$name/orders/claimed" ]; then if [ -d "$COORD/$mbox/orders/claimed" ]; then
claimed="$(ls "$COORD/$name/orders/claimed"/*.md 2>/dev/null | wc -l | tr -d ' ')" claimed="$(ls "$COORD/$mbox/orders/claimed"/*.md 2>/dev/null | wc -l | tr -d ' ')"
[ -n "$claimed" ] || claimed=0 [ -n "$claimed" ] || claimed=0
fi fi
@ -696,9 +787,9 @@ printf '%s\n' "$REPOS" | while IFS= read -r d; do
# measured 2026-08-23), so a claim without an age is that non-claim with its # measured 2026-08-23), so a claim without an age is that non-claim with its
# only counter-evidence removed. # only counter-evidence removed.
ordersage="-" ordersage="-"
[ "$orders" -eq 0 ] || ordersage="$(oldest_pending_age "$COORD/$name/orders")" [ "$orders" -eq 0 ] || ordersage="$(oldest_pending_age "$COORD/$mbox/orders")"
claimedage="-" claimedage="-"
[ "$claimed" -eq 0 ] || claimedage="$(oldest_order_age "$COORD/$name/orders/claimed")" [ "$claimed" -eq 0 ] || claimedage="$(oldest_order_age "$COORD/$mbox/orders/claimed")"
# Read for EVERY repo, not just the STATE-less ones: a repo whose plan file # Read for EVERY repo, not just the STATE-less ones: a repo whose plan file
# is fresh can still have been silent for a year, and that is precisely the # is fresh can still have been silent for a year, and that is precisely the
@ -1944,7 +2035,11 @@ voyage() {
# Order coupling: the repo's PENDING orders (claimed ones are in flight and # Order coupling: the repo's PENDING orders (claimed ones are in flight and
# are not what a reader is looking for when a brief has stopped moving). # are not what a reader is looking for when a brief has stopped moving).
vy_ord=0; vy_ids="" vy_ord=0; vy_ids=""
for vy_of in "$COORD/$vy_name/orders"/*.md; do # basename($vy_dir), never $vy_name: a nested repo's board key is
# <parent>/<child> while its mailbox is addressed by the bare basename
# (see the record loop's own note). Reading the compound key here would
# find no directory and report ordre=0 for a repo that has orders.
for vy_of in "$COORD/$(basename "$vy_dir")/orders"/*.md; do
[ -f "$vy_of" ] || continue [ -f "$vy_of" ] || continue
vy_ord=$((vy_ord+1)) vy_ord=$((vy_ord+1))
vy_ids="$vy_ids$(basename "$vy_of" .md) vy_ids="$vy_ids$(basename "$vy_of" .md)
@ -2050,6 +2145,13 @@ n_nofield="$(awk -F'|' '$4=="?"' "$RECORDS" | wc -l | tr -d ' ')"
n_unmeas="$(awk -F'|' '$7=="?"' "$RECORDS" | wc -l | tr -d ' ')" n_unmeas="$(awk -F'|' '$7=="?"' "$RECORDS" | wc -l | tr -d ' ')"
printf '\nSUM: %s uhaandterte innboks-meldinger, %s ukommiterte filer.\n' "$tot_in" "$tot_dirty" printf '\nSUM: %s uhaandterte innboks-meldinger, %s ukommiterte filer.\n' "$tot_in" "$tot_dirty"
# The scan's own denominator (order 20260903T190201Z-238406410, .claude). The
# repo count in the header answers "how many were found"; this answers "how
# many were looked at", which is the only way an admission criterion that
# excludes most nested repos is visible at all. Verifiseringsloven ansikt 4:
# a measurement without its nevner is read as a fact about the world.
printf 'undersoekt: %s katalog(er) depth 1, %s polyrepo-container(e), %s nestede repo (%s med STATE.md tatt med).\n' \
"$N_DEPTH1" "$N_CONTAINER" "$N_NESTED" "$N_NESTED_IN"
[ "${n_mal:-0}" -gt 0 ] && printf 'ADVARSEL: %s repo har MALFORMED status-token (utenfor det lukkede settet).\n' "$n_mal" [ "${n_mal:-0}" -gt 0 ] && printf 'ADVARSEL: %s repo har MALFORMED status-token (utenfor det lukkede settet).\n' "$n_mal"
[ "${n_nofield:-0}" -gt 0 ] && printf 'MERK: %s repo mangler board-linje - status/kost er ukjent (?), NESTE-utdrag brukes.\n' "$n_nofield" [ "${n_nofield:-0}" -gt 0 ] && printf 'MERK: %s repo mangler board-linje - status/kost er ukjent (?), NESTE-utdrag brukes.\n' "$n_nofield"
[ "${n_unmeas:-0}" -gt 0 ] && printf 'MERK: %s repo har umaalbart arbeidstre - git svarte ikke, DRT er ? og IKKE med i summen over.\n' "$n_unmeas" [ "${n_unmeas:-0}" -gt 0 ] && printf 'MERK: %s repo har umaalbart arbeidstre - git svarte ikke, DRT er ? og IKKE med i summen over.\n' "$n_unmeas"

View file

@ -23,7 +23,7 @@ description: >-
user names no repo and no tool — choosing *between* repos is this skill. Not for 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, "where were we" inside the current repo: that is this repo's own STATE.md,
already injected at session start. already injected at session start.
version: "0.33.0" version: "0.33.1"
--- ---
# board — which repo deserves the next session # 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 covers retiring a broadcast that has become wrong or obsolete: "retract that
broadcast", "that announcement is outdated, pull it", "trekk tilbake kringkastingen", broadcast", "that announcement is outdated, pull it", "trekk tilbake kringkastingen",
"den broadcasten er utdatert". "den broadcasten er utdatert".
version: "0.33.0" version: "0.33.1"
--- ---
# coord-send — natural-language front door for inter-repo messages # 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`), 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 not for scoring model and effort alone (that is `route`), and not for sending a
message to another repo (that is `coord-send`). message to another repo (that is `coord-send`).
version: "0.33.0" version: "0.33.1"
--- ---
# dispatch — hand a session a task it can actually start on # 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 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: session IS this skill. Not for choosing which REPO gets the next session:
that is the `board` skill. that is the `board` skill.
version: "0.33.0" version: "0.33.1"
--- ---
# route — what the next session should run with # route — what the next session should run with