§7 lead "In progress · Phase 1a landed 2026-05-08" was stale —
file header (current) says "Phase 1a (ForkScore) landed
2026-05-08; Phase 1b (consensus paper) landed 2026-05-10; Phase
1c (branch-set persistence) remains proposed-not-opened."
Refresh to match file header so the index claim and the body
section are saying the same thing.
§7 Phase 1a body referenced "tests/test_v8_fork_score.py — 25
cases" on two counts of drift:
1. **Filename stale**: file was renamed to
`tests/test_substrate_fork_score.py` in `a4058a4` 2026-05-10
under the v-prefix-retirement convention (substrate-paper
version vs schema-version disambiguation). The original path
no longer resolves.
2. **Count + scope conflated**: 25 cases at the time, but the
surface has since split into two test files:
- `tests/test_fork_score.py` (18 tests) pins the pure
ScoredFork dataclass + scoring contract.
- `tests/test_substrate_fork_score.py` (27 tests) pins the
`arborist substrate score` CLI surface.
Refresh: name both files explicitly + AUTOCOUNT-tag each count
so future drift fires (#000044 discipline). Note the rename
provenance for future readers walking the design log.
Six in-progress tickets audited for §-status drift in today's
sweep wave:
#000034 §7 lead stale (now refreshed in 952abc5)
#000035 §7 lead clean
#000036 §7 + closure stale (refreshed in 952abc5)
#000037 §20 + §17.1 stale (refreshed in 3b30126 + 952abc5)
#000025 §11 lead stale (refreshed in 3b30126)
#000012 §7 lead stale (THIS COMMIT)
5 of 6 had body-section drift. Pattern is consistent: file
header is the load-bearing surface fox updates; body sections
are point-in-time prose snapshots that freeze at landing time.
Sweep-on-amend is the right discipline; this commit closes the
last in-progress ticket §-status drift surface for today.
#000006 (rolling research log) and #000044 (closed today,
retroactive design log) excluded from sweep — different shapes.
Closed tickets prior to today excluded entirely per #000044 §5
discipline ("closed-ticket point-in-time snapshots stay
UNtagged / refreshing them changes archival meaning").
Verification:
$ pytest tests/test_doc_counts.py
3 passed in 2.48s
Tags by metric after this commit: 48 tests + 6 fixture-rows +
3 db-rows + 3 db-where = 60 active claims (was 58; +2 from this
commit's two new tests-metric tags on fork_score test files).
Two parallel landings in one commit:
== §-status sweep on in-progress tickets ==
Checked #000034 / #000035 / #000036 §7 Status sections against
their file-header status. Same pattern as earlier sweep on
#000037 / #000025 / #000006 — body-section prose freezes at
earlier snapshots while file headers stay current. 2 of 3 had
drift.
**#000034 §7** lead: was "Open · awaiting go/no-go" + "Phase 1a
proposed below" + body subsection "Phase 1a (landed 2026-05-10)".
The lead line was a 2-versions-old prose snapshot contradicting
the same section's own subsection. Refresh: "In progress · Phase
1a landed 2026-05-10 (commit 1dfb8b9; test backfill a4b3056).
Phase 1b parks until v7 reference checkpoint..."
**#000035 §7**: already says "In progress · Phase 1 landed
2026-05-10". No drift; sample-confirmed clean.
**#000036 §7** lead: was "Awaits fox + cryptographer review of
constants." Refresh to current state — "pre-review polish pass
in 8916bf3; math review in flight with dav1d (forwarded
2026-05-10 Asia/Kuala_Lumpur as Tier 2 bundle: t3-bound.md +
soft-hash-analysis.md + t3_bound_calculator.py +
test_t3_bound_calculator.py + this ticket). Empirical tightening
tracked separately under #000043." Matches file header verbatim.
**#000036 closure criterion (c)** was marked "[pending —
docs-only commit]" but soft-hash-channel-analysis.md §9.3 line
475 already reads:
"§9.3 closed 2026-05-10 via the T3 per-window bound at
docs/soft-hash-channel-t3-bound.md (under #000036)"
So criterion (c) is done. Refresh: "[done — §9.3 closure landed
in line 475 of that doc]". Also clarify criterion (d) gates on
the dav1d review verdict (was ambiguous as just "explicitly
accepted by fox").
== #000037 §20 — reference #000045 follow-on ==
fox opened #000045 (Prometheus-Σ Phase 3 sleep-sweep scaffold)
in commit 0379e4c. My §20 refresh from 3b30126 said "Phase 3
gates on a renewed §12 trigger plus a Phase 3 ticket" — now
that Phase 3 ticket is named: #000045. Refresh to point at it
explicitly so future readers don't have to grep TICKETS.md to
find the follow-on.
== CLAUDE.md — AUTOCOUNT discipline rule ==
Added a paragraph to "Operational rules" pointing future
blackops shifts at the AUTOCOUNT discipline (#000044 + the
harness at tests/test_doc_counts.py). Without this, the harness
is discoverable only by accidentally hitting a test failure or
reading commit messages. With it, "tag at write time" is a
documented operational rule alongside Python-only, PYTHONUNBUFFERED,
and fail-closed.
Rule names: format, 4 metrics (tests / fixture-rows / db-rows /
db-where), code-fence-skip behavior, closed-ticket-stay-untagged
discipline, pointer to #000044 + the harness module.
== Verification ==
$ pytest tests/test_doc_counts.py
3 passed in 2.80s
No drift introduced. fox's parallel 4 commits (4b85a0a /
43380b1 / 1f882df / 0379e4c) landed independently; my
modifications stack on top cleanly. fox's commits added 155 +
89 lines to test_prometheus.py + test_prometheus_audit.py but
collected counts stayed at 42 + 17 — those landings modified
existing tests (parametrize additions / refactors), didn't add
new test functions. AUTOCOUNT claims from 3b30126 still match.
Phase 3 of #000037 (the actual sleep-sweep scheduler that runs the
Phase 1 controller on a cadence over real shards) gates on a
measured retrigger, not a calendar date. This ticket is the gate.
§2 commits 8 governance parameters that fold into governance_policy_hash
when Phase 3 lands: chunk_size (Hermes concurrency), per-mode τ_qa
seconds (CP/LLM split from Finding 3), weight profile (default
"sweep" from Phase 1.c), active sweep targets, per-window budget
cap, scheduling cadence, quarantined-row policy.
§3 names 4 retrigger gates: ≥1000 advisory rows from Phase 2 wiring
showing reproducible REJECT/DEFERRED structure (Retrigger 1); three
consecutive weekly dry-runs with sustained ACCEPT/MARGINAL on Target
A (Retrigger 2); 5F-fixture funnel demand from #000025 plateauing
on Target A's stream and needing Target B's larger candidate pool
(Retrigger 3); operator mission need (Retrigger 4, mirrors #000037
§12 Trigger 4).
§4 explicitly excludes implementation, schema migration,
governance_policy_hash bump, dry-run sweep_weights swap, and
Hermes-call planner — all deferred to the implementation ticket
that this ticket gates.
Includes TICKETS.md index row + Next ID bump 000045 → 000046.
Per Finding 3, a uniform τ_qa=7d filtered out every recent
CANONICAL_PROJECTION row (the π* graduations from #000027/#000030/
#000032 are all younger than 7d), so the sweep saw zero high-value
kernel-only work. Splitting τ_qa by audit_mode lets the cheap kernel
re-probe path (CP) run on a short cycle while the expensive LLM
re-witness path (STRICT/HYBRID/UNGROUNDED) keeps the long cycle.
bench/scripts/prometheus_sigma_sweep_dryrun.py: new build_tau_by_mode()
helper + per-mode CASE in iter_target_a_candidates; sweep_target_a now
takes the dict instead of a single seconds value. New CLI flag
--tau-qa-cp-days (default 1d); --tau-qa-days now scopes to LLM-witness
modes only (default 7d). Report renders the per-mode τ table in the
header and marks Findings 2 and 3 RESOLVED with their landing commits.
Makefile: PROMETHEUS_SWEEP_TAU_DAYS bumped to 7 (was 1, the prior
Finding-3 workaround); new PROMETHEUS_SWEEP_TAU_CP_DAYS=1 makevar.
bench/results/prometheus-sigma-sweep-dryrun-2026-05-10.md: regenerated
under the new defaults — 9 CP rows surface alongside 1,904 LLM-
witness candidates → 1,913 total Target A candidates → 1 ACCEPT,
2 MARGINAL, 205 REJECT, 271 DEFERRED chunks; 2 cache_drift vetoes
preserved end-to-end.
docs/tickets/ticket-000037 §22: Findings 2 + 3 marked RESOLVED with
landing-commit references; total dry-run cost line updated to the
new measurements (37.6 ms / 3,913 branches / 9.6 µs per branch).
arborist.qa.runner.ask() now emits one controller_decision +
controller_difficulty + controller_budget_allocation triple per QA
cycle via _emit_qa_controller_advisory(conn, cache_key, verdict).
Single-branch synthesis from the verdict's audit_mode (Δ5F mapping
matching the dry-run simulator) and n_unverified/n_quotes
(witness_divergence). Wrapped in try/except so any advisory failure
never blocks the QA result; pure audit-only — does not enter
audit_events.event_hash preimage, audit chain semantics unchanged.
Lazy import keeps the QA hot path free of substrate-module load on
calls that never reach this helper (cache hits + early returns).
Tests: 3 new in tests/test_prometheus_audit.py — happy-path emits
all three event kinds, defensive parsing tolerates malformed verdict
without raising, second call with same (event_kind, body_hash) is
idempotent under the existing UNIQUE constraint.
Per §22 Finding 2: flat capital_cost=1.0 made every utility negative
in the dry-run sim. Split capital_cost into kernel_cost (~0.05 kernel
re-probe) + llm_cost (~1.0 LLM witness fan-out); ControllerBranch
now exposes effective_cost = kernel_cost + llm_cost when either is
positive, falling back to legacy capital_cost when both are zero.
Pre-1.c callers don't migrate. _utility() reads effective_cost so
split-cost and legacy-cost branches with the same total cost produce
byte-identical utility values.
Per §22 Finding 3 (partial): add sweep_weights() profile —
gamma_5f=1.5, lambda_capital_cost=0.25, nu_witness_divergence=0.5.
Sweep work willingly pays capital for falsification discovery and
treats high witness divergence as desirable signal (§13 step 11).
Registered in WEIGHT_PROFILES["sweep"]; folds into governance_policy
selection alongside safe / conservative / exploratory.
Tests: 6 new in tests/test_prometheus.py — effective_cost split path,
legacy fallback, _utility byte-identity across the two cost shapes,
kernel-only vs LLM-only ranking, sweep-vs-safe divergence on a
marginal branch (DEFERRED under safe, ACCEPT under sweep), and
WEIGHT_PROFILES registry now pins all four profiles.
Lock the AUTOCOUNT regression-test pattern as the design log
canonical record. Previously declined when surface was 1-metric
+ 29 tags; now mature enough (4 metrics + 58 tags + 1 same-day
drift-catch since landing) to formalize.
== Ticket content ==
10 sections covering:
1. Why this exists — the 4-drift-day baseline (6cbbf95 / 14bcb99 /
5c21e83 / 30a9488) that motivated mechanization. Five-step
walk through justifying each choice (Step 5 last).
2. Format — `<!--AUTOCOUNT:metric:path-->N<!--/AUTOCOUNT-->`.
3. Four supported metrics with examples + skip semantics:
`tests`, `fixture-rows`, `db-rows`, `db-where`.
4. Skip-on-absence — operator state (shards, qa.db) absence is a
logged skip, not a fail. Smoke verified 2026-05-10 with
HOME=/tmp/empty.
5. What NOT to tag — closed-ticket point-in-time snapshots,
aggregate floors ("2000+"), historical journey arcs.
6. Install discipline at write time + at refresh time.
7. Future metrics deferred (file-lines, gh-pr-comments-count,
module-loc, commit-hash-exists) with the "add a metric"
recipe.
8. Empirical baseline at landing (3 test functions, 58 active
tagged claims across 8 doc files, harness runtime 2-4s).
9. Scope boundaries — does NOT auto-rewrite, does NOT validate
prose quality, does NOT scan docstrings, does NOT lock
values, does NOT add deps.
10. References — every landing commit + sister doc.
Closed at landing (status quo since fc5ba50 2026-05-10 morning;
this ticket is retroactive design log per the convention "every
ticket flips to `closed · landed in commit <sha>` when the work
ships").
== Code-fence parser fix ==
Adding the ticket itself surfaced an oversight: my AUTOCOUNT
examples in §3.3 + §3.4 used literal tag pairs in ``` fenced
code blocks. The parser was reading them as live claims and
firing on the illustrative `db-rows:002.db:concept_relations`
claim (compared 1234 vs live 72576 — both meaningless because
it's an example).
Fix: `_strip_fenced_code_blocks` substitutes the body of every
triple-backtick block with newlines before regex scanning. Line
numbers stay aligned (newline-preserving substitution); tags
inside fences are skipped because their parent text no longer
matches the regex.
Both helper functions (`_iter_claims` and the well-formed-tags
test) walk through the stripped text, so the strip discipline
is consistent across all three test functions.
== TICKETS.md index ==
Added #000044 row marked closed with the 5-commit landing trail.
Bumped Next ID 000044 → 000045.
== Verification ==
$ pytest tests/test_doc_counts.py
3 passed in 2.80s
$ pytest tests/ -q
2337 passed, 37 skipped in 108.29s
Hygiene: fox's in-flight changes to arborist/qa/runner.py +
arborist/substrate/prometheus.py + tests/test_prometheus*.py
left untouched in working tree.
Three coordinated doc landings tying together fox's evening
#000037 → #000025 closed-loop work (commits f625cac through
ff1752c + 8999b55):
== #000037 §20 Status — stale prose refresh ==
§20 said "open · awaiting go/no-go" but file header + TICKETS.md
both say "in progress" with phases 0/1/1.b/2 all landed. Refresh
§20 to reflect actual state with per-phase commit anchors:
- Phase 0 (doc): landed; David review applied per §21
- Phase 1 (pure-function controller): f625cac
(arborist/substrate/prometheus.py + test_prometheus.py)
- Phase 1.b (gap-close): f9f5ae4 (§14 row 4 Hermes-saturation
guard, §13 step 11 falsification-fixture proposal, §15 entropy
+ memory gates weight-tunable, ESCALATE > QUARANTINE > REJECT
priority cascade)
- Phase 2 (advisory audit writes): a786d6d
(prometheus_audit.py + controller_events sibling table; does
NOT enter audit_events.event_hash preimage)
- §12 Trigger 2 fired 2026-05-10: divergence variance ratio
0.575 > 0.5 with N=37 — Phase 1 opening is now empirically
gate-satisfied per 8999b55
- Phase 3: deliberately NOT landed; replaced with read-only
dry-run simulator surfacing five design findings (see §22)
- Closed-loop signal: 40 corpus-derived 5F fixtures harvested
per ff1752c
== #000037 §17.1 — "78 atomic claim-pack records" → 92 ==
§17.1 said "#000031 Phase 2 has 78 atomic claim-pack records
that max out at ANCHOR-WARRANTED". #000031 closed at 92 records
(78 was an interim count during Phase 2). Refresh with the
journey (78 → 92) + AUTOCOUNT-tagged via db-where metric so
future drift fires immediately. Note the resolution context: all
92 now resolve via 74 citation-aliases + 13 term-aliases under
#000031 Phase 2.5 + B-1 + B-2. The unconscious sweep drains the
ANCHOR-WARRANTED → EVIDENCE-WARRANTED promotion backlog
(derivations.proof_blob rows still need computation even on
resolved chains).
== #000025 §11 Status — Phase 1f closure note ==
#000025 file header lists Phase 1a/1b.2/1c/1d/1e but the §11
Status section was frozen at "Open · awaiting go/no-go" — a
two-versions-old prose snapshot. Refresh with the per-phase
landing trail + add a Phase 1f section for the corpus-derived
falsification harvest that ff1752c shipped:
- Phase 1f closes the controller → 5F battery loop fox designed
in #000037 §3 ("Divergence → candidate falsification fixture")
- bench/scripts/harvest_falsification_proposals.py reads qa.db,
stratifies top-20-by-cache_key per audit_mode (HYBRID +
UNGROUNDED), writes the 41-line JSONL pack (1 _meta + 40
fixtures, AUTOCOUNT-tagged via fixture-rows)
- Every fixture row carries _harvest_meta with cache_key,
witness_divergence at harvest time, audit_mode_at_harvest,
harvest_threshold, source_ticket: "#000037 §13 step 11"
- 5F battery exercises them every test run;
test_5f_falsification_harvested_pack_runs_clean asserts
error_detection_rate == 1.0 by construction (every harvested
row IS a falsification)
- Self-amplifying — coverage grows with corpus, not with
hand-curation
Listed open items (§10.11 / 10.13 / 10.14) preserved verbatim
from file header so the index claim "still open" stays in sync.
== Cookbook: new "Adjacent: live-corpus → bench-fixture
harvest" section ==
New section in warrant-substrate-cookbook.md between "Re-running
the substrate build" and "References" documenting the harvest
pattern. Three discipline patterns reused from the textbook
substrate noted explicitly:
1. Attribution metadata on every derived artifact (same shape as
derivations.proof_blob carrying inclusion proofs back to
source chunks)
2. Determinism via sort-and-cap (same shape as citation-alias
cascade's "top 5 AND-join then top 3 OR-join" stratification)
3. Pin the metadata contract in tests (same shape as the
cookbook appendix's discipline pins — silent regression
becomes loud test failure)
Plus the reusable recipe for any controller emitting Proposal
records: define the dataclass, write a harvester filtering +
stratifying, pin metadata in tests, wire a make target.
References section gets four new entries pointing to #000037,
#000025, the harvest script, and the fixture pack.
== Drift caught + refreshed during this commit ==
While editing the cookbook, the AUTOCOUNT regression test
(from fc5ba50 / 6c6defb) caught two stale counts from fox's
in-flight prometheus work:
- test_prometheus.py: 36 → 42 (fox's uncommitted +6 for
Phase 1.c sweep weight profile)
- test_prometheus_audit.py: 14 → 17 (fox's uncommitted +3)
Refreshed both inline + in the test/code-density table
(prometheus row test LOC also bumped 804 → 955 to match wc -l).
This is the harness firing exactly as designed — fox's
uncommitted tests changed live state and my doc claims went
stale within minutes. The test message named the file + line
+ claimed-vs-live, refresh was a 60-second turnaround.
== Verification ==
$ pytest tests/test_doc_counts.py
3 passed in 2.92s
$ pytest tests/ -q
2337 passed, 37 skipped in 107.43s
Hygiene: only docs/ paths staged. fox's in-flight changes to
arborist/qa/runner.py + arborist/substrate/prometheus.py +
tests/test_prometheus.py + tests/test_prometheus_audit.py
remain in their working tree, untouched by this commit.
Re-running `make prometheus-trigger-probe` after today's controller
landings shows the divergence-variance trigger has crossed both
thresholds:
Trigger 2 — divergence variance
Sample count: 37 (N_min = 30 ✓)
Mean: 0.7568, σ: 0.435
σ/mean ratio: 0.5748 (> 0.5 threshold)
Absolute σ: 0.435 (> 0.1 threshold)
Same-day morning probe (commit baseline) had only 16 samples and
did not fire; the additional witness-sweep / dry-run / harvest
activity through the afternoon brought sample count above N_min.
Agreement-label distribution across all shards:
KERNEL-LLM-DIVERGED 22
KERNEL-LLM-AGREE 6
LLM-DIVERGED 6
STRICT-WITNESSED 3
Trigger 1 (branch density) and Trigger 3 (witness cost share) did
NOT fire. Per §12 a single trigger firing is sufficient for Phase 1
gating — and Phase 1 has already landed. This commit captures the
empirical evidence that Phase 1 was on the right side of the gate.
Trigger 1 remains structurally blocked on #000012 Phase 1c
(fork_score_branches sibling table); that's the natural next move
if anyone wants to surface multi-branch consensus signals.
Fan-out follow-up: extends AUTOCOUNT with a new metric for filtered
SQL-row claims, then tags fox's prometheus controller test surfaces
shipped this evening under #000037.
== Task 3: db-where metric ==
New metric ``db-where`` for tagging single-column equality
predicates. Target syntax::
<table>?<column>=<value>
<shard>:<table>?<column>=<value>
Resolves to ``SELECT COUNT(*) FROM <table> WHERE <column> = ?``
with ``<value>`` bound as a SQL parameter (no string
interpolation), so author typos or stray content can't escape
the predicate. Column + table names validated as bare
identifiers before string-interpolating into the query template;
sqlite3 connection opens with ``mode=ro`` URI flag.
Same skip-on-absence semantics as ``db-rows``: missing DB or
table yields a logged skip note, not a test failure. Sentinel
returns reuse the same _DB_MISSING / _TABLE_MISSING / _DB_ERROR
constants.
Smoke verified::
_live_db_where('documents?source_type=claim_pack') → 92
_live_db_where('documents?source_type=wikipedia_xml') → 866782
_live_db_where('001.db:documents?source_type=wikipedia_xml')
→ 867695
_live_db_where('documents') # malformed (no ?) → -4
Tagged claims using the new metric (cookbook):
- L36 ``92 records total`` for the claim-pack source
- L349 ``The 92 chains have three quality tiers``
Both resolve to ``documents WHERE source_type='claim_pack'``
in shard ``000.db`` — the live count of claim-pack records.
L5 ``18/92 → 92/92`` historical narrative left untagged
(expressing a journey arc, not current state).
== Task 2: tag prometheus controller test surfaces ==
fox shipped two test files this evening under #000037 that
weren't previously inventoried in any reference doc:
- ``tests/test_prometheus.py`` — 36 tests covering Phase 1
controller (commits ``f625cac`` + ``f9f5ae4``). Verifier-style
discipline (NOT calculator pattern — it's a pure-function
state-machine controller with no closed-form math).
- ``tests/test_prometheus_audit.py`` — 14 tests covering Phase 2
``controller_events`` sibling table (commit ``a786d6d``). Pins
no-chain-mutation invariant (advisory writes never enter
audit_events.event_hash preimage).
Added two paragraphs to cookbook §"Substrate-paper-spec'd
primitives" describing the test discipline + algorithmic surfaces
each pins. Renamed section header from
"(#000012 + #000018 + #000034)" to
"(#000012 + #000018 + #000034 + #000037)" to keep the
ticket-set roster current.
Two new rows in the test/code-density table:
| substrate/prometheus.py | 893 | 804 (36 tests) | 0.90 |
| substrate/prometheus_audit.py | 200 | 388 (14 tests) | 1.94 |
All four counts AUTOCOUNT-tagged (2 inline prose + 2 table rows
= 4 new tags). prometheus_audit's ratio of 1.94 is high because
the test file pins a lot of write-path invariants for what is
nominally a small (200 LOC) sibling-table module — appropriate
for foundation-level audit-discipline code.
== Task 4: test_full_suite_total_fixture_count flake — investigated ==
Earlier today's transient ``-x`` flake (1 failed, 1799 passed)
did NOT reproduce in current tree state (2328 passed, 37 skipped
under same flags). Root-cause investigation:
- ``_DEFAULT_FIXTURES`` is read-only at module scope; no test
mutates it.
- The test reads JSONL fixtures from ``bench/fixtures/`` via
``_run_one``; those files weren't being written by parallel
tests.
Hypothesis (not confirmed, since flake didn't repro): transient
filesystem state during heavy-parallel-commit window
(``f625cac`` / ``a786d6d`` / ``6142437`` / ``f9f5ae4`` all
landed in succession around 17:23-17:24 EDT 2026-05-10 while my
test run was in flight). No structural defect identified. If
flake recurs, capture stdout + filesystem state at failure time
to confirm.
== Task 1: Walked fox's 6 evening commits via Explore agent ==
Agent reported what shipped under #000037 + #000012 evening
push (Prometheus-Σ Phases 0/1/2/dry-run + v8 consensus paper).
Findings used to drive task 2 above. Notable design choices
worth surfacing as reference:
- prometheus.py is **pure function** (no DB / LLM / scheduler);
returns advisory ``ControllerDecision`` + optional proposal
records, never mutations. Verifier-style test discipline.
- ``controller_events`` sibling table never enters
``audit_events.event_hash`` preimage — audit chain unaffected.
- Phase 3 sleep-sweep scheduler **deferred** in favor of
read-only dry-run simulator surfacing 5 design constraints
(chunk_size = Hermes concurrency NOT candidate pool;
capital_cost flat=1.0 needs split; τ_qa per audit_mode;
Target B = 4.4% canonical-shape match; quarantined-row veto
exercises end-to-end). Calibration substrate for eventual
scheduler.
- Per-branch controller latency 12.5 µs at chunk_size=4 → not
the bottleneck; Hermes witness fan-out is.
v8 consensus paper at ``docs/_source/merkle-agi-v8-consensus.rst``
(834 lines; 11 parts) closes the loop from single-validator
Proof-of-Upgrade to multi-validator BFT selection. Phase 1c
(branch-set persistence) remains proposed-not-opened.
== Coverage ==
Total tags after this commit: 54 (was 49; +5)
Tags by metric:
tests: 45 (+4 new prometheus + table rows)
fixture-rows: 2
db-rows: 3
db-where: 2 (new metric, both 92 claim-pack)
Files with tags:
docs/warrant-substrate-cookbook.md 32 (+5)
docs/calculator-test-patterns.md 8
docs/soft-hash-channel-analysis.md 5
docs/tickets/ticket-000006-bench-emergent... 4
docs/seven-point-program.md 3
docs/tickets/ticket-000035-prg-choice-phi-prg.md 2
== Verification ==
$ pytest tests/test_doc_counts.py -v
3 passed in 2.60s
$ pytest tests/ -q
2328 passed, 37 skipped in 106.06s
Closes the controller → 5F battery loop fox designed: #000037 Phase
1 produces FalsificationFixtureProposal records from high-divergence
providence_cache rows; this commit lands the harvester that turns
those proposals into a real 5F fixture pack the falsification
battery exercises every test run.
bench/scripts/harvest_falsification_proposals.py — reads qa.db,
filters live rows with witness_divergence = (n_unverified / n_quotes)
>= 0.5, stratifies by audit_mode, picks 20 HYBRID + 20 UNGROUNDED
top-by-cache_key for determinism, writes embedded-mode fixtures
to bench/fixtures/5f/falsification-harvested-v1.jsonl.
Each fixture carries `_harvest_meta` with the source cache_key,
divergence at harvest time, audit_mode at harvest time, and the
ticket reference (#000037 §13 step 11). Embedded mode — uses
`observed_violations` directly without calling verify_quotes
again; `answer_text` preserved verbatim for debugging.
Pack composition (initial harvest 2026-05-10):
20 UNGROUNDED (expected_reason: UNGROUNDED)
9 HYBRID_QUOTE (NEW motif — not in falsification-v1.jsonl)
7 HYBRID_CLAIM_LATTICE (NEW motif — not in falsification-v1.jsonl)
4 HYBRID_PARAPHRASE (already covered in v1)
Two harness tests pin the pack:
- test_5f_falsification_harvested_pack_runs_clean: 100% pass-rate,
every fixture carries traceable _harvest_meta.
- test_5f_falsification_harvested_pack_widens_motif_coverage: the
HYBRID_QUOTE / HYBRID_CLAIM_LATTICE motifs surface from real
corpus (loud-fail if harvest rotation drops them).
Makefile: `make bench-5f-harvest` re-runs the harvester. Parameters
exposed: HARVEST_QA_DB, HARVEST_OUT, HARVEST_THRESHOLD,
HARVEST_SAMPLE_PER_BUCKET.
Full suite: 2328 passed, 37 skipped (+2 from the two new pins).
Two drifts caught in TICKETS.md sweep after today's wave:
1. **#000006 status row drift** — fox amended ticket
#000006's file header on 2026-05-10 to:
Status: open · rolling research log (verifier-ladder
healthy at 134 cycles; emergent gems still being
mined)
But the TICKETS.md index row still said just `open · rolling`.
Convention from peer rows (#000031, #000037, #000025) is for
the index status field to carry the same descriptors that the
ticket file header carries — the index is the load-bearing
surface for at-a-glance reading. Refresh.
2. **calculator-test-patterns.md description drift** — the
description in §"Distinction from other docs" was authored
when the doc was a 9-item-checklist codification of a
three-module pattern bench (t3_bound_calculator /
phi_alignment_probe / anchor_prg, 2026-05-10 morning). Today
evening's commit `f5dbfab` extended the doc with three new
patterns (projective-contract, dispatch-order pin,
tie-breaking-rule pin) sourced from fox's overnight π*
kernel commits, plus four new exemplar test files
(pi_star_arithmetic / _logic / _code / _time_series). The
description should reflect the 12-pattern split (9 core +
3 domain-specific contract pins) and the now-seven-exemplar
inventory. Refresh.
Spot-checked status text in 9 in-progress / open / parked
tickets against their file headers — all in sync:
#000043#000037#000036#000035#000034#000033#000025#000016#000012#000006 was the only divergence. Closed-ticket alias counts
(74 / 13 / 92/92) all match live; refreshed in earlier commits
this session.
Hygiene: docs-only commit, no code, no tests touched.
Verification: ``pytest tests/test_doc_counts.py`` 3/3 pass in 1.97s.
Two coupled doc updates capturing today's session state:
1. #000036 status pin — math review in flight with dav1d
- Ticket status line: 'awaits fox math review' → 'pre-review
polish pass 8916bf3; math review in flight with dav1d
(forwarded 2026-05-10 — Tier 2 bundle)'
- TICKETS.md index row mirrors same change
- Future shifts can now see review is live, not blocked on fox.
2. #000006 rolling research log — 2026-05-10b amend
- Fourth qualitatively different experimental shape:
Prometheus-Σ dry-run simulator (joining random-word,
witness-sweep, warrant-chain)
- Captures the five scheduler-calibration findings (F1-F5)
from bench/scripts/prometheus_sigma_sweep_dryrun.py:
- F1: chunk_size = Hermes concurrency, not pool size
- F2: capital_cost must split by audit_mode (CP=0.05 vs
STRICT=1.0); flat-1.0 blocks every allocation
- F3: τ_qa must split by audit_mode (1d for kernel-only,
7d for LLM-witness); single-τ hides CP-rows
- F4: Target B headline = 4.40 percent of docs are
canonical-shape candidates (~152K across the corpus)
- F5: quarantined-row veto exercises end-to-end on
real-corpus data, no fixture-only mocking
- Updates the distinct-signal table to four rows
- Cross-references #000037 §22 for the full per-shard log
Phase 3 scheduler (when it ships) inherits F1-F5 as known-good
defaults — the dry-run is the calibration substrate the eventual
implementation will reference for choice justification.
Doc-only updates; no schema, no governance hash, no code change.
Closes four gaps in the initial Phase 1 landing (commit f625cac):
1. §14 row 4 — Hermes-saturation guard. `hermes_utilization` was on
the input contract but never consumed. Now: `utilization >=
budget` → DEFERRED with HERMES_SATURATED note + advisory event
carrying (utilization, budget) for Phase 2 audit. Three new
tests (saturation-equal, saturation-overflow, headroom-exists).
2. §13 step 11 — falsification-fixture proposal emission.
New `FalsificationFixtureProposal` dataclass; controller now
emits one per branch whose `witness_divergence >=
falsification_divergence_threshold` (weight-tunable, default
0.5). Emission fires BEFORE the all-vetoed cascade so vetoed-
AND-diverged branches still surface as 5F-fixture candidates
per #000025. Four new tests (high-divergence emits, low-
divergence stays silent, threshold is weight-tunable, vetoed-
diverged emits anyway).
3. Entropy + memory gating moved from module-level constants
(`H_LOW=0.3`, `H_HIGH=0.7`, `KAPPA_MEMORY=0.5`) to weight
fields (`h_low`, `h_high`, `kappa_memory`). Constants stay as
back-compat exports; defaults match exactly so byte-identical
behavior when neither override fires. Three new tests
(h_low/h_high tunable, kappa_memory tunable, back-compat
match).
4. Veto-class cascade hardening. Added explicit tests for the
`replay_window_unbounded` → ESCALATE path and the
`soft_hash_signal` → QUARANTINE path (§6 + §14 documented but
previously untested). Plus tests for the §6 fail-loud
priority ordering: ESCALATE > QUARANTINE > REJECT when mixed.
Dry-run regenerated against ~/.arborist/shards corpus:
Target A at τ_qa=1d surfaces **576 FalsificationFixture
proposals** from witness_divergence >= 0.5 (24% of swept
candidates). These rows are now an actionable funnel for 5F
fixture mining under #000025 §3.
Module: arborist/substrate/prometheus.py (+117 LOC, 899 total)
Tests: tests/test_prometheus.py (+196 LOC, 22 → 36 tests)
Dryrun: bench/scripts/prometheus_sigma_sweep_dryrun.py +
bench/results/prometheus-sigma-sweep-dryrun-2026-05-10.md
track the new falsification_proposals_total counter.
Full suite: 2326 passed, 37 skipped (+14 net from the new tests).
Phases 1 (controller) and 2 (sibling-table audit writes) landed in
prior commits. This commit adds the Phase 3 dry-run simulator
instead of the actual sleep-sweep scheduler, since Phase 3's value
is mostly in what we'd learn from running it — and the dry-run
captures those findings without committing to a scheduler design
prematurely.
bench/scripts/prometheus_sigma_sweep_dryrun.py — read-only
simulator that classifies §3 Target A (providence_cache) + Target B
(documents) sweep candidates, synthesizes ControllerBranches from
real shard data, runs the Phase 1 controller, reports decision
distribution + Phase-3-design findings. No LLM calls, no
mutations.
make prometheus-sweep-dryrun — produces a dated markdown report
at bench/results/prometheus-sigma-sweep-dryrun-YYYY-MM-DD.md.
Five findings surfaced by three dry-run iterations against the
live ~/.arborist/shards corpus (3.5M docs + 2839 providence_cache
rows) — captured in ticket §22:
1. chunk-size dominates Kelly threshold (must = Hermes
concurrency, not candidate pool)
2. flat capital_cost blocks every allocation (split kernel-cost
vs LLM-cost on the contract)
3. τ_qa=7d filters every CANONICAL_PROJECTION row (all 29 are
<7d old; need per-audit-mode τ)
4. Target B canonical-shape detection is the real headline
(~152K candidates extrapolated; controller correctly returns
MARGINAL on shape-match chunks)
5. quarantined rows correctly veto via cache_drift hard-veto
Mean per-branch controller latency in dry-run: 12.5 µs at
chunk_size=4. Phase 3's actual bottleneck is the witness fan-out
(Hermes calls), not the controller itself.
Ticket #000037 status flipped to in-progress with Phases 0+1+2
landed; Phase 3 scheduler remains future work but is informed by
the five findings.
Pure-function recursive-falsification controller implementing
ticket #000037 §13 algorithm (steps 1-9 + 12), §5 Shannon-entropy
fork-selection with stable softmax, §6 8-class hard-veto order,
§7 Kelly-bounded allocation with 4 safety guards, §7.1 EMA-smoothed
difficulty update, §14 exception-matrix dispatch, and §15 three
named weight profiles (safe/conservative/exploratory).
No DB, no LLM, no scheduler — advisory pure function over already-
committed state. Phase 2 (controller_events sibling table) lands
in companion commit a786d6d. Phase 3 (sleep sweep scheduler) is
not in this commit.
Module: arborist/substrate/prometheus.py (782 lines)
Tests: tests/test_prometheus.py (22 passing tests — the 17 named
contracts from §16.2 plus 5 boundary cases for the §6 veto-class
priority dispatch and §7.1 EMA stability).
Also removes obsolete tests/test_prometheus_sigma.py — pre-Phase-1
scaffolding placeholder whose 17 tests all called pytest.fail()
with "Phase 1 implementation pending" and the @skip_until_phase_1
decorator never auto-flipped to pass-on-import. The contract is
now in tests/test_prometheus.py.
Land the three test-pattern shapes the Explore-agent investigation
of fox's overnight π* kernel commits surfaced. Patterns 1-8 in
this doc were the original 9-item checklist; patterns 9-11 are
new domain-specific contract pins that the π* kernels require but
that t3_bound_calculator (the original exemplar) does not.
== New patterns added ==
**§9 Projective-contract pin (one-way canonicalizers)**
For canonicalizers whose output type ≠ input type — output is
not in the input domain by design — assert that re-applying the
function raises. Pinned in code-py-ast@v1 (Python → S-expr) and
time-series-quantized@v1 (JSON → quantized text). When the output
type DOES equal the input type (arithmetic kernel's ℚ → ℚ),
use the dual: round-trip idempotence
``canonicalize(canonicalize(x)) == canonicalize(x)``. Both pin a
contract; pick by the kernel's type signature.
**§10 Dispatch-order pin (Python type-hierarchy gotchas)**
Python's ``bool`` subclasses ``int``, so a naive ``isinstance(x,
int)`` chain never reaches a bool branch. Kernels distinguishing
``True`` from ``1`` (Python AST normalizers, etc) must check
``bool`` first. Pin the branch order so a "simplify the dispatch"
PR fires loud. From ``593550b``.
**§11 Tie-breaking-rule pin (banker's rounding)**
Python's ``round()`` uses ties-to-even (PEP 3141): 0.5→0, 1.5→2,
2.5→2. Naive switch to ``math.floor(x + 0.5)`` (round-half-up)
produces 0.5→1, 1.5→2, 2.5→3 — different output for tie inputs
without breaking non-tie tests. From ``2585d3c``.
Each pattern has worked-example pseudocode + cross-reference to
the actual test file in fox's commit. The pattern numbers extend
the existing 1-8 sequence; renumbering would have invalidated
prior references.
== Checklist updates ==
Items 10/11/12 added (conditional — only when the kernel's shape
exposes the corresponding surface). Many calculator modules
(t3 bound, anchor PRG) need only items 1-9.
== Exemplar files reorganized ==
Replaced the single-exemplar reference (t3_bound_calculator only)
with a 5-file table cross-referencing the 9-12 checklist items
each exemplar covers:
test_t3_bound_calculator.py items 1-9 (53 tests)
test_pi_star_arithmetic.py items 1-6 + 9 + idempotence (56)
test_pi_star_logic.py items 1-6 + 9 + 11 (53)
test_pi_star_code.py items 1-6 + 9 + 10 + 11 (32)
test_pi_star_time_series.py items 1-6 + 9 + 10 + 12 (35)
All five test counts AUTOCOUNT-tagged so future drift fires the
regression test landed in ``fc5ba50`` / ``03c0f6a``. Total tagged
claims now 49 (was 44; +5).
== Source ==
Patterns surfaced from the Explore-agent investigation of fox's
overnight 2026-05-10 commits (``6c9bc04`` arithmetic, ``e7bef5f``
logic, ``593550b`` code, ``2585d3c`` time-series — 176 KATs total
across 4 π* canonical-projection kernels). The agent walked each
commit, noted the test patterns that didn't appear in the
original 9-item checklist, and reported the pattern shapes back.
This commit promotes those findings from session memory to
architecture-reference docs.
Verification:
$ pytest tests/test_doc_counts.py -v
3 passed in 3.39s
Sibling table `controller_events` for advisory persistence of
ControllerDecision output from #000037 Phase 1. Same pattern as
`capital_ledger` — forward-migrated, indexed, but does NOT enter
audit_events.event_hash preimage. Audit chain semantics are
unaffected.
Three event kinds:
controller_decision — one per ControllerDecision
controller_difficulty — one per ControllerDecision (records
the difficulty_next value)
controller_budget_allocation — one per branch with nonzero
allocation in decision.allocations
Idempotent on (event_kind, body_hash) UNIQUE constraint.
sha256 of canonical-JSON-encoded body is the dedupe key.
Tests: tests/test_prometheus_audit.py — 14 cases covering
migration, idempotency, no-chain-mutation invariant, query paths.
Uses stub ControllerDecision so tests run independently of Phase
1's controller_decide implementation.
Fan-out follow-up to ``fc5ba50``. Two thrusts in one commit since
they exercise the same surface:
== Task 3: extend AUTOCOUNT with db-rows metric ==
New metric ``db-rows`` for tagging live SQLite row counts (alias
tables, claim-pack records, etc — operator state that drifted on
``30a9488`` and earlier). Target syntax::
<!--AUTOCOUNT:db-rows:citation_aliases-->74<!--/AUTOCOUNT-->
<!--AUTOCOUNT:db-rows:002.db:concept_relations-->1234<!--/AUTOCOUNT-->
Default shard: ``~/.arborist/shards/000.db`` (where the alias
tables live per ``arborist.cli._aliases_db_path``). Operator state
is graceful-skip semantics: when DB or table is absent (CI, fresh
checkout, sibling repo), the claim is logged as skipped and the
test still passes. Drift only fires when the DB IS present and
the count diverged.
Sentinel returns:
- ``_DB_MISSING`` (-2): shards dir not present → skip
- ``_TABLE_MISSING`` (-3): DB present but table absent → skip
- ``_DB_ERROR`` (-4): malformed table name or sqlite error → skip
Table name validated against ``[A-Za-z_][A-Za-z0-9_]*`` regex
before string-interpolating into ``SELECT COUNT(*) FROM <table>``;
this is belt-and-suspenders since AUTOCOUNT tags are author-
controlled, but the dynamic SQL surface deserves a bouncer.
Smoke verified under HOME redirect to ``/tmp/<empty>``: 3 db-rows
claims gracefully skip with informative line-numbered messages,
suite still passes.
== Task 2: backfill 15 tags ==
Cookbook test/code-density table (lines 569-579, 10 rows) — every
``(N tests)`` cell now machine-checked:
| aliases.py | 512 | 469 (28 tests) | 0.92 |
→
| aliases.py | 512 | 469 (<!--AUTOCOUNT:tests:tests/test_aliases.py-->28<!--/AUTOCOUNT--> tests) | 0.92 |
Markdown renderers strip HTML comments — table cells display
``28 tests`` unchanged. The ``warrant_resolver.py`` row stays
untagged because its test count is split across two test files
(verifier + parser) and the cell encodes a combined "~430"
instead of one collected count.
Cookbook alias-count surfaces (3 db-rows tags):
- L364 ``citation_aliases (74 rows live as of 2026-05-10)``
- L437 ``#000041 — citation-aliases table + 74 live rows``
- L438 ``#000042 — term-aliases table + 13 live rows``
Ticket #000035 (in progress, line 274) — refresh ``20 tests``
→ ``27 tests`` for ``test_anchor_prg.py`` + tag. Same drift
pattern as ``5c21e83``: ticket prose was written before the
``de997f7`` 2026-05-10 pattern backfill that added 7 tests
(prefix-extension closure, hand-formula, parametrized
invalid-input cones). Also tagged ``L279``'s 10-vector KAT
fixture claim with ``fixture-rows`` metric.
== Closed-ticket counts deliberately not tagged ==
#000028, #000030, #000042, #000031, #000004, #000026, #000009,
#000032, #000008 all carry historical "N tests pass" snapshots
from their landing date. Those are point-in-time records, not
live claims — drifting from current state is BY DESIGN. Tagging
them would fire the test on every successive change to the
codebase. Closed tickets are the design log; we don't backfill
them.
== Coverage summary ==
Total tags after this commit: 44 (was 29; +15)
Tags by metric:
tests: 39
fixture-rows: 2
db-rows: 3
Files with tags:
docs/warrant-substrate-cookbook.md 27 (was 14)
docs/soft-hash-channel-analysis.md 5
docs/tickets/ticket-000006-bench-emergent... 4
docs/seven-point-program.md 3
docs/calculator-test-patterns.md 3
docs/tickets/ticket-000035-prg-choice-phi-prg.md 2 (new)
== Verification ==
$ .venv/bin/pytest tests/test_doc_counts.py -v
3 passed in 4.32s
$ .venv/bin/pytest -q
2276 passed, 54 skipped in 168.34s
$ HOME=/tmp/empty pytest tests/test_doc_counts.py -v -s
3 db-rows AUTOCOUNT claim(s) skipped:
docs/warrant-substrate-cookbook.md:364 db-rows:citation_aliases skipped — /tmp/empty/.arborist/shards not present (CI / fresh checkout)
docs/warrant-substrate-cookbook.md:437 db-rows:citation_aliases skipped — /tmp/empty/.arborist/shards not present (CI / fresh checkout)
docs/warrant-substrate-cookbook.md:438 db-rows:term_aliases skipped — /tmp/empty/.arborist/shards not present (CI / fresh checkout)
3 passed in 4.78s
No new dependencies. No schema changes.
The doc-drift pattern recurred four times today on 2026-05-10
(commits 6cbbf95, 14bcb99, 5c21e83, 30a9488). Each fix was the
same shape: walk a doc, find a count that drifted from live truth
during the hours after the doc was written, refresh it. Cost: ~5
min per drift × 4 = 20 min of manual catching, with no guarantee
the next drift gets caught before someone external reads it.
Per fox's selection: regression test that makes drift loud at
test time instead of relying on visual catching.
== Mechanism ==
`tests/test_doc_counts.py` scans `docs/**/*.md` for AUTOCOUNT
tags of the form:
<!--AUTOCOUNT:metric:path-->N<!--/AUTOCOUNT-->
Two metrics supported:
- `tests` — pytest collected count for path. Batches every
tagged path into one `pytest --collect-only` subprocess
(~0.5s total).
- `fixture-rows` — non-blank-non-comment line count in a JSONL
fixture.
GitHub and most markdown renderers strip HTML comments, so
readers see only `N`. The tags are invisible in rendered output
but make the claim machine-checkable. Three tests in the file:
1. `test_doc_autocount_claims_match_live` — the core invariant
2. `test_autocount_tags_are_well_formed` — open/close balance
3. `test_autocount_metric_names_are_documented` — fail-closed on
undocumented metrics (catches typos)
Failure message names the doc file, line number, and the
claimed-vs-live diff. Example:
`docs/foo.md:42 AUTOCOUNT(tests:tests/test_x.py) claims 23, live is 27`
== 29 tags installed across 5 docs ==
While installing tags I had to read the surrounding prose, which
surfaced six stale counts that had drifted same-day:
`docs/soft-hash-channel-analysis.md`:
- L392 14 → 23 tests for phi_alignment_probe
- L417 20 → 27 tests for anchor_prg
- L463 14 → 23 tests for phi_alignment_probe (status section)
`docs/seven-point-program.md`:
- L77 68 → 58 tests for metacognition (drift -10; the file
shed tests during a refactor and the doc didn't catch up)
- L78 9 tests for `test_dag.py::test_preflight_*` — removed
count entirely; pytest selector subsets aren't currently
supported by the AUTOCOUNT metric set (would need a
`tests-matching` metric; not worth the surface for one claim).
- L110 24 → 33 tests for test_dag.py
`docs/calculator-test-patterns.md`:
- L35 33 → 23 tests for warrant_resolver
- L35 10 → 9 tests for warrant_chain
- L16, L265 51 → 53 tests for t3_bound_calculator (kept
initial-shipment provenance in prose)
== Coverage installed ==
calculator-test-patterns.md 3 tagged claims
soft-hash-channel-analysis.md 5 tagged claims
warrant-substrate-cookbook.md 14 tagged claims
seven-point-program.md 3 tagged claims
tickets/ticket-000006-bench-... 4 tagged claims
---
29 tagged claims
Every count that drifted today is now tagged. Future drift
fires the regression test at the next pytest run instead of
waiting for human catching.
== Discipline pattern ==
Walk this pattern for any new doc that names a count:
1. Surround the number with the tag pair:
`<!--AUTOCOUNT:tests:tests/test_foo.py-->N<!--/AUTOCOUNT-->`
2. Run `pytest tests/test_doc_counts.py` (~3.5s)
3. If it passes, the claim is now machine-verified
Aim to tag counts on first authorship. Retrofitting is cheap
but only catches drift after the fact.
== Out of scope ==
Test counts inside source code (docstrings, CLI --help) are not
scanned — would expand the test surface significantly and the
drift pattern hasn't manifested there. Add `**/*.py` scope when
that pattern surfaces.
Alias-row counts and claim-pack-record counts could be tagged
with new `db-rows:<table>` and `db-where:<sql>` metrics; deferred
until the next drift on those numbers (none caught today after
30a9488's cookbook refresh).
== Verification ==
$ .venv/bin/pytest tests/test_doc_counts.py -v
3 passed in 3.89s
$ .venv/bin/pytest -q
2276 passed, 54 skipped in 153.21s
No new dependencies. No schema changes. No source-code changes.
`docs/_source/merkle-agi-v8-consensus.rst` (834 lines, RST sister
to the v7-W substrate paper at the same path). Closes Phase 1b of
ticket #000012 — the loop-closing consensus protocol that turns
single-validator Proof-of-Upgrade into Darwinian selection across
an open validator set.
11 parts:
Part 1 Introduction & motivation — gap table from v7 § 13.4,
concrete backdoor-attack scenario, paper IS/IS-NOT
scope.
Part 2 Substrate definition — SQD A1/A2/A3 inheritance,
consensus_events row schema, consensus_policy_hash
sibling (never enters cache_key).
Part 3 Validator state machine — bonding/active/challenged/
slashed/unbonding with full transition graph + invariants.
Part 4 Acceptance protocol — proposer submission, layered
fitness floor (canonical + lab-declared ceiling),
audit-replay procedure, 2/3-stake quorum + GRANDPA-
style finalization, liveness floor.
Part 5 Challenge protocol — counter-evidence shape,
adjudication, challenger reward, frivolous-challenge
bond.
Part 6 Stake mechanics — bond/unbond/challenge window
recommendations, offense-class slashing schedule,
reward distribution, optional stake cap + sqrt-weighting.
Part 7 Fork choice rule — GRANDPA-style finality, pre-finality
constraints, liveness recovery.
Part 8 Mesh wire format extension — three new message kinds,
BLS-or-concat aggregate signatures, bandwidth profile.
Part 9 BFT analysis — safety, liveness, Sybil resistance,
bootstrap honesty, re-staking attacks.
Part 10 Worked example — 7-validator deployment, one upgrade
cycle with successful challenge against one fraudulent
validator.
Part 11 Out of scope — implementation, calibration, cross-chain
anchoring, fixture selection, bootstrap-set membership,
cross-instance slashing accumulator, branch-set
persistence.
Closure §: open questions tracked separately (initial validator
set composition, threshold-key ceremony, ZK-replay, policy-hash
transition mechanics).
Ticket #000012 status updated; Phase 1c (branch-set persistence)
remains proposed-not-opened. Implementation follow-up tickets that
cite this paper land later — one per validator-state-machine,
mesh-wire-format extension, audit-replay harness, slashing
accountant.
Pre-Phase-1e: falsification-v1.jsonl covered 10 motif tags across 50
fixtures (the high-traffic warrant/title/anchor/format set). Phase
1e adds 12 fixtures (5f-fal-051..062) for the previously-uncovered
motifs from the verifier+soft-demote registries:
CITATION_MISMATCH DEFLECTION_DETECTED
MANUAL_QUOTE_VIOLATION SCHEMA_INVALID
SOURCE_ROLE_BLOCKED SUBJECT_TOKENS_ABSENT
TOO_MANY_EVIDENCE_IDS UNKNOWN_EVIDENCE_ID
BROAD_QUANTIFIER_RUNAWAY BROAD_QUANTIFIER_CAP_APPLIED
BROAD_QUANTIFIER_SCOPE_UNBOUND BROAD_QUANTIFIER_REJECTED
Coverage now: 22 unique motif tags across 62 fixtures.
Harness changes:
- test_bench_batteries.py: bump pass_count assertion 50 → 62 in both
falsification tests; add test_5f_falsification_covers_every_documented_motif
that pins the motif set against the verifier+soft-demote registries
so adding a new violation upstream surfaces here as a missing
fixture (loud signal, no silent drift).
- test_session_integration.py: bump full-suite total 662 → 674.
Closes#000025 §10.12 (every documented failure-motif tag).
Still open in Phase 1b: §10.11 (real shard finetuning chains),
§10.13 (Feedback Loop latency/efficiency against real workload),
§10.14 (threshold handoff to #000012).
Sweep after closing the #000006 amend refresh: three areas in
warrant-substrate-cookbook.md drifted apart from TICKETS.md
authoritative status while the day-long substrate/alias sprint
was running.
Findings:
1. **Line 422 `#000041` count stale**: cookbook listed "54 live
rows"; TICKETS.md row authoritative since 2026-05-10:
"74 rows live as of 2026-05-10 (count grew 40 → 54 → 74)".
Live `arborist alias citation list | wc` = 74. Refresh.
2. **Line 416 cascade-completion-state line ambiguous**: the
`# → 92 / 92 (100%) under the 18-substrate + 54-alias state`
comment is in the `make textbook-*` re-run code block. Read
as "current state of a re-run today" it's stale (74 not 54);
read as "historical state at 100% achievement" it's accurate.
Refreshed to current state with explicit `(counts as of
2026-05-10)` so a future reader knows what era it pins to.
Split out citation vs term aliases since both feed cascade.
3. **Title-from-author backfill section over-states the
workaround**: cookbook framed the SQL UPDATE pattern as
"Workaround until source-side fix lands". The source-side
fix already shipped — commit `551c969` 2026-05-10 (#000031
follow-up B-2: `--author` flag in HTML + textbook_tex +
crawler ingest paths; every `make textbook-*` Makefile
target already wires it). The SQL pattern is now legacy
fix-up for already-ingested shards that pre-date B-2;
refresh the section header + body to reflect that.
Other claims sanity-checked + accurate:
- Line 122 `4 term-aliases` for Pillar VI Newton vocab — live
domain breakdown is 5/4/4 (arithmetic / classical-physics /
geometry); 4 classical-physics matches.
- Line 350 `(74 rows live as of 2026-05-10)` — accurate.
- Pillar I-IX record counts (13/10/13/18/5/5/14/14 = 92) —
matches live `SELECT COUNT(*) FROM documents WHERE
source_type='claim_pack'` in shard 000.db (92).
- Phase-status references on lines 261/373/424/458/494/499/512
— all internally consistent with TICKETS.md authoritative
statuses (#000031 closed, #000034/35/36 Phase 1 in progress,
#000038 Phase 4 still-blocked).
Hygiene: docs-only commit, no schema, no tests. Pre-existing
order-dependent flake on test_full_suite_total_fixture_count
unrelated; test passes in isolation.
2326 tests collected; 1799 + 53 skipped pass when run with -x.
Four targeted edits before forwarding to dav1d:
1. Add §0 cover note — names the three things the reviewer should
confirm (decomposition, per-surface derivations, conservative-
constant choice) and what's explicitly out of scope (empirical
validation against a real adversarial-training run).
2. Tighten §2 decomposition. The previous text invoked DPI to
produce an additive split I(A;C) ≤ I(A;Θ) + I(Θ;C), which DPI
alone doesn't justify. Replace with a clean Markov-chain DPI
statement (A → Θ → C(M) is a Markov chain conditional on
(H_{≤t}, n_t); DPI gives I(A;C) ≤ I(A;Θ)) and frame the T1+T2
baseline as threat-model-additive (disjoint adversary surfaces),
not information-additive in the same MI sense.
3. Rename §3 'Apply Fano's inequality' → 'discrete-distinguishability
counting'. The derivation log₂(SNR+1) is the discrete channel-
capacity bound on K distinguishable outputs, not Fano's
inequality (which bounds error probability from MI). Add an
explanatory note that LR factors cancel per-step (LR's distinct
channel contribution is §4, not double-counted here). Update §10
item 1 cross-reference for the same naming consistency.
4. Resolve §5 conjecture. Move the random-shuffle conjecture out of
the headline derivation; commit C_B3 = 1 strictly under the
adversarial-order assumption stated in §5. The random-shuffle
tightening C_B3 → O(1/√N_b) stays referenced via §10 + #000043
as the formal tightening path operators can opt into via the
--c-b3 calculator flag.
No numeric examples changed; no calculator behavior changed; no
reference list changed. Pure pre-review polish to remove three
specific things a careful cryptographer would catch and ask
about, plus a cover note that frames the kind of review wanted.
Backfills zero dedicated coverage on arborist/pi_star/logic.py
(371 lines, 2026-05-10 zero-coverage sweep). KATs mirror the
docstring's equivalence classes: commutativity, associativity,
IMPL/IFF/XOR rewrites, De Morgan, double negation, distribution,
idempotence, within-clause tautology drop. Pins v1's documented
limitation: A AND NOT A is NOT collapsed (multi-clause
contradiction detection is out of scope; only empty clauses
surface as FALSE). Negative cones: >8 atoms, unrecognized token,
unexpected char, unbalanced paren, unconsumed tokens, dangling
operator, empty, non-bytes. Plus determinism + lexical-sort
canonicalization.
Real-shard workload baseline + search latency: Phases 1/2/3 all
landed 2026-05-09. Flip status from "in progress" to closed with
Phase 3 commit reference. Authorship warrant ladder followup (CLI
wiring) noted in ticket body as non-load-bearing — not blocking
closure.
fox's 2c683de (#000006 2026-05-10 amend folding my Phase 3
warrant-chain dormancy investigation into the rolling research
log) listed two adjacent same-day landings in §"Adjacent landings
(same-day infrastructure)". Both counts went stale during the
hours after fox's commit, same drift pattern caught earlier
today on the cookbook appendix.
fox's 2c683de timestamp: 13:22 EDT.
- phi_alignment_probe test backfill (a4b3056) landed 14:08 EDT
- The corresponding cookbook appendix refresh (6cbbf95)
followed shortly after.
Stale counts refreshed:
1. **#000034 Phase 1a entry** (line 725):
- "14 tests" → "23 tests" (+9 from `a4b3056` 2026-05-10 pattern
backfill: monotonicity / hand-formula / closure /
parametrized-invalid per docs/calculator-test-patterns.md)
- "10-vector KAT fixture" → "30-vector KAT fixture (10 aligned
+ 10 uniform + 10 anti-aligned synthetic checkpoints,
deterministic-seeded)". The 30 vectors were generated by
`1dfb8b9` itself; fox's amend simply summarized at "10".
Refreshed to the actual count + class breakdown.
2. **#000035 Phase 1 entry** (line 729):
- "20 tests" → "27 tests" (+7 from `de997f7` 2026-05-10 pattern
backfill: prefix-extension closure invariant, hand-computed
HMAC-SHA-512 first-block formula, parametrized
invalid-input cones).
- "10-vector KAT fixture" → confirmed 10 (matches live).
Verification:
test_anchor_prg.py 27 ✓
test_phi_alignment_probe.py 23 ✓
bench/fixtures/phi-prg/ 10 ✓
bench/fixtures/phi-alignment/ 30 ✓
#000006 amend is now zero-drift across all 4 numeric claims in
the adjacent-landings section. The recommendation in §"Verdict"
("track fire rate as a corpus-evolution signal") and the
distinct-signal table both remain accurate as fox wrote them.
Hygiene: docs-only commit, no test or code surface change.
Comprehensive cross-check of the appendix's test counts vs live
`pytest --collect-only` output found two more drift points beyond
6cbbf95's phi_alignment_probe + t3_bound_calculator count
refreshes:
1. tests/test_warrant_resolver.py — appendix described its
coverage qualitatively but didn't give a count. Live: 23
tests. Added "23 tests covering ..." prefix.
2. test/code ratio table row for t3_bound_calculator.py was
"446 351 (51 tests) | 1.4". My 581ad90 added 2 KAT-fixture-
gap-closure tests + ~95 lines of test code (the
test_b3_exact_formula + test_t3_bound_known_answer_tests
functions). Refreshed to "249 | 446 (53 tests) | 1.79".
Comprehensive verification result (all 14 appendix entries
cross-checked against `pytest --collect-only`):
test_aliases.py 28 ✓
test_warrant_resolver.py 23 (was uncounted)
test_warrant_chain.py 9 ✓
test_textbooks_manifest.py 43 ✓
test_anchor_prg.py 27 ✓
test_phi_alignment_probe.py 23 ✓ (refreshed in 6cbbf95)
test_t3_bound_calculator.py 53 ✓ (refreshed in 6cbbf95;
ratio table fixed here)
test_fork_score.py 18 ✓
test_substrate_fork_score.py 27 ✓ (added in 6cbbf95)
test_weights.py 16 ✓
test_pi_star_protocol_and_registry.py 21 ✓
test_qa_progress.py 31 ✓
test_qa_prompts.py 20 ✓
test_concepts_extract.py 20 ✓
Zero remaining drift. The cookbook appendix is now bit-for-bit
consistent with live pytest collection across all 14 entries.
Hygiene: docs-only commit, no code surface change.
The earlier audit found one observation: pyproject.toml's `dev`
extras includes arborist[math] (sympy for ticket #000030's
SymPy substrate) but NOT arborist[hessian] (numpy + scipy for
#000034's φ_linear alignment probe).
Without this, fresh checkouts running `make bootstrap` (which uses
`pip install -e '.[dev]'`) skip tests/test_phi_alignment_probe.py
via pytest.importorskip("numpy") + pytest.importorskip(
"scipy.sparse.linalg") at module top. Tests show as
collected-but-skipped instead of actively running. Phase 1a
regressions (algorithm drift, KAT fixture corruption,
threshold-band drift) would only surface when an operator
deliberately ran `pip install '.[hessian]'` first.
Following fox's pattern with `[math]` in dev — arborist[math]
pulls sympy (~30 MB) into every fresh dev checkout so CI runs
test_canonical_projection.py + math π* tests by default.
arborist[hessian] adds ~80 MB combined (numpy + scipy) — a real
cost, but numpy/scipy are nearly universal Python deps and
already installed on most modern dev environments.
Verification:
- ``pip install -e '.[dev]' --dry-run`` now resolves numpy>=1.26
+ scipy>=1.11 (previously did not).
- ``make test`` → 1986 passed, 45 skipped (no new failures; no
test count change since I already had the extras locally
installed for #000034 Phase 1a development).
Effect:
- New dev checkout: phi_alignment_probe's 23 tests run by
default (no skip).
- CI catches algorithm drift / KAT corruption / threshold drift
in #000034 Phase 1a code on every push, same as how the
[math] inclusion catches drift in canonical_cache /
canonical_projection tests.
Test/code ratio (per cookbook appendix § "Unit-test density"):
phi_alignment_probe at 419 test LOC / 200 code LOC = 2.10×
puts it firmly in the "contract-defining foundation" bracket
(≥1× threshold fox flagged for substrate-paper-spec'd
primitives). Matches the discipline.
Walking 6aca7d9 (cookbook test-coverage appendix) surfaced two
findings: (1) two stale test counts since fox wrote the appendix at
2026-05-10 13:11 EDT; (2) the appendix and docs/calculator-test-
patterns.md are complementary lenses but had no explicit
cross-reference. Both fixed in this docs-only commit.
Stale counts refreshed
======================
- `tests/test_phi_alignment_probe.py` "14 tests" → "23 tests".
Drift cause: my `a4b3056` (2026-05-10 14:08 EDT) added 9
pattern-backfill tests after fox's appendix snapshot at 13:11
EDT (~57 min lag).
- `tests/test_t3_bound_calculator.py` "51 tests" → "53 tests".
Drift cause: my `581ad90` (2026-05-10 ~13:50 EDT) added 2
KAT-fixture-gap closures after fox's appendix snapshot.
Both refreshes preserve the trajectory by noting the
``+9 from a4b3056`` / ``+2 from 581ad90`` provenance inline. Same
durability pattern fox used in `018a2a1` for the alias-count
refresh + my `6f1dbed` ditto.
Per the appendix-author's own ``unit-test density`` heuristic,
the refreshed counts confirm both files keep their ≥1× test/code
ratio. ``test_phi_alignment_probe.py`` jumps from 268/200 ≈ 1.34
to 419/200 ≈ 2.10× (closer to the contract-defining-foundation
ratio fox flagged for warrant_chain.py at 3.6×).
Missing entry added
====================
`tests/test_substrate_fork_score.py` (renamed from
`test_v8_fork_score.py` in `a4058a4` per the 2026-05-10 v-prefix
retirement) wasn't listed in fox's appendix. The file is the
``arborist substrate score`` CLI surface coverage — adapter tests
+ 4 in-process build_parser CLI tests + 1 real subprocess
invocation. Distinct from `test_fork_score.py` (fox's pure-function
unit tests for ScoredFork at 18 tests).
Added under "Substrate-paper-spec'd primitives" section alongside
test_fork_score.py.
Reciprocal cross-reference
==========================
`docs/calculator-test-patterns.md` (the per-pattern CHECKLIST for
new tests) and `docs/warrant-substrate-cookbook.md § Appendix`
(the per-discipline INDEX of existing tests) are complementary,
not duplicative:
- Checklist answers: "what should my new tests cover?"
- Index answers: "where are the tests for X?"
Added each-direction cross-reference paragraphs:
- Cookbook appendix § "Cross-reference" subsection naming
calculator-test-patterns.md as the checklist for new code.
When adding a new substrate-paper-spec'd primitive: walk the
checklist to design the test file, then add a row to the
appendix under the matching discipline.
- calculator-test-patterns.md § "What this doc is NOT" expanded
with a bullet pointing readers at the cookbook appendix as
the existing-test inventory.
Closes the gap where future shifts might find one without the
other and miss half the discipline.
Hygiene
=======
- make test → 1986 passed, 45 skipped.
- Both docs are reference-only; no test or code surface change.
Full QA-quality sweep, 75 questions × 3 modes × n=3 = 675 cells
against Hermes-3 8B at concurrency=4. No mode regressed past
the 5pp signal floor:
quote 53.8% STRICT vs 54% baseline = -0pp (stable)
claim_lattice_pointer 23.1% STRICT vs 20% baseline = +3pp (within floor)
claim_lattice (JSON) 46.7% STRICT vs 42% baseline = +5pp (at floor — marginal positive)
JSON-mode +5pp is right at the noise threshold per
docs/bench-maxing.md — could be the 2026-05-10 substrate work
(92/92 warrant chains + 18 textbook ingests + cascade tuning +
Phase 3 wiring) translating to retrieval-quality lift, OR
sample variance. Follow-up bench in 1-2 days disambiguates.
Format-collapse 0/225 in every mode. Latency stable
(10.6-11.1s median). Lattice-mode directive coverage 100%.
Phase 3 per-claim warrant-chain tail still dormant on this
fixture (rescue-only by design; no warrant-shape question
retrieves a chain-backed chunk while failing lexical anchor —
parallel shift's same finding). Source-level warrants tail
fires on claim-pack-targeted retrievals as documented in
phase3-live-validation-2026-05-10.md.
Substrate + Phase 3 sprint shipped clean.
Three threads bundled, all surfaced by today's calculator-test-
patterns.md audit + fox's directive to remove v-prefix from test
filenames:
THREAD 1 — rename test_v8_fork_score.py → test_substrate_fork_score.py
=====================================================================
Single test file in the tree had a v-prefix in its filename:
``tests/test_v8_fork_score.py``. Renamed via ``git mv`` for
consistency with yesterday's substrate refactor (the package is
``arborist/substrate/fork_score.py``; the CLI subcommand is
``arborist substrate score``; the test file should match).
No internal code changes needed — the file's imports + assertions
were already updated to ``arborist.substrate.*`` paths in
yesterday's bae5caf commit. Pure rename.
THREAD 2 — close v1 substring discipline gap
=============================================
Audit of test_anchor_prg.py + test_phi_alignment_probe.py against
docs/calculator-test-patterns.md §2 (versioned-default discipline)
found one gap: both files asserted the version string's exact
value but neither asserted the ``"v1"`` substring discipline that
fox's test_returns_calculator_version_token established.
Added ``assert "v1" in PHI_PRG_VERSION`` to
test_module_exports_version_string in test_anchor_prg.py.
Added ``assert "v1" in PROBE_VERSION`` to
test_module_exports_thresholds_and_version in
test_phi_alignment_probe.py.
Both follow fox's pattern: when the algorithm changes (v2-blake3-
expansion, v2-arnoldi-iteration, etc.), the version string MUST
change too. The "v1" substring assertion catches a future
contributor who refactors without bumping the version constant.
THREAD 3 — close CLI subprocess gap on test_substrate_fork_score.py
====================================================================
The renamed file had four CLI tests but all in-process via
build_parser() + parse_args() + func(args). That catches argparse-
shape drift but NOT entry-point / module-loading / sys.argv drift.
Added test_cli_substrate_score_subprocess_invocation: real
``subprocess.run(["python", "-m", "arborist.cli", "substrate",
"score", "--parent", ..., "--child", ..., "--out", ...])`` against
synthetic bench results. Asserts exit 0 + the --out artifact is
written + JSON-parses with valid verdict.
Pattern matches fox's test_cli_baseline_runs_clean in
test_t3_bound_calculator.py + the 581ad90 KAT-fixture-gap closure.
Same hazard fox already hit three times during the substrate
rename refactor (85be5eb, 209d670, b320e27): import-only tests
silently miss CLI surface drift.
CHECKLIST AUDIT — POST-FIX
==========================
Three calculator-style test files now all 9-item complete:
| t3 | anchor_prg | phi_alignment | substrate_fork |
KAT fixture | ✓ | ✓ | ✓ | n/a (different)|
VERSION + "v1" | ✓ | ✓ NOW | ✓ NOW | ✓ |
Hand-formula | ✓ | ✓ | ✓ | ✓ (synthetic) |
Monotonicity | ✓ | ✓ | ✓ | ✓ |
Closure / sum-of-parts | ✓ | ✓ | ✓ | ✓ |
Parametrized invalid | ✓ | ✓ | ✓ | ~ |
CLI subprocess | ✓ | n/a | n/a | ✓ NOW |
Doc parity | ✓ | KAT | KAT | KAT |
Module-export shape | ✓ | ✓ | ✓ | ✓ |
All four files now consistently track the calculator-test-patterns
checklist. test_substrate_fork_score.py is structurally different
(verifier-adjacent: tests scoring + verdict-band logic, not
closed-form math) so some checklist items map differently — KAT
fixture replaced by synthetic-input verdict tests (closer to
verifier-style), parametrized-invalid is partial (per-verdict-
class assertions rather than per-bad-input cone). Acceptable.
Test counts:
- test_substrate_fork_score.py: 26 → 27 (+1 subprocess test)
- test_anchor_prg.py: 27 → 27 (assertion added inline)
- test_phi_alignment_probe.py: 23 → 23 (assertion added inline)
- t3 file untouched in this commit (581ad90 already at 53)
Full suite: 1985 → 1986 (+1 from this commit's only
new-test-function addition; the inline assertions don't count
as new tests).
Hygiene
=======
- make test → 1986 passed, 45 skipped.
- All four calculator-style test files structurally aligned.
- No v-prefixed test filenames remain in tests/ tree.
Audited fox's exemplar 51-test file against the 9-item checklist
in docs/calculator-test-patterns.md (codified earlier today in
0725eb4). Two gaps found, both additive:
GAP 1: no KAT fixture
=====================
Checklist item 1: "KAT fixture under bench/fixtures/<module>/
(≥ 5 cases)". Fox's tests cover the doc's worked-example numbers
inline (test_baseline_matches_section_11_doc) but no separate
fixture file existed for off-the-baseline regression coverage.
Generated bench/fixtures/t3-bound/known-answer-tests.jsonl with
8 KATs:
- small-deployment-§7.1, medium-deployment-§7.2,
hardened-deployment-§7.3 (the doc's three worked examples)
- extreme-low-g (g=0.001, σ=0.5 — exercises low-SNR regime)
- tight-window-W=100 (small-W ceiling-rounding edge case)
- tightened-c-b1 (override-constants path)
- all-constants-tight (all three c_b1/c_b2/c_b3 overridden)
- b3-floor-regime (factor < 1, B3 floors to 0)
Each entry pins (calculator_version, inputs, expected_total,
expected_b1, expected_b2, expected_b3, expected_snr_grad).
Algorithm change MUST bump CALCULATOR_VERSION + emit new fixture
file under bench/fixtures/t3-bound/ — old runs replay against
old data per §1 discipline.
GAP 2: no B3 hand-computed formula test
=======================================
Checklist item 3: "Hand-computed formula tests — at least one
per independent contribution / output field". Fox had
test_b1_exact_formula + test_b2_exact_formula + test_snr_grad_formula
covering three of the five output fields. B3 had only
test_b3_floor_at_zero_when_factor_below_one (an edge case),
not a closed-form check on the general formula.
Added test_b3_exact_formula: hand-computes
``C_B3 · ⌈W/E⌉ · log₂(N_b · σ_grad / ‖∇L_max‖) / 2`` per #000036
§5 (Bottou-Bousquet refinement), asserts agreement with the
function's B3_contribution. Pairs cleanly with the B1/B2 hand-
formula tests fox had.
CHECKLIST AUDIT — POST-FIX
==========================
1. KAT fixture ✓ NOW (was ❌; 8 entries)
2. VERSION + "v1" ✓ test_returns_calculator_version_token
3. Hand-formula ✓ NOW B1/B2/B3/snr_grad all covered
(was ⚠️ partial; B3 had floor-only)
4. Monotonicity ✓ test_monotone_in_window_length /
gradient_fraction
5. Closure ✓ test_total_equals_sum_of_three_contributions
6. Parametrized invalid ✓ four @pytest.mark.parametrize blocks
7. CLI subprocess ✓ test_cli_baseline_runs_clean +
test_cli_invalid_input_exits_2
8. Doc parity ✓ test_baseline_matches_section_11_doc
(caught today's §11 calibration drift)
9. Module-export shape ✓ test_returns_calculator_version_token +
test_constants_recorded
All nine items now ✓. test_t3_bound_calculator.py is the
exemplar for calculator-style test discipline.
Test count: 51 → 53 (+2 from this commit). Full suite:
1915 → 1985 (+70 from fox's parallel work + this commit's +2;
partial cycle effects).
Hygiene
=======
- make test → 1985 passed, 45 skipped.
- KAT fixture is JSONL with header comment naming
CALCULATOR_VERSION; future drift caught at the test level.
- Eat-my-own-dogfood: applied my docs/calculator-test-patterns.md
checklist to fox's exemplar test file. The fact that gaps
surfaced (even on fox's substantive 51-test surface) validates
that the checklist has real reviewer value, not just guideline
signaling.
Per fox 2026-05-10 — file not needed. Was a point-in-time update
note; superseded by the rolling research log in #000006 and the
ticket-level status pins (#000028 closed in TICKETS.md, witness-
sweep amend in #000006 etc.).
No incoming references in the repo (grep clean).
Note for the record: the immediately-prior commit (1421d96) made
an internal-consistency fix to this same file. That fix is moot
post-deletion but stays in the audit chain — describing the
witness/carrier vocabulary distinction was useful at the time it
shipped.
Today's autonomous-quality run pushed test count from 1655
to 2093 (≈+438 across both shifts). README.md still cited the
older "641+" milestone from earlier in the project. Updated to
the current ~2000+ number with a parallel-execution latency
note.
The doc's own meta-comment at line 160 explicitly distinguishes
witnesses (kernel/cache/LLM channels over the same canonical bytes)
from carriers (text/image/audio/world modalities). Line 284 still
used the conflated phrase 'multi-modality witness' that the meta-
comment was teaching against.
Update to 'multi-witness canonical-agreement' — consistent with
the doc's own clarification, with David's 2026-05-10 review of
#000037 (which renamed #000028's mechanism descriptor across the
controller spec for the same precision reason), and with the
2026-05-10 #000006 amend that uses the corrected vocabulary.
Closed-ticket references to #000028 by its actual title (Multi-
modality witness for canonical shapes) are intentionally not
touched — those are accurate citations of the ticket title, not
generic mechanism descriptors.
Doc-only update; no schema, no governance hash, no code change.
Third qualitatively different experimental shape in the rolling
research log, parallel to the 2026-05-09 witness-sweep widening:
- random-word emergent (honesty under no ground truth)
- witness-sweep (capability under canonical ground truth)
- warrant-chain (rescue-mechanism activation under chain-backed
ground truth) ← new
Captures the structurally-grounded dormancy of #000031 Phase 3
verifier — 0/117 fires across an aggressive A/B with 12/13
chain-root retrieval, plus 5 paraphrase fixture iterations
none of which drive Phase 3 to fire empirically.
Root cause pinned at arborist/qa/warrant.py:507: warrant_check
vacuous-passes unless question shape is relation/date/entity-list/
count/why-cause. Definitional questions don't have warrant shape;
claim-pack chunks are terse axioms without prose context that
warrant-shape questions would retrieve. Phase 3 is structurally
rescue-only on the current corpus.
Mechanism correct + non-regressing + unit-tested. Recommendation:
track fire rate as a corpus-evolution signal, not a fixture-
engineering target. Audit-line tail will surface organic fires.
Adjacent same-day landings noted: #000034 Phase 1a (Hessian-
alignment probe) + #000035 Phase 1 (φ_PRG reference) — both
KAT-pinned cryptographic-primitive infrastructure ahead of v7
plastic-training deployment.
Doc-only update; no code change.
Phase 1 plan §13.5 named four test files (3 unit + 1 integration)
but did NOT name CLI subprocess tests for the three new CLI
surfaces §13.4 introduces:
- arborist ingest --embed (flag on existing subcommand)
- arborist query --retrieval={fts5|vec|hybrid} (new flag)
- arborist vec rebuild (new subcommand)
Per docs/calculator-test-patterns.md §6 (codified earlier today
in commit 0725eb4 from the three-module pattern bench): import-only
tests miss argparse + main() drift. Yesterday's substrate refactor
caught this hazard three times — fork_score.py import (85be5eb),
Makefile bench-fork-score target (209d670), .gitlab-ci.yml job
+ script (b320e27). Each fix was 1-3 lines, but each had been
shipped to main + would have surfaced as a noisy CI failure on
next pipeline run.
§13.5 now adds three CLI subprocess test files:
- tests/test_cli_vec_rebuild.py
- tests/test_cli_ingest_embed_flag.py
- tests/test_cli_query_retrieval_flag.py
Each gated via pytest.importorskip("sqlite_vec") so they skip
cleanly when [vec] extras absent. Pattern matches fox's
test_cli_baseline_runs_clean / test_cli_invalid_input_exits_2
in tests/test_t3_bound_calculator.py (the exemplar for
calculator-style CLI tests).
§13.7 size estimate revised: 4 test files → 7 test files (+3 CLI
subprocess), 250 → 400 test LOC. CLI subprocess tests are
~30-40 LOC each (boilerplate + tmp_path + subprocess.run +
JSON parse). Phase 1 total grows from ~550+250 → ~550+400 LOC.
Doc-only edit; doesn't unblock or block fox's §13.8 four
decisions — the test-plan addition is mechanical discipline,
not a scope change. Phase 1 still gates on the four §13.8
decisions before any code lands.
Cross-ref: docs/calculator-test-patterns.md §6 (CLI subprocess
pattern) + the three substrate-rename defect commits caught by
that pattern in retrospect (85be5eb / 209d670 / b320e27).
Catches the regression class where a PR breaks argparse setup
(duplicate flag, broken set_defaults reference, renamed leaf
verb) without breaking any existing test. ``--help`` exercises
the parser-construction path without invoking any handler.
Coverage:
- top-level: arborist --help / --version / no-subcommand error
- 30 top-level subcommand --help calls (parametrized)
- 38 nested-subcommand --help calls across 9 verbs that have
their own subcommand groups (alias / memory / capital /
selfmodel / mesh / crawler / canon / substrate / snapshot)
- completeness check: top-level --help mentions every verb in
_TOP_LEVEL_SUBCOMMANDS (regression guard against silent
removal)
All 68 pass. ~20s wall via subprocess (~150ms per --help call x 68
calls + Python startup overhead). Fixture is hand-curated so a
new subcommand requires fixture update — that's the discipline
which surfaces the regression as a test failure rather than as a
missed --help test.
Pattern after fox: contract phrases pinned as test invariants
(here, the subcommand verb names) so silent renames fire the
test loud + force the fixture update + force the docstring +
help-text update too.
Captures the testing patterns surfaced from the three-module
pattern bench (anchor_prg / phi_alignment_probe /
t3_bound_calculator) as a docs/ architecture reference. Future
blackops shifts find it via grep instead of having to read commit
messages from de997f7 + a4b3056 + 35aeebb to reconstruct the
discipline.
Eight patterns codified:
1. KAT (known-answer-test) regression — pin (input, expected)
fixtures under bench/fixtures/<module>/
2. Hand-computed formula assertion — compute the spec's math
in the test file from first principles, assert agreement
3. Monotonicity per input axis — scaling one knob while
holding others fixed verifies the function responds in
the expected direction
4. Closure / sum-of-parts invariants — A + B + C ≡ total;
no missing terms, no double-counting
5. Parametrized invalid-input cones — collapse N
test_rejects_X functions into one @parametrize per
validation class
6. CLI subprocess end-to-end — argparse + main() drift the
import-only tests miss
7. Doc parity — pin the spec's worked-example numbers
against the function's actual output (catches doc drift,
which surfaced today as fox's calibration-pass note on the
T3 bound doc §11)
8. Module-export shape — version constants, asdict round-trip,
JSON-serializability, "v1" version-string discipline
Includes:
- "When to use" header that explicitly limits applicability to
calculator-style code (math-heavy, closed-form output, JSON-
serializing CLI)
- "When NOT to use" disclaimer that verifier / parser /
state-machine tests have their own appropriate structures
and shouldn't be retrofitted (saves future shifts the same
realization I had today walking warrant_resolver tests)
- A 9-item checklist for new calculator-style modules to land
with consistent test density
- Concrete code excerpts from the three exemplar test files
Architecture-reference convention followed (per docs/TICKETS.md
§ "Distinction from other docs"): docs/<filename>.md, no ticket
number, listed in the architecture-reference block. Joins
concept-relations-design.md, warrant-substrate-cookbook.md, and
the cti-architecture.md / mesh.md / etc. set.
docs/TICKETS.md amended with the new entry under "Distinction
from other docs".
#000034 Phase 1a landed 2026-05-10 (synthetic-ablation
infrastructure for the Hessian-alignment probe under φ_linear):
bench/scripts/phi_alignment_probe.py + 14 tests + KAT fixture
at bench/fixtures/phi-alignment/synthetic-checkpoints.jsonl.
Same closure-loop grooming pattern as 0b038f1 (§9.2 update for
#000035 Phase 1): the analysis doc already named the test path
in §9.1 but did not yet point at the artifacts that just shipped.
This commit closes the loop for §9.1 + updates §11 status block.
Phase 1b (the actual v7-checkpoint measurement that resolves the
open question and feeds C_B1 tightening per #000043) still parks
on v7 deployment ramp-up — same exogenous gate as #000035 Phase 2.
Doc-only update; no schema, no governance hash, no code change.
Adds a per-discipline test-file index to the cookbook so audit
reviewers can click through from a substrate discipline to the
unit-test pinning that prevents silent regression. Eight
sub-sections matching the live discipline groups:
- citation/term alias mechanism (#000041 + #000042) —
test_aliases.py 28 tests
- warrant-resolver chain (#000031 P1+2+3) —
test_warrant_resolver.py + test_warrant_chain.py
- textbook ingest license-discipline gate —
test_textbooks_manifest.py 43 tests
- cascade tuning (#000040 + parenthetical/OR-fallback) —
_phrase_from_parenthetical regression guard
- substrate-paper-spec'd primitives (#000012 + #000018 +
#000034 + #000036) — 6 test files
- Q&A / verifier scaffolding — test_qa_progress.py +
test_qa_prompts.py
- concept-relations write-side — test_concepts_extract.py
Plus a unit-test-density-vs-code table: small contract-defining
modules (weights, prompts, warrant_chain) sit at 1.4-3.6× test
LOC because they're foundation; larger modules (warrant_resolver,
aliases) settle at 0.5-1.0× because they're more code-with-tests-
per-feature than contract-with-tests-per-rule.
Code-review heuristic surfaced for future shifts: new
substrate-paper-spec'd primitive without ≥1× test/code ratio
is suspect on landing.
CLI version-bake sweep surfaced one real defect: the Phase 1 test
scaffolding I shipped in c422216 imported ``from arborist.v9
import prometheus``, baking in the version-prefixed namespace path
that yesterday's substrate refactor (654d923) abolished.
The skip mechanism (try/except ImportError → CONTROLLER_AVAILABLE
= False) was masking the issue: when fox lands Phase 1 of #000037
at ``arborist/substrate/prometheus.py`` (per the topic-named
convention), my tests would CONTINUE to skip with
"controller module arborist/v9/prometheus.py absent" because the
import target itself is wrong. The skip-stub becomes permanent
dormancy instead of activating when the module ships.
Two changes:
- Import line: ``from arborist.v9 import prometheus`` →
``from arborist.substrate import prometheus``.
- Skip-reason text + module-docstring: ``arborist/v9/prometheus.py``
→ ``arborist/substrate/prometheus.py``, with a parenthetical
noting the post-2026-05-10 topic-named convention and that
§13's original sketch predated the v-dir retirement.
The fix is a real one — when fox's Phase 1 of #000037 lands, my
17 skip-stubs now activate against the correct module path.
Without this fix, they'd silently stay dormant.
Sweep summary
=============
Walked every CLI subcommand --help (arborist top-level + nested
substrate / memory / capital / selfmodel / warrant-resolve / sweep
/ alias / mesh / crawl / providence) plus full-tree grep for
``arborist v[789]`` / ``arborist\\.v[789]`` / ``arborist/v[789]``.
Remaining v-prefix mentions across the tree (all intentional):
- arborist/cli.py:5166-5169 — historical-note comment for the
v8→substrate rename
- arborist/substrate/__init__.py:8 — same convention-explanation note
- arborist/substrate/anchor_prg.py:59 — bytestring inside SHA-256
derivation of placeholder seed; can't change without breaking KAT
- bench/fixtures/phi-prg/known-answer-tests.jsonl:1 — fixture header
naming the v7 paper section §9.10 (paper version, correct)
- docs/v8-fork-score.md:4 — historical-note ("module moved from")
- docs/tickets/ticket-000019, ticket-000013 — "arborist v9.8" schema
references (schema version, correct)
- docs/_source/merkle-agi-v7w-spatial-temporal.rst — v7 paper +
v9.8 schema references (both correct)
Tests: 1915 passing, 45 skipped (was 1872; +43 from fox's parallel
test additions during this commit's prep + the 17 prometheus
skips activating against the correct path stub).
CLI version-bake sweep complete. The substrate refactor is now
surface-clean end-to-end.
Same pattern-application as de997f7 did for test_anchor_prg.py.
The phi_alignment_probe tests landed in 1dfb8b9 with KAT
regression + verdict-bucket coverage + Lanczos convergence
check, but lacked the four patterns fox demonstrated in
test_t3_bound_calculator.py (51 cases for the T3 calculator):
monotonicity, hand-computed formula, closure invariants, and
parametrized invalid-input cones.
New tests added:
1. **test_monotone_alignment_strength_in_concentration** —
tighter W concentration on low-λ subspace must monotonically
increase the ratio. Tested across 32-row → 16-row → 8-row
concentrations, normalized to constant ‖W‖_F. Catches sign
errors + drops in the alignment-score formula.
2. **test_monotone_alignment_in_dim_h** — verdict invariant
under W column-count scaling. Sanity check that A(W, H)'s
‖W‖_F² normalization decouples it from sample count.
3. **test_uniform_baseline_matches_analytical_formula** —
hand-computes the isotropic baseline
``E[A_bot(W_uniform, H)] = (1/dim_d) Σ 1/(λ_j+ε)`` from
#000034 §2.1 derivation; asserts exact agreement with the
function's ``a_uniform`` field. Catches algorithm drift the
KAT regression would miss (KAT could regenerate against a
buggy implementation).
4. **test_full_spectrum_a_top_plus_a_bot_covers_full_isotropic_baseline**
— closure invariant: when k_top + k_bot = dim_d, the function's
a_top + a_bot must equal full-spectrum A computed via dense
numpy.linalg.eigh decomposition. Catches missing terms /
double-counting.
5. **test_eigenvalue_ordering_top_dominates_bot** — closure
invariant: top-k eigenvalues must all be ≥ bot-k eigenvalues.
Catches a bug where eigsh's 'LA'/'SA' modes returned
overlapping ranges on near-degenerate spectra.
6. **test_rejects_wrong_dim_w** — parametrized over (1-D, 3-D,
0-D scalar) shape errors. Same pattern as test_anchor_prg's
parametrized rejects.
7. **test_rejects_non_positive_epsilon** — parametrized over
(0, -1e-6, -1.0). Collapsed N separate test_rejects_*
functions into a single parametrized cone.
Test count: was 14 in test_phi_alignment_probe.py; now 23
(+9 from the new patterns + parametrize expansion).
Full suite: 1727 → 1872 (note: large jump partly from fox's
parallel test additions today, +136 since my last test count
checkpoint; my contribution here is +9 directly attributable
to this commit).
Three calculator/probe-style modules now have consistent
test coverage:
bench/scripts/t3_bound_calculator.py — 51 tests (fox)
bench/scripts/phi_alignment_probe.py — 23 tests (this commit)
arborist/substrate/anchor_prg.py — 27 tests (de997f7)
Same pattern bench applied across all three. Future
calculator-style code should pin: monotonicity in each input
axis + hand-computed formula assertions + closure / sum-of-parts
invariants + parametrized invalid-input cones.
Hygiene
=======
- make test → 1872 passed, 45 skipped
- make chain-check-shards → 0 across all 7 shards
- All new tests use synthetic inputs (no LLM, no shard
dependency); run in ~35s suite-wide
arborist/qa/prompts.py — 4 string constants that ARE the contract
with the LLM. Silent edits drop bench STRICT-rate by tens of
points; per CLAUDE.md "bench-maxing" discipline, prompt
regressions need a per-PR guard, not just bench surfacing after
the fact.
This test file pins the load-bearing phrases as regression
guards for both claim_lattice modes:
CLAIM_LATTICE_SYSTEM_PROMPT (pointer mode)
- non-empty + substantial
- both worked examples present (Apple founders + Mars descriptive)
- two-pointer cap rule (folds into claim_lattice_max_pointers_per_claim)
- pointer ID shape teaching (E1, E2, E3, [E#] / [E#,E#])
- one-claim-per-line rule (parser splits on newlines)
- synthetic-elision-by-construction-impossible: NO instruction
to wrap claims in double quotes (that's legacy quote-mode)
CLAIM_LATTICE_GROUNDING_REMINDER (pointer mode user-turn)
- "REMINDER" prefix; "pointer-line" format restated
- two-pointer cap restated
CLAIM_LATTICE_JSON_SYSTEM_PROMPT (JSON mode)
- schema shape: claims/text/evidence_ids
- first-char-`{` / last-char-`}` discipline
- two-evidence-id cap
CLAIM_LATTICE_JSON_GROUNDING_REMINDER (JSON mode user-turn)
- schema restated; cap restated
Cross-prompt parity
- both modes reference the two-pointer cap
- both reminders end with "next message" (handoff to question)
- all 4 constants importable + non-empty strings
Full suite: 1872 passed, 45 skipped.