gsd-pi 2.79.0-dev.ece5fd8ba → 2.80.0

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 (193) hide show
  1. package/dist/loader.js +0 -0
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/extensions/gsd/auto/contracts.js +1 -0
  4. package/dist/resources/extensions/gsd/auto/orchestrator.js +146 -0
  5. package/dist/resources/extensions/gsd/auto/phases.js +55 -6
  6. package/dist/resources/extensions/gsd/auto/session.js +8 -0
  7. package/dist/resources/extensions/gsd/auto-recovery.js +45 -52
  8. package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -0
  9. package/dist/resources/extensions/gsd/auto.js +159 -2
  10. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +9 -1
  11. package/dist/resources/extensions/gsd/gsd-db.js +34 -1
  12. package/dist/resources/extensions/gsd/post-execution-checks.js +25 -6
  13. package/dist/resources/extensions/shared/interview-ui.js +15 -4
  14. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  15. package/dist/web/standalone/.next/BUILD_ID +1 -1
  16. package/dist/web/standalone/.next/app-path-routes-manifest.json +15 -15
  17. package/dist/web/standalone/.next/build-manifest.json +3 -3
  18. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  19. package/dist/web/standalone/.next/required-server-files.json +3 -3
  20. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  21. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  22. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  23. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  24. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  25. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  26. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  28. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  30. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  31. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  32. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  33. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  34. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  35. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  36. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  37. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  38. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  39. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  40. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  41. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  42. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  43. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  44. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  45. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  46. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  47. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  48. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  49. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  50. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  51. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  52. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  53. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  54. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  55. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  56. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  57. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  58. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  59. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  60. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  61. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  62. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  63. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  64. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  65. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  66. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  67. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  68. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  69. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  70. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  71. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  72. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  73. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  74. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  79. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  82. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  87. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  89. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  93. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  95. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  111. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
  115. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/index.html +1 -1
  125. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  126. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  127. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  128. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  130. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/page.js +2 -2
  132. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app-paths-manifest.json +15 -15
  134. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  135. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  136. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/middleware.js +2 -2
  138. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  140. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  141. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  142. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  143. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
  144. package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
  145. package/dist/web/standalone/.next/static/chunks/app/page-ff639266d978f2a0.js +1 -0
  146. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
  147. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
  148. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  149. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  150. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  151. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  152. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  153. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  154. package/dist/web/standalone/server.js +1 -1
  155. package/package.json +1 -1
  156. package/packages/daemon/package.json +2 -2
  157. package/packages/mcp-server/package.json +2 -2
  158. package/packages/native/package.json +1 -1
  159. package/packages/pi-agent-core/package.json +1 -1
  160. package/packages/pi-ai/package.json +1 -1
  161. package/packages/pi-coding-agent/package.json +1 -1
  162. package/packages/pi-tui/package.json +1 -1
  163. package/packages/rpc-client/package.json +1 -1
  164. package/pkg/package.json +1 -1
  165. package/src/resources/extensions/gsd/auto/contracts.ts +87 -0
  166. package/src/resources/extensions/gsd/auto/loop-deps.ts +10 -3
  167. package/src/resources/extensions/gsd/auto/orchestrator.ts +161 -0
  168. package/src/resources/extensions/gsd/auto/phases.ts +82 -8
  169. package/src/resources/extensions/gsd/auto/session.ts +11 -0
  170. package/src/resources/extensions/gsd/auto-recovery.ts +42 -50
  171. package/src/resources/extensions/gsd/auto-runtime-state.ts +7 -0
  172. package/src/resources/extensions/gsd/auto.ts +167 -1
  173. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +14 -1
  174. package/src/resources/extensions/gsd/gsd-db.ts +35 -1
  175. package/src/resources/extensions/gsd/interrupted-session.ts +1 -0
  176. package/src/resources/extensions/gsd/post-execution-checks.ts +31 -6
  177. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +32 -0
  178. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +353 -0
  179. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +39 -0
  180. package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +3 -0
  181. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +95 -0
  182. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +79 -0
  183. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +134 -0
  184. package/src/resources/extensions/gsd/tests/paused-session-via-db.test.ts +2 -0
  185. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +27 -0
  186. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +46 -0
  187. package/src/resources/extensions/shared/interview-ui.ts +18 -5
  188. package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +41 -0
  189. package/dist/web/standalone/.next/static/chunks/app/page-fab3ebb85b006001.js +0 -1
  190. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
  191. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
  192. /package/dist/web/standalone/.next/static/{TzEVJ1Lh8vbez4n4Q9TqQ → V-3Ehy4B24f9FCGiLPWIM}/_buildManifest.js +0 -0
  193. /package/dist/web/standalone/.next/static/{TzEVJ1Lh8vbez4n4Q9TqQ → V-3Ehy4B24f9FCGiLPWIM}/_ssgManifest.js +0 -0
@@ -147,6 +147,7 @@ import {
147
147
  MergeConflictError,
148
148
  parseSliceBranch,
149
149
  setActiveMilestoneId,
150
+ resolveProjectRoot,
150
151
  } from "./worktree.js";
151
152
  import { GitServiceImpl } from "./git-service.js";
152
153
  import { getPriorSliceCompletionBlocker } from "./dispatch-guard.js";
@@ -231,6 +232,8 @@ import type { ErrorContext } from "./auto/types.js";
231
232
  import { runAutoLoopWithUok } from "./uok/kernel.js";
232
233
  import { resolveUokFlags } from "./uok/flags.js";
233
234
  import { validateDirectory } from "./validate-directory.js";
235
+ import { createAutoOrchestrator } from "./auto/orchestrator.js";
236
+ import type { AutoOrchestrationModule, AutoOrchestratorDeps } from "./auto/contracts.js";
234
237
  // Slice-level parallelism (#2340)
235
238
  import { getEligibleSlices } from "./slice-parallel-eligibility.js";
236
239
  import { startSliceParallel } from "./slice-parallel-orchestrator.js";
@@ -1208,6 +1211,12 @@ export async function stopAuto(
1208
1211
  // changes the user made between sessions (#4959 / CodeRabbit).
1209
1212
  if (pi) clearToolBaseline(pi);
1210
1213
 
1214
+ try {
1215
+ await s.orchestration?.stop(reason ?? "stop");
1216
+ } catch (err) {
1217
+ debugLog("stop-orchestration-stop", { error: err instanceof Error ? err.message : String(err) });
1218
+ }
1219
+
1211
1220
  // Reset all session state in one call
1212
1221
  s.reset();
1213
1222
  }
@@ -1264,6 +1273,7 @@ export async function pauseAuto(
1264
1273
  activeRunDir: s.activeRunDir,
1265
1274
  autoStartTime: s.autoStartTime,
1266
1275
  milestoneLock: s.sessionMilestoneLock ?? undefined,
1276
+ pauseReason: _errorContext?.message,
1267
1277
  };
1268
1278
  setRuntimeKv("global", "", PAUSED_SESSION_KV_KEY, pausedMeta);
1269
1279
  } catch (err) {
@@ -1306,6 +1316,12 @@ export async function pauseAuto(
1306
1316
  resolveAgentEnd({ messages: [] });
1307
1317
  _resetPendingResolve();
1308
1318
 
1319
+ try {
1320
+ await s.orchestration?.stop("pause");
1321
+ } catch (err) {
1322
+ debugLog("pause-orchestration-stop", { error: err instanceof Error ? err.message : String(err) });
1323
+ }
1324
+
1309
1325
  s.active = false;
1310
1326
  s.paused = true;
1311
1327
  deactivateGSD();
@@ -1363,6 +1379,141 @@ function buildResolver(): WorktreeResolver {
1363
1379
  return new WorktreeResolver(s, buildResolverDeps());
1364
1380
  }
1365
1381
 
1382
+ /**
1383
+ * Thin entry glue for the new Auto Orchestration module.
1384
+ *
1385
+ * This intentionally wires only dispatch + error notification today, with
1386
+ * no behavior changes to the existing auto loop. It provides a concrete seam
1387
+ * the next refactor steps can adopt incrementally.
1388
+ */
1389
+ export function createWiredAutoOrchestrationModule(
1390
+ ctx: ExtensionContext,
1391
+ _pi: ExtensionAPI,
1392
+ dispatchBasePath: string,
1393
+ runtimeBasePath = resolveProjectRoot(dispatchBasePath),
1394
+ ): AutoOrchestrationModule {
1395
+ const flowId = `auto-orchestrator-${Date.now()}`;
1396
+ let seq = 0;
1397
+
1398
+ const deps: AutoOrchestratorDeps = {
1399
+ dispatch: {
1400
+ async decideNextUnit() {
1401
+ const state = await deriveState(dispatchBasePath);
1402
+ const active = state.activeMilestone;
1403
+ if (!active) return null;
1404
+
1405
+ const prefs = loadEffectiveGSDPreferences(dispatchBasePath)?.preferences;
1406
+ const action = await resolveDispatch({
1407
+ basePath: dispatchBasePath,
1408
+ mid: active.id,
1409
+ midTitle: active.title,
1410
+ state,
1411
+ prefs,
1412
+ });
1413
+
1414
+ if (action.action !== "dispatch") return null;
1415
+ return {
1416
+ unitType: action.unitType,
1417
+ unitId: action.unitId,
1418
+ reason: action.matchedRule ?? "dispatch",
1419
+ preconditions: [],
1420
+ };
1421
+ },
1422
+ },
1423
+ recovery: {
1424
+ async classifyAndRecover(input) {
1425
+ const reason = input.error instanceof Error ? input.error.message : String(input.error ?? "unknown auto error");
1426
+ return { action: "escalate" as const, reason };
1427
+ },
1428
+ },
1429
+ worktree: {
1430
+ async prepareForUnit() {},
1431
+ async syncAfterUnit() {},
1432
+ async cleanupOnStop() {},
1433
+ },
1434
+ health: {
1435
+ async preAdvanceGate() {
1436
+ const gate = await preDispatchHealthGate(dispatchBasePath);
1437
+ return {
1438
+ allow: gate.proceed,
1439
+ reason: gate.reason,
1440
+ };
1441
+ },
1442
+ async postAdvanceRecord(result) {
1443
+ if (result.kind === "error") {
1444
+ recordHealthSnapshot(1, 0, 0, [{
1445
+ code: "orchestration-error",
1446
+ message: result.reason ?? "orchestration error",
1447
+ severity: "error",
1448
+ unitId: "orchestration",
1449
+ }], [], "orchestration");
1450
+ } else if (result.kind === "blocked") {
1451
+ recordHealthSnapshot(0, 1, 0, [{
1452
+ code: "orchestration-blocked",
1453
+ message: result.reason ?? "orchestration blocked",
1454
+ severity: "warning",
1455
+ unitId: "orchestration",
1456
+ }], [], "orchestration");
1457
+ }
1458
+ },
1459
+ },
1460
+ runtime: {
1461
+ async ensureLockOwnership() {
1462
+ const status = getSessionLockStatus(runtimeBasePath);
1463
+ if (!status.valid || status.failureReason === "pid-mismatch") {
1464
+ throw new Error("session lock held by another process");
1465
+ }
1466
+ },
1467
+ async journalTransition(event) {
1468
+ const eventType = event.name === "start"
1469
+ ? "iteration-start"
1470
+ : event.name === "resume"
1471
+ ? "iteration-start"
1472
+ : event.name === "advance"
1473
+ ? "dispatch-match"
1474
+ : event.name === "advance-blocked"
1475
+ ? "guard-block"
1476
+ : event.name === "advance-stopped"
1477
+ ? "dispatch-stop"
1478
+ : event.name === "advance-error"
1479
+ ? "iteration-end"
1480
+ : event.name === "advance-paused" || event.name === "advance-retry"
1481
+ ? "guard-block"
1482
+ : event.name === "stop"
1483
+ ? "terminal"
1484
+ : "iteration-end";
1485
+
1486
+ _emitJournalEvent(runtimeBasePath, {
1487
+ ts: new Date().toISOString(),
1488
+ flowId,
1489
+ seq: ++seq,
1490
+ eventType,
1491
+ data: {
1492
+ source: "auto-orchestrator",
1493
+ name: event.name,
1494
+ reason: event.reason,
1495
+ unitType: event.unitType,
1496
+ unitId: event.unitId,
1497
+ },
1498
+ });
1499
+ },
1500
+ },
1501
+ notifications: {
1502
+ async notifyLifecycle(event) {
1503
+ if (event.name === "error") {
1504
+ ctx.ui.notify(event.detail ?? "auto orchestration error", "error");
1505
+ }
1506
+ },
1507
+ },
1508
+ };
1509
+
1510
+ return createAutoOrchestrator(deps);
1511
+ }
1512
+
1513
+ function ensureOrchestrationModule(ctx: ExtensionContext, pi: ExtensionAPI, basePath: string): void {
1514
+ s.orchestration = createWiredAutoOrchestrationModule(ctx, pi, basePath, lockBase());
1515
+ }
1516
+
1366
1517
  /**
1367
1518
  * Build the LoopDeps object from auto.ts private scope.
1368
1519
  * This bundles all private functions that autoLoop needs without exporting them.
@@ -1785,6 +1936,7 @@ export async function startAuto(
1785
1936
  rebuildScope(s.basePath, s.currentMilestoneId);
1786
1937
  }
1787
1938
 
1939
+ ensureOrchestrationModule(ctx, pi, s.basePath || base);
1788
1940
  registerSigtermHandler(lockBase());
1789
1941
 
1790
1942
  ctx.ui.setStatus("gsd-auto", s.stepMode ? "next" : "auto");
@@ -1868,6 +2020,11 @@ export async function startAuto(
1868
2020
  }
1869
2021
  pi.events.emit(CMUX_CHANNELS.LOG, { preferences: loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, message: s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.", level: "progress" });
1870
2022
 
2023
+ try {
2024
+ await s.orchestration?.resume();
2025
+ } catch (err) {
2026
+ debugLog("resume-orchestration-resume", { error: err instanceof Error ? err.message : String(err) });
2027
+ }
1871
2028
  startAutoCommandPolling(s.basePath);
1872
2029
  await runAutoLoopWithUok({
1873
2030
  ctx,
@@ -1904,7 +2061,7 @@ export async function startAuto(
1904
2061
  // Build scope after bootstrap has populated s.basePath / s.originalBasePath /
1905
2062
  // s.currentMilestoneId (including worktree setup inside bootstrapAutoSession).
1906
2063
  rebuildScope(s.basePath, s.currentMilestoneId);
1907
-
2064
+ ensureOrchestrationModule(ctx, pi, s.basePath || base);
1908
2065
  captureProjectRootEnv(s.originalBasePath || s.basePath);
1909
2066
  registerAutoWorkerForSession(s);
1910
2067
  try {
@@ -1915,6 +2072,12 @@ export async function startAuto(
1915
2072
  }
1916
2073
  pi.events.emit(CMUX_CHANNELS.LOG, { preferences: loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, message: requestedStepMode ? "Step-mode started." : "Auto-mode started.", level: "progress" });
1917
2074
 
2075
+ try {
2076
+ await s.orchestration?.start({ basePath: s.basePath, trigger: "auto-loop" });
2077
+ } catch (err) {
2078
+ debugLog("start-orchestration-start", { error: err instanceof Error ? err.message : String(err) });
2079
+ }
2080
+
1918
2081
  startAutoCommandPolling(s.basePath);
1919
2082
 
1920
2083
  // Dispatch the first unit
@@ -2037,6 +2200,9 @@ export async function dispatchHookUnit(
2037
2200
  }
2038
2201
 
2039
2202
  s.basePath = targetBasePath;
2203
+ if (!s.orchestration) {
2204
+ ensureOrchestrationModule(ctx, pi, s.basePath);
2205
+ }
2040
2206
 
2041
2207
  const hookUnitType = `hook/${hookName}`;
2042
2208
  const hookStartedAt = Date.now();
@@ -56,6 +56,19 @@ function resolveAgentEndBasePath(): string | undefined {
56
56
  }
57
57
  }
58
58
 
59
+ export function _buildAbortedPauseContext(lastMsg: { errorMessage?: unknown }): {
60
+ message: string;
61
+ category: "aborted";
62
+ isTransient: true;
63
+ } {
64
+ const hasErrorMessage = Object.prototype.hasOwnProperty.call(lastMsg, "errorMessage") && !!lastMsg.errorMessage;
65
+ return {
66
+ message: hasErrorMessage ? String(lastMsg.errorMessage) : "Operation aborted",
67
+ category: "aborted",
68
+ isTransient: true,
69
+ };
70
+ }
71
+
59
72
  async function pauseTransientWithBackoff(
60
73
  cls: ErrorClass,
61
74
  pi: ExtensionAPI,
@@ -159,7 +172,7 @@ export async function handleAgentEnd(
159
172
  return;
160
173
  }
161
174
 
162
- await pauseAuto(ctx, pi);
175
+ await pauseAuto(ctx, pi, _buildAbortedPauseContext(lastMsg as { errorMessage?: unknown }));
163
176
  return;
164
177
  }
165
178
  if (lastMsg && "stopReason" in lastMsg && lastMsg.stopReason === "error") {
@@ -753,6 +753,11 @@ function columnExists(db: DbAdapter, table: string, column: string): boolean {
753
753
  return rows.some((row) => row["name"] === column);
754
754
  }
755
755
 
756
+ function formatFtsUnavailableError(err: unknown): string {
757
+ const message = err instanceof Error ? err.message : String(err);
758
+ return message.replace(/\bmoduel\s*:\s*/gi, "module: ");
759
+ }
760
+
756
761
  /**
757
762
  * Create the FTS5 virtual table for memories plus the triggers that keep it
758
763
  * in sync with the base table. FTS5 may be unavailable on stripped-down
@@ -787,7 +792,7 @@ export function tryCreateMemoriesFts(db: DbAdapter): boolean {
787
792
  `);
788
793
  return true;
789
794
  } catch (err) {
790
- logWarning("db", `FTS5 unavailable — memory queries will use LIKE fallback: ${(err as Error).message}`);
795
+ logWarning("db", `FTS5 unavailable — memory queries will use LIKE fallback: ${formatFtsUnavailableError(err)}`);
791
796
  return false;
792
797
  }
793
798
  }
@@ -1740,6 +1745,35 @@ export function closeDatabase(): void {
1740
1745
  _lastDbPhase = null;
1741
1746
  }
1742
1747
 
1748
+ /**
1749
+ * Re-open the active database connection from disk.
1750
+ *
1751
+ * Auto-mode can observe artifacts written by a workflow server running in a
1752
+ * different process before its long-lived singleton has re-synchronized. The
1753
+ * recovery path uses this to force the next state derivation to read from the
1754
+ * current on-disk database instead of continuing with a possibly stale handle.
1755
+ */
1756
+ export function refreshOpenDatabaseFromDisk(): boolean {
1757
+ if (!currentDb || !currentPath) return false;
1758
+ if (currentPath === ":memory:") return false;
1759
+
1760
+ const dbPath = currentPath;
1761
+ const identityKey = _currentIdentityKey;
1762
+
1763
+ try {
1764
+ closeDatabase();
1765
+ const opened = openDatabase(dbPath);
1766
+ if (opened && identityKey && currentDb) {
1767
+ _dbCache.set(identityKey, { dbPath, db: currentDb });
1768
+ _currentIdentityKey = identityKey;
1769
+ }
1770
+ return opened;
1771
+ } catch (e) {
1772
+ logWarning("db", `database refresh failed: ${(e as Error).message}`);
1773
+ return false;
1774
+ }
1775
+ }
1776
+
1743
1777
  /** Run a full VACUUM — call sparingly (e.g. after milestone completion). */
1744
1778
  export function vacuumDatabase(): void {
1745
1779
  if (!currentDb) return;
@@ -37,6 +37,7 @@ export interface PausedSessionMetadata {
37
37
  activeRunDir?: string | null;
38
38
  autoStartTime?: number;
39
39
  milestoneLock?: string | null;
40
+ pauseReason?: string;
40
41
  }
41
42
 
42
43
  export interface InterruptedSessionAssessment {
@@ -144,12 +144,30 @@ export function resolveImportPath(
144
144
  if (existsSync(directPath)) {
145
145
  return { exists: true, resolvedPath: directPath };
146
146
  }
147
- // Only .js/.jsx/.mjs/.cjs imports legitimately fall through for the TS
148
- // ESM convention (.js .ts). Any other explicit extension (.css, .json,
149
- // .svg, images, fonts, .ts, .tsx, …) must stay unresolved when the direct
150
- // path is missing otherwise a stray `./missing.css.ts` could shadow a
151
- // genuinely missing `./missing.css` import.
152
- if (![".js", ".jsx", ".mjs", ".cjs"].includes(explicitExt)) {
147
+
148
+ // Known concrete extensions that should NOT fall through to code-shadow
149
+ // probing when missing. This preserves the "missing.css must stay missing"
150
+ // guarantee while still allowing dotted module stems like ./route.server
151
+ // to resolve as ./route.server.ts.
152
+ const nonFallbackExtensions = new Set([
153
+ ".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs",
154
+ ".json", ".css", ".scss", ".sass", ".less", ".styl",
155
+ ".svg", ".png", ".jpg", ".jpeg", ".gif", ".webp", ".avif", ".ico", ".bmp",
156
+ ".woff", ".woff2", ".ttf", ".otf", ".eot",
157
+ ]);
158
+ const runtimeFallbackExtensions = new Set([".js", ".jsx", ".mjs", ".cjs"]);
159
+ const dottedStemFallbackExtensions = new Set([".server", ".client", ".webhook"]);
160
+
161
+ if (
162
+ explicitExt !== "" &&
163
+ !runtimeFallbackExtensions.has(explicitExt) &&
164
+ !nonFallbackExtensions.has(explicitExt) &&
165
+ !dottedStemFallbackExtensions.has(explicitExt)
166
+ ) {
167
+ return { exists: false, resolvedPath: null };
168
+ }
169
+
170
+ if (nonFallbackExtensions.has(explicitExt) && !runtimeFallbackExtensions.has(explicitExt)) {
153
171
  return { exists: false, resolvedPath: null };
154
172
  }
155
173
  }
@@ -222,6 +240,13 @@ export function checkImportResolution(
222
240
  const imports = extractRelativeImports(source);
223
241
 
224
242
  for (const { importPath, lineNum } of imports) {
243
+ // React Router generated +types modules may not exist on disk during
244
+ // post-exec checks (generated during framework build). Don't block task
245
+ // completion on these imports.
246
+ if (/^\.{1,2}\/\+types\//.test(importPath)) {
247
+ continue;
248
+ }
249
+
225
250
  const resolution = resolveImportPath(importPath, file, basePath);
226
251
 
227
252
  if (!resolution.exists) {
@@ -0,0 +1,32 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+
4
+ import { _buildAbortedPauseContext } from "../bootstrap/agent-end-recovery.js";
5
+ import { _buildCancelledUnitStopReason } from "../auto/phases.js";
6
+
7
+ test("aborted agent_end maps errorMessage into structured aborted pause context", () => {
8
+ const withMessage = _buildAbortedPauseContext({ errorMessage: "provider aborted request" });
9
+ assert.deepEqual(withMessage, {
10
+ message: "provider aborted request",
11
+ category: "aborted",
12
+ isTransient: true,
13
+ });
14
+
15
+ const withoutMessage = _buildAbortedPauseContext({});
16
+ assert.deepEqual(withoutMessage, {
17
+ message: "Operation aborted",
18
+ category: "aborted",
19
+ isTransient: true,
20
+ });
21
+ });
22
+
23
+ test("cancelled non-session failures are labeled as unit aborts (not session-creation failures)", () => {
24
+ const cancelled = _buildCancelledUnitStopReason("execute-task", "M001-S001-T001", {
25
+ category: "aborted",
26
+ message: "tool invocation cancelled",
27
+ });
28
+
29
+ assert.match(cancelled.notifyMessage, /aborted after dispatch/);
30
+ assert.equal(cancelled.stopReason, "Unit aborted: tool invocation cancelled");
31
+ assert.equal(cancelled.loopReason, "unit-aborted");
32
+ });