Meta3.0 / scripts /meta3_smoke.py
smlflg's picture
Initial public upload from Projekte/Meta3.0
1219ee2 verified
Raw History Blame Contribute Delete
6.74 kB
#!/usr/bin/env python3
"""Local smoke checks for the Meta3 scaffold. No network calls."""
from __future__ import annotations
import json
import py_compile
import re
from pathlib import Path
from typing import Any
ROOT = Path(__file__).resolve().parents[1]
REQUIRED_IMPROVEMENT_IDS = {
"stratified_evidence",
"claim_ledger",
"counterevidence_pass",
"validity_before_synthesis",
"question_graph",
"owner_ready_output",
}
REQUIRED_PROCESS_PHASE_IDS = {
"p00_requirements_lock",
"p01_baseline_audit",
"p02_calibration_slice",
"p03_stratified_backfill",
"p04_claim_ledger_generation",
"p05_counterevidence_pass",
"p06_validity_review",
"p07_owner_synthesis",
"p08_morning_closeout",
}
REQUIRED_EXECUTION_SCRIPTS = {
"meta3_prepare.py",
"meta3_plan_batches.py",
"meta3_build_workpackets.py",
"meta3_collect_responses.py",
"meta3_create_mock_response.py",
"meta3_freeze_sources.py",
"meta3_morning_report.py",
"meta3_orchestrate_local.py",
"meta3_preflight.py",
"meta3_run_packets.py",
"meta3_runner_status.py",
"meta3_validate_run.py",
"meta3_smoke.py",
}
def load_json(path: Path) -> dict[str, Any]:
with path.open("r", encoding="utf-8") as handle:
data = json.load(handle)
if not isinstance(data, dict):
raise ValueError(f"Expected object in {path}")
return data
def check_secret_patterns(paths: list[Path]) -> list[str]:
findings: list[str] = []
patterns = [
re.compile(r"sk-[A-Za-z0-9_-]{20,}"),
re.compile(r"api[_-]?key\"?\s*[:=]\s*\"[A-Za-z0-9_\-]{16,}\"", re.IGNORECASE),
re.compile(r"token\"?\s*[:=]\s*\"[A-Za-z0-9_\-]{24,}\"", re.IGNORECASE),
]
for path in paths:
text = path.read_text(encoding="utf-8")
for pattern in patterns:
if pattern.search(text):
findings.append(str(path.relative_to(ROOT)))
break
return findings
def main() -> int:
errors: list[str] = []
warnings: list[str] = []
required_dirs = ["config", "requirements", "scripts", "runs", "data", "reports", "logs", "docs"]
for rel in required_dirs:
if not (ROOT / rel).is_dir():
errors.append(f"missing dir: {rel}")
try:
profile = load_json(ROOT / "config/run_profile.example.json")
except Exception as exc: # noqa: BLE001 - smoke should report all context
errors.append(f"profile json invalid: {exc}")
profile = {}
try:
questions_doc = load_json(ROOT / "config/questions.json")
questions = questions_doc.get("questions", [])
if not isinstance(questions, list) or not questions:
errors.append("questions list missing or empty")
else:
ids = [q.get("id") for q in questions if isinstance(q, dict)]
if len(ids) != len(set(ids)):
errors.append("duplicate question ids")
for q in questions:
if not isinstance(q, dict) or not q.get("prompt"):
errors.append("question without prompt")
except Exception as exc: # noqa: BLE001
errors.append(f"questions json invalid: {exc}")
try:
experiment = load_json(ROOT / "config/experiment_design.json")
if experiment.get("schema") != "meta3.experiment_design.v1":
errors.append("experiment design schema invalid")
requirements = experiment.get("improvement_requirements", [])
if not isinstance(requirements, list):
errors.append("experiment improvement_requirements missing or invalid")
else:
ids = {item.get("id") for item in requirements if isinstance(item, dict)}
missing = sorted(REQUIRED_IMPROVEMENT_IDS - ids)
if missing:
errors.append("experiment improvement ids missing: " + ", ".join(missing))
except Exception as exc: # noqa: BLE001
errors.append(f"experiment design json invalid: {exc}")
try:
process = load_json(ROOT / "config/process_model.json")
if process.get("schema") != "meta3.process_model.v1":
errors.append("process model schema invalid")
phases = process.get("phases", [])
if not isinstance(phases, list):
errors.append("process phases missing or invalid")
else:
phase_ids = {phase.get("id") for phase in phases if isinstance(phase, dict)}
missing = sorted(REQUIRED_PROCESS_PHASE_IDS - phase_ids)
if missing:
errors.append("process phase ids missing: " + ", ".join(missing))
except Exception as exc: # noqa: BLE001
errors.append(f"process model json invalid: {exc}")
if not (ROOT / "docs/evals/EVAL_meta3_improvement_over_meta2.md").is_file():
errors.append("missing eval spec: docs/evals/EVAL_meta3_improvement_over_meta2.md")
if not (ROOT / "docs/META3_PROCESS.md").is_file():
errors.append("missing process doc: docs/META3_PROCESS.md")
architecture_text = (ROOT / "ARCHITECTURE.md").read_text(encoding="utf-8")
if "Meta3 Improvement Contract" not in architecture_text:
errors.append("ARCHITECTURE.md missing Meta3 Improvement Contract")
for key, value in profile.get("source_artifacts", {}).items():
path = Path(value)
if not path.exists():
warnings.append(f"source missing: {key} -> {path}")
for script in sorted((ROOT / "scripts").glob("*.py")):
try:
py_compile.compile(str(script), doraise=True)
except py_compile.PyCompileError as exc:
errors.append(f"script compile failed: {script.name}: {exc.msg}")
script_names = {path.name for path in (ROOT / "scripts").glob("*.py")}
missing_scripts = sorted(REQUIRED_EXECUTION_SCRIPTS - script_names)
if missing_scripts:
errors.append("missing execution scripts: " + ", ".join(missing_scripts))
secret_findings = check_secret_patterns(
[
ROOT / "config/run_profile.example.json",
ROOT / "config/questions.json",
ROOT / "config/experiment_design.json",
ROOT / "config/process_model.json",
]
)
if secret_findings:
errors.append("possible secret in: " + ", ".join(secret_findings))
if (ROOT / ".git").exists() and not (ROOT / ".git/HEAD").exists():
warnings.append(".git directory exists but is not a valid git repo")
for warning in warnings:
print(f"WARN {warning}")
for error in errors:
print(f"ERROR {error}")
if errors:
print("SMOKE FAIL")
return 1
print("SMOKE PASS")
return 0
if __name__ == "__main__":
raise SystemExit(main())