diff --git a/.github/workflows/opencode-review.yml b/.github/workflows/opencode-review.yml index 4aabeccaf..2ab6028ae 100644 --- a/.github/workflows/opencode-review.yml +++ b/.github/workflows/opencode-review.yml @@ -69,12 +69,16 @@ jobs: WORKFLOW_REF: ${{ github.workflow_ref }} run: | set -euo pipefail - trusted_ref="${INPUT_CANONICAL_REF:-main}" - case "$WORKFLOW_REF" in - ContextualWisdomLab/.github/.github/workflows/opencode-review.yml@*) - trusted_ref="${WORKFLOW_REF##*@}" - ;; - esac + if [ -n "$INPUT_CANONICAL_REF" ]; then + trusted_ref="$INPUT_CANONICAL_REF" + else + trusted_ref="main" + case "$WORKFLOW_REF" in + ContextualWisdomLab/.github/.github/workflows/opencode-review.yml@*) + trusted_ref="${WORKFLOW_REF##*@}" + ;; + esac + fi printf 'ref=%s\n' "$trusted_ref" >>"$GITHUB_OUTPUT" - name: Checkout trusted OpenCode coverage contract @@ -844,12 +848,16 @@ jobs: WORKFLOW_REF: ${{ github.workflow_ref }} run: | set -euo pipefail - trusted_ref="${INPUT_CANONICAL_REF:-main}" - case "$WORKFLOW_REF" in - ContextualWisdomLab/.github/.github/workflows/opencode-review.yml@*) - trusted_ref="${WORKFLOW_REF##*@}" - ;; - esac + if [ -n "$INPUT_CANONICAL_REF" ]; then + trusted_ref="$INPUT_CANONICAL_REF" + else + trusted_ref="main" + case "$WORKFLOW_REF" in + ContextualWisdomLab/.github/.github/workflows/opencode-review.yml@*) + trusted_ref="${WORKFLOW_REF##*@}" + ;; + esac + fi printf 'ref=%s\n' "$trusted_ref" >>"$GITHUB_OUTPUT" - name: Checkout trusted OpenCode review workflow @@ -975,8 +983,8 @@ jobs: - name: Install OpenCode CLI env: - OPENCODE_VERSION: "1.16.0" - OPENCODE_SHA256: a741c43e737b2033f5e7ee151b162341e441034d6a64b172272a3f3a3729e87d + OPENCODE_VERSION: "1.17.13" + OPENCODE_SHA256: 157afa289d1a8d9372de0ce19ac726119b937a1f6b201808d46f06e4e59bb348 run: | set -euo pipefail archive="${RUNNER_TEMP}/opencode-linux-x64.tar.gz" @@ -991,7 +999,7 @@ jobs: "${install_dir}/opencode" --version echo "$install_dir" >>"$GITHUB_PATH" - - name: Detect central review-process fallback scope + - name: Detect central review-process scope id: central_review_process_fallback_scope if: needs.coverage-evidence.result == 'success' env: @@ -1059,12 +1067,11 @@ jobs: printf 'changed_count=%s\n' "$changed_count" printf 'scope_label=%s\n' "$scope_label" } >>"$GITHUB_OUTPUT" - printf 'Deterministic review fallback scope=%s eligible=%s changed_count=%s max_changed_count=%s\n' \ + printf 'Trusted review-process scope=%s eligible=%s changed_count=%s max_changed_count=%s\n' \ "$scope_label" "$eligible" "$changed_count" "$max_changed_count" sed 's/^/- /' "$changed_files_file" - name: Initialize CodeGraph index for OpenCode - if: steps.central_review_process_fallback_scope.outputs.eligible != 'true' env: CODEGRAPH_PACKAGE: "@colbymchenry/codegraph@0.9.9" NPM_CONFIG_IGNORE_SCRIPTS: "true" @@ -1076,7 +1083,6 @@ jobs: npx -y "$CODEGRAPH_PACKAGE" status - name: Prepare bounded OpenCode review evidence - if: steps.central_review_process_fallback_scope.outputs.eligible != 'true' timeout-minutes: 40 env: GH_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN || steps.review_read_app_token.outputs.token || github.token }} @@ -1614,7 +1620,6 @@ jobs: wc -c "$OPENCODE_EVIDENCE_FILE" - name: Prepare isolated OpenCode review workspace - if: steps.central_review_process_fallback_scope.outputs.eligible != 'true' env: OPENCODE_REVIEW_WORKDIR: ${{ runner.temp }}/opencode-review-project OPENCODE_EVIDENCE_FILE: ${{ runner.temp }}/opencode-review-evidence.md @@ -2072,14 +2077,6 @@ jobs: "apiKey": "{env:STRIX_GITHUB_MODELS_TOKEN}" }, "models": { - "openai/gpt-4.1-mini": { - "name": "OpenAI GPT-4.1 Mini", - "tool_call": true, - "limit": { - "context": 1047576, - "output": 32768 - } - }, "openai/gpt-5": { "name": "OpenAI GPT-5", "tool_call": true, @@ -2274,9 +2271,7 @@ jobs: - name: Run OpenCode PR Review model pool id: opencode_review_model_pool - if: >- - needs.coverage-evidence.result == 'success' - && steps.central_review_process_fallback_scope.outputs.eligible != 'true' + if: needs.coverage-evidence.result == 'success' timeout-minutes: 285 env: STRIX_GITHUB_MODELS_TOKEN: ${{ secrets.STRIX_GITHUB_MODELS_TOKEN || github.token }} @@ -2285,7 +2280,7 @@ jobs: SHARE: "false" NPM_CONFIG_IGNORE_SCRIPTS: "true" NO_COLOR: "1" - OPENCODE_MODEL_CANDIDATES: "github-models/openai/gpt-4.1-mini github-models/openai/gpt-5-chat github-models/openai/gpt-5-mini github-models/openai/gpt-5-nano github-models/openai/o3 github-models/openai/o3-mini github-models/openai/o4-mini github-models/mistral-ai/mistral-medium-2505 github-models/meta/llama-4-maverick-17b-128e-instruct-fp8 github-models/meta/llama-4-scout-17b-16e-instruct" + OPENCODE_MODEL_CANDIDATES: "github-models/openai/o4-mini github-models/openai/o3-mini github-models/openai/gpt-5-mini github-models/openai/gpt-5-chat github-models/openai/o3 github-models/mistral-ai/mistral-medium-2505 github-models/openai/gpt-5-nano github-models/deepseek/deepseek-r1-0528 github-models/deepseek/deepseek-r1 github-models/deepseek/deepseek-v3-0324 github-models/meta/llama-4-maverick-17b-128e-instruct-fp8 github-models/meta/llama-4-scout-17b-16e-instruct" OPENCODE_MODEL_ATTEMPTS: "1" OPENCODE_RUN_TIMEOUT_SECONDS: "600" OPENCODE_EXPORT_TIMEOUT_SECONDS: "120" @@ -2644,7 +2639,6 @@ jobs: && ( needs.coverage-evidence.result != 'success' || steps.opencode_review_model_pool.outcome == 'success' - || steps.central_review_process_fallback_scope.outputs.eligible == 'true' ) timeout-minutes: 75 env: @@ -4648,143 +4642,6 @@ jobs: scripts/ci/collect_failed_check_evidence.sh "$evidence_file" } - approve_central_review_process_fallback() { - local pending_checks_file failed_checks_file unresolved_threads_file body wait_status - pending_checks_file="$(mktemp)" - failed_checks_file="$(mktemp)" - unresolved_threads_file="$(mktemp)" - - wait_status=0 - wait_for_peer_github_checks "$pending_checks_file" || wait_status=$? - if [ "$wait_status" -eq 1 ]; then - body="$(printf '%s\n' \ - "Central review-process fallback could not validate current-head peer checks." \ - "" \ - "- Result: CHECKS_LOOKUP_FAILED" \ - "- Required next evidence: readable current-head statusCheckRollup before fallback approval." \ - "- Head SHA: \`${HEAD_SHA}\`" \ - "- Workflow run: ${RUN_ID}" \ - "- Workflow attempt: ${RUN_ATTEMPT}" - )" - stop_approval_without_review "CHECKS_LOOKUP_FAILED" "$body" - elif [ "$wait_status" -ne 0 ]; then - body="$(printf '%s\n' \ - "Central review-process fallback is waiting for current-head peer checks before approval." \ - "" \ - "- Result: WAITING_FOR_CHECKS" \ - "- Head SHA: \`${HEAD_SHA}\`" \ - "- Workflow run: ${RUN_ID}" \ - "- Workflow attempt: ${RUN_ATTEMPT}" \ - "" \ - "Pending checks:" \ - "$(cat "$pending_checks_file")" - )" - hold_approval_without_review "WAITING_FOR_CHECKS" "$body" - fi - - if ! collect_github_checks_with_retry collect_failed_github_checks "$failed_checks_file"; then - body="$(printf '%s\n' \ - "Central review-process fallback could not validate current-head failed checks." \ - "" \ - "- Result: CHECKS_LOOKUP_FAILED" \ - "- Required next evidence: readable current-head failed-check state before fallback approval." \ - "- Head SHA: \`${HEAD_SHA}\`" \ - "- Workflow run: ${RUN_ID}" \ - "- Workflow attempt: ${RUN_ATTEMPT}" - )" - stop_approval_without_review "CHECKS_LOOKUP_FAILED" "$body" - fi - if [ -s "$failed_checks_file" ]; then - body="$(printf '%s\n' \ - "## Pull request overview" \ - "" \ - "Central review-process fallback found failed current-head peer checks and did not approve." \ - "" \ - "## Findings" \ - "" \ - "### 1. HIGH review checks:1 - Failed peer checks block fallback approval" \ - "- Problem: current-head peer GitHub Checks failed before central review-process fallback approval." \ - "- Root cause: fallback approval is only valid when coverage, security, and peer checks are all green." \ - "- Fix: inspect and fix the failed peer check evidence, then rerun the current-head checks." \ - "- Regression test: keep central fallback approval gated on an empty failed-check set." \ - "" \ - "## Failed Check Evidence" \ - "" \ - "$(cat "$failed_checks_file")" \ - "" \ - "- Result: REQUEST_CHANGES" \ - "- Head SHA: \`${HEAD_SHA}\`" \ - "- Workflow run: ${RUN_ID}" \ - "- Workflow attempt: ${RUN_ATTEMPT}" - )" - create_pull_review "REQUEST_CHANGES" "$body" - return 0 - fi - - if request_changes_for_merge_conflict_if_present; then - return 0 - fi - - if ! collect_unresolved_reviewer_threads "$unresolved_threads_file"; then - body="$(printf '%s\n' \ - "Central review-process fallback could not validate unresolved review threads." \ - "" \ - "- Result: REVIEW_THREAD_LOOKUP_FAILED" \ - "- Required next evidence: readable unresolved review-thread state before fallback approval." \ - "- Head SHA: \`${HEAD_SHA}\`" \ - "- Workflow run: ${RUN_ID}" \ - "- Workflow attempt: ${RUN_ATTEMPT}" - )" - stop_approval_without_review "REVIEW_THREAD_LOOKUP_FAILED" "$body" - fi - if [ -s "$unresolved_threads_file" ]; then - body="$(printf '%s\n' \ - "## Pull request overview" \ - "" \ - "Central review-process fallback found unresolved reviewer threads and did not approve." \ - "" \ - "## Findings" \ - "" \ - "### 1. HIGH review threads:1 - Unresolved reviewer feedback blocks fallback approval" \ - "- Problem: unresolved non-outdated review feedback is present on the current pull request." \ - "- Root cause: fallback approval is only valid after reviewer feedback is addressed, resolved, or outdated." \ - "- Fix: address or resolve the listed review thread(s), then rerun current-head review." \ - "- Regression test: keep central fallback approval gated on an empty unresolved-thread set." \ - "" \ - "## Thread Evidence" \ - "" \ - "$(cat "$unresolved_threads_file")" \ - "" \ - "- Result: REQUEST_CHANGES" \ - "- Head SHA: \`${HEAD_SHA}\`" \ - "- Workflow run: ${RUN_ID}" \ - "- Workflow attempt: ${RUN_ATTEMPT}" - )" - create_pull_review "REQUEST_CHANGES" "$body" - return 0 - fi - - body="$(printf '%s\n' \ - "## Pull request overview" \ - "" \ - "OpenCode approved this restricted trusted-automation update through the deterministic fallback path because the model pool was intentionally skipped for a narrow, allowlisted change scope." \ - "" \ - "## Summary" \ - "" \ - "- Result: APPROVE" \ - "- Reason: changed files matched the deterministic fallback allowlist; coverage evidence passed; peer GitHub Checks passed; mergeability and unresolved review-thread gates passed." \ - "- Fallback scope: ${CENTRAL_REVIEW_PROCESS_FALLBACK_SCOPE_LABEL:-unsupported}" \ - "- Changed-file count: ${CENTRAL_REVIEW_PROCESS_FALLBACK_CHANGED_COUNT:-unknown}" \ - "- Model path: skipped for deterministic fallback; provider delay or model-output unavailability is not review feedback." \ - "- Head SHA: \`${HEAD_SHA}\`" \ - "- Workflow run: ${RUN_ID}" \ - "- Workflow attempt: ${RUN_ATTEMPT}" \ - "" \ - "This fallback is limited to central OpenCode/Strix review-process files and the appguardrail org-security failure collector file set." - )" - create_pull_review "APPROVE" "$body" - } - live_head_sha="$(gh api -X GET "repos/${GH_REPOSITORY}/pulls/${PR_NUMBER}" --jq '.head.sha')" if [ "$live_head_sha" != "$HEAD_SHA" ]; then echo "stale OpenCode run: event head=${HEAD_SHA}, live head=${live_head_sha}; skipping review side effects." @@ -4799,11 +4656,6 @@ jobs: opencode_review_outcome="${OPENCODE_MODEL_POOL_OUTCOME:-unknown}" if [ "$opencode_review_outcome" != "success" ]; then - if [ "${CENTRAL_REVIEW_PROCESS_FALLBACK_ELIGIBLE:-false}" = "true" ]; then - approve_central_review_process_fallback - echo "::endgroup::" - exit 0 - fi stop_without_review_after_model_unavailable fi diff --git a/.github/workflows/pr-review-autofix.yml b/.github/workflows/pr-review-autofix.yml index 6240ff320..0adec9116 100644 --- a/.github/workflows/pr-review-autofix.yml +++ b/.github/workflows/pr-review-autofix.yml @@ -182,8 +182,8 @@ jobs: - name: Install OpenCode CLI env: - OPENCODE_VERSION: "1.16.0" - OPENCODE_SHA256: a741c43e737b2033f5e7ee151b162341e441034d6a64b172272a3f3a3729e87d + OPENCODE_VERSION: "1.17.13" + OPENCODE_SHA256: 157afa289d1a8d9372de0ce19ac726119b937a1f6b201808d46f06e4e59bb348 run: | set -euo pipefail archive="${RUNNER_TEMP}/opencode-linux-x64.tar.gz" diff --git a/.github/workflows/strix.yml b/.github/workflows/strix.yml index 766dacf8d..8a1b9d310 100644 --- a/.github/workflows/strix.yml +++ b/.github/workflows/strix.yml @@ -604,8 +604,10 @@ jobs: - name: Publish same-head manual Strix status if: ${{ always() && !cancelled() && github.event_name == 'workflow_dispatch' && github.event.inputs.pr_head_sha != '' }} env: - PRIMARY_STATUS_TOKEN: ${{ steps.target_app_token.outputs.token || secrets.OPENCODE_APPROVE_TOKEN || '' }} - FALLBACK_STATUS_TOKEN: ${{ github.token }} + TARGET_APP_STATUS_TOKEN: ${{ steps.target_app_token.outputs.token || '' }} + PR_REVIEW_MERGE_STATUS_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN || '' }} + OPENCODE_APPROVE_STATUS_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN || '' }} + GITHUB_STATUS_TOKEN: ${{ github.token }} TARGET_REPOSITORY: ${{ github.event.inputs.target_repository || github.repository }} PR_HEAD_SHA: ${{ github.event.inputs.pr_head_sha }} STRIX_RESULT: ${{ job.status }} @@ -632,21 +634,43 @@ jobs: esac post_strix_status() { - token="$1" + token_label="$1" + token="$2" if [ -z "$token" ]; then return 1 fi - GH_TOKEN="$token" gh api -X POST "repos/${TARGET_REPOSITORY}/statuses/${PR_HEAD_SHA}" \ + status_response="$(mktemp)" + status_error="$(mktemp)" + if GH_TOKEN="$token" gh api -X POST "repos/${TARGET_REPOSITORY}/statuses/${PR_HEAD_SHA}" \ -f state="$state" \ -f context="strix" \ -f description="$description" \ - -f target_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" + -f target_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" \ + >"$status_response" 2>"$status_error"; then + rm -f "$status_response" "$status_error" + echo "Published manual Strix status to ${TARGET_REPOSITORY}@${PR_HEAD_SHA} using ${token_label}." + return 0 + fi + error_summary="$(head -n 1 "$status_error" | tr -d '\r' || true)" + rm -f "$status_response" "$status_error" + if [ -n "$error_summary" ]; then + echo "::notice::Manual Strix status publish using ${token_label} did not succeed: ${error_summary}" + else + echo "::notice::Manual Strix status publish using ${token_label} did not succeed." + fi + return 1 } - if post_strix_status "$PRIMARY_STATUS_TOKEN"; then + if post_strix_status "target-app-token" "$TARGET_APP_STATUS_TOKEN"; then + exit 0 + fi + if post_strix_status "pr-review-merge-token" "$PR_REVIEW_MERGE_STATUS_TOKEN"; then + exit 0 + fi + if post_strix_status "opencode-approve-token" "$OPENCODE_APPROVE_STATUS_TOKEN"; then exit 0 fi - if [ "$TARGET_REPOSITORY" = "$GITHUB_REPOSITORY" ] && post_strix_status "$FALLBACK_STATUS_TOKEN"; then + if [ "$TARGET_REPOSITORY" = "$GITHUB_REPOSITORY" ] && post_strix_status "github-token" "$GITHUB_STATUS_TOKEN"; then exit 0 fi echo "::warning::Could not publish manual Strix status from scan job; keeping scan evidence result authoritative in the workflow run." @@ -728,8 +752,10 @@ jobs: - name: Publish same-head manual Strix status env: - PRIMARY_STATUS_TOKEN: ${{ steps.target_app_token.outputs.token || secrets.OPENCODE_APPROVE_TOKEN || '' }} - FALLBACK_STATUS_TOKEN: ${{ github.token }} + TARGET_APP_STATUS_TOKEN: ${{ steps.target_app_token.outputs.token || '' }} + PR_REVIEW_MERGE_STATUS_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN || '' }} + OPENCODE_APPROVE_STATUS_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN || '' }} + GITHUB_STATUS_TOKEN: ${{ github.token }} TARGET_REPOSITORY: ${{ github.event.inputs.target_repository || github.repository }} PR_HEAD_SHA: ${{ github.event.inputs.pr_head_sha }} STRIX_RESULT: ${{ needs.strix.result }} @@ -756,21 +782,43 @@ jobs: esac post_strix_status() { - token="$1" + token_label="$1" + token="$2" if [ -z "$token" ]; then return 1 fi - GH_TOKEN="$token" gh api -X POST "repos/${TARGET_REPOSITORY}/statuses/${PR_HEAD_SHA}" \ + status_response="$(mktemp)" + status_error="$(mktemp)" + if GH_TOKEN="$token" gh api -X POST "repos/${TARGET_REPOSITORY}/statuses/${PR_HEAD_SHA}" \ -f state="$state" \ -f context="strix" \ -f description="$description" \ - -f target_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" + -f target_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" \ + >"$status_response" 2>"$status_error"; then + rm -f "$status_response" "$status_error" + echo "Published manual Strix status to ${TARGET_REPOSITORY}@${PR_HEAD_SHA} using ${token_label}." + return 0 + fi + error_summary="$(head -n 1 "$status_error" | tr -d '\r' || true)" + rm -f "$status_response" "$status_error" + if [ -n "$error_summary" ]; then + echo "::notice::Manual Strix status publish using ${token_label} did not succeed: ${error_summary}" + else + echo "::notice::Manual Strix status publish using ${token_label} did not succeed." + fi + return 1 } - if post_strix_status "$PRIMARY_STATUS_TOKEN"; then + if post_strix_status "target-app-token" "$TARGET_APP_STATUS_TOKEN"; then + exit 0 + fi + if post_strix_status "pr-review-merge-token" "$PR_REVIEW_MERGE_STATUS_TOKEN"; then + exit 0 + fi + if post_strix_status "opencode-approve-token" "$OPENCODE_APPROVE_STATUS_TOKEN"; then exit 0 fi - if [ "$TARGET_REPOSITORY" = "$GITHUB_REPOSITORY" ] && post_strix_status "$FALLBACK_STATUS_TOKEN"; then + if [ "$TARGET_REPOSITORY" = "$GITHUB_REPOSITORY" ] && post_strix_status "github-token" "$GITHUB_STATUS_TOKEN"; then exit 0 fi echo "::warning::Could not publish manual Strix status from follow-up job; scan job publishes the authoritative status when target credentials are available." diff --git a/PR_GOVERNANCE_AUDIT.md b/PR_GOVERNANCE_AUDIT.md index 2fe3f68cc..daefb573a 100644 --- a/PR_GOVERNANCE_AUDIT.md +++ b/PR_GOVERNANCE_AUDIT.md @@ -131,7 +131,7 @@ governance contract. ## Live Repository Inventory -Live generated: 2026-06-26 KST via GitHub REST/GraphQL APIs. PR #28 post-merge refresh: 2026-06-23 16:05 KST. PR #37 post-merge refresh: 2026-06-23 21:50 KST. clearfolio PR #13 post-merge refresh: 2026-06-24 04:48 KST. Non-actionable Findings refresh: 2026-06-25 KST. PR #58, #65, #66, #68, #71, #79, and #80 post-merge refreshes: 2026-06-25 to 2026-06-26 KST. The current organization target inventory contains 12 public non-fork repositories, and the public fork inventory contains 6 repositories. `VibeSec` was not in that target set, and `appguardrail` was. +Live generated: 2026-06-26 KST via GitHub REST/GraphQL APIs. PR #28 post-merge refresh: 2026-06-23 16:05 KST. PR #37 post-merge refresh: 2026-06-23 21:50 KST. clearfolio PR #13 post-merge refresh: 2026-06-24 04:48 KST. Non-actionable Findings refresh: 2026-06-25 KST. PR #58, #65, #66, #68, #71, #79, and #80 post-merge refreshes: 2026-06-25 to 2026-06-26 KST. The 2026-07-02 13:21 KST refresh found 17 public non-fork repositories, adding `kaefa` and `waf-ids-ai-soc` to the prior public non-fork inventory. The public fork inventory still contains 6 repositories. `VibeSec` was not in that target set, and `appguardrail` was. Continuation snapshot: 2026-06-26 17:53 KST (`2026-06-26T08:53:00Z`). Every public non-fork target repository inherits org ruleset `18156473`, which requires @@ -151,28 +151,32 @@ onboarding exception before relying on autonomous PR queue draining. | Bucket | Repositories | Scheduler implication | |---|---|---| -| Public target repos with central required Strix, OpenCode, and scheduler | `.github`, `ContextualWisdomLab.github.io`, `appguardrail`, `bandscope`, `clearfolio`, `codec-carver`, `contextual-orchestrator`, `hyosung-itx-slogan-brief`, `naruon`, `newsdom-api`, `pg-erd-cloud`, `scopeweave` | Treat central required workflows as the rollout mechanism. Do not add repo-local copies only to satisfy governance. | -| Public target repos missing central required Strix, OpenCode, and scheduler | `aFIPC` | Do not drain or merge the PR queue until organization ruleset `18156473` targets the default branch and produces current-head central review evidence. | -| Public target repos with repo-local Strix/OpenCode/scheduler copies | `.github`, `ContextualWisdomLab.github.io`, `appguardrail`, `clearfolio`, `codec-carver`, `naruon`, `newsdom-api`, `pg-erd-cloud`, `scopeweave` | Retire thick local copies only after central required workflow runs prove stable for that repo's current heads. | -| Public target repos with partial or no local governance workflow footprint | `bandscope`, `contextual-orchestrator`, `hyosung-itx-slogan-brief` | They are still centrally governed by ruleset `18156473`; local absence is not a required-workflow gap. | +| Public target repos with central required Strix, OpenCode, and scheduler | `.github`, `ContextualWisdomLab.github.io`, `aFIPC`, `appguardrail`, `bandscope`, `clearfolio`, `codec-carver`, `contextual-orchestrator`, `fast-mlsirm`, `hyosung-itx-slogan-brief`, `kaefa`, `naruon`, `newsdom-api`, `pg-erd-cloud`, `scopeweave`, `semantic-data-portal`, `waf-ids-ai-soc` | Treat central required workflows as the rollout mechanism. Do not add repo-local copies only to satisfy governance. | +| Public target repos missing central required Strix, OpenCode, and scheduler ruleset inheritance | none observed on 2026-07-02 13:21 KST | Keep verifying inherited checks on current heads; do not reintroduce repo-local copies to compensate for stale PR evidence. `kaefa` is a runtime proof gap, not a missing-ruleset gap. | +| Public target repos with repo-local Strix/OpenCode/scheduler copies | `.github` only; this is the central source repository | Retire thick local copies outside `.github`; repository-owned product, release, and security workflows remain separate. | +| Public target repos with partial or no local governance workflow footprint | all public non-fork targets outside `.github` | They are still centrally governed by ruleset `18156473`; local absence is not a required-workflow gap. | | Private target repos missing central required workflow onboarding | `xtrmLLMBatchPython` | Treat missing central Strix/OpenCode/scheduler checks as an organization ruleset onboarding gap. Do not bypass review or weaken repository approval rules to drain the queue. | | Public forks | `argos`, `html4tree`, `nonnest2`, `seedream_evasepic`, `vooster`, `vooster-v2-mvp` | Fork status is not a categorical exclusion; onboarding is an explicit repository decision, and PR mutation remains capability-gated per head. | | Repo | Flow | Default | Auto | Central required workflows | Repo rules/protection | Repo required checks | Stale dismissal | Open PRs | Local workflow footprint | Recent merged actor | |---|---:|---:|---:|---|---|---|---:|---:|---|---| -| `ContextualWisdomLab/.github` | GitHub Flow | `main` | on | Strix; OpenCode; scheduler | `Lock default branch` | none | ruleset true | 25 | Copilot; OpenCode Review; PR Review Merge Scheduler; Strix Security Scan | #80 `seonghobae`; #79 `seonghobae`; #78 `seonghobae` | -| `ContextualWisdomLab/aFIPC` | GitHub Flow | `master` | off | missing on PR #78 | repo ruleset `PR` only | `check`, `quality`, `secret-and-workflow-audit` | ruleset false | 1 | CodeQL; Dependency Review; R-CMD-check; quality/security audit | #45 `seonghobae`; #43 `seonghobae`; #38 `seonghobae` | -| `ContextualWisdomLab/ContextualWisdomLab.github.io` | GitHub Flow | `main` | on | Strix; OpenCode; scheduler | `Lock default branch` | none | ruleset true | 9 | Copilot; OpenCode Review; PR Review Merge Scheduler; Strix Security Scan; Pages | #25 `seonghobae`; #15 `seonghobae`; #14 `seonghobae` | -| `ContextualWisdomLab/appguardrail` | Git Flow | `develop` | on | Strix; OpenCode; scheduler | `Lock default branch`, `PR` | none | mixed: true/false by repo ruleset | 0 | CodeQL; OpenCode Review; PR Review Merge Scheduler; release/security; Strix Security Scan | #133 `seonghobae`; #131 `seonghobae`; #115 `seonghobae` | -| `ContextualWisdomLab/bandscope` | Git Flow | `develop` | on | Strix; OpenCode; scheduler | `Lock default branch`; classic branch protection | `CodeQL`, `ci / build-and-test`, `dependency-review`, `gate / build / macos`, `gate / build / windows`, `release-preflight`, `sbom`, `security-audit`, `trivy-fs-scan` | ruleset true; classic false | 81 | OpenCode Review; PR Review Merge Scheduler; many app/security workflows | #451 `github-actions`; #459 `seonghobae`; #458 `seonghobae` | -| `ContextualWisdomLab/clearfolio` | GitHub Flow | `main` | off | Strix; OpenCode; scheduler | `PR` | none | ruleset false | 18 | CodeQL; OpenCode Review; PR Review Merge Scheduler; Strix Security Scan | #30 `seonghobae`; #29 `seonghobae`; #13 `seonghobae` | -| `ContextualWisdomLab/codec-carver` | GitHub Flow | `main` | on | Strix; OpenCode; scheduler | `Lock default branch` | none | ruleset true | 11 | Dependency Graph; OpenCode Review; PR Review Merge Scheduler; Strix Security Scan | #103 `github-actions`; #98 `seonghobae`; #97 `opencode-agent` | -| `ContextualWisdomLab/contextual-orchestrator` | GitHub Flow | `main` | off | Strix; OpenCode; scheduler | org central required workflows only | none | none | 0 | Dependabot Updates; Security | none | -| `ContextualWisdomLab/hyosung-itx-slogan-brief` | GitHub Flow | `main` | off | Strix; OpenCode; scheduler | `Do not delete any branches` | none | none | 0 | OpenCode Review; PR Review Merge Scheduler; PR Validation | #4 `seonghobae`; #3 `seonghobae`; #2 `seonghobae` | -| `ContextualWisdomLab/naruon` | Git Flow | `develop` | on | Strix; OpenCode; scheduler | `Lock default branch`, `PR`; classic branch protection | classic `opencode-review`, `strix` | ruleset true; classic true | 7 | Application CI; PR Governance; OpenCode Review; PR Review Merge Scheduler; Strix Gate Self-Test; Strix Security Scan | #760 `seonghobae`; #758 `seonghobae`; #757 `seonghobae` | -| `ContextualWisdomLab/newsdom-api` | Git Flow | `develop` | on | Strix; OpenCode; scheduler | `Lock default branch`, `mirror-classic-protection-main-develop` | `codeql (python, actions)`, `dependency-review`, `pytest`, `quality-gate`, `scorecard` | ruleset true | 6 | OpenCode Review; PR Review Merge Scheduler; Strix Security Scan; quality/security/release workflows | #203 `seonghobae`; #205 `seonghobae`; #206 `seonghobae` | -| `ContextualWisdomLab/pg-erd-cloud` | GitHub Flow | `main` | on | Strix; OpenCode; scheduler | `Lock default branch` | none | ruleset true | 15 | OpenCode Review; PR Review Autofix; PR Review Fix Scheduler; PR Review Merge Scheduler; Strix Security Scan | #247 `github-actions`; #246 `github-actions`; #239 `github-actions` | -| `ContextualWisdomLab/scopeweave` | Git Flow | `develop` | on | Strix; OpenCode; scheduler | `Lock default branch` | none | ruleset true | 11 | OpenCode Review; PR Review Merge Scheduler; Strix Gate Self-Test; Strix Security Scan; security/pages workflows | #124 `seonghobae`; #118 `seonghobae`; #116 `seonghobae` | +| `ContextualWisdomLab/.github` | GitHub Flow | `main` | on | Strix; OpenCode; scheduler | `Lock default branch` | none | ruleset true | 32 | central source workflows | #267 `github-actions`; #265 `github-actions`; #263 `github-actions` | +| `ContextualWisdomLab/aFIPC` | GitHub Flow | `master` | off | Strix; OpenCode; scheduler proven on PR #78 | repo ruleset `PR` plus org central required workflows | `check`, `quality`, `secret-and-workflow-audit` | ruleset false | 21 | CodeQL; Dependency Review; R-CMD-check; quality/security audit | #78 `seonghobae`; #45 `seonghobae`; #43 `seonghobae` | +| `ContextualWisdomLab/ContextualWisdomLab.github.io` | GitHub Flow | `main` | on | Strix; OpenCode; scheduler | `Lock default branch` | none | ruleset true | 19 | none | #25 `seonghobae`; #15 `seonghobae`; #14 `seonghobae` | +| `ContextualWisdomLab/appguardrail` | Git Flow | `develop` | on | Strix; OpenCode; scheduler | `Lock default branch`, `PR` | none | mixed: true/false by repo ruleset | 9 | release/security workflows | #133 `seonghobae`; #131 `seonghobae`; #115 `seonghobae` | +| `ContextualWisdomLab/bandscope` | Git Flow | `develop` | on | Strix; OpenCode; scheduler | `Lock default branch`; classic branch protection | `CodeQL`, `ci / build-and-test`, `dependency-review`, `gate / build / macos`, `gate / build / windows`, `release-preflight`, `sbom`, `security-audit`, `trivy-fs-scan` | ruleset true; classic false | 61 | app/security/release workflows | #451 `github-actions`; #459 `seonghobae`; #458 `seonghobae` | +| `ContextualWisdomLab/clearfolio` | GitHub Flow | `main` | off | Strix; OpenCode; scheduler | `PR` | none | ruleset false | 57 | none | #30 `seonghobae`; #29 `seonghobae`; #13 `seonghobae` | +| `ContextualWisdomLab/codec-carver` | GitHub Flow | `main` | on | Strix; OpenCode; scheduler | `Lock default branch` | none | ruleset true | 42 | none | #103 `github-actions`; #98 `seonghobae`; #97 `opencode-agent` | +| `ContextualWisdomLab/contextual-orchestrator` | GitHub Flow | `main` | off | Strix; OpenCode; scheduler | org central required workflows only | none | none | 2 | scorecard/security workflows | none | +| `ContextualWisdomLab/fast-mlsirm` | GitHub Flow | `main` | on | Strix; OpenCode; scheduler | `Lock default branch` | none | ruleset true | 25 | CI | #46 `github-actions`; #45 `github-actions`; #44 `github-actions` | +| `ContextualWisdomLab/hyosung-itx-slogan-brief` | GitHub Flow | `main` | off | Strix; OpenCode; scheduler | `Do not delete any branches` | none | none | 1 | validation workflow | #4 `seonghobae`; #3 `seonghobae`; #2 `seonghobae` | +| `ContextualWisdomLab/kaefa` | Git Flow | `develop` | on | ruleset inherited; current open PRs still need central required check proof | org central required workflows plus repo rulesets `Auto Review` and `PR` | R-CMD-check and dependency review workflows observed on PR #60 | repo ruleset present | 5 | R-CMD-check; dependency review | #51 `seonghobae`; #44 `seonghobae`; #42 `seonghobae` | +| `ContextualWisdomLab/naruon` | Git Flow | `develop` | on | Strix; OpenCode; scheduler | `Lock default branch`, `PR`; classic branch protection | central ruleset; repo-local application/security checks remain | ruleset true | 7 | application/governance/security workflows | #760 `seonghobae`; #758 `seonghobae`; #757 `seonghobae` | +| `ContextualWisdomLab/newsdom-api` | Git Flow | `develop` | on | Strix; OpenCode; scheduler | `Lock default branch`, `mirror-classic-protection-main-develop` | `codeql (python, actions)`, `dependency-review`, `pytest`, `quality-gate`, `scorecard` | ruleset true | 3 | quality/security/release workflows | #203 `seonghobae`; #205 `seonghobae`; #206 `seonghobae` | +| `ContextualWisdomLab/pg-erd-cloud` | GitHub Flow | `main` | on | Strix; OpenCode; scheduler | `Lock default branch` | none | ruleset true | 81 | app/security workflows | #247 `github-actions`; #246 `github-actions`; #239 `github-actions` | +| `ContextualWisdomLab/semantic-data-portal` | GitHub Flow | `main` | on | Strix; OpenCode; scheduler | `Lock default branch` | none | ruleset true | 2 | none | #3 `seonghobae`; #1 `seonghobae` | +| `ContextualWisdomLab/scopeweave` | Git Flow | `develop` | on | Strix; OpenCode; scheduler | `Lock default branch` | none | ruleset true | 2 | security/pages workflows | #124 `seonghobae`; #118 `seonghobae`; #116 `seonghobae` | +| `ContextualWisdomLab/waf-ids-ai-soc` | GitHub Flow | `main` | off | Strix; OpenCode; scheduler present on PR #6 | org central required workflows only | `rust` local CI plus central required checks | none | 1 | CI; scorecard | #5 `seonghobae`; #4 `seonghobae`; #3 `seonghobae` | | `ContextualWisdomLab/xtrmLLMBatchPython` | Git Flow | `develop` | off | missing | `PR` | none | ruleset false | 1 | A2Z compliance; CodeQL; dependency/security checks; no OpenCode/Strix/scheduler | #49 `seonghobae`; #47 `seonghobae`; #45 `seonghobae` | ## Current Gaps By Repo @@ -183,13 +187,15 @@ onboarding exception before relying on autonomous PR queue draining. | `bandscope` | Required checks are repo-specific and broad; keep GitHub native auto-merge as the check interpreter. PR #459 merged the REST mergeability guard downstream. Scheduler run `28192186833` proved two current contracts: PR #450 emitted concrete conflict repair guidance instead of retrying `update-branch`, and PR #451/#446 requested `update-branch` with the workflow `GITHUB_TOKEN`, producing new heads authored by `github-actions[bot]`. That run also exposed a post-update `ACTION_REQUIRED` state with no jobs, so the scheduler must report workflow approval/policy wait rather than a source failure when it recurs. Follow-up PR #460 was closed because it copied the central scheduler into `bandscope` and would preserve exactly the repo-local drift this rollout should remove. | | `clearfolio` | PR #13 is merged at `4bc17c6` after same-head manual Strix run `28051319530`, same-head manual OpenCode run `28051665082`, unresolved review threads `0`, and guarded merge against head `5fe1791`. Auto-merge remains off, so direct guarded merge is the repo path. | | `codec-carver` | PR #98 replaced the legacy scheduler with the central GitHub Actions path. Keep #94 as the historical negative sample because it used `opencode-agent` as a merge actor. | -| `contextual-orchestrator` | Now inherits central required Strix, OpenCode, and scheduler workflows, but it still has no repo-local default-branch lock, no repo-local PR review ruleset, auto-merge off, and no open PRs to prove runtime behavior. Use the next real PR as the onboarding fixture rather than treating inherited ruleset presence as behavioral proof. | -| `hyosung-itx-slogan-brief` | Now inherits central required Strix, OpenCode, and scheduler workflows. It has repo-local OpenCode Review and PR Review Merge Scheduler but no repo-local Strix copy, auto-merge is off, and the only repository ruleset prevents branch deletion. It should either stay a lightweight GitHub Flow repo with explicit manual merge expectations or adopt the standard default-branch lock contract before autonomous merge is expected. | +| `contextual-orchestrator` | Now inherits central required Strix, OpenCode, and scheduler workflows. The 2026-07-02 13:21 KST refresh found two open PRs, so those PRs are the next runtime fixtures for central evidence rather than another repo-local workflow copy. | +| `aFIPC` | The old target-coverage gap is closed. PR #78 merged after central `coverage-evidence`, `opencode-review`, `strix`, and `scan-pr-queue` all passed on head `b1ddafced86302f461e95259699f1efde5ec87c9`; the current queue is now a normal per-PR review/mergeability problem, not a ruleset target gap. | +| `hyosung-itx-slogan-brief` | Now inherits central required Strix, OpenCode, and scheduler workflows. Its default branch keeps only a repository validation workflow, auto-merge is off, and the only repository ruleset prevents branch deletion. It should either stay a lightweight GitHub Flow repo with explicit manual merge expectations or adopt the standard default-branch lock contract before autonomous merge is expected. | +| `kaefa` | Newly discovered public non-fork target at the 2026-07-02 13:21 KST refresh. It inherits org ruleset `18156473`, but current PR #60 status rollup showed only repo-local R-CMD-check, dependency-review, and CodeQL signals, with no central Strix/OpenCode/scheduler check runs. Treat it as an inherited-ruleset runtime proof gap until a new PR event or manual dispatch proves central checks on the current head. | | `naruon` | Canonical strict check source. PR #756 synced the central scheduler into `naruon`; its first head proved that widening `GITHUB_TOKEN` permissions to solve DX creates Scorecard and governance failures, so the merged rollout keeps minimal token permissions and defaults risky review-dispatch/auto-merge paths off. PR #721 remains the useful historical fixture for `BEHIND` handling: central dry-run selected `update_branch`, while the older repo-local workflow treated it as `wait`. Current PR #760 is clean, approved, and green on head `57a2f8e4`, so it is a merge-readiness sample; current dry-run with auto-merge disabled reports `wait`, as expected for the low-privilege scheduler profile. | | `newsdom-api` | Ruleset-required checks must stay GitHub-interpreted. PR #207 has merged, so it is no longer an update-branch proof candidate. The remaining open PRs #187, #203, #205, and #206 currently block because the current head has no OpenCode approval. | | `pg-erd-cloud` | Good GitHub Actions merge samples; keep autofix workflows repo-local. | | `scopeweave` | PR #127 is the current representative trace. Dry-run `28147098767` selected `auto_merge`, but live run `28147157319` failed with `GraphQL: Resource not accessible by integration (mergePullRequest)` because merge through GitHub Actions requires a contents-write mutation surface. Commit `6601953` proved the tempting fix, but Scorecard immediately opened a Token-Permissions review thread against job-level `contents: write`; follow-up commit `c5c5530` restores `contents: read` and keeps update-branch on the lower-privilege PR-write path. Current head `c5c5530` is clean, approved, and green; it remains unmerged because Actions-based merge is an explicit repo policy exception, not the default rollout. | -| `appguardrail` | Public organization repo discovered in the 2026-06-26 refresh. It follows Git Flow on `develop`, inherits the central required workflow ruleset, has local review/merge/Strix workflow names, and has no open PRs at the snapshot, so it is a clean onboarding target for the central contract rather than a proof fixture. | +| `appguardrail` | Public organization repo discovered in the 2026-06-26 refresh. It follows Git Flow on `develop`, inherits the central required workflow ruleset, has no default-branch local central-workflow copies, and has eight open PRs in the 2026-07-02 refresh, so it is now an active proof candidate rather than a zero-PR control repo. | | `xtrmLLMBatchPython` | Private repository discovered during PR queue draining on 2026-06-29. PR #50 is blocked by the repository-local one-approval rule because the only visible direct collaborator is also the PR author, and no current-head central OpenCode or Strix check exists. Add the private repository to the central required-workflow ruleset before continuing autonomous merges; do not force-merge and do not reduce the approval count to zero as a workaround. | ## Representative Evidence @@ -201,7 +207,7 @@ onboarding exception before relying on autonomous PR queue draining. | `.github` | PR #28 head `811446d` reached current-head approval after manual Strix run `28007326148` published a successful `strix` status and manual OpenCode run `28008174977` approved the same head; it was merged by `seonghobae` with merge commit `a025be1`. PR #49 then merged the explicit ban on generic failed-check deflections, and PR #58 removes remaining fallback/pending/check-lookup paths that could turn review-tool states into PR review Findings. | Same-head manual evidence for self-modifying trusted workflow changes, current-head OpenCode approval, unresolved thread check, `--match-head-commit` guarded merge, and non-actionable Findings rejection. | Treating stale PR-target failure logs as merge blockers after newer same-head evidence exists, or posting an evidence-mapping failure as a user-facing Finding. | | `pg-erd-cloud` | Recent PRs #236, #237, #239 were merged by `app/github-actions`. | GitHub Actions as mechanical merge actor with head guard. | Human-only queue draining. | | `codec-carver` | Recent PR #94 was merged by `app/opencode-agent`, while later PR #103 was merged by `github-actions`. | Native auto-merge path for current-head approved PRs. | OpenCode app as merge actor. | -| `appguardrail` | Current public organization repo with default `develop`, inherited central required workflows, local central workflow names, and no open PRs at snapshot time. | Use as a clean onboarding/control repo after central changes stabilize. | Treating zero open PRs as proof that the workflow behavior is already correct. | +| `appguardrail` | Current public organization repo with default `develop`, inherited central required workflows, no default-branch local central copies, and eight open PRs at the 2026-07-02 refresh. | Use as an active policy-vs-source review fixture after central changes stabilize. | Treating inherited workflow presence alone as proof that the PR queue is drainable. | ## DX/UX Transfer Decisions @@ -215,7 +221,7 @@ both separately; a change can improve one while harming the other. | `.github` | Same-head manual evidence and `--match-head-commit` make self-modifying workflow changes reviewable without pretending stale base-branch checks are current. | Stale `pull_request_target` failures, long polling review runs, and cancelled helper checks can become misleading review noise. | Serialize Strix before OpenCode, bound approval runtime, and require failed-check explanations instead of URL-only comments. | | `naruon` | Strict required checks, stale review dismissal, changed-file Mermaid flow DAGs, and current-head evidence make review evidence easier to audit. | Earlier repo-local scheduler drift had no update-branch path, no Strix-before-OpenCode sequencing, and no failed-check interpretation from the central script. Run `28073490721` also showed that an auto-merge permission failure can stop the whole queue before later PRs are inspected. PR #756 additionally showed that broadening workflow permissions is a tempting DX shortcut, but it degrades review trust and triggers Scorecard/governance failures. | Keep the implementation contract in `.github` required workflows, retire thick local copies only after central required runs prove stable, re-review every updated head, require an exact changed-file evidence path plus a Change Flow DAG before approval, keep `actions: read`/`contents: read` unless a separate privileged workflow is deliberately introduced, and record action failures per PR instead of aborting the scan. | | `pg-erd-cloud` | GitHub Actions bot merges with head guards give a clear mechanical actor for merges. | Repo-local autofix workflows are useful there, but centralizing autofix would widen mutation scope too far. | Keep GitHub Actions as the merge actor and leave autofix workflows repo-local. | -| `appguardrail` | Security-review subject matter makes it a useful place to verify that review automation distinguishes policy failure, tool failure, and source-code failure. | With no open PRs in the snapshot, it cannot yet prove update-branch or merge behavior. | Onboard central scheduler changes deliberately, then use the next real PR as a low-noise policy-vs-source review fixture. | +| `appguardrail` | Security-review subject matter makes it a useful place to verify that review automation distinguishes policy failure, tool failure, and source-code failure. | The live queue now has open PRs, so stale zero-PR assumptions can hide actual update-branch or merge behavior. | Use the current queue as a low-noise policy-vs-source review fixture after central checks are verified on each head. | | `bandscope` | Broad required checks encode repo-specific release, build, SBOM, and security expectations. | Copying the central scheduler into this repo turns one canonical contract into another repo-local drift surface. | Let GitHub native auto-merge and rulesets interpret required checks, and replace thick local governance files with a thin caller or organization required workflow. | | `newsdom-api` | Required quality gates and security checks give API changes stronger release evidence. | Central review comments that only point at failing check URLs do not help an API maintainer fix the failure. | Require failed-check root cause, source location when available, fix direction, and rerun command. | | `scopeweave` | Strix self-test and the central scheduler are useful rollout fixtures. Live scheduler run `28147157319` proved `action_error` is reported per PR instead of aborting the queue, and follow-up `c5c5530` shows the safer rollback when Scorecard rejects a broad token. | The scheduler could identify #127 as merge-ready, but enabling GitHub Actions merge by adding job-level `contents: write` triggered a Scorecard Token-Permissions thread. | Keep update-branch on `pull-requests: write` with `contents: read`; keep OpenCode read-only; require an explicit repo-level exception before letting the scheduler perform merge or auto-merge with `contents: write`. | @@ -223,8 +229,9 @@ both separately; a change can improve one while harming the other. | `codec-carver` | Existing native merge behavior can be retained once current-head evidence is clean. Recent `github-actions` merges show the desired mechanical actor is available. | Legacy OpenCode app-token merges create a second mechanical actor and weaken audit consistency. | Keep OpenCode out of mechanical merge authority and rely on the central GitHub Actions scheduler. | | `ContextualWisdomLab.github.io` | Site and documentation changes make reader-facing UX review concrete. | Review comments that say only that a check failed do not help the site reader or maintainer understand the issue. | Treat documentation clarity, homepage behavior, and status-check explanations as UX surfaces. | | `hyosung-itx-slogan-brief` | The repo now inherits the central required workflows and has local review/merge workflow names without heavier required checks, which makes it a lightweight GitHub Flow fixture. | It lacks the default-branch lock/stale-dismissal policy used by most organization repos. | Leave autonomous merge disabled unless that policy gap is intentional; otherwise add the standard default-branch lock before relying on autonomous merge. | -| `contextual-orchestrator` | It now inherits central required workflows without carrying local governance workflow copies, which is the desired no-copy posture. | With no local branch lock, no stale-dismissal policy, no auto-merge, and no open PRs, inherited checks alone do not prove useful runtime behavior. | Use the next real PR as a proof fixture; add a default-branch lock only if autonomous merge is desired. | -| `aFIPC` | It has real PR pressure and a domain-specific requirement: fixed parameter item calibration changes must reproduce true parameters before estimates can be trusted. | PR #78 shows the central required workflows are absent; the repo ruleset requires only local checks and zero approvals, so a direct merge would bypass the central review contract. | Add or repair the organization required-workflow ruleset target for `master`, then require current-head OpenCode approval, Strix, scheduler, and the true-parameter FIPC test before merging lower-number PRs. | +| `contextual-orchestrator` | It now inherits central required workflows without carrying local governance workflow copies, which is the desired no-copy posture. | With two open PRs now present, inherited checks alone still do not prove useful runtime behavior until those current heads are inspected. | Use the current open PRs as proof fixtures; add a default-branch lock only if autonomous merge is desired. | +| `aFIPC` | It has real PR pressure and a domain-specific requirement: fixed parameter item calibration changes must reproduce true parameters before estimates can be trusted. PR #78 now proves central required workflow coverage on `master`. | Several current PRs are still `DIRTY`, `BEHIND`, `BLOCKED`, or `CHANGES_REQUESTED`, so inherited workflow presence is not enough to drain the queue. | Keep central Strix/OpenCode/scheduler as the gate, then require current-head OpenCode approval, Strix, scheduler, and true-parameter FIPC tests before each merge. | +| `waf-ids-ai-soc` | Newly discovered public non-fork target with Rust CI and scorecard workflows. PR #6 already shows central `coverage-evidence`, `strix`, and `scan-pr-queue` check runs on head `43b62b5f347d1532c81b5ae38d8e41b4494fd486`, with OpenCode still in progress at the 2026-07-02 13:21 KST refresh. | It has no classic branch protection and auto-merge is off, so inherited required workflow presence is not enough to prove autonomous merge policy. | Keep as a GitHub Flow runtime proof fixture: require central OpenCode conclusion, Rust CI, Strix, scheduler, unresolved-thread check, and explicit merge actor evidence before treating it as migrated. | ## Current Scheduler Contract @@ -311,10 +318,9 @@ PR #381: wait: OpenCode review is already in progress when they are not part of the governance contract. `pg-erd-cloud` autofix stays repo-local; Strix, OpenCode review, and PR review/merge governance should not. -7. Use `contextual-orchestrator` as the no-copy onboarding fixture when it next - has a real PR. It now inherits central required workflows, but lacks - repo-local branch-lock/stale-dismissal policy and has no open PR to prove - runtime behavior. +7. Use `contextual-orchestrator` as the no-copy onboarding fixture on its + current open PR. It now inherits central required workflows without local + central workflow copies, but still needs current-head runtime proof. ## Remaining Proof Gaps @@ -347,7 +353,8 @@ PR #381: wait: OpenCode review is already in progress - `naruon` PR #756 completed the repo-local rollout for the scheduler contract. Its initial head failed backend governance and Scorecard because `actions: write`/`contents: write` were broader than the repo policy allows; the amended and merged head restores minimal `GITHUB_TOKEN` permissions, keeps `trigger_reviews` and `enable_auto_merge` defaulted off, keeps `update_branches` defaulted on, and still dry-runs PR #694/#721 as `update_branch`. - `update-branch` `422/403` now has a safe fixture: unit tests simulate both permission-denied and stale `expected_head_sha` failures, assert they become `action_error`, and assert later PRs are still inspected. A real live `422/403` case is still useful as operational evidence, but it is no longer missing from the decision contract test surface. - `bandscope` PR #378 exposed a self-referential failed-check loop after manual retry run `28155083916`: the retry run succeeded and approved step execution, but the check rollup still contained the cancelled older `OpenCode Review/opencode-review` run `28152862698`, so OpenCode posted current-head `CHANGES_REQUESTED` review `4569063977` with the banned generic `No deterministic missing-string markers...` text. The collector now excludes OpenCode's own check by check name and by both actual (`OpenCode Review`) and legacy (`OpenCode PR Review`) workflow names before failed-check fallback evidence is built. -- `aFIPC` PR #78 is the current negative fixture for target coverage drift: head `bc78373f59310b6fbee76d1a5a72fb3d84fc84eb` has local `check`, `quality`, and `secret-and-workflow-audit` checks, but no central `opencode-review`, `strix`, or `scan-pr-queue`; repository ruleset `12815994` requires zero approving reviews. This PR must not be merged until organization required-workflow evidence exists on the current head. +- `aFIPC` PR #78 is now the closed target-coverage fixture: it merged only after central `coverage-evidence`, `opencode-review`, `strix`, and `scan-pr-queue` passed on head `b1ddafced86302f461e95259699f1efde5ec87c9`. The remaining aFIPC queue should be handled as per-PR review, conflict, stale-branch, and domain-test work, not as a missing-ruleset blocker. +- The 2026-07-02 13:21 KST live inventory added `kaefa` and `waf-ids-ai-soc` to the public non-fork target set. Both inherit org ruleset `18156473`; `waf-ids-ai-soc` PR #6 already exposes central required workflow runs, while `kaefa` PR #60 did not expose central OpenCode, Strix, or scheduler check runs in its status rollup and remains a runtime proof gap. - Public repo drift is real, not hypothetical: only `.github` matched the central scheduler/workflow byte-for-byte in the 2026-06-26 scan. Some drift is policy-specific and should not be overwritten blindly, but `bandscope` had behaviorally unsafe drift and now has PR #459 merged downstream. - The previous drift response still over-indexed on copying. `bandscope` PR #460 proved the correction: even when the copied scheduler produced the right diff --git a/docs/org-required-workflow-rollout.md b/docs/org-required-workflow-rollout.md index a7572dd49..1461608a7 100644 --- a/docs/org-required-workflow-rollout.md +++ b/docs/org-required-workflow-rollout.md @@ -1,6 +1,6 @@ # ContextualWisdomLab central required workflow rollout -Updated: 2026-07-01 10:27 KST +Updated: 2026-07-02 13:21 KST ## Decision @@ -65,28 +65,32 @@ Do not centralize the scheduler by running a `.github` scheduled job against oth ## Scope -The active ruleset no longer maintains a repository-name allowlist. Live ruleset inspection on 2026-07-01 06:30 KST reports `repository_name.include=["~ALL"]`, so all current and future organization repositories inherit the three central required workflows on their default branch unless a later ruleset exclusion is added. The table below is an inventory snapshot and rollout ledger, not the ruleset target list. +The active ruleset no longer maintains a repository-name allowlist. Live +ruleset inspection on 2026-07-02 13:21 KST reports +`repository_name.include=["~ALL"]`, so all current and future organization +repositories inherit the three central required workflows on their default +branch unless a later ruleset exclusion is added. The table below is the public +non-fork inventory snapshot and rollout ledger, not the ruleset target list. | Repository | Visibility | Default branch | Flow | Open PRs | Local central-workflow copies on default branch | Rollout status | | --- | --- | --- | --- | ---: | --- | --- | -| `ContextualWisdomLab/.github` | public | `main` | GitHub Flow | 23 | central source; keep | single source of truth; PRs through `#249` merged | -| `ContextualWisdomLab/appguardrail` | public | `develop` | Git Flow | 7 | none | migrated; re-verify inherited checks before final closure | -| `ContextualWisdomLab/bandscope` | public | `develop` | Git Flow | 78 | none | no local central copies observed; verify inherited checks on active PRs | -| `ContextualWisdomLab/clearfolio` | public | `main` | GitHub Flow | 50 | none | migrated; re-verify inherited checks before final closure | -| `ContextualWisdomLab/codec-carver` | public | `main` | GitHub Flow | 38 | none | local workflows already gone; quality uplift still needs 100% test/docstring evidence before closure | -| `ContextualWisdomLab/contextual-orchestrator` | public | `main` | GitHub Flow | 0 | none | default branch has no local central copies; no open PR evidence to verify | +| `ContextualWisdomLab/.github` | public | `main` | GitHub Flow | 32 | central source; keep | single source of truth; central PRs through `#267` merged | +| `ContextualWisdomLab/aFIPC` | public | `master` | GitHub Flow | 21 | none | central checks proven on PR `#78`; active queue still needs per-PR review | +| `ContextualWisdomLab/pg-erd-cloud` | public | `main` | GitHub Flow | 81 | none | repo-local autofix worker removed by PR `#393`; default branch now keeps only repository-owned application and security workflows | +| `ContextualWisdomLab/fast-mlsirm` | public | `main` | GitHub Flow | 25 | none | migrated; re-verify inherited checks on current open PRs | +| `ContextualWisdomLab/bandscope` | public | `develop` | Git Flow | 61 | none | no local central copies observed; verify inherited checks on active PRs | +| `ContextualWisdomLab/contextual-orchestrator` | public | `main` | GitHub Flow | 2 | none | default branch has no local central copies; current open PRs are runtime proof fixtures | +| `ContextualWisdomLab/naruon` | public | `develop` | Git Flow | 7 | none | default branch has no repo-local OpenCode, Strix, or scheduler copies; application/security workflows remain repository-owned | +| `ContextualWisdomLab/newsdom-api` | public | `develop` | Git Flow | 3 | none | local workflows already gone; re-verify inherited checks on current open PRs | +| `ContextualWisdomLab/appguardrail` | public | `develop` | Git Flow | 9 | none | migrated; re-verify inherited checks before final closure | +| `ContextualWisdomLab/scopeweave` | public | `develop` | Git Flow | 2 | none | local workflows already gone; re-verify inherited checks on current open PRs | | `ContextualWisdomLab/ContextualWisdomLab.github.io` | public | `main` | GitHub Flow | 19 | none | migrated; re-verify inherited checks on current open PRs | -| `ContextualWisdomLab/fast-mlsirm` | public | `main` | GitHub Flow | 11 | none | migrated; re-verify inherited checks on current open PRs | -| `ContextualWisdomLab/hyosung-itx-slogan-brief` | public | `main` | GitHub Flow | 1 | none | migrated; re-verify inherited checks on current open PR | -| `ContextualWisdomLab/naruon` | public | `develop` | Git Flow | 47 | none | default branch has no repo-local OpenCode, Strix, or scheduler copies; application/security workflows remain repository-owned | -| `ContextualWisdomLab/newsdom-api` | public | `develop` | Git Flow | 1 | none | local workflows already gone; re-verify inherited checks on current open PR | -| `ContextualWisdomLab/pg-erd-cloud` | public | `main` | GitHub Flow | 85 | none | repo-local autofix worker removed by PR `#393`; default branch now keeps only repository-owned application and security workflows | -| `ContextualWisdomLab/scopeweave` | public | `develop` | Git Flow | 0 | none | local workflows already gone; no open PR evidence to verify | +| `ContextualWisdomLab/codec-carver` | public | `main` | GitHub Flow | 42 | none | local workflows already gone; quality uplift still needs 100% test/docstring evidence before closure | +| `ContextualWisdomLab/clearfolio` | public | `main` | GitHub Flow | 57 | none | migrated; re-verify inherited checks before final closure | | `ContextualWisdomLab/semantic-data-portal` | public | `main` | GitHub Flow | 2 | none | PR `#3` merged; default branch has no local central copies | -| `ContextualWisdomLab/aFIPC` | private | `master` | GitHub Flow | 17 | none | ruleset target includes this repo; verify inherited checks on active PRs | -| `ContextualWisdomLab/linux-cluster-ops` | private | `develop` | Git Flow | 71 | none | ruleset target includes this repo; verify inherited checks on active PRs | -| `ContextualWisdomLab/noema` | private | `main` | GitHub Flow | 1 | none | ruleset target includes this repo; verify inherited checks on active PR | -| `ContextualWisdomLab/xtrmLLMBatchPython` | private | `develop` | Git Flow | 28 | none | ruleset target includes this repo; verify inherited checks on active PRs | +| `ContextualWisdomLab/hyosung-itx-slogan-brief` | public | `main` | GitHub Flow | 1 | none | migrated; re-verify inherited checks on current open PR | +| `ContextualWisdomLab/kaefa` | public | `develop` | Git Flow | 5 | none | newly discovered public non-fork target; ruleset inherited but current PR #60 lacked central check runs in status rollup | +| `ContextualWisdomLab/waf-ids-ai-soc` | public | `main` | GitHub Flow | 1 | none | newly discovered public non-fork target; PR #6 shows central required workflow runs on current head | ## Current policy @@ -105,6 +109,7 @@ The active ruleset no longer maintains a repository-name allowlist. Live ruleset - On 2026-06-30 08:33 KST, organization ruleset `18156473` was changed from an explicit repository-name list to `repository_name.include=["~ALL"]` while keeping `ref_name.include=["~DEFAULT_BRANCH"]` and the same three central required workflow paths from `.github@refs/heads/main`. - On 2026-07-01 02:52 KST, ruleset `18156473` still reported `enforcement=active`, `repository_name.include=["~ALL"]`, `ref_name.include=["~DEFAULT_BRANCH"]`, and the three required workflow paths from `ContextualWisdomLab/.github@refs/heads/main`. - On 2026-07-01 06:30 KST, organization ruleset `18156473` still reported `enforcement=active`, `repository_name.include=["~ALL"]`, `ref_name.include=["~DEFAULT_BRANCH"]`, and the three required workflow paths from `ContextualWisdomLab/.github@refs/heads/main`. +- On 2026-07-02 07:25 KST, organization ruleset `18156473` still reported `enforcement=active`, `repository_name.include=["~ALL"]`, `ref_name.include=["~DEFAULT_BRANCH"]`, and the same three required workflow paths from `ContextualWisdomLab/.github@refs/heads/main`. - `.github` PR `#225` raised high reasoning effort for all reasoning-capable OpenCode review model definitions and merged at `50c6ef82f52af3eeb0e58c174902fc9855c36682`. - `.github` PR `#226` stopped the merge scheduler from treating old deterministic fallback approval bodies as current-head approval evidence and merged at `57a1fa580731a0f76b31dcf29a597c5715dba2fd`. - `.github` PR `#230` added changed-file candidates to merge-conflict guidance so `DIRTY` or `CONFLICTING` PRs name the first files to inspect instead of giving only generic conflict instructions. It merged at `0cab5c8d46e88c1a3f68ef3f71b5d44d971cd2ef`. @@ -120,11 +125,14 @@ The active ruleset no longer maintains a repository-name allowlist. Live ruleset - `.github` PR `#249` guarded the central PR Review Fix Scheduler so `CHANGES_REQUESTED` review states dispatch the central autofix worker only when the latest OpenCode review is on the current head, the merge state is `CLEAN` or `HAS_HOOKS`, and the review body does not indicate process-only blockers such as merge conflict, model-pool exhaustion, unresolved human review threads, failed checks, `coverage-evidence`, or failed Strix evidence. It merged at `dbd33b3a0384de0129aa082a210383188d012415` after current-head `coverage-evidence`, `strix`, `opencode-review`, `noema-review`, and `scan-pr-queue` all completed successfully. - `.github` PR `#255` removed the remaining deterministic low-risk approval fallback from the OpenCode approval gate and changed `coverage-evidence` blocker handling to publish a `REQUEST_CHANGES` review event, producing the PR review state `CHANGES_REQUESTED`, instead of leaving only a failed check/log. It merged at `e2beae72b87a8817cd57f9f51bab3947353baa61`; the first current-head OpenCode run reached an `APPROVE` gate result but hit the OpenCode GitHub App installation rate limit while publishing the review, then a rerun published approval and native auto-merge completed. - After PR `#255` merged, `ContextualWisdomLab/bandscope` PRs `#493`, `#494`, `#495`, and `#500` were rechecked for branch freshness. Merge simulation against `develop` found real conflicts rather than update-branch candidates: `#493` conflicts in `apps/desktop/src/App.tsx` plus the design-system docs, while `#494`, `#495`, and `#500` conflict in `docs/design-system/README.md`, `docs/design-system/component-contract.md`, and `docs/design-system/figma-to-code-workflow.md`. Each PR received a corrected conflict-resolution comment with the exact file list and merge/rebase repair commands. +- `ContextualWisdomLab/aFIPC` PR `#78` is no longer a target-coverage gap. It merged after current-head central `coverage-evidence`, `opencode-review`, `strix`, and `scan-pr-queue` checks all passed on head `b1ddafced86302f461e95259699f1efde5ec87c9`; the OpenCode review approved the same head on 2026-06-30 06:02:55Z. - `ContextualWisdomLab/pg-erd-cloud` PR `#393` removed the repo-local `pr-review-autofix.yml` worker after the central autofix worker merged. The first OpenCode run on head `9d8eed5be47670b1b46f413295d9a6044d7327b2` exhausted the older model pool and requested changes. After `.github` PR `#246` merged, central OpenCode run `28485070313` approved the same head and the PR merged at `1e0d6a3dda5ea9afcd74dcd8380689672e1c8ef1` on 2026-07-01 00:33:50Z. Live default-branch content lookup returned 404 for `.github/workflows/pr-review-autofix.yml` after merge. -- Live non-fork inventory on 2026-07-01 06:30 KST found inherited ruleset `18156473` on every listed repository and no default-branch copies of `opencode-review.yml`, `strix.yml`, or `pr-review-merge-scheduler.yml` outside `.github`. +- Live non-fork inventory on 2026-07-02 13:21 KST found 17 public non-fork repositories, inherited ruleset `18156473` on `kaefa` and `waf-ids-ai-soc`, and no default-branch copies of `opencode-review.yml`, `strix.yml`, or `pr-review-merge-scheduler.yml` outside `.github`. +- `ContextualWisdomLab/waf-ids-ai-soc` PR `#6` current head `43b62b5f347d1532c81b5ae38d8e41b4494fd486` showed central `coverage-evidence`, `strix`, and `scan-pr-queue` check runs plus local Rust CI; `opencode-review` was still in progress at the 2026-07-02 13:21 KST refresh. +- `ContextualWisdomLab/kaefa` inherits ruleset `18156473`, but PR `#60` current head `13c9089855fcdd34391173560ccf6935bac1eebe` showed only repo-local R-CMD-check, dependency-review, and CodeQL signals in status rollup. Treat this as a runtime proof gap until a new PR event or manual dispatch proves central OpenCode, Strix, and scheduler checks on a kaefa current head. - `.github` scheduler default merge mode is now `direct_or_auto`: approved same-repository `CLEAN` PRs request immediate guarded merge, approved non-clean same-repository PRs can queue native auto-merge, and fork or external-head PRs are left for maintainer merge. - OpenCode approval runs the trusted central merge scheduler script directly with `pr_number` and `max_prs=1`, so the just-reviewed PR is inspected immediately even when organization required workflows are not repo-local `workflow_dispatch` targets. - `.github` PR `#74` changed OpenCode review model order to DeepSeek R1 first and added a catalog fallback pool. @@ -147,7 +155,7 @@ The active ruleset no longer maintains a repository-name allowlist. Live ruleset - The organization ruleset API reports the central required workflows ruleset as `active` and inherited by each public non-fork target repository. - `.github` PR `#100` added required-workflow job rerun support and cancels older same-PR OpenCode runs before retrying the current head. Local verification on head `3c62c37a4deabdb0c6ed4ddf0951c1987f09866b`: `pytest -q` passed 38 tests, `coverage report --fail-under=100` reported 100%, `interrogate --fail-under=100 .` reported 100%. - `.github` PR `#100` merged at 2026-06-29 05:45 KST with merge commit `81408f3dbe0a3c43dc4b76133f72a5e314df8a10`. A follow-up admin check should verify organization ruleset `18156473` is no longer pinned to `refs/heads/codex/rerun-required-opencode-job`. -- On 2026-06-29 16:33 KST, `ContextualWisdomLab/aFIPC` PR `#78` proved a target coverage gap: PR `#78` lacks inherited OpenCode, Strix, and scheduler required-workflow checks. The PR had local `check`, `quality`, and `secret-and-workflow-audit` check runs, and repository ruleset `PR` (`12815994`) required only those three local checks with zero required approvals. +- The earlier 2026-06-29 KST `aFIPC` PR `#78` target-coverage gap is closed. A later current-head run on `b1ddafced86302f461e95259699f1efde5ec87c9` produced central `coverage-evidence`, `opencode-review`, `strix`, and `scan-pr-queue` success before merge. - `.github` PR `#136` changed approved stale PR handling so `BEHIND` branches are updated before failed-check or `ACTION_REQUIRED` decisions disable auto-merge. - `.github` PR `#137` made the central `PR Review Fix Scheduler` target-repository aware through `workflow_call`, `workflow_dispatch`, schedule, and `.github` repository variables. `.github` variables currently target `ContextualWisdomLab/pg-erd-cloud` on `main`. The follow-up central autofix worker makes `ContextualWisdomLab/.github` the default `autofix_repository`, so target repositories no longer need to copy a full `pr-review-autofix.yml` worker to participate. - `.github` PR `#138` added compare-API branch freshness evidence so approved PRs with auto-merge enabled can still receive `update-branch` when GitHub reports `BLOCKED` but the base branch is ahead. Local verification passed `pytest -q`, scheduler self-test, `py_compile`, 100% coverage, 100% docstring coverage, `actionlint`, `bash -n`, and `git diff --check`. diff --git a/opencode.jsonc b/opencode.jsonc index b3d4b30a2..85298a197 100644 --- a/opencode.jsonc +++ b/opencode.jsonc @@ -122,14 +122,6 @@ "apiKey": "{env:STRIX_GITHUB_MODELS_TOKEN}" }, "models": { - "openai/gpt-4.1-mini": { - "name": "OpenAI GPT-4.1 Mini", - "tool_call": true, - "limit": { - "context": 1047576, - "output": 32768 - } - }, "openai/gpt-5": { "name": "OpenAI GPT-5", "tool_call": true, diff --git a/scripts/ci/assert_opencode_reasoning_effort.py b/scripts/ci/assert_opencode_reasoning_effort.py index 938c541e2..cee898619 100644 --- a/scripts/ci/assert_opencode_reasoning_effort.py +++ b/scripts/ci/assert_opencode_reasoning_effort.py @@ -47,11 +47,15 @@ def validate_candidate(config: dict[str, Any], candidate: str) -> list[str]: except ValueError as exc: return [str(exc)] - if not config_for_model: + if not config_for_model and ( + provider == "github-models" or is_known_reasoning_capable(model_name) + ): return [ f"OpenCode candidate {candidate} is not defined in opencode.jsonc " f"under provider {provider}." ] + if not config_for_model: + return [] configured_reasoning = config_for_model.get("reasoning") is True should_require_effort = configured_reasoning or is_known_reasoning_capable(model_name) diff --git a/scripts/ci/collect_failed_check_evidence.sh b/scripts/ci/collect_failed_check_evidence.sh index be85e2aa1..1b420a423 100755 --- a/scripts/ci/collect_failed_check_evidence.sh +++ b/scripts/ci/collect_failed_check_evidence.sh @@ -408,6 +408,27 @@ gh api graphql \ | @tsv ' >"$manual_success_check_runs" +env HEAD_SHA="$HEAD_SHA" gh run list \ + --repo "$GH_REPOSITORY" \ + --workflow strix.yml \ + --commit "$HEAD_SHA" \ + --limit 200 \ + --json databaseId,workflowName,status,conclusion,url,event,headSha \ + --jq ' + .[] + | select((.event // "") == "workflow_dispatch") + | select((.headSha // "") == env.HEAD_SHA) + | select((.workflowName // "") == "Strix Security Scan" or (.workflowName // "") == "Strix") + | select((.status // "") == "completed") + | select((.conclusion // "" | ascii_downcase) == "success") + | [ + "strix", + (.url // ""), + "Manual workflow_dispatch Strix evidence passed" + ] + | @tsv + ' >>"$manual_success_check_runs" || true + env HEAD_SHA="$HEAD_SHA" gh run list \ --repo "$GH_REPOSITORY" \ --commit "$HEAD_SHA" \ diff --git a/scripts/ci/run_opencode_review_model_pool.sh b/scripts/ci/run_opencode_review_model_pool.sh index 10092aba2..87d9da165 100644 --- a/scripts/ci/run_opencode_review_model_pool.sh +++ b/scripts/ci/run_opencode_review_model_pool.sh @@ -41,6 +41,7 @@ write_prompt() { local prompt_file="$2" local intro local contract_file + local evidence_excerpt_file if [ -n "${OPENCODE_REVIEW_INTRO:-}" ]; then intro="$OPENCODE_REVIEW_INTRO" @@ -48,6 +49,7 @@ write_prompt() { intro="Review PR #\${PR_NUMBER} in \${OPENCODE_SOURCE_WORKDIR} with \${model_candidate}." fi contract_file="$OPENCODE_REVIEW_WORKDIR/opencode-review-contract-${model_candidate//\//-}.md" + evidence_excerpt_file="$OPENCODE_REVIEW_WORKDIR/bounded-review-evidence-excerpt.md" cp "$GITHUB_WORKSPACE/scripts/ci/opencode_review_prompt_template.md" "$contract_file" OPENCODE_REVIEW_INTRO="$intro" \ PROMPT_MODEL_CANDIDATE="$model_candidate" \ @@ -55,16 +57,21 @@ write_prompt() { { printf '%s\n\n' "$intro" - printf 'Read and follow the complete review contract in `%s` before producing the final review.\n' "$contract_file" - printf 'Read bounded review evidence from `%s` and source files from `%s`.\n' "$OPENCODE_EVIDENCE_FILE" "$OPENCODE_SOURCE_WORKDIR" + printf 'Follow the complete review contract in `%s`; use this launcher as a packet-first entry point, not as a reduced policy.\n' "$contract_file" + printf 'Read bounded review evidence from `%s` and source files from `%s` when tool access works.\n' "$OPENCODE_EVIDENCE_FILE" "$OPENCODE_SOURCE_WORKDIR" printf 'Use the trusted review workspace `%s` for scripts, prompts, policy files, CodeGraph config, and validation helpers.\n\n' "$OPENCODE_REVIEW_WORKDIR" - printf 'Do not treat this compact launcher as a reduced review policy. It exists only to avoid provider context-window overflow; the contract file remains authoritative.\n' - printf 'Mandatory first actions: read the review contract, read bounded-review-evidence.md/evidence paths, inspect changed files and focused related code, use the configured structural/search tools required by the contract, then run safe verification where applicable.\n' + printf 'First review the current-head evidence excerpt in this prompt. Then inspect full evidence, changed files, focused related code, and configured structural/search tools when available.\n' + printf 'If tool calls or file reads are unavailable, do not emit progress notes or raw tool-call text. Finish from the inlined evidence packet only when it contains enough changed-file, hunk, coverage, check, and thread evidence; otherwise return REQUEST_CHANGES with a concrete missing-evidence finding tied to the absent evidence, not a generic model-exhaustion message.\n' printf 'Always return a final control block instead of a progress summary. Return only the final review body.\n\n' printf 'Required control block shape:\n' printf '```json\n' printf '{"head_sha":"%s","run_id":"%s","run_attempt":"%s","result":"APPROVE or REQUEST_CHANGES","reason":"short reason","summary":"short review summary with concrete evidence and all required labels","findings":[]}\n' "$HEAD_SHA" "$RUN_ID" "$RUN_ATTEMPT" printf '```\n' + if [ -s "$evidence_excerpt_file" ]; then + printf '\nCurrent-head evidence packet:\n\n' + cat "$evidence_excerpt_file" + printf '\n' + fi } >"$prompt_file" } diff --git a/scripts/ci/strix_quick_gate.sh b/scripts/ci/strix_quick_gate.sh index 815a43e4d..63e8a2398 100755 --- a/scripts/ci/strix_quick_gate.sh +++ b/scripts/ci/strix_quick_gate.sh @@ -3402,9 +3402,9 @@ is_model_retryable_error() { fi if is_timeout_error; then - if provider_signal_fail_closed_enabled; then - return 1 - fi + # Process and provider timeouts are not clean evidence, but they are + # recoverable across distinct fallback models. Strict provider-signal + # mode still fails closed after fallback exhaustion or partial reports. return 0 fi diff --git a/scripts/ci/test_strix_quick_gate.sh b/scripts/ci/test_strix_quick_gate.sh index 6d3c63a1a..ac3a5ab3b 100755 --- a/scripts/ci/test_strix_quick_gate.sh +++ b/scripts/ci/test_strix_quick_gate.sh @@ -402,6 +402,9 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() { assert_file_contains "$workflow_file" "failed-check-evidence.md" "opencode review copies full failed-check evidence into the isolated workspace" assert_file_contains "$workflow_file" "Resolve trusted OpenCode source ref" "opencode required workflow resolves the central trusted source ref" assert_file_contains "$workflow_file" "github.workflow_ref" "opencode required workflow can reuse the required-workflow source ref" + assert_file_contains "$workflow_file" 'if [ -n "$INPUT_CANONICAL_REF" ]; then' "opencode manual dispatch canonical_ref overrides the workflow source ref for PR-head bootstrap" + assert_file_contains "$workflow_file" 'trusted_ref="$INPUT_CANONICAL_REF"' "opencode manual dispatch can force a trusted branch ref before checkout" + assert_file_not_contains "$workflow_file" 'trusted_ref="${INPUT_CANONICAL_REF:-main}"' "opencode canonical_ref must not be overwritten by github.workflow_ref when explicitly provided" assert_file_contains "$workflow_file" "Checkout trusted OpenCode review workflow" "opencode review checks out central trusted workflow scripts before processing PR data" assert_file_contains "$workflow_file" "Checkout trusted OpenCode coverage contract" "opencode coverage job uses central trusted coverage tooling instead of target-repo copies" assert_file_contains "$workflow_file" 'R_LIBS_USER="${RUNNER_TEMP}/R-library"' "opencode R coverage installs packages into a writable runner user library" @@ -505,7 +508,15 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() { assert_file_contains "$REPO_ROOT/scripts/ci/run_opencode_review_model_pool.sh" "assert_opencode_reasoning_effort.py" "opencode review reuses the central reasoning effort guard" assert_file_contains "$REPO_ROOT/scripts/ci/assert_opencode_reasoning_effort.py" "options.reasoningEffort=high" "opencode review requires high reasoning effort in opencode.jsonc for capable models" assert_file_contains "$workflow_file" '--config "$OPENCODE_REVIEW_WORKDIR/opencode.jsonc"' "failed-check diagnosis also validates high reasoning effort before running a capable model" - assert_file_contains "$REPO_ROOT/scripts/ci/run_opencode_review_model_pool.sh" "Read and follow the complete review contract" "opencode review uses a compact launcher while keeping the full review contract on disk" + assert_file_contains "$workflow_file" 'OPENCODE_VERSION: "1.17.13"' "opencode review pins a runtime with reliable OpenAI-compatible reasoning setting support" + assert_file_contains "$workflow_file" "OPENCODE_SHA256: 157afa289d1a8d9372de0ce19ac726119b937a1f6b201808d46f06e4e59bb348" "opencode review verifies the pinned runtime archive" + assert_file_contains "$REPO_ROOT/.github/workflows/pr-review-autofix.yml" 'OPENCODE_VERSION: "1.17.13"' "opencode autofix pins the same reasoning-capable runtime" + assert_file_contains "$REPO_ROOT/.github/workflows/pr-review-autofix.yml" "OPENCODE_SHA256: 157afa289d1a8d9372de0ce19ac726119b937a1f6b201808d46f06e4e59bb348" "opencode autofix verifies the pinned runtime archive" + assert_file_not_contains "$workflow_file" 'OPENCODE_VERSION: "1.16.0"' "opencode review must not regress to a runtime without the reasoning-setting fix" + assert_file_not_contains "$REPO_ROOT/.github/workflows/pr-review-autofix.yml" 'OPENCODE_VERSION: "1.16.0"' "opencode autofix must not regress to a runtime without the reasoning-setting fix" + assert_file_contains "$REPO_ROOT/scripts/ci/run_opencode_review_model_pool.sh" "Follow the complete review contract" "opencode review keeps the full review contract on disk" + assert_file_contains "$REPO_ROOT/scripts/ci/run_opencode_review_model_pool.sh" "Current-head evidence packet" "opencode review inlines bounded current-head evidence before requiring tool reads" + assert_file_contains "$REPO_ROOT/scripts/ci/run_opencode_review_model_pool.sh" "not a generic model-exhaustion message" "opencode review tells models to return concrete missing-evidence findings instead of progress-only output" assert_file_contains "$REPO_ROOT/scripts/ci/run_opencode_review_model_pool.sh" "tokens_limit_reached" "opencode review detects provider context-window overflow" assert_file_contains "$REPO_ROOT/scripts/ci/run_opencode_review_model_pool.sh" "skipping remaining attempts for this model" "opencode review skips same-model retries after context-window overflow" assert_file_contains "$workflow_file" 'timeout-minutes: 360' "opencode review target uses the maximum GitHub-hosted runner timeout" @@ -518,7 +529,7 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() { assert_file_contains "$workflow_file" 'OPENCODE_MODEL_ATTEMPTS: "1"' "opencode fallback tries the catalog promptly instead of spending the entire review on one model" assert_file_contains "$workflow_file" "Run OpenCode PR Review model pool" "opencode review includes a broad catalog fallback pool" assert_file_contains "$workflow_file" "steps.opencode_review_model_pool.outcome == 'success'" "opencode model step must succeed before review publication" - assert_file_contains "$workflow_file" "github-models/openai/gpt-4.1-mini github-models/openai/gpt-5-chat github-models/openai/gpt-5-mini github-models/openai/gpt-5-nano github-models/openai/o3 github-models/openai/o3-mini github-models/openai/o4-mini github-models/mistral-ai/mistral-medium-2505 github-models/meta/llama-4-maverick-17b-128e-instruct-fp8 github-models/meta/llama-4-scout-17b-16e-instruct" "opencode review tries catalog-available tool-calling fallbacks after DeepSeek and GPT-5 paths" + assert_file_contains "$workflow_file" "github-models/openai/o4-mini github-models/openai/o3-mini github-models/openai/gpt-5-mini github-models/openai/gpt-5-chat github-models/openai/o3 github-models/mistral-ai/mistral-medium-2505 github-models/openai/gpt-5-nano github-models/deepseek/deepseek-r1-0528 github-models/deepseek/deepseek-r1 github-models/deepseek/deepseek-v3-0324 github-models/meta/llama-4-maverick-17b-128e-instruct-fp8 github-models/meta/llama-4-scout-17b-16e-instruct" "opencode review tries high-effort reasoning fallbacks before broader catalog models" assert_file_contains "$workflow_file" "The publish gate re-runs source-backed validation against PR-head data" "opencode review publish gate validates model output against the PR-head worktree" assert_file_contains "$workflow_file" '"openai/o3"' "opencode config declares OpenAI o3 fallback" assert_file_contains "$workflow_file" '"openai/o4-mini"' "opencode config declares OpenAI o4-mini fallback" @@ -598,18 +609,18 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() { assert_file_contains "$workflow_file" "No pull request review was posted because provider delay or model-output unavailability is not review feedback." "model-unavailable path explains delay without changing review state" assert_file_contains "$workflow_file" "request_changes_for_merge_conflict_if_present" "source-backed approval still gates on mergeability" assert_file_not_contains "$workflow_file" "No PR approval was posted because model-output failure is not evidence that the PR has no blockers." "model-failure path must not publish model-exhaustion review bodies" - assert_file_contains "$workflow_file" 'Detect central review-process fallback scope' "opencode approval detects central review-process fallback scope before model attempts" + assert_file_contains "$workflow_file" 'Detect central review-process scope' "opencode approval records central review-process scope before model attempts" assert_file_contains "$workflow_file" 'id: central_review_process_fallback_scope' "opencode approval exposes central review-process fallback scope as a step output" assert_file_not_contains "$workflow_file" 'steps.central_review_process_fallback_scope.outputs.eligible != '\''true'\''' "opencode model pool is not skipped for central review-process diffs" - assert_file_contains "$workflow_file" 'Central review-process fallback eligible=%s changed_count=%s' "opencode fallback scope detector logs eligibility" - assert_file_contains "$workflow_file" 'if [ "$changed_count" -eq 0 ]; then' "opencode fallback scope detector treats no-diff PR heads as eligible" + assert_file_contains "$workflow_file" 'Trusted review-process scope=%s eligible=%s changed_count=%s max_changed_count=%s' "opencode scope detector logs eligibility as evidence" + assert_file_contains "$workflow_file" 'if [ "$changed_count" -eq 0 ] || [ "$changed_count" -gt "$max_changed_count" ]; then' "opencode scope detector rejects no-diff PR heads instead of approving deterministically" assert_file_not_contains "$workflow_file" 'request_changes_after_model_exhaustion()' "opencode does not convert model-pool exhaustion into a review" assert_file_not_contains "$workflow_file" 'This is not approval evidence' "opencode does not publish model-exhaustion evidence as a review" assert_file_contains "$workflow_file" '.github/workflows/opencode-review.yml | \' "opencode central review fallback allowlist includes only the OpenCode workflow" assert_file_contains "$workflow_file" '.github/workflows/strix.yml | \' "opencode central review fallback allowlist includes only the Strix workflow" assert_file_contains "$workflow_file" 'scripts/ci/opencode_review_normalize_output.py | \' "opencode central review fallback allowlist includes only the OpenCode normalizer" assert_file_contains "$workflow_file" 'scripts/ci/validate_opencode_failed_check_review.sh | \' "opencode central review fallback allowlist includes the failed-check review validator" - assert_file_contains "$workflow_file" 'scripts/ci/test_strix_quick_gate.sh)' "opencode central review fallback allowlist includes only the central gate self-test" + assert_file_contains "$workflow_file" 'scripts/ci/test_strix_quick_gate.sh | \' "opencode central review scope allowlist includes the central gate self-test" assert_file_contains "$workflow_file" 'wait_for_peer_github_checks "$pending_checks_file"' "opencode model-failure path waits for peer checks before failing closed" assert_file_contains "$workflow_file" 'collect_unresolved_reviewer_threads "$unresolved_reviewer_threads_file"' "opencode model-failure path re-queries reviewer threads before failing closed" assert_file_not_contains "$workflow_file" ".github/workflows/*.yml|.github/workflows/*.yaml" "opencode model-exhaustion fallback must not allow workflow-only deterministic approval" @@ -623,7 +634,8 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() { assert_file_contains "$workflow_file" 'OPENCODE_RUN_TIMEOUT_SECONDS: "600"' "opencode catalog fallback has a bounded model review timeout before step timeout" assert_file_contains "$REPO_ROOT/scripts/ci/run_opencode_review_model_pool.sh" "OpenCode %s attempt %s/%s failed" "opencode catalog fallback records per-model retry failures" assert_file_contains "$REPO_ROOT/scripts/ci/run_opencode_review_model_pool.sh" "exponential backoff" "opencode model retry paths use exponential backoff instead of fixed sleeps" - assert_file_contains "$workflow_file" "github-models/openai/o3 github-models/openai/o3-mini github-models/openai/o4-mini" "opencode review includes additional OpenAI reasoning model fallbacks" + assert_file_contains "$workflow_file" "github-models/openai/o4-mini github-models/openai/o3-mini" "opencode review tries compact OpenAI reasoning model fallbacks early" + assert_file_contains "$workflow_file" "github-models/openai/gpt-5-chat github-models/openai/o3 github-models/mistral-ai" "opencode review keeps full OpenAI and non-OpenAI catalog fallbacks after compact reasoning attempts" assert_file_contains "$workflow_file" "coverage-evidence:" "opencode workflow measures coverage before review" assert_file_contains "$workflow_file" "github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request_target'" "manual and required OpenCode reviews measure coverage instead of approving skipped coverage evidence" assert_file_contains "$workflow_file" "Exchange OpenCode app token for target repository coverage reads" "coverage evidence can read private target repositories through the OpenCode app token" @@ -726,6 +738,10 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() { assert_file_contains "$REPO_ROOT/.github/workflows/strix.yml" 'TARGET_REPOSITORY: ${{ github.event.inputs.target_repository || github.repository }}' "strix manual evidence status publishes to the requested target repository" assert_file_contains "$REPO_ROOT/.github/workflows/strix.yml" 'context="strix"' "strix manual evidence status uses the status context consumed by OpenCode" assert_file_contains "$REPO_ROOT/.github/workflows/strix.yml" 'repos/${TARGET_REPOSITORY}/statuses/${PR_HEAD_SHA}' "strix manual evidence status does not post private-target evidence to .github by mistake" + assert_file_contains "$REPO_ROOT/.github/workflows/strix.yml" 'PR_REVIEW_MERGE_STATUS_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN || '"'"''"'"' }}' "strix manual evidence status can publish cross-repo evidence with the central mutation credential" + assert_file_contains "$REPO_ROOT/.github/workflows/strix.yml" 'post_strix_status "pr-review-merge-token" "$PR_REVIEW_MERGE_STATUS_TOKEN"' "strix manual evidence status retries the central mutation credential when the target app token cannot write statuses" + assert_file_contains "$REPO_ROOT/.github/workflows/strix.yml" 'post_strix_status "opencode-approve-token" "$OPENCODE_APPROVE_STATUS_TOKEN"' "strix manual evidence status retries the approval credential before declaring status publication unavailable" + assert_file_contains "$REPO_ROOT/.github/workflows/strix.yml" 'post_strix_status "github-token" "$GITHUB_STATUS_TOKEN"' "strix manual evidence status keeps same-repository github-token fallback" assert_file_contains "$REPO_ROOT/.github/workflows/strix.yml" 'Manual workflow_dispatch Strix evidence failed' "strix manual evidence status records failed reruns so older success cannot mask newer failure" assert_file_contains "$REPO_ROOT/.github/workflows/strix.yml" 'Could not publish manual Strix status from scan job' "strix scan evidence does not fail solely because target status publication is unavailable" assert_file_contains "$REPO_ROOT/scripts/ci/collect_failed_check_evidence.sh" '"workflow_run"' "failed-check evidence includes failed same-head workflow runs outside statusCheckRollup" @@ -807,7 +823,8 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() { assert_file_contains "$workflow_file" 'GH_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN || steps.review_read_app_token.outputs.token || github.token }}' "opencode manual dispatch uses the cross-repo approval token for target PR evidence lookups with app-token fallback" assert_file_contains "$workflow_file" 'repos/${GH_REPOSITORY}' "opencode review workflow uses env-backed repository context in shell commands" assert_file_contains "$workflow_file" "Run OpenCode PR Review model pool" "opencode review starts the central model pool" - assert_file_contains "$workflow_file" "github-models/deepseek/deepseek-r1-0528" "opencode review starts with a reachable DeepSeek R1 reasoning model" + assert_file_contains "$workflow_file" "github-models/openai/o4-mini github-models/openai/o3-mini github-models/openai/gpt-5-mini" "opencode review starts with faster reasoning-capable GitHub Models" + assert_file_contains "$workflow_file" "github-models/deepseek/deepseek-r1-0528" "opencode review keeps a reachable DeepSeek R1 reasoning fallback model" assert_file_contains "$workflow_file" "github-models/deepseek/deepseek-v3-0324" "opencode review has a reachable DeepSeek V3 fallback model" assert_file_contains "$workflow_file" "github-models/openai/gpt-5" "opencode review still has a bounded GPT-5 fallback model" assert_file_contains "$workflow_file" "Publish bounded OpenCode review comment" "opencode review workflow publishes the agent control comment for the approval gate" @@ -848,6 +865,8 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() { assert_file_contains "$REPO_ROOT/scripts/ci/collect_failed_check_evidence.sh" "Superseded failed checks" "failed-check evidence lists stale failed contexts superseded by current-head manual Strix evidence" assert_file_contains "$REPO_ROOT/scripts/ci/collect_failed_check_evidence.sh" "manual_success_contexts" "failed-check evidence compares explicit manual success statuses before active failures" assert_file_contains "$REPO_ROOT/scripts/ci/collect_failed_check_evidence.sh" "manual_success_check_runs" "failed-check evidence compares successful same-head Strix check runs before active failures" + assert_file_contains "$REPO_ROOT/scripts/ci/collect_failed_check_evidence.sh" "--workflow strix.yml" "failed-check evidence looks up same-head manual Strix success runs when status publication is unavailable" + assert_file_contains "$REPO_ROOT/scripts/ci/collect_failed_check_evidence.sh" '"Manual workflow_dispatch Strix evidence passed"' "failed-check evidence records manual Strix success without requiring a commit status" assert_file_contains "$REPO_ROOT/scripts/ci/collect_failed_check_evidence.sh" "No active failed GitHub Checks remained after superseded checks were classified" "failed-check evidence reports no active failures after stale contexts are superseded" assert_file_contains "$REPO_ROOT/scripts/ci/emit_opencode_failed_check_fallback_findings.sh" "Strix vulnerability report window([[:space:]]|$)" "failed-check fallback detects numbered Strix vulnerability report windows with a POSIX ERE boundary" assert_file_not_contains "$REPO_ROOT/scripts/ci/emit_opencode_failed_check_fallback_findings.sh" "Strix vulnerability report window\\\\b" "failed-check fallback must not rely on non-portable grep -E word boundaries" @@ -973,7 +992,7 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() { assert_file_contains "$workflow_file" '["FAILURE","ERROR"]' "opencode review workflow treats failed status contexts as request-changes blockers" assert_file_not_contains "$workflow_file" "MODEL: github-models/gpt-4.1" "opencode review must not fall back to GPT-4.1" assert_file_contains "$workflow_file" "github-models/openai/gpt-5-chat" "opencode review includes GitHub Models GPT-5 chat as a catalog fallback" - assert_file_contains "$workflow_file" "github-models/openai/gpt-4.1-mini" "opencode review includes a smoke-tested GitHub Models GPT-4.1 mini fallback" + assert_file_not_contains "$workflow_file" "github-models/openai/gpt-4.1-mini" "opencode review does not fall back to GPT-4.1 mini review evidence" assert_file_contains "$workflow_file" "github-models/openai/gpt-5-mini" "opencode review includes GitHub Models GPT-5 mini as a catalog fallback" assert_file_contains "$opencode_config" '"mcp"' "opencode config declares MCP servers" @@ -1436,7 +1455,8 @@ EOF assert_file_contains "$REPO_ROOT/.github/workflows/opencode-review.yml" "never say no source files changed, no test files changed, or no executable changes when exact changed-file evidence lists workflow, script, source, or test files" "opencode prompt rejects contradictory changed-file kind claims" assert_file_contains "$REPO_ROOT/.github/workflows/opencode-review.yml" "Never approve material workflow, script, source, config, package, or test changes with a reason or summary that says simple typo fix" "opencode prompt rejects trivial approval claims for material changes" assert_file_contains "$REPO_ROOT/.github/workflows/opencode-review.yml" "OPENCODE_CHANGED_FILES_FILE" "opencode workflow exports exact current-head changed files" - assert_file_contains "$REPO_ROOT/.github/workflows/opencode-review.yml" 'git -C "$OPENCODE_SOURCE_WORKDIR" diff --name-only --find-renames "$PR_MERGE_BASE" "$PR_HEAD_SHA" |' "opencode workflow reads exact changed files for the normalizer" + assert_file_contains "$REPO_ROOT/.github/workflows/opencode-review.yml" 'git -C "$OPENCODE_SOURCE_WORKDIR" diff --name-only --find-renames "$PR_MERGE_BASE" "$PR_HEAD_SHA" |' "opencode workflow derives exact changed files from the PR-head worktree" + assert_file_contains "$REPO_ROOT/.github/workflows/opencode-review.yml" 'awk '\''NF > 0 && $0 !~ /^\// && $0 !~ /(^|\/)\.\.($|\/)/ { print }'\'' >"$OPENCODE_CHANGED_FILES_FILE"' "opencode workflow writes path-safe exact changed files for the normalizer" assert_file_contains "$REPO_ROOT/.github/workflows/opencode-review.yml" "changed-files.txt" "opencode workflow copies exact changed-file evidence into the isolated review workspace" assert_file_contains "$REPO_ROOT/.github/workflows/opencode-review.yml" 'A["text"]' "opencode prompt requires quoted Mermaid labels" assert_file_contains "$REPO_ROOT/.github/workflows/opencode-review.yml" 'S%s["%s"]' "opencode generated Mermaid surface labels are quoted" @@ -4440,7 +4460,14 @@ EOS git config user.name "CI" git add frontend/src/App.tsx git commit -qm 'base commit' - sed -i '120s/$/ \/\/ changed search line/' frontend/src/App.tsx + python3 - <<'PY' +from pathlib import Path + +path = Path("frontend/src/App.tsx") +lines = path.read_text(encoding="utf-8").splitlines() +lines[119] = f"{lines[119]} // changed search line" +path.write_text("\n".join(lines) + "\n", encoding="utf-8") +PY git add frontend/src/App.tsx git commit -qm 'head commit' ) @@ -4750,6 +4777,28 @@ run_filtered_gate_case_if_requested() { "" \ "1" ;; + zero-findings-with-low-report-timeout) + run_gate_case_allow_provider_signal "zero-findings-with-low-report-timeout" \ + "vertex_ai/zero-low-primary" \ + "vertex_ai/fallback-one" \ + "1" \ + "Configured Vertex model and fallback models were unavailable." \ + "2" \ + "vertex_ai/zero-low-primary|vertex_ai/fallback-one" \ + "|" \ + "vertex_ai" \ + "__DEFAULT__" \ + "" \ + "0" \ + "CRITICAL" \ + "0" \ + "" \ + "" \ + "2" \ + "0" \ + "pull_request" \ + "sync-module-system/smart-crawling-biz/src/main/java/org/empasy/sync/modules/system/controller/SysPositionController.java" + ;; vertex-primary-notfound-fallback-success) run_gate_case "vertex-primary-notfound-fallback-success" \ "vertex_ai/missing-primary" \ diff --git a/tests/test_assert_opencode_reasoning_effort.py b/tests/test_assert_opencode_reasoning_effort.py index 262edb56d..d84ca6cc8 100644 --- a/tests/test_assert_opencode_reasoning_effort.py +++ b/tests/test_assert_opencode_reasoning_effort.py @@ -66,6 +66,13 @@ def test_validate_candidate_reports_missing_and_unqualified_models(): ] +def test_validate_candidate_skips_unknown_non_reasoning_provider_fallbacks(): + """Unknown provider fallbacks pass when no reasoning-effort support is known.""" + config = {"provider": {"github-models": {"models": {}}}} + + assert guard.validate_candidate(config, "vertex_ai/fallback-one") == [] + + def test_validate_candidate_reports_each_missing_high_effort_field(): """Reasoning-capable models must opt into high effort in every required field.""" config = { diff --git a/tests/test_opencode_agent_contract.py b/tests/test_opencode_agent_contract.py index cae939540..8d2e14a91 100644 --- a/tests/test_opencode_agent_contract.py +++ b/tests/test_opencode_agent_contract.py @@ -78,6 +78,25 @@ def test_opencode_model_pool_sets_high_effort_for_capable_candidates(): assert candidate_models assert set(candidate_models).issubset(set(models)) + assert candidate_models[:3] == [ + "openai/o4-mini", + "openai/o3-mini", + "openai/gpt-5-mini", + ] + assert { + "openai/gpt-5-chat", + "openai/gpt-5-mini", + "openai/gpt-5-nano", + "openai/o3", + "openai/o3-mini", + "openai/o4-mini", + "deepseek/deepseek-r1-0528", + "deepseek/deepseek-r1", + "deepseek/deepseek-v3-0324", + "mistral-ai/mistral-medium-2505", + "meta/llama-4-maverick-17b-128e-instruct-fp8", + "meta/llama-4-scout-17b-16e-instruct", + }.issubset(set(candidate_models)) for model_name in candidate_models: assert f'"{model_name}": {{' in workflow @@ -101,6 +120,35 @@ def is_reasoning_capable(model_name: str) -> bool: assert "variants" not in model_config, model_name +def test_opencode_manual_dispatch_canonical_ref_overrides_workflow_ref(): + """Allow PR-head workflow bootstrap when the required workflow is pinned to main.""" + workflow = Path(".github/workflows/opencode-review.yml").read_text(encoding="utf-8") + + assert workflow.count('if [ -n "$INPUT_CANONICAL_REF" ]; then') == 2 + assert workflow.count('trusted_ref="$INPUT_CANONICAL_REF"') == 2 + assert workflow.count('trusted_ref="${WORKFLOW_REF##*@}"') == 2 + assert 'trusted_ref="${INPUT_CANONICAL_REF:-main}"' not in workflow + + +def test_opencode_runtime_pin_supports_reasoning_options(): + """Keep OpenCode runtime new enough to apply model-level reasoning settings.""" + review_workflow = Path(".github/workflows/opencode-review.yml").read_text( + encoding="utf-8" + ) + autofix_workflow = Path(".github/workflows/pr-review-autofix.yml").read_text( + encoding="utf-8" + ) + + for workflow in (review_workflow, autofix_workflow): + assert 'OPENCODE_VERSION: "1.17.13"' in workflow + assert ( + "OPENCODE_SHA256: " + "157afa289d1a8d9372de0ce19ac726119b937a1f6b201808d46f06e4e59bb348" + in workflow + ) + assert 'OPENCODE_VERSION: "1.16.0"' not in workflow + + def test_code_reviewer_prompt_preserves_review_only_policy(): """Guard the reviewer-only behavior and output rubric in the prompt.""" prompt = Path("code-reviewer-prompt.md").read_text(encoding="utf-8") @@ -200,14 +248,16 @@ def test_workflow_provisions_sandbox_tool_and_reviewer_agent(): assert "--config \"$OPENCODE_REVIEW_WORKDIR/opencode.jsonc\"" in workflow assert 'timeout --kill-after=15s "${export_timeout_seconds}s" opencode export' in model_pool_runner assert "session export did not complete within %ss" in model_pool_runner - assert "Read and follow the complete review contract" in model_pool_runner - assert "compact launcher as a reduced review policy" in model_pool_runner + assert "Follow the complete review contract" in model_pool_runner + assert "packet-first entry point" in model_pool_runner + assert "Current-head evidence packet" in model_pool_runner + assert "not a generic model-exhaustion message" in model_pool_runner assert "is_context_overflow_failure" in model_pool_runner assert "tokens_limit_reached" in model_pool_runner assert "skipping remaining attempts for this model" in model_pool_runner assert "approve_low_risk_review_fallback_after_model_exhaustion" not in workflow assert "changed_file_is_low_risk_review_fallback" not in workflow - assert "approve_central_review_process_fallback" in workflow + assert "approve_central_review_process_fallback" not in workflow assert "opencode.jsonc | \\" in workflow assert "scripts/ci/run_opencode_review_model_pool.sh | \\" in workflow assert "tests/test_opencode_agent_contract.py | \\" in workflow @@ -217,28 +267,14 @@ def test_workflow_provisions_sandbox_tool_and_reviewer_agent(): assert "appguardrail org-security failure collector" in workflow assert 'max_changed_count=3' in workflow assert "changed_count\" -gt \"$max_changed_count\"" in workflow - assert "steps.central_review_process_fallback_scope.outputs.eligible != 'true'" in workflow - assert workflow.index("Detect central review-process fallback scope") < workflow.index( + assert "steps.central_review_process_fallback_scope.outputs.eligible != 'true'" not in workflow + assert workflow.index("Detect central review-process scope") < workflow.index( "Initialize CodeGraph index for OpenCode" ) - assert re.search( - r"Initialize CodeGraph index for OpenCode[\s\S]{0,120}" - r"if: steps\.central_review_process_fallback_scope\.outputs\.eligible != 'true'", - workflow, - ) - assert re.search( - r"Prepare bounded OpenCode review evidence[\s\S]{0,120}" - r"if: steps\.central_review_process_fallback_scope\.outputs\.eligible != 'true'", - workflow, - ) - assert re.search( - r"Prepare isolated OpenCode review workspace[\s\S]{0,120}" - r"if: steps\.central_review_process_fallback_scope\.outputs\.eligible != 'true'", - workflow, - ) assert "CENTRAL_REVIEW_PROCESS_FALLBACK_ELIGIBLE" in workflow assert "CENTRAL_REVIEW_PROCESS_FALLBACK_SCOPE_LABEL" in workflow - assert "This fallback is limited to central OpenCode/Strix review-process files and the appguardrail org-security failure collector file set." in workflow + assert "model pool was intentionally skipped" not in workflow + assert "deterministic fallback" not in workflow assert "production source 또는 package manifest 변경이 없습니다" not in workflow assert "request_changes_for_coverage_evidence_failure" in workflow assert '"## Review outcome"' in workflow @@ -250,14 +286,16 @@ def test_workflow_provisions_sandbox_tool_and_reviewer_agent(): assert 'APPROVAL_CHECK_WAIT_ATTEMPTS: "81"' in workflow assert 'APPROVAL_CHECK_WAIT_SLEEP_SECONDS: "30"' in workflow assert ( - 'OPENCODE_MODEL_CANDIDATES: "github-models/openai/gpt-4.1-mini ' - 'github-models/openai/gpt-5-chat ' + 'OPENCODE_MODEL_CANDIDATES: "github-models/openai/o4-mini ' + "github-models/openai/o3-mini " "github-models/openai/gpt-5-mini " - "github-models/openai/gpt-5-nano " + 'github-models/openai/gpt-5-chat ' "github-models/openai/o3 " - "github-models/openai/o3-mini " - "github-models/openai/o4-mini " "github-models/mistral-ai/mistral-medium-2505 " + "github-models/openai/gpt-5-nano " + "github-models/deepseek/deepseek-r1-0528 " + "github-models/deepseek/deepseek-r1 " + "github-models/deepseek/deepseek-v3-0324 " "github-models/meta/llama-4-maverick-17b-128e-instruct-fp8 " 'github-models/meta/llama-4-scout-17b-16e-instruct"' ) in workflow diff --git a/tests/test_pr_governance_audit_contract.py b/tests/test_pr_governance_audit_contract.py index fb0f10fa6..eeecca8bf 100644 --- a/tests/test_pr_governance_audit_contract.py +++ b/tests/test_pr_governance_audit_contract.py @@ -16,8 +16,8 @@ def test_html4tree_public_fork_queue_requires_central_review_gate(): assert "do not bypass the review gate" in audit -def test_afipc_queue_requires_central_required_workflow_evidence(): - """Guard the aFIPC central required-workflow coverage gap.""" +def test_afipc_queue_has_central_required_workflow_evidence(): + """Guard the closed aFIPC central required-workflow fixture.""" audit = Path("PR_GOVERNANCE_AUDIT.md").read_text(encoding="utf-8") rollout = Path("docs/org-required-workflow-rollout.md").read_text( encoding="utf-8" @@ -26,6 +26,24 @@ def test_afipc_queue_requires_central_required_workflow_evidence(): assert "aFIPC" in audit assert "aFIPC" in rollout assert "PR #78" in audit - assert "PR `#78` lacks inherited OpenCode, Strix, and scheduler" in rollout - assert "zero approving reviews" in audit - assert "must not be merged until organization required-workflow evidence exists" in audit + assert "PR `#78` is no longer a target-coverage gap" in rollout + assert "closed target-coverage fixture" in audit + assert "b1ddafced86302f461e95259699f1efde5ec87c9" in audit + + +def test_new_public_nonfork_repos_are_classified_in_rollout_inventory(): + """Guard newly discovered public non-fork repository classification.""" + audit = Path("PR_GOVERNANCE_AUDIT.md").read_text(encoding="utf-8") + rollout = Path("docs/org-required-workflow-rollout.md").read_text( + encoding="utf-8" + ) + + for document in (audit, rollout): + assert "17 public non-fork repositories" in document + assert "kaefa" in document + assert "waf-ids-ai-soc" in document + + assert "current PR #60 lacked central check runs" in rollout + assert "runtime proof gap" in audit + assert "PR #6 shows central required workflow runs" in rollout + assert "43b62b5f347d1532c81b5ae38d8e41b4494fd486" in audit