R90 hygiene + spec-drift — Step 1 audit

Step 1 of the 5-step chain. Inventories the six docs-only reconcile items the round closes. No source code is in scope; nothing under src/ is touched.

§1. Scope

Six items, all documentation drift carried forward from prior rounds:

  1. consensus.md L40 — honest-majority off-by-one (P3.1.2 finding, left documented but unfixed)
  2. s06 + consensus.md L118 — 24h dispute window vs. consecutive-rounds appears contradictory; actually two-gate (different transitions)
  3. CLAUDE.md §9.2 — docs/ / .agents/ / .venv-tools/ row counts stale vs. post-R89 reality
  4. CLAUDE.md §5 — test count anchor “1001 at 09d462f8” predates R87 κ close and R89 λ + θ closes
  5. CLAUDE.md §9.1 — verify src/domains/consensus/ and src/domains/reputation/ rows exist or add them
  6. CLAUDE.md §9.3 — verify the 6 root files list is current

§2. Base + canonical SHA

  • Branch base: 3ba5b5ac (post-R89 Phase B seal — θ graduation)
  • Counts pinned at: 3ba5b5ac
  • Worktree: .worktrees/claude/r90-hygiene-spec-drift
  • Branch: feature/r90-hygiene-spec-drift

§3. Per-item current state

Item 1 — consensus.md line 40 honest-majority

File: docs/3-world/physics/laws/consensus.md Current state at line 40 (byte-for-byte):

The formula is `quorum = floor(2n/3) + 1`; the Byzantine ceiling is `f = floor((n-1)/3)`. For any `n`, `quorum + f = n + 1 - (n mod 3 == 0 ? 1 : 0)` — an honest-majority invariant any two quorums must intersect in.

Issue: the printed formula quorum + f = n + 1 - (n mod 3 == 0 ? 1 : 0) is symbolically incorrect for n mod 3 != 0. Direct derivation against the L25–27 formula of record (quorum = floor(2n/3) + 1, f = floor((n-1)/3)):

Case quorum f quorum + f L40 prediction Match?
n = 3k 2k+1 k-1 3k = n n + 1 - 1 = n yes
n = 3k+1 2k+1 k 3k+1 = n n + 1 - 0 = n + 1 NO
n = 3k+2 2k+2 k 3k+2 = n n + 1 - 0 = n + 1 NO

The actual identity is q + f = n for all n ≥ 1. P3.1.2 verification (docs/verification/p3-1-2-quorum-verification.md §8) documented this finding and pinned the calculated truth, deferring the spec-doc reconcile to a future hygiene round — i.e. R90.

L25–27 (the formula of record) is correct and is not edited by R90.

Resolution path (b per prompt): rephrase L40 to the actual identity, keep the helpful prose (“an honest-majority invariant any two quorums must intersect in”), drop the wrong (n mod 3) expression.

Item 2 — s06 24h dispute window vs. consensus.md L118 consecutive-rounds

File A: docs/3-world/physics/laws/consensus.md lines 116–118. Current state at L118:

**Next round:** if round 43 also reaches QUORUM without a conflicting reveal, round 42 transitions `QUORUM → HARD`. Epoch sealing later promotes it to `ABSOLUTE`.

This describes the QUORUM → HARD gate as “consecutive rounds without conflicting votes” — which is what P3.2.1 ships in src/domains/consensus/finality.ts (verified at AC#6 and AC#23 in docs/verification/p3-2-1-finality-verification.md).

File B: docs/spec/s06-consensus.md §Finality levels, table rows for HARD + ABSOLUTE (lines 23–25):

| QUORUM | `votes ≥ threshold` | None (dispute window active) |
| HARD | Quorum held for full dispute window (≥24h) | Yes |
| ABSOLUTE | HARD + no pending appeals | Irreversible effects |

This describes a wall-clock 24h dispute window for QUORUM → HARD.

Issue: read alone, the two phrasings appear to conflict. They do not conflict in shipped code — they describe two different transitions:

  • QUORUM → HARD uses consecutive-rounds without conflicting votes (this is what shipped in P3.2.1; AC#6 + AC#23 prove it).
  • HARD → ABSOLUTE uses a dispute window (P3.2.1 ships this as a 100-epoch dispute_window_epochs default — see AC#9, AC#10, AC#11 in p3-2-1-finality-verification.md, and the constructor at src/domains/consensus/finality.ts).

Both gates exist; the s06 row is collapsing them into a single sentence. The phrasing “≥24h” in s06 should reference the HARD→ABSOLUTE gate (with note that the shipped default is epoch-counted, not wall-clock); the consecutive-rounds prose belongs at QUORUM→HARD.

Resolution path: add a paragraph to consensus.md § The five finality levels making the two-gate structure explicit, and add a mirroring note to s06-consensus.md § Finality levels (or just before the table).

Item 3 — CLAUDE.md §9.2 doc count drift

Current row values at 3ba5b5ac:

Row Currently claims Actual at 3ba5b5ac
.agents/ 243 251
docs/ 331 630
.venv-tools/ 0 and “absent” 0 tracked .md; directory exists on disk (Include/Lib/Scripts/pyvenv.cfg — a Python venv, no .md)

Method: git ls-files <path> | grep -c '\.md$' at 3ba5b5ac.

Resolution path:

  • Bump .agents/ row to 251 (correct number).
  • Bump docs/ row to 630 (correct number; matches the R89-close tree).
  • Update .venv-tools/ row methodology cell to acknowledge the dir exists on disk as a Python venv while the tracked .md count is 0.
  • Add a footnote pinning the SHA used for re-counting (3ba5b5ac).

Item 4 — CLAUDE.md §5 test count anchor

Current state at §5:

1001 tests pass at `09d462f8`; a regression means investigate, not ignore.

09d462f8 is R75 Wave G — historical. Post-R89 Phase B close (2026-05-13, 3ba5b5ac), the suite is materially larger.

Authoritative number at 3ba5b5ac: per p3-2-1-finality-verification.md §1 + downstream PRs, the count after the final R89 Phase B PR (#246) is 3102 tests across 69 suites (this is the prompt-asserted counter; R90 verifies it in Step 5 with a re-run).

Resolution path: dual-anchor format per prompt — keep R75 Wave G as historical context, add R89-close current. Format:

“3102 tests pass at 3ba5b5ac across 69 suites (was 1001 at R75 Wave G 09d462f8); a regression means investigate, not ignore.”

Item 5 — CLAUDE.md §9.1 directory rows

Current rows in §9.1 table:

Path Present in table?
src/server.ts yes
src/db/schema.sql yes
src/db/index.ts yes
src/middleware/ yes (inlined note)
src/domains/tasks/ yes
src/domains/router/ yes (Wave I row)
src/domains/skills/ yes
src/domains/trail/ yes
src/domains/proof/ yes
src/domains/integrations/ yes
src/__tests__/ yes
data/colibri.db yes
src/domains/consensus/ NO — missing, added in R89 Phase B (#234–#246)
src/domains/reputation/ NO — missing, added in R89 Phase A (#226–#232)
src/domains/rules/ NO — missing, added in R85–R87 (κ Phase 1, #205–#220)

Confirmation that the directories exist:

$ git ls-files src/domains/consensus/ | head -3
src/domains/consensus/...
$ git ls-files src/domains/reputation/ | head -3
src/domains/reputation/...
$ git ls-files src/domains/rules/ | head -3
src/domains/rules/...

(verified during audit; all three are present at 3ba5b5ac)

Resolution path: the prompt explicitly mentions adding src/domains/consensus/ (R89 P3) and src/domains/reputation/ (R89 P2). The κ src/domains/rules/ directory (R87) was also added to the codebase but the prompt does not authorize touching it (“Don’t add unrelated rows”). κ is referenced in §10 maturity prose but no §9.1 row. R90 adds the two prompt-authorized rows (θ + λ) and intentionally does not add a κ row (κ is left as a future hygiene follow-up if T0 wants symmetry — out of R90 scope).

Item 6 — CLAUDE.md §9.3 root files

Currently in §9.3: AGENTS.md · CLAUDE.md · CODE_OF_CONDUCT.md · CONTRIBUTING.md · README.md · SECURITY.md (6 files).

Actual at 3ba5b5ac (ls *.md):

AGENTS.md
CLAUDE.md
CODE_OF_CONDUCT.md
CONTRIBUTING.md
README.md
SECURITY.md

Six files, exact match. §9.3 is current. No edit required.

§4. Out of scope (explicit non-goals)

The prompt names these as out of scope; the audit confirms they are not touched by R90:

  • ADR-002 / ADR-003 status (both remain PROPOSED; future ADR- acceptance PRs).
  • Any src/ source code change.
  • Any rewrite of consensus.md content beyond Items 1 + 2.
  • ι Phase 5 work.
  • Memory file updates (PM session memory, not Colibri repo).
  • κ row addition to §9.1 (only θ + λ are prompt-authorized).
  • .venv-tools/ directory deletion (kept; only the §9.2 row is updated).
  • Any frontmatter changes for ι / μ / ξ / π concept docs.

§5. Files in scope for edits (Step 4)

  • docs/3-world/physics/laws/consensus.md — Items 1 + 2 (L40 rephrase
    • finality-levels-section paragraph addition)
  • docs/spec/s06-consensus.md — Item 2 (mirror two-gate note)
  • CLAUDE.md — Items 3 + 4 + 5 (§9.2 + §5 + §9.1)

No other files are touched.

§6. Gates that must hold at Step 5

  • npm run build — green (TS compile)
  • npm run lint — green (ESLint)
  • npm test3102 tests passing across 69 suites (regression guard; docs-only edits MUST NOT move the test count)

The test count is the most material gate — any drift from 3102 would mean source code was inadvertently touched. R90 is meta-only.

§7. Audit conclusion

Six items, all real, all docs-only, all under the prompt scope. Five files in total receive edits (per §5). No structural changes, no source-code changes, no ADR status changes. Step 2 contract will formalize the per-item acceptance criteria.


Back to top

Colibri — documentation-first MCP runtime. Apache 2.0 + Commons Clause.

This site uses Just the Docs, a documentation theme for Jekyll.