Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
464 changes: 408 additions & 56 deletions .github/workflows/codeql-scan-dispatch.yml

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
### CodeQL handler rollout is staged before its producer

- `codeql-scan-dispatch.yml` now owns one run-wide settlement after all
language shards finish, eliminating the observed split wake where actions
succeeded and Python received HTTP 403 on the same required run.
- Nested rerun authority requires exact schema `"1"`; the bounded top-level
form remains explicit `legacy-0`. Missing, numeric, unknown, or mixed schema
authority fails before checkout or Actions mutation.
- Exact live pull-request merge provenance, base/head/run/job identity,
terminal gate, SARIF preservation, returned status creator, and all-denied
credential behavior remain fail closed. This handler-only bootstrap is the
protected-main predecessor for `.github#2040`.
- Settlement refuses another mutation at required-run attempt 48 or later,
leaving margin below GitHub's 50-rerun platform ceiling and emitting exact
run, attempt, schema, language, and handler-attempt failure telemetry.

### Failed-check finding names the Strix sandbox instead of the gateway

- `opencode-review-dispatch.yml`'s `emit_strix_provider_failure_finding` rendered one fixed finding for every `STRIX_PROVIDER_UNAVAILABLE` line, whose Root cause read "The contextual-orchestrator gateway or its discovered provider pool was unavailable for this run". `#1953` had just given the Strix sandbox bootstrap failure its own second verdict token (`STRIX_SANDBOX_UNAVAILABLE`) precisely because that attribution is wrong for it -- the sandbox container never reaches its Caido proxy, so the run dies before the gateway serves anything -- and this consumer re-applied the wrong attribution one step downstream, into the review findings and the failure census. The emitter now branches on the second token: a sandbox verdict gets a finding that names Strix's sandbox, says the verdict does not name the gateway, and tells the reader not to change gateway or provider configuration on its strength. A `STRIX_PROVIDER_UNAVAILABLE` line without the token keeps its existing text verbatim, so the gateway class has no regression surface. No test covered this finding text at all before (`gateway or its discovered provider pool` matched nothing under `tests/`); `tests/test_opencode_dispatch_strix_sandbox_finding.py` now runs the production emitter from the published run block and pins both directions plus the no-signal case. Refs #1953, #1935.
Expand Down
53 changes: 53 additions & 0 deletions docs/adr/0025-codeql-required-workflow-dispatch-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,59 @@

**Status:** Proposed, amended 2026-09-07 (one dispatch per pull request; language independence is the handler job matrix) · **Date:** 2026-09-03 · **Owner intent recorded:** loop-brief item 41

## 2026-09-12 amendment — versioned handler-first rollout

### Decision and sequence

The protected handler must land before the producer that depends on its new
evidence and settlement contract. The bootstrap accepts exactly two rerun
protocols: the bounded top-level representation is identified as
`legacy-0`; the nested representation requires string schema `"1"` and exact
keys `schema`, `mode`, and `required_jobs`. Supplying both, omitting the nested
schema, or supplying a numeric or unknown schema fails before checkout or any
mutation. After the bootstrap merges ordinarily, `.github#2040` must be
non-force restacked and emit schema `"1"` for its nested request.

One `settle-required-run` job runs after all scan shards. It authenticates the
live repository, pull request, base, head, required run, complete language/job
set, terminal Medium+ gates, preserved SARIF artifacts, producer merge
revision, and returned creator before issuing exactly one run-level
`rerun-failed-jobs` or whole-run `rerun`. Matrix jobs have `actions: read` and
cannot race each other at the mutation boundary.

The same owner refuses another mutation at required-run attempt 48 or later.
GitHub permits at most 50 reruns of one workflow run; stopping below that
platform ceiling prevents the recovery mechanism from consuming the final
attempts and turning a repairable owner defect into a zero-job
`startup_failure`. Exhaustion is a deterministic non-passing result with
`phase=pre_mutation`, reason, exact run ID and attempt, schema, sorted language
set, and handler run/attempt. It never becomes a success receipt. A real source
repair creates a fresh exact-head run; no no-op commit or manual rerun is part
of recovery.

### Evidence, alternatives, and risks

Protected handler run `34684228601` is the production RED: actions woke the
required run, then Python received HTTP 403 from the same matrix-owned wake
path. `.github#2040` CodeQL run `34684356386` repeated the non-terminal
consumer outcome on exact head `a9b18b4b24980c7ceb8b8cc0d143a24db20c90bf`.
The predecessor required run `34629071379` reached `run_attempt=50` and then
ended as a zero-job `startup_failure` despite authenticated language scan
evidence, proving that an unbounded wake loop can exhaust the platform limit.
Manual reruns, Draft/Ready toggles, synthetic statuses, and creator-only
head-bound receipts are rejected because they neither repair single-writer
settlement nor authenticate the evidence. An atomic producer+handler merge is
also rejected: `repository_dispatch` executes the handler from protected
default-branch source, so the first invocation cannot use the proposed
handler.

The compatibility surface is temporary. `legacy-0` permits the staged
producer transition but does not authorize weaker status trust. Remove it
only after the schema-`"1"` producer is protected, queued legacy dispatches
have expired, and a fresh consumer canary proves terminal exact-head
settlement. Until protected integration and that canary, this amendment and
the bootstrap remain **Proposed**.

## Problem

`.github/workflows/codeql-pr.yml`'s `analyze-head`/`analyze-merge` jobs called
Expand Down
18 changes: 18 additions & 0 deletions docs/product-technical-gap-baseline.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@

이 문서는 제품·기술·운영 Gap을 현재 문서와 현재 GitHub 상태에 묶어 두는 기준선이다. 새 작업은 먼저 이 문서의 Gap ID를 PR 설명과 테스트 증거에 연결하고, PR의 정확한 exact HEAD·Checks·리뷰를 다시 수집한 뒤 구현한다. 표의 상태는 작성 시점의 관측값이므로, 병합 판단에는 재사용하지 않는다. 이 인벤토리는 스냅샷이며 merge authorization이 아니다.

## 2026-09-12 — CodeQL handler-first rollout bootstrap (Proposed)

- **Gap:** protected `.github/main@cb0872c9a20d5584703dffacca65c096fc034c6c`
still lets each CodeQL language matrix job mutate the same required run.
In handler run `34684228601`, actions woke the run and Python then received
HTTP 403. `.github#2040@a9b18b4b24980c7ceb8b8cc0d143a24db20c90bf`
reproduced the consumer failure in CodeQL run `34684356386`.
- **Owner repair:** land a handler-only protected-main predecessor with one
attempt-level settlement owner, exact evidence authentication, and explicit
rerun protocols: top-level `legacy-0` or nested schema `"1"`, never both.
Refuse a new mutation when `run_attempt >= 48`, before GitHub's 50-rerun
ceiling, and report exact phase/reason/run/attempt/schema/languages/handler.
- **Sequence:** ordinary-merge the bootstrap; non-force restack `.github#2040`
onto that protected revision; update its nested producer to schema `"1"`;
then obtain fresh exact-head producer→protected-handler evidence.
- **Status:** Proposed. Local RED→GREEN and repository verification do not
replace hosted exact-head Checks, independent review, or protected merge.

## 1. 근거와 범위

### 1.1 우선순위가 높은 근거
Expand Down
Loading
Loading