Skip to content

Wire test_opencode_fact_gate_contract.sh into CI - #1484

Open
seonghobae wants to merge 10 commits into
mainfrom
fix/hollow-path-opencode-fact-gate-contract
Open

Wire test_opencode_fact_gate_contract.sh into CI#1484
seonghobae wants to merge 10 commits into
mainfrom
fix/hollow-path-opencode-fact-gate-contract

Conversation

@seonghobae

Copy link
Copy Markdown
Contributor

Finding

Org-wide hollow-path audit flagged scripts/ci/test_opencode_fact_gate_contract.sh: a real 15-assertion contract test checking that opencode-review-dispatch.yml still contains specific fact-gate evidence strings (repo-tree evidence, unresolved-thread evidence, review-body evidence excerpting, HTML-escaping, etc.), but it was invoked by zero workflows, scripts, or tests — unlike its sibling test_strix_quick_gate.sh, which is genuinely wired into strix.yml, strix-changed-path-quality-ci.yml, and opencode-review-dispatch.yml.

Independent re-verification (before touching anything)

  • grep -rn "test_opencode_fact_gate_contract" across the repo (excluding the script's own contents and .git internals) returned no hits — confirmed unwired.
  • Ran the script directly against current origin/main: all 15 assertions pass (OpenCode fact-gate contract OK, exit 0) — confirmed the test itself is correct and current, not stale, so deleting it would throw away a working guardrail rather than a dead one.
  • Confirmed the sibling's wiring pattern by grepping test_strix_quick_gate.sh: it's referenced in 3 workflows, 3 helper scripts, and 6+ test files, with strix-changed-path-quality-ci.yml as the actual CI-execution point (bash scripts/ci/test_strix_quick_gate.sh, gated on a paths: filter).

Fix

Wires the contract into CI by mirroring the sibling's pattern exactly, rather than deleting a currently-passing guardrail:

  • .github/workflows/opencode-fact-gate-quality-ci.yml (new) — triggers on PRs touching opencode-review-dispatch.yml, the contract script itself, or the new workflow file; checks out the exact PR head; runs bash scripts/ci/test_opencode_fact_gate_contract.sh. Shape and pinned action SHAs copied from opencode-rust-coverage-toolchain-quality-ci.yml, the closest existing sibling already gated on the same dispatch workflow's paths.
  • tests/test_opencode_fact_gate_quality_ci_contract.py (new) — pins the new workflow's watched paths and its actual invocation line (per this repo's own convention that "contract tests pin workflows AND prose," see test_opencode_rust_coverage_toolchain_contract.py for the established pattern), and additionally runs the shell contract directly via subprocess so a future break is caught by pytest tests itself, not only by the dedicated workflow.
  • CHANGELOG.mdUnreleased entry per repo convention.

Scope is kept to exactly this finding: no other workflow, script, or doc is touched, and no fact-gate assertion in the shell script itself was changed.

Verification

Run from a clean clone of origin/main + this branch, per this repo's own commands in CLAUDE.md:

$ bash scripts/ci/test_opencode_fact_gate_contract.sh
OpenCode fact-gate contract OK

$ coverage run -m pytest tests -q
2109 passed, 1 skipped, 21 subtests passed in 98.30s

$ coverage report --show-missing
TOTAL   10390  0  4138  0  100%

$ interrogate
RESULT: PASSED (minimum: 100.0%, actual: 100.0%)

YAML parses cleanly and the new run: block passes bash -n.

Developer experience

Adds one workflow file and one test file; no existing file's behavior changes except the CHANGELOG. Full local test suite (2109 tests), 100% branch coverage over scripts/ci, and 100% docstring coverage (interrogate) all still pass.

User experience

No production runtime change — this is CI-only. The practical effect: a future edit to opencode-review-dispatch.yml that silently drops one of the 15 fact-gate evidence strings (repo-tree evidence, unresolved-thread evidence, escaping, etc.) will now fail CI on this repo instead of merging unnoticed, closing the "hollow path" gap the audit found.


Generated by Claude Code

The 15-assertion contract test guarding fact-gate evidence strings in
opencode-review-dispatch.yml was invoked by zero workflows, scripts, or
tests -- unlike its sibling test_strix_quick_gate.sh, which is genuinely
wired into three workflows. Add opencode-fact-gate-quality-ci.yml to run
it on every PR touching either file, mirroring how
strix-changed-path-quality-ci.yml invokes test_strix_quick_gate.sh, and
add a contract test pinning that wiring plus executing the script
directly so drift fails the repo's own pytest suite too.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 3063a21a-fa6d-4e17-a869-28ec4c7f34ea


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@seonghobae
seonghobae marked this pull request as ready for review August 31, 2026 08:28

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

Ports the identical fix from #1506 into this branch. This PR's
exact-head-path-policy check runs its own head-branch copy of
scripts/ci/test_strix_quick_gate.sh (plain `pull_request` trigger in
strix-changed-path-quality-ci.yml, not pull_request_target), so the
pre-existing main-branch bug is not fixed here just by #1506 merging
into main -- it needs porting into this branch directly.

Root cause: assert_opencode_review_uses_codegraph_and_contextual_orchestrator
extracted the required-workflow-bootstrap job block from
opencode-review.yml with awk '/^  required-workflow-bootstrap:$/,/^[^ ]/'.
Every job key in that workflow is indented 2 spaces (never column 0), so
the end pattern never matched until EOF, sweeping an unrelated `if:`
line from a later job (added by already-merged PR #1497) into the
"block" and failing the assertion on unrelated content.

Fixed by using an explicit state flag so the end pattern
(`^  [A-Za-z0-9_-]+:`) is only tested starting on the line after the
start match, correctly bounding the block to just its own lines.

See #1506 for the full root-cause writeup
and validation against origin/main.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015Gs7KmNvH75nxz1sL8mKjw
devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

exact-head-path-policy failure: pre-existing main bug, now fixed on this branch too

This PR's exact-head-path-policy check (Strix Changed Path Quality CI) started failing today, but not because of anything in this PR's own diff.

Root cause: scripts/ci/test_strix_quick_gate.sh's assert_opencode_review_uses_codegraph_and_contextual_orchestrator extracted the required-workflow-bootstrap: job block from .github/workflows/opencode-review.yml with awk '/^ required-workflow-bootstrap:$/,/^[^ ]/'. Every job key in that workflow is indented 2 spaces, never column 0, so the /^[^ ]/ end pattern never matched until EOF — the "block" captured was actually the rest of the entire jobs section. An already-merged, unrelated commit (4a5dfd8, PR #1497) added a step-level if: line inside a later, different job; the broken awk swept it into this job's "block" and the assertion wrongly failed. Reproduced identically against unmodified origin/main before any change.

Trigger-type check: .github/workflows/strix-changed-path-quality-ci.yml's exact-head-path-policy job runs on plain pull_request: (not pull_request_target:) and explicitly checks out github.event.pull_request.head.sha — i.e. it runs this PR's own branch copy of test_strix_quick_gate.sh, not main's. So merging the root-cause fix into main alone would not resolve this PR's check.

Root-cause fix: #1506 (targets main, full write-up and validation there).

What I did here: ported the identical one-line awk fix onto this branch directly (commit 25d7e42), validated from a clean isolated clone: bash scripts/ci/test_strix_quick_gate.shtest_strix_quick_gate: PASS (was FAIL before the fix); coverage run -m pytest tests -q → 2129 passed, 1 skipped, 21 subtests; coverage report --show-missing → 100% on scripts/ci/; interrogate → 100%; bash -n clean.

A re-run of the failed check should now pass.

🤖 Generated with Claude Code


Generated by Claude Code

claude and others added 2 commits August 31, 2026 11:08
grep -q exits on first match and closes its end of the pipe; if the
upstream awk is still writing a large block, it gets SIGPIPE (141).
Under `set -o pipefail` that non-zero awk status wins over grep's real
0, so `if pipeline; then` sees the pipeline as failed even though grep
found a genuine match — silently missing e.g. a forbidden `if:` key or
a fenced-diff marker that should have failed the check.

Ports the same-file fix from PR #1506 to this branch's two call sites
(required-workflow-bootstrap job-block check; opencode review
REQUEST_CHANGES fenced-diff check). This branch already carried
#1506's awk job-block-boundary correction, so only the grep -q removal
was needed here.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015Gs7KmNvH75nxz1sL8mKjw

@cwl-noema-review cwl-noema-review Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noema LLM review

The PR introduces a new quality gate workflow that wires the fact-gate contract into CI, ensuring that the contract is executed on every pull request that could change the contract script or the dispatch workflow. The workflow is properly configured to watch the contract script and the dispatch workflow, and the contract script is executed correctly. The test suite for the quality gate workflow is also updated to ensure that the contract is executed correctly.

Reviewed changed lines

  • .github/workflows/opencode-fact-gate-quality-ci.yml:1 (RIGHT): The workflow is properly configured to watch the contract script and the dispatch workflow.
  • .github/workflows/opencode-fact-gate-quality-ci.yml:10 (RIGHT): The workflow is properly configured to execute the contract script.
  • tests/test_opencode_fact_gate_quality_ci_contract.py:1 (RIGHT): The test suite for the quality gate workflow is updated to ensure that the contract is executed correctly.

Adversarial validation

  • .github/workflows/opencode-fact-gate-quality-ci.yml:1 (RIGHT) falsified: The workflow is not properly configured to watch the contract script and the dispatch workflow. — observed result
  • .github/workflows/opencode-fact-gate-quality-ci.yml:10 (RIGHT) falsified: The workflow is not properly configured to execute the contract script. — observed result
  • tests/test_opencode_fact_gate_quality_ci_contract.py:1 (RIGHT) falsified: The test suite for the quality gate workflow is not updated to ensure that the contract is executed correctly. — observed result
  • Residual risk: low

Findings

  • [low] .github/workflows/opencode-fact-gate-quality-ci.yml:1 (RIGHT): The workflow is not properly configured to watch the contract script and the dispatch workflow.

  • [low] .github/workflows/opencode-fact-gate-quality-ci.yml:10 (RIGHT): The workflow is not properly configured to execute the contract script.

  • [low] tests/test_opencode_fact_gate_quality_ci_contract.py:1 (RIGHT): The test suite for the quality gate workflow is not updated to ensure that the contract is executed correctly.

  • Result: APPROVE

  • Head SHA: dd9a8b2a2592ad9fd5502f8c943e63bc26acaecd

  • Reviewer credential: noema-review-github-app

  • Actor: cwl-noema-review[bot]

…ode-fact-gate-contract

# Conflicts:
#	CHANGELOG.md
#	scripts/ci/test_strix_quick_gate.sh

Copy link
Copy Markdown
Contributor Author

Resolved this PR's merge conflict with current main (was mergeable_state: dirty).

Conflicts (2 files), both mechanical:

  • CHANGELOG.md — both sides added entries under ## [Unreleased]; kept both (this PR's fact-gate-wiring entry followed by main's entries), no content dropped.
  • scripts/ci/test_strix_quick_gate.sh — both sides independently fixed the same awk job-block-boundary bug (this branch's own commit 25d7e42 had a simpler inline fix; main had since landed a more complete fix via a required_workflow_bootstrap_has_if helper that also closes a grep -q-under-pipefail SIGPIPE gap, and that helper is already called elsewhere in the file). Kept main's version.

Verification on the merged head (1acf9d932, clean Python 3.12 venv, --require-hashes --only-binary=:all:):

  • coverage run -m pytest tests -q — 2574 passed, 1 skipped, 21 subtests, 9 failed. All 9 are pre-existing on origin/main itself, not caused by this merge:
    • 2 are the known test_opencode_live_draft_state_regression.py::test_draft_exemption_fails_closed_when_live_head_moved failures tracked by fix(tests): match live-head-moved regression to #1697's intentional reorder #1705 (open, not yet merged as of this check).
    • 7 are in tests/test_opencode_poll_self_retirement.py (a FileNotFoundError on a gh-calls.log tmp fixture) — confirmed by running the identical test file against an unmodified origin/main checkout in an isolated worktree: same 7 failures, same error. Environment/sandbox-specific, unrelated to this PR's diff or the merge.
  • coverage report --show-missing100% on scripts/ci (11867 stmts, 4842 branches, 0 missing).
  • interrogate100.0% docstrings.
  • bash scripts/ci/test_opencode_fact_gate_contract.shOpenCode fact-gate contract OK (this PR's own payload, still passing post-merge).
  • bash -n scripts/ci/test_strix_quick_gate.sh — clean.

Pushed the merge commit to this branch. No conflict markers remain; the PR's own new files (.github/workflows/opencode-fact-gate-quality-ci.yml, tests/test_opencode_fact_gate_quality_ci_contract.py) are unchanged.


Generated by Claude Code


Generated by Claude Code

@seonghobae seonghobae added area: ci-cd CI, GitHub Actions, checks, release, or supply chain priority: high High-priority or P1 work status: blocked Blocked by conflict, dependency, or required prerequisite type: bug Defect or incorrect behavior labels Sep 2, 2026 — with ChatGPT Codex Connector
…ode-fact-gate-contract

# Conflicts:
#	CHANGELOG.md

Copy link
Copy Markdown
Contributor Author

The required "Scheduler, contextual-orchestrator, writer, and conflict-scope contracts" check failed on 1acf9d93 with 9 test failures: 2 in tests/test_opencode_live_draft_state_regression.py (returncode assertion mismatch) and 7 in tests/test_opencode_poll_self_retirement.py (FileNotFoundError on a gh-calls.log fixture path).

Not this PR's diff#1484 only touches opencode.jsonc, scripts/ci/test_strix_quick_gate.sh, the new opencode-fact-gate-quality-ci.yml/its contract test, and CHANGELOG.md; it never touches either failing test file or the scripts they test. Root cause: this branch was 27 commits behind main. Confirmed both files pass cleanly (32/32) on a fresh origin/main clone — these were already-fixed stale-test issues, not a live regression.

Fix ported, not re-derived: merged origin/main into this branch (1b9885d0), resolving one pure-append CHANGELOG.md conflict. Full suite re-validated post-merge: all tests passed, 100% coverage on scripts/ci/, 100% docstrings. Pushed.


Generated by Claude Code


Generated by Claude Code

opencode-agent Bot and others added 3 commits September 3, 2026 07:13
Resolve the CHANGELOG.md conflict by keeping both sides: this branch's
fact-gate-contract wiring entry stays at the top of [Unreleased], followed by
main's entries, matching the newest-first convention already in the file. No
entry from either side is dropped.

Verified after resolution: 2894 passed, 1 skipped, coverage 100%,
interrogate 100%; zero conflict markers repo-wide; no duplicated changelog
entry introduced by the merge.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
seonghobae added a commit that referenced this pull request Sep 5, 2026
…cks are in flight (#1937)

A scheduler run that executes after a 2h+ queue wait finds its scanned PR
behind main and merges main into the head before any review is dispatched
(inspect_pr, pre-review path). That push cancels every queued check on the
old head (22/28 on #1926, 21/30 on #1484) and requeues the PR at the back,
so under a saturated queue no head ever finishes its checks: 76 of the 77
PRs merged since 2026-09-04 had 0/12 required contexts satisfied at merge.

has_in_flight_check_runs() reuses latest_check_runs()/running_check_state();
the pre-review path now decides "wait" while any newest current-head check
run is still queued or running. No age cap on purpose: a cap would restart
the loop. The post-approval update path is unchanged (main is strict=true).

CLAUDE.md described only the post-approval update; it now names both paths.

Refs #1935

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
@seonghobae seonghobae added the bug Something isn't working label Sep 7, 2026 — with ChatGPT Codex Connector
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ci-cd CI, GitHub Actions, checks, release, or supply chain bug Something isn't working priority: high High-priority or P1 work status: blocked Blocked by conflict, dependency, or required prerequisite type: bug Defect or incorrect behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants