Repository navigation
Move the Null GraphQL Node Check Into the Shared Transport - #3816
Conversation
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>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
|
A recorded local strict-review pass covers head |
There was a problem hiding this comment.
🟡 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()raisesNullNodeError, which names the first connection holding a null. Thenull_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
isinstanceguards inpr_cleanup.pyare removed. A null inhandoff.py's label read now reports exit 2 instead of raisingTypeError.
| 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
Codecov Report✅ All modified and coverable lines are covered by tests. 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
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
A recorded local strict-review pass covers head |
…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)


Summary
gh_graphql.request()now raisesNullNodeError(aGraphQLError) when anynodeslist in the response holds a null. The check andnull_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.isinstance(n, dict)guards inpr_cleanup.pythat the transport makes redundant.handoff.py's label-node read, which raisedTypeErroron a null node, now reports exit 2 through its existingGraphQLErrorhandling.null_nodehelper, andhandoff.labeledwith a null label node.pr_review.pyshrinks by one line.pr_review_rounds.null_nodeis 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