gsd-pi 2.73.0 → 2.73.1-dev.d987996

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.
Files changed (194) hide show
  1. package/dist/cli.js +0 -47
  2. package/dist/help-text.js +1 -1
  3. package/dist/resources/extensions/gsd/auto-dispatch.js +5 -3
  4. package/dist/resources/extensions/gsd/auto-prompts.js +9 -6
  5. package/dist/resources/extensions/gsd/auto.js +5 -1
  6. package/dist/resources/extensions/gsd/bootstrap/crash-log.js +31 -0
  7. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +18 -7
  8. package/dist/resources/extensions/gsd/bootstrap/system-context.js +6 -1
  9. package/dist/resources/extensions/gsd/crash-recovery.js +51 -0
  10. package/dist/resources/extensions/gsd/gsd-db.js +36 -2
  11. package/dist/resources/extensions/gsd/milestone-actions.js +19 -1
  12. package/dist/startup-model-validation.js +8 -5
  13. package/dist/web/standalone/.next/BUILD_ID +1 -1
  14. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  15. package/dist/web/standalone/.next/build-manifest.json +3 -3
  16. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  17. package/dist/web/standalone/.next/required-server-files.json +3 -3
  18. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  19. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  20. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  21. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  22. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  23. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  24. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  25. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  26. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  28. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  29. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  30. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  31. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  32. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  33. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  34. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  35. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  36. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  37. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  38. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  39. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  40. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  41. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  42. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  43. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  44. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  45. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  46. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  47. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  48. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  49. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  50. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  51. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  52. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  53. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  54. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  55. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  56. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  57. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  58. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  59. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  60. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  61. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  62. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  63. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  64. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  65. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  66. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  67. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  68. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  69. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  70. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  71. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  72. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  73. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  74. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  77. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  82. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  87. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  93. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  107. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  109. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  111. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  113. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/index.html +1 -1
  123. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  124. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  125. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  126. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  128. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/page.js +2 -2
  130. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  132. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  133. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  134. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  136. package/dist/web/standalone/.next/server/middleware.js +2 -2
  137. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  139. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  140. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  141. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  142. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  143. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  144. package/dist/web/standalone/.next/static/chunks/app/page-f1e30ab6bb269149.js +1 -0
  145. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  146. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  147. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  148. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  149. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  150. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  151. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  152. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  153. package/dist/web/standalone/server.js +1 -1
  154. package/package.json +1 -1
  155. package/packages/pi-coding-agent/dist/core/auth-storage.js +1 -1
  156. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  157. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +27 -0
  158. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  159. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  160. package/packages/pi-coding-agent/dist/core/model-resolver.js +25 -68
  161. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  162. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts +1 -0
  163. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  164. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +22 -9
  165. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  166. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.d.ts +2 -0
  167. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.d.ts.map +1 -0
  168. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +63 -0
  169. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -0
  170. package/packages/pi-coding-agent/package.json +1 -1
  171. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +38 -0
  172. package/packages/pi-coding-agent/src/core/auth-storage.ts +1 -1
  173. package/packages/pi-coding-agent/src/core/model-resolver.ts +26 -70
  174. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +71 -0
  175. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +23 -9
  176. package/pkg/package.json +1 -1
  177. package/src/resources/extensions/gsd/auto-dispatch.ts +5 -0
  178. package/src/resources/extensions/gsd/auto-prompts.ts +9 -3
  179. package/src/resources/extensions/gsd/auto.ts +5 -0
  180. package/src/resources/extensions/gsd/bootstrap/crash-log.ts +32 -0
  181. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +19 -7
  182. package/src/resources/extensions/gsd/bootstrap/system-context.ts +8 -1
  183. package/src/resources/extensions/gsd/crash-recovery.ts +59 -0
  184. package/src/resources/extensions/gsd/gsd-db.ts +52 -2
  185. package/src/resources/extensions/gsd/milestone-actions.ts +19 -1
  186. package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +235 -0
  187. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +59 -1
  188. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +64 -0
  189. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +267 -0
  190. package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.js +0 -1
  191. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  192. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  193. /package/dist/web/standalone/.next/static/{KSZ2dcC3p4z6lOmUpPpzr → cGmbVq2su4f9tMpgIkG8u}/_buildManifest.js +0 -0
  194. /package/dist/web/standalone/.next/static/{KSZ2dcC3p4z6lOmUpPpzr → cGmbVq2su4f9tMpgIkG8u}/_ssgManifest.js +0 -0
package/dist/cli.js CHANGED
@@ -6,7 +6,6 @@ import { initResources, buildResourceLoader, getNewerManagedResourceVersion } fr
6
6
  import { ensureManagedTools } from './tool-bootstrap.js';
7
7
  import { loadStoredEnvKeys } from './wizard.js';
8
8
  import { migratePiCredentials, getPiDefaultModelAndProvider } from './pi-migration.js';
9
- import { shouldMigrateAnthropicToClaudeCode } from './provider-migrations.js';
10
9
  import { shouldRunOnboarding, runOnboarding } from './onboarding.js';
11
10
  import chalk from 'chalk';
12
11
  import { checkForUpdates } from './update-check.js';
@@ -455,29 +454,6 @@ if (isPrintMode) {
455
454
  isClaudeCodeReady: () => modelRegistry.isProviderRequestReady('claude-code'),
456
455
  });
457
456
  markStartup('createAgentSession');
458
- // Migrate anthropic OAuth users to claude-code provider when CLI is available (#3772).
459
- // Anthropic blocks third-party apps from using subscription quotas — routing through
460
- // the local claude CLI binary is TOS-compliant.
461
- if (shouldMigrateAnthropicToClaudeCode({
462
- authStorage,
463
- isClaudeCodeReady: modelRegistry.isProviderRequestReady('claude-code'),
464
- defaultProvider: settingsManager.getDefaultProvider(),
465
- })) {
466
- const currentModelId = settingsManager.getDefaultModel();
467
- if (currentModelId) {
468
- const ccModel = modelRegistry.find('claude-code', currentModelId);
469
- if (ccModel) {
470
- try {
471
- await session.setModel(ccModel);
472
- // Only persist after successful session switch to avoid desync
473
- settingsManager.setDefaultModelAndProvider('claude-code', currentModelId);
474
- }
475
- catch {
476
- // claude-code provider not ready — leave both session and settings unchanged
477
- }
478
- }
479
- }
480
- }
481
457
  // Validate configured model AFTER extensions have registered their models (#2626).
482
458
  // Before this, extension-provided models (e.g. claude-code/*) were not yet in the
483
459
  // registry, causing the user's valid choice to be silently overwritten.
@@ -647,29 +623,6 @@ const { session, extensionsResult, modelFallbackMessage: interactiveFallbackMsg
647
623
  isClaudeCodeReady: () => modelRegistry.isProviderRequestReady('claude-code'),
648
624
  });
649
625
  markStartup('createAgentSession');
650
- // Migrate anthropic OAuth users to claude-code provider when CLI is available (#3772).
651
- // Anthropic blocks third-party apps from using subscription quotas — routing through
652
- // the local claude CLI binary is TOS-compliant.
653
- if (shouldMigrateAnthropicToClaudeCode({
654
- authStorage,
655
- isClaudeCodeReady: modelRegistry.isProviderRequestReady('claude-code'),
656
- defaultProvider: settingsManager.getDefaultProvider(),
657
- })) {
658
- const currentModelId = settingsManager.getDefaultModel();
659
- if (currentModelId) {
660
- const ccModel = modelRegistry.find('claude-code', currentModelId);
661
- if (ccModel) {
662
- try {
663
- await session.setModel(ccModel);
664
- // Only persist after successful session switch to avoid desync
665
- settingsManager.setDefaultModelAndProvider('claude-code', currentModelId);
666
- }
667
- catch {
668
- // claude-code provider not ready — leave both session and settings unchanged
669
- }
670
- }
671
- }
672
- }
673
626
  // Validate configured model AFTER extensions have registered their models (#2626).
674
627
  // Before this, extension-provided models (e.g. claude-code/*) were not yet in the
675
628
  // registry, causing the user's valid choice to be silently overwritten.
package/dist/help-text.js CHANGED
@@ -148,7 +148,7 @@ export function printHelp(version) {
148
148
  process.stdout.write(' --print, -p Single-shot print mode\n');
149
149
  process.stdout.write(' --continue, -c Resume the most recent session\n');
150
150
  process.stdout.write(' --worktree, -w [name] Start in an isolated worktree (auto-named if omitted)\n');
151
- process.stdout.write(' --model <id> Override model (e.g. claude-opus-4-6)\n');
151
+ process.stdout.write(' --model <id> Override model (e.g. provider/model-id)\n');
152
152
  process.stdout.write(' --no-session Disable session persistence\n');
153
153
  process.stdout.write(' --extension <path> Load additional extension\n');
154
154
  process.stdout.write(' --tools <a,b,c> Restrict available tools\n');
@@ -18,6 +18,7 @@ import { logWarning, logError } from "./workflow-logger.js";
18
18
  import { join } from "node:path";
19
19
  import { hasImplementationArtifacts } from "./auto-recovery.js";
20
20
  import { buildDiscussMilestonePrompt, buildResearchMilestonePrompt, buildPlanMilestonePrompt, buildResearchSlicePrompt, buildPlanSlicePrompt, buildExecuteTaskPrompt, buildCompleteSlicePrompt, buildCompleteMilestonePrompt, buildValidateMilestonePrompt, buildReplanSlicePrompt, buildRunUatPrompt, buildReassessRoadmapPrompt, buildRewriteDocsPrompt, buildReactiveExecutePrompt, buildGateEvaluatePrompt, buildParallelResearchSlicesPrompt, checkNeedsReassessment, checkNeedsRunUat, } from "./auto-prompts.js";
21
+ import { resolveModelWithFallbacksForUnit } from "./preferences-models.js";
21
22
  function missingSliceStop(mid, phase) {
22
23
  return {
23
24
  action: "stop",
@@ -330,7 +331,7 @@ export const DISPATCH_RULES = [
330
331
  action: "dispatch",
331
332
  unitType: "research-slice",
332
333
  unitId: `${mid}/parallel-research`,
333
- prompt: await buildParallelResearchSlicesPrompt(mid, midTitle, researchReadySlices, basePath),
334
+ prompt: await buildParallelResearchSlicesPrompt(mid, midTitle, researchReadySlices, basePath, resolveModelWithFallbacksForUnit("subagent")?.primary),
334
335
  };
335
336
  },
336
337
  },
@@ -401,7 +402,7 @@ export const DISPATCH_RULES = [
401
402
  action: "dispatch",
402
403
  unitType: "gate-evaluate",
403
404
  unitId: `${mid}/${sid}/gates+${pending.map(g => g.gate_id).join(",")}`,
404
- prompt: await buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, basePath),
405
+ prompt: await buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, basePath, resolveModelWithFallbacksForUnit("subagent")?.primary),
405
406
  };
406
407
  },
407
408
  },
@@ -436,6 +437,7 @@ export const DISPATCH_RULES = [
436
437
  const sid = state.activeSlice.id;
437
438
  const sTitle = state.activeSlice.title;
438
439
  const maxParallel = reactiveConfig.max_parallel ?? 2;
440
+ const subagentModel = reactiveConfig.subagent_model ?? resolveModelWithFallbacksForUnit("subagent")?.primary;
439
441
  // Dry-run mode: max_parallel=1 means graph is derived and logged but
440
442
  // execution remains sequential
441
443
  if (maxParallel <= 1)
@@ -478,7 +480,7 @@ export const DISPATCH_RULES = [
478
480
  action: "dispatch",
479
481
  unitType: "reactive-execute",
480
482
  unitId: `${mid}/${sid}/reactive+${batchSuffix}`,
481
- prompt: await buildReactiveExecutePrompt(mid, midTitle, sid, sTitle, selected, basePath),
483
+ prompt: await buildReactiveExecutePrompt(mid, midTitle, sid, sTitle, selected, basePath, subagentModel),
482
484
  };
483
485
  }
484
486
  catch (err) {
@@ -1712,7 +1712,7 @@ export async function buildReassessRoadmapPrompt(mid, midTitle, completedSliceId
1712
1712
  });
1713
1713
  }
1714
1714
  // ─── Reactive Execute Prompt ──────────────────────────────────────────────
1715
- export async function buildReactiveExecutePrompt(mid, midTitle, sid, sTitle, readyTaskIds, base) {
1715
+ export async function buildReactiveExecutePrompt(mid, midTitle, sid, sTitle, readyTaskIds, base, subagentModel) {
1716
1716
  const { loadSliceTaskIO, deriveTaskGraph, graphMetrics } = await import("./reactive-graph.js");
1717
1717
  // Build graph for context
1718
1718
  const taskIO = await loadSliceTaskIO(base, mid, sid);
@@ -1744,10 +1744,11 @@ export async function buildReactiveExecutePrompt(mid, midTitle, sid, sTitle, rea
1744
1744
  const depPaths = await getDependencyTaskSummaryPaths(mid, sid, tid, node?.dependsOn ?? [], base);
1745
1745
  // Build a full execute-task prompt with dependency-based carry-forward
1746
1746
  const taskPrompt = await buildExecuteTaskPrompt(mid, sid, sTitle, tid, tTitle, base, { carryForwardPaths: depPaths });
1747
+ const modelSuffix = subagentModel ? ` with model: "${subagentModel}"` : "";
1747
1748
  subagentSections.push([
1748
1749
  `### ${tid}: ${tTitle}`,
1749
1750
  "",
1750
- "Use this as the prompt for a `subagent` call:",
1751
+ `Use this as the prompt for a \`subagent\` call${modelSuffix}:`,
1751
1752
  "",
1752
1753
  "```",
1753
1754
  taskPrompt,
@@ -1806,15 +1807,16 @@ function renderGatesToCloseBlock(gates, opts) {
1806
1807
  }
1807
1808
  return lines.join("\n").trimEnd();
1808
1809
  }
1809
- export async function buildParallelResearchSlicesPrompt(mid, midTitle, slices, basePath) {
1810
+ export async function buildParallelResearchSlicesPrompt(mid, midTitle, slices, basePath, subagentModel) {
1810
1811
  // Build individual research-slice prompts for each slice
1811
1812
  const subagentSections = [];
1813
+ const modelSuffix = subagentModel ? ` with model: "${subagentModel}"` : "";
1812
1814
  for (const slice of slices) {
1813
1815
  const slicePrompt = await buildResearchSlicePrompt(mid, midTitle, slice.id, slice.title, basePath);
1814
1816
  subagentSections.push([
1815
1817
  `### ${slice.id}: ${slice.title}`,
1816
1818
  "",
1817
- "Use this as the prompt for a `subagent` call (agent: `gsd-executor` or the default agent):",
1819
+ `Use this as the prompt for a \`subagent\` call${modelSuffix} (agent: \`gsd-executor\` or the default agent):`,
1818
1820
  "",
1819
1821
  "```",
1820
1822
  slicePrompt,
@@ -1829,7 +1831,7 @@ export async function buildParallelResearchSlicesPrompt(mid, midTitle, slices, b
1829
1831
  subagentPrompts: subagentSections.join("\n\n---\n\n"),
1830
1832
  });
1831
1833
  }
1832
- export async function buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, base) {
1834
+ export async function buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, base, subagentModel) {
1833
1835
  // Pull only the gates this turn actually owns (Q3/Q4). Filter via the
1834
1836
  // registry so that scope:"slice" gates owned by other turns (Q8) can't
1835
1837
  // leak into this prompt and can't block dispatch via silent skip.
@@ -1873,10 +1875,11 @@ export async function buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, base)
1873
1875
  "- `rationale`: one-sentence justification",
1874
1876
  "- `findings`: detailed markdown findings (or empty if omitted)",
1875
1877
  ].join("\n");
1878
+ const modelSuffix = subagentModel ? ` with model: "${subagentModel}"` : "";
1876
1879
  subagentSections.push([
1877
1880
  `### ${def.id}: ${def.question}`,
1878
1881
  "",
1879
- "Use this as the prompt for a `subagent` call:",
1882
+ `Use this as the prompt for a \`subagent\` call${modelSuffix}:`,
1880
1883
  "",
1881
1884
  "```",
1882
1885
  subPrompt,
@@ -19,7 +19,7 @@ import { gsdRoot, resolveMilestoneFile, resolveMilestonePath, resolveDir, milest
19
19
  import { invalidateAllCaches } from "./cache.js";
20
20
  import { clearActivityLogState } from "./activity-log.js";
21
21
  import { synthesizeCrashRecovery, getDeepDiagnostic, readActiveMilestoneId, } from "./session-forensics.js";
22
- import { writeLock, clearLock, readCrashLock, isLockProcessAlive, formatCrashInfo, } from "./crash-recovery.js";
22
+ import { writeLock, clearLock, readCrashLock, isLockProcessAlive, formatCrashInfo, emitCrashRecoveredUnitEnd, } from "./crash-recovery.js";
23
23
  import { acquireSessionLock, getSessionLockStatus, releaseSessionLock, updateSessionLock, } from "./session-lock.js";
24
24
  import { resolveAutoSupervisorConfig, loadEffectiveGSDPreferences, getIsolationMode, } from "./preferences.js";
25
25
  import { sendDesktopNotification } from "./notifications.js";
@@ -1014,6 +1014,10 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
1014
1014
  s.stepMode = requestedStepMode;
1015
1015
  }
1016
1016
  if (freshStartAssessment.lock) {
1017
+ // Emit a synthetic unit-end for any unit-start that has no closing event.
1018
+ // This closes the journal gap reported in #3348 where the worker wrote side
1019
+ // effects (SUMMARY.md, DB updates) but died before emitting unit-end.
1020
+ emitCrashRecoveredUnitEnd(base, freshStartAssessment.lock);
1017
1021
  clearLock(base);
1018
1022
  }
1019
1023
  if (!s.paused) {
@@ -0,0 +1,31 @@
1
+ /**
2
+ * crash-log.ts — Write crash diagnostics to ~/.gsd/crash/<timestamp>.log
3
+ *
4
+ * Zero cross-dependencies: only uses Node.js built-ins so it can be imported
5
+ * safely from uncaughtException / unhandledRejection handlers and from tests
6
+ * without pulling in the full extension dependency tree.
7
+ */
8
+ import { appendFileSync, mkdirSync } from "node:fs";
9
+ import { homedir } from "node:os";
10
+ import { join } from "node:path";
11
+ /**
12
+ * Write a crash log to ~/.gsd/crash/<timestamp>.log (or $GSD_HOME/crash/).
13
+ * Never throws — must be safe to call from any error handler.
14
+ */
15
+ export function writeCrashLog(err, source) {
16
+ try {
17
+ const crashDir = join(process.env.GSD_HOME ?? join(homedir(), ".gsd"), "crash");
18
+ mkdirSync(crashDir, { recursive: true });
19
+ const ts = new Date().toISOString().replace(/[:.]/g, "-");
20
+ const logPath = join(crashDir, `${ts}.log`);
21
+ const lines = [
22
+ `[gsd] ${source}: ${err.message}`,
23
+ `timestamp: ${new Date().toISOString()}`,
24
+ `pid: ${process.pid}`,
25
+ err.stack ?? "(no stack trace available)",
26
+ "",
27
+ ];
28
+ appendFileSync(logPath, lines.join("\n"));
29
+ }
30
+ catch { /* never throw from crash handler */ }
31
+ }
@@ -8,6 +8,8 @@ import { registerJournalTools } from "./journal-tools.js";
8
8
  import { registerQueryTools } from "./query-tools.js";
9
9
  import { registerHooks } from "./register-hooks.js";
10
10
  import { registerShortcuts } from "./register-shortcuts.js";
11
+ import { writeCrashLog } from "./crash-log.js";
12
+ export { writeCrashLog } from "./crash-log.js";
11
13
  export function handleRecoverableExtensionProcessError(err) {
12
14
  if (err.code === "EPIPE") {
13
15
  process.exit(0);
@@ -28,17 +30,26 @@ export function handleRecoverableExtensionProcessError(err) {
28
30
  function installEpipeGuard() {
29
31
  if (!process.listeners("uncaughtException").some((listener) => listener.name === "_gsdEpipeGuard")) {
30
32
  const _gsdEpipeGuard = (err) => {
31
- if (handleRecoverableExtensionProcessError(err)) {
33
+ if (handleRecoverableExtensionProcessError(err))
32
34
  return;
33
- }
34
- // Log unhandled errors instead of re-throwing throwing inside an
35
- // uncaughtException handler is a fatal double-fault in Node.js (#3163).
36
- process.stderr.write(`[gsd] uncaught extension error (non-fatal): ${err.message}\n`);
37
- if (err.stack)
38
- process.stderr.write(`${err.stack}\n`);
35
+ // Write crash log and exit cleanly for unrecoverable errors.
36
+ // Logging and continuing was the original double-fault fix (#3163), but
37
+ // continuing in an indeterminate state is worse than a clean exit (#3348).
38
+ writeCrashLog(err, "uncaughtException");
39
+ process.exit(1);
39
40
  };
40
41
  process.on("uncaughtException", _gsdEpipeGuard);
41
42
  }
43
+ if (!process.listeners("unhandledRejection").some((listener) => listener.name === "_gsdRejectionGuard")) {
44
+ const _gsdRejectionGuard = (reason, _promise) => {
45
+ const err = reason instanceof Error ? reason : new Error(String(reason));
46
+ if (handleRecoverableExtensionProcessError(err))
47
+ return;
48
+ writeCrashLog(err, "unhandledRejection");
49
+ process.exit(1);
50
+ };
51
+ process.on("unhandledRejection", _gsdRejectionGuard);
52
+ }
42
53
  }
43
54
  export function registerGsdExtension(pi) {
44
55
  registerGSDCommand(pi);
@@ -6,6 +6,7 @@ import { debugTime } from "../debug-logger.js";
6
6
  import { loadPrompt, getTemplatesDir } from "../prompt-loader.js";
7
7
  import { readForensicsMarker } from "../forensics.js";
8
8
  import { resolveAllSkillReferences, renderPreferencesForSystemPrompt, loadEffectiveGSDPreferences } from "../preferences.js";
9
+ import { resolveModelWithFallbacksForUnit } from "../preferences-models.js";
9
10
  import { resolveSkillReference } from "../preferences-skills.js";
10
11
  import { resolveGsdRootFile, resolveSliceFile, resolveSlicePath, resolveTaskFile, resolveTaskFiles, resolveTasksDir, relSliceFile, relSlicePath, relTaskFile } from "../paths.js";
11
12
  import { ensureCodebaseMapFresh, readCodebaseMap } from "../codebase-generator.js";
@@ -147,7 +148,11 @@ export async function buildBeforeAgentStartResult(event, ctx) {
147
148
  // Re-inject forensics context on follow-up turns (#2941)
148
149
  const forensicsInjection = !injection ? buildForensicsContextInjection(process.cwd(), event.prompt) : null;
149
150
  const worktreeBlock = buildWorktreeContextBlock();
150
- const fullSystem = `${event.systemPrompt}\n\n[SYSTEM CONTEXT — GSD]\n\n${systemContent}${preferenceBlock}${knowledgeBlock}${codebaseBlock}${memoryBlock}${newSkillsBlock}${worktreeBlock}`;
151
+ const subagentModelConfig = resolveModelWithFallbacksForUnit("subagent");
152
+ const subagentModelBlock = subagentModelConfig
153
+ ? `\n\n## Subagent Model\n\nWhen spawning subagents via the \`subagent\` tool, always pass \`model: "${subagentModelConfig.primary}"\` in the tool call parameters. Never omit this — always specify it explicitly.`
154
+ : "";
155
+ const fullSystem = `${event.systemPrompt}\n\n[SYSTEM CONTEXT — GSD]\n\n${systemContent}${preferenceBlock}${knowledgeBlock}${codebaseBlock}${memoryBlock}${newSkillsBlock}${worktreeBlock}${subagentModelBlock}`;
151
156
  stopContextTimer({
152
157
  systemPromptSize: fullSystem.length,
153
158
  injectionSize: injection?.length ?? forensicsInjection?.length ?? 0,
@@ -14,6 +14,7 @@ import { join } from "node:path";
14
14
  import { gsdRoot } from "./paths.js";
15
15
  import { atomicWriteSync } from "./atomic-write.js";
16
16
  import { effectiveLockFile } from "./session-lock.js";
17
+ import { emitJournalEvent, queryJournal } from "./journal.js";
17
18
  function lockPath(basePath) {
18
19
  return join(gsdRoot(basePath), effectiveLockFile());
19
20
  }
@@ -110,3 +111,53 @@ export function formatCrashInfo(lock) {
110
111
  }
111
112
  return lines.join("\n");
112
113
  }
114
+ /**
115
+ * Emit a synthetic unit-end event for a unit that crashed without emitting its own.
116
+ *
117
+ * Queries the journal to find the most recent unit-start for the crashed unit.
118
+ * If a matching unit-end already exists (e.g. the hard timeout fired), this is a
119
+ * no-op. Called during crash recovery, before clearing the stale lock.
120
+ *
121
+ * Addresses the gap reported in #3348 where `unit-start` was emitted but no
122
+ * `unit-end` followed — side effects landed but the worker died before closeout.
123
+ */
124
+ export function emitCrashRecoveredUnitEnd(basePath, lock) {
125
+ // Skip bootstrap / starting pseudo-units — they have no meaningful unit-start event.
126
+ if (!lock.unitType || !lock.unitId || lock.unitType === "starting")
127
+ return;
128
+ try {
129
+ const all = queryJournal(basePath);
130
+ // Find the most recent unit-start for this unitId
131
+ const starts = all.filter((e) => e.eventType === "unit-start" && e.data?.unitId === lock.unitId);
132
+ if (starts.length === 0)
133
+ return;
134
+ const lastStart = starts[starts.length - 1];
135
+ // Check if a unit-end was already emitted (e.g. hard timeout fired after the crash)
136
+ const alreadyClosed = all.some((e) => e.eventType === "unit-end" &&
137
+ e.data?.unitId === lock.unitId &&
138
+ e.causedBy?.flowId === lastStart.flowId &&
139
+ e.causedBy?.seq === lastStart.seq);
140
+ if (alreadyClosed)
141
+ return;
142
+ // Find the highest seq in this flow for monotonic ordering
143
+ const maxSeq = all
144
+ .filter((e) => e.flowId === lastStart.flowId)
145
+ .reduce((max, e) => Math.max(max, e.seq), lastStart.seq);
146
+ emitJournalEvent(basePath, {
147
+ ts: new Date().toISOString(),
148
+ flowId: lastStart.flowId,
149
+ seq: maxSeq + 1,
150
+ eventType: "unit-end",
151
+ data: {
152
+ unitType: lock.unitType,
153
+ unitId: lock.unitId,
154
+ status: "crash-recovered",
155
+ artifactVerified: false,
156
+ },
157
+ causedBy: { flowId: lastStart.flowId, seq: lastStart.seq },
158
+ });
159
+ }
160
+ catch {
161
+ // Never throw from crash recovery path — journal failure must not block recovery
162
+ }
163
+ }
@@ -1352,6 +1352,25 @@ export function setSliceSummaryMd(milestoneId, sliceId, summaryMd, uatMd) {
1352
1352
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1353
1353
  currentDb.prepare(`UPDATE slices SET full_summary_md = :summary_md, full_uat_md = :uat_md WHERE milestone_id = :mid AND id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId, ":summary_md": summaryMd, ":uat_md": uatMd });
1354
1354
  }
1355
+ function parseTaskArrayColumn(raw) {
1356
+ if (typeof raw !== "string" || raw.trim() === "")
1357
+ return [];
1358
+ try {
1359
+ const parsed = JSON.parse(raw);
1360
+ if (Array.isArray(parsed))
1361
+ return parsed.map((value) => String(value));
1362
+ if (parsed === null || parsed === undefined || parsed === "")
1363
+ return [];
1364
+ return [String(parsed)];
1365
+ }
1366
+ catch {
1367
+ // Older/corrupt rows may contain comma-separated strings instead of JSON.
1368
+ return raw
1369
+ .split(",")
1370
+ .map((value) => value.trim())
1371
+ .filter(Boolean);
1372
+ }
1373
+ }
1355
1374
  function rowToTask(row) {
1356
1375
  const parseTaskArray = (value) => {
1357
1376
  if (Array.isArray(value)) {
@@ -1390,8 +1409,8 @@ function rowToTask(row) {
1390
1409
  blocker_discovered: row["blocker_discovered"] === 1,
1391
1410
  deviations: row["deviations"],
1392
1411
  known_issues: row["known_issues"],
1393
- key_files: JSON.parse(row["key_files"] || "[]"),
1394
- key_decisions: JSON.parse(row["key_decisions"] || "[]"),
1412
+ key_files: parseTaskArrayColumn(row["key_files"]),
1413
+ key_decisions: parseTaskArrayColumn(row["key_decisions"]),
1395
1414
  full_summary_md: row["full_summary_md"],
1396
1415
  description: row["description"] ?? "",
1397
1416
  estimate: row["estimate"] ?? "",
@@ -1855,6 +1874,21 @@ export function deleteSlice(milestoneId, sliceId) {
1855
1874
  currentDb.prepare(`DELETE FROM slices WHERE milestone_id = :mid AND id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId });
1856
1875
  });
1857
1876
  }
1877
+ export function deleteMilestone(milestoneId) {
1878
+ if (!currentDb)
1879
+ throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
1880
+ transaction(() => {
1881
+ currentDb.prepare(`DELETE FROM verification_evidence WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
1882
+ currentDb.prepare(`DELETE FROM quality_gates WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
1883
+ currentDb.prepare(`DELETE FROM tasks WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
1884
+ currentDb.prepare(`DELETE FROM slice_dependencies WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
1885
+ currentDb.prepare(`DELETE FROM slices WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
1886
+ currentDb.prepare(`DELETE FROM replan_history WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
1887
+ currentDb.prepare(`DELETE FROM assessments WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
1888
+ currentDb.prepare(`DELETE FROM artifacts WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
1889
+ currentDb.prepare(`DELETE FROM milestones WHERE id = :mid`).run({ ":mid": milestoneId });
1890
+ });
1891
+ }
1858
1892
  export function updateSliceFields(milestoneId, sliceId, fields) {
1859
1893
  if (!currentDb)
1860
1894
  throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
@@ -15,7 +15,8 @@ import { join } from "node:path";
15
15
  import { resolveMilestonePath, resolveMilestoneFile, buildMilestoneFileName, } from "./paths.js";
16
16
  import { invalidateAllCaches } from "./cache.js";
17
17
  import { loadQueueOrder, saveQueueOrder } from "./queue-order.js";
18
- import { getMilestone, isDbAvailable, updateMilestoneStatus } from "./gsd-db.js";
18
+ import { deleteMilestone, getMilestone, isDbAvailable, updateMilestoneStatus } from "./gsd-db.js";
19
+ import { removeWorktree } from "./worktree-manager.js";
19
20
  import { logWarning } from "./workflow-logger.js";
20
21
  // ─── Park ──────────────────────────────────────────────────────────────────
21
22
  /**
@@ -99,12 +100,29 @@ export function discardMilestone(basePath, milestoneId) {
99
100
  const mDir = resolveMilestonePath(basePath, milestoneId);
100
101
  if (!mDir || !existsSync(mDir))
101
102
  return false;
103
+ try {
104
+ removeWorktree(basePath, milestoneId, {
105
+ branch: `milestone/${milestoneId}`,
106
+ deleteBranch: true,
107
+ });
108
+ }
109
+ catch (err) {
110
+ logWarning("engine", `discardMilestone worktree cleanup failed for ${milestoneId}: ${err.message}`);
111
+ }
102
112
  rmSync(mDir, { recursive: true, force: true });
103
113
  // Prune from queue order if present
104
114
  const order = loadQueueOrder(basePath);
105
115
  if (order && order.includes(milestoneId)) {
106
116
  saveQueueOrder(basePath, order.filter(id => id !== milestoneId));
107
117
  }
118
+ if (isDbAvailable()) {
119
+ try {
120
+ deleteMilestone(milestoneId);
121
+ }
122
+ catch (err) {
123
+ logWarning("engine", `discardMilestone DB cleanup failed for ${milestoneId}: ${err.message}`);
124
+ }
125
+ }
108
126
  invalidateAllCaches();
109
127
  return true;
110
128
  }
@@ -34,15 +34,18 @@ export function validateConfiguredModel(modelRegistry, settingsManager) {
34
34
  if (!configuredModel || !configuredExists) {
35
35
  // Model not configured at all, or removed from registry — pick a fallback.
36
36
  // Only fires when the model is genuinely unknown (not just temporarily unavailable).
37
+ //
38
+ // Model-agnostic selection order:
39
+ // 1. Pi migration default (preserves migration from ~/.pi install)
40
+ // 2. Any model from the user's previously-chosen provider (provider stickiness)
41
+ // 3. First available model in registry order (user-controlled via models.json)
37
42
  const piDefault = getPiDefaultModelAndProvider();
38
43
  const preferred = (piDefault
39
44
  ? availableModels.find((m) => m.provider === piDefault.provider && m.id === piDefault.model)
40
45
  : undefined) ||
41
- availableModels.find((m) => m.provider === 'openai' && m.id === 'gpt-5.4') ||
42
- availableModels.find((m) => m.provider === 'openai') ||
43
- availableModels.find((m) => m.provider === 'anthropic' && m.id === 'claude-opus-4-6') ||
44
- availableModels.find((m) => m.provider === 'anthropic' && m.id.includes('opus')) ||
45
- availableModels.find((m) => m.provider === 'anthropic') ||
46
+ (configuredProvider
47
+ ? availableModels.find((m) => m.provider === configuredProvider)
48
+ : undefined) ||
46
49
  availableModels[0];
47
50
  if (preferred) {
48
51
  settingsManager.setDefaultModelAndProvider(preferred.provider, preferred.id);
@@ -1 +1 @@
1
- KSZ2dcC3p4z6lOmUpPpzr
1
+ cGmbVq2su4f9tMpgIkG8u
@@ -1,44 +1,44 @@
1
1
  {
2
2
  "/_not-found/page": "/_not-found",
3
3
  "/_global-error/page": "/_global-error",
4
- "/api/bridge-terminal/resize/route": "/api/bridge-terminal/resize",
5
4
  "/api/bridge-terminal/input/route": "/api/bridge-terminal/input",
6
5
  "/api/boot/route": "/api/boot",
6
+ "/api/bridge-terminal/resize/route": "/api/bridge-terminal/resize",
7
7
  "/api/bridge-terminal/stream/route": "/api/bridge-terminal/stream",
8
8
  "/api/dev-mode/route": "/api/dev-mode",
9
9
  "/api/cleanup/route": "/api/cleanup",
10
10
  "/api/doctor/route": "/api/doctor",
11
- "/api/captures/route": "/api/captures",
12
11
  "/api/export-data/route": "/api/export-data",
13
- "/api/forensics/route": "/api/forensics",
14
12
  "/api/browse-directories/route": "/api/browse-directories",
13
+ "/api/captures/route": "/api/captures",
14
+ "/api/forensics/route": "/api/forensics",
15
15
  "/api/git/route": "/api/git",
16
- "/api/hooks/route": "/api/hooks",
17
16
  "/api/history/route": "/api/history",
17
+ "/api/hooks/route": "/api/hooks",
18
18
  "/api/inspect/route": "/api/inspect",
19
19
  "/api/knowledge/route": "/api/knowledge",
20
- "/api/notifications/route": "/api/notifications",
20
+ "/api/experimental/route": "/api/experimental",
21
21
  "/api/live-state/route": "/api/live-state",
22
+ "/api/notifications/route": "/api/notifications",
22
23
  "/api/preferences/route": "/api/preferences",
23
- "/api/experimental/route": "/api/experimental",
24
- "/api/onboarding/route": "/api/onboarding",
25
24
  "/api/recovery/route": "/api/recovery",
25
+ "/api/onboarding/route": "/api/onboarding",
26
26
  "/api/projects/route": "/api/projects",
27
27
  "/api/session/browser/route": "/api/session/browser",
28
28
  "/api/session/command/route": "/api/session/command",
29
+ "/api/session/events/route": "/api/session/events",
29
30
  "/api/session/manage/route": "/api/session/manage",
30
31
  "/api/settings-data/route": "/api/settings-data",
31
- "/api/session/events/route": "/api/session/events",
32
32
  "/api/shutdown/route": "/api/shutdown",
33
33
  "/api/skill-health/route": "/api/skill-health",
34
34
  "/api/steer/route": "/api/steer",
35
- "/api/files/route": "/api/files",
36
35
  "/api/terminal/input/route": "/api/terminal/input",
37
36
  "/api/terminal/resize/route": "/api/terminal/resize",
38
- "/api/terminal/sessions/route": "/api/terminal/sessions",
37
+ "/api/files/route": "/api/files",
39
38
  "/api/switch-root/route": "/api/switch-root",
40
- "/api/terminal/stream/route": "/api/terminal/stream",
39
+ "/api/terminal/sessions/route": "/api/terminal/sessions",
41
40
  "/api/terminal/upload/route": "/api/terminal/upload",
41
+ "/api/terminal/stream/route": "/api/terminal/stream",
42
42
  "/api/visualizer/route": "/api/visualizer",
43
43
  "/api/undo/route": "/api/undo",
44
44
  "/api/update/route": "/api/update",
@@ -4,14 +4,14 @@
4
4
  ],
5
5
  "devFiles": [],
6
6
  "lowPriorityFiles": [
7
- "static/KSZ2dcC3p4z6lOmUpPpzr/_buildManifest.js",
8
- "static/KSZ2dcC3p4z6lOmUpPpzr/_ssgManifest.js"
7
+ "static/cGmbVq2su4f9tMpgIkG8u/_buildManifest.js",
8
+ "static/cGmbVq2su4f9tMpgIkG8u/_ssgManifest.js"
9
9
  ],
10
10
  "rootMainFiles": [
11
11
  "static/chunks/webpack-b868033a5834586d.js",
12
12
  "static/chunks/4bd1b696-e356ca5ba0218e27.js",
13
13
  "static/chunks/3794-42fdce068d44fa4f.js",
14
- "static/chunks/main-app-d3d4c336195465f9.js"
14
+ "static/chunks/main-app-fdab67f7802d7832.js"
15
15
  ],
16
16
  "rootMainFilesTree": {},
17
17
  "pages": {
@@ -78,8 +78,8 @@
78
78
  "dynamicRoutes": {},
79
79
  "notFoundRoutes": [],
80
80
  "preview": {
81
- "previewModeId": "a5b55541bc3e0fa2f07c4087828bfdb9",
82
- "previewModeSigningKey": "1d263a5202d738e962bd891f42fec4583353ecdb77162ca3b09f7da49aa38e9c",
83
- "previewModeEncryptionKey": "82afb9b7e120d168495c89adfe9fcfe9feb930812ef95d0fe02a2f0d3c075948"
81
+ "previewModeId": "17f5d57cb01dfbb2206069fd8f426e90",
82
+ "previewModeSigningKey": "4d7c58c0c991aa3523143e4ea3d4c0ff316057413ab7d8fe3a226758b7a4e635",
83
+ "previewModeEncryptionKey": "0b5fb58eaf785e54b64512118db11f3096a2a9eda097e442828f917e80028bfc"
84
84
  }
85
85
  }
@@ -104,7 +104,7 @@
104
104
  "transform": "lodash/{{member}}"
105
105
  }
106
106
  },
107
- "outputFileTracingRoot": "/home/runner/_work/gsd-2/gsd-2",
107
+ "outputFileTracingRoot": "/__w/gsd-2/gsd-2",
108
108
  "cacheComponents": false,
109
109
  "cacheLife": {
110
110
  "default": {
@@ -308,11 +308,11 @@
308
308
  "node-pty"
309
309
  ],
310
310
  "turbopack": {
311
- "root": "/home/runner/_work/gsd-2/gsd-2"
311
+ "root": "/__w/gsd-2/gsd-2"
312
312
  },
313
313
  "distDirRoot": ".next"
314
314
  },
315
- "appDir": "/home/runner/_work/gsd-2/gsd-2/web",
315
+ "appDir": "/__w/gsd-2/gsd-2/web",
316
316
  "relativeAppDir": "web",
317
317
  "files": [
318
318
  ".next/routes-manifest.json",