Skip to content

feat: replace_matching_properties — bulk property edit (closes #127)#128

Merged
vicmaster merged 1 commit into
masterfrom
issue-127-replace-matching-properties
Jul 19, 2026
Merged

feat: replace_matching_properties — bulk property edit (closes #127)#128
vicmaster merged 1 commit into
masterfrom
issue-127-replace-matching-properties

Conversation

@vicmaster

Copy link
Copy Markdown
Owner

Closes #127.

What

New MCP tool replace_matching_properties: find every node whose properties equal all the match entries and apply the set properties to each in one call — the "set width: "100%" on all nodes currently width: 110" case from the issue becomes one line instead of 68 hand-authored U() ops.

replace_matching_properties({
  canvasId,
  match:  { width: 110 },     // AND across keys; $token refs match literally; structured values (shadows, gradient) by shape
  set:    { width: "100%" },  // id/type stripped, same safety rule as U()
  scope?: "nodeId",           // limit to a subtree (inclusive)
  type?:  "text",             // node-type filter
  dryRun?: true               // preview matched nodes + count without writing
})

Returns { ok, count, matches: [{ id, type, name? }] } (+ dryRun: true on previews). Refuses an empty match (would match every node) and an empty set (unless dryRun). ensureFresh runs before the mutation like every other mutating tool.

Implementation

  • src/scene-graph.ts — pure core: collectMatchingNodes (document-order walk, scope-inclusive) + replaceMatchingProperties; propEquals is strict for primitives, JSON-shape for structured values.
  • src/index.ts — thin handler after batch_design; viewer URL on real writes only.
  • Agent surfaces (same PR, per the discoverability rule) — tool docstring, server INSTRUCTIONS paragraph, GOTCHAS entry, README section, GUIDELINES "Sharp edges" bullet, VISION checklist entry.

Testing

  • test-replace-matching.ts — 14/14: AND matching, token-ref + structured-value matching, scope/type filters + decoys, scope-inclusivity, missing-scope throw, replace mutation, id/type stripping.
  • test-discoverability.ts — 14/14 (48 tools).
  • Regression: test-ops-parser, test-batch-design-idmap, test-feedback, test-init all pass; tsc clean.
  • docs-steward audit run pre-PR (one fix: README return shape now notes the dryRun marker).

Not included

The search_all_unique_properties-style companion (enumerate distinct values in use) noted in the issue as prior art — dryRun covers the preview need; the enumerator can be a follow-up if wanted.

…g nodes (#127)

One call applies a property change to every node matching a value
predicate (AND across keys; token refs match literally; structured
values by shape), with scope-subtree and node-type filters and a
dryRun preview — instead of one batch_design U() op per node.

- src/scene-graph.ts: collectMatchingNodes + replaceMatchingProperties
  (pure, id/type stripped from set like updateNode)
- src/index.ts: tool registration, INSTRUCTIONS paragraph, GOTCHAS entry
- README, GUIDELINES (Sharp edges), VISION (issue-driven improvements)
- test-replace-matching.ts: 14 checks (matching, scoping, replacing,
  id/type safety); test-discoverability stays green
@vicmaster
vicmaster merged commit da6b4de into master Jul 19, 2026
@vicmaster
vicmaster deleted the issue-127-replace-matching-properties branch July 19, 2026 20:16
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.

Add a bulk property-replace tool (like Pencil's replace_all_matching_properties)

1 participant