Skip to content
Draft
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
### Noema review publication revalidates exact-head uniqueness

- `inspect_and_review` now re-fetches the live pull request and repeats the trusted Noema receipt check immediately before review submission. A concurrent exact-head review published during model work can no longer be duplicated. The same repair removes the unconsumed `statusCheckRollup` query field. Proposed in ContextualWisdomLab/.github#1482.

### 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
39 changes: 39 additions & 0 deletions docs/doctoring/noema-final-submission-revalidation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Noema exact-head review submission is revalidated at the write boundary

검토 기준일: **2026-09-07**

## Problem

GitHub Actions concurrency cancellation is best-effort. A run already executing
model work can reach the review POST after another run has published a valid
Noema review for the same head. Head equality alone does not prove that the
write is still unique.

## Decision

The Noema gate keeps the pre-model duplicate check, then re-fetches the live
pull request after model work. Immediately before `submit_review`, it repeats
the trusted exact-head Noema receipt check. A concurrent receipt returns
successfully without publishing a duplicate. Closed or moved heads continue to
fail closed before this check.

The unused `statusCheckRollup` selection is removed because review publication
does not consume check contexts.

## Verification contract

`test_inspect_and_review_rechecks_for_a_concurrent_submission_before_posting`
models two live reads: the first has no receipt and the second contains a
trusted receipt for the same head. The POST recorder must remain empty. Hosted
exact-head checks remain mandatory.

## Status

**Proposed** in ContextualWisdomLab/.github#1482. Protected `main` remains the
release authority.

## Reference

GitHub. (n.d.). *Control the concurrency of workflows and jobs*. GitHub Docs.
Retrieved September 7, 2026, from
https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/control-workflow-concurrency
6 changes: 6 additions & 0 deletions docs/product-technical-gap-baseline.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@

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

### 2026-09-07 Noema final-submission concurrency amendment

- **Gap:** best-effort Actions cancellation cannot stop a run already inside model work, so another run can publish an exact-head Noema review before the first run reaches its POST.
- **Action:** ContextualWisdomLab/.github#1482 re-fetches the live PR after model work and re-checks the independent Noema receipt immediately before submission; the unused status-check query is removed.
- **Status:** Proposed; exact-head hosted Checks, independent review, ordinary protected integration, and post-merge current-main verification remain required.

## 1. 근거와 범위

### 1.1 우선순위가 높은 근거
Expand Down
27 changes: 6 additions & 21 deletions scripts/ci/noema_review_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,27 +329,6 @@ def graphql(query: str, **fields: str | int) -> dict[str, Any]:
commit { oid }
}
}
statusCheckRollup {
contexts(first: 100) {
nodes {
__typename
... on CheckRun {
name
status
conclusion
checkSuite {
workflowRun {
workflow { name }
}
}
}
... on StatusContext {
context
state
}
}
}
}
}
}
}
Expand Down Expand Up @@ -1795,6 +1774,12 @@ def inspect_and_review(repo: str, number: int, expected_head: str) -> int:
except RuntimeError:
print("Pull request closed or its head changed during review; stale verdict was not published.")
return 0
if existing_noema_review(current_pr, actor):
print(
"Current head already has a Noema review immediately before submission; "
"duplicate verdict was not published."
)
return 0
submit_review(repo, number, current_pr, actor, verdict)
return 0

Expand Down
55 changes: 55 additions & 0 deletions tests/test_noema_review_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -1933,6 +1933,61 @@ def test_inspect_and_review_does_not_wait_for_other_reviews_or_checks(monkeypatc
assert calls


def test_inspect_and_review_rechecks_for_a_concurrent_submission_before_posting(
monkeypatch,
):
"""Do not publish when another run reviewed the same head during model work."""
head = "a" * 40
first_pr = make_pr(headRefOid=head)
marker = "\n".join(
[
noema.NOEMA_REVIEW_FOOTER_MARKER,
"- Result: APPROVE",
f"- Head SHA: `{head}`",
"- Reviewer credential: `test`",
"- Actor: `noema`",
"",
f"<!-- noema-review-gate head_sha={head} decision=approve -->",
]
)
reviewed_pr = make_pr(
headRefOid=head,
reviews={"nodes": [review(commit=head, login="noema", body=marker)]},
)
pull_requests = iter((first_pr, reviewed_pr))
submissions = []
monkeypatch.setattr(noema, "fetch_pr", lambda repo, number: next(pull_requests))
monkeypatch.setattr(noema, "current_actor", lambda: "noema")
monkeypatch.setattr(noema, "fetch_diff", lambda repo, number: ("diff", False))
monkeypatch.setattr(
noema,
"fetch_changed_files",
lambda repo, number: [("tool.py", "modified")],
)
monkeypatch.setattr(
noema,
"build_review_context",
lambda repo, number, pr, changed_files=None: "context",
)
monkeypatch.setattr(
noema,
"call_llm",
lambda *args, **kwargs: {
"decision": "approve",
"summary": "ok",
"findings": [],
},
)
monkeypatch.setattr(
noema,
"submit_review",
lambda *args, **kwargs: submissions.append(args),
)

assert noema.inspect_and_review("owner/repo", 7, head) == 0
assert submissions == []


def test_stale_trigger_stops_before_identity_or_model_work(monkeypatch):
monkeypatch.setattr(noema, "fetch_pr", lambda repo, number: make_pr(headRefOid="b" * 40))
monkeypatch.setattr(
Expand Down
Loading