forked from Ikalus1988/MisakaNet
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmisaka_verify.py
More file actions
146 lines (120 loc) · 4.37 KB
/
Copy pathmisaka_verify.py
File metadata and controls
146 lines (120 loc) · 4.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/usr/bin/env python3
"""misaka-verify — Local task verifier using pytest exit codes.
Reads tasks/*.json, runs the verification command for each task locally.
Uses only subprocess + pytest — no Docker, no LLM, no external API.
Usage:
python3 scripts/misaka_verify.py # verify all tasks
python3 scripts/misaka_verify.py <task_id> # verify one task
python3 scripts/misaka_verify.py --domain security # filter by domain
python3 scripts/misaka_verify.py --list # list available tasks
"""
from __future__ import annotations
import json
import subprocess
import sys
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent
TASKS_DIR = REPO_ROOT / "tasks"
PASS = "✅"
FAIL = "❌"
SKIP = "⏭️"
def load_tasks(filter_domain: str | None = None) -> list[dict]:
index = TASKS_DIR / "index.json"
if not index.exists():
print(f"❌ No tasks/index.json found. Run scripts/extract_tasks.py first.")
sys.exit(1)
tasks = json.loads(index.read_text())
if filter_domain:
tasks = [t for t in tasks if t.get("domain") == filter_domain]
return tasks
def resolve_task(task_id: str) -> dict | None:
"""Find a task by ID from the index."""
tasks = load_tasks()
for t in tasks:
if t["task_id"] == task_id:
return t
return None
def run_verification(task: dict) -> tuple[str, str]:
"""Run the verification command for a task.
Returns (status, details).
"""
source_path = REPO_ROOT / task.get("source", "")
task_file = TASKS_DIR / f"{task['task_id']}.json"
# Check source exists
if not source_path.exists():
return SKIP, f"Source not found: {task['source']}"
# Read full task for test_cmd
task_data = json.loads(task_file.read_text())
test_cmd = task_data.get("test_cmd", "")
# If we have a pytest command, run it
if test_cmd:
try:
import shlex
result = subprocess.run(
shlex.split(test_cmd),
cwd=REPO_ROOT,
capture_output=True,
text=True,
timeout=120, # 2 min max per task
)
if result.returncode == 0:
return PASS, f"{test_cmd} → exit 0"
else:
summary = result.stdout.split("\n")[-3:]
return FAIL, f"{test_cmd} → exit {result.returncode}: {' '.join(summary)}"
except subprocess.TimeoutExpired:
return FAIL, f"{test_cmd} → TIMEOUT (>120s)"
except FileNotFoundError:
return FAIL, f"Command not found: {test_cmd.split()[0]}"
# No test command — verify source file integrity
if source_path.stat().st_size > 100:
return PASS, f"Source exists ({source_path.stat().st_size} bytes)"
return SKIP, f"No test_cmd and source too small" if source_path.stat().st_size > 0 else FAIL, f"Empty source"
def main():
args = sys.argv[1:]
if "--list" in args:
tasks = load_tasks()
print(f"{'Task ID':45s} {'Domain':15s} {'Title':40s}")
print("-" * 100)
for t in tasks:
print(f"{t['task_id']:45s} {t.get('domain','?'):15s} {t['title'][:38]:40s}")
return
filter_domain = None
if "--domain" in args:
idx = args.index("--domain")
if idx + 1 < len(args):
filter_domain = args[idx + 1]
# Single task mode
task_ids = [a for a in args if not a.startswith("--")]
if task_ids:
results = []
for tid in task_ids:
task = resolve_task(tid)
if not task:
print(f"❌ Task not found: {tid}")
continue
status, detail = run_verification(task)
print(f"{status} {tid}: {detail}")
return
# Batch mode
tasks = load_tasks(filter_domain)
if not tasks:
print("❌ No tasks found.")
sys.exit(1)
passed = 0
failed = 0
skipped = 0
total = len(tasks)
for task in tasks:
status, detail = run_verification(task)
if status == PASS:
passed += 1
elif status == FAIL:
failed += 1
else:
skipped += 1
print(f"{status} {task['task_id']:45s} {detail[:50]}")
print(f"\n{'='*50}")
print(f"Total: {total} Passed: {passed} Failed: {failed} Skipped: {skipped}")
if __name__ == "__main__":
main()