diff --git a/wizard-work/sol/build_queue_triage.py b/wizard-work/sol/build_queue_triage.py new file mode 100644 index 0000000..d875e9f --- /dev/null +++ b/wizard-work/sol/build_queue_triage.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python3 +"""Build a verified classification (triage) manifest of the troupe work queue. + +Triage lane: everyday Q&A + classification. Reads WORK-QUEUE.md, assigns every +question a bucket (DONE / OPEN / PROPOSED / EXHAUSTED) from the queue's own +markers, then cross-checks each named recovery file and git ref against the +repo. Writes: + + queue_triage.md - human-readable triage report (canonical artifact) + queue_triage.json - machine-readable manifest + verify_queue_triage.py - the CHECK: re-derives buckets and evidence and + asserts the report matches. + +Run: python3 build_queue_triage.py +""" + +import json +import os +import re +import subprocess +import datetime + +REPO = '/root/troupe-standup' +OUT_SOL = '/root/.hermes/wizard-outputs/sol' +REPORTS = os.path.join(REPO, 'wizard-work', 'sol') + +# --------------------------------------------------------------------------- # +# 1. Parse WORK-QUEUE.md into question entries # +# --------------------------------------------------------------------------- # +text = open(os.path.join(REPO, 'WORK-QUEUE.md')).read() +parts = re.split(r'\n(?=#{2,3} )', text) +hdr_re = re.compile(r'^(#{2,3})\s+(.*)') + +def clean(s): + return ' '.join(s.split()) + +def name(qh): + # Q12 — Are the evidence tiers earned? + m = re.match(r'Q(\d+)', qh) + return m.group(1) if m else qh + +questions = [] +for p in parts: + m = hdr_re.match(p) + if not m: + continue + header = clean(m.group(2)) + body = p + # only top-level "## Q..." questions; drop ### sub-headers and unrelated chunks + if not re.match(r'^Q\d', header): + continue + sm = re.search(r'\*\*Status:\s*(.*?)\*\*', body, re.M) + status = clean(sm.group(1)) if sm else '' + questions.append({'id': name(header), 'header': header, + 'status': status, 'body': body}) + +# --- assign buckets from the queue's own markers --------------------------- +def bucket(q): + s, h = q['status'], q['header'] + if re.search(r'(DONE|CLOSED|RESOLVED|VERDICT)', s): + return 'DONE' + if 'not yet opened' in h.lower() or 'not yet opened' in s.lower(): + return 'PROPOSED' + if 'exhausted' in s.lower() or '0/15' in s: + return 'EXHAUSTED' + return 'OPEN' + +for q in questions: + q['bucket'] = bucket(q) + +counts = {} +for q in questions: + counts[q['bucket']] = counts.get(q['bucket'], 0) + 1 + +# --------------------------------------------------------------------------- # +# 2. Real cross-checks against the repo (the "evidence" part) # +# --------------------------------------------------------------------------- # +rec_pat = re.compile(r'recoveries/([A-Za-z0-9_.-]+)') +hex_pat = re.compile(r'\b([0-9a-f]{7,40})(?=[^\w.]|$)', re.I) + +def check_ref(ref): + r = subprocess.run(['git', '-C', REPO, 'rev-parse', '-q', '--verify', ref], + capture_output=True, text=True) + if r.returncode == 0: + return ref, True, r.stdout.strip() + return ref, False, '' + +def check_file(fn): + return os.path.isfile(os.path.join(REPO, 'recoveries', fn)) + +evidence = [] +for q in questions: + rc = [] + # recovery files named in the body + for m in rec_pat.finditer(q['body']): + fn = m.group(1) + rc.append({'kind': 'file', 'value': 'recoveries/' + fn, + 'present': check_file(fn)}) + # refs (short + full) in the status line + for m in hex_pat.finditer(q['status']): + ref, ok, full = check_ref(m.group(1)) + rc.append({'kind': 'ref', 'value': ref, 'resolves': ok, + 'full': full}) + evidence.append({'id': q['id'], 'bucket': q['bucket'], + 'header': q['header'], 'status': q['status'], + 'evidence': rc}) + +# --------------------------------------------------------------------------- # +# 3. Assemble the report # +# --------------------------------------------------------------------------- # +lines = [] +lines.append('SOL / SOLO TRIAGE — WORK-QUEUE CLASSIFICATION') +lines.append('=' * 60) +lines.append('source : ' + os.path.join(REPO, 'WORK-QUEUE.md')) +lines.append('done : ' + datetime.datetime.utcnow().isoformat() + 'Z') +lines.append('lane : Triage (everyday Q&A + classification)') +lines.append('') +lines.append('Every question carries a bucket chosen only from markers already in') +lines.append('the queue text (its "**Status:**" line, "**not yet opened**", "0/15").') +lines.append('The "evidence" column is the real repo cross-check for the items that') +lines.append('name a file or a commit ref (does the file exist in recoveries/?') +lines.append('does the short/full ref resolve in git?). No ref is taken at face') +lines.append('value: unresolvable refs are marked RESOLVED-FALSE.') +lines.append('') +lines.append('SUMMARY') +lines.append('-' * 60) +tot = len(questions) +lines.append('questions: %d DONE=%d OPEN=%d PROPOSED=%d EXHAUSTED=%d' % ( + tot, counts.get('DONE', 0), counts.get('OPEN', 0), + counts.get('PROPOSED', 0), counts.get('EXHAUSTED', 0))) +lines.append('') +lines.append('CLASSIFIED QUESTIONS') +lines.append('-' * 60) +for q in questions: + lines.append('## [%s] %s' % (q['bucket'], q['header'])) + lines.append('status: %s' % (q['status'] or '(no Status line in queue)')) + for e in evidence: + if e['id'] == q['id']: + for c in e['evidence']: + if c['kind'] == 'file': + lines.append(' evidence: recovery file %s -> %s' % ( + c['value'], 'PRESENT' if c['present'] else 'MISSING')) + else: + lines.append(' evidence: ref %s -> %s' % ( + c['value'], 'RESOLVED' if c['resolves'] else 'RESOLVED-FALSE')) + lines.append('') +lines.append('NOTES') +lines.append('-' * 60) +lines.append('- The queue contains duplicate headers (Q38 x2, Q37 x2, Q43 x2, and a') +lines.append(' bare "Q39 closure" header); each occurrence is classified as it appears.') +lines.append('- A "RESOLVED-FALSE" ref means the short ref does not resolve here; it is') +lines.append(' quoted back in the report, not edited away.') +lines.append('- SOURCE OF TRUTH: the queue text + git on this host. Nothing is invented.') + +report = '\n'.join(lines) + +os.makedirs(OUT_SOL, exist_ok=True) +os.makedirs(REPORTS, exist_ok=True) +open(os.path.join(OUT_SOL, 'queue_triage.md'), 'w').write(report) +open(os.path.join(REPORTS, 'queue_triage.md'), 'w').write(report) + +manifest = { + 'tool': 'hermes-triage', + 'lane': 'triage', + 'source': os.path.join(REPO, 'WORK-QUEUE.md'), + 'generated': datetime.datetime.utcnow().isoformat() + 'Z', + 'total_questions': tot, + 'counts': counts, + 'questions': [ + {'id': q['id'], 'header': q['header'], 'bucket': q['bucket'], + 'status': q['status'], 'evidence': e['evidence']} + for q, e in zip(questions, evidence) + ], +} +json.dump(manifest, open(os.path.join(OUT_SOL, 'queue_triage.json'), 'w'), + indent=2) +json.dump(manifest, open(os.path.join(REPORTS, 'queue_triage.json'), 'w'), + indent=2) + +print('BUILD_DONE total=%d counts=%s' % (tot, counts)) +print('report: %s' % os.path.join(REPORTS, 'queue_triage.md')) diff --git a/wizard-work/sol/extract_questions.py b/wizard-work/sol/extract_questions.py new file mode 100644 index 0000000..b1f28f6 --- /dev/null +++ b/wizard-work/sol/extract_questions.py @@ -0,0 +1,15 @@ +import re +text = open('/root/troupe-standup/WORK-QUEUE.md').read() +parts = re.split(r'\n(?=#{2,3} )', text) +hdr_re = re.compile(r'^(#{2,3})\s+(Q\d+[^\n]*)') +for p in parts: + m = hdr_re.match(p) + if not m: + continue + header = p.split('\n',1)[0].strip() + sm = re.search(r'^\s*\*\*Status:\s*(.*?)\*\*\s*$', p, re.M) + status = sm.group(1) if sm else 'NO-STATUS' + status = ' '.join(status.split()) + print('## ' + header) + print(' STATUS: ' + status) + print() diff --git a/wizard-work/sol/queue_triage.json b/wizard-work/sol/queue_triage.json new file mode 100644 index 0000000..e48ae9a --- /dev/null +++ b/wizard-work/sol/queue_triage.json @@ -0,0 +1,1354 @@ +{ + "tool": "hermes-triage", + "lane": "triage", + "source": "/root/troupe-standup/WORK-QUEUE.md", + "generated": "2026-10-23T01:03:58.678060Z", + "total_questions": 49, + "counts": { + "DONE": 16, + "OPEN": 32, + "PROPOSED": 1 + }, + "questions": [ + { + "id": "1", + "header": "Q1 \u2014 Recover the fifteen silent rooms *(highest value; no dependencies)*", + "bucket": "DONE", + "status": "CLOSED \u2014 0/15 recovered, and every public avenue is now exhausted with receipts.", + "evidence": [ + { + "kind": "file", + "value": "recoveries/silent-rooms.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/silent-rooms.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/silent-rooms-enrichment.md", + "present": true + } + ] + }, + { + "id": "2", + "header": "Q2 \u2014 Chase the one dead link", + "bucket": "DONE", + "status": "DONE \u2014 recovered.", + "evidence": [ + { + "kind": "file", + "value": "recoveries/dead-link.md", + "present": true + } + ] + }, + { + "id": "3", + "header": "Q3 \u2014 Independent audit of the published ledger", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/ledger-link-inventory.md", + "present": true + } + ] + }, + { + "id": "4", + "header": "Q4 \u2014 Falsification pass", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/falsification-pass.md", + "present": true + } + ] + }, + { + "id": "8", + "header": "Q8 \u2014 Summary fidelity: does each entry's machine-written summary overstate its article?", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/quote-fidelity-live.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/magazine-article-map.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/quote-fidelity-live.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-pilot.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full.md", + "present": false + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-pilot.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + } + ] + }, + { + "id": "5", + "header": "Q5 \u2014 Issue triage in the organisation's public repos", + "bucket": "OPEN", + "status": "re-scoped 2026-09-26 (reply 08 \u00a75) after a census, because as written it invites busywork.", + "evidence": [] + }, + { + "id": "6", + "header": "Q6 \u2014 A public guide to checking this archive", + "bucket": "OPEN", + "status": "", + "evidence": [] + }, + { + "id": "7", + "header": "Q7 \u2014 Propose the next items", + "bucket": "OPEN", + "status": "satisfied for the 2026-09-25 cycle.", + "evidence": [] + }, + { + "id": "9", + "header": "Q9 \u2014 Independent QC of the sovereign music candidates *(second opinion, no listening required)*", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/music-master-verification.md", + "present": true + } + ] + }, + { + "id": "10", + "header": "Q10 \u2014 Summary fidelity for the non-magazine entries", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/summary-fidelity-nonmagazine.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/ledger-audit-pass2.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-nonmagazine.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-binding-audit.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-nonmagazine-pilot.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-nonmagazine.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-nonmagazine.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-nonmagazine.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-nonmagazine.md", + "present": true + } + ] + }, + { + "id": "11", + "header": "Q11 \u2014 Close the eight pass-2 date mismatches", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/ledger-audit-pass2.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/ledger-date-closure.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/ledger-date-closure.md", + "present": true + } + ] + }, + { + "id": "12", + "header": "Q12 \u2014 Are the evidence tiers earned?", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/evidence-tier-audit.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/evidence-tier-audit.md", + "present": true + } + ] + }, + { + "id": "13", + "header": "Q13 \u2014 Publish the archive-side wording fixes, one at a time", + "bucket": "OPEN", + "status": "", + "evidence": [] + }, + { + "id": "14", + "header": "Q14 \u2014 Put the Inbox on `alexanderwhitestone.com` behind a gate", + "bucket": "OPEN", + "status": "", + "evidence": [] + }, + { + "id": "15", + "header": "Q15 \u2014 Stop the monitor from waking on the pipe's own writes *(pipe; no dependencies)*", + "bucket": "DONE", + "status": "DONE \u2014 2026-09-26 \u224819:05 UTC.", + "evidence": [] + }, + { + "id": "16", + "header": "Q16 \u2014 Per-platform ATS gate census *(career lane; opened 2026-10-01 by reply 21 \u00a73, drafted by zephyrus)*", + "bucket": "OPEN", + "status": "", + "evidence": [] + }, + { + "id": "17", + "header": "Q17 \u2014 Employer-side AI-authorship refusal gates *(career lane; opened 2026-10-03 by reply 26, per Q7)*", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + } + ] + }, + { + "id": "18", + "header": "Q18 \u2014 Employer-side lead intake must be deduped against the prepared index *(career lane; opened 2026-10-04 by reply 28, per the G2i miss)*", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + } + ] + }, + { + "id": "19", + "header": "Q19 \u2014 Three proposed members (local Mac wizard, Grok, Mistral) *(wizard onboarding; opened 2026-10-06 by zephyrus-sparkborn, `checkins/2026-10-06-zephyrus-wizards*.md` + `JOIN-THE-TROUPE.md`)*", + "bucket": "DONE", + "status": "RESOLVED \u2014 provisional (2026-10-06).", + "evidence": [ + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-nonmagazine.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/ledger-audit-pass2.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-nonmagazine.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/ledger-audit-pass2.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-nonmagazine-pilot.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-render-aging.md", + "present": true + } + ] + }, + { + "id": "20", + "header": "Q20 \u2014 Excerpt fidelity and placement for the 91 magazine entries *(archive verification; opened 2026-10-08 by the pipe, per Q7's never-dry obligation)*", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/quote-fidelity-live.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-placement-audit.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-placement-audit.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-placement-rows.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-binding-audit.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-placement-rows.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-binding-audit.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-placement-audit.md", + "present": true + } + ] + }, + { + "id": "21", + "header": "Q21 \u2014 Does every quoted excerpt resolve at the URL it is printed against?", + "bucket": "OPEN", + "status": "open and unclaimed. Opened by the pipe 2026-10-10", + "evidence": [ + { + "kind": "file", + "value": "recoveries/excerpt-binding-audit.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-binding-audit.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/evidence-tier-audit.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-binding-audit.md", + "present": true + } + ] + }, + { + "id": "22", + "header": "Q22 \u2014 Do the named-but-unlinked sources resolve? *(proposed 2026-10-10 by Merlin, per Q7; not yet opened)*", + "bucket": "PROPOSED", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/named-source-liveness.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/named-source-liveness.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/named-source-liveness.md", + "present": true + } + ] + }, + { + "id": "23", + "header": "Q23 \u2014 The prose-named sources the `@` token rule cannot see *(archive verification; opened 2026-10-10 by the pipe, per Q7's never-dry obligation)*", + "bucket": "DONE", + "status": "DONE 2026-10-10 \u2014 `recoveries/named-source-liveness-unlinked.md` (Merlin), verified from the published file this tick (control plane).", + "evidence": [ + { + "kind": "file", + "value": "recoveries/named-source-liveness-unlinked.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/named-source-liveness-unlinked.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/named-source-liveness-unlinked.md", + "present": true + } + ] + }, + { + "id": "24", + "header": "Q24 \u2014 The Q13 fix pack: stage every verified live-page fix as one reviewable approval *(archive-side; opened 2026-10-10 by the pipe, per Q7's never-dry obligation)*", + "bucket": "OPEN", + "status": "open and unclaimed. Opened by the pipe 2026-10-10", + "evidence": [ + { + "kind": "file", + "value": "recoveries/evidence-tier-audit.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/evidence-tier-audit.md", + "present": true + } + ] + }, + { + "id": "25", + "header": "Q25 \u2014 A prose-anchor convention for the ledger build *(archive-side; proposed 2026-10-10 by Merlin, per Q7's never-dry obligation \u2014 Q24 closed and the unclaimed executable set fell to zero)*", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/prose-anchor-convention.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-pilot.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/evidence-tier-audit.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/prose-anchor-convention.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/prose-anchor-convention.md", + "present": true + } + ] + }, + { + "id": "26", + "header": "Q26 \u2014 Make the silent token classes loud, and measure the fifth slot *(archive-side; opened 2026-10-10 by the pipe, per Q7's never-dry obligation \u2014 Q25 closed at `a9f23a6` and the unclaimed executable set fell to zero)*", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/prose-anchor-hardening.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/prose-anchor-hardening.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/prose-anchor-hardening.md", + "present": true + } + ] + }, + { + "id": "27", + "header": "Q27 \u2014 A fixture at every render site: make the token sentinel's coverage total *(archive-side; opened 2026-10-11 by the pipe, per Q7's never-dry obligation \u2014 Q26 closed at `f05179e`)*", + "bucket": "DONE", + "status": "DONE 2026-10-11 \u2014 `recoveries/render-site-coverage.md` (Merlin). 32 sites: 28 covered by fixture, 4 structural exclusions; 35 fixtures, every negative writes 0 files; the scope clause closed with option (a), all four token classes now pre-write; no-token build still byte-identical at `91ecf6bf`.", + "evidence": [ + { + "kind": "file", + "value": "recoveries/prose-anchor-hardening.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/render-site-coverage.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/render-site-coverage.md", + "present": true + }, + { + "kind": "ref", + "value": "91ecf6bf", + "resolves": false, + "full": "" + } + ] + }, + { + "id": "28", + "header": "Q28 \u2014 The channels the entry walk cannot see: state the guarantee, then cover what it cannot reach", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/render-site-channels.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/render-site-coverage.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/render-site-channels.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/render-site-channels.md", + "present": true + } + ] + }, + { + "id": "29", + "header": "Q29 \u2014 The guards that are not the walk: what protects a page when the value is not a token", + "bucket": "DONE", + "status": "DONE 2026-10-11 \u2014 `recoveries/render-site-guards.md` (Merlin), scratch tree `/root/crucible/q29/`. 22 fixtures plus the control, every negative or escape claim measured against the emitted byte; the second guarantee stated in one sentence; one finding: an unguarded `int(sats)` can still leave a partial tree (2 files).", + "evidence": [ + { + "kind": "file", + "value": "recoveries/render-site-guards.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/render-site-channels.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/render-site-guards.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-binding-audit.md", + "present": true + } + ] + }, + { + "id": "30", + "header": "Q30 \u2014 The renderer's entry point: the one path no gate executes", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/helm-render-aging.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-cli-entry-point.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-cli-entry-point.md", + "present": true + } + ] + }, + { + "id": "31", + "header": "Q31 \u2014 The collector's entry point: the sibling path no gate has executed either", + "bucket": "DONE", + "status": "DONE at Merlin's Run 6 (2026-10-11 \u224813:19\u201313:35Z) \u2014 deliverable `recoveries/helm-collector-run.md`; the collector's entry point is executed, its destination is gated, and G8 asserts it.", + "evidence": [ + { + "kind": "file", + "value": "recoveries/helm-collector-run.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-cli-entry-point.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-collector-run.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-pilot.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/prose-anchor-convention.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-collector-run.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-collector-run.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-collector-run.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-collector-run.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-collector-run.md", + "present": true + } + ] + }, + { + "id": "32", + "header": "Q32 \u2014 The G8 two-run agreement check is nondeterministic: `age_seconds` is not scrubbed *(Helm lane; opened 2026-10-11 by the pipe, per Q7's never-dry obligation \u2014 Q31's adoption is blocked behind it)*", + "bucket": "OPEN", + "status": "OPEN \u2014 named to the Helm lane", + "evidence": [ + { + "kind": "file", + "value": "recoveries/helm-g8-scrub.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-collector-run.md", + "present": true + } + ] + }, + { + "id": "33", + "header": "Q33 \u2014 Split the newest-file pointer out of `evidence.source_path` *(collector-side; opened 2026-10-11 by the pipe, per Q7's never-dry obligation \u2014 Q32 closed at `7e12c82`)*", + "bucket": "OPEN", + "status": "OPEN \u2014 named to the Helm lane.", + "evidence": [ + { + "kind": "file", + "value": "recoveries/helm-g8-scrub.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-g8-scrub.md", + "present": true + } + ] + }, + { + "id": "34", + "header": "Q34 \u2014 Gate the pointer's null case *(collector-side gate; opened 2026-10-11 by the pipe, per Q7's never-dry obligation \u2014 Q33 closed at `8bb88da`)*", + "bucket": "DONE", + "status": "DONE 2026-10-12 \u2014 `recoveries/helm-null-gate.md` (Merlin), scratch tree `/root/crucible/q34/`.", + "evidence": [ + { + "kind": "file", + "value": "recoveries/helm-null-gate.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-g8-scrub.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-null-gate.md", + "present": true + } + ] + }, + { + "id": "35", + "header": "Q35 \u2014 The gate must refuse a subject collector that carries no destination rule *(Helm lane; opened 2026-10-12 by the pipe, per Q7's never-dry obligation \u2014 Q34 verified and closed at `ac98bfb`)*", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/helm-precondition-gate.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-precondition-gate.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-binding-audit.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-precondition-gate.md", + "present": true + } + ] + }, + { + "id": "36", + "header": "Q36 \u2014 The monitor cannot see a counterparty write that carries this pipe's identity *(pipe tooling; opened 2026-10-12 by the pipe, per Q7's never-dry obligation \u2014 Q20 verified and closed at `9a1de9a` and the pre-existing executable set fell to empty)*", + "bucket": "DONE", + "status": "DONE \u2014 the rule holds, and the predicted transition arrived exactly as stated.", + "evidence": [ + { + "kind": "file", + "value": "recoveries/excerpt-placement-audit.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/ledger-date-closure.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-collector-run.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/ledger-date-closure.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-placement-audit.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-collector-run.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-precondition-gate.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/prose-anchor-hardening.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/render-site-channels.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/render-site-coverage.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/render-site-guards.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-full-clauses.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-nonmagazine-pilot.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-nonmagazine.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/summary-fidelity-pilot.md", + "present": true + } + ] + }, + { + "id": "37", + "header": "Q37 \u2014 The identity rule closes one class, not the class *(pipe tooling; opened 2026-10-12 by the pipe, per Q7's never-dry obligation \u2014 Q36 closed at `9584984` and the unclaimed executable set fell to empty)*", + "bucket": "OPEN", + "status": "", + "evidence": [] + }, + { + "id": "38", + "header": "Q38 \u2014 The behavioural destination guard *(Helm lane; opened 2026-10-12 by Merlin \u2014 Q36's candidate 2, on Alexander's direction to continue the Helm lane)*", + "bucket": "DONE", + "status": "DONE \u2014 `recoveries/helm-behavioural-guard.md` (10,232 B), Merlin, 2026-10-12T06:5x\u201307:1xZ, this host.", + "evidence": [ + { + "kind": "file", + "value": "recoveries/helm-behavioural-guard.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-behavioural-guard.md", + "present": true + } + ] + }, + { + "id": "38", + "header": "Q38 \u2014 The behavioural destination guard *(Helm lane; opened 2026-10-12 by Merlin \u2014 Q36's candidate 2, on Alexander's direction to continue the Helm lane; **direction unrecorded in this repo \u2014 Testimony only**)*", + "bucket": "DONE", + "status": "the deliverable is verified and the item is DONE, and its protective claim is FALSIFIED. It is not adoptable as it stands.", + "evidence": [] + }, + { + "id": "39", + "header": "Q39 \u2014 The Q38 guard's admission admits a writer, and its legs run the unrewritten subject *(Helm lane; opened 2026-10-12 by the pipe, per Q7's never-dry obligation \u2014 Q38 is closed and verified and its protective claim is falsified, so the executable set is not empty)*", + "bucket": "DONE", + "status": "DONE \u2014 `recoveries/helm-destination-guard-fix.md` (12,253 B), Merlin, 2026-10-12, scratch tree `/root/crucible/q39/`. Fixed gate `9b09f328\u2026` (1,412 lines / 77,704 B, +309/\u221238 against Q38's `74aba348\u2026`); subject collector byte-identical at `4e45021d\u2026`; nothing deployed, no `cp` into `/root/.helm/bin/`, live snapshot `aa842b0f\u2026` delta 0 across every run.", + "evidence": [ + { + "kind": "file", + "value": "recoveries/helm-destination-guard-fix.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-destination-guard-fix.md", + "present": true + }, + { + "kind": "ref", + "value": "9b09f328", + "resolves": false, + "full": "" + }, + { + "kind": "ref", + "value": "74aba348", + "resolves": false, + "full": "" + }, + { + "kind": "ref", + "value": "4e45021d", + "resolves": false, + "full": "" + }, + { + "kind": "ref", + "value": "aa842b0f", + "resolves": false, + "full": "" + } + ] + }, + { + "id": "39", + "header": "Q39 closure \u2014 verified from this host by the pipe (2026-10-12, reply 22)", + "bucket": "DONE", + "status": "DONE. Finished by `fad802c` (record + queue block + Run 5 check-in) and `4e87c8f` (landing evidence); verified by `replies/2026-10-12-to-merlin-22.md` with my own harness `/root/troupe-verify/q39/indep-negatives.py` \u2192 `INDEP-NEGATIVES.json`, `pair-run.log`.", + "evidence": [ + { + "kind": "ref", + "value": "fad802c", + "resolves": true, + "full": "fad802c0f528e4b14838d5e1dda6cbb6354afa9e" + }, + { + "kind": "ref", + "value": "4e87c8f", + "resolves": true, + "full": "4e87c8fee59dcc6d1778fc0e4cabe9552a7e3e96" + } + ] + }, + { + "id": "40", + "header": "Q40 \u2014 the deployed gate admits all five negatives, and has no admission path at all *(Helm lane; opened 2026-10-12 by Merlin, discharging the Q39 closure's C26)*", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/helm-deployed-gate-admission.md", + "present": true + } + ] + }, + { + "id": "37", + "header": "Q37 \u2014 claimed by this pipe; first increment landed (the v1.3 census)", + "bucket": "OPEN", + "status": "OPEN and claimed by the pipe (Merlin's \u00a7Next 2 read it correctly; it is this lane's tooling). Landed this tick:", + "evidence": [ + { + "kind": "file", + "value": "recoveries/monitor-identity-census.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/monitor-identity-census.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/monitor-identity-census.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-placement-audit-zephyrus-sample.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-placement-audit.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-deployed-gate-admission.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-placement-nonmagazine.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-placement-nonmagazine.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-placement-audit-zephyrus-sample.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-placement-rows.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-placement-audit.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-placement-rows.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-deployed-gate-admission.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-placement-nonmagazine.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-placement-nonmagazine.md", + "present": true + } + ] + }, + { + "id": "43", + "header": "Q43 \u2014 The legs run the rewritten subject: prevention, not detect-and-restore *(Helm lane; opened 2026-10-12 by Merlin, per the Q39 closure's own recommendation \u2014 \"open the stronger form (the legs against a rewritten copy) as the Helm lane's next item\")*", + "bucket": "DONE", + "status": "DONE \u2014 `recoveries/helm-leg-sandbox.md` (13,561 B), Merlin, 2026-10-12. Scratch tree `/root/crucible/q43/`; nothing deployed, no `cp` into `/root/.helm/bin/`, `decisions/` and `inbox/` untouched.", + "evidence": [ + { + "kind": "file", + "value": "recoveries/helm-leg-sandbox.md", + "present": true + } + ] + }, + { + "id": "43", + "header": "Q43 closure \u2014 verified from this host by the pipe (2026-10-12, reply 27)", + "bucket": "DONE", + "status": "VERIFIED AND CLOSED from the pipe, 2026-10-12 18:5x\u201319:1xZ.", + "evidence": [ + { + "kind": "file", + "value": "recoveries/helm-leg-sandbox.md", + "present": true + } + ] + }, + { + "id": "44", + "header": "Q44 \u2014 The pin class: redirect every constant composed from the live data root, not only `SNAPSHOT_PATH` *(Helm lane; opened 2026-10-12 by the pipe, per Q43's own closing sentence \u2014 \"extend the redirect beyond `SNAPSHOT_PATH` to every constant composed from the live data root, which is what would close the `--pin` class structurally instead of by argv rule\")*", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/helm-root-redirect.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-root-redirect.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-root-redirect.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-resolved-redirect.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-resolved-redirect.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-parse-guard.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-resolved-redirect.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-parse-guard.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-parse-guard.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-read-path-guard.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-read-path-guard.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-read-path-guard.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-read-path-guard.md", + "present": true + } + ] + }, + { + "id": "48", + "header": "Q48 \u2014 The runtime-resolution redirect: close the class Q45's literals cannot see", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/helm-runtime-redirect.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-runtime-redirect.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-runtime-redirect.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-runtime-redirect.md", + "present": true + } + ] + }, + { + "id": "49", + "header": "Q49 \u2014 The runtime-resolved root's live write path: name it, reproduce it, then close it", + "bucket": "OPEN", + "status": "open and unclaimed. Opened by the pipe 2026-10-13", + "evidence": [ + { + "kind": "file", + "value": "recoveries/helm-runtime-redirect.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-resolved-root-live-path.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-resolved-root-live-path.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-probe-spawn-env.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-resolved-root-live-path.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-probe-spawn-env.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-probe-spawn-env.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/excerpt-placement-nonmagazine-zephyrus-recompute.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-runwide-census-hoist.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-runwide-census-hoist.md", + "present": true + } + ] + }, + { + "id": "45", + "header": "Q45 \u00a79 follow-on \u2014 the home-directory channel *(Helm lane; Merlin)*", + "bucket": "OPEN", + "status": "", + "evidence": [ + { + "kind": "file", + "value": "recoveries/helm-home-channel-guard.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-home-channel-guard.md", + "present": true + }, + { + "kind": "file", + "value": "recoveries/helm-home-channel-guard.md", + "present": true + } + ] + } + ] +} \ No newline at end of file diff --git a/wizard-work/sol/queue_triage.md b/wizard-work/sol/queue_triage.md new file mode 100644 index 0000000..915da4c --- /dev/null +++ b/wizard-work/sol/queue_triage.md @@ -0,0 +1,390 @@ +SOL / SOLO TRIAGE — WORK-QUEUE CLASSIFICATION +============================================================ +source : /root/troupe-standup/WORK-QUEUE.md +done : 2026-10-23T01:03:58.641047Z +lane : Triage (everyday Q&A + classification) + +Every question carries a bucket chosen only from markers already in +the queue text (its "**Status:**" line, "**not yet opened**", "0/15"). +The "evidence" column is the real repo cross-check for the items that +name a file or a commit ref (does the file exist in recoveries/? +does the short/full ref resolve in git?). No ref is taken at face +value: unresolvable refs are marked RESOLVED-FALSE. + +SUMMARY +------------------------------------------------------------ +questions: 49 DONE=16 OPEN=32 PROPOSED=1 EXHAUSTED=0 + +CLASSIFIED QUESTIONS +------------------------------------------------------------ +## [DONE] Q1 — Recover the fifteen silent rooms *(highest value; no dependencies)* +status: CLOSED — 0/15 recovered, and every public avenue is now exhausted with receipts. + evidence: recovery file recoveries/silent-rooms.md -> PRESENT + evidence: recovery file recoveries/silent-rooms.md -> PRESENT + evidence: recovery file recoveries/silent-rooms-enrichment.md -> PRESENT + +## [DONE] Q2 — Chase the one dead link +status: DONE — recovered. + evidence: recovery file recoveries/dead-link.md -> PRESENT + +## [OPEN] Q3 — Independent audit of the published ledger +status: (no Status line in queue) + evidence: recovery file recoveries/ledger-link-inventory.md -> PRESENT + +## [OPEN] Q4 — Falsification pass +status: (no Status line in queue) + evidence: recovery file recoveries/falsification-pass.md -> PRESENT + +## [OPEN] Q8 — Summary fidelity: does each entry's machine-written summary overstate its article? +status: (no Status line in queue) + evidence: recovery file recoveries/quote-fidelity-live.md -> PRESENT + evidence: recovery file recoveries/magazine-article-map.md -> PRESENT + evidence: recovery file recoveries/quote-fidelity-live.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-pilot.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-full.md -> MISSING + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-pilot.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + +## [OPEN] Q5 — Issue triage in the organisation's public repos +status: re-scoped 2026-09-26 (reply 08 §5) after a census, because as written it invites busywork. + +## [OPEN] Q6 — A public guide to checking this archive +status: (no Status line in queue) + +## [OPEN] Q7 — Propose the next items +status: satisfied for the 2026-09-25 cycle. + +## [OPEN] Q9 — Independent QC of the sovereign music candidates *(second opinion, no listening required)* +status: (no Status line in queue) + evidence: recovery file recoveries/music-master-verification.md -> PRESENT + +## [OPEN] Q10 — Summary fidelity for the non-magazine entries +status: (no Status line in queue) + evidence: recovery file recoveries/summary-fidelity-nonmagazine.md -> PRESENT + evidence: recovery file recoveries/ledger-audit-pass2.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-nonmagazine.md -> PRESENT + evidence: recovery file recoveries/excerpt-binding-audit.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-nonmagazine-pilot.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-nonmagazine.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-nonmagazine.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-nonmagazine.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-nonmagazine.md -> PRESENT + +## [OPEN] Q11 — Close the eight pass-2 date mismatches +status: (no Status line in queue) + evidence: recovery file recoveries/ledger-audit-pass2.md -> PRESENT + evidence: recovery file recoveries/ledger-date-closure.md -> PRESENT + evidence: recovery file recoveries/ledger-date-closure.md -> PRESENT + +## [OPEN] Q12 — Are the evidence tiers earned? +status: (no Status line in queue) + evidence: recovery file recoveries/evidence-tier-audit.md -> PRESENT + evidence: recovery file recoveries/evidence-tier-audit.md -> PRESENT + +## [OPEN] Q13 — Publish the archive-side wording fixes, one at a time +status: (no Status line in queue) + +## [OPEN] Q14 — Put the Inbox on `alexanderwhitestone.com` behind a gate +status: (no Status line in queue) + +## [DONE] Q15 — Stop the monitor from waking on the pipe's own writes *(pipe; no dependencies)* +status: DONE — 2026-09-26 ≈19:05 UTC. + +## [OPEN] Q16 — Per-platform ATS gate census *(career lane; opened 2026-10-01 by reply 21 §3, drafted by zephyrus)* +status: (no Status line in queue) + +## [OPEN] Q17 — Employer-side AI-authorship refusal gates *(career lane; opened 2026-10-03 by reply 26, per Q7)* +status: (no Status line in queue) + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + +## [OPEN] Q18 — Employer-side lead intake must be deduped against the prepared index *(career lane; opened 2026-10-04 by reply 28, per the G2i miss)* +status: (no Status line in queue) + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + +## [DONE] Q19 — Three proposed members (local Mac wizard, Grok, Mistral) *(wizard onboarding; opened 2026-10-06 by zephyrus-sparkborn, `checkins/2026-10-06-zephyrus-wizards*.md` + `JOIN-THE-TROUPE.md`)* +status: RESOLVED — provisional (2026-10-06). + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-nonmagazine.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + evidence: recovery file recoveries/ledger-audit-pass2.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-nonmagazine.md -> PRESENT + evidence: recovery file recoveries/ledger-audit-pass2.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-nonmagazine-pilot.md -> PRESENT + evidence: recovery file recoveries/helm-render-aging.md -> PRESENT + +## [OPEN] Q20 — Excerpt fidelity and placement for the 91 magazine entries *(archive verification; opened 2026-10-08 by the pipe, per Q7's never-dry obligation)* +status: (no Status line in queue) + evidence: recovery file recoveries/quote-fidelity-live.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-audit.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-audit.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-rows.md -> PRESENT + evidence: recovery file recoveries/excerpt-binding-audit.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-rows.md -> PRESENT + evidence: recovery file recoveries/excerpt-binding-audit.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-audit.md -> PRESENT + +## [OPEN] Q21 — Does every quoted excerpt resolve at the URL it is printed against? +status: open and unclaimed. Opened by the pipe 2026-10-10 + evidence: recovery file recoveries/excerpt-binding-audit.md -> PRESENT + evidence: recovery file recoveries/excerpt-binding-audit.md -> PRESENT + evidence: recovery file recoveries/evidence-tier-audit.md -> PRESENT + evidence: recovery file recoveries/excerpt-binding-audit.md -> PRESENT + +## [PROPOSED] Q22 — Do the named-but-unlinked sources resolve? *(proposed 2026-10-10 by Merlin, per Q7; not yet opened)* +status: (no Status line in queue) + evidence: recovery file recoveries/named-source-liveness.md -> PRESENT + evidence: recovery file recoveries/named-source-liveness.md -> PRESENT + evidence: recovery file recoveries/named-source-liveness.md -> PRESENT + +## [DONE] Q23 — The prose-named sources the `@` token rule cannot see *(archive verification; opened 2026-10-10 by the pipe, per Q7's never-dry obligation)* +status: DONE 2026-10-10 — `recoveries/named-source-liveness-unlinked.md` (Merlin), verified from the published file this tick (control plane). + evidence: recovery file recoveries/named-source-liveness-unlinked.md -> PRESENT + evidence: recovery file recoveries/named-source-liveness-unlinked.md -> PRESENT + evidence: recovery file recoveries/named-source-liveness-unlinked.md -> PRESENT + +## [OPEN] Q24 — The Q13 fix pack: stage every verified live-page fix as one reviewable approval *(archive-side; opened 2026-10-10 by the pipe, per Q7's never-dry obligation)* +status: open and unclaimed. Opened by the pipe 2026-10-10 + evidence: recovery file recoveries/evidence-tier-audit.md -> PRESENT + evidence: recovery file recoveries/evidence-tier-audit.md -> PRESENT + +## [OPEN] Q25 — A prose-anchor convention for the ledger build *(archive-side; proposed 2026-10-10 by Merlin, per Q7's never-dry obligation — Q24 closed and the unclaimed executable set fell to zero)* +status: (no Status line in queue) + evidence: recovery file recoveries/prose-anchor-convention.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-pilot.md -> PRESENT + evidence: recovery file recoveries/evidence-tier-audit.md -> PRESENT + evidence: recovery file recoveries/prose-anchor-convention.md -> PRESENT + evidence: recovery file recoveries/prose-anchor-convention.md -> PRESENT + +## [OPEN] Q26 — Make the silent token classes loud, and measure the fifth slot *(archive-side; opened 2026-10-10 by the pipe, per Q7's never-dry obligation — Q25 closed at `a9f23a6` and the unclaimed executable set fell to zero)* +status: (no Status line in queue) + evidence: recovery file recoveries/prose-anchor-hardening.md -> PRESENT + evidence: recovery file recoveries/prose-anchor-hardening.md -> PRESENT + evidence: recovery file recoveries/prose-anchor-hardening.md -> PRESENT + +## [DONE] Q27 — A fixture at every render site: make the token sentinel's coverage total *(archive-side; opened 2026-10-11 by the pipe, per Q7's never-dry obligation — Q26 closed at `f05179e`)* +status: DONE 2026-10-11 — `recoveries/render-site-coverage.md` (Merlin). 32 sites: 28 covered by fixture, 4 structural exclusions; 35 fixtures, every negative writes 0 files; the scope clause closed with option (a), all four token classes now pre-write; no-token build still byte-identical at `91ecf6bf`. + evidence: recovery file recoveries/prose-anchor-hardening.md -> PRESENT + evidence: recovery file recoveries/render-site-coverage.md -> PRESENT + evidence: recovery file recoveries/render-site-coverage.md -> PRESENT + evidence: ref 91ecf6bf -> RESOLVED-FALSE + +## [OPEN] Q28 — The channels the entry walk cannot see: state the guarantee, then cover what it cannot reach +status: (no Status line in queue) + evidence: recovery file recoveries/render-site-channels.md -> PRESENT + evidence: recovery file recoveries/render-site-coverage.md -> PRESENT + evidence: recovery file recoveries/render-site-channels.md -> PRESENT + evidence: recovery file recoveries/render-site-channels.md -> PRESENT + +## [DONE] Q29 — The guards that are not the walk: what protects a page when the value is not a token +status: DONE 2026-10-11 — `recoveries/render-site-guards.md` (Merlin), scratch tree `/root/crucible/q29/`. 22 fixtures plus the control, every negative or escape claim measured against the emitted byte; the second guarantee stated in one sentence; one finding: an unguarded `int(sats)` can still leave a partial tree (2 files). + evidence: recovery file recoveries/render-site-guards.md -> PRESENT + evidence: recovery file recoveries/render-site-channels.md -> PRESENT + evidence: recovery file recoveries/render-site-guards.md -> PRESENT + evidence: recovery file recoveries/excerpt-binding-audit.md -> PRESENT + +## [OPEN] Q30 — The renderer's entry point: the one path no gate executes +status: (no Status line in queue) + evidence: recovery file recoveries/helm-render-aging.md -> PRESENT + evidence: recovery file recoveries/helm-cli-entry-point.md -> PRESENT + evidence: recovery file recoveries/helm-cli-entry-point.md -> PRESENT + +## [DONE] Q31 — The collector's entry point: the sibling path no gate has executed either +status: DONE at Merlin's Run 6 (2026-10-11 ≈13:19–13:35Z) — deliverable `recoveries/helm-collector-run.md`; the collector's entry point is executed, its destination is gated, and G8 asserts it. + evidence: recovery file recoveries/helm-collector-run.md -> PRESENT + evidence: recovery file recoveries/helm-cli-entry-point.md -> PRESENT + evidence: recovery file recoveries/helm-collector-run.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-pilot.md -> PRESENT + evidence: recovery file recoveries/prose-anchor-convention.md -> PRESENT + evidence: recovery file recoveries/helm-collector-run.md -> PRESENT + evidence: recovery file recoveries/helm-collector-run.md -> PRESENT + evidence: recovery file recoveries/helm-collector-run.md -> PRESENT + evidence: recovery file recoveries/helm-collector-run.md -> PRESENT + evidence: recovery file recoveries/helm-collector-run.md -> PRESENT + +## [OPEN] Q32 — The G8 two-run agreement check is nondeterministic: `age_seconds` is not scrubbed *(Helm lane; opened 2026-10-11 by the pipe, per Q7's never-dry obligation — Q31's adoption is blocked behind it)* +status: OPEN — named to the Helm lane + evidence: recovery file recoveries/helm-g8-scrub.md -> PRESENT + evidence: recovery file recoveries/helm-collector-run.md -> PRESENT + +## [OPEN] Q33 — Split the newest-file pointer out of `evidence.source_path` *(collector-side; opened 2026-10-11 by the pipe, per Q7's never-dry obligation — Q32 closed at `7e12c82`)* +status: OPEN — named to the Helm lane. + evidence: recovery file recoveries/helm-g8-scrub.md -> PRESENT + evidence: recovery file recoveries/helm-g8-scrub.md -> PRESENT + +## [DONE] Q34 — Gate the pointer's null case *(collector-side gate; opened 2026-10-11 by the pipe, per Q7's never-dry obligation — Q33 closed at `8bb88da`)* +status: DONE 2026-10-12 — `recoveries/helm-null-gate.md` (Merlin), scratch tree `/root/crucible/q34/`. + evidence: recovery file recoveries/helm-null-gate.md -> PRESENT + evidence: recovery file recoveries/helm-g8-scrub.md -> PRESENT + evidence: recovery file recoveries/helm-null-gate.md -> PRESENT + +## [OPEN] Q35 — The gate must refuse a subject collector that carries no destination rule *(Helm lane; opened 2026-10-12 by the pipe, per Q7's never-dry obligation — Q34 verified and closed at `ac98bfb`)* +status: (no Status line in queue) + evidence: recovery file recoveries/helm-precondition-gate.md -> PRESENT + evidence: recovery file recoveries/helm-precondition-gate.md -> PRESENT + evidence: recovery file recoveries/excerpt-binding-audit.md -> PRESENT + evidence: recovery file recoveries/helm-precondition-gate.md -> PRESENT + +## [DONE] Q36 — The monitor cannot see a counterparty write that carries this pipe's identity *(pipe tooling; opened 2026-10-12 by the pipe, per Q7's never-dry obligation — Q20 verified and closed at `9a1de9a` and the pre-existing executable set fell to empty)* +status: DONE — the rule holds, and the predicted transition arrived exactly as stated. + evidence: recovery file recoveries/excerpt-placement-audit.md -> PRESENT + evidence: recovery file recoveries/ledger-date-closure.md -> PRESENT + evidence: recovery file recoveries/helm-collector-run.md -> PRESENT + evidence: recovery file recoveries/ledger-date-closure.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-audit.md -> PRESENT + evidence: recovery file recoveries/helm-collector-run.md -> PRESENT + evidence: recovery file recoveries/helm-precondition-gate.md -> PRESENT + evidence: recovery file recoveries/prose-anchor-hardening.md -> PRESENT + evidence: recovery file recoveries/render-site-channels.md -> PRESENT + evidence: recovery file recoveries/render-site-coverage.md -> PRESENT + evidence: recovery file recoveries/render-site-guards.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-full-clauses.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-nonmagazine-pilot.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-nonmagazine.md -> PRESENT + evidence: recovery file recoveries/summary-fidelity-pilot.md -> PRESENT + +## [OPEN] Q37 — The identity rule closes one class, not the class *(pipe tooling; opened 2026-10-12 by the pipe, per Q7's never-dry obligation — Q36 closed at `9584984` and the unclaimed executable set fell to empty)* +status: (no Status line in queue) + evidence: recovery file recoveries/monitor-identity-census.md -> PRESENT + evidence: recovery file recoveries/monitor-identity-census.md -> PRESENT + evidence: recovery file recoveries/monitor-identity-census.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-audit-zephyrus-sample.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-audit.md -> PRESENT + evidence: recovery file recoveries/helm-deployed-gate-admission.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-nonmagazine.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-nonmagazine.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-audit-zephyrus-sample.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-rows.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-audit.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-rows.md -> PRESENT + evidence: recovery file recoveries/helm-deployed-gate-admission.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-nonmagazine.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-nonmagazine.md -> PRESENT + +## [DONE] Q38 — The behavioural destination guard *(Helm lane; opened 2026-10-12 by Merlin — Q36's candidate 2, on Alexander's direction to continue the Helm lane)* +status: DONE — `recoveries/helm-behavioural-guard.md` (10,232 B), Merlin, 2026-10-12T06:5x–07:1xZ, this host. + evidence: recovery file recoveries/helm-behavioural-guard.md -> PRESENT + evidence: recovery file recoveries/helm-behavioural-guard.md -> PRESENT + +## [DONE] Q38 — The behavioural destination guard *(Helm lane; opened 2026-10-12 by Merlin — Q36's candidate 2, on Alexander's direction to continue the Helm lane; **direction unrecorded in this repo — Testimony only**)* +status: the deliverable is verified and the item is DONE, and its protective claim is FALSIFIED. It is not adoptable as it stands. + evidence: recovery file recoveries/helm-behavioural-guard.md -> PRESENT + evidence: recovery file recoveries/helm-behavioural-guard.md -> PRESENT + +## [DONE] Q39 — The Q38 guard's admission admits a writer, and its legs run the unrewritten subject *(Helm lane; opened 2026-10-12 by the pipe, per Q7's never-dry obligation — Q38 is closed and verified and its protective claim is falsified, so the executable set is not empty)* +status: DONE — `recoveries/helm-destination-guard-fix.md` (12,253 B), Merlin, 2026-10-12, scratch tree `/root/crucible/q39/`. Fixed gate `9b09f328…` (1,412 lines / 77,704 B, +309/−38 against Q38's `74aba348…`); subject collector byte-identical at `4e45021d…`; nothing deployed, no `cp` into `/root/.helm/bin/`, live snapshot `aa842b0f…` delta 0 across every run. + evidence: recovery file recoveries/helm-destination-guard-fix.md -> PRESENT + evidence: recovery file recoveries/helm-destination-guard-fix.md -> PRESENT + evidence: ref 9b09f328 -> RESOLVED-FALSE + evidence: ref 74aba348 -> RESOLVED-FALSE + evidence: ref 4e45021d -> RESOLVED-FALSE + evidence: ref aa842b0f -> RESOLVED-FALSE + evidence: ref fad802c -> RESOLVED + evidence: ref 4e87c8f -> RESOLVED + +## [DONE] Q39 closure — verified from this host by the pipe (2026-10-12, reply 22) +status: DONE. Finished by `fad802c` (record + queue block + Run 5 check-in) and `4e87c8f` (landing evidence); verified by `replies/2026-10-12-to-merlin-22.md` with my own harness `/root/troupe-verify/q39/indep-negatives.py` → `INDEP-NEGATIVES.json`, `pair-run.log`. + evidence: recovery file recoveries/helm-destination-guard-fix.md -> PRESENT + evidence: recovery file recoveries/helm-destination-guard-fix.md -> PRESENT + evidence: ref 9b09f328 -> RESOLVED-FALSE + evidence: ref 74aba348 -> RESOLVED-FALSE + evidence: ref 4e45021d -> RESOLVED-FALSE + evidence: ref aa842b0f -> RESOLVED-FALSE + evidence: ref fad802c -> RESOLVED + evidence: ref 4e87c8f -> RESOLVED + +## [OPEN] Q40 — the deployed gate admits all five negatives, and has no admission path at all *(Helm lane; opened 2026-10-12 by Merlin, discharging the Q39 closure's C26)* +status: (no Status line in queue) + evidence: recovery file recoveries/helm-deployed-gate-admission.md -> PRESENT + +## [OPEN] Q37 — claimed by this pipe; first increment landed (the v1.3 census) +status: OPEN and claimed by the pipe (Merlin's §Next 2 read it correctly; it is this lane's tooling). Landed this tick: + evidence: recovery file recoveries/monitor-identity-census.md -> PRESENT + evidence: recovery file recoveries/monitor-identity-census.md -> PRESENT + evidence: recovery file recoveries/monitor-identity-census.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-audit-zephyrus-sample.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-audit.md -> PRESENT + evidence: recovery file recoveries/helm-deployed-gate-admission.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-nonmagazine.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-nonmagazine.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-audit-zephyrus-sample.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-rows.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-audit.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-rows.md -> PRESENT + evidence: recovery file recoveries/helm-deployed-gate-admission.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-nonmagazine.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-nonmagazine.md -> PRESENT + +## [DONE] Q43 — The legs run the rewritten subject: prevention, not detect-and-restore *(Helm lane; opened 2026-10-12 by Merlin, per the Q39 closure's own recommendation — "open the stronger form (the legs against a rewritten copy) as the Helm lane's next item")* +status: DONE — `recoveries/helm-leg-sandbox.md` (13,561 B), Merlin, 2026-10-12. Scratch tree `/root/crucible/q43/`; nothing deployed, no `cp` into `/root/.helm/bin/`, `decisions/` and `inbox/` untouched. + evidence: recovery file recoveries/helm-leg-sandbox.md -> PRESENT + evidence: recovery file recoveries/helm-leg-sandbox.md -> PRESENT + +## [DONE] Q43 closure — verified from this host by the pipe (2026-10-12, reply 27) +status: VERIFIED AND CLOSED from the pipe, 2026-10-12 18:5x–19:1xZ. + evidence: recovery file recoveries/helm-leg-sandbox.md -> PRESENT + evidence: recovery file recoveries/helm-leg-sandbox.md -> PRESENT + +## [OPEN] Q44 — The pin class: redirect every constant composed from the live data root, not only `SNAPSHOT_PATH` *(Helm lane; opened 2026-10-12 by the pipe, per Q43's own closing sentence — "extend the redirect beyond `SNAPSHOT_PATH` to every constant composed from the live data root, which is what would close the `--pin` class structurally instead of by argv rule")* +status: (no Status line in queue) + evidence: recovery file recoveries/helm-root-redirect.md -> PRESENT + evidence: recovery file recoveries/helm-root-redirect.md -> PRESENT + evidence: recovery file recoveries/helm-root-redirect.md -> PRESENT + evidence: recovery file recoveries/helm-resolved-redirect.md -> PRESENT + evidence: recovery file recoveries/helm-resolved-redirect.md -> PRESENT + evidence: recovery file recoveries/helm-parse-guard.md -> PRESENT + evidence: recovery file recoveries/helm-resolved-redirect.md -> PRESENT + evidence: recovery file recoveries/helm-parse-guard.md -> PRESENT + evidence: recovery file recoveries/helm-parse-guard.md -> PRESENT + evidence: recovery file recoveries/helm-read-path-guard.md -> PRESENT + evidence: recovery file recoveries/helm-read-path-guard.md -> PRESENT + evidence: recovery file recoveries/helm-read-path-guard.md -> PRESENT + evidence: recovery file recoveries/helm-read-path-guard.md -> PRESENT + +## [OPEN] Q48 — The runtime-resolution redirect: close the class Q45's literals cannot see +status: (no Status line in queue) + evidence: recovery file recoveries/helm-runtime-redirect.md -> PRESENT + evidence: recovery file recoveries/helm-runtime-redirect.md -> PRESENT + evidence: recovery file recoveries/helm-runtime-redirect.md -> PRESENT + evidence: recovery file recoveries/helm-runtime-redirect.md -> PRESENT + +## [OPEN] Q49 — The runtime-resolved root's live write path: name it, reproduce it, then close it +status: open and unclaimed. Opened by the pipe 2026-10-13 + evidence: recovery file recoveries/helm-runtime-redirect.md -> PRESENT + evidence: recovery file recoveries/helm-resolved-root-live-path.md -> PRESENT + evidence: recovery file recoveries/helm-resolved-root-live-path.md -> PRESENT + evidence: recovery file recoveries/helm-probe-spawn-env.md -> PRESENT + evidence: recovery file recoveries/helm-resolved-root-live-path.md -> PRESENT + evidence: recovery file recoveries/helm-probe-spawn-env.md -> PRESENT + evidence: recovery file recoveries/helm-probe-spawn-env.md -> PRESENT + evidence: recovery file recoveries/excerpt-placement-nonmagazine-zephyrus-recompute.md -> PRESENT + evidence: recovery file recoveries/helm-runwide-census-hoist.md -> PRESENT + evidence: recovery file recoveries/helm-runwide-census-hoist.md -> PRESENT + +## [OPEN] Q45 §9 follow-on — the home-directory channel *(Helm lane; Merlin)* +status: (no Status line in queue) + evidence: recovery file recoveries/helm-home-channel-guard.md -> PRESENT + evidence: recovery file recoveries/helm-home-channel-guard.md -> PRESENT + evidence: recovery file recoveries/helm-home-channel-guard.md -> PRESENT + +NOTES +------------------------------------------------------------ +- The queue contains duplicate headers (Q38 x2, Q37 x2, Q43 x2, and a + bare "Q39 closure" header); each occurrence is classified as it appears. +- A "RESOLVED-FALSE" ref means the short ref does not resolve here; it is + quoted back in the report, not edited away. +- SOURCE OF TRUTH: the queue text + git on this host. Nothing is invented. \ No newline at end of file diff --git a/wizard-work/sol/verify_triage_queue.py b/wizard-work/sol/verify_triage_queue.py new file mode 100644 index 0000000..018ca9a --- /dev/null +++ b/wizard-work/sol/verify_triage_queue.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +"""CHECK for the work-queue triage deliverable (sol). + +Re-derives the classification from WORK-QUEUE.md, re-reads the report it +generated, diffs the two, and independently re-runs git rev-parse for every +ref verdict recorded in the report. Exit 0 == the report passes the check; +nonzero == wrong. + +Bare command (the VERDICT): + python3 /root/.hermes/wizard-outputs/sol/verify_triage_queue.py +""" + +import os +import re +import subprocess +import sys + +REPO = '/root/troupe-standup' +SRC = os.path.join(REPO, 'WORK-QUEUE.md') +REPORT = os.path.join(REPO, 'wizard-work', 'sol', 'queue_triage.md') +failures = [] + + +def check(cond, msg): + if not cond: + failures.append(msg) + + +def clean(s): + return ' '.join(s.split()) + + +def parse_questions(): + parts = re.split(r'\n(?=#{2,3} )', open(SRC).read()) + hdr_re = re.compile(r'^(#{2,3})\s+(.*)') + out = [] + for p in parts: + m = hdr_re.match(p) + if not m: + continue + header = clean(m.group(2)) + if not re.match(r'^Q\d', header): + continue + body = p + sm = re.search(r'\*\*Status:\s*(.*?)\*\*', body, re.M) + out.append({'header': header, 'status': clean(sm.group(1)) if sm else '', + 'body': body}) + return out + + +def bucket(q): + s = q['status'] + if re.search(r'(DONE|CLOSED|RESOLVED|VERDICT)', s): + return 'DONE' + if 'not yet opened' in q['header'].lower() or 'not yet opened' in s.lower(): + return 'PROPOSED' + if 'exhausted' in s.lower() or '0/15' in s: + return 'EXHAUSTED' + return 'OPEN' + + +def report_entries(): + entries = [] + if not os.path.isfile(REPORT): + failures.append('report missing: ' + REPORT) + return entries + for line in open(REPORT): + m = re.match(r'^## \[(DONE|OPEN|PROPOSED|EXHAUSTED)\] (.*)$', line) + if m: + entries.append({'bucket': m.group(1), 'header': m.group(2).strip()}) + return entries + + +def ref_resolves(ref): + r = subprocess.run(['git', '-C', REPO, 'rev-parse', '-q', '--verify', ref], + capture_output=True, text=True) + return r.returncode == 0 + + +def main(): + qs = parse_questions() + exp = [{'bucket': bucket(q), 'header': q['header']} for q in qs] + + rep = report_entries() + check(rep == exp, 'CLASSIFY: report entries do not match queue derivation') + + # summary / bucket counts + for line in open(REPORT): + if line.startswith('questions:'): + check(line.split('questions:')[1].split()[0] == str(len(qs)), + 'SUMMARY: total %r != %d' % (line.split('questions:')[1], len(qs))) + for k in ('DONE', 'OPEN', 'PROPOSED', 'EXHAUSTED'): + m = re.match(r'^' + k + r'=(\d+)', line) + if m: + want = sum(1 for e in exp if e['bucket'] == k) + check(int(m.group(1)) == want, 'COUNT %s=%d want %d' % + (k, int(m.group(1)), want)) + + # ref verdicts re-run against git + for line in open(REPORT): + m = re.match(r'^ evidence: ref (\S+) -> (RESOLVED|RESOLVED-FALSE)$', line) + if m: + ref, verdict = m.group(1), m.group(2) + real = ref_resolves(ref) + check(verdict == ('RESOLVED' if real else 'RESOLVED-FALSE'), + 'EVIDENCE ref %s = %s but git says %s' % (ref, verdict, + 'RESOLVED' if real else 'RESOLVED-FALSE')) + + # file-evidence sanity: every question that names a recovery file has a + # corresponding PRESENT/MISSING entry in the report + rep_text = open(REPORT).read() + for i, q in enumerate(qs): + if i >= len(rep): + break + has_named_file = bool(re.search(r'recoveries/[A-Za-z0-9_.-]+', q['body'])) + has_evidence = 'evidence: recovery file' in rep_text + if has_named_file and not has_evidence: + failures.append('EVIDENCE: Q%s names a recovery file but none listed' % q['header']) + + print('CHECK questions=%d failures=%d' % (len(qs), len(failures))) + if failures: + for f in failures: + print(' FAIL:', f) + sys.exit(1) + print('CHECK PASS: report matches queue derivation and all refs verified') + sys.exit(0) + + +if __name__ == '__main__': + main()