Spaces:
Sleeping
Sleeping
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())
|