Skip to content

fix: declare @spacedevin/deck as a peer of both packages - #26

Merged
spacedevin merged 1 commit into
mainfrom
fix/deck-as-peer
Sep 1, 2026
Merged

fix: declare @spacedevin/deck as a peer of both packages#26
spacedevin merged 1 commit into
mainfrom
fix/deck-as-peer

Conversation

@spacedevin

Copy link
Copy Markdown
Owner

The gen_block dialect registry is module-level mutable state — let dialects = {} in GenBlock.tish. A package that bundles its own copy of the language hands its consumer a second registry, so a dialect registered against one is invisible to the other. And because tish build inlines each import graph, two copies also collide every top-level symbol in the parser.

This is live, not theoretical

Deckard's main went red the moment it consumed the published catalog:

SyntaxError: Identifier 'normalizeGeneratorId' has already been declared

Its lockfile held @spacedevin/deck@1.6.2 while @spacedevin/deck-synths@1.8.0 declares ^1.8.0, so pnpm kept both on disk. spacedevin/deckard#16 pins the versions together as an immediate unblock; this is the fix that stops it recurring whenever the ranges drift.

Change

@spacedevin/deck moves from dependencies to peerDependencies in both packages/synths and packages/player, so the consumer supplies the single instance. It stays a devDependency (file:../..) so the workspace links locally, and both CI pack steps now stamp the peer range and drop the dev link.

Verified

Against a consumer deliberately pinned to the old ^1.6.2 range — the exact configuration that caused the collision:

  • one copy of the language on disk, where there were previously two
  • pnpm surfaces the skew as ✕ unmet peer @spacedevin/deck@^1.8.0: found 1.6.2 at install time, instead of a silent duplicate that explodes at build time

On the correct range: one copy, 968 assertions, 0 failures, no duplicate-declaration error.

Both suites in this repo unchanged — 8 language, 46 player.

The gen_block dialect registry is module-level mutable state (`let dialects = {}` in
GenBlock.tish). A package that bundles its own copy of the language gives its consumer a
second registry, so a dialect registered against one is invisible to the other — and
because tish build inlines each import graph, it also collides every top-level symbol in
the parser.

That is not theoretical. Deckard's main went red with "Identifier 'normalizeGeneratorId'
has already been declared" the moment it consumed the published synths package: its
lockfile held deck 1.6.2 while deck-synths declared ^1.8.0, so pnpm kept both.

Peer, so the consumer supplies the single instance. Kept as a devDependency (file:../..)
so the workspace still links locally, and both CI pack steps now stamp the peer range and
drop the dev link.

Verified against a consumer pinned to the OLD range that caused the collision: one copy of
the language on disk instead of two, and pnpm reports the skew as "unmet peer" at install
rather than a duplicate that explodes at build. On the correct range: one copy, 968
assertions, 0 failures. Both suites here unchanged (8 language, 46 player).
@spacedevin
spacedevin merged commit 83b9ad7 into main Sep 1, 2026
5 checks passed
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.

1 participant