Skip to content

[Bug]: Dev database seed keeps settle scripts, so the dev server runs them in the developer's real worktrees #33907

Open

Description

@Lenoridev

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

  1. In a source database, have a project with a script that sets runOnSettle: true, and a stopped, unsettled thread in that project whose worktreePath is an existing checkout. The thread has been idle for more than 7 days.
  2. Seed a dev database from it: the first vp run dev in a worktree, or vp run migrate-dev-db.
  3. Start the dev server. Do nothing else.

Fixture repro: I ran migrate-dev-db.ts on a fixture database whose paths were all temporary directories, then booted bin.ts serve on the result with default settings and no settings.json. The settle script was pwd > "$PWD/settle-script-ran.marker".

Expected behavior

AGENTS.md says the seed exists "so your dev server never runs the developer's agents". A copied database should not run the developer's project scripts in the developer's real checkouts on its own. Threads and scripts should still appear in the dev UI.

Actual behavior

The first automatic settlement sweep settles the seeded thread, and the settle script runs in the worktreePath copied from the source database:

  • migrate-dev-db keeps each project's scripts_json, including runOnSettle, and each thread's real worktreePath.
  • With no settings.json, the server folds scripts_json into the dev home's project settings on first load.
  • Automatic settling is on by default (sidebarAutoSettleAfterDays is 7 and sidebarAutoSettleOnMerge is true).
  • thread.auto-settle dispatches thread.settle, which emits thread.settled and sets settledOverride to "settled".
  • cleanUpSettledThread checks that the worktree exists, then calls projectScripts.runForThread({ trigger: "settle", worktreePath, ... }). Nothing checks which install the thread came from.

Settling a seeded thread by hand reaches the same handler, because thread.settle emits the same event. I did not run that path in the UI.

Impact

Major degradation or frequent failure

Version or commit

main @ 41443e5

Environment

Linux, Node 24.22.0, server started from a git worktree

Logs or stack traces

== seeded project scripts
[{"id":"teardown","name":"Teardown","command":"pwd > \"$PWD/settle-script-ran.marker\"","icon":"configure","runOnWorktreeCreate":false,"runOnSettle":true}]
== seeded thread before boot
settledOverride=null hasWorktreePath=1
== boot real server, default settings, no settings.json
thread settled by the automatic sweep: yes
settledOverride="settled"
settle script RAN in worktree: $TMP/e2e-before/real-worktree

Workaround

Run dev with --no-seed, or remove runOnSettle from the seeded project's scripts before the first dev server start.

Related

Same class as #15513, a copied database acting on the original install's worktrees. #32736 reported the pull request watch path of that class, and #32744 fixed it. This is a separate path that #32744 does not touch.

Reported with Claude Code (Claude Opus 5.5).

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions