Skip to content

docs(gap-baseline): measure PR job fan-out, disprove the workflow-waste hypothesis - #1905

Open
seonghobae wants to merge 3 commits into
docs/gap-baseline-item4-cleanfrom
docs/gap-baseline-pr-job-fanout-analysis
Open

docs(gap-baseline): measure PR job fan-out, disprove the workflow-waste hypothesis#1905
seonghobae wants to merge 3 commits into
docs/gap-baseline-item4-cleanfrom
docs/gap-baseline-pr-job-fanout-analysis

Conversation

@seonghobae

Copy link
Copy Markdown
Contributor

Summary

Stacked on #1903 (same file, avoids a guaranteed append-conflict).

The standing directive has repeatedly asked to find workflows that trigger unnecessarily, on the hypothesis that gratuitous triggering inside .github is what fills the org's Actions concurrency ceiling. I measured it directly. The hypothesis does not hold — and the negative result is worth recording so no future session re-runs this search.

Method: static analysis of all 35 workflows — resolve on: blocks, expand statically-enumerable matrices (each combination takes its own runner slot), and evaluate every job's if: with a three-valued true/false/unknown evaluator that counts a job as running unless provably false, so it never under-reports. The evaluator was validated against 7 real conditions from noema-review.yml, opencode-review.yml, strix.yml, and repository-metadata-reconcile.yml before its output was trusted.

Result: one PR synchronize dispatches 33 job slots (a naive count says 36; three jobs are provably skipped for a synchronize event).

Every candidate reduction checked and rejected on evidence:

  • 12 of the 33 slots are required status-check contexts (verified against live branch protection) — filtering or renaming any strands it Pending forever.
  • Push duplication disproven: all 12 push triggers already restrict to main/master/develop, so no push workflow fires on a PR branch.
  • Path filters already applied everywhere legal — all five small quality-CI workflows plus cloudflare-dns.yml.
  • paths-ignore on sast-semgrep.yml/python-security.yml — the one apparent remaining lever — is explicitly forbidden by tests/test_docs_only_pr_runner_admission.py, because ruleset 18156473 discards on: filters in target repos and .github's classic branch protection would strand a filtered required context.
  • The changed-scope/admit-current-head gate jobs are documented, contract-tested deliberate design, not waste.

What actually explains the queue: 76 repositories × ruleset-injected central workflows (with on: filters discarded in target repos) × open PRs, against one shared ceiling. Observed the same day: in_progress 0–1 for 3+ hours while queued climbed 372 → 424, with githubstatus.com reporting all systems operational — the shape of a capacity ceiling, not of workflow waste.

Consequence: further .github YAML optimisation is not a productive lever. The open question is org-level Actions capacity, readable only with an admin:org credential no agent session holds (gh api orgs/.../rulesets/18156473 returns a scope error). That is an owner action.

Documentation only — no code or workflow changes.

Test plan

  • pytest tests/test_product_technical_gap_baseline.py — 5 passed
  • Single-file, doc-only diff

🤖 Generated with Claude Code

…te hypothesis

Static analysis of all 35 workflows (matrix expansion + three-valued if:
evaluation, evaluator checked against 7 real conditions first): one PR
synchronize dispatches 33 job slots, not the 36 a naive count reports.

Every candidate reduction was checked and rejected on evidence: 12 slots are
required status-check contexts (live branch protection), all 12 push triggers
are already restricted to main/master/develop so no PR-branch duplication
exists, every small quality-CI workflow already carries paths filters, and
adding paths-ignore to sast-semgrep/python-security is explicitly forbidden by
tests/test_docs_only_pr_runner_admission.py. The changed-scope gate jobs are
documented deliberate design, not waste.

Conclusion: queue depth is 76-repo ruleset fan-out (where on: filters are
discarded) against a shared concurrency ceiling -- observed in_progress 0-1 for
3+ hours while queued climbed 372->424 with GitHub reporting all systems
operational. Further .github YAML optimisation is not a productive lever; the
open question is org-level Actions capacity, readable only with admin:org.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: ae25f02f-27cc-4fdd-87bb-42f9df2d1829

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…odex-found exception

An independent Codex audit, run against the same repo under the same
constraints but without knowledge of the first pass's conclusion, found one
genuine redundant slot the first pass missed: opencode-review.yml's
coverage-source-tree is a full runner slot whose whole body is one echo, and
which exists only to carry needs/if: into the required coverage-evidence
context (itself another echo-only job).

Recorded, not shipped: it is 1 slot of 33 (3%) in a queue measured 424 deep
against near-zero execution, and collapsing it edits the job graph of a
required review workflow the ruleset injects into 76 repositories. The
capacity-bound conclusion is unchanged.

The first pass classified both jobs as load-bearing gate jobs by pattern-
matching the documented changed-scope design without opening them to confirm
they do any work -- kept as a method note, since two agents re-reading one
agent's evidence is not corroboration.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… dimension

This entry counted runner slots and concluded reclaiming 1 of 33 could not
matter in a capacity-bound queue. Wrong. The two echo-only jobs sit in series
on the review critical path, and a job is not created until its needs:
complete, so each link waits out the whole queue again. Measured on
naruon#1528: 9h40m and 13h01m of queue wait for 4s and 5s of runtime, ~22h41m
total holding the real review behind it, on every PR across 76 repositories.

Slot count made that look like 3%; critical-path latency is the dimension that
governs how long a PR actually takes to clear. Fix shipped as #1910 (serial
depth 5 -> 3, queue waits 4 -> 2).

Also records the two non-obvious safety conditions: coverage-evidence had no
if: of its own and relied on transitive skipping, and opencode-review-dispatch
.yml has same-named jobs whose edge is a real artifact dependency -- job names
are unique only within a workflow file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@seonghobae

Copy link
Copy Markdown
Contributor Author

[P2] 확인된 낭비와 모순되는 최종 감사 결론을 수정해 주세요

검토 HEAD는 f7f480a820b1a8278eb4537943b0fcf830b9e97c입니다. docs/product-technical-gap-baseline.md의 이 PR 추가 절은 두 번의 정정 뒤에도 첫머리의 “No recoverable waste was found”와 마지막 “Optimising .github's workflow YAML further is not a productive lever”, “measured floor ... 33”을 유지합니다. 이 문구는 다음 작업자가 아직 필요한 구조 감사를 중단하게 만듭니다.

직접 확인한 반례는 다음과 같습니다.

  • 본문이 인용한 #1910은 실제로 2026-09-05T08:44:26Zc4a89b31a02caa1f1a5be1c36d54252cb8e57f8b로 병합됐습니다. 보호 context를 없애지 않고 echo-only 직렬 의존성을 줄일 수 있었으므로, YAML 변경의 실효성이 없다는 결론과 양립하지 않습니다. 이 조회는 병합 사실 확인이며 후속 실행 성능이나 정상 보호 병합 절차까지 입증하지 않습니다.
  • #1899는 서로 다른 main SHA의 Strix 실행 33928897846, 33932271770, 3393353033408:28:26–08:45:01 UTC에 겹친 실제 job 근거와, 첫 branch-push를 run-ID로 분리하던 식의 수정 전/후 검증을 갖고 있습니다. PR feature-branch의 push 중복이 없다는 결과는 이런 main 연속 push 누적이나 구형 run 재실행의 최신 검증 취소를 반증하지 않습니다. #1899는 아직 미병합이므로 적체 해소 완료로 계산하지 않습니다.
  • unknown 조건을 실행으로 세는 정적 합계는 해당 분석 범위의 보수적 상한 추정입니다. 실제 runner 동시 점유 수나 줄일 수 없는 하한이 아닙니다. 한 synchronize의 정적 job 개수만으로 재실행·지연 도착·dispatch 경쟁·직렬 큐 대기까지 소진했다고 말할 수 없습니다.

최소 수정은 기존 관측표를 유지하면서 제목·첫 문단·마지막 결론을 “관측한 trigger 범위와 남은 구조 감사”로 좁히는 것입니다. runner 용량 확인과 workflow 낭비 제거는 병행할 수 있습니다. 정적 분석기와 실행 명령이 PR에 없으므로 33이라는 수치는 재현 가능한 산출물을 연결하기 전에는 독립 검증된 하한으로 쓰지 말아 주세요. 현재 #1899의 tests/test_review_rerun_concurrency.py 등 실제 YAML 식 회귀와 #1910의 의존성 변경을 함께 대조해야 합니다.

이는 사용자 요청을 더 작은 목표로 바꾸지 않기 위한 문서 정확성 finding입니다. org 설정·보안 gate 변경이나 추가 모델 timeout을 요청하지 않습니다.

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

OpenCode could not approve from deterministic current-head evidence because GitHub Checks have failed.

Findings

1. HIGH Current-head GitHub Checks - Fix failed required checks before approval

  • Problem: Failed same-head checks remain for f7f480a820b1a8278eb4537943b0fcf830b9e97c.
  • Root cause: The model-unavailable evidence fallback is allowed only when peer GitHub Checks are complete and clean.
  • Fix: Read and fix the failed check logs below, then rerun the current-head checks.
  • Regression test: Keep the model-unavailable fallback gated on an empty failed-check rollup.

Failed checks:

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Docs: product-technical-gap-baseline.md"]
  S1 --> I1["operator or user guidance"]
  I1 --> R1["Review risk: Docs: product-technical-gap-baseline.md"]
  R1 --> V1["docs review"]
Loading

@opencode-agent

opencode-agent Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

OpenCode Review Overview

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant