gsd-pi 2.44.0-dev.8894d5b → 2.44.0-dev.8dd0d8e
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/activity-log.js +7 -0
- package/dist/resources/extensions/gsd/auto/infra-errors.js +3 -0
- package/dist/resources/extensions/gsd/auto/phases.js +37 -36
- package/dist/resources/extensions/gsd/auto-prompts.js +24 -1
- package/dist/resources/extensions/gsd/auto-start.js +21 -2
- package/dist/resources/extensions/gsd/auto-timers.js +57 -3
- package/dist/resources/extensions/gsd/auto-worktree-sync.js +4 -0
- package/dist/resources/extensions/gsd/auto-worktree.js +9 -6
- package/dist/resources/extensions/gsd/auto.js +30 -3
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +136 -0
- package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +2 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +10 -0
- package/dist/resources/extensions/gsd/commands-mcp-status.js +187 -0
- package/dist/resources/extensions/gsd/db-writer.js +34 -16
- package/dist/resources/extensions/gsd/doctor.js +8 -0
- package/dist/resources/extensions/gsd/git-service.js +8 -3
- package/dist/resources/extensions/gsd/gsd-db.js +12 -1
- package/dist/resources/extensions/gsd/markdown-renderer.js +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -4
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +3 -14
- package/dist/resources/extensions/gsd/prompts/rethink.md +78 -0
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
- package/dist/resources/extensions/gsd/provider-error-pause.js +7 -0
- package/dist/resources/extensions/gsd/repo-identity.js +45 -7
- package/dist/resources/extensions/gsd/rethink.js +115 -0
- package/dist/resources/extensions/gsd/state.js +22 -1
- package/dist/resources/extensions/gsd/tools/plan-slice.js +1 -0
- package/dist/resources/extensions/gsd/tools/plan-task.js +1 -0
- package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -0
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +88 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +32 -2
- package/dist/resources/extensions/gsd/worktree-resolver.js +6 -0
- package/dist/resources/extensions/mcp-client/index.js +14 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +20 -20
- 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/react-loadable-manifest.json +2 -2
- 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 +1 -1
- 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 +2 -2
- 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 +2 -2
- 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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.js +1 -1
- 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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.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_client-reference-manifest.js +1 -1
- 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_client-reference-manifest.js +1 -1
- 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_client-reference-manifest.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_client-reference-manifest.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_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 +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/page.js +1 -1
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +20 -20
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +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/4024.11ca5c01938e5948.js +9 -0
- package/dist/web/standalone/.next/static/chunks/{3721.bf31263de6d5fa46.js → 485.243af25f0cdf50d6.js} +2 -2
- package/dist/web/standalone/.next/static/chunks/app/{page-b9367c5ae13b99c6.js → page-6654a8cca61a3d1c.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/webpack-0a4cd455ec4197d2.js +1 -0
- package/dist/web/standalone/.next/static/css/dd4ae3f58ac9b600.css +1 -0
- package/package.json +1 -1
- package/packages/native/dist/stream-process/index.js +2 -2
- package/packages/native/src/__tests__/stream-process.test.mjs +34 -0
- package/packages/native/src/stream-process/index.ts +2 -2
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +3 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +15 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/local-model-check.d.ts +15 -0
- package/packages/pi-coding-agent/dist/core/local-model-check.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/local-model-check.js +41 -0
- package/packages/pi-coding-agent/dist/core/local-model-check.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +20 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +6 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/main.js +17 -0
- package/packages/pi-coding-agent/dist/main.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js +32 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +3 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +8 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +12 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts +15 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js +40 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +4 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +5 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +13 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +17 -8
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +7 -3
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/src/core/auth-storage.ts +15 -1
- package/packages/pi-coding-agent/src/core/local-model-check.ts +45 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +21 -1
- package/packages/pi-coding-agent/src/core/settings-manager.ts +9 -0
- package/packages/pi-coding-agent/src/main.ts +19 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/timestamp.test.ts +38 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +10 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/timestamp.ts +48 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +3 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +18 -3
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +16 -7
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +8 -1
- package/src/resources/extensions/gsd/activity-log.ts +1 -0
- package/src/resources/extensions/gsd/auto/infra-errors.ts +3 -0
- package/src/resources/extensions/gsd/auto/phases.ts +46 -48
- package/src/resources/extensions/gsd/auto-prompts.ts +24 -1
- package/src/resources/extensions/gsd/auto-start.ts +25 -2
- package/src/resources/extensions/gsd/auto-timers.ts +64 -3
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +5 -0
- package/src/resources/extensions/gsd/auto-worktree.ts +9 -6
- package/src/resources/extensions/gsd/auto.ts +37 -3
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +129 -0
- package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +2 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +10 -0
- package/src/resources/extensions/gsd/commands-mcp-status.ts +247 -0
- package/src/resources/extensions/gsd/db-writer.ts +39 -17
- package/src/resources/extensions/gsd/doctor.ts +7 -1
- package/src/resources/extensions/gsd/git-service.ts +6 -2
- package/src/resources/extensions/gsd/gsd-db.ts +16 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +1 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -4
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
- package/src/resources/extensions/gsd/prompts/replan-slice.md +3 -14
- package/src/resources/extensions/gsd/prompts/rethink.md +78 -0
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
- package/src/resources/extensions/gsd/provider-error-pause.ts +9 -0
- package/src/resources/extensions/gsd/repo-identity.ts +46 -7
- package/src/resources/extensions/gsd/rethink.ts +154 -0
- package/src/resources/extensions/gsd/state.ts +22 -0
- package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +121 -0
- package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/infra-error.test.ts +20 -2
- package/src/resources/extensions/gsd/tests/inherited-repo-home-dir.test.ts +121 -0
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +11 -7
- package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +176 -0
- package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +65 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +2 -0
- package/src/resources/extensions/gsd/tools/replan-slice.ts +3 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +127 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +43 -2
- package/src/resources/extensions/gsd/worktree-resolver.ts +7 -0
- package/src/resources/extensions/mcp-client/index.ts +20 -0
- package/dist/web/standalone/.next/static/chunks/4024.0de81b543b28b9fe.js +0 -9
- package/dist/web/standalone/.next/static/chunks/webpack-9014b5adb127a98a.js +0 -1
- package/dist/web/standalone/.next/static/css/8a727f372cf53002.css +0 -1
- /package/dist/web/standalone/.next/static/{oZMtyM-zfu6Inx-S59cOl → enTIm32JJtw--VTtLPSC3}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{oZMtyM-zfu6Inx-S59cOl → enTIm32JJtw--VTtLPSC3}/_ssgManifest.js +0 -0
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
export function classifyProviderError(errorMsg) {
|
|
11
11
|
const isRateLimit = /rate.?limit|too many requests|429/i.test(errorMsg);
|
|
12
12
|
const isServerError = /internal server error|500|502|503|overloaded|server_error|api_error|service.?unavailable/i.test(errorMsg);
|
|
13
|
+
// Connection/process errors — transient, auto-resume after brief backoff (#2309).
|
|
14
|
+
// These indicate the process was killed, the connection was reset, or a network
|
|
15
|
+
// blip occurred. They are NOT permanent failures.
|
|
16
|
+
const isConnectionError = /terminated|connection.?reset|connection.?refused|other side closed|fetch failed|network.?(?:is\s+)?unavailable|ECONNREFUSED|ECONNRESET|EPIPE/i.test(errorMsg);
|
|
13
17
|
// Permanent errors — never auto-resume
|
|
14
18
|
const isPermanent = /auth|unauthorized|forbidden|invalid.*key|invalid.*api|billing|quota exceeded|account/i.test(errorMsg);
|
|
15
19
|
if (isPermanent && !isRateLimit) {
|
|
@@ -24,6 +28,9 @@ export function classifyProviderError(errorMsg) {
|
|
|
24
28
|
if (isServerError) {
|
|
25
29
|
return { isTransient: true, isRateLimit: false, suggestedDelayMs: 30_000 }; // 30s for server errors
|
|
26
30
|
}
|
|
31
|
+
if (isConnectionError) {
|
|
32
|
+
return { isTransient: true, isRateLimit: false, suggestedDelayMs: 15_000 }; // 15s for connection errors
|
|
33
|
+
}
|
|
27
34
|
// Unknown error — treat as permanent (user reviews)
|
|
28
35
|
return { isTransient: false, isRateLimit: false, suggestedDelayMs: 0 };
|
|
29
36
|
}
|
|
@@ -89,16 +89,17 @@ export function readRepoMeta(externalPath) {
|
|
|
89
89
|
* Returns true when ALL of:
|
|
90
90
|
* 1. basePath is inside a git repo (git rev-parse succeeds)
|
|
91
91
|
* 2. The resolved git root is a proper ancestor of basePath
|
|
92
|
-
* 3. There is no `.gsd` directory at the git root
|
|
93
|
-
* has not been
|
|
92
|
+
* 3. There is no *project* `.gsd` directory at the git root or any
|
|
93
|
+
* intermediate ancestor (the parent project has not been
|
|
94
|
+
* initialised with GSD)
|
|
94
95
|
*
|
|
95
96
|
* When true, the caller should run `git init` at basePath so that
|
|
96
97
|
* `repoIdentity()` produces a hash unique to this directory, preventing
|
|
97
98
|
* cross-project state leaks (#1639).
|
|
98
99
|
*
|
|
99
|
-
* When the git root already has `.gsd`, the directory is a
|
|
100
|
-
* subdirectory of an existing GSD project — `cd src/ && /gsd`
|
|
101
|
-
* still load the parent project's milestones.
|
|
100
|
+
* When the git root already has a project `.gsd`, the directory is a
|
|
101
|
+
* legitimate subdirectory of an existing GSD project — `cd src/ && /gsd`
|
|
102
|
+
* should still load the parent project's milestones.
|
|
102
103
|
*/
|
|
103
104
|
export function isInheritedRepo(basePath) {
|
|
104
105
|
try {
|
|
@@ -109,12 +110,12 @@ export function isInheritedRepo(basePath) {
|
|
|
109
110
|
return false; // basePath IS the root
|
|
110
111
|
// The git root is a proper ancestor. Check whether it already has .gsd
|
|
111
112
|
// (i.e. the parent project was initialised with GSD).
|
|
112
|
-
if (
|
|
113
|
+
if (isProjectGsd(join(root, ".gsd")))
|
|
113
114
|
return false;
|
|
114
115
|
// Also walk up from basePath to the git root checking for .gsd
|
|
115
116
|
let dir = normalizedBase;
|
|
116
117
|
while (dir !== normalizedRoot && dir !== dirname(dir)) {
|
|
117
|
-
if (
|
|
118
|
+
if (isProjectGsd(join(dir, ".gsd")))
|
|
118
119
|
return false;
|
|
119
120
|
dir = dirname(dir);
|
|
120
121
|
}
|
|
@@ -124,6 +125,43 @@ export function isInheritedRepo(basePath) {
|
|
|
124
125
|
return false;
|
|
125
126
|
}
|
|
126
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Distinguish a *project* `.gsd` from the global `~/.gsd` state directory.
|
|
130
|
+
*
|
|
131
|
+
* A project `.gsd` is either:
|
|
132
|
+
* - A symlink to an external state directory (normal post-migration layout)
|
|
133
|
+
* - A legacy real directory that is NOT the global GSD home
|
|
134
|
+
*
|
|
135
|
+
* When the user's home directory is itself a git repo (e.g. dotfile managers),
|
|
136
|
+
* `~/.gsd` exists but is the global state directory — not a project `.gsd`.
|
|
137
|
+
* Treating it as a project `.gsd` would cause isInheritedRepo() to wrongly
|
|
138
|
+
* conclude that subdirectories are part of the home "project" (#2393).
|
|
139
|
+
*/
|
|
140
|
+
function isProjectGsd(gsdPath) {
|
|
141
|
+
if (!existsSync(gsdPath))
|
|
142
|
+
return false;
|
|
143
|
+
try {
|
|
144
|
+
const stat = lstatSync(gsdPath);
|
|
145
|
+
// Symlinks are always project .gsd (created by ensureGsdSymlink).
|
|
146
|
+
if (stat.isSymbolicLink())
|
|
147
|
+
return true;
|
|
148
|
+
// For real directories, check that this isn't the global GSD home.
|
|
149
|
+
// Recompute gsdHome dynamically so env overrides (GSD_HOME) are
|
|
150
|
+
// picked up at call time, not just at module load time.
|
|
151
|
+
if (stat.isDirectory()) {
|
|
152
|
+
const currentGsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
153
|
+
const normalizedGsdPath = canonicalizeExistingPath(gsdPath);
|
|
154
|
+
const normalizedGsdHome = canonicalizeExistingPath(currentGsdHome);
|
|
155
|
+
if (normalizedGsdPath === normalizedGsdHome)
|
|
156
|
+
return false;
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
// lstat failed — treat as no .gsd present
|
|
162
|
+
}
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
127
165
|
// ─── Repo Identity ──────────────────────────────────────────────────────────
|
|
128
166
|
/**
|
|
129
167
|
* Get the git remote URL for "origin", or "" if no remote is configured.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GSD Rethink — Conversational project reorganization.
|
|
3
|
+
*
|
|
4
|
+
* Collects a snapshot of all milestones (status, dependencies, slice progress,
|
|
5
|
+
* queue order) and dispatches a prompt that turns Claude into a reorganization
|
|
6
|
+
* assistant. Claude can then reorder, park, unpark, discard, or add milestones
|
|
7
|
+
* through conversation.
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync } from "node:fs";
|
|
10
|
+
import { isAutoActive } from "./auto.js";
|
|
11
|
+
import { deriveState } from "./state.js";
|
|
12
|
+
import { gsdRoot } from "./paths.js";
|
|
13
|
+
import { findMilestoneIds } from "./milestone-ids.js";
|
|
14
|
+
import { loadQueueOrder, validateQueueOrder } from "./queue-order.js";
|
|
15
|
+
import { getParkedReason } from "./milestone-actions.js";
|
|
16
|
+
import { getMilestoneSlices, isDbAvailable } from "./gsd-db.js";
|
|
17
|
+
import { buildExistingMilestonesContext } from "./guided-flow-queue.js";
|
|
18
|
+
import { loadPrompt } from "./prompt-loader.js";
|
|
19
|
+
// ─── Entry Point ──────────────────────────────────────────────────────────────
|
|
20
|
+
export async function handleRethink(_args, ctx, pi) {
|
|
21
|
+
if (isAutoActive()) {
|
|
22
|
+
ctx.ui.notify("Cannot rethink while auto-mode is active. Stop auto-mode first.", "error");
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const basePath = process.cwd();
|
|
26
|
+
const root = gsdRoot(basePath);
|
|
27
|
+
if (!existsSync(root)) {
|
|
28
|
+
ctx.ui.notify("No GSD project found. Run /gsd init first.", "warning");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
ctx.ui.notify("Building project snapshot for rethink...", "info");
|
|
32
|
+
const state = await deriveState(basePath);
|
|
33
|
+
const milestoneIds = findMilestoneIds(basePath);
|
|
34
|
+
if (milestoneIds.length === 0) {
|
|
35
|
+
ctx.ui.notify("No milestones exist yet. Nothing to rethink.", "warning");
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const queueOrder = loadQueueOrder(basePath);
|
|
39
|
+
const rethinkData = buildRethinkData(basePath, milestoneIds, state, queueOrder);
|
|
40
|
+
const existingMilestonesContext = await buildExistingMilestonesContext(basePath, milestoneIds, state);
|
|
41
|
+
const content = loadPrompt("rethink", {
|
|
42
|
+
rethinkData,
|
|
43
|
+
existingMilestonesContext,
|
|
44
|
+
});
|
|
45
|
+
pi.sendMessage({ customType: "gsd-rethink", content, display: false }, { triggerTurn: true });
|
|
46
|
+
}
|
|
47
|
+
// ─── Data Builder ─────────────────────────────────────────────────────────────
|
|
48
|
+
function buildRethinkData(basePath, milestoneIds, state, queueOrder) {
|
|
49
|
+
const lines = [];
|
|
50
|
+
const dbAvailable = isDbAvailable();
|
|
51
|
+
// ── Summary stats ───────────────────────────────────────────────────
|
|
52
|
+
const counts = { complete: 0, active: 0, pending: 0, parked: 0 };
|
|
53
|
+
for (const entry of state.registry) {
|
|
54
|
+
if (entry.status in counts)
|
|
55
|
+
counts[entry.status]++;
|
|
56
|
+
}
|
|
57
|
+
lines.push("### Summary");
|
|
58
|
+
lines.push(`${counts.complete} complete, ${counts.active} active, ${counts.pending} pending, ${counts.parked} parked — ${milestoneIds.length} total`);
|
|
59
|
+
lines.push(`Queue order source: ${queueOrder ? "explicit QUEUE-ORDER.json" : "default numeric (by ID)"}`);
|
|
60
|
+
if (state.activeMilestone) {
|
|
61
|
+
lines.push(`Active milestone: ${state.activeMilestone}`);
|
|
62
|
+
}
|
|
63
|
+
lines.push("");
|
|
64
|
+
// ── Milestone table ─────────────────────────────────────────────────
|
|
65
|
+
lines.push("### Execution Order");
|
|
66
|
+
lines.push("");
|
|
67
|
+
lines.push("| # | ID | Title | Status | Dependencies | Slices |");
|
|
68
|
+
lines.push("|---|-----|-------|--------|--------------|--------|");
|
|
69
|
+
for (let i = 0; i < milestoneIds.length; i++) {
|
|
70
|
+
const mid = milestoneIds[i];
|
|
71
|
+
const entry = state.registry.find(m => m.id === mid);
|
|
72
|
+
const title = entry?.title ?? mid;
|
|
73
|
+
const status = entry?.status ?? "unknown";
|
|
74
|
+
const deps = entry?.dependsOn?.length ? entry.dependsOn.join(", ") : "—";
|
|
75
|
+
let sliceInfo = "—";
|
|
76
|
+
if (dbAvailable && status !== "complete") {
|
|
77
|
+
const slices = getMilestoneSlices(mid);
|
|
78
|
+
if (slices.length > 0) {
|
|
79
|
+
const done = slices.filter(s => s.status === "complete").length;
|
|
80
|
+
sliceInfo = `${done}/${slices.length} complete`;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Add parked reason if applicable
|
|
84
|
+
let statusDisplay = status;
|
|
85
|
+
if (status === "parked") {
|
|
86
|
+
const reason = getParkedReason(basePath, mid);
|
|
87
|
+
if (reason)
|
|
88
|
+
statusDisplay = `parked (${reason})`;
|
|
89
|
+
}
|
|
90
|
+
lines.push(`| ${i + 1} | ${mid} | ${title} | ${statusDisplay} | ${deps} | ${sliceInfo} |`);
|
|
91
|
+
}
|
|
92
|
+
// ── Dependency validation ───────────────────────────────────────────
|
|
93
|
+
const pendingIds = milestoneIds.filter(mid => {
|
|
94
|
+
const entry = state.registry.find(m => m.id === mid);
|
|
95
|
+
return entry?.status !== "complete";
|
|
96
|
+
});
|
|
97
|
+
const completedIds = new Set(state.registry.filter(m => m.status === "complete").map(m => m.id));
|
|
98
|
+
const depsMap = new Map();
|
|
99
|
+
for (const entry of state.registry) {
|
|
100
|
+
if (entry.dependsOn?.length) {
|
|
101
|
+
depsMap.set(entry.id, entry.dependsOn);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (pendingIds.length > 0 && depsMap.size > 0) {
|
|
105
|
+
const validation = validateQueueOrder(pendingIds, depsMap, completedIds);
|
|
106
|
+
if (validation.violations.length > 0) {
|
|
107
|
+
lines.push("");
|
|
108
|
+
lines.push("### Dependency Issues");
|
|
109
|
+
for (const v of validation.violations) {
|
|
110
|
+
lines.push(`- **${v.type}**: ${v.message}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return lines.join("\n");
|
|
115
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { parseRoadmap, parsePlan, } from './parsers-legacy.js';
|
|
5
5
|
import { parseSummary, loadFile, parseRequirementCounts, parseContextDependsOn, } from './files.js';
|
|
6
6
|
import { resolveMilestoneFile, resolveSlicePath, resolveSliceFile, resolveTaskFile, resolveTasksDir, resolveGsdRootFile, gsdRoot, } from './paths.js';
|
|
7
|
-
import { findMilestoneIds } from './milestone-ids.js';
|
|
7
|
+
import { milestoneIdSort, findMilestoneIds } from './milestone-ids.js';
|
|
8
8
|
import { nativeBatchParseGsdFiles } from './native-parser-bridge.js';
|
|
9
9
|
import { join, resolve } from 'path';
|
|
10
10
|
import { existsSync, readdirSync } from 'node:fs';
|
|
@@ -210,6 +210,27 @@ export async function deriveStateFromDb(basePath) {
|
|
|
210
210
|
}
|
|
211
211
|
if (synced)
|
|
212
212
|
allMilestones = getAllMilestones();
|
|
213
|
+
// Reconcile: discover milestones that exist on disk but are missing from
|
|
214
|
+
// the DB. This happens when milestones were created before the DB migration
|
|
215
|
+
// or were manually added to the filesystem. Without this, disk-only
|
|
216
|
+
// milestones are invisible after migration (#2416).
|
|
217
|
+
const dbMilestoneIds = new Set(allMilestones.map(m => m.id));
|
|
218
|
+
const diskMilestoneIds = findMilestoneIds(basePath);
|
|
219
|
+
for (const diskId of diskMilestoneIds) {
|
|
220
|
+
if (!dbMilestoneIds.has(diskId)) {
|
|
221
|
+
// Synthesize a minimal MilestoneRow for the disk-only milestone.
|
|
222
|
+
// Title and status will be resolved from disk files in the loop below.
|
|
223
|
+
allMilestones.push({
|
|
224
|
+
id: diskId,
|
|
225
|
+
title: diskId,
|
|
226
|
+
status: 'active',
|
|
227
|
+
depends_on: [],
|
|
228
|
+
created_at: new Date().toISOString(),
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
// Re-sort so milestones are in canonical order after injection
|
|
233
|
+
allMilestones.sort((a, b) => milestoneIdSort(a.id, b.id));
|
|
213
234
|
// Parallel worker isolation: when locked, filter to just the locked milestone
|
|
214
235
|
const milestoneLock = process.env.GSD_MILESTONE_LOCK;
|
|
215
236
|
const milestones = milestoneLock
|
|
@@ -91,6 +91,7 @@ export async function handleReplanSlice(rawParams, basePath) {
|
|
|
91
91
|
verify: updatedTask.verify || "",
|
|
92
92
|
inputs: updatedTask.inputs || [],
|
|
93
93
|
expectedOutput: updatedTask.expectedOutput || [],
|
|
94
|
+
fullPlanMd: updatedTask.fullPlanMd,
|
|
94
95
|
});
|
|
95
96
|
}
|
|
96
97
|
else {
|
|
@@ -110,6 +111,7 @@ export async function handleReplanSlice(rawParams, basePath) {
|
|
|
110
111
|
verify: updatedTask.verify || "",
|
|
111
112
|
inputs: updatedTask.inputs || [],
|
|
112
113
|
expectedOutput: updatedTask.expectedOutput || [],
|
|
114
|
+
fullPlanMd: updatedTask.fullPlanMd,
|
|
113
115
|
});
|
|
114
116
|
}
|
|
115
117
|
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* validate-milestone handler — the core operation behind gsd_validate_milestone.
|
|
3
|
+
*
|
|
4
|
+
* Persists milestone validation results to the assessments table,
|
|
5
|
+
* renders VALIDATION.md to disk, and invalidates caches.
|
|
6
|
+
*/
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { transaction, _getAdapter, } from "../gsd-db.js";
|
|
9
|
+
import { resolveMilestonePath, clearPathCache } from "../paths.js";
|
|
10
|
+
import { saveFile, clearParseCache } from "../files.js";
|
|
11
|
+
import { invalidateStateCache } from "../state.js";
|
|
12
|
+
function renderValidationMarkdown(params) {
|
|
13
|
+
let md = `---
|
|
14
|
+
verdict: ${params.verdict}
|
|
15
|
+
remediation_round: ${params.remediationRound}
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Milestone Validation: ${params.milestoneId}
|
|
19
|
+
|
|
20
|
+
## Success Criteria Checklist
|
|
21
|
+
${params.successCriteriaChecklist}
|
|
22
|
+
|
|
23
|
+
## Slice Delivery Audit
|
|
24
|
+
${params.sliceDeliveryAudit}
|
|
25
|
+
|
|
26
|
+
## Cross-Slice Integration
|
|
27
|
+
${params.crossSliceIntegration}
|
|
28
|
+
|
|
29
|
+
## Requirement Coverage
|
|
30
|
+
${params.requirementCoverage}
|
|
31
|
+
|
|
32
|
+
## Verdict Rationale
|
|
33
|
+
${params.verdictRationale}
|
|
34
|
+
`;
|
|
35
|
+
if (params.verdict === "needs-remediation" && params.remediationPlan) {
|
|
36
|
+
md += `\n## Remediation Plan\n${params.remediationPlan}\n`;
|
|
37
|
+
}
|
|
38
|
+
return md;
|
|
39
|
+
}
|
|
40
|
+
export async function handleValidateMilestone(params, basePath) {
|
|
41
|
+
if (!params.milestoneId || typeof params.milestoneId !== "string" || params.milestoneId.trim() === "") {
|
|
42
|
+
return { error: "milestoneId is required and must be a non-empty string" };
|
|
43
|
+
}
|
|
44
|
+
const validVerdicts = ["pass", "needs-attention", "needs-remediation"];
|
|
45
|
+
if (!validVerdicts.includes(params.verdict)) {
|
|
46
|
+
return { error: `verdict must be one of: ${validVerdicts.join(", ")}` };
|
|
47
|
+
}
|
|
48
|
+
// ── Filesystem render ──────────────────────────────────────────────────
|
|
49
|
+
const validationMd = renderValidationMarkdown(params);
|
|
50
|
+
let validationPath;
|
|
51
|
+
const milestoneDir = resolveMilestonePath(basePath, params.milestoneId);
|
|
52
|
+
if (milestoneDir) {
|
|
53
|
+
validationPath = join(milestoneDir, `${params.milestoneId}-VALIDATION.md`);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
const gsdDir = join(basePath, ".gsd");
|
|
57
|
+
const manualDir = join(gsdDir, "milestones", params.milestoneId);
|
|
58
|
+
validationPath = join(manualDir, `${params.milestoneId}-VALIDATION.md`);
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
await saveFile(validationPath, validationMd);
|
|
62
|
+
}
|
|
63
|
+
catch (renderErr) {
|
|
64
|
+
process.stderr.write(`gsd-db: validate_milestone — disk render failed: ${renderErr.message}\n`);
|
|
65
|
+
return { error: `disk render failed: ${renderErr.message}` };
|
|
66
|
+
}
|
|
67
|
+
// ── DB write — store in assessments table ──────────────────────────────
|
|
68
|
+
const validatedAt = new Date().toISOString();
|
|
69
|
+
transaction(() => {
|
|
70
|
+
const adapter = _getAdapter();
|
|
71
|
+
adapter.prepare(`INSERT OR REPLACE INTO assessments (path, milestone_id, slice_id, task_id, status, scope, full_content, created_at)
|
|
72
|
+
VALUES (:path, :mid, NULL, NULL, :verdict, 'milestone-validation', :content, :created_at)`).run({
|
|
73
|
+
":path": validationPath,
|
|
74
|
+
":mid": params.milestoneId,
|
|
75
|
+
":verdict": params.verdict,
|
|
76
|
+
":content": validationMd,
|
|
77
|
+
":created_at": validatedAt,
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
invalidateStateCache();
|
|
81
|
+
clearPathCache();
|
|
82
|
+
clearParseCache();
|
|
83
|
+
return {
|
|
84
|
+
milestoneId: params.milestoneId,
|
|
85
|
+
verdict: params.verdict,
|
|
86
|
+
validationPath,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* 4. remove() — git worktree remove + branch cleanup
|
|
16
16
|
*/
|
|
17
17
|
import { existsSync, mkdirSync, readFileSync, realpathSync, rmSync } from "node:fs";
|
|
18
|
+
import { execFileSync } from "node:child_process";
|
|
18
19
|
import { join, resolve, sep } from "node:path";
|
|
19
20
|
import { GSDError, GSD_PARSE_ERROR, GSD_STALE_STATE, GSD_LOCK_HELD, GSD_GIT_ERROR, GSD_MERGE_CONFLICT } from "./errors.js";
|
|
20
21
|
import { nativeBranchDelete, nativeBranchExists, nativeBranchForceReset, nativeCommit, nativeDetectMainBranch, nativeDiffContent, nativeDiffNameStatus, nativeDiffNumstat, nativeGetCurrentBranch, nativeLogOneline, nativeMergeSquash, nativeWorktreeAdd, nativeWorktreeList, nativeWorktreePrune, nativeWorktreeRemove, } from "./native-git-bridge.js";
|
|
@@ -240,9 +241,38 @@ export function removeWorktree(basePath, name, opts = {}) {
|
|
|
240
241
|
}
|
|
241
242
|
return;
|
|
242
243
|
}
|
|
243
|
-
//
|
|
244
|
+
// Submodule safety (#2337): detect submodules with uncommitted changes
|
|
245
|
+
// before force-removing the worktree. Force removal destroys all uncommitted
|
|
246
|
+
// state, which is especially destructive for submodule directories.
|
|
247
|
+
let hasSubmoduleChanges = false;
|
|
248
|
+
const gitmodulesPath = join(resolvedWtPath, ".gitmodules");
|
|
249
|
+
if (existsSync(gitmodulesPath)) {
|
|
250
|
+
try {
|
|
251
|
+
const submoduleStatus = execFileSync("git", ["submodule", "status"], { cwd: resolvedWtPath, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
|
|
252
|
+
// Lines starting with '+' indicate uncommitted submodule changes
|
|
253
|
+
hasSubmoduleChanges = submoduleStatus.split("\n").some((line) => line.startsWith("+") || line.startsWith("-"));
|
|
254
|
+
if (hasSubmoduleChanges) {
|
|
255
|
+
// Stash submodule changes so they are not lost during force removal.
|
|
256
|
+
// The stash is created in the worktree before it's torn down.
|
|
257
|
+
try {
|
|
258
|
+
execFileSync("git", ["stash", "push", "-m", "gsd: auto-stash submodule changes before worktree teardown"], { cwd: resolvedWtPath, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" });
|
|
259
|
+
process.stderr.write(`[GSD] WARNING: Stashed uncommitted submodule changes in ${resolvedWtPath} before worktree teardown.\n`);
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
// Stash failed — warn the user that submodule changes may be lost
|
|
263
|
+
process.stderr.write(`[GSD] WARNING: Submodule changes detected in ${resolvedWtPath} — stash failed, changes may be lost during force removal.\n`);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
// submodule status failed — proceed with normal removal
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// Remove worktree: try non-force first when submodules have changes,
|
|
272
|
+
// falling back to force only after submodule state has been preserved.
|
|
273
|
+
const useForce = hasSubmoduleChanges ? false : force;
|
|
244
274
|
try {
|
|
245
|
-
nativeWorktreeRemove(basePath, resolvedWtPath,
|
|
275
|
+
nativeWorktreeRemove(basePath, resolvedWtPath, useForce);
|
|
246
276
|
}
|
|
247
277
|
catch { /* may fail */ }
|
|
248
278
|
// If the directory is still there (e.g. locked), try harder with force
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { existsSync, unlinkSync } from "node:fs";
|
|
16
16
|
import { join } from "node:path";
|
|
17
17
|
import { debugLog } from "./debug-logger.js";
|
|
18
|
+
import { MergeConflictError } from "./git-service.js";
|
|
18
19
|
// ─── WorktreeResolver ──────────────────────────────────────────────────────
|
|
19
20
|
export class WorktreeResolver {
|
|
20
21
|
s;
|
|
@@ -308,6 +309,11 @@ export class WorktreeResolver {
|
|
|
308
309
|
/* best-effort */
|
|
309
310
|
}
|
|
310
311
|
}
|
|
312
|
+
// Re-throw MergeConflictError so the auto loop can detect real code
|
|
313
|
+
// conflicts and stop instead of retrying forever (#2330).
|
|
314
|
+
if (err instanceof MergeConflictError) {
|
|
315
|
+
throw err;
|
|
316
|
+
}
|
|
311
317
|
}
|
|
312
318
|
// Always restore basePath and rebuild — whether merge succeeded or failed
|
|
313
319
|
this.restoreToProjectRoot();
|
|
@@ -162,6 +162,20 @@ function formatToolList(serverName, tools) {
|
|
|
162
162
|
lines.push(`Call with: mcp_call(server="${serverName}", tool="<tool_name>", args={...})`);
|
|
163
163
|
return lines.join("\n");
|
|
164
164
|
}
|
|
165
|
+
// ─── Status helper (consumed by /gsd mcp) ─────────────────────────────────────
|
|
166
|
+
/**
|
|
167
|
+
* Return the live connection status for a named MCP server.
|
|
168
|
+
* Safe to call even when the server has never been connected.
|
|
169
|
+
*/
|
|
170
|
+
export function getConnectionStatus(name) {
|
|
171
|
+
const conn = connections.get(name);
|
|
172
|
+
const cached = toolCache.get(name);
|
|
173
|
+
return {
|
|
174
|
+
connected: !!conn,
|
|
175
|
+
tools: cached ? cached.map((t) => t.name) : [],
|
|
176
|
+
error: undefined,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
165
179
|
// ─── Extension ────────────────────────────────────────────────────────────────
|
|
166
180
|
export default function (pi) {
|
|
167
181
|
// ── mcp_servers ──────────────────────────────────────────────────────────
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
enTIm32JJtw--VTtLPSC3
|
|
@@ -1,45 +1,45 @@
|
|
|
1
1
|
{
|
|
2
|
-
"/_global-error/page": "/_global-error",
|
|
3
2
|
"/_not-found/page": "/_not-found",
|
|
4
|
-
"/
|
|
5
|
-
"/api/boot/route": "/api/boot",
|
|
3
|
+
"/_global-error/page": "/_global-error",
|
|
6
4
|
"/api/bridge-terminal/input/route": "/api/bridge-terminal/input",
|
|
5
|
+
"/api/boot/route": "/api/boot",
|
|
6
|
+
"/api/bridge-terminal/resize/route": "/api/bridge-terminal/resize",
|
|
7
|
+
"/api/bridge-terminal/stream/route": "/api/bridge-terminal/stream",
|
|
8
|
+
"/api/cleanup/route": "/api/cleanup",
|
|
7
9
|
"/api/dev-mode/route": "/api/dev-mode",
|
|
10
|
+
"/api/export-data/route": "/api/export-data",
|
|
8
11
|
"/api/browse-directories/route": "/api/browse-directories",
|
|
9
|
-
"/api/cleanup/route": "/api/cleanup",
|
|
10
|
-
"/api/bridge-terminal/stream/route": "/api/bridge-terminal/stream",
|
|
11
|
-
"/api/git/route": "/api/git",
|
|
12
12
|
"/api/doctor/route": "/api/doctor",
|
|
13
|
+
"/api/captures/route": "/api/captures",
|
|
13
14
|
"/api/forensics/route": "/api/forensics",
|
|
14
|
-
"/api/
|
|
15
|
+
"/api/git/route": "/api/git",
|
|
16
|
+
"/api/hooks/route": "/api/hooks",
|
|
15
17
|
"/api/history/route": "/api/history",
|
|
16
18
|
"/api/inspect/route": "/api/inspect",
|
|
17
|
-
"/api/hooks/route": "/api/hooks",
|
|
18
19
|
"/api/knowledge/route": "/api/knowledge",
|
|
19
|
-
"/api/captures/route": "/api/captures",
|
|
20
20
|
"/api/live-state/route": "/api/live-state",
|
|
21
|
-
"/api/
|
|
21
|
+
"/api/preferences/route": "/api/preferences",
|
|
22
22
|
"/api/recovery/route": "/api/recovery",
|
|
23
|
+
"/api/onboarding/route": "/api/onboarding",
|
|
23
24
|
"/api/projects/route": "/api/projects",
|
|
24
|
-
"/api/preferences/route": "/api/preferences",
|
|
25
25
|
"/api/session/browser/route": "/api/session/browser",
|
|
26
26
|
"/api/session/command/route": "/api/session/command",
|
|
27
|
-
"/api/settings-data/route": "/api/settings-data",
|
|
28
|
-
"/api/files/route": "/api/files",
|
|
29
27
|
"/api/session/events/route": "/api/session/events",
|
|
28
|
+
"/api/session/manage/route": "/api/session/manage",
|
|
29
|
+
"/api/settings-data/route": "/api/settings-data",
|
|
30
30
|
"/api/shutdown/route": "/api/shutdown",
|
|
31
31
|
"/api/skill-health/route": "/api/skill-health",
|
|
32
32
|
"/api/steer/route": "/api/steer",
|
|
33
|
-
"/api/switch-root/route": "/api/switch-root",
|
|
34
|
-
"/api/session/manage/route": "/api/session/manage",
|
|
35
|
-
"/api/terminal/resize/route": "/api/terminal/resize",
|
|
36
33
|
"/api/terminal/input/route": "/api/terminal/input",
|
|
37
|
-
"/api/terminal/
|
|
38
|
-
"/api/
|
|
39
|
-
"/api/
|
|
34
|
+
"/api/terminal/resize/route": "/api/terminal/resize",
|
|
35
|
+
"/api/switch-root/route": "/api/switch-root",
|
|
36
|
+
"/api/files/route": "/api/files",
|
|
40
37
|
"/api/terminal/sessions/route": "/api/terminal/sessions",
|
|
41
|
-
"/api/terminal/
|
|
38
|
+
"/api/terminal/upload/route": "/api/terminal/upload",
|
|
42
39
|
"/api/undo/route": "/api/undo",
|
|
40
|
+
"/api/terminal/stream/route": "/api/terminal/stream",
|
|
43
41
|
"/api/update/route": "/api/update",
|
|
42
|
+
"/api/remote-questions/route": "/api/remote-questions",
|
|
43
|
+
"/api/visualizer/route": "/api/visualizer",
|
|
44
44
|
"/page": "/"
|
|
45
45
|
}
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
],
|
|
5
5
|
"devFiles": [],
|
|
6
6
|
"lowPriorityFiles": [
|
|
7
|
-
"static/
|
|
8
|
-
"static/
|
|
7
|
+
"static/enTIm32JJtw--VTtLPSC3/_buildManifest.js",
|
|
8
|
+
"static/enTIm32JJtw--VTtLPSC3/_ssgManifest.js"
|
|
9
9
|
],
|
|
10
10
|
"rootMainFiles": [
|
|
11
|
-
"static/chunks/webpack-
|
|
11
|
+
"static/chunks/webpack-0a4cd455ec4197d2.js",
|
|
12
12
|
"static/chunks/4bd1b696-e5d7c65570c947b7.js",
|
|
13
13
|
"static/chunks/3794-337d1ca25ad99a89.js",
|
|
14
14
|
"static/chunks/main-app-fdab67f7802d7832.js"
|
|
@@ -78,8 +78,8 @@
|
|
|
78
78
|
"dynamicRoutes": {},
|
|
79
79
|
"notFoundRoutes": [],
|
|
80
80
|
"preview": {
|
|
81
|
-
"previewModeId": "
|
|
82
|
-
"previewModeSigningKey": "
|
|
83
|
-
"previewModeEncryptionKey": "
|
|
81
|
+
"previewModeId": "9a0ceb692d677356d9b54bfb5dce441f",
|
|
82
|
+
"previewModeSigningKey": "3d776745b9c72ffc03f84eb9b6d40816aa3f7eeec4b0aa3f81e6112ecd501483",
|
|
83
|
+
"previewModeEncryptionKey": "a74c26ee7774ffc35f583cf94204b22599baab12aa1a7c557e42cca9b0b6f233"
|
|
84
84
|
}
|
|
85
85
|
}
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
"static/css/659eccb5db697b76.css",
|
|
6
6
|
"static/chunks/363642f4.f9053a63f1b97508.js",
|
|
7
7
|
"static/chunks/4986-c2fc8845ce785303.js",
|
|
8
|
-
"static/chunks/
|
|
9
|
-
"static/chunks/4024.
|
|
8
|
+
"static/chunks/485.243af25f0cdf50d6.js",
|
|
9
|
+
"static/chunks/4024.11ca5c01938e5948.js"
|
|
10
10
|
]
|
|
11
11
|
},
|
|
12
12
|
"components/gsd/chat-mode.tsx -> react-markdown": {
|
package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
globalThis.__RSC_MANIFEST=(globalThis.__RSC_MANIFEST||{});globalThis.__RSC_MANIFEST["/_global-error/page"]={"moduleLoading":{"prefix":"/_next/"},"ssrModuleMapping":{"21942":{"*":{"id":"18550","name":"*","chunks":[],"async":false}},"27123":{"*":{"id":"81921","name":"*","chunks":[],"async":false}},"57121":{"*":{"id":"35421","name":"*","chunks":[],"async":false}},"61304":{"*":{"id":"60440","name":"*","chunks":[],"async":false}},"61549":{"*":{"id":"99703","name":"*","chunks":[],"async":false}},"64777":{"*":{"id":"82265","name":"*","chunks":[],"async":false}},"66919":{"*":{"id":"65720","name":"*","chunks":[],"async":false}},"74581":{"*":{"id":"61335","name":"*","chunks":[],"async":false}},"78616":{"*":{"id":"84342","name":"*","chunks":[],"async":false}},"86869":{"*":{"id":"74661","name":"*","chunks":[],"async":false}},"90484":{"*":{"id":"70664","name":"*","chunks":[],"async":false}}},"edgeSSRModuleMapping":{},"clientModules":{"/__w/gsd-2/gsd-2/web/node_modules/next/dist/client/components/builtin/global-error.js":{"id":27123,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/esm/client/components/builtin/global-error.js":{"id":27123,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/client/components/client-page.js":{"id":61304,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/esm/client/components/client-page.js":{"id":61304,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/client/components/client-segment.js":{"id":78616,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/esm/client/components/client-segment.js":{"id":78616,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/client/components/http-access-fallback/error-boundary.js":{"id":64777,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/esm/client/components/http-access-fallback/error-boundary.js":{"id":64777,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/client/components/layout-router.js":{"id":57121,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/esm/client/components/layout-router.js":{"id":57121,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/client/components/render-from-template-context.js":{"id":74581,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/esm/client/components/render-from-template-context.js":{"id":74581,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/lib/framework/boundary-components.js":{"id":90484,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/esm/lib/framework/boundary-components.js":{"id":90484,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/lib/metadata/generate/icon-mark.js":{"id":86869,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/esm/lib/metadata/generate/icon-mark.js":{"id":86869,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/components/theme-provider.tsx":{"id":21942,"name":"*","chunks":["4986","static/chunks/4986-c2fc8845ce785303.js","7177","static/chunks/app/layout-a16c7a7ecdf0c2cf.js"],"async":false},"/__w/gsd-2/gsd-2/web/components/ui/sonner.tsx":{"id":61549,"name":"*","chunks":["4986","static/chunks/4986-c2fc8845ce785303.js","7177","static/chunks/app/layout-a16c7a7ecdf0c2cf.js"],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/font/google/target.css?{\"path\":\"app/layout.tsx\",\"import\":\"Geist\",\"arguments\":[{\"subsets\":[\"latin\"],\"variable\":\"--font-geist-sans\"}],\"variableName\":\"geistSans\"}":{"id":85048,"name":"*","chunks":["4986","static/chunks/4986-c2fc8845ce785303.js","7177","static/chunks/app/layout-a16c7a7ecdf0c2cf.js"],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/font/google/target.css?{\"path\":\"app/layout.tsx\",\"import\":\"Geist_Mono\",\"arguments\":[{\"subsets\":[\"latin\"],\"variable\":\"--font-geist-mono\"}],\"variableName\":\"geistMono\"}":{"id":35696,"name":"*","chunks":["4986","static/chunks/4986-c2fc8845ce785303.js","7177","static/chunks/app/layout-a16c7a7ecdf0c2cf.js"],"async":false},"/__w/gsd-2/gsd-2/web/app/globals.css":{"id":66872,"name":"*","chunks":["4986","static/chunks/4986-c2fc8845ce785303.js","7177","static/chunks/app/layout-a16c7a7ecdf0c2cf.js"],"async":false},"/__w/gsd-2/gsd-2/web/app/page.tsx":{"id":66919,"name":"*","chunks":["8974","static/chunks/app/page-
|
|
1
|
+
globalThis.__RSC_MANIFEST=(globalThis.__RSC_MANIFEST||{});globalThis.__RSC_MANIFEST["/_global-error/page"]={"moduleLoading":{"prefix":"/_next/"},"ssrModuleMapping":{"21942":{"*":{"id":"18550","name":"*","chunks":[],"async":false}},"27123":{"*":{"id":"81921","name":"*","chunks":[],"async":false}},"57121":{"*":{"id":"35421","name":"*","chunks":[],"async":false}},"61304":{"*":{"id":"60440","name":"*","chunks":[],"async":false}},"61549":{"*":{"id":"99703","name":"*","chunks":[],"async":false}},"64777":{"*":{"id":"82265","name":"*","chunks":[],"async":false}},"66919":{"*":{"id":"65720","name":"*","chunks":[],"async":false}},"74581":{"*":{"id":"61335","name":"*","chunks":[],"async":false}},"78616":{"*":{"id":"84342","name":"*","chunks":[],"async":false}},"86869":{"*":{"id":"74661","name":"*","chunks":[],"async":false}},"90484":{"*":{"id":"70664","name":"*","chunks":[],"async":false}}},"edgeSSRModuleMapping":{},"clientModules":{"/__w/gsd-2/gsd-2/web/node_modules/next/dist/client/components/builtin/global-error.js":{"id":27123,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/esm/client/components/builtin/global-error.js":{"id":27123,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/client/components/client-page.js":{"id":61304,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/esm/client/components/client-page.js":{"id":61304,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/client/components/client-segment.js":{"id":78616,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/esm/client/components/client-segment.js":{"id":78616,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/client/components/http-access-fallback/error-boundary.js":{"id":64777,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/esm/client/components/http-access-fallback/error-boundary.js":{"id":64777,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/client/components/layout-router.js":{"id":57121,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/esm/client/components/layout-router.js":{"id":57121,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/client/components/render-from-template-context.js":{"id":74581,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/esm/client/components/render-from-template-context.js":{"id":74581,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/lib/framework/boundary-components.js":{"id":90484,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/esm/lib/framework/boundary-components.js":{"id":90484,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/lib/metadata/generate/icon-mark.js":{"id":86869,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/dist/esm/lib/metadata/generate/icon-mark.js":{"id":86869,"name":"*","chunks":[],"async":false},"/__w/gsd-2/gsd-2/web/components/theme-provider.tsx":{"id":21942,"name":"*","chunks":["4986","static/chunks/4986-c2fc8845ce785303.js","7177","static/chunks/app/layout-a16c7a7ecdf0c2cf.js"],"async":false},"/__w/gsd-2/gsd-2/web/components/ui/sonner.tsx":{"id":61549,"name":"*","chunks":["4986","static/chunks/4986-c2fc8845ce785303.js","7177","static/chunks/app/layout-a16c7a7ecdf0c2cf.js"],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/font/google/target.css?{\"path\":\"app/layout.tsx\",\"import\":\"Geist\",\"arguments\":[{\"subsets\":[\"latin\"],\"variable\":\"--font-geist-sans\"}],\"variableName\":\"geistSans\"}":{"id":85048,"name":"*","chunks":["4986","static/chunks/4986-c2fc8845ce785303.js","7177","static/chunks/app/layout-a16c7a7ecdf0c2cf.js"],"async":false},"/__w/gsd-2/gsd-2/web/node_modules/next/font/google/target.css?{\"path\":\"app/layout.tsx\",\"import\":\"Geist_Mono\",\"arguments\":[{\"subsets\":[\"latin\"],\"variable\":\"--font-geist-mono\"}],\"variableName\":\"geistMono\"}":{"id":35696,"name":"*","chunks":["4986","static/chunks/4986-c2fc8845ce785303.js","7177","static/chunks/app/layout-a16c7a7ecdf0c2cf.js"],"async":false},"/__w/gsd-2/gsd-2/web/app/globals.css":{"id":66872,"name":"*","chunks":["4986","static/chunks/4986-c2fc8845ce785303.js","7177","static/chunks/app/layout-a16c7a7ecdf0c2cf.js"],"async":false},"/__w/gsd-2/gsd-2/web/app/page.tsx":{"id":66919,"name":"*","chunks":["8974","static/chunks/app/page-6654a8cca61a3d1c.js"],"async":false}},"entryCSSFiles":{"/__w/gsd-2/gsd-2/web/":[],"/__w/gsd-2/gsd-2/web/app/layout":[{"inlined":false,"path":"static/css/de70bee13400563f.css"},{"inlined":false,"path":"static/css/dd4ae3f58ac9b600.css"}],"/__w/gsd-2/gsd-2/web/app/page":[],"/__w/gsd-2/gsd-2/web/app/_global-error/page":[]},"rscModuleMapping":{"21942":{"*":{"id":"9796","name":"*","chunks":[],"async":false}},"27123":{"*":{"id":"95547","name":"*","chunks":[],"async":false}},"57121":{"*":{"id":"98099","name":"*","chunks":[],"async":false}},"61304":{"*":{"id":"15098","name":"*","chunks":[],"async":false}},"61549":{"*":{"id":"85561","name":"*","chunks":[],"async":false}},"64777":{"*":{"id":"33859","name":"*","chunks":[],"async":false}},"66872":{"*":{"id":"82704","name":"*","chunks":[],"async":false}},"66919":{"*":{"id":"99647","name":"*","chunks":[],"async":false}},"74581":{"*":{"id":"16237","name":"*","chunks":[],"async":false}},"78616":{"*":{"id":"47644","name":"*","chunks":[],"async":false}},"86869":{"*":{"id":"36675","name":"*","chunks":[],"async":false}},"90484":{"*":{"id":"98562","name":"*","chunks":[],"async":false}}},"edgeRscModuleMapping":{}}
|