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:
consensus.mdL40 — honest-majority off-by-one (P3.1.2 finding, left documented but unfixed)- s06 +
consensus.mdL118 — 24h dispute window vs. consecutive-rounds appears contradictory; actually two-gate (different transitions) - CLAUDE.md §9.2 —
docs//.agents//.venv-tools/row counts stale vs. post-R89 reality - CLAUDE.md §5 — test count anchor “1001 at
09d462f8” predates R87 κ close and R89 λ + θ closes - CLAUDE.md §9.1 — verify
src/domains/consensus/andsrc/domains/reputation/rows exist or add them - 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 → HARDuses consecutive-rounds without conflicting votes (this is what shipped in P3.2.1; AC#6 + AC#23 prove it).HARD → ABSOLUTEuses a dispute window (P3.2.1 ships this as a 100-epochdispute_window_epochsdefault — see AC#9, AC#10, AC#11 inp3-2-1-finality-verification.md, and the constructor atsrc/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 to251(correct number). - Bump
docs/row to630(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.mdcount is0. - 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
3ba5b5acacross 69 suites (was 1001 at R75 Wave G09d462f8); 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.mdcontent 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 test— 3102 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.