From 7df72db4877da0c983609ef6330e6d9831efac34 Mon Sep 17 00:00:00 2001 From: Keith Jackson Date: Wed, 30 Sep 2026 16:12:56 -0500 Subject: [PATCH] docs(decisions): record what the CI gate actually reported, not the tick MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PR's required check went green as "Successful in 1m40s" — a real run, not "Has been skipped". But .gitea/workflows/gate.yml:138 is `./ci/gate.sh || [ "$?" -eq 3 ]`, so a green tick means exit 0 OR 3 and cannot distinguish them. Fetched the job log and read the gate's own headline: MERGE GATE: UNDETERMINED, one stage that did not run (spec-immutability). So CI is rc 3 too, and the tick is the tolerance swallowing it. Recorded that plainly rather than leaving "CI green" to be read as rc 0. Also corrects a claim that had gone stale within the same entry: CI ran two stages my worktree run could not, and both passed — gitea-settings (the live Gitea matches infra/gitea/expected-branch-protection.json; runners online 1) and approval-policy with real PR context (no sensitive paths touched, so infra/ansible/** needs no human reviewer). My local run skipped both, and the handoff said branch protection was UNVERIFIED. It is now measured, so saying otherwise would have left a known-false line in the log. Co-Authored-By: Claude Opus 5 (1M context) --- .../2026-09-30-node-health-render-device.md | 63 ++++++++++++++++--- 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/decisions/2026-09-30-node-health-render-device.md b/decisions/2026-09-30-node-health-render-device.md index c6d3cd9..d5438d9 100644 --- a/decisions/2026-09-30-node-health-render-device.md +++ b/decisions/2026-09-30-node-health-render-device.md @@ -163,6 +163,48 @@ know the shim took effect rather than the git stages silently degrading. `ci/` and `.gitea/` and the lint stage is `yamllint -c ci/yamllint.yaml` only. I am not claiming to have matched a lint convention that does not exist. +### The CI gate on the PR — a green tick that is exit 3, read from the log + +The required context `gate / gate (pull_request)` reported **`success`, "Successful in 1m40s"** +on commit `a78f010`. That description matters: a *skipped* Gitea job reports `success` with +"Has been skipped", so this one genuinely ran, and 1m40s matches CLAUDE.md §2's ~1m35s. + +**But the green tick does NOT mean `gate.sh` returned 0.** `.gitea/workflows/gate.yml:138` is +`run: ./ci/gate.sh || [ "$?" -eq 3 ]` — the job tolerates rc 3 by design. So I fetched the job +log (`/actions/runs/173/jobs/0/logs`; the `/api/v1/.../tasks/{id}/logs` endpoints 404 on this +Gitea, the web route serves it) and read the gate's own headline: + + [fail] MERGE GATE: UNDETERMINED — greenness was NOT ESTABLISHED. + [fail] Stages that did not run: spec-immutability + +**So CI is also rc 3, with exactly ONE stage skipped — `spec-immutability`.** The green Gitea +check is the tolerance swallowing that 3, not a rc 0. + +**CI verified two things my local run could not, and both came back green:** + + [ ok ] stage gitea-settings: pass + [ ok ] enable_push = false enable_status_check = true + [ ok ] required_approvals = 1 block_admin_merge_override = true + [ ok ] block_on_rejected_reviews = true dismiss_stale_approvals = true + [ ok ] runners online: 1 (>= 1) + [ ok ] Gitea settings match the declaration. + [ ok ] stage approval-policy: pass + [ ok ] no architecturally/security-relevant paths touched — the GATE is the approver. + +My local run **skipped** `gitea-settings` (no `SETTINGS_API_TOKEN`) and could not give +`approval-policy` a PR number. CI has the secret and `REQUIRE_GITEA_SETTINGS: "true"`, so a skip +there would have failed the job. That is measured confirmation that the live Gitea matches +`infra/gitea/expected-branch-protection.json`, and that `infra/ansible/**` needs no human +reviewer. `lint` passed over 405 files. `conformance` SKIPPED in CI too +(`CLUSTER_AVAILABLE != true`), so L2/L3 remains unverified there as well. + +Corroborated independently: `GET /repos/.../branches/main` → +`protected=true user_can_push=false enable_status_check=true required_approvals=1`, +contexts `["gate / gate (pull_request)"]`; `GET /admin/actions/runners` → `incluster-dind +status=online`. And note the commit's **combined** state is `pending`, not success, because +`gate / conformance (pull_request)` sits at "Blocked by required conditions" — that context is +not in the required list, so it does not block, but the PR is not "all green" either. + The gate's `lint` stage passed with one `line too long` **warning** on `roles/node_health/tasks/assess.yml:189` — that is pre-existing, in the SMART block, well above my insertion point, and warnings do not fail the stage. @@ -222,13 +264,20 @@ above my insertion point, and warnings do not fail the stage. device, and which driver owns it. They do **not** prove a transcode succeeds — that needs a VAAPI round trip inside Plex's own container with Plex's own libva, and is out of scope for a node-level check that installs nothing. -- **The gate did not establish greenness.** It returned **rc 3**, and three stages did not run - (`spec-immutability`, `gitea-settings`, `conformance`). So: the offline L0/L1 subset passed, - the live Gitea branch-protection rule is **UNVERIFIED** from this run, and L2/L3 conformance - did not execute. I am not describing this PR as green. -- **No claim about the live platform beyond what the run printed.** Per CLAUDE.md §2b this repo - is not evidence about prod; the only prod facts I assert are the ones quoted verbatim above. - I did not query Gitea's branch protection or runner state, so I assert nothing about either. +- **Greenness was never established, locally or in CI.** Both runs returned **rc 3**. My local + run skipped three stages (`spec-immutability`, `gitea-settings`, `conformance`); CI skipped + one (`spec-immutability`) and its own headline says `MERGE GATE: UNDETERMINED`. **I am not + describing this PR as green**, and the green Gitea tick must not be read as one: the workflow + line is `./ci/gate.sh || [ "$?" -eq 3 ]`, so it is a tolerated 3. +- **L2/L3 conformance did not run anywhere** — `CLUSTER_AVAILABLE != true` in both. Whatever + runtime requirements this touches remain UNVERIFIED; only the L0/L1 offline subset passed. +- **`spec-immutability` ran in neither.** The sibling spec repo is checked out in neither my + worktree nor the CI workspace, so nothing confirms this change does not drift from the spec. + It is the expected, tolerated skip — but it is still a skip, not a pass. +- **No claim about the live platform beyond what was printed.** Per CLAUDE.md §2b this repo is + not evidence about prod; the only prod facts I assert are the ones quoted verbatim above. + Branch protection and runner state I did query directly, and the CI `gitea-settings` stage + passed — so those two I assert on measurement, not on this file's prose. - **The stale dev inventory was left alone deliberately.** `hosts.ini` still defines the `k3s-dev-*` groups as the default target of most playbooks and the dev cluster no longer exists. That is real, it is out of this change's scope, and it is unclaimed work.