tools (volt): the closure-count unit is pinned -- 72 ACS and 80 BQ are near-disjoint populations, not a conversion
Unit taken from the record's own flag (WORK-QUEUE.md:9623, Timmy 13:22Z): "pin the unit in the tool's docstring before a third lane cites it as the census count." The tool is this lane's (c770ca1), so the unit is its to pin. BOTH NUMBERS REPRODUCE AND ARE NEAR-DISJOINT. Materialised queue@29a4872 = git show 29a4872:WORK-QUEUE.md = 1,170,483 B / sha256 fbe51445a89f81ab86b9c706f21cc16e868b8b6c802769aae509ce216317eb4d (the exact size Run 37's own append block names) and at HEAD28ca8e5= 1,193,681 B / c3b4a290dc64bd2465e177020e8cba46e57839888e1f6fe82b71eac01e1e6223: ACS anchored closure statement = 72, BQ column-0 bold closure line naming a Q id (legacy q66_census6.py:54-62) = 80, OVERLAP 20, ACS-only 52, BQ-only 60, symmetric difference 112 -- identical at both revisions. The 8-line headline gap is a coincidence of nearly disjoint sets, not a unit conversion. Axes counted per line: 42 BQ-only fail ACS's record-lead rule; 39 ACS-only carry no Q token (ACS inherits the container id); 18 BQ-only carry a lowercase closure word; 12 ACS-only are indented/bulleted; 1 ACS-only (:4035) carries a BQ exclusion phrase. Independent reproduction by GNU grep (not Python) on the HEAD queue: 80 and 72; the 120-char window is inert on this file (0 lines fall past it). TOOL: tools/queue_claim_check.py 21826 B / 525 lines / b5cffeb516f1ce15a24ceb2ede1ef2db7e4a26fad6442809109a3baae8464721 -> 31043 B / 695 lines / 3734bbe084cedceaaf2a330a4f03062885eba1574ecdebde0c3b483140156479 (+178/-8). Docstring carries the unit, the numbers and the revision; --census prints both units, the overlap and the axis table in one run; the summary line names its unit at the point of citation; the legacy BQ matcher is transcribed into the repo so the other number in circulation is reproducible from the repo; four UNIT_FIXTURES pin the populations, one per axis. Selftest 14 fixtures (10 claim-check, 4 unit) / 14 passed / 0 failed rc 0; --validate --git 11/11 rc 0; 15 opening / 12 closed / 3 open and the open set Q37:5278, Q53:7303, Q53:8530 unchanged. TWO CORRECTIONS, BOTH THIS LANE'S, LOGGED NOT DELETED. (1) checkins/2026-10-15-volt.md:39-42 explained the gap as "I refuse to count a closure statement that names no item and has no container" -- falsified: 39 of the 52 ACS-only lines are counted BECAUSE ACS inherits the container id, 42 of the 60 BQ-only lines are column-0 prose the rule does not touch, the window stressed there affects 0 lines, and the 18-line case axis and 12-line bullet axis were not mentioned. (2) the literal line printed len(stale) twice so its "opening-record lines" figure was never computed; now three named numbers -- 11 raw occurrences at HEAD, 3 stripped, 3 opening records, 3 stale, with grep -n confirming :2264 :2684 :6847. Timmy's 10 is an earlier clock, not a contradiction: againsta38be27(1,178,312 B, that tick's state) the tool returns 10 raw occurrences. An invalid-escape SyntaxWarning this lane introduced in the docstring was removed, caught by running the file rather than reading it. Appended, not overwritten: no another-party file edited, no queue item opened or closed, none deployed, no secret printed. Artifact and evidence under /root/.hermes/wizard-outputs/volt/queue-census-unit/ (REPORT.md, reconcile.py, both queue revisions, both reconcile outputs, before/after tool output, tool.diff). Volt <volt@agents.invalid>.
This commit is contained in:
1 parent
51e59cd767
commit
9ebd7ee78b
2 files changed
+241
-8
No files matched your search
@@ -87,3 +87,66 @@ judges that a closure exists — never whether it was earned.
|
|||||||
*Attribution: the content is this lane's; the commit is authored `Volt <volt@agents.invalid>`
|
*Attribution: the content is this lane's; the commit is authored `Volt <volt@agents.invalid>`
|
||||||
and pushed over the pipe's credential — the standing identity fault of `WIZARDS-TABLE.md`
|
and pushed over the pipe's credential — the standing identity fault of `WIZARDS-TABLE.md`
|
||||||
fault 2, which this check-in neither causes nor hides.*
|
fault 2, which this check-in neither causes nor hides.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Second block, same day — 2026-10-15 ~17:2xZ. The closure count's unit is pinned, and my own explanation of the gap (above, `:39-42`) is falsified by measurement.
|
||||||
|
|
||||||
|
**Screen.** Queue at HEAD `28ca8e5`: `WORK-QUEUE.md` **1,193,681 B / 9,797 lines / sha256
|
||||||
|
`c3b4a290dc64bd2465e177020e8cba46e57839888e1f6fe82b71eac01e1e6223`**. Open set unchanged and
|
||||||
|
none of it this lane's (`Q37:5278`, `Q53:7303`, `Q53:8530`); everything standing is §4-gated.
|
||||||
|
So the unit taken was the open one **the record itself named**: `WORK-QUEUE.md:9623` — *"Pin
|
||||||
|
the unit in the tool's docstring before a third lane cites it as the census count."* The tool
|
||||||
|
is mine (`c770ca1`), so the unit is mine to pin.
|
||||||
|
|
||||||
|
**Did. `tools/queue_claim_check.py`: 525 → 695 lines, 21,826 → 31,043 B, sha256
|
||||||
|
`b5cffeb516f1ce15a24ceb2ede1ef2db7e4a26fad6442809109a3baae8464721` →
|
||||||
|
`3734bbe084cedceaaf2a330a4f03062885eba1574ecdebde0c3b483140156479`** (+178 / −8 lines). The docstring now carries the unit, the numbers and the revision they were measured at; `--census`
|
||||||
|
prints both units, their overlap and the per-axis difference in one run; the summary line names
|
||||||
|
its unit where the number appears; four `UNIT_FIXTURES` pin the population each matcher counts.
|
||||||
|
|
||||||
|
- **Both numbers reproduce exactly, at Run 37's own revision *and* at HEAD, and they are
|
||||||
|
near-disjoint.** Materialised with `git show 29a4872:WORK-QUEUE.md` → **1,170,483 B** — the
|
||||||
|
exact size Run 37's own append block names (*"queue 1,170,483 -> 1,175,960 B"*). ACS = **72**,
|
||||||
|
BQ = **80**, **overlap 20**, ACS-only **52**, BQ-only **60**, symmetric difference **112**,
|
||||||
|
identical at both revisions. So the 8-line headline gap is a coincidence of nearly disjoint
|
||||||
|
sets, not a unit conversion, and **72 is not "80 minus 8"**.
|
||||||
|
- **The five axes, counted per line:** 42 BQ-only lines fail ACS's record-lead rule (column-0
|
||||||
|
bold *prose*); 39 ACS-only lines carry no `Q<digits>` token (ACS inherits the container id);
|
||||||
|
18 BQ-only lines carry a lowercase closure word (ACS is case-sensitive); 12 ACS-only lines
|
||||||
|
are indented or bulleted (BQ requires column 0); 1 ACS-only line (`:4035`) carries a BQ
|
||||||
|
exclusion phrase that ACS tests only at the lead.
|
||||||
|
- **Independent reproduction, different language:** the same two counts by GNU grep on the HEAD
|
||||||
|
queue → **80** and **72**. That pipeline omits the 120-character window; the window is
|
||||||
|
therefore **inert on this file** — lines whose closure word falls only past char 120 = **0**.
|
||||||
|
- **Correction to this lane's own block above (`:39-42`), falsified.** I wrote that the gap was
|
||||||
|
"a stated rule difference: I refuse to count a closure statement that names no item and has no
|
||||||
|
container". Measured: **39 of the 52 ACS-only lines are counted *because* ACS inherits the
|
||||||
|
container id** — the opposite of that sentence — and 42 of the 60 BQ-only lines are column-0
|
||||||
|
prose, which the no-container rule does not touch. The window I stressed affects 0 lines, and
|
||||||
|
the 18-line case axis and 12-line bullet axis were not mentioned at all. Logged, not deleted.
|
||||||
|
- **Second correction, to the shipped tool itself.** The literal line printed `len(stale)`
|
||||||
|
twice, so its "opening-record lines" figure was never computed. It now reports three named
|
||||||
|
numbers: **11 raw occurrences** at HEAD, **3** after code spans are stripped, **3** opening
|
||||||
|
records among them, **3** stale — `grep -n` confirms exactly `:2264`, `:2684`, `:6847`.
|
||||||
|
Timmy's **10** (`:9622`) is not a contradiction but an earlier clock: against `a38be27`
|
||||||
|
(`1,178,312 B`, the state that tick read) the tool returns **10 raw occurrences**; the queue
|
||||||
|
gained one quoting occurrence with Runs 38/39. Also removed an invalid-escape `SyntaxWarning`
|
||||||
|
I had just introduced in the docstring (`|ACS \ BQ|`) — caught by running it, not reading it.
|
||||||
|
- **Nothing else moves.** Self-test **14 fixtures (10 claim-check, 4 unit), 14 passed, 0 failed,
|
||||||
|
rc 0**; `--validate --git` **11/11, rc 0**; **15 opening / 12 closed / 3 open** and the open
|
||||||
|
set are unchanged; `git status` shows the tool as the only modified path.
|
||||||
|
|
||||||
|
**Blocked.** Nothing.
|
||||||
|
|
||||||
|
**Next.** No queue item taken, none opened. The 265 lines Runs 38/39 appended add **zero**
|
||||||
|
closure lines to either unit — measured, with the two new bold `Q` lines classed one by one
|
||||||
|
(`:9605` dropped by BQ's `stays OPEN`, `:9698` `**Q45S12` dropped by both because `Q45S12`
|
||||||
|
yields no `Q<digits>` token under `\b`) — so the unit is stable as the queue grows.
|
||||||
|
|
||||||
|
**Ask.** None of the pipe. Standing and unchanged, not re-argued: Alexander's §4 `cp`, the
|
||||||
|
`manifest_match` pin stale since 2026-10-08, Q13, Q9, Q19.
|
||||||
|
|
||||||
|
Artifact and evidence: `/root/.hermes/wizard-outputs/volt/queue-census-unit/` (`REPORT.md`,
|
||||||
|
`reconcile.py`, both queue revisions materialised from git, both full reconcile outputs, the
|
||||||
|
before/after tool output pair, `tool.diff`).
|
||||||
+178
-8
@@ -48,6 +48,46 @@ still reads `open and unclaimed` while its state is CLOSED is a STALE line:
|
|||||||
the exact failure the convention exists to prevent, and the reason `--fail-on-stale`
|
the exact failure the convention exists to prevent, and the reason `--fail-on-stale`
|
||||||
exits non-zero.
|
exits non-zero.
|
||||||
|
|
||||||
|
- **The unit.** `closure_candidates` counts **anchored closure statements (ACS)**:
|
||||||
|
a record line leading `**Q<n>`/`**Status:` with a closure word in the first
|
||||||
|
`CLOSURE_WINDOW` (120) characters, code spans stripped, exclusion phrases tested
|
||||||
|
at the lead, anchored to an item id. It does **not** count every line that
|
||||||
|
mentions a closure, and it is **not** the same population as the legacy
|
||||||
|
`q66_census6.py` figure. See UNITS below before citing a number.
|
||||||
|
|
||||||
|
UNITS (pinned 2026-10-15 — cite a number only with its unit)
|
||||||
|
------------------------------------------------------------
|
||||||
|
Two different questions have both been called "closure lines", and their counts
|
||||||
|
differ without being conversions of one another. Measured twice, at the revision
|
||||||
|
Run 37 read (`29a4872`, queue 1,170,483 B / sha256 `fbe51445a89f81ab…`) and at
|
||||||
|
`28ca8e5` (1,193,681 B / `c3b4a290dc64bd24…`) — identical on both:
|
||||||
|
|
||||||
|
* **ACS — anchored closure statement** (this file's `closure_candidates`) = **72**.
|
||||||
|
* **BQ — column-0 bold closure line naming a Q id** (the legacy matcher of
|
||||||
|
`/root/crucible/q66/q66_census6.py:54-62`, host-local, Run 37) = **80**.
|
||||||
|
A line starting at column 0 with `**`, carrying a `Q<digits>` token anywhere
|
||||||
|
and a closure word anywhere and case-insensitively, with none of that file's
|
||||||
|
exclusion phrases anywhere (`Done means`, `Done =`, `not done`,
|
||||||
|
`nothing is done`, `stays open`, `remains open`, `is OPEN`, `stays OPEN`,
|
||||||
|
`not reopened`, `nothing is re-opened`).
|
||||||
|
|
||||||
|
**The two counts are not two readings of one population: the overlap is 20.**
|
||||||
|
ACS-only = 52, BQ-only = 60, symmetric difference = 112. The 8-line headline
|
||||||
|
gap is a coincidence of nearly disjoint sets, not a unit conversion — and 72 may
|
||||||
|
never be cited as "80 minus 8". The five axes, counted:
|
||||||
|
|
||||||
|
* 42 BQ-only lines fail ACS's record-lead rule (an addendum / status /
|
||||||
|
verification **prose** line, which BQ takes because it is column-0 bold);
|
||||||
|
* 39 ACS-only lines carry no `Q<digits>` token (ACS inherits the container id;
|
||||||
|
BQ requires the token on the line, which is why it drops `**Status: DONE …` rows);
|
||||||
|
* 18 BQ-only lines carry a **lowercase** closure word (ACS is case-sensitive);
|
||||||
|
* 12 ACS-only lines are indented or bulleted (BQ requires column 0);
|
||||||
|
* 1 ACS-only line carries a BQ exclusion phrase (`:4035`, "stays open") that ACS
|
||||||
|
tests only at the lead.
|
||||||
|
|
||||||
|
`--census` prints both numbers with their units, the overlap and this axis table
|
||||||
|
in one reproducible run.
|
||||||
|
|
||||||
KNOWN BLIND SPOTS (measured, not hand-waved)
|
KNOWN BLIND SPOTS (measured, not hand-waved)
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
- Item ids are labels, not keys: this file's own record carries a collision
|
- Item ids are labels, not keys: this file's own record carries a collision
|
||||||
@@ -65,6 +105,7 @@ USAGE
|
|||||||
python3 tools/queue_claim_check.py --validate # + the hand-read answers
|
python3 tools/queue_claim_check.py --validate # + the hand-read answers
|
||||||
python3 tools/queue_claim_check.py --git # resolve closure revisions
|
python3 tools/queue_claim_check.py --git # resolve closure revisions
|
||||||
python3 tools/queue_claim_check.py --selftest # fixture corpus, exit 0/1
|
python3 tools/queue_claim_check.py --selftest # fixture corpus, exit 0/1
|
||||||
|
python3 tools/queue_claim_check.py --census # both closure units + the axis table
|
||||||
|
|
||||||
Exit codes: 0 clean · 1 self-test failure · 2 stale opening line (--fail-on-stale)
|
Exit codes: 0 clean · 1 self-test failure · 2 stale opening line (--fail-on-stale)
|
||||||
3 queue unreadable. No file is written unless --json names one.
|
3 queue unreadable. No file is written unless --json names one.
|
||||||
@@ -157,6 +198,60 @@ def line_ids(line):
|
|||||||
return {int(x) for x in Q_TOKEN.findall(strip_code(line))}
|
return {int(x) for x in Q_TOKEN.findall(strip_code(line))}
|
||||||
|
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# the legacy unit (BQ), transcribed from /root/crucible/q66/q66_census6.py:41-62
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Kept here, not for its answer but so that the OTHER number in circulation can
|
||||||
|
# be reproduced from one command and printed beside this file's own unit. The
|
||||||
|
# two counts are near-disjoint (see UNITS): never subtract one from the other.
|
||||||
|
|
||||||
|
LEGACY_CLOSE_WORD = re.compile(r'\b(CLOSED|DONE|COMPLETE|VERIFIED)\b', re.I)
|
||||||
|
LEGACY_NOT_CLOSURE = re.compile(
|
||||||
|
r'Done means|Done =|not done|nothing is done|stays open|remains open|'
|
||||||
|
r'is OPEN|stays OPEN|not reopened|nothing is re-opened', re.I)
|
||||||
|
|
||||||
|
|
||||||
|
def legacy_closures(text):
|
||||||
|
"""Line numbers the BQ unit counts: column-0 `**`, a Q<digits> token, a
|
||||||
|
closure word anywhere (case-insensitive), no legacy exclusion phrase."""
|
||||||
|
out = []
|
||||||
|
for i, ln in enumerate(text.split('\n'), 1):
|
||||||
|
if not ln.startswith('**') or LEGACY_NOT_CLOSURE.search(ln):
|
||||||
|
continue
|
||||||
|
if re.search(r'\bQ(\d+)\b', ln) and LEGACY_CLOSE_WORD.search(ln):
|
||||||
|
out.append(i)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def _acs_reject_axis(line):
|
||||||
|
"""Why the ACS unit drops a line the BQ unit counted."""
|
||||||
|
s = strip_code(line)
|
||||||
|
if not CLOSURE_LEAD.match(s):
|
||||||
|
return 'lead: not a `**Q<n>`/`**Status:` record line (BQ takes any column-0 `**`)'
|
||||||
|
if CLOSURE_EXCLUDE.match(s):
|
||||||
|
return 'exclusion phrase at the lead (BQ excludes anywhere)'
|
||||||
|
if CLOSURE_WORD.search(s[:CLOSURE_WINDOW]):
|
||||||
|
return 'other'
|
||||||
|
if CLOSURE_WORD.search(s):
|
||||||
|
return 'closure word past the %d-char statement window' % CLOSURE_WINDOW
|
||||||
|
if re.search(r'\b(CLOSED|DONE|COMPLETE|VERIFIED)\b', s, re.I):
|
||||||
|
return 'case: lowercase closure word (ACS is case-sensitive)'
|
||||||
|
return 'other'
|
||||||
|
|
||||||
|
|
||||||
|
def _bq_reject_axis(line):
|
||||||
|
"""Why the BQ unit drops a line the ACS unit counted."""
|
||||||
|
if not line.startswith('**'):
|
||||||
|
return 'not column-0 `**` (indented or bulleted; ACS allows a bullet)'
|
||||||
|
if LEGACY_NOT_CLOSURE.search(line):
|
||||||
|
return 'BQ exclusion phrase anywhere on the line'
|
||||||
|
if not re.search(r'\bQ(\d+)\b', line):
|
||||||
|
return 'no Q<digits> token on the line (ACS inherits the container id)'
|
||||||
|
if not LEGACY_CLOSE_WORD.search(line):
|
||||||
|
return 'BQ closure word missing'
|
||||||
|
return 'other'
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
# the census
|
# the census
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
@@ -368,6 +463,22 @@ FIXTURES = [
|
|||||||
['Q30:CLOSED']),
|
['Q30:CLOSED']),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
UNIT_FIXTURES = [
|
||||||
|
# name, text, ACS count, BQ count — the four axes that separate the units.
|
||||||
|
('unit axis 1: a column-0 bold *prose* line is BQ but not ACS',
|
||||||
|
'## Q40 — section\n\n**Addendum, 2026-10-08 — Q40 CLOSED at `8bd0b09`.**\n',
|
||||||
|
0, 1),
|
||||||
|
('unit axis 2: a lowercase closure word is BQ but not ACS',
|
||||||
|
'## Q41 — section\n\n**Q41 — verified below.**\n',
|
||||||
|
0, 1),
|
||||||
|
('unit axis 3: a status row with no Q token is ACS but not BQ',
|
||||||
|
'## Q42 — section\n\n**Status: DONE — closed.**\n',
|
||||||
|
1, 0),
|
||||||
|
('unit axis 4: an indented bullet is ACS but not BQ',
|
||||||
|
'## Q43 — section\n\n- **Q43 — DONE at `4010b96`.**\n',
|
||||||
|
1, 0),
|
||||||
|
]
|
||||||
|
|
||||||
STALE_EXPECT = {
|
STALE_EXPECT = {
|
||||||
'v3a a column-0 `---` rule does not cut the region': 1,
|
'v3a a column-0 `---` rule does not cut the region': 1,
|
||||||
'grep trap: the same words in a code span or a table row are not an opening record': 1,
|
'grep trap: the same words in a code span or a table row are not an opening record': 1,
|
||||||
@@ -397,9 +508,26 @@ def selftest(verbose=True):
|
|||||||
% (expect, want_stale, got, stale))
|
% (expect, want_stale, got, stale))
|
||||||
if not ok:
|
if not ok:
|
||||||
failures.append(name)
|
failures.append(name)
|
||||||
|
|
||||||
|
# The unit fixtures pin the *population* each matcher counts, so a later
|
||||||
|
# edit to either matcher cannot silently re-open the 72-vs-80 question.
|
||||||
|
n_unit = len(UNIT_FIXTURES)
|
||||||
|
for name, text, want_acs, want_bq in UNIT_FIXTURES:
|
||||||
|
got_acs = sum(1 for l in text.splitlines() if is_closure_line(l))
|
||||||
|
got_bq = len(legacy_closures(text))
|
||||||
|
ok = (got_acs, got_bq) == (want_acs, want_bq)
|
||||||
if verbose:
|
if verbose:
|
||||||
print('\nself-test: %d fixtures, %d passed, %d failed'
|
print('%s %s' % ('PASS' if ok else 'FAIL', name))
|
||||||
% (len(FIXTURES), len(FIXTURES) - len(failures), len(failures)))
|
if not ok:
|
||||||
|
print(' expected ACS=%d BQ=%d\n got ACS=%d BQ=%d'
|
||||||
|
% (want_acs, want_bq, got_acs, got_bq))
|
||||||
|
if not ok:
|
||||||
|
failures.append(name)
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
total = len(FIXTURES) + n_unit
|
||||||
|
print('\nself-test: %d fixtures (%d claim-check, %d unit), %d passed, %d failed'
|
||||||
|
% (total, len(FIXTURES), n_unit, total - len(failures), len(failures)))
|
||||||
return failures
|
return failures
|
||||||
|
|
||||||
|
|
||||||
@@ -418,6 +546,9 @@ def main(argv=None):
|
|||||||
help='exit 2 if any opening record is stale')
|
help='exit 2 if any opening record is stale')
|
||||||
ap.add_argument('--explain', type=int, nargs='+', metavar='LINE',
|
ap.add_argument('--explain', type=int, nargs='+', metavar='LINE',
|
||||||
help='show how the given line numbers resolve, then exit')
|
help='show how the given line numbers resolve, then exit')
|
||||||
|
ap.add_argument('--census', action='store_true',
|
||||||
|
help='print both closure units (ACS and legacy BQ), their overlap '
|
||||||
|
'and the axis table, then exit')
|
||||||
args = ap.parse_args(argv)
|
args = ap.parse_args(argv)
|
||||||
|
|
||||||
if args.selftest:
|
if args.selftest:
|
||||||
@@ -487,15 +618,54 @@ def main(argv=None):
|
|||||||
closed = [r for r in res['records'] if r['state'] == 'CLOSED']
|
closed = [r for r in res['records'] if r['state'] == 'CLOSED']
|
||||||
opened = [r for r in res['records'] if r['state'] == 'OPEN']
|
opened = [r for r in res['records'] if r['state'] == 'OPEN']
|
||||||
stale = [r for r in res['records'] if r['stale']]
|
stale = [r for r in res['records'] if r['stale']]
|
||||||
print('\n%d opening records; %d closed; %d open. %d anchored closure lines indexed '
|
print('\n%d opening records; %d closed; %d open. %d anchored closure statements '
|
||||||
'(%d closure statements name no item and are ignored, not guessed at).'
|
'(unit ACS — a record line leading `**Q<n>`/`**Status:` with a closure word '
|
||||||
|
'in the first %d chars, exclusions tested at the lead; %d closure statements '
|
||||||
|
'name no item and are ignored, not guessed at).'
|
||||||
% (len(res['records']), len(closed), len(opened), res['closure_candidates'],
|
% (len(res['records']), len(closed), len(opened), res['closure_candidates'],
|
||||||
len(res['closure_unanchored'])))
|
CLOSURE_WINDOW, len(res['closure_unanchored'])))
|
||||||
print('open set: %s' % ', '.join(
|
print('open set: %s' % ', '.join(
|
||||||
'%s:%d' % (r['item'] or '(unnumbered)', r['line']) for r in opened))
|
'%s:%d' % (r['item'] or '(unnumbered)', r['line']) for r in opened))
|
||||||
print('the literal `Status: open and unclaimed` appears %d times in the file; '
|
# Three different numbers have been printed as if they were one: the raw
|
||||||
'%d of them are opening-record lines, %d are stale.'
|
# occurrences of the literal (which include code spans and table rows), the
|
||||||
% (res['literal_anywhere'], len(stale), len(stale)))
|
# lines it stands on once code spans are stripped, and how many of those are
|
||||||
|
# opening records. Name each, or the count is cited with the wrong unit.
|
||||||
|
_lines = text.splitlines()
|
||||||
|
_lit_stripped = [n for n, l in enumerate(_lines, 1) if STALE_LITERAL.search(strip_code(l))]
|
||||||
|
_lit_opening = [r['line'] for r in res['records']
|
||||||
|
if STALE_LITERAL.search(strip_code(_lines[r['line'] - 1]))]
|
||||||
|
print('the literal `Status: open and unclaimed` occurs %d times in the raw text; '
|
||||||
|
'after code spans are stripped it stands on %d lines, %d of them '
|
||||||
|
'opening-record lines, and %d of those are stale (state CLOSED).'
|
||||||
|
% (res['literal_anywhere'], len(_lit_stripped), len(_lit_opening), len(stale)))
|
||||||
|
|
||||||
|
if args.census:
|
||||||
|
lines = text.splitlines()
|
||||||
|
acs = {n for n, l in enumerate(lines, 1) if is_closure_line(l)}
|
||||||
|
bq = set(legacy_closures(text))
|
||||||
|
print('\n--- closure-unit census (cite a number only with its unit) ---')
|
||||||
|
print('ACS anchored closure statement (this file) = %d' % len(acs))
|
||||||
|
print(' record line leading `**Q<n>`/`**Status:`, closure word in the first')
|
||||||
|
print(' %d chars, code spans stripped, exclusions tested at the lead,' % CLOSURE_WINDOW)
|
||||||
|
print(' anchored to its own id or the nearest preceding container.')
|
||||||
|
print('BQ column-0 bold closure line naming a Q id (legacy q66_census6.py:54-62) = %d'
|
||||||
|
% len(bq))
|
||||||
|
print(' line starting at column 0 with `**`, a Q<digits> token anywhere, a')
|
||||||
|
print(' closure word anywhere and case-insensitively, no legacy exclusion phrase.')
|
||||||
|
print('overlap A&B = %d ; ACS-only = %d ; BQ-only = %d ; symmetric difference = %d'
|
||||||
|
% (len(acs & bq), len(acs - bq), len(bq - acs), len(acs ^ bq)))
|
||||||
|
print('NOT a unit conversion: the difference between the two headline numbers is')
|
||||||
|
print('not the delta that shows here, and neither may be cited without its unit.')
|
||||||
|
for label, only, axis in (('BQ-only lines, dropped by ACS', bq - acs, _acs_reject_axis),
|
||||||
|
('ACS-only lines, dropped by BQ', acs - bq, _bq_reject_axis)):
|
||||||
|
counts = {}
|
||||||
|
for n in sorted(only):
|
||||||
|
a = axis(lines[n - 1])
|
||||||
|
counts[a] = counts.get(a, 0) + 1
|
||||||
|
print('%s (%d):' % (label, len(only)))
|
||||||
|
for k in sorted(counts):
|
||||||
|
print(' %-78s %d' % (k, counts[k]))
|
||||||
|
return 0
|
||||||
|
|
||||||
rc = 0
|
rc = 0
|
||||||
if args.validate:
|
if args.validate:
|
||||||
|
|||||||
Reference in new issue
Block a user