Files
felhom.eu/documentation/audits/the-28-2026-09-22/assemble.py
T
admin 186546d562
gates / gates (push) Successful in 27s
THE TWENTY-EIGHT: every app no drill had touched, walked in one night
All 28 walked on scratch guest 9202 against the private drill catalog. 26 deployed, 6 proven,
5 inconclusive, 14 with no upstream edge, 1 failed honestly (outline 1.9.1->1.10.1, HELD with the
right sentence), 2 undeployable - one (plant-it) by design, refused by the lifecycle gate, proven
live for the first time. Each app also got the half the update night skipped: a restore from its own
copy with the seed read back again - 21 restored, 2 correctly REFUSED per 07 6.2.

R-630 RAISED TO P1 by measurement: a stack with NO probe container does not skip verifying - it
waits out the full health timeout and HOLDS, stopping an app whose three containers read healthy.
The controller's own words: "not healthy within 5m0s (last: no probe container)".

R-633 opened: a remove sent during a restore reports success and leaves a container restarting with
a live public route. The product already refuses that clash for update and for restore, naming the
blocker; remove has no such guard.

R-634 opened: an app can be running, healthy and serving while recorded as deployed=false, and is
then unremovable. Reproducible alone on sparkyfitness; concurrency-linked on two others.

R-631 and R-632 CLOSED. Register 321 -> 323. Seven interventions, six of them my own harness -
named, with what each cost. No product code. The live catalog's image: lines are byte-identical to
the start of the night.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-22 16:00:56 +02:00

47 lines
2.5 KiB
Python

#!/usr/bin/env python3
"""Assemble DRILL-the-28-2026-09-22.md from the parts + the generated table."""
import io, json, glob, os
HERE = os.path.dirname(os.path.abspath(__file__))
A = os.path.dirname(HERE)
recs = {}
for f in glob.glob(os.path.join(HERE, "apps", "*", "verdict.json")):
d = json.load(open(f, encoding="utf-8")); recs[d["app"]] = d
walked = [d for d in recs.values() if d["deployed"]]
proven = [d for d in recs.values() if d["verdict"] == "proven"]
failed = [d for d in recs.values() if d["verdict"] == "failed"]
seeded = [d for d in recs.values() if d["seed_read_before"]]
restored = [d for d in recs.values() if d["restore_verdict"] == "ok"]
refused = [d for d in recs.values() if d["restore_verdict"] == "refused-with-a-sentence"]
dirty = [d for d in recs.values() if d["deployed"] and not d.get("removed_clean")]
parts = [io.open(os.path.join(A, "DRILL-the-28-2026-09-22-HEAD.md"), encoding="utf-8").read()]
body1 = io.open(os.path.join(HERE, "BODY-part1.md"), encoding="utf-8").read()
body1 = (body1.replace("_N_", str(len(walked)))
.replace("_INTERVENTIONS_", os.environ.get("INTERVENTIONS", "see below"))
.replace("_HEADLINE_", os.environ.get("HEADLINE", "see below")))
parts.append(body1)
tbl = io.open(os.path.join(HERE, "TABLE.md"), encoding="utf-8").read()
parts.append("---\n\n## The table — all twenty-eight\n\n"
"Classes are `07-backup-architecture.md` §6.2's, not re-derived.\n\n" + tbl + "\n"
+ "**Read across the walk rather than down one column:** "
f"**{len(walked)} of 28 deployed**, "
f"**{len(seeded)}** had a non-browser route that seeded AND read back, "
f"**{len(restored)}** restored from their own copy, "
f"**{len(refused)}** were correctly REFUSED a restore, "
f"**{len(proven)} proven / {len(failed)} failed** on the apps that had an upstream "
f"edge, and **{len(dirty)}** left a container behind (R-633).\n")
for f in ("BODY-sidejobs.md", "BODY-r630.md", "BODY-promotion.md", "BODY-teardown.md"):
p = os.path.join(HERE, f)
if os.path.exists(p):
parts.append(io.open(p, encoding="utf-8").read())
out = "\n".join(parts)
io.open(os.path.join(A, "DRILL-the-28-2026-09-22.md"), "w", encoding="utf-8").write(out)
print("assembled", len(out), "bytes ·", len(walked), "walked ·", len(proven), "proven ·",
len(seeded), "seeded ·", len(restored), "restored ·", len(refused), "refused ·",
len(dirty), "dirty")