infra-kit 0.1.114 → 0.1.117
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintcache +1 -1
- package/.omc/state/agent-replay-1fcfe0ec-7567-41c3-9bfd-501e99e86819.jsonl +19 -0
- package/.omc/state/agent-replay-38382db5-3088-4b5a-aff7-2561a60827c7.jsonl +17 -0
- package/.omc/state/agent-replay-50c36be9-a3a2-42b9-9c85-5a06d3e22f6a.jsonl +5 -0
- package/.omc/state/agent-replay-8198b3e5-fad6-4ee0-9c59-ef773ad89af4.jsonl +1 -0
- package/.omc/state/agent-replay-8cd7652a-b8b5-49cf-9b1f-bee8e5972458.jsonl +3 -0
- package/.omc/state/agent-replay-9bea518f-a9ee-4d14-bb53-a936ebaf647c.jsonl +7 -0
- package/.omc/state/agent-replay-b52d89fb-0e24-4901-bc66-27e3c1697126.jsonl +2 -0
- package/.omc/state/agent-replay-f581a1ae-0ee4-48a3-96f3-ce31a0633bb0.jsonl +1 -0
- package/.omc/state/agent-replay-fe1057b4-9a25-4e8e-8c3f-3e11652ee697.jsonl +5 -0
- package/.omc/state/idle-notif-cooldown.json +1 -1
- package/.omc/state/sessions/1fcfe0ec-7567-41c3-9bfd-501e99e86819/last-tool-error-state.json +7 -0
- package/.omc/state/sessions/1fcfe0ec-7567-41c3-9bfd-501e99e86819/mission-state.json +109 -0
- package/.omc/state/sessions/1fcfe0ec-7567-41c3-9bfd-501e99e86819/pre-tool-advisory-throttle.json +42 -0
- package/.omc/state/sessions/1fcfe0ec-7567-41c3-9bfd-501e99e86819/ralph-state.json +13 -0
- package/.omc/state/sessions/1fcfe0ec-7567-41c3-9bfd-501e99e86819/skill-active-state.json +15 -0
- package/.omc/state/sessions/1fcfe0ec-7567-41c3-9bfd-501e99e86819/subagent-tracking-state.json +62 -0
- package/.omc/state/sessions/1fcfe0ec-7567-41c3-9bfd-501e99e86819/ultrawork-state.json +11 -0
- package/.omc/state/sessions/23d0ff82-17e5-428b-8743-38f7979bb6f3/last-tool-error-state.json +7 -0
- package/.omc/state/sessions/23d0ff82-17e5-428b-8743-38f7979bb6f3/pre-tool-advisory-throttle.json +18 -0
- package/.omc/state/sessions/38382db5-3088-4b5a-aff7-2561a60827c7/last-tool-error-state.json +7 -0
- package/.omc/state/sessions/38382db5-3088-4b5a-aff7-2561a60827c7/mission-state.json +145 -0
- package/.omc/state/sessions/38382db5-3088-4b5a-aff7-2561a60827c7/pre-tool-advisory-throttle.json +38 -0
- package/.omc/state/sessions/38382db5-3088-4b5a-aff7-2561a60827c7/ralplan-state.json +11 -0
- package/.omc/state/sessions/38382db5-3088-4b5a-aff7-2561a60827c7/subagent-tracking-state.json +98 -0
- package/.omc/state/sessions/41336850-028c-476b-be1a-2164e1e46cac/last-tool-error-state.json +7 -0
- package/.omc/state/sessions/41336850-028c-476b-be1a-2164e1e46cac/pre-tool-advisory-throttle.json +18 -0
- package/.omc/state/sessions/50c36be9-a3a2-42b9-9c85-5a06d3e22f6a/mission-state.json +61 -0
- package/.omc/state/sessions/50c36be9-a3a2-42b9-9c85-5a06d3e22f6a/pre-tool-advisory-throttle.json +22 -0
- package/.omc/state/sessions/50c36be9-a3a2-42b9-9c85-5a06d3e22f6a/skill-active-state.json +15 -0
- package/.omc/state/sessions/50c36be9-a3a2-42b9-9c85-5a06d3e22f6a/subagent-tracking-state.json +26 -0
- package/{src/lib/.omc/state/sessions/a60ac2ec-afbd-449f-a540-6df287392fc2 → .omc/state/sessions/8198b3e5-fad6-4ee0-9c59-ef773ad89af4}/pre-tool-advisory-throttle.json +3 -3
- package/.omc/state/sessions/8198b3e5-fad6-4ee0-9c59-ef773ad89af4/subagent-tracking-state.json +17 -0
- package/.omc/state/sessions/8cd7652a-b8b5-49cf-9b1f-bee8e5972458/pre-tool-advisory-throttle.json +18 -0
- package/.omc/state/sessions/8cd7652a-b8b5-49cf-9b1f-bee8e5972458/ralplan-state.json +11 -0
- package/.omc/state/sessions/8cd7652a-b8b5-49cf-9b1f-bee8e5972458/subagent-tracking-state.json +35 -0
- package/.omc/state/sessions/9bea518f-a9ee-4d14-bb53-a936ebaf647c/last-tool-error-state.json +7 -0
- package/.omc/state/sessions/9bea518f-a9ee-4d14-bb53-a936ebaf647c/mission-state.json +79 -0
- package/.omc/state/sessions/9bea518f-a9ee-4d14-bb53-a936ebaf647c/pre-tool-advisory-throttle.json +22 -0
- package/.omc/state/sessions/9bea518f-a9ee-4d14-bb53-a936ebaf647c/progress.txt +7 -0
- package/.omc/state/sessions/9bea518f-a9ee-4d14-bb53-a936ebaf647c/skill-active-state.json +15 -0
- package/.omc/state/sessions/9bea518f-a9ee-4d14-bb53-a936ebaf647c/subagent-tracking-state.json +26 -0
- package/.omc/state/sessions/b52d89fb-0e24-4901-bc66-27e3c1697126/pre-tool-advisory-throttle.json +14 -0
- package/.omc/state/sessions/b52d89fb-0e24-4901-bc66-27e3c1697126/subagent-tracking-state.json +17 -0
- package/.omc/state/sessions/c513ef38-cc3e-4a29-9c4c-1e0137245dd5/pre-tool-advisory-throttle.json +18 -0
- package/.omc/state/sessions/ed3e2cfb-a666-4bb1-bcc1-569d5d0b837a/pre-tool-advisory-throttle.json +18 -0
- package/.omc/state/sessions/f581a1ae-0ee4-48a3-96f3-ce31a0633bb0/pre-tool-advisory-throttle.json +18 -0
- package/.omc/state/sessions/f581a1ae-0ee4-48a3-96f3-ce31a0633bb0/subagent-tracking-state.json +17 -0
- package/.omc/state/sessions/fe1057b4-9a25-4e8e-8c3f-3e11652ee697/last-tool-error-state.json +7 -0
- package/.omc/state/sessions/fe1057b4-9a25-4e8e-8c3f-3e11652ee697/mission-state.json +61 -0
- package/.omc/state/sessions/fe1057b4-9a25-4e8e-8c3f-3e11652ee697/prd.json +22 -0
- package/.omc/state/sessions/fe1057b4-9a25-4e8e-8c3f-3e11652ee697/pre-tool-advisory-throttle.json +22 -0
- package/.omc/state/sessions/fe1057b4-9a25-4e8e-8c3f-3e11652ee697/progress.txt +22 -0
- package/.omc/state/sessions/fe1057b4-9a25-4e8e-8c3f-3e11652ee697/skill-active-state.json +15 -0
- package/.omc/state/sessions/fe1057b4-9a25-4e8e-8c3f-3e11652ee697/subagent-tracking-state.json +26 -0
- package/.turbo/turbo-build.log +3 -3
- package/.turbo/turbo-eslint-check.log +2 -0
- package/.turbo/turbo-test.log +90 -42
- package/dist/boot-K4QUAFSP.js +2 -0
- package/dist/boot-K4QUAFSP.js.map +7 -0
- package/dist/chunk-FEGOOVZE.js +166 -0
- package/dist/chunk-FEGOOVZE.js.map +7 -0
- package/dist/chunk-WA4BQRDC.js +2 -0
- package/dist/chunk-WA4BQRDC.js.map +7 -0
- package/dist/cli.js +11 -107
- package/dist/cli.js.map +4 -4
- package/dist/entry/index.d.ts +2 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +4 -4
- package/dist/lib/vendor/config-schema.d.ts +58 -0
- package/dist/mcp.js +1 -54
- package/dist/mcp.js.map +4 -4
- package/eslint.config.js +33 -1
- package/package.json +5 -1
- package/scripts/build.js +11 -1
- package/src/.omc/state/agent-replay-c513ef38-cc3e-4a29-9c4c-1e0137245dd5.jsonl +4 -0
- package/src/.omc/state/agent-replay-ed3e2cfb-a666-4bb1-bcc1-569d5d0b837a.jsonl +2 -0
- package/src/.omc/state/idle-notif-cooldown.json +1 -1
- package/src/.omc/state/sessions/c513ef38-cc3e-4a29-9c4c-1e0137245dd5/mission-state.json +79 -0
- package/src/.omc/state/sessions/c513ef38-cc3e-4a29-9c4c-1e0137245dd5/pre-tool-advisory-throttle.json +22 -0
- package/src/.omc/state/sessions/c513ef38-cc3e-4a29-9c4c-1e0137245dd5/subagent-tracking-state.json +26 -0
- package/src/.omc/state/sessions/ed3e2cfb-a666-4bb1-bcc1-569d5d0b837a/pre-tool-advisory-throttle.json +18 -0
- package/src/.omc/state/sessions/ed3e2cfb-a666-4bb1-bcc1-569d5d0b837a/ralph-state.json +13 -0
- package/src/.omc/state/sessions/ed3e2cfb-a666-4bb1-bcc1-569d5d0b837a/ultrawork-state.json +11 -0
- package/src/commands/config/.omc/state/sessions/41336850-028c-476b-be1a-2164e1e46cac/last-tool-error-state.json +7 -0
- package/src/commands/config/.omc/state/sessions/41336850-028c-476b-be1a-2164e1e46cac/pre-tool-advisory-throttle.json +18 -0
- package/src/commands/config/config.ts +7 -37
- package/src/commands/doctor/__tests__/agent-files.test.ts +8 -30
- package/src/commands/doctor/__tests__/check-legacy-user-global-config.test.ts +110 -0
- package/src/commands/doctor/doctor.ts +104 -44
- package/src/commands/env-autoload/env-autoload.ts +12 -0
- package/src/commands/env-autoload/index.ts +1 -0
- package/src/commands/env-clear/__tests__/env-clear.test.ts +27 -0
- package/src/commands/env-clear/env-clear.ts +22 -8
- package/src/commands/env-load/__tests__/env-load.test.ts +36 -1
- package/src/commands/env-load/env-load.ts +152 -35
- package/src/commands/env-load/index.ts +2 -1
- package/src/commands/env-status/__tests__/env-status.test.ts +78 -0
- package/src/commands/env-status/env-status.ts +19 -7
- package/src/commands/gh-release-deploy-all/gh-release-deploy-all.ts +45 -1
- package/src/commands/gh-release-deploy-selected/gh-release-deploy-selected.ts +46 -1
- package/src/commands/init/__tests__/agent-files.test.ts +145 -27
- package/src/commands/init/__tests__/migrate-config.test.ts +136 -5
- package/src/commands/init/__tests__/migrate-factory-config.test.ts +93 -0
- package/src/commands/init/__tests__/seed-user-global-config.test.ts +64 -0
- package/src/commands/init/__tests__/shell-body.test.ts +30 -0
- package/src/commands/init/agent-files.ts +65 -45
- package/src/commands/init/init.ts +140 -31
- package/src/commands/init/migrate-config.ts +160 -32
- package/src/commands/vendor-check/__tests__/runtime-isolation.test.ts +71 -0
- package/src/commands/vendor-check/__tests__/vendor-check.test.ts +87 -0
- package/src/commands/vendor-check/index.ts +1 -0
- package/src/commands/vendor-check/vendor-check.ts +127 -0
- package/src/commands/vendor-config/__tests__/vendor-config.test.ts +103 -0
- package/src/commands/vendor-config/index.ts +1 -0
- package/src/commands/vendor-config/vendor-config.ts +162 -0
- package/src/commands/vendor-diff/__tests__/vendor-diff.test.ts +74 -0
- package/src/commands/vendor-diff/index.ts +1 -0
- package/src/commands/vendor-diff/vendor-diff.ts +77 -0
- package/src/commands/vendor-manifest/index.ts +1 -0
- package/src/commands/vendor-manifest/vendor-manifest.ts +60 -0
- package/src/commands/vendor-sync/__tests__/vendor-write.test.ts +86 -0
- package/src/commands/vendor-sync/index.ts +1 -0
- package/src/commands/vendor-sync/vendor-sync.ts +90 -0
- package/src/commands/worktrees-add/worktrees-add.ts +1 -1
- package/src/commands/worktrees-reload/worktrees-reload.ts +6 -5
- package/src/commands/worktrees-remove/worktrees-remove.ts +10 -1
- package/src/commands/worktrees-sync/worktrees-sync.ts +9 -1
- package/src/entry/cli.ts +417 -210
- package/src/entry/index.ts +7 -1
- package/src/integrations/cmux/__tests__/open-workspace-with-layout.test.ts +127 -0
- package/src/integrations/cmux/close-workspace-by-title.ts +2 -2
- package/src/integrations/cmux/list-workspace-titles.ts +1 -1
- package/src/integrations/cmux/open-workspace-with-layout.ts +15 -4
- package/src/integrations/cursor/open-cursor-workspace.ts +6 -11
- package/src/integrations/doppler/__tests__/doppler-errors.test.ts +76 -0
- package/src/integrations/doppler/doppler-cli-auth.ts +12 -4
- package/src/integrations/doppler/doppler-errors.ts +88 -0
- package/src/integrations/doppler/doppler-project.ts +80 -0
- package/src/integrations/doppler/index.ts +3 -1
- package/src/integrations/gh/gh-cli-auth/gh-cli-auth.ts +9 -5
- package/src/integrations/gh/gh-release-prs/gh-release-prs.ts +16 -8
- package/src/integrations/ide/__tests__/ide-facade.test.ts +49 -10
- package/src/integrations/ide/open-ide-workspace.ts +6 -6
- package/src/integrations/ide/remove-ide-worktree-folders.ts +95 -30
- package/src/integrations/ide/types.ts +10 -1
- package/src/integrations/zed/__tests__/open-zed-workspace.test.ts +1 -17
- package/src/integrations/zed/__tests__/reuse-zed-workspace.test.ts +86 -0
- package/src/integrations/zed/index.ts +1 -0
- package/src/integrations/zed/open-zed-workspace.ts +4 -10
- package/src/integrations/zed/reuse-zed-workspace.ts +57 -0
- package/src/lib/command-catalog/__tests__/__snapshots__/command-catalog.test.ts.snap +212 -0
- package/src/lib/command-catalog/__tests__/command-catalog.test.ts +193 -0
- package/src/lib/command-catalog/command-catalog.ts +141 -0
- package/src/lib/command-catalog/index.ts +2 -0
- package/src/lib/command-echo/__tests__/command-echo.test.ts +127 -0
- package/src/lib/constants/constants.ts +13 -0
- package/src/lib/constants/index.ts +2 -0
- package/src/lib/env-autoload/__tests__/env-autoload.test.ts +288 -0
- package/src/lib/env-autoload/env-autoload.ts +294 -0
- package/src/lib/env-autoload/index.ts +9 -0
- package/src/lib/errors/operation-error.ts +1 -1
- package/src/lib/infra-kit-config/__tests__/env-autoload-schema.test.ts +71 -0
- package/src/lib/infra-kit-config/__tests__/infra-kit-config.test.ts +77 -6
- package/src/lib/infra-kit-config/index.ts +9 -1
- package/src/lib/infra-kit-config/infra-kit-config.ts +71 -11
- package/src/lib/json-output/__tests__/json-output.test.ts +139 -0
- package/src/lib/json-output/index.ts +1 -0
- package/src/lib/json-output/json-output.ts +47 -0
- package/src/lib/managed-block/managed-block.ts +4 -4
- package/src/lib/package-config/package-config.ts +1 -3
- package/src/lib/path-display/index.ts +1 -0
- package/src/lib/path-display/path-display.ts +42 -0
- package/src/lib/render/__tests__/render.test.ts +48 -0
- package/src/lib/render/index.ts +1 -0
- package/src/lib/render/render.ts +24 -0
- package/src/lib/vendor/__tests__/config-schema.test.ts +31 -0
- package/src/lib/vendor/__tests__/config.test.ts +63 -0
- package/src/lib/vendor/__tests__/factory-config.test.ts +92 -0
- package/src/lib/vendor/__tests__/vendor-lib.test.ts +158 -0
- package/src/lib/vendor/__tests__/zx-mock.ts +32 -0
- package/src/lib/vendor/config-schema.ts +78 -0
- package/src/lib/vendor/config.ts +58 -0
- package/src/lib/vendor/factory-config-schema.ts +35 -0
- package/src/lib/vendor/factory-config.ts +91 -0
- package/src/lib/vendor/hash.ts +16 -0
- package/src/lib/vendor/index.ts +23 -0
- package/src/lib/vendor/manifest.ts +151 -0
- package/src/lib/vendor/skip-sets.ts +48 -0
- package/src/lib/vendor/sync-ops.ts +290 -0
- package/src/lib/vendor/walk.ts +56 -0
- package/src/mcp/tools/index.ts +5 -42
- package/src/sanity.test.tsx +1 -0
- package/src/tui/__tests__/no-react-boundary.test.ts +51 -0
- package/src/tui/boot.tsx +45 -0
- package/src/tui/screens/__tests__/command-palette.test.tsx +136 -0
- package/src/tui/screens/command-palette.tsx +159 -0
- package/src/tui/types.ts +8 -0
- package/tsconfig.json +1 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/vitest.config.ts +8 -0
- package/src/commands/worktrees-open/__tests__/open-cmux.test.ts +0 -96
- package/src/commands/worktrees-open/index.ts +0 -1
- package/src/commands/worktrees-open/worktrees-open.ts +0 -195
|
@@ -55,6 +55,7 @@ const zed = vi.hoisted(() => {
|
|
|
55
55
|
return {
|
|
56
56
|
openZedWorkspace: vi.fn(),
|
|
57
57
|
addFoldersToZedWorkspace: vi.fn(),
|
|
58
|
+
reuseZedWorkspace: vi.fn(),
|
|
58
59
|
}
|
|
59
60
|
})
|
|
60
61
|
|
|
@@ -73,7 +74,6 @@ const baseOpenArgs = {
|
|
|
73
74
|
projectRoot: '/repo',
|
|
74
75
|
worktreeDir: '/repo.worktrees',
|
|
75
76
|
currentBranches: ['release/v1.0.0'],
|
|
76
|
-
skipRelaunchWhenEmpty: false,
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
beforeEach(() => {
|
|
@@ -191,7 +191,14 @@ describe('addIdeWorktreeFolders', () => {
|
|
|
191
191
|
})
|
|
192
192
|
|
|
193
193
|
describe('removeIdeWorktreeFolders', () => {
|
|
194
|
-
|
|
194
|
+
// currentWorktrees \ removedWorktrees => remaining = ['release/v1.1.0']
|
|
195
|
+
const args = {
|
|
196
|
+
projectRoot: '/repo',
|
|
197
|
+
worktreeDir: '/repo.worktrees',
|
|
198
|
+
currentWorktrees: ['release/v1.0.0', 'release/v1.1.0'],
|
|
199
|
+
removedWorktrees: ['release/v1.0.0'],
|
|
200
|
+
allowEditorRelaunch: false,
|
|
201
|
+
}
|
|
195
202
|
|
|
196
203
|
it('removes from the Cursor workspace', async () => {
|
|
197
204
|
config.value = cursorConfig
|
|
@@ -212,31 +219,63 @@ describe('removeIdeWorktreeFolders', () => {
|
|
|
212
219
|
expect(outcomes).toEqual([{ provider: 'cursor', supported: true, removed: [] }])
|
|
213
220
|
})
|
|
214
221
|
|
|
215
|
-
it('
|
|
222
|
+
it('does NOT relaunch Zed on the non-interactive path (allowEditorRelaunch: false)', async () => {
|
|
216
223
|
config.value = zedConfig
|
|
217
224
|
|
|
218
|
-
const outcomes = await removeIdeWorktreeFolders(args)
|
|
225
|
+
const outcomes = await removeIdeWorktreeFolders({ ...args, allowEditorRelaunch: false })
|
|
226
|
+
|
|
227
|
+
expect(zed.reuseZedWorkspace).not.toHaveBeenCalled()
|
|
228
|
+
expect(outcomes).toEqual([{ provider: 'zed', supported: true, removed: [] }])
|
|
229
|
+
})
|
|
219
230
|
|
|
220
|
-
|
|
231
|
+
it('relaunches Zed with the remaining set on the interactive path (allowEditorRelaunch: true)', async () => {
|
|
232
|
+
config.value = zedConfig
|
|
233
|
+
|
|
234
|
+
const outcomes = await removeIdeWorktreeFolders({ ...args, allowEditorRelaunch: true })
|
|
235
|
+
|
|
236
|
+
expect(zed.reuseZedWorkspace).toHaveBeenCalledWith({
|
|
237
|
+
projectRoot: '/repo',
|
|
238
|
+
worktreeDir: '/repo.worktrees',
|
|
239
|
+
remainingBranches: ['release/v1.1.0'],
|
|
240
|
+
})
|
|
241
|
+
expect(outcomes).toEqual([{ provider: 'zed', supported: true, removed: [] }])
|
|
221
242
|
})
|
|
222
243
|
|
|
223
|
-
it('
|
|
244
|
+
it('reports Zed removed:[] when the relaunch swallowed a failure (ran:false), never throwing', async () => {
|
|
245
|
+
config.value = zedConfig
|
|
246
|
+
// reuseZedWorkspace is best-effort: it swallows launch failures internally and resolves
|
|
247
|
+
// { ran: false } rather than rejecting, so the facade never sees a throw.
|
|
248
|
+
zed.reuseZedWorkspace.mockResolvedValue({ ran: false })
|
|
249
|
+
|
|
250
|
+
const outcomes = await removeIdeWorktreeFolders({ ...args, allowEditorRelaunch: true })
|
|
251
|
+
|
|
252
|
+
expect(outcomes).toEqual([{ provider: 'zed', supported: true, removed: [] }])
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
it('removes from Cursor surgically AND relaunches Zed when both are configured (interactive)', async () => {
|
|
224
256
|
config.value = bothConfig
|
|
225
257
|
cursor.removeFoldersFromCursorWorkspace.mockResolvedValue({ removed: ['x'], notFound: [] })
|
|
226
258
|
|
|
227
|
-
const outcomes = await removeIdeWorktreeFolders(args)
|
|
259
|
+
const outcomes = await removeIdeWorktreeFolders({ ...args, allowEditorRelaunch: true })
|
|
228
260
|
|
|
261
|
+
expect(cursor.removeFoldersFromCursorWorkspace).toHaveBeenCalled()
|
|
262
|
+
expect(zed.reuseZedWorkspace).toHaveBeenCalledWith({
|
|
263
|
+
projectRoot: '/repo',
|
|
264
|
+
worktreeDir: '/repo.worktrees',
|
|
265
|
+
remainingBranches: ['release/v1.1.0'],
|
|
266
|
+
})
|
|
229
267
|
expect(outcomes).toEqual([
|
|
230
268
|
{ provider: 'cursor', supported: true, removed: ['x'] },
|
|
231
|
-
{ provider: 'zed', supported:
|
|
269
|
+
{ provider: 'zed', supported: true, removed: [] },
|
|
232
270
|
])
|
|
233
271
|
})
|
|
234
272
|
|
|
235
|
-
it('short-circuits to an empty array when
|
|
273
|
+
it('short-circuits to an empty array when nothing was removed (no config read needed)', async () => {
|
|
236
274
|
config.value = zedConfig
|
|
237
275
|
|
|
238
|
-
const outcomes = await removeIdeWorktreeFolders({ ...args,
|
|
276
|
+
const outcomes = await removeIdeWorktreeFolders({ ...args, removedWorktrees: [] })
|
|
239
277
|
|
|
278
|
+
expect(zed.reuseZedWorkspace).not.toHaveBeenCalled()
|
|
240
279
|
expect(outcomes).toEqual([])
|
|
241
280
|
})
|
|
242
281
|
|
|
@@ -9,15 +9,15 @@ interface OpenIdeWorkspaceArgs {
|
|
|
9
9
|
projectRoot: string
|
|
10
10
|
worktreeDir: string
|
|
11
11
|
currentBranches: string[]
|
|
12
|
-
skipRelaunchWhenEmpty: boolean
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
/**
|
|
16
|
-
* Provider-agnostic entry point for the
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
15
|
+
* Provider-agnostic entry point for the reload open: for every configured
|
|
16
|
+
* editor, reconciles (or, for Zed, simply assembles) the workspace against the
|
|
17
|
+
* release worktrees on disk and launches it — skipping the launch when there are
|
|
18
|
+
* no worktrees, so `worktrees-reload` never pops a bare editor window. Returns
|
|
19
|
+
* one outcome per configured provider (empty array when no IDE is configured).
|
|
20
|
+
* Iterates sequentially — `worktrees-reload` already wraps this call in an outer
|
|
21
21
|
* `Promise.all` with cmux, so a `Promise.all` here would compound editor-spawn
|
|
22
22
|
* concurrency. Best-effort — every provider swallows failures into a warning.
|
|
23
23
|
*/
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { removeFoldersFromCursorWorkspace, resolveCursorWorkspacePath } from 'src/integrations/cursor'
|
|
2
|
+
import { reuseZedWorkspace } from 'src/integrations/zed'
|
|
2
3
|
import { assertNever } from 'src/lib/assert-never'
|
|
3
4
|
import { getInfraKitConfig, resolveConfiguredIdes } from 'src/lib/infra-kit-config'
|
|
4
5
|
import { logger } from 'src/lib/logger'
|
|
@@ -8,7 +9,17 @@ import type { RemoveIdeWorktreeFoldersOutcome } from './types'
|
|
|
8
9
|
interface RemoveIdeWorktreeFoldersArgs {
|
|
9
10
|
projectRoot: string
|
|
10
11
|
worktreeDir: string
|
|
11
|
-
|
|
12
|
+
/** All release worktrees BEFORE removal (release-only — see Zed note below). */
|
|
13
|
+
currentWorktrees: string[]
|
|
14
|
+
/** The subset of `currentWorktrees` that was just removed. */
|
|
15
|
+
removedWorktrees: string[]
|
|
16
|
+
/**
|
|
17
|
+
* Whether the caller is on an interactive path where firing Zed's destructive
|
|
18
|
+
* `zed --reuse` is acceptable (a human is present and confirming). Interactive
|
|
19
|
+
* `worktrees-remove` passes `!confirmedCommand`; `worktrees-sync` and every
|
|
20
|
+
* non-interactive/MCP run pass `false`.
|
|
21
|
+
*/
|
|
22
|
+
allowEditorRelaunch: boolean
|
|
12
23
|
}
|
|
13
24
|
|
|
14
25
|
/**
|
|
@@ -17,57 +28,51 @@ interface RemoveIdeWorktreeFoldersArgs {
|
|
|
17
28
|
* provider (empty array when no IDE is configured or no worktrees were removed),
|
|
18
29
|
* iterating sequentially.
|
|
19
30
|
*
|
|
20
|
-
* Cursor edits the `.code-workspace` `folders` array
|
|
21
|
-
*
|
|
22
|
-
*
|
|
31
|
+
* Cursor surgically edits the `.code-workspace` `folders` array — it removes
|
|
32
|
+
* only the named paths and leaves everything else intact.
|
|
33
|
+
*
|
|
34
|
+
* Zed has no surgical remove. The only mutation mechanism, `zed --reuse`,
|
|
35
|
+
* REPLACES the focused window's entire folder set, so it can only re-state the
|
|
36
|
+
* release worktrees we know about and silently drops any other open folder
|
|
37
|
+
* (`remaining` is built from release worktrees only). Because that is
|
|
38
|
+
* destructive and unrecoverable, it fires ONLY when `allowEditorRelaunch` is
|
|
39
|
+
* true (interactive `worktrees-remove`). On the non-interactive/MCP path it is a
|
|
40
|
+
* deliberate no-op (`supported: true`, `removed: []`) with an info message — the
|
|
41
|
+
* capability exists; skipping is a policy choice, not a missing capability.
|
|
42
|
+
*
|
|
43
|
+
* Zed's `removed` is ALWAYS `[]`: `--reuse` performs no diff, so it confirms no
|
|
44
|
+
* specific removal and we never report intended-but-unverified paths.
|
|
23
45
|
*/
|
|
24
46
|
export const removeIdeWorktreeFolders = async (
|
|
25
47
|
args: RemoveIdeWorktreeFoldersArgs,
|
|
26
48
|
): Promise<RemoveIdeWorktreeFoldersOutcome[]> => {
|
|
27
|
-
const { projectRoot, worktreeDir,
|
|
49
|
+
const { projectRoot, worktreeDir, currentWorktrees, removedWorktrees, allowEditorRelaunch } = args
|
|
28
50
|
|
|
29
|
-
if (
|
|
51
|
+
if (removedWorktrees.length === 0) {
|
|
30
52
|
return []
|
|
31
53
|
}
|
|
32
54
|
|
|
33
55
|
const config = await getInfraKitConfig()
|
|
34
56
|
const ides = resolveConfiguredIdes(config)
|
|
35
57
|
|
|
36
|
-
const folderPaths =
|
|
58
|
+
const folderPaths = removedWorktrees.map((branch) => {
|
|
37
59
|
return `${worktreeDir}/${branch}`
|
|
38
60
|
})
|
|
39
61
|
|
|
62
|
+
const remainingBranches = currentWorktrees.filter((branch) => {
|
|
63
|
+
return !removedWorktrees.includes(branch)
|
|
64
|
+
})
|
|
65
|
+
|
|
40
66
|
const outcomes: RemoveIdeWorktreeFoldersOutcome[] = []
|
|
41
67
|
|
|
42
68
|
for (const ide of ides) {
|
|
43
69
|
switch (ide.provider) {
|
|
44
70
|
case 'cursor': {
|
|
45
|
-
|
|
46
|
-
outcomes.push({ provider: 'cursor', supported: true, removed: [] })
|
|
47
|
-
break
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const workspacePath = resolveCursorWorkspacePath(ide.config.workspaceConfigPath, projectRoot)
|
|
51
|
-
|
|
52
|
-
try {
|
|
53
|
-
const { removed } = await removeFoldersFromCursorWorkspace({ workspacePath, folderPaths })
|
|
54
|
-
|
|
55
|
-
if (removed.length > 0) {
|
|
56
|
-
logger.info(`✅ Removed ${removed.length} folder(s) from ${workspacePath}`)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
outcomes.push({ provider: 'cursor', supported: true, removed })
|
|
60
|
-
} catch (error) {
|
|
61
|
-
logger.warn({ error }, `⚠️ Failed to update Cursor workspace at ${workspacePath}`)
|
|
62
|
-
|
|
63
|
-
outcomes.push({ provider: 'cursor', supported: true, removed: [] })
|
|
64
|
-
}
|
|
71
|
+
outcomes.push(await removeFromCursor({ ide, projectRoot, folderPaths }))
|
|
65
72
|
break
|
|
66
73
|
}
|
|
67
74
|
case 'zed': {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
outcomes.push({ provider: 'zed', supported: false, removed: [] })
|
|
75
|
+
outcomes.push(await removeFromZed({ projectRoot, worktreeDir, remainingBranches, allowEditorRelaunch }))
|
|
71
76
|
break
|
|
72
77
|
}
|
|
73
78
|
default: {
|
|
@@ -78,3 +83,63 @@ export const removeIdeWorktreeFolders = async (
|
|
|
78
83
|
|
|
79
84
|
return outcomes
|
|
80
85
|
}
|
|
86
|
+
|
|
87
|
+
interface RemoveFromCursorArgs {
|
|
88
|
+
ide: Extract<ReturnType<typeof resolveConfiguredIdes>[number], { provider: 'cursor' }>
|
|
89
|
+
projectRoot: string
|
|
90
|
+
folderPaths: string[]
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Surgically strip the removed folder paths from the Cursor `.code-workspace`. */
|
|
94
|
+
const removeFromCursor = async (args: RemoveFromCursorArgs): Promise<RemoveIdeWorktreeFoldersOutcome> => {
|
|
95
|
+
const { ide, projectRoot, folderPaths } = args
|
|
96
|
+
|
|
97
|
+
if (!ide.config.workspaceConfigPath) {
|
|
98
|
+
return { provider: 'cursor', supported: true, removed: [] }
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const workspacePath = resolveCursorWorkspacePath(ide.config.workspaceConfigPath, projectRoot)
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
const { removed } = await removeFoldersFromCursorWorkspace({ workspacePath, folderPaths })
|
|
105
|
+
|
|
106
|
+
if (removed.length > 0) {
|
|
107
|
+
logger.info(`✅ Removed ${removed.length} folder(s) from ${workspacePath}`)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return { provider: 'cursor', supported: true, removed }
|
|
111
|
+
} catch (error) {
|
|
112
|
+
logger.warn({ error }, `⚠️ Failed to update Cursor workspace at ${workspacePath}`)
|
|
113
|
+
|
|
114
|
+
return { provider: 'cursor', supported: true, removed: [] }
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
interface RemoveFromZedArgs {
|
|
119
|
+
projectRoot: string
|
|
120
|
+
worktreeDir: string
|
|
121
|
+
remainingBranches: string[]
|
|
122
|
+
allowEditorRelaunch: boolean
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Reflect the removal in Zed by relaunching the focused window onto the
|
|
127
|
+
* remaining set — but ONLY on an interactive path (see the module doc for why
|
|
128
|
+
* `zed --reuse` is destructive). Otherwise a deliberate no-op. `removed` is
|
|
129
|
+
* always `[]` because `--reuse` performs no diff.
|
|
130
|
+
*/
|
|
131
|
+
const removeFromZed = async (args: RemoveFromZedArgs): Promise<RemoveIdeWorktreeFoldersOutcome> => {
|
|
132
|
+
const { projectRoot, worktreeDir, remainingBranches, allowEditorRelaunch } = args
|
|
133
|
+
|
|
134
|
+
if (!allowEditorRelaunch) {
|
|
135
|
+
logger.info(
|
|
136
|
+
'ℹ️ Zed folder removal skipped (no interactive session); close removed worktree folders in Zed manually if needed.',
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
return { provider: 'zed', supported: true, removed: [] }
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
await reuseZedWorkspace({ projectRoot, worktreeDir, remainingBranches })
|
|
143
|
+
|
|
144
|
+
return { provider: 'zed', supported: true, removed: [] }
|
|
145
|
+
}
|
|
@@ -26,7 +26,16 @@ export interface AddIdeWorktreeFoldersOutcome {
|
|
|
26
26
|
|
|
27
27
|
export interface RemoveIdeWorktreeFoldersOutcome {
|
|
28
28
|
provider: IdeProvider
|
|
29
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* True when the provider can reflect a removal. Both providers now report
|
|
31
|
+
* `true`; `false` is reserved for a future provider with no remove capability.
|
|
32
|
+
*/
|
|
30
33
|
supported: boolean
|
|
34
|
+
/**
|
|
35
|
+
* Folders confirmed removed. For Cursor this is the real diff of the
|
|
36
|
+
* `.code-workspace` `folders` array. For Zed it is ALWAYS `[]`: the only
|
|
37
|
+
* mechanism (`zed --reuse`) replaces the whole window without producing a
|
|
38
|
+
* diff, so it confirms no specific removal even when it refreshed the window.
|
|
39
|
+
*/
|
|
31
40
|
removed: string[]
|
|
32
41
|
}
|
|
@@ -37,7 +37,6 @@ describe('openZedWorkspace', () => {
|
|
|
37
37
|
projectRoot: '/repo',
|
|
38
38
|
worktreeDir: '/repo.worktrees',
|
|
39
39
|
currentBranches: ['release/v1.0.0', 'release/v1.1.0'],
|
|
40
|
-
skipRelaunchWhenEmpty: false,
|
|
41
40
|
})
|
|
42
41
|
|
|
43
42
|
expect(zx.calls).toHaveLength(1)
|
|
@@ -45,25 +44,11 @@ describe('openZedWorkspace', () => {
|
|
|
45
44
|
expect(outcome).toEqual({ ran: true, added: 2, removed: 0 })
|
|
46
45
|
})
|
|
47
46
|
|
|
48
|
-
it('
|
|
47
|
+
it('skips launching when there are no worktrees', async () => {
|
|
49
48
|
const outcome = await openZedWorkspace({
|
|
50
49
|
projectRoot: '/repo',
|
|
51
50
|
worktreeDir: '/repo.worktrees',
|
|
52
51
|
currentBranches: [],
|
|
53
|
-
skipRelaunchWhenEmpty: false,
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
expect(zx.calls).toHaveLength(1)
|
|
57
|
-
expect(zx.calls[0]?.[0]).toEqual(['/repo'])
|
|
58
|
-
expect(outcome).toEqual({ ran: true, added: 0, removed: 0 })
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
it('skips launching when skipRelaunchWhenEmpty is set and there are no worktrees', async () => {
|
|
62
|
-
const outcome = await openZedWorkspace({
|
|
63
|
-
projectRoot: '/repo',
|
|
64
|
-
worktreeDir: '/repo.worktrees',
|
|
65
|
-
currentBranches: [],
|
|
66
|
-
skipRelaunchWhenEmpty: true,
|
|
67
52
|
})
|
|
68
53
|
|
|
69
54
|
expect(zx.calls).toHaveLength(0)
|
|
@@ -77,7 +62,6 @@ describe('openZedWorkspace', () => {
|
|
|
77
62
|
projectRoot: '/repo',
|
|
78
63
|
worktreeDir: '/repo.worktrees',
|
|
79
64
|
currentBranches: ['release/v1.0.0'],
|
|
80
|
-
skipRelaunchWhenEmpty: false,
|
|
81
65
|
})
|
|
82
66
|
|
|
83
67
|
expect(outcome).toEqual({ ran: false, added: 0, removed: 0 })
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { reuseZedWorkspace } from '../reuse-zed-workspace'
|
|
4
|
+
|
|
5
|
+
const zx = vi.hoisted(() => {
|
|
6
|
+
return { calls: [] as unknown[][], shouldThrow: false }
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
vi.mock('zx', () => {
|
|
10
|
+
return {
|
|
11
|
+
$: vi.fn((_strings: TemplateStringsArray, ...values: unknown[]) => {
|
|
12
|
+
zx.calls.push(values)
|
|
13
|
+
|
|
14
|
+
if (zx.shouldThrow) {
|
|
15
|
+
return Promise.reject(new Error('zed failed to launch'))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return Promise.resolve({ stdout: '' })
|
|
19
|
+
}),
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
const log = vi.hoisted(() => {
|
|
24
|
+
return { info: vi.fn(), warn: vi.fn(), error: vi.fn() }
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
vi.mock('src/lib/logger', () => {
|
|
28
|
+
return { logger: log }
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
describe('reuseZedWorkspace', () => {
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
zx.calls = []
|
|
34
|
+
zx.shouldThrow = false
|
|
35
|
+
vi.clearAllMocks()
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('runs `zed --reuse` with the project root plus the remaining worktree paths', async () => {
|
|
39
|
+
const outcome = await reuseZedWorkspace({
|
|
40
|
+
projectRoot: '/repo',
|
|
41
|
+
worktreeDir: '/repo.worktrees',
|
|
42
|
+
remainingBranches: ['release/v1.0.0', 'release/v1.1.0'],
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
expect(zx.calls).toHaveLength(1)
|
|
46
|
+
expect(zx.calls[0]?.[0]).toEqual(['/repo', '/repo.worktrees/release/v1.0.0', '/repo.worktrees/release/v1.1.0'])
|
|
47
|
+
expect(outcome).toEqual({ ran: true })
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('collapses to root-only when no worktrees remain', async () => {
|
|
51
|
+
const outcome = await reuseZedWorkspace({
|
|
52
|
+
projectRoot: '/repo',
|
|
53
|
+
worktreeDir: '/repo.worktrees',
|
|
54
|
+
remainingBranches: [],
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
expect(zx.calls).toHaveLength(1)
|
|
58
|
+
expect(zx.calls[0]?.[0]).toEqual(['/repo'])
|
|
59
|
+
expect(outcome).toEqual({ ran: true })
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
it('emits a disclosure log line warning that other open folders are not preserved', async () => {
|
|
63
|
+
await reuseZedWorkspace({
|
|
64
|
+
projectRoot: '/repo',
|
|
65
|
+
worktreeDir: '/repo.worktrees',
|
|
66
|
+
remainingBranches: ['release/v1.0.0'],
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
expect(log.info).toHaveBeenCalledWith(
|
|
70
|
+
expect.stringContaining('other folders in the focused window are not preserved'),
|
|
71
|
+
)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
it('swallows a launch failure into a best-effort warning', async () => {
|
|
75
|
+
zx.shouldThrow = true
|
|
76
|
+
|
|
77
|
+
const outcome = await reuseZedWorkspace({
|
|
78
|
+
projectRoot: '/repo',
|
|
79
|
+
worktreeDir: '/repo.worktrees',
|
|
80
|
+
remainingBranches: ['release/v1.0.0'],
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
expect(outcome).toEqual({ ran: false })
|
|
84
|
+
expect(log.warn).toHaveBeenCalled()
|
|
85
|
+
})
|
|
86
|
+
})
|
|
@@ -6,12 +6,6 @@ interface OpenZedWorkspaceArgs {
|
|
|
6
6
|
projectRoot: string
|
|
7
7
|
worktreeDir: string
|
|
8
8
|
currentBranches: string[]
|
|
9
|
-
/**
|
|
10
|
-
* When true, skip launching Zed if there are no release worktrees. Lets
|
|
11
|
-
* `worktrees-reload` avoid popping a bare Zed window while keeping the
|
|
12
|
-
* cold-start `worktrees-open` behaviour (launch unconditionally) intact.
|
|
13
|
-
*/
|
|
14
|
-
skipRelaunchWhenEmpty: boolean
|
|
15
9
|
}
|
|
16
10
|
|
|
17
11
|
interface OpenZedWorkspaceOutcome {
|
|
@@ -23,8 +17,8 @@ interface OpenZedWorkspaceOutcome {
|
|
|
23
17
|
/**
|
|
24
18
|
* Opens a single Zed workspace containing the project root plus every release
|
|
25
19
|
* worktree, via one `zed <root> <wt...>` invocation (Zed realizes a multi-folder
|
|
26
|
-
* workspace from multiple path arguments).
|
|
27
|
-
*
|
|
20
|
+
* workspace from multiple path arguments). Used by `worktrees-reload`; skips the
|
|
21
|
+
* launch when there are no worktrees so it never pops a bare Zed window.
|
|
28
22
|
*
|
|
29
23
|
* Zed has no portable workspace file and no folder-remove CLI, so there is
|
|
30
24
|
* nothing to reconcile: `added` is the number of worktrees opened and `removed`
|
|
@@ -32,9 +26,9 @@ interface OpenZedWorkspaceOutcome {
|
|
|
32
26
|
* best-effort, mirroring the Cursor integration.
|
|
33
27
|
*/
|
|
34
28
|
export const openZedWorkspace = async (args: OpenZedWorkspaceArgs): Promise<OpenZedWorkspaceOutcome> => {
|
|
35
|
-
const { projectRoot, worktreeDir, currentBranches
|
|
29
|
+
const { projectRoot, worktreeDir, currentBranches } = args
|
|
36
30
|
|
|
37
|
-
if (
|
|
31
|
+
if (currentBranches.length === 0) {
|
|
38
32
|
return { ran: false, added: 0, removed: 0 }
|
|
39
33
|
}
|
|
40
34
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { $ } from 'zx'
|
|
2
|
+
|
|
3
|
+
import { logger } from 'src/lib/logger'
|
|
4
|
+
|
|
5
|
+
interface ReuseZedWorkspaceArgs {
|
|
6
|
+
projectRoot: string
|
|
7
|
+
worktreeDir: string
|
|
8
|
+
remainingBranches: string[]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface ReuseZedWorkspaceOutcome {
|
|
12
|
+
ran: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Reflects a worktree removal in the open Zed window by running
|
|
17
|
+
* `zed --reuse <root> <remaining release worktrees...>`.
|
|
18
|
+
*
|
|
19
|
+
* IMPORTANT — this is destructive: `--reuse` REPLACES the focused window's
|
|
20
|
+
* ENTIRE folder set with exactly these paths. The remaining set is built from
|
|
21
|
+
* release worktrees only (`getCurrentWorktrees('release')`), so any other folder
|
|
22
|
+
* open in that window — feature worktrees, scratch dirs, user-added dirs — is
|
|
23
|
+
* DROPPED and is NOT recoverable by infra-kit (Zed offers no undo and we keep no
|
|
24
|
+
* record of the prior set). The caller MUST therefore only invoke this on an
|
|
25
|
+
* interactive path where a human is present and can re-add folders via
|
|
26
|
+
* `zed --add`. We emit a disclosure log line saying as much.
|
|
27
|
+
*
|
|
28
|
+
* Distinct from `openZedWorkspace`, which runs `zed <paths>` WITHOUT `--reuse`
|
|
29
|
+
* to realize a multi-folder workspace; that does not replace a focused window.
|
|
30
|
+
*
|
|
31
|
+
* Best-effort: any launch failure is swallowed into a warning, mirroring
|
|
32
|
+
* `openZedWorkspace`. Root is always included so the path list is never empty.
|
|
33
|
+
*/
|
|
34
|
+
export const reuseZedWorkspace = async (args: ReuseZedWorkspaceArgs): Promise<ReuseZedWorkspaceOutcome> => {
|
|
35
|
+
const { projectRoot, worktreeDir, remainingBranches } = args
|
|
36
|
+
|
|
37
|
+
const paths = [
|
|
38
|
+
projectRoot,
|
|
39
|
+
...remainingBranches.map((branch) => {
|
|
40
|
+
return `${worktreeDir}/${branch}`
|
|
41
|
+
}),
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
await $`zed --reuse ${paths}`
|
|
46
|
+
|
|
47
|
+
logger.info(
|
|
48
|
+
`↻ Refreshed Zed workspace to root + ${remainingBranches.length} release worktree(s) (other folders in the focused window are not preserved)`,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
return { ran: true }
|
|
52
|
+
} catch (error) {
|
|
53
|
+
logger.warn({ error }, '⚠️ Failed to refresh Zed workspace')
|
|
54
|
+
|
|
55
|
+
return { ran: false }
|
|
56
|
+
}
|
|
57
|
+
}
|