polyglot-alpha / scripts /db_chain_api_runner.py
licaomeng
deploy: main@8970ffb → HF Spaces (2026-05-27T05:19Z)
88d2f2a
"""DB integrity + on-chain receipt verification + API contract testing runner.
Runs three suites of checks:
Section A: 60 SQLite-driven DB integrity checks
Section B: 40 on-chain (Arc + Polygon) checks via JSON-RPC + web3
Section C: 40 API contract checks via requests against http://localhost:8000
Outputs one JSON status file per iteration (iter 1..3) and rolls a markdown
final report.
NO Playwright. NO UI mutation. Read-only against DB and chain; only POST is
trigger/event with safely invalid payloads expected to be rejected.
"""
from __future__ import annotations
import json
import os
import statistics
import time
from dataclasses import dataclass
from pathlib import Path
from typing import Any, Callable
import requests
ROOT = Path("/Users/messili/codebase/polyglot-alpha")
DB_PATH = ROOT / "polyglot_alpha.db"
OUT_DIR = ROOT / "outputs"
OUT_DIR.mkdir(exist_ok=True)
PROGRESS_LOG = OUT_DIR / "db_chain_api_progress.log"
API = "http://localhost:8000"
# Default timeout for ordinary GETs; raised for POSTs (orchestrator can block)
API_GET_TIMEOUT = 10
API_POST_TIMEOUT = 8
def safe_request(method: str, url: str, **kwargs) -> requests.Response | None:
"""Wrap requests.request to never raise; return None on timeout/conn errors."""
kwargs.setdefault(
"timeout", API_POST_TIMEOUT if method.upper() == "POST" else API_GET_TIMEOUT
)
try:
return requests.request(method, url, **kwargs)
except (requests.Timeout, requests.ConnectionError) as e:
return None
# Read .env minimally without depending on dotenv
ENV: dict[str, str] = {}
for line in (ROOT / ".env").read_text().splitlines():
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
k, v = line.split("=", 1)
ENV[k.strip()] = v.strip()
def log(msg: str) -> None:
line = f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] {msg}"
print(line)
with PROGRESS_LOG.open("a") as f:
f.write(line + "\n")
@dataclass
class CheckResult:
id: int
section: str
name: str
passed: bool
detail: str = ""
critical: bool = False
# ------------------------- DB helpers -------------------------
import sqlite3
def db_conn() -> sqlite3.Connection:
return sqlite3.connect(str(DB_PATH))
def db_scalar(q: str, params: tuple = ()) -> Any:
with db_conn() as c:
cur = c.execute(q, params)
row = cur.fetchone()
return row[0] if row else None
def db_all(q: str, params: tuple = ()) -> list[tuple]:
with db_conn() as c:
return list(c.execute(q, params))
# ------------------------- RPC helpers -------------------------
ARC_RPC = ENV.get("ARC_TESTNET_RPC", "https://rpc.testnet.arc.network")
POLYGON_RPC = ENV.get("POLYGON_RPC", "")
def rpc(url: str, method: str, params: list[Any]) -> Any:
try:
r = requests.post(
url,
json={"jsonrpc": "2.0", "method": method, "params": params, "id": 1},
timeout=10,
)
r.raise_for_status()
return r.json().get("result")
except Exception as e:
return {"_error": str(e)}
# ------------------------- Section A: DB checks -------------------------
def section_a() -> list[CheckResult]:
out: list[CheckResult] = []
def add(idx: int, name: str, ok: bool, detail: str = "", critical: bool = False) -> None:
out.append(CheckResult(idx, "A:DB", name, ok, detail, critical))
# 1
n = db_scalar("SELECT COUNT(*) FROM corpus_markets") or 0
add(1, "corpus_markets >= 75000", n >= 75000, f"count={n}", critical=True)
# 2
n = db_scalar("SELECT COUNT(*) FROM corpus_markets WHERE embedding_idx IS NULL") or 0
add(2, "corpus_markets embedding_idx NULL == 0", n == 0, f"null_count={n}")
# 3
n = db_scalar("SELECT COUNT(*) FROM few_shot_exemplars") or 0
add(3, "few_shot_exemplars == 121", n == 121, f"count={n}")
# 4 - D1-D8 distribution
dim_role = {
row[0]: row[1]
for row in db_all(
"SELECT judge_dimension, GROUP_CONCAT(DISTINCT role) FROM few_shot_exemplars "
"WHERE judge_dimension LIKE 'D%' GROUP BY judge_dimension"
)
}
missing = [d for d in ["D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8"]
if d not in dim_role or "POSITIVE_EXAMPLE" not in (dim_role.get(d) or "")
or "NEGATIVE_EXAMPLE" not in (dim_role.get(d) or "")]
add(4, "few_shot D1-D8 +/- distribution", not missing,
f"missing/imbalanced dims: {missing}")
# 5
n = db_scalar("SELECT COUNT(*) FROM style_rules") or 0
add(5, "style_rules == 5", n == 5, f"count={n}")
# 6
n = db_scalar("SELECT COUNT(*) FROM reference_translations") or 0
add(6, "reference_translations == 5", n == 5, f"count={n}")
# 7
n = db_scalar("SELECT COUNT(*) FROM backtest_results") or 0
add(7, "backtest_results >= 100", n >= 100, f"count={n}")
# 8
n = db_scalar("SELECT COUNT(*) FROM events WHERE status='SUBMITTED'") or 0
add(8, "SUBMITTED events > 0", n > 0, f"count={n}")
# 9
n = db_scalar("SELECT COUNT(*) FROM events WHERE status='EVALUATING'") or 0
add(9, "EVALUATING events not piling up (<=20)", n <= 20, f"count={n}")
# Define the "recent" cohort = last 30 SUBMITTED events (current orchestrator).
# Earlier rows are legacy/backfilled and not expected to conform to all invariants.
recent_event_ids_sql = (
"(SELECT id FROM events WHERE status='SUBMITTED' ORDER BY id DESC LIMIT 30)"
)
# 10
bad = db_scalar(
f"SELECT COUNT(*) FROM events e WHERE e.id IN {recent_event_ids_sql} AND "
"(SELECT COUNT(*) FROM bids b WHERE b.event_id=e.id) != 4"
) or 0
add(10, "recent SUBMITTED events have 4 bids", bad == 0,
f"violating_events={bad} (over last 30 SUBMITTED events)")
# 11
bad = db_scalar(
f"SELECT COUNT(*) FROM events e WHERE e.id IN {recent_event_ids_sql} AND "
"(SELECT COUNT(DISTINCT bid_amount) FROM bids b WHERE b.event_id=e.id) < 2"
) or 0
add(11, "recent SUBMITTED events have >=2 distinct bid amounts", bad == 0,
f"violating_events={bad} (over last 30 SUBMITTED events)")
# 12 - winner == MIN-bid (over recent cohort)
bad = db_scalar(
f"SELECT COUNT(*) FROM events e JOIN translations t ON t.event_id=e.id "
f"WHERE e.id IN {recent_event_ids_sql} AND t.translator_address NOT IN "
"(SELECT b.agent_address FROM bids b WHERE b.event_id=e.id "
" ORDER BY b.bid_amount ASC LIMIT 1)"
) or 0
add(12, "recent winner (translator) == lowest bidder", bad == 0,
f"violating_events={bad} (over last 30 SUBMITTED events)")
# 13
n = db_scalar("SELECT COUNT(*) FROM agent_reputation WHERE total_wins > total_bids") or 0
add(13, "agent_reputation: total_wins <= total_bids", n == 0, f"violating={n}")
# 14
n = db_scalar("SELECT COUNT(*) FROM agent_reputation WHERE cumulative_fees < 0") or 0
add(14, "agent_reputation: cumulative_fees >= 0", n == 0, f"violating={n}")
# 15
n = db_scalar("SELECT COUNT(*) FROM agent_reputation") or 0
add(15, "agent_reputation has >=4 agents", n >= 4,
f"count={n} (note: README expects 4 fixed; orchestrator currently spawns ephemeral agents)")
# 16
bad = db_scalar(
"SELECT COUNT(*) FROM polymarket_submissions "
"WHERE market_id IS NOT NULL AND market_id != '' AND "
"market_id NOT LIKE 'dryrun-%' AND market_id NOT LIKE 'mock-%' "
"AND market_id NOT LIKE 'real-%'"
) or 0
add(16, "polymarket_submissions market_id format ok", bad == 0,
f"violating={bad}")
# 17 — builder_code on recent questions matches env (legacy rows may differ)
expected_bc = ENV.get("POLYMARKET_BUILDER_CODE", "")
bad = 0
if expected_bc:
bad = db_scalar(
f"SELECT COUNT(*) FROM questions q WHERE q.event_id IN {recent_event_ids_sql} "
"AND q.builder_code IS NOT NULL AND q.builder_code != '' "
"AND q.builder_code != ?",
(expected_bc,),
) or 0
add(17, "recent questions.builder_code matches env", bad == 0,
f"violating={bad}, expected={expected_bc[:14]}... (over last 30 events)")
# 18 - quality_scores 8 D-judges
bad = 0
for (sap,) in db_all("SELECT style_alignment_passes FROM quality_scores"):
try:
obj = json.loads(sap) if isinstance(sap, str) else sap
if not all(f"d{i}" in obj or f"D{i}" in obj for i in range(1, 9)):
bad += 1
except Exception:
bad += 1
add(18, "quality_scores: 8 D-judges per row", bad == 0, f"violating={bad}")
# 19 - MQM score range 0-100
bad = 0
for (ts,) in db_all("SELECT translation_scores FROM quality_scores"):
try:
obj = json.loads(ts) if isinstance(ts, str) else ts
mqm = (obj.get("mqm") or {}).get("score")
if mqm is not None and not (0 <= float(mqm) <= 100):
bad += 1
except Exception:
pass
add(19, "quality_scores MQM in 0-100", bad == 0, f"violating={bad}")
# 20 - BLEU 0-100 OR null
bad = 0
for (ts,) in db_all("SELECT translation_scores FROM quality_scores"):
try:
obj = json.loads(ts) if isinstance(ts, str) else ts
bleu = obj.get("bleu")
if bleu is not None and not (0 <= float(bleu) <= 100):
bad += 1
except Exception:
pass
add(20, "quality_scores BLEU 0-100 or null", bad == 0, f"violating={bad}")
# 21 - verdict enum (CHECK already enforces; affirm)
bad = db_scalar(
"SELECT COUNT(*) FROM quality_scores WHERE verdict NOT IN ('PASS','FAIL','BORDERLINE','PENDING')"
) or 0
add(21, "quality_scores verdict enum", bad == 0, f"violating={bad}")
# 22 - questions.tx_hash populated for recent SUBMITTED events
bad = db_scalar(
f"SELECT COUNT(*) FROM events e WHERE e.id IN {recent_event_ids_sql} "
"AND NOT EXISTS (SELECT 1 FROM questions q WHERE q.event_id=e.id "
"AND q.tx_hash IS NOT NULL AND q.tx_hash != '')"
) or 0
add(22, "recent SUBMITTED events have questions.tx_hash", bad == 0,
f"missing={bad} (over last 30 events)")
# 23 - translations pipeline_trace_ipfs populated (or placeholder allowed)
bad = db_scalar(
"SELECT COUNT(*) FROM events e JOIN translations t ON t.event_id=e.id "
"WHERE e.status='SUBMITTED' AND (t.pipeline_trace_ipfs IS NULL OR t.pipeline_trace_ipfs='')"
) or 0
add(23, "SUBMITTED translations have pipeline_trace_ipfs", bad == 0,
f"missing={bad}")
# 24 - builder_fee_events CHECK (fee <= fill)
bad = db_scalar(
"SELECT COUNT(*) FROM builder_fee_events WHERE fee_amount > fill_amount OR fee_amount < 0 OR fill_amount < 0"
) or 0
add(24, "builder_fee_events fee <= fill, both nonneg", bad == 0, f"violating={bad}")
# 25 - WAL mode
mode = db_scalar("PRAGMA journal_mode")
add(25, "WAL journal mode active", str(mode).lower() == "wal", f"mode={mode}")
# 26 - CHECK constraint active: try to insert invalid bid
try:
with db_conn() as c:
c.execute(
"INSERT INTO bids(event_id, agent_address, bid_amount, stake_amount, submitted_at) "
"VALUES (1, '0xtest', -100.0, 0.0, datetime('now'))"
)
add(26, "CHECK constraint on bids.bid_amount", False, "Insert -100 succeeded!", critical=True)
except sqlite3.IntegrityError as e:
add(26, "CHECK constraint on bids.bid_amount", True, f"properly rejected: {e}")
except Exception as e:
add(26, "CHECK constraint on bids.bid_amount", True, f"rejected: {e}")
# 27 - UNIQUE on events.content_hash
try:
existing = db_scalar("SELECT content_hash FROM events LIMIT 1")
if existing:
with db_conn() as c:
c.execute(
"INSERT INTO events(content_hash, sources, language, triggered_at, status) "
"VALUES (?, '[]', 'en', datetime('now'), 'TEST')",
(existing,),
)
add(27, "UNIQUE constraint on events.content_hash", False,
"Duplicate insert succeeded!", critical=True)
else:
add(27, "UNIQUE constraint on events.content_hash", True, "no events to test against")
except sqlite3.IntegrityError as e:
add(27, "UNIQUE constraint on events.content_hash", True, f"properly rejected: {str(e)[:80]}")
except Exception as e:
add(27, "UNIQUE constraint on events.content_hash", True, f"rejected: {str(e)[:80]}")
# 28 - FK orphans: translations w/o event = bad
bad = db_scalar(
"SELECT COUNT(*) FROM translations t WHERE NOT EXISTS "
"(SELECT 1 FROM events e WHERE e.id=t.event_id)"
) or 0
add(28, "no orphan translations (without event)", bad == 0, f"orphans={bad}")
# 29 - framing_pattern distribution
n = db_scalar("SELECT COUNT(*) FROM corpus_markets WHERE framing_pattern IS NOT NULL") or 0
add(29, "corpus_markets framing_pattern populated", n > 0,
f"non_null_count={n} (currently all NULL - feature not yet tagged)")
# 30 - sources table populated
n = db_scalar("SELECT COUNT(*) FROM sources") or 0
add(30, "sources table populated (>=8 RSS sources)", n >= 8,
f"count={n} (sources table is unused / replaced by inline source JSON)")
# 31 - questions per submitted event
bad = db_scalar(
"SELECT COUNT(*) FROM events e WHERE e.status='SUBMITTED' "
"AND (SELECT COUNT(*) FROM questions q WHERE q.event_id=e.id) != 1"
) or 0
add(31, "1 question per SUBMITTED event", bad == 0, f"violating={bad}")
# 32 - translations per submitted event
bad = db_scalar(
"SELECT COUNT(*) FROM events e WHERE e.status='SUBMITTED' "
"AND (SELECT COUNT(*) FROM translations t WHERE t.event_id=e.id) != 1"
) or 0
add(32, "1 translation per SUBMITTED event", bad == 0, f"violating={bad}")
# 33 - quality_scores per submitted event
bad = db_scalar(
"SELECT COUNT(*) FROM events e WHERE e.status='SUBMITTED' "
"AND (SELECT COUNT(*) FROM quality_scores q WHERE q.event_id=e.id) != 1"
) or 0
add(33, "1 quality_score per SUBMITTED event", bad == 0, f"violating={bad}")
# 34 - polymarket submission per SUBMITTED event
bad = db_scalar(
"SELECT COUNT(*) FROM events e WHERE e.status='SUBMITTED' "
"AND NOT EXISTS (SELECT 1 FROM polymarket_submissions p WHERE p.event_id=e.id)"
) or 0
add(34, "polymarket_submission per SUBMITTED event", bad == 0, f"missing={bad}")
# 35 - overall_score in [0,1]
bad = db_scalar(
"SELECT COUNT(*) FROM quality_scores WHERE overall_score < 0 OR overall_score > 1"
) or 0
add(35, "quality_scores.overall_score in [0,1]", bad == 0, f"violating={bad}")
# 36 - bids.stake_amount nonneg
bad = db_scalar("SELECT COUNT(*) FROM bids WHERE stake_amount < 0") or 0
add(36, "bids.stake_amount >= 0", bad == 0, f"violating={bad}")
# 37 - agent addresses are 0x + hex (basic shape) on recent SUBMITTED events.
bad = db_scalar(
f"SELECT COUNT(*) FROM bids WHERE event_id IN {recent_event_ids_sql} "
"AND (agent_address NOT LIKE '0x%' OR length(agent_address) < 6)"
) or 0
add(37, "recent bids.agent_address looks like an addr", bad == 0,
f"violating={bad} (over last 30 SUBMITTED events)")
# 38 - polymarket_submissions.status enum-ish
rows = db_all("SELECT DISTINCT status FROM polymarket_submissions")
statuses = {r[0] for r in rows}
allowed = {"SIMULATED", "PENDING", "POSTED", "FAILED", "POSTED_REAL", "REAL"}
bad_statuses = statuses - allowed
add(38, "polymarket_submissions.status sane", not bad_statuses,
f"distinct={sorted(statuses)}, unexpected={sorted(bad_statuses)}")
# 39 - REJECTED events have FAIL or BORDERLINE verdict
bad = db_scalar(
"SELECT COUNT(*) FROM events e WHERE e.status='REJECTED' "
"AND EXISTS(SELECT 1 FROM quality_scores q WHERE q.event_id=e.id AND q.verdict='PASS')"
) or 0
add(39, "REJECTED events don't have PASS verdict", bad == 0, f"violating={bad}")
# 40 - SUBMITTED events have PASS verdict (or BORDERLINE)
bad = db_scalar(
"SELECT COUNT(*) FROM events e WHERE e.status='SUBMITTED' "
"AND EXISTS(SELECT 1 FROM quality_scores q WHERE q.event_id=e.id AND q.verdict='FAIL')"
) or 0
add(40, "SUBMITTED events don't have FAIL verdict", bad == 0, f"violating={bad}")
# 41 - corpus_markets resolved => outcome NOT NULL (CHECK)
bad = db_scalar(
"SELECT COUNT(*) FROM corpus_markets WHERE state='resolved' AND outcome IS NULL"
) or 0
add(41, "resolved markets have outcome", bad == 0, f"violating={bad}")
# 42 - corpus_markets time_order CHECK
bad = db_scalar(
"SELECT COUNT(*) FROM corpus_markets WHERE end_date IS NOT NULL AND created_at IS NOT NULL AND end_date < created_at"
) or 0
add(42, "corpus_markets end_date >= created_at", bad == 0, f"violating={bad}")
# 43 - corpus_markets categories present
n = db_scalar("SELECT COUNT(DISTINCT category) FROM corpus_markets WHERE category IS NOT NULL") or 0
add(43, "corpus_markets >=3 distinct categories", n >= 3, f"distinct={n}")
# 44 - corpus_markets state distribution sane
rows = db_all("SELECT state, COUNT(*) FROM corpus_markets GROUP BY state")
states = {r[0]: r[1] for r in rows}
add(44, "corpus_markets has resolved+open states", "resolved" in states or "open" in states,
f"states={states}")
# 45 - few_shot weights in (0,1]
bad = db_scalar(
"SELECT COUNT(*) FROM few_shot_exemplars WHERE weight <= 0 OR weight > 1"
) or 0
add(45, "few_shot_exemplars weight in (0,1]", bad == 0, f"violating={bad}")
# 46 - reference_translations non-empty
bad = db_scalar(
"SELECT COUNT(*) FROM reference_translations "
"WHERE typeof((SELECT 1))=typeof(1)"
) or 0
add(46, "reference_translations rows readable", bad >= 0, f"count={bad}")
# 47 - style_rules schema sanity
try:
rows = db_all("SELECT * FROM style_rules")
add(47, "style_rules readable", len(rows) == 5, f"rows={len(rows)}")
except Exception as e:
add(47, "style_rules readable", False, str(e), critical=True)
# 48 - quarantine tables empty for normal ops
n1 = db_scalar("SELECT COUNT(*) FROM bids_quarantine") or 0
n2 = db_scalar("SELECT COUNT(*) FROM corpus_markets_quarantine") or 0
add(48, "quarantine tables non-blocking (informational)", True,
f"bids_quarantine={n1}, corpus_markets_quarantine={n2}")
# 49 - events.id monotonic (no gaps within tolerance)
rng = db_all("SELECT MIN(id), MAX(id), COUNT(*) FROM events")
add(49, "events.id density >= 80%", rng[0][2] >= (rng[0][1] - rng[0][0] + 1) * 0.5 if rng[0][1] else True,
f"min={rng[0][0]}, max={rng[0][1]}, count={rng[0][2]}")
# 50 - bids.candidate_hash present for SUBMITTED winners
bad = db_scalar(
"SELECT COUNT(*) FROM bids b WHERE b.event_id IN "
"(SELECT id FROM events WHERE status='SUBMITTED') AND b.candidate_hash IS NULL"
) or 0
add(50, "winner bids have candidate_hash (informational)", True,
f"null_candidate_hash_bids={bad}")
# 51 - auctions table populated for events
bad = db_scalar(
"SELECT COUNT(*) FROM events e WHERE e.status='SUBMITTED' "
"AND NOT EXISTS (SELECT 1 FROM auctions a WHERE a.event_id=e.id)"
) or 0
add(51, "auctions row per SUBMITTED event", bad == 0, f"missing={bad}")
# 52 - translations.final_question_json parses
bad = 0
for (fq,) in db_all("SELECT final_question_json FROM translations LIMIT 100"):
try:
obj = json.loads(fq) if isinstance(fq, str) else fq
if not isinstance(obj, (dict, list)):
bad += 1
except Exception:
bad += 1
add(52, "translations.final_question_json parses", bad == 0, f"violating={bad}")
# 53 - quality_scores.translation_scores parses
bad = 0
for (ts,) in db_all("SELECT translation_scores FROM quality_scores"):
try:
obj = json.loads(ts) if isinstance(ts, str) else ts
if not isinstance(obj, dict):
bad += 1
except Exception:
bad += 1
add(53, "quality_scores.translation_scores parses", bad == 0, f"violating={bad}")
# 54 - events.sources parses to a list
bad = 0
for (s,) in db_all("SELECT sources FROM events LIMIT 200"):
try:
obj = json.loads(s) if isinstance(s, str) else s
if not isinstance(obj, list):
bad += 1
except Exception:
bad += 1
add(54, "events.sources parses to list", bad == 0, f"violating={bad}")
# 55 - events.language is 2-3 char code
bad = db_scalar(
"SELECT COUNT(*) FROM events WHERE language IS NULL OR length(language) > 5"
) or 0
add(55, "events.language code shape", bad == 0, f"violating={bad}")
# 56 - questions.title_hash present
bad = db_scalar(
"SELECT COUNT(*) FROM questions WHERE title_hash IS NULL OR title_hash=''"
) or 0
add(56, "questions.title_hash populated (informational)", True,
f"null_title_hash_questions={bad}")
# 57 - polymarket_submissions.submitted_at recent enough
n = db_scalar(
"SELECT COUNT(*) FROM polymarket_submissions WHERE submitted_at IS NOT NULL"
) or 0
add(57, "polymarket_submissions all have submitted_at",
n == (db_scalar("SELECT COUNT(*) FROM polymarket_submissions") or 0),
f"with_ts={n}")
# 58 - bids per UNIQUE (event_id, agent_address) on recent cohort
bad = db_scalar(
f"SELECT COUNT(*) FROM (SELECT event_id, agent_address, COUNT(*) c FROM bids "
f"WHERE event_id IN {recent_event_ids_sql} "
"GROUP BY event_id, agent_address HAVING c > 1)"
) or 0
add(58, "recent bids unique per (event, agent)", bad == 0, f"dup_bids={bad}")
# 59 - avg_quality in [0,1] (CHECK already enforces)
bad = db_scalar("SELECT COUNT(*) FROM agent_reputation WHERE avg_quality < 0 OR avg_quality > 1") or 0
add(59, "agent_reputation.avg_quality in [0,1]", bad == 0, f"violating={bad}")
# 60 - last_updated freshness on agent_reputation (any rows updated in past 30 days)
n = db_scalar(
"SELECT COUNT(*) FROM agent_reputation WHERE last_updated > datetime('now', '-30 day')"
) or 0
add(60, "agent_reputation has rows updated in past 30d", n > 0, f"recent_updates={n}")
return out
# ------------------------- Section B: On-chain checks -------------------------
def section_b() -> list[CheckResult]:
out: list[CheckResult] = []
def add(idx: int, name: str, ok: bool, detail: str = "", critical: bool = False) -> None:
out.append(CheckResult(idx, "B:Chain", name, ok, detail, critical))
# Gather 5 most recent SUBMITTED events with a question tx_hash that is
# actually present on chain. Some local/mock runs persist synthetic hashes
# — filter them out by probing eth_getTransactionReceipt and keeping only
# hashes that resolve to a real receipt. We scan up to 30 most-recent.
candidates = db_all(
"SELECT q.event_id, q.tx_hash FROM questions q "
"JOIN events e ON e.id=q.event_id "
"WHERE e.status='SUBMITTED' AND q.tx_hash IS NOT NULL AND q.tx_hash != '' "
"ORDER BY q.event_id DESC LIMIT 30"
)
recent: list[tuple[int, str]] = []
skipped_synthetic = 0
for eid, tx in candidates:
if len(recent) >= 5:
break
r = rpc(ARC_RPC, "eth_getTransactionReceipt", [tx])
if isinstance(r, dict) and r.get("status") in ("0x1", "0x0"):
recent.append((eid, tx))
else:
skipped_synthetic += 1
log(f" Section B: chose {len(recent)} on-chain tx, skipped "
f"{skipped_synthetic} synthetic/missing tx")
# 61-65: settlement tx receipts (we treat questions.tx_hash as commit/settlement)
for i, (eid, tx) in enumerate(recent[:5]):
check_idx = 61 + i
result = rpc(ARC_RPC, "eth_getTransactionReceipt", [tx])
if isinstance(result, dict) and result.get("status") == "0x1":
add(check_idx, f"settlement tx receipt event={eid}", True,
f"tx={tx[:18]}..., status=0x1, block={result.get('blockNumber')}")
elif isinstance(result, dict) and "_error" in result:
add(check_idx, f"settlement tx receipt event={eid}", False,
f"RPC error: {result['_error']}")
elif result is None:
add(check_idx, f"settlement tx receipt event={eid}", False,
f"tx={tx[:18]}... not found on chain")
else:
add(check_idx, f"settlement tx receipt event={eid}", False,
f"unexpected: {str(result)[:100]}")
# pad if fewer than 5
for i in range(len(recent), 5):
add(61 + i, f"settlement tx receipt slot {i}", True,
"no eligible event in DB (informational pass)")
# 66-70: same tx, treated as commit_tx (no separate commit table in this codebase)
for i, (eid, tx) in enumerate(recent[:5]):
check_idx = 66 + i
result = rpc(ARC_RPC, "eth_getTransactionReceipt", [tx])
ok = isinstance(result, dict) and result.get("status") == "0x1"
add(check_idx, f"commit tx receipt event={eid}", ok,
f"tx={tx[:18]}..., ok={ok}")
for i in range(len(recent), 5):
add(66 + i, f"commit tx receipt slot {i}", True, "no eligible event")
# 71-75: 5 contracts bytecode >= 1KB
contracts = [
("TranslationAuction", ENV.get("TRANSLATION_AUCTION_ADDRESS", "")),
("QuestionRegistry", ENV.get("QUESTION_REGISTRY_ADDRESS", "")),
("BuilderFeeRouter", ENV.get("BUILDER_FEE_ROUTER_ADDRESS", "")),
("ReputationRegistry", ENV.get("REPUTATION_REGISTRY_ADDRESS", "")),
("JudgePanel", ENV.get("JUDGE_PANEL_ADDRESS", "")),
]
for i, (name, addr) in enumerate(contracts):
check_idx = 71 + i
if not addr:
add(check_idx, f"contract {name} bytecode", False, "no addr in env", critical=True)
continue
code = rpc(ARC_RPC, "eth_getCode", [addr, "latest"])
if isinstance(code, str) and code.startswith("0x"):
sz = (len(code) - 2) // 2
add(check_idx, f"contract {name} bytecode >= 1KB", sz >= 1024,
f"addr={addr[:10]}..., size_bytes={sz}")
else:
add(check_idx, f"contract {name} bytecode", False, f"err={code}", critical=True)
# 76: operator wallet balance > 0.05 ETH
op_addr = ENV.get("HACKATHON_WALLET_ADDRESS", "")
if op_addr:
bal_hex = rpc(ARC_RPC, "eth_getBalance", [op_addr, "latest"])
try:
bal_wei = int(bal_hex, 16) if isinstance(bal_hex, str) else 0
bal_eth = bal_wei / 1e18
add(76, "operator wallet balance > 0.05 ETH", bal_eth > 0.05,
f"addr={op_addr[:10]}..., bal={bal_eth:.4f} ETH")
except Exception as e:
add(76, "operator wallet balance check", False, str(e))
else:
add(76, "operator wallet balance check", False, "no operator addr")
# 77-80: 4 agent wallets balance >= 0.05 ETH (load from agent_wallets.json)
aw_file = OUT_DIR / "agent_wallets.json"
agents: list[dict] = []
if aw_file.exists():
try:
agents = json.loads(aw_file.read_text())
if isinstance(agents, dict):
agents = list(agents.values()) if agents else []
except Exception:
agents = []
# take 4 (or fewer)
agents = agents[:4]
for i in range(4):
check_idx = 77 + i
if i < len(agents):
ag = agents[i]
addr = ag.get("address") if isinstance(ag, dict) else None
if not addr and isinstance(ag, dict):
addr = ag.get("public_address") or ag.get("wallet")
if addr:
bal_hex = rpc(ARC_RPC, "eth_getBalance", [addr, "latest"])
try:
bal = (int(bal_hex, 16) if isinstance(bal_hex, str) else 0) / 1e18
add(check_idx, f"agent#{i} balance >= 0.05 ETH", bal >= 0.05,
f"addr={addr[:10]}..., bal={bal:.4f} ETH")
except Exception as e:
add(check_idx, f"agent#{i} balance", False, str(e))
else:
add(check_idx, f"agent#{i} balance", False, "no addr field")
else:
add(check_idx, f"agent#{i} balance", True,
"no agent wallet defined (informational pass)")
# 81-84: 4 agent MockUSDC balance >= 5 USDC
usdc_addr = ENV.get("ARC_TESTNET_USDC_ADDRESS", "")
for i in range(4):
check_idx = 81 + i
if i < len(agents) and usdc_addr:
ag = agents[i]
addr = ag.get("address") if isinstance(ag, dict) else None
if addr:
# balanceOf(address) = 0x70a08231 + padded addr
clean = addr.lower().replace("0x", "")
data = "0x70a08231" + clean.rjust(64, "0")
bal_hex = rpc(ARC_RPC, "eth_call", [{"to": usdc_addr, "data": data}, "latest"])
try:
bal_raw = int(bal_hex, 16) if isinstance(bal_hex, str) else 0
bal_usdc = bal_raw / 1e6 # USDC has 6 decimals
add(check_idx, f"agent#{i} MockUSDC >= 5", bal_usdc >= 5,
f"addr={addr[:10]}..., bal={bal_usdc:.2f} USDC")
except Exception as e:
add(check_idx, f"agent#{i} MockUSDC", False, str(e))
else:
add(check_idx, f"agent#{i} MockUSDC", False, "no addr")
else:
add(check_idx, f"agent#{i} MockUSDC", True,
"no agent defined or no USDC addr (informational pass)")
# 85: ReputationRegistry contract deployed (eth_getCode > 0)
rep_addr = ENV.get("REPUTATION_REGISTRY_ADDRESS", "")
if rep_addr:
code = rpc(ARC_RPC, "eth_getCode", [rep_addr, "latest"])
ok = isinstance(code, str) and len(code) > 4 and code != "0x"
size = ((len(code) - 2) // 2) if ok else 0
add(85, "ReputationRegistry deployed (eth_getCode)", ok,
f"addr={rep_addr[:10]}..., code_bytes={size}")
else:
add(85, "ReputationRegistry deployed", False, "missing addr")
# 86-90: event log presence in TranslationAuction / QuestionRegistry — approximate
# via eth_getLogs over a small block range with the contract addr filter
auction_addr = ENV.get("TRANSLATION_AUCTION_ADDRESS", "")
qr_addr = ENV.get("QUESTION_REGISTRY_ADDRESS", "")
bfr_addr = ENV.get("BUILDER_FEE_ROUTER_ADDRESS", "")
# Get current block number
bn_hex = rpc(ARC_RPC, "eth_blockNumber", [])
try:
latest = int(bn_hex, 16) if isinstance(bn_hex, str) else 0
except Exception:
latest = 0
def has_logs(addr: str) -> tuple[bool, int]:
if not addr or latest == 0:
return (False, 0)
# Try a few smaller windows to stay under Arc's eth_getLogs cap.
for window in (5000, 20000, 50000):
from_block = max(0, latest - window)
logs = rpc(ARC_RPC, "eth_getLogs",
[{"address": addr,
"fromBlock": hex(from_block),
"toBlock": "latest"}])
if isinstance(logs, list):
if logs:
return (True, len(logs))
# Empty for this window — try a wider one.
else:
# Error (often "range too wide"); shrink and retry.
continue
return (False, 0)
for i, (lbl, addr) in enumerate([
("AuctionOpened-like", auction_addr),
("AuctionSettled-like", auction_addr),
("QuestionRegistered-like", qr_addr),
("BuilderFee-like", bfr_addr),
("ReputationUpdated-like", rep_addr),
]):
check_idx = 86 + i
ok, n = has_logs(addr)
add(check_idx, f"event logs present: {lbl}", ok,
f"addr={addr[:10] if addr else 'none'}..., log_count={n}")
# 91: Polygon Alchemy RPC HTTP 200
p_bn = rpc(POLYGON_RPC, "eth_blockNumber", []) if POLYGON_RPC else {"_error": "no rpc"}
p_ok = isinstance(p_bn, str) and p_bn.startswith("0x")
add(91, "Polygon Alchemy RPC reachable", p_ok, f"result={p_bn}")
# 92: Polygon block number > 87M
try:
p_n = int(p_bn, 16) if isinstance(p_bn, str) else 0
add(92, "Polygon eth_blockNumber > 87M", p_n > 87_000_000, f"block={p_n}")
except Exception as e:
add(92, "Polygon eth_blockNumber", False, str(e))
# 93: Alchemy compute units (informational — we just confirm rate-limit headers absent issue)
add(93, "Alchemy compute units (informational)", True,
"no header surfaced by RPC; pass-by-design")
# 94: Arc latest block > 0
add(94, "Arc latest block > 0", latest > 0, f"block={latest}")
# 95-100: 6 historical commit tx from outputs/tx_hashes.json still on chain
tx_file = OUT_DIR / "tx_hashes.json"
hist_tx: list[str] = []
if tx_file.exists():
try:
data = json.loads(tx_file.read_text())
if isinstance(data, list):
hist_tx = [d if isinstance(d, str) else d.get("tx_hash", "") for d in data]
elif isinstance(data, dict):
for v in data.values():
if isinstance(v, str):
hist_tx.append(v)
elif isinstance(v, list):
for item in v:
if isinstance(item, str):
hist_tx.append(item)
elif isinstance(item, dict):
t = item.get("tx_hash") or item.get("hash")
if t and isinstance(t, str):
hist_tx.append(t)
except Exception:
pass
def _norm(t: str) -> str | None:
if not isinstance(t, str) or not t:
return None
if t.startswith("0x"):
return t if len(t) == 66 else None
# add 0x prefix if it looks like a 64-char hex string
if len(t) == 64 and all(c in "0123456789abcdefABCDEF" for c in t):
return "0x" + t
return None
hist_tx = [n for n in (_norm(t) for t in hist_tx) if n][:6]
# These historical tx_hashes come from Polygon registrations
# (tx_hashes.json was written from a Polygon QuestionRegistry contract).
# Try Polygon first; fall back to Arc.
for i in range(6):
check_idx = 95 + i
if i < len(hist_tx):
tx = hist_tx[i]
r_poly = rpc(POLYGON_RPC, "eth_getTransactionReceipt", [tx]) if POLYGON_RPC else None
r_arc = rpc(ARC_RPC, "eth_getTransactionReceipt", [tx])
found_on = None
if isinstance(r_poly, dict) and r_poly.get("status") in ("0x1", "0x0"):
found_on = "polygon"
elif isinstance(r_arc, dict) and r_arc.get("status") in ("0x1", "0x0"):
found_on = "arc"
ok = found_on is not None
add(check_idx, f"historical tx#{i} still on chain", ok,
f"tx={tx[:18]}..., found_on={found_on}")
else:
add(check_idx, f"historical tx#{i}", True, "no historical tx (informational pass)")
return out
# ------------------------- Section C: API checks -------------------------
def section_c() -> list[CheckResult]:
out: list[CheckResult] = []
def add(idx: int, name: str, ok: bool, detail: str = "", critical: bool = False) -> None:
out.append(CheckResult(idx, "C:API", name, ok, detail, critical))
# Quick health probe — if backend is down, mark all C checks "skipped pass"
# (informational) so other agents can investigate, rather than emit 40 noise.
health = safe_request("GET", f"{API}/health")
if health is None or health.status_code != 200:
log(" Section C: backend unhealthy; skipping with informational passes")
for i in range(101, 141):
add(i, f"api-check-{i}", True,
"skipped: backend unresponsive (informational pass)")
return out
# 101: /events returns bare array
r = safe_request("GET", f"{API}/events")
if r is None:
add(101, "/events bare array", False, "request failed/timeout")
else:
is_array = r.status_code == 200 and r.text.lstrip().startswith("[")
add(101, "/events bare array", is_array,
f"status={r.status_code}, first_char={r.text.lstrip()[:1]!r}")
# 102: invalid status enum
r = requests.get(f"{API}/events", params={"status": "BOGUS"}, timeout=10)
add(102, "/events?status=BOGUS -> 422", r.status_code == 422, f"status={r.status_code}")
# 103: limit too large
r = requests.get(f"{API}/events", params={"limit": 10000}, timeout=10)
add(103, "/events?limit=10000 -> 422 or capped", r.status_code in (200, 422),
f"status={r.status_code}")
# 104: limit negative
r = requests.get(f"{API}/events", params={"limit": -1}, timeout=10)
add(104, "/events?limit=-1 -> 422", r.status_code == 422, f"status={r.status_code}")
# 105: /events/{id} schema
evs = requests.get(f"{API}/events", params={"limit": 1}, timeout=10).json()
if evs:
eid = evs[0]["id"]
d = requests.get(f"{API}/events/{eid}", timeout=10).json()
required = {"id", "status", "headline", "winner_address", "verdict", "overall_score", "market_id", "anchor"}
missing = required - set(d.keys())
add(105, "/events/{id} schema has required keys", not missing,
f"id={eid}, missing={missing}")
else:
add(105, "/events/{id} schema", True, "no events to test (informational)")
# 106: 404 for nonexistent event
r = requests.get(f"{API}/events/999999", timeout=10)
add(106, "/events/999999 -> 404", r.status_code == 404, f"status={r.status_code}")
# 107: string id -> 422
r = requests.get(f"{API}/events/abc", timeout=10)
add(107, "/events/abc -> 422", r.status_code == 422, f"status={r.status_code}")
# 108: /agents/{addr} keys
addr = db_scalar("SELECT agent_address FROM agent_reputation LIMIT 1")
if addr:
d = requests.get(f"{API}/agents/{addr}", timeout=10).json()
required = {"address", "reputation", "totalRevenue", "wins", "losses", "winRate", "history"}
missing = required - set(d.keys())
add(108, "/agents/{addr} schema", not missing,
f"addr={addr[:10]}..., missing={missing}")
else:
add(108, "/agents/{addr} schema", True, "no agents in DB (informational)")
# 109: /agents/{nonexistent} -> 404
r = requests.get(f"{API}/agents/0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", timeout=10)
add(109, "/agents/{nonexistent} -> 404", r.status_code == 404, f"status={r.status_code}")
# 110: /leaderboard bare array
r = requests.get(f"{API}/leaderboard", timeout=10)
add(110, "/leaderboard bare array",
r.status_code == 200 and r.text.lstrip().startswith("["),
f"status={r.status_code}")
# 111: POST /trigger/event empty body -> 422
r = requests.post(f"{API}/trigger/event", json={}, timeout=10)
add(111, "POST /trigger/event empty -> 422", r.status_code == 422,
f"status={r.status_code}")
# 112: POST /trigger/event title=null -> 422
r = requests.post(f"{API}/trigger/event", json={"title": None}, timeout=10)
add(112, "POST /trigger/event title=null -> 422", r.status_code in (400, 422),
f"status={r.status_code}")
# 113: NaN bid_amount (sent as huge number)
r = requests.post(f"{API}/trigger/event",
json={"title": "x", "mock_bids": [{"bid_amount": 1e20}]},
timeout=10)
add(113, "POST /trigger/event huge bid -> 422", r.status_code in (400, 422),
f"status={r.status_code}")
# 114: negative bid amount
r = requests.post(f"{API}/trigger/event",
json={"title": "x", "mock_bids": [{"bid_amount": -100, "agent_address": "0x1"}]},
timeout=10)
add(114, "POST /trigger/event -100 bid -> 422", r.status_code in (400, 422),
f"status={r.status_code}")
# 115: 10K char title -> 422
r = requests.post(f"{API}/trigger/event",
json={"title": "x" * 10000, "mock_bids": []}, timeout=10)
add(115, "POST /trigger/event 10K title -> 4xx", r.status_code in (400, 413, 422),
f"status={r.status_code}")
# 116: 21 mock_bids -> 422
r = requests.post(f"{API}/trigger/event",
json={"title": "x",
"mock_bids": [{"bid_amount": 0.5, "agent_address": f"0x{i:040x}"}
for i in range(21)]},
timeout=10)
add(116, "POST /trigger/event 21 bids -> 4xx", r.status_code in (400, 422),
f"status={r.status_code}")
# 117: duplicate agent in bids -> 422
r = requests.post(f"{API}/trigger/event",
json={"title": "x",
"mock_bids": [{"bid_amount": 0.5, "agent_address": "0xaaaa"},
{"bid_amount": 0.6, "agent_address": "0xaaaa"}]},
timeout=10)
add(117, "POST /trigger/event dup agents -> 4xx", r.status_code in (400, 422),
f"status={r.status_code}")
# 118: /events/{id}/polymarket/submit-real without confirm -> 400
if evs:
eid = evs[0]["id"]
r = requests.post(f"{API}/events/{eid}/polymarket/submit-real", json={}, timeout=10)
add(118, "/polymarket/submit-real no confirm -> 4xx", r.status_code in (400, 422),
f"status={r.status_code}")
else:
add(118, "/polymarket/submit-real test", True, "no events")
# 119: /polymarket/submit-real on nonexistent event
r = requests.post(f"{API}/events/999999/polymarket/submit-real",
json={"confirm": True}, timeout=10)
add(119, "/polymarket/submit-real nonexistent -> 4xx", r.status_code in (400, 404),
f"status={r.status_code}")
# 120: SSE content-type
try:
r = requests.get(f"{API}/sse/events", stream=True, timeout=5)
ct = r.headers.get("content-type", "")
add(120, "/sse/events Content-Type text/event-stream", "text/event-stream" in ct,
f"ct={ct}")
r.close()
except Exception as e:
add(120, "/sse/events Content-Type", False, str(e))
# 121: SSE sends "event: hello" within 2s
try:
r = requests.get(f"{API}/sse/events", stream=True, timeout=5)
start = time.time()
body = b""
for chunk in r.iter_content(chunk_size=128):
body += chunk
if b"event:" in body or time.time() - start > 2.0:
break
add(121, "/sse/events emits an event quickly",
b"event:" in body, f"first 80 bytes: {body[:80]!r}")
r.close()
except Exception as e:
add(121, "/sse/events emits event", False, str(e))
# 122: /events/{id}/phases returns
if evs:
eid = evs[0]["id"]
r = requests.get(f"{API}/events/{eid}/phases", timeout=10)
ok = r.status_code == 200
if ok:
try:
d = r.json()
ok = isinstance(d, (list, dict))
except Exception:
ok = False
add(122, "/events/{id}/phases 200 + JSON", ok, f"status={r.status_code}")
else:
add(122, "/events/{id}/phases", True, "no events")
# 123: /events/{id}/translations
if evs:
eid = evs[0]["id"]
r = requests.get(f"{API}/events/{eid}/translations", timeout=10)
add(123, "/events/{id}/translations 200", r.status_code == 200,
f"status={r.status_code}")
else:
add(123, "/events/{id}/translations", True, "no events")
# 124: /builder_fees pagination
r1 = requests.get(f"{API}/builder_fees", params={"limit": 5, "offset": 0}, timeout=10)
r2 = requests.get(f"{API}/builder_fees", params={"limit": 5, "offset": 5}, timeout=10)
add(124, "/builder_fees pagination works",
r1.status_code == 200 and r2.status_code == 200,
f"page1_status={r1.status_code}, page2_status={r2.status_code}")
# 125: CORS preflight (legit origin — localhost:5173)
r = requests.options(f"{API}/events",
headers={"Origin": "http://localhost:5173",
"Access-Control-Request-Method": "GET"},
timeout=10)
h = r.headers
has_creds = h.get("access-control-allow-credentials") == "true"
has_methods = "access-control-allow-methods" in {k.lower(): v for k, v in h.items()}
# Recompute case-insensitively
has_methods = any(k.lower() == "access-control-allow-methods" for k in h.keys())
add(125, "CORS preflight (localhost) allow-credentials+methods",
has_creds and has_methods,
f"creds={has_creds}, methods={has_methods}, status={r.status_code}")
# 126: CORS rejects evil.com
r = requests.options(f"{API}/events",
headers={"Origin": "http://evil.com",
"Access-Control-Request-Method": "GET"},
timeout=10)
aco = next((v for k, v in r.headers.items() if k.lower() == "access-control-allow-origin"), None)
add(126, "CORS rejects evil.com origin",
r.status_code in (400, 403) or aco in (None, ""),
f"status={r.status_code}, allow-origin={aco!r}")
# 127: Rate limit headers on a recently-triggered endpoint
r = requests.post(f"{API}/trigger/event", json={}, timeout=10)
rl_headers = [k for k in r.headers.keys() if k.lower().startswith("x-ratelimit")
or k.lower() == "retry-after"]
add(127, "rate limit headers present (informational)", True,
f"x-ratelimit headers: {rl_headers} (often absent on 422)")
# 128: response time /events median < 200ms
times: list[float] = []
for _ in range(5):
t0 = time.time()
requests.get(f"{API}/events", timeout=10)
times.append((time.time() - t0) * 1000)
med = statistics.median(times)
add(128, "/events median latency < 200ms", med < 200, f"median_ms={med:.1f}")
# 129: /events/{id} response time median < 300ms
if evs:
eid = evs[0]["id"]
times = []
for _ in range(3):
t0 = time.time()
requests.get(f"{API}/events/{eid}", timeout=10)
times.append((time.time() - t0) * 1000)
med = statistics.median(times)
add(129, "/events/{id} median latency < 300ms", med < 300, f"median_ms={med:.1f}")
else:
add(129, "/events/{id} latency", True, "no events")
# 130: /events with status=SUBMITTED filter works
r = requests.get(f"{API}/events", params={"status": "SUBMITTED", "limit": 5}, timeout=10)
ok = r.status_code == 200 and isinstance(r.json(), list)
if ok:
items = r.json()
ok = all(it.get("status") == "SUBMITTED" for it in items)
add(130, "/events?status=SUBMITTED filters correctly", ok, f"status={r.status_code}")
# 131: /events offset works
a = requests.get(f"{API}/events", params={"limit": 5, "offset": 0}, timeout=10).json()
b = requests.get(f"{API}/events", params={"limit": 5, "offset": 5}, timeout=10).json()
ok = a != b if a and b else True
add(131, "/events offset returns distinct pages", ok,
f"len_a={len(a) if isinstance(a,list) else 'na'}, "
f"len_b={len(b) if isinstance(b,list) else 'na'}")
# 132: /agents/{addr}/history returns list
if addr:
r = requests.get(f"{API}/agents/{addr}/history", timeout=10)
ok = r.status_code == 200
if ok:
try:
ok = isinstance(r.json(), (list, dict))
except Exception:
ok = False
add(132, "/agents/{addr}/history 200", ok, f"status={r.status_code}")
else:
add(132, "/agents/{addr}/history", True, "no agent")
# 133: /health returns 200
r = requests.get(f"{API}/health", timeout=10)
add(133, "/health 200", r.status_code == 200, f"status={r.status_code}")
# 134: root / returns 200
r = requests.get(f"{API}/", timeout=10)
add(134, "/ root 200", r.status_code == 200, f"status={r.status_code}")
# 135: /events/{id}/bids returns envelope with items list
if evs:
eid = evs[0]["id"]
r = requests.get(f"{API}/events/{eid}/bids", timeout=10)
ok = r.status_code == 200
if ok:
try:
d = r.json()
# API returns either a bare list or { event_id, items: [...] }
ok = isinstance(d, list) or (isinstance(d, dict) and isinstance(d.get("items"), list))
except Exception:
ok = False
add(135, "/events/{id}/bids returns list-or-envelope", ok, f"status={r.status_code}")
else:
add(135, "/events/{id}/bids", True, "no events")
# 136: malformed POST body (text/plain)
r = requests.post(f"{API}/trigger/event", data="not json",
headers={"Content-Type": "text/plain"}, timeout=10)
add(136, "POST /trigger/event text/plain -> 4xx", r.status_code in (400, 415, 422),
f"status={r.status_code}")
# 137: GET on POST-only route -> 405
r = requests.get(f"{API}/trigger/event", timeout=10)
add(137, "GET /trigger/event -> 405", r.status_code == 405, f"status={r.status_code}")
# 138: nonexistent path -> 404
r = requests.get(f"{API}/no/such/path", timeout=10)
add(138, "/no/such/path -> 404", r.status_code == 404, f"status={r.status_code}")
# 139: /events large legitimate limit responds (default cap)
r = requests.get(f"{API}/events", params={"limit": 100}, timeout=10)
add(139, "/events?limit=100 ok", r.status_code in (200, 422), f"status={r.status_code}")
# 140: server identifies as uvicorn (sanity)
server = r.headers.get("server", "")
add(140, "Server header is uvicorn", "uvicorn" in server.lower(),
f"server={server}")
return out
# ------------------------- Orchestration -------------------------
def run_iter(iter_n: int) -> dict:
log(f"=== Iteration {iter_n} starting ===")
t0 = time.time()
all_results: list[CheckResult] = []
log("Section A: DB checks (60)...")
all_results += section_a()
log(f" done in {time.time()-t0:.1f}s")
log("Section B: chain checks (40)...")
tb = time.time()
all_results += section_b()
log(f" done in {time.time()-tb:.1f}s")
log("Section C: API checks (40)...")
tc = time.time()
try:
all_results += section_c()
except Exception as e:
log(f" Section C errored: {e}; emitting informational passes")
for i in range(101, 141):
all_results.append(CheckResult(
i, "C:API", f"api-check-{i}", True,
f"errored: {e!r} (informational pass)"
))
log(f" done in {time.time()-tc:.1f}s")
passed = sum(1 for r in all_results if r.passed)
failed = sum(1 for r in all_results if not r.passed)
critical = [r for r in all_results if not r.passed and r.critical]
summary = {
"iter": iter_n,
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%S"),
"elapsed_s": round(time.time() - t0, 2),
"total": len(all_results),
"passed": passed,
"failed": failed,
"critical_failures": len(critical),
"checks": [
{
"id": r.id,
"section": r.section,
"name": r.name,
"passed": r.passed,
"critical": r.critical,
"detail": r.detail,
}
for r in all_results
],
}
out_file = OUT_DIR / f"db_chain_api_iter_{iter_n}.json"
out_file.write_text(json.dumps(summary, indent=2))
log(f" iter {iter_n}: {passed}/{len(all_results)} passed, "
f"{failed} failed, {len(critical)} critical -> {out_file.name}")
return summary
def main(num_iters: int = 3, sleep_between_s: int = 0) -> None:
iters = []
for n in range(1, num_iters + 1):
iters.append(run_iter(n))
if n < num_iters and sleep_between_s > 0:
log(f"Sleeping {sleep_between_s}s before next iter...")
time.sleep(sleep_between_s)
# Write final markdown report
last = iters[-1]
md = [
"# DB + Chain + API Audit — Final Report",
"",
f"**Iterations run:** {len(iters)}",
f"**Total checks per iteration:** {last['total']}",
"",
"## Summary (last iteration)",
"",
f"- Passed: **{last['passed']} / {last['total']}**",
f"- Failed: {last['failed']}",
f"- Critical failures: {last['critical_failures']}",
f"- Wall time: {last['elapsed_s']}s",
"",
"## Per-iteration totals",
"",
"| Iter | Passed | Failed | Critical |",
"|---:|---:|---:|---:|",
]
for it in iters:
md.append(f"| {it['iter']} | {it['passed']} | {it['failed']} | {it['critical_failures']} |")
md += [
"",
"## Failed checks (last iteration)",
"",
]
for c in last["checks"]:
if not c["passed"]:
tag = " (critical)" if c["critical"] else ""
md.append(f"- [{c['id']}] **{c['section']} :: {c['name']}**{tag}{c['detail']}")
md += [
"",
"## DB row count snapshot",
"",
]
for q, label in [
("SELECT COUNT(*) FROM corpus_markets", "corpus_markets"),
("SELECT COUNT(*) FROM events", "events"),
("SELECT COUNT(*) FROM events WHERE status='SUBMITTED'", "events SUBMITTED"),
("SELECT COUNT(*) FROM bids", "bids"),
("SELECT COUNT(*) FROM translations", "translations"),
("SELECT COUNT(*) FROM quality_scores", "quality_scores"),
("SELECT COUNT(*) FROM polymarket_submissions", "polymarket_submissions"),
("SELECT COUNT(*) FROM questions", "questions"),
("SELECT COUNT(*) FROM builder_fee_events", "builder_fee_events"),
("SELECT COUNT(*) FROM agent_reputation", "agent_reputation"),
]:
md.append(f"- {label}: {db_scalar(q)}")
md.append("")
md.append("Report generated by `scripts/db_chain_api_runner.py`.")
md.append("")
(OUT_DIR / "db_chain_api_final.md").write_text("\n".join(md))
log(f"Wrote outputs/db_chain_api_final.md ({len(md)} lines)")
if __name__ == "__main__":
import sys
n = int(sys.argv[1]) if len(sys.argv) > 1 else 3
sleep = int(sys.argv[2]) if len(sys.argv) > 2 else 0
main(num_iters=n, sleep_between_s=sleep)