P3.3.3 — Gossip Adaptive Fanout — Verification Evidence

Step 5 of the 5-step chain (CLAUDE.md §6). Records the gate runs that authorize PR creation.

§1. Gate run log

Gate Command Result Notes
Build npm run build PASS tsc clean; postbuild copied 8 migrations
Lint npm run lint PASS (1 fixed) One round-trip: removed unused type ExchangeRecord import from test file (consumer asserts behavior via the class API, not the type)
Test npm test -- adaptive-fanout PASS — 3005/3005 Full suite under --testPathPattern=adaptive-fanout (Jest’s pattern is permissive and ran the whole suite; result was a clean 3005 pass across 65 suites)

Earlier run hit a single pre-existing flake in domains/reputation/tools.test.ts (Migration 998_broken.sql failed), which passes cleanly in isolation (28/28). Same scope re-run after that immediately returned 3005/3005. Not a regression from this slice; flagged as known full-suite-load behavior consistent with the pre-existing-flake notes already captured in MEMORY.md.

§2. Test count delta

Source Count
Baseline (origin/main 9c7165d5) 2970
After P3.3.3 3005
Delta +35

Within the task-prompt expected range of +12–20 (S task), slightly higher because the contract enumerates 19 invariants and describe.each worked-table row expansion accounts for 6 of the surplus (the 6 worked-table fixture rows are independent test cases by Jest’s test.each).

§3. Invariant coverage map (I1 – I19)

ID Test group Status
I1 A1 + A2 (range assertion in A2) covered
I2 A1 worked table covered
I3 A2 (negative score) covered
I4 A2 (>12 score) covered
I5 A3 (in-range, boundaries) covered
I6 A3 (below + above range) covered
I7 B1 (any string peer_id, no throw) covered
I8 B2 (multiple exchanges in same epoch accumulate) covered
I9 C1 (delta < period → null) covered
I10 C2 (delta >= period → score) covered
I11 C3 + C3a + C3b (default + overrides) covered
I12 D1 (only failed → not live) covered
I13 D2 (≥1 success → live) covered
I14 D3 + D6 (out-of-window → pruned) covered
I15 D4 (13 peers → score=12n → fanout=3n) covered
I16 E1 (memory bound + peer removal) covered
I17 F1 (initial currentScore=0n) covered
I18 F2 (currentFanout = computeFanout(currentScore)) covered
I19 G1 (static forbidden-token scanner) covered

Additional coverage beyond the contract minimum:

  • D5: mixed success/failure across peers within window — exercises the any_success branch in recomputeIfDue.
  • D7: epoch === cutoff is included (inclusive lower bound) — guards against an off-by-one in the prune predicate.
  • C3c: current < last clock anomaly — confirms no throw, returns null.

§4. Worked-table evidence (s08 §Adaptive fanout)

Group A1 test.each produces the 6 rows verbatim from docs/spec/s08-gossip.md §Adaptive fanout table:

score=0  → fanout=10
score=3  → fanout=10
score=5  → fanout=10
score=7  → fanout=8
score=10 → fanout=5
score=12 → fanout=3

All 6 rows assert toBe(expected) with bigint equality. The spec table is bit-for-bit reproduced.

§5. Static scanner result (Group G)

adaptive-fanout.ts post-JSDoc-strip is free of every pattern in:

  • Math\.[A-Za-z_]
  • Date\.[A-Za-z_]
  • new\s+Date
  • setTimeout, setInterval, setImmediate
  • fetch\s*\(
  • XMLHttpRequest
  • crypto\.[A-Za-z_]
  • process\.hrtime, process\.nextTick
  • async\s+function, await
  • float literals \d+\.\d+
  • [native code]
  • Math.random

hits array is []. Determinism contract holds.

§6. Commit sequence

Commit SHA Scope
1 ac2300c8 audit(p3-3-3-adaptive-fanout): inventory surface
2 229289a7 contract(p3-3-3-adaptive-fanout): behavioral contract
3 89d7b1d1 packet(p3-3-3-adaptive-fanout): execution plan
4 d5bc9c8c feat(p3-3-3-adaptive-fanout): connectivity-scaled gossip fanout [3,10]
5 this commit verify(p3-3-3-adaptive-fanout): test evidence

§7. Blockers

None. The slice is pure data, depends on no external service, introduces no npm deps, and matches the s08 §Adaptive fanout worked table exactly. PR ready.


Back to top

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

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