@polpo-ai/core 0.15.144 → 0.16.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 (172) hide show
  1. package/README.md +30 -0
  2. package/dist/__tests__/custom-tool-runner.test.d.ts +2 -0
  3. package/dist/__tests__/custom-tool-runner.test.d.ts.map +1 -0
  4. package/dist/__tests__/custom-tool-runner.test.js +121 -0
  5. package/dist/__tests__/custom-tool-runner.test.js.map +1 -0
  6. package/dist/__tests__/mcp-runner-client.test.d.ts +2 -0
  7. package/dist/__tests__/mcp-runner-client.test.d.ts.map +1 -0
  8. package/dist/__tests__/mcp-runner-client.test.js +144 -0
  9. package/dist/__tests__/mcp-runner-client.test.js.map +1 -0
  10. package/dist/__tests__/mission-execution.test.d.ts +2 -0
  11. package/dist/__tests__/mission-execution.test.d.ts.map +1 -0
  12. package/dist/__tests__/mission-execution.test.js +68 -0
  13. package/dist/__tests__/mission-execution.test.js.map +1 -0
  14. package/dist/__tests__/run-state-monitor.test.d.ts +2 -0
  15. package/dist/__tests__/run-state-monitor.test.d.ts.map +1 -0
  16. package/dist/__tests__/run-state-monitor.test.js +59 -0
  17. package/dist/__tests__/run-state-monitor.test.js.map +1 -0
  18. package/dist/__tests__/runtime-metadata.test.d.ts +2 -0
  19. package/dist/__tests__/runtime-metadata.test.d.ts.map +1 -0
  20. package/dist/__tests__/runtime-metadata.test.js +17 -0
  21. package/dist/__tests__/runtime-metadata.test.js.map +1 -0
  22. package/dist/__tests__/task-execution-router.test.js +1 -1
  23. package/dist/__tests__/task-execution-router.test.js.map +1 -1
  24. package/dist/__tests__/task-runner-agent-lifetime.test.d.ts +2 -0
  25. package/dist/__tests__/task-runner-agent-lifetime.test.d.ts.map +1 -0
  26. package/dist/__tests__/task-runner-agent-lifetime.test.js +136 -0
  27. package/dist/__tests__/task-runner-agent-lifetime.test.js.map +1 -0
  28. package/dist/adapter.d.ts +18 -0
  29. package/dist/adapter.d.ts.map +1 -1
  30. package/dist/agent-manager.d.ts +3 -0
  31. package/dist/agent-manager.d.ts.map +1 -1
  32. package/dist/agent-manager.js +28 -2
  33. package/dist/agent-manager.js.map +1 -1
  34. package/dist/agent-store.d.ts +70 -1
  35. package/dist/agent-store.d.ts.map +1 -1
  36. package/dist/agent-store.js +103 -1
  37. package/dist/agent-store.js.map +1 -1
  38. package/dist/approval-manager.d.ts +24 -4
  39. package/dist/approval-manager.d.ts.map +1 -1
  40. package/dist/approval-manager.js +160 -112
  41. package/dist/approval-manager.js.map +1 -1
  42. package/dist/approval-manager.test.d.ts +2 -0
  43. package/dist/approval-manager.test.d.ts.map +1 -0
  44. package/dist/approval-manager.test.js +116 -0
  45. package/dist/approval-manager.test.js.map +1 -0
  46. package/dist/assessment-orchestrator.d.ts +12 -1
  47. package/dist/assessment-orchestrator.d.ts.map +1 -1
  48. package/dist/assessment-orchestrator.js +181 -83
  49. package/dist/assessment-orchestrator.js.map +1 -1
  50. package/dist/custom-tool-runner.d.ts +56 -0
  51. package/dist/custom-tool-runner.d.ts.map +1 -0
  52. package/dist/custom-tool-runner.js +197 -0
  53. package/dist/custom-tool-runner.js.map +1 -0
  54. package/dist/escalation-manager.d.ts +2 -0
  55. package/dist/escalation-manager.d.ts.map +1 -1
  56. package/dist/escalation-manager.js +79 -25
  57. package/dist/escalation-manager.js.map +1 -1
  58. package/dist/events.d.ts +4 -0
  59. package/dist/events.d.ts.map +1 -1
  60. package/dist/hooks.d.ts.map +1 -1
  61. package/dist/hooks.js +6 -0
  62. package/dist/hooks.js.map +1 -1
  63. package/dist/index.d.ts +19 -3
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +13 -1
  66. package/dist/index.js.map +1 -1
  67. package/dist/mcp-capability.d.ts +40 -0
  68. package/dist/mcp-capability.d.ts.map +1 -0
  69. package/dist/mcp-capability.js +2 -0
  70. package/dist/mcp-capability.js.map +1 -0
  71. package/dist/mcp-runner.d.ts +45 -0
  72. package/dist/mcp-runner.d.ts.map +1 -0
  73. package/dist/mcp-runner.js +238 -0
  74. package/dist/mcp-runner.js.map +1 -0
  75. package/dist/mission-cancellation.d.ts +14 -0
  76. package/dist/mission-cancellation.d.ts.map +1 -0
  77. package/dist/mission-cancellation.js +43 -0
  78. package/dist/mission-cancellation.js.map +1 -0
  79. package/dist/mission-execution.d.ts +103 -0
  80. package/dist/mission-execution.d.ts.map +1 -0
  81. package/dist/mission-execution.js +196 -0
  82. package/dist/mission-execution.js.map +1 -0
  83. package/dist/mission-executor.d.ts +18 -16
  84. package/dist/mission-executor.d.ts.map +1 -1
  85. package/dist/mission-executor.js +339 -203
  86. package/dist/mission-executor.js.map +1 -1
  87. package/dist/mission-gating.d.ts +11 -15
  88. package/dist/mission-gating.d.ts.map +1 -1
  89. package/dist/mission-gating.js +25 -33
  90. package/dist/mission-gating.js.map +1 -1
  91. package/dist/mission-inspection.d.ts +29 -0
  92. package/dist/mission-inspection.d.ts.map +1 -0
  93. package/dist/mission-inspection.js +99 -0
  94. package/dist/mission-inspection.js.map +1 -0
  95. package/dist/mission-store.d.ts +7 -0
  96. package/dist/mission-store.d.ts.map +1 -1
  97. package/dist/mission-store.js +8 -0
  98. package/dist/mission-store.js.map +1 -1
  99. package/dist/orchestrator-context.d.ts +3 -0
  100. package/dist/orchestrator-context.d.ts.map +1 -1
  101. package/dist/orchestrator-engine.d.ts +39 -39
  102. package/dist/orchestrator-engine.d.ts.map +1 -1
  103. package/dist/orchestrator-engine.js +124 -24
  104. package/dist/orchestrator-engine.js.map +1 -1
  105. package/dist/run-state-monitor.d.ts +14 -0
  106. package/dist/run-state-monitor.d.ts.map +1 -0
  107. package/dist/run-state-monitor.js +63 -0
  108. package/dist/run-state-monitor.js.map +1 -0
  109. package/dist/run-store.d.ts +15 -0
  110. package/dist/run-store.d.ts.map +1 -1
  111. package/dist/runner-capability.d.ts +43 -0
  112. package/dist/runner-capability.d.ts.map +1 -0
  113. package/dist/runner-capability.js +55 -0
  114. package/dist/runner-capability.js.map +1 -0
  115. package/dist/runtime-metadata.d.ts +5 -0
  116. package/dist/runtime-metadata.d.ts.map +1 -0
  117. package/dist/runtime-metadata.js +21 -0
  118. package/dist/runtime-metadata.js.map +1 -0
  119. package/dist/scheduler.d.ts +2 -1
  120. package/dist/scheduler.d.ts.map +1 -1
  121. package/dist/scheduler.js +16 -6
  122. package/dist/scheduler.js.map +1 -1
  123. package/dist/schemas.d.ts +8 -6
  124. package/dist/schemas.d.ts.map +1 -1
  125. package/dist/schemas.js +10 -0
  126. package/dist/schemas.js.map +1 -1
  127. package/dist/spawner.d.ts +12 -0
  128. package/dist/spawner.d.ts.map +1 -1
  129. package/dist/steering.d.ts +4 -1
  130. package/dist/steering.d.ts.map +1 -1
  131. package/dist/steering.js.map +1 -1
  132. package/dist/task-approval-coordinator.d.ts +29 -0
  133. package/dist/task-approval-coordinator.d.ts.map +1 -0
  134. package/dist/task-approval-coordinator.js +216 -0
  135. package/dist/task-approval-coordinator.js.map +1 -0
  136. package/dist/task-dispatch.d.ts +40 -0
  137. package/dist/task-dispatch.d.ts.map +1 -0
  138. package/dist/task-dispatch.js +136 -0
  139. package/dist/task-dispatch.js.map +1 -0
  140. package/dist/task-execution.d.ts +146 -0
  141. package/dist/task-execution.d.ts.map +1 -0
  142. package/dist/task-execution.js +357 -0
  143. package/dist/task-execution.js.map +1 -0
  144. package/dist/task-manager.d.ts +31 -22
  145. package/dist/task-manager.d.ts.map +1 -1
  146. package/dist/task-manager.js +74 -7
  147. package/dist/task-manager.js.map +1 -1
  148. package/dist/task-runner.d.ts +30 -3
  149. package/dist/task-runner.d.ts.map +1 -1
  150. package/dist/task-runner.js +429 -90
  151. package/dist/task-runner.js.map +1 -1
  152. package/dist/task-store.d.ts +9 -3
  153. package/dist/task-store.d.ts.map +1 -1
  154. package/dist/tool-invocation.d.ts +4 -0
  155. package/dist/tool-invocation.d.ts.map +1 -1
  156. package/dist/tool-invocation.js +8 -1
  157. package/dist/tool-invocation.js.map +1 -1
  158. package/dist/tool-invocation.test.d.ts +2 -0
  159. package/dist/tool-invocation.test.d.ts.map +1 -0
  160. package/dist/tool-invocation.test.js +40 -0
  161. package/dist/tool-invocation.test.js.map +1 -0
  162. package/dist/types/agent.d.ts +4 -0
  163. package/dist/types/agent.d.ts.map +1 -1
  164. package/dist/types/agent.js.map +1 -1
  165. package/dist/types/config.d.ts +3 -0
  166. package/dist/types/config.d.ts.map +1 -1
  167. package/dist/types/config.js.map +1 -1
  168. package/dist/types/mission.d.ts +23 -1
  169. package/dist/types/mission.d.ts.map +1 -1
  170. package/dist/types/task.d.ts +10 -0
  171. package/dist/types/task.d.ts.map +1 -1
  172. package/package.json +17 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-manager.test.js","sourceRoot":"","sources":["../src/approval-manager.test.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import type { ApprovalManager } from "./approval-manager.js";
1
2
  /**
2
3
  * AssessmentOrchestrator — handles the full assessment pipeline:
3
4
  * result collection → question detection → assessment → auto-correction → judge → fix/retry/fail.
@@ -8,6 +9,7 @@
8
9
  */
9
10
  import type { OrchestratorContext } from "./orchestrator-context.js";
10
11
  import type { Task, TaskResult, ModelConfig } from "./types.js";
12
+ import { type TaskExecutionReference } from "./task-execution.js";
11
13
  /**
12
14
  * Optional ports for runtime-specific operations that cannot go through
13
15
  * OrchestratorContext (to avoid modifying the shared interface).
@@ -46,8 +48,16 @@ export interface AssessmentPorts {
46
48
  */
47
49
  export declare class AssessmentOrchestrator {
48
50
  private ctx;
51
+ private approvals?;
52
+ setApprovalManager(manager: ApprovalManager | undefined): void;
49
53
  private ports;
54
+ private execution?;
50
55
  constructor(ctx: OrchestratorContext, ports?: AssessmentPorts);
56
+ private readTask;
57
+ private executionStore;
58
+ private patchTask;
59
+ private transitionTask;
60
+ private requeueTask;
51
61
  private orchestratorModel;
52
62
  /**
53
63
  * Build a rich ReviewContext from all available data sources:
@@ -67,7 +77,8 @@ export declare class AssessmentOrchestrator {
67
77
  private getConfidence;
68
78
  /** Check if any failed checks correspond to estimated expectations. */
69
79
  private hasEstimatedFailures;
70
- handleResult(taskId: string, result: TaskResult): Promise<void>;
80
+ handleResult(taskId: string, result: TaskResult, execution?: TaskExecutionReference): Promise<void>;
81
+ private handleExecutionResult;
71
82
  /**
72
83
  * LLM-classify a potential question, then either resolve+rerun or proceed to assessment.
73
84
  */
@@ -1 +1 @@
1
- {"version":3,"file":"assessment-orchestrator.d.ts","sourceRoot":"","sources":["../src/assessment-orchestrator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAoD,WAAW,EAAE,MAAM,YAAY,CAAC;AAWlH;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,iFAAiF;IACjF,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC1F,kDAAkD;IAClD,QAAQ,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC;IAC1C,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACjG,sFAAsF;IACtF,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW,KAAK,OAAO,CAAC;QAAE,UAAU,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3H;AAED;;;GAGG;AACH,qBAAa,sBAAsB;IAGrB,OAAO,CAAC,GAAG;IAFvB,OAAO,CAAC,KAAK,CAAkB;gBAEX,GAAG,EAAE,mBAAmB,EAAE,KAAK,CAAC,EAAE,eAAe;IAIrE,OAAO,CAAC,iBAAiB;IAOzB;;;;;;OAMG;YACW,kBAAkB;IAmChC;;;;OAIG;YACW,gBAAgB;IA2B9B,wEAAwE;IACxE,OAAO,CAAC,aAAa;IAKrB,uEAAuE;IACvE,OAAO,CAAC,oBAAoB;IAKtB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAqCrE;;OAEG;YACW,sBAAsB;IAwBpC;;OAEG;YACW,eAAe;IAyC7B;;;OAGG;YACW,oBAAoB;IAkDlC;;;OAGG;YACW,sBAAsB;IA8BpC;;OAEG;YACW,mBAAmB;IAgCjC;;OAEG;YACW,iBAAiB;IA+F/B;;;;;OAKG;YACW,0BAA0B;IA+GxC;;0EAEsE;IACtE,OAAO,CAAC,cAAc;IAoBtB;;;;;OAKG;YACW,iBAAiB;IAmG/B,mFAAmF;IACnF,OAAO,CAAC,SAAS;IAoBjB;;;OAGG;YACW,UAAU;IAsDxB,kEAAkE;IAC5D,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAsGlF"}
1
+ {"version":3,"file":"assessment-orchestrator.d.ts","sourceRoot":"","sources":["../src/assessment-orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAoD,WAAW,EAAE,MAAM,YAAY,CAAC;AAKlH,OAAO,EACL,KAAK,sBAAsB,EAA2B,MAAM,qBAAqB,CAAC;AAYpF;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,iFAAiF;IACjF,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC1F,kDAAkD;IAClD,QAAQ,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC;IAC1C,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACjG,sFAAsF;IACtF,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW,KAAK,OAAO,CAAC;QAAE,UAAU,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3H;AAED;;;GAGG;AACH,qBAAa,sBAAsB;IAMrB,OAAO,CAAC,GAAG;IALvB,OAAO,CAAC,SAAS,CAAC,CAAkB;IACpC,kBAAkB,CAAC,OAAO,EAAE,eAAe,GAAG,SAAS,GAAG,IAAI;IAC9D,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,SAAS,CAAC,CAAyB;gBAEvB,GAAG,EAAE,mBAAmB,EAAE,KAAK,CAAC,EAAE,eAAe;YAIvD,QAAQ;IAWtB,OAAO,CAAC,cAAc;YAKR,SAAS;YAKT,cAAc;YAMd,WAAW;IAezB,OAAO,CAAC,iBAAiB;IAOzB;;;;;;OAMG;YACW,kBAAkB;IAoChC;;;;OAIG;YACW,gBAAgB;IAsC9B,wEAAwE;IACxE,OAAO,CAAC,aAAa;IAKrB,uEAAuE;IACvE,OAAO,CAAC,oBAAoB;IAKtB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;YAiB3F,qBAAqB;IAuCnC;;OAEG;YACW,sBAAsB;IAyBpC;;OAEG;YACW,eAAe;IAkC7B;;;OAGG;YACW,oBAAoB;IAkDlC;;;OAGG;YACW,sBAAsB;IA8BpC;;OAEG;YACW,mBAAmB;IAiCjC;;OAEG;YACW,iBAAiB;IAiG/B;;;;;OAKG;YACW,0BAA0B;IAgHxC;;0EAEsE;IACtE,OAAO,CAAC,cAAc;IAoBtB;;;;;OAKG;YACW,iBAAiB;IAsG/B,mFAAmF;IACnF,OAAO,CAAC,SAAS;IAqBjB;;;OAGG;YACW,UAAU;IA8CxB,kEAAkE;IAC5D,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAyGlF"}
@@ -1,27 +1,68 @@
1
- /**
2
- * AssessmentOrchestrator — handles the full assessment pipeline:
3
- * result collection → question detection → assessment → auto-correction → judge → fix/retry/fail.
4
- *
5
- * Pure core version — ZERO Node.js imports.
6
- * All runtime-specific behavior is injected via OrchestratorContext ports
7
- * and the optional AssessmentPorts interface.
8
- */
9
1
  import { resolveMissionStore, resolveMissionForTask } from "./mission-store.js";
10
2
  import { setAssessment } from "./types.js";
11
3
  import { buildFixPrompt, buildRetryPrompt, buildSideEffectFixPrompt, buildSideEffectRetryPrompt, buildJudgePrompt } from "./assessment-prompts.js";
12
4
  import { looksLikeQuestion, classifyAsQuestion } from "./question-detector.js";
13
5
  import { resolveConfiguredModelSelection } from "./model-profiles.js";
6
+ import { isTaskExecutionStore, normalizeTaskExecutionReference, taskExecutionReference, TaskExecutionError } from "./task-execution.js";
7
+ function isExecutionConflict(error) {
8
+ return error instanceof TaskExecutionError && error.code === "task_execution_conflict";
9
+ }
14
10
  /**
15
11
  * Handles the full assessment pipeline: result collection → question detection →
16
12
  * assessment → auto-correction → judge → fix/retry/fail.
17
13
  */
18
14
  export class AssessmentOrchestrator {
19
15
  ctx;
16
+ approvals;
17
+ setApprovalManager(manager) { this.approvals = manager; }
20
18
  ports;
19
+ execution;
21
20
  constructor(ctx, ports) {
22
21
  this.ctx = ctx;
23
22
  this.ports = ports ?? {};
24
23
  }
24
+ async readTask(taskId) {
25
+ const task = await this.ctx.taskStore.getTask(taskId);
26
+ if (this.execution) {
27
+ const current = task && taskExecutionReference(task);
28
+ if (!current || current.taskId !== this.execution.taskId || current.revision !== this.execution.revision || current.runId !== this.execution.runId) {
29
+ throw new TaskExecutionError("task_execution_conflict", "Assessment execution changed");
30
+ }
31
+ }
32
+ return task;
33
+ }
34
+ executionStore() {
35
+ if (!isTaskExecutionStore(this.ctx.taskStore))
36
+ throw new TaskExecutionError("task_execution_unsupported", "Assessment requires execution persistence");
37
+ return this.ctx.taskStore;
38
+ }
39
+ async patchTask(taskId, updates) {
40
+ if (!this.execution)
41
+ return this.ctx.taskStore.updateTask(taskId, updates);
42
+ return (await this.executionStore().mutateTaskExecution(this.execution, { type: "patch", updates })).task;
43
+ }
44
+ async transitionTask(taskId, status, updates) {
45
+ if (this.execution)
46
+ return (await this.executionStore().mutateTaskExecution(this.execution, { type: "transition", status, updates })).task;
47
+ const task = await this.ctx.taskStore.transition(taskId, status);
48
+ return updates ? this.ctx.taskStore.updateTask(taskId, updates) : task;
49
+ }
50
+ async requeueTask(taskId, countRetry, reason, updates) {
51
+ if (this.execution) {
52
+ // Publish the next attempt and its complete input together. Once the
53
+ // revision changes, this assessor must never write through its old scope.
54
+ await this.executionStore().mutateTaskExecution(this.execution, { type: "requeue", countRetry, reason, updates });
55
+ }
56
+ else {
57
+ if (countRetry) {
58
+ await this.ctx.taskStore.transition(taskId, "failed");
59
+ await this.ctx.taskStore.transition(taskId, "pending");
60
+ }
61
+ else
62
+ await this.ctx.taskStore.unsafeSetStatus(taskId, "pending", reason);
63
+ await this.ctx.taskStore.updateTask(taskId, updates);
64
+ }
65
+ }
25
66
  orchestratorModel() {
26
67
  const selection = this.ctx.config.settings.orchestratorModel;
27
68
  return selection
@@ -36,7 +77,7 @@ export class AssessmentOrchestrator {
36
77
  * - Task outcomes
37
78
  */
38
79
  async buildReviewContext(taskId, task, result) {
39
- const run = await this.ctx.runStore.getRunByTaskId(taskId);
80
+ const run = await (this.execution?.runId ? this.ctx.runStore.getRun(this.execution.runId) : this.ctx.runStore.getRunByTaskId(taskId));
40
81
  const activity = run?.activity;
41
82
  const outcomes = run?.outcomes ?? task.outcomes;
42
83
  // Build execution summary from JSONL transcript log (via ctx ports)
@@ -52,7 +93,10 @@ export class AssessmentOrchestrator {
52
93
  }
53
94
  }
54
95
  }
55
- catch { /* best effort — don't fail assessment if log parsing fails */ }
96
+ catch (error) {
97
+ if (isExecutionConflict(error))
98
+ throw error; /* best effort — don't fail assessment if log parsing fails */
99
+ }
56
100
  return {
57
101
  taskTitle: task.title,
58
102
  taskDescription: task.originalDescription ?? task.description,
@@ -74,8 +118,14 @@ export class AssessmentOrchestrator {
74
118
  * Returns true if the task transitioned to done, false if a hook blocked it.
75
119
  */
76
120
  async transitionToDone(taskId, task, result) {
121
+ // The assessment has persisted result/phase since the original Task read.
122
+ // Re-read while preserving this invocation's captured execution reference.
123
+ const authoritative = await this.readTask(taskId);
124
+ if (!authoritative)
125
+ throw new TaskExecutionError("task_execution_conflict", "Assessment Task disappeared");
126
+ task = structuredClone(authoritative);
77
127
  const hookResult = await this.ctx.hooks.runBefore("task:complete", {
78
- taskId, task, result,
128
+ taskId, task, result: structuredClone(authoritative.result ?? result),
79
129
  });
80
130
  if (hookResult.cancelled) {
81
131
  this.ctx.emitter.emit("log", {
@@ -84,14 +134,22 @@ export class AssessmentOrchestrator {
84
134
  });
85
135
  return false;
86
136
  }
137
+ // Completion hooks can veto, but cannot replace the persisted assessment
138
+ // or principal. Consent, the done Task and after-hooks expose one output.
139
+ task = structuredClone(authoritative);
140
+ result = structuredClone(authoritative.result ?? result);
141
+ if (!this.approvals && this.ctx.config.settings.approvalGates?.some(gate => gate.hook === "task:complete")) {
142
+ throw new TaskExecutionError("task_execution_unsupported", "Task approval coordinator is required");
143
+ }
144
+ if (this.approvals && !await this.approvals.checkTask("task:complete", authoritative, { task, result }))
145
+ return false;
146
+ await this.transitionTask(taskId, "done", { phase: undefined });
87
147
  this.ctx.emitter.emit("task:transition", {
88
148
  taskId,
89
149
  from: task.status,
90
150
  to: "done",
91
151
  task: { ...task, status: "done" },
92
152
  });
93
- await this.ctx.taskStore.transition(taskId, "done");
94
- await this.ctx.taskStore.updateTask(taskId, { phase: undefined });
95
153
  // Fire after:task:complete (async, fire-and-forget)
96
154
  this.ctx.hooks.runAfter("task:complete", { taskId, task, result }).catch(() => { });
97
155
  return true;
@@ -107,10 +165,32 @@ export class AssessmentOrchestrator {
107
165
  const failedTypes = new Set(assessment.checks.filter(c => !c.passed).map(c => c.type));
108
166
  return task.expectations.some(e => failedTypes.has(e.type) && this.getConfidence(e) === "estimated");
109
167
  }
110
- async handleResult(taskId, result) {
111
- const task = await this.ctx.taskStore.getTask(taskId);
168
+ async handleResult(taskId, result, execution) {
169
+ // A separate scope per invocation keeps concurrent assessors from sharing
170
+ // mutable attempt identity across their asynchronous work.
171
+ const scope = new AssessmentOrchestrator(this.ctx, this.ports);
172
+ scope.setApprovalManager(this.approvals);
173
+ if (execution) {
174
+ scope.execution = normalizeTaskExecutionReference(execution);
175
+ if (execution.taskId !== taskId)
176
+ throw new TaskExecutionError("task_execution_invalid", "Result Task does not match execution");
177
+ }
178
+ try {
179
+ await scope.handleExecutionResult(taskId, result);
180
+ }
181
+ catch (error) {
182
+ if (!isExecutionConflict(error))
183
+ throw error;
184
+ // The old Run remains collectable history; the newer attempt is untouched.
185
+ }
186
+ }
187
+ async handleExecutionResult(taskId, result) {
188
+ const task = await this.readTask(taskId);
112
189
  if (!task)
113
190
  return;
191
+ if (!this.execution && (task.activeRunId !== undefined || task.executionRevision !== undefined)) {
192
+ throw new TaskExecutionError("task_execution_invalid", "Task result requires its execution reference");
193
+ }
114
194
  // Skip if already terminal
115
195
  if (task.status === "done" || task.status === "failed")
116
196
  return;
@@ -123,15 +203,14 @@ export class AssessmentOrchestrator {
123
203
  });
124
204
  // Ensure we're in review state
125
205
  if (task.status === "in_progress") {
126
- await this.ctx.taskStore.transition(taskId, "review");
127
- await this.ctx.taskStore.updateTask(taskId, { phase: "review" });
206
+ await this.transitionTask(taskId, "review", { phase: "review" });
128
207
  }
129
208
  // Question detection: intercept before assessment
130
209
  const maxQRounds = this.ctx.config.settings.maxQuestionRounds ?? 2;
131
210
  const questionRounds = task.questionRounds ?? 0;
132
211
  if (result.exitCode === 0 && questionRounds < maxQRounds) {
133
212
  // Get activity from RunStore for richer heuristic
134
- const run = await this.ctx.runStore.getRunByTaskId(taskId);
213
+ const run = await (this.execution?.runId ? this.ctx.runStore.getRun(this.execution.runId) : this.ctx.runStore.getRunByTaskId(taskId));
135
214
  const activity = run?.activity;
136
215
  if (looksLikeQuestion(result, activity)) {
137
216
  await this.handlePossibleQuestion(taskId, task, result);
@@ -162,7 +241,9 @@ export class AssessmentOrchestrator {
162
241
  await this.proceedToAssessment(taskId, task, result);
163
242
  }
164
243
  }
165
- catch {
244
+ catch (error) {
245
+ if (isExecutionConflict(error))
246
+ throw error;
166
247
  // Classification failed → proceed normally
167
248
  await this.proceedToAssessment(taskId, task, result);
168
249
  }
@@ -178,26 +259,23 @@ export class AssessmentOrchestrator {
178
259
  : this.generateAnswerInline(task, question);
179
260
  try {
180
261
  const answer = await answerPromise;
181
- this.ctx.emitter.emit("task:answered", { taskId, question, answer });
182
- const current = await this.ctx.taskStore.getTask(taskId);
262
+ const current = await this.readTask(taskId);
183
263
  if (!current)
184
264
  return;
185
- // Save original description before first Q&A
186
- if (!current.originalDescription) {
187
- await this.ctx.taskStore.updateTask(taskId, { originalDescription: current.description });
188
- }
189
- // Clear old outcomes before re-run — the agent will produce fresh ones.
190
- await this.ctx.taskStore.updateTask(taskId, { outcomes: [] });
191
265
  // Append Q&A to description and re-run (no retry burn)
192
266
  const qaBlock = `\n\n[Polpo Clarification]\nQ: ${question}\nA: ${answer}`;
193
- await this.ctx.taskStore.unsafeSetStatus(taskId, "pending", "Q&A re-run — no retry burn");
194
- await this.ctx.taskStore.updateTask(taskId, {
267
+ await this.requeueTask(taskId, false, "Q&A re-run — no retry burn", {
268
+ originalDescription: current.originalDescription ?? current.description,
269
+ outcomes: [],
195
270
  phase: "execution",
196
271
  description: current.description + qaBlock,
197
272
  questionRounds: (current.questionRounds ?? 0) + 1,
198
273
  });
274
+ this.ctx.emitter.emit("task:answered", { taskId, question, answer });
199
275
  }
200
- catch {
276
+ catch (error) {
277
+ if (isExecutionConflict(error))
278
+ throw error;
201
279
  // Answer generation failed → proceed to assessment normally
202
280
  await this.proceedToAssessment(taskId, task, result);
203
281
  }
@@ -271,7 +349,9 @@ export class AssessmentOrchestrator {
271
349
  try {
272
350
  hookResult = await this.ctx.hooks.runBefore("assessment:run", { taskId, task });
273
351
  }
274
- catch {
352
+ catch (error) {
353
+ if (isExecutionConflict(error))
354
+ throw error;
275
355
  // Hook failures must not detach or suppress the assessment lifecycle.
276
356
  }
277
357
  if (hookResult?.cancelled) {
@@ -279,7 +359,7 @@ export class AssessmentOrchestrator {
279
359
  level: "info",
280
360
  message: `[${taskId}] Assessment blocked by hook: ${hookResult.cancelReason ?? "no reason"}`,
281
361
  });
282
- await this.ctx.taskStore.updateTask(taskId, { result });
362
+ await this.patchTask(taskId, { result });
283
363
  if (result.exitCode === 0) {
284
364
  await this.transitionToDone(taskId, task, result);
285
365
  }
@@ -291,7 +371,7 @@ export class AssessmentOrchestrator {
291
371
  await this.runAssessmentFlow(taskId, task, result);
292
372
  }
293
373
  else {
294
- await this.ctx.taskStore.updateTask(taskId, { result });
374
+ await this.patchTask(taskId, { result });
295
375
  if (result.exitCode === 0) {
296
376
  await this.transitionToDone(taskId, task, result);
297
377
  }
@@ -319,7 +399,7 @@ export class AssessmentOrchestrator {
319
399
  try {
320
400
  const assessment = await this.runAssessmentWithRetry(task, this.ctx.agentWorkDir, progressCb, reviewContext, checkProgressCb);
321
401
  setAssessment(result, assessment, "initial");
322
- await this.ctx.taskStore.updateTask(taskId, { result });
402
+ await this.patchTask(taskId, { result });
323
403
  if (assessment.passed && result.exitCode === 0) {
324
404
  this.ctx.emitter.emit("assessment:complete", {
325
405
  taskId,
@@ -341,7 +421,7 @@ export class AssessmentOrchestrator {
341
421
  message: exitMsg,
342
422
  details: result.stderr || undefined,
343
423
  });
344
- await this.ctx.taskStore.updateTask(taskId, { result });
424
+ await this.patchTask(taskId, { result });
345
425
  this.ctx.emitter.emit("assessment:complete", {
346
426
  taskId,
347
427
  passed: false,
@@ -376,7 +456,9 @@ export class AssessmentOrchestrator {
376
456
  if (!judged)
377
457
  await this.fixOrRetry(taskId, task, result);
378
458
  }
379
- catch {
459
+ catch (error) {
460
+ if (isExecutionConflict(error))
461
+ throw error;
380
462
  await this.fixOrRetry(taskId, task, result);
381
463
  }
382
464
  }
@@ -390,9 +472,11 @@ export class AssessmentOrchestrator {
390
472
  }
391
473
  }
392
474
  catch (err) {
475
+ if (isExecutionConflict(err))
476
+ throw err;
393
477
  const message = err instanceof Error ? err.message : String(err);
394
478
  this.ctx.emitter.emit("log", { level: "error", message: `[${taskId}] Assessment error: ${message}` });
395
- await this.ctx.taskStore.updateTask(taskId, { result });
479
+ await this.patchTask(taskId, { result });
396
480
  await this.retryOrFail(taskId, task, result);
397
481
  }
398
482
  }
@@ -423,7 +507,7 @@ export class AssessmentOrchestrator {
423
507
  if (!fileExists || !baseName)
424
508
  return false;
425
509
  // Gather agent's actual file list from activity
426
- const run = await this.ctx.runStore.getRunByTaskId(taskId);
510
+ const run = await (this.execution?.runId ? this.ctx.runStore.getRun(this.execution.runId) : this.ctx.runStore.getRunByTaskId(taskId));
427
511
  const activity = run?.activity;
428
512
  const agentFiles = [
429
513
  ...(activity?.filesCreated ?? []),
@@ -476,10 +560,10 @@ export class AssessmentOrchestrator {
476
560
  for (const [idx, paths] of corrections) {
477
561
  newExpectations[idx] = { ...newExpectations[idx], paths };
478
562
  }
479
- await this.ctx.taskStore.updateTask(taskId, { expectations: newExpectations });
563
+ await this.patchTask(taskId, { expectations: newExpectations });
480
564
  this.ctx.emitter.emit("assessment:corrected", { taskId, corrections: corrections.size });
481
565
  // Re-assess with corrected expectations
482
- const current = await this.ctx.taskStore.getTask(taskId);
566
+ const current = await this.readTask(taskId);
483
567
  if (!current)
484
568
  return false;
485
569
  try {
@@ -487,7 +571,7 @@ export class AssessmentOrchestrator {
487
571
  const reCtx = await this.buildReviewContext(taskId, task, result);
488
572
  const newAssessment = await this.ctx.assessFn(current, this.ctx.agentWorkDir, progressCb, reCtx, this.ctx.config.settings.reasoning);
489
573
  setAssessment(result, newAssessment, "auto-correct");
490
- await this.ctx.taskStore.updateTask(taskId, { result });
574
+ await this.patchTask(taskId, { result });
491
575
  if (newAssessment.passed) {
492
576
  this.ctx.emitter.emit("assessment:complete", {
493
577
  taskId,
@@ -499,7 +583,9 @@ export class AssessmentOrchestrator {
499
583
  return this.transitionToDone(taskId, task, result);
500
584
  }
501
585
  }
502
- catch { /* re-assessment failed */
586
+ catch (error) {
587
+ if (isExecutionConflict(error))
588
+ throw error; /* re-assessment failed */
503
589
  }
504
590
  return false;
505
591
  }
@@ -549,14 +635,16 @@ export class AssessmentOrchestrator {
549
635
  if (!this.ctx.queryLLM)
550
636
  return false;
551
637
  // Gather context
552
- const run = await this.ctx.runStore.getRunByTaskId(taskId);
638
+ const run = await (this.execution?.runId ? this.ctx.runStore.getRun(this.execution.runId) : this.ctx.runStore.getRunByTaskId(taskId));
553
639
  const activity = run?.activity;
554
640
  const prompt = buildJudgePrompt(task, result, assessment, failedChecks, activity);
555
641
  let response;
556
642
  try {
557
643
  response = (await this.ctx.queryLLM(prompt, this.orchestratorModel())).text;
558
644
  }
559
- catch { /* LLM query failed */
645
+ catch (error) {
646
+ if (isExecutionConflict(error))
647
+ throw error; /* LLM query failed */
560
648
  return false;
561
649
  }
562
650
  // Parse LLM verdict
@@ -567,7 +655,9 @@ export class AssessmentOrchestrator {
567
655
  if (!verdict.corrections || !Array.isArray(verdict.corrections))
568
656
  return false;
569
657
  }
570
- catch { /* malformed JSON response */
658
+ catch (error) {
659
+ if (isExecutionConflict(error))
660
+ throw error; /* malformed JSON response */
571
661
  return false;
572
662
  }
573
663
  // Apply corrections only if LLM found at least one fixable expectation
@@ -600,10 +690,10 @@ export class AssessmentOrchestrator {
600
690
  }
601
691
  if (correctionCount === 0)
602
692
  return false;
603
- await this.ctx.taskStore.updateTask(taskId, { expectations: newExpectations });
693
+ await this.patchTask(taskId, { expectations: newExpectations });
604
694
  this.ctx.emitter.emit("assessment:corrected", { taskId, corrections: correctionCount });
605
695
  // Re-assess with corrected expectations
606
- const current = await this.ctx.taskStore.getTask(taskId);
696
+ const current = await this.readTask(taskId);
607
697
  if (!current)
608
698
  return false;
609
699
  try {
@@ -611,7 +701,7 @@ export class AssessmentOrchestrator {
611
701
  const judgeCtx = await this.buildReviewContext(taskId, task, result);
612
702
  const newAssessment = await this.ctx.assessFn(current, this.ctx.agentWorkDir, progressCb, judgeCtx, this.ctx.config.settings.reasoning);
613
703
  setAssessment(result, newAssessment, "judge");
614
- await this.ctx.taskStore.updateTask(taskId, { result });
704
+ await this.patchTask(taskId, { result });
615
705
  if (newAssessment.passed) {
616
706
  this.ctx.emitter.emit("assessment:complete", {
617
707
  taskId,
@@ -623,7 +713,9 @@ export class AssessmentOrchestrator {
623
713
  return this.transitionToDone(taskId, task, result);
624
714
  }
625
715
  }
626
- catch { /* re-assessment failed */
716
+ catch (error) {
717
+ if (isExecutionConflict(error))
718
+ throw error; /* re-assessment failed */
627
719
  }
628
720
  return false;
629
721
  }
@@ -649,7 +741,10 @@ export class AssessmentOrchestrator {
649
741
  }
650
742
  }
651
743
  }
652
- catch { /* permission error or missing dir */ }
744
+ catch (error) {
745
+ if (isExecutionConflict(error))
746
+ throw error; /* permission error or missing dir */
747
+ }
653
748
  return null;
654
749
  }
655
750
  /**
@@ -657,7 +752,7 @@ export class AssessmentOrchestrator {
657
752
  * without burning a full retry. After maxFixAttempts, fall back to full retry.
658
753
  */
659
754
  async fixOrRetry(taskId, _task, result) {
660
- const current = await this.ctx.taskStore.getTask(taskId);
755
+ const current = await this.readTask(taskId);
661
756
  if (!current)
662
757
  return;
663
758
  // Side-effects guard: block automatic fix/retry for tasks with irreversible actions.
@@ -669,37 +764,31 @@ export class AssessmentOrchestrator {
669
764
  this.ctx.emitter.emit("log", { level: "warn", message: `[${taskId}] ${reason}` });
670
765
  // Preserve original description and prepare fix prompt for when approval comes
671
766
  if (!current.originalDescription) {
672
- await this.ctx.taskStore.updateTask(taskId, { originalDescription: current.description });
767
+ await this.patchTask(taskId, { originalDescription: current.description });
673
768
  }
674
- await this.ctx.taskStore.updateTask(taskId, {
769
+ await this.patchTask(taskId, {
675
770
  description: buildSideEffectFixPrompt(current, result),
676
771
  phase: "fix",
677
772
  });
678
- await this.ctx.taskStore.transition(taskId, "awaiting_approval");
773
+ await this.transitionTask(taskId, "awaiting_approval");
679
774
  return;
680
775
  }
681
776
  const maxFix = this.ctx.config.settings.maxFixAttempts ?? 2;
682
777
  const fixAttempts = (current.fixAttempts ?? 0) + 1;
683
778
  if (fixAttempts <= maxFix) {
684
- // Save original description before first fix/retry
685
- if (!current.originalDescription) {
686
- await this.ctx.taskStore.updateTask(taskId, { originalDescription: current.description });
687
- }
688
- this.ctx.emitter.emit("task:fix", { taskId, attempt: fixAttempts, maxFix });
689
- // Clear old outcomes — the agent will produce fresh ones on re-execution.
690
- await this.ctx.taskStore.updateTask(taskId, { outcomes: [] });
691
- // unsafeSetStatus bypasses retry increment (fix attempts are NOT real failures)
692
- await this.ctx.taskStore.unsafeSetStatus(taskId, "pending", "fix phase — no retry burn");
693
- await this.ctx.taskStore.updateTask(taskId, {
779
+ await this.requeueTask(taskId, false, "fix phase — no retry burn", {
780
+ originalDescription: current.originalDescription ?? current.description,
781
+ outcomes: [],
694
782
  phase: "fix",
695
783
  fixAttempts,
696
784
  description: buildFixPrompt(current, result),
697
785
  });
786
+ this.ctx.emitter.emit("task:fix", { taskId, attempt: fixAttempts, maxFix });
698
787
  }
699
788
  else {
700
789
  // Fix attempts exhausted → full retry (burns 1 retry)
701
790
  this.ctx.emitter.emit("log", { level: "warn", message: `[${taskId}] Fix attempts exhausted (${maxFix}), falling back to full retry` });
702
- await this.ctx.taskStore.updateTask(taskId, {
791
+ await this.patchTask(taskId, {
703
792
  phase: "execution",
704
793
  fixAttempts: 0,
705
794
  });
@@ -708,7 +797,20 @@ export class AssessmentOrchestrator {
708
797
  }
709
798
  /** @internal — exposed for test access via Orchestrator facade */
710
799
  async retryOrFail(taskId, _task, result) {
711
- const current = await this.ctx.taskStore.getTask(taskId);
800
+ if (!this.execution && isTaskExecutionStore(this.ctx.taskStore)) {
801
+ const scope = new AssessmentOrchestrator(this.ctx, this.ports);
802
+ scope.setApprovalManager(this.approvals);
803
+ scope.execution = taskExecutionReference(_task);
804
+ try {
805
+ await scope.retryOrFail(taskId, _task, result);
806
+ }
807
+ catch (error) {
808
+ if (!isExecutionConflict(error))
809
+ throw error;
810
+ }
811
+ return;
812
+ }
813
+ const current = await this.readTask(taskId);
712
814
  if (!current)
713
815
  return;
714
816
  // Side-effects guard: block automatic retry for tasks with irreversible actions.
@@ -718,13 +820,13 @@ export class AssessmentOrchestrator {
718
820
  this.ctx.emitter.emit("log", { level: "warn", message: `[${taskId}] ${reason}` });
719
821
  // Preserve original description and prepare retry prompt for when approval comes
720
822
  if (!current.originalDescription) {
721
- await this.ctx.taskStore.updateTask(taskId, { originalDescription: current.description });
823
+ await this.patchTask(taskId, { originalDescription: current.description });
722
824
  }
723
- await this.ctx.taskStore.updateTask(taskId, {
825
+ await this.patchTask(taskId, {
724
826
  description: buildSideEffectRetryPrompt(current, result),
725
827
  phase: "execution",
726
828
  });
727
- await this.ctx.taskStore.transition(taskId, "awaiting_approval");
829
+ await this.transitionTask(taskId, "awaiting_approval");
728
830
  return;
729
831
  }
730
832
  // Don't retry tasks from cancelled missions — resolve via missionId (direct FK) first
@@ -732,7 +834,7 @@ export class AssessmentOrchestrator {
732
834
  const mission = await resolveMissionForTask(resolveMissionStore(this.ctx), current);
733
835
  if (mission && mission.status === "cancelled") {
734
836
  this.ctx.emitter.emit("log", { level: "debug", message: `[${taskId}] Skipping retry — mission cancelled` });
735
- await this.ctx.taskStore.transition(taskId, "failed");
837
+ await this.transitionTask(taskId, "failed");
736
838
  return;
737
839
  }
738
840
  }
@@ -741,7 +843,7 @@ export class AssessmentOrchestrator {
741
843
  const nextAttempt = current.retries + 1;
742
844
  // Save original description before first retry
743
845
  if (!current.originalDescription) {
744
- await this.ctx.taskStore.updateTask(taskId, { originalDescription: current.description });
846
+ await this.patchTask(taskId, { originalDescription: current.description });
745
847
  }
746
848
  // Check if we should escalate to a different agent
747
849
  // fallbackAgent resolution: explicit policy > agent.reportsTo (org chart)
@@ -757,18 +859,14 @@ export class AssessmentOrchestrator {
757
859
  }
758
860
  }
759
861
  }
760
- this.ctx.emitter.emit("task:retry", { taskId, attempt: nextAttempt, maxRetries: current.maxRetries });
761
- // Clear old outcomes — the agent will produce fresh ones on re-execution.
762
- // Without this, outcomes accumulate across retries and all get re-sent via notifications.
763
- await this.ctx.taskStore.updateTask(taskId, { outcomes: [] });
764
- await this.ctx.taskStore.transition(taskId, "failed");
765
- await this.ctx.taskStore.transition(taskId, "pending");
766
- await this.ctx.taskStore.updateTask(taskId, {
862
+ await this.requeueTask(taskId, true, "Assessment retry", {
863
+ outcomes: [],
767
864
  description: buildRetryPrompt(current, result),
768
865
  assignTo,
769
866
  phase: "execution",
770
867
  fixAttempts: 0,
771
868
  });
869
+ this.ctx.emitter.emit("task:retry", { taskId, attempt: nextAttempt, maxRetries: current.maxRetries });
772
870
  }
773
871
  else {
774
872
  this.ctx.emitter.emit("task:maxRetries", { taskId });
@@ -787,8 +885,7 @@ export class AssessmentOrchestrator {
787
885
  });
788
886
  return; // Escalation manager (or other hook) is handling this
789
887
  }
790
- await this.ctx.taskStore.transition(taskId, "failed");
791
- await this.ctx.taskStore.updateTask(taskId, { phase: undefined });
888
+ await this.transitionTask(taskId, "failed", { phase: undefined });
792
889
  // Fire after:task:fail
793
890
  this.ctx.hooks.runAfter("task:fail", {
794
891
  taskId,
@@ -797,10 +894,11 @@ export class AssessmentOrchestrator {
797
894
  reason: "maxRetries",
798
895
  }).catch(() => { });
799
896
  }
800
- catch {
897
+ catch (error) {
898
+ if (isExecutionConflict(error))
899
+ throw error;
801
900
  // Hook failed — fail the task normally
802
- await this.ctx.taskStore.transition(taskId, "failed");
803
- await this.ctx.taskStore.updateTask(taskId, { phase: undefined });
901
+ await this.transitionTask(taskId, "failed", { phase: undefined });
804
902
  }
805
903
  }
806
904
  }