#!/usr/bin/env python3 """S4: End-to-end pipeline verification.""" import json, subprocess, sys, sqlite3 DB = "/data/data/com.termux/files/home/wechat-viewer/circle.db" passed = 0; total = 0 def check(n, c, d=""): global passed, total; total += 1 print(f" {'✅' if c else '❌'} {n}{' - ' + d if d else ''}") if c: passed += 1 print("=== S4: End-to-End Verification ===\n") # 1. Find a scored article in learn_queue conn = sqlite3.connect(DB) rows = conn.execute(""" SELECT lq.id, lq.article_url, lq.title, lq.learn_type, lq.learn_target, lq.score, lq.confidence, lq.status, a.url as article_url_full, dr.content as summary FROM learn_queue lq LEFT JOIN articles a ON lq.dedup_key = a.dedup_key LEFT JOIN daily_reports dr ON dr.article_url = lq.article_url AND dr.report_date = 'summary' WHERE lq.score >= 6 AND lq.status = 'pending' ORDER BY lq.score DESC LIMIT 1 """).fetchone() if not rows: # Try without status filter rows = conn.execute(""" SELECT lq.id, lq.article_url, lq.title, lq.learn_type, lq.learn_target, lq.score, lq.confidence, lq.status FROM learn_queue lq WHERE lq.score >= 6 ORDER BY lq.score DESC LIMIT 1 """).fetchone() if rows: lid = rows[0] ltype = rows[3] ltarget = rows[4] score = rows[5] status = rows[7] if len(rows) > 7 else "?" title = (rows[2] or "?")[:50] check("Find classified article", True, f"id={lid} type={ltype} score={score} status={status} title={title}") print(f" target={ltarget}") # 2. Check summary exists for this article summary_row = conn.execute( "SELECT content FROM daily_reports WHERE article_url = ? AND report_date = 'summary' LIMIT 1", (rows[1],) ).fetchone() has_summary = summary_row and summary_row[0] and len(summary_row[0]) > 200 check("Summary available", has_summary, f"len={len(summary_row[0]) if summary_row else 0}") # 3. Check dedup logic - is this already in memory/skill? if ltype == "skill": has_dedup = conn.execute( "SELECT COUNT(*) FROM learn_queue WHERE dedup_key = (SELECT dedup_key FROM learn_queue WHERE id=?) AND status IN ('completed','processing')", (lid,) ).fetchone()[0] check("Dedup check", has_dedup == 0, f"duplicates={has_dedup}") # 4. Check learn-and-build skill exists from pathlib import Path lb_skill = Path("/data/data/com.termux/files/home/.dsh/skills/wechat/learn-and-build/SKILL.md") check("learn-and-build skill exists", lb_skill.exists()) # 5. Verify cron pipeline can self-heal scan_path = Path("/data/data/com.termux/files/home/.dsh/skills/wechat-group-digest/scripts/scan_articles.py") check("scan_articles.py exists", scan_path.exists()) # 6. Overall pipeline check conn2 = sqlite3.connect(DB) total_arts = conn2.execute("SELECT COUNT(*) FROM articles").fetchone()[0] total_reports = conn2.execute("SELECT COUNT(*) FROM daily_reports WHERE report_date='summary'").fetchone()[0] total_learn = conn2.execute("SELECT COUNT(*) FROM learn_queue WHERE score >= 6").fetchone()[0] total_pending_classify = conn2.execute(""" SELECT COUNT(*) FROM learn_queue WHERE status = 'pending' AND score >= 6 """).fetchone()[0] conn2.close() check("Pipeline: articles → summaries", total_reports > 0, f"{total_arts} arts → {total_reports} summaries") check("Pipeline: summaries → classified", total_learn > 0, f"{total_reports} summaries → {total_learn} classified (≥6)") check("Pipeline: pending review", total_pending_classify >= 0, f"{total_pending_classify} pending") conn.close() print(f"\nResult: {passed}/{total} passed") sys.exit(0 if passed == total else 1)