Files
dotfiles/claude/governance/fool/seed/FOOL-SEED-RULE.md
T
David F GliddenandClaude Opus 5 1e40b01d70 [FIX] Normalization tested at its single point; the dry run had bypassed it (PENDING-149)
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
2026-08-22 21:30:16 +02:00

13 KiB
Raw Blame History

name, description, metadata
name description metadata
FOOL-SEED-RULE The filed rule required by PENDING-149 §4 steps 1-4: ratified axes, seed derivation rule (both components), retirement and regeneration criteria. Filed and pushed BEFORE the beacon timestamp 2026-08-25T12:00:00Z. Governs derive_fool.py; where the code and this rule disagree, THIS RULE GOVERNS.
node_type type
governance-artifact reference

FOOL SEED DERIVATION RULE — filed 2026-08-22

Filed and pushed before the beacon timestamp, as §4 requires. Nothing has been derived. No target pulse has been fetched. This document governs derive_fool.py; where the code and this rule disagree, the rule governs and the code is the defect.


1 · Perception axes — RATIFIED

Ratified by the steward in writing, 2026-08-22. The steward ratified the five verbally ("Perfect", after §5a was settled) and then directed that the ratification be recorded explicitly rather than resting on v2's §5 heading — "a heading asserting ratification and a deliverable requiring it are two different records." This section is that record.

axis question
SUCCESSION would this be legible to someone arriving cold, with no thread?
ABSENCE what is not here, not asked, not yet existing?
AIM is this the right question, at the right level?
SCALE is the unit right? (item vs block vs programme)
STAKE who bears the cost if this is wrong?

A sixth PROCEDURE axis was proposed by the executor and declined by the jurist (v2 §5a) on structural grounds the executor accepts: procedure failures are checkable, §2 makes gradeable output a design failure, and a PROCEDURE-peaked fool would produce nothing but gradeable observations. Redirected to a separate [HARDENING] extension of governance-drift-check.py.

Order is fixed as listed — the derivation permutes over this order, so it is part of the rule, not presentation.

2 · The filed rule

FOOL SEED DERIVATION RULE
Filed: 2026-08-22         Governs: PENDING-149 §6

ENTROPY COMPONENT
  Source:    NIST Randomness Beacon v2.0, https://beacon.nist.gov/beacon/2.0/
  Retrieval: GET https://beacon.nist.gov/beacon/2.0/pulse/time/1787659200000
             (= 2026-08-25T12:00:00Z in epoch milliseconds)
  Field:     pulse.outputValue, hex, LOWERCASED before use
  Transport: curl. See §5 — python urllib cannot reach the host in this environment.

PROVENANCE COMPONENT
  File:      CLAUDE.md (repo root) in ~/dotfiles, at commit
             4d2ae87a4e5350c4d3bb3aa50f9544b521d9c53d
  Value:     SHA-256 of the file contents at that commit, hex, lowercase
             = 2d6e250a347d25698fb147f80e2dababbb930c4b3b3f9bb822478f360153120d
  Note:      contributes provenance, NOT unpredictability. Past commit,
             named by full hash. Verify with:
               git -C ~/dotfiles cat-file -p \
                 4d2ae87a4e5350c4d3bb3aa50f9544b521d9c53d:CLAUDE.md | shasum -a 256

SEED
  seed_string = <provenance-sha256> || <beacon-outputValue-lowercased>
  seed        = SHA-256(seed_string), hex, lowercase

DERIVATION
  seed -> FNV-1a (32-bit) -> Mulberry32 -> stat draws over the five axes of §1.
  One peak, one dump, three scattered. No salt from any reference
  implementation.

EXECUTION
  Run ONCE. The executor does not retry on its own authority.
  A re-run against the SAME recorded outputValue is legitimate (broken
  implementation). A re-run against a LATER pulse is a new draw, governed
  by §4 REGENERATION.
  Record outputValue the moment it is fetched, before running anything.

UNAVAILABILITY
  If no pulse is returned at or after the stated timestamp, retry the same
  request for up to 24 hours. If still unavailable: STOP and report. Do not
  substitute a different timestamp, beacon, or source.

TESTING
  Dry runs use a fixed historical pulse only. Never the target pulse, never
  a near-future pulse.

2a · ⚠ Two corrections to the v2 §6b block — RULED, no veto

⚠ JURIST RULING, 2026-08-22: no veto; the correction stands. Recorded with its reasons, since it will be read later.

The UNAVAILABILITY clause forbids substituting a different timestamp, beacon, or source. None of the three changed. Same beacon (NIST v2.0), same pulse (2026-08-25T12:00:00Z, epoch-ms 1787659200000), same field. What changed is the address at which the identical object is retrieved — the difference between a wrong phone number and a different person.

The test that settles it: could this correction have moved the outcome? No. The pulse's value does not exist yet and does not depend on the URL used to fetch it. A substitution rule exists to prevent redraws; a correction that cannot affect the draw is not one. Read otherwise, the clause would forbid fixing a typo in a field name, and would have guaranteed a stop on the 25th for a reason unrelated to entropy — the opposite of what it protects.

The two corrections, marked rather than silent:

The draft said to commit its block verbatim. Two values in it do not resolve, and a rule that cannot be resolved on the day is not a rule (v2's own standard). Both changes are recorded here for veto rather than absorbed quietly.

(a) The provenance commit — changed on the steward's direction, 2026-08-22. 3b0730d59336113aa3a500a889a3e154be6a1de7 → 4d2ae87a4e5350c4d3bb3aa50f9544b521d9c53d. The draft's stated rationale — "the constitution as it stood before the fool was conceived" — was false of the original: it is dated 2026-08-06, five days after trial 01, its subject line names the PENDING-89 docket (the question §11 forbids the fool from being cited on), and Constraint 6 is already present in it. Verified: at 4d2ae87 (2026-07-28) Differently biased checkers occurs 0 times, and exactly one CLAUDE.md exists at that commit.

(b) The retrieval URL — corrected on evidence, and this is the executor's change. The block's GET /pulse?timeGE=2026-08-25T12:00:00Z returns HTTP 302 with an empty body, redirecting to https://csrc.nist.gov/projects/interoperable-randomness-beacons — an HTML page, not JSON. Measured 2026-08-22 against a historical timestamp. /beacon/2.0/pulse/time/<epoch-ms> returns 200 and the expected JSON.

⚠ Had this been filed verbatim, the 25th would have produced no pulse, the UNAVAILABILITY clause would have run its 24-hour retry against a URL that cannot ever return one, and the rule would have STOPPED — correctly, and for the wrong reason. Found only because §6b's TESTING clause directs a historical dry run.

This is the same beacon, the same source and the same pulse — only the address form changes. The executor judges that correcting an unresolvable address for the named source is not "substituting a different beacon or source". If the jurist reads it otherwise, this is the line to strike, and it must be struck before 2026-08-25.

3 · Draw ranges — EXECUTOR-SPECIFIED, declared

v2 says "one peak (near max), one dump (near floor), three scattered" without numbers. The executor supplies them. Filed before the beacon value is known, which is what makes them non-steering: they set magnitudes, while the permutation — driven entirely by the entropy component — decides which axis receives which.

role range (inclusive)
peak 85–100
dump 0–15
scattered ×3 25–75

No floor is applied to the dump — it can reach 0. v2 §3 forbids the rarity mechanic precisely because it would soften the dump.

4 · Pre-registered criteria (§4 steps 3 and 4)

⚠ Naming note: §4 step 3 calls for an "abandonment criterion"; §10 defines RETIREMENT. They are the same criterion under two names; §10 is the referent.

REGENERATION — permitted ONLY on a demonstrable implementation error, verified against this filed rule. Not because the output is disliked. A re-run against the same recorded outputValue is legitimate; a re-run against a later pulse is a new draw.

RETIREMENT (abandonment) — only on mechanical failure: does not fire; fires constantly; or produces gradeable in-genre findings despite §9.

NOT grounds for retirement: being uncomfortable, being frequently wrong, being annoying, being ignored. Those are the specification. Lear ignores his Fool for four acts and the Fool is not thereby broken.

4a · ⚠ The uppercase finding is the more serious of the two — jurist's assessment, adopted

outputValue served uppercase against a rule specifying lowercase is a silent seed divergence — the pipeline would have run clean, produced bones, and nobody could have said afterwards which normalization had been applied. That is worse than the URL failure, which at least announced itself.

Both were caught by the TESTING clause's historical dry run. The clause justified itself twice on its first use, and that is recorded here rather than left to inference.

5 · Implementation and its verification

derive_fool.py, same directory. Deterministic, no cache, no reroll path, no salt. It recomputes the provenance SHA from git on every run and refuses to proceed if it disagrees with this rule.

--selftest runs 12 checks with no network and no live pulse — synthetic vectors only — including two positive controls proving the PRNG moves both peak and dump across all five axes over 200 draws. All 12 pass as of 2026-08-22.

End-to-end dry run, 2024-01-01T12:00:00Z pulse (a fixed historical pulse, per TESTING): pipeline verified from fetch through bones. That output is not the fool and is recorded nowhere as bones.

⚠ Transport constraint, measured: curl reaches the beacon; python urllib times out in this environment. The fetch on the 25th must use curl.

⚠ outputValue is served UPPERCASE (128 hex chars). The rule's "lowercased before use" is therefore load-bearing, not cosmetic — omitting it yields a different seed.

5a · Normalization — the jurist's pre-25th condition, DISCHARGED

Confirmed: lowercasing is applied at exactly ONE point — derive_fool.py:79, beacon_output_value.strip().lower(), inside derive(). It is the only .lower(), .upper() or casefold in the file. Every downstream use, including the recorded beacon_outputValue field, reads from that single normalized value.

Unit-tested against a known uppercase input, four checks, including one that proves the test can fail:

check
UPPERCASE input normalizes: bones identical to lowercase PASS
UPPERCASE input matches an independently computed seed (not read back from derive()) PASS
the recorded beacon field is stored lowercased PASS
NEGATIVE CONTROL: un-normalized input would give a different seed PASS

⚠ Checking this found that the 2026-08-22 dry run had bypassed the step it was meant to verify. The run lowercased the value outside the code (ov.lower() into a temp file) and passed it in already normalized, so the single normalization point was never exercised on an uppercase input in the only end-to-end run. The test's subject was the pipeline; it silently excluded the step under scrutiny — the same wrong-subject shape the record has been tracking all week.

Re-run with the RAW uppercase value through the real path, 2024-01-01 pulse: seed d8e5e74def52c7cd…, identical to the pre-lowercased run. Normalization verified in the path that will actually be used.

⚠ PROCEDURE FOR THE 25th, binding: the fetched outputValue is passed to derive_fool.py exactly as served. It is never lowercased, trimmed or otherwise normalized by any wrapper, shell step or hand edit before it reaches derive(). One normalization point, and it is in the code.

5b · Owed after the 25th, non-blocking

[FIX] — 'abandonment' → 'retirement' throughout the fool's doctrine. The jurist owns the mismatch (§4 step 3 says abandonment, §10 defines RETIREMENT) and rules that the fool's own doctrine should read retirement, one word with one meaning — abandonment is the word §6 of the trial design owns, with a specific sense about the jester form. Naming rather than silently harmonizing was correct; the harmonization is a [FIX] after the beacon, so no edit touches this rule before it fires.

The mumble-hook answer (v2 §8) — clock-governed, event-checked, residual burst sensitivity declared rather than claimed away. The daemon alternative to be costed, not dismissed. A build decision, not a governance one. Also after the 25th.

6 · What has NOT happened

  • The target pulse has not been fetched. No near-future pulse has been fetched.
  • No bones have been derived. No soul has been generated.
  • ~/CLAUDE.md has not been touched (PENDING-150, unbundled).
  • Nothing has been implemented of §8, §8a or §9 — the status line is confirmed free but not built.