R90 hygiene + spec-drift — Step 3 packet
Step 3 of the 5-step chain. Per-file edit list with exact line/string targets. Implementation (Step 4) applies these edits literally.
§1. Edit budget
Three files touched, eight surgical edits total:
| # | File | Edit kind |
|---|---|---|
| E1 | CLAUDE.md |
§5 single-line replace (test count) |
| E2 | CLAUDE.md |
§9.1 two-row insert (consensus + reputation) |
| E3 | CLAUDE.md |
§9.2 three row updates + footnote |
| E4 | CLAUDE.md |
Footer append R90 changelog line |
| E5 | docs/3-world/physics/laws/consensus.md |
L40 single-line rephrase |
| E6 | docs/3-world/physics/laws/consensus.md |
Paragraph insert after L118 |
| E7 | docs/spec/s06-consensus.md |
Two-gate clarification paragraph |
| E8 | (verify-only) | §9.3 no edit; verified in audit |
Total: 7 edits to 3 files (E8 is a non-edit confirmation).
§2. Edit specifications
E1 — CLAUDE.md §5 test count (AC#5)
File: CLAUDE.md
Locator (old_string for Edit tool):
- Run `npm run build && npm run lint && npm test` before claiming completion. **All three are gates** — sub-agents have historically skipped `npm run lint` when the prompt only lists `build && test`; do not make that mistake. 1001 tests pass at `09d462f8`; a regression means investigate, not ignore.
new_string:
- Run `npm run build && npm run lint && npm test` before claiming completion. **All three are gates** — sub-agents have historically skipped `npm run lint` when the prompt only lists `build && test`; do not make that mistake. 3102 tests pass at `3ba5b5ac` across 69 suites (was 1001 at R75 Wave G `09d462f8`); a regression means investigate, not ignore.
E2 — CLAUDE.md §9.1 two new rows (AC#6)
File: CLAUDE.md
Strategy: insert the two new rows in alphabetic position. The current
table sequence near the bottom is:
| `src/domains/skills/` | ε Skill Registry | ... |
| `src/domains/trail/` | ζ Decision Trail | ... |
| `src/domains/proof/` | η Proof Store | ... |
| `src/domains/integrations/` | ν Integrations | ... |
| `src/__tests__/` | Jest test suite ... | ... |
Insert src/domains/consensus/ row immediately before src/domains/integrations/,
and insert src/domains/reputation/ row also before src/domains/integrations/
(alphabetic: c, i, p, r, s, t — so consensus + integrations + proof + reputation +
skills + trail; existing order is mostly thematic, not alphabetic, so the
cleanest insert point is between src/domains/proof/ and src/domains/integrations/ for
both new rows. Reputation comes after consensus alphabetically.
Locator (old_string for Edit tool):
| `src/domains/proof/` | η Proof Store | **Yes — η shipped (Wave E/F, P0.8.1–P0.8.3)**; directory name is `proof` (not `merkle`) |
| `src/domains/integrations/` | ν Integrations | **Yes — ν shipped (Wave F/G, P0.9.1–P0.9.3, library-only; no MCP tools registered)** |
new_string:
| `src/domains/proof/` | η Proof Store | **Yes — η shipped (Wave E/F, P0.8.1–P0.8.3)**; directory name is `proof` (not `merkle`) |
| `src/domains/consensus/` | θ Consensus | **Yes — θ shipped (R89 Phase B, P3.1.1–P3.9.1)**; 5 MCP tools register the consensus surface (`consensus_propose`, `consensus_vote`, `consensus_finality`, `consensus_gossip`, `vrf_eval`). BFT strategy: ADR-003 Option C (in-process spike). VRF strategy: ADR-002 Option A (HMAC-SHA256 stub). |
| `src/domains/reputation/` | λ Reputation | **Yes — λ shipped (R89 Phase A, P2.1.1–P2.5.1)**; 4 MCP tools register the reputation surface (`reputation_get`, `reputation_history`, `reputation_leaderboard`, `reputation_check_gates`). |
| `src/domains/integrations/` | ν Integrations | **Yes — ν shipped (Wave F/G, P0.9.1–P0.9.3, library-only; no MCP tools registered)** |
E3 — CLAUDE.md §9.2 row updates + footnote (AC#4)
Three row updates plus a row-state note for .venv-tools.
E3a — .agents/ row
Locator:
| `.agents/` | 243 | CANON (skills) + HERITAGE (spawns/swarms/archive) | Agent-ops corpus. 23 canonical `colibri-*` skills in `skills/`. Spawns/swarms/archive are session traces. | Edit `skills/` via 5-step chain. Spawns are read-only. |
new_string:
| `.agents/` | 251 | CANON (skills) + HERITAGE (spawns/swarms/archive) | Agent-ops corpus. 23 canonical `colibri-*` skills in `skills/`. Spawns/swarms/archive are session traces. | Edit `skills/` via 5-step chain. Spawns are read-only. |
E3b — docs/ row
Locator:
| `docs/` | 331 | CANON | Apex of the Colibri corpus. Organized by World Schema v3: `0-mutate/` through `5-time/` (runtime layers) + `spec/` (s01–s19 law library) + `architecture/decisions/` (ADRs) + `agents/` (contracts) + `reference/extractions/` (heritage archive) + `reference/` (glossary, cross-reference, design-system, mcp-tools-phase-0) + `guides/`. | Edit via 5-step chain. Mirror to Obsidian via `robocopy` excluding `.git _vault .worktrees node_modules temp vault-staging`. |
new_string:
| `docs/` | 630 | CANON | Apex of the Colibri corpus. Organized by World Schema v3: `0-mutate/` through `5-time/` (runtime layers) + `spec/` (s01–s19 law library) + `architecture/decisions/` (ADRs) + `agents/` (contracts) + `reference/extractions/` (heritage archive) + `reference/` (glossary, cross-reference, design-system, mcp-tools-phase-0) + `guides/`. Growth since R77.D (`331`) is driven by R85–R89 audit/contract/packet/verification chains (κ Phase 1 + λ Phase 2 + θ Phase 3). | Edit via 5-step chain. Mirror to Obsidian via `robocopy` excluding `.git _vault .worktrees node_modules temp vault-staging`. |
E3c — .venv-tools/ row
Locator:
| `.venv-tools/` | 0 | VENDOR | Python package residue. | Managed by `pip`. Exclude from doc counts. |
new_string:
| `.venv-tools/` | 0 | VENDOR | Python venv present on disk (`Include/`, `Lib/`, `Scripts/`, `pyvenv.cfg`); zero tracked `.md` files. Excluded from the spec count. | Managed by `pip`. Exclude from doc counts. |
E3d — Footnote pinning methodology
The §9.2 section already ends with the “Note on .planning/” paragraph
followed by §9.3. The cleanest place for the counting-methodology
footnote is after the existing “Note on .planning/” paragraph and
before §9.3.
Locator (single-anchor unique text):
**Note on `.planning/`:** Empty directory present at repo root. R74.2 set it to empty; the directory itself was not removed. Treat as SCRATCH and do not create files there. The full deletion is deferred to whatever round next touches repo housekeeping.
### 9.3. Root-level files (6, all CANON)
new_string:
**Note on `.planning/`:** Empty directory present at repo root. R74.2 set it to empty; the directory itself was not removed. Treat as SCRATCH and do not create files there. The full deletion is deferred to whatever round next touches repo housekeeping.
**Methodology footnote (R90 reconcile):** Counts in the table above are
`git ls-files <path> | grep -c '\.md$'` at SHA `3ba5b5ac` (R89 Phase B
seal). Untracked or generated `.md` files (session traces, `temp/`
scratch, build artifacts) are not counted — see §9.4 for the zone
semantics underlying that choice.
### 9.3. Root-level files (6, all CANON)
E4 — CLAUDE.md changelog footer R90 entry (AC#8)
Strategy: append a new italic paragraph to the existing changelog footer, immediately after the R89 Phase B entry.
Locator (anchor on the unique end of the R89 Phase B entry):
*Updated R89 Phase B — 2026-05-13 (R89 Phase B seal: θ Phase 3 graduation). θ Phase 3 shipped 13/13 sub-tasks across R89 Phase B (PRs #234–#246): P3.1.1 5 typed vote message shapes #234, P3.1.2 quorum + honest-majority intersection #237, P3.1.3 commit-reveal round-state FSM with view-change wiring #241, P3.2.1 5-level monotonic finality FSM #238, P3.3.1 IHAVE/IWANT gossip wire with triple-anchor validation #236, P3.3.2 per-round sized Bloom dedup #243, P3.3.3 adaptive fanout `[3,10]` #242, P3.4.1 STA broadcast + median + drift detection #235, P3.5.1 equivocation proof + idempotent λ slashing #240, P3.6.1 HMAC-SHA256 VRF stub (ADR-002 Option A) #239, P3.7.1 5 θ MCP tools growing the surface from 18 to 23 #244, P3.8.1 4-scenario multi-arbiter parity harness #246, P3.9.1 ForkHookRegistry + ι handoff stub #245. MCP surface 14 → 18 (R89 Phase A, λ tools) → 23 (R89 Phase B, θ tools added `consensus_propose`, `consensus_vote`, `consensus_finality`, `consensus_gossip`, `vrf_eval`). θ frontmatter graduated `colibri_code: none → partial` (`docs/3-world/physics/laws/consensus.md`); `docs/3-world/physics/laws/index.md` preamble and θ row updated in lockstep. CLAUDE.md §10 maturity claim updated 10/15 → 11/15 (added θ). BFT-layer strategy: ADR-003 Option C (minimal in-process spike, no libp2p, no external transport) — multi-node P2P remains a later-phase activation. VRF strategy: ADR-002 Option A (HMAC-SHA256 internal, not RFC 9381 EC-VRF). Both ADRs remain `PROPOSED`; ADR-acceptance is a separate future PR. R89 Phase A context: PR #233 graduated λ + κ §10 backfill + Phase 3 θ unblock. T0 autonomous Phase 2+3 mandate closes with this seal. No `src/` code touched — meta hygiene only.*
new_string (append a fresh R90 paragraph below the R89 Phase B entry):
*Updated R89 Phase B — 2026-05-13 (R89 Phase B seal: θ Phase 3 graduation). θ Phase 3 shipped 13/13 sub-tasks across R89 Phase B (PRs #234–#246): P3.1.1 5 typed vote message shapes #234, P3.1.2 quorum + honest-majority intersection #237, P3.1.3 commit-reveal round-state FSM with view-change wiring #241, P3.2.1 5-level monotonic finality FSM #238, P3.3.1 IHAVE/IWANT gossip wire with triple-anchor validation #236, P3.3.2 per-round sized Bloom dedup #243, P3.3.3 adaptive fanout `[3,10]` #242, P3.4.1 STA broadcast + median + drift detection #235, P3.5.1 equivocation proof + idempotent λ slashing #240, P3.6.1 HMAC-SHA256 VRF stub (ADR-002 Option A) #239, P3.7.1 5 θ MCP tools growing the surface from 18 to 23 #244, P3.8.1 4-scenario multi-arbiter parity harness #246, P3.9.1 ForkHookRegistry + ι handoff stub #245. MCP surface 14 → 18 (R89 Phase A, λ tools) → 23 (R89 Phase B, θ tools added `consensus_propose`, `consensus_vote`, `consensus_finality`, `consensus_gossip`, `vrf_eval`). θ frontmatter graduated `colibri_code: none → partial` (`docs/3-world/physics/laws/consensus.md`); `docs/3-world/physics/laws/index.md` preamble and θ row updated in lockstep. CLAUDE.md §10 maturity claim updated 10/15 → 11/15 (added θ). BFT-layer strategy: ADR-003 Option C (minimal in-process spike, no libp2p, no external transport) — multi-node P2P remains a later-phase activation. VRF strategy: ADR-002 Option A (HMAC-SHA256 internal, not RFC 9381 EC-VRF). Both ADRs remain `PROPOSED`; ADR-acceptance is a separate future PR. R89 Phase A context: PR #233 graduated λ + κ §10 backfill + Phase 3 θ unblock. T0 autonomous Phase 2+3 mandate closes with this seal. No `src/` code touched — meta hygiene only.*
*Updated R90 — 2026-05-13 (hygiene + spec-drift reconcile). Six docs-only items closed against base `3ba5b5ac`. (1) `consensus.md` L40 honest-majority invariant rephrased — the wrong `q + f = n + 1 - (n mod 3 == 0 ? 1 : 0)` (off-by-one when `n mod 3 != 0`) replaced with the symbolically correct `q + f = n` for all `n ≥ 1` (P3.1.2 verification §8 finding closed). (2) Two-gate clarification added to `consensus.md` §The five finality levels and mirrored in `s06-consensus.md` §Finality levels: `QUORUM → HARD` is consecutive-rounds + same-triple + no-equivocation gated; `HARD → ABSOLUTE` is dispute-window gated (100-epoch default). (3) §9.2 row counts reconciled: `.agents/` 243 → 251, `docs/` 331 → 630, `.venv-tools/` row note acknowledges the on-disk Python venv (still 0 tracked `.md`); methodology footnote pins counts to `3ba5b5ac` (R89 Phase B seal). (4) §5 test-count anchor dual-anchored: 3102 tests across 69 suites at `3ba5b5ac` (was 1001 at R75 Wave G `09d462f8`). (5) §9.1 gained `src/domains/consensus/` (θ, R89 Phase B) and `src/domains/reputation/` (λ, R89 Phase A) rows. (6) §9.3 verified unchanged (6 root files current). ADR-002/003 status untouched (remain `PROPOSED`); no `src/` code touched — meta hygiene only.*
E5 — consensus.md L40 honest-majority rephrase (AC#1)
File: docs/3-world/physics/laws/consensus.md
Locator:
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.
new_string:
The formula is `quorum = floor(2n/3) + 1`; the Byzantine ceiling is `f = floor((n-1)/3)`. Together, `q + f = n` for all `n ≥ 1`, i.e. the quorum and the maximum-faulty count partition the validator set — an honest-majority invariant any two quorums must intersect in.
E6 — consensus.md two-gate paragraph after L118 (AC#2)
File: docs/3-world/physics/laws/consensus.md
Strategy: insert a paragraph immediately after the table in
§The five finality levels. The table ends at L52 (| ABSOLUTE | Epoch-sealed: ... |),
followed by L53 empty and L54 (Downstream systems choose ...). The
ideal insert point is after the existing L54 prose paragraph so it
reads as a natural follow-up to the table-level commentary.
The unique anchor for the Edit tool is L54 itself:
Locator:
Downstream systems choose the level they require. A read of "current state" accepts `SOFT`. A cross-system integration that mutates external resources should wait for `QUORUM` at minimum and may require `HARD` for irreversible effects.
## What the arbiters vote on
new_string:
Downstream systems choose the level they require. A read of "current state" accepts `SOFT`. A cross-system integration that mutates external resources should wait for `QUORUM` at minimum and may require `HARD` for irreversible effects.
**Two-gate structure (R90 clarification).** `QUORUM → HARD` and `HARD → ABSOLUTE` are governed by **distinct** gates and should not be conflated. `QUORUM → HARD` fires on **two consecutive rounds at QUORUM with the same `(round_id, merkle_root, rule_version_hash)` triple and no observed equivocation between them** — this is what P3.2.1 ships in `src/domains/consensus/finality.ts` (AC#6 + AC#23 in `docs/verification/p3-2-1-finality-verification.md`). `HARD → ABSOLUTE` fires on a **dispute window measured in epochs**, with the Phase 0 default of `100n` epochs (also in P3.2.1; see `s06-consensus.md` § Finality levels for the spec form). The spec's prose "≥24h dispute window" maps onto whichever wall-clock duration 100 epochs covers under current scheduling — round-counted for the first gate, epoch-counted for the second.
## What the arbiters vote on
E7 — s06-consensus.md two-gate clarification paragraph (AC#3)
File: docs/spec/s06-consensus.md
Strategy: insert a clarification paragraph immediately after the
finality-levels table (before the **Rule**: no irreversible … line).
The table ends with the | ABSOLUTE | … row at L25; L26 is empty;
L27 is the **Rule**: … line. The cleanest insert is between L26
and L27 so the rule still serves as the table’s closing summary.
Locator:
| ABSOLUTE | HARD + no pending appeals | Irreversible effects |
**Rule**: no irreversible external side-effects before HARD finality.
new_string:
| ABSOLUTE | HARD + no pending appeals | Irreversible effects |
**Two-gate clarification (R90).** The dispute window phrased as "≥24h"
above applies at the `HARD → ABSOLUTE` transition. The
`QUORUM → HARD` transition is gated separately by **two consecutive
rounds reaching QUORUM on the same triple
`(round_id, merkle_root, rule_version_hash)` without observed
equivocation** — see the Phase 3 implementation in
`src/domains/consensus/finality.ts` and the long-form description at
`docs/3-world/physics/laws/consensus.md § The five finality levels`.
Both gates exist; one is round-counted (QUORUM→HARD), the other is
epoch-counted with a `100n` default (HARD→ABSOLUTE).
**Rule**: no irreversible external side-effects before HARD finality.
E8 — CLAUDE.md §9.3 (verify-only, no edit)
The 6 root files list matches ls *.md output at 3ba5b5ac. No edit
required. This is a verify-only item.
§3. Implementation order
Recommended Step 4 order (low-risk first):
- E5 — consensus.md L40 single line (smallest blast radius).
- E6 — consensus.md paragraph insert.
- E7 — s06-consensus.md paragraph insert.
- E1 — CLAUDE.md §5 single line.
- E2 — CLAUDE.md §9.1 two-row insert.
- E3a, E3b, E3c — CLAUDE.md §9.2 row updates.
- E3d — CLAUDE.md §9.2 methodology footnote.
- E4 — CLAUDE.md footer R90 changelog line.
After E8 (verify): npm run build && npm run lint && npm test.
§4. Risk register
- Test count drift — if it moves from 3102, source code was inadvertently touched. Step 5 verification must pin this exactly.
- Edit-tool old_string uniqueness — each locator above is verified
unique by its full sentence form; no
replace_allis needed. - R89 Phase B footer not first line at end of file — confirmed during audit that the R89 Phase B entry is the trailing changelog line, making E4’s append safe.
§5. Packet conclusion
Eight surgical edits across three files; nine acceptance criteria; zero source-code change. Step 4 applies the edits literally as specified above.