Repository navigation
chore(graph-sdk): run Rewrite as a per-target operation with a covering verifier - #345
Merged
binaryaaron merged 6 commits intoOct 30, 2026
Conversation
One protect() call now runs the rewrite over the entity rows of the detection frame. The invocation-scoped `rewrite` operation wraps the existing frame stages (or the combined workflow) and fans out text plus a metrics value per target, keyed on the row order. The model-free `assess-final` verifier turns the final evaluation into the privacy assessment. needs_human_review is assigned from the record: not met, or utility below the flag. A row whose rewrite is not text fails as RewriteUnavailable, stays in the output with null text and does not abort the run. 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Aaron Gonzales <aagonzales@nvidia.com>
E16.1 attributes the verifier's assessment to the loop's last value, E16.2 shows a target the body fails stays out of the protected set while the run completes, and E16.3 reports the observed request count exactly under an opaque operation and a verifier that declares none. 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Aaron Gonzales <aagonzales@nvidia.com>
The record-derived column overwrote the combined path's Arrow bool column with a NumPy bool one. Build the column in the dtype the frame already holds, falling back to bool for the staged path, so the output frames match the pre-change ones dtype for dtype. 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Aaron Gonzales <aagonzales@nvidia.com>
Add E16.4-E16.9: the final verifier's leakage rules and thresholds, the needs_human_review projection and its dtype, error propagation out of the rewrite body, source positions with passthrough rows, and the replacement readiness default. 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Aaron Gonzales <aagonzales@nvidia.com>
Add E16.10 (rows returned in partial-repair order keep their own text and metrics, output in input order) and E16.11 (numpy and pyarrow booleans for replacement readiness are coerced like a Python bool). 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Aaron Gonzales <aagonzales@nvidia.com>
…on order in SP-16 Add E16.12 (a row dropped by the backend leaves every surviving target its own metrics and review flag) and E16.13 (a target that is not met with no utility score is flagged without raising). 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Aaron Gonzales <aagonzales@nvidia.com>
Base automatically changed from
aagonzales/chore/graph-sdk-execution-backend
to
aagonzales/graph-sdk/feat/main
October 29, 2026 21:15
This was referenced Oct 29, 2026
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.
Rewrite mode now runs as one graph invocation, and the record decides each row's release. An invocation-scoped
rewritestep runs today's Rewrite pipeline once over all entity rows. A model-freeassess-finalverifier then turns each row's final evaluation into an assessment.needs_human_reviewis projected from the record. Output columns, row sets and DataDesigner calls match the base, and no public name is added.This branch stacks on #319 and lands on #319's branch by fast-forward, without rewriting history.
What changes
The
rewriteoperation (engine/rewrite/rewrite_workflow.py)._rewrite_loweredmakes one target per entity row; rows with no entities stay outside the graph and take the passthrough defaults as before. The step runs the existing stages as plain calls:rewrite-combinedworkflow.The step fans out per target as
textplus arewrite-metricsvalue. Therewrite-metricskind is registered by name only, not exported. The fan-out is keyed on each row's input position, so a frame that repair has reordered still maps each row to its own target. Each row's entry falls into one of three cases:RewriteUnavailable, and its output row stays with null text;missing_output;The verifier.
assess-finalreads the final candidate's metrics and calls no model. A target is met when the privacy checks pass: no high-sensitivity leak, the replacement was ready, and leakage is withinflag_leakage_above. The last evaluation in the repair loop already scored the final candidate, so the DataDesigner calls are exactly the base's.The review flag.
needs_human_reviewis assigned in one place, per row: true when the target is not met, or when utility is belowflag_utility_below. Protection and the human-review flag stay separate decisions, so a row flagged only for low utility is protected and still flagged. The values and dtypes equal the base's on both paths. On the combined path, the finalizer still computes its own value inside the DataDesigner workflow, and that value agreed in every probed case.The combined workflow (
combined_rewrite_workflow.py). It runs through the same lowering. Its DataDesigner column config is unchanged.Spec program SP-16. It has thirteen checks:
evaluate(), detection, the Replace routes and the kernel are unchanged. Detection in Rewrite mode still runs before the graph, and moves into it with theevaluate()change.Net non-blank, non-comment, non-docstring code lines under
src/: +69 (rewrite_workflow.py+76,combined_rewrite_workflow.py−7).Known differences
TypeErrorfor the whole run.needs_human_reviewcolumn, the projected column keeps that column's dtype; before, the staged path replaced it withbool.Checks
make checkpasses.make test: 1,593 passed, withtest_wandb_snapshot_rejects_fifo_socket_and_devicedeselected as on the base.uv run --group dev python -m tests.spec_programs.run_all: 97 pass, 8 retired, 0 fail.Anonymizer.runon both Rewrite paths ran 176 assertions:needs_human_reviewequals "not met, or utility below the floor" on every row;f294dc1e) on pandas 2 and 3, over all cases: no blocking difference. Against the base branch, case by case: no blocking difference, and the only informational differences are trace-column order at the level main shows against itself.🤖 Generated with Claude Code