Collapse two pieces of copy-paste plumbing - #408
Merged
Conversation
store_code_review_diff took 18 parameters, the widest signature in the repo. Fifteen of them were pure transport: the intent pulled them out of the fetch bundle with .get() one at a time, only for the method to set them straight onto node.state. It now takes the bundle whole. `pr_url` stays a separate argument because it is genuinely not part of the bundle - it is what the user typed, and it is kept even when the fetch that used it is superseded. The intent's call site drops from 17 lines to one. Widest signature in backend/ is now 15 (run_lifecycle.run_single_shot). The per-field coercion moves with it, into a small _bundle_int: the bundle is built from a GitHub API response, so every numeric field in it is external input. diff_fetch.py already coerces on the way in; this is the second line of the same defence, for a bundle arriving by any other route. Verified: pr_number="twelve", additions="lots", changed_files=-5 and a non-dict entry in files all land as 0/0/0 and a dropped row rather than raising. Separately, start_gitlink_apply had five refusal paths that each repeated the same four lines - clear pending_request_id, release the registry slot, report, publish. Four chances each to forget one, and forgetting either of the first two is not cosmetic: a missed pending_request_id leaves the node permanently busy, a missed release leaks the slot for the session. They share one _abandon() now. Its await sits on the abandon path only, so the atomic check-and-freeze section keeps its zero-await guarantee - the comparisons there still run with no suspension point between them. The two remaining bare cleanups in that file are the task-completion `finally` blocks, which are a different concern and correctly use the guarded `if node.pending_request_id == request_id` form. Test plan: - 12 existing store_code_review_diff call sites updated; they were already unpacking a dict, so they got shorter too. - Full suite: 3212 passed, 19 skipped. ruff and mypy clean. Note for the record: the _bundle_int helper first landed between the @DataClass decorator and SceneDocument, breaking the module on import - the same line-heuristic mistake as the previous change. Caught by the test collection, relocated above the decorator. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
store_code_review_difftook 18 parameters — the widest signature in the repo. Fifteen of them were pure transport: the intent pulled them out of the fetch bundle with.get()one at a time, only for the method to set them straight ontonode.state.start_gitlink_applyhad five refusal paths that each repeated the same four lines:Four chances each to forget one, and forgetting either of the first two is not cosmetic — a missed
pending_request_idleaves the node permanently busy, a missedrelease()leaks the registry slot for the rest of the session.Change
store_code_review_difftakes the bundle whole.pr_urlstays a separate argument because it genuinely is not part of the bundle — it is what the user typed, and it survives the fetch that used it being superseded. The intent's call site drops from 17 lines to one. The widest signature inbackend/is now 15 (run_lifecycle.run_single_shot).The per-field coercion moves with it into a small
_bundle_int. The bundle is built from a GitHub API response, so every numeric field in it is external input;diff_fetch.pyalready coerces on the way in, and this is the second line of the same defence for a bundle arriving by any other route. Verified:The five gitlink refusal paths share one
_abandon(). Itsawaitsits on the abandon path only, so the atomic check-and-freeze section keeps its zero-await guarantee — the comparisons there still run with no suspension point between them;_abandononly runs once one of them has already decided to give up. The two remaining bare cleanups in that file are the task-completionfinallyblocks, a different concern, correctly using the guardedif node.pending_request_id == request_idform.Test plan
store_code_review_diffcall sites updated. They were already unpacking a dict (**{k: v for k, v in _bundle().items()}), so they got shorter too.ruffandmypyclean.Note for the record: the
_bundle_inthelper first landed between the@dataclassdecorator andSceneDocument, breaking the module on import — the same line-heuristic mistake as the previous change. Caught by test collection and relocated above the decorator.🤖 Generated with Claude Code