RQ1+RQ2 start-line: live per-cell condition assembler + guarded launcher + Holm ratification
Wire the live per-cell condition assembler (cmd_chat/sor/assembler.py): compose
the existing R1/R4/R5/R6 pieces into a condition-encoding CircuitSpec per frozen
§2 cell, so a cell_id maps to a genuinely distinct, ForwarderPlan-gated
(engine != local) isolated circuit rather than the plain 3-hop control:
- RQ1 bridge-on / on+padding insert a live bridge hop (+ R1 PADDING stream);
- RQ2 bridge-/directory-federated genuinely span >= 2 houses
(federation.select_federated_path, split-knowledge).
Plans only: opens no socket, moves no traffic, stands up no engine.
battery.assembler_dry_check validates on FIXTURES (6/6 cells distinct
fingerprints, all isolation-gated, same (cell,seed) reproduces, RQ1 bridge +
padding arms live, RQ2 federation >= 2 houses); write-once, kept out of any
confirmatory data dir. confirmatory_run preflight now runs it; the --operator-go
path no longer refuses cells as "not wired" — triple-lock + green preflight HOLD
on grid completion, then surface the operator's immutable data-run gate. No
confirmatory cell is ever fabricated.
Start-line instrument-validation gate (cmd_chat/sor/gate.py), grid + containment
pin (grid.py), and the guarded launcher (confirmatory_run.py) land alongside.
Holm: hold family_size = 7, report the 4 RQ1/RQ2 tests -> multipliers 7,6,5,4.
This is the pre-registration, not a deviation (prereg §6 [APPROVAL] size-7 family
+ D6 disclosure in the lead paper); docs/stage-05-holm-clarification.md marked
RATIFIED. RQ3-fold and alpha-split declined.
Containment intact; prereg untouched (SHA f22331a72e...); worktree-only. output/
gitignored (runtime artifacts, never source). Full SOR suite 156 passed. No
confirmatory data collected — the live data run remains the human gate.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
"""Live per-cell condition assembler — each §2 cell is a genuinely distinct,
|
||||
isolation-gated circuit, not the plain 3-hop control.
|
||||
|
||||
These are fixture-only checks: the assembler builds *plans* (ForwarderPlan targets),
|
||||
opens no socket, moves no traffic, and stands up no engine. We pin that each cell's
|
||||
structure encodes its condition, that determinism holds, that federated cells
|
||||
genuinely span >= 2 houses, and that a non-isolated engine is refused.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from cmd_chat.sor import battery
|
||||
from cmd_chat.sor.assembler import assemble, assemble_all
|
||||
from cmd_chat.sor.forwarder import ContainmentError
|
||||
|
||||
|
||||
def _cells_by_suffix():
|
||||
return {c.cell_id: c for c in battery.enumerate_cells()}
|
||||
|
||||
|
||||
def _assemble_cell(suffix, seed=7):
|
||||
cell = next(c for c in battery.enumerate_cells() if c.cell_id.endswith(suffix))
|
||||
return assemble(cell, seed)
|
||||
|
||||
|
||||
def test_all_cells_distinct_fingerprints():
|
||||
cells = battery.enumerate_cells()
|
||||
specs = assemble_all(cells, 0)
|
||||
fps = {s.fingerprint() for s in specs.values()}
|
||||
assert len(fps) == len(cells) == 6 # every cell is a distinct circuit
|
||||
|
||||
|
||||
def test_same_cell_seed_reproduces_fingerprint():
|
||||
cells = battery.enumerate_cells()
|
||||
a = assemble_all(cells, 0)
|
||||
b = assemble_all(cells, 0)
|
||||
assert {k: v.fingerprint() for k, v in a.items()} == {
|
||||
k: v.fingerprint() for k, v in b.items()
|
||||
}
|
||||
|
||||
|
||||
def test_different_run_index_changes_seed_and_circuit():
|
||||
cells = battery.enumerate_cells()
|
||||
a = assemble_all(cells, 0)
|
||||
b = assemble_all(cells, 1)
|
||||
for cid in a:
|
||||
assert a[cid].seed != b[cid].seed
|
||||
assert a[cid].fingerprint() != b[cid].fingerprint()
|
||||
|
||||
|
||||
def test_all_cells_isolation_gated():
|
||||
specs = assemble_all(battery.enumerate_cells(), 0)
|
||||
assert all(s.isolation_gated() for s in specs.values())
|
||||
|
||||
|
||||
def test_local_engine_is_refused():
|
||||
cell = battery.enumerate_cells()[0]
|
||||
with pytest.raises(ContainmentError):
|
||||
assemble(cell, 7, engine="local").plans()
|
||||
|
||||
|
||||
def test_rq1_bridge_off_is_plain_single_house():
|
||||
spec = _assemble_cell("bridge=off")
|
||||
assert spec.bridge_present is False and spec.padding_applied is False
|
||||
assert not any(h.is_bridge for h in spec.hops)
|
||||
assert spec.span_houses() == 1
|
||||
|
||||
|
||||
def test_rq1_bridge_on_inserts_a_bridge_hop():
|
||||
spec = _assemble_cell("bridge=on")
|
||||
assert spec.bridge_present is True and spec.padding_applied is False
|
||||
assert any(h.is_bridge for h in spec.hops)
|
||||
|
||||
|
||||
def test_rq1_bridge_on_padding_applies_padding():
|
||||
spec = _assemble_cell("bridge=on+padding")
|
||||
assert spec.bridge_present is True and spec.padding_applied is True
|
||||
assert any(h.is_bridge for h in spec.hops)
|
||||
|
||||
|
||||
def test_rq2_bridge_federated_spans_two_houses():
|
||||
spec = _assemble_cell("topo=bridge-federated")
|
||||
assert spec.bridge_present is True
|
||||
assert len({h.house for h in spec.hops if h.house != "bridge"}) >= 2
|
||||
|
||||
|
||||
def test_rq2_directory_federated_spans_two_houses():
|
||||
spec = _assemble_cell("topo=directory-federated")
|
||||
assert len({h.house for h in spec.hops}) >= 2
|
||||
|
||||
|
||||
def test_assembler_dry_check_all_green(tmp_path):
|
||||
summary = battery.assembler_dry_check(tmp_path / "asm")
|
||||
assert summary["all_green"] is True
|
||||
assert summary["distinct_fingerprints"] is True
|
||||
assert summary["all_isolation_gated"] is True
|
||||
assert summary["rq1_bridge_arms_live"] is True
|
||||
assert summary["rq1_padding_arm_live"] is True
|
||||
assert summary["rq2_federation_spans_2plus"] is True
|
||||
|
||||
|
||||
def test_assembler_dry_report_is_write_once(tmp_path):
|
||||
out = tmp_path / "asm"
|
||||
first = battery.assembler_dry_check(out)
|
||||
(out / "assembler-dry.json").read_text() # exists
|
||||
# A second call must not overwrite the immutable report.
|
||||
second = battery.assembler_dry_check(out)
|
||||
assert first["distinct_fingerprints"] == second["distinct_fingerprints"]
|
||||
@@ -0,0 +1,53 @@
|
||||
"""Confirmatory launcher — freeze guard + human-gate hold (no data collected).
|
||||
|
||||
The live preflight is exercised by the gate/battery/grid suites; here we pin the
|
||||
guard logic: the frozen-prereg SHA verifies, GO is refused without the operator
|
||||
token, a tokened GO holds on grid completion (3rd phone not up yet), and even a
|
||||
full grid holds for the operator rather than fabricating the data run.
|
||||
"""
|
||||
|
||||
from cmd_chat.sor import confirmatory_run as cr
|
||||
|
||||
|
||||
# A fully-ready preflight summary with the grid still completing (a device down).
|
||||
_READY_GRID_DOWN = {
|
||||
"out_dir": "x", "gate_all_green": True, "gate_offline_green": True,
|
||||
"grid_reachable": 2, "grid_engine_hosts": 1, "grid_down": ["tril"],
|
||||
"grid_honourable": True, "grid_full": False, "cell_plan": "p", "dry_ok": True,
|
||||
"assembler_ok": True, "assembler_distinct": True, "assembler_isolation_gated": True,
|
||||
"freeze_ok": True, "preflight_ready": True, "generated_utc": "now",
|
||||
}
|
||||
# The same, but with the full grid up (no device down).
|
||||
_READY_GRID_FULL = dict(_READY_GRID_DOWN, grid_down=[], grid_full=True)
|
||||
|
||||
|
||||
def test_frozen_prereg_sha_verifies():
|
||||
assert cr.verify_freeze() is True # on-disk prereg still matches the pin
|
||||
|
||||
|
||||
def test_go_refused_without_operator_token(monkeypatch):
|
||||
monkeypatch.setattr(cr, "preflight", lambda *a, **k: dict(_READY_GRID_DOWN))
|
||||
monkeypatch.delenv(cr.OPERATOR_TOKEN_ENV, raising=False)
|
||||
assert cr.main(["--operator-go", "--out", "x"]) == 2
|
||||
|
||||
|
||||
def test_go_holds_on_grid_completion(monkeypatch):
|
||||
monkeypatch.setattr(cr, "preflight", lambda *a, **k: dict(_READY_GRID_DOWN))
|
||||
monkeypatch.setattr(cr, "verify_freeze", lambda: True)
|
||||
monkeypatch.setenv(cr.OPERATOR_TOKEN_ENV, "1")
|
||||
# Triple-lock + green preflight + wired assembler, but grid still completing.
|
||||
assert cr.main(["--operator-go", "--out", "x"]) == 2
|
||||
|
||||
|
||||
def test_go_holds_for_operator_even_on_full_grid(monkeypatch):
|
||||
monkeypatch.setattr(cr, "preflight", lambda *a, **k: dict(_READY_GRID_FULL))
|
||||
monkeypatch.setattr(cr, "verify_freeze", lambda: True)
|
||||
monkeypatch.setenv(cr.OPERATOR_TOKEN_ENV, "1")
|
||||
# Full grid + all locks: the immutable data run is still the operator's to
|
||||
# initiate — the launcher does not fabricate confirmatory cells.
|
||||
assert cr.main(["--operator-go", "--out", "x"]) == 2
|
||||
|
||||
|
||||
def test_preflight_held_mode_returns_zero(monkeypatch):
|
||||
monkeypatch.setattr(cr, "preflight", lambda *a, **k: dict(_READY_GRID_DOWN))
|
||||
assert cr.main(["--out", "x"]) == 0 # no --operator-go: held, no data
|
||||
@@ -0,0 +1,43 @@
|
||||
"""Instrument-validation gate re-confirmation — offline items (2-6).
|
||||
|
||||
Item 1 (live 3-hop e2e) needs a docker daemon + sor-hop image, so it is exercised
|
||||
separately by the forwarder e2e test; here we drive the gate with ``allow_live=
|
||||
False`` and assert every *offline* item is green and the report is write-once.
|
||||
"""
|
||||
|
||||
import json
|
||||
|
||||
from cmd_chat.sor import gate
|
||||
|
||||
|
||||
def test_offline_gate_items_all_green(tmp_path):
|
||||
report = gate.run_gate(tmp_path, allow_live=False)
|
||||
assert report["offline_items_green"] is True
|
||||
by_n = {it["n"]: it for it in report["items"]}
|
||||
for n in (2, 3, 4, 5, 6):
|
||||
assert by_n[n]["status"] == "green", (n, by_n[n])
|
||||
# With live disabled, item 1 is 'unavailable' (not a red failure).
|
||||
assert by_n[1]["status"] == "unavailable"
|
||||
assert report["all_green"] is False # item 1 not confirmed in this offline run
|
||||
|
||||
|
||||
def test_gate_report_is_write_once(tmp_path):
|
||||
gate.run_gate(tmp_path, allow_live=False)
|
||||
path = tmp_path / "gate-report.json"
|
||||
first = path.read_text()
|
||||
gate.run_gate(tmp_path, allow_live=False) # second call must not overwrite
|
||||
assert path.read_text() == first
|
||||
doc = json.loads(first)
|
||||
assert doc["schema"] == "sor-gate-report/1"
|
||||
|
||||
|
||||
def test_item5_isolation_refuses_local_accepts_docker(tmp_path):
|
||||
report = gate.run_gate(tmp_path, allow_live=False)
|
||||
ev = next(it["evidence"] for it in report["items"] if it["n"] == 5)
|
||||
assert ev["refused_local"] and ev["refused_unknown"] and ev["accepts_docker"]
|
||||
|
||||
|
||||
def test_item4_entropy_is_exact_log2n(tmp_path):
|
||||
report = gate.run_gate(tmp_path, allow_live=False)
|
||||
ev = next(it["evidence"] for it in report["items"] if it["n"] == 4)
|
||||
assert all(c["exact"] for c in ev["checks"])
|
||||
Reference in New Issue
Block a user