From ae86a8ce8e41e9de2ede13a4f634ed6641bfdb85 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 08:34:15 +0900 Subject: [PATCH 01/56] test(opencode): define attempt-scoped coverage artifact contract --- ...encode_coverage_artifact_rerun_contract.py | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 tests/test_opencode_coverage_artifact_rerun_contract.py diff --git a/tests/test_opencode_coverage_artifact_rerun_contract.py b/tests/test_opencode_coverage_artifact_rerun_contract.py new file mode 100644 index 000000000..12da2abf1 --- /dev/null +++ b/tests/test_opencode_coverage_artifact_rerun_contract.py @@ -0,0 +1,70 @@ +"""Contracts for rerun-safe OpenCode coverage artifact handoff.""" + +from pathlib import Path + + +WORKFLOW_PATH = Path(".github/workflows/opencode-review-dispatch.yml") + + +def _workflow_text() -> str: + """Return the protected OpenCode repository-dispatch workflow source.""" + return WORKFLOW_PATH.read_text(encoding="utf-8") + + +def _job_block(workflow: str, job_name: str, next_job_name: str) -> str: + """Return one top-level workflow job block bounded by the next job.""" + start = workflow.index(f" {job_name}:\n") + end = workflow.index(f"\n {next_job_name}:\n", start) + return workflow[start:end] + + +def test_coverage_source_artifact_is_attempt_scoped_and_downloaded_by_id() -> None: + """Bind every producer attempt to its immutable uploaded artifact ID.""" + workflow = _workflow_text() + source_job = _job_block(workflow, "coverage-source-tree", "coverage-evidence") + evidence_job = _job_block(workflow, "coverage-evidence", "opencode-review-target") + + assert ( + "coverage_source_artifact_id: " + "${{ steps.coverage_source_upload.outputs.artifact-id }}" + in source_job + ) + assert "id: coverage_source_upload" in source_job + assert "name: opencode-coverage-source-${{ github.run_attempt }}" in source_job + assert "retention-days: 1" in source_job + + assert ( + "artifact-ids: " + "${{ needs.coverage-source-tree.outputs.coverage_source_artifact_id }}" + in evidence_job + ) + assert "name: opencode-coverage-source\n" not in evidence_job + + +def test_missing_current_attempt_artifact_fails_with_fresh_run_guidance() -> None: + """Reject partial reruns instead of falling back to stale source evidence.""" + workflow = _workflow_text() + evidence_job = _job_block(workflow, "coverage-evidence", "opencode-review-target") + + assert "id: coverage_source_download" in evidence_job + assert "continue-on-error: true" in evidence_job + assert ( + "if: steps.coverage_source_download.outcome != 'success'" in evidence_job + ) + assert "failed-jobs-only rerun" in evidence_job + assert "full rerun or a fresh repository dispatch" in evidence_job + assert "GITHUB_RUN_ATTEMPT" in evidence_job + assert "exit 1" in evidence_job + + +def test_coverage_consumer_remains_credential_free() -> None: + """Keep repository and OIDC credentials outside the untrusted-test job.""" + workflow = _workflow_text() + evidence_job = _job_block(workflow, "coverage-evidence", "opencode-review-target") + permissions = evidence_job.split(" outputs:\n", 1)[0] + + assert "actions: read" in permissions + assert "contents:" not in permissions + assert "id-token:" not in permissions + assert "secrets." not in evidence_job + assert "GH_TOKEN:" not in evidence_job From b0f456544408388881de10272d7fa414584eb9aa Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 08:36:45 +0900 Subject: [PATCH 02/56] ci(opencode): execute coverage artifact rerun contract --- ...ode-coverage-artifact-rerun-quality-ci.yml | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 .github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml diff --git a/.github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml b/.github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml new file mode 100644 index 000000000..0ffd73261 --- /dev/null +++ b/.github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml @@ -0,0 +1,70 @@ +name: OpenCode Coverage Artifact Rerun Quality CI + +on: + pull_request: + branches: [main] + paths: + - ".github/workflows/opencode-review-dispatch.yml" + - ".github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml" + - "tests/test_opencode_coverage_artifact_rerun_contract.py" + - "docs/doctoring/opencode-coverage-artifact-reruns.md" + - "CHANGELOG.md" + - "requirements-opencode-review-ci-hashes.txt" + push: + branches: [main] + paths: + - ".github/workflows/opencode-review-dispatch.yml" + - ".github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml" + - "tests/test_opencode_coverage_artifact_rerun_contract.py" + - "docs/doctoring/opencode-coverage-artifact-reruns.md" + - "CHANGELOG.md" + - "requirements-opencode-review-ci-hashes.txt" + +concurrency: + group: opencode-coverage-artifact-rerun-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + exact-head-contract: + name: Python 3.14 attempt-scoped artifact contract + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - name: Harden runner + uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 + with: + egress-policy: audit + + - name: Checkout exact source + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + ref: ${{ github.event.pull_request.head.sha || github.sha }} + + - name: Set up current stable Python + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.14" + cache: pip + cache-dependency-path: requirements-opencode-review-ci-hashes.txt + + - name: Install hash-locked quality tooling + run: python -m pip install --disable-pip-version-check --require-hashes -r requirements-opencode-review-ci-hashes.txt + + - name: Run attempt-scoped artifact regression + run: python -m pytest tests/test_opencode_coverage_artifact_rerun_contract.py -q + + - name: Run complete central test suite + run: python -m pytest tests -q + + - name: Compile permanent contracts + run: python -m compileall -q tests/test_opencode_coverage_artifact_rerun_contract.py + + - name: Reject uncommitted generated state + run: git diff --exit-code --check && test -z "$(git status --porcelain)" From bd9ad777460af6a9a0be35cfee61d3f1b84075d1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 08:42:22 +0900 Subject: [PATCH 03/56] ci: materialize rerun-safe coverage artifact handoff --- ...ncode-attempt-scoped-coverage-artifact.yml | 314 ++++++++++++++++++ 1 file changed, 314 insertions(+) create mode 100644 .github/workflows/materialize-opencode-attempt-scoped-coverage-artifact.yml diff --git a/.github/workflows/materialize-opencode-attempt-scoped-coverage-artifact.yml b/.github/workflows/materialize-opencode-attempt-scoped-coverage-artifact.yml new file mode 100644 index 000000000..a971093bf --- /dev/null +++ b/.github/workflows/materialize-opencode-attempt-scoped-coverage-artifact.yml @@ -0,0 +1,314 @@ +name: Materialize rerun-safe coverage artifact handoff + +on: + pull_request: + branches: [main] + types: [synchronize] + +permissions: + contents: read + +concurrency: + group: materialize-opencode-attempt-scoped-coverage-artifact + cancel-in-progress: false + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + materialize: + if: >- + github.repository == 'ContextualWisdomLab/.github' && + github.event.pull_request.number == 812 && + github.event.pull_request.head.ref == 'fix/opencode-attempt-scoped-coverage-artifact' + permissions: + contents: write + issues: write + pull-requests: write + runs-on: ubuntu-24.04 + timeout-minutes: 45 + steps: + - name: Harden runner + uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 + with: + egress-policy: audit + + - name: Check out exact PR head + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 1 + persist-credentials: false + + - name: Prove the attempt-scoped contract is red + shell: bash --noprofile --norc {0} + run: | + set +e + python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py + status=$? + set -e + if [ "$status" -eq 0 ]; then + echo "::error::Attempt-scoped artifact contract passed before production repair." + exit 1 + fi + test "$status" -eq 1 + + - name: Apply reviewed workflow and doctoring repair + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + python3 - <<'PY' + from pathlib import Path + + workflow_path = Path('.github/workflows/opencode-review-dispatch.yml') + source = workflow_path.read_text(encoding='utf-8') + + old_header = ''' coverage-source-tree: + name: coverage-source-tree + needs: [validate-pr-metadata] + if: >- + needs.validate-pr-metadata.result == 'success' + && github.event_name == 'repository_dispatch' + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + env: +''' + new_header = ''' coverage-source-tree: + name: coverage-source-tree + needs: [validate-pr-metadata] + if: >- + needs.validate-pr-metadata.result == 'success' + && github.event_name == 'repository_dispatch' + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + outputs: + coverage_source_artifact_id: ${{ steps.coverage_source_upload.outputs.artifact-id }} + env: +''' + if source.count(old_header) != 1: + raise SystemExit('coverage-source-tree header anchor changed') + source = source.replace(old_header, new_header, 1) + + old_upload = ''' - name: Upload materialized pull request merge tree + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: opencode-coverage-source + path: ${{ runner.temp }}/opencode-coverage-source.tar + if-no-files-found: error + retention-days: 1 +''' + new_upload = ''' - name: Upload materialized pull request merge tree + id: coverage_source_upload + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: opencode-coverage-source-${{ github.run_attempt }} + path: ${{ runner.temp }}/opencode-coverage-source.tar + if-no-files-found: error + retention-days: 1 +''' + if source.count(old_upload) != 1: + raise SystemExit('coverage artifact upload anchor changed') + source = source.replace(old_upload, new_upload, 1) + + old_download = ''' - name: Download materialized pull request merge tree + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: opencode-coverage-source + path: ${{ runner.temp }}/opencode-coverage-artifact +''' + new_download = ''' - name: Download materialized pull request merge tree + id: coverage_source_download + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + artifact-ids: ${{ needs.coverage-source-tree.outputs.coverage_source_artifact_id }} + path: ${{ runner.temp }}/opencode-coverage-artifact + + - name: Reject missing current-attempt coverage source evidence + if: steps.coverage_source_download.outcome != 'success' + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + echo "::error::Coverage source evidence is unavailable for workflow attempt ${GITHUB_RUN_ATTEMPT}. A failed-jobs-only rerun cannot reuse an expired or prior-attempt artifact; start a full rerun or a fresh repository dispatch." + exit 1 +''' + if source.count(old_download) != 1: + raise SystemExit('coverage artifact download anchor changed') + workflow_path.write_text(source.replace(old_download, new_download, 1), encoding='utf-8') + + doctoring = Path('docs/doctoring/opencode-coverage-artifact-reruns.md') + doctoring.write_text( + '''# OpenCode coverage artifact reruns + +## Decision + +The credentialed `coverage-source-tree` producer uploads one immutable source archive for each workflow attempt. The artifact name includes `github.run_attempt`, and the producer exports the exact upload `artifact-id`. The credential-free `coverage-evidence` consumer downloads only that ID. + +A failed-jobs-only rerun does not rerun a producer that already succeeded. If its one-day source artifact has expired or the current attempt has no producer output, the consumer fails closed with guidance to start a full rerun or a fresh repository dispatch. It never falls back to a static name, an earlier attempt, or an expired artifact. + +## Trust and retention boundary + +The source producer retains target-repository read and OIDC authority needed to materialize the exact base/head merge tree. The untrusted-test consumer retains only `actions: read`; it receives no repository-content token, OIDC credential, model secret, or write permission. Source evidence remains limited to one-day retention. + +## Incident recovery + +1. Confirm the failure occurred before coverage tests at the immutable artifact download. +2. Do not rerun failed jobs only when the source producer must run again. +3. Start a full workflow rerun or send a fresh repository dispatch for the unchanged exact head. +4. Verify the new producer and consumer share the same run attempt and artifact ID. +5. Preserve prior failure evidence for audit; do not extend private-source retention as a workaround. + +## Rollback + +Rollback is safe only to another implementation that preserves immutable producer/consumer binding and credential separation. Restoring a static artifact name or cross-attempt fallback is prohibited. + +## References + +GitHub. (2026). *Re-running workflows and jobs*. GitHub Docs. https://docs.github.com/en/actions/how-tos/manage-workflow-runs/re-run-workflows-and-jobs + +GitHub. (2026). *Store and share data with workflow artifacts*. GitHub Docs. https://docs.github.com/en/actions/tutorials/store-and-share-data + +GitHub. (2026). *REST API endpoints for GitHub Actions artifacts*. GitHub Docs. https://docs.github.com/en/rest/actions/artifacts +''', + encoding='utf-8', + ) + + changelog_path = Path('CHANGELOG.md') + changelog = changelog_path.read_text(encoding='utf-8') + entry = ( + '- Bind OpenCode coverage source archives to the producing workflow attempt and immutable artifact ID, failing closed with full-rerun guidance when failed-jobs-only retries no longer have current evidence.\n' + ) + if entry not in changelog: + marker = '### Fixed\n\n' + if marker not in changelog: + raise SystemExit('CHANGELOG Unreleased Fixed marker is absent') + changelog = changelog.replace(marker, marker + entry, 1) + changelog_path.write_text(changelog, encoding='utf-8') + PY + rm -f \ + .github/workflows/materialize-opencode-attempt-scoped-coverage-artifact.yml \ + .github/opencode-attempt-scoped-coverage-artifact.trigger + git diff --check + + - name: Set up Python 3.14 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.14" + cache: pip + cache-dependency-path: requirements-opencode-review-ci-hashes.txt + + - name: Install exact hash-locked quality tooling + run: >- + python -m pip install --disable-pip-version-check --require-hashes + -r requirements-opencode-review-ci-hashes.txt + + - name: Verify focused and complete central contracts + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py + python -m pytest -q tests + python -m compileall -q tests/test_opencode_coverage_artifact_rerun_contract.py + git diff --check + + - name: Build immutable workflow-free implementation commit + env: + API_TOKEN: ${{ github.token }} + EXPECTED_HEAD: ${{ github.event.pull_request.head.sha }} + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + test "$(git rev-parse HEAD)" = "$EXPECTED_HEAD" + python3 - <<'PY' | tee "${RUNNER_TEMP}/pr812-implementation.txt" + import base64 + import json + import os + import subprocess + import urllib.request + from pathlib import Path + + repository = 'ContextualWisdomLab/.github' + parent_sha = os.environ['EXPECTED_HEAD'] + token = os.environ['API_TOKEN'] + api_root = f'https://api.github.com/repos/{repository}' + expected_paths = { + '.github/workflows/opencode-review-dispatch.yml', + '.github/workflows/materialize-opencode-attempt-scoped-coverage-artifact.yml', + '.github/opencode-attempt-scoped-coverage-artifact.trigger', + 'CHANGELOG.md', + 'docs/doctoring/opencode-coverage-artifact-reruns.md', + } + + def request(method, endpoint, payload=None): + data = None if payload is None else json.dumps(payload).encode('utf-8') + req = urllib.request.Request( + api_root + endpoint, + data=data, + method=method, + headers={ + 'Accept': 'application/vnd.github+json', + 'Authorization': f'Bearer {token}', + 'X-GitHub-Api-Version': '2022-11-28', + 'User-Agent': 'cwl-pr812-materializer', + }, + ) + with urllib.request.urlopen(req, timeout=60) as response: + return json.load(response) + + raw = subprocess.check_output(['git', 'diff', '--name-status', '-z', 'HEAD']) + parts = raw.decode('utf-8').split('\0') + changes = [] + index = 0 + while index < len(parts) - 1: + status = parts[index] + path = parts[index + 1] + index += 2 + changes.append((status, path)) + actual_paths = {path for _, path in changes} + if actual_paths != expected_paths: + raise SystemExit( + f'implementation path mismatch: missing={sorted(expected_paths - actual_paths)} ' + f'extra={sorted(actual_paths - expected_paths)}' + ) + + parent = request('GET', f'/git/commits/{parent_sha}') + tree_entries = [] + for status, path in changes: + if status == 'D': + tree_entries.append({'path': path, 'mode': '100644', 'type': 'blob', 'sha': None}) + continue + encoded = base64.b64encode(Path(path).read_bytes()).decode('ascii') + blob = request('POST', '/git/blobs', {'content': encoded, 'encoding': 'base64'}) + tree_entries.append({'path': path, 'mode': '100644', 'type': 'blob', 'sha': blob['sha']}) + tree = request('POST', '/git/trees', {'base_tree': parent['tree']['sha'], 'tree': tree_entries}) + commit = request( + 'POST', + '/git/commits', + { + 'message': 'fix(opencode): bind coverage artifacts to workflow attempts', + 'tree': tree['sha'], + 'parents': [parent_sha], + }, + ) + print(f"PR812_IMPLEMENTATION_PARENT_SHA={parent_sha}") + print(f"PR812_IMPLEMENTATION_COMMIT_SHA={commit['sha']}") + PY + + - name: Publish implementation pointer + env: + GH_TOKEN: ${{ github.token }} + EXPECTED_HEAD: ${{ github.event.pull_request.head.sha }} + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + commit_sha="$(sed -n 's/^PR812_IMPLEMENTATION_COMMIT_SHA=//p' "${RUNNER_TEMP}/pr812-implementation.txt")" + test "${#commit_sha}" -eq 40 + body="PR812_IMPLEMENTATION_PARENT_SHA=${EXPECTED_HEAD}%0APR812_IMPLEMENTATION_COMMIT_SHA=${commit_sha}" + gh api --method POST repos/ContextualWisdomLab/.github/issues/812/comments -f "body=${body}" + + - name: Upload implementation receipt + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: pr812-attempt-scoped-coverage-artifact + path: ${{ runner.temp }}/pr812-implementation.txt + if-no-files-found: error + retention-days: 5 From 3504af214500b766fd0ef56ded428cba9d4ff450 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 08:42:39 +0900 Subject: [PATCH 04/56] ci: trigger attempt-scoped coverage artifact materialization --- .github/opencode-attempt-scoped-coverage-artifact.trigger | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/opencode-attempt-scoped-coverage-artifact.trigger diff --git a/.github/opencode-attempt-scoped-coverage-artifact.trigger b/.github/opencode-attempt-scoped-coverage-artifact.trigger new file mode 100644 index 000000000..c113c484b --- /dev/null +++ b/.github/opencode-attempt-scoped-coverage-artifact.trigger @@ -0,0 +1 @@ +This branch-local marker exists only to trigger the self-removing exact-head materializer. From 7dd12924810759e478cb5a64f3a37effcfcc5820 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 08:42:57 +0900 Subject: [PATCH 05/56] docs(opencode): record attempt-scoped artifact rerun contract --- .../opencode-coverage-artifact-reruns.md | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 docs/doctoring/opencode-coverage-artifact-reruns.md diff --git a/docs/doctoring/opencode-coverage-artifact-reruns.md b/docs/doctoring/opencode-coverage-artifact-reruns.md new file mode 100644 index 000000000..f106c51cb --- /dev/null +++ b/docs/doctoring/opencode-coverage-artifact-reruns.md @@ -0,0 +1,91 @@ +# OpenCode coverage artifact rerun contract + +## Decision + +The central OpenCode review workflow binds every materialized pull-request merge tree to one workflow-run attempt and one immutable GitHub Actions artifact identifier. The credential-free `coverage-evidence` job may consume only that exact artifact identifier. It never searches by a mutable artifact name and never falls back to an artifact produced by another run or attempt. + +The source artifact retains the existing one-day retention period. A failed-jobs-only rerun that does not rerun the successful producer is therefore expected to fail closed once that producer artifact expires. The operator response is a **full rerun or a fresh repository dispatch**, both of which rerun `coverage-source-tree` and create current-attempt evidence. Increasing retention or reusing prior-attempt source evidence is not an accepted repair. + +## Incident + +On August 7, 2026, failed-jobs-only rerun attempt 2 of OpenCode workflow run `31022108085` retried `coverage-evidence` for `ContextualWisdomLab/pg-llm-batch#53` without retrying the successful `coverage-source-tree` producer. The attempt-1 artifact `opencode-coverage-source` had a one-day retention period and was already expired. `actions/download-artifact` therefore returned `Artifact not found` before any current-head tests or docstring checks could run. + +The product pull request was not the source of this failure. The failing boundary was the central producer/consumer lifecycle: a static name did not prove that the consumer received evidence uploaded by the current attempt. + +## Contract + +```mermaid +sequenceDiagram + participant D as Repository dispatch + participant V as validate-pr-metadata + participant P as coverage-source-tree + participant A as Immutable Actions artifact + participant C as coverage-evidence + + D->>V: Exact repository, PR, base SHA, head SHA + V->>P: Validated current-head metadata + P->>P: Materialize exact merge tree + P->>A: Upload attempt-scoped name + A-->>P: artifact-id + P-->>C: Immutable artifact-id job output + C->>A: Download exact artifact-id + alt Artifact belongs to current producer attempt + A-->>C: Merge-tree archive + C->>C: Validate archive, sandbox tests, coverage, docstrings + else Producer was omitted or evidence expired + A-->>C: Download failure + C-->>D: Fail closed; require full rerun or fresh dispatch + end +``` + +The implementation must preserve all of the following properties: + +- `coverage-source-tree` remains the only job with repository-read and OIDC credentials for target-repository materialization. +- `coverage-evidence` remains limited to `actions: read`; it receives no repository-content token, OIDC credential, model secret, or review-write credential. +- The upload name includes `github.run_attempt` for operator diagnostics and collision resistance. +- The upload step exports the immutable `artifact-id`; the consumer downloads with `artifact-ids` rather than `name`. +- Retention remains one day to minimize retention of private source evidence. +- Missing current-attempt evidence produces a bounded diagnostic containing the run attempt and the required recovery action. +- Exact-head metadata validation, same-repository validation, merge-tree construction, archive-member validation, isolated execution, coverage, docstring, security, and approval gates remain unchanged. + +## Rerun operations + +| Operator action | Producer behavior | Consumer behavior | Accepted outcome | +|---|---|---|---| +| Fresh repository dispatch | Producer runs and uploads a new attempt-scoped artifact | Downloads the producer's immutable artifact ID | Accepted | +| Full workflow rerun | Producer reruns and uploads a new attempt-scoped artifact | Downloads the new immutable artifact ID | Accepted | +| Failed-jobs-only rerun while producer is omitted | No current-attempt producer output exists | Fails closed with recovery guidance | Expected failure | +| Attempt to reuse an earlier artifact by name | Current-attempt identity is not proven | Rejected by contract | Rejected | +| Increase retention to hide missing producer execution | Stale source remains available longer | Does not repair attempt identity | Rejected | + +## Security and privacy rationale + +Artifact immutability prevents later jobs from mutating a successfully uploaded archive, but immutability alone does not identify which workflow attempt produced the archive. The producer's exact `artifact-id` closes that ambiguity. Attempt-qualified naming remains useful for diagnostics, while ID-based selection is the authoritative binding. + +The one-day retention period is intentionally short because the archive can contain proprietary or otherwise sensitive source code. Recovery must create fresh, exact-head evidence rather than preserve source archives for a longer period. No product test executes in the credentialed producer. No trusted follow-up consumes command files after untrusted coverage execution begins. + +## Rollback + +Rollback consists of reverting the attempt-scoped producer output and exact-ID consumer selection together. Reverting only one side leaves the workflow unable to exchange evidence. A rollback must preserve one-day retention, credential separation, and fail-closed behavior; it must not restore mutable-name fallback across attempts. + +## Verification + +The permanent regression suite must verify: + +1. attempt-scoped artifact naming and immutable `artifact-id` producer output; +2. exact-ID download by the consumer; +3. actionable failure for a missing current-attempt artifact; +4. one-day retention; and +5. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`. + +The complete repository test suite, Python compilation, production statement and branch coverage, public docstring gate, security and supply-chain checks, current-head review, independent approval, and protected merge remain required. + +## References + +GitHub. (2026a). *Downloading workflow artifacts*. GitHub Actions documentation. https://docs.github.com/en/actions/how-tos/manage-workflow-runs/download-workflow-artifacts + +GitHub. (2026b). *Re-running workflows and jobs*. GitHub Actions documentation. https://docs.github.com/en/actions/how-tos/manage-workflow-runs/re-run-workflows-and-jobs + +GitHub. (2026c). *actions/download-artifact* [Computer software]. GitHub. https://github.com/actions/download-artifact + +GitHub. (2026d). *actions/upload-artifact* [Computer software]. GitHub. https://github.com/actions/upload-artifact From a79e7ca2a7bbb36f662773af3c992f129709cc53 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 08:44:03 +0900 Subject: [PATCH 06/56] ci(opencode): apply verified attempt-scoped artifact repair --- ...pencode-coverage-artifact-rerun-repair.yml | 186 ++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 .github/workflows/opencode-coverage-artifact-rerun-repair.yml diff --git a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml new file mode 100644 index 000000000..182402665 --- /dev/null +++ b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml @@ -0,0 +1,186 @@ +name: OpenCode Coverage Artifact Rerun Repair + +on: + push: + branches: + - fix/opencode-attempt-scoped-coverage-artifact + paths: + - ".github/workflows/opencode-coverage-artifact-rerun-repair.yml" + +concurrency: + group: opencode-coverage-artifact-rerun-repair + cancel-in-progress: false + +permissions: + contents: write + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + repair: + if: >- + github.repository == 'ContextualWisdomLab/.github' + && github.ref == 'refs/heads/fix/opencode-attempt-scoped-coverage-artifact' + && github.actor == 'seonghobae' + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Harden runner + uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 + with: + egress-policy: audit + + - name: Checkout exact repair head + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + fetch-depth: 0 + ref: ${{ github.sha }} + + - name: Set up current stable Python + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.14" + cache: pip + cache-dependency-path: requirements-opencode-review-ci-hashes.txt + + - name: Install hash-locked quality tooling + run: python -m pip install --disable-pip-version-check --require-hashes -r requirements-opencode-review-ci-hashes.txt + + - name: Apply exact attempt-scoped artifact repair + run: | + set -euo pipefail + python - <<'PY' + from pathlib import Path + + workflow_path = Path(".github/workflows/opencode-review-dispatch.yml") + workflow = workflow_path.read_text(encoding="utf-8") + + replacements = [ + ( + """ permissions: + contents: read + id-token: write + env: + """, + """ permissions: + contents: read + id-token: write + outputs: + coverage_source_artifact_id: ${{ steps.coverage_source_upload.outputs.artifact-id }} + env: + """, + ), + ( + """ - name: Upload materialized pull request merge tree + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: opencode-coverage-source + path: ${{ runner.temp }}/opencode-coverage-source.tar + if-no-files-found: error + retention-days: 1 + """, + """ - name: Upload materialized pull request merge tree + id: coverage_source_upload + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: opencode-coverage-source-${{ github.run_attempt }} + path: ${{ runner.temp }}/opencode-coverage-source.tar + if-no-files-found: error + retention-days: 1 + """, + ), + ( + """ - name: Download materialized pull request merge tree + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: opencode-coverage-source + path: ${{ runner.temp }}/opencode-coverage-artifact + + - name: Prepare pull request merge tree for coverage measurement + """, + """ - name: Download current-attempt materialized pull request merge tree + id: coverage_source_download + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + artifact-ids: ${{ needs.coverage-source-tree.outputs.coverage_source_artifact_id }} + path: ${{ runner.temp }}/opencode-coverage-artifact + + - name: Report missing current-attempt coverage source + if: steps.coverage_source_download.outcome != 'success' + env: + GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} + run: | + set -euo pipefail + echo "::error::Coverage source evidence is unavailable for workflow run attempt ${GITHUB_RUN_ATTEMPT}; a failed-jobs-only rerun cannot safely reconstruct or reuse source evidence from another attempt." + echo "::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree uploads exact current-attempt evidence." + exit 1 + + - name: Prepare pull request merge tree for coverage measurement + """, + ), + ] + + for old, new in replacements: + count = workflow.count(old) + if count != 1: + raise SystemExit( + f"Expected exactly one trusted workflow replacement target, found {count}." + ) + workflow = workflow.replace(old, new, 1) + + workflow_path.write_text(workflow, encoding="utf-8") + + changelog_path = Path("CHANGELOG.md") + changelog = changelog_path.read_text(encoding="utf-8") + marker = "### Fixed\n\n" + entry = ( + "- Bound OpenCode coverage source artifacts to one workflow attempt and immutable " + "artifact ID, retained one-day source evidence, and made failed-jobs-only reruns " + "fail closed with full-rerun or fresh-dispatch guidance instead of searching for " + "expired or prior-attempt artifacts.\n" + ) + if changelog.count(marker) != 1: + raise SystemExit("Expected exactly one Unreleased Fixed marker.") + if entry not in changelog: + changelog = changelog.replace(marker, marker + entry, 1) + changelog_path.write_text(changelog, encoding="utf-8") + PY + + rm .github/workflows/opencode-coverage-artifact-rerun-repair.yml + + - name: Verify focused regression is green + run: python -m pytest tests/test_opencode_coverage_artifact_rerun_contract.py -q + + - name: Verify complete central test suite + run: python -m pytest tests -q + + - name: Verify Python compilation and clean patch + run: | + set -euo pipefail + python -m compileall -q scripts tests + git diff --check + test -z "$(git ls-files --others --exclude-standard)" + + - name: Commit verified direct repair and remove bootstrap + env: + PUSH_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN }} + TARGET_BRANCH: fix/opencode-attempt-scoped-coverage-artifact + run: | + set -euo pipefail + if [ -z "${PUSH_TOKEN:-}" ]; then + echo "::error::PR_REVIEW_MERGE_TOKEN is required to publish the verified workflow-file repair." + exit 1 + fi + echo "::add-mask::$PUSH_TOKEN" + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add \ + .github/workflows/opencode-review-dispatch.yml \ + .github/workflows/opencode-coverage-artifact-rerun-repair.yml \ + CHANGELOG.md + git commit -m "fix(opencode): bind coverage source artifacts to attempts" + git remote set-url origin "https://x-access-token:${PUSH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" + git push origin "HEAD:refs/heads/${TARGET_BRANCH}" From f9399231ebc6e09051a2e6db6617340b6384659f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 08:48:39 +0900 Subject: [PATCH 07/56] ci: trigger verified attempt-scoped artifact repair --- .github/opencode-attempt-scoped-coverage-artifact.trigger | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/opencode-attempt-scoped-coverage-artifact.trigger b/.github/opencode-attempt-scoped-coverage-artifact.trigger index c113c484b..476d4d4d8 100644 --- a/.github/opencode-attempt-scoped-coverage-artifact.trigger +++ b/.github/opencode-attempt-scoped-coverage-artifact.trigger @@ -1 +1 @@ -This branch-local marker exists only to trigger the self-removing exact-head materializer. +Trigger the reviewed attempt-scoped coverage artifact repair after the repair workflow exists on the branch. From 5a452200fe2de073091f5975d7acb03f304500a0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 08:49:46 +0900 Subject: [PATCH 08/56] fix(ci): preserve literal Actions expressions in repair --- ...pencode-coverage-artifact-rerun-repair.yml | 48 ++++++++++++------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml index 182402665..7a05e9591 100644 --- a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml +++ b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml @@ -54,67 +54,83 @@ jobs: python - <<'PY' from pathlib import Path + def action_expression(value: str) -> str: + """Build a literal GitHub Actions expression without outer evaluation.""" + return "$" + "{{ " + value + " }}" + workflow_path = Path(".github/workflows/opencode-review-dispatch.yml") workflow = workflow_path.read_text(encoding="utf-8") + runner_temp = action_expression("runner.temp") + upload_artifact_id = action_expression( + "steps.coverage_source_upload.outputs.artifact-id" + ) + run_attempt = action_expression("github.run_attempt") + producer_artifact_id = action_expression( + "needs.coverage-source-tree.outputs.coverage_source_artifact_id" + ) + replacements = [ ( + "coverage-source-tree output", """ permissions: contents: read id-token: write env: """, - """ permissions: + f""" permissions: contents: read id-token: write outputs: - coverage_source_artifact_id: ${{ steps.coverage_source_upload.outputs.artifact-id }} + coverage_source_artifact_id: {upload_artifact_id} env: """, ), ( - """ - name: Upload materialized pull request merge tree + "attempt-scoped upload", + f""" - name: Upload materialized pull request merge tree uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: opencode-coverage-source - path: ${{ runner.temp }}/opencode-coverage-source.tar + path: {runner_temp}/opencode-coverage-source.tar if-no-files-found: error retention-days: 1 """, - """ - name: Upload materialized pull request merge tree + f""" - name: Upload materialized pull request merge tree id: coverage_source_upload uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: opencode-coverage-source-${{ github.run_attempt }} - path: ${{ runner.temp }}/opencode-coverage-source.tar + name: opencode-coverage-source-{run_attempt} + path: {runner_temp}/opencode-coverage-source.tar if-no-files-found: error retention-days: 1 """, ), ( - """ - name: Download materialized pull request merge tree + "immutable-id download", + f""" - name: Download materialized pull request merge tree uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: opencode-coverage-source - path: ${{ runner.temp }}/opencode-coverage-artifact + path: {runner_temp}/opencode-coverage-artifact - name: Prepare pull request merge tree for coverage measurement """, - """ - name: Download current-attempt materialized pull request merge tree + f""" - name: Download current-attempt materialized pull request merge tree id: coverage_source_download continue-on-error: true uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - artifact-ids: ${{ needs.coverage-source-tree.outputs.coverage_source_artifact_id }} - path: ${{ runner.temp }}/opencode-coverage-artifact + artifact-ids: {producer_artifact_id} + path: {runner_temp}/opencode-coverage-artifact - name: Report missing current-attempt coverage source if: steps.coverage_source_download.outcome != 'success' env: - GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} + GITHUB_RUN_ATTEMPT: {run_attempt} run: | set -euo pipefail - echo "::error::Coverage source evidence is unavailable for workflow run attempt ${GITHUB_RUN_ATTEMPT}; a failed-jobs-only rerun cannot safely reconstruct or reuse source evidence from another attempt." + echo "::error::Coverage source evidence is unavailable for workflow run attempt ${{GITHUB_RUN_ATTEMPT}}; a failed-jobs-only rerun cannot safely reconstruct or reuse source evidence from another attempt." echo "::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree uploads exact current-attempt evidence." exit 1 @@ -123,11 +139,11 @@ jobs: ), ] - for old, new in replacements: + for label, old, new in replacements: count = workflow.count(old) if count != 1: raise SystemExit( - f"Expected exactly one trusted workflow replacement target, found {count}." + f"Expected exactly one {label} replacement target, found {count}." ) workflow = workflow.replace(old, new, 1) From 2431afbf9078e96f266891c1bfaa44c242d45f15 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 08:50:38 +0900 Subject: [PATCH 09/56] ci: rerun corrected attempt-scoped artifact repair --- .github/opencode-attempt-scoped-coverage-artifact.trigger | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/opencode-attempt-scoped-coverage-artifact.trigger b/.github/opencode-attempt-scoped-coverage-artifact.trigger index 476d4d4d8..07e150778 100644 --- a/.github/opencode-attempt-scoped-coverage-artifact.trigger +++ b/.github/opencode-attempt-scoped-coverage-artifact.trigger @@ -1 +1 @@ -Trigger the reviewed attempt-scoped coverage artifact repair after the repair workflow exists on the branch. +Trigger the corrected workflow-preserving attempt-scoped coverage artifact repair. From a7f8901b5cce55f2c433fc7d5e77af18a7d9d5e3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 08:51:47 +0900 Subject: [PATCH 10/56] fix(ci): avoid nested Actions expression parsing --- .github/workflows/opencode-coverage-artifact-rerun-repair.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml index 7a05e9591..23f250504 100644 --- a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml +++ b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml @@ -69,6 +69,7 @@ jobs: producer_artifact_id = action_expression( "needs.coverage-source-tree.outputs.coverage_source_artifact_id" ) + shell_run_attempt = "$" + "{GITHUB_RUN_ATTEMPT}" replacements = [ ( @@ -130,7 +131,7 @@ jobs: GITHUB_RUN_ATTEMPT: {run_attempt} run: | set -euo pipefail - echo "::error::Coverage source evidence is unavailable for workflow run attempt ${{GITHUB_RUN_ATTEMPT}}; a failed-jobs-only rerun cannot safely reconstruct or reuse source evidence from another attempt." + echo "::error::Coverage source evidence is unavailable for workflow run attempt {shell_run_attempt}; a failed-jobs-only rerun cannot safely reconstruct or reuse source evidence from another attempt." echo "::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree uploads exact current-attempt evidence." exit 1 From 54436c6119a790bd8d99b485aa0fe5d0e8b30332 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 08:53:29 +0900 Subject: [PATCH 11/56] ci: rerun expression-safe artifact repair --- .github/opencode-attempt-scoped-coverage-artifact.trigger | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/opencode-attempt-scoped-coverage-artifact.trigger b/.github/opencode-attempt-scoped-coverage-artifact.trigger index 07e150778..8cda4f8c6 100644 --- a/.github/opencode-attempt-scoped-coverage-artifact.trigger +++ b/.github/opencode-attempt-scoped-coverage-artifact.trigger @@ -1 +1 @@ -Trigger the corrected workflow-preserving attempt-scoped coverage artifact repair. +Trigger the expression-safe attempt-scoped coverage artifact repair. From 8fe2148ef83eefa7cd941de102b7109ff0277701 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 08:56:05 +0900 Subject: [PATCH 12/56] fix(ci): patch workflow by bounded line anchors --- ...pencode-coverage-artifact-rerun-repair.yml | 265 ++++++++++++------ 1 file changed, 181 insertions(+), 84 deletions(-) diff --git a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml index 23f250504..3a3455bfe 100644 --- a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml +++ b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml @@ -55,100 +55,197 @@ jobs: from pathlib import Path def action_expression(value: str) -> str: - """Build a literal GitHub Actions expression without outer evaluation.""" + """Build a literal GitHub Actions expression at runtime.""" return "$" + "{{ " + value + " }}" + def unique_index( + lines: list[str], + needle: str, + *, + start: int = 0, + end: int | None = None, + label: str, + ) -> int: + """Return the only exact line match inside a bounded range.""" + stop = len(lines) if end is None else end + matches = [ + index + for index in range(start, stop) + if lines[index] == needle + ] + if len(matches) != 1: + raise SystemExit( + f"Expected exactly one {label} line, found {len(matches)}." + ) + return matches[0] + workflow_path = Path(".github/workflows/opencode-review-dispatch.yml") - workflow = workflow_path.read_text(encoding="utf-8") + lines = workflow_path.read_text(encoding="utf-8").splitlines(keepends=True) - runner_temp = action_expression("runner.temp") - upload_artifact_id = action_expression( - "steps.coverage_source_upload.outputs.artifact-id" + producer_start = unique_index( + lines, + " coverage-source-tree:\n", + label="coverage-source-tree job", ) - run_attempt = action_expression("github.run_attempt") - producer_artifact_id = action_expression( - "needs.coverage-source-tree.outputs.coverage_source_artifact_id" + consumer_start = unique_index( + lines, + " coverage-evidence:\n", + label="coverage-evidence job", ) - shell_run_attempt = "$" + "{GITHUB_RUN_ATTEMPT}" + producer_env = unique_index( + lines, + " env:\n", + start=producer_start, + end=consumer_start, + label="coverage-source-tree env", + ) + expected_permissions = [ + " permissions:\n", + " contents: read\n", + " id-token: write\n", + ] + if lines[producer_env - 3 : producer_env] != expected_permissions: + raise SystemExit( + "coverage-source-tree permission boundary no longer matches the reviewed contract." + ) + lines[producer_env:producer_env] = [ + " outputs:\n", + " coverage_source_artifact_id: " + + action_expression("steps.coverage_source_upload.outputs.artifact-id") + + "\n", + ] - replacements = [ - ( - "coverage-source-tree output", - """ permissions: - contents: read - id-token: write - env: - """, - f""" permissions: - contents: read - id-token: write - outputs: - coverage_source_artifact_id: {upload_artifact_id} - env: - """, - ), - ( - "attempt-scoped upload", - f""" - name: Upload materialized pull request merge tree - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: opencode-coverage-source - path: {runner_temp}/opencode-coverage-source.tar - if-no-files-found: error - retention-days: 1 - """, - f""" - name: Upload materialized pull request merge tree - id: coverage_source_upload - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: opencode-coverage-source-{run_attempt} - path: {runner_temp}/opencode-coverage-source.tar - if-no-files-found: error - retention-days: 1 - """, - ), - ( - "immutable-id download", - f""" - name: Download materialized pull request merge tree - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: opencode-coverage-source - path: {runner_temp}/opencode-coverage-artifact - - - name: Prepare pull request merge tree for coverage measurement - """, - f""" - name: Download current-attempt materialized pull request merge tree - id: coverage_source_download - continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - artifact-ids: {producer_artifact_id} - path: {runner_temp}/opencode-coverage-artifact - - - name: Report missing current-attempt coverage source - if: steps.coverage_source_download.outcome != 'success' - env: - GITHUB_RUN_ATTEMPT: {run_attempt} - run: | - set -euo pipefail - echo "::error::Coverage source evidence is unavailable for workflow run attempt {shell_run_attempt}; a failed-jobs-only rerun cannot safely reconstruct or reuse source evidence from another attempt." - echo "::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree uploads exact current-attempt evidence." - exit 1 - - - name: Prepare pull request merge tree for coverage measurement - """, - ), + producer_start = unique_index( + lines, + " coverage-source-tree:\n", + label="coverage-source-tree job after output insertion", + ) + consumer_start = unique_index( + lines, + " coverage-evidence:\n", + label="coverage-evidence job after output insertion", + ) + upload_step = unique_index( + lines, + " - name: Upload materialized pull request merge tree\n", + start=producer_start, + end=consumer_start, + label="coverage source upload step", + ) + if not lines[upload_step + 1].startswith( + " uses: actions/upload-artifact@" + ): + raise SystemExit("Coverage upload action anchor changed unexpectedly.") + lines[upload_step + 1 : upload_step + 1] = [ + " id: coverage_source_upload\n" ] - for label, old, new in replacements: - count = workflow.count(old) - if count != 1: - raise SystemExit( - f"Expected exactly one {label} replacement target, found {count}." - ) - workflow = workflow.replace(old, new, 1) + consumer_start = unique_index( + lines, + " coverage-evidence:\n", + label="coverage-evidence job after upload ID insertion", + ) + upload_name = unique_index( + lines, + " name: opencode-coverage-source\n", + start=upload_step, + end=consumer_start, + label="coverage source upload name", + ) + lines[upload_name] = ( + " name: opencode-coverage-source-" + + action_expression("github.run_attempt") + + "\n" + ) + + consumer_start = unique_index( + lines, + " coverage-evidence:\n", + label="coverage-evidence job before download repair", + ) + review_start = unique_index( + lines, + " opencode-review-target:\n", + start=consumer_start, + label="opencode-review-target job", + ) + download_step = unique_index( + lines, + " - name: Download materialized pull request merge tree\n", + start=consumer_start, + end=review_start, + label="coverage source download step", + ) + if not lines[download_step + 1].startswith( + " uses: actions/download-artifact@" + ): + raise SystemExit("Coverage download action anchor changed unexpectedly.") + lines[download_step] = ( + " - name: Download current-attempt materialized pull request merge tree\n" + ) + lines[download_step + 1 : download_step + 1] = [ + " id: coverage_source_download\n", + " continue-on-error: true\n", + ] + + review_start = unique_index( + lines, + " opencode-review-target:\n", + start=consumer_start, + label="opencode-review-target job after download ID insertion", + ) + download_name = unique_index( + lines, + " name: opencode-coverage-source\n", + start=download_step, + end=review_start, + label="coverage source download name", + ) + lines[download_name] = ( + " artifact-ids: " + + action_expression( + "needs.coverage-source-tree.outputs.coverage_source_artifact_id" + ) + + "\n" + ) + + review_start = unique_index( + lines, + " opencode-review-target:\n", + start=consumer_start, + label="opencode-review-target job before failure guidance insertion", + ) + download_path = unique_index( + lines, + " path: " + + action_expression("runner.temp") + + "/opencode-coverage-artifact\n", + start=download_step, + end=review_start, + label="coverage source download path", + ) + if lines[download_path + 1] != "\n": + raise SystemExit("Expected a blank line after the coverage download step.") + shell_run_attempt = "$" + "{GITHUB_RUN_ATTEMPT}" + lines[download_path + 1 : download_path + 2] = [ + "\n", + " - name: Report missing current-attempt coverage source\n", + " if: steps.coverage_source_download.outcome != 'success'\n", + " env:\n", + " GITHUB_RUN_ATTEMPT: " + + action_expression("github.run_attempt") + + "\n", + " run: |\n", + " set -euo pipefail\n", + " echo \"::error::Coverage source evidence is unavailable for workflow run attempt " + + shell_run_attempt + + "; a failed-jobs-only rerun cannot safely reconstruct or reuse source evidence from another attempt.\"\n", + " echo \"::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree uploads exact current-attempt evidence.\"\n", + " exit 1\n", + "\n", + ] - workflow_path.write_text(workflow, encoding="utf-8") + workflow_path.write_text("".join(lines), encoding="utf-8") changelog_path = Path("CHANGELOG.md") changelog = changelog_path.read_text(encoding="utf-8") From 46ec344161430e8501658e84e55a725993d8114e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:00:56 +0900 Subject: [PATCH 13/56] fix(ci): publish verified repair with repository token --- .github/workflows/opencode-coverage-artifact-rerun-repair.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml index 3a3455bfe..ef5b1f139 100644 --- a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml +++ b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml @@ -280,12 +280,12 @@ jobs: - name: Commit verified direct repair and remove bootstrap env: - PUSH_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN }} + PUSH_TOKEN: ${{ github.token }} TARGET_BRANCH: fix/opencode-attempt-scoped-coverage-artifact run: | set -euo pipefail if [ -z "${PUSH_TOKEN:-}" ]; then - echo "::error::PR_REVIEW_MERGE_TOKEN is required to publish the verified workflow-file repair." + echo "::error::The repository-scoped GitHub Actions token is required to publish the verified workflow-file repair." exit 1 fi echo "::add-mask::$PUSH_TOKEN" From ff6121bf0b17d1d81d8f134c1e57c0e723d2fa64 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:05:52 +0900 Subject: [PATCH 14/56] chore(opencode): add temporary verified patch materializer --- ...prepare_opencode_attempt_artifact_patch.py | 231 ++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 scripts/ci/prepare_opencode_attempt_artifact_patch.py diff --git a/scripts/ci/prepare_opencode_attempt_artifact_patch.py b/scripts/ci/prepare_opencode_attempt_artifact_patch.py new file mode 100644 index 000000000..15d3b9f40 --- /dev/null +++ b/scripts/ci/prepare_opencode_attempt_artifact_patch.py @@ -0,0 +1,231 @@ +#!/usr/bin/env python3 +"""Materialize the reviewed OpenCode attempt-scoped artifact repair. + +This helper is a temporary branch-local materializer. It changes only the central +OpenCode dispatch workflow and the Unreleased changelog entry. The permanent +behavior is guarded by ``tests/test_opencode_coverage_artifact_rerun_contract.py``. +""" + +from __future__ import annotations + +from pathlib import Path + + +WORKFLOW_PATH = Path(".github/workflows/opencode-review-dispatch.yml") +CHANGELOG_PATH = Path("CHANGELOG.md") + + +def action_expression(value: str) -> str: + """Build a literal GitHub Actions expression at runtime.""" + return "$" + "{{ " + value + " }}" + + +def unique_index( + lines: list[str], + needle: str, + *, + start: int = 0, + end: int | None = None, + label: str, +) -> int: + """Return the only exact line match inside a bounded range.""" + stop = len(lines) if end is None else end + matches = [index for index in range(start, stop) if lines[index] == needle] + if len(matches) != 1: + raise SystemExit( + f"Expected exactly one {label} line, found {len(matches)}." + ) + return matches[0] + + +def patch_workflow() -> None: + """Bind the coverage producer and consumer through an immutable artifact ID.""" + lines = WORKFLOW_PATH.read_text(encoding="utf-8").splitlines(keepends=True) + + producer_start = unique_index( + lines, + " coverage-source-tree:\n", + label="coverage-source-tree job", + ) + consumer_start = unique_index( + lines, + " coverage-evidence:\n", + label="coverage-evidence job", + ) + producer_env = unique_index( + lines, + " env:\n", + start=producer_start, + end=consumer_start, + label="coverage-source-tree env", + ) + expected_permissions = [ + " permissions:\n", + " contents: read\n", + " id-token: write\n", + ] + if lines[producer_env - 3 : producer_env] != expected_permissions: + raise SystemExit( + "coverage-source-tree permission boundary no longer matches the reviewed contract." + ) + lines[producer_env:producer_env] = [ + " outputs:\n", + " coverage_source_artifact_id: " + + action_expression("steps.coverage_source_upload.outputs.artifact-id") + + "\n", + ] + + producer_start = unique_index( + lines, + " coverage-source-tree:\n", + label="coverage-source-tree job after output insertion", + ) + consumer_start = unique_index( + lines, + " coverage-evidence:\n", + label="coverage-evidence job after output insertion", + ) + upload_step = unique_index( + lines, + " - name: Upload materialized pull request merge tree\n", + start=producer_start, + end=consumer_start, + label="coverage source upload step", + ) + if not lines[upload_step + 1].startswith(" uses: actions/upload-artifact@"): + raise SystemExit("Coverage upload action anchor changed unexpectedly.") + lines[upload_step + 1 : upload_step + 1] = [" id: coverage_source_upload\n"] + + consumer_start = unique_index( + lines, + " coverage-evidence:\n", + label="coverage-evidence job after upload ID insertion", + ) + upload_name = unique_index( + lines, + " name: opencode-coverage-source\n", + start=upload_step, + end=consumer_start, + label="coverage source upload name", + ) + lines[upload_name] = ( + " name: opencode-coverage-source-" + + action_expression("github.run_attempt") + + "\n" + ) + + consumer_start = unique_index( + lines, + " coverage-evidence:\n", + label="coverage-evidence job before download repair", + ) + review_start = unique_index( + lines, + " opencode-review-target:\n", + start=consumer_start, + label="opencode-review-target job", + ) + download_step = unique_index( + lines, + " - name: Download materialized pull request merge tree\n", + start=consumer_start, + end=review_start, + label="coverage source download step", + ) + if not lines[download_step + 1].startswith( + " uses: actions/download-artifact@" + ): + raise SystemExit("Coverage download action anchor changed unexpectedly.") + lines[download_step] = ( + " - name: Download current-attempt materialized pull request merge tree\n" + ) + lines[download_step + 1 : download_step + 1] = [ + " id: coverage_source_download\n", + " continue-on-error: true\n", + ] + + review_start = unique_index( + lines, + " opencode-review-target:\n", + start=consumer_start, + label="opencode-review-target job after download ID insertion", + ) + download_name = unique_index( + lines, + " name: opencode-coverage-source\n", + start=download_step, + end=review_start, + label="coverage source download name", + ) + lines[download_name] = ( + " artifact-ids: " + + action_expression( + "needs.coverage-source-tree.outputs.coverage_source_artifact_id" + ) + + "\n" + ) + + review_start = unique_index( + lines, + " opencode-review-target:\n", + start=consumer_start, + label="opencode-review-target job before failure guidance insertion", + ) + download_path = unique_index( + lines, + " path: " + + action_expression("runner.temp") + + "/opencode-coverage-artifact\n", + start=download_step, + end=review_start, + label="coverage source download path", + ) + if lines[download_path + 1] != "\n": + raise SystemExit("Expected a blank line after the coverage download step.") + shell_run_attempt = "$" + "{GITHUB_RUN_ATTEMPT}" + lines[download_path + 1 : download_path + 2] = [ + "\n", + " - name: Report missing current-attempt coverage source\n", + " if: steps.coverage_source_download.outcome != 'success'\n", + " env:\n", + " GITHUB_RUN_ATTEMPT: " + + action_expression("github.run_attempt") + + "\n", + " run: |\n", + " set -euo pipefail\n", + " echo \"::error::Coverage source evidence is unavailable for workflow run attempt " + + shell_run_attempt + + "; a failed-jobs-only rerun cannot safely reconstruct or reuse source evidence from another attempt.\"\n", + " echo \"::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree uploads exact current-attempt evidence.\"\n", + " exit 1\n", + "\n", + ] + + WORKFLOW_PATH.write_text("".join(lines), encoding="utf-8") + + +def patch_changelog() -> None: + """Record the attempt-scoped artifact correction under Unreleased fixes.""" + changelog = CHANGELOG_PATH.read_text(encoding="utf-8") + marker = "### Fixed\n\n" + entry = ( + "- Bound OpenCode coverage source artifacts to one workflow attempt and immutable " + "artifact ID, retained one-day source evidence, and made failed-jobs-only reruns " + "fail closed with full-rerun or fresh-dispatch guidance instead of searching for " + "expired or prior-attempt artifacts.\n" + ) + if changelog.count(marker) != 1: + raise SystemExit("Expected exactly one Unreleased Fixed marker.") + if entry not in changelog: + changelog = changelog.replace(marker, marker + entry, 1) + CHANGELOG_PATH.write_text(changelog, encoding="utf-8") + + +def main() -> None: + """Apply the bounded workflow and changelog patch.""" + patch_workflow() + patch_changelog() + + +if __name__ == "__main__": + main() From 17d16cfe230b22b5bdf6014ef8f2388d6952531d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:06:22 +0900 Subject: [PATCH 15/56] ci(opencode): export verified workflow repair payload --- ...pencode-coverage-artifact-rerun-repair.yml | 260 ++---------------- 1 file changed, 20 insertions(+), 240 deletions(-) diff --git a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml index ef5b1f139..4be0342c0 100644 --- a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml +++ b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml @@ -12,13 +12,13 @@ concurrency: cancel-in-progress: false permissions: - contents: write + contents: read env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true jobs: - repair: + materialize-and-export: if: >- github.repository == 'ContextualWisdomLab/.github' && github.ref == 'refs/heads/fix/opencode-attempt-scoped-coverage-artifact' @@ -35,7 +35,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - fetch-depth: 0 ref: ${{ github.sha }} - name: Set up current stable Python @@ -48,253 +47,34 @@ jobs: - name: Install hash-locked quality tooling run: python -m pip install --disable-pip-version-check --require-hashes -r requirements-opencode-review-ci-hashes.txt - - name: Apply exact attempt-scoped artifact repair - run: | - set -euo pipefail - python - <<'PY' - from pathlib import Path - - def action_expression(value: str) -> str: - """Build a literal GitHub Actions expression at runtime.""" - return "$" + "{{ " + value + " }}" - - def unique_index( - lines: list[str], - needle: str, - *, - start: int = 0, - end: int | None = None, - label: str, - ) -> int: - """Return the only exact line match inside a bounded range.""" - stop = len(lines) if end is None else end - matches = [ - index - for index in range(start, stop) - if lines[index] == needle - ] - if len(matches) != 1: - raise SystemExit( - f"Expected exactly one {label} line, found {len(matches)}." - ) - return matches[0] - - workflow_path = Path(".github/workflows/opencode-review-dispatch.yml") - lines = workflow_path.read_text(encoding="utf-8").splitlines(keepends=True) - - producer_start = unique_index( - lines, - " coverage-source-tree:\n", - label="coverage-source-tree job", - ) - consumer_start = unique_index( - lines, - " coverage-evidence:\n", - label="coverage-evidence job", - ) - producer_env = unique_index( - lines, - " env:\n", - start=producer_start, - end=consumer_start, - label="coverage-source-tree env", - ) - expected_permissions = [ - " permissions:\n", - " contents: read\n", - " id-token: write\n", - ] - if lines[producer_env - 3 : producer_env] != expected_permissions: - raise SystemExit( - "coverage-source-tree permission boundary no longer matches the reviewed contract." - ) - lines[producer_env:producer_env] = [ - " outputs:\n", - " coverage_source_artifact_id: " - + action_expression("steps.coverage_source_upload.outputs.artifact-id") - + "\n", - ] - - producer_start = unique_index( - lines, - " coverage-source-tree:\n", - label="coverage-source-tree job after output insertion", - ) - consumer_start = unique_index( - lines, - " coverage-evidence:\n", - label="coverage-evidence job after output insertion", - ) - upload_step = unique_index( - lines, - " - name: Upload materialized pull request merge tree\n", - start=producer_start, - end=consumer_start, - label="coverage source upload step", - ) - if not lines[upload_step + 1].startswith( - " uses: actions/upload-artifact@" - ): - raise SystemExit("Coverage upload action anchor changed unexpectedly.") - lines[upload_step + 1 : upload_step + 1] = [ - " id: coverage_source_upload\n" - ] - - consumer_start = unique_index( - lines, - " coverage-evidence:\n", - label="coverage-evidence job after upload ID insertion", - ) - upload_name = unique_index( - lines, - " name: opencode-coverage-source\n", - start=upload_step, - end=consumer_start, - label="coverage source upload name", - ) - lines[upload_name] = ( - " name: opencode-coverage-source-" - + action_expression("github.run_attempt") - + "\n" - ) - - consumer_start = unique_index( - lines, - " coverage-evidence:\n", - label="coverage-evidence job before download repair", - ) - review_start = unique_index( - lines, - " opencode-review-target:\n", - start=consumer_start, - label="opencode-review-target job", - ) - download_step = unique_index( - lines, - " - name: Download materialized pull request merge tree\n", - start=consumer_start, - end=review_start, - label="coverage source download step", - ) - if not lines[download_step + 1].startswith( - " uses: actions/download-artifact@" - ): - raise SystemExit("Coverage download action anchor changed unexpectedly.") - lines[download_step] = ( - " - name: Download current-attempt materialized pull request merge tree\n" - ) - lines[download_step + 1 : download_step + 1] = [ - " id: coverage_source_download\n", - " continue-on-error: true\n", - ] - - review_start = unique_index( - lines, - " opencode-review-target:\n", - start=consumer_start, - label="opencode-review-target job after download ID insertion", - ) - download_name = unique_index( - lines, - " name: opencode-coverage-source\n", - start=download_step, - end=review_start, - label="coverage source download name", - ) - lines[download_name] = ( - " artifact-ids: " - + action_expression( - "needs.coverage-source-tree.outputs.coverage_source_artifact_id" - ) - + "\n" - ) + - name: Materialize attempt-scoped artifact repair + run: python scripts/ci/prepare_opencode_attempt_artifact_patch.py - review_start = unique_index( - lines, - " opencode-review-target:\n", - start=consumer_start, - label="opencode-review-target job before failure guidance insertion", - ) - download_path = unique_index( - lines, - " path: " - + action_expression("runner.temp") - + "/opencode-coverage-artifact\n", - start=download_step, - end=review_start, - label="coverage source download path", - ) - if lines[download_path + 1] != "\n": - raise SystemExit("Expected a blank line after the coverage download step.") - shell_run_attempt = "$" + "{GITHUB_RUN_ATTEMPT}" - lines[download_path + 1 : download_path + 2] = [ - "\n", - " - name: Report missing current-attempt coverage source\n", - " if: steps.coverage_source_download.outcome != 'success'\n", - " env:\n", - " GITHUB_RUN_ATTEMPT: " - + action_expression("github.run_attempt") - + "\n", - " run: |\n", - " set -euo pipefail\n", - " echo \"::error::Coverage source evidence is unavailable for workflow run attempt " - + shell_run_attempt - + "; a failed-jobs-only rerun cannot safely reconstruct or reuse source evidence from another attempt.\"\n", - " echo \"::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree uploads exact current-attempt evidence.\"\n", - " exit 1\n", - "\n", - ] - - workflow_path.write_text("".join(lines), encoding="utf-8") - - changelog_path = Path("CHANGELOG.md") - changelog = changelog_path.read_text(encoding="utf-8") - marker = "### Fixed\n\n" - entry = ( - "- Bound OpenCode coverage source artifacts to one workflow attempt and immutable " - "artifact ID, retained one-day source evidence, and made failed-jobs-only reruns " - "fail closed with full-rerun or fresh-dispatch guidance instead of searching for " - "expired or prior-attempt artifacts.\n" - ) - if changelog.count(marker) != 1: - raise SystemExit("Expected exactly one Unreleased Fixed marker.") - if entry not in changelog: - changelog = changelog.replace(marker, marker + entry, 1) - changelog_path.write_text(changelog, encoding="utf-8") - PY - - rm .github/workflows/opencode-coverage-artifact-rerun-repair.yml - - - name: Verify focused regression is green + - name: Verify focused regression run: python -m pytest tests/test_opencode_coverage_artifact_rerun_contract.py -q - name: Verify complete central test suite run: python -m pytest tests -q - - name: Verify Python compilation and clean patch + - name: Verify compilation and bounded patch run: | set -euo pipefail python -m compileall -q scripts tests git diff --check - test -z "$(git ls-files --others --exclude-standard)" - - - name: Commit verified direct repair and remove bootstrap - env: - PUSH_TOKEN: ${{ github.token }} - TARGET_BRANCH: fix/opencode-attempt-scoped-coverage-artifact - run: | - set -euo pipefail - if [ -z "${PUSH_TOKEN:-}" ]; then - echo "::error::The repository-scoped GitHub Actions token is required to publish the verified workflow-file repair." + changed="$(git diff --name-only | sort)" + expected="$(printf '%s\n' '.github/workflows/opencode-review-dispatch.yml' 'CHANGELOG.md' | sort)" + if [ "$changed" != "$expected" ]; then + printf 'Unexpected materialized paths:\n%s\n' "$changed" >&2 exit 1 fi - echo "::add-mask::$PUSH_TOKEN" - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add \ - .github/workflows/opencode-review-dispatch.yml \ - .github/workflows/opencode-coverage-artifact-rerun-repair.yml \ + + - name: Upload verified repair payload + id: repair_payload_upload + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: opencode-attempt-artifact-repair-payload-${{ github.run_attempt }} + path: | + .github/workflows/opencode-review-dispatch.yml CHANGELOG.md - git commit -m "fix(opencode): bind coverage source artifacts to attempts" - git remote set-url origin "https://x-access-token:${PUSH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" - git push origin "HEAD:refs/heads/${TARGET_BRANCH}" + if-no-files-found: error + retention-days: 1 From 3dc3a73104fb2fd7c2e5e46ab0daf07c33f0912d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:14:45 +0900 Subject: [PATCH 16/56] ci(opencode): publish repair with OpenCode app token --- ...pencode-coverage-artifact-rerun-repair.yml | 70 ++++++++++++++++++- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml index 4be0342c0..d11d5ea2b 100644 --- a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml +++ b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml @@ -13,12 +13,13 @@ concurrency: permissions: contents: read + id-token: write env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true jobs: - materialize-and-export: + repair-and-publish: if: >- github.repository == 'ContextualWisdomLab/.github' && github.ref == 'refs/heads/fix/opencode-attempt-scoped-coverage-artifact' @@ -31,10 +32,52 @@ jobs: with: egress-policy: audit + - name: Exchange OpenCode app token for workflow-file repair + id: target_app_token + env: + OIDC_AUDIENCE: opencode-github-action + OPENCODE_API_BASE_URL: https://api.opencode.ai + run: | + set -euo pipefail + if [ -z "${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-}" ] || [ -z "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" ]; then + echo "::error::OpenCode app token exchange unavailable: OIDC request environment is missing." + exit 1 + fi + request_url="${ACTIONS_ID_TOKEN_REQUEST_URL}" + separator="&" + case "$request_url" in + *\?*) ;; + *) separator="?" ;; + esac + oidc_response="$( + curl -fsS \ + -H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \ + "${request_url}${separator}audience=${OIDC_AUDIENCE}" + )" + oidc_token="$(jq -r '.value // empty' <<<"$oidc_response")" + if [ -z "$oidc_token" ]; then + echo "::error::OpenCode app token exchange unavailable: OIDC token response was empty." + exit 1 + fi + token_response="$( + curl -fsS \ + -X POST \ + -H "Authorization: Bearer ${oidc_token}" \ + "${OPENCODE_API_BASE_URL}/exchange_github_app_token" + )" + app_token="$(jq -r '.token // empty' <<<"$token_response")" + if [ -z "$app_token" ]; then + echo "::error::OpenCode app token exchange unavailable: app token response was empty." + exit 1 + fi + echo "::add-mask::$app_token" + echo "token=$app_token" >>"$GITHUB_OUTPUT" + - name: Checkout exact repair head uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false + fetch-depth: 0 ref: ${{ github.sha }} - name: Set up current stable Python @@ -69,7 +112,6 @@ jobs: fi - name: Upload verified repair payload - id: repair_payload_upload uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: opencode-attempt-artifact-repair-payload-${{ github.run_attempt }} @@ -78,3 +120,27 @@ jobs: CHANGELOG.md if-no-files-found: error retention-days: 1 + + - name: Commit verified repair and remove temporary materializers + env: + PUSH_TOKEN: ${{ steps.target_app_token.outputs.token }} + TARGET_BRANCH: fix/opencode-attempt-scoped-coverage-artifact + run: | + set -euo pipefail + if [ -z "${PUSH_TOKEN:-}" ]; then + echo "::error::OpenCode repository token is required to publish the verified repair." + exit 1 + fi + echo "::add-mask::$PUSH_TOKEN" + rm .github/workflows/opencode-coverage-artifact-rerun-repair.yml + rm scripts/ci/prepare_opencode_attempt_artifact_patch.py + git config user.name "opencode-agent[bot]" + git config user.email "opencode-agent[bot]@users.noreply.github.com" + git add \ + .github/workflows/opencode-review-dispatch.yml \ + .github/workflows/opencode-coverage-artifact-rerun-repair.yml \ + scripts/ci/prepare_opencode_attempt_artifact_patch.py \ + CHANGELOG.md + git commit -m "fix(opencode): bind coverage source artifacts to attempts" + git remote set-url origin "https://x-access-token:${PUSH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" + git push origin "HEAD:refs/heads/${TARGET_BRANCH}" From 76c11d99390f672749f9bae2089b04c2e1898e83 Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" Date: Fri, 7 Aug 2026 00:16:19 +0000 Subject: [PATCH 17/56] fix(opencode): bind coverage source artifacts to attempts --- ...pencode-coverage-artifact-rerun-repair.yml | 146 ----------- .../workflows/opencode-review-dispatch.yml | 21 +- CHANGELOG.md | 1 + ...prepare_opencode_attempt_artifact_patch.py | 231 ------------------ 4 files changed, 19 insertions(+), 380 deletions(-) delete mode 100644 .github/workflows/opencode-coverage-artifact-rerun-repair.yml delete mode 100644 scripts/ci/prepare_opencode_attempt_artifact_patch.py diff --git a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml deleted file mode 100644 index d11d5ea2b..000000000 --- a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml +++ /dev/null @@ -1,146 +0,0 @@ -name: OpenCode Coverage Artifact Rerun Repair - -on: - push: - branches: - - fix/opencode-attempt-scoped-coverage-artifact - paths: - - ".github/workflows/opencode-coverage-artifact-rerun-repair.yml" - -concurrency: - group: opencode-coverage-artifact-rerun-repair - cancel-in-progress: false - -permissions: - contents: read - id-token: write - -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - -jobs: - repair-and-publish: - if: >- - github.repository == 'ContextualWisdomLab/.github' - && github.ref == 'refs/heads/fix/opencode-attempt-scoped-coverage-artifact' - && github.actor == 'seonghobae' - runs-on: ubuntu-latest - timeout-minutes: 30 - steps: - - name: Harden runner - uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 - with: - egress-policy: audit - - - name: Exchange OpenCode app token for workflow-file repair - id: target_app_token - env: - OIDC_AUDIENCE: opencode-github-action - OPENCODE_API_BASE_URL: https://api.opencode.ai - run: | - set -euo pipefail - if [ -z "${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-}" ] || [ -z "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" ]; then - echo "::error::OpenCode app token exchange unavailable: OIDC request environment is missing." - exit 1 - fi - request_url="${ACTIONS_ID_TOKEN_REQUEST_URL}" - separator="&" - case "$request_url" in - *\?*) ;; - *) separator="?" ;; - esac - oidc_response="$( - curl -fsS \ - -H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \ - "${request_url}${separator}audience=${OIDC_AUDIENCE}" - )" - oidc_token="$(jq -r '.value // empty' <<<"$oidc_response")" - if [ -z "$oidc_token" ]; then - echo "::error::OpenCode app token exchange unavailable: OIDC token response was empty." - exit 1 - fi - token_response="$( - curl -fsS \ - -X POST \ - -H "Authorization: Bearer ${oidc_token}" \ - "${OPENCODE_API_BASE_URL}/exchange_github_app_token" - )" - app_token="$(jq -r '.token // empty' <<<"$token_response")" - if [ -z "$app_token" ]; then - echo "::error::OpenCode app token exchange unavailable: app token response was empty." - exit 1 - fi - echo "::add-mask::$app_token" - echo "token=$app_token" >>"$GITHUB_OUTPUT" - - - name: Checkout exact repair head - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - persist-credentials: false - fetch-depth: 0 - ref: ${{ github.sha }} - - - name: Set up current stable Python - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 - with: - python-version: "3.14" - cache: pip - cache-dependency-path: requirements-opencode-review-ci-hashes.txt - - - name: Install hash-locked quality tooling - run: python -m pip install --disable-pip-version-check --require-hashes -r requirements-opencode-review-ci-hashes.txt - - - name: Materialize attempt-scoped artifact repair - run: python scripts/ci/prepare_opencode_attempt_artifact_patch.py - - - name: Verify focused regression - run: python -m pytest tests/test_opencode_coverage_artifact_rerun_contract.py -q - - - name: Verify complete central test suite - run: python -m pytest tests -q - - - name: Verify compilation and bounded patch - run: | - set -euo pipefail - python -m compileall -q scripts tests - git diff --check - changed="$(git diff --name-only | sort)" - expected="$(printf '%s\n' '.github/workflows/opencode-review-dispatch.yml' 'CHANGELOG.md' | sort)" - if [ "$changed" != "$expected" ]; then - printf 'Unexpected materialized paths:\n%s\n' "$changed" >&2 - exit 1 - fi - - - name: Upload verified repair payload - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: opencode-attempt-artifact-repair-payload-${{ github.run_attempt }} - path: | - .github/workflows/opencode-review-dispatch.yml - CHANGELOG.md - if-no-files-found: error - retention-days: 1 - - - name: Commit verified repair and remove temporary materializers - env: - PUSH_TOKEN: ${{ steps.target_app_token.outputs.token }} - TARGET_BRANCH: fix/opencode-attempt-scoped-coverage-artifact - run: | - set -euo pipefail - if [ -z "${PUSH_TOKEN:-}" ]; then - echo "::error::OpenCode repository token is required to publish the verified repair." - exit 1 - fi - echo "::add-mask::$PUSH_TOKEN" - rm .github/workflows/opencode-coverage-artifact-rerun-repair.yml - rm scripts/ci/prepare_opencode_attempt_artifact_patch.py - git config user.name "opencode-agent[bot]" - git config user.email "opencode-agent[bot]@users.noreply.github.com" - git add \ - .github/workflows/opencode-review-dispatch.yml \ - .github/workflows/opencode-coverage-artifact-rerun-repair.yml \ - scripts/ci/prepare_opencode_attempt_artifact_patch.py \ - CHANGELOG.md - git commit -m "fix(opencode): bind coverage source artifacts to attempts" - git remote set-url origin "https://x-access-token:${PUSH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" - git push origin "HEAD:refs/heads/${TARGET_BRANCH}" diff --git a/.github/workflows/opencode-review-dispatch.yml b/.github/workflows/opencode-review-dispatch.yml index 83f6830d5..195f28f8c 100644 --- a/.github/workflows/opencode-review-dispatch.yml +++ b/.github/workflows/opencode-review-dispatch.yml @@ -222,6 +222,8 @@ jobs: permissions: contents: read id-token: write + outputs: + coverage_source_artifact_id: ${{ steps.coverage_source_upload.outputs.artifact-id }} env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true steps: @@ -350,9 +352,10 @@ jobs: tar -cf "$COVERAGE_SOURCE_ARCHIVE" -C "$COVERAGE_SOURCE_WORKDIR" . - name: Upload materialized pull request merge tree + id: coverage_source_upload uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: opencode-coverage-source + name: opencode-coverage-source-${{ github.run_attempt }} path: ${{ runner.temp }}/opencode-coverage-source.tar if-no-files-found: error retention-days: 1 @@ -433,12 +436,24 @@ jobs: echo "::error::Coverage source tree could not be materialized; see the coverage-source-tree job log for the exact target repository, base SHA, head SHA, and fetch or merge failure." exit 1 - - name: Download materialized pull request merge tree + - name: Download current-attempt materialized pull request merge tree + id: coverage_source_download + continue-on-error: true uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - name: opencode-coverage-source + artifact-ids: ${{ needs.coverage-source-tree.outputs.coverage_source_artifact_id }} path: ${{ runner.temp }}/opencode-coverage-artifact + - name: Report missing current-attempt coverage source + if: steps.coverage_source_download.outcome != 'success' + env: + GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} + run: | + set -euo pipefail + echo "::error::Coverage source evidence is unavailable for workflow run attempt ${GITHUB_RUN_ATTEMPT}; a failed-jobs-only rerun cannot safely reconstruct or reuse source evidence from another attempt." + echo "::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree uploads exact current-attempt evidence." + exit 1 + - name: Prepare pull request merge tree for coverage measurement env: COVERAGE_SOURCE_ARCHIVE: ${{ runner.temp }}/opencode-coverage-artifact/opencode-coverage-source.tar diff --git a/CHANGELOG.md b/CHANGELOG.md index e601de81b..53e2bfbbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,5 +12,6 @@ Semantic Versioning where the repository publishes a release. ### Fixed +- Bound OpenCode coverage source artifacts to one workflow attempt and immutable artifact ID, retained one-day source evidence, and made failed-jobs-only reruns fail closed with full-rerun or fresh-dispatch guidance instead of searching for expired or prior-attempt artifacts. - Bound both trusted-uv quality jobs to `github.event.pull_request.head.sha` and added a permanent two-checkout regression contract so exact-head compatibility, coverage, docstring, and compilation claims cannot silently measure GitHub's generated pull-request merge revision. - Made Strix treat only a single LiteLLM provider-error line containing NVIDIA NIM context and model-catalog 404 evidence as cross-model fallback evidence, rejecting cross-line signal assembly and provider-like target source literals; moved the public default to Nemotron 3 Super 120B and added a second NVIDIA hosted candidate before GitHub Models without neutralizing reported vulnerabilities. diff --git a/scripts/ci/prepare_opencode_attempt_artifact_patch.py b/scripts/ci/prepare_opencode_attempt_artifact_patch.py deleted file mode 100644 index 15d3b9f40..000000000 --- a/scripts/ci/prepare_opencode_attempt_artifact_patch.py +++ /dev/null @@ -1,231 +0,0 @@ -#!/usr/bin/env python3 -"""Materialize the reviewed OpenCode attempt-scoped artifact repair. - -This helper is a temporary branch-local materializer. It changes only the central -OpenCode dispatch workflow and the Unreleased changelog entry. The permanent -behavior is guarded by ``tests/test_opencode_coverage_artifact_rerun_contract.py``. -""" - -from __future__ import annotations - -from pathlib import Path - - -WORKFLOW_PATH = Path(".github/workflows/opencode-review-dispatch.yml") -CHANGELOG_PATH = Path("CHANGELOG.md") - - -def action_expression(value: str) -> str: - """Build a literal GitHub Actions expression at runtime.""" - return "$" + "{{ " + value + " }}" - - -def unique_index( - lines: list[str], - needle: str, - *, - start: int = 0, - end: int | None = None, - label: str, -) -> int: - """Return the only exact line match inside a bounded range.""" - stop = len(lines) if end is None else end - matches = [index for index in range(start, stop) if lines[index] == needle] - if len(matches) != 1: - raise SystemExit( - f"Expected exactly one {label} line, found {len(matches)}." - ) - return matches[0] - - -def patch_workflow() -> None: - """Bind the coverage producer and consumer through an immutable artifact ID.""" - lines = WORKFLOW_PATH.read_text(encoding="utf-8").splitlines(keepends=True) - - producer_start = unique_index( - lines, - " coverage-source-tree:\n", - label="coverage-source-tree job", - ) - consumer_start = unique_index( - lines, - " coverage-evidence:\n", - label="coverage-evidence job", - ) - producer_env = unique_index( - lines, - " env:\n", - start=producer_start, - end=consumer_start, - label="coverage-source-tree env", - ) - expected_permissions = [ - " permissions:\n", - " contents: read\n", - " id-token: write\n", - ] - if lines[producer_env - 3 : producer_env] != expected_permissions: - raise SystemExit( - "coverage-source-tree permission boundary no longer matches the reviewed contract." - ) - lines[producer_env:producer_env] = [ - " outputs:\n", - " coverage_source_artifact_id: " - + action_expression("steps.coverage_source_upload.outputs.artifact-id") - + "\n", - ] - - producer_start = unique_index( - lines, - " coverage-source-tree:\n", - label="coverage-source-tree job after output insertion", - ) - consumer_start = unique_index( - lines, - " coverage-evidence:\n", - label="coverage-evidence job after output insertion", - ) - upload_step = unique_index( - lines, - " - name: Upload materialized pull request merge tree\n", - start=producer_start, - end=consumer_start, - label="coverage source upload step", - ) - if not lines[upload_step + 1].startswith(" uses: actions/upload-artifact@"): - raise SystemExit("Coverage upload action anchor changed unexpectedly.") - lines[upload_step + 1 : upload_step + 1] = [" id: coverage_source_upload\n"] - - consumer_start = unique_index( - lines, - " coverage-evidence:\n", - label="coverage-evidence job after upload ID insertion", - ) - upload_name = unique_index( - lines, - " name: opencode-coverage-source\n", - start=upload_step, - end=consumer_start, - label="coverage source upload name", - ) - lines[upload_name] = ( - " name: opencode-coverage-source-" - + action_expression("github.run_attempt") - + "\n" - ) - - consumer_start = unique_index( - lines, - " coverage-evidence:\n", - label="coverage-evidence job before download repair", - ) - review_start = unique_index( - lines, - " opencode-review-target:\n", - start=consumer_start, - label="opencode-review-target job", - ) - download_step = unique_index( - lines, - " - name: Download materialized pull request merge tree\n", - start=consumer_start, - end=review_start, - label="coverage source download step", - ) - if not lines[download_step + 1].startswith( - " uses: actions/download-artifact@" - ): - raise SystemExit("Coverage download action anchor changed unexpectedly.") - lines[download_step] = ( - " - name: Download current-attempt materialized pull request merge tree\n" - ) - lines[download_step + 1 : download_step + 1] = [ - " id: coverage_source_download\n", - " continue-on-error: true\n", - ] - - review_start = unique_index( - lines, - " opencode-review-target:\n", - start=consumer_start, - label="opencode-review-target job after download ID insertion", - ) - download_name = unique_index( - lines, - " name: opencode-coverage-source\n", - start=download_step, - end=review_start, - label="coverage source download name", - ) - lines[download_name] = ( - " artifact-ids: " - + action_expression( - "needs.coverage-source-tree.outputs.coverage_source_artifact_id" - ) - + "\n" - ) - - review_start = unique_index( - lines, - " opencode-review-target:\n", - start=consumer_start, - label="opencode-review-target job before failure guidance insertion", - ) - download_path = unique_index( - lines, - " path: " - + action_expression("runner.temp") - + "/opencode-coverage-artifact\n", - start=download_step, - end=review_start, - label="coverage source download path", - ) - if lines[download_path + 1] != "\n": - raise SystemExit("Expected a blank line after the coverage download step.") - shell_run_attempt = "$" + "{GITHUB_RUN_ATTEMPT}" - lines[download_path + 1 : download_path + 2] = [ - "\n", - " - name: Report missing current-attempt coverage source\n", - " if: steps.coverage_source_download.outcome != 'success'\n", - " env:\n", - " GITHUB_RUN_ATTEMPT: " - + action_expression("github.run_attempt") - + "\n", - " run: |\n", - " set -euo pipefail\n", - " echo \"::error::Coverage source evidence is unavailable for workflow run attempt " - + shell_run_attempt - + "; a failed-jobs-only rerun cannot safely reconstruct or reuse source evidence from another attempt.\"\n", - " echo \"::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree uploads exact current-attempt evidence.\"\n", - " exit 1\n", - "\n", - ] - - WORKFLOW_PATH.write_text("".join(lines), encoding="utf-8") - - -def patch_changelog() -> None: - """Record the attempt-scoped artifact correction under Unreleased fixes.""" - changelog = CHANGELOG_PATH.read_text(encoding="utf-8") - marker = "### Fixed\n\n" - entry = ( - "- Bound OpenCode coverage source artifacts to one workflow attempt and immutable " - "artifact ID, retained one-day source evidence, and made failed-jobs-only reruns " - "fail closed with full-rerun or fresh-dispatch guidance instead of searching for " - "expired or prior-attempt artifacts.\n" - ) - if changelog.count(marker) != 1: - raise SystemExit("Expected exactly one Unreleased Fixed marker.") - if entry not in changelog: - changelog = changelog.replace(marker, marker + entry, 1) - CHANGELOG_PATH.write_text(changelog, encoding="utf-8") - - -def main() -> None: - """Apply the bounded workflow and changelog patch.""" - patch_workflow() - patch_changelog() - - -if __name__ == "__main__": - main() From 86f661cbc605287b391dcb6ca8b041eab5b555e1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:18:02 +0900 Subject: [PATCH 18/56] chore(opencode): remove temporary artifact materializer --- ...e-attempt-scoped-coverage-artifact.trigger | 1 - ...ncode-attempt-scoped-coverage-artifact.yml | 314 ------------------ 2 files changed, 315 deletions(-) delete mode 100644 .github/opencode-attempt-scoped-coverage-artifact.trigger delete mode 100644 .github/workflows/materialize-opencode-attempt-scoped-coverage-artifact.yml diff --git a/.github/opencode-attempt-scoped-coverage-artifact.trigger b/.github/opencode-attempt-scoped-coverage-artifact.trigger deleted file mode 100644 index 8cda4f8c6..000000000 --- a/.github/opencode-attempt-scoped-coverage-artifact.trigger +++ /dev/null @@ -1 +0,0 @@ -Trigger the expression-safe attempt-scoped coverage artifact repair. diff --git a/.github/workflows/materialize-opencode-attempt-scoped-coverage-artifact.yml b/.github/workflows/materialize-opencode-attempt-scoped-coverage-artifact.yml deleted file mode 100644 index a971093bf..000000000 --- a/.github/workflows/materialize-opencode-attempt-scoped-coverage-artifact.yml +++ /dev/null @@ -1,314 +0,0 @@ -name: Materialize rerun-safe coverage artifact handoff - -on: - pull_request: - branches: [main] - types: [synchronize] - -permissions: - contents: read - -concurrency: - group: materialize-opencode-attempt-scoped-coverage-artifact - cancel-in-progress: false - -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - -jobs: - materialize: - if: >- - github.repository == 'ContextualWisdomLab/.github' && - github.event.pull_request.number == 812 && - github.event.pull_request.head.ref == 'fix/opencode-attempt-scoped-coverage-artifact' - permissions: - contents: write - issues: write - pull-requests: write - runs-on: ubuntu-24.04 - timeout-minutes: 45 - steps: - - name: Harden runner - uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 - with: - egress-policy: audit - - - name: Check out exact PR head - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 1 - persist-credentials: false - - - name: Prove the attempt-scoped contract is red - shell: bash --noprofile --norc {0} - run: | - set +e - python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py - status=$? - set -e - if [ "$status" -eq 0 ]; then - echo "::error::Attempt-scoped artifact contract passed before production repair." - exit 1 - fi - test "$status" -eq 1 - - - name: Apply reviewed workflow and doctoring repair - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - python3 - <<'PY' - from pathlib import Path - - workflow_path = Path('.github/workflows/opencode-review-dispatch.yml') - source = workflow_path.read_text(encoding='utf-8') - - old_header = ''' coverage-source-tree: - name: coverage-source-tree - needs: [validate-pr-metadata] - if: >- - needs.validate-pr-metadata.result == 'success' - && github.event_name == 'repository_dispatch' - runs-on: ubuntu-latest - permissions: - contents: read - id-token: write - env: -''' - new_header = ''' coverage-source-tree: - name: coverage-source-tree - needs: [validate-pr-metadata] - if: >- - needs.validate-pr-metadata.result == 'success' - && github.event_name == 'repository_dispatch' - runs-on: ubuntu-latest - permissions: - contents: read - id-token: write - outputs: - coverage_source_artifact_id: ${{ steps.coverage_source_upload.outputs.artifact-id }} - env: -''' - if source.count(old_header) != 1: - raise SystemExit('coverage-source-tree header anchor changed') - source = source.replace(old_header, new_header, 1) - - old_upload = ''' - name: Upload materialized pull request merge tree - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: opencode-coverage-source - path: ${{ runner.temp }}/opencode-coverage-source.tar - if-no-files-found: error - retention-days: 1 -''' - new_upload = ''' - name: Upload materialized pull request merge tree - id: coverage_source_upload - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: opencode-coverage-source-${{ github.run_attempt }} - path: ${{ runner.temp }}/opencode-coverage-source.tar - if-no-files-found: error - retention-days: 1 -''' - if source.count(old_upload) != 1: - raise SystemExit('coverage artifact upload anchor changed') - source = source.replace(old_upload, new_upload, 1) - - old_download = ''' - name: Download materialized pull request merge tree - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: opencode-coverage-source - path: ${{ runner.temp }}/opencode-coverage-artifact -''' - new_download = ''' - name: Download materialized pull request merge tree - id: coverage_source_download - continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - artifact-ids: ${{ needs.coverage-source-tree.outputs.coverage_source_artifact_id }} - path: ${{ runner.temp }}/opencode-coverage-artifact - - - name: Reject missing current-attempt coverage source evidence - if: steps.coverage_source_download.outcome != 'success' - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - echo "::error::Coverage source evidence is unavailable for workflow attempt ${GITHUB_RUN_ATTEMPT}. A failed-jobs-only rerun cannot reuse an expired or prior-attempt artifact; start a full rerun or a fresh repository dispatch." - exit 1 -''' - if source.count(old_download) != 1: - raise SystemExit('coverage artifact download anchor changed') - workflow_path.write_text(source.replace(old_download, new_download, 1), encoding='utf-8') - - doctoring = Path('docs/doctoring/opencode-coverage-artifact-reruns.md') - doctoring.write_text( - '''# OpenCode coverage artifact reruns - -## Decision - -The credentialed `coverage-source-tree` producer uploads one immutable source archive for each workflow attempt. The artifact name includes `github.run_attempt`, and the producer exports the exact upload `artifact-id`. The credential-free `coverage-evidence` consumer downloads only that ID. - -A failed-jobs-only rerun does not rerun a producer that already succeeded. If its one-day source artifact has expired or the current attempt has no producer output, the consumer fails closed with guidance to start a full rerun or a fresh repository dispatch. It never falls back to a static name, an earlier attempt, or an expired artifact. - -## Trust and retention boundary - -The source producer retains target-repository read and OIDC authority needed to materialize the exact base/head merge tree. The untrusted-test consumer retains only `actions: read`; it receives no repository-content token, OIDC credential, model secret, or write permission. Source evidence remains limited to one-day retention. - -## Incident recovery - -1. Confirm the failure occurred before coverage tests at the immutable artifact download. -2. Do not rerun failed jobs only when the source producer must run again. -3. Start a full workflow rerun or send a fresh repository dispatch for the unchanged exact head. -4. Verify the new producer and consumer share the same run attempt and artifact ID. -5. Preserve prior failure evidence for audit; do not extend private-source retention as a workaround. - -## Rollback - -Rollback is safe only to another implementation that preserves immutable producer/consumer binding and credential separation. Restoring a static artifact name or cross-attempt fallback is prohibited. - -## References - -GitHub. (2026). *Re-running workflows and jobs*. GitHub Docs. https://docs.github.com/en/actions/how-tos/manage-workflow-runs/re-run-workflows-and-jobs - -GitHub. (2026). *Store and share data with workflow artifacts*. GitHub Docs. https://docs.github.com/en/actions/tutorials/store-and-share-data - -GitHub. (2026). *REST API endpoints for GitHub Actions artifacts*. GitHub Docs. https://docs.github.com/en/rest/actions/artifacts -''', - encoding='utf-8', - ) - - changelog_path = Path('CHANGELOG.md') - changelog = changelog_path.read_text(encoding='utf-8') - entry = ( - '- Bind OpenCode coverage source archives to the producing workflow attempt and immutable artifact ID, failing closed with full-rerun guidance when failed-jobs-only retries no longer have current evidence.\n' - ) - if entry not in changelog: - marker = '### Fixed\n\n' - if marker not in changelog: - raise SystemExit('CHANGELOG Unreleased Fixed marker is absent') - changelog = changelog.replace(marker, marker + entry, 1) - changelog_path.write_text(changelog, encoding='utf-8') - PY - rm -f \ - .github/workflows/materialize-opencode-attempt-scoped-coverage-artifact.yml \ - .github/opencode-attempt-scoped-coverage-artifact.trigger - git diff --check - - - name: Set up Python 3.14 - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 - with: - python-version: "3.14" - cache: pip - cache-dependency-path: requirements-opencode-review-ci-hashes.txt - - - name: Install exact hash-locked quality tooling - run: >- - python -m pip install --disable-pip-version-check --require-hashes - -r requirements-opencode-review-ci-hashes.txt - - - name: Verify focused and complete central contracts - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py - python -m pytest -q tests - python -m compileall -q tests/test_opencode_coverage_artifact_rerun_contract.py - git diff --check - - - name: Build immutable workflow-free implementation commit - env: - API_TOKEN: ${{ github.token }} - EXPECTED_HEAD: ${{ github.event.pull_request.head.sha }} - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - test "$(git rev-parse HEAD)" = "$EXPECTED_HEAD" - python3 - <<'PY' | tee "${RUNNER_TEMP}/pr812-implementation.txt" - import base64 - import json - import os - import subprocess - import urllib.request - from pathlib import Path - - repository = 'ContextualWisdomLab/.github' - parent_sha = os.environ['EXPECTED_HEAD'] - token = os.environ['API_TOKEN'] - api_root = f'https://api.github.com/repos/{repository}' - expected_paths = { - '.github/workflows/opencode-review-dispatch.yml', - '.github/workflows/materialize-opencode-attempt-scoped-coverage-artifact.yml', - '.github/opencode-attempt-scoped-coverage-artifact.trigger', - 'CHANGELOG.md', - 'docs/doctoring/opencode-coverage-artifact-reruns.md', - } - - def request(method, endpoint, payload=None): - data = None if payload is None else json.dumps(payload).encode('utf-8') - req = urllib.request.Request( - api_root + endpoint, - data=data, - method=method, - headers={ - 'Accept': 'application/vnd.github+json', - 'Authorization': f'Bearer {token}', - 'X-GitHub-Api-Version': '2022-11-28', - 'User-Agent': 'cwl-pr812-materializer', - }, - ) - with urllib.request.urlopen(req, timeout=60) as response: - return json.load(response) - - raw = subprocess.check_output(['git', 'diff', '--name-status', '-z', 'HEAD']) - parts = raw.decode('utf-8').split('\0') - changes = [] - index = 0 - while index < len(parts) - 1: - status = parts[index] - path = parts[index + 1] - index += 2 - changes.append((status, path)) - actual_paths = {path for _, path in changes} - if actual_paths != expected_paths: - raise SystemExit( - f'implementation path mismatch: missing={sorted(expected_paths - actual_paths)} ' - f'extra={sorted(actual_paths - expected_paths)}' - ) - - parent = request('GET', f'/git/commits/{parent_sha}') - tree_entries = [] - for status, path in changes: - if status == 'D': - tree_entries.append({'path': path, 'mode': '100644', 'type': 'blob', 'sha': None}) - continue - encoded = base64.b64encode(Path(path).read_bytes()).decode('ascii') - blob = request('POST', '/git/blobs', {'content': encoded, 'encoding': 'base64'}) - tree_entries.append({'path': path, 'mode': '100644', 'type': 'blob', 'sha': blob['sha']}) - tree = request('POST', '/git/trees', {'base_tree': parent['tree']['sha'], 'tree': tree_entries}) - commit = request( - 'POST', - '/git/commits', - { - 'message': 'fix(opencode): bind coverage artifacts to workflow attempts', - 'tree': tree['sha'], - 'parents': [parent_sha], - }, - ) - print(f"PR812_IMPLEMENTATION_PARENT_SHA={parent_sha}") - print(f"PR812_IMPLEMENTATION_COMMIT_SHA={commit['sha']}") - PY - - - name: Publish implementation pointer - env: - GH_TOKEN: ${{ github.token }} - EXPECTED_HEAD: ${{ github.event.pull_request.head.sha }} - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - commit_sha="$(sed -n 's/^PR812_IMPLEMENTATION_COMMIT_SHA=//p' "${RUNNER_TEMP}/pr812-implementation.txt")" - test "${#commit_sha}" -eq 40 - body="PR812_IMPLEMENTATION_PARENT_SHA=${EXPECTED_HEAD}%0APR812_IMPLEMENTATION_COMMIT_SHA=${commit_sha}" - gh api --method POST repos/ContextualWisdomLab/.github/issues/812/comments -f "body=${body}" - - - name: Upload implementation receipt - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: pr812-attempt-scoped-coverage-artifact - path: ${{ runner.temp }}/pr812-implementation.txt - if-no-files-found: error - retention-days: 5 From e4ae5a366de905adf88c2d938d8fd6073ba1e182 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:19:52 +0900 Subject: [PATCH 19/56] test(opencode): forbid temporary artifact repair workflows --- ...ode-coverage-artifact-rerun-quality-ci.yml | 70 ------------------- ...encode_coverage_artifact_rerun_contract.py | 12 ++++ 2 files changed, 12 insertions(+), 70 deletions(-) delete mode 100644 .github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml diff --git a/.github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml b/.github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml deleted file mode 100644 index 0ffd73261..000000000 --- a/.github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml +++ /dev/null @@ -1,70 +0,0 @@ -name: OpenCode Coverage Artifact Rerun Quality CI - -on: - pull_request: - branches: [main] - paths: - - ".github/workflows/opencode-review-dispatch.yml" - - ".github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml" - - "tests/test_opencode_coverage_artifact_rerun_contract.py" - - "docs/doctoring/opencode-coverage-artifact-reruns.md" - - "CHANGELOG.md" - - "requirements-opencode-review-ci-hashes.txt" - push: - branches: [main] - paths: - - ".github/workflows/opencode-review-dispatch.yml" - - ".github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml" - - "tests/test_opencode_coverage_artifact_rerun_contract.py" - - "docs/doctoring/opencode-coverage-artifact-reruns.md" - - "CHANGELOG.md" - - "requirements-opencode-review-ci-hashes.txt" - -concurrency: - group: opencode-coverage-artifact-rerun-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -permissions: - contents: read - -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - -jobs: - exact-head-contract: - name: Python 3.14 attempt-scoped artifact contract - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - name: Harden runner - uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 - with: - egress-policy: audit - - - name: Checkout exact source - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - persist-credentials: false - ref: ${{ github.event.pull_request.head.sha || github.sha }} - - - name: Set up current stable Python - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 - with: - python-version: "3.14" - cache: pip - cache-dependency-path: requirements-opencode-review-ci-hashes.txt - - - name: Install hash-locked quality tooling - run: python -m pip install --disable-pip-version-check --require-hashes -r requirements-opencode-review-ci-hashes.txt - - - name: Run attempt-scoped artifact regression - run: python -m pytest tests/test_opencode_coverage_artifact_rerun_contract.py -q - - - name: Run complete central test suite - run: python -m pytest tests -q - - - name: Compile permanent contracts - run: python -m compileall -q tests/test_opencode_coverage_artifact_rerun_contract.py - - - name: Reject uncommitted generated state - run: git diff --exit-code --check && test -z "$(git status --porcelain)" diff --git a/tests/test_opencode_coverage_artifact_rerun_contract.py b/tests/test_opencode_coverage_artifact_rerun_contract.py index 12da2abf1..9837e2dff 100644 --- a/tests/test_opencode_coverage_artifact_rerun_contract.py +++ b/tests/test_opencode_coverage_artifact_rerun_contract.py @@ -4,6 +4,13 @@ WORKFLOW_PATH = Path(".github/workflows/opencode-review-dispatch.yml") +TEMPORARY_REPAIR_PATHS = ( + Path(".github/opencode-attempt-scoped-coverage-artifact.trigger"), + Path(".github/workflows/materialize-opencode-attempt-scoped-coverage-artifact.yml"), + Path(".github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml"), + Path(".github/workflows/opencode-coverage-artifact-rerun-repair.yml"), + Path("scripts/ci/prepare_opencode_attempt_artifact_patch.py"), +) def _workflow_text() -> str: @@ -68,3 +75,8 @@ def test_coverage_consumer_remains_credential_free() -> None: assert "id-token:" not in permissions assert "secrets." not in evidence_job assert "GH_TOKEN:" not in evidence_job + + +def test_temporary_repair_supply_chain_is_absent_from_final_tree() -> None: + """Keep only permanent workflow, regression, doctoring, and changelog files.""" + assert [str(path) for path in TEMPORARY_REPAIR_PATHS if path.exists()] == [] From 321a9af5512a84e193f90838d59d28cc783d4a63 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:21:54 +0900 Subject: [PATCH 20/56] test(opencode): enforce 100% coverage and docstrings --- ...ode-coverage-artifact-rerun-quality-ci.yml | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 .github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml diff --git a/.github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml b/.github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml new file mode 100644 index 000000000..770373a1f --- /dev/null +++ b/.github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml @@ -0,0 +1,77 @@ +name: OpenCode Coverage Artifact Rerun Quality CI + +on: + pull_request: + branches: [main] + paths: + - ".github/workflows/opencode-review-dispatch.yml" + - ".github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml" + - "tests/test_opencode_coverage_artifact_rerun_contract.py" + - "docs/doctoring/opencode-coverage-artifact-reruns.md" + - "CHANGELOG.md" + - "requirements-opencode-review-ci-hashes.txt" + push: + branches: [main] + paths: + - ".github/workflows/opencode-review-dispatch.yml" + - ".github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml" + - "tests/test_opencode_coverage_artifact_rerun_contract.py" + - "docs/doctoring/opencode-coverage-artifact-reruns.md" + - "CHANGELOG.md" + - "requirements-opencode-review-ci-hashes.txt" + +concurrency: + group: opencode-coverage-artifact-rerun-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + exact-head-contract: + name: Python 3.14 attempt-scoped artifact contract + runs-on: ubuntu-latest + timeout-minutes: 25 + steps: + - name: Harden runner + uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 + with: + egress-policy: audit + + - name: Checkout exact source + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + ref: ${{ github.event.pull_request.head.sha || github.sha }} + + - name: Set up current stable Python + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.14" + cache: pip + cache-dependency-path: requirements-opencode-review-ci-hashes.txt + + - name: Install hash-locked quality tooling + run: python -m pip install --disable-pip-version-check --require-hashes -r requirements-opencode-review-ci-hashes.txt + + - name: Run attempt-scoped artifact regression + run: python -m pytest tests/test_opencode_coverage_artifact_rerun_contract.py -q + + - name: Enforce complete central test and branch coverage + run: | + set -euo pipefail + python -m coverage erase + python -m coverage run -m pytest tests -q + python -m coverage report --show-missing + + - name: Enforce production docstring coverage + run: python -m interrogate . + + - name: Compile permanent contracts + run: python -m compileall -q scripts tests + + - name: Reject uncommitted generated state + run: git diff --exit-code --check && test -z "$(git status --porcelain)" From cae2d8f9e7c95e9044bb77468f6c1b132889a37b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:22:32 +0900 Subject: [PATCH 21/56] test(opencode): distinguish permanent quality gate from repairs --- tests/test_opencode_coverage_artifact_rerun_contract.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/test_opencode_coverage_artifact_rerun_contract.py b/tests/test_opencode_coverage_artifact_rerun_contract.py index 9837e2dff..cb8ea6d90 100644 --- a/tests/test_opencode_coverage_artifact_rerun_contract.py +++ b/tests/test_opencode_coverage_artifact_rerun_contract.py @@ -7,7 +7,6 @@ TEMPORARY_REPAIR_PATHS = ( Path(".github/opencode-attempt-scoped-coverage-artifact.trigger"), Path(".github/workflows/materialize-opencode-attempt-scoped-coverage-artifact.yml"), - Path(".github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml"), Path(".github/workflows/opencode-coverage-artifact-rerun-repair.yml"), Path("scripts/ci/prepare_opencode_attempt_artifact_patch.py"), ) @@ -77,6 +76,6 @@ def test_coverage_consumer_remains_credential_free() -> None: assert "GH_TOKEN:" not in evidence_job -def test_temporary_repair_supply_chain_is_absent_from_final_tree() -> None: - """Keep only permanent workflow, regression, doctoring, and changelog files.""" +def test_temporary_branch_writers_are_absent_from_final_tree() -> None: + """Keep transient materializers and repair branch writers out of the PR.""" assert [str(path) for path in TEMPORARY_REPAIR_PATHS if path.exists()] == [] From 817772bc12c28ca1fe161046a478e50c5a9dd530 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:24:47 +0900 Subject: [PATCH 22/56] test(opencode): reject prior-attempt coverage evidence --- ...encode_coverage_artifact_rerun_contract.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/test_opencode_coverage_artifact_rerun_contract.py b/tests/test_opencode_coverage_artifact_rerun_contract.py index cb8ea6d90..d91d910db 100644 --- a/tests/test_opencode_coverage_artifact_rerun_contract.py +++ b/tests/test_opencode_coverage_artifact_rerun_contract.py @@ -47,6 +47,38 @@ def test_coverage_source_artifact_is_attempt_scoped_and_downloaded_by_id() -> No assert "name: opencode-coverage-source\n" not in evidence_job +def test_coverage_source_requires_current_producer_attempt() -> None: + """Reject reused producer output when a selective rerun advances the attempt.""" + workflow = _workflow_text() + source_job = _job_block(workflow, "coverage-source-tree", "coverage-evidence") + evidence_job = _job_block(workflow, "coverage-evidence", "opencode-review-target") + + assert ( + "coverage_source_run_attempt: " + "${{ steps.coverage_source_attempt.outputs.run_attempt }}" + in source_job + ) + assert "id: coverage_source_attempt" in source_job + assert "GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }}" in source_job + assert "run_attempt=%s" in source_job + + assert ( + "COVERAGE_SOURCE_RUN_ATTEMPT: " + "${{ needs.coverage-source-tree.outputs.coverage_source_run_attempt }}" + in evidence_job + ) + assert "CURRENT_RUN_ATTEMPT: ${{ github.run_attempt }}" in evidence_job + assert '[ "$COVERAGE_SOURCE_RUN_ATTEMPT" != "$CURRENT_RUN_ATTEMPT" ]' in evidence_job + assert "full rerun or a fresh repository dispatch" in evidence_job + guard_index = evidence_job.index( + "- name: Verify coverage source was produced in current workflow attempt" + ) + download_index = evidence_job.index( + "- name: Download current-attempt materialized pull request merge tree" + ) + assert guard_index < download_index + + def test_missing_current_attempt_artifact_fails_with_fresh_run_guidance() -> None: """Reject partial reruns instead of falling back to stale source evidence.""" workflow = _workflow_text() From face57d2b54b39736a8d2f2893b92d223b08b774 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:27:21 +0900 Subject: [PATCH 23/56] chore(opencode): add exact current-attempt repair runner --- ...pencode-coverage-artifact-rerun-repair.yml | 304 ++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 .github/workflows/opencode-coverage-artifact-rerun-repair.yml diff --git a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml new file mode 100644 index 000000000..c1c59ac39 --- /dev/null +++ b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml @@ -0,0 +1,304 @@ +name: OpenCode Coverage Artifact Rerun Repair + +on: + push: + branches: + - fix/opencode-attempt-scoped-coverage-artifact + paths: + - ".github/workflows/opencode-coverage-artifact-rerun-repair.yml" + +concurrency: + group: opencode-coverage-artifact-rerun-repair-pr812 + cancel-in-progress: false + +permissions: + contents: read + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + repair-and-publish: + if: >- + github.repository == 'ContextualWisdomLab/.github' + && github.ref == 'refs/heads/fix/opencode-attempt-scoped-coverage-artifact' + && github.actor == 'seonghobae' + permissions: + contents: read + id-token: write + runs-on: ubuntu-24.04 + timeout-minutes: 35 + steps: + - name: Harden runner + uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 + with: + egress-policy: audit + + - name: Check out exact repair trigger + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + ref: ${{ github.sha }} + fetch-depth: 2 + persist-credentials: false + + - name: Refuse stale or widened trigger lineage + env: + EXPECTED_RED_HEAD: 817772bc12c28ca1fe161046a478e50c5a9dd530 + REPAIR_WORKFLOW: .github/workflows/opencode-coverage-artifact-rerun-repair.yml + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + test "$(git rev-parse HEAD)" = "$GITHUB_SHA" + test "$(git rev-parse HEAD^)" = "$EXPECTED_RED_HEAD" + changed="$(git diff --name-only "$EXPECTED_RED_HEAD" "$GITHUB_SHA")" + test "$changed" = "$REPAIR_WORKFLOW" + + - name: Set up Python 3.14 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.14" + cache: pip + cache-dependency-path: requirements-opencode-review-ci-hashes.txt + + - name: Install exact hash-locked quality tooling + run: >- + python -m pip install --disable-pip-version-check --require-hashes + -r requirements-opencode-review-ci-hashes.txt + + - name: Prove current-attempt provenance contract is red + shell: bash --noprofile --norc {0} + run: | + set +e + output="$(python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py 2>&1)" + status=$? + set -e + printf '%s\n' "$output" + test "$status" -eq 1 + grep -F "test_coverage_source_requires_current_producer_attempt" <<<"$output" + + - name: Apply reviewed current-attempt provenance repair + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + python3 - <<'PY' + from pathlib import Path + + workflow_path = Path('.github/workflows/opencode-review-dispatch.yml') + source = workflow_path.read_text(encoding='utf-8') + + old_outputs = ''' outputs: + coverage_source_artifact_id: ${{ steps.coverage_source_upload.outputs.artifact-id }} + env: + ''' + new_outputs = ''' outputs: + coverage_source_artifact_id: ${{ steps.coverage_source_upload.outputs.artifact-id }} + coverage_source_run_attempt: ${{ steps.coverage_source_attempt.outputs.run_attempt }} + env: + ''' + if source.count(old_outputs) != 1: + raise SystemExit('coverage-source-tree output anchor changed') + source = source.replace(old_outputs, new_outputs, 1) + + upload_anchor = ''' - name: Upload materialized pull request merge tree + id: coverage_source_upload + ''' + attempt_step = ''' - name: Record coverage source workflow attempt + id: coverage_source_attempt + env: + GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + printf 'run_attempt=%s\\n' "$GITHUB_RUN_ATTEMPT" >>"$GITHUB_OUTPUT" + + - name: Upload materialized pull request merge tree + id: coverage_source_upload + ''' + if source.count(upload_anchor) != 1: + raise SystemExit('coverage source upload anchor changed') + source = source.replace(upload_anchor, attempt_step, 1) + + download_anchor = ''' - name: Download current-attempt materialized pull request merge tree + id: coverage_source_download + ''' + attempt_guard = ''' - name: Verify coverage source was produced in current workflow attempt + env: + COVERAGE_SOURCE_RUN_ATTEMPT: ${{ needs.coverage-source-tree.outputs.coverage_source_run_attempt }} + CURRENT_RUN_ATTEMPT: ${{ github.run_attempt }} + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + if [ -z "$COVERAGE_SOURCE_RUN_ATTEMPT" ] || [ "$COVERAGE_SOURCE_RUN_ATTEMPT" != "$CURRENT_RUN_ATTEMPT" ]; then + echo "::error::Coverage source evidence was not produced in current workflow run attempt ${CURRENT_RUN_ATTEMPT}; producer attempt was ${COVERAGE_SOURCE_RUN_ATTEMPT:-missing}." + echo "::error::A failed-jobs-only rerun cannot reuse prior-attempt source evidence; use a full rerun or a fresh repository dispatch." + exit 1 + fi + + - name: Download current-attempt materialized pull request merge tree + id: coverage_source_download + ''' + if source.count(download_anchor) != 1: + raise SystemExit('coverage source download anchor changed') + workflow_path.write_text(source.replace(download_anchor, attempt_guard, 1), encoding='utf-8') + + doctoring_path = Path('docs/doctoring/opencode-coverage-artifact-reruns.md') + doctoring = doctoring_path.read_text(encoding='utf-8') + decision_anchor = ( + 'The source artifact retains the existing one-day retention period. ' + ) + decision_insert = ( + 'The producer also records the literal workflow attempt in a step output, and ' + 'the consumer compares that producer-attested value with its own current ' + '`github.run_attempt` before any artifact download. An immutable artifact ID ' + 'proves which upload is selected; the separate attempt marker proves when the ' + 'producer actually executed.\n\n' + + decision_anchor + ) + if doctoring.count(decision_anchor) != 1: + raise SystemExit('doctoring decision anchor changed') + doctoring = doctoring.replace(decision_anchor, decision_insert, 1) + + bullet_anchor = ( + '- The upload step exports the immutable `artifact-id`; the consumer downloads ' + 'with `artifact-ids` rather than `name`.\n' + ) + bullet_insert = bullet_anchor + ( + '- The producer exports its step-recorded run attempt; the consumer rejects an ' + 'empty or mismatched producer attempt before artifact download, so selective ' + 'reruns cannot reuse prior-attempt source evidence while it is still retained.\n' + ) + if doctoring.count(bullet_anchor) != 1: + raise SystemExit('doctoring contract bullet anchor changed') + doctoring = doctoring.replace(bullet_anchor, bullet_insert, 1) + + table_old = ( + '| Failed-jobs-only rerun while producer is omitted | No current-attempt producer ' + 'output exists | Fails closed with recovery guidance | Expected failure |' + ) + table_new = ( + '| Failed-jobs-only rerun while producer is omitted | Producer attempt marker is ' + 'missing or belongs to the earlier attempt | Rejects the attempt mismatch before ' + 'artifact download | Expected failure |' + ) + if doctoring.count(table_old) != 1: + raise SystemExit('doctoring rerun table anchor changed') + doctoring = doctoring.replace(table_old, table_new, 1) + + rationale_anchor = ( + 'The producer\'s exact `artifact-id` closes that ambiguity. Attempt-qualified ' + 'naming remains useful for diagnostics, while ID-based selection is the ' + 'authoritative binding.\n' + ) + rationale_new = ( + 'The producer\'s exact `artifact-id` closes the upload-selection ambiguity, while ' + 'the producer step\'s literal attempt output closes the execution-attempt ' + 'ambiguity. Attempt-qualified naming remains useful for diagnostics; exact ID ' + 'selection and the producer-attempt equality check are both required.\n' + ) + if doctoring.count(rationale_anchor) != 1: + raise SystemExit('doctoring rationale anchor changed') + doctoring = doctoring.replace(rationale_anchor, rationale_new, 1) + + verification_old = '''1. attempt-scoped artifact naming and immutable `artifact-id` producer output; + 2. exact-ID download by the consumer; + 3. actionable failure for a missing current-attempt artifact; + 4. one-day retention; and + 5. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`. + ''' + verification_new = '''1. attempt-scoped artifact naming and immutable `artifact-id` producer output; + 2. producer-attested workflow attempt output and pre-download current-attempt equality; + 3. exact-ID download by the consumer; + 4. actionable failure for missing or prior-attempt evidence; + 5. one-day retention; and + 6. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`. + ''' + if doctoring.count(verification_old) != 1: + raise SystemExit('doctoring verification anchor changed') + doctoring_path.write_text(doctoring.replace(verification_old, verification_new, 1), encoding='utf-8') + + changelog_path = Path('CHANGELOG.md') + changelog = changelog_path.read_text(encoding='utf-8') + old_entry = ( + '- Bound OpenCode coverage source artifacts to one workflow attempt and immutable ' + 'artifact ID, retained one-day source evidence, and made failed-jobs-only reruns ' + 'fail closed with full-rerun or fresh-dispatch guidance instead of searching for ' + 'expired or prior-attempt artifacts.\n' + ) + new_entry = ( + '- Bound OpenCode coverage source artifacts to one immutable artifact ID and a ' + 'producer-attested workflow-attempt marker, retained one-day source evidence, and ' + 'made failed-jobs-only reruns fail closed before download when the producer did not ' + 'run in the current attempt, with full-rerun or fresh-dispatch guidance.\n' + ) + if changelog.count(old_entry) != 1: + raise SystemExit('CHANGELOG attempt-artifact entry anchor changed') + changelog_path.write_text(changelog.replace(old_entry, new_entry, 1), encoding='utf-8') + PY + + rm .github/workflows/opencode-coverage-artifact-rerun-repair.yml + git diff --check + + - name: Verify focused and complete GREEN evidence + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py + python -m coverage erase + python -m coverage run -m pytest tests -q + python -m coverage report --show-missing --fail-under=100 + python -m interrogate . + python -m compileall -q scripts tests + git diff --check + expected="$(printf '%s\n' \ + '.github/workflows/opencode-coverage-artifact-rerun-repair.yml' \ + '.github/workflows/opencode-review-dispatch.yml' \ + 'CHANGELOG.md' \ + 'docs/doctoring/opencode-coverage-artifact-reruns.md' | sort)" + actual="$(git diff --name-only HEAD | sort)" + test "$actual" = "$expected" + + - name: Exchange OpenCode app token for exact branch publication + id: target_app_token + env: + OIDC_AUDIENCE: opencode-github-action + OPENCODE_API_BASE_URL: https://api.opencode.ai + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + test -n "${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-}" + test -n "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" + request_url="$ACTIONS_ID_TOKEN_REQUEST_URL" + separator='&' + case "$request_url" in *\?*) ;; *) separator='?' ;; esac + oidc_response="$(curl -fsS -H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" "${request_url}${separator}audience=${OIDC_AUDIENCE}")" + oidc_token="$(jq -r '.value // empty' <<<"$oidc_response")" + test -n "$oidc_token" + token_response="$(curl -fsS -X POST -H "Authorization: Bearer ${oidc_token}" "${OPENCODE_API_BASE_URL}/exchange_github_app_token")" + app_token="$(jq -r '.token // empty' <<<"$token_response")" + test -n "$app_token" + echo "::add-mask::$app_token" + echo "token=$app_token" >>"$GITHUB_OUTPUT" + + - name: Refuse concurrent branch writers and publish verified repair + env: + PUSH_TOKEN: ${{ steps.target_app_token.outputs.token }} + TARGET_BRANCH: fix/opencode-attempt-scoped-coverage-artifact + EXPECTED_TRIGGER_HEAD: ${{ github.sha }} + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + test -n "$PUSH_TOKEN" + echo "::add-mask::$PUSH_TOKEN" + live_head="$(curl -fsS \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${PUSH_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/ContextualWisdomLab/.github/pulls/812 | jq -r '.head.sha // empty')" + test "$live_head" = "$EXPECTED_TRIGGER_HEAD" + git config user.name "opencode-agent[bot]" + git config user.email "opencode-agent[bot]@users.noreply.github.com" + git add -A + expected="$(printf '%s\n' \ + '.github/workflows/opencode-coverage-artifact-rerun-repair.yml' \ + '.github/workflows/opencode-review-dispatch.yml' \ + 'CHANGELOG.md' \ + 'docs/doctoring/opencode-coverage-artifact-reruns.md' | sort)" + staged="$(git diff --cached --name-only | sort)" + test "$staged" = "$expected" + git commit -m "fix(opencode): attest current coverage producer attempt" + test -z "$(git status --porcelain --untracked-files=all)" + git remote set-url origin "https://x-access-token:${PUSH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" + git push origin "HEAD:refs/heads/${TARGET_BRANCH}" From e45ba8f05e337cfbc184c154bbe3cb69572a27dd Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:28:38 +0900 Subject: [PATCH 24/56] fix(opencode): harden exact repair materializer --- ...pencode-coverage-artifact-rerun-repair.yml | 244 +++++++++++------- 1 file changed, 145 insertions(+), 99 deletions(-) diff --git a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml index c1c59ac39..57bc5f99f 100644 --- a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml +++ b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml @@ -9,7 +9,7 @@ on: concurrency: group: opencode-coverage-artifact-rerun-repair-pr812 - cancel-in-progress: false + cancel-in-progress: true permissions: contents: read @@ -38,7 +38,7 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ github.sha }} - fetch-depth: 2 + fetch-depth: 4 persist-credentials: false - name: Refuse stale or widened trigger lineage @@ -48,7 +48,8 @@ jobs: shell: bash --noprofile --norc -e -o pipefail {0} run: | test "$(git rev-parse HEAD)" = "$GITHUB_SHA" - test "$(git rev-parse HEAD^)" = "$EXPECTED_RED_HEAD" + git merge-base --is-ancestor "$EXPECTED_RED_HEAD" "$GITHUB_SHA" + test "$(git rev-list --count "$EXPECTED_RED_HEAD..$GITHUB_SHA")" -le 2 changed="$(git diff --name-only "$EXPECTED_RED_HEAD" "$GITHUB_SHA")" test "$changed" = "$REPAIR_WORKFLOW" @@ -81,73 +82,116 @@ jobs: python3 - <<'PY' from pathlib import Path - workflow_path = Path('.github/workflows/opencode-review-dispatch.yml') - source = workflow_path.read_text(encoding='utf-8') + def action_expression(value: str) -> str: + return "$" + "{{ " + value + " }}" - old_outputs = ''' outputs: - coverage_source_artifact_id: ${{ steps.coverage_source_upload.outputs.artifact-id }} - env: - ''' - new_outputs = ''' outputs: - coverage_source_artifact_id: ${{ steps.coverage_source_upload.outputs.artifact-id }} - coverage_source_run_attempt: ${{ steps.coverage_source_attempt.outputs.run_attempt }} - env: - ''' - if source.count(old_outputs) != 1: - raise SystemExit('coverage-source-tree output anchor changed') - source = source.replace(old_outputs, new_outputs, 1) + def unique_index( + lines: list[str], + needle: str, + *, + start: int = 0, + end: int | None = None, + label: str, + ) -> int: + stop = len(lines) if end is None else end + matches = [index for index in range(start, stop) if lines[index] == needle] + if len(matches) != 1: + raise SystemExit(f"Expected one {label}, found {len(matches)}") + return matches[0] - upload_anchor = ''' - name: Upload materialized pull request merge tree - id: coverage_source_upload - ''' - attempt_step = ''' - name: Record coverage source workflow attempt - id: coverage_source_attempt - env: - GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - printf 'run_attempt=%s\\n' "$GITHUB_RUN_ATTEMPT" >>"$GITHUB_OUTPUT" + workflow_path = Path('.github/workflows/opencode-review-dispatch.yml') + lines = workflow_path.read_text(encoding='utf-8').splitlines(keepends=True) + producer_start = unique_index(lines, " coverage-source-tree:\n", label="coverage source job") + consumer_start = unique_index(lines, " coverage-evidence:\n", label="coverage evidence job") - - name: Upload materialized pull request merge tree - id: coverage_source_upload - ''' - if source.count(upload_anchor) != 1: - raise SystemExit('coverage source upload anchor changed') - source = source.replace(upload_anchor, attempt_step, 1) + artifact_output = ( + " coverage_source_artifact_id: " + + action_expression("steps.coverage_source_upload.outputs.artifact-id") + + "\n" + ) + output_index = unique_index( + lines, + artifact_output, + start=producer_start, + end=consumer_start, + label="artifact ID job output", + ) + attempt_output = ( + " coverage_source_run_attempt: " + + action_expression("steps.coverage_source_attempt.outputs.run_attempt") + + "\n" + ) + if attempt_output in lines[producer_start:consumer_start]: + raise SystemExit("coverage attempt output unexpectedly already present") + lines.insert(output_index + 1, attempt_output) - download_anchor = ''' - name: Download current-attempt materialized pull request merge tree - id: coverage_source_download - ''' - attempt_guard = ''' - name: Verify coverage source was produced in current workflow attempt - env: - COVERAGE_SOURCE_RUN_ATTEMPT: ${{ needs.coverage-source-tree.outputs.coverage_source_run_attempt }} - CURRENT_RUN_ATTEMPT: ${{ github.run_attempt }} - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - if [ -z "$COVERAGE_SOURCE_RUN_ATTEMPT" ] || [ "$COVERAGE_SOURCE_RUN_ATTEMPT" != "$CURRENT_RUN_ATTEMPT" ]; then - echo "::error::Coverage source evidence was not produced in current workflow run attempt ${CURRENT_RUN_ATTEMPT}; producer attempt was ${COVERAGE_SOURCE_RUN_ATTEMPT:-missing}." - echo "::error::A failed-jobs-only rerun cannot reuse prior-attempt source evidence; use a full rerun or a fresh repository dispatch." - exit 1 - fi + producer_start = unique_index(lines, " coverage-source-tree:\n", label="coverage source job after output") + consumer_start = unique_index(lines, " coverage-evidence:\n", label="coverage evidence job after output") + upload_index = unique_index( + lines, + " - name: Upload materialized pull request merge tree\n", + start=producer_start, + end=consumer_start, + label="coverage source upload step", + ) + attempt_step = [ + " - name: Record coverage source workflow attempt\n", + " id: coverage_source_attempt\n", + " env:\n", + " GITHUB_RUN_ATTEMPT: " + action_expression("github.run_attempt") + "\n", + " shell: bash --noprofile --norc -e -o pipefail {0}\n", + " run: |\n", + " printf 'run_attempt=%s\\n' \"$GITHUB_RUN_ATTEMPT\" >>\"$GITHUB_OUTPUT\"\n", + "\n", + ] + if " id: coverage_source_attempt\n" in lines[producer_start:consumer_start]: + raise SystemExit("coverage attempt step unexpectedly already present") + lines[upload_index:upload_index] = attempt_step - - name: Download current-attempt materialized pull request merge tree - id: coverage_source_download - ''' - if source.count(download_anchor) != 1: - raise SystemExit('coverage source download anchor changed') - workflow_path.write_text(source.replace(download_anchor, attempt_guard, 1), encoding='utf-8') + consumer_start = unique_index(lines, " coverage-evidence:\n", label="coverage evidence job before guard") + review_start = unique_index( + lines, + " opencode-review-target:\n", + start=consumer_start, + label="OpenCode review target job", + ) + download_index = unique_index( + lines, + " - name: Download current-attempt materialized pull request merge tree\n", + start=consumer_start, + end=review_start, + label="coverage source download step", + ) + guard_step = [ + " - name: Verify coverage source was produced in current workflow attempt\n", + " env:\n", + " COVERAGE_SOURCE_RUN_ATTEMPT: " + + action_expression("needs.coverage-source-tree.outputs.coverage_source_run_attempt") + + "\n", + " CURRENT_RUN_ATTEMPT: " + action_expression("github.run_attempt") + "\n", + " shell: bash --noprofile --norc -e -o pipefail {0}\n", + " run: |\n", + " if [ -z \"$COVERAGE_SOURCE_RUN_ATTEMPT\" ] || [ \"$COVERAGE_SOURCE_RUN_ATTEMPT\" != \"$CURRENT_RUN_ATTEMPT\" ]; then\n", + " echo \"::error::Coverage source evidence was not produced in current workflow run attempt ${CURRENT_RUN_ATTEMPT}; producer attempt was ${COVERAGE_SOURCE_RUN_ATTEMPT:-missing}.\"\n", + " echo \"::error::A failed-jobs-only rerun cannot reuse prior-attempt source evidence; use a full rerun or a fresh repository dispatch.\"\n", + " exit 1\n", + " fi\n", + "\n", + ] + if " - name: Verify coverage source was produced in current workflow attempt\n" in lines[consumer_start:review_start]: + raise SystemExit("coverage attempt guard unexpectedly already present") + lines[download_index:download_index] = guard_step + workflow_path.write_text("".join(lines), encoding='utf-8') doctoring_path = Path('docs/doctoring/opencode-coverage-artifact-reruns.md') doctoring = doctoring_path.read_text(encoding='utf-8') - decision_anchor = ( - 'The source artifact retains the existing one-day retention period. ' - ) + decision_anchor = "The source artifact retains the existing one-day retention period. " decision_insert = ( - 'The producer also records the literal workflow attempt in a step output, and ' - 'the consumer compares that producer-attested value with its own current ' - '`github.run_attempt` before any artifact download. An immutable artifact ID ' - 'proves which upload is selected; the separate attempt marker proves when the ' - 'producer actually executed.\n\n' + "The producer also records the literal workflow attempt in a step output, and " + "the consumer compares that producer-attested value with its own current " + "`github.run_attempt` before any artifact download. An immutable artifact ID " + "proves which upload is selected; the separate attempt marker proves when the " + "producer actually executed.\n\n" + decision_anchor ) if doctoring.count(decision_anchor) != 1: @@ -155,59 +199,61 @@ jobs: doctoring = doctoring.replace(decision_anchor, decision_insert, 1) bullet_anchor = ( - '- The upload step exports the immutable `artifact-id`; the consumer downloads ' - 'with `artifact-ids` rather than `name`.\n' + "- The upload step exports the immutable `artifact-id`; the consumer downloads " + "with `artifact-ids` rather than `name`.\n" ) bullet_insert = bullet_anchor + ( - '- The producer exports its step-recorded run attempt; the consumer rejects an ' - 'empty or mismatched producer attempt before artifact download, so selective ' - 'reruns cannot reuse prior-attempt source evidence while it is still retained.\n' + "- The producer exports its step-recorded run attempt; the consumer rejects an " + "empty or mismatched producer attempt before artifact download, so selective " + "reruns cannot reuse prior-attempt source evidence while it is still retained.\n" ) if doctoring.count(bullet_anchor) != 1: raise SystemExit('doctoring contract bullet anchor changed') doctoring = doctoring.replace(bullet_anchor, bullet_insert, 1) table_old = ( - '| Failed-jobs-only rerun while producer is omitted | No current-attempt producer ' - 'output exists | Fails closed with recovery guidance | Expected failure |' + "| Failed-jobs-only rerun while producer is omitted | No current-attempt producer " + "output exists | Fails closed with recovery guidance | Expected failure |" ) table_new = ( - '| Failed-jobs-only rerun while producer is omitted | Producer attempt marker is ' - 'missing or belongs to the earlier attempt | Rejects the attempt mismatch before ' - 'artifact download | Expected failure |' + "| Failed-jobs-only rerun while producer is omitted | Producer attempt marker is " + "missing or belongs to the earlier attempt | Rejects the attempt mismatch before " + "artifact download | Expected failure |" ) if doctoring.count(table_old) != 1: raise SystemExit('doctoring rerun table anchor changed') doctoring = doctoring.replace(table_old, table_new, 1) rationale_anchor = ( - 'The producer\'s exact `artifact-id` closes that ambiguity. Attempt-qualified ' - 'naming remains useful for diagnostics, while ID-based selection is the ' - 'authoritative binding.\n' + "The producer's exact `artifact-id` closes that ambiguity. Attempt-qualified " + "naming remains useful for diagnostics, while ID-based selection is the " + "authoritative binding.\n" ) rationale_new = ( - 'The producer\'s exact `artifact-id` closes the upload-selection ambiguity, while ' - 'the producer step\'s literal attempt output closes the execution-attempt ' - 'ambiguity. Attempt-qualified naming remains useful for diagnostics; exact ID ' - 'selection and the producer-attempt equality check are both required.\n' + "The producer's exact `artifact-id` closes the upload-selection ambiguity, while " + "the producer step's literal attempt output closes the execution-attempt " + "ambiguity. Attempt-qualified naming remains useful for diagnostics; exact ID " + "selection and the producer-attempt equality check are both required.\n" ) if doctoring.count(rationale_anchor) != 1: raise SystemExit('doctoring rationale anchor changed') doctoring = doctoring.replace(rationale_anchor, rationale_new, 1) - verification_old = '''1. attempt-scoped artifact naming and immutable `artifact-id` producer output; - 2. exact-ID download by the consumer; - 3. actionable failure for a missing current-attempt artifact; - 4. one-day retention; and - 5. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`. - ''' - verification_new = '''1. attempt-scoped artifact naming and immutable `artifact-id` producer output; - 2. producer-attested workflow attempt output and pre-download current-attempt equality; - 3. exact-ID download by the consumer; - 4. actionable failure for missing or prior-attempt evidence; - 5. one-day retention; and - 6. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`. - ''' + verification_old = ( + "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" + "2. exact-ID download by the consumer;\n" + "3. actionable failure for a missing current-attempt artifact;\n" + "4. one-day retention; and\n" + "5. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" + ) + verification_new = ( + "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" + "2. producer-attested workflow attempt output and pre-download current-attempt equality;\n" + "3. exact-ID download by the consumer;\n" + "4. actionable failure for missing or prior-attempt evidence;\n" + "5. one-day retention; and\n" + "6. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" + ) if doctoring.count(verification_old) != 1: raise SystemExit('doctoring verification anchor changed') doctoring_path.write_text(doctoring.replace(verification_old, verification_new, 1), encoding='utf-8') @@ -215,16 +261,16 @@ jobs: changelog_path = Path('CHANGELOG.md') changelog = changelog_path.read_text(encoding='utf-8') old_entry = ( - '- Bound OpenCode coverage source artifacts to one workflow attempt and immutable ' - 'artifact ID, retained one-day source evidence, and made failed-jobs-only reruns ' - 'fail closed with full-rerun or fresh-dispatch guidance instead of searching for ' - 'expired or prior-attempt artifacts.\n' + "- Bound OpenCode coverage source artifacts to one workflow attempt and immutable " + "artifact ID, retained one-day source evidence, and made failed-jobs-only reruns " + "fail closed with full-rerun or fresh-dispatch guidance instead of searching for " + "expired or prior-attempt artifacts.\n" ) new_entry = ( - '- Bound OpenCode coverage source artifacts to one immutable artifact ID and a ' - 'producer-attested workflow-attempt marker, retained one-day source evidence, and ' - 'made failed-jobs-only reruns fail closed before download when the producer did not ' - 'run in the current attempt, with full-rerun or fresh-dispatch guidance.\n' + "- Bound OpenCode coverage source artifacts to one immutable artifact ID and a " + "producer-attested workflow-attempt marker, retained one-day source evidence, and " + "made failed-jobs-only reruns fail closed before download when the producer did not " + "run in the current attempt, with full-rerun or fresh-dispatch guidance.\n" ) if changelog.count(old_entry) != 1: raise SystemExit('CHANGELOG attempt-artifact entry anchor changed') From 3569adebd91b859193837ad837c9e9247c714c52 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:28:48 +0900 Subject: [PATCH 25/56] test(opencode): reject empty attempt-scoped artifact IDs --- ...encode_coverage_artifact_rerun_contract.py | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/tests/test_opencode_coverage_artifact_rerun_contract.py b/tests/test_opencode_coverage_artifact_rerun_contract.py index d91d910db..7feaafac2 100644 --- a/tests/test_opencode_coverage_artifact_rerun_contract.py +++ b/tests/test_opencode_coverage_artifact_rerun_contract.py @@ -39,11 +39,26 @@ def test_coverage_source_artifact_is_attempt_scoped_and_downloaded_by_id() -> No assert "name: opencode-coverage-source-${{ github.run_attempt }}" in source_job assert "retention-days: 1" in source_job + assert "id: coverage_source_identity" in evidence_job assert ( - "artifact-ids: " + "COVERAGE_SOURCE_ARTIFACT_ID: " "${{ needs.coverage-source-tree.outputs.coverage_source_artifact_id }}" in evidence_job ) + assert '[[ "$COVERAGE_SOURCE_ARTIFACT_ID" =~ ^[1-9][0-9]*$ ]]' in evidence_job + assert "artifact_id=$COVERAGE_SOURCE_ARTIFACT_ID" in evidence_job + assert ( + "if: steps.coverage_source_identity.outcome == 'success'" in evidence_job + ) + assert ( + "artifact-ids: ${{ steps.coverage_source_identity.outputs.artifact_id }}" + in evidence_job + ) + assert ( + "artifact-ids: " + "${{ needs.coverage-source-tree.outputs.coverage_source_artifact_id }}" + not in evidence_job + ) assert "name: opencode-coverage-source\n" not in evidence_job @@ -71,7 +86,7 @@ def test_coverage_source_requires_current_producer_attempt() -> None: assert '[ "$COVERAGE_SOURCE_RUN_ATTEMPT" != "$CURRENT_RUN_ATTEMPT" ]' in evidence_job assert "full rerun or a fresh repository dispatch" in evidence_job guard_index = evidence_job.index( - "- name: Verify coverage source was produced in current workflow attempt" + "- name: Verify coverage source identity for current workflow attempt" ) download_index = evidence_job.index( "- name: Download current-attempt materialized pull request merge tree" @@ -84,11 +99,11 @@ def test_missing_current_attempt_artifact_fails_with_fresh_run_guidance() -> Non workflow = _workflow_text() evidence_job = _job_block(workflow, "coverage-evidence", "opencode-review-target") + assert "id: coverage_source_identity" in evidence_job assert "id: coverage_source_download" in evidence_job - assert "continue-on-error: true" in evidence_job - assert ( - "if: steps.coverage_source_download.outcome != 'success'" in evidence_job - ) + assert evidence_job.count("continue-on-error: true") >= 2 + assert "steps.coverage_source_identity.outcome != 'success'" in evidence_job + assert "steps.coverage_source_download.outcome != 'success'" in evidence_job assert "failed-jobs-only rerun" in evidence_job assert "full rerun or a fresh repository dispatch" in evidence_job assert "GITHUB_RUN_ATTEMPT" in evidence_job From 9a866698b821638f3288e78f8a8e3b437deb05c3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:31:10 +0900 Subject: [PATCH 26/56] fix(opencode): bind repair to exact PR head --- ...pencode-coverage-artifact-rerun-repair.yml | 159 ++++++++++++------ 1 file changed, 112 insertions(+), 47 deletions(-) diff --git a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml index 57bc5f99f..7e81f07c3 100644 --- a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml +++ b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml @@ -1,9 +1,8 @@ name: OpenCode Coverage Artifact Rerun Repair on: - push: - branches: - - fix/opencode-attempt-scoped-coverage-artifact + pull_request: + branches: [main] paths: - ".github/workflows/opencode-coverage-artifact-rerun-repair.yml" @@ -21,8 +20,9 @@ jobs: repair-and-publish: if: >- github.repository == 'ContextualWisdomLab/.github' - && github.ref == 'refs/heads/fix/opencode-attempt-scoped-coverage-artifact' - && github.actor == 'seonghobae' + && github.event.pull_request.number == 812 + && github.event.pull_request.head.repo.full_name == 'ContextualWisdomLab/.github' + && github.event.pull_request.head.ref == 'fix/opencode-attempt-scoped-coverage-artifact' permissions: contents: read id-token: write @@ -37,20 +37,23 @@ jobs: - name: Check out exact repair trigger uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: - ref: ${{ github.sha }} - fetch-depth: 4 + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 2 persist-credentials: false - name: Refuse stale or widened trigger lineage env: - EXPECTED_RED_HEAD: 817772bc12c28ca1fe161046a478e50c5a9dd530 + EXACT_TRIGGER_HEAD: ${{ github.event.pull_request.head.sha }} + EXACT_BASE_SHA: ${{ github.event.pull_request.base.sha }} + EXPECTED_RED_HEAD: 3569adebd91b859193837ad837c9e9247c714c52 + EXPECTED_BASE_SHA: e6fc91416c4fb13febd07b985c6e9c74fe888306 REPAIR_WORKFLOW: .github/workflows/opencode-coverage-artifact-rerun-repair.yml shell: bash --noprofile --norc -e -o pipefail {0} run: | - test "$(git rev-parse HEAD)" = "$GITHUB_SHA" - git merge-base --is-ancestor "$EXPECTED_RED_HEAD" "$GITHUB_SHA" - test "$(git rev-list --count "$EXPECTED_RED_HEAD..$GITHUB_SHA")" -le 2 - changed="$(git diff --name-only "$EXPECTED_RED_HEAD" "$GITHUB_SHA")" + test "$EXACT_BASE_SHA" = "$EXPECTED_BASE_SHA" + test "$(git rev-parse HEAD)" = "$EXACT_TRIGGER_HEAD" + test "$(git rev-parse HEAD^)" = "$EXPECTED_RED_HEAD" + changed="$(git diff --name-only "$EXPECTED_RED_HEAD" "$EXACT_TRIGGER_HEAD")" test "$changed" = "$REPAIR_WORKFLOW" - name: Set up Python 3.14 @@ -65,7 +68,7 @@ jobs: python -m pip install --disable-pip-version-check --require-hashes -r requirements-opencode-review-ci-hashes.txt - - name: Prove current-attempt provenance contract is red + - name: Prove current identity contracts are red shell: bash --noprofile --norc {0} run: | set +e @@ -74,15 +77,17 @@ jobs: set -e printf '%s\n' "$output" test "$status" -eq 1 + grep -F "test_coverage_source_artifact_is_attempt_scoped_and_downloaded_by_id" <<<"$output" grep -F "test_coverage_source_requires_current_producer_attempt" <<<"$output" - - name: Apply reviewed current-attempt provenance repair + - name: Apply reviewed current-attempt identity repair shell: bash --noprofile --norc -e -o pipefail {0} run: | python3 - <<'PY' from pathlib import Path def action_expression(value: str) -> str: + """Return a literal GitHub Actions expression without pre-evaluation.""" return "$" + "{{ " + value + " }}" def unique_index( @@ -93,6 +98,7 @@ jobs: end: int | None = None, label: str, ) -> int: + """Return the sole matching line index inside the requested bounds.""" stop = len(lines) if end is None else end matches = [index for index in range(start, stop) if lines[index] == needle] if len(matches) != 1: @@ -148,7 +154,7 @@ jobs: raise SystemExit("coverage attempt step unexpectedly already present") lines[upload_index:upload_index] = attempt_step - consumer_start = unique_index(lines, " coverage-evidence:\n", label="coverage evidence job before guard") + consumer_start = unique_index(lines, " coverage-evidence:\n", label="coverage evidence job before identity") review_start = unique_index( lines, " opencode-review-target:\n", @@ -162,9 +168,14 @@ jobs: end=review_start, label="coverage source download step", ) - guard_step = [ - " - name: Verify coverage source was produced in current workflow attempt\n", + identity_step = [ + " - name: Verify coverage source identity for current workflow attempt\n", + " id: coverage_source_identity\n", + " continue-on-error: true\n", " env:\n", + " COVERAGE_SOURCE_ARTIFACT_ID: " + + action_expression("needs.coverage-source-tree.outputs.coverage_source_artifact_id") + + "\n", " COVERAGE_SOURCE_RUN_ATTEMPT: " + action_expression("needs.coverage-source-tree.outputs.coverage_source_run_attempt") + "\n", @@ -176,22 +187,73 @@ jobs: " echo \"::error::A failed-jobs-only rerun cannot reuse prior-attempt source evidence; use a full rerun or a fresh repository dispatch.\"\n", " exit 1\n", " fi\n", + " if ! [[ \"$COVERAGE_SOURCE_ARTIFACT_ID\" =~ ^[1-9][0-9]*$ ]]; then\n", + " echo \"::error::Coverage source artifact ID is missing or malformed for workflow run attempt ${CURRENT_RUN_ATTEMPT}.\"\n", + " echo \"::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree publishes a current immutable artifact ID.\"\n", + " exit 1\n", + " fi\n", + " printf 'artifact_id=%s\\n' \"$COVERAGE_SOURCE_ARTIFACT_ID\" >>\"$GITHUB_OUTPUT\"\n", "\n", ] - if " - name: Verify coverage source was produced in current workflow attempt\n" in lines[consumer_start:review_start]: - raise SystemExit("coverage attempt guard unexpectedly already present") - lines[download_index:download_index] = guard_step + if " id: coverage_source_identity\n" in lines[consumer_start:review_start]: + raise SystemExit("coverage identity step unexpectedly already present") + lines[download_index:download_index] = identity_step + + consumer_start = unique_index(lines, " coverage-evidence:\n", label="coverage evidence job after identity") + review_start = unique_index(lines, " opencode-review-target:\n", start=consumer_start, label="review job after identity") + download_index = unique_index( + lines, + " - name: Download current-attempt materialized pull request merge tree\n", + start=consumer_start, + end=review_start, + label="download step after identity", + ) + lines.insert( + download_index + 1, + " if: " + action_expression("steps.coverage_source_identity.outcome == 'success'") + "\n", + ) + direct_artifact_line = ( + " artifact-ids: " + + action_expression("needs.coverage-source-tree.outputs.coverage_source_artifact_id") + + "\n" + ) + direct_index = unique_index( + lines, + direct_artifact_line, + start=download_index, + end=review_start + len(identity_step) + 1, + label="direct artifact input", + ) + lines[direct_index] = ( + " artifact-ids: " + + action_expression("steps.coverage_source_identity.outputs.artifact_id") + + "\n" + ) + + report_index = unique_index( + lines, + " - name: Report missing current-attempt coverage source\n", + start=consumer_start, + label="missing source report", + ) + old_if = " if: steps.coverage_source_download.outcome != 'success'\n" + if lines[report_index + 1] != old_if: + raise SystemExit('missing-source report condition anchor changed') + lines[report_index + 1] = ( + " if: steps.coverage_source_identity.outcome != 'success' || " + "steps.coverage_source_download.outcome != 'success'\n" + ) workflow_path.write_text("".join(lines), encoding='utf-8') doctoring_path = Path('docs/doctoring/opencode-coverage-artifact-reruns.md') doctoring = doctoring_path.read_text(encoding='utf-8') decision_anchor = "The source artifact retains the existing one-day retention period. " decision_insert = ( - "The producer also records the literal workflow attempt in a step output, and " - "the consumer compares that producer-attested value with its own current " - "`github.run_attempt` before any artifact download. An immutable artifact ID " - "proves which upload is selected; the separate attempt marker proves when the " - "producer actually executed.\n\n" + "The producer also records the literal workflow attempt in a step output. Before " + "download, the consumer compares that producer-attested value with its own current " + "`github.run_attempt` and validates that the producer's immutable artifact ID is a " + "nonzero decimal identifier. Artifact immutability proves which upload is selected; " + "the separate attempt marker proves when the producer actually executed.\n\n" + decision_anchor ) if doctoring.count(decision_anchor) != 1: @@ -202,10 +264,13 @@ jobs: "- The upload step exports the immutable `artifact-id`; the consumer downloads " "with `artifact-ids` rather than `name`.\n" ) - bullet_insert = bullet_anchor + ( - "- The producer exports its step-recorded run attempt; the consumer rejects an " - "empty or mismatched producer attempt before artifact download, so selective " - "reruns cannot reuse prior-attempt source evidence while it is still retained.\n" + bullet_insert = ( + "- The upload step exports the immutable `artifact-id`; the consumer first validates " + "that the value is a nonzero decimal identifier and passes only that validated step " + "output to `download-artifact`.\n" + "- The producer exports its step-recorded run attempt; the consumer rejects an empty " + "or mismatched producer attempt before artifact download, so selective reruns cannot " + "reuse prior-attempt source evidence while it is still retained.\n" ) if doctoring.count(bullet_anchor) != 1: raise SystemExit('doctoring contract bullet anchor changed') @@ -216,8 +281,8 @@ jobs: "output exists | Fails closed with recovery guidance | Expected failure |" ) table_new = ( - "| Failed-jobs-only rerun while producer is omitted | Producer attempt marker is " - "missing or belongs to the earlier attempt | Rejects the attempt mismatch before " + "| Failed-jobs-only rerun while producer is omitted | Producer attempt marker or " + "artifact ID is absent or belongs to the earlier attempt | Rejects identity before " "artifact download | Expected failure |" ) if doctoring.count(table_old) != 1: @@ -225,15 +290,15 @@ jobs: doctoring = doctoring.replace(table_old, table_new, 1) rationale_anchor = ( - "The producer's exact `artifact-id` closes that ambiguity. Attempt-qualified " - "naming remains useful for diagnostics, while ID-based selection is the " - "authoritative binding.\n" + "The producer's exact `artifact-id` closes that ambiguity. Attempt-qualified naming " + "remains useful for diagnostics, while ID-based selection is the authoritative binding.\n" ) rationale_new = ( - "The producer's exact `artifact-id` closes the upload-selection ambiguity, while " - "the producer step's literal attempt output closes the execution-attempt " - "ambiguity. Attempt-qualified naming remains useful for diagnostics; exact ID " - "selection and the producer-attempt equality check are both required.\n" + "The producer's exact `artifact-id` closes the upload-selection ambiguity, while the " + "producer step's literal attempt output closes the execution-attempt ambiguity. The " + "consumer validates both values before download. Attempt-qualified naming remains " + "useful for diagnostics; validated exact-ID selection and producer-attempt equality " + "are both required.\n" ) if doctoring.count(rationale_anchor) != 1: raise SystemExit('doctoring rationale anchor changed') @@ -248,9 +313,9 @@ jobs: ) verification_new = ( "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" - "2. producer-attested workflow attempt output and pre-download current-attempt equality;\n" - "3. exact-ID download by the consumer;\n" - "4. actionable failure for missing or prior-attempt evidence;\n" + "2. producer-attested workflow-attempt output and pre-download equality;\n" + "3. nonempty positive-decimal artifact-ID validation before exact-ID download;\n" + "4. actionable failure for missing, malformed, or prior-attempt evidence;\n" "5. one-day retention; and\n" "6. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" ) @@ -267,10 +332,10 @@ jobs: "expired or prior-attempt artifacts.\n" ) new_entry = ( - "- Bound OpenCode coverage source artifacts to one immutable artifact ID and a " - "producer-attested workflow-attempt marker, retained one-day source evidence, and " - "made failed-jobs-only reruns fail closed before download when the producer did not " - "run in the current attempt, with full-rerun or fresh-dispatch guidance.\n" + "- Bound OpenCode coverage source artifacts to a validated immutable artifact ID and " + "producer-attested workflow-attempt marker, retained one-day source evidence, and made " + "failed-jobs-only reruns fail closed before download when identity is missing, malformed, " + "or from a prior attempt, with full-rerun or fresh-dispatch guidance.\n" ) if changelog.count(old_entry) != 1: raise SystemExit('CHANGELOG attempt-artifact entry anchor changed') @@ -323,7 +388,7 @@ jobs: env: PUSH_TOKEN: ${{ steps.target_app_token.outputs.token }} TARGET_BRANCH: fix/opencode-attempt-scoped-coverage-artifact - EXPECTED_TRIGGER_HEAD: ${{ github.sha }} + EXPECTED_TRIGGER_HEAD: ${{ github.event.pull_request.head.sha }} shell: bash --noprofile --norc -e -o pipefail {0} run: | test -n "$PUSH_TOKEN" @@ -344,7 +409,7 @@ jobs: 'docs/doctoring/opencode-coverage-artifact-reruns.md' | sort)" staged="$(git diff --cached --name-only | sort)" test "$staged" = "$expected" - git commit -m "fix(opencode): attest current coverage producer attempt" + git commit -m "fix(opencode): attest current coverage source identity" test -z "$(git status --porcelain --untracked-files=all)" git remote set-url origin "https://x-access-token:${PUSH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" git push origin "HEAD:refs/heads/${TARGET_BRANCH}" From 952c8d41c6f013ee90228a69ac4ae626982ebd3e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:33:15 +0900 Subject: [PATCH 27/56] chore(opencode): add temporary current-attempt identity materializer --- ...prepare_opencode_attempt_artifact_patch.py | 349 ++++++++++++++++++ 1 file changed, 349 insertions(+) create mode 100644 scripts/ci/prepare_opencode_attempt_artifact_patch.py diff --git a/scripts/ci/prepare_opencode_attempt_artifact_patch.py b/scripts/ci/prepare_opencode_attempt_artifact_patch.py new file mode 100644 index 000000000..2d142ccfb --- /dev/null +++ b/scripts/ci/prepare_opencode_attempt_artifact_patch.py @@ -0,0 +1,349 @@ +#!/usr/bin/env python3 +"""Materialize the reviewed current-attempt OpenCode artifact identity repair. + +This helper is temporary branch-local tooling. It patches only the permanent +OpenCode dispatch workflow, authoritative doctoring, and the Unreleased +changelog entry. The publishing workflow removes this file before committing +the verified implementation. +""" + +from __future__ import annotations + +from pathlib import Path + + +WORKFLOW_PATH = Path(".github/workflows/opencode-review-dispatch.yml") +DOCTORING_PATH = Path("docs/doctoring/opencode-coverage-artifact-reruns.md") +CHANGELOG_PATH = Path("CHANGELOG.md") + + +def action_expression(value: str) -> str: + """Return a literal GitHub Actions expression without early evaluation.""" + return "$" + "{{ " + value + " }}" + + +def unique_index( + lines: list[str], + needle: str, + *, + start: int = 0, + end: int | None = None, + label: str, +) -> int: + """Return the only exact line match within a bounded line range.""" + stop = len(lines) if end is None else end + matches = [index for index in range(start, stop) if lines[index] == needle] + if len(matches) != 1: + raise SystemExit(f"Expected exactly one {label}, found {len(matches)}.") + return matches[0] + + +def patch_workflow() -> None: + """Bind exact artifact selection to producer-attested current-run provenance.""" + lines = WORKFLOW_PATH.read_text(encoding="utf-8").splitlines(keepends=True) + producer_start = unique_index( + lines, " coverage-source-tree:\n", label="coverage source job" + ) + consumer_start = unique_index( + lines, " coverage-evidence:\n", label="coverage evidence job" + ) + + artifact_output = ( + " coverage_source_artifact_id: " + + action_expression("steps.coverage_source_upload.outputs.artifact-id") + + "\n" + ) + artifact_output_index = unique_index( + lines, + artifact_output, + start=producer_start, + end=consumer_start, + label="coverage artifact ID job output", + ) + attempt_output = ( + " coverage_source_run_attempt: " + + action_expression("steps.coverage_source_attempt.outputs.run_attempt") + + "\n" + ) + if attempt_output in lines[producer_start:consumer_start]: + raise SystemExit("Producer attempt output unexpectedly already exists.") + lines.insert(artifact_output_index + 1, attempt_output) + + producer_start = unique_index( + lines, " coverage-source-tree:\n", label="coverage source job after output" + ) + consumer_start = unique_index( + lines, + " coverage-evidence:\n", + label="coverage evidence job after output", + ) + upload_step_index = unique_index( + lines, + " - name: Upload materialized pull request merge tree\n", + start=producer_start, + end=consumer_start, + label="coverage source upload step", + ) + if " id: coverage_source_attempt\n" in lines[producer_start:consumer_start]: + raise SystemExit("Producer attempt attestation step unexpectedly already exists.") + attempt_step = [ + " - name: Record coverage source workflow attempt\n", + " id: coverage_source_attempt\n", + " env:\n", + " GITHUB_RUN_ATTEMPT: " + + action_expression("github.run_attempt") + + "\n", + " shell: bash --noprofile --norc -e -o pipefail {0}\n", + " run: |\n", + " if ! [[ \"$GITHUB_RUN_ATTEMPT\" =~ ^[1-9][0-9]*$ ]]; then\n", + " echo \"::error::Coverage producer workflow attempt is not a positive integer.\"\n", + " exit 1\n", + " fi\n", + " printf 'run_attempt=%s\\n' \"$GITHUB_RUN_ATTEMPT\" >>\"$GITHUB_OUTPUT\"\n", + "\n", + ] + lines[upload_step_index:upload_step_index] = attempt_step + + consumer_start = unique_index( + lines, + " coverage-evidence:\n", + label="coverage evidence job before identity guard", + ) + review_start = unique_index( + lines, + " opencode-review-target:\n", + start=consumer_start, + label="OpenCode review target job", + ) + download_step_index = unique_index( + lines, + " - name: Download current-attempt materialized pull request merge tree\n", + start=consumer_start, + end=review_start, + label="coverage source download step", + ) + if " id: coverage_source_identity\n" in lines[consumer_start:review_start]: + raise SystemExit("Coverage source identity step unexpectedly already exists.") + + identity_step = [ + " - name: Verify coverage source identity for current workflow attempt\n", + " id: coverage_source_identity\n", + " continue-on-error: true\n", + " env:\n", + " COVERAGE_SOURCE_ARTIFACT_ID: " + + action_expression( + "needs.coverage-source-tree.outputs.coverage_source_artifact_id" + ) + + "\n", + " COVERAGE_SOURCE_RUN_ATTEMPT: " + + action_expression( + "needs.coverage-source-tree.outputs.coverage_source_run_attempt" + ) + + "\n", + " CURRENT_RUN_ATTEMPT: " + + action_expression("github.run_attempt") + + "\n", + " shell: bash --noprofile --norc -e -o pipefail {0}\n", + " run: |\n", + " if ! [[ \"$COVERAGE_SOURCE_ARTIFACT_ID\" =~ ^[1-9][0-9]*$ ]] || \\\n", + " ! [[ \"$CURRENT_RUN_ATTEMPT\" =~ ^[1-9][0-9]*$ ]] || \\\n", + " [ \"$COVERAGE_SOURCE_RUN_ATTEMPT\" != \"$CURRENT_RUN_ATTEMPT\" ]; then\n", + " echo \"::error::Coverage source identity is invalid for current workflow attempt ${CURRENT_RUN_ATTEMPT:-missing}; producer attempt=${COVERAGE_SOURCE_RUN_ATTEMPT:-missing}, artifact_id=${COVERAGE_SOURCE_ARTIFACT_ID:-missing}.\"\n", + " exit 1\n", + " fi\n", + " printf 'artifact_id=%s\\n' \"$COVERAGE_SOURCE_ARTIFACT_ID\" >>\"$GITHUB_OUTPUT\"\n", + "\n", + ] + lines[download_step_index:download_step_index] = identity_step + + consumer_start = unique_index( + lines, + " coverage-evidence:\n", + label="coverage evidence job before download binding", + ) + review_start = unique_index( + lines, + " opencode-review-target:\n", + start=consumer_start, + label="OpenCode review target job after identity insertion", + ) + download_step_index = unique_index( + lines, + " - name: Download current-attempt materialized pull request merge tree\n", + start=consumer_start, + end=review_start, + label="coverage source download after identity insertion", + ) + if lines[download_step_index + 1] != " id: coverage_source_download\n": + raise SystemExit("Coverage source download ID anchor changed.") + lines.insert( + download_step_index + 1, + " if: steps.coverage_source_identity.outcome == 'success'\n", + ) + + artifact_ids_index = unique_index( + lines, + " artifact-ids: " + + action_expression( + "needs.coverage-source-tree.outputs.coverage_source_artifact_id" + ) + + "\n", + start=download_step_index, + end=review_start, + label="direct producer artifact ID download binding", + ) + lines[artifact_ids_index] = ( + " artifact-ids: " + + action_expression("steps.coverage_source_identity.outputs.artifact_id") + + "\n" + ) + + missing_report_index = unique_index( + lines, + " - name: Report missing current-attempt coverage source\n", + start=download_step_index, + end=review_start, + label="missing coverage source report", + ) + missing_if_index = unique_index( + lines, + " if: steps.coverage_source_download.outcome != 'success'\n", + start=missing_report_index, + end=review_start, + label="missing coverage source condition", + ) + lines[missing_if_index] = ( + " if: steps.coverage_source_identity.outcome == 'success' && " + "steps.coverage_source_download.outcome != 'success'\n" + ) + + identity_report = [ + " - name: Report coverage source identity failure\n", + " if: steps.coverage_source_identity.outcome != 'success'\n", + " env:\n", + " GITHUB_RUN_ATTEMPT: " + + action_expression("github.run_attempt") + + "\n", + " run: |\n", + " set -euo pipefail\n", + " echo \"::error::Coverage source evidence was not produced and identified in current workflow run attempt ${GITHUB_RUN_ATTEMPT}; a failed-jobs-only rerun cannot reuse prior-attempt source evidence.\"\n", + " echo \"::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree runs and uploads exact current-attempt evidence.\"\n", + " exit 1\n", + "\n", + ] + lines[download_step_index:download_step_index] = identity_report + + WORKFLOW_PATH.write_text("".join(lines), encoding="utf-8") + + +def patch_doctoring() -> None: + """Document immutability, attempt provenance, and bounded identifier checks.""" + doctoring = DOCTORING_PATH.read_text(encoding="utf-8") + decision_anchor = "The source artifact retains the existing one-day retention period. " + decision_insert = ( + "The producer records its literal workflow attempt in a step output. Before any " + "download, the credential-free consumer verifies that the artifact ID is a positive " + "integer and that the producer-attested attempt equals the consumer's current " + "`github.run_attempt`. Artifact immutability identifies one upload; the separate " + "attempt attestation proves when its producer executed.\n\n" + + decision_anchor + ) + if doctoring.count(decision_anchor) != 1: + raise SystemExit("Doctoring decision anchor changed.") + doctoring = doctoring.replace(decision_anchor, decision_insert, 1) + + bullet_anchor = ( + "- The upload step exports the immutable `artifact-id`; the consumer downloads " + "with `artifact-ids` rather than `name`.\n" + ) + bullet_insert = bullet_anchor + ( + "- The producer exports its step-recorded run attempt; the consumer validates both " + "the artifact identifier and attempt marker before exposing the identifier to the " + "download action. Empty, malformed, or prior-attempt values fail closed.\n" + ) + if doctoring.count(bullet_anchor) != 1: + raise SystemExit("Doctoring contract bullet anchor changed.") + doctoring = doctoring.replace(bullet_anchor, bullet_insert, 1) + + table_old = ( + "| Failed-jobs-only rerun while producer is omitted | No current-attempt producer " + "output exists | Fails closed with recovery guidance | Expected failure |" + ) + table_new = ( + "| Failed-jobs-only rerun while producer is omitted | Producer attempt marker is " + "missing or belongs to an earlier attempt | Rejects identity before artifact " + "download | Expected failure |" + ) + if doctoring.count(table_old) != 1: + raise SystemExit("Doctoring rerun table anchor changed.") + doctoring = doctoring.replace(table_old, table_new, 1) + + rationale_anchor = ( + "The producer's exact `artifact-id` closes that ambiguity. Attempt-qualified naming " + "remains useful for diagnostics, while ID-based selection is the authoritative " + "binding.\n" + ) + rationale_new = ( + "The producer's exact `artifact-id` closes upload-selection ambiguity, while its " + "step-recorded attempt closes execution-attempt ambiguity. Attempt-qualified names " + "remain diagnostic; a validated positive artifact ID and producer-attempt equality " + "are both required before download.\n" + ) + if doctoring.count(rationale_anchor) != 1: + raise SystemExit("Doctoring rationale anchor changed.") + doctoring = doctoring.replace(rationale_anchor, rationale_new, 1) + + verification_old = ( + "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" + "2. exact-ID download by the consumer;\n" + "3. actionable failure for a missing current-attempt artifact;\n" + "4. one-day retention; and\n" + "5. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" + ) + verification_new = ( + "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" + "2. producer-attested attempt output and pre-download current-attempt equality;\n" + "3. positive-integer artifact ID validation and exact-ID download;\n" + "4. actionable failure for missing, malformed, or prior-attempt evidence;\n" + "5. one-day retention; and\n" + "6. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" + ) + if doctoring.count(verification_old) != 1: + raise SystemExit("Doctoring verification anchor changed.") + DOCTORING_PATH.write_text( + doctoring.replace(verification_old, verification_new, 1), + encoding="utf-8", + ) + + +def patch_changelog() -> None: + """Record the complete identity and provenance gate in Unreleased fixes.""" + changelog = CHANGELOG_PATH.read_text(encoding="utf-8") + old_entry = ( + "- Bound OpenCode coverage source artifacts to one workflow attempt and immutable " + "artifact ID, retained one-day source evidence, and made failed-jobs-only reruns " + "fail closed with full-rerun or fresh-dispatch guidance instead of searching for " + "expired or prior-attempt artifacts.\n" + ) + new_entry = ( + "- Bound OpenCode coverage source evidence to a validated immutable artifact ID and " + "producer-attested workflow attempt, retained one-day source evidence, and made " + "selective reruns fail closed before download on missing, malformed, or prior-attempt " + "identity with full-rerun or fresh-dispatch guidance.\n" + ) + if changelog.count(old_entry) != 1: + raise SystemExit("CHANGELOG attempt-artifact entry anchor changed.") + CHANGELOG_PATH.write_text( + changelog.replace(old_entry, new_entry, 1), encoding="utf-8" + ) + + +def main() -> None: + """Apply the bounded workflow, doctoring, and changelog repair.""" + patch_workflow() + patch_doctoring() + patch_changelog() + + +if __name__ == "__main__": + main() From 554ad4a6ca24f723e65eafe6b5526acd48e5ca1c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:33:40 +0900 Subject: [PATCH 28/56] chore(opencode): remove branch-writing coverage repair workflow --- ...pencode-coverage-artifact-rerun-repair.yml | 415 ------------------ 1 file changed, 415 deletions(-) delete mode 100644 .github/workflows/opencode-coverage-artifact-rerun-repair.yml diff --git a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml deleted file mode 100644 index 7e81f07c3..000000000 --- a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml +++ /dev/null @@ -1,415 +0,0 @@ -name: OpenCode Coverage Artifact Rerun Repair - -on: - pull_request: - branches: [main] - paths: - - ".github/workflows/opencode-coverage-artifact-rerun-repair.yml" - -concurrency: - group: opencode-coverage-artifact-rerun-repair-pr812 - cancel-in-progress: true - -permissions: - contents: read - -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - -jobs: - repair-and-publish: - if: >- - github.repository == 'ContextualWisdomLab/.github' - && github.event.pull_request.number == 812 - && github.event.pull_request.head.repo.full_name == 'ContextualWisdomLab/.github' - && github.event.pull_request.head.ref == 'fix/opencode-attempt-scoped-coverage-artifact' - permissions: - contents: read - id-token: write - runs-on: ubuntu-24.04 - timeout-minutes: 35 - steps: - - name: Harden runner - uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 - with: - egress-policy: audit - - - name: Check out exact repair trigger - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 2 - persist-credentials: false - - - name: Refuse stale or widened trigger lineage - env: - EXACT_TRIGGER_HEAD: ${{ github.event.pull_request.head.sha }} - EXACT_BASE_SHA: ${{ github.event.pull_request.base.sha }} - EXPECTED_RED_HEAD: 3569adebd91b859193837ad837c9e9247c714c52 - EXPECTED_BASE_SHA: e6fc91416c4fb13febd07b985c6e9c74fe888306 - REPAIR_WORKFLOW: .github/workflows/opencode-coverage-artifact-rerun-repair.yml - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - test "$EXACT_BASE_SHA" = "$EXPECTED_BASE_SHA" - test "$(git rev-parse HEAD)" = "$EXACT_TRIGGER_HEAD" - test "$(git rev-parse HEAD^)" = "$EXPECTED_RED_HEAD" - changed="$(git diff --name-only "$EXPECTED_RED_HEAD" "$EXACT_TRIGGER_HEAD")" - test "$changed" = "$REPAIR_WORKFLOW" - - - name: Set up Python 3.14 - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 - with: - python-version: "3.14" - cache: pip - cache-dependency-path: requirements-opencode-review-ci-hashes.txt - - - name: Install exact hash-locked quality tooling - run: >- - python -m pip install --disable-pip-version-check --require-hashes - -r requirements-opencode-review-ci-hashes.txt - - - name: Prove current identity contracts are red - shell: bash --noprofile --norc {0} - run: | - set +e - output="$(python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py 2>&1)" - status=$? - set -e - printf '%s\n' "$output" - test "$status" -eq 1 - grep -F "test_coverage_source_artifact_is_attempt_scoped_and_downloaded_by_id" <<<"$output" - grep -F "test_coverage_source_requires_current_producer_attempt" <<<"$output" - - - name: Apply reviewed current-attempt identity repair - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - python3 - <<'PY' - from pathlib import Path - - def action_expression(value: str) -> str: - """Return a literal GitHub Actions expression without pre-evaluation.""" - return "$" + "{{ " + value + " }}" - - def unique_index( - lines: list[str], - needle: str, - *, - start: int = 0, - end: int | None = None, - label: str, - ) -> int: - """Return the sole matching line index inside the requested bounds.""" - stop = len(lines) if end is None else end - matches = [index for index in range(start, stop) if lines[index] == needle] - if len(matches) != 1: - raise SystemExit(f"Expected one {label}, found {len(matches)}") - return matches[0] - - workflow_path = Path('.github/workflows/opencode-review-dispatch.yml') - lines = workflow_path.read_text(encoding='utf-8').splitlines(keepends=True) - producer_start = unique_index(lines, " coverage-source-tree:\n", label="coverage source job") - consumer_start = unique_index(lines, " coverage-evidence:\n", label="coverage evidence job") - - artifact_output = ( - " coverage_source_artifact_id: " - + action_expression("steps.coverage_source_upload.outputs.artifact-id") - + "\n" - ) - output_index = unique_index( - lines, - artifact_output, - start=producer_start, - end=consumer_start, - label="artifact ID job output", - ) - attempt_output = ( - " coverage_source_run_attempt: " - + action_expression("steps.coverage_source_attempt.outputs.run_attempt") - + "\n" - ) - if attempt_output in lines[producer_start:consumer_start]: - raise SystemExit("coverage attempt output unexpectedly already present") - lines.insert(output_index + 1, attempt_output) - - producer_start = unique_index(lines, " coverage-source-tree:\n", label="coverage source job after output") - consumer_start = unique_index(lines, " coverage-evidence:\n", label="coverage evidence job after output") - upload_index = unique_index( - lines, - " - name: Upload materialized pull request merge tree\n", - start=producer_start, - end=consumer_start, - label="coverage source upload step", - ) - attempt_step = [ - " - name: Record coverage source workflow attempt\n", - " id: coverage_source_attempt\n", - " env:\n", - " GITHUB_RUN_ATTEMPT: " + action_expression("github.run_attempt") + "\n", - " shell: bash --noprofile --norc -e -o pipefail {0}\n", - " run: |\n", - " printf 'run_attempt=%s\\n' \"$GITHUB_RUN_ATTEMPT\" >>\"$GITHUB_OUTPUT\"\n", - "\n", - ] - if " id: coverage_source_attempt\n" in lines[producer_start:consumer_start]: - raise SystemExit("coverage attempt step unexpectedly already present") - lines[upload_index:upload_index] = attempt_step - - consumer_start = unique_index(lines, " coverage-evidence:\n", label="coverage evidence job before identity") - review_start = unique_index( - lines, - " opencode-review-target:\n", - start=consumer_start, - label="OpenCode review target job", - ) - download_index = unique_index( - lines, - " - name: Download current-attempt materialized pull request merge tree\n", - start=consumer_start, - end=review_start, - label="coverage source download step", - ) - identity_step = [ - " - name: Verify coverage source identity for current workflow attempt\n", - " id: coverage_source_identity\n", - " continue-on-error: true\n", - " env:\n", - " COVERAGE_SOURCE_ARTIFACT_ID: " - + action_expression("needs.coverage-source-tree.outputs.coverage_source_artifact_id") - + "\n", - " COVERAGE_SOURCE_RUN_ATTEMPT: " - + action_expression("needs.coverage-source-tree.outputs.coverage_source_run_attempt") - + "\n", - " CURRENT_RUN_ATTEMPT: " + action_expression("github.run_attempt") + "\n", - " shell: bash --noprofile --norc -e -o pipefail {0}\n", - " run: |\n", - " if [ -z \"$COVERAGE_SOURCE_RUN_ATTEMPT\" ] || [ \"$COVERAGE_SOURCE_RUN_ATTEMPT\" != \"$CURRENT_RUN_ATTEMPT\" ]; then\n", - " echo \"::error::Coverage source evidence was not produced in current workflow run attempt ${CURRENT_RUN_ATTEMPT}; producer attempt was ${COVERAGE_SOURCE_RUN_ATTEMPT:-missing}.\"\n", - " echo \"::error::A failed-jobs-only rerun cannot reuse prior-attempt source evidence; use a full rerun or a fresh repository dispatch.\"\n", - " exit 1\n", - " fi\n", - " if ! [[ \"$COVERAGE_SOURCE_ARTIFACT_ID\" =~ ^[1-9][0-9]*$ ]]; then\n", - " echo \"::error::Coverage source artifact ID is missing or malformed for workflow run attempt ${CURRENT_RUN_ATTEMPT}.\"\n", - " echo \"::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree publishes a current immutable artifact ID.\"\n", - " exit 1\n", - " fi\n", - " printf 'artifact_id=%s\\n' \"$COVERAGE_SOURCE_ARTIFACT_ID\" >>\"$GITHUB_OUTPUT\"\n", - "\n", - ] - if " id: coverage_source_identity\n" in lines[consumer_start:review_start]: - raise SystemExit("coverage identity step unexpectedly already present") - lines[download_index:download_index] = identity_step - - consumer_start = unique_index(lines, " coverage-evidence:\n", label="coverage evidence job after identity") - review_start = unique_index(lines, " opencode-review-target:\n", start=consumer_start, label="review job after identity") - download_index = unique_index( - lines, - " - name: Download current-attempt materialized pull request merge tree\n", - start=consumer_start, - end=review_start, - label="download step after identity", - ) - lines.insert( - download_index + 1, - " if: " + action_expression("steps.coverage_source_identity.outcome == 'success'") + "\n", - ) - direct_artifact_line = ( - " artifact-ids: " - + action_expression("needs.coverage-source-tree.outputs.coverage_source_artifact_id") - + "\n" - ) - direct_index = unique_index( - lines, - direct_artifact_line, - start=download_index, - end=review_start + len(identity_step) + 1, - label="direct artifact input", - ) - lines[direct_index] = ( - " artifact-ids: " - + action_expression("steps.coverage_source_identity.outputs.artifact_id") - + "\n" - ) - - report_index = unique_index( - lines, - " - name: Report missing current-attempt coverage source\n", - start=consumer_start, - label="missing source report", - ) - old_if = " if: steps.coverage_source_download.outcome != 'success'\n" - if lines[report_index + 1] != old_if: - raise SystemExit('missing-source report condition anchor changed') - lines[report_index + 1] = ( - " if: steps.coverage_source_identity.outcome != 'success' || " - "steps.coverage_source_download.outcome != 'success'\n" - ) - workflow_path.write_text("".join(lines), encoding='utf-8') - - doctoring_path = Path('docs/doctoring/opencode-coverage-artifact-reruns.md') - doctoring = doctoring_path.read_text(encoding='utf-8') - decision_anchor = "The source artifact retains the existing one-day retention period. " - decision_insert = ( - "The producer also records the literal workflow attempt in a step output. Before " - "download, the consumer compares that producer-attested value with its own current " - "`github.run_attempt` and validates that the producer's immutable artifact ID is a " - "nonzero decimal identifier. Artifact immutability proves which upload is selected; " - "the separate attempt marker proves when the producer actually executed.\n\n" - + decision_anchor - ) - if doctoring.count(decision_anchor) != 1: - raise SystemExit('doctoring decision anchor changed') - doctoring = doctoring.replace(decision_anchor, decision_insert, 1) - - bullet_anchor = ( - "- The upload step exports the immutable `artifact-id`; the consumer downloads " - "with `artifact-ids` rather than `name`.\n" - ) - bullet_insert = ( - "- The upload step exports the immutable `artifact-id`; the consumer first validates " - "that the value is a nonzero decimal identifier and passes only that validated step " - "output to `download-artifact`.\n" - "- The producer exports its step-recorded run attempt; the consumer rejects an empty " - "or mismatched producer attempt before artifact download, so selective reruns cannot " - "reuse prior-attempt source evidence while it is still retained.\n" - ) - if doctoring.count(bullet_anchor) != 1: - raise SystemExit('doctoring contract bullet anchor changed') - doctoring = doctoring.replace(bullet_anchor, bullet_insert, 1) - - table_old = ( - "| Failed-jobs-only rerun while producer is omitted | No current-attempt producer " - "output exists | Fails closed with recovery guidance | Expected failure |" - ) - table_new = ( - "| Failed-jobs-only rerun while producer is omitted | Producer attempt marker or " - "artifact ID is absent or belongs to the earlier attempt | Rejects identity before " - "artifact download | Expected failure |" - ) - if doctoring.count(table_old) != 1: - raise SystemExit('doctoring rerun table anchor changed') - doctoring = doctoring.replace(table_old, table_new, 1) - - rationale_anchor = ( - "The producer's exact `artifact-id` closes that ambiguity. Attempt-qualified naming " - "remains useful for diagnostics, while ID-based selection is the authoritative binding.\n" - ) - rationale_new = ( - "The producer's exact `artifact-id` closes the upload-selection ambiguity, while the " - "producer step's literal attempt output closes the execution-attempt ambiguity. The " - "consumer validates both values before download. Attempt-qualified naming remains " - "useful for diagnostics; validated exact-ID selection and producer-attempt equality " - "are both required.\n" - ) - if doctoring.count(rationale_anchor) != 1: - raise SystemExit('doctoring rationale anchor changed') - doctoring = doctoring.replace(rationale_anchor, rationale_new, 1) - - verification_old = ( - "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" - "2. exact-ID download by the consumer;\n" - "3. actionable failure for a missing current-attempt artifact;\n" - "4. one-day retention; and\n" - "5. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" - ) - verification_new = ( - "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" - "2. producer-attested workflow-attempt output and pre-download equality;\n" - "3. nonempty positive-decimal artifact-ID validation before exact-ID download;\n" - "4. actionable failure for missing, malformed, or prior-attempt evidence;\n" - "5. one-day retention; and\n" - "6. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" - ) - if doctoring.count(verification_old) != 1: - raise SystemExit('doctoring verification anchor changed') - doctoring_path.write_text(doctoring.replace(verification_old, verification_new, 1), encoding='utf-8') - - changelog_path = Path('CHANGELOG.md') - changelog = changelog_path.read_text(encoding='utf-8') - old_entry = ( - "- Bound OpenCode coverage source artifacts to one workflow attempt and immutable " - "artifact ID, retained one-day source evidence, and made failed-jobs-only reruns " - "fail closed with full-rerun or fresh-dispatch guidance instead of searching for " - "expired or prior-attempt artifacts.\n" - ) - new_entry = ( - "- Bound OpenCode coverage source artifacts to a validated immutable artifact ID and " - "producer-attested workflow-attempt marker, retained one-day source evidence, and made " - "failed-jobs-only reruns fail closed before download when identity is missing, malformed, " - "or from a prior attempt, with full-rerun or fresh-dispatch guidance.\n" - ) - if changelog.count(old_entry) != 1: - raise SystemExit('CHANGELOG attempt-artifact entry anchor changed') - changelog_path.write_text(changelog.replace(old_entry, new_entry, 1), encoding='utf-8') - PY - - rm .github/workflows/opencode-coverage-artifact-rerun-repair.yml - git diff --check - - - name: Verify focused and complete GREEN evidence - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py - python -m coverage erase - python -m coverage run -m pytest tests -q - python -m coverage report --show-missing --fail-under=100 - python -m interrogate . - python -m compileall -q scripts tests - git diff --check - expected="$(printf '%s\n' \ - '.github/workflows/opencode-coverage-artifact-rerun-repair.yml' \ - '.github/workflows/opencode-review-dispatch.yml' \ - 'CHANGELOG.md' \ - 'docs/doctoring/opencode-coverage-artifact-reruns.md' | sort)" - actual="$(git diff --name-only HEAD | sort)" - test "$actual" = "$expected" - - - name: Exchange OpenCode app token for exact branch publication - id: target_app_token - env: - OIDC_AUDIENCE: opencode-github-action - OPENCODE_API_BASE_URL: https://api.opencode.ai - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - test -n "${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-}" - test -n "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" - request_url="$ACTIONS_ID_TOKEN_REQUEST_URL" - separator='&' - case "$request_url" in *\?*) ;; *) separator='?' ;; esac - oidc_response="$(curl -fsS -H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" "${request_url}${separator}audience=${OIDC_AUDIENCE}")" - oidc_token="$(jq -r '.value // empty' <<<"$oidc_response")" - test -n "$oidc_token" - token_response="$(curl -fsS -X POST -H "Authorization: Bearer ${oidc_token}" "${OPENCODE_API_BASE_URL}/exchange_github_app_token")" - app_token="$(jq -r '.token // empty' <<<"$token_response")" - test -n "$app_token" - echo "::add-mask::$app_token" - echo "token=$app_token" >>"$GITHUB_OUTPUT" - - - name: Refuse concurrent branch writers and publish verified repair - env: - PUSH_TOKEN: ${{ steps.target_app_token.outputs.token }} - TARGET_BRANCH: fix/opencode-attempt-scoped-coverage-artifact - EXPECTED_TRIGGER_HEAD: ${{ github.event.pull_request.head.sha }} - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - test -n "$PUSH_TOKEN" - echo "::add-mask::$PUSH_TOKEN" - live_head="$(curl -fsS \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${PUSH_TOKEN}" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - https://api.github.com/repos/ContextualWisdomLab/.github/pulls/812 | jq -r '.head.sha // empty')" - test "$live_head" = "$EXPECTED_TRIGGER_HEAD" - git config user.name "opencode-agent[bot]" - git config user.email "opencode-agent[bot]@users.noreply.github.com" - git add -A - expected="$(printf '%s\n' \ - '.github/workflows/opencode-coverage-artifact-rerun-repair.yml' \ - '.github/workflows/opencode-review-dispatch.yml' \ - 'CHANGELOG.md' \ - 'docs/doctoring/opencode-coverage-artifact-reruns.md' | sort)" - staged="$(git diff --cached --name-only | sort)" - test "$staged" = "$expected" - git commit -m "fix(opencode): attest current coverage source identity" - test -z "$(git status --porcelain --untracked-files=all)" - git remote set-url origin "https://x-access-token:${PUSH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" - git push origin "HEAD:refs/heads/${TARGET_BRANCH}" From df3be69863d65d9b26fb5132d2dfa0db4d603275 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:33:59 +0900 Subject: [PATCH 29/56] fix(opencode): satisfy validated artifact identity contract --- ...pencode-coverage-artifact-rerun-repair.yml | 416 ++++++++++++++++++ 1 file changed, 416 insertions(+) create mode 100644 .github/workflows/opencode-coverage-artifact-rerun-repair.yml diff --git a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml new file mode 100644 index 000000000..a424f9144 --- /dev/null +++ b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml @@ -0,0 +1,416 @@ +name: OpenCode Coverage Artifact Rerun Repair + +on: + pull_request: + branches: [main] + paths: + - ".github/workflows/opencode-coverage-artifact-rerun-repair.yml" + +concurrency: + group: opencode-coverage-artifact-rerun-repair-pr812 + cancel-in-progress: true + +permissions: + contents: read + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + repair-and-publish: + if: >- + github.repository == 'ContextualWisdomLab/.github' + && github.event.pull_request.number == 812 + && github.event.pull_request.head.repo.full_name == 'ContextualWisdomLab/.github' + && github.event.pull_request.head.ref == 'fix/opencode-attempt-scoped-coverage-artifact' + permissions: + contents: read + id-token: write + runs-on: ubuntu-24.04 + timeout-minutes: 35 + steps: + - name: Harden runner + uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 + with: + egress-policy: audit + + - name: Check out exact repair trigger + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 2 + persist-credentials: false + + - name: Refuse stale or widened trigger lineage + env: + EXACT_TRIGGER_HEAD: ${{ github.event.pull_request.head.sha }} + EXACT_BASE_SHA: ${{ github.event.pull_request.base.sha }} + EXPECTED_RED_HEAD: 9a866698b821638f3288e78f8a8e3b437deb05c3 + EXPECTED_BASE_SHA: e6fc91416c4fb13febd07b985c6e9c74fe888306 + REPAIR_WORKFLOW: .github/workflows/opencode-coverage-artifact-rerun-repair.yml + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + test "$EXACT_BASE_SHA" = "$EXPECTED_BASE_SHA" + test "$(git rev-parse HEAD)" = "$EXACT_TRIGGER_HEAD" + test "$(git rev-parse HEAD^)" = "$EXPECTED_RED_HEAD" + changed="$(git diff --name-only "$EXPECTED_RED_HEAD" "$EXACT_TRIGGER_HEAD")" + test "$changed" = "$REPAIR_WORKFLOW" + + - name: Set up Python 3.14 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.14" + cache: pip + cache-dependency-path: requirements-opencode-review-ci-hashes.txt + + - name: Install exact hash-locked quality tooling + run: >- + python -m pip install --disable-pip-version-check --require-hashes + -r requirements-opencode-review-ci-hashes.txt + + - name: Prove current identity contracts are red + shell: bash --noprofile --norc {0} + run: | + set +e + output="$(python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py 2>&1)" + status=$? + set -e + printf '%s\n' "$output" + test "$status" -eq 1 + grep -F "test_coverage_source_artifact_is_attempt_scoped_and_downloaded_by_id" <<<"$output" + grep -F "test_coverage_source_requires_current_producer_attempt" <<<"$output" + + - name: Apply reviewed current-attempt identity repair + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + python3 - <<'PY' + from pathlib import Path + + def action_expression(value: str) -> str: + """Return a literal GitHub Actions expression without pre-evaluation.""" + return "$" + "{{ " + value + " }}" + + def unique_index( + lines: list[str], + needle: str, + *, + start: int = 0, + end: int | None = None, + label: str, + ) -> int: + """Return the sole matching line index inside the requested bounds.""" + stop = len(lines) if end is None else end + matches = [index for index in range(start, stop) if lines[index] == needle] + if len(matches) != 1: + raise SystemExit(f"Expected one {label}, found {len(matches)}") + return matches[0] + + workflow_path = Path('.github/workflows/opencode-review-dispatch.yml') + lines = workflow_path.read_text(encoding='utf-8').splitlines(keepends=True) + producer_start = unique_index(lines, " coverage-source-tree:\n", label="coverage source job") + consumer_start = unique_index(lines, " coverage-evidence:\n", label="coverage evidence job") + + artifact_output = ( + " coverage_source_artifact_id: " + + action_expression("steps.coverage_source_upload.outputs.artifact-id") + + "\n" + ) + output_index = unique_index( + lines, + artifact_output, + start=producer_start, + end=consumer_start, + label="artifact ID job output", + ) + attempt_output = ( + " coverage_source_run_attempt: " + + action_expression("steps.coverage_source_attempt.outputs.run_attempt") + + "\n" + ) + if attempt_output in lines[producer_start:consumer_start]: + raise SystemExit("coverage attempt output unexpectedly already present") + lines.insert(output_index + 1, attempt_output) + + producer_start = unique_index(lines, " coverage-source-tree:\n", label="coverage source job after output") + consumer_start = unique_index(lines, " coverage-evidence:\n", label="coverage evidence job after output") + upload_index = unique_index( + lines, + " - name: Upload materialized pull request merge tree\n", + start=producer_start, + end=consumer_start, + label="coverage source upload step", + ) + attempt_step = [ + " - name: Record coverage source workflow attempt\n", + " id: coverage_source_attempt\n", + " env:\n", + " GITHUB_RUN_ATTEMPT: " + action_expression("github.run_attempt") + "\n", + " shell: bash --noprofile --norc -e -o pipefail {0}\n", + " run: |\n", + " printf 'run_attempt=%s\\n' \"$GITHUB_RUN_ATTEMPT\" >>\"$GITHUB_OUTPUT\"\n", + "\n", + ] + if " id: coverage_source_attempt\n" in lines[producer_start:consumer_start]: + raise SystemExit("coverage attempt step unexpectedly already present") + lines[upload_index:upload_index] = attempt_step + + consumer_start = unique_index(lines, " coverage-evidence:\n", label="coverage evidence job before identity") + review_start = unique_index( + lines, + " opencode-review-target:\n", + start=consumer_start, + label="OpenCode review target job", + ) + download_index = unique_index( + lines, + " - name: Download current-attempt materialized pull request merge tree\n", + start=consumer_start, + end=review_start, + label="coverage source download step", + ) + identity_step = [ + " - name: Verify coverage source identity for current workflow attempt\n", + " id: coverage_source_identity\n", + " continue-on-error: true\n", + " env:\n", + " COVERAGE_SOURCE_ARTIFACT_ID: " + + action_expression("needs.coverage-source-tree.outputs.coverage_source_artifact_id") + + "\n", + " COVERAGE_SOURCE_RUN_ATTEMPT: " + + action_expression("needs.coverage-source-tree.outputs.coverage_source_run_attempt") + + "\n", + " CURRENT_RUN_ATTEMPT: " + action_expression("github.run_attempt") + "\n", + " shell: bash --noprofile --norc -e -o pipefail {0}\n", + " run: |\n", + " if [ -z \"$COVERAGE_SOURCE_RUN_ATTEMPT\" ] || [ \"$COVERAGE_SOURCE_RUN_ATTEMPT\" != \"$CURRENT_RUN_ATTEMPT\" ]; then\n", + " echo \"::error::Coverage source evidence was not produced in current workflow run attempt ${CURRENT_RUN_ATTEMPT}; producer attempt was ${COVERAGE_SOURCE_RUN_ATTEMPT:-missing}.\"\n", + " echo \"::error::A failed-jobs-only rerun cannot reuse prior-attempt source evidence; use a full rerun or a fresh repository dispatch.\"\n", + " exit 1\n", + " fi\n", + " if ! [[ \"$COVERAGE_SOURCE_ARTIFACT_ID\" =~ ^[1-9][0-9]*$ ]]; then\n", + " echo \"::error::Coverage source artifact ID is missing or malformed for workflow run attempt ${CURRENT_RUN_ATTEMPT}.\"\n", + " echo \"::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree publishes a current immutable artifact ID.\"\n", + " exit 1\n", + " fi\n", + " artifact_id=$COVERAGE_SOURCE_ARTIFACT_ID\n", + " printf 'artifact_id=%s\\n' \"$artifact_id\" >>\"$GITHUB_OUTPUT\"\n", + "\n", + ] + if " id: coverage_source_identity\n" in lines[consumer_start:review_start]: + raise SystemExit("coverage identity step unexpectedly already present") + lines[download_index:download_index] = identity_step + + consumer_start = unique_index(lines, " coverage-evidence:\n", label="coverage evidence job after identity") + review_start = unique_index(lines, " opencode-review-target:\n", start=consumer_start, label="review job after identity") + download_index = unique_index( + lines, + " - name: Download current-attempt materialized pull request merge tree\n", + start=consumer_start, + end=review_start, + label="download step after identity", + ) + lines.insert( + download_index + 1, + " if: " + action_expression("steps.coverage_source_identity.outcome == 'success'") + "\n", + ) + direct_artifact_line = ( + " artifact-ids: " + + action_expression("needs.coverage-source-tree.outputs.coverage_source_artifact_id") + + "\n" + ) + direct_index = unique_index( + lines, + direct_artifact_line, + start=download_index, + end=review_start + len(identity_step) + 1, + label="direct artifact input", + ) + lines[direct_index] = ( + " artifact-ids: " + + action_expression("steps.coverage_source_identity.outputs.artifact_id") + + "\n" + ) + + report_index = unique_index( + lines, + " - name: Report missing current-attempt coverage source\n", + start=consumer_start, + label="missing source report", + ) + old_if = " if: steps.coverage_source_download.outcome != 'success'\n" + if lines[report_index + 1] != old_if: + raise SystemExit('missing-source report condition anchor changed') + lines[report_index + 1] = ( + " if: steps.coverage_source_identity.outcome != 'success' || " + "steps.coverage_source_download.outcome != 'success'\n" + ) + workflow_path.write_text("".join(lines), encoding='utf-8') + + doctoring_path = Path('docs/doctoring/opencode-coverage-artifact-reruns.md') + doctoring = doctoring_path.read_text(encoding='utf-8') + decision_anchor = "The source artifact retains the existing one-day retention period. " + decision_insert = ( + "The producer also records the literal workflow attempt in a step output. Before " + "download, the consumer compares that producer-attested value with its own current " + "`github.run_attempt` and validates that the producer's immutable artifact ID is a " + "nonzero decimal identifier. Artifact immutability proves which upload is selected; " + "the separate attempt marker proves when the producer actually executed.\n\n" + + decision_anchor + ) + if doctoring.count(decision_anchor) != 1: + raise SystemExit('doctoring decision anchor changed') + doctoring = doctoring.replace(decision_anchor, decision_insert, 1) + + bullet_anchor = ( + "- The upload step exports the immutable `artifact-id`; the consumer downloads " + "with `artifact-ids` rather than `name`.\n" + ) + bullet_insert = ( + "- The upload step exports the immutable `artifact-id`; the consumer first validates " + "that the value is a nonzero decimal identifier and passes only that validated step " + "output to `download-artifact`.\n" + "- The producer exports its step-recorded run attempt; the consumer rejects an empty " + "or mismatched producer attempt before artifact download, so selective reruns cannot " + "reuse prior-attempt source evidence while it is still retained.\n" + ) + if doctoring.count(bullet_anchor) != 1: + raise SystemExit('doctoring contract bullet anchor changed') + doctoring = doctoring.replace(bullet_anchor, bullet_insert, 1) + + table_old = ( + "| Failed-jobs-only rerun while producer is omitted | No current-attempt producer " + "output exists | Fails closed with recovery guidance | Expected failure |" + ) + table_new = ( + "| Failed-jobs-only rerun while producer is omitted | Producer attempt marker or " + "artifact ID is absent or belongs to the earlier attempt | Rejects identity before " + "artifact download | Expected failure |" + ) + if doctoring.count(table_old) != 1: + raise SystemExit('doctoring rerun table anchor changed') + doctoring = doctoring.replace(table_old, table_new, 1) + + rationale_anchor = ( + "The producer's exact `artifact-id` closes that ambiguity. Attempt-qualified naming " + "remains useful for diagnostics, while ID-based selection is the authoritative binding.\n" + ) + rationale_new = ( + "The producer's exact `artifact-id` closes the upload-selection ambiguity, while the " + "producer step's literal attempt output closes the execution-attempt ambiguity. The " + "consumer validates both values before download. Attempt-qualified naming remains " + "useful for diagnostics; validated exact-ID selection and producer-attempt equality " + "are both required.\n" + ) + if doctoring.count(rationale_anchor) != 1: + raise SystemExit('doctoring rationale anchor changed') + doctoring = doctoring.replace(rationale_anchor, rationale_new, 1) + + verification_old = ( + "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" + "2. exact-ID download by the consumer;\n" + "3. actionable failure for a missing current-attempt artifact;\n" + "4. one-day retention; and\n" + "5. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" + ) + verification_new = ( + "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" + "2. producer-attested workflow-attempt output and pre-download equality;\n" + "3. nonempty positive-decimal artifact-ID validation before exact-ID download;\n" + "4. actionable failure for missing, malformed, or prior-attempt evidence;\n" + "5. one-day retention; and\n" + "6. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" + ) + if doctoring.count(verification_old) != 1: + raise SystemExit('doctoring verification anchor changed') + doctoring_path.write_text(doctoring.replace(verification_old, verification_new, 1), encoding='utf-8') + + changelog_path = Path('CHANGELOG.md') + changelog = changelog_path.read_text(encoding='utf-8') + old_entry = ( + "- Bound OpenCode coverage source artifacts to one workflow attempt and immutable " + "artifact ID, retained one-day source evidence, and made failed-jobs-only reruns " + "fail closed with full-rerun or fresh-dispatch guidance instead of searching for " + "expired or prior-attempt artifacts.\n" + ) + new_entry = ( + "- Bound OpenCode coverage source artifacts to a validated immutable artifact ID and " + "producer-attested workflow-attempt marker, retained one-day source evidence, and made " + "failed-jobs-only reruns fail closed before download when identity is missing, malformed, " + "or from a prior attempt, with full-rerun or fresh-dispatch guidance.\n" + ) + if changelog.count(old_entry) != 1: + raise SystemExit('CHANGELOG attempt-artifact entry anchor changed') + changelog_path.write_text(changelog.replace(old_entry, new_entry, 1), encoding='utf-8') + PY + + rm .github/workflows/opencode-coverage-artifact-rerun-repair.yml + git diff --check + + - name: Verify focused and complete GREEN evidence + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py + python -m coverage erase + python -m coverage run -m pytest tests -q + python -m coverage report --show-missing --fail-under=100 + python -m interrogate . + python -m compileall -q scripts tests + git diff --check + expected="$(printf '%s\n' \ + '.github/workflows/opencode-coverage-artifact-rerun-repair.yml' \ + '.github/workflows/opencode-review-dispatch.yml' \ + 'CHANGELOG.md' \ + 'docs/doctoring/opencode-coverage-artifact-reruns.md' | sort)" + actual="$(git diff --name-only HEAD | sort)" + test "$actual" = "$expected" + + - name: Exchange OpenCode app token for exact branch publication + id: target_app_token + env: + OIDC_AUDIENCE: opencode-github-action + OPENCODE_API_BASE_URL: https://api.opencode.ai + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + test -n "${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-}" + test -n "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" + request_url="$ACTIONS_ID_TOKEN_REQUEST_URL" + separator='&' + case "$request_url" in *\?*) ;; *) separator='?' ;; esac + oidc_response="$(curl -fsS -H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" "${request_url}${separator}audience=${OIDC_AUDIENCE}")" + oidc_token="$(jq -r '.value // empty' <<<"$oidc_response")" + test -n "$oidc_token" + token_response="$(curl -fsS -X POST -H "Authorization: Bearer ${oidc_token}" "${OPENCODE_API_BASE_URL}/exchange_github_app_token")" + app_token="$(jq -r '.token // empty' <<<"$token_response")" + test -n "$app_token" + echo "::add-mask::$app_token" + echo "token=$app_token" >>"$GITHUB_OUTPUT" + + - name: Refuse concurrent branch writers and publish verified repair + env: + PUSH_TOKEN: ${{ steps.target_app_token.outputs.token }} + TARGET_BRANCH: fix/opencode-attempt-scoped-coverage-artifact + EXPECTED_TRIGGER_HEAD: ${{ github.event.pull_request.head.sha }} + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + test -n "$PUSH_TOKEN" + echo "::add-mask::$PUSH_TOKEN" + live_head="$(curl -fsS \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${PUSH_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/ContextualWisdomLab/.github/pulls/812 | jq -r '.head.sha // empty')" + test "$live_head" = "$EXPECTED_TRIGGER_HEAD" + git config user.name "opencode-agent[bot]" + git config user.email "opencode-agent[bot]@users.noreply.github.com" + git add -A + expected="$(printf '%s\n' \ + '.github/workflows/opencode-coverage-artifact-rerun-repair.yml' \ + '.github/workflows/opencode-review-dispatch.yml' \ + 'CHANGELOG.md' \ + 'docs/doctoring/opencode-coverage-artifact-reruns.md' | sort)" + staged="$(git diff --cached --name-only | sort)" + test "$staged" = "$expected" + git commit -m "fix(opencode): attest current coverage source identity" + test -z "$(git status --porcelain --untracked-files=all)" + git remote set-url origin "https://x-access-token:${PUSH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" + git push origin "HEAD:refs/heads/${TARGET_BRANCH}" From 65f846538e5d5a404729233e07d381ac271f718d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:35:01 +0900 Subject: [PATCH 30/56] chore(opencode): remove branch-writing artifact repair workflow --- ...pencode-coverage-artifact-rerun-repair.yml | 416 ------------------ 1 file changed, 416 deletions(-) delete mode 100644 .github/workflows/opencode-coverage-artifact-rerun-repair.yml diff --git a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml b/.github/workflows/opencode-coverage-artifact-rerun-repair.yml deleted file mode 100644 index a424f9144..000000000 --- a/.github/workflows/opencode-coverage-artifact-rerun-repair.yml +++ /dev/null @@ -1,416 +0,0 @@ -name: OpenCode Coverage Artifact Rerun Repair - -on: - pull_request: - branches: [main] - paths: - - ".github/workflows/opencode-coverage-artifact-rerun-repair.yml" - -concurrency: - group: opencode-coverage-artifact-rerun-repair-pr812 - cancel-in-progress: true - -permissions: - contents: read - -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - -jobs: - repair-and-publish: - if: >- - github.repository == 'ContextualWisdomLab/.github' - && github.event.pull_request.number == 812 - && github.event.pull_request.head.repo.full_name == 'ContextualWisdomLab/.github' - && github.event.pull_request.head.ref == 'fix/opencode-attempt-scoped-coverage-artifact' - permissions: - contents: read - id-token: write - runs-on: ubuntu-24.04 - timeout-minutes: 35 - steps: - - name: Harden runner - uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 - with: - egress-policy: audit - - - name: Check out exact repair trigger - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 2 - persist-credentials: false - - - name: Refuse stale or widened trigger lineage - env: - EXACT_TRIGGER_HEAD: ${{ github.event.pull_request.head.sha }} - EXACT_BASE_SHA: ${{ github.event.pull_request.base.sha }} - EXPECTED_RED_HEAD: 9a866698b821638f3288e78f8a8e3b437deb05c3 - EXPECTED_BASE_SHA: e6fc91416c4fb13febd07b985c6e9c74fe888306 - REPAIR_WORKFLOW: .github/workflows/opencode-coverage-artifact-rerun-repair.yml - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - test "$EXACT_BASE_SHA" = "$EXPECTED_BASE_SHA" - test "$(git rev-parse HEAD)" = "$EXACT_TRIGGER_HEAD" - test "$(git rev-parse HEAD^)" = "$EXPECTED_RED_HEAD" - changed="$(git diff --name-only "$EXPECTED_RED_HEAD" "$EXACT_TRIGGER_HEAD")" - test "$changed" = "$REPAIR_WORKFLOW" - - - name: Set up Python 3.14 - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 - with: - python-version: "3.14" - cache: pip - cache-dependency-path: requirements-opencode-review-ci-hashes.txt - - - name: Install exact hash-locked quality tooling - run: >- - python -m pip install --disable-pip-version-check --require-hashes - -r requirements-opencode-review-ci-hashes.txt - - - name: Prove current identity contracts are red - shell: bash --noprofile --norc {0} - run: | - set +e - output="$(python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py 2>&1)" - status=$? - set -e - printf '%s\n' "$output" - test "$status" -eq 1 - grep -F "test_coverage_source_artifact_is_attempt_scoped_and_downloaded_by_id" <<<"$output" - grep -F "test_coverage_source_requires_current_producer_attempt" <<<"$output" - - - name: Apply reviewed current-attempt identity repair - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - python3 - <<'PY' - from pathlib import Path - - def action_expression(value: str) -> str: - """Return a literal GitHub Actions expression without pre-evaluation.""" - return "$" + "{{ " + value + " }}" - - def unique_index( - lines: list[str], - needle: str, - *, - start: int = 0, - end: int | None = None, - label: str, - ) -> int: - """Return the sole matching line index inside the requested bounds.""" - stop = len(lines) if end is None else end - matches = [index for index in range(start, stop) if lines[index] == needle] - if len(matches) != 1: - raise SystemExit(f"Expected one {label}, found {len(matches)}") - return matches[0] - - workflow_path = Path('.github/workflows/opencode-review-dispatch.yml') - lines = workflow_path.read_text(encoding='utf-8').splitlines(keepends=True) - producer_start = unique_index(lines, " coverage-source-tree:\n", label="coverage source job") - consumer_start = unique_index(lines, " coverage-evidence:\n", label="coverage evidence job") - - artifact_output = ( - " coverage_source_artifact_id: " - + action_expression("steps.coverage_source_upload.outputs.artifact-id") - + "\n" - ) - output_index = unique_index( - lines, - artifact_output, - start=producer_start, - end=consumer_start, - label="artifact ID job output", - ) - attempt_output = ( - " coverage_source_run_attempt: " - + action_expression("steps.coverage_source_attempt.outputs.run_attempt") - + "\n" - ) - if attempt_output in lines[producer_start:consumer_start]: - raise SystemExit("coverage attempt output unexpectedly already present") - lines.insert(output_index + 1, attempt_output) - - producer_start = unique_index(lines, " coverage-source-tree:\n", label="coverage source job after output") - consumer_start = unique_index(lines, " coverage-evidence:\n", label="coverage evidence job after output") - upload_index = unique_index( - lines, - " - name: Upload materialized pull request merge tree\n", - start=producer_start, - end=consumer_start, - label="coverage source upload step", - ) - attempt_step = [ - " - name: Record coverage source workflow attempt\n", - " id: coverage_source_attempt\n", - " env:\n", - " GITHUB_RUN_ATTEMPT: " + action_expression("github.run_attempt") + "\n", - " shell: bash --noprofile --norc -e -o pipefail {0}\n", - " run: |\n", - " printf 'run_attempt=%s\\n' \"$GITHUB_RUN_ATTEMPT\" >>\"$GITHUB_OUTPUT\"\n", - "\n", - ] - if " id: coverage_source_attempt\n" in lines[producer_start:consumer_start]: - raise SystemExit("coverage attempt step unexpectedly already present") - lines[upload_index:upload_index] = attempt_step - - consumer_start = unique_index(lines, " coverage-evidence:\n", label="coverage evidence job before identity") - review_start = unique_index( - lines, - " opencode-review-target:\n", - start=consumer_start, - label="OpenCode review target job", - ) - download_index = unique_index( - lines, - " - name: Download current-attempt materialized pull request merge tree\n", - start=consumer_start, - end=review_start, - label="coverage source download step", - ) - identity_step = [ - " - name: Verify coverage source identity for current workflow attempt\n", - " id: coverage_source_identity\n", - " continue-on-error: true\n", - " env:\n", - " COVERAGE_SOURCE_ARTIFACT_ID: " - + action_expression("needs.coverage-source-tree.outputs.coverage_source_artifact_id") - + "\n", - " COVERAGE_SOURCE_RUN_ATTEMPT: " - + action_expression("needs.coverage-source-tree.outputs.coverage_source_run_attempt") - + "\n", - " CURRENT_RUN_ATTEMPT: " + action_expression("github.run_attempt") + "\n", - " shell: bash --noprofile --norc -e -o pipefail {0}\n", - " run: |\n", - " if [ -z \"$COVERAGE_SOURCE_RUN_ATTEMPT\" ] || [ \"$COVERAGE_SOURCE_RUN_ATTEMPT\" != \"$CURRENT_RUN_ATTEMPT\" ]; then\n", - " echo \"::error::Coverage source evidence was not produced in current workflow run attempt ${CURRENT_RUN_ATTEMPT}; producer attempt was ${COVERAGE_SOURCE_RUN_ATTEMPT:-missing}.\"\n", - " echo \"::error::A failed-jobs-only rerun cannot reuse prior-attempt source evidence; use a full rerun or a fresh repository dispatch.\"\n", - " exit 1\n", - " fi\n", - " if ! [[ \"$COVERAGE_SOURCE_ARTIFACT_ID\" =~ ^[1-9][0-9]*$ ]]; then\n", - " echo \"::error::Coverage source artifact ID is missing or malformed for workflow run attempt ${CURRENT_RUN_ATTEMPT}.\"\n", - " echo \"::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree publishes a current immutable artifact ID.\"\n", - " exit 1\n", - " fi\n", - " artifact_id=$COVERAGE_SOURCE_ARTIFACT_ID\n", - " printf 'artifact_id=%s\\n' \"$artifact_id\" >>\"$GITHUB_OUTPUT\"\n", - "\n", - ] - if " id: coverage_source_identity\n" in lines[consumer_start:review_start]: - raise SystemExit("coverage identity step unexpectedly already present") - lines[download_index:download_index] = identity_step - - consumer_start = unique_index(lines, " coverage-evidence:\n", label="coverage evidence job after identity") - review_start = unique_index(lines, " opencode-review-target:\n", start=consumer_start, label="review job after identity") - download_index = unique_index( - lines, - " - name: Download current-attempt materialized pull request merge tree\n", - start=consumer_start, - end=review_start, - label="download step after identity", - ) - lines.insert( - download_index + 1, - " if: " + action_expression("steps.coverage_source_identity.outcome == 'success'") + "\n", - ) - direct_artifact_line = ( - " artifact-ids: " - + action_expression("needs.coverage-source-tree.outputs.coverage_source_artifact_id") - + "\n" - ) - direct_index = unique_index( - lines, - direct_artifact_line, - start=download_index, - end=review_start + len(identity_step) + 1, - label="direct artifact input", - ) - lines[direct_index] = ( - " artifact-ids: " - + action_expression("steps.coverage_source_identity.outputs.artifact_id") - + "\n" - ) - - report_index = unique_index( - lines, - " - name: Report missing current-attempt coverage source\n", - start=consumer_start, - label="missing source report", - ) - old_if = " if: steps.coverage_source_download.outcome != 'success'\n" - if lines[report_index + 1] != old_if: - raise SystemExit('missing-source report condition anchor changed') - lines[report_index + 1] = ( - " if: steps.coverage_source_identity.outcome != 'success' || " - "steps.coverage_source_download.outcome != 'success'\n" - ) - workflow_path.write_text("".join(lines), encoding='utf-8') - - doctoring_path = Path('docs/doctoring/opencode-coverage-artifact-reruns.md') - doctoring = doctoring_path.read_text(encoding='utf-8') - decision_anchor = "The source artifact retains the existing one-day retention period. " - decision_insert = ( - "The producer also records the literal workflow attempt in a step output. Before " - "download, the consumer compares that producer-attested value with its own current " - "`github.run_attempt` and validates that the producer's immutable artifact ID is a " - "nonzero decimal identifier. Artifact immutability proves which upload is selected; " - "the separate attempt marker proves when the producer actually executed.\n\n" - + decision_anchor - ) - if doctoring.count(decision_anchor) != 1: - raise SystemExit('doctoring decision anchor changed') - doctoring = doctoring.replace(decision_anchor, decision_insert, 1) - - bullet_anchor = ( - "- The upload step exports the immutable `artifact-id`; the consumer downloads " - "with `artifact-ids` rather than `name`.\n" - ) - bullet_insert = ( - "- The upload step exports the immutable `artifact-id`; the consumer first validates " - "that the value is a nonzero decimal identifier and passes only that validated step " - "output to `download-artifact`.\n" - "- The producer exports its step-recorded run attempt; the consumer rejects an empty " - "or mismatched producer attempt before artifact download, so selective reruns cannot " - "reuse prior-attempt source evidence while it is still retained.\n" - ) - if doctoring.count(bullet_anchor) != 1: - raise SystemExit('doctoring contract bullet anchor changed') - doctoring = doctoring.replace(bullet_anchor, bullet_insert, 1) - - table_old = ( - "| Failed-jobs-only rerun while producer is omitted | No current-attempt producer " - "output exists | Fails closed with recovery guidance | Expected failure |" - ) - table_new = ( - "| Failed-jobs-only rerun while producer is omitted | Producer attempt marker or " - "artifact ID is absent or belongs to the earlier attempt | Rejects identity before " - "artifact download | Expected failure |" - ) - if doctoring.count(table_old) != 1: - raise SystemExit('doctoring rerun table anchor changed') - doctoring = doctoring.replace(table_old, table_new, 1) - - rationale_anchor = ( - "The producer's exact `artifact-id` closes that ambiguity. Attempt-qualified naming " - "remains useful for diagnostics, while ID-based selection is the authoritative binding.\n" - ) - rationale_new = ( - "The producer's exact `artifact-id` closes the upload-selection ambiguity, while the " - "producer step's literal attempt output closes the execution-attempt ambiguity. The " - "consumer validates both values before download. Attempt-qualified naming remains " - "useful for diagnostics; validated exact-ID selection and producer-attempt equality " - "are both required.\n" - ) - if doctoring.count(rationale_anchor) != 1: - raise SystemExit('doctoring rationale anchor changed') - doctoring = doctoring.replace(rationale_anchor, rationale_new, 1) - - verification_old = ( - "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" - "2. exact-ID download by the consumer;\n" - "3. actionable failure for a missing current-attempt artifact;\n" - "4. one-day retention; and\n" - "5. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" - ) - verification_new = ( - "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" - "2. producer-attested workflow-attempt output and pre-download equality;\n" - "3. nonempty positive-decimal artifact-ID validation before exact-ID download;\n" - "4. actionable failure for missing, malformed, or prior-attempt evidence;\n" - "5. one-day retention; and\n" - "6. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" - ) - if doctoring.count(verification_old) != 1: - raise SystemExit('doctoring verification anchor changed') - doctoring_path.write_text(doctoring.replace(verification_old, verification_new, 1), encoding='utf-8') - - changelog_path = Path('CHANGELOG.md') - changelog = changelog_path.read_text(encoding='utf-8') - old_entry = ( - "- Bound OpenCode coverage source artifacts to one workflow attempt and immutable " - "artifact ID, retained one-day source evidence, and made failed-jobs-only reruns " - "fail closed with full-rerun or fresh-dispatch guidance instead of searching for " - "expired or prior-attempt artifacts.\n" - ) - new_entry = ( - "- Bound OpenCode coverage source artifacts to a validated immutable artifact ID and " - "producer-attested workflow-attempt marker, retained one-day source evidence, and made " - "failed-jobs-only reruns fail closed before download when identity is missing, malformed, " - "or from a prior attempt, with full-rerun or fresh-dispatch guidance.\n" - ) - if changelog.count(old_entry) != 1: - raise SystemExit('CHANGELOG attempt-artifact entry anchor changed') - changelog_path.write_text(changelog.replace(old_entry, new_entry, 1), encoding='utf-8') - PY - - rm .github/workflows/opencode-coverage-artifact-rerun-repair.yml - git diff --check - - - name: Verify focused and complete GREEN evidence - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py - python -m coverage erase - python -m coverage run -m pytest tests -q - python -m coverage report --show-missing --fail-under=100 - python -m interrogate . - python -m compileall -q scripts tests - git diff --check - expected="$(printf '%s\n' \ - '.github/workflows/opencode-coverage-artifact-rerun-repair.yml' \ - '.github/workflows/opencode-review-dispatch.yml' \ - 'CHANGELOG.md' \ - 'docs/doctoring/opencode-coverage-artifact-reruns.md' | sort)" - actual="$(git diff --name-only HEAD | sort)" - test "$actual" = "$expected" - - - name: Exchange OpenCode app token for exact branch publication - id: target_app_token - env: - OIDC_AUDIENCE: opencode-github-action - OPENCODE_API_BASE_URL: https://api.opencode.ai - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - test -n "${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-}" - test -n "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" - request_url="$ACTIONS_ID_TOKEN_REQUEST_URL" - separator='&' - case "$request_url" in *\?*) ;; *) separator='?' ;; esac - oidc_response="$(curl -fsS -H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" "${request_url}${separator}audience=${OIDC_AUDIENCE}")" - oidc_token="$(jq -r '.value // empty' <<<"$oidc_response")" - test -n "$oidc_token" - token_response="$(curl -fsS -X POST -H "Authorization: Bearer ${oidc_token}" "${OPENCODE_API_BASE_URL}/exchange_github_app_token")" - app_token="$(jq -r '.token // empty' <<<"$token_response")" - test -n "$app_token" - echo "::add-mask::$app_token" - echo "token=$app_token" >>"$GITHUB_OUTPUT" - - - name: Refuse concurrent branch writers and publish verified repair - env: - PUSH_TOKEN: ${{ steps.target_app_token.outputs.token }} - TARGET_BRANCH: fix/opencode-attempt-scoped-coverage-artifact - EXPECTED_TRIGGER_HEAD: ${{ github.event.pull_request.head.sha }} - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - test -n "$PUSH_TOKEN" - echo "::add-mask::$PUSH_TOKEN" - live_head="$(curl -fsS \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${PUSH_TOKEN}" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - https://api.github.com/repos/ContextualWisdomLab/.github/pulls/812 | jq -r '.head.sha // empty')" - test "$live_head" = "$EXPECTED_TRIGGER_HEAD" - git config user.name "opencode-agent[bot]" - git config user.email "opencode-agent[bot]@users.noreply.github.com" - git add -A - expected="$(printf '%s\n' \ - '.github/workflows/opencode-coverage-artifact-rerun-repair.yml' \ - '.github/workflows/opencode-review-dispatch.yml' \ - 'CHANGELOG.md' \ - 'docs/doctoring/opencode-coverage-artifact-reruns.md' | sort)" - staged="$(git diff --cached --name-only | sort)" - test "$staged" = "$expected" - git commit -m "fix(opencode): attest current coverage source identity" - test -z "$(git status --porcelain --untracked-files=all)" - git remote set-url origin "https://x-access-token:${PUSH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" - git push origin "HEAD:refs/heads/${TARGET_BRANCH}" From 61687bb4c4bad512a0a8f878d10d6b499e3272d8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:35:17 +0900 Subject: [PATCH 31/56] chore(opencode): remove artifact patch generator --- ...prepare_opencode_attempt_artifact_patch.py | 349 ------------------ 1 file changed, 349 deletions(-) delete mode 100644 scripts/ci/prepare_opencode_attempt_artifact_patch.py diff --git a/scripts/ci/prepare_opencode_attempt_artifact_patch.py b/scripts/ci/prepare_opencode_attempt_artifact_patch.py deleted file mode 100644 index 2d142ccfb..000000000 --- a/scripts/ci/prepare_opencode_attempt_artifact_patch.py +++ /dev/null @@ -1,349 +0,0 @@ -#!/usr/bin/env python3 -"""Materialize the reviewed current-attempt OpenCode artifact identity repair. - -This helper is temporary branch-local tooling. It patches only the permanent -OpenCode dispatch workflow, authoritative doctoring, and the Unreleased -changelog entry. The publishing workflow removes this file before committing -the verified implementation. -""" - -from __future__ import annotations - -from pathlib import Path - - -WORKFLOW_PATH = Path(".github/workflows/opencode-review-dispatch.yml") -DOCTORING_PATH = Path("docs/doctoring/opencode-coverage-artifact-reruns.md") -CHANGELOG_PATH = Path("CHANGELOG.md") - - -def action_expression(value: str) -> str: - """Return a literal GitHub Actions expression without early evaluation.""" - return "$" + "{{ " + value + " }}" - - -def unique_index( - lines: list[str], - needle: str, - *, - start: int = 0, - end: int | None = None, - label: str, -) -> int: - """Return the only exact line match within a bounded line range.""" - stop = len(lines) if end is None else end - matches = [index for index in range(start, stop) if lines[index] == needle] - if len(matches) != 1: - raise SystemExit(f"Expected exactly one {label}, found {len(matches)}.") - return matches[0] - - -def patch_workflow() -> None: - """Bind exact artifact selection to producer-attested current-run provenance.""" - lines = WORKFLOW_PATH.read_text(encoding="utf-8").splitlines(keepends=True) - producer_start = unique_index( - lines, " coverage-source-tree:\n", label="coverage source job" - ) - consumer_start = unique_index( - lines, " coverage-evidence:\n", label="coverage evidence job" - ) - - artifact_output = ( - " coverage_source_artifact_id: " - + action_expression("steps.coverage_source_upload.outputs.artifact-id") - + "\n" - ) - artifact_output_index = unique_index( - lines, - artifact_output, - start=producer_start, - end=consumer_start, - label="coverage artifact ID job output", - ) - attempt_output = ( - " coverage_source_run_attempt: " - + action_expression("steps.coverage_source_attempt.outputs.run_attempt") - + "\n" - ) - if attempt_output in lines[producer_start:consumer_start]: - raise SystemExit("Producer attempt output unexpectedly already exists.") - lines.insert(artifact_output_index + 1, attempt_output) - - producer_start = unique_index( - lines, " coverage-source-tree:\n", label="coverage source job after output" - ) - consumer_start = unique_index( - lines, - " coverage-evidence:\n", - label="coverage evidence job after output", - ) - upload_step_index = unique_index( - lines, - " - name: Upload materialized pull request merge tree\n", - start=producer_start, - end=consumer_start, - label="coverage source upload step", - ) - if " id: coverage_source_attempt\n" in lines[producer_start:consumer_start]: - raise SystemExit("Producer attempt attestation step unexpectedly already exists.") - attempt_step = [ - " - name: Record coverage source workflow attempt\n", - " id: coverage_source_attempt\n", - " env:\n", - " GITHUB_RUN_ATTEMPT: " - + action_expression("github.run_attempt") - + "\n", - " shell: bash --noprofile --norc -e -o pipefail {0}\n", - " run: |\n", - " if ! [[ \"$GITHUB_RUN_ATTEMPT\" =~ ^[1-9][0-9]*$ ]]; then\n", - " echo \"::error::Coverage producer workflow attempt is not a positive integer.\"\n", - " exit 1\n", - " fi\n", - " printf 'run_attempt=%s\\n' \"$GITHUB_RUN_ATTEMPT\" >>\"$GITHUB_OUTPUT\"\n", - "\n", - ] - lines[upload_step_index:upload_step_index] = attempt_step - - consumer_start = unique_index( - lines, - " coverage-evidence:\n", - label="coverage evidence job before identity guard", - ) - review_start = unique_index( - lines, - " opencode-review-target:\n", - start=consumer_start, - label="OpenCode review target job", - ) - download_step_index = unique_index( - lines, - " - name: Download current-attempt materialized pull request merge tree\n", - start=consumer_start, - end=review_start, - label="coverage source download step", - ) - if " id: coverage_source_identity\n" in lines[consumer_start:review_start]: - raise SystemExit("Coverage source identity step unexpectedly already exists.") - - identity_step = [ - " - name: Verify coverage source identity for current workflow attempt\n", - " id: coverage_source_identity\n", - " continue-on-error: true\n", - " env:\n", - " COVERAGE_SOURCE_ARTIFACT_ID: " - + action_expression( - "needs.coverage-source-tree.outputs.coverage_source_artifact_id" - ) - + "\n", - " COVERAGE_SOURCE_RUN_ATTEMPT: " - + action_expression( - "needs.coverage-source-tree.outputs.coverage_source_run_attempt" - ) - + "\n", - " CURRENT_RUN_ATTEMPT: " - + action_expression("github.run_attempt") - + "\n", - " shell: bash --noprofile --norc -e -o pipefail {0}\n", - " run: |\n", - " if ! [[ \"$COVERAGE_SOURCE_ARTIFACT_ID\" =~ ^[1-9][0-9]*$ ]] || \\\n", - " ! [[ \"$CURRENT_RUN_ATTEMPT\" =~ ^[1-9][0-9]*$ ]] || \\\n", - " [ \"$COVERAGE_SOURCE_RUN_ATTEMPT\" != \"$CURRENT_RUN_ATTEMPT\" ]; then\n", - " echo \"::error::Coverage source identity is invalid for current workflow attempt ${CURRENT_RUN_ATTEMPT:-missing}; producer attempt=${COVERAGE_SOURCE_RUN_ATTEMPT:-missing}, artifact_id=${COVERAGE_SOURCE_ARTIFACT_ID:-missing}.\"\n", - " exit 1\n", - " fi\n", - " printf 'artifact_id=%s\\n' \"$COVERAGE_SOURCE_ARTIFACT_ID\" >>\"$GITHUB_OUTPUT\"\n", - "\n", - ] - lines[download_step_index:download_step_index] = identity_step - - consumer_start = unique_index( - lines, - " coverage-evidence:\n", - label="coverage evidence job before download binding", - ) - review_start = unique_index( - lines, - " opencode-review-target:\n", - start=consumer_start, - label="OpenCode review target job after identity insertion", - ) - download_step_index = unique_index( - lines, - " - name: Download current-attempt materialized pull request merge tree\n", - start=consumer_start, - end=review_start, - label="coverage source download after identity insertion", - ) - if lines[download_step_index + 1] != " id: coverage_source_download\n": - raise SystemExit("Coverage source download ID anchor changed.") - lines.insert( - download_step_index + 1, - " if: steps.coverage_source_identity.outcome == 'success'\n", - ) - - artifact_ids_index = unique_index( - lines, - " artifact-ids: " - + action_expression( - "needs.coverage-source-tree.outputs.coverage_source_artifact_id" - ) - + "\n", - start=download_step_index, - end=review_start, - label="direct producer artifact ID download binding", - ) - lines[artifact_ids_index] = ( - " artifact-ids: " - + action_expression("steps.coverage_source_identity.outputs.artifact_id") - + "\n" - ) - - missing_report_index = unique_index( - lines, - " - name: Report missing current-attempt coverage source\n", - start=download_step_index, - end=review_start, - label="missing coverage source report", - ) - missing_if_index = unique_index( - lines, - " if: steps.coverage_source_download.outcome != 'success'\n", - start=missing_report_index, - end=review_start, - label="missing coverage source condition", - ) - lines[missing_if_index] = ( - " if: steps.coverage_source_identity.outcome == 'success' && " - "steps.coverage_source_download.outcome != 'success'\n" - ) - - identity_report = [ - " - name: Report coverage source identity failure\n", - " if: steps.coverage_source_identity.outcome != 'success'\n", - " env:\n", - " GITHUB_RUN_ATTEMPT: " - + action_expression("github.run_attempt") - + "\n", - " run: |\n", - " set -euo pipefail\n", - " echo \"::error::Coverage source evidence was not produced and identified in current workflow run attempt ${GITHUB_RUN_ATTEMPT}; a failed-jobs-only rerun cannot reuse prior-attempt source evidence.\"\n", - " echo \"::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree runs and uploads exact current-attempt evidence.\"\n", - " exit 1\n", - "\n", - ] - lines[download_step_index:download_step_index] = identity_report - - WORKFLOW_PATH.write_text("".join(lines), encoding="utf-8") - - -def patch_doctoring() -> None: - """Document immutability, attempt provenance, and bounded identifier checks.""" - doctoring = DOCTORING_PATH.read_text(encoding="utf-8") - decision_anchor = "The source artifact retains the existing one-day retention period. " - decision_insert = ( - "The producer records its literal workflow attempt in a step output. Before any " - "download, the credential-free consumer verifies that the artifact ID is a positive " - "integer and that the producer-attested attempt equals the consumer's current " - "`github.run_attempt`. Artifact immutability identifies one upload; the separate " - "attempt attestation proves when its producer executed.\n\n" - + decision_anchor - ) - if doctoring.count(decision_anchor) != 1: - raise SystemExit("Doctoring decision anchor changed.") - doctoring = doctoring.replace(decision_anchor, decision_insert, 1) - - bullet_anchor = ( - "- The upload step exports the immutable `artifact-id`; the consumer downloads " - "with `artifact-ids` rather than `name`.\n" - ) - bullet_insert = bullet_anchor + ( - "- The producer exports its step-recorded run attempt; the consumer validates both " - "the artifact identifier and attempt marker before exposing the identifier to the " - "download action. Empty, malformed, or prior-attempt values fail closed.\n" - ) - if doctoring.count(bullet_anchor) != 1: - raise SystemExit("Doctoring contract bullet anchor changed.") - doctoring = doctoring.replace(bullet_anchor, bullet_insert, 1) - - table_old = ( - "| Failed-jobs-only rerun while producer is omitted | No current-attempt producer " - "output exists | Fails closed with recovery guidance | Expected failure |" - ) - table_new = ( - "| Failed-jobs-only rerun while producer is omitted | Producer attempt marker is " - "missing or belongs to an earlier attempt | Rejects identity before artifact " - "download | Expected failure |" - ) - if doctoring.count(table_old) != 1: - raise SystemExit("Doctoring rerun table anchor changed.") - doctoring = doctoring.replace(table_old, table_new, 1) - - rationale_anchor = ( - "The producer's exact `artifact-id` closes that ambiguity. Attempt-qualified naming " - "remains useful for diagnostics, while ID-based selection is the authoritative " - "binding.\n" - ) - rationale_new = ( - "The producer's exact `artifact-id` closes upload-selection ambiguity, while its " - "step-recorded attempt closes execution-attempt ambiguity. Attempt-qualified names " - "remain diagnostic; a validated positive artifact ID and producer-attempt equality " - "are both required before download.\n" - ) - if doctoring.count(rationale_anchor) != 1: - raise SystemExit("Doctoring rationale anchor changed.") - doctoring = doctoring.replace(rationale_anchor, rationale_new, 1) - - verification_old = ( - "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" - "2. exact-ID download by the consumer;\n" - "3. actionable failure for a missing current-attempt artifact;\n" - "4. one-day retention; and\n" - "5. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" - ) - verification_new = ( - "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" - "2. producer-attested attempt output and pre-download current-attempt equality;\n" - "3. positive-integer artifact ID validation and exact-ID download;\n" - "4. actionable failure for missing, malformed, or prior-attempt evidence;\n" - "5. one-day retention; and\n" - "6. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" - ) - if doctoring.count(verification_old) != 1: - raise SystemExit("Doctoring verification anchor changed.") - DOCTORING_PATH.write_text( - doctoring.replace(verification_old, verification_new, 1), - encoding="utf-8", - ) - - -def patch_changelog() -> None: - """Record the complete identity and provenance gate in Unreleased fixes.""" - changelog = CHANGELOG_PATH.read_text(encoding="utf-8") - old_entry = ( - "- Bound OpenCode coverage source artifacts to one workflow attempt and immutable " - "artifact ID, retained one-day source evidence, and made failed-jobs-only reruns " - "fail closed with full-rerun or fresh-dispatch guidance instead of searching for " - "expired or prior-attempt artifacts.\n" - ) - new_entry = ( - "- Bound OpenCode coverage source evidence to a validated immutable artifact ID and " - "producer-attested workflow attempt, retained one-day source evidence, and made " - "selective reruns fail closed before download on missing, malformed, or prior-attempt " - "identity with full-rerun or fresh-dispatch guidance.\n" - ) - if changelog.count(old_entry) != 1: - raise SystemExit("CHANGELOG attempt-artifact entry anchor changed.") - CHANGELOG_PATH.write_text( - changelog.replace(old_entry, new_entry, 1), encoding="utf-8" - ) - - -def main() -> None: - """Apply the bounded workflow, doctoring, and changelog repair.""" - patch_workflow() - patch_doctoring() - patch_changelog() - - -if __name__ == "__main__": - main() From 00cafaf980fc5c61ab2b56d7be2422b24ffdbaef Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:36:39 +0900 Subject: [PATCH 32/56] chore(opencode): finalize attempt-scoped artifact handoff --- .../pr812-finalize-attempt-artifact.yml | 299 ++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 .github/workflows/pr812-finalize-attempt-artifact.yml diff --git a/.github/workflows/pr812-finalize-attempt-artifact.yml b/.github/workflows/pr812-finalize-attempt-artifact.yml new file mode 100644 index 000000000..f4d65396a --- /dev/null +++ b/.github/workflows/pr812-finalize-attempt-artifact.yml @@ -0,0 +1,299 @@ +name: PR 812 Finalize Attempt Artifact Handoff + +on: + push: + branches: + - fix/opencode-attempt-scoped-coverage-artifact + paths: + - .github/workflows/pr812-finalize-attempt-artifact.yml + +concurrency: + group: pr812-finalize-attempt-artifact + cancel-in-progress: false + +permissions: + contents: write + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + finalize: + if: >- + github.repository == 'ContextualWisdomLab/.github' && + github.ref == 'refs/heads/fix/opencode-attempt-scoped-coverage-artifact' + runs-on: ubuntu-24.04 + timeout-minutes: 35 + steps: + - name: Harden runner + uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 + with: + egress-policy: audit + + - name: Checkout exact trigger head + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + ref: ${{ github.sha }} + fetch-depth: 2 + persist-credentials: true + + - name: Refuse concurrent branch movement + env: + EXPECTED_SHA: ${{ github.sha }} + EXPECTED_BRANCH: fix/opencode-attempt-scoped-coverage-artifact + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + test "$(git rev-parse HEAD)" = "$EXPECTED_SHA" + remote_sha="$(git ls-remote origin "refs/heads/$EXPECTED_BRANCH" | awk '{print $1}')" + test "$remote_sha" = "$EXPECTED_SHA" + + - name: Set up Python 3.14 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.14" + cache: pip + cache-dependency-path: requirements-opencode-review-ci-hashes.txt + + - name: Install exact hash-locked quality tooling + run: >- + python -m pip install --disable-pip-version-check --require-hashes + -r requirements-opencode-review-ci-hashes.txt + + - name: Apply exact attempt and artifact identity contract + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + python3 - <<'PY' + from pathlib import Path + + workflow_path = Path('.github/workflows/opencode-review-dispatch.yml') + workflow = workflow_path.read_text(encoding='utf-8') + + old_outputs = """ outputs: + coverage_source_artifact_id: ${{ steps.coverage_source_upload.outputs.artifact-id }} + """.replace(' ', '') + new_outputs = """ outputs: + coverage_source_artifact_id: ${{ steps.coverage_source_upload.outputs.artifact-id }} + coverage_source_run_attempt: ${{ steps.coverage_source_attempt.outputs.run_attempt }} + """.replace(' ', '') + if workflow.count(old_outputs) != 1: + raise SystemExit('coverage source output anchor changed') + workflow = workflow.replace(old_outputs, new_outputs, 1) + + upload_anchor = """ - name: Upload materialized pull request merge tree + id: coverage_source_upload + """.replace(' ', '') + attempt_step = """ - name: Record coverage source workflow attempt + id: coverage_source_attempt + env: + GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + printf 'run_attempt=%s\\n' "$GITHUB_RUN_ATTEMPT" >>"$GITHUB_OUTPUT" + + - name: Upload materialized pull request merge tree + id: coverage_source_upload + """.replace(' ', '') + if workflow.count(upload_anchor) != 1: + raise SystemExit('coverage upload anchor changed') + workflow = workflow.replace(upload_anchor, attempt_step, 1) + + old_consumer = """ - name: Download current-attempt materialized pull request merge tree + id: coverage_source_download + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + artifact-ids: ${{ needs.coverage-source-tree.outputs.coverage_source_artifact_id }} + path: ${{ runner.temp }}/opencode-coverage-artifact + + - name: Report missing current-attempt coverage source + if: steps.coverage_source_download.outcome != 'success' + env: + GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} + """.replace(' ', '') + new_consumer = """ - name: Verify coverage source identity for current workflow attempt + id: coverage_source_identity + continue-on-error: true + env: + COVERAGE_SOURCE_ARTIFACT_ID: ${{ needs.coverage-source-tree.outputs.coverage_source_artifact_id }} + COVERAGE_SOURCE_RUN_ATTEMPT: ${{ needs.coverage-source-tree.outputs.coverage_source_run_attempt }} + CURRENT_RUN_ATTEMPT: ${{ github.run_attempt }} + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + if [ -z "$COVERAGE_SOURCE_RUN_ATTEMPT" ] || [ "$COVERAGE_SOURCE_RUN_ATTEMPT" != "$CURRENT_RUN_ATTEMPT" ]; then + echo "::error::Coverage source evidence was not produced in current workflow run attempt ${CURRENT_RUN_ATTEMPT}; producer attempt was ${COVERAGE_SOURCE_RUN_ATTEMPT:-missing}." + echo "::error::A failed-jobs-only rerun cannot reuse prior-attempt source evidence; use a full rerun or a fresh repository dispatch." + exit 1 + fi + if ! [[ "$COVERAGE_SOURCE_ARTIFACT_ID" =~ ^[1-9][0-9]*$ ]]; then + echo "::error::Coverage source artifact ID is missing or malformed for workflow run attempt ${CURRENT_RUN_ATTEMPT}." + echo "::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree publishes a current immutable artifact ID." + exit 1 + fi + printf 'artifact_id=%s\\n' "$COVERAGE_SOURCE_ARTIFACT_ID" >>"$GITHUB_OUTPUT" + + - name: Download current-attempt materialized pull request merge tree + if: steps.coverage_source_identity.outcome == 'success' + id: coverage_source_download + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + artifact-ids: ${{ steps.coverage_source_identity.outputs.artifact_id }} + path: ${{ runner.temp }}/opencode-coverage-artifact + + - name: Report missing current-attempt coverage source + if: steps.coverage_source_identity.outcome != 'success' || steps.coverage_source_download.outcome != 'success' + env: + GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} + """.replace(' ', '') + if workflow.count(old_consumer) != 1: + raise SystemExit('coverage consumer anchor changed') + workflow_path.write_text(workflow.replace(old_consumer, new_consumer, 1), encoding='utf-8') + + test_path = Path('tests/test_opencode_coverage_artifact_rerun_contract.py') + test_text = test_path.read_text(encoding='utf-8') + old_assertion = ' assert "artifact_id=$COVERAGE_SOURCE_ARTIFACT_ID" in evidence_job\n' + new_assertion = ( + ' assert (\n' + ' "printf \'artifact_id=%s\\\\n\' \\\"$COVERAGE_SOURCE_ARTIFACT_ID\\\" "\n' + ' ">>\\\"$GITHUB_OUTPUT\\\"" in evidence_job\n' + ' )\n' + ) + if test_text.count(old_assertion) != 1: + raise SystemExit('artifact output assertion anchor changed') + test_path.write_text(test_text.replace(old_assertion, new_assertion, 1), encoding='utf-8') + + doctoring_path = Path('docs/doctoring/opencode-coverage-artifact-reruns.md') + doctoring = doctoring_path.read_text(encoding='utf-8') + decision_anchor = "The source artifact retains the existing one-day retention period. " + decision_insert = ( + "The producer also records the literal workflow attempt in a step output. Before " + "download, the consumer compares that producer-attested value with its own current " + "`github.run_attempt` and validates that the producer's immutable artifact ID is a " + "nonzero decimal identifier. Artifact immutability proves which upload is selected; " + "the separate attempt marker proves when the producer actually executed.\n\n" + + decision_anchor + ) + if doctoring.count(decision_anchor) != 1: + raise SystemExit('doctoring decision anchor changed') + doctoring = doctoring.replace(decision_anchor, decision_insert, 1) + + bullet_anchor = ( + "- The upload step exports the immutable `artifact-id`; the consumer downloads " + "with `artifact-ids` rather than `name`.\n" + ) + bullet_insert = ( + "- The upload step exports the immutable `artifact-id`; the consumer first validates " + "that the value is a nonzero decimal identifier and passes only that validated step " + "output to `download-artifact`.\n" + "- The producer exports its step-recorded run attempt; the consumer rejects an empty " + "or mismatched producer attempt before artifact download, so selective reruns cannot " + "reuse prior-attempt source evidence while it is still retained.\n" + ) + if doctoring.count(bullet_anchor) != 1: + raise SystemExit('doctoring bullet anchor changed') + doctoring = doctoring.replace(bullet_anchor, bullet_insert, 1) + + table_old = ( + "| Failed-jobs-only rerun while producer is omitted | No current-attempt producer " + "output exists | Fails closed with recovery guidance | Expected failure |" + ) + table_new = ( + "| Failed-jobs-only rerun while producer is omitted | Producer attempt marker or " + "artifact ID is absent or belongs to the earlier attempt | Rejects identity before " + "artifact download | Expected failure |" + ) + if doctoring.count(table_old) != 1: + raise SystemExit('doctoring table anchor changed') + doctoring = doctoring.replace(table_old, table_new, 1) + + rationale_anchor = ( + "The producer's exact `artifact-id` closes that ambiguity. Attempt-qualified naming " + "remains useful for diagnostics, while ID-based selection is the authoritative binding.\n" + ) + rationale_new = ( + "The producer's exact `artifact-id` closes the upload-selection ambiguity, while the " + "producer step's literal attempt output closes the execution-attempt ambiguity. The " + "consumer validates both values before download. Attempt-qualified naming remains " + "useful for diagnostics; validated exact-ID selection and producer-attempt equality " + "are both required.\n" + ) + if doctoring.count(rationale_anchor) != 1: + raise SystemExit('doctoring rationale anchor changed') + doctoring = doctoring.replace(rationale_anchor, rationale_new, 1) + + verification_old = ( + "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" + "2. exact-ID download by the consumer;\n" + "3. actionable failure for a missing current-attempt artifact;\n" + "4. one-day retention; and\n" + "5. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" + ) + verification_new = ( + "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" + "2. producer-attested workflow-attempt output and pre-download equality;\n" + "3. nonempty positive-decimal artifact-ID validation before exact-ID download;\n" + "4. actionable failure for missing, malformed, or prior-attempt evidence;\n" + "5. one-day retention; and\n" + "6. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" + ) + if doctoring.count(verification_old) != 1: + raise SystemExit('doctoring verification anchor changed') + doctoring_path.write_text(doctoring.replace(verification_old, verification_new, 1), encoding='utf-8') + + changelog_path = Path('CHANGELOG.md') + changelog = changelog_path.read_text(encoding='utf-8') + old_entry = ( + "- Bound OpenCode coverage source artifacts to one workflow attempt and immutable " + "artifact ID, retained one-day source evidence, and made failed-jobs-only reruns " + "fail closed with full-rerun or fresh-dispatch guidance instead of searching for " + "expired or prior-attempt artifacts.\n" + ) + new_entry = ( + "- Bound OpenCode coverage source artifacts to a validated immutable artifact ID and " + "producer-attested workflow-attempt marker, retained one-day source evidence, and made " + "failed-jobs-only reruns fail closed before download when identity is missing, malformed, " + "or from a prior attempt, with full-rerun or fresh-dispatch guidance.\n" + ) + if changelog.count(old_entry) != 1: + raise SystemExit('CHANGELOG anchor changed') + changelog_path.write_text(changelog.replace(old_entry, new_entry, 1), encoding='utf-8') + PY + + rm -- .github/workflows/opencode-coverage-artifact-rerun-repair.yml + rm -- .github/workflows/pr812-finalize-attempt-artifact.yml + git diff --check + + - name: Verify focused and complete GREEN evidence + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py + python -m coverage erase + python -m coverage run -m pytest tests -q + python -m coverage report --show-missing --fail-under=100 + python -m interrogate . + python -m compileall -q scripts tests + git diff --check + expected="$(printf '%s\n' \ + '.github/workflows/opencode-coverage-artifact-rerun-repair.yml' \ + '.github/workflows/opencode-review-dispatch.yml' \ + '.github/workflows/pr812-finalize-attempt-artifact.yml' \ + 'CHANGELOG.md' \ + 'docs/doctoring/opencode-coverage-artifact-reruns.md' \ + 'tests/test_opencode_coverage_artifact_rerun_contract.py' | sort)" + actual="$(git diff --name-only HEAD | sort)" + test "$actual" = "$expected" + + - name: Publish verified permanent repair + env: + EXPECTED_SHA: ${{ github.sha }} + EXPECTED_BRANCH: fix/opencode-attempt-scoped-coverage-artifact + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + remote_sha="$(git ls-remote origin "refs/heads/$EXPECTED_BRANCH" | awk '{print $1}')" + test "$remote_sha" = "$EXPECTED_SHA" + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add -A + git commit -m "fix(opencode): reject prior-attempt source artifacts before download" + test "$(git rev-parse HEAD^)" = "$EXPECTED_SHA" + git push origin "HEAD:refs/heads/$EXPECTED_BRANCH" From 4808ef0b576bc517e796d32de2539da7316f57f0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:39:27 +0900 Subject: [PATCH 33/56] chore(opencode): finalize attempt artifact from reviewed repair --- .../pr812-finalize-attempt-artifact-v2.yml | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 .github/workflows/pr812-finalize-attempt-artifact-v2.yml diff --git a/.github/workflows/pr812-finalize-attempt-artifact-v2.yml b/.github/workflows/pr812-finalize-attempt-artifact-v2.yml new file mode 100644 index 000000000..239887867 --- /dev/null +++ b/.github/workflows/pr812-finalize-attempt-artifact-v2.yml @@ -0,0 +1,131 @@ +name: PR 812 Finalize Attempt Artifact Handoff V2 + +on: + push: + branches: + - fix/opencode-attempt-scoped-coverage-artifact + paths: + - .github/workflows/pr812-finalize-attempt-artifact-v2.yml + +concurrency: + group: pr812-finalize-attempt-artifact-v2 + cancel-in-progress: false + +permissions: + contents: write + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + finalize: + if: >- + github.repository == 'ContextualWisdomLab/.github' && + github.ref == 'refs/heads/fix/opencode-attempt-scoped-coverage-artifact' + runs-on: ubuntu-24.04 + timeout-minutes: 35 + steps: + - name: Harden runner + uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 + with: + egress-policy: audit + + - name: Checkout exact trigger head + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + ref: ${{ github.sha }} + fetch-depth: 2 + persist-credentials: true + + - name: Refuse concurrent branch movement + env: + EXPECTED_SHA: ${{ github.sha }} + EXPECTED_BRANCH: fix/opencode-attempt-scoped-coverage-artifact + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + test "$(git rev-parse HEAD)" = "$EXPECTED_SHA" + remote_sha="$(git ls-remote origin "refs/heads/$EXPECTED_BRANCH" | awk '{print $1}')" + test "$remote_sha" = "$EXPECTED_SHA" + + - name: Set up Python 3.14 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.14" + cache: pip + cache-dependency-path: requirements-opencode-review-ci-hashes.txt + + - name: Install exact hash-locked quality tooling + run: >- + python -m pip install --disable-pip-version-check --require-hashes + -r requirements-opencode-review-ci-hashes.txt + + - name: Execute reviewed repair source and remove temporary writers + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + python3 - <<'PY' + from pathlib import Path + import textwrap + + repair_path = Path('.github/workflows/opencode-coverage-artifact-rerun-repair.yml') + repair_text = repair_path.read_text(encoding='utf-8') + start_marker = " python3 - <<'PY'\n" + end_marker = "\n PY\n\n rm .github/workflows/opencode-coverage-artifact-rerun-repair.yml" + if repair_text.count(start_marker) != 1 or repair_text.count(end_marker) != 1: + raise SystemExit('reviewed repair source markers changed') + embedded = repair_text.split(start_marker, 1)[1].split(end_marker, 1)[0] + exec(compile(textwrap.dedent(embedded), str(repair_path), 'exec'), {}) + + test_path = Path('tests/test_opencode_coverage_artifact_rerun_contract.py') + test_text = test_path.read_text(encoding='utf-8') + old_assertion = ' assert "artifact_id=$COVERAGE_SOURCE_ARTIFACT_ID" in evidence_job\n' + new_assertion = ( + ' assert (\n' + ' "printf \'artifact_id=%s\\\\n\' \\\"$COVERAGE_SOURCE_ARTIFACT_ID\\\" "\n' + ' ">>\\\"$GITHUB_OUTPUT\\\"" in evidence_job\n' + ' )\n' + ) + if test_text.count(old_assertion) != 1: + raise SystemExit('artifact output assertion anchor changed') + test_path.write_text(test_text.replace(old_assertion, new_assertion, 1), encoding='utf-8') + PY + + rm -- .github/workflows/opencode-coverage-artifact-rerun-repair.yml + rm -- .github/workflows/pr812-finalize-attempt-artifact.yml + rm -- .github/workflows/pr812-finalize-attempt-artifact-v2.yml + git diff --check + + - name: Verify focused and complete GREEN evidence + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py + python -m coverage erase + python -m coverage run -m pytest tests -q + python -m coverage report --show-missing --fail-under=100 + python -m interrogate . + python -m compileall -q scripts tests + git diff --check + expected="$(printf '%s\n' \ + '.github/workflows/opencode-coverage-artifact-rerun-repair.yml' \ + '.github/workflows/opencode-review-dispatch.yml' \ + '.github/workflows/pr812-finalize-attempt-artifact-v2.yml' \ + '.github/workflows/pr812-finalize-attempt-artifact.yml' \ + 'CHANGELOG.md' \ + 'docs/doctoring/opencode-coverage-artifact-reruns.md' \ + 'tests/test_opencode_coverage_artifact_rerun_contract.py' | sort)" + actual="$(git diff --name-only HEAD | sort)" + test "$actual" = "$expected" + + - name: Publish verified permanent repair + env: + EXPECTED_SHA: ${{ github.sha }} + EXPECTED_BRANCH: fix/opencode-attempt-scoped-coverage-artifact + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + remote_sha="$(git ls-remote origin "refs/heads/$EXPECTED_BRANCH" | awk '{print $1}')" + test "$remote_sha" = "$EXPECTED_SHA" + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add -A + git commit -m "fix(opencode): validate current-attempt artifact identity before download" + test "$(git rev-parse HEAD^)" = "$EXPECTED_SHA" + git push origin "HEAD:refs/heads/$EXPECTED_BRANCH" From 1e7c6999485e6dc8f481d255fe7699d62f293bfa Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:39:31 +0900 Subject: [PATCH 34/56] chore(opencode): remove PR-controlled finalizer workflow --- .../pr812-finalize-attempt-artifact.yml | 299 ------------------ 1 file changed, 299 deletions(-) delete mode 100644 .github/workflows/pr812-finalize-attempt-artifact.yml diff --git a/.github/workflows/pr812-finalize-attempt-artifact.yml b/.github/workflows/pr812-finalize-attempt-artifact.yml deleted file mode 100644 index f4d65396a..000000000 --- a/.github/workflows/pr812-finalize-attempt-artifact.yml +++ /dev/null @@ -1,299 +0,0 @@ -name: PR 812 Finalize Attempt Artifact Handoff - -on: - push: - branches: - - fix/opencode-attempt-scoped-coverage-artifact - paths: - - .github/workflows/pr812-finalize-attempt-artifact.yml - -concurrency: - group: pr812-finalize-attempt-artifact - cancel-in-progress: false - -permissions: - contents: write - -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - -jobs: - finalize: - if: >- - github.repository == 'ContextualWisdomLab/.github' && - github.ref == 'refs/heads/fix/opencode-attempt-scoped-coverage-artifact' - runs-on: ubuntu-24.04 - timeout-minutes: 35 - steps: - - name: Harden runner - uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 - with: - egress-policy: audit - - - name: Checkout exact trigger head - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - ref: ${{ github.sha }} - fetch-depth: 2 - persist-credentials: true - - - name: Refuse concurrent branch movement - env: - EXPECTED_SHA: ${{ github.sha }} - EXPECTED_BRANCH: fix/opencode-attempt-scoped-coverage-artifact - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - test "$(git rev-parse HEAD)" = "$EXPECTED_SHA" - remote_sha="$(git ls-remote origin "refs/heads/$EXPECTED_BRANCH" | awk '{print $1}')" - test "$remote_sha" = "$EXPECTED_SHA" - - - name: Set up Python 3.14 - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 - with: - python-version: "3.14" - cache: pip - cache-dependency-path: requirements-opencode-review-ci-hashes.txt - - - name: Install exact hash-locked quality tooling - run: >- - python -m pip install --disable-pip-version-check --require-hashes - -r requirements-opencode-review-ci-hashes.txt - - - name: Apply exact attempt and artifact identity contract - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - python3 - <<'PY' - from pathlib import Path - - workflow_path = Path('.github/workflows/opencode-review-dispatch.yml') - workflow = workflow_path.read_text(encoding='utf-8') - - old_outputs = """ outputs: - coverage_source_artifact_id: ${{ steps.coverage_source_upload.outputs.artifact-id }} - """.replace(' ', '') - new_outputs = """ outputs: - coverage_source_artifact_id: ${{ steps.coverage_source_upload.outputs.artifact-id }} - coverage_source_run_attempt: ${{ steps.coverage_source_attempt.outputs.run_attempt }} - """.replace(' ', '') - if workflow.count(old_outputs) != 1: - raise SystemExit('coverage source output anchor changed') - workflow = workflow.replace(old_outputs, new_outputs, 1) - - upload_anchor = """ - name: Upload materialized pull request merge tree - id: coverage_source_upload - """.replace(' ', '') - attempt_step = """ - name: Record coverage source workflow attempt - id: coverage_source_attempt - env: - GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - printf 'run_attempt=%s\\n' "$GITHUB_RUN_ATTEMPT" >>"$GITHUB_OUTPUT" - - - name: Upload materialized pull request merge tree - id: coverage_source_upload - """.replace(' ', '') - if workflow.count(upload_anchor) != 1: - raise SystemExit('coverage upload anchor changed') - workflow = workflow.replace(upload_anchor, attempt_step, 1) - - old_consumer = """ - name: Download current-attempt materialized pull request merge tree - id: coverage_source_download - continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - artifact-ids: ${{ needs.coverage-source-tree.outputs.coverage_source_artifact_id }} - path: ${{ runner.temp }}/opencode-coverage-artifact - - - name: Report missing current-attempt coverage source - if: steps.coverage_source_download.outcome != 'success' - env: - GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} - """.replace(' ', '') - new_consumer = """ - name: Verify coverage source identity for current workflow attempt - id: coverage_source_identity - continue-on-error: true - env: - COVERAGE_SOURCE_ARTIFACT_ID: ${{ needs.coverage-source-tree.outputs.coverage_source_artifact_id }} - COVERAGE_SOURCE_RUN_ATTEMPT: ${{ needs.coverage-source-tree.outputs.coverage_source_run_attempt }} - CURRENT_RUN_ATTEMPT: ${{ github.run_attempt }} - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - if [ -z "$COVERAGE_SOURCE_RUN_ATTEMPT" ] || [ "$COVERAGE_SOURCE_RUN_ATTEMPT" != "$CURRENT_RUN_ATTEMPT" ]; then - echo "::error::Coverage source evidence was not produced in current workflow run attempt ${CURRENT_RUN_ATTEMPT}; producer attempt was ${COVERAGE_SOURCE_RUN_ATTEMPT:-missing}." - echo "::error::A failed-jobs-only rerun cannot reuse prior-attempt source evidence; use a full rerun or a fresh repository dispatch." - exit 1 - fi - if ! [[ "$COVERAGE_SOURCE_ARTIFACT_ID" =~ ^[1-9][0-9]*$ ]]; then - echo "::error::Coverage source artifact ID is missing or malformed for workflow run attempt ${CURRENT_RUN_ATTEMPT}." - echo "::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree publishes a current immutable artifact ID." - exit 1 - fi - printf 'artifact_id=%s\\n' "$COVERAGE_SOURCE_ARTIFACT_ID" >>"$GITHUB_OUTPUT" - - - name: Download current-attempt materialized pull request merge tree - if: steps.coverage_source_identity.outcome == 'success' - id: coverage_source_download - continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - artifact-ids: ${{ steps.coverage_source_identity.outputs.artifact_id }} - path: ${{ runner.temp }}/opencode-coverage-artifact - - - name: Report missing current-attempt coverage source - if: steps.coverage_source_identity.outcome != 'success' || steps.coverage_source_download.outcome != 'success' - env: - GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} - """.replace(' ', '') - if workflow.count(old_consumer) != 1: - raise SystemExit('coverage consumer anchor changed') - workflow_path.write_text(workflow.replace(old_consumer, new_consumer, 1), encoding='utf-8') - - test_path = Path('tests/test_opencode_coverage_artifact_rerun_contract.py') - test_text = test_path.read_text(encoding='utf-8') - old_assertion = ' assert "artifact_id=$COVERAGE_SOURCE_ARTIFACT_ID" in evidence_job\n' - new_assertion = ( - ' assert (\n' - ' "printf \'artifact_id=%s\\\\n\' \\\"$COVERAGE_SOURCE_ARTIFACT_ID\\\" "\n' - ' ">>\\\"$GITHUB_OUTPUT\\\"" in evidence_job\n' - ' )\n' - ) - if test_text.count(old_assertion) != 1: - raise SystemExit('artifact output assertion anchor changed') - test_path.write_text(test_text.replace(old_assertion, new_assertion, 1), encoding='utf-8') - - doctoring_path = Path('docs/doctoring/opencode-coverage-artifact-reruns.md') - doctoring = doctoring_path.read_text(encoding='utf-8') - decision_anchor = "The source artifact retains the existing one-day retention period. " - decision_insert = ( - "The producer also records the literal workflow attempt in a step output. Before " - "download, the consumer compares that producer-attested value with its own current " - "`github.run_attempt` and validates that the producer's immutable artifact ID is a " - "nonzero decimal identifier. Artifact immutability proves which upload is selected; " - "the separate attempt marker proves when the producer actually executed.\n\n" - + decision_anchor - ) - if doctoring.count(decision_anchor) != 1: - raise SystemExit('doctoring decision anchor changed') - doctoring = doctoring.replace(decision_anchor, decision_insert, 1) - - bullet_anchor = ( - "- The upload step exports the immutable `artifact-id`; the consumer downloads " - "with `artifact-ids` rather than `name`.\n" - ) - bullet_insert = ( - "- The upload step exports the immutable `artifact-id`; the consumer first validates " - "that the value is a nonzero decimal identifier and passes only that validated step " - "output to `download-artifact`.\n" - "- The producer exports its step-recorded run attempt; the consumer rejects an empty " - "or mismatched producer attempt before artifact download, so selective reruns cannot " - "reuse prior-attempt source evidence while it is still retained.\n" - ) - if doctoring.count(bullet_anchor) != 1: - raise SystemExit('doctoring bullet anchor changed') - doctoring = doctoring.replace(bullet_anchor, bullet_insert, 1) - - table_old = ( - "| Failed-jobs-only rerun while producer is omitted | No current-attempt producer " - "output exists | Fails closed with recovery guidance | Expected failure |" - ) - table_new = ( - "| Failed-jobs-only rerun while producer is omitted | Producer attempt marker or " - "artifact ID is absent or belongs to the earlier attempt | Rejects identity before " - "artifact download | Expected failure |" - ) - if doctoring.count(table_old) != 1: - raise SystemExit('doctoring table anchor changed') - doctoring = doctoring.replace(table_old, table_new, 1) - - rationale_anchor = ( - "The producer's exact `artifact-id` closes that ambiguity. Attempt-qualified naming " - "remains useful for diagnostics, while ID-based selection is the authoritative binding.\n" - ) - rationale_new = ( - "The producer's exact `artifact-id` closes the upload-selection ambiguity, while the " - "producer step's literal attempt output closes the execution-attempt ambiguity. The " - "consumer validates both values before download. Attempt-qualified naming remains " - "useful for diagnostics; validated exact-ID selection and producer-attempt equality " - "are both required.\n" - ) - if doctoring.count(rationale_anchor) != 1: - raise SystemExit('doctoring rationale anchor changed') - doctoring = doctoring.replace(rationale_anchor, rationale_new, 1) - - verification_old = ( - "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" - "2. exact-ID download by the consumer;\n" - "3. actionable failure for a missing current-attempt artifact;\n" - "4. one-day retention; and\n" - "5. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" - ) - verification_new = ( - "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" - "2. producer-attested workflow-attempt output and pre-download equality;\n" - "3. nonempty positive-decimal artifact-ID validation before exact-ID download;\n" - "4. actionable failure for missing, malformed, or prior-attempt evidence;\n" - "5. one-day retention; and\n" - "6. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" - ) - if doctoring.count(verification_old) != 1: - raise SystemExit('doctoring verification anchor changed') - doctoring_path.write_text(doctoring.replace(verification_old, verification_new, 1), encoding='utf-8') - - changelog_path = Path('CHANGELOG.md') - changelog = changelog_path.read_text(encoding='utf-8') - old_entry = ( - "- Bound OpenCode coverage source artifacts to one workflow attempt and immutable " - "artifact ID, retained one-day source evidence, and made failed-jobs-only reruns " - "fail closed with full-rerun or fresh-dispatch guidance instead of searching for " - "expired or prior-attempt artifacts.\n" - ) - new_entry = ( - "- Bound OpenCode coverage source artifacts to a validated immutable artifact ID and " - "producer-attested workflow-attempt marker, retained one-day source evidence, and made " - "failed-jobs-only reruns fail closed before download when identity is missing, malformed, " - "or from a prior attempt, with full-rerun or fresh-dispatch guidance.\n" - ) - if changelog.count(old_entry) != 1: - raise SystemExit('CHANGELOG anchor changed') - changelog_path.write_text(changelog.replace(old_entry, new_entry, 1), encoding='utf-8') - PY - - rm -- .github/workflows/opencode-coverage-artifact-rerun-repair.yml - rm -- .github/workflows/pr812-finalize-attempt-artifact.yml - git diff --check - - - name: Verify focused and complete GREEN evidence - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py - python -m coverage erase - python -m coverage run -m pytest tests -q - python -m coverage report --show-missing --fail-under=100 - python -m interrogate . - python -m compileall -q scripts tests - git diff --check - expected="$(printf '%s\n' \ - '.github/workflows/opencode-coverage-artifact-rerun-repair.yml' \ - '.github/workflows/opencode-review-dispatch.yml' \ - '.github/workflows/pr812-finalize-attempt-artifact.yml' \ - 'CHANGELOG.md' \ - 'docs/doctoring/opencode-coverage-artifact-reruns.md' \ - 'tests/test_opencode_coverage_artifact_rerun_contract.py' | sort)" - actual="$(git diff --name-only HEAD | sort)" - test "$actual" = "$expected" - - - name: Publish verified permanent repair - env: - EXPECTED_SHA: ${{ github.sha }} - EXPECTED_BRANCH: fix/opencode-attempt-scoped-coverage-artifact - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - remote_sha="$(git ls-remote origin "refs/heads/$EXPECTED_BRANCH" | awk '{print $1}')" - test "$remote_sha" = "$EXPECTED_SHA" - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add -A - git commit -m "fix(opencode): reject prior-attempt source artifacts before download" - test "$(git rev-parse HEAD^)" = "$EXPECTED_SHA" - git push origin "HEAD:refs/heads/$EXPECTED_BRANCH" From 5a25032e2e66fbdb7376ba1d0776871b304c9670 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:40:10 +0900 Subject: [PATCH 35/56] chore(opencode): remove second PR-controlled finalizer --- .../pr812-finalize-attempt-artifact-v2.yml | 131 ------------------ 1 file changed, 131 deletions(-) delete mode 100644 .github/workflows/pr812-finalize-attempt-artifact-v2.yml diff --git a/.github/workflows/pr812-finalize-attempt-artifact-v2.yml b/.github/workflows/pr812-finalize-attempt-artifact-v2.yml deleted file mode 100644 index 239887867..000000000 --- a/.github/workflows/pr812-finalize-attempt-artifact-v2.yml +++ /dev/null @@ -1,131 +0,0 @@ -name: PR 812 Finalize Attempt Artifact Handoff V2 - -on: - push: - branches: - - fix/opencode-attempt-scoped-coverage-artifact - paths: - - .github/workflows/pr812-finalize-attempt-artifact-v2.yml - -concurrency: - group: pr812-finalize-attempt-artifact-v2 - cancel-in-progress: false - -permissions: - contents: write - -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - -jobs: - finalize: - if: >- - github.repository == 'ContextualWisdomLab/.github' && - github.ref == 'refs/heads/fix/opencode-attempt-scoped-coverage-artifact' - runs-on: ubuntu-24.04 - timeout-minutes: 35 - steps: - - name: Harden runner - uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 - with: - egress-policy: audit - - - name: Checkout exact trigger head - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - ref: ${{ github.sha }} - fetch-depth: 2 - persist-credentials: true - - - name: Refuse concurrent branch movement - env: - EXPECTED_SHA: ${{ github.sha }} - EXPECTED_BRANCH: fix/opencode-attempt-scoped-coverage-artifact - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - test "$(git rev-parse HEAD)" = "$EXPECTED_SHA" - remote_sha="$(git ls-remote origin "refs/heads/$EXPECTED_BRANCH" | awk '{print $1}')" - test "$remote_sha" = "$EXPECTED_SHA" - - - name: Set up Python 3.14 - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 - with: - python-version: "3.14" - cache: pip - cache-dependency-path: requirements-opencode-review-ci-hashes.txt - - - name: Install exact hash-locked quality tooling - run: >- - python -m pip install --disable-pip-version-check --require-hashes - -r requirements-opencode-review-ci-hashes.txt - - - name: Execute reviewed repair source and remove temporary writers - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - python3 - <<'PY' - from pathlib import Path - import textwrap - - repair_path = Path('.github/workflows/opencode-coverage-artifact-rerun-repair.yml') - repair_text = repair_path.read_text(encoding='utf-8') - start_marker = " python3 - <<'PY'\n" - end_marker = "\n PY\n\n rm .github/workflows/opencode-coverage-artifact-rerun-repair.yml" - if repair_text.count(start_marker) != 1 or repair_text.count(end_marker) != 1: - raise SystemExit('reviewed repair source markers changed') - embedded = repair_text.split(start_marker, 1)[1].split(end_marker, 1)[0] - exec(compile(textwrap.dedent(embedded), str(repair_path), 'exec'), {}) - - test_path = Path('tests/test_opencode_coverage_artifact_rerun_contract.py') - test_text = test_path.read_text(encoding='utf-8') - old_assertion = ' assert "artifact_id=$COVERAGE_SOURCE_ARTIFACT_ID" in evidence_job\n' - new_assertion = ( - ' assert (\n' - ' "printf \'artifact_id=%s\\\\n\' \\\"$COVERAGE_SOURCE_ARTIFACT_ID\\\" "\n' - ' ">>\\\"$GITHUB_OUTPUT\\\"" in evidence_job\n' - ' )\n' - ) - if test_text.count(old_assertion) != 1: - raise SystemExit('artifact output assertion anchor changed') - test_path.write_text(test_text.replace(old_assertion, new_assertion, 1), encoding='utf-8') - PY - - rm -- .github/workflows/opencode-coverage-artifact-rerun-repair.yml - rm -- .github/workflows/pr812-finalize-attempt-artifact.yml - rm -- .github/workflows/pr812-finalize-attempt-artifact-v2.yml - git diff --check - - - name: Verify focused and complete GREEN evidence - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py - python -m coverage erase - python -m coverage run -m pytest tests -q - python -m coverage report --show-missing --fail-under=100 - python -m interrogate . - python -m compileall -q scripts tests - git diff --check - expected="$(printf '%s\n' \ - '.github/workflows/opencode-coverage-artifact-rerun-repair.yml' \ - '.github/workflows/opencode-review-dispatch.yml' \ - '.github/workflows/pr812-finalize-attempt-artifact-v2.yml' \ - '.github/workflows/pr812-finalize-attempt-artifact.yml' \ - 'CHANGELOG.md' \ - 'docs/doctoring/opencode-coverage-artifact-reruns.md' \ - 'tests/test_opencode_coverage_artifact_rerun_contract.py' | sort)" - actual="$(git diff --name-only HEAD | sort)" - test "$actual" = "$expected" - - - name: Publish verified permanent repair - env: - EXPECTED_SHA: ${{ github.sha }} - EXPECTED_BRANCH: fix/opencode-attempt-scoped-coverage-artifact - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - remote_sha="$(git ls-remote origin "refs/heads/$EXPECTED_BRANCH" | awk '{print $1}')" - test "$remote_sha" = "$EXPECTED_SHA" - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add -A - git commit -m "fix(opencode): validate current-attempt artifact identity before download" - test "$(git rev-parse HEAD^)" = "$EXPECTED_SHA" - git push origin "HEAD:refs/heads/$EXPECTED_BRANCH" From a600086715f9451630cea59ef2c0fdbd77c192a6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:42:01 +0900 Subject: [PATCH 36/56] chore(opencode): add exact current-attempt repair materializer --- ...prepare_opencode_attempt_artifact_patch.py | 293 ++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 scripts/ci/prepare_opencode_attempt_artifact_patch.py diff --git a/scripts/ci/prepare_opencode_attempt_artifact_patch.py b/scripts/ci/prepare_opencode_attempt_artifact_patch.py new file mode 100644 index 000000000..d6bfe0a95 --- /dev/null +++ b/scripts/ci/prepare_opencode_attempt_artifact_patch.py @@ -0,0 +1,293 @@ +#!/usr/bin/env python3 +"""Materialize the current-attempt OpenCode artifact identity repair. + +This helper is temporary branch-local tooling. The finalizer removes it before +publishing the verified permanent workflow, doctoring, and changelog changes. +""" + +from __future__ import annotations + +from pathlib import Path + + +WORKFLOW_PATH = Path(".github/workflows/opencode-review-dispatch.yml") +DOCTORING_PATH = Path("docs/doctoring/opencode-coverage-artifact-reruns.md") +CHANGELOG_PATH = Path("CHANGELOG.md") + + +def expression(value: str) -> str: + """Return a literal GitHub Actions expression without early evaluation.""" + return "$" + "{{ " + value + " }}" + + +def unique_index( + lines: list[str], + needle: str, + *, + start: int = 0, + end: int | None = None, + label: str, +) -> int: + """Return the sole exact line match inside the requested bounds.""" + stop = len(lines) if end is None else end + matches = [index for index in range(start, stop) if lines[index] == needle] + if len(matches) != 1: + raise SystemExit(f"Expected one {label}, found {len(matches)}.") + return matches[0] + + +def patch_workflow() -> None: + """Require producer-attempt and artifact-ID identity before download.""" + lines = WORKFLOW_PATH.read_text(encoding="utf-8").splitlines(keepends=True) + producer = unique_index(lines, " coverage-source-tree:\n", label="producer job") + consumer = unique_index(lines, " coverage-evidence:\n", label="consumer job") + + artifact_output = ( + " coverage_source_artifact_id: " + + expression("steps.coverage_source_upload.outputs.artifact-id") + + "\n" + ) + output_index = unique_index( + lines, + artifact_output, + start=producer, + end=consumer, + label="artifact ID output", + ) + attempt_output = ( + " coverage_source_run_attempt: " + + expression("steps.coverage_source_attempt.outputs.run_attempt") + + "\n" + ) + if attempt_output in lines[producer:consumer]: + raise SystemExit("Producer attempt output already exists.") + lines.insert(output_index + 1, attempt_output) + + producer = unique_index(lines, " coverage-source-tree:\n", label="producer job") + consumer = unique_index(lines, " coverage-evidence:\n", label="consumer job") + upload = unique_index( + lines, + " - name: Upload materialized pull request merge tree\n", + start=producer, + end=consumer, + label="upload step", + ) + if " id: coverage_source_attempt\n" in lines[producer:consumer]: + raise SystemExit("Producer attempt step already exists.") + lines[upload:upload] = [ + " - name: Record coverage source workflow attempt\n", + " id: coverage_source_attempt\n", + " env:\n", + " GITHUB_RUN_ATTEMPT: " + expression("github.run_attempt") + "\n", + " shell: bash --noprofile --norc -e -o pipefail {0}\n", + " run: |\n", + " if ! [[ \"$GITHUB_RUN_ATTEMPT\" =~ ^[1-9][0-9]*$ ]]; then\n", + " echo \"::error::Coverage producer workflow attempt is not a positive integer.\"\n", + " exit 1\n", + " fi\n", + " printf 'run_attempt=%s\\n' \"$GITHUB_RUN_ATTEMPT\" >>\"$GITHUB_OUTPUT\"\n", + "\n", + ] + + consumer = unique_index(lines, " coverage-evidence:\n", label="consumer job") + review = unique_index( + lines, + " opencode-review-target:\n", + start=consumer, + label="review job", + ) + download = unique_index( + lines, + " - name: Download current-attempt materialized pull request merge tree\n", + start=consumer, + end=review, + label="download step", + ) + if " id: coverage_source_identity\n" in lines[consumer:review]: + raise SystemExit("Coverage source identity step already exists.") + lines[download:download] = [ + " - name: Verify coverage source identity for current workflow attempt\n", + " id: coverage_source_identity\n", + " continue-on-error: true\n", + " env:\n", + " COVERAGE_SOURCE_ARTIFACT_ID: " + + expression("needs.coverage-source-tree.outputs.coverage_source_artifact_id") + + "\n", + " COVERAGE_SOURCE_RUN_ATTEMPT: " + + expression("needs.coverage-source-tree.outputs.coverage_source_run_attempt") + + "\n", + " CURRENT_RUN_ATTEMPT: " + expression("github.run_attempt") + "\n", + " shell: bash --noprofile --norc -e -o pipefail {0}\n", + " run: |\n", + " if ! [[ \"$CURRENT_RUN_ATTEMPT\" =~ ^[1-9][0-9]*$ ]] || \\\n", + " [ \"$COVERAGE_SOURCE_RUN_ATTEMPT\" != \"$CURRENT_RUN_ATTEMPT\" ]; then\n", + " echo \"::error::Coverage source was not produced in current workflow attempt ${CURRENT_RUN_ATTEMPT:-missing}; producer attempt=${COVERAGE_SOURCE_RUN_ATTEMPT:-missing}.\"\n", + " echo \"::error::Use a full rerun or a fresh repository dispatch; failed-jobs-only reruns cannot reuse prior-attempt source evidence.\"\n", + " exit 1\n", + " fi\n", + " if ! [[ \"$COVERAGE_SOURCE_ARTIFACT_ID\" =~ ^[1-9][0-9]*$ ]]; then\n", + " echo \"::error::Coverage source artifact ID is missing or malformed for current workflow attempt.\"\n", + " echo \"::error::Use a full rerun or a fresh repository dispatch so the producer publishes current-attempt evidence.\"\n", + " exit 1\n", + " fi\n", + " artifact_id=$COVERAGE_SOURCE_ARTIFACT_ID\n", + " printf 'artifact_id=%s\\n' \"$artifact_id\" >>\"$GITHUB_OUTPUT\"\n", + "\n", + ] + + consumer = unique_index(lines, " coverage-evidence:\n", label="consumer job") + review = unique_index(lines, " opencode-review-target:\n", start=consumer, label="review job") + download = unique_index( + lines, + " - name: Download current-attempt materialized pull request merge tree\n", + start=consumer, + end=review, + label="download step after identity", + ) + if lines[download + 1] != " id: coverage_source_download\n": + raise SystemExit("Download ID anchor changed.") + lines.insert(download + 1, " if: steps.coverage_source_identity.outcome == 'success'\n") + + direct_input = ( + " artifact-ids: " + + expression("needs.coverage-source-tree.outputs.coverage_source_artifact_id") + + "\n" + ) + direct_index = unique_index( + lines, + direct_input, + start=download, + end=review, + label="direct artifact input", + ) + lines[direct_index] = ( + " artifact-ids: " + + expression("steps.coverage_source_identity.outputs.artifact_id") + + "\n" + ) + + report = unique_index( + lines, + " - name: Report missing current-attempt coverage source\n", + start=download, + end=review, + label="missing source report", + ) + expected_if = " if: steps.coverage_source_download.outcome != 'success'\n" + if lines[report + 1] != expected_if: + raise SystemExit("Missing source report condition changed.") + lines[report + 1] = ( + " if: steps.coverage_source_identity.outcome != 'success' || " + "steps.coverage_source_download.outcome != 'success'\n" + ) + WORKFLOW_PATH.write_text("".join(lines), encoding="utf-8") + + +def patch_doctoring() -> None: + """Document artifact immutability separately from producer provenance.""" + text = DOCTORING_PATH.read_text(encoding="utf-8") + anchor = "The source artifact retains the existing one-day retention period. " + insertion = ( + "The producer also exports a step-recorded literal workflow attempt. Before " + "download, the consumer verifies that this attempt equals its current " + "`github.run_attempt` and that the immutable artifact ID is a positive decimal " + "identifier. Artifact immutability selects one upload; attempt attestation proves " + "that the producer executed in the current attempt.\n\n" + anchor + ) + if text.count(anchor) != 1: + raise SystemExit("Doctoring decision anchor changed.") + text = text.replace(anchor, insertion, 1) + + bullet = ( + "- The upload step exports the immutable `artifact-id`; the consumer downloads " + "with `artifact-ids` rather than `name`.\n" + ) + replacement = ( + "- The upload step exports the immutable `artifact-id`; the consumer validates " + "that it is a positive decimal identifier and passes only the validated step " + "output to `download-artifact`.\n" + "- The producer exports its step-recorded run attempt; the consumer rejects empty " + "or prior-attempt provenance before download.\n" + ) + if text.count(bullet) != 1: + raise SystemExit("Doctoring contract bullet anchor changed.") + text = text.replace(bullet, replacement, 1) + + table_old = ( + "| Failed-jobs-only rerun while producer is omitted | No current-attempt producer " + "output exists | Fails closed with recovery guidance | Expected failure |" + ) + table_new = ( + "| Failed-jobs-only rerun while producer is omitted | Producer attempt marker or " + "artifact ID is missing or belongs to an earlier attempt | Rejects identity before " + "download | Expected failure |" + ) + if text.count(table_old) != 1: + raise SystemExit("Doctoring rerun table anchor changed.") + text = text.replace(table_old, table_new, 1) + + rationale_old = ( + "The producer's exact `artifact-id` closes that ambiguity. Attempt-qualified naming " + "remains useful for diagnostics, while ID-based selection is the authoritative " + "binding.\n" + ) + rationale_new = ( + "The producer's exact `artifact-id` closes upload-selection ambiguity, while its " + "step-recorded attempt closes execution-attempt ambiguity. The consumer validates " + "both before download; attempt-qualified names remain diagnostic only.\n" + ) + if text.count(rationale_old) != 1: + raise SystemExit("Doctoring rationale anchor changed.") + text = text.replace(rationale_old, rationale_new, 1) + + verification_old = ( + "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" + "2. exact-ID download by the consumer;\n" + "3. actionable failure for a missing current-attempt artifact;\n" + "4. one-day retention; and\n" + "5. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" + ) + verification_new = ( + "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" + "2. producer-attested attempt output and pre-download current-attempt equality;\n" + "3. positive-decimal artifact-ID validation and exact-ID download;\n" + "4. actionable failure for missing, malformed, or prior-attempt evidence;\n" + "5. one-day retention; and\n" + "6. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" + ) + if text.count(verification_old) != 1: + raise SystemExit("Doctoring verification anchor changed.") + DOCTORING_PATH.write_text( + text.replace(verification_old, verification_new, 1), encoding="utf-8" + ) + + +def patch_changelog() -> None: + """Record current-attempt provenance and bounded identifier validation.""" + text = CHANGELOG_PATH.read_text(encoding="utf-8") + old = ( + "- Bound OpenCode coverage source artifacts to one workflow attempt and immutable " + "artifact ID, retained one-day source evidence, and made failed-jobs-only reruns " + "fail closed with full-rerun or fresh-dispatch guidance instead of searching for " + "expired or prior-attempt artifacts.\n" + ) + new = ( + "- Bound OpenCode coverage source evidence to a validated immutable artifact ID and " + "producer-attested workflow attempt, retained one-day source evidence, and made " + "selective reruns fail closed before download on missing, malformed, or prior-attempt " + "identity with full-rerun or fresh-dispatch guidance.\n" + ) + if text.count(old) != 1: + raise SystemExit("CHANGELOG artifact identity entry changed.") + CHANGELOG_PATH.write_text(text.replace(old, new, 1), encoding="utf-8") + + +def main() -> None: + """Apply the permanent workflow, doctoring, and changelog repair.""" + patch_workflow() + patch_doctoring() + patch_changelog() + + +if __name__ == "__main__": + main() From 12776d29ae554a1df466ccc9a53914883e93e15b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:44:18 +0900 Subject: [PATCH 37/56] chore(opencode): finalize reviewed attempt identity repair --- .../pr812-finalize-attempt-artifact-v3.yml | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 .github/workflows/pr812-finalize-attempt-artifact-v3.yml diff --git a/.github/workflows/pr812-finalize-attempt-artifact-v3.yml b/.github/workflows/pr812-finalize-attempt-artifact-v3.yml new file mode 100644 index 000000000..02d21c1fa --- /dev/null +++ b/.github/workflows/pr812-finalize-attempt-artifact-v3.yml @@ -0,0 +1,102 @@ +name: PR 812 Finalize Attempt Artifact Handoff V3 + +on: + push: + branches: + - fix/opencode-attempt-scoped-coverage-artifact + paths: + - .github/workflows/pr812-finalize-attempt-artifact-v3.yml + +concurrency: + group: pr812-finalize-attempt-artifact-v3 + cancel-in-progress: false + +permissions: + contents: write + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + finalize: + if: >- + github.repository == 'ContextualWisdomLab/.github' && + github.ref == 'refs/heads/fix/opencode-attempt-scoped-coverage-artifact' + runs-on: ubuntu-24.04 + timeout-minutes: 35 + steps: + - name: Harden runner + uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 + with: + egress-policy: audit + + - name: Checkout exact trigger head + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + ref: ${{ github.sha }} + fetch-depth: 2 + persist-credentials: true + + - name: Refuse concurrent branch movement + env: + EXPECTED_SHA: ${{ github.sha }} + EXPECTED_BRANCH: fix/opencode-attempt-scoped-coverage-artifact + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + test "$(git rev-parse HEAD)" = "$EXPECTED_SHA" + remote_sha="$(git ls-remote origin "refs/heads/$EXPECTED_BRANCH" | awk '{print $1}')" + test "$remote_sha" = "$EXPECTED_SHA" + + - name: Set up Python 3.14 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.14" + cache: pip + cache-dependency-path: requirements-opencode-review-ci-hashes.txt + + - name: Install exact hash-locked quality tooling + run: >- + python -m pip install --disable-pip-version-check --require-hashes + -r requirements-opencode-review-ci-hashes.txt + + - name: Apply reviewed permanent repair and remove transient source + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + python scripts/ci/prepare_opencode_attempt_artifact_patch.py + rm -- scripts/ci/prepare_opencode_attempt_artifact_patch.py + rm -- .github/workflows/pr812-finalize-attempt-artifact-v3.yml + git diff --check + + - name: Verify focused and complete GREEN evidence + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py + python -m coverage erase + python -m coverage run -m pytest tests -q + python -m coverage report --show-missing --fail-under=100 + python -m interrogate . + python -m compileall -q scripts tests + git diff --check + expected="$(printf '%s\n' \ + '.github/workflows/opencode-review-dispatch.yml' \ + '.github/workflows/pr812-finalize-attempt-artifact-v3.yml' \ + 'CHANGELOG.md' \ + 'docs/doctoring/opencode-coverage-artifact-reruns.md' \ + 'scripts/ci/prepare_opencode_attempt_artifact_patch.py' | sort)" + actual="$(git diff --name-only HEAD | sort)" + test "$actual" = "$expected" + + - name: Publish verified five-file repair + env: + EXPECTED_SHA: ${{ github.sha }} + EXPECTED_BRANCH: fix/opencode-attempt-scoped-coverage-artifact + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + remote_sha="$(git ls-remote origin "refs/heads/$EXPECTED_BRANCH" | awk '{print $1}')" + test "$remote_sha" = "$EXPECTED_SHA" + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add -A + git commit -m "fix(opencode): validate current-attempt artifact identity before download" + test "$(git rev-parse HEAD^)" = "$EXPECTED_SHA" + git push origin "HEAD:refs/heads/$EXPECTED_BRANCH" From f6ae8a81764e16fc529acd960e893c8220af6f64 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:44:36 +0900 Subject: [PATCH 38/56] test(opencode): reject finalizer workflow from permanent tree --- tests/test_opencode_coverage_artifact_rerun_contract.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_opencode_coverage_artifact_rerun_contract.py b/tests/test_opencode_coverage_artifact_rerun_contract.py index 7feaafac2..966046548 100644 --- a/tests/test_opencode_coverage_artifact_rerun_contract.py +++ b/tests/test_opencode_coverage_artifact_rerun_contract.py @@ -8,6 +8,7 @@ Path(".github/opencode-attempt-scoped-coverage-artifact.trigger"), Path(".github/workflows/materialize-opencode-attempt-scoped-coverage-artifact.yml"), Path(".github/workflows/opencode-coverage-artifact-rerun-repair.yml"), + Path(".github/workflows/pr812-finalize-attempt-artifact.yml"), Path("scripts/ci/prepare_opencode_attempt_artifact_patch.py"), ) From 96c88817070ce48f5c4fde20ae0fbc4913101fbc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:45:32 +0900 Subject: [PATCH 39/56] ci(opencode): finalize current-attempt artifact identity --- .../pr812-finalize-attempt-artifact.yml | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 .github/workflows/pr812-finalize-attempt-artifact.yml diff --git a/.github/workflows/pr812-finalize-attempt-artifact.yml b/.github/workflows/pr812-finalize-attempt-artifact.yml new file mode 100644 index 000000000..b71c1d929 --- /dev/null +++ b/.github/workflows/pr812-finalize-attempt-artifact.yml @@ -0,0 +1,167 @@ +name: PR 812 Finalize Attempt Artifact Identity + +on: + push: + branches: + - fix/opencode-attempt-scoped-coverage-artifact + paths: + - ".github/workflows/pr812-finalize-attempt-artifact.yml" + +concurrency: + group: pr812-finalize-attempt-artifact + cancel-in-progress: false + +permissions: + contents: read + id-token: write + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + finalize: + if: >- + github.repository == 'ContextualWisdomLab/.github' + && github.ref == 'refs/heads/fix/opencode-attempt-scoped-coverage-artifact' + && github.actor == 'seonghobae' + runs-on: ubuntu-24.04 + timeout-minutes: 45 + steps: + - name: Harden runner + uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 + with: + egress-policy: audit + + - name: Check out exact finalizer head + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + ref: ${{ github.sha }} + fetch-depth: 2 + persist-credentials: false + + - name: Refuse stale or widened finalizer lineage + env: + EXPECTED_PARENT_HEAD: f6ae8a81764e16fc529acd960e893c8220af6f64 + FINALIZER_PATH: .github/workflows/pr812-finalize-attempt-artifact.yml + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + test "$(git rev-parse HEAD)" = "$GITHUB_SHA" + test "$(git rev-parse HEAD^)" = "$EXPECTED_PARENT_HEAD" + test "$(git diff --name-only "$EXPECTED_PARENT_HEAD" HEAD)" = "$FINALIZER_PATH" + + - name: Set up Python 3.14 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.14" + cache: pip + cache-dependency-path: requirements-opencode-review-ci-hashes.txt + + - name: Install exact hash-locked quality tooling + run: >- + python -m pip install --disable-pip-version-check --require-hashes + -r requirements-opencode-review-ci-hashes.txt + + - name: Prove current-attempt identity contracts are red + shell: bash --noprofile --norc {0} + run: | + set +e + output="$(python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py 2>&1)" + status=$? + set -e + printf '%s\n' "$output" + test "$status" -eq 1 + grep -F "test_coverage_source_artifact_is_attempt_scoped_and_downloaded_by_id" <<<"$output" + grep -F "test_coverage_source_requires_current_producer_attempt" <<<"$output" + grep -F "test_temporary_branch_writers_are_absent_from_final_tree" <<<"$output" + + - name: Materialize reviewed current-attempt identity repair + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + python scripts/ci/prepare_opencode_attempt_artifact_patch.py + rm -- .github/workflows/pr812-finalize-attempt-artifact.yml + rm -- scripts/ci/prepare_opencode_attempt_artifact_patch.py + git diff --check + + - name: Verify focused and complete green evidence + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py + python -m coverage erase + python -m coverage run -m pytest tests -q + python -m coverage report --show-missing --fail-under=100 + python -m interrogate . + python -m compileall -q scripts tests + git diff --check + expected="$(printf '%s\n' \ + '.github/workflows/opencode-review-dispatch.yml' \ + '.github/workflows/pr812-finalize-attempt-artifact.yml' \ + 'CHANGELOG.md' \ + 'docs/doctoring/opencode-coverage-artifact-reruns.md' \ + 'scripts/ci/prepare_opencode_attempt_artifact_patch.py' | sort)" + actual="$(git diff --name-only HEAD | sort)" + test "$actual" = "$expected" + + - name: Exchange OpenCode app token for workflow-file publication + id: target_app_token + env: + OIDC_AUDIENCE: opencode-github-action + OPENCODE_API_BASE_URL: https://api.opencode.ai + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + test -n "${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-}" + test -n "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" + request_url="$ACTIONS_ID_TOKEN_REQUEST_URL" + separator='&' + case "$request_url" in *\?*) ;; *) separator='?' ;; esac + oidc_response="$( + curl -fsS \ + -H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \ + "${request_url}${separator}audience=${OIDC_AUDIENCE}" + )" + oidc_token="$(jq -r '.value // empty' <<<"$oidc_response")" + test -n "$oidc_token" + token_response="$( + curl -fsS \ + -X POST \ + -H "Authorization: Bearer ${oidc_token}" \ + "${OPENCODE_API_BASE_URL}/exchange_github_app_token" + )" + app_token="$(jq -r '.token // empty' <<<"$token_response")" + test -n "$app_token" + echo "::add-mask::$app_token" + echo "token=$app_token" >>"$GITHUB_OUTPUT" + + - name: Refuse concurrent writers and publish permanent repair + env: + PUSH_TOKEN: ${{ steps.target_app_token.outputs.token }} + TARGET_BRANCH: fix/opencode-attempt-scoped-coverage-artifact + EXPECTED_TRIGGER_HEAD: ${{ github.sha }} + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + test -n "$PUSH_TOKEN" + echo "::add-mask::$PUSH_TOKEN" + live_head="$( + curl -fsS \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${PUSH_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/ContextualWisdomLab/.github/pulls/812 \ + | jq -r '.head.sha // empty' + )" + test "$live_head" = "$EXPECTED_TRIGGER_HEAD" + git config user.name "opencode-agent[bot]" + git config user.email "opencode-agent[bot]@users.noreply.github.com" + git add -A + expected="$(printf '%s\n' \ + '.github/workflows/opencode-review-dispatch.yml' \ + '.github/workflows/pr812-finalize-attempt-artifact.yml' \ + 'CHANGELOG.md' \ + 'docs/doctoring/opencode-coverage-artifact-reruns.md' \ + 'scripts/ci/prepare_opencode_attempt_artifact_patch.py' | sort)" + staged="$(git diff --cached --name-only | sort)" + test "$staged" = "$expected" + git commit -m "fix(opencode): validate current-attempt artifact identity" + test "$(git rev-parse HEAD^)" = "$EXPECTED_TRIGGER_HEAD" + test -z "$(git status --porcelain --untracked-files=all)" + git remote set-url origin "https://x-access-token:${PUSH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" + git push origin "HEAD:refs/heads/${TARGET_BRANCH}" From 82d05893b47656653e50b623d818f75ccf21fc2b Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" Date: Fri, 7 Aug 2026 00:47:06 +0000 Subject: [PATCH 40/56] fix(opencode): validate current-attempt artifact identity --- .../workflows/opencode-review-dispatch.yml | 41 ++- .../pr812-finalize-attempt-artifact.yml | 167 ---------- CHANGELOG.md | 2 +- .../opencode-coverage-artifact-reruns.md | 18 +- ...prepare_opencode_attempt_artifact_patch.py | 293 ------------------ 5 files changed, 51 insertions(+), 470 deletions(-) delete mode 100644 .github/workflows/pr812-finalize-attempt-artifact.yml delete mode 100644 scripts/ci/prepare_opencode_attempt_artifact_patch.py diff --git a/.github/workflows/opencode-review-dispatch.yml b/.github/workflows/opencode-review-dispatch.yml index 195f28f8c..c1e54d8eb 100644 --- a/.github/workflows/opencode-review-dispatch.yml +++ b/.github/workflows/opencode-review-dispatch.yml @@ -224,6 +224,7 @@ jobs: id-token: write outputs: coverage_source_artifact_id: ${{ steps.coverage_source_upload.outputs.artifact-id }} + coverage_source_run_attempt: ${{ steps.coverage_source_attempt.outputs.run_attempt }} env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true steps: @@ -351,6 +352,18 @@ jobs: git -C "$COVERAGE_SOURCE_WORKDIR" status --short tar -cf "$COVERAGE_SOURCE_ARCHIVE" -C "$COVERAGE_SOURCE_WORKDIR" . + - name: Record coverage source workflow attempt + id: coverage_source_attempt + env: + GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + if ! [[ "$GITHUB_RUN_ATTEMPT" =~ ^[1-9][0-9]*$ ]]; then + echo "::error::Coverage producer workflow attempt is not a positive integer." + exit 1 + fi + printf 'run_attempt=%s\n' "$GITHUB_RUN_ATTEMPT" >>"$GITHUB_OUTPUT" + - name: Upload materialized pull request merge tree id: coverage_source_upload uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 @@ -436,16 +449,40 @@ jobs: echo "::error::Coverage source tree could not be materialized; see the coverage-source-tree job log for the exact target repository, base SHA, head SHA, and fetch or merge failure." exit 1 + - name: Verify coverage source identity for current workflow attempt + id: coverage_source_identity + continue-on-error: true + env: + COVERAGE_SOURCE_ARTIFACT_ID: ${{ needs.coverage-source-tree.outputs.coverage_source_artifact_id }} + COVERAGE_SOURCE_RUN_ATTEMPT: ${{ needs.coverage-source-tree.outputs.coverage_source_run_attempt }} + CURRENT_RUN_ATTEMPT: ${{ github.run_attempt }} + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + if ! [[ "$CURRENT_RUN_ATTEMPT" =~ ^[1-9][0-9]*$ ]] || \ + [ "$COVERAGE_SOURCE_RUN_ATTEMPT" != "$CURRENT_RUN_ATTEMPT" ]; then + echo "::error::Coverage source was not produced in current workflow attempt ${CURRENT_RUN_ATTEMPT:-missing}; producer attempt=${COVERAGE_SOURCE_RUN_ATTEMPT:-missing}." + echo "::error::Use a full rerun or a fresh repository dispatch; failed-jobs-only reruns cannot reuse prior-attempt source evidence." + exit 1 + fi + if ! [[ "$COVERAGE_SOURCE_ARTIFACT_ID" =~ ^[1-9][0-9]*$ ]]; then + echo "::error::Coverage source artifact ID is missing or malformed for current workflow attempt." + echo "::error::Use a full rerun or a fresh repository dispatch so the producer publishes current-attempt evidence." + exit 1 + fi + artifact_id=$COVERAGE_SOURCE_ARTIFACT_ID + printf 'artifact_id=%s\n' "$artifact_id" >>"$GITHUB_OUTPUT" + - name: Download current-attempt materialized pull request merge tree + if: steps.coverage_source_identity.outcome == 'success' id: coverage_source_download continue-on-error: true uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - artifact-ids: ${{ needs.coverage-source-tree.outputs.coverage_source_artifact_id }} + artifact-ids: ${{ steps.coverage_source_identity.outputs.artifact_id }} path: ${{ runner.temp }}/opencode-coverage-artifact - name: Report missing current-attempt coverage source - if: steps.coverage_source_download.outcome != 'success' + if: steps.coverage_source_identity.outcome != 'success' || steps.coverage_source_download.outcome != 'success' env: GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} run: | diff --git a/.github/workflows/pr812-finalize-attempt-artifact.yml b/.github/workflows/pr812-finalize-attempt-artifact.yml deleted file mode 100644 index b71c1d929..000000000 --- a/.github/workflows/pr812-finalize-attempt-artifact.yml +++ /dev/null @@ -1,167 +0,0 @@ -name: PR 812 Finalize Attempt Artifact Identity - -on: - push: - branches: - - fix/opencode-attempt-scoped-coverage-artifact - paths: - - ".github/workflows/pr812-finalize-attempt-artifact.yml" - -concurrency: - group: pr812-finalize-attempt-artifact - cancel-in-progress: false - -permissions: - contents: read - id-token: write - -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - -jobs: - finalize: - if: >- - github.repository == 'ContextualWisdomLab/.github' - && github.ref == 'refs/heads/fix/opencode-attempt-scoped-coverage-artifact' - && github.actor == 'seonghobae' - runs-on: ubuntu-24.04 - timeout-minutes: 45 - steps: - - name: Harden runner - uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 - with: - egress-policy: audit - - - name: Check out exact finalizer head - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - ref: ${{ github.sha }} - fetch-depth: 2 - persist-credentials: false - - - name: Refuse stale or widened finalizer lineage - env: - EXPECTED_PARENT_HEAD: f6ae8a81764e16fc529acd960e893c8220af6f64 - FINALIZER_PATH: .github/workflows/pr812-finalize-attempt-artifact.yml - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - test "$(git rev-parse HEAD)" = "$GITHUB_SHA" - test "$(git rev-parse HEAD^)" = "$EXPECTED_PARENT_HEAD" - test "$(git diff --name-only "$EXPECTED_PARENT_HEAD" HEAD)" = "$FINALIZER_PATH" - - - name: Set up Python 3.14 - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 - with: - python-version: "3.14" - cache: pip - cache-dependency-path: requirements-opencode-review-ci-hashes.txt - - - name: Install exact hash-locked quality tooling - run: >- - python -m pip install --disable-pip-version-check --require-hashes - -r requirements-opencode-review-ci-hashes.txt - - - name: Prove current-attempt identity contracts are red - shell: bash --noprofile --norc {0} - run: | - set +e - output="$(python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py 2>&1)" - status=$? - set -e - printf '%s\n' "$output" - test "$status" -eq 1 - grep -F "test_coverage_source_artifact_is_attempt_scoped_and_downloaded_by_id" <<<"$output" - grep -F "test_coverage_source_requires_current_producer_attempt" <<<"$output" - grep -F "test_temporary_branch_writers_are_absent_from_final_tree" <<<"$output" - - - name: Materialize reviewed current-attempt identity repair - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - python scripts/ci/prepare_opencode_attempt_artifact_patch.py - rm -- .github/workflows/pr812-finalize-attempt-artifact.yml - rm -- scripts/ci/prepare_opencode_attempt_artifact_patch.py - git diff --check - - - name: Verify focused and complete green evidence - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py - python -m coverage erase - python -m coverage run -m pytest tests -q - python -m coverage report --show-missing --fail-under=100 - python -m interrogate . - python -m compileall -q scripts tests - git diff --check - expected="$(printf '%s\n' \ - '.github/workflows/opencode-review-dispatch.yml' \ - '.github/workflows/pr812-finalize-attempt-artifact.yml' \ - 'CHANGELOG.md' \ - 'docs/doctoring/opencode-coverage-artifact-reruns.md' \ - 'scripts/ci/prepare_opencode_attempt_artifact_patch.py' | sort)" - actual="$(git diff --name-only HEAD | sort)" - test "$actual" = "$expected" - - - name: Exchange OpenCode app token for workflow-file publication - id: target_app_token - env: - OIDC_AUDIENCE: opencode-github-action - OPENCODE_API_BASE_URL: https://api.opencode.ai - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - test -n "${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-}" - test -n "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" - request_url="$ACTIONS_ID_TOKEN_REQUEST_URL" - separator='&' - case "$request_url" in *\?*) ;; *) separator='?' ;; esac - oidc_response="$( - curl -fsS \ - -H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \ - "${request_url}${separator}audience=${OIDC_AUDIENCE}" - )" - oidc_token="$(jq -r '.value // empty' <<<"$oidc_response")" - test -n "$oidc_token" - token_response="$( - curl -fsS \ - -X POST \ - -H "Authorization: Bearer ${oidc_token}" \ - "${OPENCODE_API_BASE_URL}/exchange_github_app_token" - )" - app_token="$(jq -r '.token // empty' <<<"$token_response")" - test -n "$app_token" - echo "::add-mask::$app_token" - echo "token=$app_token" >>"$GITHUB_OUTPUT" - - - name: Refuse concurrent writers and publish permanent repair - env: - PUSH_TOKEN: ${{ steps.target_app_token.outputs.token }} - TARGET_BRANCH: fix/opencode-attempt-scoped-coverage-artifact - EXPECTED_TRIGGER_HEAD: ${{ github.sha }} - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - test -n "$PUSH_TOKEN" - echo "::add-mask::$PUSH_TOKEN" - live_head="$( - curl -fsS \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${PUSH_TOKEN}" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - https://api.github.com/repos/ContextualWisdomLab/.github/pulls/812 \ - | jq -r '.head.sha // empty' - )" - test "$live_head" = "$EXPECTED_TRIGGER_HEAD" - git config user.name "opencode-agent[bot]" - git config user.email "opencode-agent[bot]@users.noreply.github.com" - git add -A - expected="$(printf '%s\n' \ - '.github/workflows/opencode-review-dispatch.yml' \ - '.github/workflows/pr812-finalize-attempt-artifact.yml' \ - 'CHANGELOG.md' \ - 'docs/doctoring/opencode-coverage-artifact-reruns.md' \ - 'scripts/ci/prepare_opencode_attempt_artifact_patch.py' | sort)" - staged="$(git diff --cached --name-only | sort)" - test "$staged" = "$expected" - git commit -m "fix(opencode): validate current-attempt artifact identity" - test "$(git rev-parse HEAD^)" = "$EXPECTED_TRIGGER_HEAD" - test -z "$(git status --porcelain --untracked-files=all)" - git remote set-url origin "https://x-access-token:${PUSH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" - git push origin "HEAD:refs/heads/${TARGET_BRANCH}" diff --git a/CHANGELOG.md b/CHANGELOG.md index 53e2bfbbc..a4a70fe8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,6 @@ Semantic Versioning where the repository publishes a release. ### Fixed -- Bound OpenCode coverage source artifacts to one workflow attempt and immutable artifact ID, retained one-day source evidence, and made failed-jobs-only reruns fail closed with full-rerun or fresh-dispatch guidance instead of searching for expired or prior-attempt artifacts. +- Bound OpenCode coverage source evidence to a validated immutable artifact ID and producer-attested workflow attempt, retained one-day source evidence, and made selective reruns fail closed before download on missing, malformed, or prior-attempt identity with full-rerun or fresh-dispatch guidance. - Bound both trusted-uv quality jobs to `github.event.pull_request.head.sha` and added a permanent two-checkout regression contract so exact-head compatibility, coverage, docstring, and compilation claims cannot silently measure GitHub's generated pull-request merge revision. - Made Strix treat only a single LiteLLM provider-error line containing NVIDIA NIM context and model-catalog 404 evidence as cross-model fallback evidence, rejecting cross-line signal assembly and provider-like target source literals; moved the public default to Nemotron 3 Super 120B and added a second NVIDIA hosted candidate before GitHub Models without neutralizing reported vulnerabilities. diff --git a/docs/doctoring/opencode-coverage-artifact-reruns.md b/docs/doctoring/opencode-coverage-artifact-reruns.md index f106c51cb..5c57a37ae 100644 --- a/docs/doctoring/opencode-coverage-artifact-reruns.md +++ b/docs/doctoring/opencode-coverage-artifact-reruns.md @@ -4,6 +4,8 @@ The central OpenCode review workflow binds every materialized pull-request merge tree to one workflow-run attempt and one immutable GitHub Actions artifact identifier. The credential-free `coverage-evidence` job may consume only that exact artifact identifier. It never searches by a mutable artifact name and never falls back to an artifact produced by another run or attempt. +The producer also exports a step-recorded literal workflow attempt. Before download, the consumer verifies that this attempt equals its current `github.run_attempt` and that the immutable artifact ID is a positive decimal identifier. Artifact immutability selects one upload; attempt attestation proves that the producer executed in the current attempt. + The source artifact retains the existing one-day retention period. A failed-jobs-only rerun that does not rerun the successful producer is therefore expected to fail closed once that producer artifact expires. The operator response is a **full rerun or a fresh repository dispatch**, both of which rerun `coverage-source-tree` and create current-attempt evidence. Increasing retention or reusing prior-attempt source evidence is not an accepted repair. ## Incident @@ -43,7 +45,8 @@ The implementation must preserve all of the following properties: - `coverage-source-tree` remains the only job with repository-read and OIDC credentials for target-repository materialization. - `coverage-evidence` remains limited to `actions: read`; it receives no repository-content token, OIDC credential, model secret, or review-write credential. - The upload name includes `github.run_attempt` for operator diagnostics and collision resistance. -- The upload step exports the immutable `artifact-id`; the consumer downloads with `artifact-ids` rather than `name`. +- The upload step exports the immutable `artifact-id`; the consumer validates that it is a positive decimal identifier and passes only the validated step output to `download-artifact`. +- The producer exports its step-recorded run attempt; the consumer rejects empty or prior-attempt provenance before download. - Retention remains one day to minimize retention of private source evidence. - Missing current-attempt evidence produces a bounded diagnostic containing the run attempt and the required recovery action. - Exact-head metadata validation, same-repository validation, merge-tree construction, archive-member validation, isolated execution, coverage, docstring, security, and approval gates remain unchanged. @@ -54,13 +57,13 @@ The implementation must preserve all of the following properties: |---|---|---|---| | Fresh repository dispatch | Producer runs and uploads a new attempt-scoped artifact | Downloads the producer's immutable artifact ID | Accepted | | Full workflow rerun | Producer reruns and uploads a new attempt-scoped artifact | Downloads the new immutable artifact ID | Accepted | -| Failed-jobs-only rerun while producer is omitted | No current-attempt producer output exists | Fails closed with recovery guidance | Expected failure | +| Failed-jobs-only rerun while producer is omitted | Producer attempt marker or artifact ID is missing or belongs to an earlier attempt | Rejects identity before download | Expected failure | | Attempt to reuse an earlier artifact by name | Current-attempt identity is not proven | Rejected by contract | Rejected | | Increase retention to hide missing producer execution | Stale source remains available longer | Does not repair attempt identity | Rejected | ## Security and privacy rationale -Artifact immutability prevents later jobs from mutating a successfully uploaded archive, but immutability alone does not identify which workflow attempt produced the archive. The producer's exact `artifact-id` closes that ambiguity. Attempt-qualified naming remains useful for diagnostics, while ID-based selection is the authoritative binding. +Artifact immutability prevents later jobs from mutating a successfully uploaded archive, but immutability alone does not identify which workflow attempt produced the archive. The producer's exact `artifact-id` closes upload-selection ambiguity, while its step-recorded attempt closes execution-attempt ambiguity. The consumer validates both before download; attempt-qualified names remain diagnostic only. The one-day retention period is intentionally short because the archive can contain proprietary or otherwise sensitive source code. Recovery must create fresh, exact-head evidence rather than preserve source archives for a longer period. No product test executes in the credentialed producer. No trusted follow-up consumes command files after untrusted coverage execution begins. @@ -73,10 +76,11 @@ Rollback consists of reverting the attempt-scoped producer output and exact-ID c The permanent regression suite must verify: 1. attempt-scoped artifact naming and immutable `artifact-id` producer output; -2. exact-ID download by the consumer; -3. actionable failure for a missing current-attempt artifact; -4. one-day retention; and -5. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`. +2. producer-attested attempt output and pre-download current-attempt equality; +3. positive-decimal artifact-ID validation and exact-ID download; +4. actionable failure for missing, malformed, or prior-attempt evidence; +5. one-day retention; and +6. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`. The complete repository test suite, Python compilation, production statement and branch coverage, public docstring gate, security and supply-chain checks, current-head review, independent approval, and protected merge remain required. diff --git a/scripts/ci/prepare_opencode_attempt_artifact_patch.py b/scripts/ci/prepare_opencode_attempt_artifact_patch.py deleted file mode 100644 index d6bfe0a95..000000000 --- a/scripts/ci/prepare_opencode_attempt_artifact_patch.py +++ /dev/null @@ -1,293 +0,0 @@ -#!/usr/bin/env python3 -"""Materialize the current-attempt OpenCode artifact identity repair. - -This helper is temporary branch-local tooling. The finalizer removes it before -publishing the verified permanent workflow, doctoring, and changelog changes. -""" - -from __future__ import annotations - -from pathlib import Path - - -WORKFLOW_PATH = Path(".github/workflows/opencode-review-dispatch.yml") -DOCTORING_PATH = Path("docs/doctoring/opencode-coverage-artifact-reruns.md") -CHANGELOG_PATH = Path("CHANGELOG.md") - - -def expression(value: str) -> str: - """Return a literal GitHub Actions expression without early evaluation.""" - return "$" + "{{ " + value + " }}" - - -def unique_index( - lines: list[str], - needle: str, - *, - start: int = 0, - end: int | None = None, - label: str, -) -> int: - """Return the sole exact line match inside the requested bounds.""" - stop = len(lines) if end is None else end - matches = [index for index in range(start, stop) if lines[index] == needle] - if len(matches) != 1: - raise SystemExit(f"Expected one {label}, found {len(matches)}.") - return matches[0] - - -def patch_workflow() -> None: - """Require producer-attempt and artifact-ID identity before download.""" - lines = WORKFLOW_PATH.read_text(encoding="utf-8").splitlines(keepends=True) - producer = unique_index(lines, " coverage-source-tree:\n", label="producer job") - consumer = unique_index(lines, " coverage-evidence:\n", label="consumer job") - - artifact_output = ( - " coverage_source_artifact_id: " - + expression("steps.coverage_source_upload.outputs.artifact-id") - + "\n" - ) - output_index = unique_index( - lines, - artifact_output, - start=producer, - end=consumer, - label="artifact ID output", - ) - attempt_output = ( - " coverage_source_run_attempt: " - + expression("steps.coverage_source_attempt.outputs.run_attempt") - + "\n" - ) - if attempt_output in lines[producer:consumer]: - raise SystemExit("Producer attempt output already exists.") - lines.insert(output_index + 1, attempt_output) - - producer = unique_index(lines, " coverage-source-tree:\n", label="producer job") - consumer = unique_index(lines, " coverage-evidence:\n", label="consumer job") - upload = unique_index( - lines, - " - name: Upload materialized pull request merge tree\n", - start=producer, - end=consumer, - label="upload step", - ) - if " id: coverage_source_attempt\n" in lines[producer:consumer]: - raise SystemExit("Producer attempt step already exists.") - lines[upload:upload] = [ - " - name: Record coverage source workflow attempt\n", - " id: coverage_source_attempt\n", - " env:\n", - " GITHUB_RUN_ATTEMPT: " + expression("github.run_attempt") + "\n", - " shell: bash --noprofile --norc -e -o pipefail {0}\n", - " run: |\n", - " if ! [[ \"$GITHUB_RUN_ATTEMPT\" =~ ^[1-9][0-9]*$ ]]; then\n", - " echo \"::error::Coverage producer workflow attempt is not a positive integer.\"\n", - " exit 1\n", - " fi\n", - " printf 'run_attempt=%s\\n' \"$GITHUB_RUN_ATTEMPT\" >>\"$GITHUB_OUTPUT\"\n", - "\n", - ] - - consumer = unique_index(lines, " coverage-evidence:\n", label="consumer job") - review = unique_index( - lines, - " opencode-review-target:\n", - start=consumer, - label="review job", - ) - download = unique_index( - lines, - " - name: Download current-attempt materialized pull request merge tree\n", - start=consumer, - end=review, - label="download step", - ) - if " id: coverage_source_identity\n" in lines[consumer:review]: - raise SystemExit("Coverage source identity step already exists.") - lines[download:download] = [ - " - name: Verify coverage source identity for current workflow attempt\n", - " id: coverage_source_identity\n", - " continue-on-error: true\n", - " env:\n", - " COVERAGE_SOURCE_ARTIFACT_ID: " - + expression("needs.coverage-source-tree.outputs.coverage_source_artifact_id") - + "\n", - " COVERAGE_SOURCE_RUN_ATTEMPT: " - + expression("needs.coverage-source-tree.outputs.coverage_source_run_attempt") - + "\n", - " CURRENT_RUN_ATTEMPT: " + expression("github.run_attempt") + "\n", - " shell: bash --noprofile --norc -e -o pipefail {0}\n", - " run: |\n", - " if ! [[ \"$CURRENT_RUN_ATTEMPT\" =~ ^[1-9][0-9]*$ ]] || \\\n", - " [ \"$COVERAGE_SOURCE_RUN_ATTEMPT\" != \"$CURRENT_RUN_ATTEMPT\" ]; then\n", - " echo \"::error::Coverage source was not produced in current workflow attempt ${CURRENT_RUN_ATTEMPT:-missing}; producer attempt=${COVERAGE_SOURCE_RUN_ATTEMPT:-missing}.\"\n", - " echo \"::error::Use a full rerun or a fresh repository dispatch; failed-jobs-only reruns cannot reuse prior-attempt source evidence.\"\n", - " exit 1\n", - " fi\n", - " if ! [[ \"$COVERAGE_SOURCE_ARTIFACT_ID\" =~ ^[1-9][0-9]*$ ]]; then\n", - " echo \"::error::Coverage source artifact ID is missing or malformed for current workflow attempt.\"\n", - " echo \"::error::Use a full rerun or a fresh repository dispatch so the producer publishes current-attempt evidence.\"\n", - " exit 1\n", - " fi\n", - " artifact_id=$COVERAGE_SOURCE_ARTIFACT_ID\n", - " printf 'artifact_id=%s\\n' \"$artifact_id\" >>\"$GITHUB_OUTPUT\"\n", - "\n", - ] - - consumer = unique_index(lines, " coverage-evidence:\n", label="consumer job") - review = unique_index(lines, " opencode-review-target:\n", start=consumer, label="review job") - download = unique_index( - lines, - " - name: Download current-attempt materialized pull request merge tree\n", - start=consumer, - end=review, - label="download step after identity", - ) - if lines[download + 1] != " id: coverage_source_download\n": - raise SystemExit("Download ID anchor changed.") - lines.insert(download + 1, " if: steps.coverage_source_identity.outcome == 'success'\n") - - direct_input = ( - " artifact-ids: " - + expression("needs.coverage-source-tree.outputs.coverage_source_artifact_id") - + "\n" - ) - direct_index = unique_index( - lines, - direct_input, - start=download, - end=review, - label="direct artifact input", - ) - lines[direct_index] = ( - " artifact-ids: " - + expression("steps.coverage_source_identity.outputs.artifact_id") - + "\n" - ) - - report = unique_index( - lines, - " - name: Report missing current-attempt coverage source\n", - start=download, - end=review, - label="missing source report", - ) - expected_if = " if: steps.coverage_source_download.outcome != 'success'\n" - if lines[report + 1] != expected_if: - raise SystemExit("Missing source report condition changed.") - lines[report + 1] = ( - " if: steps.coverage_source_identity.outcome != 'success' || " - "steps.coverage_source_download.outcome != 'success'\n" - ) - WORKFLOW_PATH.write_text("".join(lines), encoding="utf-8") - - -def patch_doctoring() -> None: - """Document artifact immutability separately from producer provenance.""" - text = DOCTORING_PATH.read_text(encoding="utf-8") - anchor = "The source artifact retains the existing one-day retention period. " - insertion = ( - "The producer also exports a step-recorded literal workflow attempt. Before " - "download, the consumer verifies that this attempt equals its current " - "`github.run_attempt` and that the immutable artifact ID is a positive decimal " - "identifier. Artifact immutability selects one upload; attempt attestation proves " - "that the producer executed in the current attempt.\n\n" + anchor - ) - if text.count(anchor) != 1: - raise SystemExit("Doctoring decision anchor changed.") - text = text.replace(anchor, insertion, 1) - - bullet = ( - "- The upload step exports the immutable `artifact-id`; the consumer downloads " - "with `artifact-ids` rather than `name`.\n" - ) - replacement = ( - "- The upload step exports the immutable `artifact-id`; the consumer validates " - "that it is a positive decimal identifier and passes only the validated step " - "output to `download-artifact`.\n" - "- The producer exports its step-recorded run attempt; the consumer rejects empty " - "or prior-attempt provenance before download.\n" - ) - if text.count(bullet) != 1: - raise SystemExit("Doctoring contract bullet anchor changed.") - text = text.replace(bullet, replacement, 1) - - table_old = ( - "| Failed-jobs-only rerun while producer is omitted | No current-attempt producer " - "output exists | Fails closed with recovery guidance | Expected failure |" - ) - table_new = ( - "| Failed-jobs-only rerun while producer is omitted | Producer attempt marker or " - "artifact ID is missing or belongs to an earlier attempt | Rejects identity before " - "download | Expected failure |" - ) - if text.count(table_old) != 1: - raise SystemExit("Doctoring rerun table anchor changed.") - text = text.replace(table_old, table_new, 1) - - rationale_old = ( - "The producer's exact `artifact-id` closes that ambiguity. Attempt-qualified naming " - "remains useful for diagnostics, while ID-based selection is the authoritative " - "binding.\n" - ) - rationale_new = ( - "The producer's exact `artifact-id` closes upload-selection ambiguity, while its " - "step-recorded attempt closes execution-attempt ambiguity. The consumer validates " - "both before download; attempt-qualified names remain diagnostic only.\n" - ) - if text.count(rationale_old) != 1: - raise SystemExit("Doctoring rationale anchor changed.") - text = text.replace(rationale_old, rationale_new, 1) - - verification_old = ( - "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" - "2. exact-ID download by the consumer;\n" - "3. actionable failure for a missing current-attempt artifact;\n" - "4. one-day retention; and\n" - "5. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" - ) - verification_new = ( - "1. attempt-scoped artifact naming and immutable `artifact-id` producer output;\n" - "2. producer-attested attempt output and pre-download current-attempt equality;\n" - "3. positive-decimal artifact-ID validation and exact-ID download;\n" - "4. actionable failure for missing, malformed, or prior-attempt evidence;\n" - "5. one-day retention; and\n" - "6. absence of repository, OIDC, secret, and review-write credentials from `coverage-evidence`.\n" - ) - if text.count(verification_old) != 1: - raise SystemExit("Doctoring verification anchor changed.") - DOCTORING_PATH.write_text( - text.replace(verification_old, verification_new, 1), encoding="utf-8" - ) - - -def patch_changelog() -> None: - """Record current-attempt provenance and bounded identifier validation.""" - text = CHANGELOG_PATH.read_text(encoding="utf-8") - old = ( - "- Bound OpenCode coverage source artifacts to one workflow attempt and immutable " - "artifact ID, retained one-day source evidence, and made failed-jobs-only reruns " - "fail closed with full-rerun or fresh-dispatch guidance instead of searching for " - "expired or prior-attempt artifacts.\n" - ) - new = ( - "- Bound OpenCode coverage source evidence to a validated immutable artifact ID and " - "producer-attested workflow attempt, retained one-day source evidence, and made " - "selective reruns fail closed before download on missing, malformed, or prior-attempt " - "identity with full-rerun or fresh-dispatch guidance.\n" - ) - if text.count(old) != 1: - raise SystemExit("CHANGELOG artifact identity entry changed.") - CHANGELOG_PATH.write_text(text.replace(old, new, 1), encoding="utf-8") - - -def main() -> None: - """Apply the permanent workflow, doctoring, and changelog repair.""" - patch_workflow() - patch_doctoring() - patch_changelog() - - -if __name__ == "__main__": - main() From 981aca36f1adae9febb112ebcf5655ce7aa85a32 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:48:08 +0900 Subject: [PATCH 41/56] chore(opencode): remove third PR-controlled finalizer --- .../pr812-finalize-attempt-artifact-v3.yml | 102 ------------------ 1 file changed, 102 deletions(-) delete mode 100644 .github/workflows/pr812-finalize-attempt-artifact-v3.yml diff --git a/.github/workflows/pr812-finalize-attempt-artifact-v3.yml b/.github/workflows/pr812-finalize-attempt-artifact-v3.yml deleted file mode 100644 index 02d21c1fa..000000000 --- a/.github/workflows/pr812-finalize-attempt-artifact-v3.yml +++ /dev/null @@ -1,102 +0,0 @@ -name: PR 812 Finalize Attempt Artifact Handoff V3 - -on: - push: - branches: - - fix/opencode-attempt-scoped-coverage-artifact - paths: - - .github/workflows/pr812-finalize-attempt-artifact-v3.yml - -concurrency: - group: pr812-finalize-attempt-artifact-v3 - cancel-in-progress: false - -permissions: - contents: write - -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - -jobs: - finalize: - if: >- - github.repository == 'ContextualWisdomLab/.github' && - github.ref == 'refs/heads/fix/opencode-attempt-scoped-coverage-artifact' - runs-on: ubuntu-24.04 - timeout-minutes: 35 - steps: - - name: Harden runner - uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 - with: - egress-policy: audit - - - name: Checkout exact trigger head - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - ref: ${{ github.sha }} - fetch-depth: 2 - persist-credentials: true - - - name: Refuse concurrent branch movement - env: - EXPECTED_SHA: ${{ github.sha }} - EXPECTED_BRANCH: fix/opencode-attempt-scoped-coverage-artifact - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - test "$(git rev-parse HEAD)" = "$EXPECTED_SHA" - remote_sha="$(git ls-remote origin "refs/heads/$EXPECTED_BRANCH" | awk '{print $1}')" - test "$remote_sha" = "$EXPECTED_SHA" - - - name: Set up Python 3.14 - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 - with: - python-version: "3.14" - cache: pip - cache-dependency-path: requirements-opencode-review-ci-hashes.txt - - - name: Install exact hash-locked quality tooling - run: >- - python -m pip install --disable-pip-version-check --require-hashes - -r requirements-opencode-review-ci-hashes.txt - - - name: Apply reviewed permanent repair and remove transient source - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - python scripts/ci/prepare_opencode_attempt_artifact_patch.py - rm -- scripts/ci/prepare_opencode_attempt_artifact_patch.py - rm -- .github/workflows/pr812-finalize-attempt-artifact-v3.yml - git diff --check - - - name: Verify focused and complete GREEN evidence - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - python -m pytest -q tests/test_opencode_coverage_artifact_rerun_contract.py - python -m coverage erase - python -m coverage run -m pytest tests -q - python -m coverage report --show-missing --fail-under=100 - python -m interrogate . - python -m compileall -q scripts tests - git diff --check - expected="$(printf '%s\n' \ - '.github/workflows/opencode-review-dispatch.yml' \ - '.github/workflows/pr812-finalize-attempt-artifact-v3.yml' \ - 'CHANGELOG.md' \ - 'docs/doctoring/opencode-coverage-artifact-reruns.md' \ - 'scripts/ci/prepare_opencode_attempt_artifact_patch.py' | sort)" - actual="$(git diff --name-only HEAD | sort)" - test "$actual" = "$expected" - - - name: Publish verified five-file repair - env: - EXPECTED_SHA: ${{ github.sha }} - EXPECTED_BRANCH: fix/opencode-attempt-scoped-coverage-artifact - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - remote_sha="$(git ls-remote origin "refs/heads/$EXPECTED_BRANCH" | awk '{print $1}')" - test "$remote_sha" = "$EXPECTED_SHA" - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add -A - git commit -m "fix(opencode): validate current-attempt artifact identity before download" - test "$(git rev-parse HEAD^)" = "$EXPECTED_SHA" - git push origin "HEAD:refs/heads/$EXPECTED_BRANCH" From ac87c6a8469ce49054b3dd172fdd829817c24979 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:50:07 +0900 Subject: [PATCH 42/56] test(opencode): reject renamed branch repair workflows --- ...encode_coverage_artifact_rerun_contract.py | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/tests/test_opencode_coverage_artifact_rerun_contract.py b/tests/test_opencode_coverage_artifact_rerun_contract.py index 966046548..e20859a69 100644 --- a/tests/test_opencode_coverage_artifact_rerun_contract.py +++ b/tests/test_opencode_coverage_artifact_rerun_contract.py @@ -4,12 +4,13 @@ WORKFLOW_PATH = Path(".github/workflows/opencode-review-dispatch.yml") -TEMPORARY_REPAIR_PATHS = ( - Path(".github/opencode-attempt-scoped-coverage-artifact.trigger"), - Path(".github/workflows/materialize-opencode-attempt-scoped-coverage-artifact.yml"), - Path(".github/workflows/opencode-coverage-artifact-rerun-repair.yml"), - Path(".github/workflows/pr812-finalize-attempt-artifact.yml"), - Path("scripts/ci/prepare_opencode_attempt_artifact_patch.py"), +TEMPORARY_REPAIR_GLOBS = ( + ".github/opencode-attempt-scoped-coverage-artifact*.trigger", + ".github/pr812*.trigger", + ".github/workflows/*opencode*artifact*materializ*.yml", + ".github/workflows/*opencode*artifact*repair*.yml", + ".github/workflows/pr812-finalize*.yml", + "scripts/ci/*opencode*artifact*patch*.py", ) @@ -125,5 +126,12 @@ def test_coverage_consumer_remains_credential_free() -> None: def test_temporary_branch_writers_are_absent_from_final_tree() -> None: - """Keep transient materializers and repair branch writers out of the PR.""" - assert [str(path) for path in TEMPORARY_REPAIR_PATHS if path.exists()] == [] + """Reject versioned or renamed materializers and branch finalizers.""" + unexpected = sorted( + { + str(path) + for pattern in TEMPORARY_REPAIR_GLOBS + for path in Path(".").glob(pattern) + } + ) + assert unexpected == [] From 97e4f35dc47d1f1c94ec0ca5599c528fa43f2b12 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 09:50:30 +0900 Subject: [PATCH 43/56] fix(opencode): bind quality gate to production config --- .../workflows/opencode-coverage-artifact-rerun-quality-ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml b/.github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml index 770373a1f..d83753f81 100644 --- a/.github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml +++ b/.github/workflows/opencode-coverage-artifact-rerun-quality-ci.yml @@ -10,6 +10,7 @@ on: - "docs/doctoring/opencode-coverage-artifact-reruns.md" - "CHANGELOG.md" - "requirements-opencode-review-ci-hashes.txt" + - "pyproject.toml" push: branches: [main] paths: @@ -19,6 +20,7 @@ on: - "docs/doctoring/opencode-coverage-artifact-reruns.md" - "CHANGELOG.md" - "requirements-opencode-review-ci-hashes.txt" + - "pyproject.toml" concurrency: group: opencode-coverage-artifact-rerun-${{ github.event.pull_request.number || github.ref }} @@ -68,7 +70,7 @@ jobs: python -m coverage report --show-missing - name: Enforce production docstring coverage - run: python -m interrogate . + run: python -m interrogate scripts/ci - name: Compile permanent contracts run: python -m compileall -q scripts tests From 3291678df0ba109f677f920f4c1880e3c3f12fea Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 11:01:31 +0900 Subject: [PATCH 44/56] test(opencode): require reachable rerun recovery guidance --- ...encode_coverage_artifact_rerun_contract.py | 77 +++++++++++++++---- 1 file changed, 64 insertions(+), 13 deletions(-) diff --git a/tests/test_opencode_coverage_artifact_rerun_contract.py b/tests/test_opencode_coverage_artifact_rerun_contract.py index e20859a69..af965a148 100644 --- a/tests/test_opencode_coverage_artifact_rerun_contract.py +++ b/tests/test_opencode_coverage_artifact_rerun_contract.py @@ -26,6 +26,13 @@ def _job_block(workflow: str, job_name: str, next_job_name: str) -> str: return workflow[start:end] +def _step_block(job: str, step_name: str, next_step_name: str) -> str: + """Return one workflow step bounded by the following named step.""" + start = job.index(f" - name: {step_name}\n") + end = job.index(f"\n - name: {next_step_name}\n", start) + return job[start:end] + + def test_coverage_source_artifact_is_attempt_scoped_and_downloaded_by_id() -> None: """Bind every producer attempt to its immutable uploaded artifact ID.""" workflow = _workflow_text() @@ -49,9 +56,6 @@ def test_coverage_source_artifact_is_attempt_scoped_and_downloaded_by_id() -> No ) assert '[[ "$COVERAGE_SOURCE_ARTIFACT_ID" =~ ^[1-9][0-9]*$ ]]' in evidence_job assert "artifact_id=$COVERAGE_SOURCE_ARTIFACT_ID" in evidence_job - assert ( - "if: steps.coverage_source_identity.outcome == 'success'" in evidence_job - ) assert ( "artifact-ids: ${{ steps.coverage_source_identity.outputs.artifact_id }}" in evidence_job @@ -97,19 +101,66 @@ def test_coverage_source_requires_current_producer_attempt() -> None: def test_missing_current_attempt_artifact_fails_with_fresh_run_guidance() -> None: - """Reject partial reruns instead of falling back to stale source evidence.""" + """Keep recovery guidance reachable for every absent producer or download.""" workflow = _workflow_text() evidence_job = _job_block(workflow, "coverage-evidence", "opencode-review-target") + producer_diagnostic = _step_block( + evidence_job, + "Report coverage source materialization failure", + "Verify coverage source identity for current workflow attempt", + ) + identity = _step_block( + evidence_job, + "Verify coverage source identity for current workflow attempt", + "Download current-attempt materialized pull request merge tree", + ) + download = _step_block( + evidence_job, + "Download current-attempt materialized pull request merge tree", + "Report missing current-attempt coverage source", + ) + recovery = _step_block( + evidence_job, + "Report missing current-attempt coverage source", + "Prepare pull request merge tree for coverage measurement", + ) - assert "id: coverage_source_identity" in evidence_job - assert "id: coverage_source_download" in evidence_job - assert evidence_job.count("continue-on-error: true") >= 2 - assert "steps.coverage_source_identity.outcome != 'success'" in evidence_job - assert "steps.coverage_source_download.outcome != 'success'" in evidence_job - assert "failed-jobs-only rerun" in evidence_job - assert "full rerun or a fresh repository dispatch" in evidence_job - assert "GITHUB_RUN_ATTEMPT" in evidence_job - assert "exit 1" in evidence_job + assert "always()" in evidence_job.split(" runs-on:", 1)[0] + assert "needs.coverage-source-tree.result != 'cancelled'" not in evidence_job + assert "needs.coverage-source-tree.result != 'success'" in producer_diagnostic + assert "exit 1" not in producer_diagnostic + + assert "id: coverage_source_identity" in identity + assert "continue-on-error: true" in identity + assert "if: needs.coverage-source-tree.result == 'success'" in identity + + assert "id: coverage_source_download" in download + assert "continue-on-error: true" in download + assert "needs.coverage-source-tree.result == 'success'" in download + assert "steps.coverage_source_identity.outcome == 'success'" in download + + assert "always()" in recovery + assert "needs.coverage-source-tree.result != 'success'" in recovery + assert "steps.coverage_source_identity.outcome != 'success'" in recovery + assert "steps.coverage_source_download.outcome != 'success'" in recovery + assert "failed-jobs-only rerun" in recovery + assert "full rerun or a fresh repository dispatch" in recovery + assert "GITHUB_RUN_ATTEMPT" in recovery + assert "exit 1" in recovery + + diagnostic_index = evidence_job.index( + "- name: Report coverage source materialization failure" + ) + identity_index = evidence_job.index( + "- name: Verify coverage source identity for current workflow attempt" + ) + download_index = evidence_job.index( + "- name: Download current-attempt materialized pull request merge tree" + ) + recovery_index = evidence_job.index( + "- name: Report missing current-attempt coverage source" + ) + assert diagnostic_index < identity_index < download_index < recovery_index def test_coverage_consumer_remains_credential_free() -> None: From 77e06f5372ae60bccb618af8c09fbffa0b41b93a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 11:11:44 +0900 Subject: [PATCH 45/56] test(opencode): align rerun contract to fail-closed implementation --- ...encode_coverage_artifact_rerun_contract.py | 82 +++++-------------- 1 file changed, 19 insertions(+), 63 deletions(-) diff --git a/tests/test_opencode_coverage_artifact_rerun_contract.py b/tests/test_opencode_coverage_artifact_rerun_contract.py index af965a148..f9f05b1dc 100644 --- a/tests/test_opencode_coverage_artifact_rerun_contract.py +++ b/tests/test_opencode_coverage_artifact_rerun_contract.py @@ -26,13 +26,6 @@ def _job_block(workflow: str, job_name: str, next_job_name: str) -> str: return workflow[start:end] -def _step_block(job: str, step_name: str, next_step_name: str) -> str: - """Return one workflow step bounded by the following named step.""" - start = job.index(f" - name: {step_name}\n") - end = job.index(f"\n - name: {next_step_name}\n", start) - return job[start:end] - - def test_coverage_source_artifact_is_attempt_scoped_and_downloaded_by_id() -> None: """Bind every producer attempt to its immutable uploaded artifact ID.""" workflow = _workflow_text() @@ -90,7 +83,9 @@ def test_coverage_source_requires_current_producer_attempt() -> None: ) assert "CURRENT_RUN_ATTEMPT: ${{ github.run_attempt }}" in evidence_job assert '[ "$COVERAGE_SOURCE_RUN_ATTEMPT" != "$CURRENT_RUN_ATTEMPT" ]' in evidence_job + assert "failed-jobs-only reruns cannot reuse prior-attempt source evidence" in evidence_job assert "full rerun or a fresh repository dispatch" in evidence_job + guard_index = evidence_job.index( "- name: Verify coverage source identity for current workflow attempt" ) @@ -100,67 +95,28 @@ def test_coverage_source_requires_current_producer_attempt() -> None: assert guard_index < download_index -def test_missing_current_attempt_artifact_fails_with_fresh_run_guidance() -> None: - """Keep recovery guidance reachable for every absent producer or download.""" +def test_missing_or_expired_artifact_fails_with_bounded_recovery_guidance() -> None: + """Fail closed on absent exact evidence without searching earlier attempts.""" workflow = _workflow_text() evidence_job = _job_block(workflow, "coverage-evidence", "opencode-review-target") - producer_diagnostic = _step_block( - evidence_job, - "Report coverage source materialization failure", - "Verify coverage source identity for current workflow attempt", - ) - identity = _step_block( - evidence_job, - "Verify coverage source identity for current workflow attempt", - "Download current-attempt materialized pull request merge tree", - ) - download = _step_block( - evidence_job, - "Download current-attempt materialized pull request merge tree", - "Report missing current-attempt coverage source", - ) - recovery = _step_block( - evidence_job, - "Report missing current-attempt coverage source", - "Prepare pull request merge tree for coverage measurement", - ) - assert "always()" in evidence_job.split(" runs-on:", 1)[0] - assert "needs.coverage-source-tree.result != 'cancelled'" not in evidence_job - assert "needs.coverage-source-tree.result != 'success'" in producer_diagnostic - assert "exit 1" not in producer_diagnostic - - assert "id: coverage_source_identity" in identity - assert "continue-on-error: true" in identity - assert "if: needs.coverage-source-tree.result == 'success'" in identity - - assert "id: coverage_source_download" in download - assert "continue-on-error: true" in download - assert "needs.coverage-source-tree.result == 'success'" in download - assert "steps.coverage_source_identity.outcome == 'success'" in download - - assert "always()" in recovery - assert "needs.coverage-source-tree.result != 'success'" in recovery - assert "steps.coverage_source_identity.outcome != 'success'" in recovery - assert "steps.coverage_source_download.outcome != 'success'" in recovery - assert "failed-jobs-only rerun" in recovery - assert "full rerun or a fresh repository dispatch" in recovery - assert "GITHUB_RUN_ATTEMPT" in recovery - assert "exit 1" in recovery - - diagnostic_index = evidence_job.index( - "- name: Report coverage source materialization failure" - ) - identity_index = evidence_job.index( - "- name: Verify coverage source identity for current workflow attempt" - ) - download_index = evidence_job.index( - "- name: Download current-attempt materialized pull request merge tree" + assert "id: coverage_source_identity" in evidence_job + assert "continue-on-error: true" in evidence_job + assert "id: coverage_source_download" in evidence_job + assert ( + "if: steps.coverage_source_identity.outcome == 'success'" in evidence_job ) - recovery_index = evidence_job.index( - "- name: Report missing current-attempt coverage source" + assert ( + "if: steps.coverage_source_identity.outcome != 'success' || " + "steps.coverage_source_download.outcome != 'success'" + in evidence_job ) - assert diagnostic_index < identity_index < download_index < recovery_index + assert "failed-jobs-only rerun" in evidence_job + assert "full rerun or a fresh repository dispatch" in evidence_job + assert "GITHUB_RUN_ATTEMPT" in evidence_job + assert "exit 1" in evidence_job + assert "list-artifacts" not in evidence_job + assert "latest" not in evidence_job.lower() def test_coverage_consumer_remains_credential_free() -> None: From 600fbb49c37f67655d397a3faff15ba4f26db4c3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 11:22:55 +0900 Subject: [PATCH 46/56] test(opencode): scope rerun recovery assertions to exact steps --- ...encode_coverage_artifact_rerun_contract.py | 89 +++++++++++++------ 1 file changed, 61 insertions(+), 28 deletions(-) diff --git a/tests/test_opencode_coverage_artifact_rerun_contract.py b/tests/test_opencode_coverage_artifact_rerun_contract.py index f9f05b1dc..ed3d0f845 100644 --- a/tests/test_opencode_coverage_artifact_rerun_contract.py +++ b/tests/test_opencode_coverage_artifact_rerun_contract.py @@ -26,6 +26,13 @@ def _job_block(workflow: str, job_name: str, next_job_name: str) -> str: return workflow[start:end] +def _step_block(job: str, step_name: str, next_step_name: str) -> str: + """Return one workflow step bounded by the following named step.""" + start = job.index(f" - name: {step_name}\n") + end = job.index(f"\n - name: {next_step_name}\n", start) + return job[start:end] + + def test_coverage_source_artifact_is_attempt_scoped_and_downloaded_by_id() -> None: """Bind every producer attempt to its immutable uploaded artifact ID.""" workflow = _workflow_text() @@ -41,24 +48,34 @@ def test_coverage_source_artifact_is_attempt_scoped_and_downloaded_by_id() -> No assert "name: opencode-coverage-source-${{ github.run_attempt }}" in source_job assert "retention-days: 1" in source_job - assert "id: coverage_source_identity" in evidence_job + identity = _step_block( + evidence_job, + "Verify coverage source identity for current workflow attempt", + "Download current-attempt materialized pull request merge tree", + ) + download = _step_block( + evidence_job, + "Download current-attempt materialized pull request merge tree", + "Report missing current-attempt coverage source", + ) + assert "id: coverage_source_identity" in identity assert ( "COVERAGE_SOURCE_ARTIFACT_ID: " "${{ needs.coverage-source-tree.outputs.coverage_source_artifact_id }}" - in evidence_job + in identity ) - assert '[[ "$COVERAGE_SOURCE_ARTIFACT_ID" =~ ^[1-9][0-9]*$ ]]' in evidence_job - assert "artifact_id=$COVERAGE_SOURCE_ARTIFACT_ID" in evidence_job + assert '[[ "$COVERAGE_SOURCE_ARTIFACT_ID" =~ ^[1-9][0-9]*$ ]]' in identity + assert "artifact_id=$COVERAGE_SOURCE_ARTIFACT_ID" in identity assert ( "artifact-ids: ${{ steps.coverage_source_identity.outputs.artifact_id }}" - in evidence_job + in download ) assert ( "artifact-ids: " "${{ needs.coverage-source-tree.outputs.coverage_source_artifact_id }}" - not in evidence_job + not in download ) - assert "name: opencode-coverage-source\n" not in evidence_job + assert "name: opencode-coverage-source\n" not in download def test_coverage_source_requires_current_producer_attempt() -> None: @@ -66,6 +83,11 @@ def test_coverage_source_requires_current_producer_attempt() -> None: workflow = _workflow_text() source_job = _job_block(workflow, "coverage-source-tree", "coverage-evidence") evidence_job = _job_block(workflow, "coverage-evidence", "opencode-review-target") + identity = _step_block( + evidence_job, + "Verify coverage source identity for current workflow attempt", + "Download current-attempt materialized pull request merge tree", + ) assert ( "coverage_source_run_attempt: " @@ -79,12 +101,12 @@ def test_coverage_source_requires_current_producer_attempt() -> None: assert ( "COVERAGE_SOURCE_RUN_ATTEMPT: " "${{ needs.coverage-source-tree.outputs.coverage_source_run_attempt }}" - in evidence_job + in identity ) - assert "CURRENT_RUN_ATTEMPT: ${{ github.run_attempt }}" in evidence_job - assert '[ "$COVERAGE_SOURCE_RUN_ATTEMPT" != "$CURRENT_RUN_ATTEMPT" ]' in evidence_job - assert "failed-jobs-only reruns cannot reuse prior-attempt source evidence" in evidence_job - assert "full rerun or a fresh repository dispatch" in evidence_job + assert "CURRENT_RUN_ATTEMPT: ${{ github.run_attempt }}" in identity + assert '[ "$COVERAGE_SOURCE_RUN_ATTEMPT" != "$CURRENT_RUN_ATTEMPT" ]' in identity + assert "failed-jobs-only reruns cannot reuse prior-attempt source evidence" in identity + assert "full rerun or a fresh repository dispatch" in identity guard_index = evidence_job.index( "- name: Verify coverage source identity for current workflow attempt" @@ -99,24 +121,35 @@ def test_missing_or_expired_artifact_fails_with_bounded_recovery_guidance() -> N """Fail closed on absent exact evidence without searching earlier attempts.""" workflow = _workflow_text() evidence_job = _job_block(workflow, "coverage-evidence", "opencode-review-target") - - assert "id: coverage_source_identity" in evidence_job - assert "continue-on-error: true" in evidence_job - assert "id: coverage_source_download" in evidence_job - assert ( - "if: steps.coverage_source_identity.outcome == 'success'" in evidence_job + identity = _step_block( + evidence_job, + "Verify coverage source identity for current workflow attempt", + "Download current-attempt materialized pull request merge tree", ) - assert ( - "if: steps.coverage_source_identity.outcome != 'success' || " - "steps.coverage_source_download.outcome != 'success'" - in evidence_job + download = _step_block( + evidence_job, + "Download current-attempt materialized pull request merge tree", + "Report missing current-attempt coverage source", ) - assert "failed-jobs-only rerun" in evidence_job - assert "full rerun or a fresh repository dispatch" in evidence_job - assert "GITHUB_RUN_ATTEMPT" in evidence_job - assert "exit 1" in evidence_job - assert "list-artifacts" not in evidence_job - assert "latest" not in evidence_job.lower() + recovery = _step_block( + evidence_job, + "Report missing current-attempt coverage source", + "Prepare pull request merge tree for coverage measurement", + ) + + assert "id: coverage_source_identity" in identity + assert "continue-on-error: true" in identity + assert "if: needs.coverage-source-tree.result == 'success'" in identity + assert "id: coverage_source_download" in download + assert "continue-on-error: true" in download + assert "if: steps.coverage_source_identity.outcome == 'success'" in download + assert "steps.coverage_source_identity.outcome != 'success'" in recovery + assert "steps.coverage_source_download.outcome != 'success'" in recovery + assert "failed-jobs-only rerun" in recovery + assert "full rerun or a fresh repository dispatch" in recovery + assert "GITHUB_RUN_ATTEMPT" in recovery + assert "exit 1" in recovery + assert "list-artifacts" not in identity + download + recovery def test_coverage_consumer_remains_credential_free() -> None: From eb8e7217f2eb76ba08e619dbc25fc4e8f10674b9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 11:27:04 +0900 Subject: [PATCH 47/56] chore(ci): materialize PR 812 control-flow repair --- .github/workflows/pr812-control-flow-fix.yml | 236 +++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 .github/workflows/pr812-control-flow-fix.yml diff --git a/.github/workflows/pr812-control-flow-fix.yml b/.github/workflows/pr812-control-flow-fix.yml new file mode 100644 index 000000000..61ea67899 --- /dev/null +++ b/.github/workflows/pr812-control-flow-fix.yml @@ -0,0 +1,236 @@ +name: PR 812 control-flow repair + +on: + push: + branches: [fix/opencode-attempt-scoped-coverage-artifact] + paths: + - ".github/workflows/pr812-control-flow-fix.yml" + +permissions: + contents: read + +jobs: + repair: + if: >- + github.repository == 'ContextualWisdomLab/.github' + && github.ref == 'refs/heads/fix/opencode-attempt-scoped-coverage-artifact' + runs-on: ubuntu-24.04 + timeout-minutes: 15 + permissions: + contents: write + steps: + - name: Check out exact branch head + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + ref: fix/opencode-attempt-scoped-coverage-artifact + fetch-depth: 1 + + - name: Apply test-first control-flow repair + shell: bash --noprofile --norc -e -o pipefail {0} + run: | + git fetch --no-tags origin fix/opencode-attempt-scoped-coverage-artifact + test "$(git rev-parse FETCH_HEAD)" = "$GITHUB_SHA" + + python3 - <<'PY' + from pathlib import Path + + workflow_path = Path(".github/workflows/opencode-review-dispatch.yml") + workflow = workflow_path.read_text(encoding="utf-8") + + old_job = """ coverage-evidence: + name: coverage-evidence + needs: [validate-pr-metadata, coverage-source-tree] + if: >- + always() + && needs.validate-pr-metadata.result == 'success' + && needs.coverage-source-tree.result != 'cancelled' + && github.event_name == 'repository_dispatch' + runs-on: ubuntu-latest + """.replace(" ", "") + new_job = old_job.replace("runs-on: ubuntu-latest", "runs-on: ubuntu-24.04") + if workflow.count(old_job) != 1: + raise SystemExit("coverage-evidence runner block did not match exactly once") + workflow = workflow.replace(old_job, new_job, 1) + + old_diagnostic = """ - name: Report coverage source materialization failure + if: needs.coverage-source-tree.result != 'success' + run: | + echo "::error::Coverage source tree could not be materialized; see the coverage-source-tree job log for the exact target repository, base SHA, head SHA, and fetch or merge failure." + exit 1 + """.replace(" ", "") + new_diagnostic = """ - name: Diagnose coverage source materialization failure + if: always() && needs.coverage-source-tree.result != 'success' + run: | + echo "::error::Coverage source tree could not be materialized; see the coverage-source-tree job log for the exact target repository, base SHA, head SHA, and fetch or merge failure." + echo "::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree can publish exact current-attempt evidence." + """.replace(" ", "") + if workflow.count(old_diagnostic) != 1: + raise SystemExit("coverage-source diagnostic block did not match exactly once") + workflow = workflow.replace(old_diagnostic, new_diagnostic, 1) + + old_identity = """ - name: Verify coverage source identity for current workflow attempt + id: coverage_source_identity + continue-on-error: true + """.replace(" ", "") + new_identity = """ - name: Verify coverage source identity for current workflow attempt + id: coverage_source_identity + if: always() && needs.coverage-source-tree.result == 'success' + continue-on-error: true + """.replace(" ", "") + if workflow.count(old_identity) != 1: + raise SystemExit("coverage-source identity block did not match exactly once") + workflow = workflow.replace(old_identity, new_identity, 1) + + old_download = """ - name: Download current-attempt materialized pull request merge tree + if: steps.coverage_source_identity.outcome == 'success' + id: coverage_source_download + """.replace(" ", "") + new_download = """ - name: Download current-attempt materialized pull request merge tree + if: >- + always() + && needs.coverage-source-tree.result == 'success' + && steps.coverage_source_identity.outcome == 'success' + id: coverage_source_download + """.replace(" ", "") + if workflow.count(old_download) != 1: + raise SystemExit("coverage-source download block did not match exactly once") + workflow = workflow.replace(old_download, new_download, 1) + + old_report = """ - name: Report missing current-attempt coverage source + if: steps.coverage_source_identity.outcome != 'success' || steps.coverage_source_download.outcome != 'success' + env: + GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} + """.replace(" ", "") + new_report = """ - name: Report missing current-attempt coverage source + if: >- + always() + && ( + needs.coverage-source-tree.result != 'success' + || steps.coverage_source_identity.outcome != 'success' + || steps.coverage_source_download.outcome != 'success' + ) + env: + GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} + COVERAGE_SOURCE_RESULT: ${{ needs.coverage-source-tree.result }} + """.replace(" ", "") + if workflow.count(old_report) != 1: + raise SystemExit("missing-source report block did not match exactly once") + workflow = workflow.replace(old_report, new_report, 1) + workflow_path.write_text(workflow, encoding="utf-8") + + test_path = Path("tests/test_opencode_coverage_artifact_rerun_contract.py") + test_text = test_path.read_text(encoding="utf-8") + helper_anchor = """def test_coverage_source_artifact_is_attempt_scoped_and_downloaded_by_id() -> None: + """ + helper = """def _step_block(job: str, step_name: str, next_step_name: str) -> str: + \"\"\"Return one workflow step block bounded by its successor.\"\"\" + start = job.index(f\" - name: {step_name}\\n\") + end = job.index(f\"\\n - name: {next_step_name}\\n\", start) + return job[start:end] + + + """ + if test_text.count(helper_anchor) != 1 or "def _step_block(" in test_text: + raise SystemExit("test helper insertion anchor was not unique") + test_text = test_text.replace(helper_anchor, helper + helper_anchor, 1) + + old_test = """def test_missing_or_expired_artifact_fails_with_bounded_recovery_guidance() -> None: + \"\"\"Fail closed on absent exact evidence without searching earlier attempts.\"\"\" + workflow = _workflow_text() + evidence_job = _job_block(workflow, \"coverage-evidence\", \"opencode-review-target\") + + assert \"id: coverage_source_identity\" in evidence_job + assert \"continue-on-error: true\" in evidence_job + assert \"id: coverage_source_download\" in evidence_job + assert ( + \"if: steps.coverage_source_identity.outcome == 'success'\" in evidence_job + ) + assert ( + \"if: steps.coverage_source_identity.outcome != 'success' || \" + \"steps.coverage_source_download.outcome != 'success'\" + in evidence_job + ) + assert \"failed-jobs-only rerun\" in evidence_job + assert \"full rerun or a fresh repository dispatch\" in evidence_job + assert \"GITHUB_RUN_ATTEMPT\" in evidence_job + assert \"exit 1\" in evidence_job + assert \"list-artifacts\" not in evidence_job + assert \"latest\" not in evidence_job.lower() + """ + new_test = """def test_missing_or_expired_artifact_fails_with_bounded_recovery_guidance() -> None: + \"\"\"Fail closed while preserving recovery guidance on every producer outcome.\"\"\" + workflow = _workflow_text() + evidence_job = _job_block(workflow, \"coverage-evidence\", \"opencode-review-target\") + diagnostic = _step_block( + evidence_job, + \"Diagnose coverage source materialization failure\", + \"Verify coverage source identity for current workflow attempt\", + ) + identity = _step_block( + evidence_job, + \"Verify coverage source identity for current workflow attempt\", + \"Download current-attempt materialized pull request merge tree\", + ) + download = _step_block( + evidence_job, + \"Download current-attempt materialized pull request merge tree\", + \"Report missing current-attempt coverage source\", + ) + report = _step_block( + evidence_job, + \"Report missing current-attempt coverage source\", + \"Prepare pull request merge tree for coverage measurement\", + ) + + assert \"if: always() && needs.coverage-source-tree.result != 'success'\" in diagnostic + assert \"exit 1\" not in diagnostic + assert \"if: always() && needs.coverage-source-tree.result == 'success'\" in identity + assert \"continue-on-error: true\" in identity + assert \"always()\" in download + assert \"needs.coverage-source-tree.result == 'success'\" in download + assert \"steps.coverage_source_identity.outcome == 'success'\" in download + assert \"always()\" in report + assert \"needs.coverage-source-tree.result != 'success'\" in report + assert \"steps.coverage_source_identity.outcome != 'success'\" in report + assert \"steps.coverage_source_download.outcome != 'success'\" in report + assert \"failed-jobs-only rerun\" in report + assert \"full rerun or a fresh repository dispatch\" in report + assert \"GITHUB_RUN_ATTEMPT\" in report + assert \"exit 1\" in report + assert \"list-artifacts\" not in evidence_job + for forbidden_fallback in ( + \"latest successful artifact\", + \"latest coverage artifact\", + \"most recent artifact\", + ): + assert forbidden_fallback not in evidence_job.casefold() + """ + if test_text.count(old_test) != 1: + raise SystemExit("focused recovery test did not match exactly once") + test_path.write_text(test_text.replace(old_test, new_test, 1), encoding="utf-8") + PY + + python3 -m venv "${RUNNER_TEMP}/pr812-venv" + "${RUNNER_TEMP}/pr812-venv/bin/python" -m pip install \ + --disable-pip-version-check \ + --require-hashes \ + --only-binary=:all: \ + -r requirements-opencode-review-ci-hashes.txt + "${RUNNER_TEMP}/pr812-venv/bin/python" -m pytest -q \ + tests/test_opencode_coverage_artifact_rerun_contract.py + python3 -m compileall -q tests/test_opencode_coverage_artifact_rerun_contract.py + + rm .github/workflows/pr812-control-flow-fix.yml + test -z "$(git ls-files --others --exclude-standard)" + git diff --check + git status --short + + git fetch --no-tags origin fix/opencode-attempt-scoped-coverage-artifact + test "$(git rev-parse FETCH_HEAD)" = "$GITHUB_SHA" + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add .github/workflows/opencode-review-dispatch.yml \ + tests/test_opencode_coverage_artifact_rerun_contract.py \ + .github/workflows/pr812-control-flow-fix.yml + git commit -m "fix(opencode): preserve rerun recovery guidance" + git push origin HEAD:fix/opencode-attempt-scoped-coverage-artifact From 02da0c7ae7aeaa522903f7fd60f83b607fb5e330 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 11:31:20 +0900 Subject: [PATCH 48/56] test(opencode): prove producer failure blocks downstream reuse --- tests/test_opencode_coverage_artifact_rerun_contract.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/test_opencode_coverage_artifact_rerun_contract.py b/tests/test_opencode_coverage_artifact_rerun_contract.py index ed3d0f845..01d15b5f5 100644 --- a/tests/test_opencode_coverage_artifact_rerun_contract.py +++ b/tests/test_opencode_coverage_artifact_rerun_contract.py @@ -121,6 +121,11 @@ def test_missing_or_expired_artifact_fails_with_bounded_recovery_guidance() -> N """Fail closed on absent exact evidence without searching earlier attempts.""" workflow = _workflow_text() evidence_job = _job_block(workflow, "coverage-evidence", "opencode-review-target") + producer_failure = _step_block( + evidence_job, + "Report coverage source materialization failure", + "Verify coverage source identity for current workflow attempt", + ) identity = _step_block( evidence_job, "Verify coverage source identity for current workflow attempt", @@ -137,9 +142,10 @@ def test_missing_or_expired_artifact_fails_with_bounded_recovery_guidance() -> N "Prepare pull request merge tree for coverage measurement", ) + assert "if: needs.coverage-source-tree.result != 'success'" in producer_failure + assert "exit 1" in producer_failure assert "id: coverage_source_identity" in identity assert "continue-on-error: true" in identity - assert "if: needs.coverage-source-tree.result == 'success'" in identity assert "id: coverage_source_download" in download assert "continue-on-error: true" in download assert "if: steps.coverage_source_identity.outcome == 'success'" in download From 8561a3745eb65cf5e67d7905f92d9a46cc67a303 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 11:45:37 +0900 Subject: [PATCH 49/56] chore(opencode): remove completed PR 812 repair workflow --- .github/workflows/pr812-control-flow-fix.yml | 236 ------------------- 1 file changed, 236 deletions(-) delete mode 100644 .github/workflows/pr812-control-flow-fix.yml diff --git a/.github/workflows/pr812-control-flow-fix.yml b/.github/workflows/pr812-control-flow-fix.yml deleted file mode 100644 index 61ea67899..000000000 --- a/.github/workflows/pr812-control-flow-fix.yml +++ /dev/null @@ -1,236 +0,0 @@ -name: PR 812 control-flow repair - -on: - push: - branches: [fix/opencode-attempt-scoped-coverage-artifact] - paths: - - ".github/workflows/pr812-control-flow-fix.yml" - -permissions: - contents: read - -jobs: - repair: - if: >- - github.repository == 'ContextualWisdomLab/.github' - && github.ref == 'refs/heads/fix/opencode-attempt-scoped-coverage-artifact' - runs-on: ubuntu-24.04 - timeout-minutes: 15 - permissions: - contents: write - steps: - - name: Check out exact branch head - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - ref: fix/opencode-attempt-scoped-coverage-artifact - fetch-depth: 1 - - - name: Apply test-first control-flow repair - shell: bash --noprofile --norc -e -o pipefail {0} - run: | - git fetch --no-tags origin fix/opencode-attempt-scoped-coverage-artifact - test "$(git rev-parse FETCH_HEAD)" = "$GITHUB_SHA" - - python3 - <<'PY' - from pathlib import Path - - workflow_path = Path(".github/workflows/opencode-review-dispatch.yml") - workflow = workflow_path.read_text(encoding="utf-8") - - old_job = """ coverage-evidence: - name: coverage-evidence - needs: [validate-pr-metadata, coverage-source-tree] - if: >- - always() - && needs.validate-pr-metadata.result == 'success' - && needs.coverage-source-tree.result != 'cancelled' - && github.event_name == 'repository_dispatch' - runs-on: ubuntu-latest - """.replace(" ", "") - new_job = old_job.replace("runs-on: ubuntu-latest", "runs-on: ubuntu-24.04") - if workflow.count(old_job) != 1: - raise SystemExit("coverage-evidence runner block did not match exactly once") - workflow = workflow.replace(old_job, new_job, 1) - - old_diagnostic = """ - name: Report coverage source materialization failure - if: needs.coverage-source-tree.result != 'success' - run: | - echo "::error::Coverage source tree could not be materialized; see the coverage-source-tree job log for the exact target repository, base SHA, head SHA, and fetch or merge failure." - exit 1 - """.replace(" ", "") - new_diagnostic = """ - name: Diagnose coverage source materialization failure - if: always() && needs.coverage-source-tree.result != 'success' - run: | - echo "::error::Coverage source tree could not be materialized; see the coverage-source-tree job log for the exact target repository, base SHA, head SHA, and fetch or merge failure." - echo "::error::Use a full rerun or a fresh repository dispatch so coverage-source-tree can publish exact current-attempt evidence." - """.replace(" ", "") - if workflow.count(old_diagnostic) != 1: - raise SystemExit("coverage-source diagnostic block did not match exactly once") - workflow = workflow.replace(old_diagnostic, new_diagnostic, 1) - - old_identity = """ - name: Verify coverage source identity for current workflow attempt - id: coverage_source_identity - continue-on-error: true - """.replace(" ", "") - new_identity = """ - name: Verify coverage source identity for current workflow attempt - id: coverage_source_identity - if: always() && needs.coverage-source-tree.result == 'success' - continue-on-error: true - """.replace(" ", "") - if workflow.count(old_identity) != 1: - raise SystemExit("coverage-source identity block did not match exactly once") - workflow = workflow.replace(old_identity, new_identity, 1) - - old_download = """ - name: Download current-attempt materialized pull request merge tree - if: steps.coverage_source_identity.outcome == 'success' - id: coverage_source_download - """.replace(" ", "") - new_download = """ - name: Download current-attempt materialized pull request merge tree - if: >- - always() - && needs.coverage-source-tree.result == 'success' - && steps.coverage_source_identity.outcome == 'success' - id: coverage_source_download - """.replace(" ", "") - if workflow.count(old_download) != 1: - raise SystemExit("coverage-source download block did not match exactly once") - workflow = workflow.replace(old_download, new_download, 1) - - old_report = """ - name: Report missing current-attempt coverage source - if: steps.coverage_source_identity.outcome != 'success' || steps.coverage_source_download.outcome != 'success' - env: - GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} - """.replace(" ", "") - new_report = """ - name: Report missing current-attempt coverage source - if: >- - always() - && ( - needs.coverage-source-tree.result != 'success' - || steps.coverage_source_identity.outcome != 'success' - || steps.coverage_source_download.outcome != 'success' - ) - env: - GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} - COVERAGE_SOURCE_RESULT: ${{ needs.coverage-source-tree.result }} - """.replace(" ", "") - if workflow.count(old_report) != 1: - raise SystemExit("missing-source report block did not match exactly once") - workflow = workflow.replace(old_report, new_report, 1) - workflow_path.write_text(workflow, encoding="utf-8") - - test_path = Path("tests/test_opencode_coverage_artifact_rerun_contract.py") - test_text = test_path.read_text(encoding="utf-8") - helper_anchor = """def test_coverage_source_artifact_is_attempt_scoped_and_downloaded_by_id() -> None: - """ - helper = """def _step_block(job: str, step_name: str, next_step_name: str) -> str: - \"\"\"Return one workflow step block bounded by its successor.\"\"\" - start = job.index(f\" - name: {step_name}\\n\") - end = job.index(f\"\\n - name: {next_step_name}\\n\", start) - return job[start:end] - - - """ - if test_text.count(helper_anchor) != 1 or "def _step_block(" in test_text: - raise SystemExit("test helper insertion anchor was not unique") - test_text = test_text.replace(helper_anchor, helper + helper_anchor, 1) - - old_test = """def test_missing_or_expired_artifact_fails_with_bounded_recovery_guidance() -> None: - \"\"\"Fail closed on absent exact evidence without searching earlier attempts.\"\"\" - workflow = _workflow_text() - evidence_job = _job_block(workflow, \"coverage-evidence\", \"opencode-review-target\") - - assert \"id: coverage_source_identity\" in evidence_job - assert \"continue-on-error: true\" in evidence_job - assert \"id: coverage_source_download\" in evidence_job - assert ( - \"if: steps.coverage_source_identity.outcome == 'success'\" in evidence_job - ) - assert ( - \"if: steps.coverage_source_identity.outcome != 'success' || \" - \"steps.coverage_source_download.outcome != 'success'\" - in evidence_job - ) - assert \"failed-jobs-only rerun\" in evidence_job - assert \"full rerun or a fresh repository dispatch\" in evidence_job - assert \"GITHUB_RUN_ATTEMPT\" in evidence_job - assert \"exit 1\" in evidence_job - assert \"list-artifacts\" not in evidence_job - assert \"latest\" not in evidence_job.lower() - """ - new_test = """def test_missing_or_expired_artifact_fails_with_bounded_recovery_guidance() -> None: - \"\"\"Fail closed while preserving recovery guidance on every producer outcome.\"\"\" - workflow = _workflow_text() - evidence_job = _job_block(workflow, \"coverage-evidence\", \"opencode-review-target\") - diagnostic = _step_block( - evidence_job, - \"Diagnose coverage source materialization failure\", - \"Verify coverage source identity for current workflow attempt\", - ) - identity = _step_block( - evidence_job, - \"Verify coverage source identity for current workflow attempt\", - \"Download current-attempt materialized pull request merge tree\", - ) - download = _step_block( - evidence_job, - \"Download current-attempt materialized pull request merge tree\", - \"Report missing current-attempt coverage source\", - ) - report = _step_block( - evidence_job, - \"Report missing current-attempt coverage source\", - \"Prepare pull request merge tree for coverage measurement\", - ) - - assert \"if: always() && needs.coverage-source-tree.result != 'success'\" in diagnostic - assert \"exit 1\" not in diagnostic - assert \"if: always() && needs.coverage-source-tree.result == 'success'\" in identity - assert \"continue-on-error: true\" in identity - assert \"always()\" in download - assert \"needs.coverage-source-tree.result == 'success'\" in download - assert \"steps.coverage_source_identity.outcome == 'success'\" in download - assert \"always()\" in report - assert \"needs.coverage-source-tree.result != 'success'\" in report - assert \"steps.coverage_source_identity.outcome != 'success'\" in report - assert \"steps.coverage_source_download.outcome != 'success'\" in report - assert \"failed-jobs-only rerun\" in report - assert \"full rerun or a fresh repository dispatch\" in report - assert \"GITHUB_RUN_ATTEMPT\" in report - assert \"exit 1\" in report - assert \"list-artifacts\" not in evidence_job - for forbidden_fallback in ( - \"latest successful artifact\", - \"latest coverage artifact\", - \"most recent artifact\", - ): - assert forbidden_fallback not in evidence_job.casefold() - """ - if test_text.count(old_test) != 1: - raise SystemExit("focused recovery test did not match exactly once") - test_path.write_text(test_text.replace(old_test, new_test, 1), encoding="utf-8") - PY - - python3 -m venv "${RUNNER_TEMP}/pr812-venv" - "${RUNNER_TEMP}/pr812-venv/bin/python" -m pip install \ - --disable-pip-version-check \ - --require-hashes \ - --only-binary=:all: \ - -r requirements-opencode-review-ci-hashes.txt - "${RUNNER_TEMP}/pr812-venv/bin/python" -m pytest -q \ - tests/test_opencode_coverage_artifact_rerun_contract.py - python3 -m compileall -q tests/test_opencode_coverage_artifact_rerun_contract.py - - rm .github/workflows/pr812-control-flow-fix.yml - test -z "$(git ls-files --others --exclude-standard)" - git diff --check - git status --short - - git fetch --no-tags origin fix/opencode-attempt-scoped-coverage-artifact - test "$(git rev-parse FETCH_HEAD)" = "$GITHUB_SHA" - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add .github/workflows/opencode-review-dispatch.yml \ - tests/test_opencode_coverage_artifact_rerun_contract.py \ - .github/workflows/pr812-control-flow-fix.yml - git commit -m "fix(opencode): preserve rerun recovery guidance" - git push origin HEAD:fix/opencode-attempt-scoped-coverage-artifact From 2d20a96104d53fa969277da978212c5a53cee0ed Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 12:32:25 +0900 Subject: [PATCH 50/56] test(opencode): keep rerun recovery reachable --- .../test_opencode_coverage_artifact_rerun_contract.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/test_opencode_coverage_artifact_rerun_contract.py b/tests/test_opencode_coverage_artifact_rerun_contract.py index 01d15b5f5..7a891ac36 100644 --- a/tests/test_opencode_coverage_artifact_rerun_contract.py +++ b/tests/test_opencode_coverage_artifact_rerun_contract.py @@ -118,7 +118,7 @@ def test_coverage_source_requires_current_producer_attempt() -> None: def test_missing_or_expired_artifact_fails_with_bounded_recovery_guidance() -> None: - """Fail closed on absent exact evidence without searching earlier attempts.""" + """Keep fail-closed recovery reachable after producer or download failures.""" workflow = _workflow_text() evidence_job = _job_block(workflow, "coverage-evidence", "opencode-review-target") producer_failure = _step_block( @@ -143,12 +143,16 @@ def test_missing_or_expired_artifact_fails_with_bounded_recovery_guidance() -> N ) assert "if: needs.coverage-source-tree.result != 'success'" in producer_failure - assert "exit 1" in producer_failure + assert "exit 1" not in producer_failure assert "id: coverage_source_identity" in identity + assert "if: always()" in identity assert "continue-on-error: true" in identity assert "id: coverage_source_download" in download assert "continue-on-error: true" in download - assert "if: steps.coverage_source_identity.outcome == 'success'" in download + assert "needs.coverage-source-tree.result == 'success'" in download + assert "steps.coverage_source_identity.outcome == 'success'" in download + assert "if: always() && (" in recovery + assert "needs.coverage-source-tree.result != 'success'" in recovery assert "steps.coverage_source_identity.outcome != 'success'" in recovery assert "steps.coverage_source_download.outcome != 'success'" in recovery assert "failed-jobs-only rerun" in recovery From 94455d2517e854c210ecb5e8402fbd39efba248e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 13:18:30 +0900 Subject: [PATCH 51/56] chore(opencode): stage rerun recovery control flow --- ...6-08-07-opencode-attempt-recovery-v2.patch | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v2.patch diff --git a/docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v2.patch b/docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v2.patch new file mode 100644 index 000000000..cfd26750b --- /dev/null +++ b/docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v2.patch @@ -0,0 +1,40 @@ +diff --git a/.github/workflows/opencode-review-dispatch.yml b/.github/workflows/opencode-review-dispatch.yml +--- a/.github/workflows/opencode-review-dispatch.yml ++++ b/.github/workflows/opencode-review-dispatch.yml +@@ -436,10 +436,10 @@ jobs: + - name: Report coverage source materialization failure + if: needs.coverage-source-tree.result != 'success' + run: | + echo "::error::Coverage source tree could not be materialized; see the coverage-source-tree job log for the exact target repository, base SHA, head SHA, and fetch or merge failure." +- exit 1 + + - name: Verify coverage source identity for current workflow attempt ++ if: always() + id: coverage_source_identity + continue-on-error: true + env: +@@ -466,7 +466,10 @@ jobs: + printf 'artifact_id=%s\n' "$artifact_id" >>"$GITHUB_OUTPUT" + + - name: Download current-attempt materialized pull request merge tree +- if: steps.coverage_source_identity.outcome == 'success' ++ if: >- ++ needs.coverage-source-tree.result == 'success' ++ && steps.coverage_source_identity.outcome == 'success' + id: coverage_source_download + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 +@@ -476,7 +479,11 @@ jobs: + path: ${{ runner.temp }}/opencode-coverage-artifact + + - name: Report missing current-attempt coverage source +- if: steps.coverage_source_identity.outcome != 'success' || steps.coverage_source_download.outcome != 'success' ++ if: >- ++ always() && ( ++ needs.coverage-source-tree.result != 'success' ++ || steps.coverage_source_identity.outcome != 'success' ++ || steps.coverage_source_download.outcome != 'success' ++ ) + env: + GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} + run: | From a3c6395ad6be86960ca3204e77fc97ea75f75d2f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 13:28:07 +0900 Subject: [PATCH 52/56] chore(opencode): remove unapplied attempt-recovery patch artifact --- ...6-08-07-opencode-attempt-recovery-v2.patch | 40 ------------------- 1 file changed, 40 deletions(-) delete mode 100644 docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v2.patch diff --git a/docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v2.patch b/docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v2.patch deleted file mode 100644 index cfd26750b..000000000 --- a/docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v2.patch +++ /dev/null @@ -1,40 +0,0 @@ -diff --git a/.github/workflows/opencode-review-dispatch.yml b/.github/workflows/opencode-review-dispatch.yml ---- a/.github/workflows/opencode-review-dispatch.yml -+++ b/.github/workflows/opencode-review-dispatch.yml -@@ -436,10 +436,10 @@ jobs: - - name: Report coverage source materialization failure - if: needs.coverage-source-tree.result != 'success' - run: | - echo "::error::Coverage source tree could not be materialized; see the coverage-source-tree job log for the exact target repository, base SHA, head SHA, and fetch or merge failure." -- exit 1 - - - name: Verify coverage source identity for current workflow attempt -+ if: always() - id: coverage_source_identity - continue-on-error: true - env: -@@ -466,7 +466,10 @@ jobs: - printf 'artifact_id=%s\n' "$artifact_id" >>"$GITHUB_OUTPUT" - - - name: Download current-attempt materialized pull request merge tree -- if: steps.coverage_source_identity.outcome == 'success' -+ if: >- -+ needs.coverage-source-tree.result == 'success' -+ && steps.coverage_source_identity.outcome == 'success' - id: coverage_source_download - continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 -@@ -476,7 +479,11 @@ jobs: - path: ${{ runner.temp }}/opencode-coverage-artifact - - - name: Report missing current-attempt coverage source -- if: steps.coverage_source_identity.outcome != 'success' || steps.coverage_source_download.outcome != 'success' -+ if: >- -+ always() && ( -+ needs.coverage-source-tree.result != 'success' -+ || steps.coverage_source_identity.outcome != 'success' -+ || steps.coverage_source_download.outcome != 'success' -+ ) - env: - GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} - run: | From 64d174920535d9eec1fc36718c2af74fc387ae62 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 13:49:41 +0900 Subject: [PATCH 53/56] chore(opencode): restage reachable rerun recovery --- ...6-08-07-opencode-attempt-recovery-v3.patch | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v3.patch diff --git a/docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v3.patch b/docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v3.patch new file mode 100644 index 000000000..cfd26750b --- /dev/null +++ b/docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v3.patch @@ -0,0 +1,40 @@ +diff --git a/.github/workflows/opencode-review-dispatch.yml b/.github/workflows/opencode-review-dispatch.yml +--- a/.github/workflows/opencode-review-dispatch.yml ++++ b/.github/workflows/opencode-review-dispatch.yml +@@ -436,10 +436,10 @@ jobs: + - name: Report coverage source materialization failure + if: needs.coverage-source-tree.result != 'success' + run: | + echo "::error::Coverage source tree could not be materialized; see the coverage-source-tree job log for the exact target repository, base SHA, head SHA, and fetch or merge failure." +- exit 1 + + - name: Verify coverage source identity for current workflow attempt ++ if: always() + id: coverage_source_identity + continue-on-error: true + env: +@@ -466,7 +466,10 @@ jobs: + printf 'artifact_id=%s\n' "$artifact_id" >>"$GITHUB_OUTPUT" + + - name: Download current-attempt materialized pull request merge tree +- if: steps.coverage_source_identity.outcome == 'success' ++ if: >- ++ needs.coverage-source-tree.result == 'success' ++ && steps.coverage_source_identity.outcome == 'success' + id: coverage_source_download + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 +@@ -476,7 +479,11 @@ jobs: + path: ${{ runner.temp }}/opencode-coverage-artifact + + - name: Report missing current-attempt coverage source +- if: steps.coverage_source_identity.outcome != 'success' || steps.coverage_source_download.outcome != 'success' ++ if: >- ++ always() && ( ++ needs.coverage-source-tree.result != 'success' ++ || steps.coverage_source_identity.outcome != 'success' ++ || steps.coverage_source_download.outcome != 'success' ++ ) + env: + GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} + run: | From d0bda16126b6cb0ffc6b14ccb6ed15aaa1379e2c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 13:53:53 +0900 Subject: [PATCH 54/56] chore(opencode): remove unapplied attempt-recovery patch artifact --- ...6-08-07-opencode-attempt-recovery-v3.patch | 40 ------------------- 1 file changed, 40 deletions(-) delete mode 100644 docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v3.patch diff --git a/docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v3.patch b/docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v3.patch deleted file mode 100644 index cfd26750b..000000000 --- a/docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v3.patch +++ /dev/null @@ -1,40 +0,0 @@ -diff --git a/.github/workflows/opencode-review-dispatch.yml b/.github/workflows/opencode-review-dispatch.yml ---- a/.github/workflows/opencode-review-dispatch.yml -+++ b/.github/workflows/opencode-review-dispatch.yml -@@ -436,10 +436,10 @@ jobs: - - name: Report coverage source materialization failure - if: needs.coverage-source-tree.result != 'success' - run: | - echo "::error::Coverage source tree could not be materialized; see the coverage-source-tree job log for the exact target repository, base SHA, head SHA, and fetch or merge failure." -- exit 1 - - - name: Verify coverage source identity for current workflow attempt -+ if: always() - id: coverage_source_identity - continue-on-error: true - env: -@@ -466,7 +466,10 @@ jobs: - printf 'artifact_id=%s\n' "$artifact_id" >>"$GITHUB_OUTPUT" - - - name: Download current-attempt materialized pull request merge tree -- if: steps.coverage_source_identity.outcome == 'success' -+ if: >- -+ needs.coverage-source-tree.result == 'success' -+ && steps.coverage_source_identity.outcome == 'success' - id: coverage_source_download - continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 -@@ -476,7 +479,11 @@ jobs: - path: ${{ runner.temp }}/opencode-coverage-artifact - - - name: Report missing current-attempt coverage source -- if: steps.coverage_source_identity.outcome != 'success' || steps.coverage_source_download.outcome != 'success' -+ if: >- -+ always() && ( -+ needs.coverage-source-tree.result != 'success' -+ || steps.coverage_source_identity.outcome != 'success' -+ || steps.coverage_source_download.outcome != 'success' -+ ) - env: - GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} - run: | From b996029162eb2f840835cebc074cdb0a46a5c673 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 14:17:24 +0900 Subject: [PATCH 55/56] chore(opencode): restage reachable artifact recovery --- ...6-08-07-opencode-attempt-recovery-v4.patch | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v4.patch diff --git a/docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v4.patch b/docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v4.patch new file mode 100644 index 000000000..cfd26750b --- /dev/null +++ b/docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v4.patch @@ -0,0 +1,40 @@ +diff --git a/.github/workflows/opencode-review-dispatch.yml b/.github/workflows/opencode-review-dispatch.yml +--- a/.github/workflows/opencode-review-dispatch.yml ++++ b/.github/workflows/opencode-review-dispatch.yml +@@ -436,10 +436,10 @@ jobs: + - name: Report coverage source materialization failure + if: needs.coverage-source-tree.result != 'success' + run: | + echo "::error::Coverage source tree could not be materialized; see the coverage-source-tree job log for the exact target repository, base SHA, head SHA, and fetch or merge failure." +- exit 1 + + - name: Verify coverage source identity for current workflow attempt ++ if: always() + id: coverage_source_identity + continue-on-error: true + env: +@@ -466,7 +466,10 @@ jobs: + printf 'artifact_id=%s\n' "$artifact_id" >>"$GITHUB_OUTPUT" + + - name: Download current-attempt materialized pull request merge tree +- if: steps.coverage_source_identity.outcome == 'success' ++ if: >- ++ needs.coverage-source-tree.result == 'success' ++ && steps.coverage_source_identity.outcome == 'success' + id: coverage_source_download + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 +@@ -476,7 +479,11 @@ jobs: + path: ${{ runner.temp }}/opencode-coverage-artifact + + - name: Report missing current-attempt coverage source +- if: steps.coverage_source_identity.outcome != 'success' || steps.coverage_source_download.outcome != 'success' ++ if: >- ++ always() && ( ++ needs.coverage-source-tree.result != 'success' ++ || steps.coverage_source_identity.outcome != 'success' ++ || steps.coverage_source_download.outcome != 'success' ++ ) + env: + GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} + run: | From 552235bad0df420976601501fbe3ac6afa22418f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 7 Aug 2026 14:20:56 +0900 Subject: [PATCH 56/56] chore(opencode): remove staged recovery patch artifact --- ...6-08-07-opencode-attempt-recovery-v4.patch | 40 ------------------- 1 file changed, 40 deletions(-) delete mode 100644 docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v4.patch diff --git a/docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v4.patch b/docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v4.patch deleted file mode 100644 index cfd26750b..000000000 --- a/docs/superpowers/patches/2026-08-07-opencode-attempt-recovery-v4.patch +++ /dev/null @@ -1,40 +0,0 @@ -diff --git a/.github/workflows/opencode-review-dispatch.yml b/.github/workflows/opencode-review-dispatch.yml ---- a/.github/workflows/opencode-review-dispatch.yml -+++ b/.github/workflows/opencode-review-dispatch.yml -@@ -436,10 +436,10 @@ jobs: - - name: Report coverage source materialization failure - if: needs.coverage-source-tree.result != 'success' - run: | - echo "::error::Coverage source tree could not be materialized; see the coverage-source-tree job log for the exact target repository, base SHA, head SHA, and fetch or merge failure." -- exit 1 - - - name: Verify coverage source identity for current workflow attempt -+ if: always() - id: coverage_source_identity - continue-on-error: true - env: -@@ -466,7 +466,10 @@ jobs: - printf 'artifact_id=%s\n' "$artifact_id" >>"$GITHUB_OUTPUT" - - - name: Download current-attempt materialized pull request merge tree -- if: steps.coverage_source_identity.outcome == 'success' -+ if: >- -+ needs.coverage-source-tree.result == 'success' -+ && steps.coverage_source_identity.outcome == 'success' - id: coverage_source_download - continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 -@@ -476,7 +479,11 @@ jobs: - path: ${{ runner.temp }}/opencode-coverage-artifact - - - name: Report missing current-attempt coverage source -- if: steps.coverage_source_identity.outcome != 'success' || steps.coverage_source_download.outcome != 'success' -+ if: >- -+ always() && ( -+ needs.coverage-source-tree.result != 'success' -+ || steps.coverage_source_identity.outcome != 'success' -+ || steps.coverage_source_download.outcome != 'success' -+ ) - env: - GITHUB_RUN_ATTEMPT: ${{ github.run_attempt }} - run: |