arborist/docs/v8-fork-score.md
russell@unturf.com bae5cafe9a
CLI: arborist v8 score → arborist substrate score
Followup to 654d923 (which moved the package from arborist/v8/ →
arborist/substrate/ at the file layer). The CLI surface still baked
in `v8` so a new operator running `--help` would see
``arborist v8 score`` and ask the same "what's v8 vs v9.8?"
naming-confusion question that drove the package rename in the
first place. Closing the loop end-to-end.

arborist/cli.py
===============

- Subparser renamed: ``"v8"`` → ``"substrate"``; help string updated
  to "Merkle-AGI substrate primitives (ForkScore + future paper
  specs)" so the dir name and command name and help text all align.
- Inner subparser dest renamed: ``v8_op`` → ``substrate_op``.
- Function renamed: ``_cmd_v8_score`` → ``_cmd_substrate_score``;
  docstring updated.
- All ``v8_score`` local variables renamed to ``substrate_score``.
- New comment block above the subparser block explains the rename
  + why the v-prefix was retired (substrate-paper version vs v9.8
  schema version naming collision).

The old ``arborist v8 score`` is gone — no alias preserved. CI + ops
scripts must update; today's earlier commit chain has been the only
place using it and that's been refreshed in lock-step.

tests/test_v8_fork_score.py
===========================

- 4 ``parser.parse_args(["v8", "score", ...])`` calls → ``["substrate", ...]``.
- 4 test functions renamed: ``test_cli_v8_score_*`` →
  ``test_cli_substrate_score_*``.
- Module docstring + section comment + helper docstring updated.

Filename intentionally kept as ``test_v8_fork_score.py`` for git
history continuity; pytest discovers by ``test_*`` content, not
filename. Renaming the file would muddle ``git log --follow`` for
the test surface.

Docs refreshed
==============

- docs/v8-fork-score.md — §5 CLI block invocation.
- docs/_source/v8-fork-score.rst — :code-block:: bash invocation.
- docs/_source/bench.rst — invocation in `### v8 ForkScore` section.
- docs/tickets/ticket-000012-selection-consensus-protocol.md —
  three references in §7 close-out + §7 Phase 1c proposal +
  §7 future-CLI-shape note.
- docs/dav1dprometheus-update-2026-05-09.md — bench journal mention.

Doc filenames (``v8-fork-score.{md,rst}``) kept stable since they
are URL identities; the file content explains the v8→substrate
rename internally. ``index.rst`` toctree references unchanged.

Hygiene
=======
- ``.venv/bin/arborist substrate score --help`` → 0 + valid usage.
- ``.venv/bin/arborist v8 score`` → exits non-zero (subcommand
  removed, surfaced cleanly in ``argparse`` error).
- ``make test`` → 1643 passed, 45 skipped.
- ``make chain-check-shards`` → 0 across all 7 shards.
- fox's parallel work in arborist/qa/{runner,verify}.py +
  arborist/qa/warrant_chain.py left untouched.
2026-05-10 09:12:34 -04:00

8 KiB
Raw Blame History

v8 ForkScore — Phase 1a reference

Reference for arborist.substrate.fork_score (ticket #000012 Phase 1a; module moved from arborist.v8.fork_score to arborist.substrate.fork_score on 2026-05-10 when the version-prefixed namespace pattern was retired — the v in v8 referred to the substrate-paper version, which collided with the v9.8 SQLite schema version and confused readers). Pure scoring function over a (parent, child) BatteryResult pair. No validator state machine, no consensus protocol, no acceptance ledger — those are commissioned by the v8 paper itself, still open under #000012.

This document is the canonical source for the formula, term semantics, and verdict thresholds. Tests in tests/test_v8_fork_score.py enforce them.

1. Formula

ForkScore =
    α · Δ5S
  + β · Δ5T
  + γ · Δ5F                                  # incl. efficiency-aware bonus
  + δ · SelfModelCalibrationGain
  + ε · AuditCompleteness
  + ζ · ValidatorDiversity
  - η · RegressionPenalty
  - θ · CapitalCostPenalty
  - ι · SecurityRiskPenalty                  # reserved (Phase 1a = 0)
  - κ · ComplexityPenalty                    # reserved (Phase 1a = 0)
  - λ · MemoryInvalidationPenalty

Sign convention: weights are non-negative; the sign of each term is encoded in the formula. breakdown keys in the output reflect the sign:

{
  "alpha_x_delta_5s": 0.025,
  "minus_eta_x_regression_penalty": -0.0,
  "minus_lambda_x_memory_invalidation": -0.5,
  ...
}

2. Term semantics

2.1 Δ5S, Δ5T, Δ5F (Δ-rate over each battery)

Δ5S = mean of per-sub-battery rate deltas across the 5S battery:

syntax           parse_pass_rate
semantics        equivalence_recovery_rate
syllogism        step_validity_rate
synthesis        derivation_pass_rate
semiotics        invariance_under_swap

Δ5T = same shape, canonical Dav1DPrometheus vocabulary (the legacy transfer sub-battery is intentionally excluded so v2 fixtures drive the score):

transfer-learning   transfer_learning_success_rate
triangulation       triangulation_agreement_rate
truthtables         truth_table_coverage_rate
transitivity        full_chain_pass_rate
time                temporal_context_preservation_rate

Δ5F = mean of per-sub-battery rate deltas plus an efficiency-aware bonus:

function       function_pass_rate
finetuning     adaptation_improvement_rate
falsification  error_detection_rate
formulate      structural_match_rate
feedback-loop  integration_coverage_rate

The efficiency bonus is computed from the metrics shipped under ticket #000025's zero-cost guards:

  • adaptation_efficiency_mean_finite — Δ in mean efficiency, damped by 0.1 to keep efficiency from dominating rate-style improvements.
  • adaptation_efficiency_infinite_count — increase = bonus capped at INFINITE_BONUS_CAP (default 1.0). +∞ buckets must not pollute the ranking.
  • adaptation_efficiency_neg_infinite_count — increase = NEG_INF_REGRESSION flag. Hard reject (a free regression is unsafe).

Same shape applies to feedback_efficiency_* keys.

2.2 SelfModelCalibrationGain

Distance closed between SelfModel capability claim threshold and measured value. Phase 1a callers pass this as a scalar (default 0). Phase 1b will compute it from selfmodel_capability_claims history.

2.3 AuditCompleteness

Fraction of state-changing ops with an audit_event row. Phase 1a caller-supplied; Phase 1b reads from the chain directly. Range [0, 1]; missing rows visible in the audit chain bring this below 1.

2.4 ValidatorDiversity

Multi-validator agreement entropy. Zero in single-validator mode (Phase 1a default). v8 paper defines the multi-validator calibration. With ζ = 0 by default, this term has no effect on single-validator deployments.

2.5 RegressionPenalty

Sum over batteries of max(0, -Δ_battery). A battery whose mean delta is negative contributes its absolute value to the penalty term (multiplied by η).

This is softer than the hard-regression flag (§3.2): if 4 of 5 sub-batteries improve by 10pp and 1 drops by 8pp, the mean Δ is positive and RegressionPenalty = 0 — but the hard flag still fires on that one sub-battery.

2.6 CapitalCostPenalty

Capital cost delta from the #000020 ledger. Phase 1a accepts a scalar capital_delta; positive means the child costs more. Phase 1b will compute it from capital_ledger.summary.

2.7 SecurityRiskPenalty, ComplexityPenalty

Reserved for Phase 1b+. Defaults ι = κ = 0. No security-bench fixtures or LOC-delta surface exist in Phase 1a.

2.8 MemoryInvalidationPenalty

Count of memory_records rows the child fork would falsify. Phase 1a accepts a scalar; Phase 1b will compute it by simulating the fork's verifier-method-root delta and counting memory_records that cite the changed verifier.

3. Verdicts

3.1 Verdict thresholds

Score Hard flags Verdict
SIGNAL_FLOOR (0.05) none ACCEPT
[0, SIGNAL_FLOOR) none MARGINAL (insufficient signal)
< 0 any REJECT
any hard-regression OR neg-inf efficiency REJECT

CLI exit code: 0 for ACCEPT/MARGINAL, 1 for REJECT — so CI gates can run arborist substrate score … directly.

3.2 Hard flags

  • REGRESSION_5S/5T/5F: any single sub-battery dropping by ≥ HARD_REGRESSION_FLOOR (default 5pp). Reported per sub-battery in flags.
  • NEG_INF_REGRESSION: *_efficiency_neg_infinite_count increased parent → child. Free regression is unsafe regardless of other gains.

A hard flag forces REJECT even when the net score is positive. Operators can disable hard-flag gating in Phase 1b by overriding the _delta_* helpers — but the soft RegressionPenalty term stays in the formula.

4. Default weights

WeightSet(
    alpha=1.0,    # Δ5S
    beta=1.0,     # Δ5T
    gamma=1.0,    # Δ5F
    delta=0.5,    # SelfModelCalibrationGain
    epsilon=0.3,  # AuditCompleteness
    zeta=0.0,     # ValidatorDiversity (off in single-validator)
    eta=2.0,      # RegressionPenalty (heavy by design)
    theta=0.5,    # CapitalCostPenalty
    iota=0.0,     # SecurityRiskPenalty (reserved)
    kappa=0.0,    # ComplexityPenalty (reserved)
    lambda_=0.5,  # MemoryInvalidationPenalty
)

Override via JSON file passed to --weights:

{
  "alpha": 1.5,
  "eta": 5.0,
  "lambda": 1.0
}

(The JSON key "lambda" round-trips into WeightSet.lambda_ because lambda is a Python reserved word.)

5. CLI

arborist substrate score \
  --parent  parent-bench.json \
  --child   child-bench.json \
  [--weights weights.json] \
  [--capital-delta N] \
  [--selfmodel-calibration-gain N] \
  [--audit-completeness N] \
  [--memory-invalidation-count N]

parent-bench.json and child-bench.json are the JSON output of bench.batteries.runner --all for each organism. The CLI prints the ScoredFork as JSON and exits 0 on ACCEPT/MARGINAL, 1 on REJECT.

6. What's NOT in Phase 1a

  • Validator state machine (bonding / signing / slashing).
  • Acceptance protocol (proposal / quorum / finalization).
  • Challenge protocol (audit-replay disagreement).
  • Fork-choice rule (which of two competing finalizations wins).
  • Mesh wire format extensions for validator gossip.
  • Stake mechanics + economic incentives.
  • Cross-validator ZK proof exchange.

These are commissioned by the v8 paper itselfdocs/merkle-agi-v8-consensus.rst, still open under ticket #000012. Phase 1a's scoring function is the substrate the v8 paper consumes; landing it now lets the paper cite measured values instead of stipulated ones.

7. Closure of the gap fox identified

The 2026-05-08 review of fbd99a8 flagged: "the immediate frontier has shifted from 'build the fitness surface' to 'define how an organism mutation becomes canonical under that fitness surface.'"

Phase 1a closes the scoring half of that frontier. The canonicalization half (validator agreement, fork choice, slashing) remains under #000012 as the v8 paper deliverable.