docs(board): record the dot-repo discovery fix and its bounded gap

Follows the file's own convention (F3/F4, F12, ORDRE 42, ORDRE 65) of
documenting each board.sh fix in CLAUDE.md, not only in the commit message:
why the obvious alternative (shopt -s dotglob) was wrong, and the gap
deliberately left open (dot-directories that are not repos are never
treated as polyrepo containers).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019qMr8vZZFwa4dBrheNgAhj
This commit is contained in:
Kjell Tore Guttormsen 2026-08-18 15:05:23 +02:00
commit e2bce4e490

View file

@ -620,6 +620,46 @@ marketplace plugin. Three components, one boundary:
find a live one when planted - never behaviourally, because there is no find a live one when planted - never behaviourally, because there is no
behaviour to pin.** behaviour to pin.**
**Ordre 20260818T124828Z (2026-08-18): repo discovery had no dotglob, so a
dot-prefixed repo (`.profile`, the Forgejo/GitHub org-profile convention)
was permanently invisible to the board - not listed, and `--dispatch
--repo .profile` refused outright with "no repo named '.profile' in the
scanned roots".** Measured with a known-positive control by `.claude`
before the order was written: two repos in one root, one dot-prefixed one
not, `board.sh --plain` found only the non-dot one. **The obvious fix -
`shopt -s dotglob` on the existing discovery loops - is wrong, and the
order proved it before this repo ever wrote one line:** turned on, the
SAME `[ -e "$entry/.git" ]` test that already decides repo-vs-container
would route a dot-prefixed directory that is NOT itself a repo (e.g.
`.claude`) into the else-branch polyrepo-container scan, silently
expanding what counts as a container to a class of directory nobody
vetted for that. The fix is a dedicated `add_dot_repos()`, called once at
root level and once per polyrepo container (the identical gap exists at
both `board.sh:265` and `:271` - "same glob, two places" in the order's
words): it walks `"$1"/.* ` and adds an entry ONLY when that entry is
ITSELF a git repo, skipping `.` and `..` and skipping every dot-directory
that isn't a repo outright - never recursing into it as a container. No
`shopt` toggle is needed at all: `.* ` as a literal glob pattern already
matches dot-entries without `dotglob` set - only a bare `*` needs it -
which is what makes the targeted function possible without touching the
existing `*` loops' behavior for ordinary (non-dot) entries at all.
Verified against the real tree (2026-08-18): `.profile` and `.github`
(both real repos) now appear; `.claude` (a directory, not a repo) stays
invisible, exactly as before. Selftest section 22 pins the known-positive
control the order specified - two repos in one root, board must find
BOTH, not just the dot one - plus the container-non-promotion case (a
dot-dir with a child repo must NOT surface the child) and the depth-2
case (`:271`).
**Bounded gap, stated rather than closed:** a dot-prefixed directory that
is not itself a repo is never treated as a polyrepo container, so if a
directory like `.claude` ever grows an actual git-repo child, that child
stays invisible to the board - the identical class of gap `board.sh`
already accepts for orders addressed to an unscanned mailbox name. Widening
dot-directories to ALSO act as containers was deliberately left undone:
it was exactly the unmeasured side effect the order flagged, and nothing
in `~/repos` currently needs it (`.claude` has no repo children today).
- **Route (`scripts/route.sh`):** pure calculator for the next session's model - **Route (`scripts/route.sh`):** pure calculator for the next session's model
and effort. Takes four scored traits of the next task plus a required and effort. Takes four scored traits of the next task plus a required
rationale, and prints one block of `key=value` lines: the rubric row, the rule rationale, and prints one block of `key=value` lines: the rubric row, the rule