Skip to content

Move the Null GraphQL Node Check Into the Shared Transport - #3816

Merged
ptr727 merged 2 commits into
developfrom
burndown/3687-graphql-null-node
Nov 2, 2026
Merged

ptr727 merged 2 commits into
developfrom
burndown/3687-graphql-null-node

Conversation

@ptr727

@ptr727 ptr727 commented Nov 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • gh_graphql.request() now raises NullNodeError (a GraphQLError) when any nodes list in the response holds a null. The check and null_node() live in the shared transport.
  • pr_review.gh_graphql() keeps its query-only re-read around the new error and ends the run naming where the null sat. A mutation is never sent twice.
  • Removed the per-site isinstance(n, dict) guards in pr_cleanup.py that the transport makes redundant. handoff.py's label-node read, which raised TypeError on a null node, now reports exit 2 through its existing GraphQLError handling.
  • Tests: null node through the shared transport, the moved null_node helper, and handoff.labeled with a null label node.

pr_review.py shrinks by one line. pr_review_rounds.null_node is now unused by scripts and is left for a follow-up since that file is outside this change.

Closes on promotion: #3687

🤖 Generated with Claude Code

request() now raises NullNodeError on a null item in any nodes list, so every
caller shares one check. pr_review keeps its query-only re-read around it,
pr_cleanup drops two guards it makes redundant, and handoff reports a null
label node as a read that did not run.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings November 2, 2026 18:18
@coderabbitai

coderabbitai Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Important

  • Trigger review

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

Run configuration
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

Share

@ptr727

ptr727 commented Nov 2, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head d3b3da64646aedd680570cd29300b3525d89175e, the content this pull request carries at that commit against develop, and it recorded 2 findings.

Copilot AI 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.

🟡 Changes recommended

Unresolved findings remain, most notably a moderate issue where removing the null base-node guard in scripts/pr_cleanup.py sends those responses down an untested unread-reporting path for the bases, merged, and finished connections.

2 open issues
What changed in this PR

This PR moves the check for null items in GraphQL nodes lists into the shared transport, scripts/gh_graphql.py. Before, each caller had to guard against them, and handoff.py did not. Now request() raises NullNodeError, a subclass of GraphQLError, and pr_review.py keeps its query-only re-read. It also closes #3687.

Changes:

  • gh_graphql.request() raises NullNodeError, which names the first connection holding a null. The null_node() helper moved here as well.
  • pr_review.gh_graphql() still re-reads queries that hit a null, but never re-sends a mutation. A null that persists ends the run and names where it sat.
  • The isinstance guards in pr_cleanup.py are removed. A null in handoff.py's label read now reports exit 2 instead of raising TypeError.
File Description
tests/​test_pr_review.py Drops the test for the old local null_node helper. The re-read and mutation tests stay.
tests/​test_handoff.py Adds a test that a null label node is reported as an execution failure.
tests/​test_gh_graphql.py Adds tests that request() raises NullNodeError with the right location, and that null_node() finds nulls.
scripts/​pr_review.py Catches NullNodeError in the re-read path and drops the old helper import.
scripts/​pr_cleanup.py Removes the per-site isinstance guards, since the transport now handles nulls.
scripts/​gh_graphql.py Adds NullNodeError and the null_node() check that runs before request() returns.

Review effort: Lite

Comment thread scripts/pr_cleanup.py Resolved
Comment thread tests/test_gh_graphql.py Resolved
@codecov

codecov Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.91%. Comparing base (b38e084) to head (77f3be9).
⚠️ Report is 73 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #3816      +/-   ##
===========================================
+ Coverage    81.60%   82.91%   +1.30%     
===========================================
  Files           26       29       +3     
  Lines         9070     9750     +680     
===========================================
+ Hits          7402     8084     +682     
+ Misses        1668     1666       -2     
Flag Coverage Δ
python-3.13 82.91% <100.00%> (+1.30%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@ptr727

ptr727 commented Nov 2, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head 77f3be9fd17ccde9d287819cfeb01de9a495e847, the content this pull request carries at that commit against develop, and it recorded 2 findings.

@ptr727
ptr727 merged commit 71ad0a3 into develop Nov 2, 2026
13 checks passed
@ptr727
ptr727 deleted the burndown/3687-graphql-null-node branch November 2, 2026 18:41
ptr727 added a commit that referenced this pull request Nov 3, 2026
…rge on a Running Hosted Review, and Gate Skill Description Length (#3843)

Promotes the changes merged into `develop` since promotion #3797 to
`main`, the end of an away-mode backlog burndown.

- [#3803](#3803) exempts
the Roslyn embedded-language marker (`// lang=json`, `language=`) from
the prose gate's comment rules as a tool directive.
- [#3807](#3807) has
`local_review.py record` take `--report`, the file the reviewer wrote,
bind the pass to its sha256, and derive the finding count from it.
`status` gains `reportPath`.
- [#3809](#3809) holds
`pr_review.py merge` while a hosted review is still running on the head,
and routes a declined Qodo finding to a dismiss request.
- [#3811](#3811) dates an
anchored `intentRef` by the section its anchor names, and lets a
`driftNote` acknowledge a verified intent advisory.
- [#3816](#3816) moves the
null GraphQL node check into the shared `gh_graphql` transport as
`NullNodeError`.
- [#3818](#3818) explains
the workspace-edit default in `GOVERNANCE.md` and names the aggregator's
expression form.
- [#3822](#3822) moves the
abandon discard to the `backlog-burndown` orchestrator, aligns the
abandoned-branch delete, and holds a grown agent-safety set.
- [#3823](#3823) scopes
the Husky prose gate to staged paths and adds `--skip-generated` so a
named file inside a generated tree is skipped.
- [#3828](#3828) reads
Copilot's `Open findings:` label, drops the duplicate `null_node`, and
matches `scripts/README.md` to the Merge Gate.
- [#3829](#3829) bumps the
two stale hub caller snippet pins and documents the fallback's
mixed-pair refusal.
- [#3831](#3831) keeps an
inherited `GIT_DIR` from rerooting the prose gate's subdirectory git
reads.
- [#3832](#3832) gives
`backlog-burndown` a disposition for a worker's standalone clone and
keeps the agent-safety hold past a park.
- [#3835](#3835) makes
`carry.py check-sections` refuse what `apply-sections` would, and name
an open fence.
- [#3836](#3836) pins the
reusable-workflow stubs by placeholder and ticks the PlexCleaner gates
item.
- [#3838](#3838) has the
`runtime-secrets` audit dimension detect a bare `secrets/` directory
from the tracked files that name it.
- [#3839](#3839) gates
skill descriptions at the 1024-character limit and trims every one over
it.
- [#3846](#3846) fixes an
adjacent doc, an in-file pre-existing defect, and an edge case on new
code in the open pull request instead of filing an issue for each, and
keeps filing for code that runs elsewhere.
- [#3847](#3847) refuses
skill frontmatter that parses to a list or a scalar, so the description
length gate cannot be bypassed.

Fixes #3770
Fixes #3699
Fixes #3705
Fixes #3789
Fixes #1819
Fixes #727
Fixes #3710
Fixes #3706
Fixes #3623
Fixes #3687
Fixes #3617
Fixes #3757
Fixes #3790
Fixes #3786
Fixes #3785
Fixes #3772
Fixes #1657
Fixes #3443
Fixes #3824
Fixes #3817
Fixes #3805
Fixes #1666
Fixes #3700
Fixes #3821
Fixes #3771
Fixes #3794
Fixes #3825
Fixes #3690
Fixes #1472
Fixes #3813
Fixes #3719
Fixes #1592
Fixes #3845

🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.

2 participants