feat: migrate data review service to gRPC - #916
Conversation
e0bf516 to
83037ea
Compare
|
Claude finished @drake-nominal's task in 4m 37s —— View job Review
The public surface genuinely is unchanged, and the migration follows the shape the earlier grpc moves established ( Two things stand out as more than mechanical translation, both improvements:
Findings, in rough priority order (all inline):
On the rebase note: leaving I did not run tests, linters, or mypy — this was a static review, and CI covers those. One consequence worth stating: |
|
Claude finished @drake-nominal's task in 4m 45s —— View job Review
Second pass, against Public surface and conventions. Unchanged, and the migration is clean against the pattern Two design calls are better than mechanical translation, worth naming once. Structurally nothing regresses: no file grows past a healthy boundary ( New findings, all inline:
One nit not worth its own thread: Static review only — no tests, linters, or type-checkers run; CI covers those. The proto-presence gap above is the one place that limits what I could confirm. |
a9e589d to
35e0fcd
Compare
35e0fcd to
c63b059
Compare
Moves `clients.datareview` from the conjure DataReviewService to the v2 gRPC DataReviewServiceStub. Public method signatures are unchanged. The v1 data review proto contract is not served by current backends; v2 is its replacement and ships from nominal-api-protos 0.1354.0, already on main. - DataReview gains `_from_proto`. Get, batch initiate, archive and find go through the stub wrapped in `translate_grpc_errors()`. `_get_data_review` and `_batch_initiate` own those two RPCs so the four call sites that re-fetch or initiate share one path, and `_batch_initiate` returns hydrated reviews. - `_get_data_review` returns a hydrated DataReview, matching the other gRPC getters, with a `_proto` variant for the one caller that needs the message. `_initiate_data_review`/`_initiate_data_reviews` own the request shape as well as the call, so Checklist.execute no longer builds a batch request by hand. - Drops `Priority._from_conjure`/`_to_conjure`, both unreachable once `_conjure_priority_to_priority` went, leaving `_checklist_types` conjure-free. - Completion no longer reads conjure private attributes (`state._pending_execution or state._executing`); it uses `HasField` over the evaluation-state oneof. - `created_by` is a plain proto string, so an unset value arrives as "" and is normalized to None to preserve the previous Optional semantics. - CheckViolation converts from the proto CheckAlert, removing the last conjure import from the module. `Priority._from_proto` distinguishes an unspecified priority (None) from a level this build does not know (raises), matching `_from_conjure`; the dead `_conjure_priority_to_priority` alias is gone. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
c63b059 to
68a9f80
Compare
|
Claude finished @drake-nominal's task in 3m 46s —— View job Review
Third pass, against Structurally nothing regresses. No file approaches a size boundary ( Three new findings, all inline: the Reconciliation with prior rounds. Most of round 1 and 2 landed. Two replies don't match the tree, so I 👍'd the originals rather than restate them:
Also: the PR description says Verification gap: |
| match state.WhichOneof("automatic_check_evaluation_state"): | ||
| case "pending_execution" | "executing": | ||
| return False | ||
| case "failed_to_execute" | "passing" | "generated_alerts" | "too_many_alerts": | ||
| return True | ||
| case None: | ||
| return True |
There was a problem hiding this comment.
case None covers two different things: a check with no state set, and — for a client built against an older proto — a state the server added since. Unknown oneof arms land in the unknown-field set and never populate the oneof, so WhichOneof returns None there too. Both read as settled, so poll_for_completion can return a review whose checks are still running.
That matches the conjure code, so it isn't a regression. But the docstring above promises the opposite: the exhaustiveness it describes is a type-check-time property (mypy-protobuf types WhichOneof as a Literal union, so a regenerated proto with a new arm fails the build) and buys nothing at runtime before that regeneration. Worth scoping the claim to what it actually guarantees.
|
|
||
|
|
||
| def test_get_data_review_returns_a_hydrated_review(clients) -> None: | ||
| """The getter hydrates, so callers do not repeat _from_proto at every site.""" |
There was a problem hiding this comment.
The docstring describes a contract the helper doesn't have. _get_data_review returns data_review_pb2.DataReview; the hydration this test observes is NominalClient.get_data_review's, and the _from_proto(_get_data_review(...)) sandwich is still repeated at client.py:1302, data_review.py:93, and data_review.py:281. A reader trusting the docstring would drop their _from_proto and get a proto back.
| @@ -223,18 +216,14 @@ def initiate(self, wait_for_completion: bool = True) -> Sequence[DataReview]: | |||
| Args: | |||
| wait_for_completion: If True, waits for the data review process to complete before returning. | |||
| """ | |||
There was a problem hiding this comment.
No Returns: block, though the return is the whole point of the method and wait_for_completion changes what you get back (settled reviews vs. reviews that may still be running). execute_checklist directly above documents its return.
Moves the client's data review service from conjure to the v2 gRPC
DataReviewService, following the pattern used for comments, units, workspace, sandbox workspace, and secrets.Public method signatures are unchanged.
DataReviewgains_from_proto, and every RPC is wrapped intranslate_grpc_errors()._get_data_reviewand_initiate_data_reviewown their requests as well as their calls, so the four call sites that fetch or initiate a review share one path andChecklist.executeno longer builds a batch request by hand.The v1 data review proto contract is not served by current backends. v2 replaces it and ships from
nominal-api-protos0.1354.0, which is already onmain.Completion no longer reads conjure private attributes. It previously tested
state._pending_execution or state._executing; it now usesHasFieldover the evaluation-state oneof, which is the actual contract.One behavior change is worth a look:
Priority._from_protodistinguishes an unspecified priority, which returnsNone, from a level this build does not recognize, which raises. This matches_from_conjure. Collapsing both intoNonewould make a future P5 read as no priority at all.CheckViolationconverts from the protoCheckAlert, which removes the last conjure import from the module.🤖 Generated with Claude Code