Skip to content

Transform Each, Rasterize, Mosaic, Trim Marks and Rearrange: a number given as text is refused - #2917

Merged
bflatastic merged 1 commit into
storytold:mainfrom
dotCooCoo:fix/menu-commands-refuse-text-numbers
Oct 18, 2026
Merged

bflatastic merged 1 commit into
storytold:mainfrom
dotCooCoo:fix/menu-commands-refuse-text-numbers

Conversation

@dotCooCoo

@dotCooCoo dotCooCoo commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

What and why

On main, Transform Each, Rasterize, Create Object Mosaic, Create Trim Marks and Rearrange All Artboards read their optional numbers with f64_or, which falls back to a default for a value that is not a JSON number. object.transformEach {"scaleH": "50"} leaves the selected objects at their size and reports success, and object.createTrimMarks {"offset": "10"} makes the marks at the default offset.

  • object.transformEach (scaleH, scaleV, moveH, moveV, rotate), object.rasterize (ppi), object.createObjectMosaic (width, height, spacingX, spacingY), object.createTrimMarks (offset, length, bleed, weight) and artboard.rearrange (spacing) fail with "<key> must be a number, not " for a value that is not a number or null, as the transform commands do since Transform commands: a string for an optional number is an error (#1952) #1967 and the blend, envelope and mesh commands do since Blends, meshes and envelopes: a number given as text is refused #2851 (check_numbers, crates/engine/src/cmd/mod.rs:321). The document and the undo history stay as they were.
  • object.cropImage refuses a rect that is not an array, such as a string, with "rect must be [x, y, width, height]", the message it already gives for an array of the wrong length. Before, it cropped to the artboard. A null rect crops to the artboard, as a missing one does.
  • docs/mcp.md lists the keys, and docs/target-app-parity.md has one line for the change. The change adds no message, so it adds no catalog rows.

How it was tested

New tests in vectorcraft-engine, each failing on main, where the first call succeeds:

  • tests_menucmds::transform_each_refuses_a_number_given_as_text gives each scale, move and rotate as a string, an array or true; the object keeps its bounds and no undo step is added, and scaleH: 50, scaleV: 50 and moveH: 10 as numbers, with moveV: null, still transform it.
  • tests_menucmds::rasterize_refuses_a_ppi_given_as_text gives ppi as a string or an array; the art stays as it was, and ppi: 144 still rasterizes it.
  • tests::object_mosaic_refuses_a_size_or_spacing_given_as_text gives width, height, spacingX and spacingY as strings or an array; no mosaic is made, and width: 200 with spacingX: null still makes the tiles.
  • tests_menucmds::crop_image_refuses_a_rect_given_as_text gives rect as a string, an object and a number; the image stays as it was, and a null rect crops it to the artboard.
  • tests_menucmds::trim_marks_refuse_a_number_given_as_text gives each key as a string, true or an object, with an object selected and with nothing selected; no marks are made.
  • tests_menucmds::rearrange_refuses_a_spacing_given_as_text gives spacing as a string or false; the artboards stay where they were, and spacing: 50 still spaces them 50 pt apart.

Targeted checks while building: cargo clippy -p vectorcraft-engine --all-targets -- -D warnings; the new tests; cargo fmt --all -- --check; cargo xtask brands, layers and assets.

On Windows 11 (x86-64) with rustc 1.99.1, on top of main at cdba0aa:

  • CRAFT_FONTS_DIR=<craft-fonts checkout> cargo xtask ci passes its 10 steps: 8,256 tests passed, 0 failed, 12 ignored.

git merge-tree reports no conflicts with main at cdba0aa. #2592, #2532, #2403, #2038 and #1838 also change crates/engine/src/cmd/menucmds.rs and merge with this branch there; their conflicts with main in other files are the same with or without this branch.

Checklist

  • cargo xtask ci passes (fmt, clippy, tests, assets, brands, layers, wasm).
  • No panics in shipped code: no unwrap(), expect(), panic!, unreachable!, todo! or
    unimplemented! outside tests, and no unchecked indexing on data from files, parameters or
    messages. Errors are returned as Result and shown to the user
    (why and how).
  • Clean-room: nothing copied from Adobe products or GPL/AGPL code (AGENTS.md).
  • Every new asset has a row in ASSETS.md.

Summary by CodeRabbit

  • Bug Fixes
    • Commands for transforming, rasterizing, creating mosaics or trim marks, cropping, and rearranging artboards now reject invalid numeric inputs without applying changes.
    • Invalid crop rectangles are rejected; an omitted or null rectangle crops to the artboard.
  • Documentation
    • Updated parameter guidance to describe numeric validation and how optional null values are handled.

@coderabbitai

coderabbitai Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 7562f157-5106-4edf-b327-63bc57fc284a
📥 Commits

Reviewing files that changed from the base of the PR and between a9befa3 and cc8944a.

📒 Files selected for processing: 3
  • crates/engine/src/tests.rs
  • docs/mcp.md
  • docs/target-app-parity.md
+----------------------------------------------------------------+
| This is the kind of code that makes on-call believe in ghosts. |
+----------------------------------------------------------------+
  \
   \   (\__/)
       (•ㅅ•)
       /   づ

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: afa67bd6-1662-4781-8cc7-a702952eaecf
📥 Commits

Reviewing files that changed from the base of the PR and between cdba0aa and a9befa3.

📒 Files selected for processing: 5
  • crates/engine/src/cmd/menucmds.rs
  • crates/engine/src/tests.rs
  • crates/engine/src/tests_menucmds.rs
  • docs/mcp.md
  • docs/target-app-parity.md

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 2 remain after this review.

📝 Walkthrough

Menu commands now validate numeric parameters and reject invalid crop rectangles. Tests and MCP documentation cover the validation behavior. The target-app parity documentation adds a Create Strokes baseline measurement.

Changes: Menu Command Parameter Validation

Layer / File(s) Summary
Validate menu command parameters
crates/engine/src/cmd/menucmds.rs
Transform, rasterize, mosaic, crop, trim-mark, and artboard rearrangement commands validate parameter types before processing. Invalid crop rectangles reach the existing invalid-rectangle error path.
Test and document parameter validation
crates/engine/src/tests.rs, crates/engine/src/tests_menucmds.rs, docs/mcp.md
Tests check errors for invalid values, accepted numeric and nullable values, and unchanged document state on failure. MCP documentation describes the parameter rules.

Create Strokes Parity Baseline

Layer / File(s) Summary
Record Create Strokes measurements
docs/target-app-parity.md
The documentation records a baseline for 23 scenes in antialiased and hard-edged variants. It notes that topology is recovered from emitted geometry, width-profile metrics remain unavailable, and scores and estimates are unchanged.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~12 minutes

Change: Bug fix

Suggested reviewers: echelon

Merge Risk: ⚪ Minimal · up to a9bef

No actionable merge-blocking risk remains from the reviewed changes.

Security architecture risk: ⚪ Minimal · up to a9bef

The change rejects malformed command values before editing a document. It does not add operations or privileges, and existing transactional editing and undo behavior remain in place. No material security risk introduced or worsened by this change was identified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The affected authority remains the existing command session's document, selected objects, and artboards. Comparing base and head shows stricter input acceptance without a new command registration, caller, credential, cross-service dependency, or privileged sink. Exclusive mutable Session access remains the mutation ownership boundary.

Security Findings and Attack Paths

  • inferred — No introduced or expanded attack path was identified in the assessed contract change. Caller-controlled malformed values now terminate before document mutation instead of selecting defaults. Trim-mode precedence is unchanged, and the additional rasterization consumer constructs its PPI parameter from typed settings. This conclusion is scoped to the inspected change, not a whole-application security assurance.
Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 78.26% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 23 functions across 3 files. (2 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly summarizes the primary change: nonnumeric values are rejected for the listed menu commands. It is concise and specific.
Description check Passed The description includes the required What and why, How it was tested, and Checklist sections. It explains the behavior, affected keys, documentation changes, test coverage, validation commands, and c…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description includes the required What and why, How it was tested, and Checklist sections. It explains the behavior, affected keys, documentation changes, test coverage, validation commands, and completed checklist items.

Full details: Docstring Coverage

Explanation

Docstring coverage is 78.26% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 23 functions across 3 files. (2 skipped: 2 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

… given as text is refused

Transform Each, Rasterize, Create Object Mosaic, Create Trim Marks and
Rearrange All Artboards read their optional numbers with f64_or, which
falls back to a default for a value that is not a JSON number.
object.transformEach {"scaleH": "50"} left the selected objects at
their size and reported success. Rasterize did the same with ppi,
Create Object Mosaic did the same with width, height, spacingX and
spacingY, Create Trim Marks did the same with offset, length, bleed and
weight, and Rearrange All Artboards did the same with spacing. Crop
Image cropped to the artboard when rect was a string or another value
that is not an array.

These commands now fail with "`<key>` must be a number, not <value>"
for a value that is not a number or null, as the transform commands
do, and change nothing. Transform Each checks scaleH, scaleV, moveH,
moveV and rotate. Crop Image refuses a rect that is not an array of
four numbers with "rect must be [x, y, width, height]", the message it
already gave for an array of the wrong length; a null rect crops to the
artboard, as a missing one does.

Docs: docs/mcp.md, docs/target-app-parity.md.
@bflatastic
bflatastic force-pushed the fix/menu-commands-refuse-text-numbers branch from a9befa3 to cc8944a Compare October 18, 2026 17:08
@bflatastic
bflatastic merged commit c092ca1 into storytold:main Oct 18, 2026
@bflatastic

Copy link
Copy Markdown
Member

Thanks @dotCooCoo, merged. It went through the full gate (fmt, clippy, tests, layers, wasm) in a batch with the other PRs landed today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants