[FIX] The jurist's three conditions on the rejection log, made structural; §9 fix corrected

CONDITION 1, and it is the one that had to stop being an intention: log_rejection()
refuses an empty `why`, and acceptable() returns an empty `why` EXACTLY when the line
passed. So there is no call site from which an accepted line could be written — logging
one would require inventing a violation it does not have. The same guarantee render()
takes from its signature, applied to the clause the jurist named as the condition under
which this log is not a §9 breach. Both polarities asserted.

CONDITION 2: deletion tracked as its own DEFERRED-DECISION on 2026-09-08, so retaining
it requires an act rather than an omission. A corpus of suppressed speech would let
someone reconstruct a register — the hazard PENDING-153's freeze exists to prevent.

CONDITION 3: not read for content before then. ⚠ Not clean already, and the item says so:
the executor displayed one rejected line to the steward earlier today, before the
condition existed. Disclosed rather than left to be discovered.

⚠ THE §9 [FIX] WAS OVER-APPLIED AND THE EXECUTOR APPLIED IT AS GIVEN. The clause is a
disjunction with one live branch; only the jurist half is unreachable. The first edit
struck the whole thing and rewrote the clause. A [FIX] tag licenses implementing
directly; it does not license implementing UNREAD, and the disjunction was visible in a
three-word span. Corrected, both versions left visible.

PENDING-159 AMENDMENT 2 files the jurist's answer to the item's own caveat and the
narrowing it produces: the marker may be NOTED, NEVER COUNTED — an aggregate becomes a
measurement, and a measurement invites accuracy. And PENDING-89 now carries the sentence
saying what it can and cannot expect: individual instances, unaggregated, in unknown
proportion, non-neutral — therefore NO correlation statistic. If its falsifier needs a
rate, it needs another instrument or an honest admission that it has none.

125 controls across five scripts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J6hZXNYSxEfZseBGTni4sf
This commit is contained in:
David F Glidden
2026-08-25 17:19:18 +02:00
co-authored by Claude Opus 5
parent 593c983999
commit b95ee736bd
7 changed files with 184 additions and 50 deletions
+4 -9
View File
@@ -30,7 +30,7 @@ import time
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from tarbuckle_mumble_shim import (acceptable, soul_register, session_material, # noqa: E402
source_lacks, muted, log_event, # noqa: E402
echoes_soul, REJECTS)
echoes_soul, log_rejection, REJECTS)
MAX_WORDS_INVOKED = 180 # §9's "at length", made a number
TIMEOUT_S = 90 # the steward is deliberately waiting; he may take longer
@@ -87,14 +87,9 @@ Absolute constraints, none of which the floor suspends:
Speak."""
def log_silence(why: str, line: str) -> None:
try:
import json
with open(REJECTS, "a") as fh:
fh.write(json.dumps({"t": time.strftime("%Y-%m-%dT%H:%M:%S%z"),
"kind": "invoked", "why": why, "line": line[:400]}) + "\n")
except Exception:
pass
def log_silence(why: str, line: str = "") -> None:
"""Routed through the canonical writer, which cannot record an accepted line."""
log_rejection(why, line, "invoke")
def main() -> int:
+57 -8
View File
@@ -90,6 +90,44 @@ def muted() -> str:
return ""
def log_rejection(why: str, line: str, surface: str = "") -> None:
"""The rejection log. ⚠ STRUCTURALLY UNABLE TO RECORD AN ACCEPTED LINE.
Jurist ruling, 2026-08-25, on whether this log breaches §9's "filed nowhere":
"The rejection log is a log of my instruction, not of Tarbuckle... The rejected
lines were never uttered: he was silent, and the log holds what silence cost.
Nothing there entered the room... the fool cannot be cited from it because
there is nothing to cite — only material the net suppressed.
THE CONDITION: the log holds rejections only. If it ever holds an accepted
line, that is filing, straightforwardly, and §9 is breached."
Made structural rather than intentional, as the ruling asked. `why` is acceptable()'s
violation reason, and it is EMPTY EXACTLY WHEN THE LINE PASSED. Refusing an empty
`why` means no call site exists from which an accepted line could be written: to log
one you would have to invent a violation it does not have. Same guarantee render()
takes from its signature — a function that cannot be handed the thing it must not
see.
⚠ TEMPORARY. Deleted on 2026-09-08 with the fortnight's report, per the same ruling:
"a permanent store of rejected lines is a corpus, and a corpus of his suppressed
speech is exactly what would let someone reconstruct a register." Tracked as a
DEFERRED-DECISION so it cannot be quietly retained.
⚠ NOT READ FOR CONTENT BEFORE THEN. Reading it as it accumulates is reading Tarbuckle
by the back door and would shape the net toward lines the reader happens to like.
"""
if not why:
return # an accepted line has no reason; there is no path
try:
with open(REJECTS, "a") as fh:
fh.write(json.dumps({"t": time.strftime("%Y-%m-%dT%H:%M:%S%z"),
"kind": surface, "why": why,
"line": line[:200]}) + "\n")
except Exception:
pass
def _grams(text: str, n: int) -> set:
w = re.findall(r"[a-z']+", text.lower())
return {" ".join(w[i:i + n]) for i in range(len(w) - n + 1)}
@@ -260,12 +298,7 @@ def main() -> int:
if echo:
ok, why = False, f"recited the soul: {echo!r}"
if not ok:
try:
with open(REJECTS, "a") as fh:
fh.write(json.dumps({"t": time.strftime("%Y-%m-%dT%H:%M:%S%z"),
"kind": kind, "why": why, "line": line[:200]}) + "\n")
except Exception:
pass
log_rejection(why, line, kind)
log_event(kind, "rejected")
return 1 # silence. The draw was already consumed.
try:
@@ -279,6 +312,8 @@ def main() -> int:
def selftest() -> int:
global MUTE, REJECTS
import tempfile
checks, failed = [], []
def ck(name, cond):
@@ -333,8 +368,6 @@ def selftest() -> int:
ck("A4 material paths are session/soul only",
not any(("PENDING" in q or "REVIEWED" in q) for q in paths))
# A5 — the mute switch, and that every surface must be able to see it.
import tempfile
global MUTE
_m = MUTE
MUTE = os.path.join(tempfile.mkdtemp(), "mute")
try:
@@ -361,6 +394,22 @@ def selftest() -> int:
not echoes_soul("Second surface you've found for the same voice.", _soul))
ck("A7n passes an ordinary short observation",
not echoes_soul("Third one that's held together with a name.", _soul))
# A8 — THE JURIST'S CONDITION, structural. An accepted line has no `why`, so there
# is no call from which it could be written.
_r = REJECTS
REJECTS = os.path.join(tempfile.mkdtemp(), "rej.jsonl")
try:
log_rejection("", "an accepted line, offered to the log", "test")
ck("A8 an accepted line CANNOT be logged", not os.path.exists(REJECTS))
log_rejection("12 words", "a rejected line", "test")
ck("A8n a rejected line IS logged", os.path.exists(REJECTS))
ck("A8n the predicate can fail",
"a rejected line" in open(REJECTS).read())
log_rejection("", "a second accepted line", "test")
ck("A8 accepted lines never appear",
"second accepted" not in open(REJECTS).read())
finally:
REJECTS = _r
ck("A6n it cannot be handed a line",
"line" not in log_event.__code__.co_varnames)
ck("A4n the predicate can fail",
+3 -17
View File
@@ -42,7 +42,7 @@ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
# copy of `acceptable()` is a second, quietly divergent standard.
from tarbuckle_mumble_shim import (acceptable, soul_register, session_material, # noqa: E402
source_lacks, muted, log_event, # noqa: E402
echoes_soul, REJECTS)
echoes_soul, log_rejection, REJECTS)
LAST_TICK = os.path.expanduser("~/.claude/state/tarbuckle-last-tick")
SEAM_TIMEOUT_S = 15
@@ -84,22 +84,8 @@ Output the line and nothing else. No quotes, no preamble."""
def log_silence(why: str, line: str = "") -> None:
"""⚠ THE REJECTED LINE IS RECORDED, and the first run is why.
This logged `"line": ""` unconditionally, so the very first seam rejection — a
10-word line against a 9-word cap — recorded the verdict and threw away the
evidence. The steward had named this log as the instrument for deciding whether
the register and the net are mismatched; a log holding only reasons cannot answer
that. Found by reading the log after one use, which is the whole argument for
reviewing an instrument after every run rather than after failures.
"""
try:
import json
with open(REJECTS, "a") as fh:
fh.write(json.dumps({"t": time.strftime("%Y-%m-%dT%H:%M:%S%z"),
"kind": "seam", "why": why, "line": line[:200]}) + "\n")
except Exception:
pass
"""Routed through the canonical writer, which cannot record an accepted line."""
log_rejection(why, line, "seam")
def main() -> int:
+3 -7
View File
@@ -32,7 +32,7 @@ import time
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from tarbuckle_mumble_shim import (acceptable, soul_register, session_material, # noqa: E402
source_lacks, muted, log_event, # noqa: E402
echoes_soul, REJECTS)
echoes_soul, log_rejection, REJECTS)
FIRED = os.path.expanduser("~/.claude/state/tarbuckle-wrap-fired")
TIMEOUT_S = 15
@@ -132,12 +132,8 @@ Output the line and nothing else. No quotes, no preamble."""
def log_silence(why: str, line: str = "") -> None:
try:
with open(REJECTS, "a") as fh:
fh.write(json.dumps({"t": time.strftime("%Y-%m-%dT%H:%M:%S%z"),
"kind": "wrap", "why": why, "line": line[:200]}) + "\n")
except Exception:
pass
"""Routed through the canonical writer, which cannot record an accepted line."""
log_rejection(why, line, "wrap")
def main() -> int: