File size: 3,803 Bytes
2e658e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
#!/usr/bin/env python3
"""P11-T07: Produce final technical evidence package (file-based artifacts)."""
from __future__ import annotations

import datetime
import hashlib
import os
import subprocess
import sys
import tempfile
from pathlib import Path


def sha256_file(path: Path) -> str:
    h = hashlib.sha256()
    with open(path, "rb") as f:
        for chunk in iter(lambda: f.read(65536), b""):
            h.update(chunk)
    return h.hexdigest()


def main() -> int:
    root = Path(__file__).resolve().parents[1]
    out_dir = root / "evidence_package"
    out_dir.mkdir(exist_ok=True)
    ts = datetime.datetime.now(datetime.timezone.utc).strftime("%Y%m%dT%H%M%SZ")
    lines = [
        f"# Technical Evidence Package",
        f"Generated (UTC): {ts}",
        f"Project root: {root}",
        "",
        "## Safety posture",
        "- TRADING_MODE default paper",
        "- HERMES_EXECUTION_ENABLED default false",
        "- Agent mutation tools unregistered",
        "- GAP-001 kill switch closed",
        "",
        "## Automated checks (full local suite)",
    ]
    env = os.environ.copy()
    env["PYTHONPATH"] = str(root / "hermes_overlay")
    # Write test output to a real file rather than a PIPE. Some integration
    # subprocesses can inherit pipe descriptors and delay EOF even after the
    # pytest parent exits; a temporary file keeps evidence generation bounded.
    with tempfile.TemporaryFile(mode="w+t", encoding="utf-8") as test_output:
        try:
            r = subprocess.run(
                [sys.executable, "-m", "pytest", "hermes_overlay/tests", "-vv"],
                cwd=str(root), env=env, stdout=test_output, stderr=subprocess.STDOUT,
                text=True, timeout=300,
            )
            returncode = r.returncode
        except subprocess.TimeoutExpired:
            returncode = 124
            test_output.write("\nERROR: full local suite exceeded 300 seconds\n")
        test_output.seek(0)
        captured = test_output.read()
    lines.append("```")
    lines.append(captured[-2500:] if captured else "")
    lines.append(f"exit={returncode}")
    lines.append("```")
    lines.append("")
    # runbook validator
    v = subprocess.run([sys.executable, "scripts/validate_runbook_consistency.py", "--skip-evidence-hashes"],
                       cwd=str(root), capture_output=True, text=True)
    lines.append("## Runbook consistency")
    lines.append("```")
    lines.append(v.stdout)
    lines.append("```")
    lines.append("")
    lines.append("## Key artifact hashes")
    for rel in [
        "hermes_overlay/trading/futures_execution.py",
        "hermes_overlay/trading/domain/execution_service.py",
        "scripts/backup_allowlist.py",
        "HERMES_V5_CLOUD_DESKTOP_MASTER_RUNBOOK.md",
    ]:
        path = root / rel
        if path.is_file():
            lines.append(f"- `{rel}`: `{sha256_file(path)}`")
    lines.append("")
    lines.append("## Deferred (require operator / external)")
    lines.append("- OP-P0-01 credential rotation")
    lines.append("- OP-P1-01 upstream approval")
    lines.append("- P11-T05 Testnet lifecycle")
    lines.append("- P11-T06 independent human audit")
    lines.append("- P11-T08 program sign-off")
    lines.append("- S1-T05/T06 strategy Testnet comparison and approval")
    lines.append("")
    lines.append("## Release gates")
    lines.append("All gates A–F remain NOT_REVIEWED. This package does not approve Testnet or Live.")
    report = out_dir / f"evidence_{ts}.md"
    report.write_text("\n".join(lines), encoding="utf-8")
    latest = out_dir / "EVIDENCE_LATEST.md"
    latest.write_text(report.read_text(encoding="utf-8"), encoding="utf-8")
    print(f"wrote {report}")
    return 0 if returncode == 0 else 1


if __name__ == "__main__":
    sys.exit(main())