#!/usr/bin/env python3 """Hand a file to another agent without putting it in git history. share put --note "what this is" [--for decoder|port|referee|all] share ls [--for ] [--from ] [--all] share get [] share drop Why this exists --------------- Three kinds of thing were travelling down one channel, and they want opposite treatment: * decoded knowledge and code -- want history, review, permanence -> git * evidence cited in a finding -- wants permanence -> git * "look at this PNG I just made" -- wants NO history at all -> here Committing the third kind bloats the repository forever with files nobody will read twice. Passing it by message is worse: the receiver gets bytes with no idea which build produced them. So this writes to a shared volume with a manifest entry recording who, when, what, and -- the part that matters -- **the commit the sender was on**. A capture with no provenance is not evidence, it is a picture. Nothing here is durable. If a result is worth keeping, it belongs in the corpus with its evidence, and this tool is not how you put it there. """ from __future__ import annotations import argparse import getpass import hashlib import json import os import shutil import subprocess import sys import time from pathlib import Path ROOT = Path(os.environ.get("SYLPH_EXCHANGE", "/exchange")) MANIFEST = ROOT / "manifest.jsonl" WHO = os.environ.get("SYLPH_AGENT", getpass.getuser()) # A transient store that never forgets is just a slow repository. TTL_DAYS = 14 def _git(*args: str) -> str: try: return subprocess.run( ["git", *args], capture_output=True, text=True, timeout=10 ).stdout.strip() except Exception: return "" def _provenance() -> dict: """The sender's commit, and whether the tree was dirty at the time. `dirty` is not a footnote: a capture taken from a modified tree cannot be reproduced from the sha alone, and the receiver deserves to know that before building an argument on it. """ return { "commit": _git("rev-parse", "--short", "HEAD") or None, "branch": _git("rev-parse", "--abbrev-ref", "HEAD") or None, "dirty": bool(_git("status", "--porcelain")), } def _entries() -> list[dict]: if not MANIFEST.exists(): return [] out = [] for line in MANIFEST.read_text().splitlines(): line = line.strip() if line: try: out.append(json.loads(line)) except json.JSONDecodeError: continue return out def _append(entry: dict) -> None: ROOT.mkdir(parents=True, exist_ok=True) with MANIFEST.open("a") as f: f.write(json.dumps(entry) + "\n") def cmd_put(a: argparse.Namespace) -> int: src = Path(a.file) if not src.is_file(): print(f"share: not a file: {src}", file=sys.stderr) return 1 digest = hashlib.sha256(src.read_bytes()).hexdigest()[:12] ident = f"{int(time.time())}-{digest}" dest_dir = ROOT / "files" dest_dir.mkdir(parents=True, exist_ok=True) dest = dest_dir / f"{ident}-{src.name}" shutil.copy2(src, dest) _append( { "id": ident, "name": src.name, "path": str(dest), "bytes": dest.stat().st_size, "note": a.note, "from": WHO, "for": a.audience, "at": time.strftime("%Y-%m-%dT%H:%M:%S"), "source": _provenance(), } ) print(f"share: {ident} {src.name} ({dest.stat().st_size} B) for {a.audience}") print(f" {dest}") return 0 def cmd_ls(a: argparse.Namespace) -> int: cutoff = time.time() - TTL_DAYS * 86400 rows = _entries() shown = 0 for e in rows: if e.get("id") in _dropped(): continue stamp = int(str(e.get("id", "0")).split("-")[0] or 0) if not a.all and stamp < cutoff: continue if a.audience and e.get("for") not in (a.audience, "all"): continue if a.sender and e.get("from") != a.sender: continue src = e.get("source") or {} mark = "*" if src.get("dirty") else " " exists = "" if Path(e.get("path", "")).exists() else " [MISSING]" print( f"{e['id']} {e['at']} {e['from']:>9} -> {e['for']:<8} " f"@{src.get('commit') or '?'}{mark} {e['name']}{exists}" ) if e.get("note"): print(f" {e['note']}") shown += 1 if not shown: print("share: nothing to show" + ("" if a.all else f" (last {TTL_DAYS} days)")) else: print(f"\n* = sender's tree was dirty; the commit alone will not reproduce it") return 0 def _dropped() -> set[str]: return {e["id"] for e in _entries() if e.get("dropped")} def cmd_get(a: argparse.Namespace) -> int: for e in reversed(_entries()): if e.get("id") == a.id: src = Path(e["path"]) if not src.exists(): print(f"share: {a.id} is in the manifest but its file is gone", file=sys.stderr) return 1 dest = Path(a.dest) if a.dest else Path(e["name"]) if dest.is_dir(): dest = dest / e["name"] shutil.copy2(src, dest) print(f"share: {a.id} -> {dest}") src_meta = e.get("source") or {} if src_meta.get("dirty"): print(" NOTE: sender's tree was dirty -- not reproducible " "from its commit alone") return 0 print(f"share: no such id: {a.id}", file=sys.stderr) return 1 def cmd_drop(a: argparse.Namespace) -> int: for e in _entries(): if e.get("id") == a.id: p = Path(e.get("path", "")) if p.exists(): p.unlink() _append({"id": a.id, "dropped": True, "by": WHO, "at": time.strftime("%Y-%m-%dT%H:%M:%S")}) print(f"share: dropped {a.id}") return 0 print(f"share: no such id: {a.id}", file=sys.stderr) return 1 def main() -> int: ap = argparse.ArgumentParser(prog="share", description=__doc__.splitlines()[0]) sub = ap.add_subparsers(dest="cmd", required=True) p = sub.add_parser("put", help="offer a file to another agent") p.add_argument("file") p.add_argument("--note", required=True, help="what it is and why the receiver should care") p.add_argument("--for", dest="audience", default="all", choices=["decoder", "port", "referee", "all"]) p.set_defaults(fn=cmd_put) p = sub.add_parser("ls", help="list what is on offer") p.add_argument("--for", dest="audience", default=None) p.add_argument("--from", dest="sender", default=None) p.add_argument("--all", action="store_true", help="include entries past the TTL") p.set_defaults(fn=cmd_ls) p = sub.add_parser("get", help="copy one out") p.add_argument("id") p.add_argument("dest", nargs="?") p.set_defaults(fn=cmd_get) p = sub.add_parser("drop", help="withdraw one") p.add_argument("id") p.set_defaults(fn=cmd_drop) args = ap.parse_args() return args.fn(args) if __name__ == "__main__": sys.exit(main())