LiveHouse-TS / scripts /build_bootstrap.py
ziyuzhou02's picture
Deploy GitHub main 3feb6cda1511
e317359 verified
Raw
History Blame Contribute Delete
4.04 kB
#!/usr/bin/env python3
"""Build a portable seed from public source responses and metrics, without secrets."""
from datetime import datetime, timezone
import gzip
import hashlib
import io
import json
from pathlib import Path
import tarfile
import subprocess
import sys
import tempfile
ROOT = Path(__file__).resolve().parents[1]
def main():
source = ROOT / "space/vendor/ts_bench/data/sample_week"
files = [p for name in ("normalized", "raw")
for p in (source / name).rglob("*") if p.is_file()]
if (source / "summary.json").exists():
files.append(source / "summary.json")
for p in (ROOT / "space/results").rglob("*"):
if not p.is_file():
continue
rel = p.relative_to(ROOT / "space/results")
if any(part in rel.parts for part in ("prequential", "saved_evals", "forecasts", "canonical_all_history")):
continue
if p.suffix not in (".json", ".csv", ".tex", ".jsonl") or p.name == "eval_state.json":
continue
if p.suffix == ".jsonl" and rel.as_posix() not in ("evaluation_metrics_canonical.jsonl", "eval_history.jsonl"):
continue
files.append(p)
# Check literal configured credentials before any file enters the archive.
from dotenv import dotenv_values
secrets = [v.encode() for k, v in dotenv_values(ROOT / ".env").items()
if v and len(v) >= 12 and any(word in k for word in ("TOKEN", "KEY", "SECRET", "PASSWORD"))]
members = []
for p in sorted(files):
content = p.read_bytes()
if any(secret in content for secret in secrets):
raise SystemExit(f"Credential found in seed candidate: {p.relative_to(ROOT)}")
if p.name == "online_status.json":
status = json.loads(content)
status.update(status="bootstrap", issued_forecasts=0, resolved_forecasts=0,
pending_tasks=0, issued_tasks=0, push_status="not_published",
bootstrap_note="Private pending forecast state is excluded; start a new live cycle.")
content = (json.dumps(status, indent=2) + "\n").encode()
members.append((p.relative_to(ROOT).as_posix(), content))
# Export into an empty directory: old runtime exports otherwise accumulate
# tens of thousands of unreachable task files across collection cycles.
with tempfile.TemporaryDirectory(prefix="livehouse-seed-inputs-") as temp:
subprocess.run([sys.executable, str(ROOT / "space/vendor/ts_bench/export_model_inputs.py"),
"--input", str(source / "normalized"), "--output", temp, "--limit", "20"], check=True)
prefix = "space/vendor/ts_bench/data/sample_week/model_inputs_latest/"
members.extend((prefix + p.relative_to(temp).as_posix(), p.read_bytes())
for p in Path(temp).rglob("*") if p.is_file())
archive = ROOT / "bootstrap/seed.tar.gz"
with archive.open("wb") as raw, gzip.GzipFile(filename="", fileobj=raw, mode="wb", mtime=0) as compressed:
with tarfile.open(fileobj=compressed, mode="w") as bundle:
for name, content in members:
info = tarfile.TarInfo(name)
info.size = len(content)
info.mode = 0o644
bundle.addfile(info, io.BytesIO(content))
manifest = {"snapshot_date": datetime.now(timezone.utc).date().isoformat(),
"sha256": hashlib.sha256(archive.read_bytes()).hexdigest(),
"bytes": archive.stat().st_size, "files": len(members),
"contents": "Current public raw responses, normalized observations, latest inputs, historical canonical metrics, public tables and forecast visualization snapshots. No credentials or private task/inference archives.",
"historical_raw_available": False, "current_raw_included": True}
(ROOT / "bootstrap/manifest.json").write_text(json.dumps(manifest, indent=2) + "\n")
print(json.dumps(manifest, indent=2))
if __name__ == "__main__":
main()