steps/<key>.felhom.yml: gate rule 4b, writer, backfill (8) (R-664)
gates / gates (push) Successful in 2s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-09-24 11:45:34 +02:00
parent 635c7e68f7
commit cf7cf8456f
15 changed files with 1321 additions and 2 deletions
+9
View File
@@ -22,6 +22,8 @@ WHAT IT CHECKS, per template that carries `update_ladder:` (format and field rul
4. every entry but the newest carries its OWN definition at `steps/<step_key(to)>.yml`, whose
images per service are EXACTLY that entry's `to` (`09` §6.4 part 5: the box pins that file, one
step per press). The name alone is not the fact: the file's own `image:` lines are read.
4b. ... and its own `.felhom.yml` at `steps/<step_key(to)>.felhom.yml` (R-664), with a healthcheck
when the template has one.
A template WITHOUT a ladder passes here — it has never been moved since the gate existed, and its
first move is refused by the twin unless that move brings the first entry.
@@ -65,6 +67,13 @@ def check_app(app_dir):
got = ladder.images_in(open(sp, encoding="utf-8").read())
if got != to:
problems.append("%s names %s, but entry %d's `to` is %s" % (ladder.step_file(to), got, i + 1, to))
# rule 4b (R-664, 2026-09-24): the step's own .felhom.yml — the box judges the step with it.
smp = os.path.join(app_dir, ladder.step_meta_file(to))
if not os.path.isfile(smp):
problems.append("entry %d of %d has no %s — the box would judge the step with the head's probe (R-664)"
% (i + 1, len(entries), ladder.step_meta_file(to)))
elif "healthcheck:" not in open(smp, encoding="utf-8").read() and "healthcheck:" in open(os.path.join(app_dir, ".felhom.yml"), encoding="utf-8").read():
problems.append("%s carries no healthcheck: while the template does — not a real step file" % ladder.step_meta_file(to))
if entries:
current = ladder.images_in(open(comp, encoding="utf-8").read())
head = entries[-1].get("to")