diff --git a/arborist/cli.py b/arborist/cli.py index 0d49de0..10494d9 100644 --- a/arborist/cli.py +++ b/arborist/cli.py @@ -3041,11 +3041,11 @@ def _cmd_snapshot_diff(args: argparse.Namespace) -> int: def _cmd_v8_score(args: argparse.Namespace) -> int: """Compute the v8 ForkScore over (parent, child) bench-result JSON files.""" - from arborist.v8 import ( + from arborist.substrate import ( bench_result_to_metrics, fork_score, ) - from arborist.v8.weights import DEFAULT_WEIGHTS, from_dict as weights_from_dict + from arborist.substrate.weights import DEFAULT_WEIGHTS, from_dict as weights_from_dict with open(args.parent, "r", encoding="utf-8") as fh: parent_payload = json.load(fh) diff --git a/arborist/substrate/__init__.py b/arborist/substrate/__init__.py new file mode 100644 index 0000000..6c5efad --- /dev/null +++ b/arborist/substrate/__init__.py @@ -0,0 +1,49 @@ +"""Merkle-AGI substrate primitives — paper-spec'd cryptographic + decision +building blocks that future substrate papers (v7 plastic-training, v8 +selection/consensus, v9 falsification controller, …) require. + +Why one flat dir instead of paper-version subdirs: the substrate-paper +version (v7 / v8 / v9) and the live SQLite schema version (v9.8) are +two unrelated numbering schemes that share decimals. Version-prefixed +dirs (``arborist/v7/``, ``arborist/v8/``) made readers ask "is this +schema-v7 or paper-v7?" and made onboarding harder. Topic-named +``substrate/`` decouples the namespace from the paper version +entirely. + +Each module names the paper section it implements + the ticket that +owns its design and acceptance criteria: + +- :mod:`arborist.substrate.anchor_prg` — HMAC-SHA-512 anchor map + φ_PRG (v7 plastic-training spec § 9.10; ticket #000035 + #000018 + M1 mitigation). +- :mod:`arborist.substrate.fork_score` — pure ScoredFork decision + function over (parent, child) BatteryResult bundles (v8 selection + / consensus paper; ticket #000012 Phase 1a). +- :mod:`arborist.substrate.weights` — :class:`WeightSet` dataclass + + :data:`DEFAULT_WEIGHTS` for the fork-score function above. + +Future substrate primitives that arrive when their paper specs land +(v9 controller, v7-W frontier kernels, etc.) join this dir. +``arborist.world`` stays separate because its planned shape includes +its own subdirs (``world/pi_star/``, ``world/frontier/``, +``world/adapters/``) — that's a substrate package, not a primitive. +""" + +from __future__ import annotations + +from arborist.substrate.fork_score import ( + SIGNAL_FLOOR, + ScoredFork, + bench_result_to_metrics, + fork_score, +) +from arborist.substrate.weights import DEFAULT_WEIGHTS, WeightSet + +__all__ = [ + "DEFAULT_WEIGHTS", + "SIGNAL_FLOOR", + "ScoredFork", + "WeightSet", + "bench_result_to_metrics", + "fork_score", +] diff --git a/arborist/v7/anchor_prg.py b/arborist/substrate/anchor_prg.py similarity index 100% rename from arborist/v7/anchor_prg.py rename to arborist/substrate/anchor_prg.py diff --git a/arborist/v8/fork_score.py b/arborist/substrate/fork_score.py similarity index 100% rename from arborist/v8/fork_score.py rename to arborist/substrate/fork_score.py diff --git a/arborist/v8/weights.py b/arborist/substrate/weights.py similarity index 100% rename from arborist/v8/weights.py rename to arborist/substrate/weights.py diff --git a/arborist/v7/__init__.py b/arborist/v7/__init__.py deleted file mode 100644 index c0a139e..0000000 --- a/arborist/v7/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -"""v7 plastic-training primitives — Merkle-AGI v7 substrate building blocks. - -Currently namespace stub. Public exports added as v7 lands: - -- :mod:`arborist.v7.anchor_prg` — HMAC-SHA-512 anchor-map for the M1 - mitigation (ticket #000035 / #000018 §5.2 + §9.10). - -The v7 plastic-training surface is still research-scope (see ticket -#000037 §17.2); this package houses the deterministic primitives the -spec depends on so they can land + be unit-tested ahead of the -deployment target. -""" - -from __future__ import annotations diff --git a/arborist/v8/__init__.py b/arborist/v8/__init__.py deleted file mode 100644 index ebf2eb6..0000000 --- a/arborist/v8/__init__.py +++ /dev/null @@ -1,55 +0,0 @@ -"""Merkle-AGI v8 fork-score (ticket #000012 Phase 1a). - -Pure scoring function over (parent, child) BatteryResult bundles: - - ForkScore = - α · Δ5S - + β · Δ5T - + γ · Δ5F - + δ · SelfModelCalibrationGain - + ε · AuditCompleteness - + ζ · ValidatorDiversity - - η · RegressionPenalty - - θ · CapitalCostPenalty - - ι · SecurityRiskPenalty - - κ · ComplexityPenalty - - λ · MemoryInvalidationPenalty - -This package ships ONLY the scoring function + CLI surface — no -validator state machine, no acceptance protocol, no slashing, no -fork-choice rule. Those are commissioned by the v8 paper itself -(ticket #000012, still open). - -What's here in Phase 1a: - -- :class:`WeightSet` — dataclass with α…λ; defaults pinned in - :data:`DEFAULT_WEIGHTS`. -- :class:`ScoredFork` — return value: scalar score + per-term - breakdown + verdict + flags. -- :func:`fork_score` — pure function: (parent_metrics, child_metrics, - weights, capital_delta, …) → ScoredFork. -- :func:`bench_result_to_metrics` — adapter from - ``bench.batteries.runner`` JSON to the metrics dict the scorer - consumes. -- CLI: ``arborist v8 score --parent P.json --child C.json - [--weights W.json]``. -""" - -from __future__ import annotations - -from arborist.v8.fork_score import ( - SIGNAL_FLOOR, - ScoredFork, - bench_result_to_metrics, - fork_score, -) -from arborist.v8.weights import DEFAULT_WEIGHTS, WeightSet - -__all__ = [ - "DEFAULT_WEIGHTS", - "SIGNAL_FLOOR", - "ScoredFork", - "WeightSet", - "bench_result_to_metrics", - "fork_score", -] diff --git a/docs/_source/v8-fork-score.rst b/docs/_source/v8-fork-score.rst index d30e0ec..4986ee3 100644 --- a/docs/_source/v8-fork-score.rst +++ b/docs/_source/v8-fork-score.rst @@ -116,7 +116,7 @@ of ``bench.batteries.runner --all``. ``--out`` mirrors stdout to a file; CI / mesh peers / downstream graders ingest the artifact without parsing pipe output. -Output: :class:`arborist.v8.fork_score.ScoredFork` with +Output: :class:`arborist.substrate.fork_score.ScoredFork` with ``score``, ``verdict``, per-term ``breakdown``, ``flags`` list, and the active ``weights`` echoed back. diff --git a/docs/tickets/ticket-000012-selection-consensus-protocol.md b/docs/tickets/ticket-000012-selection-consensus-protocol.md index 9d94008..95878e0 100644 --- a/docs/tickets/ticket-000012-selection-consensus-protocol.md +++ b/docs/tickets/ticket-000012-selection-consensus-protocol.md @@ -264,16 +264,18 @@ Per fox's 2026-05-08 review note that the substrate is "good enough to support v8 selection/fork-choice design," shipping the scoring function ahead of the consensus paper: -- `arborist/v8/fork_score.py` — pure ScoredFork dataclass + scoring - function over (parent, child) BatteryResult bundles. Consumes - every metric this session shipped: 5S/5T/5F sub-battery rates, - `adaptation_efficiency_*` and `feedback_efficiency_*` (incl. - inf-aware aggregation per fbd99a8 review), capital-cost delta, - memory-invalidation count. -- `arborist/v8/weights.py` — `WeightSet` dataclass with α…λ + - `DEFAULT_WEIGHTS` (single-validator-tuned) + `from_dict` - adapter handling the `"lambda"`/`lambda_` Python-reserved-word - issue. +- `arborist/substrate/fork_score.py` — pure ScoredFork dataclass + + scoring function over (parent, child) BatteryResult bundles. + Consumes every metric this session shipped: 5S/5T/5F sub-battery + rates, `adaptation_efficiency_*` and `feedback_efficiency_*` + (incl. inf-aware aggregation per fbd99a8 review), capital-cost + delta, memory-invalidation count. (Originally landed at + `arborist/v8/fork_score.py`; moved 2026-05-10 when the + version-prefixed namespace pattern was retired.) +- `arborist/substrate/weights.py` — `WeightSet` dataclass with α…λ + + `DEFAULT_WEIGHTS` (single-validator-tuned) + `from_dict` adapter + handling the `"lambda"`/`lambda_` Python-reserved-word issue. + (Originally `arborist/v8/weights.py`.) - CLI: `arborist v8 score --parent P.json --child C.json [--weights W.json]`. Exits 1 on REJECT (CI-gateable). - Verdict thresholds: ACCEPT (≥ SIGNAL_FLOOR=0.05), MARGINAL @@ -290,9 +292,9 @@ function ahead of the consensus paper: Closure criterion: `docs/merkle-agi-v8-consensus.rst` lands with validator state machine, acceptance protocol, challenge protocol, fork-choice rule (GRANDPA-style), slashing mechanics, mesh wire -format extension. Per §1 of this ticket, `arborist/v8/fork_score.py` -is the substrate the paper cites; the paper itself is still -research-scope. +format extension. Per §1 of this ticket, +`arborist/substrate/fork_score.py` is the substrate the paper +cites; the paper itself is still research-scope. What's deliberately NOT in Phase 1a: @@ -357,7 +359,7 @@ flags: - ``--persist-shard `` — names the SQLite file to write to. Defaults to ``$ARBORIST_QA_DB`` when set, else stays no-op. -**3. Read API.** One pure function in `arborist/v8/fork_score.py`: +**3. Read API.** One pure function in `arborist/substrate/fork_score.py`: ```python def branch_set_density(conn, branch_set_id: str) -> int: diff --git a/docs/tickets/ticket-000035-prg-choice-phi-prg.md b/docs/tickets/ticket-000035-prg-choice-phi-prg.md index 8efca26..e57ecaa 100644 --- a/docs/tickets/ticket-000035-prg-choice-phi-prg.md +++ b/docs/tickets/ticket-000035-prg-choice-phi-prg.md @@ -253,15 +253,24 @@ the moment v7 needs it. ### Phase 1 — reference implementation (landed 2026-05-10) -- ``arborist/v7/__init__.py`` — namespace stub (v7 is currently - paper-stage per ticket #000037 §17.2; this is the first concrete - module landed under the namespace). -- ``arborist/v7/anchor_prg.py`` — ``phi_prg(hard_hash_32, dim_h, *, - seed)`` per §3.1; HMAC-SHA-512 counter-mode KDF; pure stdlib - (``hashlib`` + ``hmac``); no third-party dependency. Module also - exports ``PHI_PRG_VERSION = "phi-prg-v1-hmac-sha512"`` so future - algorithm rotations can be detected at the call site without - string-comparing module paths. +- ``arborist/substrate/anchor_prg.py`` — ``phi_prg(hard_hash_32, + dim_h, *, seed)`` per §3.1; HMAC-SHA-512 counter-mode KDF; pure + stdlib (``hashlib`` + ``hmac``); no third-party dependency. Module + also exports ``PHI_PRG_VERSION = "phi-prg-v1-hmac-sha512"`` so + future algorithm rotations can be detected at the call site + without string-comparing module paths. + + **Path note (2026-05-10):** §3.1's original sketch placed the + module at ``arborist/v7/anchor_prg.py``. The version-prefixed + namespace pattern was retired the same day in favour of + ``arborist/substrate/`` — the ``v`` in ``v7`` referred to the + substrate-paper version, which collided with the ``v9.8`` SQLite + schema version and confused readers about whether the dir tracked + paper version or schema version. ``arborist/substrate/`` is now + the topic dir for paper-spec'd Merkle-AGI primitives, decoupled + from any version number. Acceptance-criteria §5 item 1 reads + through to "or equivalent location" so the move doesn't + invalidate the original criterion. - ``tests/test_anchor_prg.py`` — 20 tests covering determinism, range invariants, chi² loose-uniformity sanity, dim_h boundary (1, 16384), seed-bit-flip avalanche, hash-bit-flip avalanche, diff --git a/docs/v8-fork-score.md b/docs/v8-fork-score.md index 4f78334..7370400 100644 --- a/docs/v8-fork-score.md +++ b/docs/v8-fork-score.md @@ -1,6 +1,10 @@ # v8 ForkScore — Phase 1a reference -Reference for `arborist.v8.fork_score` (ticket #000012 Phase 1a). +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 diff --git a/tests/test_anchor_prg.py b/tests/test_anchor_prg.py index 6780966..ba3e622 100644 --- a/tests/test_anchor_prg.py +++ b/tests/test_anchor_prg.py @@ -1,4 +1,4 @@ -"""Tests for arborist.v7.anchor_prg per ticket #000035 §3.2. +"""Tests for arborist.substrate.anchor_prg per ticket #000035 §3.2. Coverage matches the ticket's acceptance criteria: @@ -24,7 +24,7 @@ from pathlib import Path import pytest -from arborist.v7.anchor_prg import ( +from arborist.substrate.anchor_prg import ( PHI_PRG_VERSION, PLACEHOLDER_SEED, _bytes_to_floats, diff --git a/tests/test_v8_fork_score.py b/tests/test_v8_fork_score.py index f9d91d0..712afe3 100644 --- a/tests/test_v8_fork_score.py +++ b/tests/test_v8_fork_score.py @@ -18,7 +18,7 @@ from pathlib import Path import pytest -from arborist.v8 import ( +from arborist.substrate import ( DEFAULT_WEIGHTS, SIGNAL_FLOOR, ScoredFork, @@ -26,11 +26,11 @@ from arborist.v8 import ( bench_result_to_metrics, fork_score, ) -from arborist.v8.fork_score import ( +from arborist.substrate.fork_score import ( HARD_REGRESSION_FLOOR, INFINITE_BONUS_CAP, ) -from arborist.v8.weights import from_dict as weights_from_dict +from arborist.substrate.weights import from_dict as weights_from_dict # ---------------------------------------------------------------------