@useorgx/openclaw-plugin 0.7.8 → 0.7.15

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 (203) hide show
  1. package/README.md +94 -122
  2. package/dashboard/dist/assets/0RUEVzJa.js +1 -0
  3. package/dashboard/dist/assets/0RUEVzJa.js.br +0 -0
  4. package/dashboard/dist/assets/0RUEVzJa.js.gz +0 -0
  5. package/dashboard/dist/assets/3TtV4moZ.js +1 -0
  6. package/dashboard/dist/assets/3TtV4moZ.js.br +0 -0
  7. package/dashboard/dist/assets/3TtV4moZ.js.gz +0 -0
  8. package/dashboard/dist/assets/3VwNyxUf.js +1 -0
  9. package/dashboard/dist/assets/3VwNyxUf.js.br +0 -0
  10. package/dashboard/dist/assets/3VwNyxUf.js.gz +0 -0
  11. package/dashboard/dist/assets/{DpuQm1oF.js → 7DhYqBrM.js} +2 -2
  12. package/dashboard/dist/assets/7DhYqBrM.js.br +0 -0
  13. package/dashboard/dist/assets/7DhYqBrM.js.gz +0 -0
  14. package/dashboard/dist/assets/{tcEHYcbW.js → BCudUvwg.js} +1 -1
  15. package/dashboard/dist/assets/BCudUvwg.js.br +0 -0
  16. package/dashboard/dist/assets/BCudUvwg.js.gz +0 -0
  17. package/dashboard/dist/assets/BV0BcV1u.js +53 -0
  18. package/dashboard/dist/assets/BV0BcV1u.js.br +0 -0
  19. package/dashboard/dist/assets/BV0BcV1u.js.gz +0 -0
  20. package/dashboard/dist/assets/BVvffj0x.js +1 -0
  21. package/dashboard/dist/assets/BVvffj0x.js.br +0 -0
  22. package/dashboard/dist/assets/BVvffj0x.js.gz +0 -0
  23. package/dashboard/dist/assets/BiOgVMED.js +1 -0
  24. package/dashboard/dist/assets/BiOgVMED.js.br +0 -0
  25. package/dashboard/dist/assets/BiOgVMED.js.gz +0 -0
  26. package/dashboard/dist/assets/BjK42gtU.js +1 -0
  27. package/dashboard/dist/assets/BjK42gtU.js.br +0 -0
  28. package/dashboard/dist/assets/BjK42gtU.js.gz +0 -0
  29. package/dashboard/dist/assets/C-MOJWHs.js +1 -0
  30. package/dashboard/dist/assets/C-MOJWHs.js.br +0 -0
  31. package/dashboard/dist/assets/C-MOJWHs.js.gz +0 -0
  32. package/dashboard/dist/assets/C91KLKit.js +1 -0
  33. package/dashboard/dist/assets/C91KLKit.js.br +0 -0
  34. package/dashboard/dist/assets/C91KLKit.js.gz +0 -0
  35. package/dashboard/dist/assets/{CnitK1MX.js → C9fvfXmS.js} +1 -1
  36. package/dashboard/dist/assets/C9fvfXmS.js.br +0 -0
  37. package/dashboard/dist/assets/C9fvfXmS.js.gz +0 -0
  38. package/dashboard/dist/assets/CFZ4Swr5.js +1 -0
  39. package/dashboard/dist/assets/CFZ4Swr5.js.br +0 -0
  40. package/dashboard/dist/assets/CFZ4Swr5.js.gz +0 -0
  41. package/dashboard/dist/assets/{77gGFBt6.js → CGj8kRhg.js} +1 -1
  42. package/dashboard/dist/assets/CGj8kRhg.js.br +0 -0
  43. package/dashboard/dist/assets/CGj8kRhg.js.gz +0 -0
  44. package/dashboard/dist/assets/CJjEAGFN.js +1 -0
  45. package/dashboard/dist/assets/CJjEAGFN.js.br +0 -0
  46. package/dashboard/dist/assets/CJjEAGFN.js.gz +0 -0
  47. package/dashboard/dist/assets/CKrH5fYO.js +1 -0
  48. package/dashboard/dist/assets/CKrH5fYO.js.br +0 -0
  49. package/dashboard/dist/assets/CKrH5fYO.js.gz +0 -0
  50. package/dashboard/dist/assets/CMTTPXch.js +1 -0
  51. package/dashboard/dist/assets/CMTTPXch.js.br +0 -0
  52. package/dashboard/dist/assets/CMTTPXch.js.gz +0 -0
  53. package/dashboard/dist/assets/CSlBSRyv.js +1 -0
  54. package/dashboard/dist/assets/CSlBSRyv.js.br +0 -0
  55. package/dashboard/dist/assets/CSlBSRyv.js.gz +0 -0
  56. package/dashboard/dist/assets/CnPC783_.js +1 -0
  57. package/dashboard/dist/assets/CnPC783_.js.br +0 -0
  58. package/dashboard/dist/assets/CnPC783_.js.gz +0 -0
  59. package/dashboard/dist/assets/Ctw95IkC.js +1 -0
  60. package/dashboard/dist/assets/Ctw95IkC.js.br +0 -0
  61. package/dashboard/dist/assets/Ctw95IkC.js.gz +0 -0
  62. package/dashboard/dist/assets/DHz-aQPw.js +1 -0
  63. package/dashboard/dist/assets/DHz-aQPw.js.br +0 -0
  64. package/dashboard/dist/assets/DHz-aQPw.js.gz +0 -0
  65. package/dashboard/dist/assets/DNX2foSJ.css +1 -0
  66. package/dashboard/dist/assets/DNX2foSJ.css.br +0 -0
  67. package/dashboard/dist/assets/DNX2foSJ.css.gz +0 -0
  68. package/dashboard/dist/assets/Dj2k1r16.js +8 -0
  69. package/dashboard/dist/assets/Dj2k1r16.js.br +0 -0
  70. package/dashboard/dist/assets/Dj2k1r16.js.gz +0 -0
  71. package/dashboard/dist/assets/DxUw4FMR.js +212 -0
  72. package/dashboard/dist/assets/DxUw4FMR.js.br +0 -0
  73. package/dashboard/dist/assets/DxUw4FMR.js.gz +0 -0
  74. package/dashboard/dist/assets/T2NFtzAv.js +1 -0
  75. package/dashboard/dist/assets/T2NFtzAv.js.br +0 -0
  76. package/dashboard/dist/assets/T2NFtzAv.js.gz +0 -0
  77. package/dashboard/dist/assets/cX2e-TLi.js +1 -0
  78. package/dashboard/dist/assets/cX2e-TLi.js.br +0 -0
  79. package/dashboard/dist/assets/cX2e-TLi.js.gz +0 -0
  80. package/dashboard/dist/assets/eeHXe_OQ.js +9 -0
  81. package/dashboard/dist/assets/eeHXe_OQ.js.br +0 -0
  82. package/dashboard/dist/assets/eeHXe_OQ.js.gz +0 -0
  83. package/dashboard/dist/assets/{DxKG5zy8.js → gZr_xKlA.js} +2 -2
  84. package/dashboard/dist/assets/gZr_xKlA.js.br +0 -0
  85. package/dashboard/dist/assets/gZr_xKlA.js.gz +0 -0
  86. package/dashboard/dist/brand/control-tower.png +0 -0
  87. package/dashboard/dist/brand/design-codex.png +0 -0
  88. package/dashboard/dist/brand/engineering-autopilot.png +0 -0
  89. package/dashboard/dist/brand/launch-captain.png +0 -0
  90. package/dashboard/dist/brand/orgx-logo.png +0 -0
  91. package/dashboard/dist/brand/pipeline-intelligence.png +0 -0
  92. package/dashboard/dist/brand/product-orchestrator.png +0 -0
  93. package/dashboard/dist/brand/xandy-orchestrator.png +0 -0
  94. package/dashboard/dist/index.html +8 -6
  95. package/dashboard/dist/index.html.br +0 -0
  96. package/dashboard/dist/index.html.gz +0 -0
  97. package/dist/hash-utils.d.ts +1 -0
  98. package/dist/hash-utils.js +4 -0
  99. package/dist/http/helpers/auto-continue-engine.d.ts +36 -0
  100. package/dist/http/helpers/auto-continue-engine.js +198 -75
  101. package/dist/http/helpers/autopilot-runtime.d.ts +1 -0
  102. package/dist/http/helpers/autopilot-runtime.js +31 -3
  103. package/dist/http/helpers/autopilot-slice-utils.d.ts +10 -0
  104. package/dist/http/helpers/autopilot-slice-utils.js +158 -54
  105. package/dist/http/helpers/hash-utils.d.ts +1 -1
  106. package/dist/http/helpers/hash-utils.js +1 -1
  107. package/dist/http/helpers/humanize-slice-failure.d.ts +35 -0
  108. package/dist/http/helpers/humanize-slice-failure.js +137 -0
  109. package/dist/http/helpers/mission-control.d.ts +1 -0
  110. package/dist/http/helpers/mission-control.js +73 -7
  111. package/dist/http/helpers/queue-constants.d.ts +37 -0
  112. package/dist/http/helpers/queue-constants.js +34 -0
  113. package/dist/http/helpers/slice-experience-v2.js +2 -5
  114. package/dist/http/helpers/slice-run-projections.js +2 -5
  115. package/dist/http/helpers/workspace-scope.js +4 -3
  116. package/dist/http/index.js +166 -63
  117. package/dist/http/routes/chat.js +1 -21
  118. package/dist/http/routes/live-misc.js +9 -2
  119. package/dist/http/routes/live-snapshot.js +14 -27
  120. package/dist/http/routes/mission-control-actions.js +7 -18
  121. package/dist/http/routes/mission-control-read.d.ts +1 -0
  122. package/dist/http/routes/mission-control-read.js +14 -56
  123. package/dist/index.d.ts +8 -1
  124. package/dist/index.js +21 -1
  125. package/dist/lib/type-coercion.d.ts +10 -0
  126. package/dist/lib/type-coercion.js +82 -0
  127. package/dist/mcp-http-handler.js +14 -2
  128. package/dist/openclaw.plugin.json +1 -1
  129. package/dist/services/experiment-randomization.js +9 -2
  130. package/dist/tools/core-tools.d.ts +27 -0
  131. package/dist/tools/core-tools.js +89 -0
  132. package/openclaw.plugin.json +1 -1
  133. package/package.json +3 -2
  134. package/dashboard/dist/assets/77gGFBt6.js.br +0 -0
  135. package/dashboard/dist/assets/77gGFBt6.js.gz +0 -0
  136. package/dashboard/dist/assets/BBpTN_SR.js +0 -1
  137. package/dashboard/dist/assets/BBpTN_SR.js.br +0 -0
  138. package/dashboard/dist/assets/BBpTN_SR.js.gz +0 -0
  139. package/dashboard/dist/assets/BJgZIVUQ.js +0 -53
  140. package/dashboard/dist/assets/BJgZIVUQ.js.br +0 -0
  141. package/dashboard/dist/assets/BJgZIVUQ.js.gz +0 -0
  142. package/dashboard/dist/assets/BTAEErUY.js +0 -1
  143. package/dashboard/dist/assets/BTAEErUY.js.br +0 -0
  144. package/dashboard/dist/assets/BTAEErUY.js.gz +0 -0
  145. package/dashboard/dist/assets/BVShoyjA.js +0 -1
  146. package/dashboard/dist/assets/BVShoyjA.js.br +0 -0
  147. package/dashboard/dist/assets/BVShoyjA.js.gz +0 -0
  148. package/dashboard/dist/assets/BgcAY5rE.js +0 -1
  149. package/dashboard/dist/assets/BgcAY5rE.js.br +0 -0
  150. package/dashboard/dist/assets/BgcAY5rE.js.gz +0 -0
  151. package/dashboard/dist/assets/C-KIc3Wc.js +0 -1
  152. package/dashboard/dist/assets/C-KIc3Wc.js.br +0 -0
  153. package/dashboard/dist/assets/C-KIc3Wc.js.gz +0 -0
  154. package/dashboard/dist/assets/C-PAoJF-.js +0 -1
  155. package/dashboard/dist/assets/C-PAoJF-.js.br +0 -0
  156. package/dashboard/dist/assets/C-PAoJF-.js.gz +0 -0
  157. package/dashboard/dist/assets/C0nA-iUG.js +0 -1
  158. package/dashboard/dist/assets/C0nA-iUG.js.br +0 -0
  159. package/dashboard/dist/assets/C0nA-iUG.js.gz +0 -0
  160. package/dashboard/dist/assets/C6GO-FKy.js +0 -1
  161. package/dashboard/dist/assets/C6GO-FKy.js.br +0 -0
  162. package/dashboard/dist/assets/C6GO-FKy.js.gz +0 -0
  163. package/dashboard/dist/assets/CFwPph5U.js +0 -1
  164. package/dashboard/dist/assets/CFwPph5U.js.br +0 -0
  165. package/dashboard/dist/assets/CFwPph5U.js.gz +0 -0
  166. package/dashboard/dist/assets/CL_wXqR7.js +0 -1
  167. package/dashboard/dist/assets/CL_wXqR7.js.br +0 -0
  168. package/dashboard/dist/assets/CL_wXqR7.js.gz +0 -0
  169. package/dashboard/dist/assets/CPjsbbgZ.js +0 -212
  170. package/dashboard/dist/assets/CPjsbbgZ.js.br +0 -0
  171. package/dashboard/dist/assets/CPjsbbgZ.js.gz +0 -0
  172. package/dashboard/dist/assets/CSr2ZnTV.js +0 -1
  173. package/dashboard/dist/assets/CSr2ZnTV.js.br +0 -0
  174. package/dashboard/dist/assets/CSr2ZnTV.js.gz +0 -0
  175. package/dashboard/dist/assets/CgQDT6yL.js +0 -1
  176. package/dashboard/dist/assets/CgQDT6yL.js.br +0 -0
  177. package/dashboard/dist/assets/CgQDT6yL.js.gz +0 -0
  178. package/dashboard/dist/assets/CnitK1MX.js.br +0 -0
  179. package/dashboard/dist/assets/CnitK1MX.js.gz +0 -0
  180. package/dashboard/dist/assets/CxQ08qFN.js +0 -9
  181. package/dashboard/dist/assets/CxQ08qFN.js.br +0 -0
  182. package/dashboard/dist/assets/CxQ08qFN.js.gz +0 -0
  183. package/dashboard/dist/assets/D7DHFX0D.js +0 -1
  184. package/dashboard/dist/assets/D7DHFX0D.js.br +0 -0
  185. package/dashboard/dist/assets/D7DHFX0D.js.gz +0 -0
  186. package/dashboard/dist/assets/DEip7uko.js +0 -1
  187. package/dashboard/dist/assets/DEip7uko.js.br +0 -0
  188. package/dashboard/dist/assets/DEip7uko.js.gz +0 -0
  189. package/dashboard/dist/assets/DHUSLc01.css +0 -1
  190. package/dashboard/dist/assets/DHUSLc01.css.br +0 -0
  191. package/dashboard/dist/assets/DHUSLc01.css.gz +0 -0
  192. package/dashboard/dist/assets/DOFL9l8s.js +0 -1
  193. package/dashboard/dist/assets/DOFL9l8s.js.br +0 -0
  194. package/dashboard/dist/assets/DOFL9l8s.js.gz +0 -0
  195. package/dashboard/dist/assets/DpuQm1oF.js.br +0 -0
  196. package/dashboard/dist/assets/DpuQm1oF.js.gz +0 -0
  197. package/dashboard/dist/assets/DxKG5zy8.js.br +0 -0
  198. package/dashboard/dist/assets/DxKG5zy8.js.gz +0 -0
  199. package/dashboard/dist/assets/cNrhgGc1.js +0 -8
  200. package/dashboard/dist/assets/cNrhgGc1.js.br +0 -0
  201. package/dashboard/dist/assets/cNrhgGc1.js.gz +0 -0
  202. package/dashboard/dist/assets/tcEHYcbW.js.br +0 -0
  203. package/dashboard/dist/assets/tcEHYcbW.js.gz +0 -0
@@ -9,11 +9,13 @@ import { appendTeamCompletion } from "../../team-context-store.js";
9
9
  import { readOpenClawGatewayPort, readOpenClawSettingsSnapshot, } from "../../openclaw-settings.js";
10
10
  import { resolveRuntimeHookToken, } from "../../runtime-instance-store.js";
11
11
  import { detectMcpHandshakeFailure, shouldKillWorker } from "../../worker-supervisor.js";
12
+ import { humanizeSliceFailure, humanizeSliceFailureSummary } from "./humanize-slice-failure.js";
12
13
  import { getOrgxPluginConfigDir } from "../../paths.js";
13
14
  import { buildMissionControlGraph, DEFAULT_TOKEN_BUDGET_ASSUMPTIONS, dedupeStrings, detectBehaviorConfigDrift, deriveBehaviorAutomationLevel, deriveBehaviorConfigContext, deriveExecutionPolicy, evaluateScopeCompletion, isDispatchableWorkstreamStatus, isDoneStatus, isTodoStatus, readBudgetEnvNumber, selectSliceTasksByScope, SLICE_SCOPE_TIMEOUT_MULTIPLIER, spawnGuardIsRateLimited, summarizeSpawnGuardBlockReason, } from "./mission-control.js";
14
15
  import { createAutopilotRuntime } from "./autopilot-runtime.js";
15
- import { buildScopeDirective, buildSliceOutputInstructions, buildWorkstreamSlicePrompt, createCodexBinResolver, ensureAutopilotSliceSchemaPath, fileUpdatedAtEpochMs, parseSliceResult, readFileTailSafe, readSliceOutputFile, } from "./autopilot-slice-utils.js";
16
+ import { buildScopeDirective, buildSliceOutputInstructions, buildWorkstreamSlicePrompt, createCodexBinResolver, ensureAutopilotSliceSchemaPath, extractSessionIdFromLog, extractSessionIdFromOutput, fileUpdatedAtEpochMs, parseSliceResult, readFileTailSafe, readSliceOutputFile, } from "./autopilot-slice-utils.js";
16
17
  import { pickString } from "./value-utils.js";
18
+ import { LaneState, RunStatus, } from "./queue-constants.js";
17
19
  function resolveAutopilotDefaultCwd(filename) {
18
20
  let cursor = dirname(filename);
19
21
  for (let i = 0; i < 12; i += 1) {
@@ -63,6 +65,35 @@ export function createAutoContinueEngine(deps) {
63
65
  ? "reject"
64
66
  : "approve";
65
67
  const autoContinueSliceRuns = new Map();
68
+ const workstreamSessionStore = new Map();
69
+ function sessionResumeEnabled() {
70
+ const raw = (process.env.ORGX_AUTOPILOT_SESSION_RESUME ?? "").trim().toLowerCase();
71
+ if (!raw)
72
+ return false;
73
+ return !(raw === "0" || raw === "false" || raw === "no" || raw === "off");
74
+ }
75
+ function setWorkstreamSession(workstreamId, entry) {
76
+ workstreamSessionStore.set(workstreamId, entry);
77
+ }
78
+ function getWorkstreamSession(workstreamId) {
79
+ return workstreamSessionStore.get(workstreamId) ?? null;
80
+ }
81
+ function clearWorkstreamSession(initiativeId) {
82
+ for (const [key, entry] of workstreamSessionStore.entries()) {
83
+ if (entry.initiativeId === initiativeId) {
84
+ workstreamSessionStore.delete(key);
85
+ }
86
+ }
87
+ }
88
+ function listWorkstreamSessions(initiativeId) {
89
+ const results = [];
90
+ for (const entry of workstreamSessionStore.values()) {
91
+ if (!initiativeId || entry.initiativeId === initiativeId) {
92
+ results.push(entry);
93
+ }
94
+ }
95
+ return results;
96
+ }
66
97
  /** Spread into any metadata object to flag mock-worker activity. */
67
98
  function mockMeta(slice) {
68
99
  return slice.isMockWorker ? { mock: true } : {};
@@ -999,7 +1030,7 @@ export function createAutoContinueEngine(deps) {
999
1030
  }
1000
1031
  const existing = run.laneByWorkstreamId[normalizedWorkstreamId] ?? {
1001
1032
  workstreamId: normalizedWorkstreamId,
1002
- state: "idle",
1033
+ state: LaneState.IDLE,
1003
1034
  activeRunId: null,
1004
1035
  activeTaskIds: [],
1005
1036
  blockedReason: null,
@@ -1051,12 +1082,12 @@ export function createAutoContinueEngine(deps) {
1051
1082
  if (lane && lane.activeRunId === sliceRunId) {
1052
1083
  setLaneState(run, {
1053
1084
  workstreamId: normalizedWorkstreamId,
1054
- state: lane.state === "blocked" ? "blocked" : "idle",
1085
+ state: lane.state === LaneState.BLOCKED ? "blocked" : "idle",
1055
1086
  activeRunId: null,
1056
1087
  activeTaskIds: [],
1057
1088
  retryAt: lane.retryAt ?? null,
1058
1089
  waitingOnWorkstreamIds: lane.waitingOnWorkstreamIds ?? [],
1059
- blockedReason: lane.state === "blocked" ? lane.blockedReason : null,
1090
+ blockedReason: lane.state === LaneState.BLOCKED ? lane.blockedReason : null,
1060
1091
  });
1061
1092
  }
1062
1093
  }
@@ -1359,7 +1390,7 @@ export function createAutoContinueEngine(deps) {
1359
1390
  updated_at: lane.updatedAt,
1360
1391
  }));
1361
1392
  const patch = {
1362
- auto_continue_enabled: input.run.status === "running" || input.run.status === "stopping",
1393
+ auto_continue_enabled: input.run.status === RunStatus.RUNNING || input.run.status === RunStatus.STOPPING,
1363
1394
  auto_continue_status: input.run.status,
1364
1395
  auto_continue_stop_reason: input.run.stopReason,
1365
1396
  auto_continue_started_at: input.run.startedAt,
@@ -1398,7 +1429,7 @@ export function createAutoContinueEngine(deps) {
1398
1429
  const now = new Date().toISOString();
1399
1430
  ensureRunInternals(input.run);
1400
1431
  const activeRunIds = listActiveSliceRunIds(input.run);
1401
- input.run.status = "stopped";
1432
+ input.run.status = RunStatus.STOPPED;
1402
1433
  input.run.stopReason = input.reason;
1403
1434
  input.run.stoppedAt = now;
1404
1435
  input.run.updatedAt = now;
@@ -1412,7 +1443,7 @@ export function createAutoContinueEngine(deps) {
1412
1443
  if (lane.activeRunId || lane.activeTaskIds.length > 0) {
1413
1444
  setLaneState(input.run, {
1414
1445
  workstreamId: lane.workstreamId,
1415
- state: lane.state === "blocked" ? "blocked" : "idle",
1446
+ state: lane.state === LaneState.BLOCKED ? "blocked" : "idle",
1416
1447
  activeRunId: null,
1417
1448
  activeTaskIds: [],
1418
1449
  });
@@ -1542,7 +1573,7 @@ export function createAutoContinueEngine(deps) {
1542
1573
  event: "autopilot_transition",
1543
1574
  actionType: "run_state_transition",
1544
1575
  }),
1545
- old_state: "running",
1576
+ old_state: LaneState.RUNNING,
1546
1577
  new_state: input.reason === "completed" || input.reason === "stopped" ? "idle" : input.reason === "blocked" ? "blocked" : input.reason === "error" ? "error" : "idle",
1547
1578
  reason: input.reason,
1548
1579
  workspace_id: input.run.allowedWorkstreamIds?.[0] ?? null,
@@ -1700,8 +1731,8 @@ export function createAutoContinueEngine(deps) {
1700
1731
  const decisionResult = await requestDecisionQueued({
1701
1732
  initiativeId: run.initiativeId,
1702
1733
  correlationId: slice.runId,
1703
- title: `Autopilot slice MCP failed: ${slice.workstreamTitle ?? slice.workstreamId}`,
1704
- summary: `MCP handshake failed${mcpHandshake.server ? ` for ${mcpHandshake.server}` : ""}. Review logs/output and decide whether to retry or pause autopilot.`,
1734
+ title: `Agent couldn't connect to tools: ${slice.workstreamTitle ?? slice.workstreamId}`,
1735
+ summary: humanizeSliceFailureSummary(`MCP handshake failed${mcpHandshake.server ? ` for ${mcpHandshake.server}` : ""}.`),
1705
1736
  urgency: "high",
1706
1737
  options: [
1707
1738
  "Retry this workstream slice",
@@ -1744,7 +1775,7 @@ export function createAutoContinueEngine(deps) {
1744
1775
  });
1745
1776
  setLaneState(run, {
1746
1777
  workstreamId: slice.workstreamId,
1747
- state: "blocked",
1778
+ state: LaneState.BLOCKED,
1748
1779
  activeRunId: null,
1749
1780
  activeTaskIds: [],
1750
1781
  blockedReason: slice.lastError,
@@ -1786,6 +1817,9 @@ export function createAutoContinueEngine(deps) {
1786
1817
  clearAutoContinueSliceTransientState(slice.runId);
1787
1818
  const event = killDecision.kind === "timeout" ? "autopilot_slice_timeout" : "autopilot_slice_log_stall";
1788
1819
  const humanLabel = killDecision.kind === "timeout" ? "timed out" : "stalled";
1820
+ const stallDecisionTitle = killDecision.kind === "timeout"
1821
+ ? `Autopilot slice timed out: ${slice.workstreamTitle ?? slice.workstreamId}`
1822
+ : `Autopilot slice stalled: ${slice.workstreamTitle ?? slice.workstreamId}`;
1789
1823
  await emitActivitySafe({
1790
1824
  initiativeId: run.initiativeId,
1791
1825
  runId: slice.runId,
@@ -1819,8 +1853,8 @@ export function createAutoContinueEngine(deps) {
1819
1853
  const decisionResult = await requestDecisionQueued({
1820
1854
  initiativeId: run.initiativeId,
1821
1855
  correlationId: slice.runId,
1822
- title: `Autopilot slice ${humanLabel}: ${slice.workstreamTitle ?? slice.workstreamId}`,
1823
- summary: "The slice was terminated because it stopped making progress. Review logs/output and decide whether to retry or pause autopilot.",
1856
+ title: stallDecisionTitle,
1857
+ summary: humanizeSliceFailureSummary(slice.lastError ?? `Autopilot slice ${humanLabel}`),
1824
1858
  urgency: "high",
1825
1859
  options: [
1826
1860
  "Retry this workstream slice",
@@ -1872,7 +1906,7 @@ export function createAutoContinueEngine(deps) {
1872
1906
  });
1873
1907
  setLaneState(run, {
1874
1908
  workstreamId: slice.workstreamId,
1875
- state: "blocked",
1909
+ state: LaneState.BLOCKED,
1876
1910
  activeRunId: null,
1877
1911
  activeTaskIds: [],
1878
1912
  blockedReason: slice.lastError,
@@ -1904,6 +1938,25 @@ export function createAutoContinueEngine(deps) {
1904
1938
  const raw = readSliceOutputFile(slice.outputPath);
1905
1939
  const parsed = raw ? parseSliceResult(raw) : null;
1906
1940
  const parsedStatus = parsed?.status ?? "error";
1941
+ // Session capture: extract CLI session ID from output or log for future resume.
1942
+ if (sessionResumeEnabled()) {
1943
+ const outputSessionId = raw ? extractSessionIdFromOutput(raw, slice.sourceClient) : null;
1944
+ const logSessionId = outputSessionId
1945
+ ? null
1946
+ : extractSessionIdFromLog(readFileTailSafe(slice.logPath, 32_000), slice.sourceClient);
1947
+ const capturedSessionId = outputSessionId ?? logSessionId ?? null;
1948
+ if (capturedSessionId) {
1949
+ slice.cliSessionId = capturedSessionId;
1950
+ setWorkstreamSession(slice.workstreamId, {
1951
+ sessionId: capturedSessionId,
1952
+ workstreamId: slice.workstreamId,
1953
+ initiativeId: slice.initiativeId,
1954
+ sourceClient: slice.sourceClient,
1955
+ capturedAt: new Date().toISOString(),
1956
+ fromRunId: slice.runId,
1957
+ });
1958
+ }
1959
+ }
1907
1960
  const defaultDecisionBlocking = parsedStatus === "completed" ? false : true;
1908
1961
  const allDecisions = Array.isArray(parsed?.decisions_needed)
1909
1962
  ? (parsed?.decisions_needed ?? [])
@@ -1919,13 +1972,25 @@ export function createAutoContinueEngine(deps) {
1919
1972
  const decisions = allDecisions.filter((item) => !isParserSyntheticFallbackDecision(item));
1920
1973
  const normalizedBlockingDecisionCount = allDecisions.filter((item) => typeof item.blocking === "boolean" ? item.blocking : defaultDecisionBlocking).length;
1921
1974
  const normalizedNonBlockingDecisionCount = Math.max(0, allDecisions.length - normalizedBlockingDecisionCount);
1922
- const effectiveParsedStatus = parsedStatus === "completed" && normalizedBlockingDecisionCount > 0
1975
+ const operationalParsedStatus = parsedStatus === "completed" && normalizedBlockingDecisionCount > 0
1923
1976
  ? "needs_decision"
1924
1977
  : parsedStatus;
1978
+ const parsedSummarySignal = String(parsed?.summary ?? "").toLowerCase();
1979
+ const parsedLooksLikeNoOutcomeCompletion = operationalParsedStatus === "error" &&
1980
+ (parsedSummarySignal.includes("without verifiable outcomes") ||
1981
+ parsedSummarySignal.includes("without output") ||
1982
+ parsedSummarySignal.includes("without artifacts") ||
1983
+ parsedSummarySignal.includes("did not report artifacts") ||
1984
+ (parsedSummarySignal.includes("did not report") &&
1985
+ parsedSummarySignal.includes("status updates")) ||
1986
+ parsedSummarySignal.includes("produced nothing"));
1987
+ const reportedParsedStatus = parsedLooksLikeNoOutcomeCompletion
1988
+ ? "completed"
1989
+ : operationalParsedStatus;
1925
1990
  slice.status =
1926
- effectiveParsedStatus === "completed"
1991
+ operationalParsedStatus === "completed"
1927
1992
  ? "completed"
1928
- : effectiveParsedStatus === "blocked" || effectiveParsedStatus === "needs_decision"
1993
+ : operationalParsedStatus === "blocked" || operationalParsedStatus === "needs_decision"
1929
1994
  ? "blocked"
1930
1995
  : "error";
1931
1996
  slice.finishedAt = now;
@@ -2005,7 +2070,7 @@ export function createAutoContinueEngine(deps) {
2005
2070
  : [];
2006
2071
  const resultEnvelope = {
2007
2072
  summary: userSummary,
2008
- parsed_status: effectiveParsedStatus,
2073
+ parsed_status: reportedParsedStatus,
2009
2074
  task_updates: taskUpdates,
2010
2075
  milestone_updates: milestoneUpdates,
2011
2076
  next_actions: nextActions,
@@ -2196,7 +2261,7 @@ export function createAutoContinueEngine(deps) {
2196
2261
  correlation_id: slice.runId,
2197
2262
  requested_by_agent_id: run.agentId,
2198
2263
  requested_by_agent_name: run.agentName,
2199
- status: effectiveParsedStatus,
2264
+ status: reportedParsedStatus,
2200
2265
  artifacts: artifacts.length,
2201
2266
  decisions: allDecisions.length,
2202
2267
  blocking_decisions: normalizedBlockingDecisionCount,
@@ -2240,7 +2305,7 @@ export function createAutoContinueEngine(deps) {
2240
2305
  userSummary,
2241
2306
  event: "autopilot_slice_handoff",
2242
2307
  extra: {
2243
- parsed_status: effectiveParsedStatus,
2308
+ parsed_status: reportedParsedStatus,
2244
2309
  artifacts: artifacts.length,
2245
2310
  decisions: decisions.length,
2246
2311
  decision_ids: decisionIds,
@@ -2286,7 +2351,7 @@ export function createAutoContinueEngine(deps) {
2286
2351
  behavior_config_hash: slice.behaviorConfigHash,
2287
2352
  policy_source: slice.behaviorPolicySource,
2288
2353
  behavior_automation_level: slice.behaviorAutomationLevel,
2289
- parsed_status: effectiveParsedStatus,
2354
+ parsed_status: reportedParsedStatus,
2290
2355
  has_output: Boolean(parsed),
2291
2356
  artifacts: artifacts.length,
2292
2357
  decisions: allDecisions.length,
@@ -2295,7 +2360,7 @@ export function createAutoContinueEngine(deps) {
2295
2360
  decision_ids: decisionIds,
2296
2361
  blocking_decision_ids: Array.from(new Set(blockingDecisionIds)),
2297
2362
  non_blocking_decision_ids: Array.from(new Set(nonBlockingDecisionIds)),
2298
- decision_required: blockingDecisionQueued || effectiveParsedStatus === "needs_decision",
2363
+ decision_required: blockingDecisionQueued || operationalParsedStatus === "needs_decision",
2299
2364
  status_updates_applied: statusUpdateResult.applied,
2300
2365
  status_updates_buffered: statusUpdateResult.buffered,
2301
2366
  reported_skill_evidence_count: skillEvidence.length,
@@ -2333,19 +2398,63 @@ export function createAutoContinueEngine(deps) {
2333
2398
  queued: false,
2334
2399
  decisionIds: [],
2335
2400
  };
2401
+ const fallbackRawError = parsed?.summary ??
2402
+ slice.lastError ??
2403
+ (slice.status === "blocked"
2404
+ ? "Execution is blocked and needs intervention."
2405
+ : "Agent process exited without a valid output contract.");
2406
+ const fallbackHumanized = humanizeSliceFailure(fallbackRawError);
2407
+ const fallbackErrorSignal = [
2408
+ parsed?.summary ?? null,
2409
+ slice.lastError ?? null,
2410
+ fallbackRawError,
2411
+ ]
2412
+ .filter((entry) => typeof entry === "string" && entry.trim().length > 0)
2413
+ .join(" ")
2414
+ .toLowerCase();
2415
+ const looksLikeNoOutcome = fallbackErrorSignal.includes("without verifiable outcomes") ||
2416
+ fallbackErrorSignal.includes("without output") ||
2417
+ fallbackErrorSignal.includes("without artifacts") ||
2418
+ fallbackErrorSignal.includes("did not report artifacts") ||
2419
+ (fallbackErrorSignal.includes("did not report") &&
2420
+ fallbackErrorSignal.includes("status updates")) ||
2421
+ fallbackErrorSignal.includes("produced nothing");
2422
+ const looksLikeStall = fallbackErrorSignal.includes("stall") ||
2423
+ fallbackErrorSignal.includes("stopped making progress");
2424
+ const looksLikeTimeout = fallbackErrorSignal.includes("timeout") ||
2425
+ fallbackErrorSignal.includes("timed out") ||
2426
+ fallbackErrorSignal.includes("ran out of time");
2427
+ const blockedLike = slice.status === "blocked" ||
2428
+ looksLikeNoOutcome ||
2429
+ looksLikeStall ||
2430
+ looksLikeTimeout;
2431
+ const decisionConflictSource = looksLikeNoOutcome
2432
+ ? "slice_completed_without_outcome"
2433
+ : looksLikeTimeout
2434
+ ? "slice_timeout"
2435
+ : looksLikeStall
2436
+ ? "slice_stall_no_output"
2437
+ : blockedLike
2438
+ ? "slice_missing_blocking_decision"
2439
+ : "slice_invalid_output";
2440
+ const fallbackDecisionTitle = looksLikeNoOutcome
2441
+ ? `Autopilot slice needs verification: ${slice.workstreamTitle ?? slice.workstreamId}`
2442
+ : looksLikeStall
2443
+ ? `Autopilot slice stalled: ${slice.workstreamTitle ?? slice.workstreamId}`
2444
+ : looksLikeTimeout
2445
+ ? `Autopilot slice timed out: ${slice.workstreamTitle ?? slice.workstreamId}`
2446
+ : blockedLike
2447
+ ? `Autopilot slice blocked: ${slice.workstreamTitle ?? slice.workstreamId}`
2448
+ : `Autopilot slice failed: ${slice.workstreamTitle ?? slice.workstreamId}`;
2449
+ const fallbackDecisionSummary = looksLikeNoOutcome
2450
+ ? "The slice reported completion but did not produce artifacts or status updates. Decide whether to retry, request stronger output, or mark tasks manually."
2451
+ : fallbackHumanized.explanation;
2336
2452
  if (!blockingDecisionQueued) {
2337
- const blockedLike = slice.status === "blocked";
2338
2453
  fallbackDecisionResult = await requestDecisionQueued({
2339
2454
  initiativeId: run.initiativeId,
2340
2455
  correlationId: slice.runId,
2341
- title: blockedLike
2342
- ? `Autopilot slice blocked: ${slice.workstreamTitle ?? slice.workstreamId}`
2343
- : `Autopilot slice failed: ${slice.workstreamTitle ?? slice.workstreamId}`,
2344
- summary: parsed?.summary ??
2345
- slice.lastError ??
2346
- (blockedLike
2347
- ? "The slice reported a blocked/decision-required state without a blocking decision payload. Review logs/output and decide whether to retry, unblock, or skip."
2348
- : "The slice failed without producing a valid output contract. Review logs/output and decide whether to retry or pause autopilot."),
2456
+ title: fallbackDecisionTitle,
2457
+ summary: fallbackDecisionSummary,
2349
2458
  urgency: "high",
2350
2459
  options: [
2351
2460
  "Retry this workstream slice",
@@ -2353,18 +2462,20 @@ export function createAutoContinueEngine(deps) {
2353
2462
  "Skip this workstream for now",
2354
2463
  ],
2355
2464
  blocking: true,
2356
- decisionType: blockedLike ? "autopilot_blocked_without_decision" : "autopilot_failure",
2465
+ decisionType: looksLikeNoOutcome
2466
+ ? "autopilot_completed_without_outcome"
2467
+ : blockedLike
2468
+ ? "autopilot_blocked_without_decision"
2469
+ : "autopilot_failure",
2357
2470
  workstreamId: slice.workstreamId,
2358
2471
  agentId: slice.agentId,
2359
2472
  sourceSystem: "orgx-autopilot",
2360
- conflictSource: blockedLike
2361
- ? "slice_missing_blocking_decision"
2362
- : "slice_invalid_output",
2473
+ conflictSource: decisionConflictSource,
2363
2474
  dedupeKey: [
2364
2475
  "autopilot",
2365
2476
  run.initiativeId,
2366
2477
  slice.workstreamId,
2367
- blockedLike ? "slice_missing_blocking_decision" : "slice_invalid_output",
2478
+ decisionConflictSource,
2368
2479
  ].join(":"),
2369
2480
  recommendedAction: nextActions[0] ??
2370
2481
  "Review the output contract and logs, then retry or pause autopilot until the blocker is resolved.",
@@ -2372,19 +2483,17 @@ export function createAutoContinueEngine(deps) {
2372
2483
  sourceRef: {
2373
2484
  run_id: slice.runId,
2374
2485
  workstream_id: slice.workstreamId,
2375
- parsed_status: effectiveParsedStatus,
2486
+ parsed_status: reportedParsedStatus,
2376
2487
  },
2377
2488
  evidenceRefs: [
2378
2489
  {
2379
2490
  evidence_type: "slice_output_validation",
2380
2491
  title: "Slice output requires fallback decision",
2381
- summary: parsed?.summary ??
2382
- slice.lastError ??
2383
- "Slice did not provide a blocking decision payload.",
2492
+ summary: fallbackDecisionSummary,
2384
2493
  source_pointer: slice.outputPath,
2385
2494
  payload: {
2386
2495
  log_path: slice.logPath,
2387
- parsed_status: effectiveParsedStatus,
2496
+ parsed_status: reportedParsedStatus,
2388
2497
  },
2389
2498
  },
2390
2499
  ...artifactEvidenceRefs,
@@ -2393,12 +2502,12 @@ export function createAutoContinueEngine(deps) {
2393
2502
  }
2394
2503
  setLaneState(run, {
2395
2504
  workstreamId: slice.workstreamId,
2396
- state: "blocked",
2505
+ state: LaneState.BLOCKED,
2397
2506
  activeRunId: null,
2398
2507
  activeTaskIds: [],
2399
2508
  blockedReason: parsed?.summary ??
2400
2509
  slice.lastError ??
2401
- `Slice returned status: ${effectiveParsedStatus}`,
2510
+ `Slice returned status: ${reportedParsedStatus}`,
2402
2511
  waitingOnWorkstreamIds: [],
2403
2512
  retryAt: null,
2404
2513
  });
@@ -2407,10 +2516,8 @@ export function createAutoContinueEngine(deps) {
2407
2516
  }
2408
2517
  await stopAutoContinueRun({
2409
2518
  run,
2410
- reason: slice.status === "error" ? "error" : "blocked",
2411
- error: parsed?.summary ??
2412
- slice.lastError ??
2413
- `Slice returned status: ${effectiveParsedStatus}`,
2519
+ reason: blockedLike ? "blocked" : "error",
2520
+ error: fallbackRawError,
2414
2521
  decisionRequired: blockingDecisionQueued || fallbackDecisionResult.queued,
2415
2522
  decisionIds: Array.from(new Set([...decisionIds, ...fallbackDecisionResult.decisionIds])),
2416
2523
  });
@@ -2421,12 +2528,14 @@ export function createAutoContinueEngine(deps) {
2421
2528
  decisions.length === 0 &&
2422
2529
  statusUpdateResult.applied === 0;
2423
2530
  if (!parsed || parsedStatus === "error" || completionHadNoOutcome) {
2531
+ const rawError = slice.lastError ?? (completionHadNoOutcome
2532
+ ? "Completed without verifiable outcomes or artifacts."
2533
+ : "Agent process exited without a valid output contract.");
2534
+ const humanized = humanizeSliceFailure(rawError);
2424
2535
  const attentionTitle = completionHadNoOutcome
2425
- ? `Autopilot slice needs verification: ${slice.workstreamTitle ?? slice.workstreamId}`
2426
- : `Autopilot slice failed: ${slice.workstreamTitle ?? slice.workstreamId}`;
2427
- const attentionSummary = completionHadNoOutcome
2428
- ? "The slice reported completion but did not produce artifacts or status updates. Decide whether to retry, request stronger output, or mark tasks manually."
2429
- : "The slice exited without a valid output contract. Review logs/output and decide whether to retry or pause autopilot.";
2536
+ ? `Agent finished but produced nothing: ${slice.workstreamTitle ?? slice.workstreamId}`
2537
+ : `${humanized.headline}: ${slice.workstreamTitle ?? slice.workstreamId}`;
2538
+ const attentionSummary = humanized.explanation;
2430
2539
  const decisionResult = await requestDecisionQueued({
2431
2540
  initiativeId: run.initiativeId,
2432
2541
  correlationId: slice.runId,
@@ -2481,7 +2590,7 @@ export function createAutoContinueEngine(deps) {
2481
2590
  });
2482
2591
  setLaneState(run, {
2483
2592
  workstreamId: slice.workstreamId,
2484
- state: "blocked",
2593
+ state: LaneState.BLOCKED,
2485
2594
  activeRunId: null,
2486
2595
  activeTaskIds: [],
2487
2596
  blockedReason: slice.lastError ??
@@ -2515,7 +2624,7 @@ export function createAutoContinueEngine(deps) {
2515
2624
  });
2516
2625
  setLaneState(run, {
2517
2626
  workstreamId: slice.workstreamId,
2518
- state: "completed",
2627
+ state: LaneState.COMPLETED,
2519
2628
  activeRunId: null,
2520
2629
  activeTaskIds: [],
2521
2630
  blockedReason: null,
@@ -2593,7 +2702,7 @@ export function createAutoContinueEngine(deps) {
2593
2702
  }
2594
2703
  syncLegacyRunPointers(run);
2595
2704
  if (run.stopRequested) {
2596
- run.status = "stopping";
2705
+ run.status = RunStatus.STOPPING;
2597
2706
  run.updatedAt = now;
2598
2707
  await stopAutoContinueRun({ run, reason: "stopped" });
2599
2708
  return;
@@ -2725,7 +2834,7 @@ export function createAutoContinueEngine(deps) {
2725
2834
  for (const [workstreamId, waitingOnWorkstreamIds] of waitingByWorkstream.entries()) {
2726
2835
  setLaneState(run, {
2727
2836
  workstreamId,
2728
- state: "waiting_dependency",
2837
+ state: LaneState.WAITING_DEPENDENCY,
2729
2838
  activeRunId: null,
2730
2839
  activeTaskIds: [],
2731
2840
  blockedReason: null,
@@ -2976,7 +3085,7 @@ export function createAutoContinueEngine(deps) {
2976
3085
  }
2977
3086
  setLaneState(run, {
2978
3087
  workstreamId: selectedWorkstreamId,
2979
- state: "blocked",
3088
+ state: LaneState.BLOCKED,
2980
3089
  activeRunId: null,
2981
3090
  activeTaskIds: [],
2982
3091
  blockedReason,
@@ -3071,7 +3180,7 @@ export function createAutoContinueEngine(deps) {
3071
3180
  }
3072
3181
  setLaneState(run, {
3073
3182
  workstreamId: selectedWorkstreamId,
3074
- state: "blocked",
3183
+ state: LaneState.BLOCKED,
3075
3184
  activeRunId: null,
3076
3185
  activeTaskIds: [],
3077
3186
  blockedReason,
@@ -3136,7 +3245,7 @@ export function createAutoContinueEngine(deps) {
3136
3245
  });
3137
3246
  setLaneState(run, {
3138
3247
  workstreamId: selectedWorkstreamId,
3139
- state: "rate_limited",
3248
+ state: LaneState.RATE_LIMITED,
3140
3249
  activeRunId: null,
3141
3250
  activeTaskIds: [],
3142
3251
  blockedReason,
@@ -3219,7 +3328,7 @@ export function createAutoContinueEngine(deps) {
3219
3328
  run.updatedAt = now;
3220
3329
  setLaneState(run, {
3221
3330
  workstreamId: selectedWorkstreamId,
3222
- state: "idle",
3331
+ state: LaneState.IDLE,
3223
3332
  activeRunId: null,
3224
3333
  activeTaskIds: [],
3225
3334
  blockedReason: null,
@@ -3327,7 +3436,7 @@ export function createAutoContinueEngine(deps) {
3327
3436
  }
3328
3437
  setLaneState(run, {
3329
3438
  workstreamId: selectedWorkstreamId,
3330
- state: "blocked",
3439
+ state: LaneState.BLOCKED,
3331
3440
  activeRunId: null,
3332
3441
  activeTaskIds: [],
3333
3442
  blockedReason,
@@ -3463,6 +3572,9 @@ export function createAutoContinueEngine(deps) {
3463
3572
  catch {
3464
3573
  // best effort
3465
3574
  }
3575
+ // Session resume: check if a previous session exists for this workstream.
3576
+ const priorSession = sessionResumeEnabled() ? getWorkstreamSession(selectedWorkstreamId) : null;
3577
+ const resumedFromSessionId = priorSession?.sessionId ?? null;
3466
3578
  const spawned = spawnCodexSliceWorker({
3467
3579
  runId: sliceRunId,
3468
3580
  prompt,
@@ -3470,6 +3582,7 @@ export function createAutoContinueEngine(deps) {
3470
3582
  logPath,
3471
3583
  outputPath,
3472
3584
  outputSchemaPath: schemaPath,
3585
+ resumeSessionId: resumedFromSessionId,
3473
3586
  env: {
3474
3587
  ORGX_SOURCE_CLIENT: executorSourceClient,
3475
3588
  ORGX_RUN_ID: sliceRunId,
@@ -3510,7 +3623,7 @@ export function createAutoContinueEngine(deps) {
3510
3623
  behaviorAutomationLevel,
3511
3624
  sourceClient: executorSourceClient,
3512
3625
  pid: spawned.pid,
3513
- status: "running",
3626
+ status: RunStatus.RUNNING,
3514
3627
  startedAt: now,
3515
3628
  finishedAt: null,
3516
3629
  updatedAt: now,
@@ -3523,6 +3636,8 @@ export function createAutoContinueEngine(deps) {
3523
3636
  scopeMilestoneIds: scopeMilestoneIds,
3524
3637
  lastError: null,
3525
3638
  isMockWorker: workerKind === "mock",
3639
+ cliSessionId: null,
3640
+ resumedFromSessionId,
3526
3641
  };
3527
3642
  autoContinueSliceRuns.set(sliceRunId, slice);
3528
3643
  try {
@@ -3626,7 +3741,7 @@ export function createAutoContinueEngine(deps) {
3626
3741
  run.activeTaskIds = dedupeStrings([...run.activeTaskIds, ...slice.taskIds]);
3627
3742
  setLaneState(run, {
3628
3743
  workstreamId: selectedWorkstreamId,
3629
- state: "running",
3744
+ state: LaneState.RUNNING,
3630
3745
  activeRunId: sliceRunId,
3631
3746
  activeTaskIds: slice.taskIds,
3632
3747
  blockedReason: null,
@@ -3705,16 +3820,16 @@ export function createAutoContinueEngine(deps) {
3705
3820
  }
3706
3821
  const lane = run.laneByWorkstreamId[workstreamId] ?? null;
3707
3822
  if (lane &&
3708
- (lane.state === "running" ||
3709
- lane.state === "blocked" ||
3710
- lane.state === "waiting_dependency" ||
3711
- lane.state === "rate_limited")) {
3823
+ (lane.state === LaneState.RUNNING ||
3824
+ lane.state === LaneState.BLOCKED ||
3825
+ lane.state === LaneState.WAITING_DEPENDENCY ||
3826
+ lane.state === LaneState.RATE_LIMITED)) {
3712
3827
  return run;
3713
3828
  }
3714
3829
  if (Array.isArray(run.allowedWorkstreamIds) &&
3715
3830
  run.allowedWorkstreamIds.length > 0 &&
3716
3831
  run.allowedWorkstreamIds.includes(workstreamId) &&
3717
- (run.status === "running" || run.status === "stopping")) {
3832
+ (run.status === RunStatus.RUNNING || run.status === RunStatus.STOPPING)) {
3718
3833
  return run;
3719
3834
  }
3720
3835
  return null;
@@ -3798,13 +3913,13 @@ export function createAutoContinueEngine(deps) {
3798
3913
  const existingRun = autoContinueRuns.get(initiativeId) ?? null;
3799
3914
  if (existingRun &&
3800
3915
  (existingRun.stopRequested ||
3801
- existingRun.status === "stopping" ||
3916
+ existingRun.status === RunStatus.STOPPING ||
3802
3917
  existingRun.stopReason === "stopped")) {
3803
3918
  await emitSkip("paused_by_user");
3804
3919
  return;
3805
3920
  }
3806
3921
  if (existingRun &&
3807
- (existingRun.status === "running" || existingRun.status === "stopping") &&
3922
+ (existingRun.status === RunStatus.RUNNING || existingRun.status === RunStatus.STOPPING) &&
3808
3923
  listActiveSliceRunIds(existingRun).length > 0) {
3809
3924
  const activeRunIds = listActiveSliceRunIds(existingRun);
3810
3925
  await emitSkip("already_running", {
@@ -4017,7 +4132,7 @@ export function createAutoContinueEngine(deps) {
4017
4132
  async function startAutoContinueRun(input) {
4018
4133
  const now = new Date().toISOString();
4019
4134
  const existing = autoContinueRuns.get(input.initiativeId) ?? null;
4020
- const existingIsLive = existing?.status === "running" || existing?.status === "stopping";
4135
+ const existingIsLive = existing?.status === RunStatus.RUNNING || existing?.status === RunStatus.STOPPING;
4021
4136
  const run = existing ??
4022
4137
  {
4023
4138
  initiativeId: input.initiativeId,
@@ -4032,7 +4147,7 @@ export function createAutoContinueEngine(deps) {
4032
4147
  scope: "task",
4033
4148
  tokenBudget: defaultAutoContinueTokenBudget(),
4034
4149
  tokensUsed: 0,
4035
- status: "running",
4150
+ status: RunStatus.RUNNING,
4036
4151
  stopReason: null,
4037
4152
  stopRequested: false,
4038
4153
  startedAt: now,
@@ -4075,7 +4190,7 @@ export function createAutoContinueEngine(deps) {
4075
4190
  ? normalizeTokenBudget(run.tokenBudget, defaultAutoContinueTokenBudget())
4076
4191
  : defaultAutoContinueTokenBudget();
4077
4192
  }
4078
- run.status = "running";
4193
+ run.status = RunStatus.RUNNING;
4079
4194
  run.stopReason = null;
4080
4195
  run.stopRequested = false;
4081
4196
  run.stoppedAt = null;
@@ -4094,6 +4209,7 @@ export function createAutoContinueEngine(deps) {
4094
4209
  run.activeTaskId = null;
4095
4210
  run.activeRunId = null;
4096
4211
  run.activeTaskTokenEstimate = null;
4212
+ clearWorkstreamSession(input.initiativeId);
4097
4213
  }
4098
4214
  syncLegacyRunPointers(run);
4099
4215
  autoContinueRuns.set(input.initiativeId, run);
@@ -4157,8 +4273,8 @@ export function createAutoContinueEngine(deps) {
4157
4273
  event: "autopilot_transition",
4158
4274
  actionType: "run_state_transition",
4159
4275
  }),
4160
- old_state: "idle",
4161
- new_state: "running",
4276
+ old_state: LaneState.IDLE,
4277
+ new_state: LaneState.RUNNING,
4162
4278
  reason: "started",
4163
4279
  workspace_id: run.allowedWorkstreamIds?.[0] ?? null,
4164
4280
  },
@@ -4191,5 +4307,12 @@ export function createAutoContinueEngine(deps) {
4191
4307
  getAutoContinueLaneForWorkstream,
4192
4308
  scheduleAutoFixForWorkstream,
4193
4309
  startAutoContinueRun,
4310
+ // Session store (for resume support)
4311
+ workstreamSessionStore,
4312
+ getWorkstreamSession,
4313
+ setWorkstreamSession,
4314
+ clearWorkstreamSession,
4315
+ listWorkstreamSessions,
4316
+ sessionResumeEnabled,
4194
4317
  };
4195
4318
  }
@@ -21,6 +21,7 @@ export declare function createAutopilotRuntime(deps: CreateAutopilotRuntimeDeps)
21
21
  outputPath: string;
22
22
  outputSchemaPath?: string;
23
23
  env: Record<string, string | undefined>;
24
+ resumeSessionId?: string | null;
24
25
  }) => {
25
26
  pid: number | null;
26
27
  };