Skip to content

fix(verify-pr): self-exclude own workflow check-runs from CI Status - #307

Merged
mrizzi merged 3 commits into
verify-pr-fullsendfrom
TC-6343
Sep 17, 2026
Merged

mrizzi merged 3 commits into
verify-pr-fullsendfrom
TC-6343

Conversation

@mrizzi

@mrizzi mrizzi commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator

Implements TC-6343. Fixes TC-6332. Also implements TC-6349 (doc-accuracy follow-up).

Problem

The head-SHA check-run prefetch enumerated every check-run on the commit — including verify-pr's own workflow (fullsend verify-pr) runs (the in-progress dispatch and any superseded prior attempt). Those own runs are non-terminal (or a superseded attempt failed) at evaluation time, so correctness.md Check 1a mapped them to pending/failed, dragging CI Status to a permanent self-referential WARN/FAIL. verify-pr could essentially never report CI Status = PASS.

Fix

The CI-Status analogue of Step 1's running-workflow-name: wait-for-checks self-exclusion:

  • pre-verify-pr.sh enumerates this workflow's own check-run names for the head SHA — across all of its runs at that SHA, so superseded attempts are covered too — and passes them to the transform. Best-effort: a token lacking actions:read degrades to no self-exclusion (prior behavior) with a warning rather than aborting.
  • pre_verify_pr.py gains a pure, unit-testable helper filter_own_check_runs(check_runs, own_names) (plus _read_own_check_names), applied in _github_from_dir before the bundle reaches github.check_runs. Exclusion is by workflow name, not run ID.
  • correctness.md Check 1a documents the self-exclusion as best-effort (TC-6349): it degrades to a no-op with a WARNING when own-run enumeration fails (e.g. missing actions:read), so the evaluator is told the CI Status input may still contain verify-pr's own runs and must map each entry on its merits.

Verification

  • python3 -m pytest plugins/sdlc-workflow/scripts/test_pre_verify_pr.py -q90 passed (new reproducer, filter unit tests, preservation, _read_own_check_names, two CLI round-trips, shell regression guard).
  • uvx skillsaw — 0 errors.
  • claude plugin validate plugins/sdlc-workflow — passed.

🤖 Generated with Claude Code

Summary by Sourcery

Exclude verify-pr's own workflow check-runs from CI Status evaluation so successful substantive checks can report PASS.

Bug Fixes:

  • Prevent verify-pr's own in-progress and superseded workflow check-runs from incorrectly forcing CI Status to WARN or FAIL.

Enhancements:

  • Make self-exclusion best-effort, preserving prior behavior with a warning when own-run enumeration is unavailable.
  • Document how CI Status should handle verify-pr's own check-runs when self-exclusion cannot be performed.

Documentation:

  • Clarify the best-effort CI Status self-exclusion behavior and fallback evaluation guidance.

Tests:

  • Add unit, CLI, and shell regression coverage for filtering own check-runs and preserving behavior when no own-run names are available.

Chores:

  • Update the pinned verify-pr harness and lock metadata to consume the revised workflow scripts and documentation.

The head-SHA check-run prefetch enumerated every check-run on the commit,
including verify-pr's own workflow (`fullsend verify-pr`) runs — the
in-progress dispatch and any superseded prior attempt. Those are
non-terminal/failed at evaluation time, so correctness.md Check 1a mapped
them to pending/failed and forced a permanent self-referential CI Status
WARN/FAIL: verify-pr could never report CI Status = PASS (TC-6332).

Add the CI-Status analogue of Step 1's `running-workflow-name` self-
exclusion. pre-verify-pr.sh enumerates this workflow's own check-run names
for the head SHA — across all of its runs at that SHA, so superseded
attempts are covered — and passes them to a pure, unit-testable Python
helper `filter_own_check_runs`, which drops them before they reach
`github.check_runs`. Exclusion is by workflow NAME, not run ID. Name
gathering is best-effort: a token lacking actions:read degrades to no
self-exclusion (prior behavior) with a warning rather than aborting.

Fixes TC-6332.

Assisted-by: Claude Code
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

The PR prevents verify-pr from evaluating its own workflow check-runs as substantive CI results by collecting all matching job names on the head SHA in the trusted shell prefetch, filtering them in a pure Python transform helper, and documenting and testing the behavior, including graceful fallback when GitHub enumeration is unavailable.

Sequence diagram for verify-pr self-excluding workflow checks

sequenceDiagram
    participant Shell as pre-verify-pr.sh
    participant GitHub as GitHub API
    participant Transform as pre_verify_pr.py
    participant Bundle as CI Status input
    participant Correctness as correctness.md

    Shell->>GitHub: gh api check-runs for head SHA
    Shell->>GitHub: gh api workflow runs and jobs for head SHA
    GitHub-->>Shell: Own job names across all workflow runs
    Shell->>Transform: --own-check-names-file
    Transform->>Transform: _read_own_check_names
    Transform->>Transform: filter_own_check_runs
    Transform-->>Bundle: Bundle without verify-pr check-runs
    Bundle->>Correctness: Evaluate substantive CI checks
    Correctness-->>Correctness: CI Status can reach PASS
Loading

File-Level Changes

Change Details Files
Excludes verify-pr’s own workflow check-runs from the prefetched CI Status inputs before correctness evaluation.
  • Enumerate all runs of fullsend-verify-pr.yml for the head SHA and collect their job/check-run names, including superseded attempts.
  • Treat enumeration as best-effort and preserve prior behavior when names cannot be gathered.
  • Pass the names file through the transform and filter check-runs by workflow name while preserving substantive and nameless entries.
plugins/sdlc-workflow/scripts/pre-verify-pr.sh
plugins/sdlc-workflow/scripts/pre_verify_pr.py
Adds regression and unit coverage for self-exclusion and fallback behavior.
  • Test filtering, input immutability, field preservation, nameless entries, and empty-name no-op behavior.
  • Test file parsing and CLI transform round-trips with and without self-exclusion data.
  • Add a shell-source regression guard for head-SHA workflow enumeration and transform wiring.
plugins/sdlc-workflow/scripts/test_pre_verify_pr.py
Documents that CI Status receives trusted, self-excluded check-run data.
  • Clarify that verify-pr’s in-progress and superseded workflow runs are removed before sandbox evaluation.
  • Preserve the existing Check 1a status mapping for the remaining check-runs.
plugins/sdlc-workflow/skills/verify-pr/correctness.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="plugins/sdlc-workflow/skills/verify-pr/correctness.md" line_range="46-51" />
<code_context>
 **Sandbox mode** (CI Status input provided): do **not** run `gh` — read the
 pre-fetched check-run outcomes from the CI Status input (each entry has `name`,
-`status`, `conclusion`, `details_url`). Map each entry to a status:
+`status`, `conclusion`, `details_url`). These are already **self-excluded** on the
+trusted runner: verify-pr's own workflow (`fullsend verify-pr`) check-runs — the
+in-progress dispatch and any superseded prior attempt — are removed before the
+bundle is written (the CI-Status analogue of Step 1's `running-workflow-name`
+self-exclusion), so the sandbox never evaluates verify-pr's own runs and a PR
+whose substantive checks all pass can reach CI Status = PASS. Map each entry to a
+status:

</code_context>
<issue_to_address>
**issue:** The sandbox guidance unconditionally says verify-pr's own check-runs are already removed and that the sandbox never evaluates them, but the shell explicitly falls back to an empty names file when enumeration fails, and `filter_own_check_runs` then preserves all check-runs. In that documented fallback case, the original self-referential WARN/FAIL behavior remains while the correctness instructions incorrectly imply it cannot occur.

**Triggers:** When the runner token lacks `actions:read` or own-run enumeration encounters an API failure.

**Suggested fix:** Document the best-effort fallback and instruct the evaluator to account for an input that can still contain verify-pr's own runs, or make self-exclusion a required successful prefetch.

```suggestion
`status`, `conclusion`, `details_url`). The trusted runner best-effort
**self-excludes** verify-pr's own workflow (`fullsend verify-pr`) check-runs — the
in-progress dispatch and any superseded prior attempt — before writing the bundle
(the CI-Status analogue of Step 1's `running-workflow-name` self-exclusion). If
check-run enumeration fails, the fallback may leave verify-pr's own runs in the
CI Status input; account for that possibility when evaluating each entry. Map each entry to a
```
</issue_to_address>

Sourcery assessment

Needs a human reviewer. 1 finding to address first, and a name-based exclusion changes the CI verification policy for every PR and could hide a real failing check, causing false PASS results with no inherent signal that the check was omitted. Reverting prevents future false statuses but does not undo verification results already produced while the exclusion was active.

Blocking findings: plugins/sdlc-workflow/skills/verify-pr/correctness.md:51


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread plugins/sdlc-workflow/skills/verify-pr/correctness.md Outdated
mrizzi added a commit that referenced this pull request Sep 17, 2026
The real fullsend-verify-pr.yml (pull_request_target + ok-to-test, TC-6331)
lived only on the verify-pr-fullsend feature branch; main still carried the
workflow_dispatch placeholder. GitHub registers and dispatches
pull_request_target from the workflow file on the DEFAULT branch (unlike
pull_request, which is read from the PR base branch), so the trigger was
never active: since TC-6331 merged, no verify-pr run fired for any PR —
fork or same-repo (e.g. PR #307 got zero dispatch).

Replace the placeholder on main with the real workflow so the event
registers. A `branches: [verify-pr-fullsend]` filter scopes the rollout to
PRs targeting the feature branch, so verify-pr does not yet review PRs into
main; the base-branch copy still executes in trusted context. Widen/remove
the filter when the feature graduates to main.

Assisted-by: Claude Code
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mrizzi mrizzi closed this Sep 17, 2026
@mrizzi mrizzi reopened this Sep 17, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Sep 17, 2026

Copy link
Copy Markdown

🤖 Finished Verify Pr · ✅ Success · Started 3:28 PM UTC · Completed 3:41 PM UTC

Commit: 654cf01 · View workflow run →

Runtime: claude · Model: claude-opus-4-8 · Effort: high · Cost: $5.14

@fullsend-ai-review

Copy link
Copy Markdown

[sdlc-workflow/verify-pr] Re: @sourcery-ai[bot] review — Classified as code change request — this is the same finding as the inline comment on correctness.md:51 (the best-effort self-exclusion is documented as unconditional). Sub-task TC-6349 created to address it. Noted the accompanying Sourcery assessment that a name-based exclusion changes CI verification policy for every PR and could mask a real failing check — a human reviewer should weigh that before merging.

@fullsend-ai-review

Copy link
Copy Markdown

Verification Report for TC-6343 (commit 654cf01)

Check Result Details
Review Feedback WARN 1 finding from sourcery-ai (raised as an inline comment + review body) — correctness.md's new sandbox guidance states self-exclusion unconditionally though the code has a best-effort fallback; 1 review-feedback sub-task created.
Root-Cause Investigation DONE 1 root-cause task created (plan-feature gap: task's Documentation Updates prescribed unconditional doc wording inconsistent with the best-effort fallback specified in the same task).
Scope Containment PASS All 4 changed files match the task's Files to Modify exactly; no out-of-scope or unimplemented files.
Diff Size PASS 357 additions / 3 deletions across 4 files (= expected 4); dominated by the 266-line test file. Proportionate.
Commit Traceability FAIL The sole commit (654cf01) references TC-6332 (the underlying bug) but never the task ID TC-6343.
Sensitive Patterns PASS No secrets, keys, or credentials in any added line.
CI Status WARN 33/34 head-SHA check-runs pass or skip; 1 pending — verify-pr's own in-progress harness run ('verify-pr / Harness run (verify-pr)'), still present in this bundle because the runner prefetch has not applied this PR's self-exclusion fix. No substantive check failed.
Acceptance Criteria PASS 5 of 5 criteria met (verified statically from the diff).
Test Quality PASS Repetitive Test Detection: PASS; Test Documentation: PASS (all added tests have docstrings); Eval Quality: N/A.
Test Change Classification ADDITIVE +266 test lines appended, no removals/relaxations.
Verification Commands N/A pytest command not runnable in-sandbox (PR files absent from the checked-out base tree; pytest not installed); added tests are statically well-formed. No eval-infra changes.

Overall: FAIL

Overall FAIL is driven by Commit Traceability: the sole commit cites the underlying bug TC-6332 but not the task TC-6343 — recommend amending/adding a commit that references TC-6343. Two informational WARNs: (1) Review Feedback — sourcery-ai flagged that correctness.md's new sandbox guidance states verify-pr's own check-runs are 'already self-excluded' unconditionally, while pre-verify-pr.sh degrades to a no-op when own-run enumeration fails (e.g. a token lacking actions:read), so the self-referential WARN/FAIL can still occur; a review-feedback sub-task was created to document the fallback. (2) CI Status — the only non-passing check is verify-pr's own in-progress harness run (the very self-referential artifact this PR fixes), still present because the runner's prefetch has not yet applied this PR's fix; all substantive checks pass. Acceptance criteria are fully met, the change is additive and well-tested, and no secrets were introduced. This report is informational — a human reviewer decides whether to merge.


This comment was AI-generated by sdlc-workflow/verify-pr v0.13.9.

Reword correctness.md Check 1a sandbox-mode note: the own-check-run
self-exclusion is best-effort (needs actions:read) and degrades to a
no-op with a WARNING when enumeration fails, so the CI Status input can
still contain verify-pr's own runs. Instruct the evaluator to map each
entry on its merits and note own-run-only non-passing entries in the
evidence rather than treating the PR as blocked.

Implements TC-6349

Assisted-by: Claude Code
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Sep 17, 2026

Copy link
Copy Markdown

🤖 Finished Verify Pr · ✅ Success · Started 4:25 PM UTC · Completed 4:36 PM UTC

Commit: da053ba · View workflow run →

Runtime: claude · Model: claude-opus-4-8 · Effort: high · Cost: $5.20

@fullsend-ai-review

Copy link
Copy Markdown

Verification Report for TC-6343 (commit da053ba)

Check Result Details
Review Feedback WARN 1 code change request (sourcery-ai, correctness.md self-exclusion note) — already classified and tracked by sub-task TC-6349 in a prior run and addressed by commit da053ba; no new sub-task created this run (idempotent).
Root-Cause Investigation N/A No sub-tasks created this run (idempotent); root-cause task TC-6350 already exists from a prior run.
Scope Containment PASS All 4 task-listed files modified; no out-of-scope or unimplemented files.
Diff Size PASS 364 insertions / 3 deletions across 4 files — test-heavy and proportionate to the task.
Commit Traceability FAIL Neither commit references the parent task TC-6343 (654cf01 references bug TC-6332; da053ba references sub-task TC-6349).
Sensitive Patterns PASS No secrets, tokens, keys, or credentials in added lines.
CI Status WARN All substantive checks pass (Script Unit Tests 3.11–3.14, Plugin Validation, Skill Lint, Sourcery); the only non-passing entry is verify-pr's own in-progress harness run (best-effort self-exclusion was a no-op for this prefetch), not a genuine blocker.
Acceptance Criteria PASS 5 of 5 met — verified from the PR diff (reproducer + filter unit tests + field-preservation test) and corroborated by the green pytest suite on the head SHA.
Test Quality PASS Repetitive Test Detection PASS; Test Documentation PASS (all 14 new tests carry docstrings); Eval Quality N/A.
Test Change Classification ADDITIVE test_pre_verify_pr.py +266/-0: only new test functions/assertions added; none removed, no skips, no matcher relaxation.
Verification Commands PASS python3 -m pytest plugins/sdlc-workflow/scripts/test_pre_verify_pr.py runs green on the head SHA via Script Unit Tests (3.11–3.14) CI; not runnable in-sandbox (no pytest / PR head tree not checked out).

Overall: FAIL

Overall: FAIL — driven solely by Commit Traceability: neither of the PR's two commits references the parent task TC-6343. Commit 654cf01 references the bug TC-6332 (Fixes TC-6332) and commit da053ba references the review-feedback sub-task TC-6349 (Implements TC-6349), but the task under verification (TC-6343) is not referenced by either.

All substantive verification passed: scope is contained to the 4 task-listed files, no secrets, and all 5 acceptance criteria are met — the reproducer test (test_filter_own_check_runs_reproduces_and_fixes_ci_status_bug), the filter unit tests (empty / no-own / only-own / empty-names no-op), and the field-preservation test are present, and the pytest suite is green on the head SHA (Script Unit Tests 3.11–3.14). Test changes are additive and documented.

CI Status is WARN, not FAIL: the only non-passing entry is verify-pr's own verify-pr / Harness run (verify-pr) (in_progress → pending). The best-effort self-exclusion this PR introduces was a no-op for this prefetch (the own runs remained in the bundle), so — per the reworded correctness.md Check 1a — this is verify-pr's own self-referential run, not a genuine blocker.

The one review finding (sourcery-ai: the correctness.md self-exclusion note was stated unconditionally despite the best-effort fallback) was already classified as a code change request, tracked as sub-task TC-6349, and addressed by commit da053ba. No new sub-tasks or replies were created this run (idempotent).

This skill does not merge the PR. A human reviewer should decide on merge — and consider adding a TC-6343 reference to a follow-up commit (e.g. Implements TC-6343) to close the traceability gap.


This comment was AI-generated by sdlc-workflow/verify-pr v0.13.9.

TC-6343

Option A self-pin: move the base URL commit and re-lock so the verify-pr
CI run fetches the fixed pre-verify-pr.sh (CI-Status own-workflow
self-exclusion) and the reworded correctness.md Check 1a from this PR's
own fix commits, rather than the stale fa3f4b7 pin.

- .fullsend/harness/verify-pr.yaml: base URL commit fa3f4b7 -> da053ba
  (root harness/verify-pr.yaml is byte-identical, sha256 unchanged)
- .fullsend/lock.yaml: fullsend lock regenerates all 11 child pins at
  da053ba; pre-verify-pr.sh, pre_verify_pr.py, and correctness.md
  hashes now reflect the TC-6343 / TC-6349 fixes

Merge via merge commit (squash disabled) so da053ba stays reachable and
the pin keeps resolving after merge.

Assisted-by: Claude Code
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Sep 17, 2026

Copy link
Copy Markdown

🤖 Finished Verify Pr · ✅ Success · Started 5:01 PM UTC · Completed 5:10 PM UTC

Commit: 02f271b · View workflow run →

Runtime: claude · Model: claude-opus-4-8 · Effort: high · Cost: $4.50

@fullsend-ai-review

Copy link
Copy Markdown

Verification Report for TC-6343 (commit 02f271b)

Check Result Details
Review Feedback WARN 1 code change request (sourcery-ai: correctness.md CI-Status self-exclusion note stated unconditionally vs. best-effort fallback). Already classified and tracked by sub-task TC-6349 in a prior run and addressed by commit da053ba; no new sub-task this run (idempotent).
Root-Cause Investigation N/A No sub-tasks created this run (idempotent); root-cause task TC-6350 already exists from a prior run.
Scope Containment WARN All 4 task-listed files modified; 2 out-of-scope files (.fullsend/harness/verify-pr.yaml, .fullsend/lock.yaml) are a justified harness re-pin/lock so the fixed pre-script runs in CI.
Diff Size PASS 406 insertions / 45 deletions across 6 files - test-heavy (266-line test file) plus machine-regenerated lock; proportionate.
Commit Traceability WARN 1 of 3 commits references TC-6343 (02f271b); the other two reference related issues TC-6332 (fix) and TC-6349 (docs).
Sensitive Patterns PASS No secrets, keys, tokens, or credentials in added lines; sha256 lock hashes and commit SHAs are not secrets.
CI Status WARN All substantive checks pass (Plugin Validation, Skill Lint, Sourcery, Script Unit Tests 3.11-3.14, wait-for-checks). Only non-passing entry is verify-pr's own 'Harness run (verify-pr)' (in_progress -> pending) - the self-referential run this PR exists to exclude; the best-effort prefetch did not self-exclude it this run.
Acceptance Criteria PASS 5 of 5 criteria met - filter_own_check_runs helper, name-based shell enumeration, reproducer + filter/preservation unit tests, no regression (additive test changes).
Test Quality PASS Repetitive Test Detection PASS (distinct edge cases, no parameterizable duplicates); Test Documentation PASS (all 14 added tests have docstrings); Eval Quality: N/A (no eval reviews).
Test Change Classification ADDITIVE Only new def test_* functions and fixtures added; no existing tests removed or assertions relaxed.
Verification Commands PASS pytest test_pre_verify_pr.py evidenced green by CI Script Unit Tests x4 (all success on PR head); new tests present in diff; no eval-infra changes.

Overall: WARN

Overall: WARN - no FAIL, but several WARN checks a human should weigh before merging:

  • CI Status (WARN) is self-referential: every substantive check passes; the only non-passing entry is verify-pr's own in-progress harness run - precisely the run this PR (fixing TC-6332) teaches the prefetch to self-exclude. The self-exclusion is best-effort and did not apply to this run's own prefetch.
  • Review Feedback (WARN): sourcery-ai flagged that the correctness.md self-exclusion note was worded unconditionally though the mechanism is best-effort. Already classified and tracked by sub-task TC-6349 and addressed by commit da053ba (note reworded to describe the fallback). No new sub-task created this run (idempotent).
  • Scope Containment (WARN): two out-of-scope files (.fullsend/harness/verify-pr.yaml, .fullsend/lock.yaml) are a justified harness re-pin so the fixed pre-script/correctness.md actually run in CI - not scope creep.
  • Commit Traceability (WARN): only 1 of 3 commits names TC-6343; the other two cite the related bug (TC-6332) and sub-task (TC-6349).

Sourcery also noted (informationally) that name-based CI self-exclusion changes verification policy for every PR and could mask a genuinely failing check - a human reviewer should weigh that trade-off. This skill does not merge the PR or transition the issue.


This comment was AI-generated by sdlc-workflow/verify-pr v0.13.9.

@mrizzi
mrizzi merged commit 162be4a into verify-pr-fullsend Sep 17, 2026
18 checks passed
@mrizzi
mrizzi deleted the TC-6343 branch September 17, 2026 17:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant