0030cbd1de
gates / gates (push) Successful in 26s
The records the catalog's ladder entries cite (apps/<app>/bench and apps/<app>/verdict.json), the drill tools, the spike, R-626's run, R-612/R-613 red-proofs, the chaos schedule (seed 20260923) drawn BEFORE round 1. Docs and register follow at the end of the night. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
61 lines
2.8 KiB
Python
61 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
|
"""chaos_schedule.py — Part D's twelve rounds, drawn ONCE from seed 20260923 and committed before round 1.
|
|
|
|
python3 chaos_schedule.py # prints the table the findings doc carries
|
|
|
|
Each round is ACTION x ACCIDENT, the accident landing DELAY seconds into the action.
|
|
|
|
actions : good_update · fail_health (wrong probe -> the undo) · cutoff (the undo's copy loses its
|
|
finished-marker -> an honest HOLD) · install · remove · restore
|
|
accidents : none · power_cut (pct stop/start) · controller_kill (kill -9, max 3, >= 20 min apart)
|
|
· docker_restart · disk_fill (to 1 GB above the update floor) · memory_hog (1 GB, 5 min)
|
|
· box_backup (the whole-box backup, on 9202 only) · two_updates (a second Update pressed
|
|
at the same moment)
|
|
|
|
The draw is constrained, and the constraints are the brief's, not tuning: rounds 1 and 12 are `none`;
|
|
every action appears twice; every accident appears at least once; `controller_kill` at most three
|
|
times and never in consecutive-or-adjacent rounds (a round lasts ~6-8 min, so two rounds between
|
|
kills keeps them >= 20 min apart). A draw that breaks a constraint is redrawn from the SAME generator,
|
|
so the schedule is a pure function of the seed.
|
|
|
|
WHICH APP a round acts on is NOT drawn: it is fixed by rule in chaos.py (the action decides the app
|
|
class) and printed beside the schedule, because an app's state after round N decides what round N+1
|
|
can do to it.
|
|
"""
|
|
import random
|
|
|
|
SEED = 20260923
|
|
ACTIONS = ["good_update", "fail_health", "cutoff", "install", "remove", "restore"]
|
|
ACCIDENTS = ["power_cut", "controller_kill", "docker_restart", "disk_fill", "memory_hog",
|
|
"box_backup", "two_updates"]
|
|
|
|
|
|
def draw():
|
|
rng = random.Random(SEED)
|
|
tries = 0
|
|
while True:
|
|
tries += 1
|
|
acts = ACTIONS * 2
|
|
rng.shuffle(acts)
|
|
mid = ACCIDENTS + [rng.choice(ACCIDENTS) for _ in range(3)]
|
|
rng.shuffle(mid)
|
|
accs = ["none"] + mid + ["none"]
|
|
kills = [i for i, a in enumerate(accs) if a == "controller_kill"]
|
|
if len(kills) > 3 or any(b - a < 3 for a, b in zip(kills, kills[1:])):
|
|
continue
|
|
# an install/remove round cannot also be `two_updates` (there is no second update to race)
|
|
if any(a in ("install", "remove") and c == "two_updates" for a, c in zip(acts, accs)):
|
|
continue
|
|
delays = [rng.randint(10, 60) for _ in range(12)]
|
|
return [{"round": i + 1, "action": acts[i], "accident": accs[i], "delay_s": delays[i]}
|
|
for i in range(12)], tries
|
|
|
|
|
|
if __name__ == "__main__":
|
|
rounds, tries = draw()
|
|
print(f"seed {SEED}, drawn in {tries} attempt(s)\n")
|
|
print("| round | action | accident | at +s |")
|
|
print("|---|---|---|---|")
|
|
for r in rounds:
|
|
print(f"| {r['round']} | {r['action']} | {r['accident']} | {r['delay_s']} |")
|