186546d562
gates / gates (push) Successful in 27s
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
48 lines
2.5 KiB
Python
48 lines
2.5 KiB
Python
#!/usr/bin/env python3
|
|
"""The SECOND promotion list, for the operator. CC promotes nothing.
|
|
|
|
A move is proposed only when the walk PROVED it: the update reached `done`, and the data the app
|
|
was given came back through the app's own interface afterwards. An edge that ended `done` with no
|
|
seed route is NOT proposed — `done` alone says the containers changed, not that the household's
|
|
data survived.
|
|
"""
|
|
import glob, io, json, os
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
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
|
|
|
|
move, hold, noedge = [], [], []
|
|
for a, d in sorted(recs.items()):
|
|
e = d.get("edge")
|
|
if not e:
|
|
noedge.append(a); continue
|
|
fr, to = e["from"].rsplit(":", 1)[1], e["to"].rsplit(":", 1)[1]
|
|
if d["verdict"] == "proven" and d["seed_read_after_update"]:
|
|
move.append((a, fr, to, d.get("duration_s"), d.get("migration_observed")))
|
|
elif d.get("update_phase_final") == "done":
|
|
hold.append((a, fr, to, "the update reached `done`, but this app has no non-browser data "
|
|
"route, so nothing proves the household's data survived it"))
|
|
else:
|
|
hold.append((a, fr, to, f"the update ended `{d.get('update_phase_final')}` — "
|
|
+ ("; ".join(d["notes"]) or "see the record")))
|
|
|
|
out = ["## The second promotion list — for the operator, not for me\n",
|
|
"**CC promotes nothing.** These are proposals with the evidence beside them.\n",
|
|
f"### Proposed to move ({len(move)})\n",
|
|
"| app | move | update took | its own migration line |", "|---|---|---|---|"]
|
|
for a, fr, to, s, mig in move:
|
|
out.append("| `%s` | `%s` → `%s` | %s s | %s |" % (
|
|
a, fr, to, s,
|
|
# a literal `|` inside a cell ends it — the migration lines carry them
|
|
("yes — `" + mig[:90].replace("|", "\\|").replace("`", "'") + "`") if mig
|
|
else "none printed"))
|
|
out += [f"\n### Must NOT move, with why ({len(hold)})\n", "| app | edge | why not |", "|---|---|---|"]
|
|
for a, fr, to, why in hold:
|
|
out.append("| `%s` | `%s` → `%s` | %s |" % (a, fr, to, why))
|
|
out.append(f"\n**No upstream edge tonight, so nothing to propose ({len(noedge)}):** "
|
|
+ ", ".join("`%s`" % a for a in noedge) + ".\n")
|
|
io.open(os.path.join(HERE, "BODY-promotion.md"), "w", encoding="utf-8").write("\n".join(out) + "\n")
|
|
print("\n".join(out[:8]))
|
|
print("...", len(move), "proposed,", len(hold), "held,", len(noedge), "no edge")
|