derived
Is a generated file stale against the command that makes it? A derived file (one a build command produces, that no human should hand-edit) still exists on disk when it falls behind its source — so no presence check ever catches it. derived runs the build fresh in a private sandbox and byte-compares its output against the committed file: CURRENT (exit 0), STALE (exit 3, difference named), BUILD-FAILED, or a usage error. Non-mutating by contract — it never touches your working tree.
The honest edge
this checks STALENESS (committed vs a fresh build), not CORRECTNESS: a green means the file matches what the command emits right now, never that the command or its output is right. It runs your build command, so only point it at a command you trust.
Run it
python3 derived.py --build-cmd "python3 gen.py" --derived out/table.json --copy gen.py
test_derived.py (11/11, mutation-bitten)
Python 3, standard library only
The code — every file that ships
derived.py245 lineson GitHub →
#!/usr/bin/env python3
"""derived.py — is a generated file STALE against the command that makes it?
A "derived" file is one no human should hand-edit: a build command produces it
from some source, and the committed copy is only ever supposed to be whatever
that command most recently emitted. The failure this catches is the oldest one
in generated code: the source moved, nobody re-ran the build, and the committed
derived file quietly fell behind. It works today (it is a real file on disk) and
breaks silently later, so no "does the file exist?" check ever sees it.
A script-generated file cannot DRIFT; it can only be STALE,
and stale is one command.
That sentence is TRUE and it is NOT A GUARD. The command is unenforced, so the
sentence describes the fix, not a mechanism -- and the file goes stale while the
sentence sits there being correct. This tool is the mechanism: it RUNS the build
command and byte-compares its fresh output against the committed derived file.
NON-MUTATING BY CONTRACT (the property this gift is built around).
This never edits your working tree. It runs the build command inside a private
temporary directory, seeded with a copy of your inputs, and compares the fresh
output there against the committed derived file here. Your files are never
touched -- there is no reading of a tree that proves an edit is worthless, and a
checker must not destroy one on a guess. If the build command insists on writing
in place, pass --in-place and it runs against a full copy of the working tree in
the sandbox (still never your real tree).
THE ORACLE IS THE COMMAND ITSELF, ON PURPOSE.
This carries no copy of the source->derived mapping. You name the build command
and the file it is supposed to produce; the tool asks the only question that
needs no mapping: run the command fresh -- does what it emits match what is
committed, byte for byte? A checker that re-declared the mapping would be a
second source of truth for it, which is the very fault class being guarded.
EXITS
0 CURRENT -- the committed derived file matches a fresh build, byte for byte
3 STALE -- it does not; the diff summary is printed (and --show-diff dumps it)
4 BUILD-FAILED -- the build command exited non-zero; nothing can be concluded
2 USAGE -- bad arguments, or the derived file / a --copy input is missing
USAGE
# The build command writes the derived file to a path you name.
python3 derived.py --build-cmd "python3 gen.py" --derived out/table.json --copy gen.py --copy data/
# The build command writes to stdout; capture it and compare.
python3 derived.py --build-cmd "python3 gen.py" --derived out/table.json --stdout --copy gen.py
# The build insists on editing files in place: run it against a tree copy.
python3 derived.py --build-cmd "make derived" --derived out/x --in-place
python3 derived.py --json # machine-readable verdict
"""
import argparse
import json
import os
import shutil
import subprocess
import sys
import tempfile
EXIT_CURRENT = 0
EXIT_USAGE = 2
EXIT_STALE = 3
EXIT_BUILD_FAILED = 4
# --- the printed edge: what this gift does NOT do -------------------------
EDGE = (
"this checks STALENESS (committed vs a fresh build), not CORRECTNESS: "
"a green means the file matches what the command emits right now, never "
"that the command or its output is right. It runs your build command, so "
"only point it at a command you trust."
)
def _read_bytes(path):
with open(path, "rb") as fh:
return fh.read()
def _diff_summary(want, got):
"""A short, deterministic description of a byte difference. No external diff."""
if want == got:
return "identical"
if len(want) != len(got):
lead = "committed" if len(want) > len(got) else "fresh-build"
return f"length differs: committed={len(want)}B fresh={len(got)}B (longer: {lead})"
for i, (a, b) in enumerate(zip(want, got)):
if a != b:
return f"first byte differs at offset {i}: committed=0x{a:02x} fresh=0x{b:02x}"
return "differ" # unreachable given the length/zip checks above
def check(build_cmd, derived, copies, use_stdout=False, in_place=False,
repo_root=None):
"""Run the build fresh in a sandbox and compare to the committed derived file.
Returns a result dict with a 'status' of current | stale | build-failed | usage.
Never mutates the working tree.
"""
root = repo_root or os.getcwd()
result = {
"build_cmd": build_cmd,
"derived": derived,
"status": "current",
"diff": "identical",
"edge": EDGE,
}
committed_path = os.path.join(root, derived)
if not os.path.isfile(committed_path):
result["status"] = "usage"
result["error"] = f"derived file not found: {derived}"
return result
committed = _read_bytes(committed_path)
sandbox = tempfile.mkdtemp(prefix="derived-check.")
try:
if in_place:
# Copy the whole working tree so an in-place build can't touch the real one.
for entry in os.listdir(root):
if entry == ".git":
continue # never needed to rebuild a derived file; huge
src = os.path.join(root, entry)
dst = os.path.join(sandbox, entry)
if os.path.isdir(src):
shutil.copytree(src, dst, symlinks=True)
else:
shutil.copy2(src, dst)
else:
for rel in copies:
src = os.path.join(root, rel)
if not os.path.exists(src):
result["status"] = "usage"
result["error"] = f"--copy input not found: {rel}"
return result
dst = os.path.join(sandbox, rel)
os.makedirs(os.path.dirname(dst) or sandbox, exist_ok=True)
if os.path.isdir(src):
shutil.copytree(src, dst, symlinks=True)
else:
shutil.copy2(src, dst)
proc = subprocess.run(
build_cmd, shell=True, cwd=sandbox,
capture_output=True, timeout=300,
)
if proc.returncode != 0:
result["status"] = "build-failed"
result["exit"] = proc.returncode
result["stderr"] = proc.stderr.decode("utf-8", "replace")[:2000]
return result
if use_stdout:
fresh = proc.stdout
else:
fresh_path = os.path.join(sandbox, derived)
if not os.path.isfile(fresh_path):
result["status"] = "build-failed"
result["error"] = (
f"build ran but produced no {derived} in the sandbox "
f"(did you mean --stdout, or a different --derived path?)"
)
return result
fresh = _read_bytes(fresh_path)
if fresh == committed:
result["status"] = "current"
result["diff"] = "identical"
else:
result["status"] = "stale"
result["diff"] = _diff_summary(committed, fresh)
result["_fresh"] = fresh
result["_committed"] = committed
return result
finally:
shutil.rmtree(sandbox, ignore_errors=True)
def main(argv=None):
ap = argparse.ArgumentParser(
description="Is a generated file stale against the command that makes it?",
epilog="EDGE: " + EDGE,
)
ap.add_argument("--build-cmd", required=True,
help="the command that regenerates the derived file (run in a sandbox)")
ap.add_argument("--derived", required=True,
help="repo-relative path of the file the command is supposed to produce")
ap.add_argument("--copy", action="append", default=[], metavar="PATH",
help="input file/dir the build needs; repeatable (ignored with --in-place)")
ap.add_argument("--stdout", action="store_true",
help="the build writes the derived content to stdout; capture and compare it")
ap.add_argument("--in-place", action="store_true",
help="the build edits files in place; run it against a full copy of the tree")
ap.add_argument("--show-diff", action="store_true",
help="on STALE, dump both versions' first differing region")
ap.add_argument("--json", action="store_true", help="machine-readable verdict")
ap.add_argument("--edge", action="store_true", help="print the printed edge and exit")
args = ap.parse_args(argv)
if args.edge:
print(EDGE)
return EXIT_CURRENT
res = check(
args.build_cmd, args.derived, args.copy,
use_stdout=args.stdout, in_place=args.in_place,
)
status = res["status"]
# strip internal blobs before any user-facing emission
fresh = res.pop("_fresh", None)
committed = res.pop("_committed", None)
if args.json:
print(json.dumps(res, indent=2, sort_keys=True))
else:
if status == "current":
print(f"CURRENT — {args.derived} matches a fresh build")
elif status == "stale":
print(f"STALE — {args.derived} is behind its build command")
print(f" {res['diff']}")
print(f" regenerate with: {args.build_cmd}")
if args.show_diff and fresh is not None:
print(" --- committed (first 400B) ---")
sys.stdout.buffer.write(committed[:400])
print("\n --- fresh build (first 400B) ---")
sys.stdout.buffer.write(fresh[:400])
print()
elif status == "build-failed":
print(f"BUILD-FAILED — {res.get('error') or 'the build command exited non-zero'}")
if res.get("stderr"):
print(res["stderr"])
else: # usage
print(f"USAGE ERROR — {res.get('error', 'bad arguments')}", file=sys.stderr)
return {
"current": EXIT_CURRENT,
"stale": EXIT_STALE,
"build-failed": EXIT_BUILD_FAILED,
"usage": EXIT_USAGE,
}[status]
if __name__ == "__main__":
sys.exit(main())
test_derived.py207 lineson GitHub →
#!/usr/bin/env python3
"""test_derived.py — mutation-bitten behavior proof for the derived gift.
stdlib only. Each test asserts a distinct BEHAVIOR, so deleting the behavior
from derived.py makes a test fail (that is the "mutation bite"). Run:
python3 test_derived.py # prints N/N and exits 0 on all-green
"""
import os
import shutil
import subprocess
import sys
import tempfile
HERE = os.path.dirname(os.path.abspath(__file__))
GIFT = os.path.join(HERE, "derived.py")
CURRENT, USAGE, STALE, BUILD_FAILED = 0, 2, 3, 4
def _scratch():
d = tempfile.mkdtemp(prefix="derived-test.")
return d
def _run(cwd, *args):
"""Run the gift with cwd set so repo-relative paths resolve there."""
p = subprocess.run(
[sys.executable, GIFT, *args],
cwd=cwd, capture_output=True, text=True, timeout=120,
)
return p.returncode, p.stdout, p.stderr
# A build command that writes "1\n2\n3\n" to out.txt, deterministically.
GEN = 'python3 -c "open(\'out.txt\',\'w\').write(\'1\\n2\\n3\\n\')"'
results = []
def check(name, cond):
results.append((name, bool(cond)))
print(f" [{'PASS' if cond else 'FAIL'}] {name}")
def t_current_when_committed_matches_fresh_build():
"""A committed file equal to a fresh build reads CURRENT (exit 0)."""
d = _scratch()
try:
with open(os.path.join(d, "out.txt"), "w") as f:
f.write("1\n2\n3\n") # matches GEN
rc, out, _ = _run(d, "--build-cmd", GEN, "--derived", "out.txt")
check("current when committed == fresh build", rc == CURRENT and "CURRENT" in out)
finally:
shutil.rmtree(d, ignore_errors=True)
def t_stale_when_committed_differs():
"""A committed file that differs from the fresh build reads STALE (exit 3)."""
d = _scratch()
try:
with open(os.path.join(d, "out.txt"), "w") as f:
f.write("1\n2\n") # stale: build emits three lines
rc, out, _ = _run(d, "--build-cmd", GEN, "--derived", "out.txt")
check("stale when committed != fresh build", rc == STALE and "STALE" in out)
finally:
shutil.rmtree(d, ignore_errors=True)
def t_non_mutating_leaves_committed_file_untouched():
"""Running the check never edits the working tree's committed file."""
d = _scratch()
try:
stale_content = "1\n2\n"
with open(os.path.join(d, "out.txt"), "w") as f:
f.write(stale_content)
_run(d, "--build-cmd", GEN, "--derived", "out.txt")
after = open(os.path.join(d, "out.txt")).read()
check("non-mutating: committed file unchanged after a check", after == stale_content)
finally:
shutil.rmtree(d, ignore_errors=True)
def t_build_failed_when_command_errors():
"""A build command that exits non-zero yields BUILD-FAILED (exit 4), never a verdict."""
d = _scratch()
try:
with open(os.path.join(d, "out.txt"), "w") as f:
f.write("anything\n")
rc, out, _ = _run(d, "--build-cmd", "python3 -c \"import sys; sys.exit(1)\"",
"--derived", "out.txt")
check("build-failed on non-zero build command", rc == BUILD_FAILED and "BUILD-FAILED" in out)
finally:
shutil.rmtree(d, ignore_errors=True)
def t_usage_when_derived_missing():
"""A missing derived file is a usage error (exit 2), not STALE/CURRENT."""
d = _scratch()
try:
rc, out, err = _run(d, "--build-cmd", GEN, "--derived", "nope.txt")
check("usage error when derived file is absent", rc == USAGE and "USAGE" in (out + err))
finally:
shutil.rmtree(d, ignore_errors=True)
def t_stdout_mode_compares_captured_output():
"""--stdout compares the build's stdout, not a file on disk."""
d = _scratch()
try:
with open(os.path.join(d, "cur.txt"), "w") as f:
f.write("hello\n")
rc, out, _ = _run(d, "--build-cmd", 'python3 -c "print(\'hello\')"',
"--derived", "cur.txt", "--stdout")
check("--stdout compares captured stdout", rc == CURRENT and "CURRENT" in out)
finally:
shutil.rmtree(d, ignore_errors=True)
def t_stdout_mode_detects_stale():
"""--stdout still detects a mismatch as STALE."""
d = _scratch()
try:
with open(os.path.join(d, "cur.txt"), "w") as f:
f.write("goodbye\n")
rc, out, _ = _run(d, "--build-cmd", 'python3 -c "print(\'hello\')"',
"--derived", "cur.txt", "--stdout")
check("--stdout detects stale", rc == STALE and "STALE" in out)
finally:
shutil.rmtree(d, ignore_errors=True)
def t_deterministic_same_verdict_across_runs():
"""The same inputs yield the same verdict every run (byte-oracle determinism)."""
d = _scratch()
try:
with open(os.path.join(d, "out.txt"), "w") as f:
f.write("1\n2\n3\n")
verdicts = set()
for _ in range(3):
rc, _, _ = _run(d, "--build-cmd", GEN, "--derived", "out.txt")
verdicts.add(rc)
check("deterministic: identical verdict across 3 runs", verdicts == {CURRENT})
finally:
shutil.rmtree(d, ignore_errors=True)
def t_json_mode_emits_status():
"""--json emits a parseable object carrying the status."""
d = _scratch()
try:
import json as _json
with open(os.path.join(d, "out.txt"), "w") as f:
f.write("1\n2\n3\n")
rc, out, _ = _run(d, "--build-cmd", GEN, "--derived", "out.txt", "--json")
obj = _json.loads(out)
check("--json emits status object", obj.get("status") == "current")
finally:
shutil.rmtree(d, ignore_errors=True)
def t_edge_is_present_and_printed():
"""The printed edge exists in the artifact and prints on demand."""
d = _scratch()
src = open(GIFT).read()
rc, out, _ = _run(d, "--edge", "--build-cmd", "x", "--derived", "y")
check("printed edge present in source AND on --edge",
"STALENESS" in src and "not CORRECTNESS" in src and "STALENESS" in out)
def t_diff_summary_names_the_difference():
"""On STALE, the output names WHERE/HOW it differs (not just 'differ')."""
d = _scratch()
try:
with open(os.path.join(d, "out.txt"), "w") as f:
f.write("1\n2\n") # shorter than fresh
rc, out, _ = _run(d, "--build-cmd", GEN, "--derived", "out.txt")
check("stale output names the difference (length/offset)",
rc == STALE and ("length differs" in out or "offset" in out))
finally:
shutil.rmtree(d, ignore_errors=True)
def main():
print("test_derived.py")
for fn in [
t_current_when_committed_matches_fresh_build,
t_stale_when_committed_differs,
t_non_mutating_leaves_committed_file_untouched,
t_build_failed_when_command_errors,
t_usage_when_derived_missing,
t_stdout_mode_compares_captured_output,
t_stdout_mode_detects_stale,
t_deterministic_same_verdict_across_runs,
t_json_mode_emits_status,
t_edge_is_present_and_printed,
t_diff_summary_names_the_difference,
]:
fn()
passed = sum(1 for _, ok in results if ok)
total = len(results)
print(f"\n{passed}/{total} passing")
return 0 if passed == total else 1
if __name__ == "__main__":
sys.exit(main())