Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
848d796
fix(ci): restore OpenCode coverage honesty and mermaid surfaces
seonghobae Aug 27, 2026
7c9e472
fix(ci): restore OpenCode receipt-gate and coverage identity
seonghobae Aug 27, 2026
d450f56
fix(ci): retarget honesty-surface contract pins to live dispatch
seonghobae Aug 27, 2026
664fd63
fix(ci): restore path-policy honesty-surface contracts
seonghobae Aug 27, 2026
3705a5d
fix(review): restore required formal-verdict gate
seonghobae Aug 27, 2026
809187e
test(opencode): reproduce coverage publication identity defects
seonghobae Aug 27, 2026
7fec164
fix(opencode): bind coverage publication to workflow run
seonghobae Aug 27, 2026
4c23b89
test(opencode): repin reviewed dispatch workflow blob
seonghobae Aug 27, 2026
cc6d065
test(opencode): reject arbitrary unchanged-workflow anchors
seonghobae Aug 27, 2026
5692744
fix(opencode): reject spoofed workflow anchors
seonghobae Aug 27, 2026
a89c4d3
test(opencode): expose dead overview sentinel lookup
seonghobae Aug 27, 2026
15ae377
test(opencode): make sentinel regression executable
seonghobae Aug 27, 2026
4c97a37
test(opencode): isolate dead sentinel lookup
seonghobae Aug 27, 2026
ab76452
fix(opencode): remove dead overview sentinel lookup
seonghobae Aug 27, 2026
9170d26
test(opencode): retire sentinel-read throttle contract
seonghobae Aug 27, 2026
671b500
test: remove invalid blank line at EOF
seonghobae Aug 27, 2026
5abc3dd
test: reject COMMENTED as formal OpenCode receipt
seonghobae Aug 27, 2026
069ded2
fix: require substantive OpenCode review verdicts
seonghobae Aug 27, 2026
ce68e19
test: align receipt fixtures with formal verdict contract
seonghobae Aug 27, 2026
263f565
test: execute required verdict workflow instead of mirror
seonghobae Aug 27, 2026
63913cb
test: correct runtime jq fixture delimiter
seonghobae Aug 27, 2026
360fa42
test: use unambiguous jq marker literal
seonghobae Aug 27, 2026
34e02bd
refactor: remove test-only verdict mirror
seonghobae Aug 27, 2026
dea5106
test: retry transient coverage identity reads
seonghobae Aug 27, 2026
0d11fdf
fix: retry transient coverage identity reads
seonghobae Aug 27, 2026
5c42c79
test: reproduce bare HTTP 502 retry
seonghobae Aug 27, 2026
b41ff0e
fix: match transient HTTP status tokens
seonghobae Aug 27, 2026
e76a54b
test: reject workflow anchor path aliases
seonghobae Aug 27, 2026
f75e98b
fix: normalize untrusted workflow anchor paths
seonghobae Aug 27, 2026
5725539
fix: correct workflow anchor regex escapes
seonghobae Aug 27, 2026
3e31eb5
test(opencode): expose later comment verdict masking
seonghobae Aug 27, 2026
3d98c59
fix(opencode): retain latest formal head verdict
seonghobae Aug 27, 2026
aa43e61
test(opencode): bind coverage to dispatch run job
seonghobae Aug 27, 2026
61c0bab
test(opencode): require central run coverage authority
seonghobae Aug 27, 2026
2ec8215
fix(opencode): verify exact dispatch coverage job
seonghobae Aug 27, 2026
186996c
fix(opencode): bind coverage to central run
seonghobae Aug 27, 2026
61a9624
fix(opencode): accept central dot repository
seonghobae Aug 27, 2026
37cb0ea
test(opencode): scope dispatch argument assertions
seonghobae Aug 27, 2026
dc106b8
test(opencode): pin reviewed dispatch workflow
seonghobae Aug 27, 2026
e27eb23
test(opencode): expose redundant overview writes
seonghobae Aug 27, 2026
c451532
fix(opencode): publish coverage overview once
seonghobae Aug 27, 2026
fbd0e6f
test(opencode): repin reviewed dispatch workflow
seonghobae Aug 27, 2026
ef60df3
test(opencode): distinguish shell fallback operator
seonghobae Aug 27, 2026
d229fc6
test(opencode): align overview helper contract
seonghobae Aug 27, 2026
82c5ed2
test(opencode): expose Rust merge-conflict diagram drift
seonghobae Aug 27, 2026
b4919d3
fix(opencode): retain Rust merge-conflict diagram state
seonghobae Aug 27, 2026
8d7d137
fix(ci): bind coverage jobs to exact dispatch run
seonghobae Aug 27, 2026
c5772d8
fix(ci): reject parent workflow anchor aliases
seonghobae Aug 28, 2026
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
245 changes: 164 additions & 81 deletions .github/workflows/opencode-review-dispatch.yml
Comment thread
seonghobae marked this conversation as resolved.

Large diffs are not rendered by default.

57 changes: 54 additions & 3 deletions .github/workflows/opencode-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ concurrency:

permissions:
contents: read
pull-requests: read

jobs:
required-workflow-bootstrap:
Expand Down Expand Up @@ -53,7 +54,57 @@ jobs:
name: opencode-review
needs: [coverage-evidence]
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
steps:
- run: >-
echo "Review approval remains a separate current-head PR review
requirement produced by the authenticated dispatch workflow."
- name: Fail closed without a current-head OpenCode verdict
env:
GH_TOKEN: ${{ github.token }}
TARGET_REPOSITORY: ${{ github.event.pull_request.base.repo.full_name || github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
set -euo pipefail
if [ "${{ github.event.action }}" = "closed" ]; then
echo "PR closed; a current-head OpenCode verdict is not required."
exit 0
fi
if [ -z "${PR_NUMBER:-}" ] || [ -z "${HEAD_SHA:-}" ]; then
echo "::error::Missing PR number or head SHA; cannot verify a current-head OpenCode verdict."
exit 1
fi
reviews="$(gh api --paginate "repos/${TARGET_REPOSITORY}/pulls/${PR_NUMBER}/reviews")"
verdict="$(printf '%s\n' "$reviews" | jq -r -s --arg sha "$HEAD_SHA" '
(add // [])
| [
.[]
| select(
(.user.login // "" | ascii_downcase) as $user
| $user == "opencode-agent" or $user == "opencode-agent[bot]"
)
| select((.commit_id // "" | ascii_downcase) == ($sha | ascii_downcase))
| select(.state == "APPROVED" or .state == "CHANGES_REQUESTED")
]
| (last // {}) as $review
| ($review.body // "" | ascii_downcase) as $body
| if $review.state == "CHANGES_REQUESTED" then
"CHANGES_REQUESTED"
elif $review.state == "APPROVED"
and ($body | contains("deterministic current-head evidence") | not)
and ($body | contains("deterministic fallback approval") | not)
and ($body | contains("model-unavailable evidence fallback") | not)
and ($body | contains("did not emit a usable current-head control block") | not)
and ($body | contains("scope: `unsupported`") | not)
and ($body | contains("model-pool outcome: `unknown`") | not)
then
"APPROVED"
else
empty
end
Comment thread
seonghobae marked this conversation as resolved.
Comment thread
seonghobae marked this conversation as resolved.
')"
Comment thread
seonghobae marked this conversation as resolved.
if [ -z "$verdict" ]; then
echo "::error::No APPROVED or CHANGES_REQUESTED from opencode-agent on the current head. This required check is not a review and must not succeed until the authenticated dispatch posts a current-head verdict."
exit 1
fi
echo "Current-head OpenCode verdict: ${verdict}."
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ this file. The format follows Keep a Changelog, and versioned releases follow
Semantic Versioning where the repository publishes a release.

## [Unreleased]
- Restore OpenCode coverage honesty and mermaid surfaces stacked on main after #1360 squash `17052a7c`: `publish_fallback_diff_review` posts a COMMENT product-file review then `request_changes_for_coverage_evidence_failure` sets the status comment to `COVERAGE_BLOCKED` so a coverage miss never looks finished as `Gate result: COMMENT`; mermaid labels crates/packages instead of generic `Changed file (N files)` and does not invent class edges; findings say `Review process` instead of `.github/workflows/opencode-review.yml:1` unless that file is in the diff. Does not change `noema-review.yml` (PM owns `feat/noema-orchestrator-free-zdr`) and is not NIM-2h or GitHub Models.
- Central review now routes through the vendored `contextual-orchestrator`
gateway sidecar: the write-capable PR autofix and the shared `opencode.jsonc`
default use the fail-closed zero-cost pool `orchestrator/free`, with
Expand Down
9 changes: 9 additions & 0 deletions ci-review-prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,15 @@ green checks are not runtime-tool receipts. When no receipt exists, describe
only the source trace or explicit execution limitation; fabricating browser or
DevTools evidence invalidates the entire control block.

The formal review must name the actual changed files and what they do,
include file/line findings on the current-head diff or an explicit APPROVE
with a real walkthrough, and draw a useful sequence/class/state diagram of
the changed API rather than a generic `Changed file (N files)` inventory.
Coverage is a gate, not the review: cite coverage evidence in the status
surface and never replace the product-file walkthrough with a coverage
blocker. Never cite `.github/workflows/opencode-review.yml:1` unless that
file is in the current-head diff.

Review the diff first, then inspect surrounding code only when needed to
understand impact. Evaluate correctness, API compatibility, security/privacy,
data integrity, concurrency, error handling, observability, performance,
Expand Down
82 changes: 82 additions & 0 deletions docs/doctoring/opencode-review-surfaces-originweave-47.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# OpenCode review surfaces and OriginWeave coverage sandbox

검토 기준일: **2026-08-16**

## Incident

ContextualWisdomLab/OriginWeave#47, head
`79cf275686e2376a51783a2d03128eca21e7c0e5`, workflow run `31951179896`,
published the same body as both the formal pull-request review and the issue
comment: a generic overview plus one HIGH finding on
`.github/workflows/opencode-review.yml:1` saying coverage-evidence failed. The
pull request actually changed
`crates/originweave-destination/src/lib.rs`, `resolution.rs`, and
`tests/resolution_freshness.rs` (FreshResolutionSnapshot / DNS-rebinding
TOCTOU). The mermaid inventory said `Changed file (3 files)` because unknown
paths, including `crates/`, were bucketed as "Changed file". Repository CI on
that head passed. The central isolated coverage job failed and replaced the
entire review.

## Root cause

When `needs.coverage-evidence.result != success`, the publisher synthesized
`REQUEST_CHANGES`, posted it with `gh pr review` and again as an issue comment,
and exited before the model pool could review the diff. Coverage-evidence
failure became the review. The mermaid helper bucketed unknown paths,
including `crates/`, as a generic `Changed file (N files)` inventory and
findings were anchored to `.github/workflows/opencode-review.yml:1` even
when that file was not in the pull-request diff.

## Decision

Coverage remains a fail-closed gate. It is no longer the review.

1. The formal pull-request review is a source-backed walkthrough of the
current-head product diff, including a fallback review that names the
changed crate files when the model pool did not emit a control block.
2. The issue comment is gate/status only: head SHA, run id/attempt, coverage
result, model-pool outcome, verdict, and a link to the formal review. It
must not repeat `## Pull request overview`, `## Findings`, mermaid, or the
model walkthrough.
3. A coverage miss, skip, or unsupported-tooling result blocks approval and
fails the required review job after the diff review is published. It must
not cite `.github/workflows/opencode-review.yml:1` unless that file is in
the pull-request diff.
4. Coverage-evidence failure is injected into `bounded-review-evidence.md` as
a `## Coverage gate` section. The model pool still runs. The publisher
does not early-return before the model path. `format_request_changes_review`
keeps model walkthrough/diagrams and appends structured findings.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

## Verification contract

Regression tests prove that:

1. the formal review body is not equal to the status comment;
2. a coverage-gate failure still produces a review that names the changed
crate files;
3. no finding is anchored to `opencode-review.yml:1` unless that file is in
the diff;
4. mermaid labels a `crates/...` change as a Rust crate surface, not
`Changed file (3 files)`;
5. the publisher function
`request_changes_for_coverage_evidence_failure` updates the status comment
and does not call `create_pull_review`;
6. the model pool still runs when coverage-evidence failed (`!= cancelled`);
7. `publish_fallback_diff_review` restores `COVERAGE_BLOCKED` on the status
comment after the COMMENT product-file review, so a coverage miss never
looks finished as `Gate result: COMMENT`; and
8. mermaid class diagrams list extracted public Rust API names only and do
not invent a `FirstType --> SecondType` class edge.

## Limitations

A later coverage-image or tooling catalog change can still fail the isolated
coverage job. That failure remains a coverage-gate failure, not a synthesized
product-file finding. The sandbox does not weaken a genuine below-threshold
coverage miss.

## References

GitHub, Inc. (2026). *REST API endpoints for pull request reviews*. GitHub
Docs.
https://docs.github.com/en/rest/pulls/reviews
Loading
Loading