요약
opencode-review-dispatch.yml의 인가 게이트가 현재 디스패처 신원을 거부합니다. 허용 목록 변수는 github-actions[bot]인데 실제 디스패처는 opencode-agent[bot]입니다. 그 결과 verdict가 생산되지 않고, 상위 opencode-review job이 Fail closed without a current-head OpenCode verdict로 종료됩니다.
이것이 열린 PR 어느 것도 리뷰 증거를 얻지 못하는 이유입니다.
증거
변수 OPENCODE_REPOSITORY_DISPATCH_ACTOR = github-actions[bot] (updated 2026-07-16)
opencode-review-dispatch.yml 누적: success 466 / failure 9611 / completed 17311 (실패율 95.4%)
repository_dispatch run 표본 각 40건:
success actor: github-actions[bot] 40건 최신 2026-08-26T18:22:23Z
failure actor: opencode-agent[bot] 27건 / github-actions[bot] 11 / seonghobae 2
최신 2026-09-05T07:07:04Z
최근 실패 10건 전부 첫 job에서 종료:
validate-pr-metadata → "Bind workflow inputs to live organization pull request metadata"
게이트 조건(.github/workflows/opencode-review-dispatch.yml:107 이하):
if [ -z "$ALLOWED_DISPATCH_ACTOR" ] ||
[ "$DISPATCH_ACTOR" != "$ALLOWED_DISPATCH_ACTOR" ] ||
[ "$DISPATCH_SENDER" != "$ALLOWED_DISPATCH_ACTOR" ]; then
exit 1
디스패치를 보내는 쪽은 opencode-review.yml:431이고 앱 토큰을 씁니다:
GH_TOKEN="$app_token" gh api -X POST repos/ContextualWisdomLab/.github/dispatches --input -
그 앱 토큰 경로는 4a5dfd82 (2026-08-31, #1497)에서 도입됐고, 그때부터 sender가 opencode-agent[bot]이 됩니다. 허용 목록은 그보다 6주 전에 마지막으로 갱신됐습니다.
하류 영향 (다른 세션들이 측정한 값)
- 열린 non-draft PR 99건 중 현재 head에 성공한 opencode-review run을 가진 것 0건
- 그중 24건은 현재 head에
failure가 있는데, 표본 12건 전부 실패 스텝이 Fail closed without a current-head OpenCode verdict
- 해당 job들은
steps=4에 실제 runner_id를 받았습니다 — 러너 기아가 아니라 상류 verdict 부재입니다
즉 지금까지 "리뷰가 큐에서 굶는다"로 설명하던 것의 상당 부분이, 실제로는 verdict 생산자가 인가 단계에서 거부되는 것입니다.
주장하지 않는 것
이것이 유일한 원인이라고 주장하지 않습니다. 마지막 성공이 2026-08-26이고 앱 토큰 전환은 2026-08-31이라 그 사이 5일의 실패는 이 설명으로 덮이지 않습니다. 실패 표본에 github-actions[bot] 11건이 있는 것도 같은 이야기입니다 — 그 건들은 신원이 일치하는데도 실패했으므로 별개의 원인이 최소 하나 더 있습니다(대상 허용 목록, 또는 이후 스텝).
확정된 것은 이것뿐입니다: 현재 디스패처 신원은 현재 허용 목록과 일치하지 않으며, 그 조건에서 모든 앱 토큰 디스패치가 첫 게이트에서 거부됩니다.
수정 방향 — 소유자 판단 필요
두 갈래이고, 어느 쪽이 옳은지는 앱 토큰 전환의 의도에 달려 있어 제가 정할 수 없습니다.
opencode-agent[bot]이 의도된 신원이라면 → OPENCODE_REPOSITORY_DISPATCH_ACTOR를 그 값으로 갱신. 한 줄이지만 인가 허용 목록이라 자가 승인하지 않았습니다.
github-actions[bot]이 유지돼야 한다면 → opencode-review.yml:431이 앱 토큰 대신 github.token으로 디스패치해야 합니다. 다만 #1497이 앱 토큰을 도입한 이유가 따로 있을 것이므로 그 근거를 먼저 봐야 합니다.
어느 쪽이든 두 값을 일치시키는 계약 테스트를 함께 넣는 것을 권합니다. 이 저장소는 이미 같은 계열의 드리프트를 한 번 겪었고(#1747: 스케줄러 매트릭스와 OPENCODE_REPOSITORY_DISPATCH_TARGETS 변수가 갈라져 매시간 조용히 fail-closed), 그때의 처방이 두 목록을 계약으로 묶는 것이었습니다. 이번은 같은 패턴의 신원 축 버전입니다.
재현
gh api repos/ContextualWisdomLab/.github/actions/variables/OPENCODE_REPOSITORY_DISPATCH_ACTOR --jq .value
gh api "repos/ContextualWisdomLab/.github/actions/workflows/opencode-review-dispatch.yml/runs?status=failure&per_page=5" \
--jq '.workflow_runs[]|"\(.created_at) \(.triggering_actor.login)"'
요약
opencode-review-dispatch.yml의 인가 게이트가 현재 디스패처 신원을 거부합니다. 허용 목록 변수는github-actions[bot]인데 실제 디스패처는opencode-agent[bot]입니다. 그 결과 verdict가 생산되지 않고, 상위opencode-reviewjob이Fail closed without a current-head OpenCode verdict로 종료됩니다.이것이 열린 PR 어느 것도 리뷰 증거를 얻지 못하는 이유입니다.
증거
게이트 조건(
.github/workflows/opencode-review-dispatch.yml:107이하):디스패치를 보내는 쪽은
opencode-review.yml:431이고 앱 토큰을 씁니다:GH_TOKEN="$app_token" gh api -X POST repos/ContextualWisdomLab/.github/dispatches --input -그 앱 토큰 경로는
4a5dfd82(2026-08-31, #1497)에서 도입됐고, 그때부터 sender가opencode-agent[bot]이 됩니다. 허용 목록은 그보다 6주 전에 마지막으로 갱신됐습니다.하류 영향 (다른 세션들이 측정한 값)
failure가 있는데, 표본 12건 전부 실패 스텝이Fail closed without a current-head OpenCode verdictsteps=4에 실제runner_id를 받았습니다 — 러너 기아가 아니라 상류 verdict 부재입니다즉 지금까지 "리뷰가 큐에서 굶는다"로 설명하던 것의 상당 부분이, 실제로는 verdict 생산자가 인가 단계에서 거부되는 것입니다.
주장하지 않는 것
이것이 유일한 원인이라고 주장하지 않습니다. 마지막 성공이
2026-08-26이고 앱 토큰 전환은2026-08-31이라 그 사이 5일의 실패는 이 설명으로 덮이지 않습니다. 실패 표본에github-actions[bot]11건이 있는 것도 같은 이야기입니다 — 그 건들은 신원이 일치하는데도 실패했으므로 별개의 원인이 최소 하나 더 있습니다(대상 허용 목록, 또는 이후 스텝).확정된 것은 이것뿐입니다: 현재 디스패처 신원은 현재 허용 목록과 일치하지 않으며, 그 조건에서 모든 앱 토큰 디스패치가 첫 게이트에서 거부됩니다.
수정 방향 — 소유자 판단 필요
두 갈래이고, 어느 쪽이 옳은지는 앱 토큰 전환의 의도에 달려 있어 제가 정할 수 없습니다.
opencode-agent[bot]이 의도된 신원이라면 →OPENCODE_REPOSITORY_DISPATCH_ACTOR를 그 값으로 갱신. 한 줄이지만 인가 허용 목록이라 자가 승인하지 않았습니다.github-actions[bot]이 유지돼야 한다면 →opencode-review.yml:431이 앱 토큰 대신github.token으로 디스패치해야 합니다. 다만 #1497이 앱 토큰을 도입한 이유가 따로 있을 것이므로 그 근거를 먼저 봐야 합니다.어느 쪽이든 두 값을 일치시키는 계약 테스트를 함께 넣는 것을 권합니다. 이 저장소는 이미 같은 계열의 드리프트를 한 번 겪었고(#1747: 스케줄러 매트릭스와
OPENCODE_REPOSITORY_DISPATCH_TARGETS변수가 갈라져 매시간 조용히 fail-closed), 그때의 처방이 두 목록을 계약으로 묶는 것이었습니다. 이번은 같은 패턴의 신원 축 버전입니다.재현