doc_census_check (volt): a number ending a line and its unit opening the next is ONE claim -- joined only when structural, spent only when a leg prints that unit, every unbound pair named; 16-module-docstring A/B 134->140 (+6, -0), 4-tool census +1 MATCHES and 0 verdicts moved, selftest 82->104 cells
This commit is contained in:
1 parent
3487b2b4ea
commit
495a591e08
4 files changed
+375
-19
No files matched your search
+301
-10
@@ -48,6 +48,33 @@ WHAT IT MEASURES (read-only: this tool only writes --json)
|
||||
A claim is `<digits> <unitword>` with the unit word ADJACENT, which is the
|
||||
archive's own notation. A bare number is not a claim and is not checked.
|
||||
|
||||
A WRAPPED PAIR IS A CLAIM ONLY WHEN A LEG CAN BIND IT. A number that ENDS one
|
||||
line with its unit opening the next is the same claim the archive writes on
|
||||
one line, and until 2026-10-20 this reader was line-local: a docstring reflow
|
||||
retired the claim silently while every command exited 0 (measured -- the
|
||||
pinned pair in `queue_claim_check.py` fell out of the census and the claim
|
||||
count fell with it, with no verdict moving). The reader now joins the pair,
|
||||
under the same refusals the adjacency reader already applies: a number welded
|
||||
to a preceding `-`, `/`, `.`, `:`, `_` or letter is not standalone, so a
|
||||
date's tail and `UTF-8` and `0/1` are not counts, and a unit with a hyphen
|
||||
behind it is a compound adjective. Whether the joined pair is SPENT is a
|
||||
second question, and it is answered by the census rather than by a lexicon of
|
||||
English: the pair is graded only when some leg prints its unit UNDER THAT
|
||||
SPELLING, and every pair no leg binds is printed as WRAP_UNBOUND and counted
|
||||
in the banner, never dropped. The spelling is exact and that is deliberate: a
|
||||
plural fold (`notes` -> `note`) is affordable for a one-line claim, because
|
||||
both sides are census voice, but a wrap is this reader's hypothesis about two
|
||||
lines of prose. Measured at HEAD 2026-10-20, the fold spent `the queue's own
|
||||
reply 62 / notes it` and graded a correct sentence STALE 62-vs-7; with the
|
||||
fold refused, that pair is WRAP_UNBOUND and the one wrapped claim a leg really
|
||||
binds -- `1,062 CONTENT_SHA256` at `citation_hash_class.py:53` -- is the only
|
||||
one graded. The other five candidates are named, not graded: `69 filenames`
|
||||
(`checkin_check.py:14`), `18 cells`, `24 spendable` and `0 without` (all
|
||||
three in this file -- its `--selftest`, fast-mode and `--fail` paragraphs),
|
||||
and `62 notes` (`queue_claim_check.py:119`). With `--no-run` there is no leg, so
|
||||
no wrap is spent and each one is reported unbound -- a mode that cannot see a
|
||||
census cannot bind a claim.
|
||||
|
||||
TWO ORACLE LEGS, AND WHY THE SECOND ONE EXISTS
|
||||
Leg 1 is the tool's own run at the block's revision, exactly as above. Leg 2
|
||||
is the SAME TOOL'S `--selftest`, added 2026-10-16 after the control plane
|
||||
@@ -220,7 +247,7 @@ FAILING ON THE CLASS IT CATCHES (`--fail`)
|
||||
USAGE
|
||||
python3 doc_census_check.py [--repo DIR] [--rev HEAD] [--tools NAME...]
|
||||
[--json OUT] [--fail] [--no-run] [--vocab PATH] [--save-vocab PATH]
|
||||
[--selftest] # selftest: 82 cells, one per claim class
|
||||
[--selftest] # selftest: 104 cells, one per claim class
|
||||
"""
|
||||
import argparse
|
||||
import ast
|
||||
@@ -290,6 +317,51 @@ CLAIM = re.compile(
|
||||
r"(?P<unit>[A-Za-z_][A-Za-z0-9_]*|[A-Z][A-Z_]{2,})\b(?!-)")
|
||||
CLAIM_EQ = re.compile(
|
||||
r"(?P<unit>[A-Za-z_][A-Za-z0-9_]*)\s*[:=]\s*\**\s*(?P<num>[0-9]+(?:,[0-9]{3})*)")
|
||||
|
||||
# A WRAPPED PAIR: the number ENDS one line and its unit OPENS the next. Until
|
||||
# 2026-10-20 this reader was line-local, so a claim that a docstring's 79-column
|
||||
# wrap cut in two was not a claim at all. That is not cosmetic: `queue_claim_check
|
||||
# .py`'s pinned pair `1,229,541 B / 9,953 lines` was broken onto two lines at
|
||||
# `70fa8b2` and the census silently fell from seventeen claims to sixteen with no
|
||||
# verdict moving -- the archive's own instrument, blind to the archive's own
|
||||
# notation, while every command exited 0. Measured at HEAD 2026-10-20 by running
|
||||
# this reader over all sixteen tracked `tools/*.py` MODULE docstrings -- the only
|
||||
# scope docstring_span reads: SIX
|
||||
# number-ends-a-line candidates -- FOUR real counts with their unit
|
||||
# (`69 filenames` at checkin_check.py:14, `1,062 CONTENT_SHA256` at
|
||||
# citation_hash_class.py:53, `18 cells` and `24 spendable` in this file's
|
||||
# `--selftest` and fast-mode paragraphs) and TWO words that merely open a
|
||||
# sentence (`0 without` in the `--fail` paragraph here, `62 notes` at
|
||||
# queue_claim_check.py:119). The same reader at `70fa8b2`, where the break was
|
||||
# introduced, reads seven -- the same six plus the pinned `9,953 lines` pair --
|
||||
# and spends it, so that docstring reads sixteen claims against the old reader
|
||||
# and seventeen against this one. `4e6b2ef`, the commit that put the pair back on
|
||||
# one line, is the control on the other side: it reads six candidates and
|
||||
# seventeen claims on BOTH readers, so the six is a measurement of HEAD's prose
|
||||
# and not a fallback the join quietly invents. A twelve-row artifact was produced
|
||||
# that day by a looser net that counted every number ending a line with any word
|
||||
# after it, non-counts included; the reader itself reads six.
|
||||
# The same measurement over FUNCTION and CLASS docstrings -- which this tool does
|
||||
# not read at all, module docstrings only -- finds two more real counts, `29
|
||||
# literal` in append_only_audit.py and `74 files` in checkin_check.py. They are
|
||||
# named here rather than quietly excluded: a scope the reader cannot see is
|
||||
# worth knowing, and the join would spend either one if the scope ever widened.
|
||||
#
|
||||
# WHY THERE IS NO WORD LIST HERE. The obvious reader is "join the wrap unless the
|
||||
# unit is a verb", and it needs an English lexicon that would refuse a real claim
|
||||
# the day one is written in an unlucky voice. The discrimination is made where
|
||||
# this tool already makes it: A WRAPPED PAIR IS SPENT ONLY WHEN A LEG PRINTS ITS
|
||||
# UNIT (see check_tool). At HEAD that spends exactly one of the six --
|
||||
# `1,062 CONTENT_SHA256`, whose census prints the label -- and the other five
|
||||
# (`69 filenames`, `18 cells`, `24 spendable`, `0 without`, `62 notes`) are
|
||||
# printed unbound and never graded. The structural half below is the part that
|
||||
# must not be guessed at, and it is the same half the adjacency reader already
|
||||
# enforces: a number welded to a preceding `-`, `/`, `.`, `:`, `_` or
|
||||
# alphanumeric is not standalone (`2026-10-18`, `UTF-8` and `0/1` are three of
|
||||
# the strings this refuses, each one a refusal cell in the selftest below), and
|
||||
# a unit with a hyphen behind it is a compound adjective, not a unit noun.
|
||||
WRAP_LEAD = re.compile(r"(?:^|[\s(\[{*`'\"])(?P<num>[0-9]+(?:,[0-9]{3})*)[ \t]*$")
|
||||
WRAP_UNIT = re.compile(r"^[ \t]*(?P<unit>[A-Za-z_][A-Za-z0-9_]*|[A-Z][A-Z_]{2,})\b(?!-)")
|
||||
REV_LONG = re.compile(r"\b[0-9a-f]{7,40}\b")
|
||||
|
||||
# A hex run introduced as a DIGEST is not a revision, and reading it as one costs
|
||||
@@ -477,15 +549,20 @@ def ordinal_at(raw, pos):
|
||||
|
||||
|
||||
def claims_in(blk):
|
||||
"""[(line, value, unit, token, offset)] for one block.
|
||||
"""[(line, value, unit, token, offset, wrapped)] for one block.
|
||||
|
||||
Both claim forms are read and a claim found by both is reported once. The
|
||||
offset is measured on the block text so a RESTATEMENT (far apart) can be
|
||||
told from an ENUMERATION of neighbouring sub-counts, the same
|
||||
discrimination num_agreement_check.py applies.
|
||||
|
||||
`wrapped` is True for a claim whose number ends one line and whose unit opens
|
||||
the next -- see WRAP_LEAD. It is a reading decision only: whether such a pair
|
||||
is SPENT is decided in check_tool, by whether a leg prints its unit.
|
||||
"""
|
||||
out, off = [], 0
|
||||
out, off, starts = [], 0, []
|
||||
for ln, raw in blk:
|
||||
starts.append(off)
|
||||
found = {}
|
||||
for m in CLAIM.finditer(raw):
|
||||
u = m.group("unit")
|
||||
@@ -504,8 +581,25 @@ def claims_in(blk):
|
||||
found[m.start()] = (int(m.group("num").replace(",", "")), u, m.group(0))
|
||||
for pos in sorted(found):
|
||||
val, u, tok = found[pos]
|
||||
out.append((ln, val, u, tok, off + pos))
|
||||
out.append((ln, val, u, tok, off + pos, False))
|
||||
off += len(raw) + 1
|
||||
for i in range(len(blk) - 1):
|
||||
ln, raw = blk[i]
|
||||
m = WRAP_LEAD.search(raw)
|
||||
if not m:
|
||||
continue
|
||||
um = WRAP_UNIT.match(blk[i + 1][1])
|
||||
if not um:
|
||||
continue
|
||||
u = um.group("unit")
|
||||
if len(u) < 3 or u.lower() in STOPWORDS or re.fullmatch(r"[qQ]\d+", u):
|
||||
continue
|
||||
if ordinal_at(raw, m.start("num")):
|
||||
continue
|
||||
num = m.group("num")
|
||||
out.append((ln, int(num.replace(",", "")), u, f"{num} {u}",
|
||||
starts[i] + m.start("num"), True))
|
||||
out.sort(key=lambda r: r[4])
|
||||
return out
|
||||
|
||||
|
||||
@@ -633,7 +727,7 @@ def _fixture_checks():
|
||||
for first, blk in blocks(lines, 1, len(lines)):
|
||||
revs = block_revs("\n".join(r for _, r in blk))
|
||||
revs_seen |= set(revs)
|
||||
for ln, val, unit, _tok, _pos in claims_in(blk):
|
||||
for ln, val, unit, _tok, _pos, _w in claims_in(blk):
|
||||
got.append((unit, val))
|
||||
if first == 1:
|
||||
first_block.append((unit, val))
|
||||
@@ -646,7 +740,7 @@ def _fixture_checks():
|
||||
# the tightened separator, one cell per form it now refuses, plus the
|
||||
# positive control -- a rule that refuses everything proves nothing
|
||||
def claims_of(text):
|
||||
return [(u, v) for _ln, v, u, _t, _p in claims_in([(1, text)])]
|
||||
return [(u, v) for _ln, v, u, _t, _p, _w in claims_in([(1, text)])]
|
||||
|
||||
check("claims: a welded digit-and-letter run is not a claim",
|
||||
claims_of("sha 83acffe0 / rev 9188dd3 at HEAD"), [])
|
||||
@@ -675,6 +769,57 @@ def _fixture_checks():
|
||||
check("claims: a count beside a line cite is still a claim",
|
||||
claims_of("open set: Q37:5278 while 13 rows close"), [("rows", 13)])
|
||||
check("claims: the block's rev is read", "babdadc" in revs_seen, True)
|
||||
|
||||
# THE WRAPPED PAIR, 2026-10-20. A count that ends one line with its unit
|
||||
# opening the next is the same claim the archive writes on one line, and
|
||||
# every ADMIT text below is a real wrap copied out of the docstring it was
|
||||
# measured in -- not an invented example. The four ADMIT cells are the four
|
||||
# counts at HEAD; the fifth candidate, `62 notes`, is a verb and is settled
|
||||
# by binding (wrap_bound, the FOLD cells below) rather than by these cells.
|
||||
# The four refusal cells are the structural half, synthesized rather than
|
||||
# copied because at HEAD no welded or hyphenated string survives to the
|
||||
# candidate stage for a text to be lifted from.
|
||||
def claims_lines(text):
|
||||
blk = [(i + 1, raw) for i, raw in enumerate(text.split("\n"))]
|
||||
return [(u, v, w) for _ln, v, u, _t, _p, w in claims_in(blk)]
|
||||
|
||||
check("wrap: a number ending a line and its unit opening the next is a claim",
|
||||
claims_lines("Twenty-five of the 69\nfilenames are not the form"),
|
||||
[("filenames", 69, True)])
|
||||
check("wrap: a thousands separator survives the join",
|
||||
claims_lines("594 BLOB_OID / 1,062\nCONTENT_SHA256 and the rest"),
|
||||
[("BLOB_OID", 594, False), ("CONTENT_SHA256", 1062, True)])
|
||||
check("wrap: a backtick before the number and a closing one after the unit",
|
||||
claims_lines("a selftest that prints `18\ncells` -- the defect class"),
|
||||
[("cells", 18, True)])
|
||||
check("wrap: an adjective is a unit when it is the count's own word",
|
||||
claims_lines("observed keys at 30c8120, 24\nspendable, the other 398"),
|
||||
[("spendable", 24, True)])
|
||||
check("wrap: a claim that does not wrap is not tagged",
|
||||
claims_lines("a selftest that prints 18 cells"), [("cells", 18, False)])
|
||||
check("wrap: the same text wrapped and unwrapped is two claims, not three",
|
||||
claims_lines("prints 18 cells\nand 18\ncells"),
|
||||
[("cells", 18, False), ("cells", 18, True)])
|
||||
# the four refusals, one cell each -- the structural half no candidate at
|
||||
# HEAD exercises, because the reader refuses these strings before the join
|
||||
check("wrap: a date's tail is welded to its hyphens, not a count",
|
||||
claims_lines("--today 2026-10-18\npython3 tools/x.py"), [])
|
||||
check("wrap: `UTF-8` ends a line and is still not a count",
|
||||
claims_lines("a malformed name, non-UTF-8\nbytes are refused"), [])
|
||||
check("wrap: a slash-separated pair (`0/1`) is not a count",
|
||||
claims_lines("exit 0/1\npython3 tools/x.py"), [])
|
||||
check("wrap: a hyphen behind the joined unit is a compound adjective",
|
||||
claims_lines("the queue read 65 same-party / 9\nother-party. Neither"),
|
||||
[])
|
||||
# THE FOLD, as a unit rule: keys_for folds a plural (it must -- a one-line
|
||||
# claim and a printed label are both census voice), wrap_bound does not.
|
||||
check("wrap: a plural verb is bound by no fold -- `notes` is not `note`",
|
||||
wrap_bound("notes", [({"note": {7}}, set(), "")]), False)
|
||||
check("wrap: and a unit printed under its own spelling IS bound",
|
||||
wrap_bound("notes", [({"notes": {62}}, set(), "")]), True)
|
||||
check("wrap: an uppercase label binds to the lowercase printed key",
|
||||
wrap_bound("CONTENT_SHA256",
|
||||
[({"content_sha256": {1062}}, set(), "")]), True)
|
||||
# the digest rule, one signal per cell, and the negative control between
|
||||
# them -- the text of each is the text of the defect, measured at HEAD
|
||||
check("revs: `sha256 <hex>` is a digest, not the block's revision",
|
||||
@@ -906,6 +1051,40 @@ def _fixture_checks():
|
||||
"\n471 UNRESOLVED at the head.\n" + "pad " * 80 + "\n"
|
||||
'441 UNRESOLVED at the tail.\n"""\n'
|
||||
"print('UNRESOLVED: 471')\n")
|
||||
# THE WRAPPED PAIR, three stubs that differ only in whether a leg can
|
||||
# bind the unit: agreeing, disagreeing, and a wrap that is prose.
|
||||
with open(os.path.join(td, "tools", "stub_wrap_ok.py"), "w") as fh:
|
||||
fh.write('"""A stub whose claim wraps onto the next line.\n'
|
||||
"\nWe measured 7\n"
|
||||
'widgets at HEAD.\n"""\n'
|
||||
"print('widgets: 7')\n")
|
||||
with open(os.path.join(td, "tools", "stub_wrap_stale.py"), "w") as fh:
|
||||
fh.write('"""A stub whose wrapped claim disagrees with its census.\n'
|
||||
"\nWe measured 9\n"
|
||||
'widgets at HEAD.\n"""\n'
|
||||
"print('widgets: 7')\n")
|
||||
with open(os.path.join(td, "tools", "stub_wrap_unbound.py"), "w") as fh:
|
||||
fh.write('"""A stub whose wrap is prose, not a census.\n'
|
||||
"\nIt exited 0\n"
|
||||
'without a census.\n"""\n'
|
||||
"print('widgets: 7')\n")
|
||||
# THE FOLD, end to end -- the false fault measured on the real archive at
|
||||
# HEAD (queue_claim_check.py:119, `reply 62 / notes it`). `notes` folds to
|
||||
# the printed key `note`, which the loose printed reader picked out of a
|
||||
# PASS line's prose, so a plural fold would spend this sentence and grade
|
||||
# it STALE. The pair must land as unbound instead.
|
||||
with open(os.path.join(td, "tools", "stub_wrap_fold.py"), "w") as fh:
|
||||
fh.write('"""A stub whose wrap is a verb that folds onto a key.\n'
|
||||
"\nThe queue's own reply 62\n"
|
||||
'notes it).\n"""\n'
|
||||
"print('note: 7')\n")
|
||||
# ...and the boundary: the SAME text on ONE line is still a claim, still
|
||||
# folded, still graded -- the narrowing is the wrap's price, not a new
|
||||
# rule for the adjacency reader.
|
||||
with open(os.path.join(td, "tools", "stub_note_adjacent.py"), "w") as fh:
|
||||
fh.write('"""A stub whose one-line claim folds onto a key.\n'
|
||||
"\nThe queue's own reply 62 notes it).\n\"\"\"\n"
|
||||
"print('note: 7')\n")
|
||||
genv = dict(os.environ, GIT_AUTHOR_NAME="t", GIT_AUTHOR_EMAIL="t@t",
|
||||
GIT_COMMITTER_NAME="t", GIT_COMMITTER_EMAIL="t@t")
|
||||
for sub in (["init", "-q"], ["add", "-A"], ["commit", "-qm", "fixture"]):
|
||||
@@ -929,6 +1108,24 @@ def _fixture_checks():
|
||||
run_gate("--tools", "tools/stub_split.py", "--no-run", "--fail"), 0)
|
||||
check("gate e2e: --fail with the run grades that same split (rc 1)",
|
||||
run_gate("--tools", "tools/stub_split.py", "--fail"), 1)
|
||||
# THE WRAPPED PAIR, END TO END. Three stubs whose only difference is
|
||||
# whether a leg prints the unit the wrap names, so these cells grade the
|
||||
# SPENDING rule and not just the reading rule above.
|
||||
check("gate e2e: a wrapped claim a leg binds, agreeing, is rc 0",
|
||||
run_gate("--tools", "tools/stub_wrap_ok.py", "--fail"), 0)
|
||||
check("gate e2e: and its wrapped VALUE is graded -- disagreeing is rc 1",
|
||||
run_gate("--tools", "tools/stub_wrap_stale.py", "--fail"), 1)
|
||||
check("gate e2e: a wrapped pair no leg binds is not a claim (rc 0)",
|
||||
run_gate("--tools", "tools/stub_wrap_unbound.py", "--fail"), 0)
|
||||
check("gate e2e: --no-run spends no wrap and fails on none (rc 0)",
|
||||
run_gate("--tools", "tools/stub_wrap_stale.py", "--no-run",
|
||||
"--fail"), 0)
|
||||
# THE FOLD: a plural verb must not be bound to a singular printed key by
|
||||
# a wrap, and the same text on one line must still be graded.
|
||||
check("gate e2e: a wrapped verb is NOT bound by a plural fold (rc 0)",
|
||||
run_gate("--tools", "tools/stub_wrap_fold.py", "--fail"), 0)
|
||||
check("gate e2e: the same words on one line ARE folded and graded (rc 1)",
|
||||
run_gate("--tools", "tools/stub_note_adjacent.py", "--fail"), 1)
|
||||
# the process exit code through the vocabulary, both directions, plus
|
||||
# the two ways a vocabulary can fail to be usable at all
|
||||
vpath = os.path.join(td, "vocab-names-unit.json")
|
||||
@@ -1017,6 +1214,30 @@ def _fixture_checks():
|
||||
if l.strip().startswith("ADVISORY above (no census label")],
|
||||
["ADVISORY above (no census label and no cached vocabulary): "
|
||||
"5@3, 7@5 -- reported, not graded"])
|
||||
# A WRAP IS NEVER SILENT: the banner says how many pairs were read
|
||||
# across a break and how many were spent, on both outcomes.
|
||||
_rc, out_wb = run_gate_out("--tools", "tools/stub_wrap_ok.py")
|
||||
check("gate e2e: the banner says the wrap was read and spent",
|
||||
[l.strip() for l in out_wb.splitlines()
|
||||
if l.strip().startswith("wrapped:")],
|
||||
["wrapped: 1 pair(s) read across a line break, 1 spent, "
|
||||
"0 not a claim (no leg prints the unit)"])
|
||||
_rc, out_wu = run_gate_out("--tools", "tools/stub_wrap_unbound.py")
|
||||
check("gate e2e: an unbound wrap is counted and named, not dropped",
|
||||
[l.strip() for l in out_wu.splitlines()
|
||||
if l.strip().startswith(("wrapped:", "WRAP_UNBOUND"))],
|
||||
["wrapped: 1 pair(s) read across a line break, 0 spent, "
|
||||
"1 not a claim (no leg prints the unit)",
|
||||
"WRAP_UNBOUND tools/stub_wrap_unbound.py:3 0 without -- the "
|
||||
"unit is printed by no leg"])
|
||||
_rc, out_wf = run_gate_out("--tools", "tools/stub_wrap_fold.py")
|
||||
check("gate e2e: a folded verb is named UNBOUND, not graded STALE",
|
||||
[l.strip() for l in out_wf.splitlines()
|
||||
if l.strip().startswith(("wrapped:", "WRAP_UNBOUND", "STALE"))],
|
||||
["wrapped: 1 pair(s) read across a line break, 0 spent, "
|
||||
"1 not a claim (no leg prints the unit)",
|
||||
"WRAP_UNBOUND tools/stub_wrap_fold.py:3 62 notes -- the unit "
|
||||
"is printed by no leg"])
|
||||
|
||||
print(f"selftest: {cells[0]} cells, {cells[0] - bad[0]} passed, {bad[0]} failed")
|
||||
return 0 if ok else 1
|
||||
@@ -1118,6 +1339,29 @@ def unit_scope(unit, legs, no_run):
|
||||
return "NOT_A_CENSUS_UNIT"
|
||||
|
||||
|
||||
def wrap_bound(unit, legs):
|
||||
"""True when some leg prints this unit under its OWN spelling.
|
||||
|
||||
This is keys_for WITHOUT the plural fold, and the narrowing is the whole
|
||||
point. `keys_for` tries `unit.lower().rstrip("s")` because a one-line claim
|
||||
and a printed label are both hand-written census voice (`18 claims` vs
|
||||
`claim: 18`), so folding the plural costs nothing there. A WRAP IS NOT
|
||||
HAND-WRITTEN CENSUS VOICE -- it is two lines this reader hypothesised into
|
||||
one claim, and the word that opens the second line is a word in a sentence
|
||||
far more often than it is a label: `the queue's own reply 62 / notes it`
|
||||
folds `notes` onto a printed key `note`, and the tool printed that key only
|
||||
because `parse_printed`'s loose reader took it out of the prose of its own
|
||||
PASS line (`PASS v2 loose key: a Q7 continuation note is not an opening
|
||||
record`). Measured 2026-10-20: that fold spent the pair and graded the
|
||||
docstring STALE 62-vs-7 -- a false fault about a correct sentence.
|
||||
So a wrap binds on the unit's own spelling or not at all; a pair that only a
|
||||
fold would bind is printed as WRAP_UNBOUND and never graded, which is the
|
||||
same landing place as a pair no leg touches.
|
||||
"""
|
||||
u = unit.lower()
|
||||
return any(u in (printed or {}) for printed, _clone, _tag in legs)
|
||||
|
||||
|
||||
def vocab_has(unit, vocab):
|
||||
"""True when a cached census vocabulary names this unit word.
|
||||
|
||||
@@ -1200,13 +1444,51 @@ def check_tool(repo, script, name, cache, run=True, tmpdir=".", isolation=240,
|
||||
out.append((selftest_leg[0][0], selftest_leg[0][1], "selftest"))
|
||||
return out
|
||||
|
||||
# A WRAPPED PAIR IS SPENT ONLY WHEN A LEG CAN BIND ITS UNIT. Joining a line
|
||||
# break is a reading decision and it is the only place in this tool where a
|
||||
# claim is manufactured out of two lines instead of found inside one, so it
|
||||
# gets the tool's own test for census-hood rather than a lexicon of English:
|
||||
# a unit some leg prints IS a unit; a word that merely opens a sentence is
|
||||
# not, and the difference is measured on the tool's output rather than
|
||||
# asserted in a word list. Measured at HEAD, spent: `1,062 CONTENT_SHA256`
|
||||
# (citation_hash_class.py:53). Measured at HEAD, NOT spent and named in the
|
||||
# banner: `69 filenames` (checkin_check.py:14, no leg prints `filenames`),
|
||||
# `18 cells`, `24 spendable` and `0 without` (doc_census_check.py self), and
|
||||
# `62 notes` (queue_claim_check.py:119, `reply 62 / notes it` -- prose, and
|
||||
# only a plural fold would have bound it; see wrap_bound). Nothing is dropped
|
||||
# silently -- every unbound pair is counted and printed (the `wrapped:` line
|
||||
# in the banner), because a candidate that vanishes is the defect this rule
|
||||
# exists to close. With no run there is no leg, so no wrap is spent and every
|
||||
# one is reported unbound: a mode that cannot see a census cannot bind a
|
||||
# claim, which is the same contract unit_scope already applies to a split.
|
||||
wrap_candidates, wrap_unbound = 0, []
|
||||
if any(w for _f, _r, cl, _b in blk_claims for _ln, _v, _u, _t, _p, w in cl):
|
||||
kept_blocks = []
|
||||
for first, revs, cl, btext in blk_claims:
|
||||
rows = []
|
||||
for ln, val, unit, tok, pos, wrapped in cl:
|
||||
if not wrapped:
|
||||
rows.append((ln, val, unit, tok, pos, wrapped))
|
||||
continue
|
||||
wrap_candidates += 1
|
||||
bound = any(wrap_bound(unit, legs_for(first, r))
|
||||
for r in (revs or ["HEAD"]))
|
||||
if bound:
|
||||
rows.append((ln, val, unit, tok, pos, wrapped))
|
||||
else:
|
||||
wrap_unbound.append({"file": name, "line": ln, "unit": unit,
|
||||
"claim": val, "token": tok})
|
||||
if rows:
|
||||
kept_blocks.append((first, revs, rows, btext))
|
||||
blk_claims = kept_blocks
|
||||
|
||||
# 1. INTERNAL SPLIT: one unit, one revision scope, two values, far enough
|
||||
# apart to be a restatement rather than a neighbouring sub-count.
|
||||
splits, advisory, unchecked = [], [], collections.Counter()
|
||||
by_unit = collections.defaultdict(list)
|
||||
for first, revs, cl, _b in blk_claims:
|
||||
scope = tuple(revs)
|
||||
for ln, val, unit, _t, pos in cl:
|
||||
for ln, val, unit, _t, pos, _w in cl:
|
||||
by_unit[(unit.upper() if unit.isupper() else unit.lower(), scope)].append(
|
||||
(first, ln, val, pos))
|
||||
for (unit, scope), items in sorted(by_unit.items()):
|
||||
@@ -1261,7 +1543,7 @@ def check_tool(repo, script, name, cache, run=True, tmpdir=".", isolation=240,
|
||||
for first, revs, cl, _b in blk_claims:
|
||||
for rev in (revs or ["HEAD"]):
|
||||
if is_self:
|
||||
for ln, val, unit, tok, _pos in cl:
|
||||
for ln, val, unit, tok, _pos, _w in cl:
|
||||
verdicts.append({"file": name, "block": first, "line": ln,
|
||||
"rev": rev, "unit": unit, "claim": val,
|
||||
"token": tok, "verdict": "SELF_NOT_RUN",
|
||||
@@ -1290,7 +1572,7 @@ def check_tool(repo, script, name, cache, run=True, tmpdir=".", isolation=240,
|
||||
legs = [l for l in legs if l[2] == "selftest"]
|
||||
if not legs:
|
||||
continue
|
||||
for ln, val, unit, tok, _pos in cl:
|
||||
for ln, val, unit, tok, _pos, _w in cl:
|
||||
v, detail = adjudicate(legs, unit, val, revs)
|
||||
verdicts.append({"file": name, "block": first, "line": ln,
|
||||
"rev": rev, "unit": unit, "claim": val,
|
||||
@@ -1299,8 +1581,9 @@ def check_tool(repo, script, name, cache, run=True, tmpdir=".", isolation=240,
|
||||
"unchecked": dict(unchecked),
|
||||
"claim_units": sorted({(u.upper() if u.isupper() else u.lower())
|
||||
for _f, _r, cl, _b in blk_claims
|
||||
for _ln, _v, u, _t, _p in cl}),
|
||||
for _ln, _v, u, _t, _p, _w in cl}),
|
||||
"failures": failures, "verdicts": verdicts,
|
||||
"wrap_candidates": wrap_candidates, "wrap_unbound": wrap_unbound,
|
||||
"self": is_self and run, "selftest_leg": (not run) or bool(selftest_leg and selftest_leg[0]),
|
||||
"blocks_with_claims": len(blk_claims)}
|
||||
|
||||
@@ -1461,6 +1744,14 @@ def main():
|
||||
f"{nstale} STALE claim(s), {nfail} leg failure(s), "
|
||||
f"{nclaims} claims checked"
|
||||
+ (" [" + "; ".join(notes) + "]" if notes else ""))
|
||||
if rep.get("wrap_candidates"):
|
||||
print(f" wrapped: {rep['wrap_candidates']} pair(s) read across a "
|
||||
f"line break, {rep['wrap_candidates'] - len(rep.get('wrap_unbound') or [])} "
|
||||
f"spent, {len(rep.get('wrap_unbound') or [])} not a claim "
|
||||
f"(no leg prints the unit)")
|
||||
for u in rep.get("wrap_unbound") or []:
|
||||
print(f" WRAP_UNBOUND {u['file']}:{u['line']} "
|
||||
f"{u['token']} -- the unit is printed by no leg")
|
||||
for s in rep["splits"]:
|
||||
vals = ", ".join(f"{r['value']}@{r['line']}" for r in s["rows"])
|
||||
scope = ",".join(s["revs"]) or "no rev named"
|
||||
|
||||
Reference in new issue
Block a user