docs(592): record that a skipped CI context is not red #593

Merged
timothy merged 1 commits from chore/skipped-not-red into main 2026-07-25 12:07:12 +02:00
Owner

fixes #592

Docs-only. Amends ci.monitor-armed-at-pr-open in docs/decisions/workflow-process.md (prose + Signals: only — heading and key: unchanged, no supersession, [decisions-edit] in the commit).

Why

Landing #436/#583 today, my CI monitor enumerated per-context statuses and treated anything != "success" as red, so it announced "NOT all green" on two fully green PRs — because Build & push image (amd64) reports skipped. Nothing was blocked (Gitea's combined /status treats skipped as non-blocking and reported overall=success, and both merged cleanly), but the monitor is what an agent reads to decide whether to investigate, so a false red costs a diagnosis cycle each time.

Two corrections

  1. The image job is skipped on every PR — job-level if: github.event_name != 'pull_request'; images build only on push-to-main and tags. Not the docs-only mechanism. I initially misattributed it to #416's docs-only skip, which is a plausible-sounding wrong diagnosis: docs-only deliberately gates individual steps so required jobs still report success in seconds (ci.docs-only-skip-steps). decisions.md already records "build is skipped on every PR" from the branch-protection angle — the missing piece was the monitor-authoring consequence.
  2. skipped / failure / cancelled are three meanings, not one. Settled-not-applicable; a real red; no verdict. Prefer gating on the combined .state, which already gets this right.

The snippet was itself broken first — that's the point

My first draft documented select(.status != "success" and .status != "skipped") after the jq pipeline had renamed .status to .st. It compared against null, passed everything, and reported a fully green PR as nine failures. The committed version is verified in both directions:

  • silent on green PR #584 (which carries a skipped build) ✅
  • still reports the unfinished contexts on pending PR #589 — i.e. proven able to go dirty ✅

That two-way check is process.bom-format-detection-recipe's "verify your detector" rule, which exists because a detector that can only say "ok" is worse than none.

Review

Pure docs leaf, no server-state effect — process.independent-review-rubric permits a skip, but the record carries factual claims about CI wiring, so a bounded verification pass is running against the workflow file rather than taking my word for the job-level if.

Note

decisions_validate.py now warns aggregate active-corpus is 5606 lines (budget 5600) — schedule a consolidation. Non-blocking; flagged in #592 for its own pass.

fixes #592 Docs-only. Amends `ci.monitor-armed-at-pr-open` in `docs/decisions/workflow-process.md` (prose + `Signals:` only — heading and `key:` unchanged, no supersession, `[decisions-edit]` in the commit). ## Why Landing #436/#583 today, my CI monitor enumerated per-context statuses and treated anything `!= "success"` as red, so it announced "NOT all green" on two **fully green** PRs — because `Build & push image (amd64)` reports `skipped`. Nothing was blocked (Gitea's combined `/status` treats `skipped` as non-blocking and reported `overall=success`, and both merged cleanly), but the monitor is what an agent reads to decide whether to investigate, so a false red costs a diagnosis cycle each time. ## Two corrections 1. **The image job is skipped on *every* PR** — job-level `if: github.event_name != 'pull_request'`; images build only on push-to-main and tags. Not the docs-only mechanism. I initially misattributed it to #416's docs-only skip, which is a plausible-sounding wrong diagnosis: docs-only deliberately gates individual **steps** so required jobs still report `success` in seconds (`ci.docs-only-skip-steps`). `decisions.md` already records "`build` is `skipped` on every PR" from the branch-protection angle — the missing piece was the monitor-authoring consequence. 2. **`skipped` / `failure` / `cancelled` are three meanings, not one.** Settled-not-applicable; a real red; no verdict. Prefer gating on the combined `.state`, which already gets this right. ## The snippet was itself broken first — that's the point My first draft documented `select(.status != "success" and .status != "skipped")` **after** the jq pipeline had renamed `.status` to `.st`. It compared against `null`, passed everything, and reported a fully green PR as nine failures. The committed version is verified in both directions: - silent on green PR #584 (which carries a `skipped` build) ✅ - still reports the unfinished contexts on pending PR #589 — i.e. proven able to go dirty ✅ That two-way check is `process.bom-format-detection-recipe`'s "verify your detector" rule, which exists because a detector that can only say "ok" is worse than none. ## Review Pure docs leaf, no server-state effect — `process.independent-review-rubric` permits a skip, but the record carries factual claims about CI wiring, so a bounded verification pass is running against the workflow file rather than taking my word for the job-level `if`. ## Note `decisions_validate.py` now warns `aggregate active-corpus is 5606 lines (budget 5600) — schedule a consolidation`. Non-blocking; flagged in #592 for its own pass.
timothy added 1 commit 2026-07-25 11:54:02 +02:00
docs(592): record that a skipped CI context is not red [decisions-edit]
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 11s
PR Gates / Docs update reminder (pull_request) Successful in 12s
PR Gates / decisions lifecycle (pull_request) Successful in 25s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 40s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 23s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 20s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 21s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 13s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
2fee3f0b94
Amends ci.monitor-armed-at-pr-open (prose + Signals only; heading and key
unchanged, no supersession) with the monitor-classification rules that were
missing.

Landing #436/#583 today, my CI monitor filtered per-context statuses on
`!= "success"` and announced "NOT all green" on two fully green PRs, because
`Build & push image (amd64)` reports `skipped`. Nothing was blocked — Gitea's
combined /status already treats skipped as non-blocking and reported
overall=success — but a false red costs a diagnosis cycle every time.

Two corrections recorded:
- The image job is skipped on EVERY PR (job-level `if: github.event_name !=
  'pull_request'`; images build only on push-to-main and tags), NOT because of
  the docs-only mechanism. Misattributing it to docs-only is a plausible-sounding
  wrong diagnosis, since docs-only gates STEPS precisely so required jobs still
  report success. decisions.md already stated the fact from the branch-protection
  angle; the monitor-authoring consequence was missing.
- skipped / failure / cancelled are three distinct meanings and must not be
  collapsed. Prefer gating on the combined `.state`.

The documented filter is verified in BOTH directions: silent on a green PR
carrying a skipped build, and still dirty on a genuinely pending run. My first
draft of it was itself broken — `select(.status != …)` after the pipeline had
renamed `.status` to `.st`, so it compared against null and reported a green PR
as nine failures. That failure is recorded in the note, per the "verify your
detector" rule.

fixes #592
Author
Owner

Bounded independent fact-check (read-only, cheapest tier at bounded scope — proportionate to a pure-docs leaf per process.independent-review-rubric, but run rather than skipped because the record makes factual claims about CI wiring). Not a style pass; accuracy only.

All six claims verified TRUE, 4 files read:

  1. Build & push image (amd64) is gated at the JOB level — .gitea/workflows/docker-build.yml:518, if: github.event_name != 'pull_request' on the build job. Confirms it is skipped on every PR regardless of content.
  2. The docs-only mechanism gates STEPS (steps.detect.outputs.docs_only != 'true', lines 534/557/565/573); the job runs regardless — confirming the two mechanisms are genuinely different, which was the misdiagnosis this record exists to prevent.
  3. ci.docs-only-skip-steps exists, status: active, and contains the exact phrase "build is skipped on every PR" (docs/decisions.md:1699, key at :1677).
  4. No dangling key references — all four cross-referenced keys exist and are active: ci.cancelled-is-not-a-verdict, ci.killed-job-triage, ci.infra-shaped-red-under-load, process.bom-format-detection-recipe. This was the defect I most wanted caught.
  5. The amended record's key:/status:/since:/supersedes:/superseded-by: line is byte-identical to origin/main, and the ## heading is unchanged — so the decisions lifecycle job sees a prose edit, not an unlogged removal.
  6. The documented jq filter is syntactically valid and correct: on the synthetic payload [success, skipped, pending, failure] it emits only pending and failure.

No untrue claims, no syntax errors, no dangling references.

Review-verdict: MERGEABLE @ 2fee3f0b94

Bounded independent fact-check (read-only, cheapest tier at bounded scope — proportionate to a pure-docs leaf per `process.independent-review-rubric`, but run rather than skipped because the record makes factual claims about CI wiring). Not a style pass; accuracy only. All six claims verified TRUE, 4 files read: 1. `Build & push image (amd64)` is gated at the JOB level — `.gitea/workflows/docker-build.yml:518`, `if: github.event_name != 'pull_request'` on the `build` job. Confirms it is skipped on every PR regardless of content. 2. The docs-only mechanism gates STEPS (`steps.detect.outputs.docs_only != 'true'`, lines 534/557/565/573); the job runs regardless — confirming the two mechanisms are genuinely different, which was the misdiagnosis this record exists to prevent. 3. `ci.docs-only-skip-steps` exists, `status: active`, and contains the exact phrase "`build` is `skipped` on every PR" (`docs/decisions.md:1699`, key at :1677). 4. No dangling key references — all four cross-referenced keys exist and are active: `ci.cancelled-is-not-a-verdict`, `ci.killed-job-triage`, `ci.infra-shaped-red-under-load`, `process.bom-format-detection-recipe`. This was the defect I most wanted caught. 5. The amended record's `key:`/`status:`/`since:`/`supersedes:`/`superseded-by:` line is byte-identical to `origin/main`, and the `## ` heading is unchanged — so the `decisions lifecycle` job sees a prose edit, not an unlogged removal. 6. The documented jq filter is syntactically valid and correct: on the synthetic payload `[success, skipped, pending, failure]` it emits only `pending` and `failure`. No untrue claims, no syntax errors, no dangling references. Review-verdict: MERGEABLE @ 2fee3f0b9403cff23654aff99364623fbb3312f6
timothy merged commit b7d9e0ecb9 into main 2026-07-25 12:07:12 +02:00
timothy deleted branch chore/skipped-not-red 2026-07-25 12:07:44 +02:00
Sign in to join this conversation.