Skip to content

fix: palette-add mints unique node ids against live topology - #47

Closed
Dahhrk wants to merge 2 commits into
xevrion:mainfrom
Dahhrk:cursor/fix-palette-add-duplicate-ids-39bf
Closed

fix: palette-add mints unique node ids against live topology#47
Dahhrk wants to merge 2 commits into
xevrion:mainfrom
Dahhrk:cursor/fix-palette-add-duplicate-ids-39bf

Conversation

@Dahhrk

@Dahhrk Dahhrk commented Sep 3, 2026

Copy link
Copy Markdown

What this changes

Palette-add (handleAddNode) now mints node ids against the live topology instead of a module counter that resets on page load. Closes #46.

Why

makeNode uses a module-level nodeCounter that resets on load. Two palette-adds of the same kind mint the same id. isTopology rejects the save, and loadSession silently falls back to PRESETS[0].

Changes

  • src/clipboard.ts: export freshId (contract unchanged)
  • src/App.tsx: handleAddNode still calls makeNode for kind/label/config/position, then overrides id with freshId against topoLiveRef.current.nodes. makeNode counter left for presets.
  • src/clipboard.test.ts: regression tests for unique mints, skip-existing, isTopology accepts

Keep

Fork PR (same branch): Dahhrk#1

makeNode uses a module counter that resets on page load, causing
duplicate ids when adding nodes of the same kind. handleAddNode now
overrides the id using freshId (exported from clipboard.ts), which
scans the live node id set — matching the pattern freshAnnId already
uses for annotations.

Closes xevrion#46
@vercel

vercel Bot commented Sep 3, 2026

Copy link
Copy Markdown

@cursoragent is attempting to deploy a commit to the whoarrryou's projects Team on Vercel.

A member of the Team first needs to authorize it.

…ral tests

handleAddNode now reads topoLiveRef.current instead of the React
topology closure, preventing two rapid adds from dropping the first
node. topology removed from the dependency array.

New test file handleAddNode.wiring.test.ts:
- Source assertion: handleAddNode spreads topoLiveRef.current, not
  the React topology binding, and freshId is called.
- Behavioral test: two sequential cache adds against the default
  preset produce unique ids, both nodes survive, isTopology accepts.
@Dahhrk
Dahhrk marked this pull request as ready for review September 3, 2026 02:06
@Dahhrk
Dahhrk requested a review from xevrion as a code owner September 3, 2026 02:06
@xevrion

xevrion commented Sep 5, 2026

Copy link
Copy Markdown
Owner

This is a real fix and the diff reads well. Minting against the live topology is right, and picking up the stale-closure bug on the way (reading topology instead of topoLiveRef.current) is a good catch, since two rapid adds dropped the first node.

One change before I merge. Could you drop the handleAddNode wiring describe block from handleAddNode.wiring.test.ts, the one that reads App.tsx as a string and greps it for topoLiveRef.current and the dep array?

I follow the argument in the comment, and you're right that a pure-function test can't catch a reintroduced stale closure. But a test that asserts on source text breaks when someone renames a local or reformats the callback, and the failure it gives them won't point at anything real. That maintenance cost sits on every future contributor who touches that function.

The behavioural describe blocks in the same file, plus the freshId tests in clipboard.test.ts, already cover the bug in the issue. Keep those.

Once that's out I'll merge.

@xevrion

xevrion commented Sep 7, 2026

Copy link
Copy Markdown
Owner

Going to close this one, and I want to be straight about why since you've been waiting on me.

#65 came in for the same issue and puts the dedupe inside makeNode rather than overriding the id afterwards, which covers every caller instead of just the palette path. I've asked them to pick up your topoLiveRef fix too, since you found that stale closure and they hadn't.

That's a call about structure, not about your work, and the four day wait was on me. Sorry for the wasted time.

#52 and #55 are both open and unclaimed if you want another.

@xevrion xevrion closed this Sep 7, 2026
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.

Adding a component from the rail can mint a duplicate id, and the next reload silently discards the design

3 participants