The jurist's pre-25th condition: confirm lowercasing happens at exactly one point and is unit-tested against a known uppercase input. Single point confirmed at derive_fool.py:79 — the only .lower()/.upper()/ casefold in the file. Four checks added, including a negative control proving the test can fail. Selftest 16/16. Checking it found the defect the condition was aimed at, in my own work: the 2026-08-22 dry run lowercased the value OUTSIDE the code and passed it in already normalized, so the single normalization point was never exercised on uppercase input in the only end-to-end run. The test's subject was the pipeline; it excluded the step under scrutiny. Re-run with the raw uppercase value through the real path reproduces the same seed. Binding procedure added: on the 25th the outputValue is passed exactly as served. Jurist ruling on the URL correction recorded verbatim — no veto, with the reasoning, since it will be read later. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JQKeKY9T9d95KpvHwwok8T
162 lines
7.1 KiB
Python
Executable File
162 lines
7.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Fool bones derivation — PENDING-149 §6 / §6b.
|
|
|
|
Deterministic. No salt. No reroll path. Nothing is cached: the caller supplies
|
|
the two seed components and the bones are recomputed from them every time.
|
|
|
|
This file implements the FILED RULE (FOOL-SEED-RULE.md). Where this code and the
|
|
filed rule disagree, THE FILED RULE GOVERNS and this file is the defect.
|
|
|
|
Usage:
|
|
derive_fool.py --beacon <outputValue-hex> # bones from a pulse value
|
|
derive_fool.py --selftest # determinism + range checks, no network
|
|
"""
|
|
import argparse, hashlib, subprocess, sys
|
|
|
|
# ---- the filed rule's constants. Do not edit without amending the filed rule. ----
|
|
PROVENANCE_COMMIT = "4d2ae87a4e5350c4d3bb3aa50f9544b521d9c53d"
|
|
PROVENANCE_PATH = "CLAUDE.md"
|
|
PROVENANCE_REPO = "/Users/davidglidden/dotfiles"
|
|
PROVENANCE_SHA256 = "2d6e250a347d25698fb147f80e2dababbb930c4b3b3f9bb822478f360153120d"
|
|
|
|
AXES = ["SUCCESSION", "ABSENCE", "AIM", "SCALE", "STAKE"] # §5, ratified order
|
|
PEAK_RANGE = (85, 100) # "near max" — executor-specified, filed pre-beacon
|
|
DUMP_RANGE = (0, 15) # "near floor" — executor-specified, filed pre-beacon
|
|
SCATTER_RANGE = (25, 75) # "scattered" — executor-specified, filed pre-beacon
|
|
|
|
|
|
def provenance_sha() -> str:
|
|
"""SHA-256 of CLAUDE.md at the named past commit. Recomputed, never trusted from the constant."""
|
|
blob = subprocess.run(
|
|
["git", "-C", PROVENANCE_REPO, "cat-file", "-p", f"{PROVENANCE_COMMIT}:{PROVENANCE_PATH}"],
|
|
capture_output=True, check=True).stdout
|
|
got = hashlib.sha256(blob).hexdigest()
|
|
if got != PROVENANCE_SHA256:
|
|
raise SystemExit(f"STOP: provenance blob does not match the filed rule.\n"
|
|
f" filed: {PROVENANCE_SHA256}\n got: {got}")
|
|
return got
|
|
|
|
|
|
def fnv1a_32(data: bytes) -> int:
|
|
h = 0x811C9DC5
|
|
for b in data:
|
|
h ^= b
|
|
h = (h * 0x01000193) & 0xFFFFFFFF
|
|
return h
|
|
|
|
|
|
def mulberry32(a: int):
|
|
"""Reference Mulberry32, 32-bit wrapped to match the JS original exactly:
|
|
a = a + 0x6D2B79F5 | 0
|
|
t = Math.imul(a ^ a >>> 15, 1 | a)
|
|
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t
|
|
return ((t ^ t >>> 14) >>> 0) / 4294967296
|
|
"""
|
|
M = 0xFFFFFFFF
|
|
state = a & M
|
|
|
|
def imul(x, y):
|
|
r = (x * y) & M
|
|
return r - 0x100000000 if r & 0x80000000 else r
|
|
|
|
def rnd():
|
|
nonlocal state
|
|
state = (state + 0x6D2B79F5) & M
|
|
a_ = state
|
|
t = imul(a_ ^ (a_ >> 15), 1 | a_) & M
|
|
t = ((t + imul(t ^ (t >> 7), 61 | t)) & M) ^ t
|
|
return ((t ^ (t >> 14)) & M) / 4294967296.0
|
|
|
|
return rnd
|
|
|
|
|
|
def draw_int(rnd, lo: int, hi: int) -> int:
|
|
return lo + int(rnd() * (hi - lo + 1))
|
|
|
|
|
|
def derive(beacon_output_value: str) -> dict:
|
|
beacon = beacon_output_value.strip().lower()
|
|
if not beacon or any(c not in "0123456789abcdef" for c in beacon):
|
|
raise SystemExit("STOP: beacon outputValue must be non-empty lowercase hex.")
|
|
prov = provenance_sha()
|
|
seed_string = prov + beacon
|
|
seed = hashlib.sha256(seed_string.encode()).hexdigest()
|
|
rnd = mulberry32(fnv1a_32(seed.encode()))
|
|
|
|
order = list(range(len(AXES))) # Fisher-Yates over the PRNG
|
|
for i in range(len(order) - 1, 0, -1):
|
|
j = int(rnd() * (i + 1))
|
|
order[i], order[j] = order[j], order[i]
|
|
|
|
stats = {}
|
|
stats[AXES[order[0]]] = draw_int(rnd, *PEAK_RANGE)
|
|
stats[AXES[order[1]]] = draw_int(rnd, *DUMP_RANGE)
|
|
for k in order[2:]:
|
|
stats[AXES[k]] = draw_int(rnd, *SCATTER_RANGE)
|
|
|
|
return {"provenance_sha256": prov, "beacon_outputValue": beacon,
|
|
"seed_string": seed_string, "seed": seed,
|
|
"peak": AXES[order[0]], "dump": AXES[order[1]],
|
|
"stats": {a: stats[a] for a in AXES}}
|
|
|
|
|
|
def selftest() -> int:
|
|
"""No network. Fixed synthetic vectors only — never a live or near-future pulse."""
|
|
ok = True
|
|
V1 = "0" * 128
|
|
V2 = "f" * 128
|
|
r1, r1b, r2 = derive(V1), derive(V1), derive(V2)
|
|
checks = [
|
|
("determinism: same input twice -> identical bones", r1 == r1b),
|
|
("sensitivity: different beacon -> different seed", r1["seed"] != r2["seed"]),
|
|
("provenance recomputed matches filed rule", r1["provenance_sha256"] == PROVENANCE_SHA256),
|
|
("seed_string is prov||beacon, no salt", r1["seed_string"] == PROVENANCE_SHA256 + V1),
|
|
("exactly five axes", sorted(r1["stats"]) == sorted(AXES)),
|
|
("peak in range", PEAK_RANGE[0] <= r1["stats"][r1["peak"]] <= PEAK_RANGE[1]),
|
|
("dump in range", DUMP_RANGE[0] <= r1["stats"][r1["dump"]] <= DUMP_RANGE[1]),
|
|
("peak is not dump", r1["peak"] != r1["dump"]),
|
|
("three scattered in range", all(SCATTER_RANGE[0] <= v <= SCATTER_RANGE[1]
|
|
for a, v in r1["stats"].items()
|
|
if a not in (r1["peak"], r1["dump"]))),
|
|
("no floor: dump can reach the bottom of its range",
|
|
min(derive(f"{i:0128x}")["stats"][derive(f"{i:0128x}")["dump"]] for i in range(200)) <= DUMP_RANGE[0] + 1),
|
|
]
|
|
# --- normalization: the jurist's pre-25th condition. outputValue is served UPPERCASE. ---
|
|
UP = "A1B2C3D4E5F6" * 10 + "ABCDEFAB" # 128 chars, uppercase hex
|
|
LOW = UP.lower()
|
|
r_up, r_low = derive(UP), derive(LOW)
|
|
# independent expectation, computed here rather than read back from derive()
|
|
import hashlib as _h
|
|
expected_seed = _h.sha256((PROVENANCE_SHA256 + LOW).encode()).hexdigest()
|
|
wrong_seed = _h.sha256((PROVENANCE_SHA256 + UP ).encode()).hexdigest()
|
|
checks += [
|
|
("UPPERCASE input normalizes: bones identical to lowercase", r_up == r_low),
|
|
("UPPERCASE input matches independently computed seed", r_up["seed"] == expected_seed),
|
|
("recorded beacon field is stored lowercased", r_up["beacon_outputValue"] == LOW),
|
|
("NEGATIVE CONTROL: un-normalized input WOULD give a different seed "
|
|
"(so the check above can fail)", expected_seed != wrong_seed),
|
|
]
|
|
|
|
# positive control: the PRNG must actually move both peak and dump around the axes
|
|
peaks = {derive(f"{i:0128x}")["peak"] for i in range(200)}
|
|
dumps = {derive(f"{i:0128x}")["dump"] for i in range(200)}
|
|
checks.append(("POSITIVE CONTROL: peak lands on all five axes over 200 draws", peaks == set(AXES)))
|
|
checks.append(("POSITIVE CONTROL: dump lands on all five axes over 200 draws", dumps == set(AXES)))
|
|
for name, passed in checks:
|
|
print(f" {'PASS' if passed else 'FAIL'} {name}")
|
|
ok &= passed
|
|
print(f"\n{'SELFTEST PASSED' if ok else 'SELFTEST FAILED — do not run against a live pulse'}")
|
|
return 0 if ok else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
p = argparse.ArgumentParser()
|
|
p.add_argument("--beacon"); p.add_argument("--selftest", action="store_true")
|
|
a = p.parse_args()
|
|
if a.selftest:
|
|
sys.exit(selftest())
|
|
if not a.beacon:
|
|
p.error("--beacon <outputValue-hex> required (or --selftest)")
|
|
import json; print(json.dumps(derive(a.beacon), indent=2))
|