From 2a2ad205923a068148c5f2ab90eeff71fbda3bb1 Mon Sep 17 00:00:00 2001 From: Tibsfox Date: Mon, 6 Apr 2026 22:31:40 -0700 Subject: [PATCH] test: add regression test for sync-worktree skip current milestone Co-Authored-By: Claude Opus 4.6 (1M context) --- .../tests/sync-worktree-skip-current.test.ts | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts diff --git a/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts b/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts new file mode 100644 index 000000000..9b0070cb1 --- /dev/null +++ b/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts @@ -0,0 +1,65 @@ +/** + * Regression test for #3641 — syncWorktreeStateBack skips current milestone + * + * When syncing worktree state back to main, the current milestone being + * merged should be skipped. Its files are already in the milestone branch + * and copying them back would conflict with the squash merge. + * + * The fix adds a `mid === milestoneId` skip guard inside the milestone + * iteration loop in syncWorktreeStateBack. + */ + +import { describe, it } from 'node:test' +import assert from 'node:assert/strict' +import { readFileSync } from 'node:fs' +import { resolve } from 'node:path' + +const src = readFileSync( + resolve(process.cwd(), 'src', 'resources', 'extensions', 'gsd', 'auto-worktree.ts'), + 'utf-8', +) + +describe('syncWorktreeStateBack skips current milestone (#3641)', () => { + it('syncWorktreeStateBack function exists', () => { + assert.ok( + src.includes('function syncWorktreeStateBack('), + 'syncWorktreeStateBack function must be defined', + ) + }) + + it('mid === milestoneId skip guard exists in the milestone loop', () => { + // Find syncWorktreeStateBack + const fnStart = src.indexOf('function syncWorktreeStateBack(') + assert.ok(fnStart !== -1) + + // Get a reasonable portion of the function + const fnBlock = src.slice(fnStart, fnStart + 3000) + + // Find the for loop iterating milestones + const loopIdx = fnBlock.indexOf('for (const mid of wtMilestones)') + assert.ok(loopIdx !== -1, 'milestone iteration loop must exist') + + // After the loop, there should be the skip guard + const loopBody = fnBlock.slice(loopIdx, loopIdx + 300) + assert.ok( + loopBody.includes('mid === milestoneId'), + 'mid === milestoneId skip guard must exist inside the milestone loop', + ) + assert.ok( + loopBody.includes('continue'), + 'skip guard must use continue to skip the current milestone', + ) + }) + + it('syncMilestoneDir is still called for non-current milestones', () => { + const fnStart = src.indexOf('function syncWorktreeStateBack(') + assert.ok(fnStart !== -1) + + const fnBlock = src.slice(fnStart, fnStart + 3000) + + assert.ok( + fnBlock.includes('syncMilestoneDir('), + 'syncMilestoneDir must still be called for other milestones', + ) + }) +})