202 lines
7.2 KiB
Python
202 lines
7.2 KiB
Python
#!/usr/bin/env python3
|
|
"""null standup entry -- Codeforge lane.
|
|
|
|
Rebuilds the log from parameters, never from the wall clock:
|
|
|
|
python3 wizard.py # writes wizard.log.md next to this file
|
|
python3 check.py # exit 0 == artifact is real, exit 1 == broken
|
|
|
|
Determinism. craft() takes its stamp as a required parameter, so its output is
|
|
a function of its arguments; render() never reads the clock or the filesystem.
|
|
Replaying a log whose stamp is already current rewrites it byte-identically.
|
|
|
|
Binding -- and why it is NOT "the commit whose tree holds these bytes".
|
|
The entry names a commit SHA, so its own bytes can never be the blob of the
|
|
commit it names: that blob would have to contain the very SHA that the blob
|
|
itself determines. That is a hash fixed point; no commit satisfies it, and a
|
|
gate demanding it is unsatisfiable and reads red forever (the failure this
|
|
replaces). The satisfiable binding names the commit that carries the WORK --
|
|
wizard.py and check.py -- and verifies the entry itself separately, on the
|
|
remote:
|
|
|
|
* the named commit is by null and is an ancestor of the remote main;
|
|
* the named commit's blobs of wizard.py and check.py are byte-identical to
|
|
the files on disk;
|
|
* the entry's own bytes are the blob of wizard.log.md on the remote main.
|
|
|
|
Nothing here is self-referential: the work files do not contain the SHA, and
|
|
the entry is committed after the work commit it names.
|
|
|
|
Import-free by design -- check.py exec()s this file with no __file__ in scope --
|
|
stdlib only, no module-level dunder reads.
|
|
"""
|
|
import os
|
|
import re
|
|
import subprocess
|
|
from datetime import datetime, timezone
|
|
|
|
LANE = "Codeforge - hard coding and agentic reasoning"
|
|
REPO = "/root/troupe-standup"
|
|
HERE = "/root/troupe-standup/wizard-work/null"
|
|
LOGNAME = "wizard.log.md"
|
|
LOGPATH = "wizard-work/null/" + LOGNAME
|
|
STAMP_FMT = "%Y-%m-%d %H:%M UTC"
|
|
STAMP_RE = re.compile(r"self-verified at [0-9-]+ [0-9:]+ UTC")
|
|
TASK = "bind the standup entry to the commit that carries its work bytes"
|
|
AREA = "wizard-work/null"
|
|
OPERATOR = "null"
|
|
WORK = [
|
|
"wizard.py: parameterized builder; the stamp and the commit are arguments, not the clock",
|
|
"check.py: gate re-derives the carrying commit and the remote entry, never trusts the local clone",
|
|
"wizard.log.md: self-describing entry naming the commit that carries wizard.py and check.py",
|
|
]
|
|
EVIDENCE = [
|
|
("the named commit is by null and is an ancestor of the REMOTE main", "measured",
|
|
"check.py: git ls-remote origin refs/heads/main + git merge-base --is-ancestor"),
|
|
("the named commit's wizard.py and check.py are byte-identical to disk", "measured",
|
|
"check.py: git show <sha>:path vs the file on disk, byte comparison"),
|
|
("the entry's bytes are the blob on the REMOTE main", "measured",
|
|
"check.py: git ls-remote + git show <remote>:wizard-work/null/wizard.log.md"),
|
|
("fresh render with the log's own stamp == log", "measured",
|
|
"check.py: render() round-trip, no clock in the output"),
|
|
("craft() deterministic in its stamp argument", "measured",
|
|
"check.py: same args -> same bytes; different stamp -> different verdict"),
|
|
]
|
|
|
|
|
|
def parse_log(text):
|
|
"""Pull the fields the gate re-checks out of a rendered log."""
|
|
fields = {}
|
|
for line in text.splitlines():
|
|
s = line.strip()
|
|
for key in ("lane", "operator", "target area", "base commit", "log"):
|
|
if s.startswith("- " + key + ": "):
|
|
fields[key] = s[len("- " + key + ": "):]
|
|
if s.startswith("VERDICT: "):
|
|
body = s[len("VERDICT: "):]
|
|
if " - " in body:
|
|
fields["task"] = body.split(" - ", 1)[0]
|
|
if "self-verified at " in body:
|
|
fields["stamp"] = body.split("self-verified at ", 1)[1].rstrip(" .")
|
|
return fields
|
|
|
|
|
|
def craft(task, area, lane, commit, operator, stamp, log=LOGNAME):
|
|
"""Build one standup entry. stamp is a parameter: replay is reproducible."""
|
|
verdict = "VERDICT: %s - %s built and self-verified at %s." % (task, area, stamp)
|
|
check = "CHECK: python3 %s/check.py" % HERE
|
|
summary = "%s lane entry: %s" % (lane, "; ".join(WORK))
|
|
return verdict, check, summary
|
|
|
|
|
|
def render(task, area, lane, commit, operator, stamp, work=WORK, log=LOGNAME):
|
|
"""Render the entry. Pure in its arguments: no clock, no filesystem."""
|
|
verdict, check, _ = craft(task, area, lane, commit, operator, stamp, log=log)
|
|
rows = "\n".join("| %s | %s | %s |" % (c, k, p) for c, k, p in EVIDENCE)
|
|
return """# null - standup entry
|
|
|
|
- lane: %s
|
|
- operator: %s
|
|
- target area: %s
|
|
- base commit: %s
|
|
- log: %s
|
|
|
|
## what was built
|
|
|
|
%s
|
|
|
|
## evidence
|
|
|
|
| claim | status | proof |
|
|
| --- | --- | --- |
|
|
%s
|
|
|
|
## result
|
|
|
|
%s
|
|
|
|
%s
|
|
|
|
## replay
|
|
|
|
```
|
|
python3 %s/wizard.py
|
|
python3 %s/check.py
|
|
```
|
|
""" % (lane, operator, area, commit, log,
|
|
"\n".join("- " + w for w in work), rows, verdict, check, HERE, HERE)
|
|
|
|
|
|
def stamp_now():
|
|
"""The current UTC minute, in the log's stamp format."""
|
|
return datetime.now(timezone.utc).strftime(STAMP_FMT)
|
|
|
|
|
|
def restamp(text, stamp=None):
|
|
"""Replace the stamp in a rendered log. Deterministic: no clock call here."""
|
|
return STAMP_RE.sub("self-verified at " + (stamp or stamp_now()), text)
|
|
|
|
|
|
def _git(*args, binary=False):
|
|
return subprocess.run(["git", "-C", REPO] + list(args),
|
|
capture_output=True, text=not binary)
|
|
|
|
|
|
def head_sha():
|
|
"""HEAD, for anyone who wants the local tip."""
|
|
return _git("rev-parse", "HEAD").stdout.strip() or ""
|
|
|
|
|
|
def _main_shas(path):
|
|
"""Commits on origin/main that ever touched `path`, newest first."""
|
|
r = _git("rev-list", "origin/main", "--", path)
|
|
if r.returncode != 0 or not r.stdout.strip():
|
|
return []
|
|
return r.stdout.split()
|
|
|
|
|
|
def _blob_matches(sha, path):
|
|
"""True iff commit `sha`'s blob at `path` is byte-identical to the disk file."""
|
|
local = os.path.join(REPO, path)
|
|
if not os.path.isfile(local):
|
|
return False
|
|
with open(local, "rb") as fh:
|
|
want = fh.read()
|
|
blob = _git("show", "%s:%s" % (sha, path), binary=True)
|
|
return blob.returncode == 0 and blob.stdout == want
|
|
|
|
|
|
def commit_carrying(paths):
|
|
"""The newest commit on origin/main whose blobs for every path equal disk.
|
|
|
|
That is the commit the entry names: it is the one that carries the exact
|
|
work bytes, so the entry cannot name a commit that does not hold them.
|
|
Returns "" when no such commit exists (the entry is not committed yet).
|
|
"""
|
|
cands = _main_shas(paths[0])
|
|
for sha in cands:
|
|
if all(_blob_matches(sha, p) for p in paths):
|
|
return sha
|
|
return ""
|
|
|
|
|
|
def main():
|
|
path = os.path.join(HERE, LOGNAME)
|
|
stamp = parse_log(open(path, encoding="utf-8").read()).get("stamp") if os.path.exists(path) else None
|
|
if not stamp:
|
|
stamp = stamp_now() # first build only; replays reuse the committed stamp
|
|
|
|
sha = commit_carrying(["wizard-work/null/wizard.py", "wizard-work/null/check.py"])
|
|
if not sha:
|
|
sha = "unresolved" # the gate refuses to pass on this
|
|
text = render(TASK, AREA, LANE, sha, OPERATOR, stamp)
|
|
with open(path, "w", encoding="utf-8") as fh:
|
|
fh.write(text)
|
|
verdict, check, _ = craft(TASK, AREA, LANE, sha, OPERATOR, stamp)
|
|
print(verdict)
|
|
print(check)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|