Skip to content

fix: bootstrap .gsd state in manual worktree creation#3447

Open
murataslan1 wants to merge 1 commit intogsd-build:mainfrom
murataslan1:fix/worktree-gsd-bootstrap
Open

fix: bootstrap .gsd state in manual worktree creation#3447
murataslan1 wants to merge 1 commit intogsd-build:mainfrom
murataslan1:fix/worktree-gsd-bootstrap

Conversation

@murataslan1
Copy link
Copy Markdown

Summary

  • Manual worktree creation (gsd -w and /worktree create) skipped the syncGsdStateToWorktree() call that auto/parallel flows already use
  • The new worktree was a valid git worktree but had no .gsd/ state, causing GSD to treat it as uninitialized
  • Added the missing sync call in both CLI (worktree-cli.ts) and TUI (worktree-command.ts) paths, right after the post-create hook and before process.chdir()

Fixes #3427

Test plan

  • gsd -w test-wt creates a worktree with .gsd/ state synced from main
  • /worktree create test-wt inside TUI also syncs .gsd/ state
  • Running /gsd auto inside the new worktree works without "No .gsd/ directory found" error
  • Existing auto/parallel worktree flows are unaffected

Manual worktree creation (gsd -w and /worktree create) skipped the
syncGsdStateToWorktree() call that auto/parallel flows already use.
The new worktree was a valid git worktree but had no .gsd/ state,
so GSD treated it as uninitialized.

Fixes gsd-build#3427
Copilot AI review requested due to automatic review settings April 3, 2026 13:26
@github-actions github-actions bot added bug Something isn't working High Priority labels Apr 3, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 3, 2026

🟡 PR Risk Report — MEDIUM

Files changed 2
Systems affected 3
Overall risk 🟡 MEDIUM

Affected Systems

Risk System
🟡 medium Commands
🟡 medium Worktree
🟡 medium CLI
File Breakdown
Risk File Systems
🟡 src/resources/extensions/gsd/worktree-command.ts Commands, Worktree
🟡 src/worktree-cli.ts Worktree, CLI

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes manual worktree creation flows so newly created worktrees receive .gsd/ state seeding/sync similar to auto/parallel worktree flows, addressing cases where GSD treats the worktree as uninitialized.

Changes:

  • Exposes syncGsdStateToWorktree() to the CLI worktree module loader and invokes it after worktree creation.
  • Invokes syncGsdStateToWorktree() in the TUI /worktree create path after the post-create hook and before chdir.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/worktree-cli.ts Adds syncGsdStateToWorktree to loaded extension modules and calls it after creating a worktree in the CLI -w path.
src/resources/extensions/gsd/worktree-command.ts Imports and calls syncGsdStateToWorktree during TUI worktree creation to seed .gsd/ state.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 381 to +387
const hookError = ext.runWorktreePostCreateHook(basePath, info.path)
if (hookError) {
process.stderr.write(chalk.yellow(`[gsd] ${hookError}\n`))
}

ext.syncGsdStateToWorktree(basePath, info.path)

Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syncGsdStateToWorktree() currently returns early when the destination worktree has no .gsd directory (if (!existsSync(mainGsd) || !existsSync(wtGsd)) return). Fresh worktrees created via git worktree add don’t carry over untracked .gsd/ content, so .gsd may be missing entirely—the reported failure mode in #3427. As a result, this call can be a no-op and still leave the new worktree uninitialized. Consider ensuring the worktree-local .gsd/ directory exists (or using the same seeding logic as auto-worktree’s planning-artifact copy) before invoking sync, so manual worktree creation reliably bootstraps state.

Copilot uses AI. Check for mistakes.
Comment on lines +332 to +334
// Sync .gsd/ state from main into the new worktree (#3427)
syncGsdStateToWorktree(mainBase, info.path);

Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syncGsdStateToWorktree() is a no-op when the destination worktree doesn’t already have a .gsd/ directory (if (!existsSync(mainGsd) || !existsSync(wtGsd)) return). For manual worktree creation, .gsd/ is commonly untracked and therefore won’t exist in the freshly created worktree, which means this call may not actually bootstrap any state (the #3427 failure case). Consider creating/initializing the worktree-local .gsd/ directory (or reusing the auto-worktree planning-artifact seeding logic) before calling sync so /worktree create produces an immediately usable workspace.

Copilot uses AI. Check for mistakes.
Comment on lines +332 to +334
// Sync .gsd/ state from main into the new worktree (#3427)
syncGsdStateToWorktree(mainBase, info.path);

Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change adds new behavior (bootstrapping .gsd/ during manual worktree creation) but doesn’t appear to be covered by tests. Since the repo already has worktree integration coverage (e.g. auto-worktree/worktree-manager tests), consider adding a regression test that creates a repo where .gsd/ is untracked in git, runs the manual create path, and asserts the new worktree contains the expected .gsd planning/state artifacts.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working High Priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: manual worktree creation (/worktree create, gsd -w) does not initialize worktree-local .gsd

2 participants