Files
troupe-standup/recoveries/helm-cli-entry-point.md
T
Merlin adfff7a39a Q30 DONE: the renderer's entry point runs, and it refuses production by default
- reproduced the defect first: python3 helm-render.py exits 1 with
  NameError: name 'build_page' is not defined (guard at :90-91 above
  def build_page at :232), same with --out, no file written
- moved the __main__ guard to the end of helm-render.py (:495 of 495);
  --out/--as-of semantics unchanged; fixed renderer 21,766 B sha256
  5c67473d89283c3d4434928dc96d45ff48a41d8f443ecc3c98e9236be8b597f9
- destination gate per the 09:21Z control-plane addendum: OUT_DEFAULT is
  production, so main() resolves the destination and refuses without
  --deploy (exit 2, message naming the path and flag); parse_args now
  returns (out, now, explicit_out, deploy)
- gate G7: the CLI executed in a subprocess, asserting emitted bytes
  (exit 0, file exists, bytes equal build_page()'s at the pinned clock,
  byte count matches, --as-of honoured, live root untouched); production
  destination refused by default and by explicit --out at the prod path
  (resolve(), not string equality); --deploy branch exercised against a
  patched OUT_DEFAULT; source-order guard so the defect cannot return
- gates re-run: 119 passed, 0 failed (102 before; G7 adds 17); the gate
  discriminates - the same command against the pre-fix file exits 1
- CONTRACT.md appended append-only: transcripts, digests, gate, and a
  revision note on :213-214 (deploy is now --deploy)
- nothing deployed: live page 9,865 B / 427b7b54c69b18d2... and snapshot
  aa842b0fd88037f8... unchanged before and after every run; --deploy
  alone never executed
2026-10-11 11:16:20 +00:00

122 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Q30 — the renderer's entry point: fixed, gated, and nothing deployed
*(Merlin, 2026-10-11 ≈09:50–11:20 UTC. Helm lane. All figures measured on this host;
nothing in this record is testimony from another runtime.)*
## The claim under test
`python3 /root/.helm/bin/helm-render.py` — the usage line in the module's own
docstring (`:6-7`), the reproduce block in `CONTRACT.md` (`:102`), and the §4
deploy sentence (`CONTRACT.md:213-214`) — had never executed. The
`if __name__ == "__main__":` guard sat at `:90-91`, above `def build_page` at
`:232`.
## 1. The defect, reproduced before the fix (measured 2026-10-11 ~09:50Z)
```
$ python3 /root/.helm/bin/helm-render.py
Traceback (most recent call last):
File "/root/.helm/bin/helm-render.py", line 91, in <module>
sys.exit(main(sys.argv))
File "/root/.helm/bin/helm-render.py", line 78, in main
html, report = build_page(now)
^^^^^^^^^^^^^^^
NameError: name 'build_page' is not defined
exit=1
$ python3 /root/.helm/bin/helm-render.py --out /tmp/helm-cli-probe.html --as-of 2026-10-11T12:00:00Z
…same NameError, same traceback…
exit=1
$ ls -la /tmp/helm-cli-probe.html
ls: cannot access '/tmp/helm-cli-probe.html': No such file or directory
```
Pre-fix file: 18,929 B, sha256
`00d14453d95234ef49a1d8758ab2de76143e848191331bfec38603e6263403e6`.
Production was never at risk from this failure — it lands before
`out.write_text` — and the live page stayed at `427b7b54…` throughout.
## 2. The fix (two parts)
1. **The guard moved to the end of the file** — `:495` of 495 lines, below
`build_page()` (`:273`). `--out` / `--as-of` semantics unchanged.
2. **The destination is gated** (the control plane's 2026-10-11 09:21Z
addendum). `OUT_DEFAULT` is the live document root, so `main()` resolves the
destination and refuses a production write without `--deploy`, returning
**2** with a message naming the path and the flag. `parse_args()` now
returns `(out, now, explicit_out, deploy)`.
| file | bytes | sha256 (measured 2026-10-11T11:14Z) |
|---|---|---|
| `/root/.helm/bin/helm-render.py` | 21,766 | `5c67473d89283c3d4434928dc96d45ff48a41d8f443ecc3c98e9236be8b597f9` |
| `/root/.helm/bin/helm-selftest.py` | 33,647 | `7ed1bca8f9da624f69b03313506097a0ce9b1130cbad9511908776e5015a0f46` |
| `/root/.helm/CONTRACT.md` | 17,657 | `2c527635ff96eb677e7419ef5b15516811e05cedfa1f072f84dcf67c10214f91` |
## 3. The CLI transcript, after the fix (exit codes from unpiped runs)
```
$ python3 /root/.helm/bin/helm-render.py --out /tmp/helm-cli-evidence.html --as-of 2026-10-11T12:00:00Z
rendered -> /tmp/helm-cli-evidence.html (11806 bytes)
render clock 2026-10-11T12:00:00+00:00 snapshot age 2d 18h 47m
verdict at render: 0 green / 6 not green (5 stale, 1 unreachable)
exit=0
$ sha256sum /tmp/helm-cli-evidence.html
8b839754b9e33911ec6d74834e4899a8f77f71c361eec98757d6ef08ad891839 /tmp/helm-cli-evidence.html
$ python3 /root/.helm/bin/helm-render.py
refused: this render would write the live document root (/var/www/alexander-whitestone/helm/index.html) and --deploy was not given.
staged render : --out /path/index.html
deploy : --deploy (an operator's call under §4; nothing here authorises it)
exit=2
$ python3 /root/.helm/bin/helm-render.py --out /var/www/alexander-whitestone/helm/index.html --as-of 2026-10-11T12:00:00Z
…same refusal (the destination is matched by resolve(), not string equality)…
exit=2
$ python3 /root/.helm/bin/helm-render.py --deploy --out /tmp/helm-cli-evidence2.html --as-of 2026-10-11T12:00:00Z
…renders the staged path…
exit=0
```
`--deploy` alone (which would write production) was **not executed**. It is
exercised inside gate G7 against a patched `OUT_DEFAULT`.
## 4. Gate G7 — the CLI, executed
`python3 /root/.helm/bin/helm-selftest.py` → `helm-selftest: 119 passed, 0
failed`, `VERDICT: ALL GATES PASS`. G7 adds **17** assertions (102 before):
- exit 0 on a staged render; the file exists; its bytes equal `build_page()`'s
at the same pinned clock; the reported byte count matches the file; `--as-of`
is honoured; the live document root is untouched.
- the default (production) destination is refused (exit ≠ 0), the refusal
names the path and `--deploy`, and nothing is written; an explicit
`--out <production path>` is refused too.
- the `--deploy` branch runs against a patched `OUT_DEFAULT` (a temp path),
never the real one.
- a source-order guard asserts the `__main__` guard sits below `def
build_page`, so the Q30 defect cannot silently return.
**The gate discriminates**: the exact G7 subprocess command, run against the
pre-fix file, exited 1 with `NameError` (transcript in §1); the same command
now exits 0 and emits 11,806 bytes.
## 5. Nothing deployed (measured before and after every run in this tick)
| target | state |
|---|---|
| `/var/www/alexander-whitestone/helm/index.html` | 9,865 B, sha256 `427b7b54c69b18d270288910fc810732463129f48ec4bdd7dbc75cdb22997ce4`, mtime `2026-10-11 08:57:14.017837233Z` (the 08:57:14 write is this lane's earlier byte-exact restore, not a deploy) |
| `/root/.helm/data/snapshot.json` | 14,039 B, sha256 `aa842b0fd88037f83115b4a54d617f27666f4de06ef84f9a64c8fd0a5f04656d`, mtime `2026-10-08T17:12:59.475780303Z` |
The collector was not re-run; no cron job was added; both remain Alexander's
call under §4.
## 6. Revision note on the deploy sentence (`CONTRACT.md:213-214`)
The sentence *"Deploying is `python3 /root/.helm/bin/helm-render.py` — one
command"* is true of every revision up to and including `00d14453d952…`. As of
`5c67473d89283c3d…` the bare command is refused with exit 2, and deploying is
`python3 /root/.helm/bin/helm-render.py --deploy` — still Alexander's call
under §4, now an explicit flag rather than the default behaviour of running
the script. The old text was not rewritten; the note is appended.