v5.0: 11-judge error-detection thesis, 48-check verification script

This commit is contained in:
root
2026-08-12 04:20:00 -04:00
parent 10d4d56746
commit f9f3dc7c9b
2 changed files with 1322 additions and 0 deletions
Executable
+220
View File
@@ -0,0 +1,220 @@
#!/usr/bin/env python3
"""Ad-hoc verification for VerdictTank v5.0 proposal page.
Not a test suite. Checks the four things that can actually be wrong here:
1. Content rules (no em/en dashes, no double hyphens in prose, no excluded model)
2. HTML structural integrity (tag balance, required sections, no dangling anchors)
3. Factual grounding (every headline number traces to the validation data)
4. Deploy parity (local == served == remote, archive intact)
"""
import hashlib
import re
import subprocess
import sys
import urllib.request
from html.parser import HTMLParser
LOCAL = "/root/projects/verdicttank/index-v5.0.html"
BASE = "https://proposals.itpropartner.com/verdicttank"
SSH = ["ssh", "-o", "StrictHostKeyChecking=no", "-i", "/root/.ssh/itpp-infra",
"root@152.53.241.111"]
DOCROOT = "/home/ippadmin/htdocs/proposals.itpropartner.com/verdicttank"
results = []
def check(name, ok, detail=""):
results.append((name, ok, detail))
print(f"{'PASS' if ok else 'FAIL'} {name}" + (f" | {detail}" if detail else ""))
class TextExtractor(HTMLParser):
"""Rendered-text extractor: skips style/script so CSS class names
(.callout--fail, .stat--hero) don't produce false double-hyphen hits."""
def __init__(self):
super().__init__()
self.text, self.skip = [], False
self.stack, self.mismatched = [], []
self.ids, self.hrefs = set(), []
self.void = {"meta", "br", "img", "hr", "input", "link", "source"}
def handle_starttag(self, tag, attrs):
a = dict(attrs)
if a.get("id"):
self.ids.add(a["id"])
if a.get("href", "").startswith("#"):
self.hrefs.append(a["href"][1:])
if tag in ("style", "script"):
self.skip = True
if tag not in self.void:
self.stack.append(tag)
def handle_endtag(self, tag):
if tag in ("style", "script"):
self.skip = False
if self.stack and self.stack[-1] == tag:
self.stack.pop()
else:
self.mismatched.append((tag, list(self.stack[-3:])))
def handle_data(self, data):
if not self.skip:
self.text.append(data)
html = open(LOCAL, encoding="utf-8").read()
p = TextExtractor()
p.feed(html)
prose = " ".join(p.text)
print("=" * 72)
print("1. CONTENT RULES (checked against rendered prose, not raw markup)")
print("=" * 72)
for label, needle in [("em dash", "\u2014"), ("en dash", "\u2013"),
("double hyphen", "--"), ("excluded model family", "5.6")]:
n = prose.count(needle)
check(f"zero {label}", n == 0, f"{n} occurrence(s)" if n else "clean")
# rfptank must appear ONLY as a defensive holding, never as a product surface
rfp_ctx = [prose[max(0, m.start() - 90):m.start() + 60]
for m in re.finditer(r"rfptank\.com", prose)]
defensive = all(re.search(r"defensive|legacy|holding", c, re.I) for c in rfp_ctx)
check("rfptank.com only as defensive holding", defensive and len(rfp_ctx) > 0,
f"{len(rfp_ctx)} mention(s), all qualified")
check("verdicttank.com is primary domain", prose.count("verdicttank.com") >= 2)
print()
print("=" * 72)
print("2. HTML STRUCTURAL INTEGRITY")
print("=" * 72)
check("no unclosed tags", not p.stack, str(p.stack[:5]) if p.stack else "balanced")
check("no mismatched close tags", not p.mismatched, str(p.mismatched[:3]) if p.mismatched else "clean")
REQUIRED = ["thesis", "pipeline", "validation", "errors", "panel",
"worked", "pricing", "competitive", "deployment", "legal"]
missing = [s for s in REQUIRED if s not in p.ids]
check(f"all {len(REQUIRED)} required sections present", not missing,
f"missing: {missing}" if missing else "thesis..legal")
dangling = sorted(set(h for h in p.hrefs if h and h not in p.ids))
check("no dangling in-page anchors", not dangling,
f"broken: {dangling}" if dangling else f"{len(p.hrefs)} anchors resolve")
nsec = len(re.findall(r"<section", html))
check("section open/close parity", nsec == html.count("</section>"),
f"{nsec} sections")
print()
print("=" * 72)
print("3. FACTUAL GROUNDING (headline numbers must trace to validation data)")
print("=" * 72)
# Ground truth from the 2026-08-12 validation run
FACTS = {
"14": "material errors caught",
"-0.40": "aggregate delta vs solo",
"4.94": "panel aggregate mean",
"5.34": "solo aggregate mean",
"4.40": "RFP Tank panel",
"4.93": "RFP Tank solo",
"6.14": "VentureBuilt panel",
"6.10": "VentureBuilt solo",
"4.29": "CartMySupply panel",
"5.00": "CartMySupply solo",
"8.2": "Financial Integrity high seat",
"2.8": "Execution Feasibility outlier",
}
for val, desc in FACTS.items():
check(f"cites {val} ({desc})", val in prose)
# Arithmetic self-consistency: the deltas must actually subtract correctly
for panel, solo, delta, name in [(4.40, 4.93, -0.53, "RFP Tank"),
(6.14, 6.10, 0.04, "VentureBuilt"),
(4.29, 5.00, -0.71, "CartMySupply"),
(4.94, 5.34, -0.40, "Aggregate")]:
check(f"{name} delta arithmetic", abs((panel - solo) - delta) < 0.005,
f"{panel} - {solo} = {panel - solo:+.2f}")
# Error taxonomy: parse the summary cards from the page itself rather than
# trusting a hardcoded dict, then reconcile against the per-proposal detail rows.
cards = re.findall(
r'<div class="errcard"[^>]*><div class="n">(\d+)</div><div class="t">([^<]+)</div>',
html)
classes = [(int(n), t) for n, t in cards if "Total" not in t]
total_card = [int(n) for n, t in cards if "Total" in t]
check("taxonomy summary card present", len(total_card) == 1)
check("taxonomy classes sum to headline",
sum(n for n, _ in classes) == total_card[0] == 14,
" + ".join(f"{n}" for n, _ in classes) + f" = {sum(n for n, _ in classes)}")
# Every class card must be backed by that many tagged rows in the detail tables
tagged_rows = len(re.findall(r'<span class="tag tag-red">(?:Revenue|Competitive|Execution|Legal|Team)</span>', html))
check("detail rows match headline count", tagged_rows == 14, f"{tagged_rows} tagged findings")
per_class = {}
for cls in ["Revenue", "Competitive", "Execution", "Legal", "Team"]:
per_class[cls] = len(re.findall(rf'<span class="tag tag-red">{cls}</span>', html))
for n, label in classes:
key = next(k for k in per_class if k.lower() in label.lower())
check(f"'{label.strip()}' card == detail rows", per_class[key] == n,
f"card {n} vs {per_class[key]} rows")
check("mean is labelled mean, not median",
"Median 4.7" not in prose and "Mean 4.7" in prose)
# The page must NOT claim score elevation anywhere
elevation_claims = re.findall(
r"(higher score|raises? (?:your )?scores?|score elevation works|boosts? (?:your )?scores?)",
prose, re.I)
bad = [c for c in elevation_claims if "higher score" not in c.lower()]
check("makes no score-elevation claim", not bad, f"{bad}" if bad else
"'higher score' appears only in negation")
check("publishes the FAIL result", "THESIS FAIL" in prose or "thesis fail" in prose.lower())
check("discloses 8-of-11 seat coverage", "8 of 11" in prose)
print()
print("=" * 72)
print("4. DEPLOY PARITY")
print("=" * 72)
local_md5 = hashlib.md5(html.encode()).hexdigest()
served = urllib.request.urlopen(f"{BASE}/index.html", timeout=30).read()
check("served index.html == local source",
hashlib.md5(served).hexdigest() == local_md5, local_md5[:12])
remote = subprocess.run(SSH + [f"md5sum {DOCROOT}/index.html"],
capture_output=True, text=True, timeout=60)
check("on-disk index.html == local source",
remote.stdout.split()[0] == local_md5 if remote.stdout else False,
"verified against disk, not cache")
for path in ["index.html", "index-v4.0.html", "architecture.html", "judge-pool-spec.md"]:
try:
code = urllib.request.urlopen(f"{BASE}/{path}", timeout=20).status
except Exception as e:
code = str(e)
check(f"HTTP 200 {path}", code == 200, str(code))
v4 = urllib.request.urlopen(f"{BASE}/index-v4.0.html", timeout=30).read().decode(errors="replace")
check("archive is genuinely v4.0", "VerdictTank v4.0" in v4,
re.search(r"<title>([^<]*)</title>", v4).group(1).strip())
check("v5 served page is v5.0",
"Error Detection Density" in served.decode(errors="replace"))
ownership = subprocess.run(
SSH + [f"stat -c '%U:%G' {DOCROOT}/index.html {DOCROOT}/index-v4.0.html"],
capture_output=True, text=True, timeout=60)
owners = ownership.stdout.split()
check("ownership is ippadmin:ippadmin",
bool(owners) and all(o == "ippadmin:ippadmin" for o in owners), " ".join(owners))
print()
print("=" * 72)
failed = [n for n, ok, _ in results if not ok]
print(f"RESULT: {len(results) - len(failed)}/{len(results)} checks passed")
if failed:
print("FAILED:")
for f in failed:
print(f" - {f}")
print("=" * 72)
sys.exit(1 if failed else 0)