#!/usr/bin/env python3 """ emit.py — the 10-line telemetry emitter agents call as they work. Appends one event (per SPEC.md) to the build's event log. Zero dependencies. Shell (the way agents use it): python emit.py human_touch --kind prompt python emit.py work_completed --domain fpga --tool Questa --deliverable gateware --duration_s 900 --iterations 2 --result pass python emit.py rework --deliverable compute.html --cause "false claim: FPGA in Capital" python emit.py seam_crossing --domain electrical --tool bridge --from neutral-bundle --to Capital --duration_s 1200 --failures 5 python emit.py verification --domain fpga --deliverable safety --method formal --machine_checkable true --result pass Code: from emit import emit; emit("human_touch", kind="prompt") Env: TTS_RUN (run id, default "dev") e.g. export TTS_RUN=qx250-2 TTS_LOG (log path, default ./events.live.jsonl next to this file) TTS_ACTOR (actor, default "agent") Unknown --keys go into meta (so kind/from/to/cause/iterations/method/machine_checkable all land in meta exactly as the schema and aggregate.py expect). """ import os, sys, json, datetime HERE = os.path.dirname(os.path.abspath(__file__)) LOG = os.environ.get("TTS_LOG") or os.path.join(HERE, "events.live.jsonl") TOP = {"phase", "domain", "tool", "deliverable", "duration_s", "result", "actor"} # rest -> meta # --- the emitter: ~10 lines ------------------------------------------------- def emit(event, **f): e = {"ts": datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"), "run_id": os.environ.get("TTS_RUN", "dev"), "event": event, "actor": f.pop("actor", os.environ.get("TTS_ACTOR", "agent"))} meta = f.pop("meta", {}) for k in list(f): (e if k in TOP else meta)[k] = f.pop(k) if meta: e["meta"] = meta with open(LOG, "a", encoding="utf-8") as fh: fh.write(json.dumps(e) + "\n") return e # --------------------------------------------------------------------------- def _val(v): if v in ("true", "false"): return v == "true" for cast in (int, float): try: return cast(v) except ValueError: pass return v if __name__ == "__main__": args = sys.argv[1:] if not args: sys.exit("usage: emit.py [--key value ...] (e.g. emit.py human_touch --kind prompt)") event, kw, i = args[0], {}, 1 while i < len(args): tok = args[i] if tok.startswith("--"): key = tok[2:] if i + 1 < len(args) and not args[i + 1].startswith("--"): kw[key] = _val(args[i + 1]); i += 2 # --key value else: kw[key] = True; i += 1 # --flag (bare) else: i += 1 print(json.dumps(emit(event, **kw)))