gsd-pi 2.48.0 → 2.49.0-dev.c319e08
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/dist/resources/extensions/gsd/auto/session.js +4 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +17 -2
- package/dist/resources/extensions/gsd/auto-post-unit.js +17 -3
- package/dist/resources/extensions/gsd/auto-worktree.js +5 -2
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +43 -3
- package/dist/resources/extensions/gsd/git-service.js +11 -10
- package/dist/resources/extensions/gsd/guided-flow-queue.js +10 -11
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +223 -56
- package/dist/resources/extensions/gsd/prompts/run-uat.md +4 -4
- package/dist/resources/extensions/gsd/worktree-command.js +1 -1
- package/dist/resources/extensions/gsd/worktree-resolver.js +24 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
- package/dist/web/standalone/.next/server/chunks/229.js +1 -1
- package/dist/web/standalone/.next/server/chunks/471.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-6654a8cca61a3d1c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/dist/worktree-cli.js +1 -1
- package/package.json +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/github-sync/tests/commit-linking.test.ts +8 -4
- package/src/resources/extensions/gsd/auto/session.ts +5 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +18 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +18 -3
- package/src/resources/extensions/gsd/auto-worktree.ts +4 -2
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +46 -3
- package/src/resources/extensions/gsd/git-service.ts +12 -11
- package/src/resources/extensions/gsd/guided-flow-queue.ts +11 -12
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +223 -56
- package/src/resources/extensions/gsd/prompts/run-uat.md +4 -4
- package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-stash-merge.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +14 -12
- package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/git-service.test.ts +19 -9
- package/src/resources/extensions/gsd/tests/milestone-transition-worktree.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/parallel-merge.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/queue-completed-milestone-perf.test.ts +155 -0
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +67 -0
- package/src/resources/extensions/gsd/worktree-command.ts +1 -1
- package/src/resources/extensions/gsd/worktree-resolver.ts +31 -0
- package/dist/web/standalone/.next/static/chunks/app/page-12dd5ece0df4badc.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
- /package/dist/web/standalone/.next/static/{zGWUKFTfjCQerNgsPpAbF → QBhWLjeTSHlwrt9jbPmIz}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{zGWUKFTfjCQerNgsPpAbF → QBhWLjeTSHlwrt9jbPmIz}/_ssgManifest.js +0 -0
|
@@ -252,7 +252,7 @@ describe('feature-branch-lifecycle-integration', async () => {
|
|
|
252
252
|
// Exactly one new commit on feature branch (the squash merge)
|
|
253
253
|
const featureLog = run(`git log --oneline ${featureBranch}`, repo);
|
|
254
254
|
assert.ok(
|
|
255
|
-
featureLog.includes(
|
|
255
|
+
featureLog.includes("feat:"),
|
|
256
256
|
"feature branch has milestone merge commit",
|
|
257
257
|
);
|
|
258
258
|
|
|
@@ -215,10 +215,12 @@ describe('git-service', async () => {
|
|
|
215
215
|
oneLiner: "Added JWT-based auth with refresh token rotation",
|
|
216
216
|
keyFiles: ["src/auth.ts", "src/middleware/jwt.ts"],
|
|
217
217
|
});
|
|
218
|
-
assert.ok(msg.startsWith("feat
|
|
218
|
+
assert.ok(msg.startsWith("feat:"), "message starts with type: (no scope)");
|
|
219
|
+
assert.ok(!msg.includes("(S01/T02)"), "no GSD ID in subject line");
|
|
219
220
|
assert.ok(msg.includes("JWT-based auth"), "message includes one-liner content");
|
|
220
221
|
assert.ok(msg.includes("- src/auth.ts"), "message body includes key files");
|
|
221
222
|
assert.ok(msg.includes("- src/middleware/jwt.ts"), "message body includes second key file");
|
|
223
|
+
assert.ok(msg.includes("GSD-Task: S01/T02"), "GSD-Task trailer in body");
|
|
222
224
|
});
|
|
223
225
|
|
|
224
226
|
{
|
|
@@ -226,9 +228,9 @@ describe('git-service', async () => {
|
|
|
226
228
|
taskId: "S02/T01",
|
|
227
229
|
taskTitle: "fix login redirect bug",
|
|
228
230
|
});
|
|
229
|
-
assert.ok(msg.startsWith("fix
|
|
231
|
+
assert.ok(msg.startsWith("fix:"), "infers fix type from title");
|
|
230
232
|
assert.ok(msg.includes("fix login redirect bug"), "uses task title when no one-liner");
|
|
231
|
-
assert.ok(
|
|
233
|
+
assert.ok(msg.includes("GSD-Task: S02/T01"), "GSD-Task trailer present");
|
|
232
234
|
}
|
|
233
235
|
|
|
234
236
|
{
|
|
@@ -237,7 +239,8 @@ describe('git-service', async () => {
|
|
|
237
239
|
taskTitle: "add tests",
|
|
238
240
|
oneLiner: "Unit tests for auth module with coverage",
|
|
239
241
|
});
|
|
240
|
-
assert.ok(msg.startsWith("test
|
|
242
|
+
assert.ok(msg.startsWith("test:"), "infers test type");
|
|
243
|
+
assert.ok(msg.includes("GSD-Task: S01/T03"), "GSD-Task trailer present");
|
|
241
244
|
}
|
|
242
245
|
|
|
243
246
|
// ─── RUNTIME_EXCLUSION_PATHS ───────────────────────────────────────────
|
|
@@ -478,10 +481,10 @@ describe('git-service', async () => {
|
|
|
478
481
|
|
|
479
482
|
// Without task context, autoCommit uses generic chore message
|
|
480
483
|
const msg = svc.autoCommit("task", "T01");
|
|
481
|
-
assert.deepStrictEqual(msg, "chore
|
|
484
|
+
assert.deepStrictEqual(msg, "chore: auto-commit after task\n\nGSD-Unit: T01", "autoCommit returns generic format with trailer");
|
|
482
485
|
|
|
483
486
|
const log = run("git log --oneline -1", repo);
|
|
484
|
-
assert.ok(log.includes("chore
|
|
487
|
+
assert.ok(log.includes("chore: auto-commit after task"), "generic commit message is in git log");
|
|
485
488
|
|
|
486
489
|
// With task context, autoCommit uses meaningful message
|
|
487
490
|
createFile(repo, "src/auth.ts", "export function login() {}");
|
|
@@ -492,8 +495,9 @@ describe('git-service', async () => {
|
|
|
492
495
|
keyFiles: ["src/auth.ts"],
|
|
493
496
|
});
|
|
494
497
|
assert.ok(msg2 !== null, "autoCommit with task context returns a message");
|
|
495
|
-
assert.ok(msg2!.startsWith("feat
|
|
498
|
+
assert.ok(msg2!.startsWith("feat:"), "meaningful commit uses feat type without scope");
|
|
496
499
|
assert.ok(msg2!.includes("JWT-based auth"), "meaningful commit includes one-liner content");
|
|
500
|
+
assert.ok(msg2!.includes("GSD-Task: S01/T02"), "meaningful commit has GSD-Task trailer");
|
|
497
501
|
|
|
498
502
|
rmSync(repo, { recursive: true, force: true });
|
|
499
503
|
});
|
|
@@ -529,7 +533,7 @@ describe('git-service', async () => {
|
|
|
529
533
|
|
|
530
534
|
// Auto-commit with .gsd/ excluded (simulates pre-switch)
|
|
531
535
|
const msg = svc.autoCommit("pre-switch", "main", [".gsd/"]);
|
|
532
|
-
assert.deepStrictEqual(msg, "chore
|
|
536
|
+
assert.deepStrictEqual(msg, "chore: auto-commit after pre-switch\n\nGSD-Unit: main", "pre-switch autoCommit with .gsd/ exclusion commits");
|
|
533
537
|
|
|
534
538
|
// Verify .gsd/ file was NOT committed
|
|
535
539
|
const show = run("git show --stat HEAD", repo);
|
|
@@ -1295,7 +1299,12 @@ describe('git-service', async () => {
|
|
|
1295
1299
|
issueNumber: 42,
|
|
1296
1300
|
});
|
|
1297
1301
|
assert.ok(msg.includes("Resolves #42"), "buildTaskCommitMessage includes Resolves #N trailer when issueNumber is set");
|
|
1298
|
-
assert.ok(msg.startsWith("fix
|
|
1302
|
+
assert.ok(msg.startsWith("fix:"), "buildTaskCommitMessage infers fix type");
|
|
1303
|
+
assert.ok(msg.includes("GSD-Task: S01/T03"), "GSD-Task trailer present");
|
|
1304
|
+
// GSD-Task should come before Resolves
|
|
1305
|
+
const taskIdx = msg.indexOf("GSD-Task: S01/T03");
|
|
1306
|
+
const resolvesIdx = msg.indexOf("Resolves #42");
|
|
1307
|
+
assert.ok(taskIdx < resolvesIdx, "GSD-Task trailer before Resolves trailer");
|
|
1299
1308
|
});
|
|
1300
1309
|
|
|
1301
1310
|
{
|
|
@@ -1305,6 +1314,7 @@ describe('git-service', async () => {
|
|
|
1305
1314
|
taskTitle: "add dashboard widget",
|
|
1306
1315
|
});
|
|
1307
1316
|
assert.ok(!msg.includes("Resolves"), "buildTaskCommitMessage omits Resolves trailer when issueNumber is absent");
|
|
1317
|
+
assert.ok(msg.includes("GSD-Task: S01/T04"), "GSD-Task trailer still present");
|
|
1308
1318
|
}
|
|
1309
1319
|
|
|
1310
1320
|
// ─── runPreMergeCheck: skips when no package.json ────────────────────────
|
|
@@ -94,8 +94,8 @@ test("worktree swap on milestone transition: merge old, create new", () => {
|
|
|
94
94
|
assert.equal(process.cwd(), tempDir, "cwd restored to project root after merge");
|
|
95
95
|
assert.ok(!isInAutoWorktree(tempDir), "no longer in auto-worktree after merge");
|
|
96
96
|
|
|
97
|
-
// Verify M001 work was merged to main
|
|
98
|
-
const mainLog = run("git log
|
|
97
|
+
// Verify M001 work was merged to main (milestone ID is in trailer, not subject)
|
|
98
|
+
const mainLog = run("git log -3", tempDir);
|
|
99
99
|
assert.ok(mainLog.includes("M001"), "M001 squash commit should be on main");
|
|
100
100
|
|
|
101
101
|
// Phase 3: Create new worktree for M002 (simulates new milestone)
|
|
@@ -168,7 +168,7 @@ test("formatMergeResults — empty results", () => {
|
|
|
168
168
|
|
|
169
169
|
test("formatMergeResults — successful merge", () => {
|
|
170
170
|
const results: MergeResult[] = [
|
|
171
|
-
{ milestoneId: "M001", success: true, commitMessage: "feat
|
|
171
|
+
{ milestoneId: "M001", success: true, commitMessage: "feat: Auth\n\nGSD-Milestone: M001\nBranch: milestone/M001", pushed: true },
|
|
172
172
|
];
|
|
173
173
|
const output = formatMergeResults(results);
|
|
174
174
|
assert.ok(output.includes("M001"));
|
|
@@ -178,7 +178,7 @@ test("formatMergeResults — successful merge", () => {
|
|
|
178
178
|
|
|
179
179
|
test("formatMergeResults — successful merge without push", () => {
|
|
180
180
|
const results: MergeResult[] = [
|
|
181
|
-
{ milestoneId: "M001", success: true, commitMessage: "feat
|
|
181
|
+
{ milestoneId: "M001", success: true, commitMessage: "feat: Auth\n\nGSD-Milestone: M001\nBranch: milestone/M001", pushed: false },
|
|
182
182
|
];
|
|
183
183
|
const output = formatMergeResults(results);
|
|
184
184
|
assert.ok(output.includes("merged successfully"));
|
|
@@ -213,7 +213,7 @@ test("formatMergeResults — generic failure without conflict files", () => {
|
|
|
213
213
|
|
|
214
214
|
test("formatMergeResults — mixed results", () => {
|
|
215
215
|
const results: MergeResult[] = [
|
|
216
|
-
{ milestoneId: "M001", success: true, commitMessage: "feat
|
|
216
|
+
{ milestoneId: "M001", success: true, commitMessage: "feat: OK\n\nGSD-Milestone: M001\nBranch: milestone/M001", pushed: false },
|
|
217
217
|
{ milestoneId: "M002", success: false, error: "conflict", conflictFiles: ["a.ts"] },
|
|
218
218
|
];
|
|
219
219
|
const output = formatMergeResults(results);
|
|
@@ -281,9 +281,9 @@ test("mergeCompletedMilestone — clean merge, session status cleaned up", async
|
|
|
281
281
|
// Verify file merged to main
|
|
282
282
|
assert.ok(existsSync(join(repo, "auth.ts")), "auth.ts should be on main");
|
|
283
283
|
|
|
284
|
-
// Verify commit on main
|
|
285
|
-
const log = run("git log --
|
|
286
|
-
assert.ok(log.includes("M010"), "commit message should reference M010");
|
|
284
|
+
// Verify commit on main (M010 is now in the body as a GSD-Milestone trailer)
|
|
285
|
+
const log = run("git log -1 --format=%B main", repo);
|
|
286
|
+
assert.ok(log.includes("GSD-Milestone: M010"), "commit message should reference M010 in trailer");
|
|
287
287
|
|
|
288
288
|
// Verify session status cleaned up
|
|
289
289
|
const statusAfter = readSessionStatus(repo, "M010");
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #2379: /gsd queue fails with 429 rate limit on projects
|
|
3
|
+
* with many completed milestones.
|
|
4
|
+
*
|
|
5
|
+
* The bug: buildExistingMilestonesContext iterates over ALL milestones
|
|
6
|
+
* (including completed ones) and calls loadFile for CONTEXT, SUMMARY,
|
|
7
|
+
* CONTEXT-DRAFT, and ROADMAP files on each — causing excessive I/O that
|
|
8
|
+
* triggers rate limits on large projects.
|
|
9
|
+
*
|
|
10
|
+
* The fix: completed milestones should emit a short summary line without
|
|
11
|
+
* loading their heavy artifact files (CONTEXT.md, SUMMARY.md, etc.).
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
import { tmpdir } from "node:os";
|
|
17
|
+
|
|
18
|
+
import { buildExistingMilestonesContext } from "../guided-flow-queue.ts";
|
|
19
|
+
import type { GSDState, MilestoneRegistryEntry } from "../types.ts";
|
|
20
|
+
import { createTestContext } from "./test-helpers.ts";
|
|
21
|
+
|
|
22
|
+
const { assertTrue, assertEq, report } = createTestContext();
|
|
23
|
+
|
|
24
|
+
// ─── Fixture: project with many completed milestones ─────────────────────
|
|
25
|
+
|
|
26
|
+
const tmpBase = mkdtempSync(join(tmpdir(), "gsd-queue-perf-"));
|
|
27
|
+
const gsd = join(tmpBase, ".gsd");
|
|
28
|
+
mkdirSync(join(gsd, "milestones"), { recursive: true });
|
|
29
|
+
|
|
30
|
+
const COMPLETED_COUNT = 25;
|
|
31
|
+
const ACTIVE_COUNT = 1;
|
|
32
|
+
const PENDING_COUNT = 2;
|
|
33
|
+
|
|
34
|
+
const allMilestoneIds: string[] = [];
|
|
35
|
+
const registry: MilestoneRegistryEntry[] = [];
|
|
36
|
+
|
|
37
|
+
// Create 25 completed milestones with CONTEXT.md and SUMMARY.md files
|
|
38
|
+
for (let i = 1; i <= COMPLETED_COUNT; i++) {
|
|
39
|
+
const mid = `M${String(i).padStart(3, "0")}`;
|
|
40
|
+
allMilestoneIds.push(mid);
|
|
41
|
+
registry.push({ id: mid, title: `Completed milestone ${i}`, status: "complete" });
|
|
42
|
+
mkdirSync(join(gsd, "milestones", mid), { recursive: true });
|
|
43
|
+
writeFileSync(
|
|
44
|
+
join(gsd, "milestones", mid, `${mid}-CONTEXT.md`),
|
|
45
|
+
`# ${mid}: Completed milestone ${i}\n\nThis is a large context document for ${mid}.\n${"Lorem ipsum dolor sit amet. ".repeat(50)}\n`,
|
|
46
|
+
);
|
|
47
|
+
writeFileSync(
|
|
48
|
+
join(gsd, "milestones", mid, `${mid}-SUMMARY.md`),
|
|
49
|
+
`# ${mid} Summary\n\nDelivered feature ${i} successfully.\n`,
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Create 1 active milestone
|
|
54
|
+
{
|
|
55
|
+
const mid = `M${String(COMPLETED_COUNT + 1).padStart(3, "0")}`;
|
|
56
|
+
allMilestoneIds.push(mid);
|
|
57
|
+
registry.push({ id: mid, title: "Active milestone", status: "active" });
|
|
58
|
+
mkdirSync(join(gsd, "milestones", mid), { recursive: true });
|
|
59
|
+
writeFileSync(
|
|
60
|
+
join(gsd, "milestones", mid, `${mid}-CONTEXT.md`),
|
|
61
|
+
`# ${mid}: Active milestone\n\nCurrently in progress.\n`,
|
|
62
|
+
);
|
|
63
|
+
writeFileSync(
|
|
64
|
+
join(gsd, "milestones", mid, `${mid}-ROADMAP.md`),
|
|
65
|
+
`# ${mid} Roadmap\n\nSlices planned.\n`,
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Create 2 pending milestones
|
|
70
|
+
for (let i = 0; i < PENDING_COUNT; i++) {
|
|
71
|
+
const mid = `M${String(COMPLETED_COUNT + ACTIVE_COUNT + 1 + i).padStart(3, "0")}`;
|
|
72
|
+
allMilestoneIds.push(mid);
|
|
73
|
+
registry.push({ id: mid, title: `Pending milestone ${i + 1}`, status: "pending" });
|
|
74
|
+
mkdirSync(join(gsd, "milestones", mid), { recursive: true });
|
|
75
|
+
writeFileSync(
|
|
76
|
+
join(gsd, "milestones", mid, `${mid}-CONTEXT.md`),
|
|
77
|
+
`# ${mid}: Pending milestone ${i + 1}\n\nQueued work.\n`,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const state: GSDState = {
|
|
82
|
+
activeMilestone: { id: `M${String(COMPLETED_COUNT + 1).padStart(3, "0")}`, title: "Active milestone" },
|
|
83
|
+
activeSlice: null,
|
|
84
|
+
activeTask: null,
|
|
85
|
+
phase: "executing",
|
|
86
|
+
recentDecisions: [],
|
|
87
|
+
blockers: [],
|
|
88
|
+
nextAction: "",
|
|
89
|
+
registry,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// ─── Test: completed milestones should NOT have their files loaded ────────
|
|
93
|
+
|
|
94
|
+
console.log("\n=== Queue completed milestone performance (#2379) ===");
|
|
95
|
+
|
|
96
|
+
const context = await buildExistingMilestonesContext(tmpBase, allMilestoneIds, state);
|
|
97
|
+
|
|
98
|
+
// Active and pending milestones SHOULD have full context loaded
|
|
99
|
+
const activeMid = `M${String(COMPLETED_COUNT + 1).padStart(3, "0")}`;
|
|
100
|
+
assertTrue(
|
|
101
|
+
context.includes("Currently in progress"),
|
|
102
|
+
"Active milestone context content should be loaded",
|
|
103
|
+
);
|
|
104
|
+
assertTrue(
|
|
105
|
+
context.includes("Slices planned"),
|
|
106
|
+
"Active milestone roadmap should be loaded",
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
for (let i = 0; i < PENDING_COUNT; i++) {
|
|
110
|
+
const mid = `M${String(COMPLETED_COUNT + ACTIVE_COUNT + 1 + i).padStart(3, "0")}`;
|
|
111
|
+
assertTrue(
|
|
112
|
+
context.includes(`Pending milestone ${i + 1}`),
|
|
113
|
+
`Pending milestone ${mid} context should be loaded`,
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Completed milestones should NOT have their CONTEXT.md body or SUMMARY.md
|
|
118
|
+
// content loaded — only a status line
|
|
119
|
+
for (let i = 1; i <= COMPLETED_COUNT; i++) {
|
|
120
|
+
const mid = `M${String(i).padStart(3, "0")}`;
|
|
121
|
+
|
|
122
|
+
// Should still mention the milestone ID and status
|
|
123
|
+
assertTrue(
|
|
124
|
+
context.includes(mid),
|
|
125
|
+
`Completed milestone ${mid} should still be referenced`,
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
// Should NOT contain the heavy context body text
|
|
129
|
+
assertTrue(
|
|
130
|
+
!context.includes(`This is a large context document for ${mid}`),
|
|
131
|
+
`Completed milestone ${mid} should NOT have its full CONTEXT.md body loaded`,
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
// Should NOT contain the summary body
|
|
135
|
+
assertTrue(
|
|
136
|
+
!context.includes(`Delivered feature ${i} successfully`),
|
|
137
|
+
`Completed milestone ${mid} should NOT have its SUMMARY.md body loaded`,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ─── Test: the overall context should be reasonable in size ──────────────
|
|
142
|
+
|
|
143
|
+
// With 25 completed milestones NOT loading files, the context should be
|
|
144
|
+
// significantly smaller than if all files were loaded
|
|
145
|
+
const contextLines = context.split("\n").length;
|
|
146
|
+
assertTrue(
|
|
147
|
+
contextLines < 200,
|
|
148
|
+
`Context should be concise (got ${contextLines} lines); completed milestones should not inflate it`,
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
// ─── Cleanup ──────────────────────────────────────────────────────────────
|
|
152
|
+
|
|
153
|
+
rmSync(tmpBase, { recursive: true, force: true });
|
|
154
|
+
|
|
155
|
+
report();
|
|
@@ -343,6 +343,74 @@ test('(m) non-artifact UAT skip', async () => {
|
|
|
343
343
|
}
|
|
344
344
|
});
|
|
345
345
|
|
|
346
|
+
test('(o) verdict gate: PARTIAL is acceptable for mixed/human-experience/live-runtime UAT types', () => {
|
|
347
|
+
// This test verifies the contract that extractUatType correctly identifies
|
|
348
|
+
// the modes where PARTIAL should not block progression.
|
|
349
|
+
// The verdict gate in auto-dispatch.ts uses this to build acceptableVerdicts.
|
|
350
|
+
const mixedType = extractUatType(makeUatContent('mixed'));
|
|
351
|
+
const humanExpType = extractUatType(makeUatContent('human-experience'));
|
|
352
|
+
const liveRuntimeType = extractUatType(makeUatContent('live-runtime'));
|
|
353
|
+
const artifactType = extractUatType(makeUatContent('artifact-driven'));
|
|
354
|
+
const browserType = extractUatType(makeUatContent('browser-executable'));
|
|
355
|
+
const runtimeExecType = extractUatType(makeUatContent('runtime-executable'));
|
|
356
|
+
|
|
357
|
+
// These modes should allow PARTIAL (non-fully-automatable)
|
|
358
|
+
const partialAcceptableModes = ['mixed', 'human-experience', 'live-runtime'];
|
|
359
|
+
assert.ok(
|
|
360
|
+
partialAcceptableModes.includes(mixedType!),
|
|
361
|
+
`mixed → "${mixedType}" is in partialAcceptableModes`,
|
|
362
|
+
);
|
|
363
|
+
assert.ok(
|
|
364
|
+
partialAcceptableModes.includes(humanExpType!),
|
|
365
|
+
`human-experience → "${humanExpType}" is in partialAcceptableModes`,
|
|
366
|
+
);
|
|
367
|
+
assert.ok(
|
|
368
|
+
partialAcceptableModes.includes(liveRuntimeType!),
|
|
369
|
+
`live-runtime → "${liveRuntimeType}" is in partialAcceptableModes`,
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
// These modes should NOT allow PARTIAL (fully automatable)
|
|
373
|
+
assert.ok(
|
|
374
|
+
!partialAcceptableModes.includes(artifactType!),
|
|
375
|
+
`artifact-driven → "${artifactType}" is NOT in partialAcceptableModes`,
|
|
376
|
+
);
|
|
377
|
+
assert.ok(
|
|
378
|
+
!partialAcceptableModes.includes(browserType!),
|
|
379
|
+
`browser-executable → "${browserType}" is NOT in partialAcceptableModes`,
|
|
380
|
+
);
|
|
381
|
+
assert.ok(
|
|
382
|
+
!partialAcceptableModes.includes(runtimeExecType!),
|
|
383
|
+
`runtime-executable → "${runtimeExecType}" is NOT in partialAcceptableModes`,
|
|
384
|
+
);
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
test('(p) run-uat prompt allows PASS when human-only checks remain as NEEDS-HUMAN', () => {
|
|
388
|
+
const promptResult = loadPromptFromWorktree('run-uat', {
|
|
389
|
+
workingDirectory: '/tmp/test-project',
|
|
390
|
+
milestoneId: 'M001',
|
|
391
|
+
sliceId: 'S01',
|
|
392
|
+
uatPath: '.gsd/milestones/M001/slices/S01/S01-UAT.md',
|
|
393
|
+
uatResultPath: '.gsd/milestones/M001/slices/S01/S01-UAT-RESULT.md',
|
|
394
|
+
uatType: 'mixed',
|
|
395
|
+
inlinedContext: '<!-- no context -->',
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
// PASS verdict should be usable when automatable checks pass (even with NEEDS-HUMAN remaining)
|
|
399
|
+
assert.ok(
|
|
400
|
+
/PASS.*automatable checks passed/i.test(promptResult),
|
|
401
|
+
'prompt defines PASS as valid when all automatable checks passed',
|
|
402
|
+
);
|
|
403
|
+
assert.ok(
|
|
404
|
+
/PARTIAL.*automatable checks.*(skipped|inconclusive)/i.test(promptResult),
|
|
405
|
+
'prompt reserves PARTIAL for when automatable checks themselves are inconclusive',
|
|
406
|
+
);
|
|
407
|
+
// human-experience mode should NOT force PARTIAL when automatable checks pass
|
|
408
|
+
assert.ok(
|
|
409
|
+
!promptResult.includes('use an overall verdict of `PARTIAL`'),
|
|
410
|
+
'prompt does not force PARTIAL verdict for human-experience mode',
|
|
411
|
+
);
|
|
412
|
+
});
|
|
413
|
+
|
|
346
414
|
test('(n) stale replay guard', async () => {
|
|
347
415
|
const base = createFixtureBase();
|
|
348
416
|
try {
|
|
@@ -846,3 +846,70 @@ test("GitService is rebuilt with originalBasePath after exitMilestone", () => {
|
|
|
846
846
|
|
|
847
847
|
assert.equal(gitServiceBasePath, "/project"); // project root, not worktree
|
|
848
848
|
});
|
|
849
|
+
|
|
850
|
+
// ─── Isolation Degradation Tests (#2483) ──────────────────────────────────
|
|
851
|
+
|
|
852
|
+
test("enterMilestone sets isolationDegraded when worktree creation throws (#2483)", () => {
|
|
853
|
+
const s = makeSession();
|
|
854
|
+
const deps = makeDeps({
|
|
855
|
+
getAutoWorktreePath: () => null,
|
|
856
|
+
createAutoWorktree: () => {
|
|
857
|
+
throw new Error("empty repo");
|
|
858
|
+
},
|
|
859
|
+
});
|
|
860
|
+
const ctx = makeNotifyCtx();
|
|
861
|
+
const resolver = new WorktreeResolver(s, deps);
|
|
862
|
+
|
|
863
|
+
resolver.enterMilestone("M001", ctx);
|
|
864
|
+
|
|
865
|
+
assert.equal(s.isolationDegraded, true);
|
|
866
|
+
assert.equal(s.basePath, "/project"); // unchanged — error recovery
|
|
867
|
+
});
|
|
868
|
+
|
|
869
|
+
test("enterMilestone is no-op when isolationDegraded is true (#2483)", () => {
|
|
870
|
+
const s = makeSession();
|
|
871
|
+
s.isolationDegraded = true;
|
|
872
|
+
const deps = makeDeps();
|
|
873
|
+
const ctx = makeNotifyCtx();
|
|
874
|
+
const resolver = new WorktreeResolver(s, deps);
|
|
875
|
+
|
|
876
|
+
resolver.enterMilestone("M001", ctx);
|
|
877
|
+
|
|
878
|
+
assert.equal(s.basePath, "/project"); // unchanged
|
|
879
|
+
assert.equal(findCalls(deps.calls, "createAutoWorktree").length, 0);
|
|
880
|
+
assert.equal(findCalls(deps.calls, "enterAutoWorktree").length, 0);
|
|
881
|
+
assert.equal(findCalls(deps.calls, "shouldUseWorktreeIsolation").length, 0);
|
|
882
|
+
});
|
|
883
|
+
|
|
884
|
+
test("mergeAndExit is no-op when isolationDegraded is true (#2483)", () => {
|
|
885
|
+
const s = makeSession({
|
|
886
|
+
basePath: "/project",
|
|
887
|
+
originalBasePath: "/project",
|
|
888
|
+
});
|
|
889
|
+
s.isolationDegraded = true;
|
|
890
|
+
const deps = makeDeps({
|
|
891
|
+
getIsolationMode: () => "worktree",
|
|
892
|
+
});
|
|
893
|
+
const ctx = makeNotifyCtx();
|
|
894
|
+
const resolver = new WorktreeResolver(s, deps);
|
|
895
|
+
|
|
896
|
+
resolver.mergeAndExit("M001", ctx);
|
|
897
|
+
|
|
898
|
+
assert.equal(findCalls(deps.calls, "mergeMilestoneToMain").length, 0);
|
|
899
|
+
assert.equal(findCalls(deps.calls, "teardownAutoWorktree").length, 0);
|
|
900
|
+
assert.equal(findCalls(deps.calls, "getIsolationMode").length, 0);
|
|
901
|
+
assert.ok(
|
|
902
|
+
ctx.messages.some(
|
|
903
|
+
(m) => m.level === "info" && m.msg.includes("isolation was degraded"),
|
|
904
|
+
),
|
|
905
|
+
);
|
|
906
|
+
});
|
|
907
|
+
|
|
908
|
+
test("isolationDegraded is reset by session.reset() (#2483)", () => {
|
|
909
|
+
const s = new AutoSession();
|
|
910
|
+
s.isolationDegraded = true;
|
|
911
|
+
|
|
912
|
+
s.reset();
|
|
913
|
+
|
|
914
|
+
assert.equal(s.isolationDegraded, false);
|
|
915
|
+
});
|
|
@@ -661,7 +661,7 @@ async function handleMerge(
|
|
|
661
661
|
// --- Deterministic merge path (preferred) ---
|
|
662
662
|
// Try a direct squash-merge first. Only fall back to LLM on conflict.
|
|
663
663
|
const commitType = inferCommitType(name);
|
|
664
|
-
const commitMessage = `${commitType}
|
|
664
|
+
const commitMessage = `${commitType}: merge worktree ${name}\n\nGSD-Worktree: ${name}`;
|
|
665
665
|
|
|
666
666
|
// Reconcile worktree DB into main DB before squash merge
|
|
667
667
|
const wtDbPath = join(worktreePath(basePath, name), ".gsd", "gsd.db");
|
|
@@ -150,6 +150,18 @@ export class WorktreeResolver {
|
|
|
150
150
|
*/
|
|
151
151
|
enterMilestone(milestoneId: string, ctx: NotifyCtx): void {
|
|
152
152
|
this.validateMilestoneId(milestoneId);
|
|
153
|
+
|
|
154
|
+
// If worktree creation failed earlier this session, skip all future attempts
|
|
155
|
+
if (this.s.isolationDegraded) {
|
|
156
|
+
debugLog("WorktreeResolver", {
|
|
157
|
+
action: "enterMilestone",
|
|
158
|
+
milestoneId,
|
|
159
|
+
skipped: true,
|
|
160
|
+
reason: "isolation-degraded",
|
|
161
|
+
});
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
153
165
|
if (!this.deps.shouldUseWorktreeIsolation()) {
|
|
154
166
|
debugLog("WorktreeResolver", {
|
|
155
167
|
action: "enterMilestone",
|
|
@@ -220,6 +232,9 @@ export class WorktreeResolver {
|
|
|
220
232
|
`Auto-worktree creation for ${milestoneId} failed: ${msg}. Continuing in project root.`,
|
|
221
233
|
"warning",
|
|
222
234
|
);
|
|
235
|
+
// Degrade isolation for the rest of this session so mergeAndExit
|
|
236
|
+
// doesn't try to merge a nonexistent worktree branch (#2483)
|
|
237
|
+
this.s.isolationDegraded = true;
|
|
223
238
|
// Do NOT update s.basePath — stay in project root
|
|
224
239
|
}
|
|
225
240
|
}
|
|
@@ -304,6 +319,22 @@ export class WorktreeResolver {
|
|
|
304
319
|
*/
|
|
305
320
|
mergeAndExit(milestoneId: string, ctx: NotifyCtx): void {
|
|
306
321
|
this.validateMilestoneId(milestoneId);
|
|
322
|
+
|
|
323
|
+
// If worktree creation failed earlier, skip merge — work is on current branch (#2483)
|
|
324
|
+
if (this.s.isolationDegraded) {
|
|
325
|
+
debugLog("WorktreeResolver", {
|
|
326
|
+
action: "mergeAndExit",
|
|
327
|
+
milestoneId,
|
|
328
|
+
skipped: true,
|
|
329
|
+
reason: "isolation-degraded",
|
|
330
|
+
});
|
|
331
|
+
ctx.notify(
|
|
332
|
+
`Skipping worktree merge for ${milestoneId} — isolation was degraded (worktree creation failed earlier). Work is on the current branch.`,
|
|
333
|
+
"info",
|
|
334
|
+
);
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
|
|
307
338
|
const mode = this.deps.getIsolationMode();
|
|
308
339
|
debugLog("WorktreeResolver", {
|
|
309
340
|
action: "mergeAndExit",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[8974],{5214:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"workAsyncStorage",{enumerable:!0,get:function(){return r.workAsyncStorageInstance}});let r=n(17828)},15726:(e,t,n)=>{Promise.resolve().then(n.bind(n,66919))},17828:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"workAsyncStorageInstance",{enumerable:!0,get:function(){return r}});let r=(0,n(64054).createAsyncLocalStorage)()},21957:(e,t,n)=>{"use strict";function r({moduleIds:e}){return null}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"PreloadChunks",{enumerable:!0,get:function(){return r}}),n(95155),n(47650),n(5214),n(2451),n(53887)},37206:(e,t,n)=>{"use strict";n.d(t,{default:()=>u.a});var r=n(75707),u=n.n(r)},41112:(e,t,n)=>{"use strict";function r({reason:e,children:t}){return t}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"BailoutToCSR",{enumerable:!0,get:function(){return r}}),n(1980)},64054:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n={bindSnapshot:function(){return s},createAsyncLocalStorage:function(){return a},createSnapshot:function(){return i}};for(var r in n)Object.defineProperty(t,r,{enumerable:!0,get:n[r]});let u=Object.defineProperty(Error("Invariant: AsyncLocalStorage accessed in runtime where it is not available"),"__NEXT_ERROR_CODE",{value:"E504",enumerable:!1,configurable:!0});class l{disable(){throw u}getStore(){}run(){throw u}exit(){throw u}enterWith(){throw u}static bind(e){return e}}let o="u">typeof globalThis&&globalThis.AsyncLocalStorage;function a(){return o?new o:new l}function s(e){return o?o.bind(e):l.bind(e)}function i(){return o?o.snapshot():function(e,...t){return e(...t)}}},66919:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>l});var r=n(95155);let u=(0,n(37206).default)(()=>Promise.all([n.e(1838),n.e(6079),n.e(4986),n.e(485),n.e(4024)]).then(n.bind(n,4024)).then(e=>e.GSDAppShell),{loadableGenerated:{webpack:()=>[4024]},ssr:!1,loading:()=>(0,r.jsx)("div",{className:"flex h-screen items-center justify-center bg-background text-sm text-muted-foreground",children:"Loading workspace…"})});function l(){return(0,r.jsx)(u,{})}},68635:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return s}});let r=n(95155),u=n(12115),l=n(41112);function o(e){return{default:e&&"default"in e?e.default:e}}n(21957);let a={loader:()=>Promise.resolve(o(()=>null)),loading:null,ssr:!0},s=function(e){let t={...a,...e},n=(0,u.lazy)(()=>t.loader().then(o)),s=t.loading;function i(e){let o=s?(0,r.jsx)(s,{isLoading:!0,pastDelay:!0,error:null}):null,a=!t.ssr||!!t.loading,i=a?u.Suspense:u.Fragment,c=t.ssr?(0,r.jsxs)(r.Fragment,{children:[null,(0,r.jsx)(n,{...e})]}):(0,r.jsx)(l.BailoutToCSR,{reason:"next/dynamic",children:(0,r.jsx)(n,{...e})});return(0,r.jsx)(i,{...a?{fallback:o}:{},children:c})}return i.displayName="LoadableComponent",i}},75707:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return u}});let r=n(73623)._(n(68635));function u(e,t){let n={};"function"==typeof e&&(n.loader=e);let u={...n,...t};return(0,r.default)({...u,modules:u.loadableGenerated?.modules})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=15726)),_N_E=e.O()}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[7358],{2852:(e,s,n)=>{Promise.resolve().then(n.t.bind(n,27123,23)),Promise.resolve().then(n.t.bind(n,61304,23)),Promise.resolve().then(n.t.bind(n,78616,23)),Promise.resolve().then(n.t.bind(n,64777,23)),Promise.resolve().then(n.t.bind(n,57121,23)),Promise.resolve().then(n.t.bind(n,74581,23)),Promise.resolve().then(n.t.bind(n,90484,23)),Promise.resolve().then(n.bind(n,86869))},19393:()=>{}},e=>{var s=s=>e(e.s=s);e.O(0,[8441,3794],()=>(s(83861),s(2852))),_N_E=e.O()}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[9337],{52560:(e,s,_)=>{Promise.resolve().then(_.t.bind(_,27123,23))}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=52560)),_N_E=e.O()}]);
|
|
File without changes
|
|
File without changes
|