chainlesschain 0.166.26 → 0.166.28

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 (175) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/assets/{AIOps-Z8_dnLd8.js → AIOps-TeJoc3XQ.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-C4bKCISV.js → ActionButton-SZ9klC71.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-GztAv2jy.js → Analytics-BvxMGhXs.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-DEqNcuVx.js → AppLayout-5zUWvYnk.js} +4 -4
  6. package/src/assets/web-panel/assets/{Artifacts-D-R4Ehap.js → Artifacts-0BfSQj3N.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-mzzdTIlM.js → Audit-cScBdt3p.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-DS2QupIC.js → BackgroundAgents-022mS_uG.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-CQSirC39.js → Backup-CWnqpCpj.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-Bhuc-eOV.js → BaseInput-BCp80_Kc.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-B-RLVGnt.js → Chat-B2rj5NdZ.js} +6 -6
  12. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CBbMoVuE.js → ChatBubbleRenderer-2Lw_8bkr.js} +1 -1
  13. package/src/assets/web-panel/assets/{Checkbox-DxwgBryW.js → Checkbox-BTHrb0x7.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-Cwrm-7nh.js → Codegen-Y17WGsCF.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-DrSCT-nF.js → Col-BBBucqHI.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-DY2D9WNs.js → Community-B2qcNGY4.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-o-tV0URw.js → Compact-BhDyZd93.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-Bndh6S8f.js → Compliance-BUEgTVrI.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-CSNQODak.js → Cowork-_wey4IKY.js} +3 -3
  20. package/src/assets/web-panel/assets/{Cron-CTgxRHdy.js → Cron-BSO7RSdx.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-BJoGQzDI.js → Crosschain-DawYCk-u.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-V0Ztm8ne.js → DID-DvtgImFY.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-B-38THOj.js → Dashboard-DYAyw4yL.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-B3FdOwMO.js → Dropdown-CIaenBpM.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-YQDz4mUF.js → EmailListRenderer-jKv7wz64.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DYE45IF9.js → FamilyGuardDashboard-BxQggJuN.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-DjBFjdRZ.js → Federation-CDi_BOHj.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-CVTXEa0R.js → FormItemContext-C-7XWf-w.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-B6Tkke8X.js → GenericCardRenderer-D8PAhWue.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-CD0hyAzT.js → Git-yhajzO5I.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-CWOQQJr8.js → Governance-DjM6hZK3.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-lHYwUk-C.js → Inference-C-gVn1ci.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-Cledxv7t.js → KnowledgeGraph-CyG5TgH-.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-D45mt-rM.js → Logs-CnIbZJc3.js} +2 -2
  35. package/src/assets/web-panel/assets/MarkdownRenderer-BDfOgqr1.js +1 -0
  36. package/src/assets/web-panel/assets/{Marketplace-Yy30UZPw.js → Marketplace-BQry6ziq.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-Cil5l-bh.js → McpTools-7MBu8YsX.js} +3 -3
  38. package/src/assets/web-panel/assets/{Memory-DdJcnyqy.js → Memory-BlaZL_vM.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-IrzFYHEv.js → MobileBridge-iUYdZA22.js} +1 -1
  40. package/src/assets/web-panel/assets/{MobileProjects-D8q64LMd.js → MobileProjects-CUO-OpoO.js} +1 -1
  41. package/src/assets/web-panel/assets/{Mtc-CpdTJzW7.js → Mtc-6sD7414H.js} +4 -4
  42. package/src/assets/web-panel/assets/{MtcAudit-C7Tvw2m6.js → MtcAudit-BW8hjlD8.js} +4 -4
  43. package/src/assets/web-panel/assets/{Multisig-Dmj9F5Kr.js → Multisig-BA7_DWLu.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-C9Xchob5.js → NLProgramming-7P7H52-B.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-Bzq6Yry5.js → Notes-D2O2aG0R.js} +4 -4
  46. package/src/assets/web-panel/assets/{NotificationSettings-DxG9eKb4.js → NotificationSettings-SD4fdxcr.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-BS_IYoCe.js → OrderTableRenderer-BbXM4Ueq.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-kazsRvcq.js → Organization-DNabgtKX.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-i4wP-hwn.js → Overflow-B7Bqrhq0.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-CfGeU3h-.js → P2P-Dh0Df0zq.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-CS-VhVUx.js → PdhVaultBrowser-DHfJarF9.js} +5 -5
  52. package/src/assets/web-panel/assets/{Permissions-DnEHXs0I.js → Permissions-Bz3ddnZ9.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-DeD82qke.js → PersonalDataHub-Dfe0X6p8.js} +5 -5
  54. package/src/assets/web-panel/assets/{Pipeline-CMGGLgBY.js → Pipeline-kCnDqnwc.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-CvHoFv32.js → Privacy-CPveUX9G.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-DnJapCc1.js → ProjectInit-ddXd7WTL.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-CqVdv3-g.js → ProjectSettings-DnXcEjyu.js} +2 -2
  58. package/src/assets/web-panel/assets/{Projects-B_o8vcs_.js → Projects-O2yaPDuU.js} +1 -1
  59. package/src/assets/web-panel/assets/{Providers-CPKseoDW.js → Providers-hJpcyGxR.js} +1 -1
  60. package/src/assets/web-panel/assets/{QrScannerModal-_iBfKbPQ.js → QrScannerModal-CkbMoodn.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-CMrlZ69a.js → QuickAsk-CyFailNZ.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-BwDtSZ0l.js → Recommend-jpIDoqHs.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-DomUAtn4.js → RemoteSession-CieiVXM-.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-Cuu2GCHr.js → Reputation-DHtgC0AY.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-C7GVts31.js → Row-CSUyTUkR.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-DRKvgEog.js → RssFeed-CkHylSMs.js} +3 -3
  67. package/src/assets/web-panel/assets/{Search-BGI9wOeA.js → Search-ykyn3OaJ.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-BlLaHy_L.js → Security-DjM95Eyb.js} +3 -3
  69. package/src/assets/web-panel/assets/{Services-DFqZbjmX.js → Services-Cf4UMvka.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-BCGxdooP.js → Skeleton-BnR-ZNiM.js} +1 -1
  71. package/src/assets/web-panel/assets/{Skills-CwFKgcmm.js → Skills-oC5jYJgK.js} +1 -1
  72. package/src/assets/web-panel/assets/{Sla-CiXXh9eS.js → Sla-CTc_YFxW.js} +1 -1
  73. package/src/assets/web-panel/assets/{SpeechSettings-WSx2CLqO.js → SpeechSettings-31rddoaP.js} +1 -1
  74. package/src/assets/web-panel/assets/{SyncSettings-BBIqQOtW.js → SyncSettings-C-h00U59.js} +2 -2
  75. package/src/assets/web-panel/assets/{Tasks-D1BGLjO1.js → Tasks-CGn_IiAO.js} +1 -1
  76. package/src/assets/web-panel/assets/{Templates-CUIl9axA.js → Templates-B9Hz_RuF.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-BFZJ0hNz.js → Tenant-CJnIeKrI.js} +1 -1
  78. package/src/assets/web-panel/assets/{Terminal-Cw-3eYVn.js → Terminal-DfGtwDMA.js} +2 -2
  79. package/src/assets/web-panel/assets/{TimelineRenderer-bOVPB56L.js → TimelineRenderer-CISmCIFj.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-Czfyq2VY.js → Tokens-DNr-VU6W.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-C-o4uJY0.js → Trigger-CCYolBXm.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-BKq_S6iF.js → Trust-DD75_Hjo.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-fKlWUvMx.js → UkeySign-BXulgGCu.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-DB5MLuS7.js → VideoEditing-B0DgHQiZ.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-WGXBn7IS.js → Wallet-BV3CEPVS.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-B8TC4EMF.js → WebAuthn-CI9bXloP.js} +4 -4
  87. package/src/assets/web-panel/assets/{WorkflowEditor-DLY--KmM.js → WorkflowEditor-B4z18zZp.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-Crw3XQaA.js → chat-BsQ4S4Nh.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-CxhWauPV.js → colors-C0Jsl3u8.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-Cp3ojtk5.js → compact-item-CMZ_5Gdj.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-CRuRXjSo.js → createContext-VeTZ9pjJ.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-ChXQhXs6.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-XGW474dj.js → hasIn-R2ip_4t-.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-38TRdZb6.js → index-02inSVeg.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-C73pqyDb.js → index-0LEUdXks.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-B5fJS-kn.js → index-4i3UILe7.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-DoUC5_ry.js → index-6vvyh4N2.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-DHNixOg_.js → index-B53MC1iz.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-CDIpH_8Q.js → index-BDl3jun-.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DfPLIA-f.js → index-BGFKUUsv.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DxOtBFVy.js → index-BGKhfuHU.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-BXnNbbwa.js → index-BJvl_XUa.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-qzmihx1d.js → index-BPTTGRU9.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-BetOkRLs.js → index-BX_8_UFn.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CTE32qol.js → index-BdwYZI-H.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-Ctu98x57.js → index-Bhz0a_oU.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-jrIcbPUa.js → index-BjW7Qlh-.js} +1 -1
  108. package/src/assets/web-panel/assets/index-BpqhSIKB.js +1 -0
  109. package/src/assets/web-panel/assets/{index-BUWZ57T4.js → index-BtV-unhh.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-C8UOVaUH.js → index-ByPe74vs.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BElgeKJ0.js → index-Bz4O8exa.js} +3 -3
  112. package/src/assets/web-panel/assets/{index-DUSVsOGS.js → index-C3oYV_lA.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-De2FN0xN.js → index-CIanQUmB.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-CdlfrcC-.js → index-CNMfIBsh.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-QqAuH7-S.js → index-CsoYgCfM.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CPFam-me.js → index-CuIo38St.js} +1 -1
  117. package/src/assets/web-panel/assets/index-Cv9p7aNY.js +1 -0
  118. package/src/assets/web-panel/assets/{index-DhomnuaB.js → index-D4DUCUMd.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-BYkjs7eP.js → index-DF8AVnyq.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-DBcBsJYg.js → index-DUfRaQ2R.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-BW028Pwn.js → index-DdXJoar7.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-Yq3bFbYX.js → index-DjkLws9g.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-J_08R33H.js → index-Dqf95oif.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-BVmSfIkJ.js → index-Du20UePt.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-BuVA26SD.js → index-DvYF07ij.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-rsACoVT9.js → index-DwfM7rYW.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-WvNZXbIO.js → index-WJ_YxlwK.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-E-RSfImO.js → index-Zlt4hVX9.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-Dp2nC5On.js → index-iHgBGK8l.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-nJR64pA_.js → index-nM2lMEZ4.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-B45Vkh3T.js → index-q_5BV7Pj.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-W8_0yAi_.js → index-yIN1stc7.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-DAu-hgme.js → initDefaultProps-D1uCn3z4.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-Db8yk0Hu.js → motion-5TP3EY0Q.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-Cii2jOin.js → move-C_bi-KUq.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-CnZBDkyZ.js → mtc-parser-CmdzT6ro.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-Buzt1FTL.js → omit-Ce0_wQke.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-CpZ_NmE6.js → pickAttrs-DG8auaWM.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-mBrx3dYm.js → placementArrow-CaWVLdLv.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-DC_QzljB.js → responsiveObserve-Bot4LFBx.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-DT_UVED-.js → slide-HCFYDpKc.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-78t6eNLV.js → statusUtils-CWNqwWxQ.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-CV_T1ULL.js → styleChecker-BUyR4PCy.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-s8edGuXD.js → useFlexGapSupport-C4XRVB5s.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-Pk9dH2HC.js → useFs-D2VOJbk-.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-B_GqAm8c.js → usePersonalDataHub-dN8G1tq6.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-Cxyss24q.js → vnode-DSQKKZnw.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-0UY3cOuc.js → zoom-Dl0bVMqQ.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/commands/ask.js +84 -5
  151. package/src/commands/chat.js +67 -1
  152. package/src/commands/compact.js +81 -2
  153. package/src/commands/complete.js +64 -5
  154. package/src/commands/cowork.js +133 -0
  155. package/src/commands/orchestrate.js +18 -7
  156. package/src/data/changelog.json +13 -0
  157. package/src/gateways/ws/action-protocol.js +2 -0
  158. package/src/lib/agent-router.js +116 -36
  159. package/src/lib/cowork-task-runner.js +107 -4
  160. package/src/lib/evolution/agent-evolution-ingress.js +231 -40
  161. package/src/lib/evolution/agent-evolution-runtime-composition.js +85 -5
  162. package/src/lib/evolution/evolution-deployment-loader.js +17 -1
  163. package/src/lib/evolution/evolution-evidence-projector.js +25 -6
  164. package/src/lib/model-failure-policy.js +10 -0
  165. package/src/lib/orchestrator.js +97 -27
  166. package/src/lib/read-file-loop-guard.js +21 -1
  167. package/src/lib/sub-agent-context.js +34 -2
  168. package/src/repl/chat-repl.js +60 -10
  169. package/src/runtime/agent-core.js +96 -5
  170. package/src/runtime/agent-runtime.js +20 -1
  171. package/src/runtime/runtime-factory.js +1 -1
  172. package/src/assets/web-panel/assets/MarkdownRenderer-DJjPaOnM.js +0 -1
  173. package/src/assets/web-panel/assets/devWarning-CKAQY2zn.js +0 -1
  174. package/src/assets/web-panel/assets/index-Cetfwq8j.js +0 -1
  175. package/src/assets/web-panel/assets/index-DOpcRO2-.js +0 -1
@@ -26,7 +26,9 @@ import crypto from "crypto";
26
26
  import { AgentRouter } from "./agent-router.js";
27
27
  import { NotificationManager } from "./notifiers/index.js";
28
28
  import { createChatFn } from "./cowork-adapter.js";
29
+ import { captureAgentEvolutionRuntimeComposition } from "./evolution/agent-evolution-runtime-composition-brand.js";
29
30
  import { firstBalancedJson } from "./json-schema-output.js";
31
+ import { isTerminalModelFailure } from "./model-failure-policy.js";
30
32
  import {
31
33
  assertCLILegacyMutationAllowed,
32
34
  cliLegacyRuntimeReadOnly,
@@ -58,6 +60,7 @@ export const TASK_STATUS = {
58
60
  CI_PASSED: "ci-passed",
59
61
  CI_FAILED: "ci-failed",
60
62
  RETRYING: "retrying",
63
+ FINALIZING: "finalizing",
61
64
  COMPLETED: "completed",
62
65
  FAILED: "failed",
63
66
  };
@@ -98,6 +101,15 @@ export class Orchestrator extends EventEmitter {
98
101
  this.maxRetries = options.maxRetries || 3;
99
102
  this.ciCommand = options.ciCommand || "npm test";
100
103
  this.verbose = options.verbose || false;
104
+ this._evolutionCompositionFactory =
105
+ options.evolutionCompositionFactory ?? null;
106
+ if (
107
+ this._evolutionCompositionFactory !== null &&
108
+ typeof this._evolutionCompositionFactory !== "function"
109
+ ) {
110
+ throw new TypeError("evolutionCompositionFactory must be a function");
111
+ }
112
+ this._llmOptions = options.llm || {};
101
113
 
102
114
  // Cap retained task history. Every addTask stores a record in _tasks and
103
115
  // nothing ever removes it, so a long-running orchestrator (cron-watch /
@@ -141,7 +153,7 @@ export class Orchestrator extends EventEmitter {
141
153
  this.notifier =
142
154
  options.notifier || NotificationManager.fromEnv(options.notify || {});
143
155
 
144
- this._chat = createChatFn(options.llm || {});
156
+ this._chat = createChatFn(this._llmOptions);
145
157
  this._cronTimer = null;
146
158
 
147
159
  // Forward router events
@@ -210,7 +222,51 @@ export class Orchestrator extends EventEmitter {
210
222
  .catch(() => {});
211
223
  }
212
224
 
213
- await this._orchestrate(task);
225
+ let evolutionComposition = null;
226
+ try {
227
+ if (this._evolutionCompositionFactory !== null) {
228
+ evolutionComposition = captureAgentEvolutionRuntimeComposition(
229
+ await this._evolutionCompositionFactory(
230
+ Object.freeze({
231
+ mode: "orchestrate",
232
+ runId: task.id,
233
+ taskId: task.id,
234
+ source: task.source,
235
+ cwd: task.cwd,
236
+ }),
237
+ ),
238
+ );
239
+ if (
240
+ evolutionComposition.runId !== task.id ||
241
+ evolutionComposition.evolutionIngress.runId !== task.id ||
242
+ evolutionComposition.evolutionIngress.tenantId !==
243
+ evolutionComposition.tenantId
244
+ ) {
245
+ const error = new Error(
246
+ "Orchestrator evolution composition is not bound to the requested Run",
247
+ );
248
+ error.code = "CC_AGENT_EVOLUTION_INGRESS_FAILED";
249
+ throw error;
250
+ }
251
+ await evolutionComposition.evolutionIngress.start();
252
+ await evolutionComposition.evolutionIngress.ingestUserPrompt({
253
+ content: task.description,
254
+ context: task.context,
255
+ taskId: task.id,
256
+ source: `orchestrate:${task.source}`,
257
+ });
258
+ }
259
+ } catch (error) {
260
+ task.status = TASK_STATUS.FAILED;
261
+ task.error = error.message;
262
+ this.emit("task:failed", { task, error });
263
+ throw error;
264
+ }
265
+
266
+ await this._orchestrate(
267
+ task,
268
+ evolutionComposition?.evolutionIngress ?? null,
269
+ );
214
270
  return task;
215
271
  }
216
272
 
@@ -257,24 +313,22 @@ export class Orchestrator extends EventEmitter {
257
313
 
258
314
  // ─── Orchestration pipeline ──────────────────────────────────────
259
315
 
260
- async _orchestrate(task) {
316
+ async _orchestrate(task, evolutionIngress = null) {
261
317
  assertCLILegacyMutationAllowed("Orchestrator._orchestrate");
262
318
  try {
263
319
  // Step 1: Decompose
264
- task.subtasks = await this._decompose(task);
320
+ task.subtasks = await this._decompose(task, evolutionIngress);
265
321
  task.status = TASK_STATUS.DISPATCHED;
266
322
 
267
323
  // Step 2: Dispatch to Claude Code agents
268
- task.agentResults = await this._dispatch(task);
324
+ task.agentResults = await this._dispatch(task, evolutionIngress);
269
325
  this._assertSuccessfulAgentResults(task);
270
326
 
271
327
  // Step 3: CI/CD check
272
328
  if (task.runCI) {
273
- await this._ciLoop(task);
329
+ await this._ciLoop(task, evolutionIngress);
274
330
  } else {
275
- task.status = TASK_STATUS.COMPLETED;
276
- task.completedAt = new Date().toISOString();
277
- this.emit("task:complete", task);
331
+ await this._completeTask(task, evolutionIngress);
278
332
  }
279
333
  } catch (err) {
280
334
  task.status = TASK_STATUS.FAILED;
@@ -284,8 +338,26 @@ export class Orchestrator extends EventEmitter {
284
338
  }
285
339
  }
286
340
 
341
+ async _completeTask(task, evolutionIngress, ciResult = null) {
342
+ assertCLILegacyMutationAllowed("Orchestrator._completeTask");
343
+ task.status = TASK_STATUS.FINALIZING;
344
+ if (evolutionIngress !== null) await evolutionIngress.complete();
345
+ if (ciResult !== null && this.notifier.isConfigured && task.notify) {
346
+ await this.notifier.notifySuccess({
347
+ taskId: task.id,
348
+ description: task.description.slice(0, 100),
349
+ agentCount: task.subtasks.length,
350
+ duration: Date.now() - new Date(task.createdAt).getTime(),
351
+ filesChanged: ciResult.filesChanged || [],
352
+ });
353
+ }
354
+ task.completedAt = new Date().toISOString();
355
+ task.status = TASK_STATUS.COMPLETED;
356
+ this.emit("task:complete", task);
357
+ }
358
+
287
359
  /** LLM-driven task decomposition into coding subtasks. */
288
- async _decompose(task) {
360
+ async _decompose(task, evolutionIngress = null) {
289
361
  assertCLILegacyMutationAllowed("Orchestrator._decompose");
290
362
  task.status = TASK_STATUS.DECOMPOSING;
291
363
  this.emit("task:decomposing", task);
@@ -302,7 +374,14 @@ export class Orchestrator extends EventEmitter {
302
374
  (task.context ? `\nAdditional context:\n${task.context}` : "");
303
375
 
304
376
  try {
305
- const raw = await this._chat(
377
+ const chat =
378
+ evolutionIngress === null
379
+ ? this._chat
380
+ : createChatFn({
381
+ ...this._llmOptions,
382
+ evolutionIngress,
383
+ });
384
+ const raw = await chat(
306
385
  [
307
386
  { role: "system", content: systemPrompt },
308
387
  { role: "user", content: userMsg },
@@ -317,7 +396,8 @@ export class Orchestrator extends EventEmitter {
317
396
  this.emit("task:decomposed", { task, subtasks });
318
397
  this._log(`Decomposed into ${subtasks.length} subtask(s)`);
319
398
  return subtasks;
320
- } catch {
399
+ } catch (error) {
400
+ if (isTerminalModelFailure(error)) throw error;
321
401
  // Fallback: treat whole task as single subtask
322
402
  const fallback = [
323
403
  { id: "sub-1", description: task.description, context: task.context },
@@ -328,7 +408,7 @@ export class Orchestrator extends EventEmitter {
328
408
  }
329
409
 
330
410
  /** Dispatch subtasks to the Claude Code pool. */
331
- async _dispatch(task) {
411
+ async _dispatch(task, evolutionIngress = null) {
332
412
  assertCLILegacyMutationAllowed("Orchestrator._dispatch");
333
413
  this.emit("agents:dispatched", { task, count: task.subtasks.length });
334
414
  this._log(
@@ -337,13 +417,14 @@ export class Orchestrator extends EventEmitter {
337
417
 
338
418
  const results = await this._router.dispatch(task.subtasks, {
339
419
  cwd: task.cwd,
420
+ ...(evolutionIngress === null ? {} : { evolutionIngress }),
340
421
  });
341
422
  this.emit("agents:complete", { task, results });
342
423
  return results;
343
424
  }
344
425
 
345
426
  /** Run CI command and retry loop. */
346
- async _ciLoop(task) {
427
+ async _ciLoop(task, evolutionIngress = null) {
347
428
  assertCLILegacyMutationAllowed("Orchestrator._ciLoop");
348
429
  for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
349
430
  task.status = TASK_STATUS.CI_CHECKING;
@@ -356,22 +437,10 @@ export class Orchestrator extends EventEmitter {
356
437
 
357
438
  if (ciResult.pass) {
358
439
  task.status = TASK_STATUS.CI_PASSED;
359
- task.completedAt = new Date().toISOString();
360
440
  this.emit("ci:pass", { task });
361
441
  this._log(`CI passed for task ${task.id}`);
362
442
 
363
- if (this.notifier.isConfigured && task.notify) {
364
- await this.notifier.notifySuccess({
365
- taskId: task.id,
366
- description: task.description.slice(0, 100),
367
- agentCount: task.subtasks.length,
368
- duration: Date.now() - new Date(task.createdAt).getTime(),
369
- filesChanged: ciResult.filesChanged || [],
370
- });
371
- }
372
-
373
- task.status = TASK_STATUS.COMPLETED;
374
- this.emit("task:complete", task);
443
+ await this._completeTask(task, evolutionIngress, ciResult);
375
444
  return;
376
445
  }
377
446
 
@@ -409,6 +478,7 @@ export class Orchestrator extends EventEmitter {
409
478
 
410
479
  task.agentResults = await this._router.dispatch(fixSubtasks, {
411
480
  cwd: task.cwd,
481
+ ...(evolutionIngress === null ? {} : { evolutionIngress }),
412
482
  });
413
483
  this._assertSuccessfulAgentResults(task);
414
484
  this.emit("agents:complete", { task, results: task.agentResults });
@@ -34,6 +34,7 @@ export class ReadFileLoopGuard {
34
34
  this.repeatedBatches = 0;
35
35
  this.recoveryOfferedAt = 0;
36
36
  this.batch = null;
37
+ this.largeOutputs = new Set();
37
38
  }
38
39
 
39
40
  startBatch() {
@@ -152,6 +153,24 @@ export class ReadFileLoopGuard {
152
153
  if (result?.readRecovery?.action === "targeted-review")
153
154
  this.batch.advanced = true;
154
155
  if (result?.readProgress?.newContent === false) this.batch.duplicates++;
156
+ } else if (
157
+ (tool === "run_code" || tool === "run_shell") &&
158
+ typeof result?.output === "string" &&
159
+ result.output.length >= 8000
160
+ ) {
161
+ // Arbitrary code may just dump the same file again. Compare returned
162
+ // evidence, not code spelling or timings. Never cache/skip execution:
163
+ // identical stdout does not imply identical filesystem side effects.
164
+ const fingerprint = createHash("sha256")
165
+ .update(result.output)
166
+ .digest("hex");
167
+ if (this.largeOutputs.has(fingerprint)) this.batch.duplicates++;
168
+ else {
169
+ this.largeOutputs.add(fingerprint);
170
+ this.batch.advanced = true;
171
+ while (this.largeOutputs.size > 64)
172
+ this.largeOutputs.delete(this.largeOutputs.values().next().value);
173
+ }
155
174
  } else if (!DISCOVERY_TOOLS.has(tool)) {
156
175
  this.batch.substantive = true;
157
176
  }
@@ -163,6 +182,7 @@ export class ReadFileLoopGuard {
163
182
  this.repeatedBatches = 0;
164
183
  this.recoveryOfferedAt = 0;
165
184
  if (this.batch.substantive) {
185
+ this.largeOutputs.clear();
166
186
  for (const entry of this.progress.values()) entry.rereads.clear();
167
187
  }
168
188
  } else if (this.batch.duplicates) this.repeatedBatches++;
@@ -172,7 +192,7 @@ export class ReadFileLoopGuard {
172
192
 
173
193
  get recoveryHint() {
174
194
  return this.repeatedBatches >= 1
175
- ? "Repeated unchanged file reads detected. The runtime continues unfinished scans automatically and returns use-findings after EOF. Use the retained file outline to locate the relevant work, then implement/verify the user's task. Do not restart a whole-file scan after context compaction. A targeted search does not itself complete the task."
195
+ ? "Repeated file reads or identical large command outputs detected. Do not switch to run_code/run_shell to dump the same file again. Filter/count locally and print only relevant rows, totals and source line numbers, or use a focused search. The runtime continues unfinished read_file scans automatically and returns use-findings after EOF. Use the retained outline to perform the user's task. Do not restart a whole-file scan after context compaction; answer once the requested evidence is sufficient."
176
196
  : null;
177
197
  }
178
198
 
@@ -12,6 +12,8 @@ import crypto from "crypto";
12
12
  import { CLIContextEngineering } from "./cli-context-engineering.js";
13
13
  import { agentLoop, buildSystemPrompt, AGENT_TOOLS } from "./agent-core.js";
14
14
  import { feature } from "./feature-flags.js";
15
+ import { isEvolutionIngressFailure } from "./model-failure-policy.js";
16
+ import { captureAgentEvolutionIngress } from "./evolution/agent-evolution-ingress.js";
15
17
  import {
16
18
  createWorktree,
17
19
  removeWorktree,
@@ -589,7 +591,13 @@ export class SubAgentContext {
589
591
  }
590
592
  return result;
591
593
  } catch (err) {
592
- if (err?.runtimeLedgerPersistence === true || this._workflowEffectId) {
594
+ if (
595
+ isEvolutionIngressFailure(err) ||
596
+ err?.runtimeLedgerPersistence === true ||
597
+ this._workflowEffectId
598
+ ) {
599
+ this.status = "failed";
600
+ this.completedAt = new Date().toISOString();
593
601
  throw err;
594
602
  }
595
603
  // If worktree creation fails (e.g. not a git repo), fall back to direct
@@ -875,12 +883,21 @@ export class SubAgentContext {
875
883
  options.approvalGate = this._approvalGate;
876
884
  }
877
885
 
886
+ const evolutionIngress =
887
+ options.evolutionIngress == null
888
+ ? null
889
+ : captureAgentEvolutionIngress(options.evolutionIngress);
890
+ if (evolutionIngress !== null) options.evolutionIngress = evolutionIngress;
891
+
878
892
  try {
879
893
  // Use a separate messages array for the agent loop
880
894
  // The agentLoop will append to this.messages directly
881
895
  const gen = agentLoop(this.messages, options);
882
896
 
883
897
  for await (const event of gen) {
898
+ if (evolutionIngress !== null) {
899
+ await evolutionIngress.ingestAgentEvent(event);
900
+ }
884
901
  this._iterationCount++;
885
902
 
886
903
  if (event.type === "run-started" && event.runId) {
@@ -1099,6 +1116,13 @@ export class SubAgentContext {
1099
1116
  this._tokenCount += Math.ceil((lastContent.length || 0) / 4);
1100
1117
  }
1101
1118
 
1119
+ if (event.type === "run-ended" && event.reason !== "complete") {
1120
+ this.forceComplete(event.reason || "unknown-terminal-reason", {
1121
+ partialContent: lastContent,
1122
+ artifacts,
1123
+ });
1124
+ }
1125
+
1102
1126
  // Emit progress to consumer if callback provided
1103
1127
  if (this._onProgress) {
1104
1128
  try {
@@ -1161,7 +1185,13 @@ export class SubAgentContext {
1161
1185
  throw error;
1162
1186
  }
1163
1187
  } catch (err) {
1164
- if (err?.runtimeLedgerPersistence === true || this._workflowEffectId) {
1188
+ if (
1189
+ isEvolutionIngressFailure(err) ||
1190
+ err?.runtimeLedgerPersistence === true ||
1191
+ this._workflowEffectId
1192
+ ) {
1193
+ this.status = "failed";
1194
+ this.completedAt = new Date().toISOString();
1165
1195
  throw err;
1166
1196
  }
1167
1197
  if (this.isAborted()) {
@@ -1295,6 +1325,8 @@ export class SubAgentContext {
1295
1325
  : "";
1296
1326
  this.result = {
1297
1327
  summary: `(Sub-agent force-completed: ${reason})${partialText}`,
1328
+ incomplete: true,
1329
+ completionReason: reason,
1298
1330
  artifacts: Array.isArray(partial.artifacts) ? partial.artifacts : [],
1299
1331
  tokenCount: this._tokenCount,
1300
1332
  toolsUsed: [...new Set(this._toolsUsed)],
@@ -56,6 +56,8 @@ import { installPipeSafety } from "../runtime/pipe-safety.js";
56
56
  import { installOutputBackpressure } from "../runtime/output-backpressure.js";
57
57
  import { assertChatSessionUsageAdmission } from "../lib/chat-session-admission.js";
58
58
  import { captureAmbientExecutionLocation } from "../lib/execution-location-runtime.js";
59
+ import { captureAgentEvolutionIngress } from "../lib/evolution/agent-evolution-ingress.js";
60
+ import { createAgentEvolutionSessionLifecycle } from "../lib/evolution/agent-evolution-session-lifecycle.js";
59
61
 
60
62
  const SLASH_COMMANDS = {
61
63
  "/exit": "Exit the chat",
@@ -94,9 +96,17 @@ const SLASH_COMMANDS = {
94
96
  * @param {object} options
95
97
  */
96
98
  export async function startChatRepl(options = {}) {
99
+ const evolutionIngress =
100
+ options.evolutionIngress == null
101
+ ? null
102
+ : captureAgentEvolutionIngress(options.evolutionIngress);
97
103
  const admittedSessionId = options.sessionId
98
104
  ? assertChatSessionUsageAdmission(options.sessionId)
99
105
  : null;
106
+ const evolutionSession =
107
+ evolutionIngress === null
108
+ ? null
109
+ : createAgentEvolutionSessionLifecycle(evolutionIngress);
100
110
  let model = options.model || "qwen2:7b";
101
111
  let provider = options.provider || "ollama";
102
112
  const baseUrl = options.baseUrl || "http://localhost:11434";
@@ -147,7 +157,9 @@ export async function startChatRepl(options = {}) {
147
157
  ),
148
158
  );
149
159
  try {
150
- rl = readline.createInterface({
160
+ const createInterface =
161
+ options.createInterface || readline.createInterface.bind(readline);
162
+ rl = createInterface({
151
163
  input: options.input || process.stdin,
152
164
  output: stdout,
153
165
  prompt: chalk.green("you> "),
@@ -266,13 +278,20 @@ export async function startChatRepl(options = {}) {
266
278
  logger.verbose?.(`[@ref] expansion skipped: ${err.message}`);
267
279
  }
268
280
 
269
- // Add user message
270
- messages.push({ role: "user", content: userContent });
281
+ try {
282
+ if (evolutionIngress !== null) {
283
+ await evolutionIngress.ingestUserPrompt({
284
+ content: userContent,
285
+ sessionId,
286
+ });
287
+ }
271
288
 
272
- // Stream the response
273
- stdout.write(chalk.blue("ai> "));
289
+ // Add user message
290
+ messages.push({ role: "user", content: userContent });
291
+
292
+ // Stream the response
293
+ stdout.write(chalk.blue("ai> "));
274
294
 
275
- try {
276
295
  let response;
277
296
  const onToken = (token) => {
278
297
  const accepted = stdout.write(token);
@@ -302,9 +321,19 @@ export async function startChatRepl(options = {}) {
302
321
  if (sessionId)
303
322
  appendEvent(sessionId, "user_message", { content: trimmed });
304
323
 
324
+ const providerMessages =
325
+ evolutionIngress === null
326
+ ? messages
327
+ : (
328
+ await evolutionIngress.prepareModelRequest({
329
+ messages,
330
+ tools: [],
331
+ })
332
+ ).messages;
333
+
305
334
  if (provider === "ollama") {
306
335
  response = await streamOllama(
307
- messages,
336
+ providerMessages,
308
337
  model,
309
338
  baseUrl,
310
339
  onToken,
@@ -325,7 +354,7 @@ export async function startChatRepl(options = {}) {
325
354
  `API key required for anthropic (set ${providerDef?.apiKeyEnv || "ANTHROPIC_API_KEY"})`,
326
355
  );
327
356
  response = await streamAnthropic(
328
- messages,
357
+ providerMessages,
329
358
  model,
330
359
  url,
331
360
  key,
@@ -348,7 +377,7 @@ export async function startChatRepl(options = {}) {
348
377
  `API key required for ${provider} (set ${providerDef?.apiKeyEnv || "API key"})`,
349
378
  );
350
379
  response = await streamOpenAI(
351
- messages,
380
+ providerMessages,
352
381
  model,
353
382
  url,
354
383
  key,
@@ -358,6 +387,14 @@ export async function startChatRepl(options = {}) {
358
387
  );
359
388
  }
360
389
 
390
+ if (evolutionIngress !== null) {
391
+ await evolutionIngress.ingestAgentEvent({
392
+ type: "response-complete",
393
+ content: response,
394
+ sessionId,
395
+ });
396
+ }
397
+
361
398
  stdout.write("\n\n");
362
399
  messages.push({ role: "assistant", content: response });
363
400
 
@@ -410,6 +447,19 @@ export async function startChatRepl(options = {}) {
410
447
  : 0;
411
448
  disposePipeSafety();
412
449
  outputFlow.restore();
413
- process.exit(exitCode);
450
+ if (evolutionSession !== null) {
451
+ try {
452
+ await evolutionSession.close(outputFailure);
453
+ } catch (error) {
454
+ outputFailure ||= error;
455
+ }
456
+ }
457
+ const finalExitCode = outputFailure
458
+ ? outputFailure.code === "EPIPE"
459
+ ? 0
460
+ : 1
461
+ : exitCode;
462
+ process.exit(finalExitCode);
414
463
  });
464
+ return evolutionSession?.handle;
415
465
  }