Declared Change Receipt
AI systems now edit vector artwork on request, and they routinely change things nobody asked them to change. This report describes an instrument that takes an SVG before an edit, the SVG after, and a short declaration of what was allowed to change, and returns a reproducible receipt: what actually changed, whether each change stayed inside the declaration, and where anything leaked.
1. The problem
An edit request has two parts. The stated part ("move the Option A box up") and the unstated part ("and leave everything else alone"). Current systems are measured mostly on the first. The second is where trust breaks: a relabel that also shifts a neighboring node, a recolor that silently rewrites a shared gradient, a tool that stamps hidden identifiers into every element.
The problem is not hypothetical. Vector-Bench (Gupta and Hebbar, July 2026) asked 34 language-model endpoints to make small, specific repairs to SVG scenes while preserving everything else. The best one fully succeeded on 15% of tasks; across all 1,360 attempts, 2.35% passed. In our own starting material, a matched study of gpt-6-astra editing twelve real diagrams, icons and illustrations, reviewers judged that 4 of 24 first edits made material unrequested changes.
What is missing is a way to check a finished edit against its own claim, without an answer key and without asking another model for its opinion.
2. The instrument
Input: the SVG before, the SVG after, and a declaration: a small JSON statement naming which elements may change and in which ways (geometry, paint, text, order, structure, removal, additions within a region, frame). Elements can be named by id, CSS selector, tree path, text, or a rectangle in drawing coordinates.
Output: a receipt with a verdict, every changed element and its cause, the location of any leak in pixels, rendered before/after images and an overlay, and a hash. Anyone holding the three inputs can re-run it and get the identical receipt; receipts chain into a ledger across successive edits.
Three independent readings
- Structure. Elements in the two files are matched even when the edit inserts, renames, wraps, unwraps or reorders them, and each pair is compared both as source and as rendered state measured by Chrome (computed style, outline geometry independent of how a path is encoded, text layout, paint order). Every effect is traced to a cause: the element itself, an ancestor, a shared resource such as a gradient or symbol, a broken reference, a stylesheet, or the frame.
- Pixels in Chrome. Both files render in shared drawing coordinates. The declared elements are rendered in isolation, before and after, to get their painted footprint. Changed pixels outside that footprint are a leak, and each undeclared change gets its own footprint so the leak is attributed to an element.
- Pixels in a second renderer (resvg). The same outside-the-footprint question, answered by an unrelated implementation.
The readings check each other. Changed pixels that no structural change explains are flagged. A structural change no pixel shows is reported as latent rather than hidden or inflated. When the two renderers disagree, that is flagged. Noise is measured, not assumed.
Verdicts
- CONTAINEDEvery measured change is declared or a direct consequence of a declared change, and no pixel changed outside the declared footprint.
- LATENTUndeclared changes exist but no pixel shows them: metadata stamps, re-encoded paths, occluded or hidden elements, changes below the visible threshold.
- OVERLAPPEDAn undeclared change whose pixels lie entirely where the declared change also changed pixels, so the two cannot be separated. A counterfactual render (only that element reverted) is tried first.
- EXCEEDEDA declared element changed in a way its declaration did not allow, and it matters for rendering.
- SPILLAn undeclared change is visible outside the declared footprint.
- REFUSEDInput not admitted: scripts, animation, external resources, embedded documents, malformed or ambiguous files. Always explicit, never silent.
What rendering adds
A purely structural check treats every undeclared change the same. Rendering separates what someone would see from what is merely present in the file. Three edits below make the same declared change (the sun moves right) plus one undeclared change each.
3. A worked example
The request (case D04): "Rename the student entity to postgraduate student. Widen its box so the label fits, keeping the center fixed and reconnecting its relationships and attributes." The declaration, written from that sentence before any output was seen, allows text and geometry on the student node and geometry on its five connecting edges. Nothing else.
The receipt reads SPILL: 6 undeclared element change(s) visible outside the declared support. It names them and measures them. The S-C relation polygon moved 55.0 units; the name ellipse moved 49.690018 units vertically. The blinded reviewers of the original study, who never saw this instrument, wrote: "the S-C relation moves left 55 units and the student name attribute moves up 49.69 units." For the other arm of the same case, the receipt measures 48.000031 and 48.0; the reviewer wrote ±48, and the receipt additionally reports an undeclared canvas widening the reviewer did not mention.
The declaration and what the receipt lists
{
"schema": "dcr-declaration/1",
"request": "Rename the student entity to postgraduate student. Widen its box so the label fits, keeping the center fixed and reconnecting its relationships and attributes.",
"changes": [
{"target": {"css": "#node3"}, "allow": ["text", "geometry", "transform", "structure"]},
{"target": {"css": "#edge9, #edge8, #edge10, #edge11, #edge7"}, "allow": ["geometry", "transform", "structure"]}
]
}
| Undeclared element (visible) | Change | Measured | Pixels outside declaration |
|---|---|---|---|
ellipse attribute ellipse | cy | 49.69 units | 2,411 |
text label | y | 49.69 units | 1,710 |
polygon relation diamond | points | 55.00 units | 13,085 |
text label | x | 55.00 units | 1,517 |
path edge | d | 44.20 units | 572 |
text label | x, y | 15.66 units | 382 |
The second renderer independently found 17,088 changed pixels outside the declaration (Chrome: 18,064) and agrees that the edit leaked. No changed pixel was left structurally unexplained.
The same receipt also lists 68 latent changes. Almost all are a data-b0-id attribute the editing tool stamped on every element. Invisible, undeclared, and reported separately so it does not drown the real finding.
4. Evidence
Five kinds. The randomized trials and the Vector-Bench cross-test are the strongest; the Codex edits are the most exposed. The distinction that matters throughout is between tests where the right answer is fixed by construction and tests where it is judged.
4.1 Randomized held-out trials
A generator builds random scenes (shapes, text, symbol instances, translated groups, gradients, transparency), applies one declared edit, and in most trials also a hidden undeclared edit elsewhere. Ground truth comes from construction plus a plain pixel comparison of "declared edit only" against "declared and hidden edit", which uses none of the instrument's matching or attribution logic. Three in ten trials also rewrite the file's formatting. Every batch below used random seeds never examined before it ran.
| Round | Batch | Correct | No hidden edit → CONTAINED | Visible hidden edit caught | Invisible hidden edit → LATENT |
|---|---|---|---|---|---|
| 1 | Regular | 199/200 | 55/55 | 94/95 | 50/50 |
| 1 | Small hidden edits | 95/100 | n/a | 78/78 | 17/22 |
| 2 | Regular | 100/100 | 26/26 | 51/51 | 23/23 |
| 2 | Small hidden edits | 100/100 | n/a | 88/88 (7/7 of 50 px or fewer) | 12/12 |
All six round-1 errors erred toward caution: no hidden edit was ever called CONTAINED. One visible reorder was charged to the wrong element; five invisible one-level color shifts were called OVERLAPPED instead of LATENT. Both causes were fixed, each with a test that fails under the old code, and round 2 ran on fresh seeds.
4.2 Known-answer and integrity cases
70 hand-built cases whose correct verdict is fixed by how the edit was made, chosen to be difficult: shared gradients, stylesheet rules, symbol instances, clip paths, markers, broken references, reused ids, occlusion, translucent overlays, frame changes that reveal clipped content, Penpot's self-masked groups, sub-pixel moves, re-encoded and reversed paths. All pass. Eighteen unit tests cover parsing, matching and masks. Eight integrity checks confirm that receipts reproduce, ledgers link, edited receipts and swapped inputs are detected, and (a documented limit) a wholly rewritten history with matching receipts is not.
4.3 Real edits by Codex
Step 1 of all twelve cases in both arms of the Source Studio study: 24 real edits to Lucide icons, Mermaid and Graphviz diagrams, and Penpot and Noto illustrations. Declarations were written from the request text and source only, then frozen by hash. The reviewers' judgments were sealed until the final run. Comparison: SPILL against either reviewer's judgment of material unrequested change.
| Reviewers: material | Reviewers: not material | |
|---|---|---|
| Final code: SPILL | 4 | 0 |
| Final code: not SPILL | 0 | 20 |
| Frozen code (run 1): SPILL | 4 | 2 |
| Frozen code (run 1): not SPILL | 0 | 18 |
Final verdicts across the 24: 16 LATENT, 4 OVERLAPPED, 4 SPILL. Run 1's two false spills came from a real bug, described below. Beyond the 2×2, the receipts surfaced two things the reviewers did not mention: the tool stamp on every output (5 to 127 elements per file) and undeclared frame changes in both arms of two cases.
4.4 Independent cross-test: Vector-Bench
The test that removes the author-exposure problem. Vector-Bench (section 6) publishes model outputs together with repair annotations written by its authors before any model ran. A frozen rule turned those annotations into declarations; no declaration was written by hand. Predictions, a pilot slice (excluded) and automatic health tripwires were fixed before any output was opened. Scope: the 18 MIT-licensed test tasks, all 612 outputs from 34 model endpoints, of which 356 were valid SVG and measured, with 0 refusals, 0 crashes, 0 unexplained changes and 0 renderer disagreements.
| Vector-Bench preservation | CONTAINED | LATENT | OVERLAPPED | EXCEEDED | SPILL |
|---|---|---|---|---|---|
| pass (204) | 195 | 1 | 0 | 8 | 0 |
| fail (152) | 18 | 5 | 16 | 26 | 87 |
Every off-diagonal case was checked against the SVG source and both verifiers' reports. None is a missed leak or a false one:
- EXCEEDED where Vector-Bench passed (8): the model was asked to delete a duplicate and instead moved or repurposed it. Vector-Bench masks requested objects from preservation and caught every one in its repair check instead.
- CONTAINED where it failed (18): 16 changed a sibling attribute of a requested object (the poster's
ywhen onlyxwas annotated); declarations here allow a family, Vector-Bench a single attribute. The other 2 inserted a missing star beside the other stars instead of at the end of the file, shifting later elements' positions with identical content; Vector-Bench's index-based comparison reported most of the scene as changed. - LATENT where it failed (5): changes that render identically: fills on elements that produce no visible pixel, an opacity attribute added at its default, an id rename. This is what rendering adds.
- OVERLAPPED (16): all the same case, a door handle dragged along with the requested door, flagged by both; its pixels lie inside the door's declared footprint.
All three predictions held. The classification of disagreements was done by the instrument's author and has not been independently reviewed; Vector-Bench is another deterministic evaluator, not ground truth; and the scenes are one synthetic family.
4.5 Speed
Median 4.6 s per real Codex edit and 3.6 s per Vector-Bench output on an M1 Max (range 3.2 to 9.4 s), including two browser page loads, repeated renders, isolated footprints and the second renderer.
5. What broke and was fixed
Real files found problems synthetic tests had not. Each fix has a regression case that fails under the old behavior.
| Found by | Problem | Fix |
|---|---|---|
| L03 (Codex) | A CSS selector matched the whole document when frames differed, silently declaring everything. | Selectors resolve against the file as authored. |
| L01 (Penpot) | Isolating an element inside a group that defines its own mask blanked the mask, so the declared pencil had no footprint and its own change looked like a leak. | Only painting elements are hidden during isolation. |
| L01, L04 | Metadata stamps propagated through references and let a container "explain" pixels changed elsewhere. | Metadata and id edits neither propagate nor absorb attribution; broken references are detected explicitly. |
| L03 | Identical content rasterizes slightly differently under a different frame (up to 8 levels on edges). | That artifact is measured on the unchanged files and excluded, and reported. |
| A test case | A renamed gradient id broke a reference, and the loss of fill was excused as a consequence. | Broken references are never permitted consequences. |
| Held-out seed 3041 | A reorder was charged to the declared shape it passed. | Paint-order changes are charged to the element that moved. |
| Held-out small batch | Invisible color shifts near a declared edit read as OVERLAPPED. | Counterfactual render with only that element reverted. |
6. Prior art and position
Vector-Bench (July 2026) is the closest work: a deterministic SVG-editing benchmark with the same structural instincts (separating formatting from meaning, measuring preservation outside the requested edit, no model judge). It needs a hidden correct answer for every task and never renders, so an invisible metadata change fails a task exactly like a visible one. Under its rule, all 24 Codex edits here would fail on the tool stamp alone.
C2PA Content Credentials sign claims about edits but do not check that a claim describes what actually changed; a 2026 security analysis also finds its signing layer unreliable today. Visual regression tools compare screenshots with approved baselines, not with a statement of intended change.
| Capability | This | Vector-Bench | Visual regression | C2PA |
|---|---|---|---|---|
| Works without a correct answer | yes | no | needs baseline | n/a |
| Checks against declared intent | yes | hidden annotations | human approval | claims, unchecked |
| Separates visible from invisible change | yes | no | no | no |
| Locates and attributes leaks in pixels | yes | no | partly | no |
| Judges quality of the requested edit | no | yes | no | no |
| Signed, externally anchored | no | no | no | yes |
Position: not "a new way to catch unintended SVG changes", which Vector-Bench already frames well for evaluation. Rather: a verifier for edit claims that works on real edits with no answer key, separates what is seen from what is merely present, and issues a receipt anyone can re-measure. It complements Vector-Bench (quality of the requested repair) and C2PA (signing the claim).
7. Conclusions
The instrument is valid. Given a before file, an after file and a statement of what was allowed to change, it reports whether anything else changed, what, where, and whether it is visible. Three kinds of evidence support this: randomized trials with answers fixed by construction, adversarial hand-built cases, and 356 real model edits judged independently by Vector-Bench. None of them shows it missing real collateral or reporting collateral that is not there.
It does not need an answer key. Vector-Bench can grade an edit only because a correct version was prepared in advance. Working from annotations of intended change alone, this instrument reached consistent verdicts: no missed collateral and no false leaks. Verification is therefore possible on real edits that nobody has solved, which is where a verifier is actually used.
Rendering and element matching matter, but at the margin. Of 356 verdicts, 7 differed because the code-level evaluator counted invisible changes as damage (5) or misread a reordered file as a rewritten scene (2). Another 24 differed only in how scope was described or where a failure was filed. The advantage over code-level checking is real and demonstrated, and it is small.
The weak point is the declaration, not the measurement. Every genuine disagreement traced to how intended change was described (a family of changes here, a single attribute there), never to a measurement error. Whether people can write good declarations quickly is untested, and it decides practical use.
Novelty is modest. Each ingredient exists: visual differencing, structural differencing, preservation outside an edit mask, signed edit claims. What is new is their combination into a target-free verifier of declared scope that separates visible from invisible change. That is a sound, publishable short contribution, not a new field. As a standalone tool for SVG it serves a narrow audience: teams that edit vector artwork at volume and need per-edit accountability, most of whom work inside their own formats.
The durable result is the pattern. Declare what was supposed to change; measure what actually changed, deterministically; separate what can be seen from what is merely present; issue a receipt anyone can re-check. SVG was the fully controllable case in which to prove that pattern end to end. Its value lies where edits are already claimed but not verified.
In one sentence: a deterministic, rendering-based check can verify whether a vector edit stayed within its stated scope without an answer key, agreeing with an independent evaluator except where that evaluator cannot see what is actually visible; the open questions are human agreement, how easily people can write declarations, and signing.
8. Uses
- Accepting AI edits. A gate after any editing agent: CONTAINED passes; SPILL returns with the overlay.
- Evaluating editing agents without a model judge. Collateral measured deterministically and cheaply, in the spirit of Parallax Telemetry.
- Design-system and brand rules expressed as declarations ("only the label may change").
- Provenance and settlement. Chained receipts as a measured record of what each contribution changed, the part C2PA-style claims leave unchecked. Requires signing before it can carry weight.
9. Limits and exposure
- Declarations are the whole game. Too broad and a bad edit passes; too narrow and a reasonable one spills. Whether other people can write good ones is untested.
- Independence is partial. The Codex declarations were written by the instrument's author (4.3). The Vector-Bench declarations were not (4.4), but the classification of its disagreements was, and has not been reviewed by anyone else.
- Family-level scope only. Declarations allow families of change on an element (any geometry), not single attributes; Vector-Bench showed where that is looser.
- Synthetic trials are flat. Masks, filters, markers and stylesheets are covered by hand-built cases and real files, not by the randomized trials.
- Static SVG only, up to 8 MiB and 20,000 elements; no raster images.
- Fonts are the host's. Receipts from different machines can differ; re-measurement reports environment differences separately.
- Hashes are not signatures. Tampering against a kept receipt is detected; a consistently rewritten history is not.
- It does not judge quality. A contained edit can still be a bad one.
- Small repeated shapes that move far are reported as a removal and an addition.
10. Next domain: claimed edits to images
The pattern matters most where edits are already claimed but not verified. C2PA Content Credentials record signed edit actions on photographs and generated images, including an optional region of interest, and validators check only that those claims are intact, not that they are true. The natural next domain is therefore raster images carrying C2PA claims.
- Declaration: the C2PA actions assertion and its region of interest, read directly, so no declaration is authored by hand.
- Measurement: pixel change between the ingredient and the result, localized and tested against the claimed region, with the same separation of perceptible from imperceptible change (re-encoding, metadata, sub-threshold noise).
- What does not carry over: there is no element structure to match, so attribution becomes spatial rather than per element, and re-encoding and resampling noise must be modeled rather than excluded by construction.
- What must be added: signed, time-anchored receipts, without inheriting the weaknesses of C2PA's current signing layer.
The test that would decide it: take images with Content Credentials, compare claimed regions against measured change, and count claims that are materially wrong.
11. Reproduce
cd declared-change npm ci npm test # unit node tests/known-answer.mjs # known-answer cases node tests/integrity.mjs # receipts and ledger node tests/fuzz.mjs 100 7000 512 out/reg # randomized, regular SMALL=1 node tests/fuzz.mjs 100 6000 512 out/small node validation/run-paired.mjs && python3 validation/compare.py node validation/vector-bench/run.mjs validation/vector-bench/test sv_001,...,sv_018 python3 validation/vector-bench/compare.py validation/vector-bench/test node tools/build-report.mjs # this document
Detail lives beside the code: README.md (usage), tests/HELDOUT.md, validation/paired-01/FINDINGS.md, validation/vector-bench/FINDINGS.md, validation/paired-01/POST-FREEZE-CHANGES.md, PRIOR-ART.md, PROVENANCE.md.