repo-mailbox v0.19.0 — release. Catalog ref now pins the v0.19.0 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The stat-badge gate skips any axis the plugin does not badge, so those
numbers are structurally unverifiable and rot in silence. Hand-audited
every remaining one against ground truth extracted from the pinned tag
(git archive <ref>, never the sibling working tree).
12 of 13 measured exact. The one defect: voyage's `500+ tests`, which is
832 at v5.9.1 — true as a lower bound, so the gate could never have seen
it, but a 40% understatement to a reader comparing plugin blocks.
Also corrects CLAUDE.md's own worked example: `1441 tests` was the number
the ref-defect produced by reading config-audit's working tree; 1398 is
what v5.13.0 installs. Records the two counting rules calibrated against
the badged plugins — hooks = hook command entries (events and matchers
both diverge from the badge), tests = `ℹ tests` and not `ℹ pass`.
Gate: 11 OK / 0 WARN / 0 ERROR. Tests 120/120.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D6Sy2bjLWXjh59g1WsAe4X
ai-psychosis v1.2.2 — release. Catalog ref now pins the v1.2.2 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Same defect as 780f86e, in a number I wrote myself in e9054f8: 374 came from
repo-mailbox's working tree, which has committed past v0.18.0 (board-selftest.sh
is +44 lines there, worth 4 extra checks). The catalog documents what installs.
Measured at the pinned tag, extracted read-only with `git archive v0.18.0` into a
scratch dir (never a checkout in another repo): coord 183 + route 73 + board 114
= 370. CLI scripts stays 8 — scripts/ holds the same 11 *.sh at the tag as at
HEAD, of which 3 are selftests.
Both axes are badge-less, so the gate cannot check either. That is the point:
this is the class that needs a human pass, and it just proved it twice.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RDSiMcgLMpEETwtkc86Nym
Found live minutes after shipping fc95cbd: llm-security went ERROR on scanners
(23 vs 22) and tests (2013 vs 2034). The catalog was RIGHT and the gate was
wrong. llm-security had committed past its v7.8.3 tag without bumping the
version, and the gate was reading the sibling working tree — but the catalog
documents what INSTALLS, and `ref: v7.8.3` still installs 23/2013.
Stat badges are now read with `git show <ref>:README.md`, falling back to the
working tree only when the ref cannot be read (a ref resolving to nothing is
already its own ERROR, so the fallback cannot hide a dangling ref). The
version-badge check is unchanged and still reads the working tree: that one is
about the plugin's internal consistency, not about what the catalog promises.
This also corrects a stat I got wrong in fc95cbd. I had moved config-audit from
1410 to 1441 tests off the working tree; at the pinned v5.13.0 the badge says
1398. 1441 is unreleased. The catalog now says 1398 — what installs.
[skip-docs]: CLAUDE.md carries the rule and the "check `git show <ref>:README.md`
before believing the working tree" instruction; README.md changes by one number
because the gate was wrong about it.
Tests 117 -> 120 (+3, all regression). Gate green at 11 OK / 0 WARN / 0 ERROR.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RDSiMcgLMpEETwtkc86Nym
029ffb8 (this session, hours ago) said one emitter remained. okr migrated the
same day, so that is already stale. Both emitters are gone:
- linkedin-studio at its bc47c18 (scaffold.ts)
- okr at its 1da9dd8 — okf-index.mjs now emits okf_version via writeFrontmatter
ahead of the `# heading`; only okf_layout stays in body text.
Verified read-only against okr e662196 rather than taken from their notice.
The fallback stays, but its justification changed with them: it now covers
bundles already written in the old form, not emitters still producing it. okr
made its own checker tolerant (049259d) BEFORE moving the emitter (1da9dd8), so
nothing forces a simultaneous migration and the parity signature does not split.
Re-measured after the change: check-okf-parity 9/9 green, okf-check 25/25.
Removal condition restated honestly: only once every bundle in the wild has been
rewritten — which nothing tracks today.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RDSiMcgLMpEETwtkc86Nym
[skip-docs]: the user-facing doc here is CLAUDE.md, not README.md. This is a
maintainer-side consistency gate — the catalog landing page should not describe
it — and CLAUDE.md gains a full paragraph covering the rule, the measured
badge-less gap, and the never-hand-edit-a-stat-line instruction. README.md
changes by exactly one number because the gate found it wrong.
The catalog restates each plugin's counts in a per-plugin stat line, and those
numbers rot silently: nothing compared them to anything. Measured across all 11
plugin READMEs today, config-audit's line claimed 1410 tests while the plugin's
own badge said 1441.
Rule is PER-AXIS, not per-plugin. For each number on a catalog stat line, if the
plugin carries a shields badge for that axis, they must agree (ERROR otherwise);
if it carries no such badge, the axis is skipped. This was measured, not assumed:
21 axis-pairs are badge-covered, but 14 axes across 8 of the 11 plugins are
badge-less (voyage 4, ms-ai-architect 3, repo-mailbox 2, ai-psychosis 2,
linkedin-studio 1, claude-design 1, graceful-handoff 1). A per-plugin exception
list — the original sketch, scoped around voyage alone — would have had to name 8
of 11 repos and be hand-edited for every new axis.
Stated plainly rather than hidden: those 14 axes stay ungated. repo-mailbox's two
were 6 and 251 against a true 8 and 374 (fixed in e9054f8).
Parsing is measured against the real corpus: shields' `--` literal-hyphen escape,
`_`/`%20` spaces, zero as a real count, non-numeric badges (version/platform/
license) excluded, parenthetical asides read as their own axis ("5 skills (389
docs)"), doc/docs/references/reference_docs/knowledge_docs folded onto one axis,
and `N+` read as a lower bound.
Only the catalog's config-audit number changed; the plugin badge is the source.
Tests 106 -> 117 (+11). Gate green at 11 OK / 0 WARN / 0 ERROR.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RDSiMcgLMpEETwtkc86Nym
Both numbers were measured at v0.12.x and never re-measured across six version
bumps. Neither axis carries a shields badge, so the badge-mirroring gate now
being designed would not have caught either — they are stated here as the
ungated class that still needs a human pass.
Measured today against repo-mailbox v0.18.0:
- CLI scripts 6 -> 8: scripts/ holds 11 *.sh, of which 3 are selftests
(board, coord, route), leaving 8 operator-facing entry points.
- selftest checks 251 -> 374: coord 183 + route 73 + board 118, from running
the three selftests (each sandboxes its mailbox via mktemp -d).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RDSiMcgLMpEETwtkc86Nym
linkedin-studio migrated its bundle-root okf_version from body text into the
root index.md frontmatter block (their bc47c18, which is their HEAD). The
comment justifying the body-text fallback still claimed two live emitters.
Verified against ground truth rather than taken from the notice:
- linkedin-studio scaffold.ts now emits okf_version 0.1 inside the frontmatter
block (measured 2026-08-02 at bc47c18).
- okr scripts/okf-index.mjs:204 still pushes it as body text, after the
`# heading` line with no `---` delimiters (measured 2026-08-02 at d634385).
So the fallback stays — it is still load-bearing for okr, and check-okf-parity
still compares this value against okr's live checker. Only the count and the
removal condition change. Comment-only; 106/106 tests green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RDSiMcgLMpEETwtkc86Nym
repo-mailbox v0.18.0 — release. Catalog ref now pins the v0.18.0 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
repo-mailbox v0.17.0 — release. Catalog ref now pins the v0.17.0 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
repo-mailbox v0.16.0 — release. Catalog ref now pins the v0.16.0 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
repo-mailbox v0.15.0 — release. Catalog ref now pins the v0.15.0 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
repo-mailbox v0.14.0 — release. Catalog ref now pins the v0.14.0 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The frontmatter reader matched `^\s*<key>:` with the m flag — indentation-
agnostic, so a block-form nested entry satisfied a top-level lookup. Measured
against okf/SPEC.md at frozen 3fcbb9f, this is a field confusion, not a near
miss: :467-469 names `resource`, `sources[].resource`, `executor.resource` and
`attester.resource` as DISTINCT fields. Top-level `resource` is the URI of the
asset a concept describes (:196); `sources[].resource` is the material it
derives from (:302). `sources` entries carry their own `title` and `type` too.
The consequence was not confined to warnings. Measured before the fix, a
concept with NO top-level `type:` and a `sources[].type` reported "0 files
without type: / OK: valid OKF bundle" — a false negative on §4.1's only
always-required field. `untyped` IS in the parity signature
(check-okf-parity.mjs:73-76), but okr vendors the same regex, so both impls
were blind identically and the gate stayed green while both were wrong.
Anchoring the key at column 0 fixes it. Flow-form never had the bug: in
`sources: [{ id: s1, resource: fixture }]` the nested key is mid-line, so `^`
cannot match it — measured against llm-ingestion-okf's v0.2 golden bundle
(6e0a7c0, read-only), which warns about `resource` and `description` both
before and after.
The divergence from okr is deliberate and is NOT okr lagging. Their reader is
SHARED, and the nested match is documented as load-bearing for their injector
(lib/frontmatter.mjs:7-9 -> inject:69) — while the same module backs their
scripts/okf-check.mjs:101, which needs the opposite. Pinned as parity fixture
`red-nested-key` (catalog FAILs on the nested type, okr passes it), so the
split is a running red/green signal instead of a note. It flips to `agree`
only if okr scopes the checker's reader without touching inject.
Correcting two premises carried in from the previous session, both measured:
- The reader was NOT flat/top-level-only. It read nested keys, so the suspected
false POSITIVE on `resource` was actually a false NEGATIVE, opposite sign.
- "No v0.2 bundle exists" held for our own corpora and emitters only.
llm-ingestion-okf ships a v0.2 golden bundle, where the previous commit's
version-conditional list has real effect — and behaves correctly there.
docs/okf-second-brain/spec.md is untouched deliberately: it makes no claim
about key scope, so gate and convention do not disagree here.
Tests 103 -> 106 (okf-check 22 -> 25), parity 9/9 -> 10/10. All six suites
green; check-versions 11 OK / 0 WARN / 0 ERROR.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RGZGiDPYcHUMSDCVJavRhp
route.sh now writes --advisor opus into the startup command it emits,
per row and on a need: always on the Sonnet rows (capability lift, which
is what makes the quota fallback safe to take), on the Opus rows only at
costly/one-way stakes, never on Fable (the CLI rejects it).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X8N8hQEJSWWtieWUx37txT
The gate carried a flat RECOMMENDED list ending in `timestamp`. Upstream retired
that field in v0.2: "`timestamp` is superseded by `generated.at`" (okf/SPEC.md
§13.1:802-803, read at frozen 3fcbb9f), one of the version's two breaking
changes — while :804 still lets a consumer "fall back to a legacy `timestamp`
when `generated` is absent".
A version-unconditional list cannot serve both readings. It either nags a
correct v0.2 bundle about a retired field, or goes silent about a field v0.1
still wants. So the list is now chosen by the bundle root's own okf_version:
< 0.2 (or absent/unshaped) keeps `timestamp`, >= 0.2 asks for `generated`.
Absence gets the legacy floor deliberately — §3 echoes a missing marker rather
than failing it, so it still needs a defined list.
Measured, not assumed:
- Every fixture in both corpora and both live emitters (okr, linkedin-studio)
still write `okf_version: 0.1`, so this changes NO verdict today. It is
written now because the upstream reading is fresh and pinned to a commit.
- The parity signature is conceptCount|untyped|okfVersion|okfVersionAccepted
(check-okf-parity.mjs:73-76) — warnings are not in it, so diverging from
okr's list here cannot red the parity gate. Confirmed: 9/9 fixtures pass.
- The compare is component-wise, NOT parseFloat: okf_version is version-SHAPED,
and parseFloat('0.10') is 0.1, which would sort 0.10 before 0.2 and hand a
newer bundle the retired field. Guarded by its own test.
spec §4 is updated in the same commit — a gate and the convention it enforces
must not disagree about which field they want.
Tests 98 -> 103 (okf-check 17 -> 22). All six suites green; check-versions
11 OK / 0 WARN / 0 ERROR.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0135YZBcCDvH3BgG5yEtuHCA
Same defect class as 9992235, found by auditing the remaining ten blocks:
the version label v0.12.1 was correct while the prose sat three minor
bumps behind. The block promised "3 skills" in its stat line and then
described exactly one of them.
`board` (v0.10.0) and `route` (v0.10.0) were invisible in the catalog --
the cross-repo attention board and the model/effort rubric that is now
the single copy of the operator's global routing policy. `reply-expected`
/ `--fyi` (v0.11.0) was missing too: the format can finally tell a
question from a notice, and absence means expected.
Two numbers were measured wrong, not estimated wrong:
3 CLI scripts -> 6 operational (board, coord-count, coord-done,
coord-inbox, coord-send, route) + 3 selftests
70 selftest checks -> 251, by running them:
coord 159, route 56, board 36
The other nine blocks were audited on the same two axes and are correct.
Every "Key commands" line was checked against real command files -- no
phantom commands anywhere, so the flag half of the graceful-handoff
defect does not repeat. Two prose claims I suspected held up on close
reading: voyage's annotation HTML view (README:24, 509+) and
claude-design's "enforced by test" -- that test says "collision", not
"overlap", so the first grep was too narrow, not the catalog wrong.
voyage's "500+ tests" stays UNMEASURED (76 test files, assertions not
run). Not asserted either way.
The stat line was fixed in 950c7a9, but it sat above four bullets that
still sold the architecture the plugin removed in v3.0 (BREAKING). The
catalog advertised a Stop hook at ~70% context, model-aware context
detection, a statusLine hint with SessionStart auto-load, and a
"handoff artifact" -- none of which exist. The version label v3.1.0 was
correct all along; only the prose was a major version behind.
The flags were wrong too: the catalog documented
`[topic-slug] [--no-push]`, neither of which the skill accepts. Measured
contract is `argument-hint: "[--no-commit] [--dry-run]"`.
Rewritten from the plugin's own README and SKILL.md: one user-initiated
skill (`disable-model-invocation: true`), overwrites the nearest
STATE.md with a mandatory NESTE block, remote-aware commit that stages
only STATE.md, push left to the operator.
The removal reason is worth stating rather than hiding -- a hook has no
session context, so it could only ever write a poor snapshot, and would
overwrite a good model-written STATE.md. That is a design argument for
the plugin, not an omission to paper over.
check-versions 11 OK / 0 WARN / 0 ERROR; tests 28 pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JoD3K9WDXSZNACArc7zTwn
The catalog invented its own counts and drifted from every plugin it
describes. Ten of eleven plugin READMEs publish their numbers as badges;
the plugin owns its count, so the catalog now mirrors it instead of
counting independently. File counts in agents/, commands/, skills/ and
entries in hooks/hooks.json agree with those badges everywhere both
exist, which is what makes the mirror trustworthy.
Voyage publishes no stat badges, so its numbers come from measurement:
all files in agents/ (24, including three self-declared reference
documents) and registered entries in hooks.json (7).
Corrections, measured 2026-07-31:
- llm-security 26 -> 23 scanners, 1863 -> 2013 tests
- config-audit 6 -> 7 agents, 13 -> 16 scanners, 18 -> 21 commands,
954+ -> 1410 tests
- voyage 23 -> 24 agents, 5 -> 7 hooks
- ms-ai-architect 25 -> 29 commands, 387 -> 389 docs
- linkedin-studio 19 -> 20 agents, 29 -> 30 commands
- okr 10 -> 14 commands, 4 -> 3 hooks (an over-claim)
- repo-mailbox 1 -> 3 skills
- graceful-handoff drops "3 hooks": the plugin removed hooks in v3.0
and its README says "No hooks" with a hooks-0 badge.
Tests 57 -> 30.
ai-psychosis, human-friendly-style and claude-design were already
correct. Test counts without a badge (voyage 500+, claude-design 5,
repo-mailbox 70) are left untouched: unmeasured, not verified.
No gate catches this class of drift -- check-versions compares versions,
not counts. check-versions 11 OK / 0 WARN / 0 ERROR; tests 28 pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JoD3K9WDXSZNACArc7zTwn
repo-mailbox v0.12.1 — release. Catalog ref now pins the v0.12.1 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
README.md:15 asserted two things that were measurably false as of
2026-07-31, both introduced in b4648e1 (2026-05-30):
- "Works with the Claude Code CLI, desktop app, and IDE extensions on
macOS, Linux, and Windows" — omits the web surface, and the desktop
app ships only for macOS and Windows (x64/ARM64), not Linux.
- "No external dependencies" — okr declares 4 runtime deps (mammoth,
postal-mime, turndown, unpdf).
Replaced with the requirement itself, which does not rot: install
happens via /plugin inside Claude Code, and the marketplace-add command
above registers the marketplace without installing anything.
No gate catches catalog prose — check-versions does not read README body
text. Verified by hand: check-versions 11 OK / 0 WARN / 0 ERROR,
28 pass / 0 fail.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012gHfoARehGggASpC29muRz
The voyage entry was 625 chars against a field where the second-longest is
linkedin-studio at 274 and the median is 163 (measured 2026-07-31, n=11).
Roughly half of it was annotation-HTML implementation detail — scripts/annotate.mjs,
"modelled on claude-code-100x", pencil-toggle mode, Fiks/Endre/Spørsmål, Copy Prompt.
That belongs in the plugin's own docs; README.md:66 already carries the one-sentence
catalog-level version of it. Kept: the six phases, agent swarms, external research
triangulation, the adversarial-vs-independent-review distinction, and multi-session
resumption — the parts that distinguish voyage from any other pipeline in the list.
No gate covers this: check-versions.mjs does not inspect description length, so a bad
rewrite would still go green. Three variants were measured (189/237/328) and the
operator picked 237.
Verification: JSON parses, 11 plugins intact; check-versions 11 OK / 0 WARN / 0 ERROR
(exit 0); check-versions + release-plugin tests 28 pass / 0 fail; diff is 1 line.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wsm9DJmoiL5g9M8JXjFTE1
okr v1.8.2 — release. Catalog ref now pins the v1.8.2 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Upstream (~/repos/_okf-upstream @ 3fcbb9f, okf/SPEC.md) is unambiguous: a bundle-root
index.md MAY carry okf_version in a FRONTMATTER block, "the only place frontmatter is
permitted in an index.md" (§8:509-510 + §12:773-775). Through 0.2 this convention said
the opposite — no frontmatter, marker in body text. The divergence was OURS against
upstream, so 0.3 removes it rather than documenting it. Operator ruling, 2026-07-31.
Measured before deciding (date pinned to every number):
- emitters: okr (body, okf-index.mjs:204) · linkedin-studio (body, scaffold.ts:38)
· commons (FRONTMATTER, examples/nav-golden-*/bundle/index.md)
- this repo already carried BOTH forms, both green: okf-parity-corpus (9, body) and
nav-golden-corpus (4, frontmatter, byte-exact from commons @ b641741). Invisible
because the marker regex was unanchored /m, i.e. placement-blind.
THE READER IS TRANSITIONAL BY DESIGN, NOT BY OMISSION. check-okf-parity.mjs:36-39 runs
okr's LIVE checker and compares conceptCount|untyped|okfVersion|okfVersionAccepted. A
frontmatter-only reader reports null here and 0.1 there, splitting the signature on all
9 body-text fixtures — a red gate produced by a doc change, with no bundle having become
less conformant. So both placements are read, one is canonical, and placement is
DECLARED, NOT ENFORCED — the same shape §3 presence has carried since 07-23.
QUOTING WAS UPSTREAM'S OWN FORM, NOT A CORNER CASE. §12:773 is the only place in the
upstream spec showing the key with a value, and it is quoted: okf_version: "0.2". The
0.2 gate ran the shape regex on the RAW string and failed upstream's canonical example.
Fixed by unquoting BEFORE the shape check. Implemented by reusing okf-frontmatter.mjs's
existing get(), which already unquoted (lines 22-26) — no new parsing code.
okf_layout STAYS IN BODY TEXT (§12). Upstream's exception is enumerated to one key, so
the block exists by upstream's leave and for upstream's key; our own extension marker
stays outside it. Asymmetric on purpose: it survives either construction of upstream's
parenthesis — a question okr has flagged as open and we do not own.
MEASURED CONSEQUENCE, REPORTED NOT HIDDEN: okr v1.8.2 fixed their PRODUCER, not their
checker (rootMarkers/pick returns the raw string). On a quoted fixture the two impls now
diverge on the VALUE — catalog 0.2 vs okr "0.2" — measured directly via evaluateBundle.
No existing gate is affected because the corpus carries no quoted fixture, which also
means the parity gate's green does NOT cover the quoting axis: "not run", not "as
expected". The shared unquote-before-compare decision has to reach okr's CHECKER too.
Verification: suite 90 -> 98/98 (8 new; written red first — 6 genuinely failed, 2 were
regression guards already correct). Parity 9/9, red-marker-layout still diverging per
its manifest. nav-golden 2/2. git status test/ clean: NO fixture migrated — the 9
body-text fixtures are now the coverage for the transitional path.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRhqgd8hws7SxT3mC4Lm4U
config-audit v5.13.0 — release. Catalog ref now pins the v5.13.0 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
repo-mailbox v0.12.0 — release. Catalog ref now pins the v0.12.0 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
repo-mailbox v0.11.0 — release. Catalog ref now pins the v0.11.0 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The catalog half of a shared gap that was previously PINNED rather than fixed.
This reader of ~/repos tested `.git` with a directory check, so a plain
`git worktree add ~/repos/feature-x` produced a depth-1 sibling that can carry
its own STATE.md and was dropped SILENTLY - no warning, no count,
indistinguishable from a repo with nothing to say. A submodule fails the same
way for the same reason.
It was pinned, not fixed, because diverging would break the very
same-name-from-both-readers invariant discoverRepos exists to hold. ~/repos
answered YES to the gated question and reported their half landed. Verified
here rather than taken on report: board.sh's Discovery block tests `-e`, and
has done since board.sh was introduced (repo-mailbox 61e224c, first released
v0.9.0) - so the released reader has no `-d` era at all, and only this side
was ever the outlier. The two move together from here - change one, change the
other.
THE ACCEPTANCE TRAP, MEASURED RATHER THAN ASSUMED. This changes NO number
against real ~/repos. Old and new builders were run back to back against the
live tree and diffed: stdout and stderr byte-identical, both exit 0. Directly
measured why: 0 directories at depth 1 or 2 currently carry .git as a file.
A number standing still is not ambiguous here, it is the ONLY possible outcome,
and it is why a fixture is not the best way to test this but the only way.
FIXTURE GATED BEFORE BEHAVIOUR. The worktree fixture uses a real `git worktree
add`, not a hand-written `.git` file - faking it would assert against our guess
at git's on-disk format instead of against git. A separate test asserts the
fixture itself: .git exists, is a file, is not a directory. Without it, the day
git stops writing worktree .git as a file the behaviour tests would go green
while measuring nothing, and a green run cannot distinguish that from success.
The gate says which one it was, and says the premise of the -e rule is gone
rather than inviting a test tweak.
Two behaviour tests: a worktree at depth 1, and one under a polyrepo container
at depth 2 - the same rule at both depths board.sh walks.
Suite 90/90 across the six files (rollup 31 -> 34). check-versions 11 OK,
0 WARN, 0 ERROR. Real run unchanged at 8 repos, 17 markers, Output B 0 lines,
1 V6 warning, exit 0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KSX2v1m7Fz22BKrGJZuUpQ
repo-mailbox v0.10.0 — release. Catalog ref now pins the v0.10.0 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
repo-mailbox v0.9.0 — release. Catalog ref now pins the v0.9.0 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
repo-mailbox v0.8.0 — release. Catalog ref now pins the v0.8.0 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
repo-mailbox v0.7.0 — release. Catalog ref now pins the v0.7.0 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
linkedin-studio v0.8.0 — release. Catalog ref now pins the v0.8.0 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
repo-mailbox v0.6.0 — release. Catalog ref now pins the v0.6.0 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two measured defects in build-rollup-register.mjs, reported by ~/repos and
independently re-measured here with the producer's own parser as instrument.
D1 - discovery saw only depth 1, so 5 markers across 3 marketplace repos were
invisible (11 STATE.md files live at depth 2). discoverRepos now mirrors
board.sh:63-89 EXACTLY: a dir that is itself a git repo contributes itself and
is NOT descended into; a non-repo dir holding git repos is a polyrepo container
contributing its children. Identity stays the RAW BASENAME (board.sh:100) so
this builder, board.sh and the coord mailboxes name a repo alike.
Not descending into a git repo is what makes the known nested-name trap
(claude-code-100x/claude-code-100x, both git repos) structurally unreachable
rather than merely absent - blanket depth-2, as proposed, would have reached it.
A collision gate still fails HIGH on two STATE-bearing dirs resolving to one
name, gated on CONTRIBUTING repos so a same-named dir without STATE.md cannot
stop the build. Measured today: 0 collisions across 25 state-bearing dirs.
D2 - parseMarkerLine returns null for two DIFFERENT facts ("not a marker" /
"a marker that failed to parse"), so a malformed marker vanished with exit 0.
V4/V5 only ever gated the carrier; nothing gated marker loss. New V6 reports a
line whose topic and KNOWN status token are both present but which does not
parse, naming file + line number. A warning, not a failure: a typo in another
repo's LOCAL state file must be visible, but is not this builder's business to
fail on. Unknown tokens stay "not a marker", keeping prose out of the channel.
A repo with only losses is still discovered - skipping it would re-open the
exact silent channel V6 closes.
Acceptance against real ~/repos: 15 markers (was 10, +5 exactly as predicted),
2 V6 warnings naming the two measured "--" lines, 0 collisions, exit 0.
Test fixtures are synthetic: marker prose is Output-A material (LOCAL-ONLY),
so quoting a real one into this public repo would be the same
durability-vs-publicity conflation the builder header warns about.
Suite 87/87 (was 78, +9). check-versions 11 OK / 0 WARN / 0 ERROR.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CPHvLhn2U3j2XD3Cn8zeYa
Two findings from the inbox, both re-verified against the other repo's code
rather than its summary.
§8 -- the "contradiction" we flagged was ours to misread. We had SKILL.md:94
(union) against CLAUDE.md:67 (precedence) and asked okr to adjudicate, assuming
SKILL.md because it describes actual procedure. Right, and right for the stated
reason. Verified @52129b5: SKILL.md:35-36 "always search both, project first",
:46-47 "overrides ... ON CONFLICT", :94-95 "Glob both roots". Union is the
search SPACE; precedence is a tie-break that fires only when the same content
sits in both roots -- orthogonal, which is why one file carries both without
contradicting itself. okr fixed CLAUDE.md:67 ("else" implied a lookup stopping
at the first root). §8 stays OPEN at the convention level; only its description
of okr is refined -- retrieval carries union AND precedence as two layers, not
one axis each.
The wiki -- llm-ingestion-okf reported, unprompted, that claude-code-llm-wiki
requires exactly the construction rule §3/§6 forbids. Re-read here @59ef033:
validate.py:74 puts BUNDLE_INDEX_COMPLETE at ERROR, :1097-1104 derives expected
from the directory and demands bidirectional match, bundle.py:498 generates
indexes machine-side. This is not our trap sprung -- it is its mirror image,
chosen: we forbid derivation because a derived index CANNOT DISAGREE with the
directory and so hides what is missing, while they make "cannot disagree" an
enforced invariant with a loud outcome. Our index is a curated selection that
must be able to disagree; theirs must not be. Neither is incoherent.
Consequence (theirs): authored-vs-derived cannot be a library invariant in
either direction; it becomes policy. And the sharpest argument came back at us
-- a field carrying only "per-directory: yes" would have hidden the difference
entirely. That is a better case for splitting scope from construction than the
one we gave them.
Suite 78/78. Inbox emptied: 4 in, 2 replies, 2 closed without reply.
The 2026-07-23 reservation said enforcement waits until "the emitters have
migrated". Measured rather than assumed, and the emitter set turned out to be
TWO, not three:
okr @0059da7 okf_version: 0.1 + okf_layout: kb-layout-2026-06. Migrated.
linkedin-studio scaffold.ts:38 -> okf_version: 0.1. Never carried a layout
string; has no okf_layout and needs none.
ms-ai-architect NOT an emitter. Zero index.md in the repo; okf_version
appears in one planning doc. The status table already said
"designed, not built" -- only the word "emitters" implied it.
Swept the whole marketplace plus the sibling consumer repos: every live
okf_version value is 0.1. The flip is a no-op today and locks the invariant.
The gate checks SHAPE (/^\d+(\.\d+)*$/), never membership: the upstream value
set is Google's (spec §12), so a bundle targeting a newer version passes. A
membership check would be the convention claiming a set it says it does not own
-- the over-reach class this round has corrected three times. Presence stays
unenforced (reported, not failed) as a separate §3 MUST.
Convention bumped 0.1 -> 0.2 by this log's own criterion: the set of conforming
bundles changed (the spec explicitly said a layout string "conforms today", and
rollout rule 6 defines conformance as gate output). The §12 per-plugin re-check
is pre-measured as finding zero violations.
Also closes a parity blind spot found while landing this: check-okf-parity
compared the okf_version VALUE, which is identical exactly when two impls
disagree about whether it is acceptable -- a false "agree" on the axis the gate
exists to watch. The signature now carries a boolean shape verdict, with
red-marker-layout as the committed red proof. Its "diverge" expectation encodes
okr's lag (they still pure-echo) and flips to "agree" when they mirror it.
And a correction the round earned: portfolio-optimiser enumerated their own
bundle surface and it is four, not three. The dormant fourth
(reference_domain.py:49 -> package data at :70) has no flag form at all, so our
published claim that the re-measurement surfaced "one" unreported entry was
itself one-of-two. Sharpens the standing rule: a search shaped like one entry
type cannot see another; install-vs-fixture is one instance, not the class.
Suite 73 -> 78. coord: PO replied, okr + llm-ingestion-okf notified (the latter
under the standing promise to flag any okf-check.mjs change).
repo-mailbox v0.5.0 — release. Catalog ref now pins the v0.5.0 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
commons reviewed the STEG 5 text at 3ccb5f6 against their own anchors.
Both questions we asked passed; the findings we did not ask about are
the ones that mattered. All four anchors re-verified here against their
files before acting — including their own mid-review correction, which
was right (the "never by directory enumeration" clause is
method-spec.md:82-83, not :70-73; :68-73 is the escape-not-depth rule).
3(b) — §3's "(directory enumeration)" was ambiguous against a rule that
forbids navigating by directory enumeration. Now "an authored
enumeration of that directory's children — never a filesystem read".
Fixed at BOTH sites: §3 and §6 (commons flagged one; the second was
found here). Their reason for flagging it hard holds: code written
against the wrong reading passes every test you would think to write.
3(a) — "This is exactly okr's okf-check.mjs semantics, generalized" read
as a restatement of upstream while being stricter than it. Upstream
binds index.md to the bundle root alone (method-spec.md:81-85); we bind
every level. That is a legitimate floor of our own under §8, but it must
not borrow upstream's authority. Now stated as a superset, with the
single point of difference named. This was also the catalog's own
longest-open proposed correction, independently confirmed.
Q2 — the precedence hole is now named OPEN in §8. The two shapes were
installed and not-installed; okr is a third, two marked roots at once,
and the marker predicate cannot say which is read. okr's answer is that
there is no single answer: precedence for the org profile
(inject-okr-context.mjs:54-56), union for retrieval
(okr-second-brain-search/SKILL.md:94), because the roots carry different
content. Free while placement is descriptive; the first question a
second implementer asks if marker-based discovery ever goes normative.
Q1 hygiene — "root" carries four specified meanings across this
ecosystem. §1's bare uses are now qualified, with the other three named
and anchored so a reader arriving from method-spec cannot misparse.
Nothing normative changed for consumers: placement stays unmandated, the
§3 floor is unchanged in substance, and no path form is mandated.
Verified: suite 73/73; check-versions 11 OK · 0 WARN · 0 ERROR. The
okf-check FAIL on docs/okf-second-brain is structural and pre-existing
(the spec directory is not itself a bundle) — confirmed identical at
HEAD before this change.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CPHvLhn2U3j2XD3Cn8zeYa
okr v1.8.1 — release. Catalog ref now pins the v1.8.1 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
p-o-claude re-measured their own source after our (b) finding and sent
back the root cause. It generalizes past them, including to us.
The counting error: their --bundle surface is four sites, not three
(run.py:554 default=None, run_s10.py:46 has a fixture default,
hitl.py:290 append/no default, contracts.py:81 required field).
Verified here against their tree, not their report.
The same blind spot in our own work: we greped both PO repos for the
installation-root signature (expanduser|Path.home|.claude/), got 0 hits,
and reported "no default". The grep was sound; the inference was wider
than it supported. Enumerating declarations instead surfaces one neither
side had reported — portfolio-optimiser's simulation.py:48
_default_bundle_dir() -> shared_root()/examples/bygg-energi-mikro, used
at simulation.py:293. Both PO repos carry a fixture-shaped default, not
just p-o-claude.
The headline is unchanged and survives contact: a fixture default aimed
at golden bytes creates no installation root and is not user-owned
second-brain state. Still one installation against three
non-installations; STEG 5 stays descriptive; §8 untouched. What changed
is the support — "caller-supplied with no default" was too strong, and
the accurate claim is the narrower one the grep actually proved: no
installation root anywhere in either src/.
Citations now pinned to commits rather than lines (PO 9e149c6, POC
bf50d2c) — portfolio-optimiser landed 8+ commits the same day and
already invalidated run.py:653, now run.py:679.
Verified: suite 73/73; check-versions 11 OK · 0 WARN · 0 ERROR.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CPHvLhn2U3j2XD3Cn8zeYa
The reference impl read the STEG 5 text and objected to one word: §1 said
okr "runs per-root over a project root … ahead of a home root". Verified
here against their code rather than their report, the objection holds —
that phrasing fused three distinct behaviours into one.
- profile axis is precedence (inject-okr-context.mjs:54-56 short-circuits
on the project hit)
- retrieval axis is union (okr-second-brain-search/SKILL.md:94 globs both
roots; they carry different content — project is cwd-bound cycle/work
data, home is org identity that survives reinstall)
- checking is neither (okf-check.mjs:11 runs each root independently)
So "ahead of" was true of exactly one axis and false as a statement about
the only implementation §1 describes.
Fixed by deletion, not elaboration: §1's job is that placement is not in
this contract, and that claim never needed an ordering. The axis detail
goes to log.md instead — naming one consumer's internal resolution order
in a scope section is the same class of leak the format exists to keep
out.
Placement remains unmandated (§8); nothing in the contract changed.
Verified: suite 73/73 across the six test files; check-versions 11 OK ·
0 WARN · 0 ERROR (okr released v1.8.0 mid-session and bumped the catalog
ref themselves in 8afd4f0).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CPHvLhn2U3j2XD3Cn8zeYa
repo-mailbox v0.4.0 — release. Catalog ref now pins the v0.4.0 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
okr v1.8.0 — release. Catalog ref now pins the v1.8.0 tag so `claude plugin update` resolves the release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The sample does not support a mandated path form. Of the four consumers
polled, exactly one installs a bundle anywhere (okr: project .claude/okr/
ahead of home ~/.claude/okr/org/); the other three install none — the
bundle dir is a caller-supplied argument per run, with no default, no
discovery, and no $HOME/~ expansion in their sources (verified by grep in
each repo, not taken from their reports).
One installation and three non-installations makes the standing criterion
("three installations before normative text") unmeetable from this
population, so no normative path form was written.
- spec.md §1: correct the in-scope example. A lone `~/.claude/<plugin>/…`
misstates okr's project-first precedence, i.e. it contradicts the only
real implementation — a fix that stands on its own regardless of n.
- spec.md §8: placement unmandated; "no installation root" named a
conforming consumer shape; installing vs. writing marked separate axes
(a consumer may write into a bundle it never placed).
- log.md: the measured sample with file:line evidence, plus two findings
the responses did not supply — neither portfolio-optimiser repo reads
okf_version at all (so neither is evidence for or against marker-based
discovery), and p-o-claude has a third --bundle entry point that does
carry a fixture default, contra its own account.
Confirms distilled note 3 ("discovery, not placement") rather than
extending it, and bears on Stage 2 (§10): three of four consumers have
nothing to discover.
Verified: suite 73/73 across the six test files; check-versions 10 OK ·
1 WARN · 0 ERROR (okr 1.8.0 untagged — their release is still in flight).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CPHvLhn2U3j2XD3Cn8zeYa
The plugin repo moved from open/coord to open/repo-mailbox. Bumps the
entry name, source URL and ref together, and updates the README heading,
link and label to match.
Also corrects the per-plugin stat line: it claimed 48 selftest checks;
the actual count has been 70 since v0.2.2.
check-versions.mjs: 11 plugins, 10 OK, 1 WARN (pre-existing okr), 0 ERROR.
§3's okf_version MUST now states the value is the upstream OKF version alone;
a plugin's own layout revision belongs in the optional okf_layout marker (§12).
Marked explicitly NOT YET ENFORCED — no checker validates the value's shape, so
an emitter still carrying a layout string conforms today.
No convention version bump: §12 ties a bump to a change in the §3 floor, and the
set of conforming bundles is unchanged (a clarification, deliberately inert).
Non-enforcing is the deliberate shape. okr ratified the split and owns the
migration, but their scripts/okf-* are file-fenced frozen through the 1.8.0
consolidation. Enforcing okf_layout presence now would redden the STEG 3 parity
gate on okr with nothing they could do until that ships. Enforcement is a
separate scoped step after their migration lands.
log.md records the round's other settled items, each verified against ground
truth rather than accepted as asserted: the roll-up carrier is a no-op for the
public-mirror class (builder tolerates absence by design); the catalog runs no
index.md generator (read-side only), so commons' inherited item is stale; the
okf_version ruling already existed in §12; and the catalog's okf-check.mjs is
NOT byte-identical to okr's (141 differing lines), so parity here is behavioural
over the §3 floor in default read-mode via check-okf-parity.mjs — never byte
identity.
Verified: suite 73/73, check-okf-parity 8/8 exit 0, check-versions 11 OK/0 WARN/
0 ERROR.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CPHvLhn2U3j2XD3Cn8zeYa