Skip to content

Resolve project slug clashes between device group computers - #243

Merged
danielehrhardt merged 2 commits into
mainfrom
fix/setup-copy-project-slug
Oct 25, 2026
Merged

danielehrhardt merged 2 commits into
mainfrom
fix/setup-copy-project-slug

Conversation

@danielehrhardt

@danielehrhardt danielehrhardt commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Problem

While the main Mac was away, the stand-in Mac created a project "Earshot" in a workspace where the main Mac had created one with the same slug a bit earlier (different ids). From then on:

  • every setup copy to the stand-in failed with UNIQUE constraint failed: projects.workspace_id, projects.slug
  • the main Mac deferred the stand-in's project, plus the agent, automation and repository source hanging on it, retrying forever
  • sending a message to a chat on the stand-in failed with "Message not sent: Couldn't copy your setup to ..."

Fix

  • Setup copy (snapshot.ts): before upserting a table with a unique slug (projects, workspaces), local rows whose slug the copy claims step aside: a placeholder when the copy rewrites them anyway (also fixes slug swaps), or the next free slug (earshot-2) when the row was made on this computer and is kept. That rename is written as this computer's own change (asOwn), so it still replicates to the primary.
  • Replica intake (replica.ts): a project or workspace whose slug another row holds gets the next free slug, but only on the retry pass after the whole pull is in, so a slug that a later change in the same pull frees doesn't cause a rename.
  • Runners (runners.ts): when the setup copy fails before a chat starts or a message is sent, the work goes ahead on the runner's earlier setup (memory and browser sessions still sync, the runner card keeps the error). This does not apply if the runner never had a setup, is missing the vault key, or is unreachable.

Tests

  • replica.test.ts: a project both computers made while apart lands as earshot-2 on the retry pass instead of staying deferred
  • remote-snapshot.test.ts: projects that swapped slugs on the controller swap on the runner too; a project a secondary made while apart yields its slug and stays pending for the primary
  • The new tests fail without the fix. All 295 tests in remote/device/replica/runner pass, and typecheck is clean.

Both computers of a group could create a project with the same slug in the
same workspace while apart. The setup copy then failed on every sync with a
UNIQUE constraint error and the primary deferred the secondary's project (and
everything hanging on it) forever.

- Setup copy: local rows whose slug the copy claims step aside (placeholder
  when the copy rewrites them, a free slug as this computer's own change when
  they are kept)
- Replica intake: a project or workspace whose slug is taken gets a free slug
  once the whole pull is in
- A failed setup copy no longer blocks messages to a runner that already has
  a setup and the vault key
@danielehrhardt
danielehrhardt merged commit ebaad4c into main Oct 25, 2026
8 checks passed
danielehrhardt added a commit that referenced this pull request Oct 25, 2026
The merge left duplicate group/replica imports in remote-snapshot.test.ts, and
#241's two same-name tests expected the secondary's project to be skipped. With
#243 the local project steps aside to a free slug instead and both are kept, so
the tests now expect that.
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