Repository navigation
measure(actions): 재측정 필요 — inherited required-workflow rules가 기존 게이팅 분류에서 누락됨 #1928
Description
2026-09-21 정정 — 게이팅 비율은 다시 측정해야 함
기존 본문의 61.3% / 71개 수치와 댓글에서 정정한 47.1% / 67개 수치는 모두 현재 권위로 쓰지 마십시오. 두 번째 정정은 기본 브랜치와 required_status_checks 판정은 고쳤지만, organization/repository ruleset의 type: workflows를 merge-blocking gate로 계산하지 않았습니다.
Fresh repository-effective ruleset reads reproduce that omission:
OriginWeave와wardnet모두 inherited organization ruleset **18156473(CWL Central required workflows)**가enforcement=active,~DEFAULT_BRANCH에 적용됩니다. 이 ruleset은pull_requestrule과 7개 required workflow (opencode-review.yml,pr-review-merge-scheduler.yml,security-scan.yml,strix.yml,sast-semgrep.yml,noema-review.yml,codeql-pr.yml)를 요구합니다.naruon에도 같은 organization ruleset18156473가 effective ruleset으로 반환됩니다.noema에는 별도 inherited organization ruleset **18794436(CWL Noema central security scan)**가enforcement=active,~DEFAULT_BRANCH에 적용되고security-scan.yml을 required workflow로 요구하며 bypass actor도 없습니다.
따라서 기존 분류에서 OriginWeave, wardnet, noema 등을 “중앙 리뷰가 merge를 막지 못하는 저장소”로 취급한 부분은 적어도 현재 effective ruleset과 모순됩니다. 특히 댓글의 재현식은 /rules/branches/$db에서 type=="required_status_checks"만 추출하므로 type=="workflows"를 구조적으로 놓칩니다.
다음 측정 계약
76개 저장소 전수 재측정 전에는 merge-blocking / non-blocking 비율을 새로 제시하지 않습니다. 새 측정은 저장소별 default branch를 확인하고, classic branch protection뿐 아니라 repository-effective inherited ruleset을 읽어 다음을 모두 판정해야 합니다.
required_status_checkscontexts;workflowsrules의 required workflow 목록;- ruleset
enforcement, ref 조건, bypass semantics; - 현재 queued-run depth와의 exact join.
현재 연결로 repository-effective inherited ruleset은 읽을 수 있으므로 “admin:org가 없어 확인도 불가능하다”는 기존 blocker 표현도 더 이상 정확하지 않습니다. 조직 ruleset 자체의 mutation은 별도 권한/소유자 판단이 필요하지만, 측정·검증은 repo-effective view로 진행할 수 있습니다.
아래 최초 측정과 댓글의 47.1% 정정은 원인 분석의 역사적 증거로 보존하되, 새 전수 결과가 나올 때까지 비율 인용에는 사용하지 마십시오.
최초 측정 — historical / superseded classifier
org 전체 대기 실행 2093건 가운데 1282건(61.3%)이 중앙 리뷰 체크가 merge를 막지 않는 저장소에서 나온다고 최초 계산했습니다.
중앙 리뷰 체크가 merge를 막는 저장소 5개 : 811건 (38.7%)
중앙 리뷰 체크를 merge gate로 보지 못한 저장소 71개 : 1282건 (61.3%)
합계 : 2093건
이 최초 분류는 이후 기본 브랜치 상수 오류가 발견되어 댓글에서 47.1%로 한 차례 정정됐고, 이번 2026-09-21 검증에서 다시 required-workflow rules 누락이 확인됐습니다. 수치 자체보다 아래 운영 관찰만 역사적 근거로 남깁니다.
- queue depth는 저장소별
actions/runs?status=queued&per_page=1의total_count로 측정해야 하며, 필터 없는 최근-run 목록으로 깊이를 추정하면 안 됩니다. - PR-triggered central/repository workflows가 queue pressure의 주요 공급원이라는 관찰은 별도 event 분포로 확인됐습니다.
- queue가 줄었다는 사실만으로 recovery를 뜻하지 않습니다. 실제 runner execution과 cancellation/skip을 구분해야 합니다.
- merge gate를 약화하거나 리뷰 역량을 제거하는 것은 해결책으로 승인되지 않았습니다. 정확한 effective-gating 분류가 먼저입니다.
재현 방향
repo="ContextualWisdomLab/<repo>"
db=$(gh api "repos/$repo" --jq .default_branch)
gh api "repos/$repo/actions/runs?status=queued&per_page=1" --jq .total_count
gh api "repos/$repo/rulesets"
# 각 effective ruleset id를 다시 읽고 .rules[]에서
# required_status_checks와 workflows를 모두 분류한다.최초 측정 시각은 2026-09-05 11:2x UTC입니다. queue depth는 snapshot이며, gating classification도 ruleset revision과 함께 versioned evidence로 다뤄야 합니다.
Activity
seonghobae commentedon Sep 5, 2026
정정: 헤드라인 수치가 틀렸습니다 (61.3% → 47.1%)
원 본문의 "61.3%가 merge를 막지 못한다"는 틀렸습니다. host1 세션이 잡아줬습니다.
무엇이 틀렸나
저장소마다
branches/main/protection을 조회했는데, 76곳 중 35곳의 기본 브랜치가main이 아닙니다.naruon은main브랜치 자체가 없어서 API가"Branch not found"를 돌려줬고, 저는 그 404를 "보호 설정 없음"으로 읽었습니다. 실제로는develop에서 중앙 리뷰 체크 5개(required-workflow-bootstrap,strix,coverage-source-tree,coverage-evidence,opencode-review)가 merge를 막습니다. 대기 231건으로 org 2위 기여자입니다.bandscope가 기본 브랜치는develop인데도 제 원래 조회에서 게이팅으로 잡힌 건, 이 저장소에는 기본이 아닌main브랜치가 따로 존재하고 거기에 보호가 걸려 있기 때문입니다. 즉 브랜치 이름을 상수로 박으면 오류가 나는 게 아니라 엉뚱한 브랜치의 그럴듯한 답이 돌아올 수도 있습니다.정정된 수치
기본 브랜치를 저장소마다
.default_branch로 확인해 다시 전수한 결과입니다.게이팅되는 9곳:
.github,contextual-orchestrator,fast-mlsirm,pg-erd-cloud,semantic-data-portal(이상main),naruon,bandscope,scopeweave,linux-cluster-ops(이상develop).이 정정 자체의 한계
정정하면서 두 가지를 동시에 바꿨습니다 — 기본 브랜치 확인, 그리고 중앙 체크 판정 정규식에
Analyze(CodeQL의 실제 job 이름)와coverage-source-tree추가. 그래서 61.3 → 47.1의 이동분을 브랜치 수정 하나에 귀속시킬 수 없습니다. 두 수치의 차이를 인용하지 마시고, 정정된 값만 쓰십시오.결론은 어떻게 바뀌나
과반 주장은 죽었습니다. "큐의 대부분이 merge를 못 막는다"고 더 이상 말할 수 없습니다.
방향과 처방은 남습니다. 대기의 **약 47%**가 어떤 merge도 막지 못하면서 org 공유 60-job 상한을 똑같이 소비하고, 실제로 게이팅하는 1107건이 그 뒤에 줄 서 있습니다. 절반에 가까운 수치이므로 "실행 시점을 바꾼다"는 방향은 그대로 유효합니다. 바뀐 것은 강도이지 결론이 아닙니다.
재현 (브랜치 상수를 쓰지 마십시오)
[-]measure(actions): 대기 큐의 61%가 중앙 리뷰 체크로 merge를 막지 못하는 71개 저장소에서 나온다 (76개 전수)[/-][+]measure(actions): 대기 큐의 약 47%가 중앙 리뷰 체크로 merge를 막지 못하는 67개 저장소에서 나온다 (76개 전수, 기본 브랜치 기준 정정됨)[/+]seonghobae commentedon Sep 5, 2026
완주한 실행 하나를 끝까지 뜯었습니다 — 대기가 벽시계의 99.87%입니다
.githubrun 33863887680 (fix/pyo3-native-peer-gate). #1910 병합 전에 생성돼서 옛 depth-5 그래프를 그대로 통과한 완전한 실행입니다. 6개 job 전부 실제 러너를 받았고 steps도 다 있습니다.실제 계산은 6개 job 합쳐 약 73초입니다. 벽시계는 15시간 37분 50초입니다.
직렬 sentinel 홉의 값이 처음으로 실측됐습니다
admit-current-head(2초),coverage-source-tree(3초),coverage-evidence(3초) — 이 세 job이 하는 일은 합쳐서 8초입니다. 이걸 실행하려고 지불한 큐 대기는2:32:42 + 4:33:22 + 2:19:19= 9시간 25분 23초입니다."직렬 링크 하나가 큐 패스 하나를 문다"는 주장이 이제 추론이 아니라 한 실행 안의 관측입니다.
#1910에 대해 말할 수 있는 것과 없는 것
#1910은
coverage-source-tree와coverage-evidence를 임계 경로에서 뺐습니다. 이 실행에서 그 두 홉의 대기는4:33:22 + 2:19:19= 6시간 52분 41초였습니다.단, 이걸 예측으로 쓰면 안 됩니다. 같은 날 같은 워크플로군에서 layer0 대기가 1.87h에서 7.75h까지 흔들린다는 측정이 따로 있습니다(host1 세션, n=80). 분산이 이 정도면 반사실 한 건은 "이 실행이었다면 얼마였을까"이지 "앞으로 얼마가 된다"가 아닙니다. 홉당 상수는 이미 폐기했고 여기서 되살리지 않습니다.
"25시간째 실행 없음"은 필터 아티팩트였습니다
status=success로만 조회하면 이 실행이 안 보입니다.failure로 끝났기 때문입니다. 마지막 실제 실행은 09-04T10:14Z가 아니라 09-05T02:12Z이고, 측정 시점 기준 약 9.4시간 전입니다.opencode-reviewjob 자체는steps=4로 정상 실행됐고 결론만failure입니다. 즉 리뷰가 안 돈 게 아니라 돌아서 부정 판정이 났거나 판정 생산에 실패한 것이고, 이건 러너를 못 받는 것과 전혀 다른 상태입니다.교훈: 파이프라인 생존을 볼 때
status=success만 보면 실패로 끝난 실제 실행이 통째로 빠집니다.success와failure를 각각 조회하거나, run 결론이 아니라 job의steps로 판정하십시오.seonghobae commentedon Sep 5, 2026
후속 측정: 기아가 org 전체에 균일하지 않습니다.
.github이 가장 나쁩니다큐가 줄고 있어서 "회복 중"이라고 쓸 뻔했는데, 큐는 실행으로도 줄고 취소로도 줍니다. 둘은 반대 뜻이라 갈라서 셌습니다.
2026-09-05 11:45Z~12:50Z(약 65분) 사이에 종결된 run을 conclusion별로 전수 집계했습니다.
failure는 contextual-orchestrator 2건뿐입니다.절단 확인: 다섯 저장소 모두
per_page=100페이지가 창 경계(11:45Z)보다 훨씬 이전(06:42~10:58Z)까지 닿고, 창 내 건수도 전부 100 미만(51/30/33/23/36)입니다. 창이 잘리지 않았습니다. 오늘 이 이슈에서 이미 한 번 상한 절단으로 틀린 적이 있어 먼저 확인했습니다.두 가지가 동시에 참입니다
하나, 큐 감소의 대부분은 실행이 아니라 취소입니다. 173건 중 109건(63%)이
cancelled입니다. 그러니 "큐가 줄었다 = 처리되고 있다"로 읽으면 안 됩니다.둘, 그럼에도 실제 실행은 재개됐습니다. 오늘 오전에는
.github에서 3시간 넘게 success/failure가 0건이었는데, 지금은 표본 전체에서 29건의 success가 나옵니다. contextual-orchestrator 16건, naruon 10건입니다. 그건 진짜 변화입니다.그런데 그 회복이
.github에는 오지 않았습니다.github은 **51건 종결 중 success 1건(2%)**입니다. skip 33건은 러너를 안 먹으니 빼고 보면 실질 18건 중 1건, 5.6%입니다. 같은 창에서 contextual-orchestrator는 33건 중 16건(48%)입니다..github은 org에서 가장 깊은 큐(562건)를 들고 있으면서 가장 낮은 실행률을 받고 있습니다.fast-mlsirm도 36건 전부 취소로 0%입니다.원인은 주장하지 않습니다
저장소별 실행률이 0%에서 48%까지 벌어지는 이유를 이 데이터는 말해주지 않습니다. 큐 깊이 대비 배분, 저장소별 concurrency 그룹의 취소 패턴, 혹은
.github이 required-workflow 원본 저장소라는 사실 — 어느 것도 확인 안 했습니다. 관측만 올립니다.운영상 함의
이건 지금 무엇을 어디서 하느냐를 바꿉니다.
.github에 push하는 작업은 지금 가장 비쌉니다. 가장 깊은 큐 + 가장 낮은 실행률이라 결과를 보기까지 가장 오래 걸립니다. 충돌 해소처럼 필요한 작업은 계속해야 하지만, "기다리면 체크가 붙는다"는 전제는.github에서 제일 약합니다.측정 시각 2026-09-05 12:50 UTC. 스냅샷이며, 오전 관측(3시간 무완주)과 다르다는 것 자체가 이 값이 빠르게 변한다는 증거입니다.
seonghobae commentedon Sep 5, 2026
재측정:
.github실행률 2% → 0%, 형제 저장소는 전부 상승. 비대칭이 유지가 아니라 확대됐습니다13:15Z~13:48Z(33분) 종결 run, conclusion별. 절단 확인: 다섯 저장소 모두 페이지가 창 경계 이전까지 닿음.
인용할 수 있는 대비는
.github0/92 대 naruon 22/32입니다. 나머지 셋은 방향만 일치하고 n이 작아 비율로 쓰지 마십시오..github의 92건은 전부 러너 없는 종결입니다67 cancelled + 25 skipped = 92. success 0, failure 0 — 33분 동안
.github에서 실제로 실행돼 끝난 run이 하나도 없습니다. 같은 33분에 org의 다른 곳에서는 실제 종결이 33건(22+4+6+1) 있었습니다.그리고 그 67건 취소의 대부분은 우리 자신의 작업입니다: #1932 머지가
d44aa07d의 27건을 취소했고, peer3의 재해소 push 3건과 #1661 push가 superseded run을 취소했습니다. 그래서.github은 "종결 92건"으로 활발해 보이지만 실행은 0입니다. 큐가 줄거나 종결이 늘어도 실행이 늘었다는 뜻이 아니라는 것, 이 이슈에서 두 번째로 확인됩니다.큐 깊이
다시 오르고 있고, 마찬가지로 우리 push입니다.
원인은 여전히 주장하지 않습니다
큐 깊이 비례 기아, 저장소별 공평 배분, required-workflow 원본 저장소라는 사실 — 셋 다 확인 안 했습니다. 이 데이터가 말하는 건
.github이 org에서 유일하게 실행률이 0인 저장소이고, 그 상태가 최소 2시간(11:45Z~13:48Z) 지속됐으며, 형제들은 그 사이 회복했다는 것까지입니다.운영상 결론 (변경 없음, 강화됨)
.github에 push하고 체크를 기다리는 것은 지금 어떤 정보도 주지 않습니다. 로컬 전체 스위트가 유일한 검출기입니다..github자체를 고치는 PR은 이 실행률에서는 정상 경로로 절대 초록이 될 수 없습니다 — chicken-and-egg 승인이 정확히 이 경우를 위한 것이고, 실제로 그렇게 처리했습니다.OPENCODE_REPOSITORY_DISPATCH_ACTOR변수 갱신(CodeQL dispatch terminal status publication remains unproven across repositories #1929), 그리고 org Actions 배분 자체(admin:org 없이는 읽을 수도 없음).측정 13:48Z.
seonghobae commentedon Sep 5, 2026
정정: 앞 코멘트의 "비대칭 확대"는 틀렸습니다 — 그 창의 0%는 배분이 아니라 우리 churn입니다
15분 전 제가 올린 "13:15~13:48Z 창에서
.github0/92, 형제들은 회복 → 비대칭 확대"를 철회합니다. host1 세션이 잡았고, 제가 독립 확인했습니다.왜 0%가 배분에 대해 아무것도 말하지 않는가
그 창에서 취소된
.githubrun의 수명(생성→취소)을 쟀습니다:오늘 layer-0 러너 대기의 일자별 중앙값은 3.3~5시간입니다(host1 n=80). 그런데 이 창의 run은 최대 36분밖에 못 살았습니다. 어느 run도 러너를 받을 수 있는 나이에 도달하지 못했습니다. 배분이 완벽했어도 0/92였을 겁니다 — 러너가 오기 세 시간 전에 우리가 죽였으니까요. skipped 25건은
if:스킵이라 러너와 무관합니다.취소의 원인도 우리입니다: 같은 브랜치의 후속 run에 의한 취소 37/60(62%), 그중
fix/dispatch-actor-allowlist17건은 #1932 머지가 자기 리뷰 run을 취소한 것입니다.naruon 22/32과의 대비도 성립하지 않습니다
naruon에는 여섯 세션이 몇 분마다 push하지 않습니다. naruon의 run은 살아서 러너를 기다릴 수 있었고
.github의 run은 그럴 기회가 없었습니다. 두 모집단이 "배분"이 아니라 "생존 기회"에서 이미 갈립니다. 비교가 아니라 오독이었습니다.무엇이 살아남는가
.github이 유일하게 실행률 0"은 참이지만 원인은 유일하게 에이전트 여섯이 동시에 push하는 저장소라서입니다.새로 적어야 할 것
배분 기아를 실측하려면 "3시간 이상 산
.githubrun이 있는데도 러너를 못 받았는가"를 봐야 하는데, 지금 그런 run은 0건입니다. 그건 "배분이 정상"이 아니라 우리가 측정을 막고 있다는 뜻입니다. 우리가 고치려는 push가 우리가 재려는 run을 죽이고, 그 결과를 기아로 읽을 뻔했습니다. 오늘 오전 freeze 실험에서 배운 "분류기가 결과를 결정한다"의 재발이고, 이번엔 우리 행동이 그 분류기입니다.한 push가 이 저장소의 실행률 측정을 통째로 오염시킵니다. #1932 머지 하나가 그랬습니다. 앞으로
.github실행률을 인용할 때는 그 창의 취소 run 수명 분포를 같이 붙여야 하고, 최대 수명이 러너 대기 중앙값보다 짧으면 그 창은 배분에 대해 무효입니다.앞 코멘트는 남겨두되 이 정정이 그 위에 섭니다. 잡아준 건 host1 세션입니다.
seonghobae commentedon Sep 8, 2026
Fresh downstream evidence from
pg-llm-batch#336at exact headdb134cea645608c045ef86039c0be72dcd1a21c0: repository-localactions/runs?status=queuedreports only 2 queued workflows (CI34189677890, Release Acceptance34189677891), but all 5 CI jobs are stillqueuedwithrunner_id=0, empty runner name/group, and no steps materialized. That distinguishes this case from a pg-local workflow fan-out/backlog: the current-head jobs have not reached runner admission despite the repo itself having only those two queued runs. I am preserving them as the sole current-head evidence and not retriggering/cancelling them. This is consistent with the organization-level shared-capacity/queue starvation tracked here; use the exact run/job IDs as a canary when validating central queue relief.seonghobae commentedon Sep 8, 2026
Fresh Noema canary, 2026-09-08 08:01Z+:
ContextualWisdomLab/noema#560@632c77b9db9f39662f78087b3b4eca45b46cf9d9has application CI34202304265still queued before runner assignment (job 101983686698,runner_id=0, empty steps). reviewer-ci34202304445, required Security34202304440, and patch-validator-image34202304393are likewise non-terminal. This head is deliberately test-only for a real Tool/Capability admission-provenance RED, so capacity delay is directly postponing causal repair rather than a routine reporting lane. Noema-side gates/workflows were not weakened or manually bypassed. Treat this as a current canary for the org-wide queue/capacity problem already measured here.seonghobae commentedon Sep 9, 2026
Fresh classification correction from Naruon authority, 2026-09-09: the issue body still lists
naruonamong repositories where central review cannot block merge, but current Naruon governance no longer supports that classification.Live Naruon ruleset
PR(15586698, active on the defaultdevelopbranch) currently requires central/security contexts includingopencode-review,trivy-fs,osv-scan,scorecard,dependency-reviewplus the repository's other protected checks. The protecteddevelopbranch likewise exposes 17 required contexts. Current #1623 exacte8a54fc...demonstrates the effect:opencode-reviewjob102330151945is failed and the PR remains non-merge-authorized even though Application CI/Bandit/Semgrep are GREEN and CodeRabbit has current-head approval.So any current queue-capacity denominator or "non-gating repositories" list should re-read Naruon's live ruleset before using the 2026-09-05 classification. Separately, #1623 security jobs are presently queued with no assigned runner while other exact-head jobs are progressing, but that observation alone does not prove the 60-job ceiling is the immediate cause; I am only correcting the gating classification here.
seonghobae commentedon Sep 9, 2026
Fresh consumer-side queue evidence from
ContextualWisdomLab/accounting-information-platform, captured while advancing #57 without any no-op retrigger..githubcurrently reports 43 queued workflow runs viaactions/runs?status=queued&per_page=100.accounting-information-platformcurrently reports 11 queued workflow runs on the same API surface.89b8bcaa6ae3268554171abfebd2a9b65b8cab80has a fresh substantive RED commit, not queue churn. Its Accounting Foundation34331096008has all four jobs queued withrunner_id=0; standalone Security34331096129, SAST34331096110, and CodeQL34331096131are also queued. The predecessor exact head already had real behavior RED plus same-head security/SAST evidence; no historical rerun is being issued.develop@239008c4edc7d305c97704c5102b593c6622b36falready contains 보안: subprocess 호출 시 shell=False 명시 (B603 취약점 방지) #48's docs-only Accounting Foundation suppression, so the correct next capacity work is central fan-out/coalescing/obsolete-run hygiene rather than weakening AIP required evidence.Please treat this as current consumer evidence for the existing organization queue owner. I am leaving the AIP exact-head runs untouched: no cancellation of sole current-head evidence, no synthetic status, no Draft/Ready churn, and no no-op push. If central hygiene removes obsolete queued runs, #57 is a clean canary because its current generation is bound to one exact substantive head.
[-]measure(actions): 대기 큐의 약 47%가 중앙 리뷰 체크로 merge를 막지 못하는 67개 저장소에서 나온다 (76개 전수, 기본 브랜치 기준 정정됨)[/-][+]measure(actions): 대기 큐의 61.3%가 중앙 리뷰 체크로 merge를 막지 못하는 71개 저장소에서 나온다 (76개 전수)[/+][-]measure(actions): 대기 큐의 61.3%가 중앙 리뷰 체크로 merge를 막지 못하는 71개 저장소에서 나온다 (76개 전수)[/-][+]measure(actions): 재측정 필요 — inherited required-workflow rules가 기존 게이팅 분류에서 누락됨[/+]