@opengsd/gsd-pi 1.1.1-dev.75048e7 → 1.1.1-dev.9f86580
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/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +18 -2
- package/dist/resources/extensions/browser-tools/engine/selection.js +1 -1
- package/dist/resources/extensions/browser-tools/extension-manifest.json +1 -1
- package/dist/resources/extensions/browser-tools/index.js +29 -2
- package/dist/resources/extensions/browser-tools/web-app-detect.js +52 -0
- package/dist/resources/extensions/gsd/auto/phases.js +45 -3
- package/dist/resources/extensions/gsd/auto/session.js +2 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +10 -2
- package/dist/resources/extensions/gsd/auto-model-selection.js +26 -0
- package/dist/resources/extensions/gsd/auto-timers.js +24 -10
- package/dist/resources/extensions/gsd/auto.js +26 -4
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +29 -21
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +1 -1
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +10 -0
- package/dist/resources/extensions/gsd/commands-mcp-status.js +1 -1
- package/dist/resources/extensions/gsd/config-overlay.js +1 -0
- package/dist/resources/extensions/gsd/context-masker.js +129 -5
- package/dist/resources/extensions/gsd/guided-flow.js +4 -1
- package/dist/resources/extensions/gsd/planner-handoff.js +98 -0
- package/dist/resources/extensions/gsd/preferences-models.js +1 -0
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +2 -2
- package/dist/resources/extensions/gsd/prompts/system.md +1 -1
- package/dist/resources/extensions/gsd/skill-manifest.js +12 -0
- package/dist/resources/extensions/gsd/tool-contract.js +1 -1
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +19 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +28 -1
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +32 -4
- package/dist/resources/extensions/gsd/unit-tool-contracts.js +38 -14
- package/dist/resources/extensions/gsd/workflow-mcp.js +2 -3
- package/dist/resources/extensions/gsd/worktree-manager.js +26 -0
- package/dist/resources/extensions/gsd/worktree-reentry.js +96 -0
- package/dist/resources/extensions/shared/gsd-browser-cli.js +6 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- 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.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- 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 +1 -1
- 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/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +158 -2
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +149 -9
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.js +8 -1
- package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/scripts/install/handoff.js +16 -3
- package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +21 -2
- package/src/resources/extensions/browser-tools/engine/selection.ts +1 -1
- package/src/resources/extensions/browser-tools/extension-manifest.json +1 -1
- package/src/resources/extensions/browser-tools/index.ts +36 -5
- package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +2 -2
- package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +37 -0
- package/src/resources/extensions/browser-tools/tests/web-app-detect.test.mjs +68 -0
- package/src/resources/extensions/browser-tools/web-app-detect.ts +63 -0
- package/src/resources/extensions/gsd/auto/phases.ts +48 -6
- package/src/resources/extensions/gsd/auto/session.ts +2 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +34 -2
- package/src/resources/extensions/gsd/auto-model-selection.ts +26 -0
- package/src/resources/extensions/gsd/auto-timers.ts +25 -9
- package/src/resources/extensions/gsd/auto.ts +28 -4
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +40 -21
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +1 -1
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -0
- package/src/resources/extensions/gsd/commands-mcp-status.ts +1 -1
- package/src/resources/extensions/gsd/config-overlay.ts +1 -0
- package/src/resources/extensions/gsd/context-masker.ts +152 -5
- package/src/resources/extensions/gsd/guided-flow.ts +4 -1
- package/src/resources/extensions/gsd/planner-handoff.ts +149 -0
- package/src/resources/extensions/gsd/preferences-models.ts +1 -0
- package/src/resources/extensions/gsd/preferences-types.ts +8 -0
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +2 -2
- package/src/resources/extensions/gsd/prompts/system.md +1 -1
- package/src/resources/extensions/gsd/skill-manifest.ts +12 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +66 -4
- package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +4 -0
- package/src/resources/extensions/gsd/tests/bundled-skill-triggers.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +118 -0
- package/src/resources/extensions/gsd/tests/context-masker.test.ts +56 -1
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/interrupted-session-auto.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/planner-handoff.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +113 -1
- package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +77 -10
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +131 -2
- package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +102 -0
- package/src/resources/extensions/gsd/tool-contract.ts +1 -1
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +21 -2
- package/src/resources/extensions/gsd/tools/complete-slice.ts +29 -1
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +46 -4
- package/src/resources/extensions/gsd/unit-tool-contracts.ts +38 -14
- package/src/resources/extensions/gsd/workflow-mcp.ts +2 -3
- package/src/resources/extensions/gsd/worktree-manager.ts +32 -0
- package/src/resources/extensions/gsd/worktree-reentry.ts +103 -0
- package/src/resources/extensions/shared/gsd-browser-cli.ts +6 -0
- /package/dist/web/standalone/.next/static/{h4TGni4xJzlZjGkxaT6uU → zzYMrKpPGfRQRxSFO32Jr}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{h4TGni4xJzlZjGkxaT6uU → zzYMrKpPGfRQRxSFO32Jr}/_ssgManifest.js +0 -0
|
@@ -52,8 +52,14 @@ export const UNIT_TOOL_CONTRACTS: Record<string, UnitToolSurfaceContract> = {
|
|
|
52
52
|
requiredWorkflowTools: ["gsd_summary_save"],
|
|
53
53
|
},
|
|
54
54
|
"plan-milestone": {
|
|
55
|
-
allowedGsdTools: [
|
|
56
|
-
|
|
55
|
+
allowedGsdTools: [
|
|
56
|
+
"gsd_milestone_status",
|
|
57
|
+
"gsd_plan_milestone",
|
|
58
|
+
"gsd_plan_slice",
|
|
59
|
+
"gsd_decision_save",
|
|
60
|
+
"gsd_requirement_update",
|
|
61
|
+
],
|
|
62
|
+
requiredWorkflowTools: ["gsd_milestone_status", "gsd_plan_milestone", "gsd_plan_slice"],
|
|
57
63
|
},
|
|
58
64
|
"discuss-milestone": {
|
|
59
65
|
allowedGsdTools: [
|
|
@@ -77,27 +83,38 @@ export const UNIT_TOOL_CONTRACTS: Record<string, UnitToolSurfaceContract> = {
|
|
|
77
83
|
requiredWorkflowTools: ["gsd_summary_save"],
|
|
78
84
|
},
|
|
79
85
|
"validate-milestone": {
|
|
80
|
-
allowedGsdTools: ["gsd_validate_milestone", "gsd_reassess_roadmap", "subagent"],
|
|
86
|
+
allowedGsdTools: ["gsd_milestone_status", "gsd_validate_milestone", "gsd_reassess_roadmap", "subagent"],
|
|
81
87
|
requiredWorkflowTools: ["gsd_milestone_status", "gsd_validate_milestone", "gsd_reassess_roadmap"],
|
|
82
88
|
},
|
|
83
89
|
"complete-milestone": {
|
|
84
|
-
allowedGsdTools: [
|
|
85
|
-
|
|
90
|
+
allowedGsdTools: [
|
|
91
|
+
"gsd_milestone_status",
|
|
92
|
+
"gsd_requirement_update",
|
|
93
|
+
"gsd_summary_save",
|
|
94
|
+
"gsd_complete_milestone",
|
|
95
|
+
"subagent",
|
|
96
|
+
],
|
|
97
|
+
requiredWorkflowTools: [
|
|
98
|
+
"gsd_milestone_status",
|
|
99
|
+
"gsd_requirement_update",
|
|
100
|
+
"gsd_summary_save",
|
|
101
|
+
"gsd_complete_milestone",
|
|
102
|
+
],
|
|
86
103
|
},
|
|
87
104
|
"research-slice": {
|
|
88
105
|
allowedGsdTools: ["gsd_summary_save", "gsd_decision_save"],
|
|
89
106
|
requiredWorkflowTools: ["gsd_summary_save"],
|
|
90
107
|
},
|
|
91
108
|
"plan-slice": {
|
|
92
|
-
allowedGsdTools: ["gsd_plan_slice", "
|
|
93
|
-
requiredWorkflowTools: ["gsd_plan_slice"],
|
|
109
|
+
allowedGsdTools: ["gsd_plan_slice", "gsd_reassess_roadmap", "gsd_decision_save"],
|
|
110
|
+
requiredWorkflowTools: ["gsd_plan_slice", "gsd_reassess_roadmap"],
|
|
94
111
|
},
|
|
95
112
|
"refine-slice": {
|
|
96
|
-
allowedGsdTools: ["gsd_plan_slice", "
|
|
97
|
-
requiredWorkflowTools: [],
|
|
113
|
+
allowedGsdTools: ["gsd_plan_slice", "gsd_decision_save"],
|
|
114
|
+
requiredWorkflowTools: ["gsd_plan_slice"],
|
|
98
115
|
},
|
|
99
116
|
"replan-slice": {
|
|
100
|
-
allowedGsdTools: ["gsd_replan_slice", "
|
|
117
|
+
allowedGsdTools: ["gsd_replan_slice", "gsd_decision_save"],
|
|
101
118
|
requiredWorkflowTools: ["gsd_replan_slice"],
|
|
102
119
|
},
|
|
103
120
|
"complete-slice": {
|
|
@@ -107,15 +124,22 @@ export const UNIT_TOOL_CONTRACTS: Record<string, UnitToolSurfaceContract> = {
|
|
|
107
124
|
"gsd_replan_slice",
|
|
108
125
|
"gsd_decision_save",
|
|
109
126
|
"gsd_requirement_update",
|
|
127
|
+
"gsd_summary_save",
|
|
110
128
|
"subagent",
|
|
111
129
|
],
|
|
112
|
-
requiredWorkflowTools: [
|
|
130
|
+
requiredWorkflowTools: [
|
|
131
|
+
"gsd_slice_complete",
|
|
132
|
+
"gsd_task_reopen",
|
|
133
|
+
"gsd_replan_slice",
|
|
134
|
+
"gsd_requirement_update",
|
|
135
|
+
"gsd_summary_save",
|
|
136
|
+
],
|
|
113
137
|
forbiddenGsdTools: {
|
|
114
138
|
gsd_uat_result_save: "Run UAT owns persisted UAT Assessment.",
|
|
115
139
|
},
|
|
116
140
|
},
|
|
117
141
|
"reassess-roadmap": {
|
|
118
|
-
allowedGsdTools: ["gsd_reassess_roadmap"],
|
|
142
|
+
allowedGsdTools: ["gsd_milestone_status", "gsd_reassess_roadmap"],
|
|
119
143
|
requiredWorkflowTools: ["gsd_milestone_status", "gsd_reassess_roadmap"],
|
|
120
144
|
},
|
|
121
145
|
"execute-task": {
|
|
@@ -127,8 +151,8 @@ export const UNIT_TOOL_CONTRACTS: Record<string, UnitToolSurfaceContract> = {
|
|
|
127
151
|
requiredWorkflowTools: ["gsd_task_complete"],
|
|
128
152
|
},
|
|
129
153
|
"reactive-execute": {
|
|
130
|
-
allowedGsdTools: ["gsd_task_complete", "gsd_decision_save"],
|
|
131
|
-
requiredWorkflowTools: ["gsd_task_complete"],
|
|
154
|
+
allowedGsdTools: ["gsd_task_complete", "gsd_summary_save", "gsd_decision_save"],
|
|
155
|
+
requiredWorkflowTools: ["gsd_task_complete", "gsd_summary_save"],
|
|
132
156
|
},
|
|
133
157
|
"run-uat": {
|
|
134
158
|
allowedGsdTools: [...RUN_UAT_WORKFLOW_TOOL_NAMES, "subagent"],
|
|
@@ -487,10 +487,9 @@ export function getWorkflowTransportSupportError(
|
|
|
487
487
|
}
|
|
488
488
|
|
|
489
489
|
const uniqueRequired = [...new Set(requiredTools)];
|
|
490
|
-
const piRuntimeRequired = uniqueRequired.filter((tool) => !MCP_WORKFLOW_TOOL_SURFACE.has(tool));
|
|
491
490
|
const missing = (options.activeTools && options.activeTools.length > 0)
|
|
492
|
-
?
|
|
493
|
-
:
|
|
491
|
+
? uniqueRequired.filter((tool) => !hasRequiredTool(tool, options.activeTools!))
|
|
492
|
+
: uniqueRequired.filter((tool) => !MCP_WORKFLOW_TOOL_SURFACE.has(tool));
|
|
494
493
|
if (missing.length === 0) return null;
|
|
495
494
|
|
|
496
495
|
if (options.activeTools && options.activeTools.length > 0) {
|
|
@@ -259,6 +259,38 @@ export function resolveCanonicalMilestoneRoot(
|
|
|
259
259
|
return wtPath;
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
+
/**
|
|
263
|
+
* Build human-facing guidance for manually validating a milestone's work.
|
|
264
|
+
*
|
|
265
|
+
* When a milestone runs in a git worktree, its checkout lives under the hidden
|
|
266
|
+
* `.gsd/worktrees/<MID>/` path that a human can't easily discover. The UAT
|
|
267
|
+
* pause/handoff and the saved assessment use this to tell the human exactly
|
|
268
|
+
* where to `cd` to run or inspect the app before signing off on NEEDS-HUMAN
|
|
269
|
+
* checks, rather than leaving them to hunt for a buried path.
|
|
270
|
+
*
|
|
271
|
+
* Returns null when no milestone id is available.
|
|
272
|
+
*/
|
|
273
|
+
export function buildManualValidationGuidance(
|
|
274
|
+
basePath: string,
|
|
275
|
+
milestoneId: string,
|
|
276
|
+
opts: { uatPath?: string } = {},
|
|
277
|
+
): string | null {
|
|
278
|
+
if (!milestoneId) return null;
|
|
279
|
+
const validationRoot = resolveCanonicalMilestoneRoot(basePath, milestoneId);
|
|
280
|
+
const inWorktree = validationRoot.includes(`${sep}.gsd${sep}worktrees${sep}`);
|
|
281
|
+
const lines: string[] = [`Validate the work here: ${validationRoot}`];
|
|
282
|
+
if (inWorktree) {
|
|
283
|
+
lines.push(
|
|
284
|
+
"This milestone runs in a git worktree, so the code lives under the hidden " +
|
|
285
|
+
`\`.gsd/worktrees/\` path. Open it with: cd "${validationRoot}"`,
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
if (opts.uatPath) {
|
|
289
|
+
lines.push(`Follow the UAT checklist at: ${opts.uatPath}`);
|
|
290
|
+
}
|
|
291
|
+
return lines.join("\n");
|
|
292
|
+
}
|
|
293
|
+
|
|
262
294
|
// ─── Core Operations ───────────────────────────────────────────────────────
|
|
263
295
|
|
|
264
296
|
/**
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Deterministically re-enter the active milestone's worktree on a
|
|
3
|
+
// cold start (after /quit + relaunch). Without this, Claude Code relaunches with
|
|
4
|
+
// cwd at the project root, and a bare /gsd leaves the agent there — forcing it to
|
|
5
|
+
// search the filesystem ("git worktree list", branch sniffing) to find its way
|
|
6
|
+
// back into the worktree. The worktree path is fully derivable from state, so we
|
|
7
|
+
// resolve and chdir into it directly instead.
|
|
8
|
+
|
|
9
|
+
import { readdirSync } from "node:fs";
|
|
10
|
+
|
|
11
|
+
import { enterAutoWorktree, getAutoWorktreePath } from "./auto-worktree.js";
|
|
12
|
+
import { getIsolationMode } from "./preferences.js";
|
|
13
|
+
import { worktreesDir } from "./worktree-manager.js";
|
|
14
|
+
import { isGsdWorktreePath, resolveWorktreeProjectRoot } from "./worktree-root.js";
|
|
15
|
+
|
|
16
|
+
interface LiveWorktree {
|
|
17
|
+
id: string;
|
|
18
|
+
path: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Enumerate the live (valid git) auto-worktrees under <projectRoot>/.gsd/worktrees/.
|
|
23
|
+
* Reuses getAutoWorktreePath's validation so stray directories are ignored.
|
|
24
|
+
*/
|
|
25
|
+
function liveMilestoneWorktrees(projectRoot: string): LiveWorktree[] {
|
|
26
|
+
let names: string[];
|
|
27
|
+
try {
|
|
28
|
+
names = readdirSync(worktreesDir(projectRoot));
|
|
29
|
+
} catch {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
const live: LiveWorktree[] = [];
|
|
33
|
+
for (const id of names) {
|
|
34
|
+
const path = getAutoWorktreePath(projectRoot, id);
|
|
35
|
+
if (path) live.push({ id, path });
|
|
36
|
+
}
|
|
37
|
+
return live;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* If we're sitting at the project root with worktree isolation enabled and the
|
|
42
|
+
* active milestone has a live worktree, chdir into it. No-op when already inside
|
|
43
|
+
* a worktree, when isolation is off, or when the target is ambiguous.
|
|
44
|
+
*
|
|
45
|
+
* Single live worktree → enter it (covers the common case without deriveState).
|
|
46
|
+
* Multiple live worktrees → disambiguate by the active milestone from state;
|
|
47
|
+
* if that can't be resolved unambiguously, do nothing.
|
|
48
|
+
*
|
|
49
|
+
* Best-effort: any failure resolves to a no-op so it can never block startup.
|
|
50
|
+
*
|
|
51
|
+
* @returns the worktree path entered, or null when nothing was done.
|
|
52
|
+
*/
|
|
53
|
+
export async function reenterActiveWorktreeIfNeeded(
|
|
54
|
+
basePath: string,
|
|
55
|
+
opts: { notify?: (message: string) => void } = {},
|
|
56
|
+
): Promise<string | null> {
|
|
57
|
+
let projectRoot: string;
|
|
58
|
+
try {
|
|
59
|
+
projectRoot = resolveWorktreeProjectRoot(basePath);
|
|
60
|
+
} catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Only worktree-isolation projects have worktrees to re-enter.
|
|
65
|
+
if (getIsolationMode(projectRoot) !== "worktree") return null;
|
|
66
|
+
|
|
67
|
+
// Already inside a worktree (warm session, or auto-mode already entered) —
|
|
68
|
+
// nothing to do.
|
|
69
|
+
let cwd: string;
|
|
70
|
+
try {
|
|
71
|
+
cwd = process.cwd();
|
|
72
|
+
} catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
if (isGsdWorktreePath(cwd)) return null;
|
|
76
|
+
|
|
77
|
+
const live = liveMilestoneWorktrees(projectRoot);
|
|
78
|
+
if (live.length === 0) return null;
|
|
79
|
+
|
|
80
|
+
let target: LiveWorktree | null = live.length === 1 ? live[0]! : null;
|
|
81
|
+
if (!target) {
|
|
82
|
+
// Multiple live worktrees — disambiguate by the active milestone.
|
|
83
|
+
try {
|
|
84
|
+
const { deriveState } = await import("./state.js");
|
|
85
|
+
const state = await deriveState(projectRoot);
|
|
86
|
+
const activeId = state.activeMilestone?.id;
|
|
87
|
+
target = activeId ? live.find((w) => w.id === activeId) ?? null : null;
|
|
88
|
+
} catch {
|
|
89
|
+
target = null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (!target) return null;
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const entered = enterAutoWorktree(projectRoot, target.id);
|
|
96
|
+
opts.notify?.(`Resumed in worktree for ${target.id}.`);
|
|
97
|
+
return entered;
|
|
98
|
+
} catch {
|
|
99
|
+
// Worktree vanished or chdir failed — leave cwd as-is, caller falls back to
|
|
100
|
+
// the project root.
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -140,6 +140,10 @@ export function resolveGsdBrowserMcpLaunchConfig(
|
|
|
140
140
|
: null;
|
|
141
141
|
const sessionName =
|
|
142
142
|
options.sessionName?.trim() || buildGsdBrowserSessionName(resolvedProjectRoot, options.sessionSuffix);
|
|
143
|
+
// Stable per-project identity key (no per-session suffix) so the browser
|
|
144
|
+
// profile/cookies persist across pi sessions for the same project. gsd-browser
|
|
145
|
+
// rejects --identity-scope unless --identity-key is also supplied.
|
|
146
|
+
const identityKey = env.GSD_BROWSER_IDENTITY_KEY?.trim() || buildGsdBrowserSessionName(resolvedProjectRoot);
|
|
143
147
|
const command =
|
|
144
148
|
explicitCommand
|
|
145
149
|
|| explicitCliPath
|
|
@@ -155,6 +159,8 @@ export function resolveGsdBrowserMcpLaunchConfig(
|
|
|
155
159
|
sessionName,
|
|
156
160
|
"--identity-scope",
|
|
157
161
|
"project",
|
|
162
|
+
"--identity-key",
|
|
163
|
+
identityKey,
|
|
158
164
|
"--identity-project",
|
|
159
165
|
resolvedProjectRoot,
|
|
160
166
|
];
|
|
File without changes
|
|
File without changes
|