[HARDENING] STATE-CLAIM + the resolution state, built together (REVIEWED-127)
Both halves of the schema, shipped in one change because the ruling said half a schema
invites a third patch and a third patch is how a vocabulary accretes instead of being
designed.
157 — resolution state. `resolved:` on any block; a resolved block is no longer due but
is NOT dropped: it prints as a closed ledger, because a discharge that vanishes from the
report is its own decay. The pointer must RESOLVE — a real path or a real git object —
so an undocumented discharge is impossible to express rather than merely discouraged. A
dangling pointer reports in the register-integrity lane, the same lane as an amendment
that replaced the record it amends; both are a record closing over its own history.
The 25th's hand-rename is MIGRATED back to DEFERRED-DECISION with resolved: set. That
block was the per-instance workaround 157 was filed against, and it is now the
migration's own test case.
158 — STATE-CLAIM. Reuses trigger_fired() verbatim and inverts only what firing MEANS:
for a deferral, fired = the decision is due; for a state-claim, fired = THE CLAIM IS
FALSE. Two new trigger kinds earned directly from today's instances: text-present (the
trial-09 hold, falsified by REVIEWED-124's existence) and file-changed-since ("the filed
rule not edited", false one hour after writing).
16 new controls, each with its discriminating half — fires on met, silent on unmet,
manual listed-never-fired, resolved excluded from due-ness, the SAME block unresolved
still due, a real pointer resolves, "yes, done" does not.
Proven on the LIVE blocks, not only fixtures: pointing the state-claim at an older
commit made it report FALSIFIED by name; replacing the resolution with "yes done" made
register-integrity report it; both restored and both returned to quiet.
⚠ One control failed before shipping and the failure was the useful part. The negative
control for file-changed-since pointed at FOOL-SEED-RULE.md, which this same session then
edited — so "unchanged since HEAD" broke, correctly. A control whose subject is "did this
file change" must not point at a file the session is changing. Re-pointed at a frozen
2026-08-02 trial artifact, with the reason recorded at the fixture. Caught because the
controls run on every invocation rather than in a separate suite.
First two real state-claims filed, deliberately one of each kind: ~/CLAUDE.md untouched
under PENDING-150, mechanically watched and [ESCALATE]-grade the moment it goes false;
and §9's channel unbuilt, marked `manual` because it has no filename yet and inventing a
proxy falsifier is the error the schema's own comment warns against.
⚠ The zero-state prints a WARNING, not a tick: "0 marked, NOT none-stale" with the ~57
unmarked candidates named as a grep. An instrument that reads nothing reports exactly
like one that finds nothing, and that is the failure this item exists to end.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J6hZXNYSxEfZseBGTni4sf
This commit is contained in:
co-authored by
Claude Opus 5
parent
0dcf304486
commit
063eccfd80
+10
-10
@@ -4252,20 +4252,20 @@ Jurist: *"Confirm that lowercasing is applied at exactly one point in the code a
|
||||
| PENDING-89 source (iv) | **AUTHORIZED to read** — 55 files; answers generation diversity only, never correlation of misses |
|
||||
| §13.6 block | ⚠ **LIFTED** — its stated condition (§5 ratification) is met |
|
||||
|
||||
<!-- DISCHARGED-DECISION: fool-beacon-derivation-run-once
|
||||
<!-- DEFERRED-DECISION: fool-beacon-derivation-run-once
|
||||
since: 2026-08-22
|
||||
trigger: date 2026-08-25 — FIRED. Announced BY NAME at the 2026-08-25 wake, which is
|
||||
the first time this mechanism carried a real one rather than a rehearsed one.
|
||||
trigger: date 2026-08-25
|
||||
owner: executor
|
||||
discharged: 2026-08-25 — the derivation ran ONCE. Record:
|
||||
claude/governance/fool/seed/FOOL-BONES-2026-08-25.md, commit 5694b925.
|
||||
RENAMED, not deleted: governance-drift-check.py's parser has no `resolved:` field, so a
|
||||
taken decision would be reported COME DUE forever and the instrument would degrade into
|
||||
crying wolf. Renaming the key stops the report while leaving the record that the trigger
|
||||
existed, fired, and was answered. If a `resolved:` field is ever added, this reverts to
|
||||
DEFERRED-DECISION with that field set.
|
||||
resolved: 2026-08-25 — ran once; claude/governance/fool/seed/FOOL-BONES-2026-08-25.md, commit 5694b925
|
||||
-->
|
||||
|
||||
⚠ **MIGRATED 2026-08-25 under REVIEWED-127.** This block was closed on the 25th by
|
||||
hand-renaming its key to `DISCHARGED-DECISION`, because the schema had no way to say
|
||||
*answered*. That rename was the per-instance workaround PENDING-157 was filed against, and
|
||||
it is now reverted: the key is `DEFERRED-DECISION` again and the closure is carried by a
|
||||
`resolved:` field the checker reads. **This block is the migration's own test case** — the
|
||||
first resolved deferral, and the one whose pointer must resolve.
|
||||
|
||||
⚠ **TRIGGER BLOCK ADDED 2026-08-24.** Until today this run-once, irreversible, dated act had **no
|
||||
trigger of any kind** — no cron, no launchd, no scheduled agent, and not a tracked
|
||||
DEFERRED-DECISION. It was one of the 105 prose deferrals the drift-check reports as carrying no
|
||||
|
||||
@@ -299,7 +299,16 @@ which is the entire point of having filed it early. Current state lives in
|
||||
- ~~No bones have been derived. No soul has been generated.~~
|
||||
→ **Bones derived 2026-08-25**, once, commit `5694b925`. **No soul generated** — that
|
||||
remains true, and §7 of the doctrine is unrun.
|
||||
- `~/CLAUDE.md` has **not** been touched (PENDING-150, unbundled).
|
||||
- `~/CLAUDE.md` has **not** been touched (PENDING-150, unbundled). — **still true, and now watched.**
|
||||
|
||||
<!-- STATE-CLAIM: claude-md-untouched-pending-150
|
||||
since: 2026-08-22
|
||||
claims: ~/CLAUDE.md has not been touched under PENDING-149; PENDING-150 stays unbundled
|
||||
falsified-by: file-changed-since d6377af CLAUDE.md
|
||||
-->
|
||||
*(The first negative state-claim in this system to carry a falsifier. It is the one bullet
|
||||
in §6 still true, it is `[ESCALATE]`-grade the moment it stops being true, and until today
|
||||
nothing in this system would have noticed. REVIEWED-127.)*
|
||||
- Nothing has been implemented of §8, §8a or §9 — the status line is confirmed free but
|
||||
not built.
|
||||
|
||||
|
||||
@@ -207,6 +207,16 @@ both went false within hours of being written and neither was caught by any mech
|
||||
- §8a body — unbuilt; condition 2 (variation from time or nothing, never content) unmet.
|
||||
- §9 channel — unbuilt. **Tarbuckle has a name, bones and a voice, and nowhere yet to be
|
||||
silent.**
|
||||
|
||||
<!-- STATE-CLAIM: fool-channel-unbuilt
|
||||
since: 2026-08-25
|
||||
claims: §9's channel is unbuilt; Tarbuckle has nowhere to speak or be silent
|
||||
falsified-by: manual
|
||||
-->
|
||||
*(Deliberately `manual`. §9's channel has no filename yet, so there is no path to test and
|
||||
no string to match — inventing a proxy falsifier would be exactly the error this schema's
|
||||
own comment warns against. `manual` is listed and never fired: the claim is tracked AND
|
||||
known to be unwatched, rather than merely looking watched. REVIEWED-127.)*
|
||||
- No second generation. No hand edit.
|
||||
- ~~No regeneration ruling.~~ → **Ruled 2026-08-25** (§4a): the glosses were never a §7
|
||||
input, so there is no implementation error to demonstrate and §4 REGENERATION is not
|
||||
|
||||
@@ -20,6 +20,7 @@ import json
|
||||
import os
|
||||
import re
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import date
|
||||
from pathlib import Path
|
||||
@@ -282,6 +283,55 @@ control("register file is reachable", REVIEWED_MD.exists())
|
||||
DEFERRED_RE = re.compile(
|
||||
r"<!--\s*DEFERRED-DECISION:\s*([a-z0-9][a-z0-9-]*)\s*\n(.*?)-->", re.S)
|
||||
|
||||
# REVIEWED-127 / PENDING-158. A negative STATE-claim is the same sentence as a deferral
|
||||
# about a different object: a deferral says "not yet" about a DECISION, a state-claim says
|
||||
# "not yet" about a STATE. Same words, same forgetting, same substrate standing ready to
|
||||
# contradict them — and until now only one of the two had a trigger.
|
||||
#
|
||||
# So this reuses trigger_fired() verbatim and inverts only what firing MEANS: for a
|
||||
# deferral, fired = the decision is due; for a state-claim, fired = THE CLAIM IS FALSE.
|
||||
#
|
||||
# <!-- STATE-CLAIM: <slug>
|
||||
# since: YYYY-MM-DD
|
||||
# claims: <the negative claim, in words>
|
||||
# falsified-by: glob <p> | path-exists <p> | date <d> | text-present <f> <s>
|
||||
# | file-changed-since <commit> <path> | manual
|
||||
# resolved: YYYY-MM-DD — <pointer> (optional; see resolution state below) -->
|
||||
#
|
||||
# ⚠ Opt-in, and the limit is the item's, not a caveat added here: a marker is used by
|
||||
# authors who remember to mark their claims, which is the same population that would have
|
||||
# caught the claim anyway. ADOPTION is the open question, not expressibility.
|
||||
STATE_CLAIM_RE = re.compile(
|
||||
r"<!--\s*STATE-CLAIM:\s*([a-z0-9][a-z0-9-]*)\s*\n(.*?)-->", re.S)
|
||||
|
||||
# REVIEWED-127 C1 / PENDING-157. The resolution state, which BOTH kinds carry.
|
||||
#
|
||||
# Earned 2026-08-25: a trigger came due, was correctly discharged, and the schema had no
|
||||
# way to say so. The only options were deleting the block (losing the record) or renaming
|
||||
# its key by hand (losing machine-checkability, and relying on the reflex the mechanism
|
||||
# exists to replace). Renaming keys one at a time is how you live with a defect.
|
||||
#
|
||||
# `resolved:` must SAY WHAT DISCHARGED IT. Non-empty is not enough — an undocumented
|
||||
# discharge records THAT a gate closed and not WHY, which six months on is no record at
|
||||
# all. A resolved block whose pointer resolves to nothing is reported as a defect, in the
|
||||
# same lane as an amendment that replaced the record it amends: both close over history.
|
||||
state_claims: list[dict] = []
|
||||
|
||||
|
||||
def pointer_resolves(text: str) -> bool:
|
||||
"""True if the resolution names something that exists — a path, or a git object."""
|
||||
for tok in re.findall(r"[A-Za-z0-9_./~-]{4,}", text or ""):
|
||||
tok = tok.strip(".,;:")
|
||||
if re.fullmatch(r"[0-9a-f]{7,40}", tok):
|
||||
if subprocess.run(["git", "-C", str(HOME / "dotfiles"), "cat-file", "-e",
|
||||
tok + "^{commit}"], capture_output=True).returncode == 0:
|
||||
return True
|
||||
cand = (Path(os.path.expanduser(tok)) if tok.startswith(("~", "/"))
|
||||
else HOME / "dotfiles" / tok)
|
||||
if cand.exists():
|
||||
return True
|
||||
return False
|
||||
|
||||
SCAN_ROOTS = [HOME / "_Dev", HOME / "dotfiles"]
|
||||
TRANSCRIPTS = HOME / ".claude/projects/-Users-davidglidden"
|
||||
# Governance packages live outside the */docs/** convention the scan was written for,
|
||||
@@ -306,7 +356,22 @@ def parse_deferrals(text: str, src: Path) -> list[dict]:
|
||||
out.append({"slug": slug, "file": src, "root": _repo_root(src),
|
||||
"trigger": fields.get("trigger", "manual"),
|
||||
"owner": fields.get("owner", "?"),
|
||||
"since": fields.get("since", "?")})
|
||||
"since": fields.get("since", "?"),
|
||||
"resolved": fields.get("resolved", "").strip()})
|
||||
return out
|
||||
|
||||
|
||||
def parse_state_claims(text: str, src: Path) -> list[dict]:
|
||||
"""Same shape as a deferral; `falsified-by` is mapped onto `trigger` so the one
|
||||
evaluator serves both. Firing means the CLAIM IS FALSE, not that a decision is due."""
|
||||
out = []
|
||||
for slug, body in STATE_CLAIM_RE.findall(text):
|
||||
fields = dict(re.findall(r"^\s*([a-z-]+):\s*(.+?)\s*$", body, re.M))
|
||||
out.append({"slug": slug, "file": src, "root": _repo_root(src),
|
||||
"trigger": fields.get("falsified-by", "manual"),
|
||||
"claims": fields.get("claims", "?"),
|
||||
"since": fields.get("since", "?"),
|
||||
"resolved": fields.get("resolved", "").strip()})
|
||||
return out
|
||||
|
||||
|
||||
@@ -321,6 +386,33 @@ def trigger_fired(d: dict) -> bool | None:
|
||||
else (d["root"] / arg).exists()
|
||||
if kind == "date":
|
||||
return datetime.date.today().isoformat() >= arg
|
||||
if kind == "text-present":
|
||||
# Falsified by a string appearing somewhere — e.g. a hold claim falsified by the
|
||||
# ruling that lifted it. Earned by trial 09: "the run is held" stayed true-looking
|
||||
# for five days after REVIEWED-124 voided it, because nothing compared the two.
|
||||
fp, _, needle = arg.partition(" ")
|
||||
needle = needle.strip()
|
||||
if not needle:
|
||||
return None
|
||||
target = (Path(os.path.expanduser(fp)) if fp.startswith(("~", "/"))
|
||||
else d["root"] / fp)
|
||||
try:
|
||||
return needle in target.read_text(errors="replace")
|
||||
except OSError:
|
||||
return None
|
||||
if kind == "file-changed-since":
|
||||
# Falsified by a file having been edited since a named commit — e.g. "the filed
|
||||
# rule not edited", which went false one hour after it was written.
|
||||
commit, _, path = arg.partition(" ")
|
||||
path = path.strip()
|
||||
if not commit or not path:
|
||||
return None
|
||||
try:
|
||||
r = subprocess.run(["git", "-C", str(d["root"]), "diff", "--quiet",
|
||||
commit, "--", path], capture_output=True)
|
||||
except OSError:
|
||||
return None
|
||||
return True if r.returncode == 1 else (False if r.returncode == 0 else None)
|
||||
if kind == "transcripts":
|
||||
# Session-count trigger. Added 2026-08-07 for PENDING-112's pre-registered
|
||||
# 20-session falsifier, which the jurist required be BINDING rather than a
|
||||
@@ -384,9 +476,27 @@ for root, pattern in _scan_targets:
|
||||
continue
|
||||
if "DEFERRED-DECISION:" in body:
|
||||
deferrals.extend(parse_deferrals(body, f))
|
||||
if "STATE-CLAIM:" in body:
|
||||
state_claims.extend(parse_state_claims(body, f))
|
||||
|
||||
fired = [d for d in deferrals if trigger_fired(d) is True]
|
||||
manual = [d for d in deferrals if trigger_fired(d) is None]
|
||||
# REVIEWED-127 C1. A resolved block is no longer due — but it is NOT dropped. It stays
|
||||
# counted as a closed ledger, because a discharge that vanishes from the report is its own
|
||||
# species of decay: the register would show three tracked deferrals and no evidence at all
|
||||
# that a fourth had ever been answered.
|
||||
resolved_deferrals = [d for d in deferrals if d["resolved"]]
|
||||
open_deferrals = [d for d in deferrals if not d["resolved"]]
|
||||
fired = [d for d in open_deferrals if trigger_fired(d) is True]
|
||||
manual = [d for d in open_deferrals if trigger_fired(d) is None]
|
||||
|
||||
resolved_claims = [c for c in state_claims if c["resolved"]]
|
||||
open_claims = [c for c in state_claims if not c["resolved"]]
|
||||
falsified = [c for c in open_claims if trigger_fired(c) is True]
|
||||
claims_manual = [c for c in open_claims if trigger_fired(c) is None]
|
||||
|
||||
# Same lane as the amendment-that-replaced-its-own-record check: both are a record
|
||||
# closing over its own history.
|
||||
dangling = [d for d in (resolved_deferrals + resolved_claims)
|
||||
if not pointer_resolves(d["resolved"])]
|
||||
|
||||
_T_OK = ("<!-- DEFERRED-DECISION: tei-native\n since: 2026-08-07\n"
|
||||
" owner: steward\n trigger: date 2000-01-01\n-->")
|
||||
@@ -428,6 +538,70 @@ control("trigger evaluator does NOT fire on an unmet condition "
|
||||
_p_wait and trigger_fired(_p_wait[0]) is False)
|
||||
control("deferred-decision scan surface is reachable",
|
||||
any(r.is_dir() for r in SCAN_ROOTS))
|
||||
|
||||
# ---- REVIEWED-127: state-claims, the two new trigger kinds, and the resolution state.
|
||||
# Every one carries its discriminating half. An absence is not evidence until the
|
||||
# instrument is shown capable of detecting presence — and this whole item exists because
|
||||
# an instrument that reads nothing reports exactly like one that finds nothing.
|
||||
_SC = ("<!-- STATE-CLAIM: fixture\n since: 2026-08-25\n"
|
||||
" claims: the pulse has not been fetched\n"
|
||||
" falsified-by: date 2000-01-01\n-->")
|
||||
_sc = parse_state_claims(_SC, CLAUDE_MD)
|
||||
control("state-claim parser reads a well-formed block",
|
||||
len(_sc) == 1 and _sc[0]["slug"] == "fixture"
|
||||
and _sc[0]["claims"] == "the pulse has not been fetched")
|
||||
control("state-claim parser rejects a non-block [negative control]",
|
||||
not parse_state_claims("<!-- STATE: nope -->", CLAUDE_MD))
|
||||
control("state-claim FIRES when its falsifier is met [= the claim is now false]",
|
||||
_sc and trigger_fired(_sc[0]) is True)
|
||||
control("state-claim SILENT when its falsifier is unmet [the discriminating half]",
|
||||
trigger_fired(parse_state_claims(
|
||||
_SC.replace("date 2000-01-01", "date 2999-01-01"), CLAUDE_MD)[0]) is False)
|
||||
control("state-claim `manual` is listed, never fired",
|
||||
trigger_fired(parse_state_claims(
|
||||
_SC.replace("date 2000-01-01", "manual"), CLAUDE_MD)[0]) is None)
|
||||
|
||||
_DF = HOME / "dotfiles"
|
||||
control("text-present FIRES on a string that is present",
|
||||
trigger_fired({"trigger": "text-present PENDING.md PENDING-158", "root": _DF}) is True)
|
||||
control("text-present SILENT on a string that is absent [negative control]",
|
||||
trigger_fired({"trigger": "text-present PENDING.md zzz-not-in-this-file-zzz",
|
||||
"root": _DF}) is False)
|
||||
control("text-present returns None on an unreadable target [honest degradation]",
|
||||
trigger_fired({"trigger": "text-present no/such/file.md x", "root": _DF}) is None)
|
||||
control("file-changed-since FIRES on a file edited since the named commit",
|
||||
trigger_fired({"trigger": "file-changed-since 5694b92 "
|
||||
"claude/governance/fool/seed/FOOL-BONES-2026-08-25.md",
|
||||
"root": _DF}) is True)
|
||||
# ⚠ The fixture below is deliberately a FROZEN artifact — a trial-03 run output from
|
||||
# 2026-08-02 that is never edited. The first version of this control pointed at
|
||||
# FOOL-SEED-RULE.md and failed the moment that file was edited in the working tree, which
|
||||
# is correct behaviour from the trigger and a badly chosen fixture: a control whose
|
||||
# subject is "did this file change" must not point at a file the session is changing.
|
||||
# Caught by the controls running on every invocation rather than in a separate suite.
|
||||
control("file-changed-since SILENT on a file unchanged since HEAD [discriminating half]",
|
||||
trigger_fired({"trigger": "file-changed-since HEAD "
|
||||
"claude/governance/fool/runs/trial-03-20260802T144136Z.raw.txt",
|
||||
"root": _DF}) is False)
|
||||
|
||||
_RES_OK = _SC.replace("-->", " resolved: 2026-08-25 — commit 5694b925\n-->")
|
||||
_RES_BAD = _SC.replace("-->", " resolved: yes, done\n-->")
|
||||
control("resolved block parses its resolution",
|
||||
parse_state_claims(_RES_OK, CLAUDE_MD)[0]["resolved"].startswith("2026-08-25"))
|
||||
control("a resolved block is EXCLUDED from due-ness even with a met trigger "
|
||||
"[C1: discharge without a hand-rename]",
|
||||
not [c for c in parse_state_claims(_RES_OK, CLAUDE_MD)
|
||||
if not c["resolved"] and trigger_fired(c) is True])
|
||||
control("the SAME block unresolved IS due [negative control — the exclusion must be "
|
||||
"the resolution, not the fixture]",
|
||||
trigger_fired(parse_state_claims(_SC, CLAUDE_MD)[0]) is True)
|
||||
control("pointer that names something real resolves",
|
||||
pointer_resolves("2026-08-25 — commit 5694b925"))
|
||||
control("pointer that names nothing is DANGLING [C1: an undocumented discharge must be "
|
||||
"impossible to express, not merely discouraged]",
|
||||
not pointer_resolves("yes, done"))
|
||||
control("a path pointer resolves too, not only a commit",
|
||||
pointer_resolves("see claude/governance/fool/seed/FOOL-BONES-2026-08-25.md"))
|
||||
# Prose-deferral census: counted, never classified, and never read as absence.
|
||||
prose_counts = {}
|
||||
for _f in (HOME / "dotfiles" / "PENDING.md", HOME / "dotfiles" / "PENDING-archive.md"):
|
||||
@@ -580,16 +754,21 @@ else:
|
||||
# Deferred decisions: a fired trigger is a decision that has come DUE, not a defect.
|
||||
if deferrals:
|
||||
if fired:
|
||||
print(f"\n⏰ deferred decisions: {len(fired)} of {len(deferrals)} have COME DUE")
|
||||
print(f"\n⏰ deferred decisions: {len(fired)} of {len(open_deferrals)} open have COME DUE")
|
||||
for d in fired:
|
||||
print(f" {d['slug']} — owner: {d['owner']}, deferred since {d['since']}")
|
||||
print(f" trigger MET: {d['trigger']}")
|
||||
print(f" {d['file'].relative_to(HOME)}")
|
||||
print("\n A deferral is the claim 'not yet'. These triggers say otherwise.")
|
||||
else:
|
||||
waiting = len(deferrals) - len(manual)
|
||||
print(f"✓ deferred decisions: {len(deferrals)} tracked, none due "
|
||||
waiting = len(open_deferrals) - len(manual)
|
||||
print(f"✓ deferred decisions: {len(open_deferrals)} tracked, none due "
|
||||
f"({waiting} checkable, {len(manual)} manual-only)")
|
||||
if resolved_deferrals:
|
||||
print(f" ✓ plus {len(resolved_deferrals)} RESOLVED — answered, and kept in the "
|
||||
f"ledger rather than dropped:")
|
||||
for _r in resolved_deferrals:
|
||||
print(f" {_r['slug']} — {_r['resolved']}")
|
||||
if prose_counts:
|
||||
_tot = sum(prose_counts.values())
|
||||
print(f" ⚠ plus {_tot} PROSE deferral mention(s) in the register "
|
||||
@@ -605,4 +784,36 @@ if deferrals:
|
||||
print(" Any DEFERRED-DECISION block in these is INERT. This is 'could not assess',")
|
||||
print(" not 'nothing there' — the distinction REVIEWED-104 rules may not be collapsed.")
|
||||
|
||||
# State claims: a fired falsifier is not a decision coming due — it is a claim that has
|
||||
# STOPPED BEING TRUE while still being written down as true.
|
||||
if state_claims:
|
||||
if falsified:
|
||||
print(f"\n⚠ state claims: {len(falsified)} of {len(open_claims)} open are NOW FALSE")
|
||||
for c in falsified:
|
||||
print(f" {c['slug']} — claims: {c['claims']}")
|
||||
print(f" FALSIFIED BY: {c['trigger']}")
|
||||
print(f" {c['file'].relative_to(HOME)}")
|
||||
print("\n A state-claim is the claim 'not yet' about a state, not a decision.")
|
||||
print(" The substrate says otherwise. Correct the document, or resolve the block.")
|
||||
else:
|
||||
_ok = len(open_claims) - len(claims_manual)
|
||||
print(f"✓ state claims: {len(open_claims)} tracked, none falsified "
|
||||
f"({_ok} checkable, {len(claims_manual)} manual-only)")
|
||||
if resolved_claims:
|
||||
print(f" ✓ plus {len(resolved_claims)} RESOLVED — kept in the ledger.")
|
||||
else:
|
||||
# Silence here is NOT evidence of clean state-claims. Nothing has opted in yet, and
|
||||
# PENDING-158 records why that is the open question: an opt-in marker is used by the
|
||||
# authors who would have caught the claim anyway. Say so rather than print a tick.
|
||||
print("· state claims: 0 marked. ⚠ NOT 'none stale' — nothing has opted in yet;")
|
||||
print(" ~57 candidate negative-state claims are unmarked and unread (a grep, not a")
|
||||
print(" census). Adoption is the open question, not expressibility (PENDING-158).")
|
||||
|
||||
if dangling:
|
||||
print(f"\n⚠ register integrity: {len(dangling)} resolved block(s) name no pointer "
|
||||
f"that resolves")
|
||||
for _d in dangling:
|
||||
print(f" {_d['slug']} — resolved: {_d['resolved'] or '(empty)'}")
|
||||
print(" A discharge recording THAT a gate closed but not WHAT closed it is no record.")
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
Reference in New Issue
Block a user