docs(decisions): record what the CI gate actually reported, not the tick
gate / gate (pull_request) Successful in 1m39s
gate / conformance (pull_request) Has been skipped

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) <[email protected]>
This commit is contained in:
jakman85andClaude Opus 5 committed 2026-09-30 16:12:56 -05:00
1 parent a78f010368
commit 7df72db487
1 file changed
+56 -7
@@ -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.