@straiffi/archon 1.8.8 → 1.8.9

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 (176) hide show
  1. package/dist/client/assets/{ActivityView--4X_m6mR.js → ActivityView-gBeoYQdD.js} +1 -1
  2. package/dist/client/assets/{GitHubActionsDialog-DZ1lHM01.js → GitHubActionsDialog-fc1Vwafm.js} +1 -1
  3. package/dist/client/assets/RepositoryGraphDialog-DCOjwUR3.js +1 -0
  4. package/dist/client/assets/VerificationDialog-CIObj1Rw.js +4 -0
  5. package/dist/client/assets/{architectureDiagram-3BPJPVTR-CY5xTOZJ.js → architectureDiagram-3BPJPVTR-B1tJZe1S.js} +1 -1
  6. package/dist/client/assets/{blockDiagram-GPEHLZMM-DkMi7gMh.js → blockDiagram-GPEHLZMM-D_90AQ2Z.js} +1 -1
  7. package/dist/client/assets/{c4Diagram-AAUBKEIU-ZZxXBBU4.js → c4Diagram-AAUBKEIU-DSyJfqly.js} +1 -1
  8. package/dist/client/assets/channel-DFw1f2Rh.js +1 -0
  9. package/dist/client/assets/{chunk-2J33WTMH-C9PiKMs-.js → chunk-2J33WTMH-B9RStQGj.js} +1 -1
  10. package/dist/client/assets/{chunk-3OPIFGDE-B81aUmvi.js → chunk-3OPIFGDE-CHKuJYq0.js} +1 -1
  11. package/dist/client/assets/{chunk-5ZQYHXKU-Bk2Owm90.js → chunk-5ZQYHXKU-Cznw7LTJ.js} +1 -1
  12. package/dist/client/assets/{chunk-727SXJPM-Bx-79aJk.js → chunk-727SXJPM-ix6OeZwJ.js} +1 -1
  13. package/dist/client/assets/{chunk-AQP2D5EJ-GQNXYOf0.js → chunk-AQP2D5EJ-DrPJIcE7.js} +1 -1
  14. package/dist/client/assets/{chunk-CSCIHK7Q-BV22j6vn.js → chunk-CSCIHK7Q-BSEHTnBR.js} +1 -1
  15. package/dist/client/assets/{chunk-KSCS5N6A-C9LlcbWv.js → chunk-KSCS5N6A-MdDdaLn8.js} +1 -1
  16. package/dist/client/assets/{chunk-L5ZTLDWV-D8PJqJnh.js → chunk-L5ZTLDWV-D_5xeDG1.js} +1 -1
  17. package/dist/client/assets/{chunk-LZXEDZCA-DcbPPozR.js → chunk-LZXEDZCA-Bz8_Fyt2.js} +2 -2
  18. package/dist/client/assets/{chunk-ND2GUHAM-NV-_2KqZ.js → chunk-ND2GUHAM-DCINKlk8.js} +1 -1
  19. package/dist/client/assets/{chunk-NZK2D7GU-CbqA26gb.js → chunk-NZK2D7GU-rGPgryKx.js} +1 -1
  20. package/dist/client/assets/{chunk-O5CBEL6O-B0DMN44B.js → chunk-O5CBEL6O-BHB8UIYA.js} +1 -1
  21. package/dist/client/assets/{chunk-WU5MYG2G-CYpcnwf9.js → chunk-WU5MYG2G-Bz5BJWjF.js} +1 -1
  22. package/dist/client/assets/classDiagram-4FO5ZUOK-Dt0kmMzQ.js +1 -0
  23. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BuxhA4Gw.js +1 -0
  24. package/dist/client/assets/{dagre-BM42HDAG-B5HD9fyK.js → dagre-BM42HDAG-B4TXLkOG.js} +1 -1
  25. package/dist/client/assets/{diagram-2AECGRRQ-BCXvWFpM.js → diagram-2AECGRRQ-CxMup1wq.js} +1 -1
  26. package/dist/client/assets/{diagram-5GNKFQAL-CSpWGfAO.js → diagram-5GNKFQAL-CTfP_wnS.js} +1 -1
  27. package/dist/client/assets/{diagram-KO2AKTUF-CFECGppT.js → diagram-KO2AKTUF-31NKNt4r.js} +1 -1
  28. package/dist/client/assets/{diagram-LMA3HP47-Dpb99QbZ.js → diagram-LMA3HP47-Cxo7yvjc.js} +1 -1
  29. package/dist/client/assets/{diagram-OG6HWLK6-DJcTGnx0.js → diagram-OG6HWLK6-ChgSAMLv.js} +1 -1
  30. package/dist/client/assets/{erDiagram-TEJ5UH35-jWArJxNU.js → erDiagram-TEJ5UH35-u6msywL_.js} +1 -1
  31. package/dist/client/assets/{flowDiagram-I6XJVG4X-DDF3P1hY.js → flowDiagram-I6XJVG4X-CimeXkDN.js} +1 -1
  32. package/dist/client/assets/{ganttDiagram-6RSMTGT7-Corwr_18.js → ganttDiagram-6RSMTGT7-DOu5sDUI.js} +1 -1
  33. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-WzlpszWn.js → gitGraphDiagram-PVQCEYII-zIToibUf.js} +1 -1
  34. package/dist/client/assets/index-C-VHd0Pr.js +274 -0
  35. package/dist/client/assets/index-D3xlEyeM.css +2 -0
  36. package/dist/client/assets/{infoDiagram-5YYISTIA-C0VwTwNC.js → infoDiagram-5YYISTIA-CAtWGGJI.js} +1 -1
  37. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-m9l3k2qX.js → ishikawaDiagram-YF4QCWOH-7N-C7DEt.js} +1 -1
  38. package/dist/client/assets/{journeyDiagram-JHISSGLW-DMhT8HTW.js → journeyDiagram-JHISSGLW-D7VUypFG.js} +1 -1
  39. package/dist/client/assets/{kanban-definition-UN3LZRKU-C2ZkcOi0.js → kanban-definition-UN3LZRKU-AmbDmzSD.js} +1 -1
  40. package/dist/client/assets/{line-gKkUdUWR.js → line-qf4UZ8vh.js} +1 -1
  41. package/dist/client/assets/{mermaid-parser.core-DdBfJWbP.js → mermaid-parser.core-BssCd1kF.js} +1 -1
  42. package/dist/client/assets/{mermaid.core-DXnhq-eu.js → mermaid.core-DzeMqg9Y.js} +3 -3
  43. package/dist/client/assets/{mindmap-definition-RKZ34NQL-B0gX4aJy.js → mindmap-definition-RKZ34NQL-dEnNQcDm.js} +1 -1
  44. package/dist/client/assets/{pieDiagram-4H26LBE5-BHYdLmpx.js → pieDiagram-4H26LBE5-VjMue0a-.js} +1 -1
  45. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-C-H-yQwU.js → quadrantDiagram-W4KKPZXB-DQFdm-0f.js} +1 -1
  46. package/dist/client/assets/{requirementDiagram-4Y6WPE33-DY_pSCFy.js → requirementDiagram-4Y6WPE33-CHIaXlsy.js} +1 -1
  47. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-CC61HRGf.js → sankeyDiagram-5OEKKPKP-D-kzGaKb.js} +1 -1
  48. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-B8fXWNxw.js → sequenceDiagram-3UESZ5HK-CiDmlD8k.js} +1 -1
  49. package/dist/client/assets/{stateDiagram-AJRCARHV-C_VYKsXW.js → stateDiagram-AJRCARHV-BKlnnFdT.js} +1 -1
  50. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-DhJxc4em.js +1 -0
  51. package/dist/client/assets/{timeline-definition-PNZ67QCA-0fB4PIIX.js → timeline-definition-PNZ67QCA-D-BK07Un.js} +1 -1
  52. package/dist/client/assets/{vennDiagram-CIIHVFJN-CfpVF7Aa.js → vennDiagram-CIIHVFJN-CB9_GqSx.js} +1 -1
  53. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-CgdK4FcC.js → wardleyDiagram-YWT4CUSO-BEuNfyLT.js} +1 -1
  54. package/dist/client/assets/{xychartDiagram-2RQKCTM6-BEfatQYR.js → xychartDiagram-2RQKCTM6-CSS5WMrZ.js} +1 -1
  55. package/dist/client/index.html +2 -2
  56. package/dist/server/db.js +481 -27
  57. package/dist/server/db.js.map +1 -1
  58. package/dist/server/index.js +72 -18
  59. package/dist/server/index.js.map +1 -1
  60. package/dist/server/lib/activeAutomationChild.js +1 -0
  61. package/dist/server/lib/activeAutomationChild.js.map +1 -1
  62. package/dist/server/lib/agent.js +127 -15
  63. package/dist/server/lib/agent.js.map +1 -1
  64. package/dist/server/lib/agentRuns.js +12 -0
  65. package/dist/server/lib/agentRuns.js.map +1 -1
  66. package/dist/server/lib/agentSpawnPermits.js +37 -0
  67. package/dist/server/lib/agentSpawnPermits.js.map +1 -0
  68. package/dist/server/lib/automationCheckGate.js +9 -1
  69. package/dist/server/lib/automationCheckGate.js.map +1 -1
  70. package/dist/server/lib/automationProgression.js +19 -5
  71. package/dist/server/lib/automationProgression.js.map +1 -1
  72. package/dist/server/lib/automationReviewGate.js +1 -0
  73. package/dist/server/lib/automationReviewGate.js.map +1 -1
  74. package/dist/server/lib/buildCompletionContinuation.js +144 -4
  75. package/dist/server/lib/buildCompletionContinuation.js.map +1 -1
  76. package/dist/server/lib/buildSequences.js +13 -1
  77. package/dist/server/lib/buildSequences.js.map +1 -1
  78. package/dist/server/lib/bundleActivity.js +19 -0
  79. package/dist/server/lib/bundleActivity.js.map +1 -1
  80. package/dist/server/lib/chatOperations.js +81 -2
  81. package/dist/server/lib/chatOperations.js.map +1 -1
  82. package/dist/server/lib/checkAutoFix.js +604 -0
  83. package/dist/server/lib/checkAutoFix.js.map +1 -0
  84. package/dist/server/lib/checkAutoFixDetails.js +83 -0
  85. package/dist/server/lib/checkAutoFixDetails.js.map +1 -0
  86. package/dist/server/lib/checkAutoFixPolicy.js +59 -0
  87. package/dist/server/lib/checkAutoFixPolicy.js.map +1 -0
  88. package/dist/server/lib/checkRepair.js +149 -54
  89. package/dist/server/lib/checkRepair.js.map +1 -1
  90. package/dist/server/lib/checkRepairDispatch.js +91 -0
  91. package/dist/server/lib/checkRepairDispatch.js.map +1 -0
  92. package/dist/server/lib/checkRepairEvidence.js +84 -0
  93. package/dist/server/lib/checkRepairEvidence.js.map +1 -0
  94. package/dist/server/lib/checkRepairParent.js +21 -0
  95. package/dist/server/lib/checkRepairParent.js.map +1 -0
  96. package/dist/server/lib/checkRepairReconciliation.js +14 -5
  97. package/dist/server/lib/checkRepairReconciliation.js.map +1 -1
  98. package/dist/server/lib/checkRunner.js +27 -8
  99. package/dist/server/lib/checkRunner.js.map +1 -1
  100. package/dist/server/lib/checkRuns.js +63 -4
  101. package/dist/server/lib/checkRuns.js.map +1 -1
  102. package/dist/server/lib/executionReconciliation.js +387 -8
  103. package/dist/server/lib/executionReconciliation.js.map +1 -1
  104. package/dist/server/lib/executionRuns.js +24 -1
  105. package/dist/server/lib/executionRuns.js.map +1 -1
  106. package/dist/server/lib/integrations/github.js +10 -7
  107. package/dist/server/lib/integrations/github.js.map +1 -1
  108. package/dist/server/lib/postBuildCheckRuns.js +200 -5
  109. package/dist/server/lib/postBuildCheckRuns.js.map +1 -1
  110. package/dist/server/lib/postBuildChecks.js +83 -13
  111. package/dist/server/lib/postBuildChecks.js.map +1 -1
  112. package/dist/server/lib/projects.js +25 -1
  113. package/dist/server/lib/projects.js.map +1 -1
  114. package/dist/server/lib/queue.js +9 -3
  115. package/dist/server/lib/queue.js.map +1 -1
  116. package/dist/server/lib/repositoryGraphQueries.js +5 -3
  117. package/dist/server/lib/repositoryGraphQueries.js.map +1 -1
  118. package/dist/server/lib/repositoryGraphScan.js +13 -2
  119. package/dist/server/lib/repositoryGraphScan.js.map +1 -1
  120. package/dist/server/lib/repositoryGraphStore.js +61 -1
  121. package/dist/server/lib/repositoryGraphStore.js.map +1 -1
  122. package/dist/server/lib/specArtifact.js +10 -1
  123. package/dist/server/lib/specArtifact.js.map +1 -1
  124. package/dist/server/lib/specDraft.js +10 -2
  125. package/dist/server/lib/specDraft.js.map +1 -1
  126. package/dist/server/lib/specExport.js +70 -6
  127. package/dist/server/lib/specExport.js.map +1 -1
  128. package/dist/server/lib/specFormatting.js +3 -2
  129. package/dist/server/lib/specFormatting.js.map +1 -1
  130. package/dist/server/lib/specRepositoryEvidenceFormatting.js +75 -0
  131. package/dist/server/lib/specRepositoryEvidenceFormatting.js.map +1 -0
  132. package/dist/server/lib/specRepositoryImpact.js +447 -0
  133. package/dist/server/lib/specRepositoryImpact.js.map +1 -0
  134. package/dist/server/lib/specRepositoryImpactLimits.js +6 -0
  135. package/dist/server/lib/specRepositoryImpactLimits.js.map +1 -0
  136. package/dist/server/lib/specReviewContext.js +15 -5
  137. package/dist/server/lib/specReviewContext.js.map +1 -1
  138. package/dist/server/lib/specReviewValidation.js +1 -1
  139. package/dist/server/lib/specReviewValidation.js.map +1 -1
  140. package/dist/server/lib/specSections.js +28 -3
  141. package/dist/server/lib/specSections.js.map +1 -1
  142. package/dist/server/lib/specSnapshotEvidence.js +162 -0
  143. package/dist/server/lib/specSnapshotEvidence.js.map +1 -0
  144. package/dist/server/lib/specSnapshotEvidenceSerialization.js +202 -0
  145. package/dist/server/lib/specSnapshotEvidenceSerialization.js.map +1 -0
  146. package/dist/server/lib/specs.js +31 -5
  147. package/dist/server/lib/specs.js.map +1 -1
  148. package/dist/server/lib/ticketAutomationCommit.js +3 -1
  149. package/dist/server/lib/ticketAutomationCommit.js.map +1 -1
  150. package/dist/server/lib/ticketFollowUpOperations.js +16 -12
  151. package/dist/server/lib/ticketFollowUpOperations.js.map +1 -1
  152. package/dist/server/lib/ticketRunOperations.js +13 -1
  153. package/dist/server/lib/ticketRunOperations.js.map +1 -1
  154. package/dist/server/lib/ticketWorkflowOperations.js +5 -2
  155. package/dist/server/lib/ticketWorkflowOperations.js.map +1 -1
  156. package/dist/server/lib/types.js +1 -0
  157. package/dist/server/lib/types.js.map +1 -1
  158. package/dist/server/workers/build.js +46 -148
  159. package/dist/server/workers/build.js.map +1 -1
  160. package/dist/server/workers/chat.js +141 -31
  161. package/dist/server/workers/chat.js.map +1 -1
  162. package/dist/server/workers/followUp.js +210 -48
  163. package/dist/server/workers/followUp.js.map +1 -1
  164. package/dist/server/workers/specReview.js +17 -4
  165. package/dist/server/workers/specReview.js.map +1 -1
  166. package/dist/server/workers/specSession.js +127 -22
  167. package/dist/server/workers/specSession.js.map +1 -1
  168. package/package.json +1 -1
  169. package/dist/client/assets/RepositoryGraphDialog-B--YlQcV.js +0 -1
  170. package/dist/client/assets/VerificationDialog-BIWPtBg3.js +0 -4
  171. package/dist/client/assets/channel-b2AN-U3x.js +0 -1
  172. package/dist/client/assets/classDiagram-4FO5ZUOK-C0exS5oM.js +0 -1
  173. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DkB9dQZ1.js +0 -1
  174. package/dist/client/assets/index-Bs5SQZhz.css +0 -2
  175. package/dist/client/assets/index-Dy-7h3lN.js +0 -274
  176. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Ctk1r914.js +0 -1
@@ -2,6 +2,7 @@ import db from '../db.js';
2
2
  export const AUTOMATION_CHILD_KINDS = [
3
3
  'check_batch',
4
4
  'check_repair',
5
+ 'check_auto_fix',
5
6
  'review',
6
7
  'automation_review_fix',
7
8
  'automation_commit',
@@ -1 +1 @@
1
- {"version":3,"file":"activeAutomationChild.js","sourceRoot":"","sources":["../../../server/lib/activeAutomationChild.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAA;AAGzB,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,aAAa;IACb,cAAc;IACd,QAAQ;IACR,uBAAuB;IACvB,mBAAmB;IACnB,iBAAiB;IACjB,yBAAyB;CACqB,CAAA;AAIhD,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IAC1C,SAAS,CAAqB;IAEvC,YAAY,SAA8B;QACxC,KAAK,CAAC,oDAAoD,CAAC,CAAA;QAC3D,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;IAC5B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,SAAiB,EACjB,gBAAwB,EACxB,iBAA0B,EAC1B,EAAE;IACF,MAAM,YAAY,GAAG,sBAAsB,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACrE,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAAC;;;;qBAIZ,YAAY;;;GAG9B,CAAC,CAAC,GAAG,CACJ,SAAS,EACT,gBAAgB,EAChB,iBAAiB,IAAI,EAAE,EACvB,GAAG,sBAAsB,CACmB,CAAA;IAC9C,OAAO,WAAW,IAAI,IAAI,CAAA;AAC5B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAC3C,SAAiB,EACjB,gBAAwB,EACxB,iBAA0B,EAC1B,EAAE;IACF,MAAM,WAAW,GAAG,wBAAwB,CAAC,SAAS,EAAE,gBAAgB,EAAE,iBAAiB,CAAC,CAAA;IAC5F,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,IAAI,0BAA0B,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IACxD,CAAC;AACH,CAAC,CAAA"}
1
+ {"version":3,"file":"activeAutomationChild.js","sourceRoot":"","sources":["../../../server/lib/activeAutomationChild.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAA;AAGzB,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,aAAa;IACb,cAAc;IACd,gBAAgB;IAChB,QAAQ;IACR,uBAAuB;IACvB,mBAAmB;IACnB,iBAAiB;IACjB,yBAAyB;CACqB,CAAA;AAIhD,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IAC1C,SAAS,CAAqB;IAEvC,YAAY,SAA8B;QACxC,KAAK,CAAC,oDAAoD,CAAC,CAAA;QAC3D,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;IAC5B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,SAAiB,EACjB,gBAAwB,EACxB,iBAA0B,EAC1B,EAAE;IACF,MAAM,YAAY,GAAG,sBAAsB,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACrE,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAAC;;;;qBAIZ,YAAY;;;GAG9B,CAAC,CAAC,GAAG,CACJ,SAAS,EACT,gBAAgB,EAChB,iBAAiB,IAAI,EAAE,EACvB,GAAG,sBAAsB,CACmB,CAAA;IAC9C,OAAO,WAAW,IAAI,IAAI,CAAA;AAC5B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAC3C,SAAiB,EACjB,gBAAwB,EACxB,iBAA0B,EAC1B,EAAE;IACF,MAAM,WAAW,GAAG,wBAAwB,CAAC,SAAS,EAAE,gBAAgB,EAAE,iBAAiB,CAAC,CAAA;IAC5F,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,IAAI,0BAA0B,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IACxD,CAAC;AACH,CAAC,CAAA"}
@@ -17,6 +17,7 @@ import { markTicketDescriptionVisibleInBundle } from './ticketMessages.js';
17
17
  import { getTicket } from './tickets.js';
18
18
  import { createTranscriptRunSnapshots } from './transcriptRuns.js';
19
19
  import { createWorkspaceProcessEnvironment } from './workspaceProcessEnvironment.js';
20
+ import { assertAgentSpawnPermit, AgentSpawnPermitRevokedError } from './agentSpawnPermits.js';
20
21
  const withTranscriptRuns = (value, transcriptRuns) => {
21
22
  return transcriptRuns ? { ...value, transcriptRuns } : value;
22
23
  };
@@ -51,6 +52,14 @@ const createOpencodeRecoveryTracker = () => {
51
52
  const isSuccessfulOpencodeExit = (code, modelError, recoveryTracker) => (!modelError
52
53
  && !recoveryTracker.hasUnrecoveredError()
53
54
  && (code === 0 || recoveryTracker.hasRecoveredFinalAnswer()));
55
+ export class AgentContinuationRejectedError extends Error {
56
+ constructor(message) {
57
+ super(message);
58
+ this.name = 'AgentContinuationRejectedError';
59
+ }
60
+ }
61
+ export const isAgentContinuationRejectedError = (error) => (error instanceof AgentContinuationRejectedError);
62
+ const isTypedPreExecutionContinuationRejection = (message) => (/(?:session|conversation).*(?:not found|does not exist|invalid|expired)|(?:invalid|unknown).*(?:session|conversation)/i.test(message));
54
63
  const attachTranscriptRunsToError = (error, transcriptRuns) => {
55
64
  const resolvedError = (error instanceof Error ? error : new Error(String(error)));
56
65
  if (transcriptRuns) {
@@ -948,6 +957,9 @@ const emptyParsedStreamLine = () => ({
948
957
  subagentEvents: [],
949
958
  providerSessionId: null,
950
959
  });
960
+ const isExecutionCapableParsedStreamLine = (parsed) => (parsed.logFragment !== null
961
+ || parsed.responseFragment !== null
962
+ || parsed.subagentEvents.length > 0);
951
963
  const parseClaudeStreamJsonLine = (line, cwd) => {
952
964
  const trimmed = line.trim();
953
965
  if (!trimmed) {
@@ -1792,6 +1804,17 @@ export const registerChatProcessPlaceholder = (chatSessionId) => {
1792
1804
  activeChatProcesses.set(chatSessionId, state);
1793
1805
  return state;
1794
1806
  };
1807
+ export const registerBuildProcessPlaceholder = (ticketId) => {
1808
+ const state = { child: null, stopRequested: false, sessionLookupTimer: null };
1809
+ activeBuildProcesses.set(ticketId, state);
1810
+ return state;
1811
+ };
1812
+ export const untrackBuildProcessById = (ticketId) => {
1813
+ const state = activeBuildProcesses.get(ticketId);
1814
+ if (state) {
1815
+ untrackBuildProcess(ticketId, state);
1816
+ }
1817
+ };
1795
1818
  export const untrackChatProcessById = (chatSessionId) => {
1796
1819
  const state = activeChatProcesses.get(chatSessionId);
1797
1820
  if (state) {
@@ -1833,6 +1856,22 @@ const untrackSpecReviewProcess = (specReviewRunId, state) => {
1833
1856
  state.metadataRefresher?.stop();
1834
1857
  state.metadataRefresher = null;
1835
1858
  };
1859
+ export const registerSpecReviewProcessPlaceholder = (specReviewRunId) => {
1860
+ const state = {
1861
+ child: null,
1862
+ researchChildren: new Set(),
1863
+ stopRequested: false,
1864
+ metadataRefresher: null,
1865
+ };
1866
+ activeSpecReviewProcesses.set(specReviewRunId, state);
1867
+ return state;
1868
+ };
1869
+ export const untrackSpecReviewProcessById = (specReviewRunId) => {
1870
+ const state = activeSpecReviewProcesses.get(specReviewRunId);
1871
+ if (state) {
1872
+ untrackSpecReviewProcess(specReviewRunId, state);
1873
+ }
1874
+ };
1836
1875
  export const isBuildAgentRunning = (ticketId) => activeBuildProcesses.has(ticketId);
1837
1876
  export const registerReviewProcess = (ticketId) => {
1838
1877
  const state = { children: new Set(), stopRequested: false };
@@ -1858,10 +1897,13 @@ export const stopAllBuildAgents = async () => {
1858
1897
  };
1859
1898
  export const stopBuildAgent = async (ticketId) => {
1860
1899
  const state = activeBuildProcesses.get(ticketId);
1861
- if (!state?.child) {
1900
+ if (!state) {
1862
1901
  return false;
1863
1902
  }
1864
1903
  state.stopRequested = true;
1904
+ if (!state.child) {
1905
+ return true;
1906
+ }
1865
1907
  killProcess(state.child, 'SIGTERM');
1866
1908
  await waitForProcessExit(state.child, 5000);
1867
1909
  if (isProcessAlive(state.child)) {
@@ -1933,11 +1975,14 @@ export const stopSpecAgent = async (specSessionId) => {
1933
1975
  };
1934
1976
  export const stopSpecReviewAgent = async (specReviewRunId) => {
1935
1977
  const state = activeSpecReviewProcesses.get(specReviewRunId);
1936
- if (!state?.child) {
1978
+ if (!state) {
1937
1979
  return false;
1938
1980
  }
1939
1981
  state.stopRequested = true;
1940
1982
  state.metadataRefresher?.stop();
1983
+ if (!state.child) {
1984
+ return true;
1985
+ }
1941
1986
  killProcess(state.child, 'SIGTERM');
1942
1987
  await waitForProcessExit(state.child, 5000);
1943
1988
  if (isProcessAlive(state.child)) {
@@ -1946,7 +1991,7 @@ export const stopSpecReviewAgent = async (specReviewRunId) => {
1946
1991
  }
1947
1992
  return true;
1948
1993
  };
1949
- export const runAgent = ({ ticketId, tool, prompt, cwd, io, model, variant = null, resumeSessionId = null, sessionField = 'session_id', trackBuildProcess = false, reviewProcessState, emitSuccessUpdate = true, opencodeAgentMode, runStream, executionContext, persistSessionIdToTicket = false, }) => {
1994
+ export const runAgent = ({ ticketId, tool, prompt, cwd, io, model, variant = null, resumeSessionId = null, sessionField = 'session_id', trackBuildProcess = false, reviewProcessState, emitSuccessUpdate = true, opencodeAgentMode, runStream, executionContext, persistSessionIdToTicket = false, spawnPermitId, }) => {
1950
1995
  const resolvedModel = resolveAgentModel(tool, model);
1951
1996
  const subagentTracker = createSubagentRunTracker({
1952
1997
  parentType: 'ticket',
@@ -2002,8 +2047,9 @@ export const runAgent = ({ ticketId, tool, prompt, cwd, io, model, variant = nul
2002
2047
  let startTime = null;
2003
2048
  let firstFinalAnswerTime = null;
2004
2049
  let reviewChild = null;
2050
+ let executionCapableEventObserved = false;
2005
2051
  const buildState = trackBuildProcess
2006
- ? { child: null, stopRequested: false, sessionLookupTimer: null }
2052
+ ? activeBuildProcesses.get(ticketId) ?? registerBuildProcessPlaceholder(ticketId)
2007
2053
  : null;
2008
2054
  const settle = (handler) => (value) => {
2009
2055
  if (settled) {
@@ -2071,6 +2117,12 @@ export const runAgent = ({ ticketId, tool, prompt, cwd, io, model, variant = nul
2071
2117
  }
2072
2118
  let child;
2073
2119
  try {
2120
+ if (buildState?.stopRequested) {
2121
+ throw new AgentSpawnPermitRevokedError();
2122
+ }
2123
+ if (spawnPermitId && executionContext) {
2124
+ assertAgentSpawnPermit(spawnPermitId, executionContext.runId);
2125
+ }
2074
2126
  child = spawn(cmd, args, {
2075
2127
  cwd,
2076
2128
  stdio: tool === 'claude' ? ['pipe', 'pipe', 'pipe'] : ['ignore', 'pipe', 'pipe'],
@@ -2131,7 +2183,11 @@ export const runAgent = ({ ticketId, tool, prompt, cwd, io, model, variant = nul
2131
2183
  remainder = lines.pop() ?? '';
2132
2184
  for (const line of lines) {
2133
2185
  usageSnapshot = mergeUsageFromJsonLine(usageSnapshot, line);
2134
- const { logFragment, responseFragment, subagentEvents } = parseClaudeStreamJsonLine(line, cwd);
2186
+ const parsed = parseClaudeStreamJsonLine(line, cwd);
2187
+ const { logFragment, responseFragment, subagentEvents } = parsed;
2188
+ if (isExecutionCapableParsedStreamLine(parsed)) {
2189
+ executionCapableEventObserved = true;
2190
+ }
2135
2191
  subagentTracker.handle(subagentEvents);
2136
2192
  if (logFragment !== null) {
2137
2193
  logLines.push(logFragment);
@@ -2149,7 +2205,11 @@ export const runAgent = ({ ticketId, tool, prompt, cwd, io, model, variant = nul
2149
2205
  progressUpdater.cancel();
2150
2206
  if (remainder.trim()) {
2151
2207
  usageSnapshot = mergeUsageFromJsonLine(usageSnapshot, remainder);
2152
- const { logFragment, responseFragment, subagentEvents } = parseClaudeStreamJsonLine(remainder, cwd);
2208
+ const parsed = parseClaudeStreamJsonLine(remainder, cwd);
2209
+ const { logFragment, responseFragment, subagentEvents } = parsed;
2210
+ if (isExecutionCapableParsedStreamLine(parsed)) {
2211
+ executionCapableEventObserved = true;
2212
+ }
2153
2213
  subagentTracker.handle(subagentEvents);
2154
2214
  if (logFragment !== null) {
2155
2215
  logLines.push(logFragment);
@@ -2173,8 +2233,12 @@ export const runAgent = ({ ticketId, tool, prompt, cwd, io, model, variant = nul
2173
2233
  resolveOnce(withTranscriptRuns({ response: finalResponse, responseTiming: timing, usageSnapshot }, transcriptRuns));
2174
2234
  return;
2175
2235
  }
2176
- const transcriptRuns = finalizeRun('error', finalLog + (errOutput ? '\n\n' + errOutput : ''), finalResponse);
2177
- rejectOnce(attachTranscriptRunsToError(new Error(`Agent exited with code ${code ?? 'null'}\n${finalLog}${errOutput !== finalLog && errOutput ? '\n\n' + errOutput : ''}`), transcriptRuns));
2236
+ const failureMessage = `Agent exited with code ${code ?? 'null'}\n${finalLog}${errOutput !== finalLog && errOutput ? '\n\n' + errOutput : ''}`;
2237
+ const error = resumeSessionId && !executionCapableEventObserved && isTypedPreExecutionContinuationRejection(failureMessage)
2238
+ ? new AgentContinuationRejectedError(failureMessage)
2239
+ : new Error(failureMessage);
2240
+ const transcriptRuns = finalizeRun('error', failureMessage, finalResponse);
2241
+ rejectOnce(attachTranscriptRunsToError(error, transcriptRuns));
2178
2242
  });
2179
2243
  child.on('error', err => {
2180
2244
  progressUpdater.cancel();
@@ -2218,6 +2282,9 @@ export const runAgent = ({ ticketId, tool, prompt, cwd, io, model, variant = nul
2218
2282
  }
2219
2283
  const parsed = parseOpencodeJsonLine(line);
2220
2284
  const { logFragment, responseFragment, subagentEvents, providerSessionId } = parsed;
2285
+ if (isExecutionCapableParsedStreamLine(parsed)) {
2286
+ executionCapableEventObserved = true;
2287
+ }
2221
2288
  bindResolvedOpencodeSession(providerSessionId);
2222
2289
  subagentTracker.handle(subagentEvents);
2223
2290
  if (appendOpencodeTranscriptLine({ parsed, logLines, responseLines, recoveryTracker })) {
@@ -2248,6 +2315,9 @@ export const runAgent = ({ ticketId, tool, prompt, cwd, io, model, variant = nul
2248
2315
  if (remainder.trim()) {
2249
2316
  const parsed = parseOpencodeJsonLine(remainder);
2250
2317
  const { subagentEvents, providerSessionId } = parsed;
2318
+ if (isExecutionCapableParsedStreamLine(parsed)) {
2319
+ executionCapableEventObserved = true;
2320
+ }
2251
2321
  bindResolvedOpencodeSession(providerSessionId);
2252
2322
  subagentTracker.handle(subagentEvents);
2253
2323
  if (appendOpencodeTranscriptLine({ parsed, logLines, responseLines, recoveryTracker })) {
@@ -2273,8 +2343,12 @@ export const runAgent = ({ ticketId, tool, prompt, cwd, io, model, variant = nul
2273
2343
  resolveOnce(withTranscriptRuns({ response: finalResponse, responseTiming: timing }, transcriptRuns));
2274
2344
  return;
2275
2345
  }
2346
+ const failureMessage = `Agent exited with code ${code ?? 'null'}\n${log}${stderrOutput !== log && stderrOutput ? '\n\n' + stderrOutput : ''}`;
2347
+ const error = resumeSessionId && !executionCapableEventObserved && isTypedPreExecutionContinuationRejection(failureMessage)
2348
+ ? new AgentContinuationRejectedError(failureMessage)
2349
+ : new Error(failureMessage);
2276
2350
  const transcriptRuns = finalizeRun('error', log, finalResponse);
2277
- rejectOnce(attachTranscriptRunsToError(new Error(`Agent exited with code ${code ?? 'null'}\n${log}${stderrOutput !== log && stderrOutput ? '\n\n' + stderrOutput : ''}`), transcriptRuns));
2351
+ rejectOnce(attachTranscriptRunsToError(error, transcriptRuns));
2278
2352
  });
2279
2353
  child.on('error', err => {
2280
2354
  progressUpdater.cancel();
@@ -2292,7 +2366,7 @@ export const runAgent = ({ ticketId, tool, prompt, cwd, io, model, variant = nul
2292
2366
  });
2293
2367
  });
2294
2368
  };
2295
- export const runChatAgent = ({ chatSessionId, tool, prompt, files = [], cwd, io, model, variant = null, resumeSessionId = null, opencodeAgentMode = 'build', executionContext, mainRun, }) => {
2369
+ export const runChatAgent = ({ chatSessionId, tool, prompt, files = [], cwd, io, model, variant = null, resumeSessionId = null, opencodeAgentMode = 'build', executionContext, mainRun, spawnPermitId, }) => {
2296
2370
  const resolvedModel = resolveAgentModel(tool, model);
2297
2371
  const subagentTracker = createSubagentRunTracker({
2298
2372
  parentType: 'chat',
@@ -2311,6 +2385,7 @@ export const runChatAgent = ({ chatSessionId, tool, prompt, files = [], cwd, io,
2311
2385
  let startTime = null;
2312
2386
  let firstFinalAnswerTime = null;
2313
2387
  let usageSnapshot = EMPTY_CHAT_USAGE_SNAPSHOT;
2388
+ let executionCapableEventObserved = false;
2314
2389
  const chatState = activeChatProcesses.get(chatSessionId) ?? registerChatProcessPlaceholder(chatSessionId);
2315
2390
  const settle = (handler) => (value) => {
2316
2391
  if (settled) {
@@ -2367,6 +2442,12 @@ export const runChatAgent = ({ chatSessionId, tool, prompt, files = [], cwd, io,
2367
2442
  }
2368
2443
  let child;
2369
2444
  try {
2445
+ if (chatState.stopRequested) {
2446
+ throw new AgentSpawnPermitRevokedError();
2447
+ }
2448
+ if (spawnPermitId) {
2449
+ assertAgentSpawnPermit(spawnPermitId, executionContext.runId);
2450
+ }
2370
2451
  child = spawn(cmd, args, {
2371
2452
  cwd,
2372
2453
  stdio: tool === 'claude' ? ['pipe', 'pipe', 'pipe'] : ['ignore', 'pipe', 'pipe'],
@@ -2419,7 +2500,11 @@ export const runChatAgent = ({ chatSessionId, tool, prompt, files = [], cwd, io,
2419
2500
  const lines = text.split('\n');
2420
2501
  remainder = lines.pop() ?? '';
2421
2502
  for (const line of lines) {
2422
- const { logFragment, responseFragment, subagentEvents } = parseClaudeStreamJsonLine(line);
2503
+ const parsed = parseClaudeStreamJsonLine(line);
2504
+ const { logFragment, responseFragment, subagentEvents } = parsed;
2505
+ if (isExecutionCapableParsedStreamLine(parsed)) {
2506
+ executionCapableEventObserved = true;
2507
+ }
2423
2508
  subagentTracker.handle(subagentEvents);
2424
2509
  usageSnapshot = mergeUsageFromJsonLine(usageSnapshot, line);
2425
2510
  if (logFragment !== null) {
@@ -2438,7 +2523,11 @@ export const runChatAgent = ({ chatSessionId, tool, prompt, files = [], cwd, io,
2438
2523
  progressUpdater.cancel();
2439
2524
  if (remainder.trim()) {
2440
2525
  usageSnapshot = mergeUsageFromJsonLine(usageSnapshot, remainder);
2441
- const { logFragment, responseFragment, subagentEvents } = parseClaudeStreamJsonLine(remainder);
2526
+ const parsed = parseClaudeStreamJsonLine(remainder);
2527
+ const { logFragment, responseFragment, subagentEvents } = parsed;
2528
+ if (isExecutionCapableParsedStreamLine(parsed)) {
2529
+ executionCapableEventObserved = true;
2530
+ }
2442
2531
  subagentTracker.handle(subagentEvents);
2443
2532
  if (logFragment !== null) {
2444
2533
  logLines.push(logFragment);
@@ -2483,9 +2572,13 @@ export const runChatAgent = ({ chatSessionId, tool, prompt, files = [], cwd, io,
2483
2572
  }, transcriptRuns));
2484
2573
  return;
2485
2574
  }
2575
+ const failureMessage = `Agent exited with code ${code ?? 'null'}\n${finalLog}${errOutput !== finalLog && errOutput ? '\n\n' + errOutput : ''}`;
2576
+ const error = resumeSessionId && !executionCapableEventObserved && isTypedPreExecutionContinuationRejection(failureMessage)
2577
+ ? new AgentContinuationRejectedError(failureMessage)
2578
+ : new Error(failureMessage);
2486
2579
  updateChatSessionStatus(chatSessionId, 'error', finalLog + (errOutput ? '\n\n' + errOutput : ''), io, finalResponse);
2487
2580
  const transcriptRuns = subagentTracker.finalize('error', finalLog, finalResponse);
2488
- rejectOnce(attachTranscriptRunsToError(new Error(`Agent exited with code ${code ?? 'null'}\n${finalLog}${errOutput !== finalLog && errOutput ? '\n\n' + errOutput : ''}`), transcriptRuns));
2581
+ rejectOnce(attachTranscriptRunsToError(error, transcriptRuns));
2489
2582
  });
2490
2583
  child.on('error', err => {
2491
2584
  progressUpdater.cancel();
@@ -2547,6 +2640,9 @@ export const runChatAgent = ({ chatSessionId, tool, prompt, files = [], cwd, io,
2547
2640
  }
2548
2641
  const parsed = parseOpencodeJsonLine(line, cwd);
2549
2642
  const { logFragment, responseFragment, subagentEvents, providerSessionId } = parsed;
2643
+ if (isExecutionCapableParsedStreamLine(parsed)) {
2644
+ executionCapableEventObserved = true;
2645
+ }
2550
2646
  opencodeSubagentMonitor?.setParentSessionId(providerSessionId);
2551
2647
  subagentTracker.handle(subagentEvents);
2552
2648
  if (appendOpencodeTranscriptLine({ parsed, logLines, responseLines, recoveryTracker })) {
@@ -2567,6 +2663,9 @@ export const runChatAgent = ({ chatSessionId, tool, prompt, files = [], cwd, io,
2567
2663
  usageSnapshot = mergeUsageFromJsonLine(usageSnapshot, remainder);
2568
2664
  const parsed = parseOpencodeJsonLine(remainder, cwd);
2569
2665
  const { subagentEvents, providerSessionId } = parsed;
2666
+ if (isExecutionCapableParsedStreamLine(parsed)) {
2667
+ executionCapableEventObserved = true;
2668
+ }
2570
2669
  opencodeSubagentMonitor?.setParentSessionId(providerSessionId);
2571
2670
  subagentTracker.handle(subagentEvents);
2572
2671
  if (appendOpencodeTranscriptLine({ parsed, logLines, responseLines, recoveryTracker })) {
@@ -2635,8 +2734,12 @@ export const runChatAgent = ({ chatSessionId, tool, prompt, files = [], cwd, io,
2635
2734
  return;
2636
2735
  }
2637
2736
  updateChatSessionStatus(chatSessionId, 'error', log, io, finalResponse);
2737
+ const failureMessage = `Agent exited with code ${code ?? 'null'}\n${log}${stderrOutput !== log && stderrOutput ? '\n\n' + stderrOutput : ''}`;
2738
+ const error = resumeSessionId && !executionCapableEventObserved && isTypedPreExecutionContinuationRejection(failureMessage)
2739
+ ? new AgentContinuationRejectedError(failureMessage)
2740
+ : new Error(failureMessage);
2638
2741
  const transcriptRuns = subagentTracker.finalize('error', log, finalResponse);
2639
- rejectOnce(attachTranscriptRunsToError(new Error(`Agent exited with code ${code ?? 'null'}\n${log}${stderrOutput !== log && stderrOutput ? '\n\n' + stderrOutput : ''}`), transcriptRuns));
2742
+ rejectOnce(attachTranscriptRunsToError(error, transcriptRuns));
2640
2743
  });
2641
2744
  child.on('error', err => {
2642
2745
  progressUpdater.cancel();
@@ -3045,6 +3148,15 @@ export const runSpecAgent = ({ specSessionId, tool, prompt, files = [], cwd, io,
3045
3148
  * the spec_sessions row is never touched by this path.
3046
3149
  */
3047
3150
  export const runSpecReviewAgent = ({ specReviewRunId, specSessionId, tool, prompt, files = [], cwd, io, model, variant = null, executionContext, }) => {
3151
+ const registeredState = activeSpecReviewProcesses.get(specReviewRunId);
3152
+ if (registeredState?.stopRequested) {
3153
+ return Promise.resolve({
3154
+ completionStatus: 'stopped',
3155
+ finalResponse: null,
3156
+ usageSnapshot: EMPTY_CHAT_USAGE_SNAPSHOT,
3157
+ responseTiming: null,
3158
+ });
3159
+ }
3048
3160
  const resolvedModel = resolveAgentModel(tool, model);
3049
3161
  const subagentTracker = createSubagentRunTracker({
3050
3162
  parentType: 'spec',
@@ -3059,7 +3171,7 @@ export const runSpecReviewAgent = ({ specReviewRunId, specSessionId, tool, promp
3059
3171
  let startTime = null;
3060
3172
  let firstFinalAnswerTime = null;
3061
3173
  let usageSnapshot = EMPTY_CHAT_USAGE_SNAPSHOT;
3062
- const reviewState = {
3174
+ const reviewState = registeredState ?? {
3063
3175
  child: null,
3064
3176
  researchChildren: new Set(),
3065
3177
  stopRequested: false,